From c6a33e2464edd87f8c12cc2d11369a5b44c65b77 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Wed, 12 Oct 2005 15:12:26 +0800 Subject: [PATCH] libata CHS: LBA28/LBA48 optimization (revise #6) - add lba_28_ok() and lba_48_ok() to ata.h. - check ending block number instead of staring block number. - use lba_28_ok() for CHS range check - LBA28/LBA48 optimization Suggested by Mark Lord and Alan Cox. Signed-off-by: Albert Lee ===== Signed-off-by: Jeff Garzik --- include/linux/ata.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'include') diff --git a/include/linux/ata.h b/include/linux/ata.h index 630908c9378b..b7e7e1cb2633 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -291,4 +291,16 @@ static inline int ata_ok(u8 status) == ATA_DRDY); } +static inline int lba_28_ok(u64 block, u32 n_block) +{ + /* check the ending block number */ + return ((block + n_block - 1) < ((u64)1 << 28)) && (n_block <= 256); +} + +static inline int lba_48_ok(u64 block, u32 n_block) +{ + /* check the ending block number */ + return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= 65536); +} + #endif /* __LINUX_ATA_H__ */ -- cgit v1.2.3 From ff741906ad3cf4b8ca1a958acb013a97a6381ca2 Mon Sep 17 00:00:00 2001 From: Ashok Raj Date: Fri, 11 Nov 2005 14:32:40 -0800 Subject: [IA64] support for cpu0 removal here is the BSP removal support for IA64. Its pretty much the same thing that was released a while back, but has your feedback incorporated. - Removed CONFIG_BSP_REMOVE_WORKAROUND and associated cmdline param - Fixed compile issue with sn2/zx1 due to a undefined fix_b0_for_bsp - some formatting nits (whitespace etc) This has been tested on tiger and long back by alex on hp systems as well. Signed-off-by: Ashok Raj Signed-off-by: Tony Luck --- arch/ia64/Kconfig | 19 +++++++ arch/ia64/configs/tiger_defconfig | 2 + arch/ia64/kernel/acpi.c | 12 ++-- arch/ia64/kernel/iosapic.c | 6 ++ arch/ia64/kernel/irq.c | 13 ++++- arch/ia64/kernel/mca.c | 6 +- arch/ia64/kernel/perfmon.c | 5 +- arch/ia64/kernel/smpboot.c | 114 ++++++++++++++++++++++++++++++++++++-- arch/ia64/kernel/time.c | 9 ++- arch/ia64/mm/contig.c | 4 +- arch/ia64/mm/discontig.c | 9 ++- include/asm-ia64/mca.h | 2 + 12 files changed, 183 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 199eeaf0f4e3..5e0f58e37c59 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -272,6 +272,25 @@ config SCHED_SMT Intel IA64 chips with MultiThreading at a cost of slightly increased overhead in some places. If unsure say N here. +config PERMIT_BSP_REMOVE + bool "Support removal of Bootstrap Processor" + depends on HOTPLUG_CPU + default n + ---help--- + Say Y here if your platform SAL will support removal of BSP with HOTPLUG_CPU + support. + +config FORCE_CPEI_RETARGET + bool "Force assumption that CPEI can be re-targetted" + depends on PERMIT_BSP_REMOVE + default n + ---help--- + Say Y if you need to force the assumption that CPEI can be re-targetted to + any cpu in the system. This hint is available via ACPI 3.0 specifications. + Tiger4 systems are capable of re-directing CPEI to any CPU other than BSP. + This option it useful to enable this feature on older BIOS's as well. + You can also enable this by using boot command line option force_cpei=1. + config PREEMPT bool "Preemptible Kernel" help diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig index b1e8f09e9fd5..aed034d33976 100644 --- a/arch/ia64/configs/tiger_defconfig +++ b/arch/ia64/configs/tiger_defconfig @@ -114,6 +114,8 @@ CONFIG_FORCE_MAX_ZONEORDER=17 CONFIG_SMP=y CONFIG_NR_CPUS=4 CONFIG_HOTPLUG_CPU=y +CONFIG_PERMIT_BSP_REMOVE=y +CONFIG_FORCE_CPEI_RETARGET=y # CONFIG_SCHED_SMT is not set # CONFIG_PREEMPT is not set CONFIG_SELECT_MEMORY_MODEL=y diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 9ad94ddf6687..fe1d90b0c6ea 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -287,16 +287,20 @@ acpi_parse_plat_int_src(acpi_table_entry_header * header, unsigned int can_cpei_retarget(void) { extern int cpe_vector; + extern unsigned int force_cpei_retarget; /* * Only if CPEI is supported and the override flag * is present, otherwise return that its re-targettable * if we are in polling mode. */ - if (cpe_vector > 0 && !acpi_cpei_override) - return 0; - else - return 1; + if (cpe_vector > 0) { + if (acpi_cpei_override || force_cpei_retarget) + return 1; + else + return 0; + } + return 1; } unsigned int is_cpu_cpei_target(unsigned int cpu) diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 574084f343fa..37ac742da8ed 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -631,6 +631,7 @@ get_target_cpu (unsigned int gsi, int vector) { #ifdef CONFIG_SMP static int cpu = -1; + extern int cpe_vector; /* * In case of vector shared by multiple RTEs, all RTEs that @@ -653,6 +654,11 @@ get_target_cpu (unsigned int gsi, int vector) if (!cpu_online(smp_processor_id())) return cpu_physical_id(smp_processor_id()); +#ifdef CONFIG_ACPI + if (cpe_vector > 0 && vector == IA64_CPEP_VECTOR) + return get_cpei_target_cpu(); +#endif + #ifdef CONFIG_NUMA { int num_cpus, cpu_index, iosapic_index, numa_cpu, i = 0; diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index d33244c32759..5ce908ef9c95 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c @@ -163,8 +163,19 @@ void fixup_irqs(void) { unsigned int irq; extern void ia64_process_pending_intr(void); + extern void ia64_disable_timer(void); + extern volatile int time_keeper_id; + + ia64_disable_timer(); + + /* + * Find a new timesync master + */ + if (smp_processor_id() == time_keeper_id) { + time_keeper_id = first_cpu(cpu_online_map); + printk ("CPU %d is now promoted to time-keeper master\n", time_keeper_id); + } - ia64_set_itv(1<<16); /* * Phase 1: Locate irq's bound to this cpu and * relocate them for cpu removal. diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 355af15287c7..967571b466a2 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -289,6 +289,7 @@ ia64_mca_log_sal_error_record(int sal_info_type) #ifdef CONFIG_ACPI int cpe_vector = -1; +int ia64_cpe_irq = -1; static irqreturn_t ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs) @@ -1444,11 +1445,13 @@ void __devinit ia64_mca_cpu_init(void *cpu_data) { void *pal_vaddr; + static int first_time = 1; - if (smp_processor_id() == 0) { + if (first_time) { void *mca_data; int cpu; + first_time = 0; mca_data = alloc_bootmem(sizeof(struct ia64_mca_cpu) * NR_CPUS + KERNEL_STACK_SIZE); mca_data = (void *)(((unsigned long)mca_data + @@ -1704,6 +1707,7 @@ ia64_mca_late_init(void) desc = irq_descp(irq); desc->status |= IRQ_PER_CPU; setup_irq(irq, &mca_cpe_irqaction); + ia64_cpe_irq = irq; } ia64_mca_register_cpev(cpe_vector); IA64_MCA_DEBUG("%s: CPEI/P setup and enabled.\n", __FUNCTION__); diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 410d4804fa6e..18c51c37a9a3 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -6718,6 +6718,7 @@ __initcall(pfm_init); void pfm_init_percpu (void) { + static int first_time=1; /* * make sure no measurement is active * (may inherit programmed PMCs from EFI). @@ -6730,8 +6731,10 @@ pfm_init_percpu (void) */ pfm_unfreeze_pmu(); - if (smp_processor_id() == 0) + if (first_time) { register_percpu_irq(IA64_PERFMON_VECTOR, &perfmon_irqaction); + first_time=0; + } ia64_setreg(_IA64_REG_CR_PMV, IA64_PERFMON_VECTOR); ia64_srlz_d(); diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 8f44e7d2df66..e9d37bf67d69 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -70,6 +70,12 @@ #endif #ifdef CONFIG_HOTPLUG_CPU +#ifdef CONFIG_PERMIT_BSP_REMOVE +#define bsp_remove_ok 1 +#else +#define bsp_remove_ok 0 +#endif + /* * Store all idle threads, this can be reused instead of creating * a new thread. Also avoids complicated thread destroy functionality @@ -104,7 +110,7 @@ struct sal_to_os_boot *sal_state_for_booting_cpu = &sal_boot_rendez_state[0]; /* * ITC synchronization related stuff: */ -#define MASTER 0 +#define MASTER (0) #define SLAVE (SMP_CACHE_BYTES/8) #define NUM_ROUNDS 64 /* magic value */ @@ -151,6 +157,27 @@ char __initdata no_int_routing; unsigned char smp_int_redirect; /* are INT and IPI redirectable by the chipset? */ +#ifdef CONFIG_FORCE_CPEI_RETARGET +#define CPEI_OVERRIDE_DEFAULT (1) +#else +#define CPEI_OVERRIDE_DEFAULT (0) +#endif + +unsigned int force_cpei_retarget = CPEI_OVERRIDE_DEFAULT; + +static int __init +cmdl_force_cpei(char *str) +{ + int value=0; + + get_option (&str, &value); + force_cpei_retarget = value; + + return 1; +} + +__setup("force_cpei=", cmdl_force_cpei); + static int __init nointroute (char *str) { @@ -161,6 +188,27 @@ nointroute (char *str) __setup("nointroute", nointroute); +static void fix_b0_for_bsp(void) +{ +#ifdef CONFIG_HOTPLUG_CPU + int cpuid; + static int fix_bsp_b0 = 1; + + cpuid = smp_processor_id(); + + /* + * Cache the b0 value on the first AP that comes up + */ + if (!(fix_bsp_b0 && cpuid)) + return; + + sal_boot_rendez_state[0].br[0] = sal_boot_rendez_state[cpuid].br[0]; + printk ("Fixed BSP b0 value from CPU %d\n", cpuid); + + fix_bsp_b0 = 0; +#endif +} + void sync_master (void *arg) { @@ -327,8 +375,9 @@ smp_setup_percpu_timer (void) static void __devinit smp_callin (void) { - int cpuid, phys_id; + int cpuid, phys_id, itc_master; extern void ia64_init_itm(void); + extern volatile int time_keeper_id; #ifdef CONFIG_PERFMON extern void pfm_init_percpu(void); @@ -336,6 +385,7 @@ smp_callin (void) cpuid = smp_processor_id(); phys_id = hard_smp_processor_id(); + itc_master = time_keeper_id; if (cpu_online(cpuid)) { printk(KERN_ERR "huh, phys CPU#0x%x, CPU#0x%x already present??\n", @@ -343,6 +393,8 @@ smp_callin (void) BUG(); } + fix_b0_for_bsp(); + lock_ipi_calllock(); cpu_set(cpuid, cpu_online_map); unlock_ipi_calllock(); @@ -365,8 +417,8 @@ smp_callin (void) * calls spin_unlock_bh(), which calls spin_unlock_bh(), which calls * local_bh_enable(), which bugs out if irqs are not enabled... */ - Dprintk("Going to syncup ITC with BP.\n"); - ia64_sync_itc(0); + Dprintk("Going to syncup ITC with ITC Master.\n"); + ia64_sync_itc(itc_master); } /* @@ -638,6 +690,47 @@ remove_siblinginfo(int cpu) } extern void fixup_irqs(void); + +int migrate_platform_irqs(unsigned int cpu) +{ + int new_cpei_cpu; + irq_desc_t *desc = NULL; + cpumask_t mask; + int retval = 0; + + /* + * dont permit CPEI target to removed. + */ + if (cpe_vector > 0 && is_cpu_cpei_target(cpu)) { + printk ("CPU (%d) is CPEI Target\n", cpu); + if (can_cpei_retarget()) { + /* + * Now re-target the CPEI to a different processor + */ + new_cpei_cpu = any_online_cpu(cpu_online_map); + mask = cpumask_of_cpu(new_cpei_cpu); + set_cpei_target_cpu(new_cpei_cpu); + desc = irq_descp(ia64_cpe_irq); + /* + * Switch for now, immediatly, we need to do fake intr + * as other interrupts, but need to study CPEI behaviour with + * polling before making changes. + */ + if (desc) { + desc->handler->disable(ia64_cpe_irq); + desc->handler->set_affinity(ia64_cpe_irq, mask); + desc->handler->enable(ia64_cpe_irq); + printk ("Re-targetting CPEI to cpu %d\n", new_cpei_cpu); + } + } + if (!desc) { + printk ("Unable to retarget CPEI, offline cpu [%d] failed\n", cpu); + retval = -EBUSY; + } + } + return retval; +} + /* must be called with cpucontrol mutex held */ int __cpu_disable(void) { @@ -646,8 +739,17 @@ int __cpu_disable(void) /* * dont permit boot processor for now */ - if (cpu == 0) - return -EBUSY; + if (cpu == 0 && !bsp_remove_ok) { + printk ("Your platform does not support removal of BSP\n"); + return (-EBUSY); + } + + cpu_clear(cpu, cpu_online_map); + + if (migrate_platform_irqs(cpu)) { + cpu_set(cpu, cpu_online_map); + return (-EBUSY); + } remove_siblinginfo(cpu); cpu_clear(cpu, cpu_online_map); diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index 028a2b95936c..1ca130a83856 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c @@ -32,7 +32,7 @@ extern unsigned long wall_jiffies; -#define TIME_KEEPER_ID 0 /* smp_processor_id() of time-keeper */ +volatile int time_keeper_id = 0; /* smp_processor_id() of time-keeper */ #ifdef CONFIG_IA64_DEBUG_IRQ @@ -71,7 +71,7 @@ timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) new_itm += local_cpu_data->itm_delta; - if (smp_processor_id() == TIME_KEEPER_ID) { + if (smp_processor_id() == time_keeper_id) { /* * Here we are in the timer irq handler. We have irqs locally * disabled, but we don't know if the timer_bh is running on @@ -236,6 +236,11 @@ static struct irqaction timer_irqaction = { .name = "timer" }; +void __devinit ia64_disable_timer(void) +{ + ia64_set_itv(1 << 16); +} + void __init time_init (void) { diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c index acaaec4e4681..9855ba318094 100644 --- a/arch/ia64/mm/contig.c +++ b/arch/ia64/mm/contig.c @@ -181,13 +181,15 @@ per_cpu_init (void) { void *cpu_data; int cpu; + static int first_time=1; /* * get_free_pages() cannot be used before cpu_init() done. BSP * allocates "NR_CPUS" pages for all CPUs to avoid that AP calls * get_zeroed_page(). */ - if (smp_processor_id() == 0) { + if (first_time) { + first_time=0; cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS, PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); for (cpu = 0; cpu < NR_CPUS; cpu++) { diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index c87d6d1d5813..573d5cc63e2b 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -528,12 +528,17 @@ void __init find_memory(void) void *per_cpu_init(void) { int cpu; + static int first_time = 1; + if (smp_processor_id() != 0) return __per_cpu_start + __per_cpu_offset[smp_processor_id()]; - for (cpu = 0; cpu < NR_CPUS; cpu++) - per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu]; + if (first_time) { + first_time = 0; + for (cpu = 0; cpu < NR_CPUS; cpu++) + per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu]; + } return __per_cpu_start + __per_cpu_offset[smp_processor_id()]; } diff --git a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h index c7d9c9ed38ba..bfbbb8da79c7 100644 --- a/include/asm-ia64/mca.h +++ b/include/asm-ia64/mca.h @@ -131,6 +131,8 @@ struct ia64_mca_cpu { /* Array of physical addresses of each CPU's MCA area. */ extern unsigned long __per_cpu_mca[NR_CPUS]; +extern int cpe_vector; +extern int ia64_cpe_irq; extern void ia64_mca_init(void); extern void ia64_mca_cpu_init(void *); extern void ia64_os_mca_dispatch(void); -- cgit v1.2.3 From bfd6057959ecd3ff779a373a4d07cda2c2d0eec1 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 17 Jan 2006 19:34:42 -0500 Subject: From: Borislav Petkov libata new debugging macro definitions Signed-off-by: Borislav Petkov Signed-off-by: Randy Dunlap --- include/linux/libata.h | 52 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/linux/libata.h b/include/linux/libata.h index a43c95f8f968..339f7e75cb60 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -35,7 +35,8 @@ #include /* - * compile-time options + * compile-time options: to be removed as soon as all the drivers are + * converted to the new debugging mechanism */ #undef ATA_DEBUG /* debugging output */ #undef ATA_VERBOSE_DEBUG /* yet more debugging output */ @@ -71,6 +72,38 @@ } #endif +/* NEW: debug levels */ +#define HAVE_LIBATA_MSG 1 + +enum { + ATA_MSG_DRV = 0x0001, + ATA_MSG_INFO = 0x0002, + ATA_MSG_PROBE = 0x0004, + ATA_MSG_WARN = 0x0008, + ATA_MSG_MALLOC = 0x0010, + ATA_MSG_CTL = 0x0020, + ATA_MSG_INTR = 0x0040, + ATA_MSG_ERR = 0x0080, +}; + +#define ata_msg_drv(p) ((p)->msg_enable & ATA_MSG_DRV) +#define ata_msg_info(p) ((p)->msg_enable & ATA_MSG_INFO) +#define ata_msg_probe(p) ((p)->msg_enable & ATA_MSG_PROBE) +#define ata_msg_warn(p) ((p)->msg_enable & ATA_MSG_WARN) +#define ata_msg_malloc(p) ((p)->msg_enable & ATA_MSG_MALLOC) +#define ata_msg_ctl(p) ((p)->msg_enable & ATA_MSG_CTL) +#define ata_msg_intr(p) ((p)->msg_enable & ATA_MSG_INTR) +#define ata_msg_err(p) ((p)->msg_enable & ATA_MSG_ERR) + +static inline u32 ata_msg_init(int dval, int default_msg_enable_bits) +{ + if (dval < 0 || dval >= (sizeof(u32) * 8)) + return default_msg_enable_bits; /* should be 0x1 - only driver info msgs */ + if (!dval) + return 0; + return (1 << dval) - 1; +} + /* defines only for the constants which don't work well as enums */ #define ATA_TAG_POISON 0xfafbfcfdU @@ -356,6 +389,8 @@ struct ata_port { unsigned int hsm_task_state; unsigned long pio_task_timeout; + u32 msg_enable; + void *private_data; }; @@ -640,9 +675,9 @@ static inline u8 ata_wait_idle(struct ata_port *ap) if (status & (ATA_BUSY | ATA_DRQ)) { unsigned long l = ap->ioaddr.status_addr; - printk(KERN_WARNING - "ATA: abnormal status 0x%X on port 0x%lX\n", - status, l); + if (ata_msg_warn(ap)) + printk(KERN_WARNING "ATA: abnormal status 0x%X on port 0x%lX\n", + status, l); } return status; @@ -734,7 +769,8 @@ static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq) status = ata_busy_wait(ap, bits, 1000); if (status & bits) - DPRINTK("abnormal status 0x%X\n", status); + if (ata_msg_err(ap)) + printk(KERN_ERR "abnormal status 0x%X\n", status); /* get controller status; clear intr, err bits */ if (ap->flags & ATA_FLAG_MMIO) { @@ -752,8 +788,10 @@ static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq) post_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); } - VPRINTK("irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n", - host_stat, post_stat, status); + if (ata_msg_intr(ap)) + printk(KERN_INFO "%s: irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n", + __FUNCTION__, + host_stat, post_stat, status); return status; } -- cgit v1.2.3 From 0ce928e1b2ad4309fae6c4324b9e9e433fbf62a2 Mon Sep 17 00:00:00 2001 From: Vitaly Bordug Date: Sun, 15 Jan 2006 17:30:29 +0300 Subject: [PATCH] ppc32 8xx: Added setbitsXX/clrbitsXX macro for read-modify-write operations This adds setbitsXX/clrbitsXX macro for read-modify-write operations and converts the 8xx core and drivers to use them. Signed-off-by: Vitaly Bordug Signed-off-by: Marcelo Tosatti Signed-off-by: Paul Mackerras --- arch/ppc/8xx_io/commproc.c | 6 +++--- arch/ppc/syslib/m8xx_setup.c | 13 +++++++------ arch/ppc/syslib/m8xx_wdt.c | 3 +-- include/asm-ppc/io.h | 7 +++++++ 4 files changed, 18 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c index 579cd40258b9..12b84ca51327 100644 --- a/arch/ppc/8xx_io/commproc.c +++ b/arch/ppc/8xx_io/commproc.c @@ -73,7 +73,7 @@ cpm_mask_irq(unsigned int irq) { int cpm_vec = irq - CPM_IRQ_OFFSET; - out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr, in_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr) & ~(1 << cpm_vec)); + clrbits32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr, (1 << cpm_vec)); } static void @@ -81,7 +81,7 @@ cpm_unmask_irq(unsigned int irq) { int cpm_vec = irq - CPM_IRQ_OFFSET; - out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr, in_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr) | (1 << cpm_vec)); + setbits32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr, (1 << cpm_vec)); } static void @@ -198,7 +198,7 @@ cpm_interrupt_init(void) if (setup_irq(CPM_IRQ_OFFSET + CPMVEC_ERROR, &cpm_error_irqaction)) panic("Could not allocate CPM error IRQ!"); - out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr, in_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr) | CICR_IEN); + setbits32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr, CICR_IEN); } /* diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c index 688616de3cde..ff0282479a78 100644 --- a/arch/ppc/syslib/m8xx_setup.c +++ b/arch/ppc/syslib/m8xx_setup.c @@ -140,9 +140,11 @@ void __init __attribute__ ((weak)) init_internal_rtc(void) { /* Disable the RTC one second and alarm interrupts. */ - out_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, in_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc) & ~(RTCSC_SIE | RTCSC_ALE)); + clrbits16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, (RTCSC_SIE | RTCSC_ALE)); + /* Enable the RTC */ - out_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, in_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc) | (RTCSC_RTF | RTCSC_RTE)); + setbits16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, (RTCSC_RTF | RTCSC_RTE)); + } /* The decrementer counts at the system (internal) clock frequency divided by @@ -159,8 +161,7 @@ void __init m8xx_calibrate_decr(void) out_be32(&((immap_t *)IMAP_ADDR)->im_clkrstk.cark_sccrk, KAPWR_KEY); /* Force all 8xx processors to use divide by 16 processor clock. */ - out_be32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_sccr, - in_be32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_sccr)|0x02000000); + setbits32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_sccr, 0x02000000); /* Processor frequency is MHz. * The value 'fp' is the number of decrementer ticks per second. */ @@ -239,8 +240,8 @@ m8xx_restart(char *cmd) __volatile__ unsigned char dummy; local_irq_disable(); - out_be32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr, in_be32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr) | 0x00000080); + setbits32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr, 0x00000080); /* Clear the ME bit in MSR to cause checkstop on machine check */ mtmsr(mfmsr() & ~0x1000); @@ -310,8 +311,8 @@ m8xx_init_IRQ(void) i8259_init(0); /* The i8259 cascade interrupt must be level sensitive. */ - out_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel, in_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel & ~(0x80000000 >> ISA_BRIDGE_INT))); + clrbits32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel, (0x80000000 >> ISA_BRIDGE_INT)); if (setup_irq(ISA_BRIDGE_INT, &mbx_i8259_irqaction)) enable_irq(ISA_BRIDGE_INT); #endif /* CONFIG_PCI */ diff --git a/arch/ppc/syslib/m8xx_wdt.c b/arch/ppc/syslib/m8xx_wdt.c index df6c9557b86a..ac11d7bab443 100644 --- a/arch/ppc/syslib/m8xx_wdt.c +++ b/arch/ppc/syslib/m8xx_wdt.c @@ -41,8 +41,7 @@ static irqreturn_t m8xx_wdt_interrupt(int irq, void *dev, struct pt_regs *regs) m8xx_wdt_reset(); - out_be16(&imap->im_sit.sit_piscr, in_be16(&imap->im_sit.sit_piscr) | PISCR_PS); /* clear irq */ - + setbits16(&imap->im_sit.sit_piscr, PISCR_PS); return IRQ_HANDLED; } diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h index df9cf6ed189d..b919d8fb7d98 100644 --- a/include/asm-ppc/io.h +++ b/include/asm-ppc/io.h @@ -575,4 +575,11 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *); */ #define xlate_dev_kmem_ptr(p) p +/* access ports */ +#define setbits32(_addr, _v) out_be32((_addr), in_be32(_addr) | (_v)) +#define clrbits32(_addr, _v) out_be32((_addr), in_be32(_addr) & ~(_v)) + +#define setbits16(_addr, _v) out_be16((_addr), in_be16(_addr) | (_v)) +#define clrbits16(_addr, _v) out_be16((_addr), in_be16(_addr) & ~(_v)) + #endif /* __KERNEL__ */ -- cgit v1.2.3 From 0ec57e53c945fe962b190953f61e1ffd127e68d3 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Tue, 17 Jan 2006 00:24:42 -0200 Subject: [PATCH] powerpc: generalize PPC44x_PIN_SIZE The following patch generalizes PPC44x_PIN_SIZE by changing it to PPC_PIN_SIZE, which can be defined by any sub-arch to automatically adjust VMALLOC_START. Define PPC_PIN_SIZE on 8xx, avoiding potential conflicts with the pinned space. Signed-off-by: Marcelo Tosatti Signed-off-by: Paul Mackerras --- arch/ppc/mm/44x_mmu.c | 4 ++-- include/asm-ppc/ibm44x.h | 2 +- include/asm-ppc/mpc8xx.h | 2 ++ include/asm-ppc/pgtable.h | 6 +++--- 4 files changed, 8 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/arch/ppc/mm/44x_mmu.c b/arch/ppc/mm/44x_mmu.c index 3d79ce281b67..e0152a9b26e6 100644 --- a/arch/ppc/mm/44x_mmu.c +++ b/arch/ppc/mm/44x_mmu.c @@ -104,7 +104,7 @@ unsigned long __init mmu_mapin_ram(void) /* Determine number of entries necessary to cover lowmem */ pinned_tlbs = (unsigned int) - (_ALIGN(total_lowmem, PPC44x_PIN_SIZE) >> PPC44x_PIN_SHIFT); + (_ALIGN(total_lowmem, PPC_PIN_SIZE) >> PPC44x_PIN_SHIFT); /* Write upper watermark to save location */ tlb_44x_hwater = PPC44x_LOW_SLOT - pinned_tlbs; @@ -112,7 +112,7 @@ unsigned long __init mmu_mapin_ram(void) /* If necessary, set additional pinned TLBs */ if (pinned_tlbs > 1) for (i = (PPC44x_LOW_SLOT-(pinned_tlbs-1)); i < PPC44x_LOW_SLOT; i++) { - unsigned int phys_addr = (PPC44x_LOW_SLOT-i) * PPC44x_PIN_SIZE; + unsigned int phys_addr = (PPC44x_LOW_SLOT-i) * PPC_PIN_SIZE; ppc44x_pin_tlb(i, phys_addr+PAGE_OFFSET, phys_addr); } diff --git a/include/asm-ppc/ibm44x.h b/include/asm-ppc/ibm44x.h index f835066fb3ca..3acc382cc83f 100644 --- a/include/asm-ppc/ibm44x.h +++ b/include/asm-ppc/ibm44x.h @@ -29,7 +29,7 @@ /* TLB entry offset/size used for pinning kernel lowmem */ #define PPC44x_PIN_SHIFT 28 -#define PPC44x_PIN_SIZE (1 << PPC44x_PIN_SHIFT) +#define PPC_PIN_SIZE (1 << PPC44x_PIN_SHIFT) /* Lowest TLB slot consumed by the default pinned TLBs */ #define PPC44x_LOW_SLOT 63 diff --git a/include/asm-ppc/mpc8xx.h b/include/asm-ppc/mpc8xx.h index 46f159cf589e..73ec9a6db0b1 100644 --- a/include/asm-ppc/mpc8xx.h +++ b/include/asm-ppc/mpc8xx.h @@ -113,6 +113,8 @@ enum ppc_sys_devices { MPC8xx_CPM_USB, }; +#define PPC_PIN_SIZE (24 * 1024 * 1024) /* 24Mbytes of data pinned */ + #ifndef BOARD_CHIP_NAME #define BOARD_CHIP_NAME "" #endif diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h index 6d1c39e8a6af..e1c62da12e74 100644 --- a/include/asm-ppc/pgtable.h +++ b/include/asm-ppc/pgtable.h @@ -12,6 +12,7 @@ #include /* For TASK_SIZE */ #include #include +#include /* For sub-arch specific PPC_PIN_SIZE */ struct mm_struct; extern unsigned long va_to_phys(unsigned long address); @@ -127,9 +128,8 @@ extern unsigned long ioremap_bot, ioremap_base; * of RAM. -- Cort */ #define VMALLOC_OFFSET (0x1000000) /* 16M */ -#ifdef CONFIG_44x -#include -#define VMALLOC_START (((_ALIGN((long)high_memory, PPC44x_PIN_SIZE) + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))) +#ifdef PPC_PIN_SIZE +#define VMALLOC_START (((_ALIGN((long)high_memory, PPC_PIN_SIZE) + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))) #else #define VMALLOC_START ((((long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))) #endif -- cgit v1.2.3 From 4c0f631e14b849782259519c749414b1f1ddbfa8 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Mon, 23 Jan 2006 09:42:06 -0200 Subject: V4L/DVB (3393): Move all IR keymaps to ir-common module - All the keymaps have the same structure, and can be shared between different chips, so it makes no sense having them scattered between the input files. This aggregates them all at ir-common module. - Added new Hauppauge remote (Hauppauge grey), contributed by J.O. Aho (with some small changes) Changed KEY_KPx (keypad numerals) references to KEY_x, to avoid problems when NumLock is off (suggested by Peter Missel ) - Some cleanups at IR code Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/Makefile | 1 + drivers/media/common/ir-common.c | 519 --------- drivers/media/common/ir-keymaps.c | 1537 +++++++++++++++++++++++++++ drivers/media/video/bttv-input.c | 245 ----- drivers/media/video/cx88/cx88-input.c | 331 ------ drivers/media/video/em28xx/em28xx-input.c | 85 -- drivers/media/video/ir-kbd-i2c.c | 41 +- drivers/media/video/saa7134/saa7134-input.c | 501 +-------- include/media/ir-common.h | 42 +- 9 files changed, 1585 insertions(+), 1717 deletions(-) delete mode 100644 drivers/media/common/ir-common.c create mode 100644 drivers/media/common/ir-keymaps.c (limited to 'include') diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile index bd458cb9b4ea..61b89617a967 100644 --- a/drivers/media/common/Makefile +++ b/drivers/media/common/Makefile @@ -1,5 +1,6 @@ saa7146-objs := saa7146_i2c.o saa7146_core.o saa7146_vv-objs := saa7146_vv_ksyms.o saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o +ir-common-objs := ir-functions.o ir-keymaps.o obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c deleted file mode 100644 index 97fa3fc571c4..000000000000 --- a/drivers/media/common/ir-common.c +++ /dev/null @@ -1,519 +0,0 @@ -/* - * - * some common structs and functions to handle infrared remotes via - * input layer ... - * - * (c) 2003 Gerd Knorr [SuSE Labs] - * - * 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. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include - -/* -------------------------------------------------------------------------- */ - -MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); -MODULE_LICENSE("GPL"); - -static int repeat = 1; -module_param(repeat, int, 0444); -MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)"); - -static int debug = 0; /* debug level (0,1,2) */ -module_param(debug, int, 0644); - -#define dprintk(level, fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG fmt , ## arg) - -/* -------------------------------------------------------------------------- */ - -/* generic RC5 keytable */ -/* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ -/* used by old (black) Hauppauge remotes */ -IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { - /* Keys 0 to 9 */ - [ 0x00 ] = KEY_KP0, - [ 0x01 ] = KEY_KP1, - [ 0x02 ] = KEY_KP2, - [ 0x03 ] = KEY_KP3, - [ 0x04 ] = KEY_KP4, - [ 0x05 ] = KEY_KP5, - [ 0x06 ] = KEY_KP6, - [ 0x07 ] = KEY_KP7, - [ 0x08 ] = KEY_KP8, - [ 0x09 ] = KEY_KP9, - - [ 0x0b ] = KEY_CHANNEL, /* channel / program (japan: 11) */ - [ 0x0c ] = KEY_POWER, /* standby */ - [ 0x0d ] = KEY_MUTE, /* mute / demute */ - [ 0x0f ] = KEY_TV, /* display */ - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_VOLUMEDOWN, - [ 0x12 ] = KEY_BRIGHTNESSUP, - [ 0x13 ] = KEY_BRIGHTNESSDOWN, - [ 0x1e ] = KEY_SEARCH, /* search + */ - [ 0x20 ] = KEY_CHANNELUP, /* channel / program + */ - [ 0x21 ] = KEY_CHANNELDOWN, /* channel / program - */ - [ 0x22 ] = KEY_CHANNEL, /* alt / channel */ - [ 0x23 ] = KEY_LANGUAGE, /* 1st / 2nd language */ - [ 0x26 ] = KEY_SLEEP, /* sleeptimer */ - [ 0x2e ] = KEY_MENU, /* 2nd controls (USA: menu) */ - [ 0x30 ] = KEY_PAUSE, - [ 0x32 ] = KEY_REWIND, - [ 0x33 ] = KEY_GOTO, - [ 0x35 ] = KEY_PLAY, - [ 0x36 ] = KEY_STOP, - [ 0x37 ] = KEY_RECORD, /* recording */ - [ 0x3c ] = KEY_TEXT, /* teletext submode (Japan: 12) */ - [ 0x3d ] = KEY_SUSPEND, /* system standby */ - -}; -EXPORT_SYMBOL_GPL(ir_codes_rc5_tv); - -/* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ -IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { - /* Keys 0 to 9 */ - [ 18 ] = KEY_KP0, - [ 5 ] = KEY_KP1, - [ 6 ] = KEY_KP2, - [ 7 ] = KEY_KP3, - [ 9 ] = KEY_KP4, - [ 10 ] = KEY_KP5, - [ 11 ] = KEY_KP6, - [ 13 ] = KEY_KP7, - [ 14 ] = KEY_KP8, - [ 15 ] = KEY_KP9, - - [ 0 ] = KEY_POWER, - [ 2 ] = KEY_TUNER, /* TV/FM */ - [ 30 ] = KEY_VIDEO, - [ 4 ] = KEY_VOLUMEUP, - [ 8 ] = KEY_VOLUMEDOWN, - [ 12 ] = KEY_CHANNELUP, - [ 16 ] = KEY_CHANNELDOWN, - [ 3 ] = KEY_ZOOM, /* fullscreen */ - [ 31 ] = KEY_SUBTITLE, /* closed caption/teletext */ - [ 32 ] = KEY_SLEEP, - [ 20 ] = KEY_MUTE, - [ 43 ] = KEY_RED, - [ 44 ] = KEY_GREEN, - [ 45 ] = KEY_YELLOW, - [ 46 ] = KEY_BLUE, - [ 24 ] = KEY_KPPLUS, /* fine tune + */ - [ 25 ] = KEY_KPMINUS, /* fine tune - */ - [ 33 ] = KEY_KPDOT, - [ 19 ] = KEY_KPENTER, - [ 34 ] = KEY_BACK, - [ 35 ] = KEY_PLAYPAUSE, - [ 36 ] = KEY_NEXT, - [ 38 ] = KEY_STOP, - [ 39 ] = KEY_RECORD -}; -EXPORT_SYMBOL_GPL(ir_codes_winfast); - -IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = { - [ 0x59 ] = KEY_MUTE, - [ 0x4a ] = KEY_POWER, - - [ 0x18 ] = KEY_TEXT, - [ 0x26 ] = KEY_TV, - [ 0x3d ] = KEY_PRINT, - - [ 0x48 ] = KEY_RED, - [ 0x04 ] = KEY_GREEN, - [ 0x11 ] = KEY_YELLOW, - [ 0x00 ] = KEY_BLUE, - - [ 0x2d ] = KEY_VOLUMEUP, - [ 0x1e ] = KEY_VOLUMEDOWN, - - [ 0x49 ] = KEY_MENU, - - [ 0x16 ] = KEY_CHANNELUP, - [ 0x17 ] = KEY_CHANNELDOWN, - - [ 0x20 ] = KEY_UP, - [ 0x21 ] = KEY_DOWN, - [ 0x22 ] = KEY_LEFT, - [ 0x23 ] = KEY_RIGHT, - [ 0x0d ] = KEY_SELECT, - - - - [ 0x08 ] = KEY_BACK, - [ 0x07 ] = KEY_REFRESH, - - [ 0x2f ] = KEY_ZOOM, - [ 0x29 ] = KEY_RECORD, - - [ 0x4b ] = KEY_PAUSE, - [ 0x4d ] = KEY_REWIND, - [ 0x2e ] = KEY_PLAY, - [ 0x4e ] = KEY_FORWARD, - [ 0x53 ] = KEY_PREVIOUS, - [ 0x4c ] = KEY_STOP, - [ 0x54 ] = KEY_NEXT, - - [ 0x69 ] = KEY_KP0, - [ 0x6a ] = KEY_KP1, - [ 0x6b ] = KEY_KP2, - [ 0x6c ] = KEY_KP3, - [ 0x6d ] = KEY_KP4, - [ 0x6e ] = KEY_KP5, - [ 0x6f ] = KEY_KP6, - [ 0x70 ] = KEY_KP7, - [ 0x71 ] = KEY_KP8, - [ 0x72 ] = KEY_KP9, - - [ 0x74 ] = KEY_CHANNEL, - [ 0x0a ] = KEY_BACKSPACE, -}; - -EXPORT_SYMBOL_GPL(ir_codes_pinnacle); - -/* empty keytable, can be used as placeholder for not-yet created keytables */ -IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = { - [ 42 ] = KEY_COFFEE, -}; -EXPORT_SYMBOL_GPL(ir_codes_empty); - -/* Hauppauge: the newer, gray remotes (seems there are multiple - * slightly different versions), shipped with cx88+ivtv cards. - * almost rc5 coding, but some non-standard keys */ -IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { - /* Keys 0 to 9 */ - [ 0x00 ] = KEY_KP0, - [ 0x01 ] = KEY_KP1, - [ 0x02 ] = KEY_KP2, - [ 0x03 ] = KEY_KP3, - [ 0x04 ] = KEY_KP4, - [ 0x05 ] = KEY_KP5, - [ 0x06 ] = KEY_KP6, - [ 0x07 ] = KEY_KP7, - [ 0x08 ] = KEY_KP8, - [ 0x09 ] = KEY_KP9, - - [ 0x0a ] = KEY_TEXT, /* keypad asterisk as well */ - [ 0x0b ] = KEY_RED, /* red button */ - [ 0x0c ] = KEY_RADIO, - [ 0x0d ] = KEY_MENU, - [ 0x0e ] = KEY_SUBTITLE, /* also the # key */ - [ 0x0f ] = KEY_MUTE, - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_VOLUMEDOWN, - [ 0x12 ] = KEY_PREVIOUS, /* previous channel */ - [ 0x14 ] = KEY_UP, - [ 0x15 ] = KEY_DOWN, - [ 0x16 ] = KEY_LEFT, - [ 0x17 ] = KEY_RIGHT, - [ 0x18 ] = KEY_VIDEO, /* Videos */ - [ 0x19 ] = KEY_AUDIO, /* Music */ - /* 0x1a: Pictures - presume this means - "Multimedia Home Platform" - - no "PICTURES" key in input.h - */ - [ 0x1a ] = KEY_MHP, - - [ 0x1b ] = KEY_EPG, /* Guide */ - [ 0x1c ] = KEY_TV, - [ 0x1e ] = KEY_NEXTSONG, /* skip >| */ - [ 0x1f ] = KEY_EXIT, /* back/exit */ - [ 0x20 ] = KEY_CHANNELUP, /* channel / program + */ - [ 0x21 ] = KEY_CHANNELDOWN, /* channel / program - */ - [ 0x22 ] = KEY_CHANNEL, /* source (old black remote) */ - [ 0x24 ] = KEY_PREVIOUSSONG, /* replay |< */ - [ 0x25 ] = KEY_ENTER, /* OK */ - [ 0x26 ] = KEY_SLEEP, /* minimize (old black remote) */ - [ 0x29 ] = KEY_BLUE, /* blue key */ - [ 0x2e ] = KEY_GREEN, /* green button */ - [ 0x30 ] = KEY_PAUSE, /* pause */ - [ 0x32 ] = KEY_REWIND, /* backward << */ - [ 0x34 ] = KEY_FASTFORWARD, /* forward >> */ - [ 0x35 ] = KEY_PLAY, - [ 0x36 ] = KEY_STOP, - [ 0x37 ] = KEY_RECORD, /* recording */ - [ 0x38 ] = KEY_YELLOW, /* yellow key */ - [ 0x3b ] = KEY_SELECT, /* top right button */ - [ 0x3c ] = KEY_ZOOM, /* full */ - [ 0x3d ] = KEY_POWER, /* system power (green button) */ -}; -EXPORT_SYMBOL(ir_codes_hauppauge_new); - -IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { - [ 2 ] = KEY_KP0, - [ 1 ] = KEY_KP1, - [ 11 ] = KEY_KP2, - [ 27 ] = KEY_KP3, - [ 5 ] = KEY_KP4, - [ 9 ] = KEY_KP5, - [ 21 ] = KEY_KP6, - [ 6 ] = KEY_KP7, - [ 10 ] = KEY_KP8, - [ 18 ] = KEY_KP9, - - [ 3 ] = KEY_TUNER, /* TV/FM */ - [ 7 ] = KEY_SEARCH, /* scan */ - [ 28 ] = KEY_ZOOM, /* full screen */ - [ 30 ] = KEY_POWER, - [ 23 ] = KEY_VOLUMEDOWN, - [ 31 ] = KEY_VOLUMEUP, - [ 20 ] = KEY_CHANNELDOWN, - [ 22 ] = KEY_CHANNELUP, - [ 24 ] = KEY_MUTE, - - [ 0 ] = KEY_LIST, /* source */ - [ 19 ] = KEY_INFO, /* loop */ - [ 16 ] = KEY_LAST, /* +100 */ - [ 13 ] = KEY_CLEAR, /* reset */ - [ 12 ] = BTN_RIGHT, /* fun++ */ - [ 4 ] = BTN_LEFT, /* fun-- */ - [ 14 ] = KEY_GOTO, /* function */ - [ 15 ] = KEY_STOP, /* freeze */ -}; -EXPORT_SYMBOL(ir_codes_pixelview); - -/* -------------------------------------------------------------------------- */ - -static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) -{ - if (KEY_RESERVED == ir->keycode) { - printk(KERN_INFO "%s: unknown key: key=0x%02x raw=0x%02x down=%d\n", - dev->name,ir->ir_key,ir->ir_raw,ir->keypressed); - return; - } - dprintk(1,"%s: key event code=%d down=%d\n", - dev->name,ir->keycode,ir->keypressed); - input_report_key(dev,ir->keycode,ir->keypressed); - input_sync(dev); -} - -/* -------------------------------------------------------------------------- */ - -void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, - int ir_type, IR_KEYTAB_TYPE *ir_codes) -{ - int i; - - ir->ir_type = ir_type; - if (ir_codes) - memcpy(ir->ir_codes, ir_codes, sizeof(ir->ir_codes)); - - - dev->keycode = ir->ir_codes; - dev->keycodesize = sizeof(IR_KEYTAB_TYPE); - dev->keycodemax = IR_KEYTAB_SIZE; - for (i = 0; i < IR_KEYTAB_SIZE; i++) - set_bit(ir->ir_codes[i], dev->keybit); - clear_bit(0, dev->keybit); - - set_bit(EV_KEY, dev->evbit); - if (repeat) - set_bit(EV_REP, dev->evbit); -} - -void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir) -{ - if (ir->keypressed) { - ir->keypressed = 0; - ir_input_key_event(dev,ir); - } -} - -void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir, - u32 ir_key, u32 ir_raw) -{ - u32 keycode = IR_KEYCODE(ir->ir_codes, ir_key); - - if (ir->keypressed && ir->keycode != keycode) { - ir->keypressed = 0; - ir_input_key_event(dev,ir); - } - if (!ir->keypressed) { - ir->ir_key = ir_key; - ir->ir_raw = ir_raw; - ir->keycode = keycode; - ir->keypressed = 1; - ir_input_key_event(dev,ir); - } -} - -/* -------------------------------------------------------------------------- */ - -u32 ir_extract_bits(u32 data, u32 mask) -{ - int mbit, vbit; - u32 value; - - value = 0; - vbit = 0; - for (mbit = 0; mbit < 32; mbit++) { - if (!(mask & ((u32)1 << mbit))) - continue; - if (data & ((u32)1 << mbit)) - value |= (1 << vbit); - vbit++; - } - return value; -} - -static int inline getbit(u32 *samples, int bit) -{ - return (samples[bit/32] & (1 << (31-(bit%32)))) ? 1 : 0; -} - -/* sump raw samples for visual debugging ;) */ -int ir_dump_samples(u32 *samples, int count) -{ - int i, bit, start; - - printk(KERN_DEBUG "ir samples: "); - start = 0; - for (i = 0; i < count * 32; i++) { - bit = getbit(samples,i); - if (bit) - start = 1; - if (0 == start) - continue; - printk("%s", bit ? "#" : "_"); - } - printk("\n"); - return 0; -} - -/* decode raw samples, pulse distance coding used by NEC remotes */ -int ir_decode_pulsedistance(u32 *samples, int count, int low, int high) -{ - int i,last,bit,len; - u32 curBit; - u32 value; - - /* find start burst */ - for (i = len = 0; i < count * 32; i++) { - bit = getbit(samples,i); - if (bit) { - len++; - } else { - if (len >= 29) - break; - len = 0; - } - } - - /* start burst to short */ - if (len < 29) - return 0xffffffff; - - /* find start silence */ - for (len = 0; i < count * 32; i++) { - bit = getbit(samples,i); - if (bit) { - break; - } else { - len++; - } - } - - /* silence to short */ - if (len < 7) - return 0xffffffff; - - /* go decoding */ - len = 0; - last = 1; - value = 0; curBit = 1; - for (; i < count * 32; i++) { - bit = getbit(samples,i); - if (last) { - if(bit) { - continue; - } else { - len = 1; - } - } else { - if (bit) { - if (len > (low + high) /2) - value |= curBit; - curBit <<= 1; - if (curBit == 1) - break; - } else { - len++; - } - } - last = bit; - } - - return value; -} - -/* decode raw samples, biphase coding, used by rc5 for example */ -int ir_decode_biphase(u32 *samples, int count, int low, int high) -{ - int i,last,bit,len,flips; - u32 value; - - /* find start bit (1) */ - for (i = 0; i < 32; i++) { - bit = getbit(samples,i); - if (bit) - break; - } - - /* go decoding */ - len = 0; - flips = 0; - value = 1; - for (; i < count * 32; i++) { - if (len > high) - break; - if (flips > 1) - break; - last = bit; - bit = getbit(samples,i); - if (last == bit) { - len++; - continue; - } - if (len < low) { - len++; - flips++; - continue; - } - value <<= 1; - value |= bit; - flips = 0; - len = 1; - } - return value; -} - -EXPORT_SYMBOL_GPL(ir_input_init); -EXPORT_SYMBOL_GPL(ir_input_nokey); -EXPORT_SYMBOL_GPL(ir_input_keydown); - -EXPORT_SYMBOL_GPL(ir_extract_bits); -EXPORT_SYMBOL_GPL(ir_dump_samples); -EXPORT_SYMBOL_GPL(ir_decode_biphase); -EXPORT_SYMBOL_GPL(ir_decode_pulsedistance); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ - diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c new file mode 100644 index 000000000000..468f66013393 --- /dev/null +++ b/drivers/media/common/ir-keymaps.c @@ -0,0 +1,1537 @@ +/* + + + Keytables for supported remote controls. This file is part of + video4linux. + + 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. 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. + + */ +#include +#include + +#include +#include + +/* empty keytable, can be used as placeholder for not-yet created keytables */ +IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = { + [ 0x2a ] = KEY_COFFEE, +}; + +EXPORT_SYMBOL_GPL(ir_codes_empty); + +IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { + [ 0x22 ] = KEY_0, + [ 0x28 ] = KEY_1, + [ 0x18 ] = KEY_2, + [ 0x38 ] = KEY_3, + [ 0x24 ] = KEY_4, + [ 0x14 ] = KEY_5, + [ 0x34 ] = KEY_6, + [ 0x2c ] = KEY_7, + [ 0x1c ] = KEY_8, + [ 0x3c ] = KEY_9, + + [ 0x30 ] = KEY_EJECTCD, // Unmarked on my controller + [ 0x00 ] = KEY_POWER, + [ 0x12 ] = BTN_LEFT, // DISPLAY/L + [ 0x32 ] = BTN_RIGHT, // LOOP/R + [ 0x0a ] = KEY_MUTE, + [ 0x26 ] = KEY_RECORD, + [ 0x16 ] = KEY_PAUSE, + [ 0x36 ] = KEY_STOP, + [ 0x1e ] = KEY_VOLUMEDOWN, + [ 0x3e ] = KEY_VOLUMEUP, + + [ 0x20 ] = KEY_TUNER, // TV/FM + [ 0x10 ] = KEY_CD, + [ 0x08 ] = KEY_VIDEO, + [ 0x04 ] = KEY_AUDIO, + [ 0x0c ] = KEY_ZOOM, // full screen + [ 0x02 ] = KEY_INFO, // preview + [ 0x2a ] = KEY_SEARCH, // autoscan + [ 0x1a ] = KEY_STOP, // freeze + [ 0x3a ] = KEY_RECORD, // capture + [ 0x06 ] = KEY_PLAY, // unmarked + [ 0x2e ] = KEY_RED, // unmarked + [ 0x0e ] = KEY_GREEN, // unmarked + + [ 0x21 ] = KEY_YELLOW, // unmarked + [ 0x11 ] = KEY_CHANNELDOWN, + [ 0x31 ] = KEY_CHANNELUP, + [ 0x01 ] = KEY_BLUE, // unmarked +}; + +EXPORT_SYMBOL_GPL(ir_codes_avermedia); + +/* Matt Jesson >' + [ 0x3a ] = KEY_RECORD, // 'capture' + [ 0x0a ] = KEY_MUTE, // 'mute' + [ 0x2c ] = KEY_RECORD, // 'record' + [ 0x1c ] = KEY_PAUSE, // 'pause' + [ 0x3c ] = KEY_STOP, // 'stop' + [ 0x0c ] = KEY_PLAY, // 'play' + [ 0x2e ] = KEY_RED, // 'red' + [ 0x01 ] = KEY_BLUE, // 'blue' / 'cancel' + [ 0x0e ] = KEY_YELLOW, // 'yellow' / 'ok' + [ 0x21 ] = KEY_GREEN, // 'green' + [ 0x11 ] = KEY_CHANNELDOWN, // 'channel -' + [ 0x31 ] = KEY_CHANNELUP, // 'channel +' + [ 0x1e ] = KEY_VOLUMEDOWN, // 'volume -' + [ 0x3e ] = KEY_VOLUMEUP, // 'volume +' +}; + +EXPORT_SYMBOL_GPL(ir_codes_avermedia_dvbt); + +/* Attila Kondoros */ +IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { + + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + [ 0x00 ] = KEY_0, + [ 0x17 ] = KEY_LAST, // +100 + [ 0x0a ] = KEY_LIST, // recall + + + [ 0x1c ] = KEY_TUNER, // TV/FM + [ 0x15 ] = KEY_SEARCH, // scan + [ 0x12 ] = KEY_POWER, // power + [ 0x1f ] = KEY_VOLUMEDOWN, // vol up + [ 0x1b ] = KEY_VOLUMEUP, // vol down + [ 0x1e ] = KEY_CHANNELDOWN, // chn up + [ 0x1a ] = KEY_CHANNELUP, // chn down + + [ 0x11 ] = KEY_VIDEO, // video + [ 0x0f ] = KEY_ZOOM, // full screen + [ 0x13 ] = KEY_MUTE, // mute/unmute + [ 0x10 ] = KEY_TEXT, // min + + [ 0x0d ] = KEY_STOP, // freeze + [ 0x0e ] = KEY_RECORD, // record + [ 0x1d ] = KEY_PLAYPAUSE, // stop + [ 0x19 ] = KEY_PLAY, // play + + [ 0x16 ] = KEY_GOTO, // osd + [ 0x14 ] = KEY_REFRESH, // default + [ 0x0c ] = KEY_KPPLUS, // fine tune >>>> + [ 0x18 ] = KEY_KPMINUS // fine tune <<<< +}; + +EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp); + +/* ---------------------------------------------------------------------- */ + +IR_KEYTAB_TYPE ir_codes_conceptronic[IR_KEYTAB_SIZE] = { + + [ 0x1e ] = KEY_POWER, // power + [ 0x07 ] = KEY_MEDIA, // source + [ 0x1c ] = KEY_SEARCH, // scan + +/* FIXME: duplicate keycodes? + * + * These four keys seem to share the same GPIO as CH+, CH-, <<< and >>> + * The GPIO values are + * 6397fb for both "Scan <" and "CH -", + * 639ffb for "Scan >" and "CH+", + * 6384fb for "Tune <" and "<<<", + * 638cfb for "Tune >" and ">>>", regardless of the mask. + * + * [ 0x17 ] = KEY_BACK, // fm scan << + * [ 0x1f ] = KEY_FORWARD, // fm scan >> + * + * [ 0x04 ] = KEY_LEFT, // fm tuning < + * [ 0x0c ] = KEY_RIGHT, // fm tuning > + * + * For now, these four keys are disabled. Pressing them will generate + * the CH+/CH-/<<>> events + */ + + [ 0x03 ] = KEY_TUNER, // TV/FM + + [ 0x00 ] = KEY_RECORD, + [ 0x08 ] = KEY_STOP, + [ 0x11 ] = KEY_PLAY, + + [ 0x1a ] = KEY_PLAYPAUSE, // freeze + [ 0x19 ] = KEY_ZOOM, // zoom + [ 0x0f ] = KEY_TEXT, // min + + [ 0x01 ] = KEY_1, + [ 0x0b ] = KEY_2, + [ 0x1b ] = KEY_3, + [ 0x05 ] = KEY_4, + [ 0x09 ] = KEY_5, + [ 0x15 ] = KEY_6, + [ 0x06 ] = KEY_7, + [ 0x0a ] = KEY_8, + [ 0x12 ] = KEY_9, + [ 0x02 ] = KEY_0, + [ 0x10 ] = KEY_LAST, // +100 + [ 0x13 ] = KEY_LIST, // recall + + [ 0x1f ] = KEY_CHANNELUP, // chn down + [ 0x17 ] = KEY_CHANNELDOWN, // chn up + [ 0x16 ] = KEY_VOLUMEUP, // vol down + [ 0x14 ] = KEY_VOLUMEDOWN, // vol up + + [ 0x04 ] = KEY_KPMINUS, // <<< + [ 0x0e ] = KEY_SETUP, // function + [ 0x0c ] = KEY_KPPLUS, // >>> + + [ 0x0d ] = KEY_GOTO, // mts + [ 0x1d ] = KEY_REFRESH, // reset + [ 0x18 ] = KEY_MUTE // mute/unmute +}; + +EXPORT_SYMBOL_GPL(ir_codes_conceptronic); + +IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = { + [ 0x00 ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + [ 0x0a ] = KEY_TV, + [ 0x0b ] = KEY_AUX, + [ 0x0c ] = KEY_DVD, + [ 0x0d ] = KEY_POWER, + [ 0x0e ] = KEY_MHP, /* labelled 'Picture' */ + [ 0x0f ] = KEY_AUDIO, + [ 0x10 ] = KEY_INFO, + [ 0x11 ] = KEY_F13, /* 16:9 */ + [ 0x12 ] = KEY_F14, /* 14:9 */ + [ 0x13 ] = KEY_EPG, + [ 0x14 ] = KEY_EXIT, + [ 0x15 ] = KEY_MENU, + [ 0x16 ] = KEY_UP, + [ 0x17 ] = KEY_DOWN, + [ 0x18 ] = KEY_LEFT, + [ 0x19 ] = KEY_RIGHT, + [ 0x1a ] = KEY_ENTER, + [ 0x1b ] = KEY_CHANNELUP, + [ 0x1c ] = KEY_CHANNELDOWN, + [ 0x1d ] = KEY_VOLUMEUP, + [ 0x1e ] = KEY_VOLUMEDOWN, + [ 0x1f ] = KEY_RED, + [ 0x20 ] = KEY_GREEN, + [ 0x21 ] = KEY_YELLOW, + [ 0x22 ] = KEY_BLUE, + [ 0x23 ] = KEY_SUBTITLE, + [ 0x24 ] = KEY_F15, /* AD */ + [ 0x25 ] = KEY_TEXT, + [ 0x26 ] = KEY_MUTE, + [ 0x27 ] = KEY_REWIND, + [ 0x28 ] = KEY_STOP, + [ 0x29 ] = KEY_PLAY, + [ 0x2a ] = KEY_FASTFORWARD, + [ 0x2b ] = KEY_F16, /* chapter */ + [ 0x2c ] = KEY_PAUSE, + [ 0x2d ] = KEY_PLAY, + [ 0x2e ] = KEY_RECORD, + [ 0x2f ] = KEY_F17, /* picture in picture */ + [ 0x30 ] = KEY_KPPLUS, /* zoom in */ + [ 0x31 ] = KEY_KPMINUS, /* zoom out */ + [ 0x32 ] = KEY_F18, /* capture */ + [ 0x33 ] = KEY_F19, /* web */ + [ 0x34 ] = KEY_EMAIL, + [ 0x35 ] = KEY_PHONE, + [ 0x36 ] = KEY_PC +}; + +EXPORT_SYMBOL_GPL(ir_codes_nebula); + +/* DigitalNow DNTV Live DVB-T Remote */ +IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE] = { + [ 0x00 ] = KEY_ESC, /* 'go up a level?' */ + /* Keys 0 to 9 */ + [ 0x0a ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + + [ 0x0b ] = KEY_TUNER, /* tv/fm */ + [ 0x0c ] = KEY_SEARCH, /* scan */ + [ 0x0d ] = KEY_STOP, + [ 0x0e ] = KEY_PAUSE, + [ 0x0f ] = KEY_LIST, /* source */ + + [ 0x10 ] = KEY_MUTE, + [ 0x11 ] = KEY_REWIND, /* backward << */ + [ 0x12 ] = KEY_POWER, + [ 0x13 ] = KEY_S, /* snap */ + [ 0x14 ] = KEY_AUDIO, /* stereo */ + [ 0x15 ] = KEY_CLEAR, /* reset */ + [ 0x16 ] = KEY_PLAY, + [ 0x17 ] = KEY_ENTER, + [ 0x18 ] = KEY_ZOOM, /* full screen */ + [ 0x19 ] = KEY_FASTFORWARD, /* forward >> */ + [ 0x1a ] = KEY_CHANNELUP, + [ 0x1b ] = KEY_VOLUMEUP, + [ 0x1c ] = KEY_INFO, /* preview */ + [ 0x1d ] = KEY_RECORD, /* record */ + [ 0x1e ] = KEY_CHANNELDOWN, + [ 0x1f ] = KEY_VOLUMEDOWN, +}; + +EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvb_t); + +/* ---------------------------------------------------------------------- */ + +/* IO-DATA BCTV7E Remote */ +IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = { + [ 0x40 ] = KEY_TV, + [ 0x20 ] = KEY_RADIO, /* FM */ + [ 0x60 ] = KEY_EPG, + [ 0x00 ] = KEY_POWER, + + /* Keys 0 to 9 */ + [ 0x44 ] = KEY_0, /* 10 */ + [ 0x50 ] = KEY_1, + [ 0x30 ] = KEY_2, + [ 0x70 ] = KEY_3, + [ 0x48 ] = KEY_4, + [ 0x28 ] = KEY_5, + [ 0x68 ] = KEY_6, + [ 0x58 ] = KEY_7, + [ 0x38 ] = KEY_8, + [ 0x78 ] = KEY_9, + + [ 0x10 ] = KEY_L, /* Live */ + [ 0x08 ] = KEY_T, /* Time Shift */ + + [ 0x18 ] = KEY_PLAYPAUSE, /* Play */ + + [ 0x24 ] = KEY_ENTER, /* 11 */ + [ 0x64 ] = KEY_ESC, /* 12 */ + [ 0x04 ] = KEY_M, /* Multi */ + + [ 0x54 ] = KEY_VIDEO, + [ 0x34 ] = KEY_CHANNELUP, + [ 0x74 ] = KEY_VOLUMEUP, + [ 0x14 ] = KEY_MUTE, + + [ 0x4c ] = KEY_S, /* SVIDEO */ + [ 0x2c ] = KEY_CHANNELDOWN, + [ 0x6c ] = KEY_VOLUMEDOWN, + [ 0x0c ] = KEY_ZOOM, + + [ 0x5c ] = KEY_PAUSE, + [ 0x3c ] = KEY_C, /* || (red) */ + [ 0x7c ] = KEY_RECORD, /* recording */ + [ 0x1c ] = KEY_STOP, + + [ 0x41 ] = KEY_REWIND, /* backward << */ + [ 0x21 ] = KEY_PLAY, + [ 0x61 ] = KEY_FASTFORWARD, /* forward >> */ + [ 0x01 ] = KEY_NEXT, /* skip >| */ +}; + +EXPORT_SYMBOL_GPL(ir_codes_iodata_bctv7e); + +/* ---------------------------------------------------------------------- */ + +/* ADS Tech Instant TV DVB-T PCI Remote */ +IR_KEYTAB_TYPE ir_codes_adstech_dvb_t_pci[IR_KEYTAB_SIZE] = { + /* Keys 0 to 9 */ + [ 0x4d ] = KEY_0, + [ 0x57 ] = KEY_1, + [ 0x4f ] = KEY_2, + [ 0x53 ] = KEY_3, + [ 0x56 ] = KEY_4, + [ 0x4e ] = KEY_5, + [ 0x5e ] = KEY_6, + [ 0x54 ] = KEY_7, + [ 0x4c ] = KEY_8, + [ 0x5c ] = KEY_9, + + [ 0x5b ] = KEY_POWER, + [ 0x5f ] = KEY_MUTE, + [ 0x55 ] = KEY_GOTO, + [ 0x5d ] = KEY_SEARCH, + [ 0x17 ] = KEY_EPG, /* Guide */ + [ 0x1f ] = KEY_MENU, + [ 0x0f ] = KEY_UP, + [ 0x46 ] = KEY_DOWN, + [ 0x16 ] = KEY_LEFT, + [ 0x1e ] = KEY_RIGHT, + [ 0x0e ] = KEY_SELECT, /* Enter */ + [ 0x5a ] = KEY_INFO, + [ 0x52 ] = KEY_EXIT, + [ 0x59 ] = KEY_PREVIOUS, + [ 0x51 ] = KEY_NEXT, + [ 0x58 ] = KEY_REWIND, + [ 0x50 ] = KEY_FORWARD, + [ 0x44 ] = KEY_PLAYPAUSE, + [ 0x07 ] = KEY_STOP, + [ 0x1b ] = KEY_RECORD, + [ 0x13 ] = KEY_TUNER, /* Live */ + [ 0x0a ] = KEY_A, + [ 0x12 ] = KEY_B, + [ 0x03 ] = KEY_PROG1, /* 1 */ + [ 0x01 ] = KEY_PROG2, /* 2 */ + [ 0x00 ] = KEY_PROG3, /* 3 */ + [ 0x06 ] = KEY_DVD, + [ 0x48 ] = KEY_AUX, /* Photo */ + [ 0x40 ] = KEY_VIDEO, + [ 0x19 ] = KEY_AUDIO, /* Music */ + [ 0x0b ] = KEY_CHANNELUP, + [ 0x08 ] = KEY_CHANNELDOWN, + [ 0x15 ] = KEY_VOLUMEUP, + [ 0x1c ] = KEY_VOLUMEDOWN, +}; + +EXPORT_SYMBOL_GPL(ir_codes_adstech_dvb_t_pci); + +/* ---------------------------------------------------------------------- */ + +/* MSI TV@nywhere remote */ +IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = { + /* Keys 0 to 9 */ + [ 0x00 ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + + [ 0x0c ] = KEY_MUTE, + [ 0x0f ] = KEY_SCREEN, /* Full Screen */ + [ 0x10 ] = KEY_F, /* Funtion */ + [ 0x11 ] = KEY_T, /* Time shift */ + [ 0x12 ] = KEY_POWER, + [ 0x13 ] = KEY_MEDIA, /* MTS */ + [ 0x14 ] = KEY_SLOW, + [ 0x16 ] = KEY_REWIND, /* backward << */ + [ 0x17 ] = KEY_ENTER, /* Return */ + [ 0x18 ] = KEY_FASTFORWARD, /* forward >> */ + [ 0x1a ] = KEY_CHANNELUP, + [ 0x1b ] = KEY_VOLUMEUP, + [ 0x1e ] = KEY_CHANNELDOWN, + [ 0x1f ] = KEY_VOLUMEDOWN, +}; + +EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere); + +/* ---------------------------------------------------------------------- */ + +/* Cinergy 1400 DVB-T */ +IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = { + [ 0x01 ] = KEY_POWER, + [ 0x02 ] = KEY_1, + [ 0x03 ] = KEY_2, + [ 0x04 ] = KEY_3, + [ 0x05 ] = KEY_4, + [ 0x06 ] = KEY_5, + [ 0x07 ] = KEY_6, + [ 0x08 ] = KEY_7, + [ 0x09 ] = KEY_8, + [ 0x0a ] = KEY_9, + [ 0x0c ] = KEY_0, + + [ 0x0b ] = KEY_VIDEO, + [ 0x0d ] = KEY_REFRESH, + [ 0x0e ] = KEY_SELECT, + [ 0x0f ] = KEY_EPG, + [ 0x10 ] = KEY_UP, + [ 0x11 ] = KEY_LEFT, + [ 0x12 ] = KEY_OK, + [ 0x13 ] = KEY_RIGHT, + [ 0x14 ] = KEY_DOWN, + [ 0x15 ] = KEY_TEXT, + [ 0x16 ] = KEY_INFO, + + [ 0x17 ] = KEY_RED, + [ 0x18 ] = KEY_GREEN, + [ 0x19 ] = KEY_YELLOW, + [ 0x1a ] = KEY_BLUE, + + [ 0x1b ] = KEY_CHANNELUP, + [ 0x1c ] = KEY_VOLUMEUP, + [ 0x1d ] = KEY_MUTE, + [ 0x1e ] = KEY_VOLUMEDOWN, + [ 0x1f ] = KEY_CHANNELDOWN, + + [ 0x40 ] = KEY_PAUSE, + [ 0x4c ] = KEY_PLAY, + [ 0x58 ] = KEY_RECORD, + [ 0x54 ] = KEY_PREVIOUS, + [ 0x48 ] = KEY_STOP, + [ 0x5c ] = KEY_NEXT, +}; + +EXPORT_SYMBOL_GPL(ir_codes_cinergy_1400); + +/* ---------------------------------------------------------------------- */ + +/* AVERTV STUDIO 303 Remote */ +IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE] = { + [ 0x2a ] = KEY_1, + [ 0x32 ] = KEY_2, + [ 0x3a ] = KEY_3, + [ 0x4a ] = KEY_4, + [ 0x52 ] = KEY_5, + [ 0x5a ] = KEY_6, + [ 0x6a ] = KEY_7, + [ 0x72 ] = KEY_8, + [ 0x7a ] = KEY_9, + [ 0x0e ] = KEY_0, + + [ 0x02 ] = KEY_POWER, + [ 0x22 ] = KEY_VIDEO, + [ 0x42 ] = KEY_AUDIO, + [ 0x62 ] = KEY_ZOOM, + [ 0x0a ] = KEY_TV, + [ 0x12 ] = KEY_CD, + [ 0x1a ] = KEY_TEXT, + + [ 0x16 ] = KEY_SUBTITLE, + [ 0x1e ] = KEY_REWIND, + [ 0x06 ] = KEY_PRINT, + + [ 0x2e ] = KEY_SEARCH, + [ 0x36 ] = KEY_SLEEP, + [ 0x3e ] = KEY_SHUFFLE, + [ 0x26 ] = KEY_MUTE, + + [ 0x4e ] = KEY_RECORD, + [ 0x56 ] = KEY_PAUSE, + [ 0x5e ] = KEY_STOP, + [ 0x46 ] = KEY_PLAY, + + [ 0x6e ] = KEY_RED, + [ 0x0b ] = KEY_GREEN, + [ 0x66 ] = KEY_YELLOW, + [ 0x03 ] = KEY_BLUE, + + [ 0x76 ] = KEY_LEFT, + [ 0x7e ] = KEY_RIGHT, + [ 0x13 ] = KEY_DOWN, + [ 0x1b ] = KEY_UP, +}; + +EXPORT_SYMBOL_GPL(ir_codes_avertv_303); + +/* ---------------------------------------------------------------------- */ + +/* DigitalNow DNTV Live! DVB-T Pro Remote */ +IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE] = { + [ 0x16 ] = KEY_POWER, + [ 0x5b ] = KEY_HOME, + + [ 0x55 ] = KEY_TV, /* live tv */ + [ 0x58 ] = KEY_TUNER, /* digital Radio */ + [ 0x5a ] = KEY_RADIO, /* FM radio */ + [ 0x59 ] = KEY_DVD, /* dvd menu */ + [ 0x03 ] = KEY_1, + [ 0x01 ] = KEY_2, + [ 0x06 ] = KEY_3, + [ 0x09 ] = KEY_4, + [ 0x1d ] = KEY_5, + [ 0x1f ] = KEY_6, + [ 0x0d ] = KEY_7, + [ 0x19 ] = KEY_8, + [ 0x1b ] = KEY_9, + [ 0x0c ] = KEY_CANCEL, + [ 0x15 ] = KEY_0, + [ 0x4a ] = KEY_CLEAR, + [ 0x13 ] = KEY_BACK, + [ 0x00 ] = KEY_TAB, + [ 0x4b ] = KEY_UP, + [ 0x4e ] = KEY_LEFT, + [ 0x4f ] = KEY_OK, + [ 0x52 ] = KEY_RIGHT, + [ 0x51 ] = KEY_DOWN, + [ 0x1e ] = KEY_VOLUMEUP, + [ 0x0a ] = KEY_VOLUMEDOWN, + [ 0x02 ] = KEY_CHANNELDOWN, + [ 0x05 ] = KEY_CHANNELUP, + [ 0x11 ] = KEY_RECORD, + [ 0x14 ] = KEY_PLAY, + [ 0x4c ] = KEY_PAUSE, + [ 0x1a ] = KEY_STOP, + [ 0x40 ] = KEY_REWIND, + [ 0x12 ] = KEY_FASTFORWARD, + [ 0x41 ] = KEY_PREVIOUSSONG, /* replay |< */ + [ 0x42 ] = KEY_NEXTSONG, /* skip >| */ + [ 0x54 ] = KEY_CAMERA, /* capture */ + [ 0x50 ] = KEY_LANGUAGE, /* sap */ + [ 0x47 ] = KEY_TV2, /* pip */ + [ 0x4d ] = KEY_SCREEN, + [ 0x43 ] = KEY_SUBTITLE, + [ 0x10 ] = KEY_MUTE, + [ 0x49 ] = KEY_AUDIO, /* l/r */ + [ 0x07 ] = KEY_SLEEP, + [ 0x08 ] = KEY_VIDEO, /* a/v */ + [ 0x0e ] = KEY_PREVIOUS, /* recall */ + [ 0x45 ] = KEY_ZOOM, /* zoom + */ + [ 0x46 ] = KEY_ANGLE, /* zoom - */ + [ 0x56 ] = KEY_RED, + [ 0x57 ] = KEY_GREEN, + [ 0x5c ] = KEY_YELLOW, + [ 0x5d ] = KEY_BLUE, +}; + +EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvbt_pro); + +IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = { + [ 0x01 ] = KEY_CHANNEL, + [ 0x02 ] = KEY_SELECT, + [ 0x03 ] = KEY_MUTE, + [ 0x04 ] = KEY_POWER, + [ 0x05 ] = KEY_1, + [ 0x06 ] = KEY_2, + [ 0x07 ] = KEY_3, + [ 0x08 ] = KEY_CHANNELUP, + [ 0x09 ] = KEY_4, + [ 0x0a ] = KEY_5, + [ 0x0b ] = KEY_6, + [ 0x0c ] = KEY_CHANNELDOWN, + [ 0x0d ] = KEY_7, + [ 0x0e ] = KEY_8, + [ 0x0f ] = KEY_9, + [ 0x10 ] = KEY_VOLUMEUP, + [ 0x11 ] = KEY_0, + [ 0x12 ] = KEY_MENU, + [ 0x13 ] = KEY_PRINT, + [ 0x14 ] = KEY_VOLUMEDOWN, + [ 0x16 ] = KEY_PAUSE, + [ 0x18 ] = KEY_RECORD, + [ 0x19 ] = KEY_REWIND, + [ 0x1a ] = KEY_PLAY, + [ 0x1b ] = KEY_FORWARD, + [ 0x1c ] = KEY_BACKSPACE, + [ 0x1e ] = KEY_STOP, + [ 0x40 ] = KEY_ZOOM, +}; + +EXPORT_SYMBOL_GPL(ir_codes_em_terratec); + +IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = { + [ 0x3a ] = KEY_0, + [ 0x31 ] = KEY_1, + [ 0x32 ] = KEY_2, + [ 0x33 ] = KEY_3, + [ 0x34 ] = KEY_4, + [ 0x35 ] = KEY_5, + [ 0x36 ] = KEY_6, + [ 0x37 ] = KEY_7, + [ 0x38 ] = KEY_8, + [ 0x39 ] = KEY_9, + + [ 0x2f ] = KEY_POWER, + + [ 0x2e ] = KEY_P, + [ 0x1f ] = KEY_L, + [ 0x2b ] = KEY_I, + + [ 0x2d ] = KEY_ZOOM, + [ 0x1e ] = KEY_ZOOM, + [ 0x1b ] = KEY_VOLUMEUP, + [ 0x0f ] = KEY_VOLUMEDOWN, + [ 0x17 ] = KEY_CHANNELUP, + [ 0x1c ] = KEY_CHANNELDOWN, + [ 0x25 ] = KEY_INFO, + + [ 0x3c ] = KEY_MUTE, + + [ 0x3d ] = KEY_LEFT, + [ 0x3b ] = KEY_RIGHT, + + [ 0x3f ] = KEY_UP, + [ 0x3e ] = KEY_DOWN, + [ 0x1a ] = KEY_PAUSE, + + [ 0x1d ] = KEY_MENU, + [ 0x19 ] = KEY_PLAY, + [ 0x16 ] = KEY_REWIND, + [ 0x13 ] = KEY_FORWARD, + [ 0x15 ] = KEY_PAUSE, + [ 0x0e ] = KEY_REWIND, + [ 0x0d ] = KEY_PLAY, + [ 0x0b ] = KEY_STOP, + [ 0x07 ] = KEY_FORWARD, + [ 0x27 ] = KEY_RECORD, + [ 0x26 ] = KEY_TUNER, + [ 0x29 ] = KEY_TEXT, + [ 0x2a ] = KEY_MEDIA, + [ 0x18 ] = KEY_EPG, + [ 0x27 ] = KEY_RECORD, +}; + +EXPORT_SYMBOL_GPL(ir_codes_em_pinnacle_usb); + +IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = { + [ 0x0f ] = KEY_0, + [ 0x03 ] = KEY_1, + [ 0x04 ] = KEY_2, + [ 0x05 ] = KEY_3, + [ 0x07 ] = KEY_4, + [ 0x08 ] = KEY_5, + [ 0x09 ] = KEY_6, + [ 0x0b ] = KEY_7, + [ 0x0c ] = KEY_8, + [ 0x0d ] = KEY_9, + + [ 0x0e ] = KEY_MODE, // Air/Cable + [ 0x11 ] = KEY_VIDEO, // Video + [ 0x15 ] = KEY_AUDIO, // Audio + [ 0x00 ] = KEY_POWER, // Power + [ 0x18 ] = KEY_TUNER, // AV Source + [ 0x02 ] = KEY_ZOOM, // Fullscreen + [ 0x1a ] = KEY_LANGUAGE, // Stereo + [ 0x1b ] = KEY_MUTE, // Mute + [ 0x14 ] = KEY_VOLUMEUP, // Volume + + [ 0x17 ] = KEY_VOLUMEDOWN, // Volume - + [ 0x12 ] = KEY_CHANNELUP, // Channel + + [ 0x13 ] = KEY_CHANNELDOWN, // Channel - + [ 0x06 ] = KEY_AGAIN, // Recall + [ 0x10 ] = KEY_ENTER, // Enter +}; + +EXPORT_SYMBOL_GPL(ir_codes_flyvideo); + +IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE] = { + [ 0x01 ] = KEY_ZOOM, // Full Screen + [ 0x00 ] = KEY_POWER, // Power + + [ 0x03 ] = KEY_1, + [ 0x04 ] = KEY_2, + [ 0x05 ] = KEY_3, + [ 0x07 ] = KEY_4, + [ 0x08 ] = KEY_5, + [ 0x09 ] = KEY_6, + [ 0x0b ] = KEY_7, + [ 0x0c ] = KEY_8, + [ 0x0d ] = KEY_9, + [ 0x06 ] = KEY_AGAIN, // Recall + [ 0x0f ] = KEY_0, + [ 0x10 ] = KEY_MUTE, // Mute + [ 0x02 ] = KEY_RADIO, // TV/Radio + [ 0x1b ] = KEY_LANGUAGE, // SAP (Second Audio Program) + + [ 0x14 ] = KEY_VOLUMEUP, // VOL+ + [ 0x17 ] = KEY_VOLUMEDOWN, // VOL- + [ 0x12 ] = KEY_CHANNELUP, // CH+ + [ 0x13 ] = KEY_CHANNELDOWN, // CH- + [ 0x1d ] = KEY_ENTER, // Enter + + [ 0x1a ] = KEY_MODE, // PIP + [ 0x18 ] = KEY_TUNER, // Source + + [ 0x1e ] = KEY_RECORD, // Record/Pause + [ 0x15 ] = KEY_ANGLE, // Swap (no label on key) + [ 0x1c ] = KEY_PAUSE, // Timeshift/Pause + [ 0x19 ] = KEY_BACK, // Rewind << + [ 0x0a ] = KEY_PLAYPAUSE, // Play/Pause + [ 0x1f ] = KEY_FORWARD, // Forward >> + [ 0x16 ] = KEY_PREVIOUS, // Back |<< + [ 0x11 ] = KEY_STOP, // Stop + [ 0x0e ] = KEY_NEXT, // End >>| +}; + +EXPORT_SYMBOL_GPL(ir_codes_flydvb); + +IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE] = { + [ 0x00 ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + + [ 0x0a ] = KEY_POWER, + [ 0x0b ] = KEY_PROG1, // app + [ 0x0c ] = KEY_ZOOM, // zoom/fullscreen + [ 0x0d ] = KEY_CHANNELUP, // channel + [ 0x0e ] = KEY_CHANNELDOWN, // channel- + [ 0x0f ] = KEY_VOLUMEUP, + [ 0x10 ] = KEY_VOLUMEDOWN, + [ 0x11 ] = KEY_TUNER, // AV + [ 0x12 ] = KEY_NUMLOCK, // -/-- + [ 0x13 ] = KEY_AUDIO, // audio + [ 0x14 ] = KEY_MUTE, + [ 0x15 ] = KEY_UP, + [ 0x16 ] = KEY_DOWN, + [ 0x17 ] = KEY_LEFT, + [ 0x18 ] = KEY_RIGHT, + [ 0x19 ] = BTN_LEFT, + [ 0x1a ] = BTN_RIGHT, + [ 0x1b ] = KEY_WWW, // text + [ 0x1c ] = KEY_REWIND, + [ 0x1d ] = KEY_FORWARD, + [ 0x1e ] = KEY_RECORD, + [ 0x1f ] = KEY_PLAY, + [ 0x20 ] = KEY_PREVIOUSSONG, + [ 0x21 ] = KEY_NEXTSONG, + [ 0x22 ] = KEY_PAUSE, + [ 0x23 ] = KEY_STOP, +}; + +EXPORT_SYMBOL_GPL(ir_codes_cinergy); + +/* Alfons Geser + * updates from Job D. R. Borges */ +IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE] = { + [ 0x12 ] = KEY_POWER, + [ 0x01 ] = KEY_TV, // DVR + [ 0x15 ] = KEY_DVD, // DVD + [ 0x17 ] = KEY_AUDIO, // music + // DVR mode / DVD mode / music mode + + [ 0x1b ] = KEY_MUTE, // mute + [ 0x02 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek + [ 0x1e ] = KEY_SUBTITLE, // closed captioning / subtitle / seek + [ 0x16 ] = KEY_ZOOM, // full screen + [ 0x1c ] = KEY_VIDEO, // video source / eject / delall + [ 0x1d ] = KEY_RESTART, // playback / angle / del + [ 0x2f ] = KEY_SEARCH, // scan / menu / playlist + [ 0x30 ] = KEY_CHANNEL, // CH surfing / bookmark / memo + + [ 0x31 ] = KEY_HELP, // help + [ 0x32 ] = KEY_MODE, // num/memo + [ 0x33 ] = KEY_ESC, // cancel + + [ 0x0c ] = KEY_UP, // up + [ 0x10 ] = KEY_DOWN, // down + [ 0x08 ] = KEY_LEFT, // left + [ 0x04 ] = KEY_RIGHT, // right + [ 0x03 ] = KEY_SELECT, // select + + [ 0x1f ] = KEY_REWIND, // rewind + [ 0x20 ] = KEY_PLAYPAUSE, // play/pause + [ 0x29 ] = KEY_FORWARD, // forward + [ 0x14 ] = KEY_AGAIN, // repeat + [ 0x2b ] = KEY_RECORD, // recording + [ 0x2c ] = KEY_STOP, // stop + [ 0x2d ] = KEY_PLAY, // play + [ 0x2e ] = KEY_SHUFFLE, // snapshot / shuffle + + [ 0x00 ] = KEY_0, + [ 0x05 ] = KEY_1, + [ 0x06 ] = KEY_2, + [ 0x07 ] = KEY_3, + [ 0x09 ] = KEY_4, + [ 0x0a ] = KEY_5, + [ 0x0b ] = KEY_6, + [ 0x0d ] = KEY_7, + [ 0x0e ] = KEY_8, + [ 0x0f ] = KEY_9, + + [ 0x2a ] = KEY_VOLUMEUP, + [ 0x11 ] = KEY_VOLUMEDOWN, + [ 0x18 ] = KEY_CHANNELUP, // CH.tracking up + [ 0x19 ] = KEY_CHANNELDOWN, // CH.tracking down + + [ 0x13 ] = KEY_ENTER, // enter + [ 0x21 ] = KEY_DOT, // . (decimal dot) +}; + +EXPORT_SYMBOL_GPL(ir_codes_eztv); + +IR_KEYTAB_TYPE ir_codes_avacssmart[IR_KEYTAB_SIZE] = { + [ 0x1e ] = KEY_POWER, // power + [ 0x1c ] = KEY_SEARCH, // scan + [ 0x07 ] = KEY_SELECT, // source + + [ 0x16 ] = KEY_VOLUMEUP, + [ 0x14 ] = KEY_VOLUMEDOWN, + [ 0x1f ] = KEY_CHANNELUP, + [ 0x17 ] = KEY_CHANNELDOWN, + [ 0x18 ] = KEY_MUTE, + + [ 0x02 ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x0b ] = KEY_2, + [ 0x1b ] = KEY_3, + [ 0x05 ] = KEY_4, + [ 0x09 ] = KEY_5, + [ 0x15 ] = KEY_6, + [ 0x06 ] = KEY_7, + [ 0x0a ] = KEY_8, + [ 0x12 ] = KEY_9, + [ 0x10 ] = KEY_DOT, + + [ 0x03 ] = KEY_TUNER, // tv/fm + [ 0x04 ] = KEY_REWIND, // fm tuning left or function left + [ 0x0c ] = KEY_FORWARD, // fm tuning right or function right + + [ 0x00 ] = KEY_RECORD, + [ 0x08 ] = KEY_STOP, + [ 0x11 ] = KEY_PLAY, + + [ 0x19 ] = KEY_ZOOM, + [ 0x0e ] = KEY_MENU, // function + [ 0x13 ] = KEY_AGAIN, // recall + [ 0x1d ] = KEY_RESTART, // reset + [ 0x1a ] = KEY_SHUFFLE, // snapshot/shuffle + +// FIXME + [ 0x0d ] = KEY_F21, // mts + [ 0x0f ] = KEY_F22, // min +}; + +EXPORT_SYMBOL_GPL(ir_codes_avacssmart); + +/* Alex Hermann */ +IR_KEYTAB_TYPE ir_codes_md2819[IR_KEYTAB_SIZE] = { + [ 0x28 ] = KEY_1, + [ 0x18 ] = KEY_2, + [ 0x38 ] = KEY_3, + [ 0x24 ] = KEY_4, + [ 0x14 ] = KEY_5, + [ 0x34 ] = KEY_6, + [ 0x2c ] = KEY_7, + [ 0x1c ] = KEY_8, + [ 0x3c ] = KEY_9, + [ 0x22 ] = KEY_0, + + [ 0x20 ] = KEY_TV, // TV/FM + [ 0x10 ] = KEY_CD, // CD + [ 0x30 ] = KEY_TEXT, // TELETEXT + [ 0x00 ] = KEY_POWER, // POWER + + [ 0x08 ] = KEY_VIDEO, // VIDEO + [ 0x04 ] = KEY_AUDIO, // AUDIO + [ 0x0c ] = KEY_ZOOM, // FULL SCREEN + + [ 0x12 ] = KEY_SUBTITLE, // DISPLAY - ??? + [ 0x32 ] = KEY_REWIND, // LOOP - ??? + [ 0x02 ] = KEY_PRINT, // PREVIEW - ??? + + [ 0x2a ] = KEY_SEARCH, // AUTOSCAN + [ 0x1a ] = KEY_SLEEP, // FREEZE - ??? + [ 0x3a ] = KEY_SHUFFLE, // SNAPSHOT - ??? + [ 0x0a ] = KEY_MUTE, // MUTE + + [ 0x26 ] = KEY_RECORD, // RECORD + [ 0x16 ] = KEY_PAUSE, // PAUSE + [ 0x36 ] = KEY_STOP, // STOP + [ 0x06 ] = KEY_PLAY, // PLAY + + [ 0x2e ] = KEY_RED, // + [ 0x21 ] = KEY_GREEN, // + [ 0x0e ] = KEY_YELLOW, // + [ 0x01 ] = KEY_BLUE, // + + [ 0x1e ] = KEY_VOLUMEDOWN, // VOLUME- + [ 0x3e ] = KEY_VOLUMEUP, // VOLUME+ + [ 0x11 ] = KEY_CHANNELDOWN, // CHANNEL/PAGE- + [ 0x31 ] = KEY_CHANNELUP // CHANNEL/PAGE+ +}; + +EXPORT_SYMBOL_GPL(ir_codes_md2819); + +IR_KEYTAB_TYPE ir_codes_videomate_tv_pvr[IR_KEYTAB_SIZE] = { + [ 0x14 ] = KEY_MUTE, + [ 0x24 ] = KEY_ZOOM, + + [ 0x01 ] = KEY_DVD, + [ 0x23 ] = KEY_RADIO, + [ 0x00 ] = KEY_TV, + + [ 0x0a ] = KEY_REWIND, + [ 0x08 ] = KEY_PLAYPAUSE, + [ 0x0f ] = KEY_FORWARD, + + [ 0x02 ] = KEY_PREVIOUS, + [ 0x07 ] = KEY_STOP, + [ 0x06 ] = KEY_NEXT, + + [ 0x0c ] = KEY_UP, + [ 0x0e ] = KEY_DOWN, + [ 0x0b ] = KEY_LEFT, + [ 0x0d ] = KEY_RIGHT, + [ 0x11 ] = KEY_OK, + + [ 0x03 ] = KEY_MENU, + [ 0x09 ] = KEY_SETUP, + [ 0x05 ] = KEY_VIDEO, + [ 0x22 ] = KEY_CHANNEL, + + [ 0x12 ] = KEY_VOLUMEUP, + [ 0x15 ] = KEY_VOLUMEDOWN, + [ 0x10 ] = KEY_CHANNELUP, + [ 0x13 ] = KEY_CHANNELDOWN, + + [ 0x04 ] = KEY_RECORD, + + [ 0x16 ] = KEY_1, + [ 0x17 ] = KEY_2, + [ 0x18 ] = KEY_3, + [ 0x19 ] = KEY_4, + [ 0x1a ] = KEY_5, + [ 0x1b ] = KEY_6, + [ 0x1c ] = KEY_7, + [ 0x1d ] = KEY_8, + [ 0x1e ] = KEY_9, + [ 0x1f ] = KEY_0, + + [ 0x20 ] = KEY_LANGUAGE, + [ 0x21 ] = KEY_SLEEP, +}; + +EXPORT_SYMBOL_GPL(ir_codes_videomate_tv_pvr); + +/* Michael Tokarev + http://www.corpit.ru/mjt/beholdTV/remote_control.jpg + keytable is used by MANLI MTV00[ 0x0c ] and BeholdTV 40[13] at + least, and probably other cards too. + The "ascii-art picture" below (in comments, first row + is the keycode in hex, and subsequent row(s) shows + the button labels (several variants when appropriate) + helps to descide which keycodes to assign to the buttons. + */ +IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { + + /* 0x1c 0x12 * + * FUNCTION POWER * + * FM (|) * + * */ + [ 0x1c ] = KEY_RADIO, /*XXX*/ + [ 0x12 ] = KEY_POWER, + + /* 0x01 0x02 0x03 * + * 1 2 3 * + * * + * 0x04 0x05 0x06 * + * 4 5 6 * + * * + * 0x07 0x08 0x09 * + * 7 8 9 * + * */ + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + + /* 0x0a 0x00 0x17 * + * RECALL 0 +100 * + * PLUS * + * */ + [ 0x0a ] = KEY_AGAIN, /*XXX KEY_REWIND? */ + [ 0x00 ] = KEY_0, + [ 0x17 ] = KEY_DIGITS, /*XXX*/ + + /* 0x14 0x10 * + * MENU INFO * + * OSD */ + [ 0x14 ] = KEY_MENU, + [ 0x10 ] = KEY_INFO, + + /* 0x0b * + * Up * + * * + * 0x18 0x16 0x0c * + * Left Ok Right * + * * + * 0x015 * + * Down * + * */ + [ 0x0b ] = KEY_UP, /*XXX KEY_SCROLLUP? */ + [ 0x18 ] = KEY_LEFT, /*XXX KEY_BACK? */ + [ 0x16 ] = KEY_OK, /*XXX KEY_SELECT? KEY_ENTER? */ + [ 0x0c ] = KEY_RIGHT, /*XXX KEY_FORWARD? */ + [ 0x15 ] = KEY_DOWN, /*XXX KEY_SCROLLDOWN? */ + + /* 0x11 0x0d * + * TV/AV MODE * + * SOURCE STEREO * + * */ + [ 0x11 ] = KEY_TV, /*XXX*/ + [ 0x0d ] = KEY_MODE, /*XXX there's no KEY_STEREO */ + + /* 0x0f 0x1b 0x1a * + * AUDIO Vol+ Chan+ * + * TIMESHIFT??? * + * * + * 0x0e 0x1f 0x1e * + * SLEEP Vol- Chan- * + * */ + [ 0x0f ] = KEY_AUDIO, + [ 0x1b ] = KEY_VOLUMEUP, + [ 0x1a ] = KEY_CHANNELUP, + [ 0x0e ] = KEY_SLEEP, /*XXX maybe KEY_PAUSE */ + [ 0x1f ] = KEY_VOLUMEDOWN, + [ 0x1e ] = KEY_CHANNELDOWN, + + /* 0x13 0x19 * + * MUTE SNAPSHOT* + * */ + [ 0x13 ] = KEY_MUTE, + [ 0x19 ] = KEY_RECORD, /*XXX*/ + + // 0x1d unused ? +}; + +EXPORT_SYMBOL_GPL(ir_codes_manli); + +/* Mike Baikov */ +IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE] = { + + [ 0x21 ] = KEY_POWER, + [ 0x69 ] = KEY_TV, + [ 0x33 ] = KEY_0, + [ 0x51 ] = KEY_1, + [ 0x31 ] = KEY_2, + [ 0x71 ] = KEY_3, + [ 0x3b ] = KEY_4, + [ 0x58 ] = KEY_5, + [ 0x41 ] = KEY_6, + [ 0x48 ] = KEY_7, + [ 0x30 ] = KEY_8, + [ 0x53 ] = KEY_9, + [ 0x73 ] = KEY_AGAIN, /* LOOP */ + [ 0x0a ] = KEY_AUDIO, + [ 0x61 ] = KEY_PRINT, /* PREVIEW */ + [ 0x7a ] = KEY_VIDEO, + [ 0x20 ] = KEY_CHANNELUP, + [ 0x40 ] = KEY_CHANNELDOWN, + [ 0x18 ] = KEY_VOLUMEDOWN, + [ 0x50 ] = KEY_VOLUMEUP, + [ 0x10 ] = KEY_MUTE, + [ 0x4a ] = KEY_SEARCH, + [ 0x7b ] = KEY_SHUFFLE, /* SNAPSHOT */ + [ 0x22 ] = KEY_RECORD, + [ 0x62 ] = KEY_STOP, + [ 0x78 ] = KEY_PLAY, + [ 0x39 ] = KEY_REWIND, + [ 0x59 ] = KEY_PAUSE, + [ 0x19 ] = KEY_FORWARD, + [ 0x09 ] = KEY_ZOOM, + + [ 0x52 ] = KEY_F21, /* LIVE TIMESHIFT */ + [ 0x1a ] = KEY_F22, /* MIN TIMESHIFT */ + [ 0x3a ] = KEY_F23, /* TIMESHIFT */ + [ 0x70 ] = KEY_F24, /* NORMAL TIMESHIFT */ +}; + +EXPORT_SYMBOL_GPL(ir_codes_gotview7135); + +IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { + [ 0x03 ] = KEY_POWER, + [ 0x6f ] = KEY_MUTE, + [ 0x10 ] = KEY_BACKSPACE, /* Recall */ + + [ 0x11 ] = KEY_0, + [ 0x04 ] = KEY_1, + [ 0x05 ] = KEY_2, + [ 0x06 ] = KEY_3, + [ 0x08 ] = KEY_4, + [ 0x09 ] = KEY_5, + [ 0x0a ] = KEY_6, + [ 0x0c ] = KEY_7, + [ 0x0d ] = KEY_8, + [ 0x0e ] = KEY_9, + [ 0x12 ] = KEY_DOT, /* 100+ */ + + [ 0x07 ] = KEY_VOLUMEUP, + [ 0x0b ] = KEY_VOLUMEDOWN, + [ 0x1a ] = KEY_KPPLUS, + [ 0x18 ] = KEY_KPMINUS, + [ 0x15 ] = KEY_UP, + [ 0x1d ] = KEY_DOWN, + [ 0x0f ] = KEY_CHANNELUP, + [ 0x13 ] = KEY_CHANNELDOWN, + [ 0x48 ] = KEY_ZOOM, + + [ 0x1b ] = KEY_VIDEO, /* Video source */ + [ 0x49 ] = KEY_LANGUAGE, /* MTS Select */ + [ 0x19 ] = KEY_SEARCH, /* Auto Scan */ + + [ 0x4b ] = KEY_RECORD, + [ 0x46 ] = KEY_PLAY, + [ 0x45 ] = KEY_PAUSE, /* Pause */ + [ 0x44 ] = KEY_STOP, + [ 0x40 ] = KEY_FORWARD, /* Forward ? */ + [ 0x42 ] = KEY_REWIND, /* Backward ? */ + +}; + +EXPORT_SYMBOL_GPL(ir_codes_purpletv); + +/* Mapping for the 28 key remote control as seen at + http://www.sednacomputer.com/photo/cardbus-tv.jpg + Pavel Mihaylov */ +IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = { + [ 0x00 ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + + [ 0x0a ] = KEY_AGAIN, /* Recall */ + [ 0x0b ] = KEY_CHANNELUP, + [ 0x0c ] = KEY_VOLUMEUP, + [ 0x0d ] = KEY_MODE, /* Stereo */ + [ 0x0e ] = KEY_STOP, + [ 0x0f ] = KEY_PREVIOUSSONG, + [ 0x10 ] = KEY_ZOOM, + [ 0x11 ] = KEY_TUNER, /* Source */ + [ 0x12 ] = KEY_POWER, + [ 0x13 ] = KEY_MUTE, + [ 0x15 ] = KEY_CHANNELDOWN, + [ 0x18 ] = KEY_VOLUMEDOWN, + [ 0x19 ] = KEY_SHUFFLE, /* Snapshot */ + [ 0x1a ] = KEY_NEXTSONG, + [ 0x1b ] = KEY_TEXT, /* Time Shift */ + [ 0x1c ] = KEY_RADIO, /* FM Radio */ + [ 0x1d ] = KEY_RECORD, + [ 0x1e ] = KEY_PAUSE, +}; + +EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna); + +/* Mark Phalan */ +IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = { + [ 0x00 ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + + [ 0x12 ] = KEY_POWER, + [ 0x10 ] = KEY_MUTE, + [ 0x1f ] = KEY_VOLUMEDOWN, + [ 0x1b ] = KEY_VOLUMEUP, + [ 0x1a ] = KEY_CHANNELUP, + [ 0x1e ] = KEY_CHANNELDOWN, + [ 0x0e ] = KEY_PAGEUP, + [ 0x1d ] = KEY_PAGEDOWN, + [ 0x13 ] = KEY_SOUND, + + [ 0x18 ] = KEY_KPPLUSMINUS, /* CH +/- */ + [ 0x16 ] = KEY_SUBTITLE, /* CC */ + [ 0x0d ] = KEY_TEXT, /* TTX */ + [ 0x0b ] = KEY_TV, /* AIR/CBL */ + [ 0x11 ] = KEY_PC, /* PC/TV */ + [ 0x17 ] = KEY_OK, /* CH RTN */ + [ 0x19 ] = KEY_MODE, /* FUNC */ + [ 0x0c ] = KEY_SEARCH, /* AUTOSCAN */ + + /* Not sure what to do with these ones! */ + [ 0x0f ] = KEY_SELECT, /* SOURCE */ + [ 0x0a ] = KEY_KPPLUS, /* +100 */ + [ 0x14 ] = KEY_EQUAL, /* SYNC */ + [ 0x1c ] = KEY_MEDIA, /* PC/TV */ +}; + +EXPORT_SYMBOL_GPL(ir_codes_pv951); + +/* generic RC5 keytable */ +/* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ +/* used by old (black) Hauppauge remotes */ +IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { + /* Keys 0 to 9 */ + [ 0x00 ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + + [ 0x0b ] = KEY_CHANNEL, /* channel / program (japan: 11) */ + [ 0x0c ] = KEY_POWER, /* standby */ + [ 0x0d ] = KEY_MUTE, /* mute / demute */ + [ 0x0f ] = KEY_TV, /* display */ + [ 0x10 ] = KEY_VOLUMEUP, + [ 0x11 ] = KEY_VOLUMEDOWN, + [ 0x12 ] = KEY_BRIGHTNESSUP, + [ 0x13 ] = KEY_BRIGHTNESSDOWN, + [ 0x1e ] = KEY_SEARCH, /* search + */ + [ 0x20 ] = KEY_CHANNELUP, /* channel / program + */ + [ 0x21 ] = KEY_CHANNELDOWN, /* channel / program - */ + [ 0x22 ] = KEY_CHANNEL, /* alt / channel */ + [ 0x23 ] = KEY_LANGUAGE, /* 1st / 2nd language */ + [ 0x26 ] = KEY_SLEEP, /* sleeptimer */ + [ 0x2e ] = KEY_MENU, /* 2nd controls (USA: menu) */ + [ 0x30 ] = KEY_PAUSE, + [ 0x32 ] = KEY_REWIND, + [ 0x33 ] = KEY_GOTO, + [ 0x35 ] = KEY_PLAY, + [ 0x36 ] = KEY_STOP, + [ 0x37 ] = KEY_RECORD, /* recording */ + [ 0x3c ] = KEY_TEXT, /* teletext submode (Japan: 12) */ + [ 0x3d ] = KEY_SUSPEND, /* system standby */ + +}; + +EXPORT_SYMBOL_GPL(ir_codes_rc5_tv); + +/* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ +IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { + /* Keys 0 to 9 */ + [ 0x12 ] = KEY_0, + [ 0x05 ] = KEY_1, + [ 0x06 ] = KEY_2, + [ 0x07 ] = KEY_3, + [ 0x09 ] = KEY_4, + [ 0x0a ] = KEY_5, + [ 0x0b ] = KEY_6, + [ 0x0d ] = KEY_7, + [ 0x0e ] = KEY_8, + [ 0x0f ] = KEY_9, + + [ 0x00 ] = KEY_POWER, + [ 0x02 ] = KEY_TUNER, /* TV/FM */ + [ 0x1e ] = KEY_VIDEO, + [ 0x04 ] = KEY_VOLUMEUP, + [ 0x08 ] = KEY_VOLUMEDOWN, + [ 0x0c ] = KEY_CHANNELUP, + [ 0x10 ] = KEY_CHANNELDOWN, + [ 0x03 ] = KEY_ZOOM, /* fullscreen */ + [ 0x1f ] = KEY_SUBTITLE, /* closed caption/teletext */ + [ 0x20 ] = KEY_SLEEP, + [ 0x14 ] = KEY_MUTE, + [ 0x2b ] = KEY_RED, + [ 0x2c ] = KEY_GREEN, + [ 0x2d ] = KEY_YELLOW, + [ 0x2e ] = KEY_BLUE, + [ 0x18 ] = KEY_KPPLUS, /* fine tune + */ + [ 0x19 ] = KEY_KPMINUS, /* fine tune - */ + [ 0x21 ] = KEY_DOT, + [ 0x13 ] = KEY_ENTER, + [ 0x22 ] = KEY_BACK, + [ 0x23 ] = KEY_PLAYPAUSE, + [ 0x24 ] = KEY_NEXT, + [ 0x26 ] = KEY_STOP, + [ 0x27 ] = KEY_RECORD +}; + +EXPORT_SYMBOL_GPL(ir_codes_winfast); + +IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = { + [ 0x59 ] = KEY_MUTE, + [ 0x4a ] = KEY_POWER, + + [ 0x18 ] = KEY_TEXT, + [ 0x26 ] = KEY_TV, + [ 0x3d ] = KEY_PRINT, + + [ 0x48 ] = KEY_RED, + [ 0x04 ] = KEY_GREEN, + [ 0x11 ] = KEY_YELLOW, + [ 0x00 ] = KEY_BLUE, + + [ 0x2d ] = KEY_VOLUMEUP, + [ 0x1e ] = KEY_VOLUMEDOWN, + + [ 0x49 ] = KEY_MENU, + + [ 0x16 ] = KEY_CHANNELUP, + [ 0x17 ] = KEY_CHANNELDOWN, + + [ 0x20 ] = KEY_UP, + [ 0x21 ] = KEY_DOWN, + [ 0x22 ] = KEY_LEFT, + [ 0x23 ] = KEY_RIGHT, + [ 0x0d ] = KEY_SELECT, + + + + [ 0x08 ] = KEY_BACK, + [ 0x07 ] = KEY_REFRESH, + + [ 0x2f ] = KEY_ZOOM, + [ 0x29 ] = KEY_RECORD, + + [ 0x4b ] = KEY_PAUSE, + [ 0x4d ] = KEY_REWIND, + [ 0x2e ] = KEY_PLAY, + [ 0x4e ] = KEY_FORWARD, + [ 0x53 ] = KEY_PREVIOUS, + [ 0x4c ] = KEY_STOP, + [ 0x54 ] = KEY_NEXT, + + [ 0x69 ] = KEY_0, + [ 0x6a ] = KEY_1, + [ 0x6b ] = KEY_2, + [ 0x6c ] = KEY_3, + [ 0x6d ] = KEY_4, + [ 0x6e ] = KEY_5, + [ 0x6f ] = KEY_6, + [ 0x70 ] = KEY_7, + [ 0x71 ] = KEY_8, + [ 0x72 ] = KEY_9, + + [ 0x74 ] = KEY_CHANNEL, + [ 0x0a ] = KEY_BACKSPACE, +}; + +EXPORT_SYMBOL_GPL(ir_codes_pinnacle); + +/* Hauppauge: the newer, gray remotes (seems there are multiple + * slightly different versions), shipped with cx88+ivtv cards. + * almost rc5 coding, but some non-standard keys */ +IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { + /* Keys 0 to 9 */ + [ 0x00 ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + + [ 0x0a ] = KEY_TEXT, /* keypad asterisk as well */ + [ 0x0b ] = KEY_RED, /* red button */ + [ 0x0c ] = KEY_RADIO, + [ 0x0d ] = KEY_MENU, + [ 0x0e ] = KEY_SUBTITLE, /* also the # key */ + [ 0x0f ] = KEY_MUTE, + [ 0x10 ] = KEY_VOLUMEUP, + [ 0x11 ] = KEY_VOLUMEDOWN, + [ 0x12 ] = KEY_PREVIOUS, /* previous channel */ + [ 0x14 ] = KEY_UP, + [ 0x15 ] = KEY_DOWN, + [ 0x16 ] = KEY_LEFT, + [ 0x17 ] = KEY_RIGHT, + [ 0x18 ] = KEY_VIDEO, /* Videos */ + [ 0x19 ] = KEY_AUDIO, /* Music */ + /* 0x1a: Pictures - presume this means + "Multimedia Home Platform" - + no "PICTURES" key in input.h + */ + [ 0x1a ] = KEY_MHP, + + [ 0x1b ] = KEY_EPG, /* Guide */ + [ 0x1c ] = KEY_TV, + [ 0x1e ] = KEY_NEXTSONG, /* skip >| */ + [ 0x1f ] = KEY_EXIT, /* back/exit */ + [ 0x20 ] = KEY_CHANNELUP, /* channel / program + */ + [ 0x21 ] = KEY_CHANNELDOWN, /* channel / program - */ + [ 0x22 ] = KEY_CHANNEL, /* source (old black remote) */ + [ 0x24 ] = KEY_PREVIOUSSONG, /* replay |< */ + [ 0x25 ] = KEY_ENTER, /* OK */ + [ 0x26 ] = KEY_SLEEP, /* minimize (old black remote) */ + [ 0x29 ] = KEY_BLUE, /* blue key */ + [ 0x2e ] = KEY_GREEN, /* green button */ + [ 0x30 ] = KEY_PAUSE, /* pause */ + [ 0x32 ] = KEY_REWIND, /* backward << */ + [ 0x34 ] = KEY_FASTFORWARD, /* forward >> */ + [ 0x35 ] = KEY_PLAY, + [ 0x36 ] = KEY_STOP, + [ 0x37 ] = KEY_RECORD, /* recording */ + [ 0x38 ] = KEY_YELLOW, /* yellow key */ + [ 0x3b ] = KEY_SELECT, /* top right button */ + [ 0x3c ] = KEY_ZOOM, /* full */ + [ 0x3d ] = KEY_POWER, /* system power (green button) */ +}; + +EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new); + +IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { + [ 0x02 ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x0b ] = KEY_2, + [ 0x1b ] = KEY_3, + [ 0x05 ] = KEY_4, + [ 0x09 ] = KEY_5, + [ 0x15 ] = KEY_6, + [ 0x06 ] = KEY_7, + [ 0x0a ] = KEY_8, + [ 0x12 ] = KEY_9, + + [ 0x03 ] = KEY_TUNER, /* TV/FM */ + [ 0x07 ] = KEY_SEARCH, /* scan */ + [ 0x1c ] = KEY_ZOOM, /* full screen */ + [ 0x1e ] = KEY_POWER, + [ 0x17 ] = KEY_VOLUMEDOWN, + [ 0x1f ] = KEY_VOLUMEUP, + [ 0x14 ] = KEY_CHANNELDOWN, + [ 0x16 ] = KEY_CHANNELUP, + [ 0x18 ] = KEY_MUTE, + + [ 0x00 ] = KEY_LIST, /* source */ + [ 0x13 ] = KEY_INFO, /* loop */ + [ 0x10 ] = KEY_LAST, /* +100 */ + [ 0x0d ] = KEY_CLEAR, /* reset */ + [ 0x0c ] = BTN_RIGHT, /* fun++ */ + [ 0x04 ] = BTN_LEFT, /* fun-- */ + [ 0x0e ] = KEY_GOTO, /* function */ + [ 0x0f ] = KEY_STOP, /* freeze */ +}; + +EXPORT_SYMBOL_GPL(ir_codes_pixelview); + diff --git a/drivers/media/video/bttv-input.c b/drivers/media/video/bttv-input.c index 221b36e7f392..42760ae867d6 100644 --- a/drivers/media/video/bttv-input.c +++ b/drivers/media/video/bttv-input.c @@ -28,251 +28,6 @@ #include "bttv.h" #include "bttvp.h" -/* ---------------------------------------------------------------------- */ - -static IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { - [ 34 ] = KEY_KP0, - [ 40 ] = KEY_KP1, - [ 24 ] = KEY_KP2, - [ 56 ] = KEY_KP3, - [ 36 ] = KEY_KP4, - [ 20 ] = KEY_KP5, - [ 52 ] = KEY_KP6, - [ 44 ] = KEY_KP7, - [ 28 ] = KEY_KP8, - [ 60 ] = KEY_KP9, - - [ 48 ] = KEY_EJECTCD, // Unmarked on my controller - [ 0 ] = KEY_POWER, - [ 18 ] = BTN_LEFT, // DISPLAY/L - [ 50 ] = BTN_RIGHT, // LOOP/R - [ 10 ] = KEY_MUTE, - [ 38 ] = KEY_RECORD, - [ 22 ] = KEY_PAUSE, - [ 54 ] = KEY_STOP, - [ 30 ] = KEY_VOLUMEDOWN, - [ 62 ] = KEY_VOLUMEUP, - - [ 32 ] = KEY_TUNER, // TV/FM - [ 16 ] = KEY_CD, - [ 8 ] = KEY_VIDEO, - [ 4 ] = KEY_AUDIO, - [ 12 ] = KEY_ZOOM, // full screen - [ 2 ] = KEY_INFO, // preview - [ 42 ] = KEY_SEARCH, // autoscan - [ 26 ] = KEY_STOP, // freeze - [ 58 ] = KEY_RECORD, // capture - [ 6 ] = KEY_PLAY, // unmarked - [ 46 ] = KEY_RED, // unmarked - [ 14 ] = KEY_GREEN, // unmarked - - [ 33 ] = KEY_YELLOW, // unmarked - [ 17 ] = KEY_CHANNELDOWN, - [ 49 ] = KEY_CHANNELUP, - [ 1 ] = KEY_BLUE, // unmarked -}; - -/* Matt Jesson >' - [ 0x3a ] = KEY_RECORD, // 'capture' - [ 0x0a ] = KEY_MUTE, // 'mute' - [ 0x2c ] = KEY_RECORD, // 'record' - [ 0x1c ] = KEY_PAUSE, // 'pause' - [ 0x3c ] = KEY_STOP, // 'stop' - [ 0x0c ] = KEY_PLAY, // 'play' - [ 0x2e ] = KEY_RED, // 'red' - [ 0x01 ] = KEY_BLUE, // 'blue' / 'cancel' - [ 0x0e ] = KEY_YELLOW, // 'yellow' / 'ok' - [ 0x21 ] = KEY_GREEN, // 'green' - [ 0x11 ] = KEY_CHANNELDOWN, // 'channel -' - [ 0x31 ] = KEY_CHANNELUP, // 'channel +' - [ 0x1e ] = KEY_VOLUMEDOWN, // 'volume -' - [ 0x3e ] = KEY_VOLUMEUP, // 'volume +' -}; - -/* Attila Kondoros */ -static IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { - - [ 1 ] = KEY_KP1, - [ 2 ] = KEY_KP2, - [ 3 ] = KEY_KP3, - [ 4 ] = KEY_KP4, - [ 5 ] = KEY_KP5, - [ 6 ] = KEY_KP6, - [ 7 ] = KEY_KP7, - [ 8 ] = KEY_KP8, - [ 9 ] = KEY_KP9, - [ 0 ] = KEY_KP0, - [ 23 ] = KEY_LAST, // +100 - [ 10 ] = KEY_LIST, // recall - - - [ 28 ] = KEY_TUNER, // TV/FM - [ 21 ] = KEY_SEARCH, // scan - [ 18 ] = KEY_POWER, // power - [ 31 ] = KEY_VOLUMEDOWN, // vol up - [ 27 ] = KEY_VOLUMEUP, // vol down - [ 30 ] = KEY_CHANNELDOWN, // chn up - [ 26 ] = KEY_CHANNELUP, // chn down - - [ 17 ] = KEY_VIDEO, // video - [ 15 ] = KEY_ZOOM, // full screen - [ 19 ] = KEY_MUTE, // mute/unmute - [ 16 ] = KEY_TEXT, // min - - [ 13 ] = KEY_STOP, // freeze - [ 14 ] = KEY_RECORD, // record - [ 29 ] = KEY_PLAYPAUSE, // stop - [ 25 ] = KEY_PLAY, // play - - [ 22 ] = KEY_GOTO, // osd - [ 20 ] = KEY_REFRESH, // default - [ 12 ] = KEY_KPPLUS, // fine tune >>>> - [ 24 ] = KEY_KPMINUS // fine tune <<<< -}; - -/* ---------------------------------------------------------------------- */ - -static IR_KEYTAB_TYPE ir_codes_conceptronic[IR_KEYTAB_SIZE] = { - - [ 30 ] = KEY_POWER, // power - [ 7 ] = KEY_MEDIA, // source - [ 28 ] = KEY_SEARCH, // scan - -/* FIXME: duplicate keycodes? - * - * These four keys seem to share the same GPIO as CH+, CH-, <<< and >>> - * The GPIO values are - * 6397fb for both "Scan <" and "CH -", - * 639ffb for "Scan >" and "CH+", - * 6384fb for "Tune <" and "<<<", - * 638cfb for "Tune >" and ">>>", regardless of the mask. - * - * [ 23 ] = KEY_BACK, // fm scan << - * [ 31 ] = KEY_FORWARD, // fm scan >> - * - * [ 4 ] = KEY_LEFT, // fm tuning < - * [ 12 ] = KEY_RIGHT, // fm tuning > - * - * For now, these four keys are disabled. Pressing them will generate - * the CH+/CH-/<<>> events - */ - - [ 3 ] = KEY_TUNER, // TV/FM - - [ 0 ] = KEY_RECORD, - [ 8 ] = KEY_STOP, - [ 17 ] = KEY_PLAY, - - [ 26 ] = KEY_PLAYPAUSE, // freeze - [ 25 ] = KEY_ZOOM, // zoom - [ 15 ] = KEY_TEXT, // min - - [ 1 ] = KEY_KP1, - [ 11 ] = KEY_KP2, - [ 27 ] = KEY_KP3, - [ 5 ] = KEY_KP4, - [ 9 ] = KEY_KP5, - [ 21 ] = KEY_KP6, - [ 6 ] = KEY_KP7, - [ 10 ] = KEY_KP8, - [ 18 ] = KEY_KP9, - [ 2 ] = KEY_KP0, - [ 16 ] = KEY_LAST, // +100 - [ 19 ] = KEY_LIST, // recall - - [ 31 ] = KEY_CHANNELUP, // chn down - [ 23 ] = KEY_CHANNELDOWN, // chn up - [ 22 ] = KEY_VOLUMEUP, // vol down - [ 20 ] = KEY_VOLUMEDOWN, // vol up - - [ 4 ] = KEY_KPMINUS, // <<< - [ 14 ] = KEY_SETUP, // function - [ 12 ] = KEY_KPPLUS, // >>> - - [ 13 ] = KEY_GOTO, // mts - [ 29 ] = KEY_REFRESH, // reset - [ 24 ] = KEY_MUTE // mute/unmute -}; - -static IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = { - [0x00] = KEY_KP0, - [0x01] = KEY_KP1, - [0x02] = KEY_KP2, - [0x03] = KEY_KP3, - [0x04] = KEY_KP4, - [0x05] = KEY_KP5, - [0x06] = KEY_KP6, - [0x07] = KEY_KP7, - [0x08] = KEY_KP8, - [0x09] = KEY_KP9, - [0x0a] = KEY_TV, - [0x0b] = KEY_AUX, - [0x0c] = KEY_DVD, - [0x0d] = KEY_POWER, - [0x0e] = KEY_MHP, /* labelled 'Picture' */ - [0x0f] = KEY_AUDIO, - [0x10] = KEY_INFO, - [0x11] = KEY_F13, /* 16:9 */ - [0x12] = KEY_F14, /* 14:9 */ - [0x13] = KEY_EPG, - [0x14] = KEY_EXIT, - [0x15] = KEY_MENU, - [0x16] = KEY_UP, - [0x17] = KEY_DOWN, - [0x18] = KEY_LEFT, - [0x19] = KEY_RIGHT, - [0x1a] = KEY_ENTER, - [0x1b] = KEY_CHANNELUP, - [0x1c] = KEY_CHANNELDOWN, - [0x1d] = KEY_VOLUMEUP, - [0x1e] = KEY_VOLUMEDOWN, - [0x1f] = KEY_RED, - [0x20] = KEY_GREEN, - [0x21] = KEY_YELLOW, - [0x22] = KEY_BLUE, - [0x23] = KEY_SUBTITLE, - [0x24] = KEY_F15, /* AD */ - [0x25] = KEY_TEXT, - [0x26] = KEY_MUTE, - [0x27] = KEY_REWIND, - [0x28] = KEY_STOP, - [0x29] = KEY_PLAY, - [0x2a] = KEY_FASTFORWARD, - [0x2b] = KEY_F16, /* chapter */ - [0x2c] = KEY_PAUSE, - [0x2d] = KEY_PLAY, - [0x2e] = KEY_RECORD, - [0x2f] = KEY_F17, /* picture in picture */ - [0x30] = KEY_KPPLUS, /* zoom in */ - [0x31] = KEY_KPMINUS, /* zoom out */ - [0x32] = KEY_F18, /* capture */ - [0x33] = KEY_F19, /* web */ - [0x34] = KEY_EMAIL, - [0x35] = KEY_PHONE, - [0x36] = KEY_PC -}; static int debug; module_param(debug, int, 0644); /* debug level (0,1,2) */ diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index da2ad5c4b553..a4fa92c1b0c7 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -34,337 +34,6 @@ /* ---------------------------------------------------------------------- */ -/* DigitalNow DNTV Live DVB-T Remote */ -static IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE] = { - [0x00] = KEY_ESC, /* 'go up a level?' */ - /* Keys 0 to 9 */ - [0x0a] = KEY_KP0, - [0x01] = KEY_KP1, - [0x02] = KEY_KP2, - [0x03] = KEY_KP3, - [0x04] = KEY_KP4, - [0x05] = KEY_KP5, - [0x06] = KEY_KP6, - [0x07] = KEY_KP7, - [0x08] = KEY_KP8, - [0x09] = KEY_KP9, - - [0x0b] = KEY_TUNER, /* tv/fm */ - [0x0c] = KEY_SEARCH, /* scan */ - [0x0d] = KEY_STOP, - [0x0e] = KEY_PAUSE, - [0x0f] = KEY_LIST, /* source */ - - [0x10] = KEY_MUTE, - [0x11] = KEY_REWIND, /* backward << */ - [0x12] = KEY_POWER, - [0x13] = KEY_S, /* snap */ - [0x14] = KEY_AUDIO, /* stereo */ - [0x15] = KEY_CLEAR, /* reset */ - [0x16] = KEY_PLAY, - [0x17] = KEY_ENTER, - [0x18] = KEY_ZOOM, /* full screen */ - [0x19] = KEY_FASTFORWARD, /* forward >> */ - [0x1a] = KEY_CHANNELUP, - [0x1b] = KEY_VOLUMEUP, - [0x1c] = KEY_INFO, /* preview */ - [0x1d] = KEY_RECORD, /* record */ - [0x1e] = KEY_CHANNELDOWN, - [0x1f] = KEY_VOLUMEDOWN, -}; - -/* ---------------------------------------------------------------------- */ - -/* IO-DATA BCTV7E Remote */ -static IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = { - [0x40] = KEY_TV, - [0x20] = KEY_RADIO, /* FM */ - [0x60] = KEY_EPG, - [0x00] = KEY_POWER, - - /* Keys 0 to 9 */ - [0x44] = KEY_KP0, /* 10 */ - [0x50] = KEY_KP1, - [0x30] = KEY_KP2, - [0x70] = KEY_KP3, - [0x48] = KEY_KP4, - [0x28] = KEY_KP5, - [0x68] = KEY_KP6, - [0x58] = KEY_KP7, - [0x38] = KEY_KP8, - [0x78] = KEY_KP9, - - [0x10] = KEY_L, /* Live */ - [0x08] = KEY_T, /* Time Shift */ - - [0x18] = KEY_PLAYPAUSE, /* Play */ - - [0x24] = KEY_ENTER, /* 11 */ - [0x64] = KEY_ESC, /* 12 */ - [0x04] = KEY_M, /* Multi */ - - [0x54] = KEY_VIDEO, - [0x34] = KEY_CHANNELUP, - [0x74] = KEY_VOLUMEUP, - [0x14] = KEY_MUTE, - - [0x4c] = KEY_S, /* SVIDEO */ - [0x2c] = KEY_CHANNELDOWN, - [0x6c] = KEY_VOLUMEDOWN, - [0x0c] = KEY_ZOOM, - - [0x5c] = KEY_PAUSE, - [0x3c] = KEY_C, /* || (red) */ - [0x7c] = KEY_RECORD, /* recording */ - [0x1c] = KEY_STOP, - - [0x41] = KEY_REWIND, /* backward << */ - [0x21] = KEY_PLAY, - [0x61] = KEY_FASTFORWARD, /* forward >> */ - [0x01] = KEY_NEXT, /* skip >| */ -}; - -/* ---------------------------------------------------------------------- */ - -/* ADS Tech Instant TV DVB-T PCI Remote */ -static IR_KEYTAB_TYPE ir_codes_adstech_dvb_t_pci[IR_KEYTAB_SIZE] = { - /* Keys 0 to 9 */ - [0x4d] = KEY_0, - [0x57] = KEY_1, - [0x4f] = KEY_2, - [0x53] = KEY_3, - [0x56] = KEY_4, - [0x4e] = KEY_5, - [0x5e] = KEY_6, - [0x54] = KEY_7, - [0x4c] = KEY_8, - [0x5c] = KEY_9, - - [0x5b] = KEY_POWER, - [0x5f] = KEY_MUTE, - [0x55] = KEY_GOTO, - [0x5d] = KEY_SEARCH, - [0x17] = KEY_EPG, /* Guide */ - [0x1f] = KEY_MENU, - [0x0f] = KEY_UP, - [0x46] = KEY_DOWN, - [0x16] = KEY_LEFT, - [0x1e] = KEY_RIGHT, - [0x0e] = KEY_SELECT, /* Enter */ - [0x5a] = KEY_INFO, - [0x52] = KEY_EXIT, - [0x59] = KEY_PREVIOUS, - [0x51] = KEY_NEXT, - [0x58] = KEY_REWIND, - [0x50] = KEY_FORWARD, - [0x44] = KEY_PLAYPAUSE, - [0x07] = KEY_STOP, - [0x1b] = KEY_RECORD, - [0x13] = KEY_TUNER, /* Live */ - [0x0a] = KEY_A, - [0x12] = KEY_B, - [0x03] = KEY_PROG1, /* 1 */ - [0x01] = KEY_PROG2, /* 2 */ - [0x00] = KEY_PROG3, /* 3 */ - [0x06] = KEY_DVD, - [0x48] = KEY_AUX, /* Photo */ - [0x40] = KEY_VIDEO, - [0x19] = KEY_AUDIO, /* Music */ - [0x0b] = KEY_CHANNELUP, - [0x08] = KEY_CHANNELDOWN, - [0x15] = KEY_VOLUMEUP, - [0x1c] = KEY_VOLUMEDOWN, -}; - -/* ---------------------------------------------------------------------- */ - -/* MSI TV@nywhere remote */ -static IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = { - /* Keys 0 to 9 */ - [0x00] = KEY_0, - [0x01] = KEY_1, - [0x02] = KEY_2, - [0x03] = KEY_3, - [0x04] = KEY_4, - [0x05] = KEY_5, - [0x06] = KEY_6, - [0x07] = KEY_7, - [0x08] = KEY_8, - [0x09] = KEY_9, - - [0x0c] = KEY_MUTE, - [0x0f] = KEY_SCREEN, /* Full Screen */ - [0x10] = KEY_F, /* Funtion */ - [0x11] = KEY_T, /* Time shift */ - [0x12] = KEY_POWER, - [0x13] = KEY_MEDIA, /* MTS */ - [0x14] = KEY_SLOW, - [0x16] = KEY_REWIND, /* backward << */ - [0x17] = KEY_ENTER, /* Return */ - [0x18] = KEY_FASTFORWARD, /* forward >> */ - [0x1a] = KEY_CHANNELUP, - [0x1b] = KEY_VOLUMEUP, - [0x1e] = KEY_CHANNELDOWN, - [0x1f] = KEY_VOLUMEDOWN, -}; - -/* ---------------------------------------------------------------------- */ - -/* Cinergy 1400 DVB-T */ -static IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = { - [0x01] = KEY_POWER, - [0x02] = KEY_1, - [0x03] = KEY_2, - [0x04] = KEY_3, - [0x05] = KEY_4, - [0x06] = KEY_5, - [0x07] = KEY_6, - [0x08] = KEY_7, - [0x09] = KEY_8, - [0x0a] = KEY_9, - [0x0c] = KEY_0, - - [0x0b] = KEY_VIDEO, - [0x0d] = KEY_REFRESH, - [0x0e] = KEY_SELECT, - [0x0f] = KEY_EPG, - [0x10] = KEY_UP, - [0x11] = KEY_LEFT, - [0x12] = KEY_OK, - [0x13] = KEY_RIGHT, - [0x14] = KEY_DOWN, - [0x15] = KEY_TEXT, - [0x16] = KEY_INFO, - - [0x17] = KEY_RED, - [0x18] = KEY_GREEN, - [0x19] = KEY_YELLOW, - [0x1a] = KEY_BLUE, - - [0x1b] = KEY_CHANNELUP, - [0x1c] = KEY_VOLUMEUP, - [0x1d] = KEY_MUTE, - [0x1e] = KEY_VOLUMEDOWN, - [0x1f] = KEY_CHANNELDOWN, - - [0x40] = KEY_PAUSE, - [0x4c] = KEY_PLAY, - [0x58] = KEY_RECORD, - [0x54] = KEY_PREVIOUS, - [0x48] = KEY_STOP, - [0x5c] = KEY_NEXT, -}; - -/* ---------------------------------------------------------------------- */ - -/* AVERTV STUDIO 303 Remote */ -static IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE] = { - [ 0x2a ] = KEY_KP1, - [ 0x32 ] = KEY_KP2, - [ 0x3a ] = KEY_KP3, - [ 0x4a ] = KEY_KP4, - [ 0x52 ] = KEY_KP5, - [ 0x5a ] = KEY_KP6, - [ 0x6a ] = KEY_KP7, - [ 0x72 ] = KEY_KP8, - [ 0x7a ] = KEY_KP9, - [ 0x0e ] = KEY_KP0, - - [ 0x02 ] = KEY_POWER, - [ 0x22 ] = KEY_VIDEO, - [ 0x42 ] = KEY_AUDIO, - [ 0x62 ] = KEY_ZOOM, - [ 0x0a ] = KEY_TV, - [ 0x12 ] = KEY_CD, - [ 0x1a ] = KEY_TEXT, - - [ 0x16 ] = KEY_SUBTITLE, - [ 0x1e ] = KEY_REWIND, - [ 0x06 ] = KEY_PRINT, - - [ 0x2e ] = KEY_SEARCH, - [ 0x36 ] = KEY_SLEEP, - [ 0x3e ] = KEY_SHUFFLE, - [ 0x26 ] = KEY_MUTE, - - [ 0x4e ] = KEY_RECORD, - [ 0x56 ] = KEY_PAUSE, - [ 0x5e ] = KEY_STOP, - [ 0x46 ] = KEY_PLAY, - - [ 0x6e ] = KEY_RED, - [ 0x0b ] = KEY_GREEN, - [ 0x66 ] = KEY_YELLOW, - [ 0x03 ] = KEY_BLUE, - - [ 0x76 ] = KEY_LEFT, - [ 0x7e ] = KEY_RIGHT, - [ 0x13 ] = KEY_DOWN, - [ 0x1b ] = KEY_UP, -}; - -/* ---------------------------------------------------------------------- */ - -/* DigitalNow DNTV Live! DVB-T Pro Remote */ -static IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE] = { - [ 0x16 ] = KEY_POWER, - [ 0x5b ] = KEY_HOME, - - [ 0x55 ] = KEY_TV, /* live tv */ - [ 0x58 ] = KEY_TUNER, /* digital Radio */ - [ 0x5a ] = KEY_RADIO, /* FM radio */ - [ 0x59 ] = KEY_DVD, /* dvd menu */ - [ 0x03 ] = KEY_1, - [ 0x01 ] = KEY_2, - [ 0x06 ] = KEY_3, - [ 0x09 ] = KEY_4, - [ 0x1d ] = KEY_5, - [ 0x1f ] = KEY_6, - [ 0x0d ] = KEY_7, - [ 0x19 ] = KEY_8, - [ 0x1b ] = KEY_9, - [ 0x0c ] = KEY_CANCEL, - [ 0x15 ] = KEY_0, - [ 0x4a ] = KEY_CLEAR, - [ 0x13 ] = KEY_BACK, - [ 0x00 ] = KEY_TAB, - [ 0x4b ] = KEY_UP, - [ 0x4e ] = KEY_LEFT, - [ 0x4f ] = KEY_OK, - [ 0x52 ] = KEY_RIGHT, - [ 0x51 ] = KEY_DOWN, - [ 0x1e ] = KEY_VOLUMEUP, - [ 0x0a ] = KEY_VOLUMEDOWN, - [ 0x02 ] = KEY_CHANNELDOWN, - [ 0x05 ] = KEY_CHANNELUP, - [ 0x11 ] = KEY_RECORD, - [ 0x14 ] = KEY_PLAY, - [ 0x4c ] = KEY_PAUSE, - [ 0x1a ] = KEY_STOP, - [ 0x40 ] = KEY_REWIND, - [ 0x12 ] = KEY_FASTFORWARD, - [ 0x41 ] = KEY_PREVIOUSSONG, /* replay |< */ - [ 0x42 ] = KEY_NEXTSONG, /* skip >| */ - [ 0x54 ] = KEY_CAMERA, /* capture */ - [ 0x50 ] = KEY_LANGUAGE, /* sap */ - [ 0x47 ] = KEY_TV2, /* pip */ - [ 0x4d ] = KEY_SCREEN, - [ 0x43 ] = KEY_SUBTITLE, - [ 0x10 ] = KEY_MUTE, - [ 0x49 ] = KEY_AUDIO, /* l/r */ - [ 0x07 ] = KEY_SLEEP, - [ 0x08 ] = KEY_VIDEO, /* a/v */ - [ 0x0e ] = KEY_PREVIOUS, /* recall */ - [ 0x45 ] = KEY_ZOOM, /* zoom + */ - [ 0x46 ] = KEY_ANGLE, /* zoom - */ - [ 0x56 ] = KEY_RED, - [ 0x57 ] = KEY_GREEN, - [ 0x5c ] = KEY_YELLOW, - [ 0x5d ] = KEY_BLUE, -}; - -/* ---------------------------------------------------------------------- */ - struct cx88_IR { struct cx88_core *core; struct input_dev *input; diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 30dfa5370c73..31e89e4f18be 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -43,91 +43,6 @@ MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); #define dprintk(fmt, arg...) if (ir_debug) \ printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) -/* ---------------------------------------------------------------------- */ - -static IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = { - [ 0x01 ] = KEY_CHANNEL, - [ 0x02 ] = KEY_SELECT, - [ 0x03 ] = KEY_MUTE, - [ 0x04 ] = KEY_POWER, - [ 0x05 ] = KEY_KP1, - [ 0x06 ] = KEY_KP2, - [ 0x07 ] = KEY_KP3, - [ 0x08 ] = KEY_CHANNELUP, - [ 0x09 ] = KEY_KP4, - [ 0x0a ] = KEY_KP5, - [ 0x0b ] = KEY_KP6, - [ 0x0c ] = KEY_CHANNELDOWN, - [ 0x0d ] = KEY_KP7, - [ 0x0e ] = KEY_KP8, - [ 0x0f ] = KEY_KP9, - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_KP0, - [ 0x12 ] = KEY_MENU, - [ 0x13 ] = KEY_PRINT, - [ 0x14 ] = KEY_VOLUMEDOWN, - [ 0x16 ] = KEY_PAUSE, - [ 0x18 ] = KEY_RECORD, - [ 0x19 ] = KEY_REWIND, - [ 0x1a ] = KEY_PLAY, - [ 0x1b ] = KEY_FORWARD, - [ 0x1c ] = KEY_BACKSPACE, - [ 0x1e ] = KEY_STOP, - [ 0x40 ] = KEY_ZOOM, -}; - -static IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = { - [ 0x3a ] = KEY_KP0, - [ 0x31 ] = KEY_KP1, - [ 0x32 ] = KEY_KP2, - [ 0x33 ] = KEY_KP3, - [ 0x34 ] = KEY_KP4, - [ 0x35 ] = KEY_KP5, - [ 0x36 ] = KEY_KP6, - [ 0x37 ] = KEY_KP7, - [ 0x38 ] = KEY_KP8, - [ 0x39 ] = KEY_KP9, - - [ 0x2f ] = KEY_POWER, - - [ 0x2e ] = KEY_P, - [ 0x1f ] = KEY_L, - [ 0x2b ] = KEY_I, - - [ 0x2d ] = KEY_ZOOM, - [ 0x1e ] = KEY_ZOOM, - [ 0x1b ] = KEY_VOLUMEUP, - [ 0x0f ] = KEY_VOLUMEDOWN, - [ 0x17 ] = KEY_CHANNELUP, - [ 0x1c ] = KEY_CHANNELDOWN, - [ 0x25 ] = KEY_INFO, - - [ 0x3c ] = KEY_MUTE, - - [ 0x3d ] = KEY_LEFT, - [ 0x3b ] = KEY_RIGHT, - - [ 0x3f ] = KEY_UP, - [ 0x3e ] = KEY_DOWN, - [ 0x1a ] = KEY_PAUSE, - - [ 0x1d ] = KEY_MENU, - [ 0x19 ] = KEY_PLAY, - [ 0x16 ] = KEY_REWIND, - [ 0x13 ] = KEY_FORWARD, - [ 0x15 ] = KEY_PAUSE, - [ 0x0e ] = KEY_REWIND, - [ 0x0d ] = KEY_PLAY, - [ 0x0b ] = KEY_STOP, - [ 0x07 ] = KEY_FORWARD, - [ 0x27 ] = KEY_RECORD, - [ 0x26 ] = KEY_TUNER, - [ 0x29 ] = KEY_TEXT, - [ 0x2a ] = KEY_MEDIA, - [ 0x18 ] = KEY_EPG, - [ 0x27 ] = KEY_RECORD, -}; - /* ----------------------------------------------------------------------- */ static int get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 3963481b3130..95bacf435414 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -44,45 +44,6 @@ #include #include -/* Mark Phalan */ -static IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = { - [ 0 ] = KEY_KP0, - [ 1 ] = KEY_KP1, - [ 2 ] = KEY_KP2, - [ 3 ] = KEY_KP3, - [ 4 ] = KEY_KP4, - [ 5 ] = KEY_KP5, - [ 6 ] = KEY_KP6, - [ 7 ] = KEY_KP7, - [ 8 ] = KEY_KP8, - [ 9 ] = KEY_KP9, - - [ 18 ] = KEY_POWER, - [ 16 ] = KEY_MUTE, - [ 31 ] = KEY_VOLUMEDOWN, - [ 27 ] = KEY_VOLUMEUP, - [ 26 ] = KEY_CHANNELUP, - [ 30 ] = KEY_CHANNELDOWN, - [ 14 ] = KEY_PAGEUP, - [ 29 ] = KEY_PAGEDOWN, - [ 19 ] = KEY_SOUND, - - [ 24 ] = KEY_KPPLUSMINUS, /* CH +/- */ - [ 22 ] = KEY_SUBTITLE, /* CC */ - [ 13 ] = KEY_TEXT, /* TTX */ - [ 11 ] = KEY_TV, /* AIR/CBL */ - [ 17 ] = KEY_PC, /* PC/TV */ - [ 23 ] = KEY_OK, /* CH RTN */ - [ 25 ] = KEY_MODE, /* FUNC */ - [ 12 ] = KEY_SEARCH, /* AUTOSCAN */ - - /* Not sure what to do with these ones! */ - [ 15 ] = KEY_SELECT, /* SOURCE */ - [ 10 ] = KEY_KPPLUS, /* +100 */ - [ 20 ] = KEY_KPEQUAL, /* SYNC */ - [ 28 ] = KEY_MEDIA, /* PC/TV */ -}; - /* ----------------------------------------------------------------------- */ /* insmod parameters */ @@ -342,7 +303,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir->get_key = get_key_haup; ir_type = IR_TYPE_RC5; if (hauppauge == 1) { - ir_codes = ir_codes_rc5_tv_grey; + ir_codes = ir_codes_hauppauge_new; } else { ir_codes = ir_codes_rc5_tv; } diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 82d28cbf289f..342568cf728f 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -42,485 +42,6 @@ MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); #define i2cdprintk(fmt, arg...) if (ir_debug) \ printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) -/* ---------------------------------------------------------------------- */ - -static IR_KEYTAB_TYPE flyvideo_codes[IR_KEYTAB_SIZE] = { - [ 15 ] = KEY_KP0, - [ 3 ] = KEY_KP1, - [ 4 ] = KEY_KP2, - [ 5 ] = KEY_KP3, - [ 7 ] = KEY_KP4, - [ 8 ] = KEY_KP5, - [ 9 ] = KEY_KP6, - [ 11 ] = KEY_KP7, - [ 12 ] = KEY_KP8, - [ 13 ] = KEY_KP9, - - [ 14 ] = KEY_MODE, // Air/Cable - [ 17 ] = KEY_VIDEO, // Video - [ 21 ] = KEY_AUDIO, // Audio - [ 0 ] = KEY_POWER, // Power - [ 24 ] = KEY_TUNER, // AV Source - [ 2 ] = KEY_ZOOM, // Fullscreen - [ 26 ] = KEY_LANGUAGE, // Stereo - [ 27 ] = KEY_MUTE, // Mute - [ 20 ] = KEY_VOLUMEUP, // Volume + - [ 23 ] = KEY_VOLUMEDOWN, // Volume - - [ 18 ] = KEY_CHANNELUP, // Channel + - [ 19 ] = KEY_CHANNELDOWN, // Channel - - [ 6 ] = KEY_AGAIN, // Recall - [ 16 ] = KEY_ENTER, // Enter -}; - - -static IR_KEYTAB_TYPE cinergy_codes[IR_KEYTAB_SIZE] = { - [ 0 ] = KEY_KP0, - [ 1 ] = KEY_KP1, - [ 2 ] = KEY_KP2, - [ 3 ] = KEY_KP3, - [ 4 ] = KEY_KP4, - [ 5 ] = KEY_KP5, - [ 6 ] = KEY_KP6, - [ 7 ] = KEY_KP7, - [ 8 ] = KEY_KP8, - [ 9 ] = KEY_KP9, - - [ 0x0a ] = KEY_POWER, - [ 0x0b ] = KEY_PROG1, // app - [ 0x0c ] = KEY_ZOOM, // zoom/fullscreen - [ 0x0d ] = KEY_CHANNELUP, // channel - [ 0x0e ] = KEY_CHANNELDOWN, // channel- - [ 0x0f ] = KEY_VOLUMEUP, - [ 0x10 ] = KEY_VOLUMEDOWN, - [ 0x11 ] = KEY_TUNER, // AV - [ 0x12 ] = KEY_NUMLOCK, // -/-- - [ 0x13 ] = KEY_AUDIO, // audio - [ 0x14 ] = KEY_MUTE, - [ 0x15 ] = KEY_UP, - [ 0x16 ] = KEY_DOWN, - [ 0x17 ] = KEY_LEFT, - [ 0x18 ] = KEY_RIGHT, - [ 0x19 ] = BTN_LEFT, - [ 0x1a ] = BTN_RIGHT, - [ 0x1b ] = KEY_WWW, // text - [ 0x1c ] = KEY_REWIND, - [ 0x1d ] = KEY_FORWARD, - [ 0x1e ] = KEY_RECORD, - [ 0x1f ] = KEY_PLAY, - [ 0x20 ] = KEY_PREVIOUSSONG, - [ 0x21 ] = KEY_NEXTSONG, - [ 0x22 ] = KEY_PAUSE, - [ 0x23 ] = KEY_STOP, -}; - -/* Alfons Geser - * updates from Job D. R. Borges */ -static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = { - [ 18 ] = KEY_POWER, - [ 1 ] = KEY_TV, // DVR - [ 21 ] = KEY_DVD, // DVD - [ 23 ] = KEY_AUDIO, // music - // DVR mode / DVD mode / music mode - - [ 27 ] = KEY_MUTE, // mute - [ 2 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek - [ 30 ] = KEY_SUBTITLE, // closed captioning / subtitle / seek - [ 22 ] = KEY_ZOOM, // full screen - [ 28 ] = KEY_VIDEO, // video source / eject / delall - [ 29 ] = KEY_RESTART, // playback / angle / del - [ 47 ] = KEY_SEARCH, // scan / menu / playlist - [ 48 ] = KEY_CHANNEL, // CH surfing / bookmark / memo - - [ 49 ] = KEY_HELP, // help - [ 50 ] = KEY_MODE, // num/memo - [ 51 ] = KEY_ESC, // cancel - - [ 12 ] = KEY_UP, // up - [ 16 ] = KEY_DOWN, // down - [ 8 ] = KEY_LEFT, // left - [ 4 ] = KEY_RIGHT, // right - [ 3 ] = KEY_SELECT, // select - - [ 31 ] = KEY_REWIND, // rewind - [ 32 ] = KEY_PLAYPAUSE, // play/pause - [ 41 ] = KEY_FORWARD, // forward - [ 20 ] = KEY_AGAIN, // repeat - [ 43 ] = KEY_RECORD, // recording - [ 44 ] = KEY_STOP, // stop - [ 45 ] = KEY_PLAY, // play - [ 46 ] = KEY_SHUFFLE, // snapshot / shuffle - - [ 0 ] = KEY_KP0, - [ 5 ] = KEY_KP1, - [ 6 ] = KEY_KP2, - [ 7 ] = KEY_KP3, - [ 9 ] = KEY_KP4, - [ 10 ] = KEY_KP5, - [ 11 ] = KEY_KP6, - [ 13 ] = KEY_KP7, - [ 14 ] = KEY_KP8, - [ 15 ] = KEY_KP9, - - [ 42 ] = KEY_VOLUMEUP, - [ 17 ] = KEY_VOLUMEDOWN, - [ 24 ] = KEY_CHANNELUP, // CH.tracking up - [ 25 ] = KEY_CHANNELDOWN, // CH.tracking down - - [ 19 ] = KEY_KPENTER, // enter - [ 33 ] = KEY_KPDOT, // . (decimal dot) -}; - -static IR_KEYTAB_TYPE avacssmart_codes[IR_KEYTAB_SIZE] = { - [ 30 ] = KEY_POWER, // power - [ 28 ] = KEY_SEARCH, // scan - [ 7 ] = KEY_SELECT, // source - - [ 22 ] = KEY_VOLUMEUP, - [ 20 ] = KEY_VOLUMEDOWN, - [ 31 ] = KEY_CHANNELUP, - [ 23 ] = KEY_CHANNELDOWN, - [ 24 ] = KEY_MUTE, - - [ 2 ] = KEY_KP0, - [ 1 ] = KEY_KP1, - [ 11 ] = KEY_KP2, - [ 27 ] = KEY_KP3, - [ 5 ] = KEY_KP4, - [ 9 ] = KEY_KP5, - [ 21 ] = KEY_KP6, - [ 6 ] = KEY_KP7, - [ 10 ] = KEY_KP8, - [ 18 ] = KEY_KP9, - [ 16 ] = KEY_KPDOT, - - [ 3 ] = KEY_TUNER, // tv/fm - [ 4 ] = KEY_REWIND, // fm tuning left or function left - [ 12 ] = KEY_FORWARD, // fm tuning right or function right - - [ 0 ] = KEY_RECORD, - [ 8 ] = KEY_STOP, - [ 17 ] = KEY_PLAY, - - [ 25 ] = KEY_ZOOM, - [ 14 ] = KEY_MENU, // function - [ 19 ] = KEY_AGAIN, // recall - [ 29 ] = KEY_RESTART, // reset - [ 26 ] = KEY_SHUFFLE, // snapshot/shuffle - -// FIXME - [ 13 ] = KEY_F21, // mts - [ 15 ] = KEY_F22, // min -}; - -/* Alex Hermann */ -static IR_KEYTAB_TYPE md2819_codes[IR_KEYTAB_SIZE] = { - [ 40 ] = KEY_KP1, - [ 24 ] = KEY_KP2, - [ 56 ] = KEY_KP3, - [ 36 ] = KEY_KP4, - [ 20 ] = KEY_KP5, - [ 52 ] = KEY_KP6, - [ 44 ] = KEY_KP7, - [ 28 ] = KEY_KP8, - [ 60 ] = KEY_KP9, - [ 34 ] = KEY_KP0, - - [ 32 ] = KEY_TV, // TV/FM - [ 16 ] = KEY_CD, // CD - [ 48 ] = KEY_TEXT, // TELETEXT - [ 0 ] = KEY_POWER, // POWER - - [ 8 ] = KEY_VIDEO, // VIDEO - [ 4 ] = KEY_AUDIO, // AUDIO - [ 12 ] = KEY_ZOOM, // FULL SCREEN - - [ 18 ] = KEY_SUBTITLE, // DISPLAY - ??? - [ 50 ] = KEY_REWIND, // LOOP - ??? - [ 2 ] = KEY_PRINT, // PREVIEW - ??? - - [ 42 ] = KEY_SEARCH, // AUTOSCAN - [ 26 ] = KEY_SLEEP, // FREEZE - ??? - [ 58 ] = KEY_SHUFFLE, // SNAPSHOT - ??? - [ 10 ] = KEY_MUTE, // MUTE - - [ 38 ] = KEY_RECORD, // RECORD - [ 22 ] = KEY_PAUSE, // PAUSE - [ 54 ] = KEY_STOP, // STOP - [ 6 ] = KEY_PLAY, // PLAY - - [ 46 ] = KEY_RED, // - [ 33 ] = KEY_GREEN, // - [ 14 ] = KEY_YELLOW, // - [ 1 ] = KEY_BLUE, // - - [ 30 ] = KEY_VOLUMEDOWN, // VOLUME- - [ 62 ] = KEY_VOLUMEUP, // VOLUME+ - [ 17 ] = KEY_CHANNELDOWN, // CHANNEL/PAGE- - [ 49 ] = KEY_CHANNELUP // CHANNEL/PAGE+ -}; - -static IR_KEYTAB_TYPE videomate_tv_pvr_codes[IR_KEYTAB_SIZE] = { - [ 20 ] = KEY_MUTE, - [ 36 ] = KEY_ZOOM, - - [ 1 ] = KEY_DVD, - [ 35 ] = KEY_RADIO, - [ 0 ] = KEY_TV, - - [ 10 ] = KEY_REWIND, - [ 8 ] = KEY_PLAYPAUSE, - [ 15 ] = KEY_FORWARD, - - [ 2 ] = KEY_PREVIOUS, - [ 7 ] = KEY_STOP, - [ 6 ] = KEY_NEXT, - - [ 12 ] = KEY_UP, - [ 14 ] = KEY_DOWN, - [ 11 ] = KEY_LEFT, - [ 13 ] = KEY_RIGHT, - [ 17 ] = KEY_OK, - - [ 3 ] = KEY_MENU, - [ 9 ] = KEY_SETUP, - [ 5 ] = KEY_VIDEO, - [ 34 ] = KEY_CHANNEL, - - [ 18 ] = KEY_VOLUMEUP, - [ 21 ] = KEY_VOLUMEDOWN, - [ 16 ] = KEY_CHANNELUP, - [ 19 ] = KEY_CHANNELDOWN, - - [ 4 ] = KEY_RECORD, - - [ 22 ] = KEY_KP1, - [ 23 ] = KEY_KP2, - [ 24 ] = KEY_KP3, - [ 25 ] = KEY_KP4, - [ 26 ] = KEY_KP5, - [ 27 ] = KEY_KP6, - [ 28 ] = KEY_KP7, - [ 29 ] = KEY_KP8, - [ 30 ] = KEY_KP9, - [ 31 ] = KEY_KP0, - - [ 32 ] = KEY_LANGUAGE, - [ 33 ] = KEY_SLEEP, -}; - -/* Michael Tokarev - http://www.corpit.ru/mjt/beholdTV/remote_control.jpg - keytable is used by MANLI MTV00[12] and BeholdTV 40[13] at - least, and probably other cards too. - The "ascii-art picture" below (in comments, first row - is the keycode in hex, and subsequent row(s) shows - the button labels (several variants when appropriate) - helps to descide which keycodes to assign to the buttons. - */ -static IR_KEYTAB_TYPE manli_codes[IR_KEYTAB_SIZE] = { - - /* 0x1c 0x12 * - * FUNCTION POWER * - * FM (|) * - * */ - [ 0x1c ] = KEY_RADIO, /*XXX*/ - [ 0x12 ] = KEY_POWER, - - /* 0x01 0x02 0x03 * - * 1 2 3 * - * * - * 0x04 0x05 0x06 * - * 4 5 6 * - * * - * 0x07 0x08 0x09 * - * 7 8 9 * - * */ - [ 0x01 ] = KEY_KP1, - [ 0x02 ] = KEY_KP2, - [ 0x03 ] = KEY_KP3, - [ 0x04 ] = KEY_KP4, - [ 0x05 ] = KEY_KP5, - [ 0x06 ] = KEY_KP6, - [ 0x07 ] = KEY_KP7, - [ 0x08 ] = KEY_KP8, - [ 0x09 ] = KEY_KP9, - - /* 0x0a 0x00 0x17 * - * RECALL 0 +100 * - * PLUS * - * */ - [ 0x0a ] = KEY_AGAIN, /*XXX KEY_REWIND? */ - [ 0x00 ] = KEY_KP0, - [ 0x17 ] = KEY_DIGITS, /*XXX*/ - - /* 0x14 0x10 * - * MENU INFO * - * OSD */ - [ 0x14 ] = KEY_MENU, - [ 0x10 ] = KEY_INFO, - - /* 0x0b * - * Up * - * * - * 0x18 0x16 0x0c * - * Left Ok Right * - * * - * 0x015 * - * Down * - * */ - [ 0x0b ] = KEY_UP, /*XXX KEY_SCROLLUP? */ - [ 0x18 ] = KEY_LEFT, /*XXX KEY_BACK? */ - [ 0x16 ] = KEY_OK, /*XXX KEY_SELECT? KEY_ENTER? */ - [ 0x0c ] = KEY_RIGHT, /*XXX KEY_FORWARD? */ - [ 0x15 ] = KEY_DOWN, /*XXX KEY_SCROLLDOWN? */ - - /* 0x11 0x0d * - * TV/AV MODE * - * SOURCE STEREO * - * */ - [ 0x11 ] = KEY_TV, /*XXX*/ - [ 0x0d ] = KEY_MODE, /*XXX there's no KEY_STEREO */ - - /* 0x0f 0x1b 0x1a * - * AUDIO Vol+ Chan+ * - * TIMESHIFT??? * - * * - * 0x0e 0x1f 0x1e * - * SLEEP Vol- Chan- * - * */ - [ 0x0f ] = KEY_AUDIO, - [ 0x1b ] = KEY_VOLUMEUP, - [ 0x1a ] = KEY_CHANNELUP, - [ 0x0e ] = KEY_SLEEP, /*XXX maybe KEY_PAUSE */ - [ 0x1f ] = KEY_VOLUMEDOWN, - [ 0x1e ] = KEY_CHANNELDOWN, - - /* 0x13 0x19 * - * MUTE SNAPSHOT* - * */ - [ 0x13 ] = KEY_MUTE, - [ 0x19 ] = KEY_RECORD, /*XXX*/ - - // 0x1d unused ? -}; - - -/* Mike Baikov */ -static IR_KEYTAB_TYPE gotview7135_codes[IR_KEYTAB_SIZE] = { - - [ 33 ] = KEY_POWER, - [ 105] = KEY_TV, - [ 51 ] = KEY_KP0, - [ 81 ] = KEY_KP1, - [ 49 ] = KEY_KP2, - [ 113] = KEY_KP3, - [ 59 ] = KEY_KP4, - [ 88 ] = KEY_KP5, - [ 65 ] = KEY_KP6, - [ 72 ] = KEY_KP7, - [ 48 ] = KEY_KP8, - [ 83 ] = KEY_KP9, - [ 115] = KEY_AGAIN, /* LOOP */ - [ 10 ] = KEY_AUDIO, - [ 97 ] = KEY_PRINT, /* PREVIEW */ - [ 122] = KEY_VIDEO, - [ 32 ] = KEY_CHANNELUP, - [ 64 ] = KEY_CHANNELDOWN, - [ 24 ] = KEY_VOLUMEDOWN, - [ 80 ] = KEY_VOLUMEUP, - [ 16 ] = KEY_MUTE, - [ 74 ] = KEY_SEARCH, - [ 123] = KEY_SHUFFLE, /* SNAPSHOT */ - [ 34 ] = KEY_RECORD, - [ 98 ] = KEY_STOP, - [ 120] = KEY_PLAY, - [ 57 ] = KEY_REWIND, - [ 89 ] = KEY_PAUSE, - [ 25 ] = KEY_FORWARD, - [ 9 ] = KEY_ZOOM, - - [ 82 ] = KEY_F21, /* LIVE TIMESHIFT */ - [ 26 ] = KEY_F22, /* MIN TIMESHIFT */ - [ 58 ] = KEY_F23, /* TIMESHIFT */ - [ 112] = KEY_F24, /* NORMAL TIMESHIFT */ -}; - -static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { - [ 0x3 ] = KEY_POWER, - [ 0x6f ] = KEY_MUTE, - [ 0x10 ] = KEY_BACKSPACE, /* Recall */ - - [ 0x11 ] = KEY_KP0, - [ 0x4 ] = KEY_KP1, - [ 0x5 ] = KEY_KP2, - [ 0x6 ] = KEY_KP3, - [ 0x8 ] = KEY_KP4, - [ 0x9 ] = KEY_KP5, - [ 0xa ] = KEY_KP6, - [ 0xc ] = KEY_KP7, - [ 0xd ] = KEY_KP8, - [ 0xe ] = KEY_KP9, - [ 0x12 ] = KEY_KPDOT, /* 100+ */ - - [ 0x7 ] = KEY_VOLUMEUP, - [ 0xb ] = KEY_VOLUMEDOWN, - [ 0x1a ] = KEY_KPPLUS, - [ 0x18 ] = KEY_KPMINUS, - [ 0x15 ] = KEY_UP, - [ 0x1d ] = KEY_DOWN, - [ 0xf ] = KEY_CHANNELUP, - [ 0x13 ] = KEY_CHANNELDOWN, - [ 0x48 ] = KEY_ZOOM, - - [ 0x1b ] = KEY_VIDEO, /* Video source */ - [ 0x49 ] = KEY_LANGUAGE, /* MTS Select */ - [ 0x19 ] = KEY_SEARCH, /* Auto Scan */ - - [ 0x4b ] = KEY_RECORD, - [ 0x46 ] = KEY_PLAY, - [ 0x45 ] = KEY_PAUSE, /* Pause */ - [ 0x44 ] = KEY_STOP, - [ 0x40 ] = KEY_FORWARD, /* Forward ? */ - [ 0x42 ] = KEY_REWIND, /* Backward ? */ - -}; - -/* Mapping for the 28 key remote control as seen at - http://www.sednacomputer.com/photo/cardbus-tv.jpg - Pavel Mihaylov */ -static IR_KEYTAB_TYPE pctv_sedna_codes[IR_KEYTAB_SIZE] = { - [ 0 ] = KEY_KP0, - [ 1 ] = KEY_KP1, - [ 2 ] = KEY_KP2, - [ 3 ] = KEY_KP3, - [ 4 ] = KEY_KP4, - [ 5 ] = KEY_KP5, - [ 6 ] = KEY_KP6, - [ 7 ] = KEY_KP7, - [ 8 ] = KEY_KP8, - [ 9 ] = KEY_KP9, - - [ 0x0a ] = KEY_AGAIN, /* Recall */ - [ 0x0b ] = KEY_CHANNELUP, - [ 0x0c ] = KEY_VOLUMEUP, - [ 0x0d ] = KEY_MODE, /* Stereo */ - [ 0x0e ] = KEY_STOP, - [ 0x0f ] = KEY_PREVIOUSSONG, - [ 0x10 ] = KEY_ZOOM, - [ 0x11 ] = KEY_TUNER, /* Source */ - [ 0x12 ] = KEY_POWER, - [ 0x13 ] = KEY_MUTE, - [ 0x15 ] = KEY_CHANNELDOWN, - [ 0x18 ] = KEY_VOLUMEDOWN, - [ 0x19 ] = KEY_SHUFFLE, /* Snapshot */ - [ 0x1a ] = KEY_NEXTSONG, - [ 0x1b ] = KEY_TEXT, /* Time Shift */ - [ 0x1c ] = KEY_RADIO, /* FM Radio */ - [ 0x1d ] = KEY_RECORD, - [ 0x1e ] = KEY_PAUSE, -}; - - /* -------------------- GPIO generic keycode builder -------------------- */ static int build_key(struct saa7134_dev *dev) @@ -628,27 +149,27 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_FLYVIDEO3000: case SAA7134_BOARD_FLYTVPLATINUM_FM: case SAA7134_BOARD_FLYTVPLATINUM_MINI2: - ir_codes = flyvideo_codes; + ir_codes = ir_codes_flyvideo; mask_keycode = 0xEC00000; mask_keydown = 0x0040000; break; case SAA7134_BOARD_CINERGY400: case SAA7134_BOARD_CINERGY600: case SAA7134_BOARD_CINERGY600_MK3: - ir_codes = cinergy_codes; + ir_codes = ir_codes_cinergy; mask_keycode = 0x00003f; mask_keyup = 0x040000; break; case SAA7134_BOARD_ECS_TVP3XP: case SAA7134_BOARD_ECS_TVP3XP_4CB5: - ir_codes = eztv_codes; + ir_codes = ir_codes_eztv; mask_keycode = 0x00017c; mask_keyup = 0x000002; polling = 50; // ms break; case SAA7134_BOARD_KWORLD_XPERT: case SAA7134_BOARD_AVACSSMARTTV: - ir_codes = avacssmart_codes; + ir_codes = ir_codes_avacssmart; mask_keycode = 0x00001F; mask_keyup = 0x000020; polling = 50; // ms @@ -660,7 +181,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_STUDIO_305: case SAA7134_BOARD_AVERMEDIA_STUDIO_307: case SAA7134_BOARD_AVERMEDIA_GO_007_FM: - ir_codes = md2819_codes; + ir_codes = ir_codes_md2819; mask_keycode = 0x0007C8; mask_keydown = 0x000010; polling = 50; // ms @@ -669,7 +190,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); break; case SAA7134_BOARD_KWORLD_TERMINATOR: - ir_codes = avacssmart_codes; + ir_codes = ir_codes_avacssmart; mask_keycode = 0x00001f; mask_keyup = 0x000060; polling = 50; // ms @@ -677,19 +198,19 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: case SAA7134_BOARD_BEHOLD_409FM: - ir_codes = manli_codes; + ir_codes = ir_codes_manli; mask_keycode = 0x001f00; mask_keyup = 0x004000; polling = 50; // ms break; case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS: - ir_codes = pctv_sedna_codes; + ir_codes = ir_codes_pctv_sedna; mask_keycode = 0x001f00; mask_keyup = 0x004000; polling = 50; // ms break; case SAA7134_BOARD_GOTVIEW_7135: - ir_codes = gotview7135_codes; + ir_codes = ir_codes_gotview7135; mask_keycode = 0x0003EC; mask_keyup = 0x008000; mask_keydown = 0x000010; @@ -698,14 +219,14 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_VIDEOMATE_TV_PVR: case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: - ir_codes = videomate_tv_pvr_codes; + ir_codes = ir_codes_videomate_tv_pvr; mask_keycode = 0x00003F; mask_keyup = 0x400000; polling = 50; // ms break; case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_VIDEOMATE_DVBT_200: - ir_codes = videomate_tv_pvr_codes; + ir_codes = ir_codes_videomate_tv_pvr; mask_keycode = 0x003F00; mask_keyup = 0x040000; break; diff --git a/include/media/ir-common.h b/include/media/ir-common.h index ad3e9bb670c3..50fe522bad33 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -47,13 +47,6 @@ struct ir_input_state { int keypressed; /* current state */ }; -extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE]; - void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, int ir_type, IR_KEYTAB_TYPE *ir_codes); void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir); @@ -64,6 +57,41 @@ int ir_dump_samples(u32 *samples, int count); int ir_decode_biphase(u32 *samples, int count, int low, int high); int ir_decode_pulsedistance(u32 *samples, int count, int low, int high); +/* Keymaps to be used by other modules */ + +extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_conceptronic[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_adstech_dvb_t_pci[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_avacssmart[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_md2819[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_videomate_tv_pvr[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE]; + #endif /* -- cgit v1.2.3 From b639f9d286f2216795492eac2a39b8ed6b4d555c Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Mon, 23 Jan 2006 09:44:10 -0200 Subject: V4L/DVB (3400): Remove duplicated keymaps and add keymap for KWorld LTV883IR. - Remove duplicated keymaps and add keymap for KWorld LTV883IR. Thanks to Jon Ferguson . Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-keymaps.c | 194 ++++++---------------------- drivers/media/video/bttv-input.c | 2 +- drivers/media/video/cx88/cx88-input.c | 7 + drivers/media/video/saa7134/saa7134-input.c | 6 +- include/media/ir-common.h | 6 +- 5 files changed, 49 insertions(+), 166 deletions(-) (limited to 'include') diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index 468f66013393..a294d5c2c73f 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -32,50 +32,6 @@ IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = { EXPORT_SYMBOL_GPL(ir_codes_empty); -IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { - [ 0x22 ] = KEY_0, - [ 0x28 ] = KEY_1, - [ 0x18 ] = KEY_2, - [ 0x38 ] = KEY_3, - [ 0x24 ] = KEY_4, - [ 0x14 ] = KEY_5, - [ 0x34 ] = KEY_6, - [ 0x2c ] = KEY_7, - [ 0x1c ] = KEY_8, - [ 0x3c ] = KEY_9, - - [ 0x30 ] = KEY_EJECTCD, // Unmarked on my controller - [ 0x00 ] = KEY_POWER, - [ 0x12 ] = BTN_LEFT, // DISPLAY/L - [ 0x32 ] = BTN_RIGHT, // LOOP/R - [ 0x0a ] = KEY_MUTE, - [ 0x26 ] = KEY_RECORD, - [ 0x16 ] = KEY_PAUSE, - [ 0x36 ] = KEY_STOP, - [ 0x1e ] = KEY_VOLUMEDOWN, - [ 0x3e ] = KEY_VOLUMEUP, - - [ 0x20 ] = KEY_TUNER, // TV/FM - [ 0x10 ] = KEY_CD, - [ 0x08 ] = KEY_VIDEO, - [ 0x04 ] = KEY_AUDIO, - [ 0x0c ] = KEY_ZOOM, // full screen - [ 0x02 ] = KEY_INFO, // preview - [ 0x2a ] = KEY_SEARCH, // autoscan - [ 0x1a ] = KEY_STOP, // freeze - [ 0x3a ] = KEY_RECORD, // capture - [ 0x06 ] = KEY_PLAY, // unmarked - [ 0x2e ] = KEY_RED, // unmarked - [ 0x0e ] = KEY_GREEN, // unmarked - - [ 0x21 ] = KEY_YELLOW, // unmarked - [ 0x11 ] = KEY_CHANNELDOWN, - [ 0x31 ] = KEY_CHANNELUP, - [ 0x01 ] = KEY_BLUE, // unmarked -}; - -EXPORT_SYMBOL_GPL(ir_codes_avermedia); - /* Matt Jesson */ -IR_KEYTAB_TYPE ir_codes_md2819[IR_KEYTAB_SIZE] = { +IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { [ 0x28 ] = KEY_1, [ 0x18 ] = KEY_2, [ 0x38 ] = KEY_3, @@ -945,41 +857,41 @@ IR_KEYTAB_TYPE ir_codes_md2819[IR_KEYTAB_SIZE] = { [ 0x3c ] = KEY_9, [ 0x22 ] = KEY_0, - [ 0x20 ] = KEY_TV, // TV/FM - [ 0x10 ] = KEY_CD, // CD - [ 0x30 ] = KEY_TEXT, // TELETEXT - [ 0x00 ] = KEY_POWER, // POWER - - [ 0x08 ] = KEY_VIDEO, // VIDEO - [ 0x04 ] = KEY_AUDIO, // AUDIO - [ 0x0c ] = KEY_ZOOM, // FULL SCREEN - - [ 0x12 ] = KEY_SUBTITLE, // DISPLAY - ??? - [ 0x32 ] = KEY_REWIND, // LOOP - ??? - [ 0x02 ] = KEY_PRINT, // PREVIEW - ??? - - [ 0x2a ] = KEY_SEARCH, // AUTOSCAN - [ 0x1a ] = KEY_SLEEP, // FREEZE - ??? - [ 0x3a ] = KEY_SHUFFLE, // SNAPSHOT - ??? - [ 0x0a ] = KEY_MUTE, // MUTE - - [ 0x26 ] = KEY_RECORD, // RECORD - [ 0x16 ] = KEY_PAUSE, // PAUSE - [ 0x36 ] = KEY_STOP, // STOP - [ 0x06 ] = KEY_PLAY, // PLAY - - [ 0x2e ] = KEY_RED, // - [ 0x21 ] = KEY_GREEN, // - [ 0x0e ] = KEY_YELLOW, // - [ 0x01 ] = KEY_BLUE, // - - [ 0x1e ] = KEY_VOLUMEDOWN, // VOLUME- - [ 0x3e ] = KEY_VOLUMEUP, // VOLUME+ - [ 0x11 ] = KEY_CHANNELDOWN, // CHANNEL/PAGE- - [ 0x31 ] = KEY_CHANNELUP // CHANNEL/PAGE+ + [ 0x20 ] = KEY_TV, /* TV/FM */ + [ 0x10 ] = KEY_CD, /* CD */ + [ 0x30 ] = KEY_TEXT, /* TELETEXT */ + [ 0x00 ] = KEY_POWER, /* POWER */ + + [ 0x08 ] = KEY_VIDEO, /* VIDEO */ + [ 0x04 ] = KEY_AUDIO, /* AUDIO */ + [ 0x0c ] = KEY_ZOOM, /* FULL SCREEN */ + + [ 0x12 ] = KEY_SUBTITLE, /* DISPLAY */ + [ 0x32 ] = KEY_REWIND, /* LOOP */ + [ 0x02 ] = KEY_PRINT, /* PREVIEW */ + + [ 0x2a ] = KEY_SEARCH, /* AUTOSCAN */ + [ 0x1a ] = KEY_SLEEP, /* FREEZE */ + [ 0x3a ] = KEY_SHUFFLE, /* SNAPSHOT */ + [ 0x0a ] = KEY_MUTE, /* MUTE */ + + [ 0x26 ] = KEY_RECORD, /* RECORD */ + [ 0x16 ] = KEY_PAUSE, /* PAUSE */ + [ 0x36 ] = KEY_STOP, /* STOP */ + [ 0x06 ] = KEY_PLAY, /* PLAY */ + + [ 0x2e ] = KEY_RED, /* RED */ + [ 0x21 ] = KEY_GREEN, /* GREEN */ + [ 0x0e ] = KEY_YELLOW, /* YELLOW */ + [ 0x01 ] = KEY_BLUE, /* BLUE */ + + [ 0x1e ] = KEY_VOLUMEDOWN, /* VOLUME- */ + [ 0x3e ] = KEY_VOLUMEUP, /* VOLUME+ */ + [ 0x11 ] = KEY_CHANNELDOWN, /* CHANNEL/PAGE- */ + [ 0x31 ] = KEY_CHANNELUP /* CHANNEL/PAGE+ */ }; -EXPORT_SYMBOL_GPL(ir_codes_md2819); +EXPORT_SYMBOL_GPL(ir_codes_avermedia); IR_KEYTAB_TYPE ir_codes_videomate_tv_pvr[IR_KEYTAB_SIZE] = { [ 0x14 ] = KEY_MUTE, @@ -1501,37 +1413,3 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new); -IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { - [ 0x02 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x0b ] = KEY_2, - [ 0x1b ] = KEY_3, - [ 0x05 ] = KEY_4, - [ 0x09 ] = KEY_5, - [ 0x15 ] = KEY_6, - [ 0x06 ] = KEY_7, - [ 0x0a ] = KEY_8, - [ 0x12 ] = KEY_9, - - [ 0x03 ] = KEY_TUNER, /* TV/FM */ - [ 0x07 ] = KEY_SEARCH, /* scan */ - [ 0x1c ] = KEY_ZOOM, /* full screen */ - [ 0x1e ] = KEY_POWER, - [ 0x17 ] = KEY_VOLUMEDOWN, - [ 0x1f ] = KEY_VOLUMEUP, - [ 0x14 ] = KEY_CHANNELDOWN, - [ 0x16 ] = KEY_CHANNELUP, - [ 0x18 ] = KEY_MUTE, - - [ 0x00 ] = KEY_LIST, /* source */ - [ 0x13 ] = KEY_INFO, /* loop */ - [ 0x10 ] = KEY_LAST, /* +100 */ - [ 0x0d ] = KEY_CLEAR, /* reset */ - [ 0x0c ] = BTN_RIGHT, /* fun++ */ - [ 0x04 ] = BTN_LEFT, /* fun-- */ - [ 0x0e ] = KEY_GOTO, /* function */ - [ 0x0f ] = KEY_STOP, /* freeze */ -}; - -EXPORT_SYMBOL_GPL(ir_codes_pixelview); - diff --git a/drivers/media/video/bttv-input.c b/drivers/media/video/bttv-input.c index 42760ae867d6..c637677acefd 100644 --- a/drivers/media/video/bttv-input.c +++ b/drivers/media/video/bttv-input.c @@ -328,7 +328,7 @@ int bttv_input_init(struct bttv *btv) ir->polling = 50; // ms break; case BTTV_BOARD_CONCEPTRONIC_CTVFMI2: - ir_codes = ir_codes_conceptronic; + ir_codes = ir_codes_pixelview; ir->mask_keycode = 0x001F00; ir->mask_keyup = 0x006000; ir->polling = 50; // ms diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index a4fa92c1b0c7..800e2b31ac7b 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -192,6 +192,13 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->mask_keyup = 0x80; ir->polling = 1; /* ms */ break; + case CX88_BOARD_KWORLD_LTV883: + ir_codes = ir_codes_pixelview; + ir->gpio_addr = MO_GP1_IO; + ir->mask_keycode = 0x1f; + ir->mask_keyup = 0x60; + ir->polling = 1; /* ms */ + break; case CX88_BOARD_ADSTECH_DVB_T_PCI: ir_codes = ir_codes_adstech_dvb_t_pci; ir->gpio_addr = MO_GP1_IO; diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 342568cf728f..ecfb6e2b3bd3 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -169,7 +169,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) break; case SAA7134_BOARD_KWORLD_XPERT: case SAA7134_BOARD_AVACSSMARTTV: - ir_codes = ir_codes_avacssmart; + ir_codes = ir_codes_pixelview; mask_keycode = 0x00001F; mask_keyup = 0x000020; polling = 50; // ms @@ -181,7 +181,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_STUDIO_305: case SAA7134_BOARD_AVERMEDIA_STUDIO_307: case SAA7134_BOARD_AVERMEDIA_GO_007_FM: - ir_codes = ir_codes_md2819; + ir_codes = ir_codes_avermedia; mask_keycode = 0x0007C8; mask_keydown = 0x000010; polling = 50; // ms @@ -190,7 +190,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); break; case SAA7134_BOARD_KWORLD_TERMINATOR: - ir_codes = ir_codes_avacssmart; + ir_codes = ir_codes_pixelview; mask_keycode = 0x00001f; mask_keyup = 0x000060; polling = 50; // ms diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 50fe522bad33..302d5b3946e7 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -63,7 +63,7 @@ extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_conceptronic[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE]; @@ -78,8 +78,7 @@ extern IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_avacssmart[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_md2819[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_videomate_tv_pvr[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE]; @@ -90,7 +89,6 @@ extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE]; #endif -- cgit v1.2.3 From 6ac48b458769059ee6147dd8bf2767e820407292 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Jan 2006 17:11:05 -0200 Subject: V4L/DVB (3408): Included new sliced VBI types to videodev2.h and tvp5150 - Added other sliced VBI types to videodev2.h - tvp5150 now uses standard V4L2 API codes from videodev2.h - Implemented VIDIOC_G_SLICED_VBI_CAP for tvp5150. This is dynamically filled based on defined VDP C-RAM values filled by the driver. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-vbi.c | 6 +- drivers/media/video/saa7115.c | 6 +- drivers/media/video/tvp5150.c | 161 +++++++++++++++++++----------- drivers/media/video/tvp5150_reg.h | 7 ++ include/linux/videodev2.h | 51 ++++++++-- 5 files changed, 161 insertions(+), 70 deletions(-) (limited to 'include') diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c index 04d879da7d63..e96fd1f1d6dc 100644 --- a/drivers/media/video/cx25840/cx25840-vbi.c +++ b/drivers/media/video/cx25840/cx25840-vbi.c @@ -151,7 +151,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) case VIDIOC_G_FMT: { static u16 lcr2vbi[] = { - 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ + 0, V4L2_SLICED_TELETEXT_PAL_B, 0, /* 1 */ 0, V4L2_SLICED_WSS_625, 0, /* 4 */ V4L2_SLICED_CAPTION_525, /* 6 */ 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ @@ -231,7 +231,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) for (i = 7; i <= 23; i++) { for (x = 0; x <= 1; x++) { switch (svbi->service_lines[1-x][i]) { - case V4L2_SLICED_TELETEXT_B: + case V4L2_SLICED_TELETEXT_PAL_B: lcr[i] |= 1 << (4 * x); break; case V4L2_SLICED_WSS_625: @@ -282,7 +282,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) switch (id2) { case 1: - id2 = V4L2_SLICED_TELETEXT_B; + id2 = V4L2_SLICED_TELETEXT_PAL_B; break; case 4: id2 = V4L2_SLICED_WSS_625; diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 048d000941c7..487a42970963 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -791,7 +791,7 @@ static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo case 0: lcr[i] |= 0xf << (4 * x); break; - case V4L2_SLICED_TELETEXT_B: + case V4L2_SLICED_TELETEXT_PAL_B: lcr[i] |= 1 << (4 * x); break; case V4L2_SLICED_CAPTION_525: @@ -820,7 +820,7 @@ static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo static int saa7115_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) { static u16 lcr2vbi[] = { - 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ + 0, V4L2_SLICED_TELETEXT_PAL_B, 0, /* 1 */ 0, V4L2_SLICED_CAPTION_525, /* 4 */ V4L2_SLICED_WSS_625, 0, /* 5 */ V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */ @@ -985,7 +985,7 @@ static void saa7115_decode_vbi_line(struct i2c_client *client, /* decode payloads */ switch (id2) { case 1: - vbi->type = V4L2_SLICED_TELETEXT_B; + vbi->type = V4L2_SLICED_TELETEXT_PAL_B; break; case 4: if (!saa7115_odd_parity(p[0]) || !saa7115_odd_parity(p[1])) diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index f7fa93c64d11..17a8dd726912 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -1,8 +1,8 @@ /* - * tvp5150 - Texas Instruments TVP5150A(M) video decoder driver + * tvp5150 - Texas Instruments TVP5150A/AM1 video decoder driver * - * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br) - * This code is placed under the terms of the GNU General Public License + * Copyright (c) 2005,2006 Mauro Carvalho Chehab (mchehab@infradead.org) + * This code is placed under the terms of the GNU General Public License v2 */ #include @@ -13,10 +13,11 @@ #include "tvp5150_reg.h" -MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver"); /* standard i2c insmod options */ +MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver"); MODULE_AUTHOR("Mauro Carvalho Chehab"); MODULE_LICENSE("GPL"); +/* standard i2c insmod options */ static unsigned short normal_i2c[] = { 0xb8 >> 1, 0xba >> 1, @@ -477,82 +478,101 @@ static const struct i2c_reg_value tvp5150_init_enable[] = { } }; +struct tvp5150_vbi_type { + unsigned int vbi_type; + unsigned int ini_line; + unsigned int end_line; + unsigned int by_field :1; +}; + struct i2c_vbi_ram_value { u16 reg; - unsigned char values[26]; + struct tvp5150_vbi_type type; + unsigned char values[16]; }; -/* tvp5150_vbi_types should follow the same order as vbi_ram_default +/* This struct have the values for each supported VBI Standard + * by + tvp5150_vbi_types should follow the same order as vbi_ram_default * value 0 means rom position 0x10, value 1 means rom position 0x30 * and so on. There are 16 possible locations from 0 to 15. */ -enum tvp5150_vbi_types { /* Video line number Description */ - VBI_WST_SECAM, /* 6-23 (field 1,2) Teletext, SECAM */ - VBI_WST_PAL_B, /* 6-22 (field 1,2) Teletext, PAL, System B */ - VBI_WST_PAL_C, /* 6-22 (field 1,2) Teletext, PAL, System C */ - VBI_WST_NTSC_B, /* 10-21 (field 1,2) Teletext, NTSC, System B */ - VBI_NABTS_NTSC_C, /* 10-21 (field 1,2) Teletext, NTSC, System C */ - VBI_NABTS_NTSC_D, /* 10-21 (field 1,2) Teletext, NTSC, System D */ - VBI_CC_PAL_SECAM, /* 22 (field 1,2) Closed Caption PAL/SECAM */ - VBI_CC_NTSC, /* 21 (field 1,2) Closed Caption NTSC */ - VBI_WSS_PAL_SECAM, /* 23 (field 1,2) Wide Screen Signal PAL/SECAM */ - VBI_WSS_NTSC, /* 20 (field 1,2) Wide Screen Signal NTSC */ - VBI_VITC_PAL_SECAM, /* 6-22 Vertical Interval Timecode PAL/SECAM */ - VBI_VITC_NTSC, /* 10-20 Vertical Interval Timecode NTSC */ - VBI_VPS_PAL, /* 16 Video Program System PAL */ - VBI_EPG_GEMSTAR, /* EPG/Gemstar Electronic program guide */ - VBI_RESERVED, /* not in use on vbi_ram_default table */ - VBI_FULL_FIELD /* Active video/Full Field */ -}; static struct i2c_vbi_ram_value vbi_ram_default[] = { - {0x010, /* WST SECAM */ - { 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x26, 0xe6, 0xb4, 0x0e, 0x0, 0x0, 0x0, 0x10, 0x0 } + {0x010, /* Teletext, SECAM, WST System A */ + {V4L2_SLICED_TELETEXT_SECAM,6,23,1}, + { 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x26, + 0xe6, 0xb4, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00 } }, - {0x030, /* WST PAL B */ - { 0xaa, 0xaa, 0xff, 0xff , 0x27, 0x2e, 0x20, 0x2b, 0xa6, 0x72, 0x10, 0x0, 0x0, 0x0, 0x10, 0x0 } + {0x030, /* Teletext, PAL, WST System B */ + {V4L2_SLICED_TELETEXT_PAL_B,6,22,1}, + { 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x2b, + 0xa6, 0x72, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00 } }, - {0x050, /* WST PAL C */ - { 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x22, 0xa6, 0x98, 0x0d, 0x0, 0x0, 0x0, 0x10, 0x0 } + {0x050, /* Teletext, PAL, WST System C */ + {V4L2_SLICED_TELETEXT_PAL_C,6,22,1}, + { 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22, + 0xa6, 0x98, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 } }, - {0x070, /* WST NTSC B */ - { 0xaa, 0xaa, 0xff, 0xff , 0x27, 0x2e, 0x20, 0x23, 0x69, 0x93, 0x0d, 0x0, 0x0, 0x0, 0x10, 0x0 } + {0x070, /* Teletext, NTSC, WST System B */ + {V4L2_SLICED_TELETEXT_NTSC_B,10,21,1}, + { 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x23, + 0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 } }, - {0x090, /* NABTS, NTSC */ - { 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x22, 0x69, 0x93, 0x0d, 0x0, 0x0, 0x0, 0x15, 0x0 } + {0x090, /* Tetetext, NTSC NABTS System C */ + {V4L2_SLICED_TELETEXT_NTSC_C,10,21,1}, + { 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22, + 0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x15, 0x00 } }, - {0x0b0, /* NABTS, NTSC-J */ - { 0xaa, 0xaa, 0xff, 0xff , 0xa7, 0x2e, 0x20, 0x23, 0x69, 0x93, 0x0d, 0x0, 0x0, 0x0, 0x10, 0x0 } + {0x0b0, /* Teletext, NTSC-J, NABTS System D */ + {V4L2_SLICED_TELETEXT_NTSC_D,10,21,1}, + { 0xaa, 0xaa, 0xff, 0xff, 0xa7, 0x2e, 0x20, 0x23, + 0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 } }, - {0x0d0, /* CC, PAL/SECAM */ - { 0xaa, 0x2a, 0xff, 0x3f , 0x04, 0x51, 0x6e, 0x02, 0xa6, 0x7b, 0x09, 0x0, 0x0, 0x0, 0x27, 0x0 } + {0x0d0, /* Closed Caption, PAL/SECAM */ + {V4L2_SLICED_CAPTION_625,22,22,1}, + { 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02, + 0xa6, 0x7b, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 } }, - {0x0f0, /* CC, NTSC */ - { 0xaa, 0x2a, 0xff, 0x3f , 0x04, 0x51, 0x6e, 0x02, 0x69, 0x8c, 0x09, 0x0, 0x0, 0x0, 0x27, 0x0 } + {0x0f0, /* Closed Caption, NTSC */ + {V4L2_SLICED_CAPTION_525,21,21,1}, + { 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02, + 0x69, 0x8c, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 } }, - {0x110, /* WSS, PAL/SECAM */ - { 0x5b, 0x55, 0xc5, 0xff , 0x0, 0x71, 0x6e, 0x42, 0xa6, 0xcd, 0x0f, 0x0, 0x0, 0x0, 0x3a, 0x0 } + {0x110, /* Wide Screen Signal, PAL/SECAM */ + {V4L2_SLICED_WSS_625,20,21,1}, + { 0x5b, 0x55, 0xc5, 0xff, 0x00, 0x71, 0x6e, 0x42, + 0xa6, 0xcd, 0x0f, 0x00, 0x00, 0x00, 0x3a, 0x00 } }, - {0x130, /* WSS, NTSC C */ - { 0x38, 0x00, 0x3f, 0x00 , 0x0, 0x71, 0x6e, 0x43, 0x69, 0x7c, 0x08, 0x0, 0x0, 0x0, 0x39, 0x0 } + {0x130, /* Wide Screen Signal, NTSC C */ + {V4L2_SLICED_WSS_525,20,20,1}, + { 0x38, 0x00, 0x3f, 0x00, 0x00, 0x71, 0x6e, 0x43, + 0x69, 0x7c, 0x08, 0x00, 0x00, 0x00, 0x39, 0x00 } }, - {0x150, /* VITC, PAL/SECAM */ - { 0x0, 0x0, 0x0, 0x0 , 0x0, 0x8f, 0x6d, 0x49, 0xa6, 0x85, 0x08, 0x0, 0x0, 0x0, 0x4c, 0x0 } + {0x150, /* Vertical Interval Timecode (VITC), PAL/SECAM */ + {V4l2_SLICED_VITC_625,6,22,0}, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49, + 0xa6, 0x85, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 } }, - {0x170, /* VITC, NTSC */ - { 0x0, 0x0, 0x0, 0x0 , 0x0, 0x8f, 0x6d, 0x49, 0x69, 0x94, 0x08, 0x0, 0x0, 0x0, 0x4c, 0x0 } + {0x170, /* Vertical Interval Timecode (VITC), NTSC */ + {V4l2_SLICED_VITC_525,10,20,0}, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49, + 0x69, 0x94, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 } }, - {0x190, /* VPS, PAL */ - { 0xaa, 0xaa, 0xff, 0xff, 0xba, 0xce, 0x2b, 0x0d, 0xa6, 0xda, 0x0b, 0x0, 0x0, 0x0, 0x60, 0x0 } - }, - {0x1b0, /* Gemstar Custom 1 */ - { 0xcc, 0xcc, 0xff, 0xff, 0x05, 0x51, 0x6e, 0x05, 0x69, 0x19, 0x13, 0x0, 0x0, 0x0, 0x60, 0x0 } + {0x190, /* Video Program System (VPS), PAL */ + {V4L2_SLICED_VPS,16,16,0}, + { 0xaa, 0xaa, 0xff, 0xff, 0xba, 0xce, 0x2b, 0x0d, + 0xa6, 0xda, 0x0b, 0x00, 0x00, 0x00, 0x60, 0x00 } }, + /* 0x1d0 User programmable */ + + /* End of struct */ + { (u16)-1 } }; static int tvp5150_write_inittab(struct i2c_client *c, - const struct i2c_reg_value *regs) + const struct i2c_reg_value *regs) { while (regs->reg != 0xff) { tvp5150_write(c, regs->reg, regs->value); @@ -562,7 +582,7 @@ static int tvp5150_write_inittab(struct i2c_client *c, } static int tvp5150_vdp_init(struct i2c_client *c, - const struct i2c_vbi_ram_value *regs) + const struct i2c_vbi_ram_value *regs) { unsigned int i; @@ -586,6 +606,24 @@ static int tvp5150_vdp_init(struct i2c_client *c, return 0; } +/* Fills VBI capabilities based on i2c_vbi_ram_value struct */ +static void tvp5150_vbi_get_cap(const struct i2c_vbi_ram_value *regs, + struct v4l2_sliced_vbi_cap *cap) +{ + int line; + + memset(cap, 0, sizeof *cap); + + while (regs->reg != (u16)-1 ) { + for (line=regs->type.ini_line;line<=regs->type.end_line;line++) { + cap->service_lines[0][line] |= regs->type.vbi_type; + } + cap->service_set |= regs->type.vbi_type; + + regs++; + } +} + /* Set vbi processing * type - one of tvp5150_vbi_types * line - line to gather data @@ -599,7 +637,7 @@ static int tvp5150_vdp_init(struct i2c_client *c, * LSB = field1 * MSB = field2 */ -static int tvp5150_set_vbi(struct i2c_client *c, enum tvp5150_vbi_types type, +static int tvp5150_set_vbi(struct i2c_client *c, unsigned int type, u8 flags, int line, const int fields) { struct tvp5150 *decoder = i2c_get_clientdata(c); @@ -775,6 +813,15 @@ static int tvp5150_command(struct i2c_client *c, *(v4l2_std_id *)arg = decoder->norm; break; + case VIDIOC_G_SLICED_VBI_CAP: + { + struct v4l2_sliced_vbi_cap *cap = arg; + tvp5150_dbg(1, "VIDIOC_G_SLICED_VBI_CAP\n"); + + tvp5150_vbi_get_cap(vbi_ram_default, cap); + break; + } + #ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_INT_G_REGISTER: { @@ -1021,7 +1068,7 @@ static int tvp5150_detect_client(struct i2c_adapter *adapter, return rv; } - if (debug > 1) +// if (debug > 1) dump_reg(c); return 0; } diff --git a/drivers/media/video/tvp5150_reg.h b/drivers/media/video/tvp5150_reg.h index c81587e06e37..4240043c0b2a 100644 --- a/drivers/media/video/tvp5150_reg.h +++ b/drivers/media/video/tvp5150_reg.h @@ -1,3 +1,10 @@ +/* + * tvp5150 - Texas Instruments TVP5150A/AM1 video decoder registers + * + * Copyright (c) 2005,2006 Mauro Carvalho Chehab (mchehab@infradead.org) + * This code is placed under the terms of the GNU General Public License v2 + */ + #define TVP5150_VD_IN_SRC_SEL_1 0x00 /* Video input source selection #1 */ #define TVP5150_ANAL_CHL_CTL 0x01 /* Analog channel controls */ #define TVP5150_OP_MODE_CTL 0x02 /* Operation mode controls */ diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index ce40675324bd..27ae3d679cbe 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -949,13 +949,50 @@ struct v4l2_sliced_vbi_format __u32 reserved[2]; /* must be zero */ }; -#define V4L2_SLICED_TELETEXT_B (0x0001) -#define V4L2_SLICED_VPS (0x0400) -#define V4L2_SLICED_CAPTION_525 (0x1000) -#define V4L2_SLICED_WSS_625 (0x4000) - -#define V4L2_SLICED_VBI_525 (V4L2_SLICED_CAPTION_525) -#define V4L2_SLICED_VBI_625 (V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS | V4L2_SLICED_WSS_625) +/* Teletext WST, defined on ITU-R BT.653-2 */ +#define V4L2_SLICED_TELETEXT_PAL_B (0x000001) +#define V4L2_SLICED_TELETEXT_PAL_C (0x000002) +#define V4L2_SLICED_TELETEXT_NTSC_B (0x000010) +#define V4L2_SLICED_TELETEXT_SECAM (0x000020) + +/* Teletext NABTS, defined on ITU-R BT.653-2 */ +#define V4L2_SLICED_TELETEXT_NTSC_C (0x000040) +#define V4L2_SLICED_TELETEXT_NTSC_D (0x000080) + +/* Video Program System, defined on ETS 300 231*/ +#define V4L2_SLICED_VPS (0x000400) + +/* Closed Caption, defined on EIA-608 */ +#define V4L2_SLICED_CAPTION_525 (0x001000) +#define V4L2_SLICED_CAPTION_625 (0x002000) + +/* Wide Screen System, defined on ITU-R BT1119.1 */ +#define V4L2_SLICED_WSS_625 (0x004000) + +/* Wide Screen System, defined on IEC 61880 */ +#define V4L2_SLICED_WSS_525 (0x008000) + +/* Vertical Interval Timecode (VITC), defined on SMPTE 12M */ +#define V4l2_SLICED_VITC_625 (0x010000) +#define V4l2_SLICED_VITC_525 (0x020000) + +/* Compat macro - Should be removed for 2.6.18 */ +#define V4L2_SLICED_TELETEXT_B V4L2_SLICED_TELETEXT_PAL_B + +#define V4L2_SLICED_VBI_525 (V4L2_SLICED_TELETEXT_NTSC_B |\ + V4L2_SLICED_TELETEXT_NTSC_C |\ + V4L2_SLICED_TELETEXT_NTSC_D |\ + V4L2_SLICED_CAPTION_525 |\ + V4L2_SLICED_WSS_525 |\ + V4l2_SLICED_VITC_525) + +#define V4L2_SLICED_VBI_625 (V4L2_SLICED_TELETEXT_PAL_B |\ + V4L2_SLICED_TELETEXT_PAL_C |\ + V4L2_SLICED_TELETEXT_SECAM |\ + V4L2_SLICED_VPS |\ + V4L2_SLICED_CAPTION_625 |\ + V4L2_SLICED_WSS_625 |\ + V4l2_SLICED_VITC_625) struct v4l2_sliced_vbi_cap { -- cgit v1.2.3 From 4d0dddb10723cee2b3048bd2389673703bc228e4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Jan 2006 17:11:07 -0200 Subject: V4L/DVB (3419): added some VBI macros and moved minor definitions to header file - Moved some hardcoded minor numbers to videodev2.h - Included more comments for sliced VBI standards - Included some VBI macros to group similar standards Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videodev.c | 16 ++++++++-------- include/linux/videodev2.h | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 078880e4c8c0..908fbec776ac 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -279,23 +279,23 @@ int video_register_device(struct video_device *vfd, int type, int nr) switch(type) { case VFL_TYPE_GRABBER: - base=0; - end=64; + base=MINOR_VFL_TYPE_GRABBER_MIN; + end=MINOR_VFL_TYPE_GRABBER_MAX+1; name_base = "video"; break; case VFL_TYPE_VTX: - base=192; - end=224; + base=MINOR_VFL_TYPE_VTX_MIN; + end=MINOR_VFL_TYPE_VTX_MAX+1; name_base = "vtx"; break; case VFL_TYPE_VBI: - base=224; - end=256; + base=MINOR_VFL_TYPE_VBI_MIN; + end=MINOR_VFL_TYPE_VBI_MAX+1; name_base = "vbi"; break; case VFL_TYPE_RADIO: - base=64; - end=128; + base=MINOR_VFL_TYPE_RADIO_MIN; + end=MINOR_VFL_TYPE_RADIO_MAX+1; name_base = "radio"; break; default: diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 27ae3d679cbe..6e33ce96cab0 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -21,7 +21,7 @@ #include /* need __user */ -#define OBSOLETE_OWNER 1 /* It will be removed for 2.6.15 */ +#define OBSOLETE_OWNER 1 /* It will be removed for 2.6.17 */ #define HAVE_V4L2 1 /* @@ -48,6 +48,16 @@ #ifdef __KERNEL__ +/* Minor device allocation */ +#define MINOR_VFL_TYPE_GRABBER_MIN 0 +#define MINOR_VFL_TYPE_GRABBER_MAX 63 +#define MINOR_VFL_TYPE_RADIO_MIN 64 +#define MINOR_VFL_TYPE_RADIO_MAX 127 +#define MINOR_VFL_TYPE_VTX_MIN 192 +#define MINOR_VFL_TYPE_VTX_MAX 223 +#define MINOR_VFL_TYPE_VBI_MIN 224 +#define MINOR_VFL_TYPE_VBI_MAX 255 + #define VFL_TYPE_GRABBER 0 #define VFL_TYPE_VBI 1 #define VFL_TYPE_RADIO 2 @@ -949,13 +959,15 @@ struct v4l2_sliced_vbi_format __u32 reserved[2]; /* must be zero */ }; -/* Teletext WST, defined on ITU-R BT.653-2 */ +/* Teletext World System Teletext + (WST), defined on ITU-R BT.653-2 */ #define V4L2_SLICED_TELETEXT_PAL_B (0x000001) #define V4L2_SLICED_TELETEXT_PAL_C (0x000002) #define V4L2_SLICED_TELETEXT_NTSC_B (0x000010) #define V4L2_SLICED_TELETEXT_SECAM (0x000020) -/* Teletext NABTS, defined on ITU-R BT.653-2 */ +/* Teletext North American Broadcast Teletext Specification + (NABTS), defined on ITU-R BT.653-2 */ #define V4L2_SLICED_TELETEXT_NTSC_C (0x000040) #define V4L2_SLICED_TELETEXT_NTSC_D (0x000080) @@ -976,8 +988,24 @@ struct v4l2_sliced_vbi_format #define V4l2_SLICED_VITC_625 (0x010000) #define V4l2_SLICED_VITC_525 (0x020000) -/* Compat macro - Should be removed for 2.6.18 */ -#define V4L2_SLICED_TELETEXT_B V4L2_SLICED_TELETEXT_PAL_B +#define V4L2_SLICED_TELETEXT_B (V4L2_SLICED_TELETEXT_PAL_B |\ + V4L2_SLICED_TELETEXT_NTSC_B) + +#define V4L2_SLICED_TELETEXT (V4L2_SLICED_TELETEXT_PAL_B |\ + V4L2_SLICED_TELETEXT_PAL_C |\ + V4L2_SLICED_TELETEXT_SECAM |\ + V4L2_SLICED_TELETEXT_NTSC_B |\ + V4L2_SLICED_TELETEXT_NTSC_C |\ + V4L2_SLICED_TELETEXT_NTSC_D) + +#define V4L2_SLICED_CAPTION (V4L2_SLICED_CAPTION_525 |\ + V4L2_SLICED_CAPTION_625) + +#define V4L2_SLICED_WSS (V4L2_SLICED_WSS_525 |\ + V4L2_SLICED_WSS_625) + +#define V4L2_SLICED_VITC (V4L2_SLICED_VITC_525 |\ + V4L2_SLICED_VITC_625) #define V4L2_SLICED_VBI_525 (V4L2_SLICED_TELETEXT_NTSC_B |\ V4L2_SLICED_TELETEXT_NTSC_C |\ -- cgit v1.2.3 From 12db56071b473a59c550d0aa70db6972a49d73af Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Jan 2006 17:11:08 -0200 Subject: V4L/DVB (3420): Added iocls to configure VBI on tvp5150 - Added iocls to configure VBI on tvp5150 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvp5150.c | 70 +++++++++++++++++++++++++++++++++++++++++-- include/media/v4l2-common.h | 3 +- 2 files changed, 70 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index df7f304416c9..20e63593e441 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -541,7 +541,7 @@ static struct i2c_vbi_ram_value vbi_ram_default[] = 0x69, 0x8c, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 } }, {0x110, /* Wide Screen Signal, PAL/SECAM */ - {V4L2_SLICED_WSS_625,20,21,1}, + {V4L2_SLICED_WSS_625,23,23,1}, { 0x5b, 0x55, 0xc5, 0xff, 0x00, 0x71, 0x6e, 0x42, 0xa6, 0xcd, 0x0f, 0x00, 0x00, 0x00, 0x3a, 0x00 } }, @@ -649,7 +649,7 @@ static int tvp5150_set_vbi(struct i2c_client *c, if (std == V4L2_STD_ALL) { tvp5150_err("VBI can't be configured without knowing number of lines\n"); - return -EINVAL; + return 0; } else if (std && V4L2_STD_625_50) { /* Don't follow NTSC Line number convension */ line += 3; @@ -686,6 +686,37 @@ static int tvp5150_set_vbi(struct i2c_client *c, return type; } +static int tvp5150_get_vbi(struct i2c_client *c, + const struct i2c_vbi_ram_value *regs, int line) +{ + struct tvp5150 *decoder = i2c_get_clientdata(c); + v4l2_std_id std=decoder->norm; + u8 reg; + int pos, type=0; + + if (std == V4L2_STD_ALL) { + tvp5150_err("VBI can't be configured without knowing number of lines\n"); + return 0; + } else if (std && V4L2_STD_625_50) { + /* Don't follow NTSC Line number convension */ + line += 3; + } + + if (line<6||line>27) + return 0; + + reg=((line-6)<<1)+TVP5150_LINE_MODE_INI; + + pos=tvp5150_read(c, reg)&0x0f; + if (pos<0x0f) + type=regs[pos].type.vbi_type; + + pos=tvp5150_read(c, reg+1)&0x0f; + if (pos<0x0f) + type|=regs[pos].type.vbi_type; + + return type; +} static int tvp5150_set_std(struct i2c_client *c, v4l2_std_id std) { struct tvp5150 *decoder = i2c_get_clientdata(c); @@ -856,9 +887,43 @@ static int tvp5150_command(struct i2c_client *c, vbi_ram_default, svbi->service_lines[0][i],0xf0,i,3); } + /* Enables FIFO */ + tvp5150_write(c, TVP5150_FIFO_OUT_CTRL,1); + } else { + /* Disables FIFO*/ + tvp5150_write(c, TVP5150_FIFO_OUT_CTRL,0); + + /* Disable Full Field */ + tvp5150_write(c, TVP5150_FULL_FIELD_ENA, 0); + + /* Disable Line modes */ + for (i=TVP5150_LINE_MODE_INI; i<=TVP5150_LINE_MODE_END; i++) + tvp5150_write(c, i, 0xff); + } + break; + } + case VIDIOC_G_FMT: + { + struct v4l2_format *fmt; + struct v4l2_sliced_vbi_format *svbi; + + int i, mask=0; + + fmt = arg; + if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) + return -EINVAL; + svbi = &fmt->fmt.sliced; + memset(svbi, 0, sizeof(*svbi)); + + for (i = 0; i <= 23; i++) { + svbi->service_lines[0][i]=tvp5150_get_vbi(c, + vbi_ram_default,i); + mask|=svbi->service_lines[0][i]; } + svbi->service_set=mask; break; } + #ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_INT_G_REGISTER: { @@ -883,6 +948,7 @@ static int tvp5150_command(struct i2c_client *c, } #endif + case VIDIOC_LOG_STATUS: case DECODER_DUMP: dump_reg(c); break; diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index d4030a7e16e0..11728daf0096 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -160,7 +160,8 @@ struct msp_matrix { /* Used to generate VBI signals on a video signal. v4l2_sliced_vbi_data is filled with the data packets that should be output. Note that if you set - the line field to 0, then that VBI signal is disabled. */ + the line field to 0, then that VBI signal is disabled. If no + valid VBI data was found, then the type field is set to 0 on return. */ #define VIDIOC_INT_S_VBI_DATA _IOW ('d', 105, struct v4l2_sliced_vbi_data) /* Used to obtain the sliced VBI packet from a readback register. Not all -- cgit v1.2.3 From 757d250518c4905c5d13c8974446e08a2e3cf244 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 23 Jan 2006 17:11:10 -0200 Subject: V4L/DVB (3430): Add new internal VIDIOC_INT commands - Add new internal VIDIOC_INT commands for setting the tuner mode, for putting a chip into standby mode and to set/get the routing of inputs/outputs of audio or video of a chip. These new commands will replace older commands that are no longer up to the task. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-common.h | 51 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 11728daf0096..234e9cf7e844 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -115,12 +115,15 @@ enum v4l2_chip_ident { }; /* audio ioctls */ -/* v4l device was opened in Radio mode */ + +/* v4l device was opened in Radio mode, to be replaced by VIDIOC_INT_S_TUNER_MODE */ #define AUDC_SET_RADIO _IO('d',88) -/* select from TV,radio,extern,MUTE */ + +/* select from TV,radio,extern,MUTE, to be replaced with VIDIOC_INT_S_AUDIO_ROUTING */ #define AUDC_SET_INPUT _IOW('d',89,int) -/* msp3400 ioctl: will be removed in the near future */ +/* msp3400 ioctl: will be removed in the near future, to be replaced by + VIDIOC_INT_S_AUDIO_ROUTING. */ struct msp_matrix { int input; int output; @@ -128,12 +131,25 @@ struct msp_matrix { #define MSP_SET_MATRIX _IOW('m',17,struct msp_matrix) /* tuner ioctls */ + /* Sets tuner type and its I2C addr */ -#define TUNER_SET_TYPE_ADDR _IOW('d',90,int) -/* Puts tuner on powersaving state, disabling it, except for i2c */ -#define TUNER_SET_STANDBY _IOW('d',91,int) +#define TUNER_SET_TYPE_ADDR _IOW('d', 90, int) + +/* Puts tuner on powersaving state, disabling it, except for i2c. To be replaced + by VIDIOC_INT_S_STANDBY. */ +#define TUNER_SET_STANDBY _IOW('d', 91, int) + /* Sets tda9887 specific stuff, like port1, port2 and qss */ -#define TDA9887_SET_CONFIG _IOW('d',92,int) +#define TDA9887_SET_CONFIG _IOW('d', 92, int) + +/* Switch the tuner to a specific tuner mode. Replacement of AUDC_SET_RADIO */ +#define VIDIOC_INT_S_TUNER_MODE _IOW('d', 93, enum v4l2_tuner_type) + +/* Generic standby command. Passing -1 (all bits set to 1) will put the whole + chip into standby mode, value 0 will make the chip fully active. Specific + bits can be used by certain chips to enable/disable specific subsystems. + Replacement of TUNER_SET_STANDBY. */ +#define VIDIOC_INT_S_STANDBY _IOW('d', 94, u32) /* only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */ #define VIDIOC_INT_S_REGISTER _IOR ('d', 100, struct v4l2_register) @@ -181,4 +197,25 @@ struct msp_matrix { If the frequency is not supported, then -EINVAL is returned. */ #define VIDIOC_INT_I2S_CLOCK_FREQ _IOW ('d', 108, u32) +/* Routing definition, device dependent. It specifies which inputs (if any) + should be routed to which outputs (if any). */ +struct v4l2_routing { + u32 input; + u32 output; +}; + +/* These internal commands should be used to define the inputs and outputs + of an audio/video chip. They will replace AUDC_SET_INPUT. + The v4l2 API commands VIDIOC_S/G_INPUT, VIDIOC_S/G_OUTPUT, + VIDIOC_S/G_AUDIO and VIDIOC_S/G_AUDOUT are meant to be used by the + user. Internally these commands should be used to switch inputs/outputs + because only the driver knows how to map a 'Television' input to the precise + input/output routing of an A/D converter, or a DSP, or a video digitizer. + These four commands should only be sent directly to an i2c device, they + should not be broadcast as the routing is very device specific. */ +#define VIDIOC_INT_S_AUDIO_ROUTING _IOW ('d', 109, struct v4l2_routing) +#define VIDIOC_INT_G_AUDIO_ROUTING _IOR ('d', 110, struct v4l2_routing *) +#define VIDIOC_INT_S_VIDEO_ROUTING _IOW ('d', 111, struct v4l2_routing) +#define VIDIOC_INT_G_VIDEO_ROUTING _IOR ('d', 112, struct v4l2_routing *) + #endif /* V4L2_COMMON_H_ */ -- cgit v1.2.3 From 3fc46d35b30cfae018c4903228a270c9543f4d7a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 23 Jan 2006 17:11:11 -0200 Subject: V4L/DVB (3436): move config byte from tuner_params to tuner_range struct. - Move config byte from tuner_params to tuner_range struct. - dvb tuners must be able to set different config byte for each range. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 15 +- drivers/media/video/tuner-types.c | 395 ++++++++++++++++--------------------- include/media/tuner-types.h | 2 +- 3 files changed, 176 insertions(+), 236 deletions(-) (limited to 'include') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 2c6410cc0fe9..6f0d376f0d18 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -133,7 +133,7 @@ static int tuner_stereo(struct i2c_client *c) static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) { struct tuner *t = i2c_get_clientdata(c); - u8 cb, tuneraddr; + u8 config, cb, tuneraddr; u16 div; struct tunertype *tun; u8 buffer[4]; @@ -152,6 +152,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) freq, tun->params[j].ranges[i - 1].limit); freq = tun->params[j].ranges[--i].limit; } + config = tun->params[j].ranges[i].config; cb = tun->params[j].ranges[i].cb; /* i == 0 -> VHF_LO */ /* i == 1 -> VHF_HI */ @@ -215,7 +216,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) case TUNER_MICROTUNE_4042FI5: /* Set the charge pump for fast tuning */ - tun->params[j].config |= TUNER_CHARGE_PUMP; + config |= TUNER_CHARGE_PUMP; break; case TUNER_PHILIPS_TUV1236D: @@ -276,14 +277,14 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) div); if (tuners[t->type].params->cb_first_if_lower_freq && div < t->last_div) { - buffer[0] = tun->params[j].config; + buffer[0] = config; buffer[1] = cb; buffer[2] = (div>>8) & 0x7f; buffer[3] = div & 0xff; } else { buffer[0] = (div>>8) & 0x7f; buffer[1] = div & 0xff; - buffer[2] = tun->params[j].config; + buffer[2] = config; buffer[3] = cb; } t->last_div = div; @@ -312,10 +313,10 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) } /* Set the charge pump for optimized phase noise figure */ - tun->params[j].config &= ~TUNER_CHARGE_PUMP; + config &= ~TUNER_CHARGE_PUMP; buffer[0] = (div>>8) & 0x7f; buffer[1] = div & 0xff; - buffer[2] = tun->params[j].config; + buffer[2] = config; buffer[3] = cb; tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", buffer[0],buffer[1],buffer[2],buffer[3]); @@ -337,7 +338,7 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) j = TUNER_PARAM_ANALOG; div = (20 * freq / 16000) + (int)(20*10.7); /* IF 10.7 MHz */ - buffer[2] = (tun->params[j].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */ + buffer[2] = (tun->params[j].ranges[0].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */ switch (t->type) { case TUNER_TENA_9533_DI: diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 6fe781798d89..d37f833997dd 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -36,9 +36,9 @@ /* ------------ TUNER_TEMIC_PAL - TEMIC PAL ------------ */ static struct tuner_range tuner_temic_pal_ranges[] = { - { 16 * 140.25 /*MHz*/, 0x02, }, - { 16 * 463.25 /*MHz*/, 0x04, }, - { 16 * 999.99 , 0x01, }, + { 16 * 140.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 463.25 /*MHz*/, 0x8e, 0x04, }, + { 16 * 999.99 , 0x8e, 0x01, }, }; static struct tuner_params tuner_temic_pal_params[] = { @@ -46,16 +46,15 @@ static struct tuner_params tuner_temic_pal_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_pal_ranges, .count = ARRAY_SIZE(tuner_temic_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_PAL_I - Philips PAL_I ------------ */ static struct tuner_range tuner_philips_pal_i_ranges[] = { - { 16 * 140.25 /*MHz*/, 0xa0, }, - { 16 * 463.25 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 140.25 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 463.25 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_philips_pal_i_params[] = { @@ -63,16 +62,15 @@ static struct tuner_params tuner_philips_pal_i_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_philips_pal_i_ranges, .count = ARRAY_SIZE(tuner_philips_pal_i_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_NTSC - Philips NTSC ------------ */ static struct tuner_range tuner_philips_ntsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0xa0, }, - { 16 * 451.25 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 451.25 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_philips_ntsc_params[] = { @@ -80,7 +78,6 @@ static struct tuner_params tuner_philips_ntsc_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_philips_ntsc_ranges, .count = ARRAY_SIZE(tuner_philips_ntsc_ranges), - .config = 0x8e, .cb_first_if_lower_freq = 1, }, }; @@ -88,9 +85,9 @@ static struct tuner_params tuner_philips_ntsc_params[] = { /* ------------ TUNER_PHILIPS_SECAM - Philips SECAM ------------ */ static struct tuner_range tuner_philips_secam_ranges[] = { - { 16 * 168.25 /*MHz*/, 0xa7, }, - { 16 * 447.25 /*MHz*/, 0x97, }, - { 16 * 999.99 , 0x37, }, + { 16 * 168.25 /*MHz*/, 0x8e, 0xa7, }, + { 16 * 447.25 /*MHz*/, 0x8e, 0x97, }, + { 16 * 999.99 , 0x8e, 0x37, }, }; static struct tuner_params tuner_philips_secam_params[] = { @@ -98,7 +95,6 @@ static struct tuner_params tuner_philips_secam_params[] = { .type = TUNER_PARAM_TYPE_SECAM, .ranges = tuner_philips_secam_ranges, .count = ARRAY_SIZE(tuner_philips_secam_ranges), - .config = 0x8e, .cb_first_if_lower_freq = 1, }, }; @@ -106,9 +102,9 @@ static struct tuner_params tuner_philips_secam_params[] = { /* ------------ TUNER_PHILIPS_PAL - Philips PAL ------------ */ static struct tuner_range tuner_philips_pal_ranges[] = { - { 16 * 168.25 /*MHz*/, 0xa0, }, - { 16 * 447.25 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 168.25 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 447.25 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_philips_pal_params[] = { @@ -116,7 +112,6 @@ static struct tuner_params tuner_philips_pal_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_philips_pal_ranges, .count = ARRAY_SIZE(tuner_philips_pal_ranges), - .config = 0x8e, .cb_first_if_lower_freq = 1, }, }; @@ -124,9 +119,9 @@ static struct tuner_params tuner_philips_pal_params[] = { /* ------------ TUNER_TEMIC_NTSC - TEMIC NTSC ------------ */ static struct tuner_range tuner_temic_ntsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0x02, }, - { 16 * 463.25 /*MHz*/, 0x04, }, - { 16 * 999.99 , 0x01, }, + { 16 * 157.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 463.25 /*MHz*/, 0x8e, 0x04, }, + { 16 * 999.99 , 0x8e, 0x01, }, }; static struct tuner_params tuner_temic_ntsc_params[] = { @@ -134,16 +129,15 @@ static struct tuner_params tuner_temic_ntsc_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_temic_ntsc_ranges, .count = ARRAY_SIZE(tuner_temic_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TEMIC_PAL_I - TEMIC PAL_I ------------ */ static struct tuner_range tuner_temic_pal_i_ranges[] = { - { 16 * 170.00 /*MHz*/, 0x02, }, - { 16 * 450.00 /*MHz*/, 0x04, }, - { 16 * 999.99 , 0x01, }, + { 16 * 170.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 450.00 /*MHz*/, 0x8e, 0x04, }, + { 16 * 999.99 , 0x8e, 0x01, }, }; static struct tuner_params tuner_temic_pal_i_params[] = { @@ -151,16 +145,15 @@ static struct tuner_params tuner_temic_pal_i_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_pal_i_ranges, .count = ARRAY_SIZE(tuner_temic_pal_i_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TEMIC_4036FY5_NTSC - TEMIC NTSC ------------ */ static struct tuner_range tuner_temic_4036fy5_ntsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0xa0, }, - { 16 * 463.25 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 463.25 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_temic_4036fy5_ntsc_params[] = { @@ -168,16 +161,15 @@ static struct tuner_params tuner_temic_4036fy5_ntsc_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_temic_4036fy5_ntsc_ranges, .count = ARRAY_SIZE(tuner_temic_4036fy5_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_ALPS_TSBH1_NTSC - TEMIC NTSC ------------ */ static struct tuner_range tuner_alps_tsb_1_ranges[] = { - { 16 * 137.25 /*MHz*/, 0x01, }, - { 16 * 385.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 137.25 /*MHz*/, 0x8e, 0x01, }, + { 16 * 385.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x08, }, }; static struct tuner_params tuner_alps_tsbh1_ntsc_params[] = { @@ -185,7 +177,6 @@ static struct tuner_params tuner_alps_tsbh1_ntsc_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_alps_tsb_1_ranges, .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges), - .config = 0x8e, }, }; @@ -197,16 +188,15 @@ static struct tuner_params tuner_alps_tsb_1_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_alps_tsb_1_ranges, .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_ALPS_TSBB5_PAL_I - Alps PAL_I ------------ */ static struct tuner_range tuner_alps_tsb_5_pal_ranges[] = { - { 16 * 133.25 /*MHz*/, 0x01, }, - { 16 * 351.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 133.25 /*MHz*/, 0x8e, 0x01, }, + { 16 * 351.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x08, }, }; static struct tuner_params tuner_alps_tsbb5_params[] = { @@ -214,7 +204,6 @@ static struct tuner_params tuner_alps_tsbb5_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_alps_tsb_5_pal_ranges, .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges), - .config = 0x8e, }, }; @@ -225,7 +214,6 @@ static struct tuner_params tuner_alps_tsbe5_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_alps_tsb_5_pal_ranges, .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges), - .config = 0x8e, }, }; @@ -236,16 +224,15 @@ static struct tuner_params tuner_alps_tsbc5_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_alps_tsb_5_pal_ranges, .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TEMIC_4006FH5_PAL - TEMIC PAL ------------ */ static struct tuner_range tuner_temic_4006fh5_pal_ranges[] = { - { 16 * 170.00 /*MHz*/, 0xa0, }, - { 16 * 450.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 170.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 450.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_temic_4006fh5_params[] = { @@ -253,16 +240,15 @@ static struct tuner_params tuner_temic_4006fh5_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_4006fh5_pal_ranges, .count = ARRAY_SIZE(tuner_temic_4006fh5_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_ALPS_TSHC6_NTSC - Alps NTSC ------------ */ static struct tuner_range tuner_alps_tshc6_ntsc_ranges[] = { - { 16 * 137.25 /*MHz*/, 0x14, }, - { 16 * 385.25 /*MHz*/, 0x12, }, - { 16 * 999.99 , 0x11, }, + { 16 * 137.25 /*MHz*/, 0x8e, 0x14, }, + { 16 * 385.25 /*MHz*/, 0x8e, 0x12, }, + { 16 * 999.99 , 0x8e, 0x11, }, }; static struct tuner_params tuner_alps_tshc6_params[] = { @@ -270,16 +256,15 @@ static struct tuner_params tuner_alps_tshc6_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_alps_tshc6_ntsc_ranges, .count = ARRAY_SIZE(tuner_alps_tshc6_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TEMIC_PAL_DK - TEMIC PAL ------------ */ static struct tuner_range tuner_temic_pal_dk_ranges[] = { - { 16 * 168.25 /*MHz*/, 0xa0, }, - { 16 * 456.25 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 168.25 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 456.25 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_temic_pal_dk_params[] = { @@ -287,16 +272,15 @@ static struct tuner_params tuner_temic_pal_dk_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_pal_dk_ranges, .count = ARRAY_SIZE(tuner_temic_pal_dk_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_NTSC_M - Philips NTSC ------------ */ static struct tuner_range tuner_philips_ntsc_m_ranges[] = { - { 16 * 160.00 /*MHz*/, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 160.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_philips_ntsc_m_params[] = { @@ -304,16 +288,15 @@ static struct tuner_params tuner_philips_ntsc_m_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_philips_ntsc_m_ranges, .count = ARRAY_SIZE(tuner_philips_ntsc_m_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TEMIC_4066FY5_PAL_I - TEMIC PAL_I ------------ */ static struct tuner_range tuner_temic_40x6f_5_pal_ranges[] = { - { 16 * 169.00 /*MHz*/, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 169.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_temic_4066fy5_pal_i_params[] = { @@ -321,7 +304,6 @@ static struct tuner_params tuner_temic_4066fy5_pal_i_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_40x6f_5_pal_ranges, .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges), - .config = 0x8e, }, }; @@ -332,7 +314,6 @@ static struct tuner_params tuner_temic_4006fn5_multi_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_40x6f_5_pal_ranges, .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges), - .config = 0x8e, }, }; @@ -340,9 +321,9 @@ static struct tuner_params tuner_temic_4006fn5_multi_params[] = { /* ------------ TUNER_TEMIC_4009FR5_PAL - TEMIC PAL ------------ */ static struct tuner_range tuner_temic_4009f_5_pal_ranges[] = { - { 16 * 141.00 /*MHz*/, 0xa0, }, - { 16 * 464.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 141.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 464.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_temic_4009f_5_params[] = { @@ -350,16 +331,15 @@ static struct tuner_params tuner_temic_4009f_5_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_4009f_5_pal_ranges, .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TEMIC_4039FR5_NTSC - TEMIC NTSC ------------ */ static struct tuner_range tuner_temic_4039fr5_ntsc_ranges[] = { - { 16 * 158.00 /*MHz*/, 0xa0, }, - { 16 * 453.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 158.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 453.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_temic_4039fr5_params[] = { @@ -367,16 +347,15 @@ static struct tuner_params tuner_temic_4039fr5_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_temic_4039fr5_ntsc_ranges, .count = ARRAY_SIZE(tuner_temic_4039fr5_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TEMIC_4046FM5 - TEMIC PAL ------------ */ static struct tuner_range tuner_temic_4046fm5_pal_ranges[] = { - { 16 * 169.00 /*MHz*/, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 169.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_temic_4046fm5_params[] = { @@ -384,16 +363,15 @@ static struct tuner_params tuner_temic_4046fm5_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_4046fm5_pal_ranges, .count = ARRAY_SIZE(tuner_temic_4046fm5_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_PAL_DK - Philips PAL ------------ */ static struct tuner_range tuner_lg_pal_ranges[] = { - { 16 * 170.00 /*MHz*/, 0xa0, }, - { 16 * 450.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 170.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 450.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_philips_pal_dk_params[] = { @@ -401,7 +379,6 @@ static struct tuner_params tuner_philips_pal_dk_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_lg_pal_ranges, .count = ARRAY_SIZE(tuner_lg_pal_ranges), - .config = 0x8e, }, }; @@ -412,7 +389,6 @@ static struct tuner_params tuner_philips_fq1216me_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_lg_pal_ranges, .count = ARRAY_SIZE(tuner_lg_pal_ranges), - .config = 0x8e, }, }; @@ -423,7 +399,6 @@ static struct tuner_params tuner_lg_pal_i_fm_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_lg_pal_ranges, .count = ARRAY_SIZE(tuner_lg_pal_ranges), - .config = 0x8e, }, }; @@ -434,16 +409,15 @@ static struct tuner_params tuner_lg_pal_i_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_lg_pal_ranges, .count = ARRAY_SIZE(tuner_lg_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_LG_NTSC_FM - LGINNOTEK NTSC ------------ */ static struct tuner_range tuner_lg_ntsc_fm_ranges[] = { - { 16 * 210.00 /*MHz*/, 0xa0, }, - { 16 * 497.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 210.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 497.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_lg_ntsc_fm_params[] = { @@ -451,7 +425,6 @@ static struct tuner_params tuner_lg_ntsc_fm_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_lg_ntsc_fm_ranges, .count = ARRAY_SIZE(tuner_lg_ntsc_fm_ranges), - .config = 0x8e, }, }; @@ -462,7 +435,6 @@ static struct tuner_params tuner_lg_pal_fm_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_lg_pal_ranges, .count = ARRAY_SIZE(tuner_lg_pal_ranges), - .config = 0x8e, }, }; @@ -473,7 +445,6 @@ static struct tuner_params tuner_lg_pal_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_lg_pal_ranges, .count = ARRAY_SIZE(tuner_lg_pal_ranges), - .config = 0x8e, }, }; @@ -485,16 +456,15 @@ static struct tuner_params tuner_temic_4009_fn5_multi_pal_fm_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_4009f_5_pal_ranges, .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_SHARP_2U5JF5540_NTSC - SHARP NTSC ------------ */ static struct tuner_range tuner_sharp_2u5jf5540_ntsc_ranges[] = { - { 16 * 137.25 /*MHz*/, 0x01, }, - { 16 * 317.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 137.25 /*MHz*/, 0x8e, 0x01, }, + { 16 * 317.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x08, }, }; static struct tuner_params tuner_sharp_2u5jf5540_params[] = { @@ -502,16 +472,15 @@ static struct tuner_params tuner_sharp_2u5jf5540_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_sharp_2u5jf5540_ntsc_ranges, .count = ARRAY_SIZE(tuner_sharp_2u5jf5540_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_Samsung_PAL_TCPM9091PD27 - Samsung PAL ------------ */ static struct tuner_range tuner_samsung_pal_tcpm9091pd27_ranges[] = { - { 16 * 169 /*MHz*/, 0xa0, }, - { 16 * 464 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 169 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 464 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_samsung_pal_tcpm9091pd27_params[] = { @@ -519,7 +488,6 @@ static struct tuner_params tuner_samsung_pal_tcpm9091pd27_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_samsung_pal_tcpm9091pd27_ranges, .count = ARRAY_SIZE(tuner_samsung_pal_tcpm9091pd27_ranges), - .config = 0x8e, }, }; @@ -530,16 +498,15 @@ static struct tuner_params tuner_temic_4106fh5_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_4009f_5_pal_ranges, .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TEMIC_4012FY5 - TEMIC PAL ------------ */ static struct tuner_range tuner_temic_4012fy5_pal_ranges[] = { - { 16 * 140.25 /*MHz*/, 0x02, }, - { 16 * 463.25 /*MHz*/, 0x04, }, - { 16 * 999.99 , 0x01, }, + { 16 * 140.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 463.25 /*MHz*/, 0x8e, 0x04, }, + { 16 * 999.99 , 0x8e, 0x01, }, }; static struct tuner_params tuner_temic_4012fy5_params[] = { @@ -547,16 +514,15 @@ static struct tuner_params tuner_temic_4012fy5_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_4012fy5_pal_ranges, .count = ARRAY_SIZE(tuner_temic_4012fy5_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TEMIC_4136FY5 - TEMIC NTSC ------------ */ static struct tuner_range tuner_temic_4136_fy5_ntsc_ranges[] = { - { 16 * 158.00 /*MHz*/, 0xa0, }, - { 16 * 453.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 158.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 453.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_temic_4136_fy5_params[] = { @@ -564,16 +530,15 @@ static struct tuner_params tuner_temic_4136_fy5_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_temic_4136_fy5_ntsc_ranges, .count = ARRAY_SIZE(tuner_temic_4136_fy5_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_LG_PAL_NEW_TAPC - LGINNOTEK PAL ------------ */ static struct tuner_range tuner_lg_new_tapc_ranges[] = { - { 16 * 170.00 /*MHz*/, 0x01, }, - { 16 * 450.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 170.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 450.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x08, }, }; static struct tuner_params tuner_lg_pal_new_tapc_params[] = { @@ -581,16 +546,15 @@ static struct tuner_params tuner_lg_pal_new_tapc_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_lg_new_tapc_ranges, .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_FM1216ME_MK3 - Philips PAL ------------ */ static struct tuner_range tuner_fm1216me_mk3_pal_ranges[] = { - { 16 * 158.00 /*MHz*/, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, + { 16 * 158.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x04, }, }; static struct tuner_params tuner_fm1216me_mk3_params[] = { @@ -598,7 +562,6 @@ static struct tuner_params tuner_fm1216me_mk3_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_fm1216me_mk3_pal_ranges, .count = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges), - .config = 0x8e, .cb_first_if_lower_freq = 1, }, }; @@ -610,7 +573,6 @@ static struct tuner_params tuner_lg_ntsc_new_tapc_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_lg_new_tapc_ranges, .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges), - .config = 0x8e, }, }; @@ -622,16 +584,15 @@ static struct tuner_params tuner_hitachi_ntsc_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_lg_new_tapc_ranges, .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_PAL_MK - Philips PAL ------------ */ static struct tuner_range tuner_philips_pal_mk_pal_ranges[] = { - { 16 * 140.25 /*MHz*/, 0x01, }, - { 16 * 463.25 /*MHz*/, 0xc2, }, - { 16 * 999.99 , 0xcf, }, + { 16 * 140.25 /*MHz*/, 0x8e, 0x01, }, + { 16 * 463.25 /*MHz*/, 0x8e, 0xc2, }, + { 16 * 999.99 , 0x8e, 0xcf, }, }; static struct tuner_params tuner_philips_pal_mk_params[] = { @@ -639,16 +600,15 @@ static struct tuner_params tuner_philips_pal_mk_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_philips_pal_mk_pal_ranges, .count = ARRAY_SIZE(tuner_philips_pal_mk_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_ATSC - Philips ATSC ------------ */ static struct tuner_range tuner_philips_atsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_philips_atsc_params[] = { @@ -656,16 +616,15 @@ static struct tuner_params tuner_philips_atsc_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_philips_atsc_ranges, .count = ARRAY_SIZE(tuner_philips_atsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_FM1236_MK3 - Philips NTSC ------------ */ static struct tuner_range tuner_fm1236_mk3_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, + { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x04, }, }; static struct tuner_params tuner_fm1236_mk3_params[] = { @@ -673,7 +632,6 @@ static struct tuner_params tuner_fm1236_mk3_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_fm1236_mk3_ntsc_ranges, .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), - .config = 0x8e, .cb_first_if_lower_freq = 1, }, }; @@ -681,9 +639,9 @@ static struct tuner_params tuner_fm1236_mk3_params[] = { /* ------------ TUNER_PHILIPS_4IN1 - Philips NTSC ------------ */ static struct tuner_range tuner_philips_4in1_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, + { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x04, }, }; static struct tuner_params tuner_philips_4in1_params[] = { @@ -691,7 +649,6 @@ static struct tuner_params tuner_philips_4in1_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_philips_4in1_ntsc_ranges, .count = ARRAY_SIZE(tuner_philips_4in1_ntsc_ranges), - .config = 0x8e, }, }; @@ -702,16 +659,15 @@ static struct tuner_params tuner_microtune_4049_fm5_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_4009f_5_pal_ranges, .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PANASONIC_VP27 - Panasonic NTSC ------------ */ static struct tuner_range tuner_panasonic_vp27_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 454.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 160.00 /*MHz*/, 0xce, 0x01, }, + { 16 * 454.00 /*MHz*/, 0xce, 0x02, }, + { 16 * 999.99 , 0xce, 0x08, }, }; static struct tuner_params tuner_panasonic_vp27_params[] = { @@ -719,16 +675,15 @@ static struct tuner_params tuner_panasonic_vp27_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_panasonic_vp27_ntsc_ranges, .count = ARRAY_SIZE(tuner_panasonic_vp27_ntsc_ranges), - .config = 0xce, }, }; /* ------------ TUNER_LG_NTSC_TAPE - LGINNOTEK NTSC ------------ */ static struct tuner_range tuner_lg_ntsc_tape_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, + { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x04, }, }; static struct tuner_params tuner_lg_ntsc_tape_params[] = { @@ -736,16 +691,15 @@ static struct tuner_params tuner_lg_ntsc_tape_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_lg_ntsc_tape_ranges, .count = ARRAY_SIZE(tuner_lg_ntsc_tape_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */ static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = { - { 16 * 161.25 /*MHz*/, 0xa0, }, - { 16 * 463.25 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 161.25 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 463.25 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_tnf_8831bgff_params[] = { @@ -753,16 +707,15 @@ static struct tuner_params tuner_tnf_8831bgff_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_tnf_8831bgff_pal_ranges, .count = ARRAY_SIZE(tuner_tnf_8831bgff_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_MICROTUNE_4042FI5 - Microtune NTSC ------------ */ static struct tuner_range tuner_microtune_4042fi5_ntsc_ranges[] = { - { 16 * 162.00 /*MHz*/, 0xa2, }, - { 16 * 457.00 /*MHz*/, 0x94, }, - { 16 * 999.99 , 0x31, }, + { 16 * 162.00 /*MHz*/, 0x8e, 0xa2, }, + { 16 * 457.00 /*MHz*/, 0x8e, 0x94, }, + { 16 * 999.99 , 0x8e, 0x31, }, }; static struct tuner_params tuner_microtune_4042fi5_params[] = { @@ -770,7 +723,6 @@ static struct tuner_params tuner_microtune_4042fi5_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_microtune_4042fi5_ntsc_ranges, .count = ARRAY_SIZE(tuner_microtune_4042fi5_ntsc_ranges), - .config = 0x8e, }, }; @@ -778,9 +730,9 @@ static struct tuner_params tuner_microtune_4042fi5_params[] = { /* ------------ TUNER_TCL_2002N - TCL NTSC ------------ */ static struct tuner_range tuner_tcl_2002n_ntsc_ranges[] = { - { 16 * 172.00 /*MHz*/, 0x01, }, - { 16 * 448.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 172.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 448.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x08, }, }; static struct tuner_params tuner_tcl_2002n_params[] = { @@ -788,7 +740,6 @@ static struct tuner_params tuner_tcl_2002n_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_tcl_2002n_ntsc_ranges, .count = ARRAY_SIZE(tuner_tcl_2002n_ntsc_ranges), - .config = 0x8e, .cb_first_if_lower_freq = 1, }, }; @@ -796,9 +747,9 @@ static struct tuner_params tuner_tcl_2002n_params[] = { /* ------------ TUNER_PHILIPS_FM1256_IH3 - Philips PAL ------------ */ static struct tuner_range tuner_philips_fm1256_ih3_pal_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, + { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x04, }, }; static struct tuner_params tuner_philips_fm1256_ih3_params[] = { @@ -806,16 +757,15 @@ static struct tuner_params tuner_philips_fm1256_ih3_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_philips_fm1256_ih3_pal_ranges, .count = ARRAY_SIZE(tuner_philips_fm1256_ih3_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_THOMSON_DTT7610 - THOMSON ATSC ------------ */ static struct tuner_range tuner_thomson_dtt7610_ntsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0x39, }, - { 16 * 454.00 /*MHz*/, 0x3a, }, - { 16 * 999.99 , 0x3c, }, + { 16 * 157.25 /*MHz*/, 0x8e, 0x39, }, + { 16 * 454.00 /*MHz*/, 0x8e, 0x3a, }, + { 16 * 999.99 , 0x8e, 0x3c, }, }; static struct tuner_params tuner_thomson_dtt7610_params[] = { @@ -823,16 +773,15 @@ static struct tuner_params tuner_thomson_dtt7610_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_thomson_dtt7610_ntsc_ranges, .count = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_FQ1286 - Philips NTSC ------------ */ static struct tuner_range tuner_philips_fq1286_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x41, }, - { 16 * 454.00 /*MHz*/, 0x42, }, - { 16 * 999.99 , 0x04, }, + { 16 * 160.00 /*MHz*/, 0x8e, 0x41, }, + { 16 * 454.00 /*MHz*/, 0x8e, 0x42, }, + { 16 * 999.99 , 0x8e, 0x04, }, }; static struct tuner_params tuner_philips_fq1286_params[] = { @@ -840,16 +789,15 @@ static struct tuner_params tuner_philips_fq1286_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_philips_fq1286_ntsc_ranges, .count = ARRAY_SIZE(tuner_philips_fq1286_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TCL_2002MB - TCL PAL ------------ */ static struct tuner_range tuner_tcl_2002mb_pal_ranges[] = { - { 16 * 170.00 /*MHz*/, 0x01, }, - { 16 * 450.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 170.00 /*MHz*/, 0xce, 0x01, }, + { 16 * 450.00 /*MHz*/, 0xce, 0x02, }, + { 16 * 999.99 , 0xce, 0x08, }, }; static struct tuner_params tuner_tcl_2002mb_params[] = { @@ -857,44 +805,47 @@ static struct tuner_params tuner_tcl_2002mb_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_tcl_2002mb_pal_ranges, .count = ARRAY_SIZE(tuner_tcl_2002mb_pal_ranges), - .config = 0xce, }, }; /* ------------ TUNER_PHILIPS_FQ1216AME_MK4 - Philips PAL ------------ */ -static struct tuner_range tuner_philips_fq12_6a___mk4_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, +static struct tuner_range tuner_philips_fq12_6a___mk4_pal_ranges[] = { + { 16 * 160.00 /*MHz*/, 0xce, 0x01, }, + { 16 * 442.00 /*MHz*/, 0xce, 0x02, }, + { 16 * 999.99 , 0xce, 0x04, }, }; static struct tuner_params tuner_philips_fq1216ame_mk4_params[] = { { .type = TUNER_PARAM_TYPE_PAL, - .ranges = tuner_philips_fq12_6a___mk4_ranges, - .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_ranges), - .config = 0xce, + .ranges = tuner_philips_fq12_6a___mk4_pal_ranges, + .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_pal_ranges), }, }; /* ------------ TUNER_PHILIPS_FQ1236A_MK4 - Philips NTSC ------------ */ +static struct tuner_range tuner_philips_fq12_6a___mk4_ntsc_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x04, }, +}; + static struct tuner_params tuner_philips_fq1236a_mk4_params[] = { { .type = TUNER_PARAM_TYPE_NTSC, - .ranges = tuner_philips_fq12_6a___mk4_ranges, - .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_ranges), - .config = 0x8e, + .ranges = tuner_philips_fq12_6a___mk4_ntsc_ranges, + .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_ntsc_ranges), }, }; /* ------------ TUNER_YMEC_TVF_8531MF - Philips NTSC ------------ */ static struct tuner_range tuner_ymec_tvf_8531mf_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 160.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_ymec_tvf_8531mf_params[] = { @@ -902,16 +853,15 @@ static struct tuner_params tuner_ymec_tvf_8531mf_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_ymec_tvf_8531mf_ntsc_ranges, .count = ARRAY_SIZE(tuner_ymec_tvf_8531mf_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_YMEC_TVF_5533MF - Philips NTSC ------------ */ static struct tuner_range tuner_ymec_tvf_5533mf_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 454.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, + { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 454.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x04, }, }; static struct tuner_params tuner_ymec_tvf_5533mf_params[] = { @@ -919,7 +869,6 @@ static struct tuner_params tuner_ymec_tvf_5533mf_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_ymec_tvf_5533mf_ntsc_ranges, .count = ARRAY_SIZE(tuner_ymec_tvf_5533mf_ntsc_ranges), - .config = 0x8e, }, }; @@ -928,9 +877,9 @@ static struct tuner_params tuner_ymec_tvf_5533mf_params[] = { /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */ static struct tuner_range tuner_thomson_dtt761x_ntsc_ranges[] = { - { 16 * 145.25 /*MHz*/, 0x39, }, - { 16 * 415.25 /*MHz*/, 0x3a, }, - { 16 * 999.99 , 0x3c, }, + { 16 * 145.25 /*MHz*/, 0x8e, 0x39, }, + { 16 * 415.25 /*MHz*/, 0x8e, 0x3a, }, + { 16 * 999.99 , 0x8e, 0x3c, }, }; @@ -939,16 +888,15 @@ static struct tuner_params tuner_thomson_dtt761x_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_thomson_dtt761x_ntsc_ranges, .count = ARRAY_SIZE(tuner_thomson_dtt761x_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TENA_9533_DI - Philips PAL ------------ */ static struct tuner_range tuner_tuner_tena_9533_di_pal_ranges[] = { - { 16 * 160.25 /*MHz*/, 0x01, }, - { 16 * 464.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, + { 16 * 160.25 /*MHz*/, 0x8e, 0x01, }, + { 16 * 464.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x04, }, }; static struct tuner_params tuner_tena_9533_di_params[] = { @@ -956,16 +904,15 @@ static struct tuner_params tuner_tena_9533_di_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_tuner_tena_9533_di_pal_ranges, .count = ARRAY_SIZE(tuner_tuner_tena_9533_di_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_FMD1216ME_MK3 - Philips PAL ------------ */ static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x51, }, - { 16 * 442.00 /*MHz*/, 0x52, }, - { 16 * 999.99 , 0x54, }, + { 16 * 160.00 /*MHz*/, 0x86, 0x51, }, + { 16 * 442.00 /*MHz*/, 0x86, 0x52, }, + { 16 * 999.99 , 0x86, 0x54, }, }; @@ -974,7 +921,6 @@ static struct tuner_params tuner_tuner_philips_fmd1216me_mk3_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_philips_fmd1216me_mk3_pal_ranges, .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_pal_ranges), - .config = 0x86, }, }; @@ -982,9 +928,9 @@ static struct tuner_params tuner_tuner_philips_fmd1216me_mk3_params[] = { /* ------------ TUNER_LG_TDVS_H062F - INFINEON ATSC ------------ */ static struct tuner_range tuner_tua6034_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x01 }, - { 16 * 455.00 /*MHz*/, 0x02 }, - { 16 * 999.99 , 0x04 }, + { 16 * 160.00 /*MHz*/, 0x8e, 0x01 }, + { 16 * 455.00 /*MHz*/, 0x8e, 0x02 }, + { 16 * 999.99 , 0x8e, 0x04 }, }; @@ -993,16 +939,15 @@ static struct tuner_params tuner_tua6034_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_tua6034_ntsc_ranges, .count = ARRAY_SIZE(tuner_tua6034_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_YMEC_TVF66T5_B_DFF - Philips PAL ------------ */ static struct tuner_range tuner_ymec_tvf66t5_b_dff_pal_ranges[] = { - { 16 * 160.25 /*MHz*/, 0x01, }, - { 16 * 464.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 160.25 /*MHz*/, 0x8e, 0x01, }, + { 16 * 464.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x08, }, }; static struct tuner_params tuner_ymec_tvf66t5_b_dff_params[] = { @@ -1010,16 +955,15 @@ static struct tuner_params tuner_ymec_tvf66t5_b_dff_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_ymec_tvf66t5_b_dff_pal_ranges, .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_LG_NTSC_TALN_MINI - LGINNOTEK NTSC ------------ */ static struct tuner_range tuner_lg_taln_mini_ntsc_ranges[] = { - { 16 * 137.25 /*MHz*/, 0x01, }, - { 16 * 373.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 137.25 /*MHz*/, 0x8e, 0x01, }, + { 16 * 373.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x08, }, }; static struct tuner_params tuner_lg_taln_mini_params[] = { @@ -1027,16 +971,15 @@ static struct tuner_params tuner_lg_taln_mini_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_lg_taln_mini_ntsc_ranges, .count = ARRAY_SIZE(tuner_lg_taln_mini_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_TD1316 - Philips PAL ------------ */ static struct tuner_range tuner_philips_td1316_pal_ranges[] = { - { 16 * 160.00 /*MHz*/, 0xa1, }, - { 16 * 442.00 /*MHz*/, 0xa2, }, - { 16 * 999.99 , 0xa4, }, + { 16 * 160.00 /*MHz*/, 0xc8, 0xa1, }, + { 16 * 442.00 /*MHz*/, 0xc8, 0xa2, }, + { 16 * 999.99 , 0xc8, 0xa4, }, }; static struct tuner_params tuner_philips_td1316_params[] = { @@ -1044,16 +987,15 @@ static struct tuner_params tuner_philips_td1316_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_philips_td1316_pal_ranges, .count = ARRAY_SIZE(tuner_philips_td1316_pal_ranges), - .config = 0xc8, }, }; /* ------------ TUNER_PHILIPS_TUV1236D - Philips ATSC ------------ */ static struct tuner_range tuner_tuv1236d_ntsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0x01, }, - { 16 * 454.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, + { 16 * 157.25 /*MHz*/, 0xce, 0x01, }, + { 16 * 454.00 /*MHz*/, 0xce, 0x02, }, + { 16 * 999.99 , 0xce, 0x04, }, }; @@ -1062,16 +1004,15 @@ static struct tuner_params tuner_tuner_tuv1236d_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_tuv1236d_ntsc_ranges, .count = ARRAY_SIZE(tuner_tuv1236d_ntsc_ranges), - .config = 0xce, }, }; /* ------------ TUNER_TNF_5335MF - Philips NTSC ------------ */ static struct tuner_range tuner_tnf_5335mf_ntsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0x01, }, - { 16 * 454.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, + { 16 * 157.25 /*MHz*/, 0x8e, 0x01, }, + { 16 * 454.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x04, }, }; static struct tuner_params tuner_tnf_5335mf_params[] = { @@ -1079,7 +1020,6 @@ static struct tuner_params tuner_tnf_5335mf_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_tnf_5335mf_ntsc_ranges, .count = ARRAY_SIZE(tuner_tnf_5335mf_ntsc_ranges), - .config = 0x8e, }, }; @@ -1087,9 +1027,9 @@ static struct tuner_params tuner_tnf_5335mf_params[] = { /* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */ static struct tuner_range tuner_samsung_tcpn_2121p30a_ntsc_ranges[] = { - { 16 * 175.75 /*MHz*/, 0x01, }, - { 16 * 410.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 175.75 /*MHz*/, 0xce, 0x01, }, + { 16 * 410.25 /*MHz*/, 0xce, 0x02, }, + { 16 * 999.99 , 0xce, 0x08, }, }; static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = { @@ -1097,7 +1037,6 @@ static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_samsung_tcpn_2121p30a_ntsc_ranges, .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_ntsc_ranges), - .config = 0xce, }, }; diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h index 15821ab14a9e..53ac66e0114b 100644 --- a/include/media/tuner-types.h +++ b/include/media/tuner-types.h @@ -14,6 +14,7 @@ enum param_type { struct tuner_range { unsigned short limit; + unsigned char config; unsigned char cb; }; @@ -38,7 +39,6 @@ struct tuner_params { * static unless the control byte was sent first. */ unsigned int cb_first_if_lower_freq:1; - unsigned char config; /* to be moved into struct tuner_range for dvb-pll merge */ unsigned int count; struct tuner_range *ranges; -- cgit v1.2.3 From a454c2f3d1fd1cab7073b53c6c14d6d4b61f4e09 Mon Sep 17 00:00:00 2001 From: "Chen, Kenneth W" Date: Wed, 11 Jan 2006 17:11:09 -0800 Subject: [IA64] implement ia64 specific mutex primitives Implement ia64 optimized mutex primitives. It properly uses acquire/release memory ordering semantics in lock/unlock path. 2nd version making them all static inline functions. Signed-off-by: Ken Chen Signed-off-by: Tony Luck --- include/asm-ia64/mutex.h | 93 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 88 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/asm-ia64/mutex.h b/include/asm-ia64/mutex.h index 458c1f7fbc18..5a3224f6af38 100644 --- a/include/asm-ia64/mutex.h +++ b/include/asm-ia64/mutex.h @@ -1,9 +1,92 @@ /* - * Pull in the generic implementation for the mutex fastpath. + * ia64 implementation of the mutex fastpath. * - * TODO: implement optimized primitives instead, or leave the generic - * implementation in place, or pick the atomic_xchg() based generic - * implementation. (see asm-generic/mutex-xchg.h for details) + * Copyright (C) 2006 Ken Chen + * + */ + +#ifndef _ASM_MUTEX_H +#define _ASM_MUTEX_H + +/** + * __mutex_fastpath_lock - try to take the lock by moving the count + * from 1 to a 0 value + * @count: pointer of type atomic_t + * @fail_fn: function to call if the original value was not 1 + * + * Change the count from 1 to a value lower than 1, and call if + * it wasn't 1 originally. This function MUST leave the value lower than + * 1 even when the "1" assertion wasn't true. + */ +static inline void +__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *)) +{ + if (unlikely(ia64_fetchadd4_acq(count, -1) != 1)) + fail_fn(count); +} + +/** + * __mutex_fastpath_lock_retval - try to take the lock by moving the count + * from 1 to a 0 value + * @count: pointer of type atomic_t + * @fail_fn: function to call if the original value was not 1 + * + * Change the count from 1 to a value lower than 1, and call if + * it wasn't 1 originally. This function returns 0 if the fastpath succeeds, + * or anything the slow path function returns. + */ +static inline int +__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) +{ + if (unlikely(ia64_fetchadd4_acq(count, -1) != 1)) + return fail_fn(count); + return 0; +} + +/** + * __mutex_fastpath_unlock - try to promote the count from 0 to 1 + * @count: pointer of type atomic_t + * @fail_fn: function to call if the original value was not 0 + * + * Try to promote the count from 0 to 1. If it wasn't 0, call . + * In the failure case, this function is allowed to either set the value to + * 1, or to set it to a value lower than 1. + * + * If the implementation sets it to a value of lower than 1, then the + * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs + * to return 0 otherwise. + */ +static inline void +__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *)) +{ + int ret = ia64_fetchadd4_rel(count, 1); + if (unlikely(ret < 0)) + fail_fn(count); +} + +#define __mutex_slowpath_needs_to_unlock() 1 + +/** + * __mutex_fastpath_trylock - try to acquire the mutex, without waiting + * + * @count: pointer of type atomic_t + * @fail_fn: fallback function + * + * Change the count from 1 to a value lower than 1, and return 0 (failure) + * if it wasn't 1 originally, or return 1 (success) otherwise. This function + * MUST leave the value lower than 1 even when the "1" assertion wasn't true. + * Additionally, if the value was < 0 originally, this function must not leave + * it to 0 on failure. + * + * If the architecture has no effective trylock variant, it should call the + * spinlock-based trylock variant unconditionally. */ +static inline int +__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) +{ + if (likely(cmpxchg_acq(count, 1, 0)) == 1) + return 1; + return 0; +} -#include +#endif -- cgit v1.2.3 From b0a06623dc4caf6dfb6a84419507643471676d20 Mon Sep 17 00:00:00 2001 From: Keith Owens Date: Sun, 22 Jan 2006 10:55:25 +1100 Subject: [IA64] Delete MCA/INIT sigdelayed code The only user of the MCA/INIT sigdelayed code (SGI's I/O probing) has moved from the kernel into SAL. Delete the MCA/INIT sigdelayed code. Signed-off-by: Keith Owens Signed-off-by: Tony Luck --- arch/ia64/kernel/entry.S | 14 ------ arch/ia64/kernel/signal.c | 101 ----------------------------------------- include/asm-ia64/signal.h | 2 - include/asm-ia64/thread_info.h | 11 +---- 4 files changed, 1 insertion(+), 127 deletions(-) (limited to 'include') diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 7a6ffd613789..9dda7a36d1ee 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1100,9 +1100,6 @@ skip_rbs_switch: st8 [r2]=r8 st8 [r3]=r10 .work_pending: - tbit.nz p6,p0=r31,TIF_SIGDELAYED // signal delayed from MCA/INIT/NMI/PMI context? -(p6) br.cond.sptk.few .sigdelayed - ;; tbit.z p6,p0=r31,TIF_NEED_RESCHED // current_thread_info()->need_resched==0? (p6) br.cond.sptk.few .notify #ifdef CONFIG_PREEMPT @@ -1129,17 +1126,6 @@ skip_rbs_switch: (pLvSys)br.cond.sptk.few .work_pending_syscall_end br.cond.sptk.many .work_processed_kernel // don't re-check -// There is a delayed signal that was detected in MCA/INIT/NMI/PMI context where -// it could not be delivered. Deliver it now. The signal might be for us and -// may set TIF_SIGPENDING, so redrive ia64_leave_* after processing the delayed -// signal. - -.sigdelayed: - br.call.sptk.many rp=do_sigdelayed - cmp.eq p6,p0=r0,r0 // p6 <- 1, always re-check -(pLvSys)br.cond.sptk.few .work_pending_syscall_end - br.cond.sptk.many .work_processed_kernel // re-check - .work_pending_syscall_end: adds r2=PT(R8)+16,r12 adds r3=PT(R10)+16,r12 diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index 463f6bb44d07..1d7903ee2126 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c @@ -588,104 +588,3 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) } return 0; } - -/* Set a delayed signal that was detected in MCA/INIT/NMI/PMI context where it - * could not be delivered. It is important that the target process is not - * allowed to do any more work in user space. Possible cases for the target - * process: - * - * - It is sleeping and will wake up soon. Store the data in the current task, - * the signal will be sent when the current task returns from the next - * interrupt. - * - * - It is running in user context. Store the data in the current task, the - * signal will be sent when the current task returns from the next interrupt. - * - * - It is running in kernel context on this or another cpu and will return to - * user context. Store the data in the target task, the signal will be sent - * to itself when the target task returns to user space. - * - * - It is running in kernel context on this cpu and will sleep before - * returning to user context. Because this is also the current task, the - * signal will not get delivered and the task could sleep indefinitely. - * Store the data in the idle task for this cpu, the signal will be sent - * after the idle task processes its next interrupt. - * - * To cover all cases, store the data in the target task, the current task and - * the idle task on this cpu. Whatever happens, the signal will be delivered - * to the target task before it can do any useful user space work. Multiple - * deliveries have no unwanted side effects. - * - * Note: This code is executed in MCA/INIT/NMI/PMI context, with interrupts - * disabled. It must not take any locks nor use kernel structures or services - * that require locks. - */ - -/* To ensure that we get the right pid, check its start time. To avoid extra - * include files in thread_info.h, convert the task start_time to unsigned long, - * giving us a cycle time of > 580 years. - */ -static inline unsigned long -start_time_ul(const struct task_struct *t) -{ - return t->start_time.tv_sec * NSEC_PER_SEC + t->start_time.tv_nsec; -} - -void -set_sigdelayed(pid_t pid, int signo, int code, void __user *addr) -{ - struct task_struct *t; - unsigned long start_time = 0; - int i; - - for (i = 1; i <= 3; ++i) { - switch (i) { - case 1: - t = find_task_by_pid(pid); - if (t) - start_time = start_time_ul(t); - break; - case 2: - t = current; - break; - default: - t = idle_task(smp_processor_id()); - break; - } - - if (!t) - return; - task_thread_info(t)->sigdelayed.signo = signo; - task_thread_info(t)->sigdelayed.code = code; - task_thread_info(t)->sigdelayed.addr = addr; - task_thread_info(t)->sigdelayed.start_time = start_time; - task_thread_info(t)->sigdelayed.pid = pid; - wmb(); - set_tsk_thread_flag(t, TIF_SIGDELAYED); - } -} - -/* Called from entry.S when it detects TIF_SIGDELAYED, a delayed signal that - * was detected in MCA/INIT/NMI/PMI context where it could not be delivered. - */ - -void -do_sigdelayed(void) -{ - struct siginfo siginfo; - pid_t pid; - struct task_struct *t; - - clear_thread_flag(TIF_SIGDELAYED); - memset(&siginfo, 0, sizeof(siginfo)); - siginfo.si_signo = current_thread_info()->sigdelayed.signo; - siginfo.si_code = current_thread_info()->sigdelayed.code; - siginfo.si_addr = current_thread_info()->sigdelayed.addr; - pid = current_thread_info()->sigdelayed.pid; - t = find_task_by_pid(pid); - if (!t) - return; - if (current_thread_info()->sigdelayed.start_time != start_time_ul(t)) - return; - force_sig_info(siginfo.si_signo, &siginfo, t); -} diff --git a/include/asm-ia64/signal.h b/include/asm-ia64/signal.h index 608168d713d3..5e328ed5d01d 100644 --- a/include/asm-ia64/signal.h +++ b/include/asm-ia64/signal.h @@ -158,8 +158,6 @@ struct k_sigaction { #define ptrace_signal_deliver(regs, cookie) do { } while (0) -void set_sigdelayed(pid_t pid, int signo, int code, void __user *addr); - #endif /* __KERNEL__ */ # endif /* !__ASSEMBLY__ */ diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h index 1d6518fe1f02..a6ee27343a4a 100644 --- a/include/asm-ia64/thread_info.h +++ b/include/asm-ia64/thread_info.h @@ -29,13 +29,6 @@ struct thread_info { mm_segment_t addr_limit; /* user-level address space limit */ int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */ struct restart_block restart_block; - struct { - int signo; - int code; - void __user *addr; - unsigned long start_time; - pid_t pid; - } sigdelayed; /* Saved information for TIF_SIGDELAYED */ }; #define THREAD_SIZE KERNEL_STACK_SIZE @@ -89,7 +82,6 @@ struct thread_info { #define TIF_NEED_RESCHED 2 /* rescheduling necessary */ #define TIF_SYSCALL_TRACE 3 /* syscall trace active */ #define TIF_SYSCALL_AUDIT 4 /* syscall auditing active */ -#define TIF_SIGDELAYED 5 /* signal delayed from MCA/INIT/NMI/PMI context */ #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_MEMDIE 17 #define TIF_MCA_INIT 18 /* this task is processing MCA or INIT */ @@ -101,13 +93,12 @@ struct thread_info { #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) -#define _TIF_SIGDELAYED (1 << TIF_SIGDELAYED) #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) #define _TIF_MCA_INIT (1 << TIF_MCA_INIT) #define _TIF_DB_DISABLED (1 << TIF_DB_DISABLED) /* "work to do on user-return" bits */ -#define TIF_ALLWORK_MASK (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SIGDELAYED) +#define TIF_ALLWORK_MASK (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT) /* like TIF_ALLWORK_BITS but sans TIF_SYSCALL_TRACE or TIF_SYSCALL_AUDIT */ #define TIF_WORK_MASK (TIF_ALLWORK_MASK&~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)) -- cgit v1.2.3 From 13938ca7a1ad9a4788cf73309f187d99c97ddfde Mon Sep 17 00:00:00 2001 From: Mark Maule Date: Thu, 26 Jan 2006 14:46:39 -0600 Subject: [IA64-SGI] driver bugfixes and hardware workarounds for CE1.0 asic Various bugfixes and hardware bug workarounds necessary for the rev 1.0 version of the altix TIO CE asic. Signed-off-by: Mark Maule Signed-off-by: Tony Luck --- arch/ia64/sn/pci/tioce_provider.c | 326 +++++++++++++++++++++++++++++++++++--- include/asm-ia64/sn/addrs.h | 8 + include/asm-ia64/sn/tioce.h | 36 ++++- 3 files changed, 345 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c index e52831ed93eb..fa073cc4b565 100644 --- a/arch/ia64/sn/pci/tioce_provider.c +++ b/arch/ia64/sn/pci/tioce_provider.c @@ -15,6 +15,124 @@ #include #include #include +#include + +/* + * 1/26/2006 + * + * WAR for SGI PV 944642. For revA TIOCE, need to use the following recipe + * (taken from the above PV) before and after accessing tioce internal MMR's + * to avoid tioce lockups. + * + * The recipe as taken from the PV: + * + * if(mmr address < 0x45000) { + * if(mmr address == 0 or 0x80) + * mmr wrt or read address 0xc0 + * else if(mmr address == 0x148 or 0x200) + * mmr wrt or read address 0x28 + * else + * mmr wrt or read address 0x158 + * + * do desired mmr access (rd or wrt) + * + * if(mmr address == 0x100) + * mmr wrt or read address 0x38 + * mmr wrt or read address 0xb050 + * } else + * do desired mmr access + * + * According to hw, we can use reads instead of writes to the above addres + * + * Note this WAR can only to be used for accessing internal MMR's in the + * TIOCE Coretalk Address Range 0x0 - 0x07ff_ffff. This includes the + * "Local CE Registers and Memories" and "PCI Compatible Config Space" address + * spaces from table 2-1 of the "CE Programmer's Reference Overview" document. + * + * All registers defined in struct tioce will meet that criteria. + */ + +static void inline +tioce_mmr_war_pre(struct tioce_kernel *kern, void *mmr_addr) +{ + u64 mmr_base; + u64 mmr_offset; + + if (kern->ce_common->ce_rev != TIOCE_REV_A) + return; + + mmr_base = kern->ce_common->ce_pcibus.bs_base; + mmr_offset = (u64)mmr_addr - mmr_base; + + if (mmr_offset < 0x45000) { + u64 mmr_war_offset; + + if (mmr_offset == 0 || mmr_offset == 0x80) + mmr_war_offset = 0xc0; + else if (mmr_offset == 0x148 || mmr_offset == 0x200) + mmr_war_offset = 0x28; + else + mmr_war_offset = 0x158; + + readq_relaxed((void *)(mmr_base + mmr_war_offset)); + } +} + +static void inline +tioce_mmr_war_post(struct tioce_kernel *kern, void *mmr_addr) +{ + u64 mmr_base; + u64 mmr_offset; + + if (kern->ce_common->ce_rev != TIOCE_REV_A) + return; + + mmr_base = kern->ce_common->ce_pcibus.bs_base; + mmr_offset = (u64)mmr_addr - mmr_base; + + if (mmr_offset < 0x45000) { + if (mmr_offset == 0x100) + readq_relaxed((void *)(mmr_base + 0x38)); + readq_relaxed((void *)(mmr_base + 0xb050)); + } +} + +/* load mmr contents into a variable */ +#define tioce_mmr_load(kern, mmrp, varp) do {\ + tioce_mmr_war_pre(kern, mmrp); \ + *(varp) = readq_relaxed(mmrp); \ + tioce_mmr_war_post(kern, mmrp); \ +} while (0) + +/* store variable contents into mmr */ +#define tioce_mmr_store(kern, mmrp, varp) do {\ + tioce_mmr_war_pre(kern, mmrp); \ + writeq(*varp, mmrp); \ + tioce_mmr_war_post(kern, mmrp); \ +} while (0) + +/* store immediate value into mmr */ +#define tioce_mmr_storei(kern, mmrp, val) do {\ + tioce_mmr_war_pre(kern, mmrp); \ + writeq(val, mmrp); \ + tioce_mmr_war_post(kern, mmrp); \ +} while (0) + +/* set bits (immediate value) into mmr */ +#define tioce_mmr_seti(kern, mmrp, bits) do {\ + u64 tmp; \ + tioce_mmr_load(kern, mmrp, &tmp); \ + tmp |= (bits); \ + tioce_mmr_store(kern, mmrp, &tmp); \ +} while (0) + +/* clear bits (immediate value) into mmr */ +#define tioce_mmr_clri(kern, mmrp, bits) do { \ + u64 tmp; \ + tioce_mmr_load(kern, mmrp, &tmp); \ + tmp &= ~(bits); \ + tioce_mmr_store(kern, mmrp, &tmp); \ +} while (0) /** * Bus address ranges for the 5 flavors of TIOCE DMA @@ -62,9 +180,9 @@ #define TIOCE_ATE_M40 2 #define TIOCE_ATE_M40S 3 -#define KB(x) ((x) << 10) -#define MB(x) ((x) << 20) -#define GB(x) ((x) << 30) +#define KB(x) ((u64)(x) << 10) +#define MB(x) ((u64)(x) << 20) +#define GB(x) ((u64)(x) << 30) /** * tioce_dma_d64 - create a DMA mapping using 64-bit direct mode @@ -151,7 +269,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, int last; int entries; int nates; - int pagesize; + u64 pagesize; u64 *ate_shadow; u64 *ate_reg; u64 addr; @@ -228,7 +346,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, ate = ATE_MAKE(addr, pagesize); ate_shadow[i + j] = ate; - writeq(ate, &ate_reg[i + j]); + tioce_mmr_storei(ce_kern, &ate_reg[i + j], ate); addr += pagesize; } @@ -272,7 +390,8 @@ tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr) u64 tmp; ce_kern->ce_port[port].dirmap_shadow = ct_upper; - writeq(ct_upper, &ce_mmr->ce_ure_dir_map[port]); + tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_dir_map[port], + ct_upper); tmp = ce_mmr->ce_ure_dir_map[port]; dma_ok = 1; } else @@ -344,7 +463,8 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) if (TIOCE_D32_ADDR(bus_addr)) { if (--ce_kern->ce_port[port].dirmap_refcnt == 0) { ce_kern->ce_port[port].dirmap_shadow = 0; - writeq(0, &ce_mmr->ce_ure_dir_map[port]); + tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_dir_map[port], + 0); } } else { struct tioce_dmamap *map; @@ -365,7 +485,7 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) } else if (--map->refcnt == 0) { for (i = 0; i < map->ate_count; i++) { map->ate_shadow[i] = 0; - map->ate_hw[i] = 0; + tioce_mmr_storei(ce_kern, &map->ate_hw[i], 0); } list_del(&map->ce_dmamap_list); @@ -486,7 +606,7 @@ tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, spin_unlock_irqrestore(&ce_kern->ce_lock, flags); dma_map_done: - if (mapaddr & barrier) + if (mapaddr && barrier) mapaddr = tioce_dma_barrier(mapaddr, 1); return mapaddr; @@ -541,17 +661,61 @@ tioce_error_intr_handler(int irq, void *arg, struct pt_regs *pt) soft->ce_pcibus.bs_persist_segment, soft->ce_pcibus.bs_persist_busnum, 0, 0, 0, 0, 0); + if (ret_stuff.v0) + panic("tioce_error_intr_handler: Fatal TIOCE error"); + return IRQ_HANDLED; } +/** + * tioce_reserve_m32 - reserve M32 ate's for the indicated address range + * @tioce_kernel: TIOCE context to reserve ate's for + * @base: starting bus address to reserve + * @limit: last bus address to reserve + * + * If base/limit falls within the range of bus space mapped through the + * M32 space, reserve the resources corresponding to the range. + */ +static void +tioce_reserve_m32(struct tioce_kernel *ce_kern, u64 base, u64 limit) +{ + int ate_index, last_ate, ps; + struct tioce *ce_mmr; + + if (!TIOCE_M32_ADDR(base)) + return; + + ce_mmr = (struct tioce *)ce_kern->ce_common->ce_pcibus.bs_base; + ps = ce_kern->ce_ate3240_pagesize; + ate_index = ATE_PAGE(base, ps); + last_ate = ate_index + ATE_NPAGES(base, limit-base+1, ps) - 1; + + if (ate_index < 64) + ate_index = 64; + + while (ate_index <= last_ate) { + u64 ate; + + ate = ATE_MAKE(0xdeadbeef, ps); + ce_kern->ce_ate3240_shadow[ate_index] = ate; + tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_ate3240[ate_index], + ate); + ate_index++; + } +} + /** * tioce_kern_init - init kernel structures related to a given TIOCE * @tioce_common: ptr to a cached tioce_common struct that originated in prom - */ static struct tioce_kernel * + */ +static struct tioce_kernel * tioce_kern_init(struct tioce_common *tioce_common) { int i; + int ps; + int dev; u32 tmp; + unsigned int seg, bus; struct tioce *tioce_mmr; struct tioce_kernel *tioce_kern; @@ -572,9 +736,10 @@ tioce_kern_init(struct tioce_common *tioce_common) * here to use pci_read_config_xxx() so use the raw_pci_ops vector. */ - raw_pci_ops->read(tioce_common->ce_pcibus.bs_persist_segment, - tioce_common->ce_pcibus.bs_persist_busnum, - PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1, &tmp); + seg = tioce_common->ce_pcibus.bs_persist_segment; + bus = tioce_common->ce_pcibus.bs_persist_busnum; + + raw_pci_ops->read(seg, bus, PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1,&tmp); tioce_kern->ce_port1_secondary = (u8) tmp; /* @@ -583,18 +748,76 @@ tioce_kern_init(struct tioce_common *tioce_common) */ tioce_mmr = (struct tioce *)tioce_common->ce_pcibus.bs_base; - __sn_clrq_relaxed(&tioce_mmr->ce_ure_page_map, CE_URE_PAGESIZE_MASK); - __sn_setq_relaxed(&tioce_mmr->ce_ure_page_map, CE_URE_256K_PAGESIZE); - tioce_kern->ce_ate3240_pagesize = KB(256); + tioce_mmr_clri(tioce_kern, &tioce_mmr->ce_ure_page_map, + CE_URE_PAGESIZE_MASK); + tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_ure_page_map, + CE_URE_256K_PAGESIZE); + ps = tioce_kern->ce_ate3240_pagesize = KB(256); for (i = 0; i < TIOCE_NUM_M40_ATES; i++) { tioce_kern->ce_ate40_shadow[i] = 0; - writeq(0, &tioce_mmr->ce_ure_ate40[i]); + tioce_mmr_storei(tioce_kern, &tioce_mmr->ce_ure_ate40[i], 0); } for (i = 0; i < TIOCE_NUM_M3240_ATES; i++) { tioce_kern->ce_ate3240_shadow[i] = 0; - writeq(0, &tioce_mmr->ce_ure_ate3240[i]); + tioce_mmr_storei(tioce_kern, &tioce_mmr->ce_ure_ate3240[i], 0); + } + + /* + * Reserve ATE's corresponding to reserved address ranges. These + * include: + * + * Memory space covered by each PPB mem base/limit register + * Memory space covered by each PPB prefetch base/limit register + * + * These bus ranges are for pio (downstream) traffic only, and so + * cannot be used for DMA. + */ + + for (dev = 1; dev <= 2; dev++) { + u64 base, limit; + + /* mem base/limit */ + + raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0), + PCI_MEMORY_BASE, 2, &tmp); + base = (u64)tmp << 16; + + raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0), + PCI_MEMORY_LIMIT, 2, &tmp); + limit = (u64)tmp << 16; + limit |= 0xfffffUL; + + if (base < limit) + tioce_reserve_m32(tioce_kern, base, limit); + + /* + * prefetch mem base/limit. The tioce ppb's have 64-bit + * decoders, so read the upper portions w/o checking the + * attributes. + */ + + raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0), + PCI_PREF_MEMORY_BASE, 2, &tmp); + base = ((u64)tmp & PCI_PREF_RANGE_MASK) << 16; + + raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0), + PCI_PREF_BASE_UPPER32, 4, &tmp); + base |= (u64)tmp << 32; + + raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0), + PCI_PREF_MEMORY_LIMIT, 2, &tmp); + + limit = ((u64)tmp & PCI_PREF_RANGE_MASK) << 16; + limit |= 0xfffffUL; + + raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0), + PCI_PREF_LIMIT_UPPER32, 4, &tmp); + limit |= (u64)tmp << 32; + + if ((base < limit) && TIOCE_M32_ADDR(base)) + tioce_reserve_m32(tioce_kern, base, limit); } return tioce_kern; @@ -614,6 +837,7 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info) { struct pcidev_info *pcidev_info; struct tioce_common *ce_common; + struct tioce_kernel *ce_kern; struct tioce *ce_mmr; u64 force_int_val; @@ -629,6 +853,29 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info) ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info; ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base; + ce_kern = (struct tioce_kernel *)ce_common->ce_kernel_private; + + /* + * TIOCE Rev A workaround (PV 945826), force an interrupt by writing + * the TIO_INTx register directly (1/26/2006) + */ + if (ce_common->ce_rev == TIOCE_REV_A) { + u64 int_bit_mask = (1ULL << sn_irq_info->irq_int_bit); + u64 status; + + tioce_mmr_load(ce_kern, &ce_mmr->ce_adm_int_status, &status); + if (status & int_bit_mask) { + u64 force_irq = (1 << 8) | sn_irq_info->irq_irq; + u64 ctalk = sn_irq_info->irq_xtalkaddr; + u64 nasid, offset; + + nasid = (ctalk & CTALK_NASID_MASK) >> CTALK_NASID_SHFT; + offset = (ctalk & CTALK_NODE_OFFSET); + HUB_S(TIO_IOSPACE_ADDR(nasid, offset), force_irq); + } + + return; + } /* * irq_int_bit is originally set up by prom, and holds the interrupt @@ -666,7 +913,7 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info) default: return; } - writeq(force_int_val, &ce_mmr->ce_adm_force_int); + tioce_mmr_storei(ce_kern, &ce_mmr->ce_adm_force_int, force_int_val); } /** @@ -685,6 +932,7 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info) { struct pcidev_info *pcidev_info; struct tioce_common *ce_common; + struct tioce_kernel *ce_kern; struct tioce *ce_mmr; int bit; u64 vector; @@ -695,14 +943,15 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info) ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info; ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base; + ce_kern = (struct tioce_kernel *)ce_common->ce_kernel_private; bit = sn_irq_info->irq_int_bit; - __sn_setq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit)); + tioce_mmr_seti(ce_kern, &ce_mmr->ce_adm_int_mask, (1UL << bit)); vector = (u64)sn_irq_info->irq_irq << INTR_VECTOR_SHFT; vector |= sn_irq_info->irq_xtalkaddr; - writeq(vector, &ce_mmr->ce_adm_int_dest[bit]); - __sn_clrq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit)); + tioce_mmr_storei(ce_kern, &ce_mmr->ce_adm_int_dest[bit], vector); + tioce_mmr_clri(ce_kern, &ce_mmr->ce_adm_int_mask, (1UL << bit)); tioce_force_interrupt(sn_irq_info); } @@ -721,7 +970,11 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info) static void * tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller) { + int my_nasid; + cnodeid_t my_cnode, mem_cnode; struct tioce_common *tioce_common; + struct tioce_kernel *tioce_kern; + struct tioce *tioce_mmr; /* * Allocate kernel bus soft and copy from prom. @@ -734,11 +987,23 @@ tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont memcpy(tioce_common, prom_bussoft, sizeof(struct tioce_common)); tioce_common->ce_pcibus.bs_base |= __IA64_UNCACHED_OFFSET; - if (tioce_kern_init(tioce_common) == NULL) { + tioce_kern = tioce_kern_init(tioce_common); + if (tioce_kern == NULL) { kfree(tioce_common); return NULL; } + /* + * Clear out any transient errors before registering the error + * interrupt handler. + */ + + tioce_mmr = (struct tioce *)tioce_common->ce_pcibus.bs_base; + tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_int_status_alias, ~0ULL); + tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_error_summary_alias, + ~0ULL); + tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_dre_comp_err_addr, ~0ULL); + if (request_irq(SGI_PCIASIC_ERROR, tioce_error_intr_handler, SA_SHIRQ, "TIOCE error", (void *)tioce_common)) @@ -750,6 +1015,21 @@ tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont tioce_common->ce_pcibus.bs_persist_segment, tioce_common->ce_pcibus.bs_persist_busnum); + /* + * identify closest nasid for memory allocations + */ + + my_nasid = NASID_GET(tioce_common->ce_pcibus.bs_base); + my_cnode = nasid_to_cnodeid(my_nasid); + + if (sn_hwperf_get_nearest_node(my_cnode, &mem_cnode, NULL) < 0) { + printk(KERN_WARNING "tioce_bus_fixup: failed to find " + "closest node with MEM to TIO node %d\n", my_cnode); + mem_cnode = (cnodeid_t)-1; /* use any node */ + } + + controller->node = mem_cnode; + return tioce_common; } diff --git a/include/asm-ia64/sn/addrs.h b/include/asm-ia64/sn/addrs.h index 2c32e4b77b54..1d9efe541662 100644 --- a/include/asm-ia64/sn/addrs.h +++ b/include/asm-ia64/sn/addrs.h @@ -283,5 +283,13 @@ #define REMOTE_HUB_L(n, a) HUB_L(REMOTE_HUB_ADDR((n), (a))) #define REMOTE_HUB_S(n, a, d) HUB_S(REMOTE_HUB_ADDR((n), (a)), (d)) +/* + * Coretalk address breakdown + */ +#define CTALK_NASID_SHFT 40 +#define CTALK_NASID_MASK (0x3FFFULL << CTALK_NASID_SHFT) +#define CTALK_CID_SHFT 38 +#define CTALK_CID_MASK (0x3ULL << CTALK_CID_SHFT) +#define CTALK_NODE_OFFSET 0x3FFFFFFFFF #endif /* _ASM_IA64_SN_ADDRS_H */ diff --git a/include/asm-ia64/sn/tioce.h b/include/asm-ia64/sn/tioce.h index d4c990712eac..893468e1b41b 100644 --- a/include/asm-ia64/sn/tioce.h +++ b/include/asm-ia64/sn/tioce.h @@ -11,7 +11,7 @@ /* CE ASIC part & mfgr information */ #define TIOCE_PART_NUM 0xCE00 -#define TIOCE_MFGR_NUM 0x36 +#define TIOCE_SRC_ID 0x01 #define TIOCE_REV_A 0x1 /* CE Virtual PPB Vendor/Device IDs */ @@ -20,7 +20,7 @@ /* CE Host Bridge Vendor/Device IDs */ #define CE_HOST_BRIDGE_VENDOR_ID 0x10a9 -#define CE_HOST_BRIDGE_DEVICE_ID 0x4003 +#define CE_HOST_BRIDGE_DEVICE_ID 0x4001 #define TIOCE_NUM_M40_ATES 4096 @@ -463,6 +463,25 @@ typedef volatile struct tioce { u64 ce_end_of_struct; /* 0x044400 */ } tioce_t; +/* ce_lsiX_gb_cfg1 register bit masks & shifts */ +#define CE_LSI_GB_CFG1_RXL0S_THS_SHFT 0 +#define CE_LSI_GB_CFG1_RXL0S_THS_MASK (0xffULL << 0) +#define CE_LSI_GB_CFG1_RXL0S_SMP_SHFT 8 +#define CE_LSI_GB_CFG1_RXL0S_SMP_MASK (0xfULL << 8); +#define CE_LSI_GB_CFG1_RXL0S_ADJ_SHFT 12 +#define CE_LSI_GB_CFG1_RXL0S_ADJ_MASK (0x7ULL << 12) +#define CE_LSI_GB_CFG1_RXL0S_FLT_SHFT 15 +#define CE_LSI_GB_CFG1_RXL0S_FLT_MASK (0x1ULL << 15) +#define CE_LSI_GB_CFG1_LPBK_SEL_SHFT 16 +#define CE_LSI_GB_CFG1_LPBK_SEL_MASK (0x3ULL << 16) +#define CE_LSI_GB_CFG1_LPBK_EN_SHFT 18 +#define CE_LSI_GB_CFG1_LPBK_EN_MASK (0x1ULL << 18) +#define CE_LSI_GB_CFG1_RVRS_LB_SHFT 19 +#define CE_LSI_GB_CFG1_RVRS_LB_MASK (0x1ULL << 19) +#define CE_LSI_GB_CFG1_RVRS_CLK_SHFT 20 +#define CE_LSI_GB_CFG1_RVRS_CLK_MASK (0x3ULL << 20) +#define CE_LSI_GB_CFG1_SLF_TS_SHFT 24 +#define CE_LSI_GB_CFG1_SLF_TS_MASK (0xfULL << 24) /* ce_adm_int_mask/ce_adm_int_status register bit defines */ #define CE_ADM_INT_CE_ERROR_SHFT 0 @@ -592,6 +611,11 @@ typedef volatile struct tioce { #define CE_URE_RD_MRG_ENABLE (0x1ULL << 0) #define CE_URE_WRT_MRG_ENABLE1 (0x1ULL << 4) #define CE_URE_WRT_MRG_ENABLE2 (0x1ULL << 5) +#define CE_URE_WRT_MRG_TIMER_SHFT 12 +#define CE_URE_WRT_MRG_TIMER_MASK (0x7FFULL << CE_URE_WRT_MRG_TIMER_SHFT) +#define CE_URE_WRT_MRG_TIMER(x) (((u64)(x) << \ + CE_URE_WRT_MRG_TIMER_SHFT) & \ + CE_URE_WRT_MRG_TIMER_MASK) #define CE_URE_RSPQ_BYPASS_DISABLE (0x1ULL << 24) #define CE_URE_UPS_DAT1_PAR_DISABLE (0x1ULL << 32) #define CE_URE_UPS_HDR1_PAR_DISABLE (0x1ULL << 33) @@ -653,8 +677,12 @@ typedef volatile struct tioce { #define CE_URE_SI (0x1ULL << 0) #define CE_URE_ELAL_SHFT 4 #define CE_URE_ELAL_MASK (0x7ULL << CE_URE_ELAL_SHFT) +#define CE_URE_ELAL_SET(n) (((u64)(n) << CE_URE_ELAL_SHFT) & \ + CE_URE_ELAL_MASK) #define CE_URE_ELAL1_SHFT 8 #define CE_URE_ELAL1_MASK (0x7ULL << CE_URE_ELAL1_SHFT) +#define CE_URE_ELAL1_SET(n) (((u64)(n) << CE_URE_ELAL1_SHFT) & \ + CE_URE_ELAL1_MASK) #define CE_URE_SCC (0x1ULL << 12) #define CE_URE_PN1_SHFT 16 #define CE_URE_PN1_MASK (0xFFULL << CE_URE_PN1_SHFT) @@ -675,8 +703,12 @@ typedef volatile struct tioce { #define CE_URE_HPC (0x1ULL << 6) #define CE_URE_SPLV_SHFT 7 #define CE_URE_SPLV_MASK (0xFFULL << CE_URE_SPLV_SHFT) +#define CE_URE_SPLV_SET(n) (((u64)(n) << CE_URE_SPLV_SHFT) & \ + CE_URE_SPLV_MASK) #define CE_URE_SPLS_SHFT 15 #define CE_URE_SPLS_MASK (0x3ULL << CE_URE_SPLS_SHFT) +#define CE_URE_SPLS_SET(n) (((u64)(n) << CE_URE_SPLS_SHFT) & \ + CE_URE_SPLS_MASK) #define CE_URE_PSN1_SHFT 19 #define CE_URE_PSN1_MASK (0x1FFFULL << CE_URE_PSN1_SHFT) #define CE_URE_PSN2_SHFT 32 -- cgit v1.2.3 From e08e6c521355cd33e647b2f739885bc3050eead6 Mon Sep 17 00:00:00 2001 From: Brent Casavant Date: Thu, 26 Jan 2006 15:55:52 -0800 Subject: [IA64] hooks to wait for mmio writes to drain when migrating processes On SN2, MMIO writes which are issued from separate processors are not guaranteed to arrive in any particular order at the IO hardware. When performing such writes from the kernel this is not a problem, as a kernel thread will not migrate to another CPU during execution, and mmiowb() calls can guarantee write ordering when control of the IO resource is allowed to move between threads. However, when MMIO writes can be performed from user space (e.g. DRM) there are no such guarantees and mechanisms, as the process may context-switch at any time, and may migrate to a different CPU as part of the switch. For such programs/hardware to operate correctly, it is required that the MMIO writes from the old CPU be accepted by the IO hardware before subsequent writes from the new CPU can be issued. The following patch implements this behavior on SN2 by waiting for a Shub register to indicate that these writes have been accepted. This is placed in the context switch-in path, and only performs the wait when the newly scheduled task changes CPUs. Signed-off-by: Prarit Bhargava Signed-off-by: Brent Casavant --- arch/ia64/sn/kernel/setup.c | 6 ++++-- arch/ia64/sn/kernel/sn2/sn2_smp.c | 23 ++++++++++++++++++++++- include/asm-ia64/machvec.h | 13 +++++++++++++ include/asm-ia64/machvec_sn2.h | 4 +++- include/asm-ia64/processor.h | 3 ++- include/asm-ia64/system.h | 7 +++++++ include/asm-ia64/thread_info.h | 1 + 7 files changed, 52 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index e510dce9971f..f1c1338b10b4 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1999,2001-2006 Silicon Graphics, Inc. All rights reserved. */ #include @@ -496,6 +496,7 @@ void __init sn_setup(char **cmdline_p) * for sn. */ pm_power_off = ia64_sn_power_down; + current->thread.flags |= IA64_THREAD_MIGRATION; } /** @@ -654,7 +655,8 @@ void __init sn_cpu_init(void) SH2_PIO_WRITE_STATUS_1, SH2_PIO_WRITE_STATUS_3}; u64 *pio; pio = is_shub1() ? pio1 : pio2; - pda->pio_write_status_addr = (volatile unsigned long *) LOCAL_MMR_ADDR(pio[slice]); + pda->pio_write_status_addr = + (volatile unsigned long *)GLOBAL_MMR_ADDR(nasid, pio[slice]); pda->pio_write_status_val = is_shub1() ? SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK : 0; } diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c index 471bbaa65d1b..1b33fd5e4e3a 100644 --- a/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2006 Silicon Graphics, Inc. All rights reserved. */ #include @@ -169,6 +169,27 @@ static inline unsigned long wait_piowc(void) return ws; } +/** + * sn_migrate - SN-specific task migration actions + * @task: Task being migrated to new CPU + * + * SN2 PIO writes from separate CPUs are not guaranteed to arrive in order. + * Context switching user threads which have memory-mapped MMIO may cause + * PIOs to issue from seperate CPUs, thus the PIO writes must be drained + * from the previous CPU's Shub before execution resumes on the new CPU. + */ +void sn_migrate(struct task_struct *task) +{ + pda_t *last_pda = pdacpu(task_thread_info(task)->last_cpu); + volatile unsigned long *adr = last_pda->pio_write_status_addr; + unsigned long val = last_pda->pio_write_status_val; + + /* Drain PIO writes from old CPU's Shub */ + while (unlikely((*adr & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK) + != val)) + cpu_relax(); +} + void sn_tlb_migrate_finish(struct mm_struct *mm) { if (mm == current->mm) diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h index ca5ea994d688..c3e4ed8a3e17 100644 --- a/include/asm-ia64/machvec.h +++ b/include/asm-ia64/machvec.h @@ -20,6 +20,7 @@ struct scatterlist; struct page; struct mm_struct; struct pci_bus; +struct task_struct; typedef void ia64_mv_setup_t (char **); typedef void ia64_mv_cpu_init_t (void); @@ -34,6 +35,7 @@ typedef int ia64_mv_pci_legacy_read_t (struct pci_bus *, u16 port, u32 *val, u8 size); typedef int ia64_mv_pci_legacy_write_t (struct pci_bus *, u16 port, u32 val, u8 size); +typedef void ia64_mv_migrate_t(struct task_struct * task); /* DMA-mapping interface: */ typedef void ia64_mv_dma_init (void); @@ -85,6 +87,11 @@ machvec_noop_mm (struct mm_struct *mm) { } +static inline void +machvec_noop_task (struct task_struct *task) +{ +} + extern void machvec_setup (char **); extern void machvec_timer_interrupt (int, void *, struct pt_regs *); extern void machvec_dma_sync_single (struct device *, dma_addr_t, size_t, int); @@ -146,6 +153,7 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *); # define platform_readw_relaxed ia64_mv.readw_relaxed # define platform_readl_relaxed ia64_mv.readl_relaxed # define platform_readq_relaxed ia64_mv.readq_relaxed +# define platform_migrate ia64_mv.migrate # endif /* __attribute__((__aligned__(16))) is required to make size of the @@ -194,6 +202,7 @@ struct ia64_machine_vector { ia64_mv_readw_relaxed_t *readw_relaxed; ia64_mv_readl_relaxed_t *readl_relaxed; ia64_mv_readq_relaxed_t *readq_relaxed; + ia64_mv_migrate_t *migrate; } __attribute__((__aligned__(16))); /* align attrib? see above comment */ #define MACHVEC_INIT(name) \ @@ -238,6 +247,7 @@ struct ia64_machine_vector { platform_readw_relaxed, \ platform_readl_relaxed, \ platform_readq_relaxed, \ + platform_migrate, \ } extern struct ia64_machine_vector ia64_mv; @@ -386,5 +396,8 @@ extern ia64_mv_dma_supported swiotlb_dma_supported; #ifndef platform_readq_relaxed # define platform_readq_relaxed __ia64_readq_relaxed #endif +#ifndef platform_migrate +# define platform_migrate machvec_noop_task +#endif #endif /* _ASM_IA64_MACHVEC_H */ diff --git a/include/asm-ia64/machvec_sn2.h b/include/asm-ia64/machvec_sn2.h index e1b6cd63f49e..6f0021bb3874 100644 --- a/include/asm-ia64/machvec_sn2.h +++ b/include/asm-ia64/machvec_sn2.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2003 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2002-2003,2006 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License @@ -71,6 +71,7 @@ extern ia64_mv_dma_sync_single_for_device sn_dma_sync_single_for_device; extern ia64_mv_dma_sync_sg_for_device sn_dma_sync_sg_for_device; extern ia64_mv_dma_mapping_error sn_dma_mapping_error; extern ia64_mv_dma_supported sn_dma_supported; +extern ia64_mv_migrate_t sn_migrate; /* * This stuff has dual use! @@ -120,6 +121,7 @@ extern ia64_mv_dma_supported sn_dma_supported; #define platform_dma_sync_sg_for_device sn_dma_sync_sg_for_device #define platform_dma_mapping_error sn_dma_mapping_error #define platform_dma_supported sn_dma_supported +#define platform_migrate sn_migrate #include diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h index 09b99029ac1a..29d5574d4375 100644 --- a/include/asm-ia64/processor.h +++ b/include/asm-ia64/processor.h @@ -50,7 +50,8 @@ #define IA64_THREAD_PM_VALID (__IA64_UL(1) << 2) /* performance registers valid? */ #define IA64_THREAD_UAC_NOPRINT (__IA64_UL(1) << 3) /* don't log unaligned accesses */ #define IA64_THREAD_UAC_SIGBUS (__IA64_UL(1) << 4) /* generate SIGBUS on unaligned acc. */ - /* bit 5 is currently unused */ +#define IA64_THREAD_MIGRATION (__IA64_UL(1) << 5) /* require migration + sync at ctx sw */ #define IA64_THREAD_FPEMU_NOPRINT (__IA64_UL(1) << 6) /* don't log any fpswa faults */ #define IA64_THREAD_FPEMU_SIGFPE (__IA64_UL(1) << 7) /* send a SIGFPE for fpswa faults */ diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h index 80c5a234e259..99b6f307e94b 100644 --- a/include/asm-ia64/system.h +++ b/include/asm-ia64/system.h @@ -244,6 +244,13 @@ extern void ia64_load_extra (struct task_struct *task); __ia64_save_fpu((prev)->thread.fph); \ } \ __switch_to(prev, next, last); \ + /* "next" in old context is "current" in new context */ \ + if (unlikely((current->thread.flags & IA64_THREAD_MIGRATION) && \ + (task_cpu(current) != \ + task_thread_info(current)->last_cpu))) { \ + platform_migrate(current); \ + task_thread_info(current)->last_cpu = task_cpu(current); \ + } \ } while (0) #else # define switch_to(prev,next,last) __switch_to(prev, next, last) diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h index 1d6518fe1f02..81641a6905d1 100644 --- a/include/asm-ia64/thread_info.h +++ b/include/asm-ia64/thread_info.h @@ -26,6 +26,7 @@ struct thread_info { struct exec_domain *exec_domain;/* execution domain */ __u32 flags; /* thread_info flags (see TIF_*) */ __u32 cpu; /* current CPU */ + __u32 last_cpu; /* Last CPU thread ran on */ mm_segment_t addr_limit; /* user-level address space limit */ int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */ struct restart_block restart_block; -- cgit v1.2.3 From 77853bf2b48e34449e826a9ef4df5ea0dbe947f4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 23 Jan 2006 13:09:36 +0900 Subject: [PATCH] libata: make the owner of a qc responsible for freeing it qc used to be freed automatically on command completion. However, as a qc can carry information about its completion status, it can be useful to its owner/issuer after command completion. This patch makes freeing qc responsibility of its owner. This simplifies ata_exec_internal() and makes command turn-around for atapi request sensing less hackish. This change was originally suggested by Jeff Garzik. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 47 +++++++++++++--------------------------------- drivers/scsi/libata-scsi.c | 14 +++++++------- include/linux/libata.h | 2 +- 3 files changed, 21 insertions(+), 42 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 0e4932362949..15df633521d0 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1072,24 +1072,12 @@ static unsigned int ata_pio_modes(const struct ata_device *adev) timing API will get this right anyway */ } -struct ata_exec_internal_arg { - unsigned int err_mask; - struct ata_taskfile *tf; - struct completion *waiting; -}; - -int ata_qc_complete_internal(struct ata_queued_cmd *qc) +void ata_qc_complete_internal(struct ata_queued_cmd *qc) { - struct ata_exec_internal_arg *arg = qc->private_data; - struct completion *waiting = arg->waiting; + struct completion *waiting = qc->private_data; - if (!(qc->err_mask & ~AC_ERR_DEV)) - qc->ap->ops->tf_read(qc->ap, arg->tf); - arg->err_mask = qc->err_mask; - arg->waiting = NULL; + qc->ap->ops->tf_read(qc->ap, &qc->tf); complete(waiting); - - return 0; } /** @@ -1120,7 +1108,7 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, struct ata_queued_cmd *qc; DECLARE_COMPLETION(wait); unsigned long flags; - struct ata_exec_internal_arg arg; + unsigned int err_mask; spin_lock_irqsave(&ap->host_set->lock, flags); @@ -1134,9 +1122,7 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, qc->nsect = buflen / ATA_SECT_SIZE; } - arg.waiting = &wait; - arg.tf = tf; - qc->private_data = &arg; + qc->private_data = &wait; qc->complete_fn = ata_qc_complete_internal; if (ata_qc_issue(qc)) @@ -1153,7 +1139,7 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, * before the caller cleans up, it will result in a * spurious interrupt. We can live with that. */ - if (arg.waiting) { + if (qc->flags & ATA_QCFLAG_ACTIVE) { qc->err_mask = AC_ERR_OTHER; ata_qc_complete(qc); printk(KERN_WARNING "ata%u: qc timeout (cmd 0x%x)\n", @@ -1163,7 +1149,12 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, spin_unlock_irqrestore(&ap->host_set->lock, flags); } - return arg.err_mask; + *tf = qc->tf; + err_mask = qc->err_mask; + + ata_qc_free(qc); + + return err_mask; issue_fail: ata_qc_free(qc); @@ -3633,8 +3624,6 @@ void ata_qc_free(struct ata_queued_cmd *qc) void ata_qc_complete(struct ata_queued_cmd *qc) { - int rc; - assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */ assert(qc->flags & ATA_QCFLAG_ACTIVE); @@ -3648,17 +3637,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc) qc->flags &= ~ATA_QCFLAG_ACTIVE; /* call completion callback */ - rc = qc->complete_fn(qc); - - /* if callback indicates not to complete command (non-zero), - * return immediately - */ - if (rc != 0) - return; - - ata_qc_free(qc); - - VPRINTK("EXIT\n"); + qc->complete_fn(qc); } static inline int ata_should_dma_map(struct ata_queued_cmd *qc) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 0e65bfe92e6f..ce3fe928a386 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1219,7 +1219,7 @@ nothing_to_do: return 1; } -static int ata_scsi_qc_complete(struct ata_queued_cmd *qc) +static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) { struct scsi_cmnd *cmd = qc->scsicmd; u8 *cdb = cmd->cmnd; @@ -1256,7 +1256,7 @@ static int ata_scsi_qc_complete(struct ata_queued_cmd *qc) qc->scsidone(cmd); - return 0; + ata_qc_free(qc); } /** @@ -1982,7 +1982,7 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 done(cmd); } -static int atapi_sense_complete(struct ata_queued_cmd *qc) +static void atapi_sense_complete(struct ata_queued_cmd *qc) { if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) /* FIXME: not quite right; we don't want the @@ -1993,7 +1993,7 @@ static int atapi_sense_complete(struct ata_queued_cmd *qc) ata_gen_ata_desc_sense(qc); qc->scsidone(qc->scsicmd); - return 0; + ata_qc_free(qc); } /* is it pointless to prefer PIO for "safety reasons"? */ @@ -2050,7 +2050,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) DPRINTK("EXIT\n"); } -static int atapi_qc_complete(struct ata_queued_cmd *qc) +static void atapi_qc_complete(struct ata_queued_cmd *qc) { struct scsi_cmnd *cmd = qc->scsicmd; unsigned int err_mask = qc->err_mask; @@ -2060,7 +2060,7 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc) if (unlikely(err_mask & AC_ERR_DEV)) { cmd->result = SAM_STAT_CHECK_CONDITION; atapi_request_sense(qc); - return 1; + return; } else if (unlikely(err_mask)) @@ -2100,7 +2100,7 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc) } qc->scsidone(cmd); - return 0; + ata_qc_free(qc); } /** * atapi_xlat - Initialize PACKET taskfile diff --git a/include/linux/libata.h b/include/linux/libata.h index 46ccea215892..d58b659cf3f5 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -235,7 +235,7 @@ struct ata_port; struct ata_queued_cmd; /* typedefs */ -typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc); +typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc); struct ata_ioports { unsigned long cmd_addr; -- cgit v1.2.3 From 11a56d2439259892319df81cf1582687d7e7fde5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 23 Jan 2006 13:09:36 +0900 Subject: [PATCH] libata: add detailed AC_ERR_* flags Add detailed AC_ERR_* flags and use them. Long-term goal is to describe all errors with err_mask and tf combination (tf for failed sector information, etc...). After proper error diagnosis is implemented, sense data should also be generated from err_mask instead of directly from hardware tf registers as it is currently. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 2 +- drivers/scsi/libata-core.c | 12 ++++++------ drivers/scsi/sata_mv.c | 2 +- drivers/scsi/sata_sil24.c | 2 +- include/linux/libata.h | 15 ++++++++++----- 5 files changed, 19 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index a168b525d079..bb3686ae1885 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -680,7 +680,7 @@ static void ahci_eng_timeout(struct ata_port *ap) * not being called from the SCSI EH. */ qc->scsidone = scsi_finish_command; - qc->err_mask |= AC_ERR_OTHER; + qc->err_mask |= AC_ERR_TIMEOUT; ata_qc_complete(qc); } diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 43a23286d6fe..f5519f01491c 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1142,7 +1142,7 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, * spurious interrupt. We can live with that. */ if (qc->flags & ATA_QCFLAG_ACTIVE) { - qc->err_mask = AC_ERR_OTHER; + qc->err_mask = AC_ERR_TIMEOUT; ata_qc_complete(qc); printk(KERN_WARNING "ata%u: qc timeout (cmd 0x%x)\n", ap->id, command); @@ -2917,7 +2917,7 @@ static unsigned long ata_pio_poll(struct ata_port *ap) status = ata_chk_status(ap); if (status & ATA_BUSY) { if (time_after(jiffies, ap->pio_task_timeout)) { - qc->err_mask |= AC_ERR_ATA_BUS; + qc->err_mask |= AC_ERR_TIMEOUT; ap->hsm_task_state = HSM_ST_TMOUT; return 0; } @@ -3295,7 +3295,7 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc) err_out: printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n", ap->id, dev->devno); - qc->err_mask |= AC_ERR_ATA_BUS; + qc->err_mask |= AC_ERR_HSM; ap->hsm_task_state = HSM_ST_ERR; } @@ -3353,7 +3353,7 @@ static void ata_pio_block(struct ata_port *ap) } else { /* handle BSY=0, DRQ=0 as error */ if ((status & ATA_DRQ) == 0) { - qc->err_mask |= AC_ERR_ATA_BUS; + qc->err_mask |= AC_ERR_HSM; ap->hsm_task_state = HSM_ST_ERR; return; } @@ -4159,14 +4159,14 @@ static void atapi_packet_task(void *_data) /* sleep-wait for BSY to clear */ DPRINTK("busy wait\n"); if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) { - qc->err_mask |= AC_ERR_ATA_BUS; + qc->err_mask |= AC_ERR_TIMEOUT; goto err_out; } /* make sure DRQ is set */ status = ata_chk_status(ap); if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) { - qc->err_mask |= AC_ERR_ATA_BUS; + qc->err_mask |= AC_ERR_HSM; goto err_out; } diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index cd54244058b5..89bcd85fa58c 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -1866,7 +1866,7 @@ static void mv_eng_timeout(struct ata_port *ap) */ spin_lock_irqsave(&ap->host_set->lock, flags); qc->scsidone = scsi_finish_command; - qc->err_mask |= AC_ERR_OTHER; + qc->err_mask |= AC_ERR_TIMEOUT; ata_qc_complete(qc); spin_unlock_irqrestore(&ap->host_set->lock, flags); } diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 923130185a9e..fb59012b9fbe 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -653,7 +653,7 @@ static void sil24_eng_timeout(struct ata_port *ap) */ printk(KERN_ERR "ata%u: command timeout\n", ap->id); qc->scsidone = scsi_finish_command; - qc->err_mask |= AC_ERR_OTHER; + qc->err_mask |= AC_ERR_TIMEOUT; ata_qc_complete(qc); sil24_reset_controller(ap); diff --git a/include/linux/libata.h b/include/linux/libata.h index d58b659cf3f5..8ff3a7f6f63c 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -222,10 +222,15 @@ enum hsm_task_states { }; enum ata_completion_errors { - AC_ERR_OTHER = (1 << 0), - AC_ERR_DEV = (1 << 1), - AC_ERR_ATA_BUS = (1 << 2), - AC_ERR_HOST_BUS = (1 << 3), + AC_ERR_DEV = (1 << 0), /* device reported error */ + AC_ERR_HSM = (1 << 1), /* host state machine violation */ + AC_ERR_TIMEOUT = (1 << 2), /* timeout */ + AC_ERR_MEDIA = (1 << 3), /* media error */ + AC_ERR_ATA_BUS = (1 << 4), /* ATA bus error */ + AC_ERR_HOST_BUS = (1 << 5), /* host bus error */ + AC_ERR_SYSTEM = (1 << 6), /* system error */ + AC_ERR_INVALID = (1 << 7), /* invalid argument */ + AC_ERR_OTHER = (1 << 8), /* unknown */ }; /* forward declarations */ @@ -833,7 +838,7 @@ static inline int ata_try_flush_cache(const struct ata_device *dev) static inline unsigned int ac_err_mask(u8 status) { if (status & ATA_BUSY) - return AC_ERR_ATA_BUS; + return AC_ERR_HSM; if (status & (ATA_ERR | ATA_DF)) return AC_ERR_DEV; return 0; -- cgit v1.2.3 From 9a3d9eb0177eb10500d49cd283b35576082a522d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 23 Jan 2006 13:09:36 +0900 Subject: [PATCH] libata: return AC_ERR_* from issue functions Return AC_ERR_* mask from issue fuctions instead of 0/-1. This enables things like failing a qc with AC_ERR_HSM when the device doesn't set DRDY when the qc is about to be issued. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 4 ++-- drivers/scsi/libata-core.c | 17 ++++++++--------- drivers/scsi/libata-scsi.c | 10 ++++------ drivers/scsi/libata.h | 2 +- drivers/scsi/pdc_adma.c | 4 ++-- drivers/scsi/sata_mv.c | 4 ++-- drivers/scsi/sata_promise.c | 4 ++-- drivers/scsi/sata_qstor.c | 4 ++-- drivers/scsi/sata_sil24.c | 4 ++-- drivers/scsi/sata_sx4.c | 4 ++-- include/linux/libata.h | 4 ++-- 11 files changed, 29 insertions(+), 32 deletions(-) (limited to 'include') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index bb3686ae1885..0f6e4dd22901 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -184,7 +184,7 @@ struct ahci_port_priv { static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg); static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); -static int ahci_qc_issue(struct ata_queued_cmd *qc); +static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc); static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs); static void ahci_phy_reset(struct ata_port *ap); static void ahci_irq_clear(struct ata_port *ap); @@ -800,7 +800,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs * return IRQ_RETVAL(handled); } -static int ahci_qc_issue(struct ata_queued_cmd *qc) +static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f5519f01491c..b29bf0dc948a 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1125,10 +1125,9 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, qc->private_data = &wait; qc->complete_fn = ata_qc_complete_internal; - if (ata_qc_issue(qc)) { - qc->err_mask = AC_ERR_OTHER; + qc->err_mask = ata_qc_issue(qc); + if (qc->err_mask) ata_qc_complete(qc); - } spin_unlock_irqrestore(&ap->host_set->lock, flags); @@ -3674,10 +3673,10 @@ static inline int ata_should_dma_map(struct ata_queued_cmd *qc) * spin_lock_irqsave(host_set lock) * * RETURNS: - * Zero on success, negative on error. + * Zero on success, AC_ERR_* mask on failure */ -int ata_qc_issue(struct ata_queued_cmd *qc) +unsigned int ata_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; @@ -3702,7 +3701,7 @@ int ata_qc_issue(struct ata_queued_cmd *qc) sg_err: qc->flags &= ~ATA_QCFLAG_DMAMAP; - return -1; + return AC_ERR_SYSTEM; } @@ -3721,10 +3720,10 @@ sg_err: * spin_lock_irqsave(host_set lock) * * RETURNS: - * Zero on success, negative on error. + * Zero on success, AC_ERR_* mask on failure */ -int ata_qc_issue_prot(struct ata_queued_cmd *qc) +unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; @@ -3769,7 +3768,7 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc) default: WARN_ON(1); - return -1; + return AC_ERR_SYSTEM; } return 0; diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index c496309f691a..95e3c278dd43 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1322,10 +1322,9 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, goto early_finish; /* select device, send command to hardware */ - if (ata_qc_issue(qc)) { - qc->err_mask |= AC_ERR_OTHER; + qc->err_mask = ata_qc_issue(qc); + if (qc->err_mask) ata_qc_complete(qc); - } VPRINTK("EXIT\n"); return; @@ -2044,10 +2043,9 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) qc->complete_fn = atapi_sense_complete; - if (ata_qc_issue(qc)) { - qc->err_mask |= AC_ERR_OTHER; + qc->err_mask = ata_qc_issue(qc); + if (qc->err_mask) ata_qc_complete(qc); - } DPRINTK("EXIT\n"); } diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index e03ce48b7b4b..9d76923a2253 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -45,7 +45,7 @@ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, struct ata_device *dev); extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); extern void ata_qc_free(struct ata_queued_cmd *qc); -extern int ata_qc_issue(struct ata_queued_cmd *qc); +extern unsigned int ata_qc_issue(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); extern void ata_dev_select(struct ata_port *ap, unsigned int device, unsigned int wait, unsigned int can_sleep); diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index e8df0c9ec1e6..3a6bf58dc37b 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -131,7 +131,7 @@ static void adma_host_stop(struct ata_host_set *host_set); static void adma_port_stop(struct ata_port *ap); static void adma_phy_reset(struct ata_port *ap); static void adma_qc_prep(struct ata_queued_cmd *qc); -static int adma_qc_issue(struct ata_queued_cmd *qc); +static unsigned int adma_qc_issue(struct ata_queued_cmd *qc); static int adma_check_atapi_dma(struct ata_queued_cmd *qc); static void adma_bmdma_stop(struct ata_queued_cmd *qc); static u8 adma_bmdma_status(struct ata_port *ap); @@ -419,7 +419,7 @@ static inline void adma_packet_start(struct ata_queued_cmd *qc) writew(aPIOMD4 | aGO, chan + ADMA_CONTROL); } -static int adma_qc_issue(struct ata_queued_cmd *qc) +static unsigned int adma_qc_issue(struct ata_queued_cmd *qc) { struct adma_port_priv *pp = qc->ap->private_data; diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 89bcd85fa58c..281223a0e45f 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -328,7 +328,7 @@ static void mv_host_stop(struct ata_host_set *host_set); static int mv_port_start(struct ata_port *ap); static void mv_port_stop(struct ata_port *ap); static void mv_qc_prep(struct ata_queued_cmd *qc); -static int mv_qc_issue(struct ata_queued_cmd *qc); +static unsigned int mv_qc_issue(struct ata_queued_cmd *qc); static irqreturn_t mv_interrupt(int irq, void *dev_instance, struct pt_regs *regs); static void mv_eng_timeout(struct ata_port *ap); @@ -1040,7 +1040,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) * LOCKING: * Inherited from caller. */ -static int mv_qc_issue(struct ata_queued_cmd *qc) +static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) { void __iomem *port_mmio = mv_ap_base(qc->ap); struct mv_port_priv *pp = qc->ap->private_data; diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index b0b0a69b3563..bac36d5b7c3e 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -95,7 +95,7 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc); static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf); static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf); static void pdc_irq_clear(struct ata_port *ap); -static int pdc_qc_issue_prot(struct ata_queued_cmd *qc); +static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc); static struct scsi_host_template pdc_ata_sht = { @@ -544,7 +544,7 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc) readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */ } -static int pdc_qc_issue_prot(struct ata_queued_cmd *qc) +static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc) { switch (qc->tf.protocol) { case ATA_PROT_DMA: diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index de05e2883f9c..2afbeb77f6fe 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -120,7 +120,7 @@ static void qs_host_stop(struct ata_host_set *host_set); static void qs_port_stop(struct ata_port *ap); static void qs_phy_reset(struct ata_port *ap); static void qs_qc_prep(struct ata_queued_cmd *qc); -static int qs_qc_issue(struct ata_queued_cmd *qc); +static unsigned int qs_qc_issue(struct ata_queued_cmd *qc); static int qs_check_atapi_dma(struct ata_queued_cmd *qc); static void qs_bmdma_stop(struct ata_queued_cmd *qc); static u8 qs_bmdma_status(struct ata_port *ap); @@ -352,7 +352,7 @@ static inline void qs_packet_start(struct ata_queued_cmd *qc) readl(chan + QS_CCT_CFF); /* flush */ } -static int qs_qc_issue(struct ata_queued_cmd *qc) +static unsigned int qs_qc_issue(struct ata_queued_cmd *qc) { struct qs_port_priv *pp = qc->ap->private_data; diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index fb59012b9fbe..5a7a7b1d4add 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -251,7 +251,7 @@ static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf); static void sil24_phy_reset(struct ata_port *ap); static void sil24_qc_prep(struct ata_queued_cmd *qc); -static int sil24_qc_issue(struct ata_queued_cmd *qc); +static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); static void sil24_irq_clear(struct ata_port *ap); static void sil24_eng_timeout(struct ata_port *ap); static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs); @@ -557,7 +557,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) sil24_fill_sg(qc, sge); } -static int sil24_qc_issue(struct ata_queued_cmd *qc) +static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index bc87c16c80d2..3175c6bb4fec 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -174,7 +174,7 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource, u32 offset, u32 size); static void pdc20621_irq_clear(struct ata_port *ap); -static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc); +static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc); static struct scsi_host_template pdc_sata_sht = { @@ -678,7 +678,7 @@ static void pdc20621_packet_start(struct ata_queued_cmd *qc) } } -static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc) +static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc) { switch (qc->tf.protocol) { case ATA_PROT_DMA: diff --git a/include/linux/libata.h b/include/linux/libata.h index 8ff3a7f6f63c..b1ea2f98bfbb 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -427,7 +427,7 @@ struct ata_port_operations { void (*bmdma_start) (struct ata_queued_cmd *qc); void (*qc_prep) (struct ata_queued_cmd *qc); - int (*qc_issue) (struct ata_queued_cmd *qc); + unsigned int (*qc_issue) (struct ata_queued_cmd *qc); void (*eng_timeout) (struct ata_port *ap); @@ -515,7 +515,7 @@ extern void ata_port_stop (struct ata_port *ap); extern void ata_host_stop (struct ata_host_set *host_set); extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs); extern void ata_qc_prep(struct ata_queued_cmd *qc); -extern int ata_qc_issue_prot(struct ata_queued_cmd *qc); +extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc); extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen); extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, -- cgit v1.2.3 From 041c5fc33cb7ed4fe5322585a611fb6e29a05d3a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 23 Jan 2006 13:09:36 +0900 Subject: [PATCH] SCSI: export scsi_eh_finish_cmd() and scsi_eh_flush_done_q() Export two SCSI EH command handling functions. To be used by libata EH. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/scsi_error.c | 7 ++++--- include/scsi/scsi_eh.h | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index a2333d2c7af0..6bac3d2668fa 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -584,8 +584,7 @@ static int scsi_request_sense(struct scsi_cmnd *scmd) * keep a list of pending commands for final completion, and once we * are ready to leave error handling we handle completion for real. **/ -static void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, - struct list_head *done_q) +void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q) { scmd->device->host->host_failed--; scmd->eh_eflags = 0; @@ -597,6 +596,7 @@ static void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, scsi_setup_cmd_retry(scmd); list_move_tail(&scmd->eh_entry, done_q); } +EXPORT_SYMBOL(scsi_eh_finish_cmd); /** * scsi_eh_get_sense - Get device sense data. @@ -1425,7 +1425,7 @@ static void scsi_eh_ready_devs(struct Scsi_Host *shost, * @done_q: list_head of processed commands. * **/ -static void scsi_eh_flush_done_q(struct list_head *done_q) +void scsi_eh_flush_done_q(struct list_head *done_q) { struct scsi_cmnd *scmd, *next; @@ -1454,6 +1454,7 @@ static void scsi_eh_flush_done_q(struct list_head *done_q) } } } +EXPORT_SYMBOL(scsi_eh_flush_done_q); /** * scsi_unjam_host - Attempt to fix a host which has a cmd that failed. diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index fabd879c2f2e..d160880b2a87 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -35,6 +35,9 @@ static inline int scsi_sense_valid(struct scsi_sense_hdr *sshdr) } +extern void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, + struct list_head *done_q); +extern void scsi_eh_flush_done_q(struct list_head *done_q); extern void scsi_report_bus_reset(struct Scsi_Host *, int); extern void scsi_report_device_reset(struct Scsi_Host *, int, int); extern int scsi_block_when_processing_errors(struct scsi_device *); -- cgit v1.2.3 From a72ec4ce6d3ae92e76baf5b2c65cc26e5e775e83 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 23 Jan 2006 13:09:37 +0900 Subject: [PATCH] libata: implement and apply ata_eh_qc_complete/retry() Implement ata_eh_qc_complete/retry() using scsi_eh_finish_cmd() and scsi_eh_flush_done_q(). This removes all eh scsicmd finish hacks from low level drivers. This change was first suggested by Jeff Garzik. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 12 +++------ drivers/scsi/libata-core.c | 14 ++++------- drivers/scsi/libata-scsi.c | 59 ++++++++++++++++++++++++++++++++++++++++----- drivers/scsi/sata_mv.c | 12 +-------- drivers/scsi/sata_promise.c | 12 ++------- drivers/scsi/sata_sil24.c | 10 +------- drivers/scsi/sata_sx4.c | 12 ++------- include/linux/libata.h | 3 +++ 8 files changed, 70 insertions(+), 64 deletions(-) (limited to 'include') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 0f6e4dd22901..5a6b23009897 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -672,19 +672,13 @@ static void ahci_eng_timeout(struct ata_port *ap) ap->id); } else { ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT)); - - /* hack alert! We cannot use the supplied completion - * function from inside the ->eh_strategy_handler() thread. - * libata is the only user of ->eh_strategy_handler() in - * any kernel, so the default scsi_done() assumes it is - * not being called from the SCSI EH. - */ - qc->scsidone = scsi_finish_command; qc->err_mask |= AC_ERR_TIMEOUT; - ata_qc_complete(qc); } spin_unlock_irqrestore(&host_set->lock, flags); + + if (qc) + ata_eh_qc_complete(qc); } static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index b29bf0dc948a..93ae2dcc837c 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3449,14 +3449,6 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) spin_lock_irqsave(&host_set->lock, flags); - /* hack alert! We cannot use the supplied completion - * function from inside the ->eh_strategy_handler() thread. - * libata is the only user of ->eh_strategy_handler() in - * any kernel, so the default scsi_done() assumes it is - * not being called from the SCSI EH. - */ - qc->scsidone = scsi_finish_command; - switch (qc->tf.protocol) { case ATA_PROT_DMA: @@ -3480,12 +3472,13 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) /* complete taskfile transaction */ qc->err_mask |= ac_err_mask(drv_stat); - ata_qc_complete(qc); break; } spin_unlock_irqrestore(&host_set->lock, flags); + ata_eh_qc_complete(qc); + DPRINTK("EXIT\n"); } @@ -4422,6 +4415,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, INIT_WORK(&ap->packet_task, atapi_packet_task, ap); INIT_WORK(&ap->pio_task, ata_pio_task, ap); + INIT_LIST_HEAD(&ap->eh_done_q); for (i = 0; i < ATA_MAX_DEVICES; i++) ap->device[i].devno = i; @@ -5165,6 +5159,8 @@ EXPORT_SYMBOL_GPL(ata_dev_classify); EXPORT_SYMBOL_GPL(ata_dev_id_string); EXPORT_SYMBOL_GPL(ata_dev_config); EXPORT_SYMBOL_GPL(ata_scsi_simulate); +EXPORT_SYMBOL_GPL(ata_eh_qc_complete); +EXPORT_SYMBOL_GPL(ata_eh_qc_retry); EXPORT_SYMBOL_GPL(ata_pio_need_iordy); EXPORT_SYMBOL_GPL(ata_timing_compute); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 95e3c278dd43..ab6b53349d6f 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -738,17 +738,64 @@ int ata_scsi_error(struct Scsi_Host *host) ap = (struct ata_port *) &host->hostdata[0]; ap->ops->eng_timeout(ap); - /* TODO: this is per-command; when queueing is supported - * this code will either change or move to a more - * appropriate place - */ - host->host_failed--; - INIT_LIST_HEAD(&host->eh_cmd_q); + assert(host->host_failed == 0 && list_empty(&host->eh_cmd_q)); + + scsi_eh_flush_done_q(&ap->eh_done_q); DPRINTK("EXIT\n"); return 0; } +static void ata_eh_scsidone(struct scsi_cmnd *scmd) +{ + /* nada */ +} + +static void __ata_eh_qc_complete(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct scsi_cmnd *scmd = qc->scsicmd; + unsigned long flags; + + spin_lock_irqsave(&ap->host_set->lock, flags); + qc->scsidone = ata_eh_scsidone; + ata_qc_complete(qc); + assert(!ata_tag_valid(qc->tag)); + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + scsi_eh_finish_cmd(scmd, &ap->eh_done_q); +} + +/** + * ata_eh_qc_complete - Complete an active ATA command from EH + * @qc: Command to complete + * + * Indicate to the mid and upper layers that an ATA command has + * completed. To be used from EH. + */ +void ata_eh_qc_complete(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *scmd = qc->scsicmd; + scmd->retries = scmd->allowed; + __ata_eh_qc_complete(qc); +} + +/** + * ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH + * @qc: Command to retry + * + * Indicate to the mid and upper layers that an ATA command + * should be retried. To be used from EH. + * + * SCSI midlayer limits the number of retries to scmd->allowed. + * This function might need to adjust scmd->retries for commands + * which get retried due to unrelated NCQ failures. + */ +void ata_eh_qc_retry(struct ata_queued_cmd *qc) +{ + __ata_eh_qc_complete(qc); +} + /** * ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command * @qc: Storage for translated ATA taskfile diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 281223a0e45f..d9a554ca45c7 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -1839,7 +1839,6 @@ static void mv_phy_reset(struct ata_port *ap) static void mv_eng_timeout(struct ata_port *ap) { struct ata_queued_cmd *qc; - unsigned long flags; printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id); DPRINTK("All regs @ start of eng_timeout\n"); @@ -1858,17 +1857,8 @@ static void mv_eng_timeout(struct ata_port *ap) printk(KERN_ERR "ata%u: BUG: timeout without command\n", ap->id); } else { - /* hack alert! We cannot use the supplied completion - * function from inside the ->eh_strategy_handler() thread. - * libata is the only user of ->eh_strategy_handler() in - * any kernel, so the default scsi_done() assumes it is - * not being called from the SCSI EH. - */ - spin_lock_irqsave(&ap->host_set->lock, flags); - qc->scsidone = scsi_finish_command; qc->err_mask |= AC_ERR_TIMEOUT; - ata_qc_complete(qc); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + ata_eh_qc_complete(qc); } } diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index bac36d5b7c3e..77ef646b0f92 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -400,21 +400,12 @@ static void pdc_eng_timeout(struct ata_port *ap) goto out; } - /* hack alert! We cannot use the supplied completion - * function from inside the ->eh_strategy_handler() thread. - * libata is the only user of ->eh_strategy_handler() in - * any kernel, so the default scsi_done() assumes it is - * not being called from the SCSI EH. - */ - qc->scsidone = scsi_finish_command; - switch (qc->tf.protocol) { case ATA_PROT_DMA: case ATA_PROT_NODATA: printk(KERN_ERR "ata%u: command timeout\n", ap->id); drv_stat = ata_wait_idle(ap); qc->err_mask |= __ac_err_mask(drv_stat); - ata_qc_complete(qc); break; default: @@ -424,12 +415,13 @@ static void pdc_eng_timeout(struct ata_port *ap) ap->id, qc->tf.command, drv_stat); qc->err_mask |= ac_err_mask(drv_stat); - ata_qc_complete(qc); break; } out: spin_unlock_irqrestore(&host_set->lock, flags); + if (qc) + ata_eh_qc_complete(qc); DPRINTK("EXIT\n"); } diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 5a7a7b1d4add..7222fc7ff3fc 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -644,17 +644,9 @@ static void sil24_eng_timeout(struct ata_port *ap) return; } - /* - * hack alert! We cannot use the supplied completion - * function from inside the ->eh_strategy_handler() thread. - * libata is the only user of ->eh_strategy_handler() in - * any kernel, so the default scsi_done() assumes it is - * not being called from the SCSI EH. - */ printk(KERN_ERR "ata%u: command timeout\n", ap->id); - qc->scsidone = scsi_finish_command; qc->err_mask |= AC_ERR_TIMEOUT; - ata_qc_complete(qc); + ata_eh_qc_complete(qc); sil24_reset_controller(ap); } diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index 3175c6bb4fec..9f992fbcf2e7 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -872,20 +872,11 @@ static void pdc_eng_timeout(struct ata_port *ap) goto out; } - /* hack alert! We cannot use the supplied completion - * function from inside the ->eh_strategy_handler() thread. - * libata is the only user of ->eh_strategy_handler() in - * any kernel, so the default scsi_done() assumes it is - * not being called from the SCSI EH. - */ - qc->scsidone = scsi_finish_command; - switch (qc->tf.protocol) { case ATA_PROT_DMA: case ATA_PROT_NODATA: printk(KERN_ERR "ata%u: command timeout\n", ap->id); qc->err_mask |= __ac_err_mask(ata_wait_idle(ap)); - ata_qc_complete(qc); break; default: @@ -895,12 +886,13 @@ static void pdc_eng_timeout(struct ata_port *ap) ap->id, qc->tf.command, drv_stat); qc->err_mask |= ac_err_mask(drv_stat); - ata_qc_complete(qc); break; } out: spin_unlock_irqrestore(&host_set->lock, flags); + if (qc) + ata_eh_qc_complete(qc); DPRINTK("EXIT\n"); } diff --git a/include/linux/libata.h b/include/linux/libata.h index b1ea2f98bfbb..576788de962a 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -398,6 +398,7 @@ struct ata_port { unsigned long pio_task_timeout; u32 msg_enable; + struct list_head eh_done_q; void *private_data; }; @@ -490,6 +491,8 @@ extern int ata_scsi_detect(struct scsi_host_template *sht); extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); extern int ata_scsi_error(struct Scsi_Host *host); +extern void ata_eh_qc_complete(struct ata_queued_cmd *qc); +extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); extern int ata_scsi_release(struct Scsi_Host *host); extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); extern int ata_scsi_device_resume(struct scsi_device *); -- cgit v1.2.3 From 6f8b99589524f3e759e44721376abcdf88ed8915 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 24 Jan 2006 17:05:21 +0900 Subject: [PATCH] libata: export ata_busy_sleep Export ata_busy_sleep(), to be used by low level driver reset functions. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 9 +++------ include/linux/libata.h | 3 +++ 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 71de697e2327..4336fc889acd 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -61,9 +61,6 @@ #include "libata.h" -static unsigned int ata_busy_sleep (struct ata_port *ap, - unsigned long tmout_pat, - unsigned long tmout); static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev); static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev); static void ata_set_mode(struct ata_port *ap); @@ -1960,9 +1957,8 @@ err_out: * */ -static unsigned int ata_busy_sleep (struct ata_port *ap, - unsigned long tmout_pat, - unsigned long tmout) +unsigned int ata_busy_sleep (struct ata_port *ap, + unsigned long tmout_pat, unsigned long tmout) { unsigned long timer_start, timeout; u8 status; @@ -5167,6 +5163,7 @@ EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); EXPORT_SYMBOL_GPL(ata_port_disable); EXPORT_SYMBOL_GPL(ata_ratelimit); +EXPORT_SYMBOL_GPL(ata_busy_sleep); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); EXPORT_SYMBOL_GPL(ata_scsi_error); diff --git a/include/linux/libata.h b/include/linux/libata.h index 576788de962a..45646f6ebbf5 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -500,6 +500,9 @@ extern int ata_scsi_device_suspend(struct scsi_device *); extern int ata_device_resume(struct ata_port *, struct ata_device *); extern int ata_device_suspend(struct ata_port *, struct ata_device *); extern int ata_ratelimit(void); +extern unsigned int ata_busy_sleep(struct ata_port *ap, + unsigned long timeout_pat, + unsigned long timeout); /* * Default driver ops implementations -- cgit v1.2.3 From c19ba8af4f104cca28d548cac55c128b28dd31fb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 24 Jan 2006 17:05:22 +0900 Subject: [PATCH] libata: new ->probe_reset operation Add new ->probe_reset operation to ata_port_operations obsoleting ->phy_reset. The main difference from ->phy_reset is that the new operation is not allowed to manipulate libata internals directly. It's not allowed to configure or disable the port or devices. It can only succeed or fail and classify attached devices into passed @classes. This change gives more control to higher level and eases sharing reset methods with EH. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 19 ++++++++++++++++++- include/linux/libata.h | 8 +++++--- 2 files changed, 23 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 1f78e246f5e0..147e1461062d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1485,7 +1485,24 @@ static int ata_bus_probe(struct ata_port *ap) { unsigned int i, found = 0; - ap->ops->phy_reset(ap); + if (ap->ops->probe_reset) { + unsigned int classes[ATA_MAX_DEVICES]; + int rc; + + ata_port_probe(ap); + + rc = ap->ops->probe_reset(ap, classes); + if (rc == 0) { + for (i = 0; i < ATA_MAX_DEVICES; i++) + ap->device[i].class = classes[i]; + } else { + printk(KERN_ERR "ata%u: probe reset failed, " + "disabling port\n", ap->id); + ata_port_disable(ap); + } + } else + ap->ops->phy_reset(ap); + if (ap->flags & ATA_FLAG_PORT_DISABLED) goto err_out; diff --git a/include/linux/libata.h b/include/linux/libata.h index 45646f6ebbf5..a84d1c3a5429 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -148,9 +148,9 @@ enum { ATA_FLAG_PORT_DISABLED = (1 << 2), /* port is disabled, ignore it */ ATA_FLAG_SATA = (1 << 3), ATA_FLAG_NO_LEGACY = (1 << 4), /* no legacy mode check */ - ATA_FLAG_SRST = (1 << 5), /* use ATA SRST, not E.D.D. */ + ATA_FLAG_SRST = (1 << 5), /* (obsolete) use ATA SRST, not E.D.D. */ ATA_FLAG_MMIO = (1 << 6), /* use MMIO, not PIO */ - ATA_FLAG_SATA_RESET = (1 << 7), /* use COMRESET */ + ATA_FLAG_SATA_RESET = (1 << 7), /* (obsolete) use COMRESET */ ATA_FLAG_PIO_DMA = (1 << 8), /* PIO cmds via DMA */ ATA_FLAG_NOINTR = (1 << 9), /* FIXME: Remove this once * proper HSM is in place. */ @@ -419,7 +419,9 @@ struct ata_port_operations { u8 (*check_altstatus)(struct ata_port *ap); void (*dev_select)(struct ata_port *ap, unsigned int device); - void (*phy_reset) (struct ata_port *ap); + void (*phy_reset) (struct ata_port *ap); /* obsolete */ + int (*probe_reset) (struct ata_port *ap, unsigned int *classes); + void (*post_set_mode) (struct ata_port *ap); int (*check_atapi_dma) (struct ata_queued_cmd *qc); -- cgit v1.2.3 From a62c0fc526c344d8163f7a9e45e68cc63826ffd3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 24 Jan 2006 17:05:22 +0900 Subject: [PATCH] libata: implement ata_drive_probe_reset() Most low level drivers share supported reset/classify actions and sequence. This patch implements ata_drive_probe_reset() which helps constructing ->probe_reset from three component operations - softreset, hardreset and postreset. This minimizes duplicate code and yet allows flexibility if needed. The three component operations can also be shared by EH later. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 5 +++ 2 files changed, 94 insertions(+) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 147e1461062d..cf91fdc08ef6 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2233,6 +2233,94 @@ err_out: DPRINTK("EXIT\n"); } +static int do_probe_reset(struct ata_port *ap, ata_reset_fn_t reset, + ata_postreset_fn_t postreset, + unsigned int *classes) +{ + int i, rc; + + for (i = 0; i < ATA_MAX_DEVICES; i++) + classes[i] = ATA_DEV_UNKNOWN; + + rc = reset(ap, 0, classes); + if (rc) + return rc; + + /* If any class isn't ATA_DEV_UNKNOWN, consider classification + * is complete and convert all ATA_DEV_UNKNOWN to + * ATA_DEV_NONE. + */ + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (classes[i] != ATA_DEV_UNKNOWN) + break; + + if (i < ATA_MAX_DEVICES) + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (classes[i] == ATA_DEV_UNKNOWN) + classes[i] = ATA_DEV_NONE; + + if (postreset) + postreset(ap, classes); + + return classes[0] != ATA_DEV_UNKNOWN ? 0 : -ENODEV; +} + +/** + * ata_drive_probe_reset - Perform probe reset with given methods + * @ap: port to reset + * @softreset: softreset method (can be NULL) + * @hardreset: hardreset method (can be NULL) + * @postreset: postreset method (can be NULL) + * @classes: resulting classes of attached devices + * + * Reset the specified port and classify attached devices using + * given methods. This function prefers softreset but tries all + * possible reset sequences to reset and classify devices. This + * function is intended to be used for constructing ->probe_reset + * callback by low level drivers. + * + * Reset methods should follow the following rules. + * + * - Return 0 on sucess, -errno on failure. + * - If classification is supported, fill classes[] with + * recognized class codes. + * - If classification is not supported, leave classes[] alone. + * - If verbose is non-zero, print error message on failure; + * otherwise, shut up. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, -EINVAL if no reset method is avaliable, -ENODEV + * if classification fails, and any error code from reset + * methods. + */ +int ata_drive_probe_reset(struct ata_port *ap, + ata_reset_fn_t softreset, ata_reset_fn_t hardreset, + ata_postreset_fn_t postreset, unsigned int *classes) +{ + int rc = -EINVAL; + + if (softreset) { + rc = do_probe_reset(ap, softreset, postreset, classes); + if (rc == 0) + return 0; + } + + if (!hardreset) + return rc; + + rc = do_probe_reset(ap, hardreset, postreset, classes); + if (rc == 0 || rc != -ENODEV) + return rc; + + if (softreset) + rc = do_probe_reset(ap, softreset, postreset, classes); + + return rc; +} + static void ata_pr_blacklisted(const struct ata_port *ap, const struct ata_device *dev) { @@ -5180,6 +5268,7 @@ EXPORT_SYMBOL_GPL(ata_port_probe); EXPORT_SYMBOL_GPL(sata_phy_reset); EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); +EXPORT_SYMBOL_GPL(ata_drive_probe_reset); EXPORT_SYMBOL_GPL(ata_port_disable); EXPORT_SYMBOL_GPL(ata_ratelimit); EXPORT_SYMBOL_GPL(ata_busy_sleep); diff --git a/include/linux/libata.h b/include/linux/libata.h index a84d1c3a5429..38e08ce2d1af 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -241,6 +241,8 @@ struct ata_queued_cmd; /* typedefs */ typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc); +typedef int (*ata_reset_fn_t)(struct ata_port *, int, unsigned int *); +typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *); struct ata_ioports { unsigned long cmd_addr; @@ -478,6 +480,9 @@ extern void ata_port_probe(struct ata_port *); extern void __sata_phy_reset(struct ata_port *ap); extern void sata_phy_reset(struct ata_port *ap); extern void ata_bus_reset(struct ata_port *ap); +extern int ata_drive_probe_reset(struct ata_port *ap, + ata_reset_fn_t softreset, ata_reset_fn_t hardreset, + ata_postreset_fn_t postreset, unsigned int *classes); extern void ata_port_disable(struct ata_port *); extern void ata_std_ports(struct ata_ioports *ioaddr); #ifdef CONFIG_PCI -- cgit v1.2.3 From c2bd58047b9b5c91a3b0a851de66a877f2eb7ae3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 24 Jan 2006 17:05:22 +0900 Subject: [PATCH] libata: implement standard reset component operations and ->probe_reset Implement SRST, COMRESET and standard postreset component operations for ata_drive_probe_reset(), and use these three functions to implement ata_std_probe_reset. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 206 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 6 ++ 2 files changed, 212 insertions(+) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index cf91fdc08ef6..b369dbd7cb23 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2233,6 +2233,208 @@ err_out: DPRINTK("EXIT\n"); } +/** + * ata_std_softreset - reset host port via ATA SRST + * @ap: port to reset + * @verbose: fail verbosely + * @classes: resulting classes of attached devices + * + * Reset host port using ATA SRST. This function is to be used + * as standard callback for ata_drive_*_reset() functions. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, -errno otherwise. + */ +int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes) +{ + unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; + unsigned int devmask = 0, err_mask; + u8 err; + + DPRINTK("ENTER\n"); + + /* determine if device 0/1 are present */ + if (ata_devchk(ap, 0)) + devmask |= (1 << 0); + if (slave_possible && ata_devchk(ap, 1)) + devmask |= (1 << 1); + + /* devchk reports device presence without actual device on + * most SATA controllers. Check SStatus and turn devmask off + * if link is offline. Note that we should continue resetting + * even when it seems like there's no device. + */ + if (ap->ops->scr_read && !sata_dev_present(ap)) + devmask = 0; + + /* select device 0 again */ + ap->ops->dev_select(ap, 0); + + /* issue bus reset */ + DPRINTK("about to softreset, devmask=%x\n", devmask); + err_mask = ata_bus_softreset(ap, devmask); + if (err_mask) { + if (verbose) + printk(KERN_ERR "ata%u: SRST failed (err_mask=0x%x)\n", + ap->id, err_mask); + else + DPRINTK("EXIT, softreset failed (err_mask=0x%x)\n", + err_mask); + return -EIO; + } + + /* determine by signature whether we have ATA or ATAPI devices */ + classes[0] = ata_dev_try_classify(ap, 0, &err); + if (slave_possible && err != 0x81) + classes[1] = ata_dev_try_classify(ap, 1, &err); + + DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]); + return 0; +} + +/** + * sata_std_hardreset - reset host port via SATA phy reset + * @ap: port to reset + * @verbose: fail verbosely + * @class: resulting class of attached device + * + * SATA phy-reset host port using DET bits of SControl register. + * This function is to be used as standard callback for + * ata_drive_*_reset(). + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, -errno otherwise. + */ +int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class) +{ + u32 sstatus, serror; + unsigned long timeout = jiffies + (HZ * 5); + + DPRINTK("ENTER\n"); + + /* Issue phy wake/reset */ + scr_write_flush(ap, SCR_CONTROL, 0x301); + + /* + * Couldn't find anything in SATA I/II specs, but AHCI-1.1 + * 10.4.2 says at least 1 ms. + */ + msleep(1); + + scr_write_flush(ap, SCR_CONTROL, 0x300); + + /* Wait for phy to become ready, if necessary. */ + do { + msleep(200); + sstatus = scr_read(ap, SCR_STATUS); + if ((sstatus & 0xf) != 1) + break; + } while (time_before(jiffies, timeout)); + + /* Clear SError */ + serror = scr_read(ap, SCR_ERROR); + scr_write(ap, SCR_ERROR, serror); + + /* TODO: phy layer with polling, timeouts, etc. */ + if (!sata_dev_present(ap)) { + *class = ATA_DEV_NONE; + DPRINTK("EXIT, link offline\n"); + return 0; + } + + if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { + if (verbose) + printk(KERN_ERR "ata%u: COMRESET failed " + "(device not ready)\n", ap->id); + else + DPRINTK("EXIT, device not ready\n"); + return -EIO; + } + + *class = ata_dev_try_classify(ap, 0, NULL); + + DPRINTK("EXIT, class=%u\n", *class); + return 0; +} + +/** + * ata_std_postreset - standard postreset callback + * @ap: the target ata_port + * @classes: classes of attached devices + * + * This function is invoked after a successful reset. Note that + * the device might have been reset more than once using + * different reset methods before postreset is invoked. + * postreset is also reponsible for setting cable type. + * + * This function is to be used as standard callback for + * ata_drive_*_reset(). + * + * LOCKING: + * Kernel thread context (may sleep) + */ +void ata_std_postreset(struct ata_port *ap, unsigned int *classes) +{ + DPRINTK("ENTER\n"); + + /* set cable type */ + if (ap->cbl == ATA_CBL_NONE && ap->flags & ATA_FLAG_SATA) + ap->cbl = ATA_CBL_SATA; + + /* print link status */ + if (ap->cbl == ATA_CBL_SATA) + sata_print_link_status(ap); + + /* bail out if no device is present */ + if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) { + DPRINTK("EXIT, no device\n"); + return; + } + + /* is double-select really necessary? */ + if (classes[0] != ATA_DEV_NONE) + ap->ops->dev_select(ap, 1); + if (classes[1] != ATA_DEV_NONE) + ap->ops->dev_select(ap, 0); + + /* re-enable interrupts & set up device control */ + if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */ + ata_irq_on(ap); + + DPRINTK("EXIT\n"); +} + +/** + * ata_std_probe_reset - standard probe reset method + * @ap: prot to perform probe-reset + * @classes: resulting classes of attached devices + * + * The stock off-the-shelf ->probe_reset method. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, -errno otherwise. + */ +int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes) +{ + ata_reset_fn_t hardreset; + + hardreset = NULL; + if (ap->cbl == ATA_CBL_SATA && ap->ops->scr_read) + hardreset = sata_std_hardreset; + + return ata_drive_probe_reset(ap, ata_std_softreset, hardreset, + ata_std_postreset, classes); +} + static int do_probe_reset(struct ata_port *ap, ata_reset_fn_t reset, ata_postreset_fn_t postreset, unsigned int *classes) @@ -5268,6 +5470,10 @@ EXPORT_SYMBOL_GPL(ata_port_probe); EXPORT_SYMBOL_GPL(sata_phy_reset); EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); +EXPORT_SYMBOL_GPL(ata_std_softreset); +EXPORT_SYMBOL_GPL(sata_std_hardreset); +EXPORT_SYMBOL_GPL(ata_std_postreset); +EXPORT_SYMBOL_GPL(ata_std_probe_reset); EXPORT_SYMBOL_GPL(ata_drive_probe_reset); EXPORT_SYMBOL_GPL(ata_port_disable); EXPORT_SYMBOL_GPL(ata_ratelimit); diff --git a/include/linux/libata.h b/include/linux/libata.h index 38e08ce2d1af..474cdfa35d1e 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -483,6 +483,11 @@ extern void ata_bus_reset(struct ata_port *ap); extern int ata_drive_probe_reset(struct ata_port *ap, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset, unsigned int *classes); +extern int ata_std_softreset(struct ata_port *ap, int verbose, + unsigned int *classes); +extern int sata_std_hardreset(struct ata_port *ap, int verbose, + unsigned int *class); +extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes); extern void ata_port_disable(struct ata_port *); extern void ata_std_ports(struct ata_ioports *ioaddr); #ifdef CONFIG_PCI @@ -523,6 +528,7 @@ extern void ata_std_dev_select (struct ata_port *ap, unsigned int device); extern u8 ata_check_status(struct ata_port *ap); extern u8 ata_altstatus(struct ata_port *ap); extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf); +extern int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes); extern int ata_port_start (struct ata_port *ap); extern void ata_port_stop (struct ata_port *ap); extern void ata_host_stop (struct ata_host_set *host_set); -- cgit v1.2.3 From bbab6fd81f26b210f0815d79064a3387c3a1ade3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 6 Feb 2006 09:15:11 -0200 Subject: V4L/DVB (3265): Add count to tunertype struct The tuner_params element is an array of undefined length, with each array member being a set of parameters for each video standard type. The number of members in the tuner_params array will be stored in tuners[]->count Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-types.c | 67 +++++++++++++++++++++++++++++++++++++++ include/media/tuner-types.h | 1 + 2 files changed, 68 insertions(+) (limited to 'include') diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index f77584dd356e..27fc4d06b1d2 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -987,18 +987,22 @@ struct tunertype tuners[] = { [TUNER_TEMIC_PAL] = { /* TEMIC PAL */ .name = "Temic PAL (4002 FH5)", .params = tuner_temic_pal_params, + .count = ARRAY_SIZE(tuner_temic_pal_params), }, [TUNER_PHILIPS_PAL_I] = { /* Philips PAL_I */ .name = "Philips PAL_I (FI1246 and compatibles)", .params = tuner_philips_pal_i_params, + .count = ARRAY_SIZE(tuner_philips_pal_i_params), }, [TUNER_PHILIPS_NTSC] = { /* Philips NTSC */ .name = "Philips NTSC (FI1236,FM1236 and compatibles)", .params = tuner_philips_ntsc_params, + .count = ARRAY_SIZE(tuner_philips_ntsc_params), }, [TUNER_PHILIPS_SECAM] = { /* Philips SECAM */ .name = "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)", .params = tuner_philips_secam_params, + .count = ARRAY_SIZE(tuner_philips_secam_params), }, [TUNER_ABSENT] = { /* Tuner Absent */ .name = "NoTuner", @@ -1006,120 +1010,148 @@ struct tunertype tuners[] = { [TUNER_PHILIPS_PAL] = { /* Philips PAL */ .name = "Philips PAL_BG (FI1216 and compatibles)", .params = tuner_philips_pal_params, + .count = ARRAY_SIZE(tuner_philips_pal_params), }, [TUNER_TEMIC_NTSC] = { /* TEMIC NTSC */ .name = "Temic NTSC (4032 FY5)", .params = tuner_temic_ntsc_params, + .count = ARRAY_SIZE(tuner_temic_ntsc_params), }, [TUNER_TEMIC_PAL_I] = { /* TEMIC PAL_I */ .name = "Temic PAL_I (4062 FY5)", .params = tuner_temic_pal_i_params, + .count = ARRAY_SIZE(tuner_temic_pal_i_params), }, [TUNER_TEMIC_4036FY5_NTSC] = { /* TEMIC NTSC */ .name = "Temic NTSC (4036 FY5)", .params = tuner_temic_4036fy5_ntsc_params, + .count = ARRAY_SIZE(tuner_temic_4036fy5_ntsc_params), }, [TUNER_ALPS_TSBH1_NTSC] = { /* TEMIC NTSC */ .name = "Alps HSBH1", .params = tuner_alps_tsbh1_ntsc_params, + .count = ARRAY_SIZE(tuner_alps_tsbh1_ntsc_params), }, /* 10-19 */ [TUNER_ALPS_TSBE1_PAL] = { /* TEMIC PAL */ .name = "Alps TSBE1", .params = tuner_alps_tsb_1_params, + .count = ARRAY_SIZE(tuner_alps_tsb_1_params), }, [TUNER_ALPS_TSBB5_PAL_I] = { /* Alps PAL_I */ .name = "Alps TSBB5", .params = tuner_alps_tsbb5_params, + .count = ARRAY_SIZE(tuner_alps_tsbb5_params), }, [TUNER_ALPS_TSBE5_PAL] = { /* Alps PAL */ .name = "Alps TSBE5", .params = tuner_alps_tsbe5_params, + .count = ARRAY_SIZE(tuner_alps_tsbe5_params), }, [TUNER_ALPS_TSBC5_PAL] = { /* Alps PAL */ .name = "Alps TSBC5", .params = tuner_alps_tsbc5_params, + .count = ARRAY_SIZE(tuner_alps_tsbc5_params), }, [TUNER_TEMIC_4006FH5_PAL] = { /* TEMIC PAL */ .name = "Temic PAL_BG (4006FH5)", .params = tuner_temic_4006fh5_params, + .count = ARRAY_SIZE(tuner_temic_4006fh5_params), }, [TUNER_ALPS_TSHC6_NTSC] = { /* Alps NTSC */ .name = "Alps TSCH6", .params = tuner_alps_tshc6_params, + .count = ARRAY_SIZE(tuner_alps_tshc6_params), }, [TUNER_TEMIC_PAL_DK] = { /* TEMIC PAL */ .name = "Temic PAL_DK (4016 FY5)", .params = tuner_temic_pal_dk_params, + .count = ARRAY_SIZE(tuner_temic_pal_dk_params), }, [TUNER_PHILIPS_NTSC_M] = { /* Philips NTSC */ .name = "Philips NTSC_M (MK2)", .params = tuner_philips_ntsc_m_params, + .count = ARRAY_SIZE(tuner_philips_ntsc_m_params), }, [TUNER_TEMIC_4066FY5_PAL_I] = { /* TEMIC PAL_I */ .name = "Temic PAL_I (4066 FY5)", .params = tuner_temic_4066fy5_pal_i_params, + .count = ARRAY_SIZE(tuner_temic_4066fy5_pal_i_params), }, [TUNER_TEMIC_4006FN5_MULTI_PAL] = { /* TEMIC PAL */ .name = "Temic PAL* auto (4006 FN5)", .params = tuner_temic_4006fn5_multi_params, + .count = ARRAY_SIZE(tuner_temic_4006fn5_multi_params), }, /* 20-29 */ [TUNER_TEMIC_4009FR5_PAL] = { /* TEMIC PAL */ .name = "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", .params = tuner_temic_4009f_5_params, + .count = ARRAY_SIZE(tuner_temic_4009f_5_params), }, [TUNER_TEMIC_4039FR5_NTSC] = { /* TEMIC NTSC */ .name = "Temic NTSC (4039 FR5)", .params = tuner_temic_4039fr5_params, + .count = ARRAY_SIZE(tuner_temic_4039fr5_params), }, [TUNER_TEMIC_4046FM5] = { /* TEMIC PAL */ .name = "Temic PAL/SECAM multi (4046 FM5)", .params = tuner_temic_4046fm5_params, + .count = ARRAY_SIZE(tuner_temic_4046fm5_params), }, [TUNER_PHILIPS_PAL_DK] = { /* Philips PAL */ .name = "Philips PAL_DK (FI1256 and compatibles)", .params = tuner_philips_pal_dk_params, + .count = ARRAY_SIZE(tuner_philips_pal_dk_params), }, [TUNER_PHILIPS_FQ1216ME] = { /* Philips PAL */ .name = "Philips PAL/SECAM multi (FQ1216ME)", .params = tuner_philips_fq1216me_params, + .count = ARRAY_SIZE(tuner_philips_fq1216me_params), }, [TUNER_LG_PAL_I_FM] = { /* LGINNOTEK PAL_I */ .name = "LG PAL_I+FM (TAPC-I001D)", .params = tuner_lg_pal_i_fm_params, + .count = ARRAY_SIZE(tuner_lg_pal_i_fm_params), }, [TUNER_LG_PAL_I] = { /* LGINNOTEK PAL_I */ .name = "LG PAL_I (TAPC-I701D)", .params = tuner_lg_pal_i_params, + .count = ARRAY_SIZE(tuner_lg_pal_i_params), }, [TUNER_LG_NTSC_FM] = { /* LGINNOTEK NTSC */ .name = "LG NTSC+FM (TPI8NSR01F)", .params = tuner_lg_ntsc_fm_params, + .count = ARRAY_SIZE(tuner_lg_ntsc_fm_params), }, [TUNER_LG_PAL_FM] = { /* LGINNOTEK PAL */ .name = "LG PAL_BG+FM (TPI8PSB01D)", .params = tuner_lg_pal_fm_params, + .count = ARRAY_SIZE(tuner_lg_pal_fm_params), }, [TUNER_LG_PAL] = { /* LGINNOTEK PAL */ .name = "LG PAL_BG (TPI8PSB11D)", .params = tuner_lg_pal_params, + .count = ARRAY_SIZE(tuner_lg_pal_params), }, /* 30-39 */ [TUNER_TEMIC_4009FN5_MULTI_PAL_FM] = { /* TEMIC PAL */ .name = "Temic PAL* auto + FM (4009 FN5)", .params = tuner_temic_4009_fn5_multi_pal_fm_params, + .count = ARRAY_SIZE(tuner_temic_4009_fn5_multi_pal_fm_params), }, [TUNER_SHARP_2U5JF5540_NTSC] = { /* SHARP NTSC */ .name = "SHARP NTSC_JP (2U5JF5540)", .params = tuner_sharp_2u5jf5540_params, + .count = ARRAY_SIZE(tuner_sharp_2u5jf5540_params), }, [TUNER_Samsung_PAL_TCPM9091PD27] = { /* Samsung PAL */ .name = "Samsung PAL TCPM9091PD27", .params = tuner_samsung_pal_tcpm9091pd27_params, + .count = ARRAY_SIZE(tuner_samsung_pal_tcpm9091pd27_params), }, [TUNER_MT2032] = { /* Microtune PAL|NTSC */ .name = "MT20xx universal", @@ -1127,86 +1159,106 @@ struct tunertype tuners[] = { [TUNER_TEMIC_4106FH5] = { /* TEMIC PAL */ .name = "Temic PAL_BG (4106 FH5)", .params = tuner_temic_4106fh5_params, + .count = ARRAY_SIZE(tuner_temic_4106fh5_params), }, [TUNER_TEMIC_4012FY5] = { /* TEMIC PAL */ .name = "Temic PAL_DK/SECAM_L (4012 FY5)", .params = tuner_temic_4012fy5_params, + .count = ARRAY_SIZE(tuner_temic_4012fy5_params), }, [TUNER_TEMIC_4136FY5] = { /* TEMIC NTSC */ .name = "Temic NTSC (4136 FY5)", .params = tuner_temic_4136_fy5_params, + .count = ARRAY_SIZE(tuner_temic_4136_fy5_params), }, [TUNER_LG_PAL_NEW_TAPC] = { /* LGINNOTEK PAL */ .name = "LG PAL (newer TAPC series)", .params = tuner_lg_pal_new_tapc_params, + .count = ARRAY_SIZE(tuner_lg_pal_new_tapc_params), }, [TUNER_PHILIPS_FM1216ME_MK3] = { /* Philips PAL */ .name = "Philips PAL/SECAM multi (FM1216ME MK3)", .params = tuner_fm1216me_mk3_params, + .count = ARRAY_SIZE(tuner_fm1216me_mk3_params), }, [TUNER_LG_NTSC_NEW_TAPC] = { /* LGINNOTEK NTSC */ .name = "LG NTSC (newer TAPC series)", .params = tuner_lg_ntsc_new_tapc_params, + .count = ARRAY_SIZE(tuner_lg_ntsc_new_tapc_params), }, /* 40-49 */ [TUNER_HITACHI_NTSC] = { /* HITACHI NTSC */ .name = "HITACHI V7-J180AT", .params = tuner_hitachi_ntsc_params, + .count = ARRAY_SIZE(tuner_hitachi_ntsc_params), }, [TUNER_PHILIPS_PAL_MK] = { /* Philips PAL */ .name = "Philips PAL_MK (FI1216 MK)", .params = tuner_philips_pal_mk_params, + .count = ARRAY_SIZE(tuner_philips_pal_mk_params), }, [TUNER_PHILIPS_ATSC] = { /* Philips ATSC */ .name = "Philips 1236D ATSC/NTSC dual in", .params = tuner_philips_atsc_params, + .count = ARRAY_SIZE(tuner_philips_atsc_params), }, [TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */ .name = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", .params = tuner_fm1236_mk3_params, + .count = ARRAY_SIZE(tuner_fm1236_mk3_params), }, [TUNER_PHILIPS_4IN1] = { /* Philips NTSC */ .name = "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", .params = tuner_philips_4in1_params, + .count = ARRAY_SIZE(tuner_philips_4in1_params), }, [TUNER_MICROTUNE_4049FM5] = { /* Microtune PAL */ .name = "Microtune 4049 FM5", .params = tuner_microtune_4049_fm5_params, + .count = ARRAY_SIZE(tuner_microtune_4049_fm5_params), }, [TUNER_PANASONIC_VP27] = { /* Panasonic NTSC */ .name = "Panasonic VP27s/ENGE4324D", .params = tuner_panasonic_vp27_params, + .count = ARRAY_SIZE(tuner_panasonic_vp27_params), }, [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */ .name = "LG NTSC (TAPE series)", .params = tuner_lg_ntsc_tape_params, + .count = ARRAY_SIZE(tuner_lg_ntsc_tape_params), }, [TUNER_TNF_8831BGFF] = { /* Philips PAL */ .name = "Tenna TNF 8831 BGFF)", .params = tuner_tnf_8831bgff_params, + .count = ARRAY_SIZE(tuner_tnf_8831bgff_params), }, [TUNER_MICROTUNE_4042FI5] = { /* Microtune NTSC */ .name = "Microtune 4042 FI5 ATSC/NTSC dual in", .params = tuner_microtune_4042fi5_params, + .count = ARRAY_SIZE(tuner_microtune_4042fi5_params), }, /* 50-59 */ [TUNER_TCL_2002N] = { /* TCL NTSC */ .name = "TCL 2002N", .params = tuner_tcl_2002n_params, + .count = ARRAY_SIZE(tuner_tcl_2002n_params), }, [TUNER_PHILIPS_FM1256_IH3] = { /* Philips PAL */ .name = "Philips PAL/SECAM_D (FM 1256 I-H3)", .params = tuner_philips_fm1256_ih3_params, + .count = ARRAY_SIZE(tuner_philips_fm1256_ih3_params), }, [TUNER_THOMSON_DTT7610] = { /* THOMSON ATSC */ .name = "Thomson DTT 7610 (ATSC/NTSC)", .params = tuner_thomson_dtt7610_params, + .count = ARRAY_SIZE(tuner_thomson_dtt7610_params), }, [TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */ .name = "Philips FQ1286", .params = tuner_philips_fq1286_params, + .count = ARRAY_SIZE(tuner_philips_fq1286_params), }, [TUNER_PHILIPS_TDA8290] = { /* Philips PAL|NTSC */ .name = "tda8290+75", @@ -1214,22 +1266,27 @@ struct tunertype tuners[] = { [TUNER_TCL_2002MB] = { /* TCL PAL */ .name = "TCL 2002MB", .params = tuner_tcl_2002mb_params, + .count = ARRAY_SIZE(tuner_tcl_2002mb_params), }, [TUNER_PHILIPS_FQ1216AME_MK4] = { /* Philips PAL */ .name = "Philips PAL/SECAM multi (FQ1216AME MK4)", .params = tuner_philips_fq1216ame_mk4_params, + .count = ARRAY_SIZE(tuner_philips_fq1216ame_mk4_params), }, [TUNER_PHILIPS_FQ1236A_MK4] = { /* Philips NTSC */ .name = "Philips FQ1236A MK4", .params = tuner_philips_fq1236a_mk4_params, + .count = ARRAY_SIZE(tuner_philips_fq1236a_mk4_params), }, [TUNER_YMEC_TVF_8531MF] = { /* Philips NTSC */ .name = "Ymec TVision TVF-8531MF/8831MF/8731MF", .params = tuner_ymec_tvf_8531mf_params, + .count = ARRAY_SIZE(tuner_ymec_tvf_8531mf_params), }, [TUNER_YMEC_TVF_5533MF] = { /* Philips NTSC */ .name = "Ymec TVision TVF-5533MF", .params = tuner_ymec_tvf_5533mf_params, + .count = ARRAY_SIZE(tuner_ymec_tvf_5533mf_params), }, /* 60-69 */ @@ -1237,10 +1294,12 @@ struct tunertype tuners[] = { /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */ .name = "Thomson DTT 761X (ATSC/NTSC)", .params = tuner_thomson_dtt761x_params, + .count = ARRAY_SIZE(tuner_thomson_dtt761x_params), }, [TUNER_TENA_9533_DI] = { /* Philips PAL */ .name = "Tena TNF9533-D/IF/TNF9533-B/DF", .params = tuner_tena_9533_di_params, + .count = ARRAY_SIZE(tuner_tena_9533_di_params), }, [TUNER_TEA5767] = { /* Philips RADIO */ .name = "Philips TEA5767HN FM Radio", @@ -1249,36 +1308,44 @@ struct tunertype tuners[] = { [TUNER_PHILIPS_FMD1216ME_MK3] = { /* Philips PAL */ .name = "Philips FMD1216ME MK3 Hybrid Tuner", .params = tuner_philips_fmd1216me_mk3_params, + .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_params), }, [TUNER_LG_TDVS_H062F] = { /* LGINNOTEK ATSC */ .name = "LG TDVS-H062F/TUA6034", .params = tuner_tua6034_params, + .count = ARRAY_SIZE(tuner_tua6034_params), }, [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */ .name = "Ymec TVF66T5-B/DFF", .params = tuner_ymec_tvf66t5_b_dff_params, + .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_params), }, [TUNER_LG_NTSC_TALN_MINI] = { /* LGINNOTEK NTSC */ .name = "LG NTSC (TALN mini series)", .params = tuner_lg_taln_mini_params, + .count = ARRAY_SIZE(tuner_lg_taln_mini_params), }, [TUNER_PHILIPS_TD1316] = { /* Philips PAL */ .name = "Philips TD1316 Hybrid Tuner", .params = tuner_philips_td1316_params, + .count = ARRAY_SIZE(tuner_philips_td1316_params), }, [TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */ .name = "Philips TUV1236D ATSC/NTSC dual in", .params = tuner_tuv1236d_params, + .count = ARRAY_SIZE(tuner_tuv1236d_params), }, [TUNER_TNF_5335MF] = { /* Philips NTSC */ .name = "Tena TNF 5335 MF", .params = tuner_tnf_5335mf_params, + .count = ARRAY_SIZE(tuner_tnf_5335mf_params), }, /* 70-79 */ [TUNER_SAMSUNG_TCPN_2121P30A] = { /* Samsung NTSC */ .name = "Samsung TCPN 2121P30A", .params = tuner_samsung_tcpn_2121p30a_params, + .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_params), }, }; diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h index 53ac66e0114b..ad9c171bfa07 100644 --- a/include/media/tuner-types.h +++ b/include/media/tuner-types.h @@ -46,6 +46,7 @@ struct tuner_params { struct tunertype { char *name; + unsigned int count; struct tuner_params *params; }; -- cgit v1.2.3 From d97a11e091a0bf40f1cfb0bbf443ddd7b455b133 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 7 Feb 2006 06:48:40 -0200 Subject: V4L/DVB (3300): Add standard for South Korean NTSC-M using A2 audio. South Korea uses NTSC-M but with A2 audio instead of BTSC. Several audio chips need this information in order to set the correct audio processing registers. Acked-by: Mauro Carvalho Chehab Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bttv-driver.c | 2 +- drivers/media/video/cx25840/cx25840-core.c | 50 ++++++++++++------------------ drivers/media/video/tda9887.c | 7 ++++- drivers/media/video/tuner-core.c | 5 +++ include/linux/videodev2.h | 4 ++- 5 files changed, 35 insertions(+), 33 deletions(-) (limited to 'include') diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index aa4c4c521880..578b20085082 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -214,7 +214,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { we can capture, of the first and second field. */ .vbistart = { 7,320 }, },{ - .v4l2_id = V4L2_STD_NTSC_M, + .v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR, .name = "NTSC", .Fsc = 28636363, .swidth = 768, diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 3acd587b160c..8d8aa8ec8304 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -220,33 +220,23 @@ static void input_change(struct i2c_client *client) cx25840_write(client, 0x808, 0xff); cx25840_write(client, 0x80b, 0x10); } else if (std & V4L2_STD_NTSC) { - /* NTSC */ - if (state->pvr150_workaround) { - /* Certain Hauppauge PVR150 models have a hardware bug - that causes audio to drop out. For these models the - audio standard must be set explicitly. - To be precise: it affects cards with tuner models - 85, 99 and 112 (model numbers from tveeprom). */ - if (std == V4L2_STD_NTSC_M_JP) { - /* Japan uses EIAJ audio standard */ - cx25840_write(client, 0x808, 0x2f); - } else { - /* Others use the BTSC audio standard */ - cx25840_write(client, 0x808, 0x1f); - } - /* South Korea uses the A2-M (aka Zweiton M) audio - standard, and should set 0x808 to 0x3f, but I don't - know how to detect this. */ - } else if (std == V4L2_STD_NTSC_M_JP) { + /* Certain Hauppauge PVR150 models have a hardware bug + that causes audio to drop out. For these models the + audio standard must be set explicitly. + To be precise: it affects cards with tuner models + 85, 99 and 112 (model numbers from tveeprom). */ + int hw_fix = state->pvr150_workaround; + + if (std == V4L2_STD_NTSC_M_JP) { /* Japan uses EIAJ audio standard */ - cx25840_write(client, 0x808, 0xf7); + cx25840_write(client, 0x808, hw_fix ? 0x2f : 0xf7); + } else if (std == V4L2_STD_NTSC_M_KR) { + /* South Korea uses A2 audio standard */ + cx25840_write(client, 0x808, hw_fix ? 0x3f : 0xf8); } else { /* Others use the BTSC audio standard */ - cx25840_write(client, 0x808, 0xf6); + cx25840_write(client, 0x808, hw_fix ? 0x1f : 0xf6); } - /* South Korea uses the A2-M (aka Zweiton M) audio standard, - and should set 0x808 to 0xf8, but I don't know how to - detect this. */ cx25840_write(client, 0x80b, 0x00); } @@ -330,17 +320,17 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std) u8 fmt=0; /* zero is autodetect */ /* First tests should be against specific std */ - if (std & V4L2_STD_NTSC_M_JP) { + if (std == V4L2_STD_NTSC_M_JP) { fmt=0x2; - } else if (std & V4L2_STD_NTSC_443) { + } else if (std == V4L2_STD_NTSC_443) { fmt=0x3; - } else if (std & V4L2_STD_PAL_M) { + } else if (std == V4L2_STD_PAL_M) { fmt=0x5; - } else if (std & V4L2_STD_PAL_N) { + } else if (std == V4L2_STD_PAL_N) { fmt=0x6; - } else if (std & V4L2_STD_PAL_Nc) { + } else if (std == V4L2_STD_PAL_Nc) { fmt=0x7; - } else if (std & V4L2_STD_PAL_60) { + } else if (std == V4L2_STD_PAL_60) { fmt=0x8; } else { /* Then, test against generic ones */ @@ -369,7 +359,7 @@ v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client) } switch (fmt) { - case 0x1: return V4L2_STD_NTSC_M; + case 0x1: return V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR; case 0x2: return V4L2_STD_NTSC_M_JP; case 0x3: return V4L2_STD_NTSC_443; case 0x4: return V4L2_STD_PAL; diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 7c71422f5d3f..0d54f6c1982b 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -231,7 +231,7 @@ static struct tvnorm tvnorms[] = { cAudioIF_6_5 | cVideoIF_38_90 ), },{ - .std = V4L2_STD_NTSC_M, + .std = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR, .name = "NTSC-M", .b = ( cNegativeFmTV | cQSS ), @@ -619,6 +619,11 @@ static int tda9887_fixup_std(struct tda9887 *t) tda9887_dbg("insmod fixup: NTSC => NTSC_M_JP\n"); t->std = V4L2_STD_NTSC_M_JP; break; + case 'k': + case 'K': + tda9887_dbg("insmod fixup: NTSC => NTSC_M_KR\n"); + t->std = V4L2_STD_NTSC_M_KR; + break; case '-': /* default parameter, do nothing */ break; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 788eadaae672..e34f801c9a10 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -366,6 +366,11 @@ static int tuner_fixup_std(struct tuner *t) tuner_dbg("insmod fixup: NTSC => NTSC_M_JP\n"); t->std = V4L2_STD_NTSC_M_JP; break; + case 'k': + case 'K': + tuner_dbg("insmod fixup: NTSC => NTSC_M_KR\n"); + t->std = V4L2_STD_NTSC_M_KR; + break; case '-': /* default parameter, do nothing */ break; diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 6e33ce96cab0..965c8902fe60 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -638,6 +638,7 @@ typedef __u64 v4l2_std_id; #define V4L2_STD_NTSC_M ((v4l2_std_id)0x00001000) #define V4L2_STD_NTSC_M_JP ((v4l2_std_id)0x00002000) #define V4L2_STD_NTSC_443 ((v4l2_std_id)0x00004000) +#define V4L2_STD_NTSC_M_KR ((v4l2_std_id)0x00008000) #define V4L2_STD_SECAM_B ((v4l2_std_id)0x00010000) #define V4L2_STD_SECAM_D ((v4l2_std_id)0x00020000) @@ -670,7 +671,8 @@ typedef __u64 v4l2_std_id; V4L2_STD_PAL_H |\ V4L2_STD_PAL_I) #define V4L2_STD_NTSC (V4L2_STD_NTSC_M |\ - V4L2_STD_NTSC_M_JP) + V4L2_STD_NTSC_M_JP |\ + V4L2_STD_NTSC_M_KR) #define V4L2_STD_SECAM_DK (V4L2_STD_SECAM_D |\ V4L2_STD_SECAM_K |\ V4L2_STD_SECAM_K1) -- cgit v1.2.3 From 3593cab5d62c4c7abced1076710f9bc2d8847433 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 7 Feb 2006 06:49:14 -0200 Subject: V4L/DVB (3318b): sem2mutex: drivers/media/, #2 Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/saa7146_core.c | 6 +- drivers/media/common/saa7146_fops.c | 18 ++-- drivers/media/common/saa7146_i2c.c | 4 +- drivers/media/common/saa7146_vbi.c | 2 +- drivers/media/common/saa7146_video.c | 30 +++--- drivers/media/dvb/b2c2/flexcop-common.h | 4 +- drivers/media/dvb/b2c2/flexcop-i2c.c | 6 +- drivers/media/dvb/bt8xx/bt878.c | 4 +- drivers/media/dvb/bt8xx/bt878.h | 4 +- drivers/media/dvb/bt8xx/dst.c | 14 +-- drivers/media/dvb/bt8xx/dst_ca.c | 6 +- drivers/media/dvb/bt8xx/dst_common.h | 3 +- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 12 +-- drivers/media/dvb/bt8xx/dvb-bt8xx.h | 3 +- drivers/media/dvb/cinergyT2/cinergyT2.c | 47 ++++----- drivers/media/dvb/dvb-core/dmxdev.c | 86 ++++++++--------- drivers/media/dvb/dvb-core/dmxdev.h | 6 +- drivers/media/dvb/dvb-core/dvb_demux.c | 104 ++++++++++---------- drivers/media/dvb/dvb-core/dvb_demux.h | 4 +- drivers/media/dvb/dvb-core/dvb_frontend.c | 13 ++- drivers/media/dvb/dvb-core/dvb_net.c | 14 +-- drivers/media/dvb/dvb-usb/cxusb.c | 4 +- drivers/media/dvb/dvb-usb/dibusb-common.c | 4 +- drivers/media/dvb/dvb-usb/digitv.c | 4 +- drivers/media/dvb/dvb-usb/dvb-usb-init.c | 4 +- drivers/media/dvb/dvb-usb/dvb-usb-urb.c | 4 +- drivers/media/dvb/dvb-usb/dvb-usb.h | 9 +- drivers/media/dvb/dvb-usb/vp702x.c | 4 +- drivers/media/dvb/dvb-usb/vp7045.c | 4 +- drivers/media/dvb/frontends/bcm3510.c | 9 +- drivers/media/dvb/ttpci/av7110.c | 23 +++-- drivers/media/dvb/ttpci/av7110.h | 7 +- drivers/media/dvb/ttpci/av7110_hw.c | 40 ++++---- drivers/media/dvb/ttpci/budget.h | 4 +- drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 32 ++++--- drivers/media/dvb/ttusb-dec/ttusb_dec.c | 31 +++--- drivers/media/radio/miropcm20-rds-core.c | 11 ++- drivers/media/radio/radio-aimslab.c | 20 ++-- drivers/media/radio/radio-aztech.c | 12 +-- drivers/media/radio/radio-maestro.c | 11 ++- drivers/media/radio/radio-maxiradio.c | 11 ++- drivers/media/radio/radio-sf16fmi.c | 22 ++--- drivers/media/radio/radio-sf16fmr2.c | 22 ++--- drivers/media/radio/radio-typhoon.c | 12 +-- drivers/media/radio/radio-zoltrix.c | 26 ++--- drivers/media/video/arv.c | 16 ++-- drivers/media/video/bttv-driver.c | 48 +++++----- drivers/media/video/bw-qcam.c | 16 ++-- drivers/media/video/bw-qcam.h | 2 +- drivers/media/video/c-qcam.c | 19 ++-- drivers/media/video/cpia.c | 102 ++++++++++---------- drivers/media/video/cpia.h | 5 +- drivers/media/video/cx88/cx88-core.c | 2 +- drivers/media/video/cx88/cx88-video.c | 26 ++--- drivers/media/video/cx88/cx88.h | 4 +- drivers/media/video/em28xx/em28xx-video.c | 106 ++++++++++---------- drivers/media/video/em28xx/em28xx.h | 3 +- drivers/media/video/meye.c | 112 +++++++++++----------- drivers/media/video/meye.h | 4 +- drivers/media/video/mxb.c | 4 +- drivers/media/video/planb.c | 8 +- drivers/media/video/planb.h | 2 +- drivers/media/video/pms.c | 28 +++--- drivers/media/video/saa5246a.c | 10 +- drivers/media/video/saa5249.c | 10 +- drivers/media/video/saa7134/saa7134-alsa.c | 6 +- drivers/media/video/saa7134/saa7134-core.c | 2 +- drivers/media/video/saa7134/saa7134-empress.c | 8 +- drivers/media/video/saa7134/saa7134-oss.c | 40 ++++---- drivers/media/video/saa7134/saa7134-video.c | 40 ++++---- drivers/media/video/saa7134/saa7134.h | 5 +- drivers/media/video/video-buf-dvb.c | 10 +- drivers/media/video/video-buf.c | 42 ++++---- drivers/media/video/videodev.c | 6 +- drivers/media/video/vino.c | 33 +++---- include/linux/videodev2.h | 3 +- include/media/saa7146.h | 21 ++-- include/media/video-buf-dvb.h | 2 +- include/media/video-buf.h | 2 +- 79 files changed, 749 insertions(+), 718 deletions(-) (limited to 'include') diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index 04c1938b9c91..ee16c042ef6e 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c @@ -21,7 +21,7 @@ #include LIST_HEAD(saa7146_devices); -DECLARE_MUTEX(saa7146_devices_lock); +DEFINE_MUTEX(saa7146_devices_lock); static int saa7146_num; @@ -402,11 +402,11 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent pci_set_drvdata(pci, dev); - init_MUTEX(&dev->lock); + mutex_init(&dev->lock); spin_lock_init(&dev->int_slock); spin_lock_init(&dev->slock); - init_MUTEX(&dev->i2c_lock); + mutex_init(&dev->i2c_lock); dev->module = THIS_MODULE; init_waitqueue_head(&dev->i2c_wq); diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index f8cf73ed49ad..dc7fb20f47b5 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -17,18 +17,18 @@ int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit) } /* is it free? */ - down(&dev->lock); + mutex_lock(&dev->lock); if (vv->resources & bit) { DEB_D(("locked! vv->resources:0x%02x, we want:0x%02x\n",vv->resources,bit)); /* no, someone else uses it */ - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } /* it's free, grab it */ fh->resources |= bit; vv->resources |= bit; DEB_D(("res: get 0x%02x, cur:0x%02x\n",bit,vv->resources)); - up(&dev->lock); + mutex_unlock(&dev->lock); return 1; } @@ -40,11 +40,11 @@ void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits) if ((fh->resources & bits) != bits) BUG(); - down(&dev->lock); + mutex_lock(&dev->lock); fh->resources &= ~bits; vv->resources &= ~bits; DEB_D(("res: put 0x%02x, cur:0x%02x\n",bits,vv->resources)); - up(&dev->lock); + mutex_unlock(&dev->lock); } @@ -204,7 +204,7 @@ static int fops_open(struct inode *inode, struct file *file) DEB_EE(("inode:%p, file:%p, minor:%d\n",inode,file,minor)); - if (down_interruptible(&saa7146_devices_lock)) + if (mutex_lock_interruptible(&saa7146_devices_lock)) return -ERESTARTSYS; list_for_each(list,&saa7146_devices) { @@ -276,7 +276,7 @@ out: kfree(fh); file->private_data = NULL; } - up(&saa7146_devices_lock); + mutex_unlock(&saa7146_devices_lock); return result; } @@ -287,7 +287,7 @@ static int fops_release(struct inode *inode, struct file *file) DEB_EE(("inode:%p, file:%p\n",inode,file)); - if (down_interruptible(&saa7146_devices_lock)) + if (mutex_lock_interruptible(&saa7146_devices_lock)) return -ERESTARTSYS; if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { @@ -303,7 +303,7 @@ static int fops_release(struct inode *inode, struct file *file) file->private_data = NULL; kfree(fh); - up(&saa7146_devices_lock); + mutex_unlock(&saa7146_devices_lock); return 0; } diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c index 8aabdd8fb3c5..d9953f7a8b6b 100644 --- a/drivers/media/common/saa7146_i2c.c +++ b/drivers/media/common/saa7146_i2c.c @@ -279,7 +279,7 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, in int address_err = 0; int short_delay = 0; - if (down_interruptible (&dev->i2c_lock)) + if (mutex_lock_interruptible(&dev->i2c_lock)) return -ERESTARTSYS; for(i=0;ii2c_lock); + mutex_unlock(&dev->i2c_lock); return err; } diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c index 468d3c959075..500bd3f05e16 100644 --- a/drivers/media/common/saa7146_vbi.c +++ b/drivers/media/common/saa7146_vbi.c @@ -410,7 +410,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file) V4L2_FIELD_SEQ_TB, // FIXME: does this really work? sizeof(struct saa7146_buf), file); - init_MUTEX(&fh->vbi_q.lock); + mutex_init(&fh->vbi_q.lock); init_timer(&fh->vbi_read_timeout); fh->vbi_read_timeout.function = vbi_read_timeout; diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 7ebac7949df3..6b42713d97f4 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -378,20 +378,20 @@ static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f) err = try_win(dev,&f->fmt.win); if (0 != err) return err; - down(&dev->lock); + mutex_lock(&dev->lock); fh->ov.win = f->fmt.win; fh->ov.nclips = f->fmt.win.clipcount; if (fh->ov.nclips > 16) fh->ov.nclips = 16; if (copy_from_user(fh->ov.clips,f->fmt.win.clips,sizeof(struct v4l2_clip)*fh->ov.nclips)) { - up(&dev->lock); + mutex_unlock(&dev->lock); return -EFAULT; } /* fh->ov.fh is used to indicate that we have valid overlay informations, too */ fh->ov.fh = fh; - up(&dev->lock); + mutex_unlock(&dev->lock); /* check if our current overlay is active */ if (IS_OVERLAY_ACTIVE(fh) != 0) { @@ -516,7 +516,7 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c) return -EINVAL; } - down(&dev->lock); + mutex_lock(&dev->lock); switch (ctrl->type) { case V4L2_CTRL_TYPE_BOOLEAN: @@ -560,7 +560,7 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c) /* fixme: we can support changing VFLIP and HFLIP here... */ if (IS_CAPTURE_ACTIVE(fh) != 0) { DEB_D(("V4L2_CID_HFLIP while active capture.\n")); - up(&dev->lock); + mutex_unlock(&dev->lock); return -EINVAL; } vv->hflip = c->value; @@ -568,7 +568,7 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c) case V4L2_CID_VFLIP: if (IS_CAPTURE_ACTIVE(fh) != 0) { DEB_D(("V4L2_CID_VFLIP while active capture.\n")); - up(&dev->lock); + mutex_unlock(&dev->lock); return -EINVAL; } vv->vflip = c->value; @@ -577,7 +577,7 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c) return -EINVAL; } } - up(&dev->lock); + mutex_unlock(&dev->lock); if (IS_OVERLAY_ACTIVE(fh) != 0) { saa7146_stop_preview(fh); @@ -939,7 +939,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int } } - down(&dev->lock); + mutex_lock(&dev->lock); /* ok, accept it */ vv->ov_fb = *fb; @@ -948,7 +948,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width*fmt->depth/8; - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } @@ -1086,7 +1086,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int } } - down(&dev->lock); + mutex_lock(&dev->lock); for(i = 0; i < dev->ext_vv_data->num_stds; i++) if (*id & dev->ext_vv_data->stds[i].id) @@ -1098,7 +1098,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int found = 1; } - up(&dev->lock); + mutex_unlock(&dev->lock); if (vv->ov_suspend != NULL) { saa7146_start_preview(vv->ov_suspend); @@ -1201,11 +1201,11 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int DEB_D(("VIDIOCGMBUF \n")); q = &fh->video_q; - down(&q->lock); + mutex_lock(&q->lock); err = videobuf_mmap_setup(q,gbuffers,gbufsize, V4L2_MEMORY_MMAP); if (err < 0) { - up(&q->lock); + mutex_unlock(&q->lock); return err; } memset(mbuf,0,sizeof(*mbuf)); @@ -1213,7 +1213,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int mbuf->size = gbuffers * gbufsize; for (i = 0; i < gbuffers; i++) mbuf->offsets[i] = i * gbufsize; - up(&q->lock); + mutex_unlock(&q->lock); return 0; } default: @@ -1414,7 +1414,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file) sizeof(struct saa7146_buf), file); - init_MUTEX(&fh->video_q.lock); + mutex_init(&fh->video_q.lock); return 0; } diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h index 7d7e1613c5a7..b3dd0603cd92 100644 --- a/drivers/media/dvb/b2c2/flexcop-common.h +++ b/drivers/media/dvb/b2c2/flexcop-common.h @@ -10,6 +10,7 @@ #include #include +#include #include "flexcop-reg.h" @@ -73,8 +74,7 @@ struct flexcop_device { int (*fe_sleep) (struct dvb_frontend *); struct i2c_adapter i2c_adap; - struct semaphore i2c_sem; - + struct mutex i2c_mutex; struct module *owner; /* options and status */ diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c index 56495cb6cd02..e0bd2d8f0f0c 100644 --- a/drivers/media/dvb/b2c2/flexcop-i2c.c +++ b/drivers/media/dvb/b2c2/flexcop-i2c.c @@ -135,7 +135,7 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs struct flexcop_device *fc = i2c_get_adapdata(i2c_adap); int i, ret = 0; - if (down_interruptible(&fc->i2c_sem)) + if (mutex_lock_interruptible(&fc->i2c_mutex)) return -ERESTARTSYS; /* reading */ @@ -161,7 +161,7 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs else ret = num; - up(&fc->i2c_sem); + mutex_unlock(&fc->i2c_mutex); return ret; } @@ -180,7 +180,7 @@ int flexcop_i2c_init(struct flexcop_device *fc) { int ret; - sema_init(&fc->i2c_sem,1); + mutex_init(&fc->i2c_mutex); memset(&fc->i2c_adap, 0, sizeof(struct i2c_adapter)); strncpy(fc->i2c_adap.name, "B2C2 FlexCop device",I2C_NAME_SIZE); diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c index 34c3189a1a33..d276ce6b3661 100644 --- a/drivers/media/dvb/bt8xx/bt878.c +++ b/drivers/media/dvb/bt8xx/bt878.c @@ -344,7 +344,7 @@ bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet * int retval; retval = 0; - if (down_interruptible (&bt->gpio_lock)) + if (mutex_lock_interruptible(&bt->gpio_lock)) return -ERESTARTSYS; /* special gpio signal */ switch (cmd) { @@ -375,7 +375,7 @@ bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet * retval = -EINVAL; break; } - up(&bt->gpio_lock); + mutex_unlock(&bt->gpio_lock); return retval; } diff --git a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/dvb/bt8xx/bt878.h index 9faf93770d08..f685bc129609 100644 --- a/drivers/media/dvb/bt8xx/bt878.h +++ b/drivers/media/dvb/bt8xx/bt878.h @@ -25,6 +25,8 @@ #include #include #include +#include + #include "bt848.h" #include "bttv.h" @@ -108,7 +110,7 @@ struct cards { extern int bt878_num; struct bt878 { - struct semaphore gpio_lock; + struct mutex gpio_lock; unsigned int nr; unsigned int bttv_nr; struct i2c_adapter *adapter; diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 3a2ff1cc24b7..d800df1212c5 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -910,7 +910,7 @@ static int dst_get_device_id(struct dst_state *state) static int dst_probe(struct dst_state *state) { - sema_init(&state->dst_mutex, 1); + mutex_init(&state->dst_mutex); if ((rdc_8820_reset(state)) < 0) { dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed."); return -1; @@ -962,7 +962,7 @@ int dst_command(struct dst_state *state, u8 *data, u8 len) { u8 reply; - down(&state->dst_mutex); + mutex_lock(&state->dst_mutex); if ((dst_comm_init(state)) < 0) { dprintk(verbose, DST_NOTICE, 1, "DST Communication Initialization Failed."); goto error; @@ -1013,11 +1013,11 @@ int dst_command(struct dst_state *state, u8 *data, u8 len) dprintk(verbose, DST_INFO, 1, "checksum failure"); goto error; } - up(&state->dst_mutex); + mutex_unlock(&state->dst_mutex); return 0; error: - up(&state->dst_mutex); + mutex_unlock(&state->dst_mutex); return -EIO; } @@ -1128,7 +1128,7 @@ static int dst_write_tuna(struct dvb_frontend *fe) dst_set_voltage(fe, SEC_VOLTAGE_13); } state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE); - down(&state->dst_mutex); + mutex_lock(&state->dst_mutex); if ((dst_comm_init(state)) < 0) { dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed."); goto error; @@ -1160,11 +1160,11 @@ static int dst_write_tuna(struct dvb_frontend *fe) state->diseq_flags |= ATTEMPT_TUNE; retval = dst_get_tuna(state); werr: - up(&state->dst_mutex); + mutex_unlock(&state->dst_mutex); return retval; error: - up(&state->dst_mutex); + mutex_unlock(&state->dst_mutex); return -EIO; } diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c index c650b4bf7f5f..f6b49a801eba 100644 --- a/drivers/media/dvb/bt8xx/dst_ca.c +++ b/drivers/media/dvb/bt8xx/dst_ca.c @@ -81,7 +81,7 @@ static int dst_ci_command(struct dst_state* state, u8 * data, u8 *ca_string, u8 { u8 reply; - down(&state->dst_mutex); + mutex_lock(&state->dst_mutex); dst_comm_init(state); msleep(65); @@ -110,11 +110,11 @@ static int dst_ci_command(struct dst_state* state, u8 * data, u8 *ca_string, u8 goto error; } } - up(&state->dst_mutex); + mutex_unlock(&state->dst_mutex); return 0; error: - up(&state->dst_mutex); + mutex_unlock(&state->dst_mutex); return -EIO; } diff --git a/drivers/media/dvb/bt8xx/dst_common.h b/drivers/media/dvb/bt8xx/dst_common.h index 81557f38fe38..51d4e043716c 100644 --- a/drivers/media/dvb/bt8xx/dst_common.h +++ b/drivers/media/dvb/bt8xx/dst_common.h @@ -25,6 +25,7 @@ #include #include #include +#include #include "bt878.h" #include "dst_ca.h" @@ -121,7 +122,7 @@ struct dst_state { u8 vendor[8]; u8 board_info[8]; - struct semaphore dst_mutex; + struct mutex dst_mutex; }; struct dst_types { diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index ea27b15007e9..1649846f9ceb 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -76,13 +76,13 @@ static int dvb_bt8xx_start_feed(struct dvb_demux_feed *dvbdmxfeed) if (!dvbdmx->dmx.frontend) return -EINVAL; - down(&card->lock); + mutex_lock(&card->lock); card->nfeeds++; rc = card->nfeeds; if (card->nfeeds == 1) bt878_start(card->bt, card->gpio_mode, card->op_sync_orin, card->irq_err_ignore); - up(&card->lock); + mutex_unlock(&card->lock); return rc; } @@ -96,11 +96,11 @@ static int dvb_bt8xx_stop_feed(struct dvb_demux_feed *dvbdmxfeed) if (!dvbdmx->dmx.frontend) return -EINVAL; - down(&card->lock); + mutex_lock(&card->lock); card->nfeeds--; if (card->nfeeds == 0) bt878_stop(card->bt); - up(&card->lock); + mutex_unlock(&card->lock); return 0; } @@ -788,7 +788,7 @@ static int dvb_bt8xx_probe(struct bttv_sub_device *sub) if (!(card = kzalloc(sizeof(struct dvb_bt8xx_card), GFP_KERNEL))) return -ENOMEM; - init_MUTEX(&card->lock); + mutex_init(&card->lock); card->bttv_nr = sub->core->nr; strncpy(card->card_name, sub->core->name, sizeof(sub->core->name)); card->i2c_adapter = &sub->core->i2c_adap; @@ -881,7 +881,7 @@ static int dvb_bt8xx_probe(struct bttv_sub_device *sub) return -EFAULT; } - init_MUTEX(&card->bt->gpio_lock); + mutex_init(&card->bt->gpio_lock); card->bt->bttv_nr = sub->core->nr; if ( (ret = dvb_bt8xx_load_card(card, sub->core->type)) ) { diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h index cf035a80361c..00dd9fa54c82 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h @@ -26,6 +26,7 @@ #define DVB_BT8XX_H #include +#include #include "dvbdev.h" #include "dvb_net.h" #include "bttv.h" @@ -38,7 +39,7 @@ #include "lgdt330x.h" struct dvb_bt8xx_card { - struct semaphore lock; + struct mutex lock; int nfeeds; char card_name[32]; struct dvb_adapter dvb_adapter; diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index c4b4c5b6b7c8..29b7be5271d4 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "dmxdev.h" #include "dvb_demux.h" @@ -116,7 +117,7 @@ static struct dvb_frontend_info cinergyt2_fe_info = { struct cinergyt2 { struct dvb_demux demux; struct usb_device *udev; - struct semaphore sem; + struct mutex sem; struct dvb_adapter adapter; struct dvb_device *fedev; struct dmxdev dmxdev; @@ -345,14 +346,14 @@ static int cinergyt2_start_feed(struct dvb_demux_feed *dvbdmxfeed) struct dvb_demux *demux = dvbdmxfeed->demux; struct cinergyt2 *cinergyt2 = demux->priv; - if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; if (cinergyt2->streaming == 0) cinergyt2_start_stream_xfer(cinergyt2); cinergyt2->streaming++; - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); return 0; } @@ -361,13 +362,13 @@ static int cinergyt2_stop_feed(struct dvb_demux_feed *dvbdmxfeed) struct dvb_demux *demux = dvbdmxfeed->demux; struct cinergyt2 *cinergyt2 = demux->priv; - if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; if (--cinergyt2->streaming == 0) cinergyt2_stop_stream_xfer(cinergyt2); - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); return 0; } @@ -483,11 +484,11 @@ static int cinergyt2_open (struct inode *inode, struct file *file) struct cinergyt2 *cinergyt2 = dvbdev->priv; int err = -ERESTARTSYS; - if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; if ((err = dvb_generic_open(inode, file))) { - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); return err; } @@ -499,7 +500,7 @@ static int cinergyt2_open (struct inode *inode, struct file *file) atomic_inc(&cinergyt2->inuse); - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); return 0; } @@ -517,7 +518,7 @@ static int cinergyt2_release (struct inode *inode, struct file *file) struct dvb_device *dvbdev = file->private_data; struct cinergyt2 *cinergyt2 = dvbdev->priv; - if (down_interruptible(&cinergyt2->sem)) + if (mutex_lock_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) { @@ -526,7 +527,7 @@ static int cinergyt2_release (struct inode *inode, struct file *file) cinergyt2_sleep(cinergyt2, 1); } - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); if (atomic_dec_and_test(&cinergyt2->inuse) && cinergyt2->disconnect_pending) { warn("delayed unregister in release"); @@ -541,12 +542,12 @@ static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct struct dvb_device *dvbdev = file->private_data; struct cinergyt2 *cinergyt2 = dvbdev->priv; - if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; poll_wait(file, &cinergyt2->poll_wq, wait); - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); return (POLLIN | POLLRDNORM | POLLPRI); } @@ -613,7 +614,7 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file, if (copy_from_user(&p, (void __user*) arg, sizeof(p))) return -EFAULT; - if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; @@ -629,7 +630,7 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file, (char *) param, sizeof(*param), NULL, 0); - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); return (err < 0) ? err : 0; } @@ -724,7 +725,7 @@ static void cinergyt2_query_rc (void *data) struct cinergyt2_rc_event rc_events[12]; int n, len, i; - if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return; len = cinergyt2_command(cinergyt2, buf, sizeof(buf), @@ -784,7 +785,7 @@ out: schedule_delayed_work(&cinergyt2->rc_query_work, msecs_to_jiffies(RC_QUERY_INTERVAL)); - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); } static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) @@ -849,7 +850,7 @@ static void cinergyt2_query (void *data) uint8_t lock_bits; uint32_t unc; - if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return; unc = s->uncorrected_block_count; @@ -868,7 +869,7 @@ static void cinergyt2_query (void *data) schedule_delayed_work(&cinergyt2->query_work, msecs_to_jiffies(QUERY_INTERVAL)); - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); } static int cinergyt2_probe (struct usb_interface *intf, @@ -885,7 +886,7 @@ static int cinergyt2_probe (struct usb_interface *intf, memset (cinergyt2, 0, sizeof (struct cinergyt2)); usb_set_intfdata (intf, (void *) cinergyt2); - init_MUTEX(&cinergyt2->sem); + mutex_init(&cinergyt2->sem); init_waitqueue_head (&cinergyt2->poll_wq); INIT_WORK(&cinergyt2->query_work, cinergyt2_query, cinergyt2); @@ -967,7 +968,7 @@ static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state) { struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); - if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; if (state.event > PM_EVENT_ON) { @@ -981,7 +982,7 @@ static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state) cinergyt2_sleep(cinergyt2, 1); } - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); return 0; } @@ -990,7 +991,7 @@ static int cinergyt2_resume (struct usb_interface *intf) struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); struct dvbt_set_parameters_msg *param = &cinergyt2->param; - if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; if (!cinergyt2->sleeping) { @@ -1003,7 +1004,7 @@ static int cinergyt2_resume (struct usb_interface *intf) cinergyt2_resume_rc(cinergyt2); - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); return 0; } diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index 7b8373ad121b..ead5343d7706 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -175,12 +175,12 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) dprintk ("function : %s\n", __FUNCTION__); - if (down_interruptible (&dmxdev->mutex)) + if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; if ((file->f_flags&O_ACCMODE)==O_RDWR) { if (!(dmxdev->capabilities&DMXDEV_CAP_DUPLEX)) { - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return -EOPNOTSUPP; } } @@ -190,7 +190,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) dmxdev->dvr_buffer.size=DVR_BUFFER_SIZE; dmxdev->dvr_buffer.data=vmalloc(DVR_BUFFER_SIZE); if (!dmxdev->dvr_buffer.data) { - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return -ENOMEM; } } @@ -199,20 +199,20 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) dmxdev->dvr_orig_fe=dmxdev->demux->frontend; if (!dmxdev->demux->write) { - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return -EOPNOTSUPP; } front=get_fe(dmxdev->demux, DMX_MEMORY_FE); if (!front) { - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return -EINVAL; } dmxdev->demux->disconnect_frontend(dmxdev->demux); dmxdev->demux->connect_frontend(dmxdev->demux, front); } - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return 0; } @@ -221,7 +221,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) struct dvb_device *dvbdev = file->private_data; struct dmxdev *dmxdev = dvbdev->priv; - if (down_interruptible (&dmxdev->mutex)) + if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; if ((file->f_flags&O_ACCMODE)==O_WRONLY) { @@ -239,7 +239,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) vfree(mem); } } - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return 0; } @@ -254,10 +254,10 @@ static ssize_t dvb_dvr_write(struct file *file, const char __user *buf, return -EOPNOTSUPP; if ((file->f_flags&O_ACCMODE)!=O_WRONLY) return -EINVAL; - if (down_interruptible (&dmxdev->mutex)) + if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; ret=dmxdev->demux->write(dmxdev->demux, buf, count); - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return ret; } @@ -268,11 +268,11 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count, struct dmxdev *dmxdev = dvbdev->priv; int ret; - //down(&dmxdev->mutex); + //mutex_lock(&dmxdev->mutex); ret= dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer, file->f_flags&O_NONBLOCK, buf, count, ppos); - //up(&dmxdev->mutex); + //mutex_unlock(&dmxdev->mutex); return ret; } @@ -688,7 +688,7 @@ static int dvb_demux_open(struct inode *inode, struct file *file) if (!dmxdev->filter) return -EINVAL; - if (down_interruptible(&dmxdev->mutex)) + if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; for (i=0; ifilternum; i++) @@ -696,12 +696,12 @@ static int dvb_demux_open(struct inode *inode, struct file *file) break; if (i==dmxdev->filternum) { - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return -EMFILE; } dmxdevfilter=&dmxdev->filter[i]; - sema_init(&dmxdevfilter->mutex, 1); + mutex_init(&dmxdevfilter->mutex); dmxdevfilter->dvbdev=dmxdev->dvbdev; file->private_data=dmxdevfilter; @@ -711,18 +711,18 @@ static int dvb_demux_open(struct inode *inode, struct file *file) dmxdevfilter->feed.ts=NULL; init_timer(&dmxdevfilter->timer); - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return 0; } static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, struct dmxdev_filter *dmxdevfilter) { - if (down_interruptible(&dmxdev->mutex)) + if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; - if (down_interruptible(&dmxdevfilter->mutex)) { - up(&dmxdev->mutex); + if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { + mutex_unlock(&dmxdev->mutex); return -ERESTARTSYS; } @@ -740,8 +740,8 @@ static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, struct dmxdev_filter *d dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_FREE); wake_up(&dmxdevfilter->buffer.queue); - up(&dmxdevfilter->mutex); - up(&dmxdev->mutex); + mutex_unlock(&dmxdevfilter->mutex); + mutex_unlock(&dmxdev->mutex); return 0; } @@ -841,7 +841,7 @@ dvb_demux_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) struct dmxdev_filter *dmxdevfilter= file->private_data; int ret=0; - if (down_interruptible(&dmxdevfilter->mutex)) + if (mutex_lock_interruptible(&dmxdevfilter->mutex)) return -ERESTARTSYS; if (dmxdevfilter->type==DMXDEV_TYPE_SEC) @@ -851,7 +851,7 @@ dvb_demux_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) file->f_flags&O_NONBLOCK, buf, count, ppos); - up(&dmxdevfilter->mutex); + mutex_unlock(&dmxdevfilter->mutex); return ret; } @@ -864,58 +864,58 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file, unsigned long arg=(unsigned long) parg; int ret=0; - if (down_interruptible (&dmxdev->mutex)) + if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; switch (cmd) { case DMX_START: - if (down_interruptible(&dmxdevfilter->mutex)) { - up(&dmxdev->mutex); + if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { + mutex_unlock(&dmxdev->mutex); return -ERESTARTSYS; } if (dmxdevfilter->statemutex); + mutex_unlock(&dmxdevfilter->mutex); break; case DMX_STOP: - if (down_interruptible(&dmxdevfilter->mutex)) { - up(&dmxdev->mutex); + if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { + mutex_unlock(&dmxdev->mutex); return -ERESTARTSYS; } ret=dvb_dmxdev_filter_stop(dmxdevfilter); - up(&dmxdevfilter->mutex); + mutex_unlock(&dmxdevfilter->mutex); break; case DMX_SET_FILTER: - if (down_interruptible(&dmxdevfilter->mutex)) { - up(&dmxdev->mutex); + if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { + mutex_unlock(&dmxdev->mutex); return -ERESTARTSYS; } ret = dvb_dmxdev_filter_set(dmxdev, dmxdevfilter, (struct dmx_sct_filter_params *)parg); - up(&dmxdevfilter->mutex); + mutex_unlock(&dmxdevfilter->mutex); break; case DMX_SET_PES_FILTER: - if (down_interruptible(&dmxdevfilter->mutex)) { - up(&dmxdev->mutex); + if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { + mutex_unlock(&dmxdev->mutex); return -ERESTARTSYS; } ret=dvb_dmxdev_pes_filter_set(dmxdev, dmxdevfilter, (struct dmx_pes_filter_params *)parg); - up(&dmxdevfilter->mutex); + mutex_unlock(&dmxdevfilter->mutex); break; case DMX_SET_BUFFER_SIZE: - if (down_interruptible(&dmxdevfilter->mutex)) { - up(&dmxdev->mutex); + if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { + mutex_unlock(&dmxdev->mutex); return -ERESTARTSYS; } ret=dvb_dmxdev_set_buffer_size(dmxdevfilter, arg); - up(&dmxdevfilter->mutex); + mutex_unlock(&dmxdevfilter->mutex); break; case DMX_GET_EVENT: @@ -959,7 +959,7 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file, default: ret=-EINVAL; } - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return ret; } @@ -1030,7 +1030,7 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file, int ret=0; - if (down_interruptible (&dmxdev->mutex)) + if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; switch (cmd) { @@ -1042,7 +1042,7 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file, default: ret=-EINVAL; } - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return ret; } @@ -1113,7 +1113,7 @@ dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) return -ENOMEM; } - sema_init(&dmxdev->mutex, 1); + mutex_init(&dmxdev->mutex); spin_lock_init(&dmxdev->lock); for (i=0; ifilternum; i++) { dmxdev->filter[i].dev=dmxdev; diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h index fd72920c2199..ec2a7a4da5e4 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.h +++ b/drivers/media/dvb/dvb-core/dmxdev.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include @@ -83,7 +83,7 @@ struct dmxdev_filter { struct dmxdev *dev; struct dmxdev_buffer buffer; - struct semaphore mutex; + struct mutex mutex; /* only for sections */ struct timer_list timer; @@ -117,7 +117,7 @@ struct dmxdev { struct dmxdev_buffer dvr_buffer; #define DVR_BUFFER_SIZE (10*188*1024) - struct semaphore mutex; + struct mutex mutex; spinlock_t lock; }; diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c index b4c899b15959..83ec5e06c482 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/drivers/media/dvb/dvb-core/dvb_demux.c @@ -589,18 +589,18 @@ static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type, if (pid > DMX_MAX_PID) return -EINVAL; - if (down_interruptible(&demux->mutex)) + if (mutex_lock_interruptible(&demux->mutex)) return -ERESTARTSYS; if (ts_type & TS_DECODER) { if (pes_type >= DMX_TS_PES_OTHER) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -EINVAL; } if (demux->pesfilter[pes_type] && demux->pesfilter[pes_type] != feed) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -EINVAL; } @@ -622,14 +622,14 @@ static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type, #else feed->buffer = vmalloc(feed->buffer_size); if (!feed->buffer) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -ENOMEM; } #endif } feed->state = DMX_STATE_READY; - up(&demux->mutex); + mutex_unlock(&demux->mutex); return 0; } @@ -640,21 +640,21 @@ static int dmx_ts_feed_start_filtering(struct dmx_ts_feed *ts_feed) struct dvb_demux *demux = feed->demux; int ret; - if (down_interruptible(&demux->mutex)) + if (mutex_lock_interruptible(&demux->mutex)) return -ERESTARTSYS; if (feed->state != DMX_STATE_READY || feed->type != DMX_TYPE_TS) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -EINVAL; } if (!demux->start_feed) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -ENODEV; } if ((ret = demux->start_feed(feed)) < 0) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return ret; } @@ -662,7 +662,7 @@ static int dmx_ts_feed_start_filtering(struct dmx_ts_feed *ts_feed) ts_feed->is_filtering = 1; feed->state = DMX_STATE_GO; spin_unlock_irq(&demux->lock); - up(&demux->mutex); + mutex_unlock(&demux->mutex); return 0; } @@ -673,16 +673,16 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed) struct dvb_demux *demux = feed->demux; int ret; - if (down_interruptible(&demux->mutex)) + if (mutex_lock_interruptible(&demux->mutex)) return -ERESTARTSYS; if (feed->state < DMX_STATE_GO) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -EINVAL; } if (!demux->stop_feed) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -ENODEV; } @@ -692,7 +692,7 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed) ts_feed->is_filtering = 0; feed->state = DMX_STATE_ALLOCATED; spin_unlock_irq(&demux->lock); - up(&demux->mutex); + mutex_unlock(&demux->mutex); return ret; } @@ -704,11 +704,11 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx, struct dvb_demux *demux = (struct dvb_demux *)dmx; struct dvb_demux_feed *feed; - if (down_interruptible(&demux->mutex)) + if (mutex_lock_interruptible(&demux->mutex)) return -ERESTARTSYS; if (!(feed = dvb_dmx_feed_alloc(demux))) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -EBUSY; } @@ -729,7 +729,7 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx, if (!(feed->filter = dvb_dmx_filter_alloc(demux))) { feed->state = DMX_STATE_FREE; - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -EBUSY; } @@ -737,7 +737,7 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx, feed->filter->feed = feed; feed->filter->state = DMX_STATE_READY; - up(&demux->mutex); + mutex_unlock(&demux->mutex); return 0; } @@ -748,11 +748,11 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dvb_demux *demux = (struct dvb_demux *)dmx; struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; - if (down_interruptible(&demux->mutex)) + if (mutex_lock_interruptible(&demux->mutex)) return -ERESTARTSYS; if (feed->state == DMX_STATE_FREE) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -EINVAL; } #ifndef NOBUFS @@ -770,7 +770,7 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_TS_PES_OTHER) demux->pesfilter[feed->pes_type] = NULL; - up(&demux->mutex); + mutex_unlock(&demux->mutex); return 0; } @@ -785,12 +785,12 @@ static int dmx_section_feed_allocate_filter(struct dmx_section_feed *feed, struct dvb_demux *dvbdemux = dvbdmxfeed->demux; struct dvb_demux_filter *dvbdmxfilter; - if (down_interruptible(&dvbdemux->mutex)) + if (mutex_lock_interruptible(&dvbdemux->mutex)) return -ERESTARTSYS; dvbdmxfilter = dvb_dmx_filter_alloc(dvbdemux); if (!dvbdmxfilter) { - up(&dvbdemux->mutex); + mutex_unlock(&dvbdemux->mutex); return -EBUSY; } @@ -805,7 +805,7 @@ static int dmx_section_feed_allocate_filter(struct dmx_section_feed *feed, dvbdmxfeed->filter = dvbdmxfilter; spin_unlock_irq(&dvbdemux->lock); - up(&dvbdemux->mutex); + mutex_unlock(&dvbdemux->mutex); return 0; } @@ -819,7 +819,7 @@ static int dmx_section_feed_set(struct dmx_section_feed *feed, if (pid > 0x1fff) return -EINVAL; - if (down_interruptible(&dvbdmx->mutex)) + if (mutex_lock_interruptible(&dvbdmx->mutex)) return -ERESTARTSYS; dvb_demux_feed_add(dvbdmxfeed); @@ -833,13 +833,13 @@ static int dmx_section_feed_set(struct dmx_section_feed *feed, #else dvbdmxfeed->buffer = vmalloc(dvbdmxfeed->buffer_size); if (!dvbdmxfeed->buffer) { - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return -ENOMEM; } #endif dvbdmxfeed->state = DMX_STATE_READY; - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return 0; } @@ -871,16 +871,16 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed) struct dvb_demux *dvbdmx = dvbdmxfeed->demux; int ret; - if (down_interruptible(&dvbdmx->mutex)) + if (mutex_lock_interruptible(&dvbdmx->mutex)) return -ERESTARTSYS; if (feed->is_filtering) { - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return -EBUSY; } if (!dvbdmxfeed->filter) { - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return -EINVAL; } @@ -890,14 +890,14 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed) dvbdmxfeed->feed.sec.seclen = 0; if (!dvbdmx->start_feed) { - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return -ENODEV; } prepare_secfilters(dvbdmxfeed); if ((ret = dvbdmx->start_feed(dvbdmxfeed)) < 0) { - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return ret; } @@ -906,7 +906,7 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed) dvbdmxfeed->state = DMX_STATE_GO; spin_unlock_irq(&dvbdmx->lock); - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return 0; } @@ -916,11 +916,11 @@ static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed) struct dvb_demux *dvbdmx = dvbdmxfeed->demux; int ret; - if (down_interruptible(&dvbdmx->mutex)) + if (mutex_lock_interruptible(&dvbdmx->mutex)) return -ERESTARTSYS; if (!dvbdmx->stop_feed) { - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return -ENODEV; } @@ -931,7 +931,7 @@ static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed) feed->is_filtering = 0; spin_unlock_irq(&dvbdmx->lock); - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return ret; } @@ -942,11 +942,11 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed, struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; struct dvb_demux *dvbdmx = dvbdmxfeed->demux; - if (down_interruptible(&dvbdmx->mutex)) + if (mutex_lock_interruptible(&dvbdmx->mutex)) return -ERESTARTSYS; if (dvbdmxfilter->feed != dvbdmxfeed) { - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return -EINVAL; } @@ -966,7 +966,7 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed, dvbdmxfilter->state = DMX_STATE_FREE; spin_unlock_irq(&dvbdmx->lock); - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return 0; } @@ -977,11 +977,11 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux, struct dvb_demux *dvbdmx = (struct dvb_demux *)demux; struct dvb_demux_feed *dvbdmxfeed; - if (down_interruptible(&dvbdmx->mutex)) + if (mutex_lock_interruptible(&dvbdmx->mutex)) return -ERESTARTSYS; if (!(dvbdmxfeed = dvb_dmx_feed_alloc(dvbdmx))) { - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return -EBUSY; } @@ -1006,7 +1006,7 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux, (*feed)->stop_filtering = dmx_section_feed_stop_filtering; (*feed)->release_filter = dmx_section_feed_release_filter; - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return 0; } @@ -1016,11 +1016,11 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux, struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; struct dvb_demux *dvbdmx = (struct dvb_demux *)demux; - if (down_interruptible(&dvbdmx->mutex)) + if (mutex_lock_interruptible(&dvbdmx->mutex)) return -ERESTARTSYS; if (dvbdmxfeed->state == DMX_STATE_FREE) { - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return -EINVAL; } #ifndef NOBUFS @@ -1033,7 +1033,7 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux, dvbdmxfeed->pid = 0xffff; - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return 0; } @@ -1071,10 +1071,10 @@ static int dvbdmx_write(struct dmx_demux *demux, const char *buf, size_t count) if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE)) return -EINVAL; - if (down_interruptible(&dvbdemux->mutex)) + if (mutex_lock_interruptible(&dvbdemux->mutex)) return -ERESTARTSYS; dvb_dmx_swfilter(dvbdemux, buf, count); - up(&dvbdemux->mutex); + mutex_unlock(&dvbdemux->mutex); if (signal_pending(current)) return -EINTR; @@ -1126,11 +1126,11 @@ static int dvbdmx_connect_frontend(struct dmx_demux *demux, if (demux->frontend) return -EINVAL; - if (down_interruptible(&dvbdemux->mutex)) + if (mutex_lock_interruptible(&dvbdemux->mutex)) return -ERESTARTSYS; demux->frontend = frontend; - up(&dvbdemux->mutex); + mutex_unlock(&dvbdemux->mutex); return 0; } @@ -1138,11 +1138,11 @@ static int dvbdmx_disconnect_frontend(struct dmx_demux *demux) { struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; - if (down_interruptible(&dvbdemux->mutex)) + if (mutex_lock_interruptible(&dvbdemux->mutex)) return -ERESTARTSYS; demux->frontend = NULL; - up(&dvbdemux->mutex); + mutex_unlock(&dvbdemux->mutex); return 0; } @@ -1215,7 +1215,7 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux) dmx->disconnect_frontend = dvbdmx_disconnect_frontend; dmx->get_pes_pids = dvbdmx_get_pes_pids; - sema_init(&dvbdemux->mutex, 1); + mutex_init(&dvbdemux->mutex); spin_lock_init(&dvbdemux->lock); return 0; diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h index 0cc888339d52..2c5f915329ca 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.h +++ b/drivers/media/dvb/dvb-core/dvb_demux.h @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include "demux.h" @@ -125,7 +125,7 @@ struct dvb_demux { u8 tsbuf[204]; int tsbufp; - struct semaphore mutex; + struct mutex mutex; spinlock_t lock; }; diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 771f32d889e6..22e96cf8497a 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -37,7 +37,6 @@ #include #include #include -#include #include "dvb_frontend.h" #include "dvbdev.h" @@ -88,7 +87,7 @@ MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB vola * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again. */ -static DECLARE_MUTEX(frontend_mutex); +static DEFINE_MUTEX(frontend_mutex); struct dvb_frontend_private { @@ -1021,12 +1020,12 @@ int dvb_register_frontend(struct dvb_adapter* dvb, dprintk ("%s\n", __FUNCTION__); - if (down_interruptible (&frontend_mutex)) + if (mutex_lock_interruptible(&frontend_mutex)) return -ERESTARTSYS; fe->frontend_priv = kzalloc(sizeof(struct dvb_frontend_private), GFP_KERNEL); if (fe->frontend_priv == NULL) { - up(&frontend_mutex); + mutex_unlock(&frontend_mutex); return -ENOMEM; } fepriv = fe->frontend_priv; @@ -1045,7 +1044,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb, dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template, fe, DVB_DEVICE_FRONTEND); - up (&frontend_mutex); + mutex_unlock(&frontend_mutex); return 0; } EXPORT_SYMBOL(dvb_register_frontend); @@ -1055,7 +1054,7 @@ int dvb_unregister_frontend(struct dvb_frontend* fe) struct dvb_frontend_private *fepriv = fe->frontend_priv; dprintk ("%s\n", __FUNCTION__); - down (&frontend_mutex); + mutex_lock(&frontend_mutex); dvb_unregister_device (fepriv->dvbdev); dvb_frontend_stop (fe); if (fe->ops->release) @@ -1064,7 +1063,7 @@ int dvb_unregister_frontend(struct dvb_frontend* fe) printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops->info.name); /* fe is invalid now */ kfree(fepriv); - up (&frontend_mutex); + mutex_unlock(&frontend_mutex); return 0; } EXPORT_SYMBOL(dvb_unregister_frontend); diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index 6711eb6a058c..2f0f35811bf7 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -62,6 +62,7 @@ #include #include #include +#include #include "dvb_demux.h" #include "dvb_net.h" @@ -151,8 +152,7 @@ struct dvb_net_priv { unsigned char ule_bridged; /* Whether the ULE_BRIDGED extension header was found. */ int ule_sndu_remain; /* Nr. of bytes still required for current ULE SNDU. */ unsigned long ts_count; /* Current ts cell counter. */ - - struct semaphore mutex; + struct mutex mutex; }; @@ -889,7 +889,7 @@ static int dvb_net_feed_start(struct net_device *dev) unsigned char *mac = (unsigned char *) dev->dev_addr; dprintk("%s: rx_mode %i\n", __FUNCTION__, priv->rx_mode); - down(&priv->mutex); + mutex_lock(&priv->mutex); if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0]) printk("%s: BUG %d\n", __FUNCTION__, __LINE__); @@ -974,7 +974,7 @@ static int dvb_net_feed_start(struct net_device *dev) ret = -EINVAL; error: - up(&priv->mutex); + mutex_unlock(&priv->mutex); return ret; } @@ -984,7 +984,7 @@ static int dvb_net_feed_stop(struct net_device *dev) int i, ret = 0; dprintk("%s\n", __FUNCTION__); - down(&priv->mutex); + mutex_lock(&priv->mutex); if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) { if (priv->secfeed) { if (priv->secfeed->is_filtering) { @@ -1026,7 +1026,7 @@ static int dvb_net_feed_stop(struct net_device *dev) printk("%s: no ts feed to stop\n", dev->name); } else ret = -EINVAL; - up(&priv->mutex); + mutex_unlock(&priv->mutex); return ret; } @@ -1208,7 +1208,7 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype) INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list, net); INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed, net); - init_MUTEX(&priv->mutex); + mutex_init(&priv->mutex); net->base_addr = pid; diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index f327fac1688e..e62a293c7e5a 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -77,7 +77,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) struct dvb_usb_device *d = i2c_get_adapdata(adap); int i; - if (down_interruptible(&d->i2c_sem) < 0) + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; if (num > 2) @@ -126,7 +126,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) } } - up(&d->i2c_sem); + mutex_unlock(&d->i2c_mutex); return i; } diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c index 269d899da488..2d52b76671d3 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-common.c +++ b/drivers/media/dvb/dvb-usb/dibusb-common.c @@ -128,7 +128,7 @@ static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num struct dvb_usb_device *d = i2c_get_adapdata(adap); int i; - if (down_interruptible(&d->i2c_sem) < 0) + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; if (num > 2) @@ -146,7 +146,7 @@ static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num break; } - up(&d->i2c_sem); + mutex_unlock(&d->i2c_mutex); return i; } diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c index caa1346e3063..91136c00ce9d 100644 --- a/drivers/media/dvb/dvb-usb/digitv.c +++ b/drivers/media/dvb/dvb-usb/digitv.c @@ -48,7 +48,7 @@ static int digitv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num struct dvb_usb_device *d = i2c_get_adapdata(adap); int i; - if (down_interruptible(&d->i2c_sem) < 0) + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; if (num > 2) @@ -67,7 +67,7 @@ static int digitv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num break; } - up(&d->i2c_sem); + mutex_unlock(&d->i2c_mutex); return i; } diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c index 716f8bf528cd..4258a995dce1 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c @@ -42,8 +42,8 @@ static int dvb_usb_init(struct dvb_usb_device *d) { int ret = 0; - sema_init(&d->usb_sem, 1); - sema_init(&d->i2c_sem, 1); + mutex_init(&d->usb_mutex); + mutex_init(&d->i2c_mutex); d->state = DVB_USB_STATE_INIT; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c index ee821974dc60..9002f35aa952 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c @@ -21,7 +21,7 @@ int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, if (wbuf == NULL || wlen == 0) return -EINVAL; - if ((ret = down_interruptible(&d->usb_sem))) + if ((ret = mutex_lock_interruptible(&d->usb_mutex))) return ret; deb_xfer(">>> "); @@ -53,7 +53,7 @@ int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, } } - up(&d->usb_sem); + mutex_unlock(&d->usb_mutex); return ret; } EXPORT_SYMBOL(dvb_usb_generic_rw); diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index 5e5d21ad93c9..d2be37cc43b7 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -12,6 +12,7 @@ #include #include #include +#include #include "dvb_frontend.h" #include "dvb_demux.h" @@ -227,8 +228,8 @@ struct dvb_usb_properties { * @feedcount: number of reqested feeds (used for streaming-activation) * @pid_filtering: is hardware pid_filtering used or not. * - * @usb_sem: semaphore of USB control messages (reading needs two messages) - * @i2c_sem: semaphore for i2c-transfers + * @usb_mutex: semaphore of USB control messages (reading needs two messages) + * @i2c_mutex: semaphore for i2c-transfers * * @i2c_adap: device's i2c_adapter if it uses I2CoverUSB * @pll_addr: I2C address of the tuner for programming @@ -283,10 +284,10 @@ struct dvb_usb_device { int pid_filtering; /* locking */ - struct semaphore usb_sem; + struct mutex usb_mutex; /* i2c */ - struct semaphore i2c_sem; + struct mutex i2c_mutex; struct i2c_adapter i2c_adap; /* tuner programming information */ diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c index 4a95eca81c5c..b2f098a2d5f7 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.c +++ b/drivers/media/dvb/dvb-usb/vp702x.c @@ -75,7 +75,7 @@ int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int il { int ret; - if ((ret = down_interruptible(&d->usb_sem))) + if ((ret = mutex_lock_interruptible(&d->usb_mutex))) return ret; if ((ret = vp702x_usb_out_op(d,REQUEST_OUT,0,0,o,olen)) < 0) @@ -84,7 +84,7 @@ int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int il ret = vp702x_usb_in_op(d,REQUEST_IN,0,0,i,ilen); unlock: - up(&d->usb_sem); + mutex_unlock(&d->usb_mutex); return ret; } diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c index 028204956bb0..7fa656b108cc 100644 --- a/drivers/media/dvb/dvb-usb/vp7045.c +++ b/drivers/media/dvb/dvb-usb/vp7045.c @@ -38,7 +38,7 @@ int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, deb_xfer("out buffer: "); debug_dump(outbuf,outlen+1,deb_xfer); - if ((ret = down_interruptible(&d->usb_sem))) + if ((ret = mutex_lock_interruptible(&d->usb_mutex))) return ret; if (usb_control_msg(d->udev, @@ -68,7 +68,7 @@ int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, memcpy(in,&inbuf[1],inlen); unlock: - up(&d->usb_sem); + mutex_unlock(&d->usb_mutex); return ret; } diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c index caaee893ca76..1708a1d4893e 100644 --- a/drivers/media/dvb/frontends/bcm3510.c +++ b/drivers/media/dvb/frontends/bcm3510.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "dvb_frontend.h" #include "bcm3510.h" @@ -52,7 +53,7 @@ struct bcm3510_state { struct dvb_frontend frontend; /* demodulator private data */ - struct semaphore hab_sem; + struct mutex hab_mutex; u8 firmware_loaded:1; unsigned long next_status_check; @@ -213,7 +214,7 @@ static int bcm3510_do_hab_cmd(struct bcm3510_state *st, u8 cmd, u8 msgid, u8 *ob dbufout(ob,olen+2,deb_hab); deb_hab("\n"); - if (down_interruptible(&st->hab_sem) < 0) + if (mutex_lock_interruptible(&st->hab_mutex) < 0) return -EAGAIN; if ((ret = bcm3510_hab_send_request(st, ob, olen+2)) < 0 || @@ -226,7 +227,7 @@ static int bcm3510_do_hab_cmd(struct bcm3510_state *st, u8 cmd, u8 msgid, u8 *ob memcpy(ibuf,&ib[2],ilen); error: - up(&st->hab_sem); + mutex_unlock(&st->hab_mutex); return ret; } @@ -796,7 +797,7 @@ struct dvb_frontend* bcm3510_attach(const struct bcm3510_config *config, state->frontend.ops = &state->ops; state->frontend.demodulator_priv = state; - sema_init(&state->hab_sem, 1); + mutex_init(&state->hab_mutex); if ((ret = bcm3510_readB(state,0xe0,&v)) < 0) goto error; diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index d36369e9e88f..1aa61bf29ad6 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -54,7 +54,6 @@ #include #include -#include #include @@ -242,10 +241,10 @@ static int arm_thread(void *data) if (!av7110->arm_ready) continue; - if (down_interruptible(&av7110->dcomlock)) + if (mutex_lock_interruptible(&av7110->dcomlock)) break; newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); if (newloops == av7110->arm_loops || av7110->arm_errors > 3) { printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n", @@ -253,10 +252,10 @@ static int arm_thread(void *data) recover_arm(av7110); - if (down_interruptible(&av7110->dcomlock)) + if (mutex_lock_interruptible(&av7110->dcomlock)) break; newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1; - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); } av7110->arm_loops = newloops; av7110->arm_errors = 0; @@ -741,7 +740,7 @@ int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, int ret = 0; dprintk(4, "%p\n", av7110); - if (down_interruptible(&av7110->pid_mutex)) + if (mutex_lock_interruptible(&av7110->pid_mutex)) return -ERESTARTSYS; if (!(vpid & 0x8000)) @@ -760,7 +759,7 @@ int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid); } - up(&av7110->pid_mutex); + mutex_unlock(&av7110->pid_mutex); return ret; } @@ -2096,7 +2095,7 @@ static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status) if (av7110->playing) return 0; - if (down_interruptible(&av7110->pid_mutex)) + if (mutex_lock_interruptible(&av7110->pid_mutex)) return -ERESTARTSYS; if (synced) { @@ -2118,7 +2117,7 @@ static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status) if (!ret) av7110->fe_synced = synced; - up(&av7110->pid_mutex); + mutex_unlock(&av7110->pid_mutex); return ret; } @@ -2713,16 +2712,16 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110); tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110); - sema_init(&av7110->pid_mutex, 1); + mutex_init(&av7110->pid_mutex); /* locks for data transfers from/to AV7110 */ spin_lock_init(&av7110->debilock); - sema_init(&av7110->dcomlock, 1); + mutex_init(&av7110->dcomlock); av7110->debitype = -1; /* default OSD window */ av7110->osdwin = 1; - sema_init(&av7110->osd_sema, 1); + mutex_init(&av7110->osd_mutex); /* ARM "watchdog" */ init_waitqueue_head(&av7110->arm_wait); diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h index fafd25fab835..3e2e12124bae 100644 --- a/drivers/media/dvb/ttpci/av7110.h +++ b/drivers/media/dvb/ttpci/av7110.h @@ -16,6 +16,7 @@ #include #include #include +#include #include "dvbdev.h" #include "demux.h" @@ -127,7 +128,7 @@ struct av7110 { /* DEBI and polled command interface */ spinlock_t debilock; - struct semaphore dcomlock; + struct mutex dcomlock; volatile int debitype; volatile int debilen; @@ -146,7 +147,7 @@ struct av7110 { int osdwin; /* currently active window */ u16 osdbpp[8]; - struct semaphore osd_sema; + struct mutex osd_mutex; /* CA */ @@ -172,7 +173,7 @@ struct av7110 { struct tasklet_struct vpe_tasklet; int fe_synced; - struct semaphore pid_mutex; + struct mutex pid_mutex; int video_blank; struct video_status videostate; diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c index b2e63e9fc053..3c5366d15a8a 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.c +++ b/drivers/media/dvb/ttpci/av7110_hw.c @@ -324,10 +324,10 @@ int av7110_wait_msgstate(struct av7110 *av7110, u16 flags) start = jiffies; for (;;) { err = time_after(jiffies, start + ARM_WAIT_FREE); - if (down_interruptible(&av7110->dcomlock)) + if (mutex_lock_interruptible(&av7110->dcomlock)) return -ERESTARTSYS; stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); if ((stat & flags) == 0) break; if (err) { @@ -484,11 +484,11 @@ static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) dprintk(1, "arm not ready.\n"); return -1; } - if (down_interruptible(&av7110->dcomlock)) + if (mutex_lock_interruptible(&av7110->dcomlock)) return -ERESTARTSYS; ret = __av7110_send_fw_cmd(av7110, buf, length); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); if (ret && ret!=-ERESTARTSYS) printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n", __FUNCTION__, ret); @@ -560,11 +560,11 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, return -1; } - if (down_interruptible(&av7110->dcomlock)) + if (mutex_lock_interruptible(&av7110->dcomlock)) return -ERESTARTSYS; if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) { - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); printk(KERN_ERR "dvb-ttpci: av7110_fw_request error %d\n", err); return err; } @@ -576,7 +576,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, break; if (err) { printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); return -ETIMEDOUT; } #ifdef _NOHANDSHAKE @@ -592,7 +592,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, break; if (err) { printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); return -ETIMEDOUT; } msleep(1); @@ -603,12 +603,12 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); if (stat & GPMQOver) { printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); return -1; } else if (stat & OSDQOver) { printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); return -1; } #endif @@ -616,7 +616,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, for (i = 0; i < reply_buf_len; i++) reply_buf[i] = rdebi(av7110, DEBINOSWAP, COM_BUFF + 2 * i, 0, 2); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); return 0; } @@ -732,7 +732,7 @@ static int FlushText(struct av7110 *av7110) unsigned long start; int err; - if (down_interruptible(&av7110->dcomlock)) + if (mutex_lock_interruptible(&av7110->dcomlock)) return -ERESTARTSYS; start = jiffies; while (1) { @@ -742,12 +742,12 @@ static int FlushText(struct av7110 *av7110) if (err) { printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n", __FUNCTION__); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); return -ETIMEDOUT; } msleep(1); } - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); return 0; } @@ -758,7 +758,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf) int length = strlen(buf) + 1; u16 cbuf[5] = { (COMTYPE_OSD << 8) + DText, 3, win, x, y }; - if (down_interruptible(&av7110->dcomlock)) + if (mutex_lock_interruptible(&av7110->dcomlock)) return -ERESTARTSYS; start = jiffies; @@ -769,7 +769,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf) if (ret) { printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n", __FUNCTION__); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); return -ETIMEDOUT; } msleep(1); @@ -783,7 +783,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf) if (ret) { printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); return -ETIMEDOUT; } msleep(1); @@ -795,7 +795,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf) if (length & 1) wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 0, 2); ret = __av7110_send_fw_cmd(av7110, cbuf, 5); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); if (ret && ret!=-ERESTARTSYS) printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret); return ret; @@ -1059,7 +1059,7 @@ int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc) { int ret; - if (down_interruptible(&av7110->osd_sema)) + if (mutex_lock_interruptible(&av7110->osd_mutex)) return -ERESTARTSYS; switch (dc->cmd) { @@ -1195,7 +1195,7 @@ int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc) break; } - up(&av7110->osd_sema); + mutex_unlock(&av7110->osd_mutex); if (ret==-ERESTARTSYS) dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc->cmd); else if (ret) diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h index c7bb63c4d98d..4ac0f4d08025 100644 --- a/drivers/media/dvb/ttpci/budget.h +++ b/drivers/media/dvb/ttpci/budget.h @@ -10,6 +10,8 @@ #include "dvb_net.h" #include +#include + #include extern int budget_debug; @@ -51,7 +53,7 @@ struct budget { struct dmx_frontend mem_frontend; int fe_synced; - struct semaphore pid_mutex; + struct mutex pid_mutex; int ci_present; int video_port; diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index 5a13c4744f61..ecb15d4ecf81 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include "dvb_frontend.h" #include "dmxdev.h" @@ -35,7 +35,6 @@ #include #include - /* TTUSB_HWSECTIONS: the DSP supports filtering in hardware, however, since the "muxstream" @@ -83,8 +82,8 @@ struct ttusb { struct dvb_net dvbnet; /* and one for USB access. */ - struct semaphore semi2c; - struct semaphore semusb; + struct mutex semi2c; + struct mutex semusb; struct dvb_adapter adapter; struct usb_device *dev; @@ -150,7 +149,7 @@ static int ttusb_cmd(struct ttusb *ttusb, printk("\n"); #endif - if (down_interruptible(&ttusb->semusb) < 0) + if (mutex_lock_interruptible(&ttusb->semusb) < 0) return -EAGAIN; err = usb_bulk_msg(ttusb->dev, ttusb->bulk_out_pipe, @@ -158,13 +157,13 @@ static int ttusb_cmd(struct ttusb *ttusb, if (err != 0) { dprintk("%s: usb_bulk_msg(send) failed, err == %i!\n", __FUNCTION__, err); - up(&ttusb->semusb); + mutex_unlock(&ttusb->semusb); return err; } if (actual_len != len) { dprintk("%s: only wrote %d of %d bytes\n", __FUNCTION__, actual_len, len); - up(&ttusb->semusb); + mutex_unlock(&ttusb->semusb); return -1; } @@ -174,7 +173,7 @@ static int ttusb_cmd(struct ttusb *ttusb, if (err != 0) { printk("%s: failed, receive error %d\n", __FUNCTION__, err); - up(&ttusb->semusb); + mutex_unlock(&ttusb->semusb); return err; } #if DEBUG >= 3 @@ -185,14 +184,14 @@ static int ttusb_cmd(struct ttusb *ttusb, printk("\n"); #endif if (!needresult) - up(&ttusb->semusb); + mutex_unlock(&ttusb->semusb); return 0; } static int ttusb_result(struct ttusb *ttusb, u8 * data, int len) { memcpy(data, ttusb->last_result, len); - up(&ttusb->semusb); + mutex_unlock(&ttusb->semusb); return 0; } @@ -250,7 +249,7 @@ static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num int i = 0; int inc; - if (down_interruptible(&ttusb->semi2c) < 0) + if (mutex_lock_interruptible(&ttusb->semi2c) < 0) return -EAGAIN; while (i < num) { @@ -284,7 +283,7 @@ static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num i += inc; } - up(&ttusb->semi2c); + mutex_unlock(&ttusb->semi2c); return i; } @@ -1495,8 +1494,11 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i ttusb->dev = udev; ttusb->c = 0; ttusb->mux_state = 0; - sema_init(&ttusb->semi2c, 0); - sema_init(&ttusb->semusb, 1); + mutex_init(&ttusb->semi2c); + + mutex_lock(&ttusb->semi2c); + + mutex_init(&ttusb->semusb); ttusb_setup_interfaces(ttusb); @@ -1504,7 +1506,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i if (ttusb_init_controller(ttusb)) printk("ttusb_init_controller: error\n"); - up(&ttusb->semi2c); + mutex_unlock(&ttusb->semi2c); dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE); ttusb->adapter.priv = ttusb; diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index df831171e03c..44dea3211848 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -20,7 +20,8 @@ * */ -#include +#include + #include #include #include @@ -115,7 +116,7 @@ struct ttusb_dec { unsigned int out_pipe; unsigned int irq_pipe; enum ttusb_dec_interface interface; - struct semaphore usb_sem; + struct mutex usb_mutex; void *irq_buffer; struct urb *irq_urb; @@ -124,7 +125,7 @@ struct ttusb_dec { dma_addr_t iso_dma_handle; struct urb *iso_urb[ISO_BUF_COUNT]; int iso_stream_count; - struct semaphore iso_sem; + struct mutex iso_mutex; u8 packet[MAX_PVA_LENGTH + 4]; enum ttusb_dec_packet_type packet_type; @@ -273,9 +274,9 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, if (!b) return -ENOMEM; - if ((result = down_interruptible(&dec->usb_sem))) { + if ((result = mutex_lock_interruptible(&dec->usb_mutex))) { kfree(b); - printk("%s: Failed to down usb semaphore.\n", __FUNCTION__); + printk("%s: Failed to lock usb mutex.\n", __FUNCTION__); return result; } @@ -300,7 +301,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, if (result) { printk("%s: command bulk message failed: error %d\n", __FUNCTION__, result); - up(&dec->usb_sem); + mutex_unlock(&dec->usb_mutex); kfree(b); return result; } @@ -311,7 +312,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, if (result) { printk("%s: result bulk message failed: error %d\n", __FUNCTION__, result); - up(&dec->usb_sem); + mutex_unlock(&dec->usb_mutex); kfree(b); return result; } else { @@ -327,7 +328,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, if (cmd_result && b[3] > 0) memcpy(cmd_result, &b[4], b[3]); - up(&dec->usb_sem); + mutex_unlock(&dec->usb_mutex); kfree(b); return 0; @@ -835,7 +836,7 @@ static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec) dprintk("%s\n", __FUNCTION__); - if (down_interruptible(&dec->iso_sem)) + if (mutex_lock_interruptible(&dec->iso_mutex)) return; dec->iso_stream_count--; @@ -845,7 +846,7 @@ static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec) usb_kill_urb(dec->iso_urb[i]); } - up(&dec->iso_sem); + mutex_unlock(&dec->iso_mutex); } /* Setting the interface of the DEC tends to take down the USB communications @@ -890,7 +891,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec) dprintk("%s\n", __FUNCTION__); - if (down_interruptible(&dec->iso_sem)) + if (mutex_lock_interruptible(&dec->iso_mutex)) return -EAGAIN; if (!dec->iso_stream_count) { @@ -911,7 +912,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec) i--; } - up(&dec->iso_sem); + mutex_unlock(&dec->iso_mutex); return result; } } @@ -919,7 +920,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec) dec->iso_stream_count++; - up(&dec->iso_sem); + mutex_unlock(&dec->iso_mutex); return 0; } @@ -1229,8 +1230,8 @@ static int ttusb_dec_init_usb(struct ttusb_dec *dec) { dprintk("%s\n", __FUNCTION__); - sema_init(&dec->usb_sem, 1); - sema_init(&dec->iso_sem, 1); + mutex_init(&dec->usb_mutex); + mutex_init(&dec->iso_mutex); dec->command_pipe = usb_sndbulkpipe(dec->udev, COMMAND_PIPE); dec->result_pipe = usb_rcvbulkpipe(dec->udev, RESULT_PIPE); diff --git a/drivers/media/radio/miropcm20-rds-core.c b/drivers/media/radio/miropcm20-rds-core.c index a917a90cb5dc..b602c73e2309 100644 --- a/drivers/media/radio/miropcm20-rds-core.c +++ b/drivers/media/radio/miropcm20-rds-core.c @@ -18,14 +18,15 @@ #include #include #include -#include +#include + #include #include "../../../sound/oss/aci.h" #include "miropcm20-rds-core.h" #define DEBUG 0 -static struct semaphore aci_rds_sem; +static struct mutex aci_rds_mutex; #define RDS_DATASHIFT 2 /* Bit 2 */ #define RDS_DATAMASK (1 << RDS_DATASHIFT) @@ -181,7 +182,7 @@ int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize) { int ret; - if (down_interruptible(&aci_rds_sem)) + if (mutex_lock_interruptible(&aci_rds_mutex)) return -EINTR; rds_write(cmd); @@ -192,7 +193,7 @@ int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize) else ret = 0; - up(&aci_rds_sem); + mutex_unlock(&aci_rds_mutex); return ret; } @@ -200,7 +201,7 @@ EXPORT_SYMBOL(aci_rds_cmd); int __init attach_aci_rds(void) { - init_MUTEX(&aci_rds_sem); + mutex_init(&aci_rds_mutex); return 0; } diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index 914deab4e044..557fb5c4af38 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -43,7 +43,7 @@ static int io = CONFIG_RADIO_RTRACK_PORT; static int radio_nr = -1; -static struct semaphore lock; +static struct mutex lock; struct rt_device { @@ -83,23 +83,23 @@ static void rt_incvol(void) static void rt_mute(struct rt_device *dev) { dev->muted = 1; - down(&lock); + mutex_lock(&lock); outb(0xd0, io); /* volume steady, off */ - up(&lock); + mutex_unlock(&lock); } static int rt_setvol(struct rt_device *dev, int vol) { int i; - down(&lock); + mutex_lock(&lock); if(vol == dev->curvol) { /* requested volume = current */ if (dev->muted) { /* user is unmuting the card */ dev->muted = 0; outb (0xd8, io); /* enable card */ } - up(&lock); + mutex_unlock(&lock); return 0; } @@ -108,7 +108,7 @@ static int rt_setvol(struct rt_device *dev, int vol) sleep_delay(2000000); /* make sure it's totally down */ outb(0xd0, io); /* volume steady, off */ dev->curvol = 0; /* track the volume state! */ - up(&lock); + mutex_unlock(&lock); return 0; } @@ -121,7 +121,7 @@ static int rt_setvol(struct rt_device *dev, int vol) rt_decvol(); dev->curvol = vol; - up(&lock); + mutex_unlock(&lock); return 0; } @@ -168,7 +168,7 @@ static int rt_setfreq(struct rt_device *dev, unsigned long freq) freq += 171200; /* Add 10.7 MHz IF */ freq /= 800; /* Convert to 50 kHz units */ - down(&lock); /* Stop other ops interfering */ + mutex_lock(&lock); /* Stop other ops interfering */ send_0_byte (io, dev); /* 0: LSB of frequency */ @@ -196,7 +196,7 @@ static int rt_setfreq(struct rt_device *dev, unsigned long freq) else outb (0xd8, io); /* volume steady + sigstr + on */ - up(&lock); + mutex_unlock(&lock); return 0; } @@ -337,7 +337,7 @@ static int __init rtrack_init(void) /* Set up the I/O locking */ - init_MUTEX(&lock); + mutex_init(&lock); /* mute card - prevents noisy bootups */ diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index 523be820f9c6..83bdae23417d 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c @@ -42,7 +42,7 @@ static int io = CONFIG_RADIO_AZTECH_PORT; static int radio_nr = -1; static int radio_wait_time = 1000; -static struct semaphore lock; +static struct mutex lock; struct az_device { @@ -87,9 +87,9 @@ static void send_1_byte (struct az_device *dev) static int az_setvol(struct az_device *dev, int vol) { - down(&lock); + mutex_lock(&lock); outb (volconvert(vol), io); - up(&lock); + mutex_unlock(&lock); return 0; } @@ -122,7 +122,7 @@ static int az_setfreq(struct az_device *dev, unsigned long frequency) frequency += 171200; /* Add 10.7 MHz IF */ frequency /= 800; /* Convert to 50 kHz units */ - down(&lock); + mutex_lock(&lock); send_0_byte (dev); /* 0: LSB of frequency */ @@ -152,7 +152,7 @@ static int az_setfreq(struct az_device *dev, unsigned long frequency) udelay (radio_wait_time); outb_p(128+64+volconvert(dev->curvol), io); - up(&lock); + mutex_unlock(&lock); return 0; } @@ -283,7 +283,7 @@ static int __init aztech_init(void) return -EBUSY; } - init_MUTEX(&lock); + mutex_init(&lock); aztech_radio.priv=&aztech_unit; if(video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr)==-1) diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c index 36c9f5bf8cdd..39c1d9118636 100644 --- a/drivers/media/radio/radio-maestro.c +++ b/drivers/media/radio/radio-maestro.c @@ -23,10 +23,11 @@ #include #include #include -#include +#include #include #include + #define DRIVER_VERSION "0.05" #define GPIO_DATA 0x60 /* port offset from ESS_IO_BASE */ @@ -104,7 +105,7 @@ struct radio_device { muted, /* VIDEO_AUDIO_MUTE */ stereo, /* VIDEO_TUNER_STEREO_ON */ tuned; /* signal strength (0 or 0xffff) */ - struct semaphore lock; + struct mutex lock; }; static u32 radio_bits_get(struct radio_device *dev) @@ -258,9 +259,9 @@ static int radio_ioctl(struct inode *inode, struct file *file, struct radio_device *card = video_get_drvdata(dev); int ret; - down(&card->lock); + mutex_lock(&card->lock); ret = video_usercopy(inode, file, cmd, arg, radio_function); - up(&card->lock); + mutex_unlock(&card->lock); return ret; } @@ -311,7 +312,7 @@ static int __devinit maestro_probe(struct pci_dev *pdev, } radio_unit->io = pci_resource_start(pdev, 0) + GPIO_DATA; - init_MUTEX(&radio_unit->lock); + mutex_init(&radio_unit->lock); maestro_radio_inst = video_device_alloc(); if (maestro_radio_inst == NULL) { diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index c975ddd86cd5..f0bf47bcb64c 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -37,7 +37,8 @@ #include #include #include -#include +#include + #include #include @@ -101,7 +102,7 @@ static struct radio_device unsigned long freq; - struct semaphore lock; + struct mutex lock; } radio_unit = {0, 0, 0, 0, }; @@ -267,9 +268,9 @@ static int radio_ioctl(struct inode *inode, struct file *file, struct radio_device *card=dev->priv; int ret; - down(&card->lock); + mutex_lock(&card->lock); ret = video_usercopy(inode, file, cmd, arg, radio_function); - up(&card->lock); + mutex_unlock(&card->lock); return ret; } @@ -290,7 +291,7 @@ static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_d goto err_out_free_region; radio_unit.io = pci_resource_start(pdev, 0); - init_MUTEX(&radio_unit.lock); + mutex_init(&radio_unit.lock); maxiradio_radio.priv = &radio_unit; if(video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr)==-1) { diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 0229f792a059..53073b424107 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -24,7 +24,7 @@ #include #include /* outb, outb_p */ #include /* copy to/from user */ -#include +#include struct fmi_device { @@ -37,7 +37,7 @@ struct fmi_device static int io = -1; static int radio_nr = -1; static struct pnp_dev *dev = NULL; -static struct semaphore lock; +static struct mutex lock; /* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */ /* It is only useful to give freq in intervall of 800 (=0.05Mhz), @@ -68,16 +68,16 @@ static void outbits(int bits, unsigned int data, int port) static inline void fmi_mute(int port) { - down(&lock); + mutex_lock(&lock); outb(0x00, port); - up(&lock); + mutex_unlock(&lock); } static inline void fmi_unmute(int port) { - down(&lock); + mutex_lock(&lock); outb(0x08, port); - up(&lock); + mutex_unlock(&lock); } static inline int fmi_setfreq(struct fmi_device *dev) @@ -85,12 +85,12 @@ static inline int fmi_setfreq(struct fmi_device *dev) int myport = dev->port; unsigned long freq = dev->curfreq; - down(&lock); + mutex_lock(&lock); outbits(16, RSF16_ENCODE(freq), myport); outbits(8, 0xC0, myport); msleep(143); /* was schedule_timeout(HZ/7) */ - up(&lock); + mutex_unlock(&lock); if (dev->curvol) fmi_unmute(myport); return 0; } @@ -102,7 +102,7 @@ static inline int fmi_getsigstr(struct fmi_device *dev) int myport = dev->port; - down(&lock); + mutex_lock(&lock); val = dev->curvol ? 0x08 : 0x00; /* unmute/mute */ outb(val, myport); outb(val | 0x10, myport); @@ -110,7 +110,7 @@ static inline int fmi_getsigstr(struct fmi_device *dev) res = (int)inb(myport+1); outb(val, myport); - up(&lock); + mutex_unlock(&lock); return (res & 2) ? 0 : 0xFFFF; } @@ -296,7 +296,7 @@ static int __init fmi_init(void) fmi_unit.flags = VIDEO_TUNER_LOW; fmi_radio.priv = &fmi_unit; - init_MUTEX(&lock); + mutex_init(&lock); if (video_register_device(&fmi_radio, VFL_TYPE_RADIO, radio_nr) == -1) { release_region(io, 2); diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 099ffb3b9c71..bcebd8cb19ad 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -19,9 +19,9 @@ #include /* outb, outb_p */ #include /* copy to/from user */ #include /* kernel radio structs */ -#include +#include -static struct semaphore lock; +static struct mutex lock; #undef DEBUG //#define DEBUG 1 @@ -238,9 +238,9 @@ static int fmr2_do_ioctl(struct inode *inode, struct file *file, if (fmr2->mute) v->flags |= VIDEO_AUDIO_MUTE; v->mode=VIDEO_MODE_AUTO; - down(&lock); + mutex_lock(&lock); v->signal = fmr2_getsigstr(fmr2); - up(&lock); + mutex_unlock(&lock); return 0; } case VIDIOCSTUNER: @@ -274,9 +274,9 @@ static int fmr2_do_ioctl(struct inode *inode, struct file *file, /* set card freq (if not muted) */ if (fmr2->curvol && !fmr2->mute) { - down(&lock); + mutex_lock(&lock); fmr2_setfreq(fmr2); - up(&lock); + mutex_unlock(&lock); } return 0; } @@ -318,14 +318,14 @@ static int fmr2_do_ioctl(struct inode *inode, struct file *file, else printk(KERN_DEBUG "mute\n"); #endif - down(&lock); + mutex_lock(&lock); if (fmr2->curvol && !fmr2->mute) { fmr2_setvolume(fmr2); fmr2_setfreq(fmr2); } else fmr2_mute(fmr2->port); - up(&lock); + mutex_unlock(&lock); return 0; } case VIDIOCGUNIT: @@ -380,7 +380,7 @@ static int __init fmr2_init(void) fmr2_unit.card_type = 0; fmr2_radio.priv = &fmr2_unit; - init_MUTEX(&lock); + mutex_init(&lock); if (request_region(io, 2, "sf16fmr2")) { @@ -397,10 +397,10 @@ static int __init fmr2_init(void) printk(KERN_INFO "SF16FMR2 radio card driver at 0x%x.\n", io); debug_print((KERN_DEBUG "Mute %d Low %d\n",VIDEO_AUDIO_MUTE,VIDEO_TUNER_LOW)); /* mute card - prevents noisy bootups */ - down(&lock); + mutex_lock(&lock); fmr2_mute(io); fmr2_product_info(&fmr2_unit); - up(&lock); + mutex_unlock(&lock); debug_print((KERN_DEBUG "card_type %d\n", fmr2_unit.card_type)); return 0; } diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c index 8ac9a8ef9094..e50955836d6b 100644 --- a/drivers/media/radio/radio-typhoon.c +++ b/drivers/media/radio/radio-typhoon.c @@ -59,7 +59,7 @@ struct typhoon_device { int muted; unsigned long curfreq; unsigned long mutefreq; - struct semaphore lock; + struct mutex lock; }; static void typhoon_setvol_generic(struct typhoon_device *dev, int vol); @@ -77,12 +77,12 @@ static int typhoon_get_info(char *buf, char **start, off_t offset, int len); static void typhoon_setvol_generic(struct typhoon_device *dev, int vol) { - down(&dev->lock); + mutex_lock(&dev->lock); vol >>= 14; /* Map 16 bit to 2 bit */ vol &= 3; outb_p(vol / 2, dev->iobase); /* Set the volume, high bit. */ outb_p(vol % 2, dev->iobase + 2); /* Set the volume, low bit. */ - up(&dev->lock); + mutex_unlock(&dev->lock); } static int typhoon_setfreq_generic(struct typhoon_device *dev, @@ -102,7 +102,7 @@ static int typhoon_setfreq_generic(struct typhoon_device *dev, * */ - down(&dev->lock); + mutex_lock(&dev->lock); x = frequency / 160; outval = (x * x + 2500) / 5000; outval = (outval * x + 5000) / 10000; @@ -112,7 +112,7 @@ static int typhoon_setfreq_generic(struct typhoon_device *dev, outb_p((outval >> 8) & 0x01, dev->iobase + 4); outb_p(outval >> 9, dev->iobase + 6); outb_p(outval & 0xff, dev->iobase + 8); - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } @@ -337,7 +337,7 @@ static int __init typhoon_init(void) #endif /* MODULE */ printk(KERN_INFO BANNER); - init_MUTEX(&typhoon_unit.lock); + mutex_init(&typhoon_unit.lock); io = typhoon_unit.iobase; if (!request_region(io, 8, "typhoon")) { printk(KERN_ERR "radio-typhoon: port 0x%x already in use\n", diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index d590e80c922e..7bf1a4264891 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c @@ -48,7 +48,7 @@ struct zol_device { unsigned long curfreq; int muted; unsigned int stereo; - struct semaphore lock; + struct mutex lock; }; static int zol_setvol(struct zol_device *dev, int vol) @@ -57,30 +57,30 @@ static int zol_setvol(struct zol_device *dev, int vol) if (dev->muted) return 0; - down(&dev->lock); + mutex_lock(&dev->lock); if (vol == 0) { outb(0, io); outb(0, io); inb(io + 3); /* Zoltrix needs to be read to confirm */ - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } outb(dev->curvol-1, io); msleep(10); inb(io + 2); - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } static void zol_mute(struct zol_device *dev) { dev->muted = 1; - down(&dev->lock); + mutex_lock(&dev->lock); outb(0, io); outb(0, io); inb(io + 3); /* Zoltrix needs to be read to confirm */ - up(&dev->lock); + mutex_unlock(&dev->lock); } static void zol_unmute(struct zol_device *dev) @@ -104,7 +104,7 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq) bitmask = 0xc480402c10080000ull; i = 45; - down(&dev->lock); + mutex_lock(&dev->lock); outb(0, io); outb(0, io); @@ -149,7 +149,7 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq) udelay(1000); } - up(&dev->lock); + mutex_unlock(&dev->lock); if(!dev->muted) { @@ -164,7 +164,7 @@ static int zol_getsigstr(struct zol_device *dev) { int a, b; - down(&dev->lock); + mutex_lock(&dev->lock); outb(0x00, io); /* This stuff I found to do nothing */ outb(dev->curvol, io); msleep(20); @@ -173,7 +173,7 @@ static int zol_getsigstr(struct zol_device *dev) msleep(10); b = inb(io); - up(&dev->lock); + mutex_unlock(&dev->lock); if (a != b) return (0); @@ -188,7 +188,7 @@ static int zol_is_stereo (struct zol_device *dev) { int x1, x2; - down(&dev->lock); + mutex_lock(&dev->lock); outb(0x00, io); outb(dev->curvol, io); @@ -198,7 +198,7 @@ static int zol_is_stereo (struct zol_device *dev) msleep(10); x2 = inb(io); - up(&dev->lock); + mutex_unlock(&dev->lock); if ((x1 == x2) && (x1 == 0xcf)) return 1; @@ -350,7 +350,7 @@ static int __init zoltrix_init(void) } printk(KERN_INFO "Zoltrix Radio Plus card driver.\n"); - init_MUTEX(&zoltrix_unit.lock); + mutex_init(&zoltrix_unit.lock); /* mute card - prevents noisy bootups */ diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index 994b75fe165a..c586f64b6b7f 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -31,8 +31,8 @@ #include #include #include +#include -#include #include #include #include @@ -117,7 +117,7 @@ struct ar_device { int width, height; int frame_bytes, line_bytes; wait_queue_head_t wait; - struct semaphore lock; + struct mutex lock; }; static int video_nr = -1; /* video device number (first free) */ @@ -288,7 +288,7 @@ static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) if (ar->mode == AR_MODE_NORMAL) arvcr1 |= ARVCR1_NORMAL; - down(&ar->lock); + mutex_lock(&ar->lock); #if USE_INT local_irq_save(flags); @@ -392,7 +392,7 @@ static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) } DEBUG(1, "ret = %d\n", ret); out_up: - up(&ar->lock); + mutex_unlock(&ar->lock); return ret; } @@ -456,7 +456,7 @@ static int ar_do_ioctl(struct inode *inode, struct file *file, (w->width != AR_WIDTH_QVGA || w->height != AR_HEIGHT_QVGA)) return -EINVAL; - down(&ar->lock); + mutex_lock(&ar->lock); ar->width = w->width; ar->height = w->height; if (ar->width == AR_WIDTH_VGA) { @@ -473,7 +473,7 @@ static int ar_do_ioctl(struct inode *inode, struct file *file, ar->line_bytes = AR_LINE_BYTES_QVGA; ar->mode = AR_MODE_INTERLACE; } - up(&ar->lock); + mutex_unlock(&ar->lock); return 0; } case VIDIOCGFBUF: @@ -734,7 +734,7 @@ static int ar_initialize(struct video_device *dev) void ar_release(struct video_device *vfd) { struct ar_device *ar = vfd->priv; - down(&ar->lock); + mutex_lock(&ar->lock); video_device_release(vfd); } @@ -824,7 +824,7 @@ static int __init ar_init(void) ar->line_bytes = AR_LINE_BYTES_QVGA; ar->mode = AR_MODE_INTERLACE; } - init_MUTEX(&ar->lock); + mutex_init(&ar->lock); init_waitqueue_head(&ar->wait); #if USE_INT diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 578b20085082..c0415d6e7fee 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -1965,7 +1965,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv, BUG(); } - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); kfree(fh->ov.clips); fh->ov.clips = clips; fh->ov.nclips = n; @@ -1986,7 +1986,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv, bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); retval = bttv_switch_overlay(btv,fh,new); } - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return retval; } @@ -2166,7 +2166,7 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, fmt = format_by_fourcc(f->fmt.pix.pixelformat); /* update our state informations */ - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); fh->fmt = fmt; fh->cap.field = f->fmt.pix.field; fh->cap.last = V4L2_FIELD_NONE; @@ -2175,7 +2175,7 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, btv->init.fmt = fmt; btv->init.width = f->fmt.pix.width; btv->init.height = f->fmt.pix.height; - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return 0; } @@ -2282,7 +2282,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, fmt = format_by_palette(pic->palette); if (NULL == fmt) return -EINVAL; - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); if (fmt->depth != pic->depth) { retval = -EINVAL; goto fh_unlock_and_return; @@ -2313,7 +2313,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, bt848_contrast(btv,pic->contrast); bt848_hue(btv,pic->hue); bt848_sat(btv,pic->colour); - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return 0; } @@ -2379,7 +2379,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, return -EPERM; end = (unsigned long)fbuf->base + fbuf->height * fbuf->bytesperline; - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); retval = -EINVAL; switch (fbuf->depth) { @@ -2417,7 +2417,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, btv->fbuf.fmt.bytesperline = fbuf->bytesperline; else btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fbuf->depth/8; - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return 0; } @@ -2440,7 +2440,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY)) return -EBUSY; - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); if (*on) { fh->ov.tvnorm = btv->tvnorm; new = videobuf_alloc(sizeof(*new)); @@ -2451,7 +2451,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, /* switch over */ retval = bttv_switch_overlay(btv,fh,new); - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return retval; } @@ -2460,7 +2460,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, struct video_mbuf *mbuf = arg; unsigned int i; - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); retval = videobuf_mmap_setup(&fh->cap,gbuffers,gbufsize, V4L2_MEMORY_MMAP); if (retval < 0) @@ -2470,7 +2470,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, mbuf->size = gbuffers * gbufsize; for (i = 0; i < gbuffers; i++) mbuf->offsets[i] = i * gbufsize; - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return 0; } case VIDIOCMCAPTURE: @@ -2482,7 +2482,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (vm->frame >= VIDEO_MAX_FRAME) return -EINVAL; - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); retval = -EINVAL; buf = (struct bttv_buffer *)fh->cap.bufs[vm->frame]; if (NULL == buf) @@ -2504,7 +2504,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, spin_lock_irqsave(&btv->s_lock,flags); buffer_queue(&fh->cap,&buf->vb); spin_unlock_irqrestore(&btv->s_lock,flags); - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return 0; } case VIDIOCSYNC: @@ -2515,7 +2515,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (*frame >= VIDEO_MAX_FRAME) return -EINVAL; - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); retval = -EINVAL; buf = (struct bttv_buffer *)fh->cap.bufs[*frame]; if (NULL == buf) @@ -2535,7 +2535,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, retval = -EINVAL; break; } - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return retval; } @@ -2719,7 +2719,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (0 == (fmt->flags & FORMAT_FLAGS_PACKED)) return -EINVAL; - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); retval = -EINVAL; if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) { if (fb->fmt.width > bttv_tvnorms[btv->tvnorm].swidth) @@ -2759,7 +2759,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, retval = bttv_switch_overlay(btv,fh,new); } } - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return retval; } @@ -2890,7 +2890,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, return 0; fh_unlock_and_return: - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return retval; } @@ -2957,16 +2957,16 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream); } else { /* read() capture */ - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); if (NULL == fh->cap.read_buf) { /* need to capture a new frame */ if (locked_btres(fh->btv,RESOURCE_VIDEO)) { - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return POLLERR; } fh->cap.read_buf = videobuf_alloc(fh->cap.msize); if (NULL == fh->cap.read_buf) { - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return POLLERR; } fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR; @@ -2974,13 +2974,13 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) { kfree (fh->cap.read_buf); fh->cap.read_buf = NULL; - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return POLLERR; } fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); fh->cap.read_off = 0; } - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); buf = (struct bttv_buffer*)fh->cap.read_buf; } diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 6bad93ef969f..d97b7d8ac33d 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c @@ -73,7 +73,7 @@ OTHER DEALINGS IN THE SOFTWARE. #include #include #include -#include +#include #include #include "bw-qcam.h" @@ -168,7 +168,7 @@ static struct qcam_device *qcam_init(struct parport *port) memcpy(&q->vdev, &qcam_template, sizeof(qcam_template)); - init_MUTEX(&q->lock); + mutex_init(&q->lock); q->port_mode = (QC_ANY | QC_NOTSET); q->width = 320; @@ -772,9 +772,9 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file, qcam->whitebal = p->whiteness>>8; qcam->bpp = p->depth; - down(&qcam->lock); + mutex_lock(&qcam->lock); qc_setscanmode(qcam); - up(&qcam->lock); + mutex_unlock(&qcam->lock); qcam->status |= QC_PARAM_CHANGE; return 0; @@ -805,9 +805,9 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file, qcam->height = 240; qcam->transfer_scale = 1; } - down(&qcam->lock); + mutex_lock(&qcam->lock); qc_setscanmode(qcam); - up(&qcam->lock); + mutex_unlock(&qcam->lock); /* We must update the camera before we grab. We could just have changed the grab size */ @@ -854,7 +854,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf, int len; parport_claim_or_block(qcam->pdev); - down(&qcam->lock); + mutex_lock(&qcam->lock); qc_reset(qcam); @@ -864,7 +864,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf, len=qc_capture(qcam, buf,count); - up(&qcam->lock); + mutex_unlock(&qcam->lock); parport_release(qcam->pdev); return len; diff --git a/drivers/media/video/bw-qcam.h b/drivers/media/video/bw-qcam.h index 723e8ad9e56a..6701dafbc0da 100644 --- a/drivers/media/video/bw-qcam.h +++ b/drivers/media/video/bw-qcam.h @@ -55,7 +55,7 @@ struct qcam_device { struct video_device vdev; struct pardevice *pdev; struct parport *pport; - struct semaphore lock; + struct mutex lock; int width, height; int bpp; int mode; diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index 9976db4f6da8..8211fd8d7cbf 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -34,7 +34,8 @@ #include #include #include -#include +#include + #include struct qcam_device { @@ -47,7 +48,7 @@ struct qcam_device { int contrast, brightness, whitebal; int top, left; unsigned int bidirectional; - struct semaphore lock; + struct mutex lock; }; /* cameras maximum */ @@ -581,11 +582,11 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file, qcam->contrast = p->contrast>>8; qcam->whitebal = p->whiteness>>8; - down(&qcam->lock); + mutex_lock(&qcam->lock); parport_claim_or_block(qcam->pdev); qc_setup(qcam); parport_release(qcam->pdev); - up(&qcam->lock); + mutex_unlock(&qcam->lock); return 0; } case VIDIOCSWIN: @@ -628,11 +629,11 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file, #endif /* Ok we figured out what to use from our wide choice */ - down(&qcam->lock); + mutex_lock(&qcam->lock); parport_claim_or_block(qcam->pdev); qc_setup(qcam); parport_release(qcam->pdev); - up(&qcam->lock); + mutex_unlock(&qcam->lock); return 0; } case VIDIOCGWIN: @@ -672,12 +673,12 @@ static ssize_t qcam_read(struct file *file, char __user *buf, struct qcam_device *qcam=(struct qcam_device *)v; int len; - down(&qcam->lock); + mutex_lock(&qcam->lock); parport_claim_or_block(qcam->pdev); /* Probably should have a semaphore against multiple users */ len = qc_capture(qcam, buf,count); parport_release(qcam->pdev); - up(&qcam->lock); + mutex_unlock(&qcam->lock); return len; } @@ -727,7 +728,7 @@ static struct qcam_device *qcam_init(struct parport *port) memcpy(&q->vdev, &qcam_template, sizeof(qcam_template)); - init_MUTEX(&q->lock); + mutex_init(&q->lock); q->width = q->ccd_width = 320; q->height = q->ccd_height = 240; q->mode = QC_MILLIONS | QC_DECIMATION_1; diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index 9f59541155d9..c2405029a720 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -39,7 +39,7 @@ #include #include #include -#include +#include #ifdef CONFIG_KMOD #include @@ -622,7 +622,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf, buffer = page; - if (down_interruptible(&cam->param_lock)) + if (mutex_lock_interruptible(&cam->param_lock)) return -ERESTARTSYS; /* @@ -1350,7 +1350,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf, } else DBG("error: %d\n", retval); - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); out: free_page((unsigned long)page); @@ -1664,7 +1664,7 @@ static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d) case CPIA_COMMAND_GetColourParams: case CPIA_COMMAND_GetColourBalance: case CPIA_COMMAND_GetExposure: - down(&cam->param_lock); + mutex_lock(&cam->param_lock); datasize=8; break; case CPIA_COMMAND_ReadMCPorts: @@ -1691,7 +1691,7 @@ static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d) if (command == CPIA_COMMAND_GetColourParams || command == CPIA_COMMAND_GetColourBalance || command == CPIA_COMMAND_GetExposure) - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); } else { switch(command) { case CPIA_COMMAND_GetCPIAVersion: @@ -1726,13 +1726,13 @@ static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d) cam->params.colourParams.brightness = data[0]; cam->params.colourParams.contrast = data[1]; cam->params.colourParams.saturation = data[2]; - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); break; case CPIA_COMMAND_GetColourBalance: cam->params.colourBalance.redGain = data[0]; cam->params.colourBalance.greenGain = data[1]; cam->params.colourBalance.blueGain = data[2]; - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); break; case CPIA_COMMAND_GetExposure: cam->params.exposure.gain = data[0]; @@ -1743,7 +1743,7 @@ static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d) cam->params.exposure.green1Comp = data[5]; cam->params.exposure.green2Comp = data[6]; cam->params.exposure.blueComp = data[7]; - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); break; case CPIA_COMMAND_ReadMCPorts: @@ -2059,7 +2059,7 @@ static int parse_picture(struct cam_data *cam, int size) int rows, cols, linesize, subsample_422; /* make sure params don't change while we are decoding */ - down(&cam->param_lock); + mutex_lock(&cam->param_lock); obuf = cam->decompressed_frame.data; end_obuf = obuf+CPIA_MAX_FRAME_SIZE; @@ -2069,26 +2069,26 @@ static int parse_picture(struct cam_data *cam, int size) if ((ibuf[0] != MAGIC_0) || (ibuf[1] != MAGIC_1)) { LOG("header not found\n"); - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return -1; } if ((ibuf[16] != VIDEOSIZE_QCIF) && (ibuf[16] != VIDEOSIZE_CIF)) { LOG("wrong video size\n"); - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return -1; } if (ibuf[17] != SUBSAMPLE_420 && ibuf[17] != SUBSAMPLE_422) { LOG("illegal subtype %d\n",ibuf[17]); - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return -1; } subsample_422 = ibuf[17] == SUBSAMPLE_422; if (ibuf[18] != YUVORDER_YUYV && ibuf[18] != YUVORDER_UYVY) { LOG("illegal yuvorder %d\n",ibuf[18]); - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return -1; } in_uyvy = ibuf[18] == YUVORDER_UYVY; @@ -2098,7 +2098,7 @@ static int parse_picture(struct cam_data *cam, int size) (ibuf[26] != cam->params.roi.rowStart) || (ibuf[27] != cam->params.roi.rowEnd)) { LOG("ROI mismatch\n"); - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return -1; } cols = 8*(ibuf[25] - ibuf[24]); @@ -2107,14 +2107,14 @@ static int parse_picture(struct cam_data *cam, int size) if ((ibuf[28] != NOT_COMPRESSED) && (ibuf[28] != COMPRESSED)) { LOG("illegal compression %d\n",ibuf[28]); - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return -1; } compressed = (ibuf[28] == COMPRESSED); if (ibuf[29] != NO_DECIMATION && ibuf[29] != DECIMATION_ENAB) { LOG("illegal decimation %d\n",ibuf[29]); - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return -1; } decimation = (ibuf[29] == DECIMATION_ENAB); @@ -2130,7 +2130,7 @@ static int parse_picture(struct cam_data *cam, int size) cam->params.status.vpStatus = ibuf[38]; cam->params.status.errorCode = ibuf[39]; cam->fps = ibuf[41]; - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); linesize = skipcount(cols, out_fmt); ibuf += FRAME_HEADER_SIZE; @@ -2271,9 +2271,9 @@ static int find_over_exposure(int brightness) /* update various camera modes and settings */ static void dispatch_commands(struct cam_data *cam) { - down(&cam->param_lock); + mutex_lock(&cam->param_lock); if (cam->cmd_queue==COMMAND_NONE) { - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return; } DEB_BYTE(cam->cmd_queue); @@ -2415,7 +2415,7 @@ static void dispatch_commands(struct cam_data *cam) } cam->cmd_queue = COMMAND_NONE; - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return; } @@ -2562,7 +2562,7 @@ static void monitor_exposure(struct cam_data *cam) gain = data[2]; coarseL = data[3]; - down(&cam->param_lock); + mutex_lock(&cam->param_lock); light_exp = cam->params.colourParams.brightness + TC - 50 + EXP_ACC_LIGHT; if(light_exp > 255) @@ -2762,7 +2762,7 @@ static void monitor_exposure(struct cam_data *cam) LOG("Automatically increasing sensor_fps\n"); } } - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); } /*-----------------------------------------------------------------*/ @@ -2778,10 +2778,10 @@ static void restart_flicker(struct cam_data *cam) int cam_exposure, old_exp; if(!FIRMWARE_VERSION(1,2)) return; - down(&cam->param_lock); + mutex_lock(&cam->param_lock); if(cam->params.flickerControl.flickerMode == 0 || cam->raw_image[39] == 0) { - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return; } cam_exposure = cam->raw_image[39]*2; @@ -2810,7 +2810,7 @@ static void restart_flicker(struct cam_data *cam) cam->exposure_status = EXPOSURE_NORMAL; } - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); } #undef FIRMWARE_VERSION @@ -3186,7 +3186,7 @@ static int cpia_open(struct inode *inode, struct file *file) if (!try_module_get(cam->ops->owner)) return -ENODEV; - down(&cam->busy_lock); + mutex_lock(&cam->busy_lock); err = -ENOMEM; if (!cam->raw_image) { cam->raw_image = rvmalloc(CPIA_MAX_IMAGE_SIZE); @@ -3227,7 +3227,7 @@ static int cpia_open(struct inode *inode, struct file *file) ++cam->open_count; file->private_data = dev; - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return 0; oops: @@ -3239,7 +3239,7 @@ static int cpia_open(struct inode *inode, struct file *file) rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE); cam->raw_image = NULL; } - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); put_cam(cam->ops); return err; } @@ -3303,24 +3303,24 @@ static ssize_t cpia_read(struct file *file, char __user *buf, int err; /* make this _really_ smp and multithread-safe */ - if (down_interruptible(&cam->busy_lock)) + if (mutex_lock_interruptible(&cam->busy_lock)) return -EINTR; if (!buf) { DBG("buf NULL\n"); - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return -EINVAL; } if (!count) { DBG("count 0\n"); - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return 0; } if (!cam->ops) { DBG("ops NULL\n"); - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return -ENODEV; } @@ -3329,7 +3329,7 @@ static ssize_t cpia_read(struct file *file, char __user *buf, cam->mmap_kludge=0; if((err = fetch_frame(cam)) != 0) { DBG("ERROR from fetch_frame: %d\n", err); - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return err; } cam->decompressed_frame.state = FRAME_UNUSED; @@ -3338,17 +3338,17 @@ static ssize_t cpia_read(struct file *file, char __user *buf, if (cam->decompressed_frame.count > count) { DBG("count wrong: %d, %lu\n", cam->decompressed_frame.count, (unsigned long) count); - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return -EFAULT; } if (copy_to_user(buf, cam->decompressed_frame.data, cam->decompressed_frame.count)) { DBG("copy_to_user failed\n"); - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return -EFAULT; } - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return cam->decompressed_frame.count; } @@ -3363,7 +3363,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, return -ENODEV; /* make this _really_ smp-safe */ - if (down_interruptible(&cam->busy_lock)) + if (mutex_lock_interruptible(&cam->busy_lock)) return -EINTR; //DBG("cpia_ioctl: %u\n", ioctlnr); @@ -3439,7 +3439,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, break; } - down(&cam->param_lock); + mutex_lock(&cam->param_lock); /* brightness, colour, contrast need no check 0-65535 */ cam->vp = *vp; /* update cam->params.colourParams */ @@ -3466,7 +3466,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, /* queue command to update camera */ cam->cmd_queue |= COMMAND_SETCOLOURPARAMS; - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); DBG("VIDIOCSPICT: %d / %d // %d / %d / %d / %d\n", vp->depth, vp->palette, vp->brightness, vp->hue, vp->colour, vp->contrast); @@ -3501,13 +3501,13 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, /* we set the video window to something smaller or equal to what * is requested by the user??? */ - down(&cam->param_lock); + mutex_lock(&cam->param_lock); if (vw->width != cam->vw.width || vw->height != cam->vw.height) { int video_size = match_videosize(vw->width, vw->height); if (video_size < 0) { retval = -EINVAL; - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); break; } cam->video_size = video_size; @@ -3520,7 +3520,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, cam->cmd_queue |= COMMAND_SETFORMAT; } - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); /* setformat ignored by camera during streaming, * so stop/dispatch/start */ @@ -3682,7 +3682,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, DBG("%d,%d/%dx%d\n", vc->x,vc->y,vc->width, vc->height); - down(&cam->param_lock); + mutex_lock(&cam->param_lock); cam->vc.x = vc->x; cam->vc.y = vc->y; @@ -3692,7 +3692,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, set_vw_size(cam); cam->cmd_queue |= COMMAND_SETFORMAT; - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); /* setformat ignored by camera during streaming, * so stop/dispatch/start */ @@ -3736,7 +3736,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, break; } - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return retval; } @@ -3769,12 +3769,12 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma) return -ENODEV; /* make this _really_ smp-safe */ - if (down_interruptible(&cam->busy_lock)) + if (mutex_lock_interruptible(&cam->busy_lock)) return -EINTR; if (!cam->frame_buf) { /* we do lazy allocation */ if ((retval = allocate_frame_buf(cam))) { - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return retval; } } @@ -3783,7 +3783,7 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma) while (size > 0) { page = vmalloc_to_pfn((void *)pos); if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return -EAGAIN; } start += PAGE_SIZE; @@ -3795,7 +3795,7 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma) } DBG("cpia_mmap: %ld\n", size); - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return 0; } @@ -3936,8 +3936,8 @@ static void init_camera_struct(struct cam_data *cam, memset(cam, 0, sizeof(struct cam_data)); cam->ops = ops; - init_MUTEX(&cam->param_lock); - init_MUTEX(&cam->busy_lock); + mutex_init(&cam->param_lock); + mutex_init(&cam->busy_lock); reset_camera_struct(cam); diff --git a/drivers/media/video/cpia.h b/drivers/media/video/cpia.h index f629b693ee65..de6678200a57 100644 --- a/drivers/media/video/cpia.h +++ b/drivers/media/video/cpia.h @@ -47,6 +47,7 @@ #include #include #include +#include struct cpia_camera_ops { @@ -246,7 +247,7 @@ enum v4l_camstates { struct cam_data { struct list_head cam_data_list; - struct semaphore busy_lock; /* guard against SMP multithreading */ + struct mutex busy_lock; /* guard against SMP multithreading */ struct cpia_camera_ops *ops; /* lowlevel driver operations */ void *lowlevel_data; /* private data for lowlevel driver */ u8 *raw_image; /* buffer for raw image data */ @@ -261,7 +262,7 @@ struct cam_data { u8 mainsFreq; /* for flicker control */ /* proc interface */ - struct semaphore param_lock; /* params lock for this camera */ + struct mutex param_lock; /* params lock for this camera */ struct cam_params params; /* camera settings */ struct proc_dir_entry *proc_entry; /* /proc/cpia/videoX */ diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 3720f24a25cf..eda7cd8b2d4a 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -1061,7 +1061,7 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci) core->pci_bus = pci->bus->number; core->pci_slot = PCI_SLOT(pci->devfn); core->pci_irqmask = 0x00fc00; - init_MUTEX(&core->lock); + mutex_init(&core->lock); core->nr = cx88_devcount++; sprintf(core->name,"cx88[%d]",core->nr); diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 073494ceab0f..d15ef158ac8f 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -336,17 +336,17 @@ static int res_get(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bi return 1; /* is it free? */ - down(&core->lock); + mutex_lock(&core->lock); if (dev->resources & bit) { /* no, someone else uses it */ - up(&core->lock); + mutex_unlock(&core->lock); return 0; } /* it's free, grab it */ fh->resources |= bit; dev->resources |= bit; dprintk(1,"res: get %d\n",bit); - up(&core->lock); + mutex_unlock(&core->lock); return 1; } @@ -369,11 +369,11 @@ void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits) if ((fh->resources & bits) != bits) BUG(); - down(&core->lock); + mutex_lock(&core->lock); fh->resources &= ~bits; dev->resources &= ~bits; dprintk(1,"res: put %d\n",bits); - up(&core->lock); + mutex_unlock(&core->lock); } /* ------------------------------------------------------------------ */ @@ -1291,9 +1291,9 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, if (i == ARRAY_SIZE(tvnorms)) return -EINVAL; - down(&core->lock); + mutex_lock(&core->lock); cx88_set_tvnorm(core,&tvnorms[i]); - up(&core->lock); + mutex_unlock(&core->lock); return 0; } @@ -1343,10 +1343,10 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, if (*i >= 4) return -EINVAL; - down(&core->lock); + mutex_lock(&core->lock); cx88_newstation(core); video_mux(core,*i); - up(&core->lock); + mutex_unlock(&core->lock); return 0; } @@ -1438,7 +1438,7 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, return -EINVAL; if (1 == radio && f->type != V4L2_TUNER_RADIO) return -EINVAL; - down(&core->lock); + mutex_lock(&core->lock); core->freq = f->frequency; cx88_newstation(core); cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f); @@ -1447,7 +1447,7 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, msleep (10); cx88_set_tvaudio(core); - up(&core->lock); + mutex_unlock(&core->lock); return 0; } @@ -1921,11 +1921,11 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, pci_set_drvdata(pci_dev,dev); /* initial device configuration */ - down(&core->lock); + mutex_lock(&core->lock); cx88_set_tvnorm(core,tvnorms); init_controls(core); video_mux(core,0); - up(&core->lock); + mutex_unlock(&core->lock); /* start tvaudio thread */ if (core->tuner_type != TUNER_ABSENT) diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 31a688a3fb77..a4cf2473eacf 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -35,6 +35,7 @@ #include "cx88-reg.h" #include +#include #define CX88_VERSION_CODE KERNEL_VERSION(0,0,5) #ifndef TRUE @@ -309,8 +310,7 @@ struct cx88_core { /* IR remote control state */ struct cx88_IR *ir; - struct semaphore lock; - + struct mutex lock; /* various v4l controls */ u32 freq; diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 1c1557d9bace..671fc52b6a88 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -362,12 +362,12 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) return -EBUSY; } - init_MUTEX(&dev->fileop_lock); /* to 1 == available */ + mutex_init(&dev->fileop_lock); /* to 1 == available */ spin_lock_init(&dev->queue_lock); init_waitqueue_head(&dev->wait_frame); init_waitqueue_head(&dev->wait_stream); - down(&dev->lock); + mutex_lock(&dev->lock); if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { em28xx_set_alternate(dev); @@ -404,8 +404,8 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) dev->state |= DEV_INITIALIZED; - err: - up(&dev->lock); +err: + mutex_unlock(&dev->lock); up_read(&em28xx_disconnect); return errCode; } @@ -447,7 +447,7 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) em28xx_videodbg("users=%d\n", dev->users); - down(&dev->lock); + mutex_lock(&dev->lock); em28xx_uninit_isoc(dev); @@ -456,7 +456,7 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) /* the device is already disconnect, free the remaining resources */ if (dev->state & DEV_DISCONNECTED) { em28xx_release_resources(dev); - up(&dev->lock); + mutex_unlock(&dev->lock); kfree(dev); return 0; } @@ -472,7 +472,7 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) dev->users--; wake_up_interruptible_nr(&dev->open, 1); - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } @@ -496,7 +496,7 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, em28xx_videodbg("V4L2_BUF_TYPE_VBI_CAPTURE is set\n"); em28xx_videodbg("not supported yet! ...\n"); if (copy_to_user(buf, "", 1)) { - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EFAULT; } return (1); @@ -505,38 +505,38 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, em28xx_videodbg("V4L2_BUF_TYPE_SLICED_VBI_CAPTURE is set\n"); em28xx_videodbg("not supported yet! ...\n"); if (copy_to_user(buf, "", 1)) { - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EFAULT; } return (1); } - if (down_interruptible(&dev->fileop_lock)) + if (mutex_lock_interruptible(&dev->fileop_lock)) return -ERESTARTSYS; if (dev->state & DEV_DISCONNECTED) { em28xx_videodbg("device not present\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -ENODEV; } if (dev->state & DEV_MISCONFIGURED) { em28xx_videodbg("device misconfigured; close and open it again\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EIO; } if (dev->io == IO_MMAP) { em28xx_videodbg ("IO method is set to mmap; close and open" " the device again to choose the read method\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EINVAL; } if (dev->io == IO_NONE) { if (!em28xx_request_buffers(dev, EM28XX_NUM_READ_FRAMES)) { em28xx_errdev("read failed, not enough memory\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -ENOMEM; } dev->io = IO_READ; @@ -545,13 +545,13 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, } if (!count) { - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return 0; } if (list_empty(&dev->outqueue)) { if (filp->f_flags & O_NONBLOCK) { - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EAGAIN; } ret = wait_event_interruptible @@ -559,11 +559,11 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, (!list_empty(&dev->outqueue)) || (dev->state & DEV_DISCONNECTED)); if (ret) { - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return ret; } if (dev->state & DEV_DISCONNECTED) { - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -ENODEV; } } @@ -582,12 +582,12 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, count = f->buf.length; if (copy_to_user(buf, f->bufmem, count)) { - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EFAULT; } *f_pos += count; - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return count; } @@ -601,7 +601,7 @@ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait) unsigned int mask = 0; struct em28xx *dev = filp->private_data; - if (down_interruptible(&dev->fileop_lock)) + if (mutex_lock_interruptible(&dev->fileop_lock)) return POLLERR; if (dev->state & DEV_DISCONNECTED) { @@ -627,13 +627,13 @@ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait) if (!list_empty(&dev->outqueue)) mask |= POLLIN | POLLRDNORM; - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return mask; } } - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return POLLERR; } @@ -673,25 +673,25 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) struct em28xx *dev = filp->private_data; - if (down_interruptible(&dev->fileop_lock)) + if (mutex_lock_interruptible(&dev->fileop_lock)) return -ERESTARTSYS; if (dev->state & DEV_DISCONNECTED) { em28xx_videodbg("mmap: device not present\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -ENODEV; } if (dev->state & DEV_MISCONFIGURED) { em28xx_videodbg ("mmap: Device is misconfigured; close and " "open it again\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EIO; } if (dev->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || size != PAGE_ALIGN(dev->frame[0].buf.length)) { - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EINVAL; } @@ -701,7 +701,7 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) } if (i == dev->num_frames) { em28xx_videodbg("mmap: user supplied mapping address is out of range\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EINVAL; } @@ -713,7 +713,7 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) while (size > 0) { /* size is page-aligned */ if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { em28xx_videodbg("mmap: vm_insert_page failed\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EAGAIN; } start += PAGE_SIZE; @@ -725,7 +725,7 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_private_data = &dev->frame[i]; em28xx_vm_open(vma); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return 0; } @@ -1125,7 +1125,7 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, if (i == TVNORMS) return -EINVAL; - down(&dev->lock); + mutex_lock(&dev->lock); dev->tvnorm = &tvnorms[i]; em28xx_set_norm(dev, dev->width, dev->height); @@ -1135,7 +1135,7 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, em28xx_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id); - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } @@ -1189,9 +1189,9 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, if (0 == INPUT(*index)->type) return -EINVAL; - down(&dev->lock); + mutex_lock(&dev->lock); video_mux(dev, *index); - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } @@ -1338,10 +1338,10 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, /* t->signal = 0xffff;*/ /* em28xx_i2c_call_clients(dev,VIDIOC_G_TUNER,t);*/ /* No way to get signal strength? */ - down(&dev->lock); + mutex_lock(&dev->lock); em28xx_i2c_call_clients(dev, DECODER_GET_STATUS, &status); - up(&dev->lock); + mutex_unlock(&dev->lock); t->signal = (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0; @@ -1363,10 +1363,10 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, t->rangehigh = 0xffffffffUL; /* FIXME: set correct range */ /* t->signal = 0xffff; */ /* No way to get signal strength? */ - down(&dev->lock); + mutex_lock(&dev->lock); em28xx_i2c_call_clients(dev, DECODER_GET_STATUS, &status); - up(&dev->lock); + mutex_unlock(&dev->lock); t->signal = (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0; @@ -1394,10 +1394,10 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, if (V4L2_TUNER_ANALOG_TV != f->type) return -EINVAL; - down(&dev->lock); + mutex_lock(&dev->lock); dev->ctl_freq = f->frequency; em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f); - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } case VIDIOC_CROPCAP: @@ -1660,25 +1660,25 @@ static int em28xx_v4l2_ioctl(struct inode *inode, struct file *filp, int ret = 0; struct em28xx *dev = filp->private_data; - if (down_interruptible(&dev->fileop_lock)) + if (mutex_lock_interruptible(&dev->fileop_lock)) return -ERESTARTSYS; if (dev->state & DEV_DISCONNECTED) { em28xx_errdev("v4l2 ioctl: device not present\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -ENODEV; } if (dev->state & DEV_MISCONFIGURED) { em28xx_errdev ("v4l2 ioctl: device is misconfigured; close and open it again\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EIO; } ret = video_usercopy(inode, filp, cmd, arg, em28xx_video_do_ioctl); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return ret; } @@ -1712,7 +1712,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->udev = udev; dev->model = model; - init_MUTEX(&dev->lock); + mutex_init(&dev->lock); init_waitqueue_head(&dev->open); dev->em28xx_write_regs = em28xx_write_regs; @@ -1788,7 +1788,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, return -ENOMEM; } - down(&dev->lock); + mutex_lock(&dev->lock); /* register i2c bus */ em28xx_i2c_register(dev); @@ -1798,7 +1798,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, /* configure the device */ em28xx_config_i2c(dev); - up(&dev->lock); + mutex_unlock(&dev->lock); errCode = em28xx_config(dev); @@ -1849,12 +1849,12 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, list_add_tail(&dev->devlist,&em28xx_devlist); /* register v4l2 device */ - down(&dev->lock); + mutex_lock(&dev->lock); if ((retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, video_nr[dev->devno]))) { em28xx_errdev("unable to register video device (error=%i).\n", retval); - up(&dev->lock); + mutex_unlock(&dev->lock); list_del(&dev->devlist); video_device_release(dev->vdev); kfree(dev); @@ -1865,7 +1865,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, if (video_register_device(dev->vbi_dev, VFL_TYPE_VBI, vbi_nr[dev->devno]) < 0) { printk("unable to register vbi device\n"); - up(&dev->lock); + mutex_unlock(&dev->lock); list_del(&dev->devlist); video_device_release(dev->vbi_dev); video_device_release(dev->vdev); @@ -1886,7 +1886,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, } video_mux(dev, 0); - up(&dev->lock); + mutex_unlock(&dev->lock); em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, @@ -2035,7 +2035,7 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) down_write(&em28xx_disconnect); - down(&dev->lock); + mutex_lock(&dev->lock); em28xx_info("disconnecting %s\n", dev->vdev->name); @@ -2057,7 +2057,7 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) em28xx_release_resources(dev); } - up(&dev->lock); + mutex_unlock(&dev->lock); if (!dev->users) { kfree(dev->alt_max_pkt_size); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index ddf06c520e99..4e2fe62b7350 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -27,6 +27,7 @@ #include #include +#include #include /* Boards supported by driver */ @@ -260,7 +261,7 @@ struct em28xx { enum em28xx_stream_state stream; enum em28xx_io_method io; /* locks */ - struct semaphore lock, fileop_lock; + struct mutex lock, fileop_lock; spinlock_t queue_lock; struct list_head inqueue, outqueue; wait_queue_head_t open, wait_frame, wait_stream; diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 2869464aee0d..850bee97090c 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -925,7 +925,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; if (p->palette != VIDEO_PALETTE_YUV422) return -EINVAL; - down(&meye.lock); + mutex_lock(&meye.lock); sonypi_camera_command(SONYPI_COMMAND_SETCAMERABRIGHTNESS, p->brightness >> 10); sonypi_camera_command(SONYPI_COMMAND_SETCAMERAHUE, @@ -935,7 +935,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, sonypi_camera_command(SONYPI_COMMAND_SETCAMERACONTRAST, p->contrast >> 10); meye.picture = *p; - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -946,21 +946,21 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, if (*i < 0 || *i >= gbuffers) return -EINVAL; - down(&meye.lock); + mutex_lock(&meye.lock); switch (meye.grab_buffer[*i].state) { case MEYE_BUF_UNUSED: - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINVAL; case MEYE_BUF_USING: if (file->f_flags & O_NONBLOCK) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EAGAIN; } if (wait_event_interruptible(meye.proc_list, (meye.grab_buffer[*i].state != MEYE_BUF_USING))) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINTR; } /* fall through */ @@ -968,7 +968,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int)); } - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -987,7 +987,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, if (meye.grab_buffer[vm->frame].state != MEYE_BUF_UNUSED) return -EBUSY; - down(&meye.lock); + mutex_lock(&meye.lock); if (vm->width == 640 && vm->height == 480) { if (meye.params.subsample) { meye.params.subsample = 0; @@ -999,7 +999,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, restart = 1; } } else { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINVAL; } @@ -1007,7 +1007,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, mchip_continuous_start(); meye.grab_buffer[vm->frame].state = MEYE_BUF_USING; kfifo_put(meye.grabq, (unsigned char *)&vm->frame, sizeof(int)); - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1039,7 +1039,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; if (jp->framerate > 31) return -EINVAL; - down(&meye.lock); + mutex_lock(&meye.lock); if (meye.params.subsample != jp->subsample || meye.params.quality != jp->quality) mchip_hic_stop(); /* need restart */ @@ -1050,7 +1050,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, meye.params.agc); sonypi_camera_command(SONYPI_COMMAND_SETCAMERAPICTURE, meye.params.picture); - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1068,12 +1068,12 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, } if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED) return -EBUSY; - down(&meye.lock); + mutex_lock(&meye.lock); if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP) mchip_cont_compression_start(); meye.grab_buffer[*nb].state = MEYE_BUF_USING; kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int)); - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1084,20 +1084,20 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, if (*i < 0 || *i >= gbuffers) return -EINVAL; - down(&meye.lock); + mutex_lock(&meye.lock); switch (meye.grab_buffer[*i].state) { case MEYE_BUF_UNUSED: - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINVAL; case MEYE_BUF_USING: if (file->f_flags & O_NONBLOCK) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EAGAIN; } if (wait_event_interruptible(meye.proc_list, (meye.grab_buffer[*i].state != MEYE_BUF_USING))) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINTR; } /* fall through */ @@ -1106,7 +1106,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int)); } *i = meye.grab_buffer[*i].size; - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1116,14 +1116,14 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED) return -EBUSY; - down(&meye.lock); + mutex_lock(&meye.lock); meye.grab_buffer[0].state = MEYE_BUF_USING; mchip_take_picture(); mchip_get_picture( meye.grab_fbuffer, mchip_hsize() * mchip_vsize() * 2); meye.grab_buffer[0].state = MEYE_BUF_DONE; - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1134,7 +1134,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED) return -EBUSY; - down(&meye.lock); + mutex_lock(&meye.lock); meye.grab_buffer[0].state = MEYE_BUF_USING; *len = -1; while (*len == -1) { @@ -1142,7 +1142,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, *len = mchip_compress_frame(meye.grab_fbuffer, gbufsize); } meye.grab_buffer[0].state = MEYE_BUF_DONE; - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1285,7 +1285,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_S_CTRL: { struct v4l2_control *c = arg; - down(&meye.lock); + mutex_lock(&meye.lock); switch (c->id) { case V4L2_CID_BRIGHTNESS: sonypi_camera_command( @@ -1329,17 +1329,17 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, meye.params.framerate = c->value; break; default: - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINVAL; } - up(&meye.lock); + mutex_unlock(&meye.lock); break; } case VIDIOC_G_CTRL: { struct v4l2_control *c = arg; - down(&meye.lock); + mutex_lock(&meye.lock); switch (c->id) { case V4L2_CID_BRIGHTNESS: c->value = meye.picture.brightness >> 10; @@ -1369,10 +1369,10 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, c->value = meye.params.framerate; break; default: - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINVAL; } - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1469,7 +1469,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, f->fmt.pix.field != V4L2_FIELD_NONE) return -EINVAL; f->fmt.pix.field = V4L2_FIELD_NONE; - down(&meye.lock); + mutex_lock(&meye.lock); if (f->fmt.pix.width <= 320) { f->fmt.pix.width = 320; f->fmt.pix.height = 240; @@ -1487,7 +1487,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP; break; } - up(&meye.lock); + mutex_unlock(&meye.lock); f->fmt.pix.bytesperline = f->fmt.pix.width * 2; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; @@ -1509,11 +1509,11 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, /* already allocated, no modifications */ break; } - down(&meye.lock); + mutex_lock(&meye.lock); if (meye.grab_fbuffer) { for (i = 0; i < gbuffers; i++) if (meye.vma_use_count[i]) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINVAL; } rvfree(meye.grab_fbuffer, gbuffers * gbufsize); @@ -1525,12 +1525,12 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, if (!meye.grab_fbuffer) { printk(KERN_ERR "meye: v4l framebuffer allocation" " failed\n"); - up(&meye.lock); + mutex_unlock(&meye.lock); return -ENOMEM; } for (i = 0; i < gbuffers; i++) meye.vma_use_count[i] = 0; - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1569,12 +1569,12 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED) return -EINVAL; - down(&meye.lock); + mutex_lock(&meye.lock); buf->flags |= V4L2_BUF_FLAG_QUEUED; buf->flags &= ~V4L2_BUF_FLAG_DONE; meye.grab_buffer[buf->index].state = MEYE_BUF_USING; kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int)); - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1587,23 +1587,23 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, if (buf->memory != V4L2_MEMORY_MMAP) return -EINVAL; - down(&meye.lock); + mutex_lock(&meye.lock); if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EAGAIN; } if (wait_event_interruptible(meye.proc_list, kfifo_len(meye.doneq) != 0) < 0) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINTR; } if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr, sizeof(int))) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EBUSY; } if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINVAL; } buf->index = reqnr; @@ -1616,12 +1616,12 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, buf->m.offset = reqnr * gbufsize; buf->length = gbufsize; meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED; - up(&meye.lock); + mutex_unlock(&meye.lock); break; } case VIDIOC_STREAMON: { - down(&meye.lock); + mutex_lock(&meye.lock); switch (meye.mchip_mode) { case MCHIP_HIC_MODE_CONT_OUT: mchip_continuous_start(); @@ -1630,23 +1630,23 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, mchip_cont_compression_start(); break; default: - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINVAL; } - up(&meye.lock); + mutex_unlock(&meye.lock); break; } case VIDIOC_STREAMOFF: { int i; - down(&meye.lock); + mutex_lock(&meye.lock); mchip_hic_stop(); kfifo_reset(meye.grabq); kfifo_reset(meye.doneq); for (i = 0; i < MEYE_MAX_BUFNBRS; i++) meye.grab_buffer[i].state = MEYE_BUF_UNUSED; - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1672,11 +1672,11 @@ static unsigned int meye_poll(struct file *file, poll_table *wait) { unsigned int res = 0; - down(&meye.lock); + mutex_lock(&meye.lock); poll_wait(file, &meye.proc_list, wait); if (kfifo_len(meye.doneq)) res = POLLIN | POLLRDNORM; - up(&meye.lock); + mutex_unlock(&meye.lock); return res; } @@ -1704,9 +1704,9 @@ static int meye_mmap(struct file *file, struct vm_area_struct *vma) unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; unsigned long page, pos; - down(&meye.lock); + mutex_lock(&meye.lock); if (size > gbuffers * gbufsize) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINVAL; } if (!meye.grab_fbuffer) { @@ -1716,7 +1716,7 @@ static int meye_mmap(struct file *file, struct vm_area_struct *vma) meye.grab_fbuffer = rvmalloc(gbuffers*gbufsize); if (!meye.grab_fbuffer) { printk(KERN_ERR "meye: v4l framebuffer allocation failed\n"); - up(&meye.lock); + mutex_unlock(&meye.lock); return -ENOMEM; } for (i = 0; i < gbuffers; i++) @@ -1727,7 +1727,7 @@ static int meye_mmap(struct file *file, struct vm_area_struct *vma) while (size > 0) { page = vmalloc_to_pfn((void *)pos); if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EAGAIN; } start += PAGE_SIZE; @@ -1744,7 +1744,7 @@ static int meye_mmap(struct file *file, struct vm_area_struct *vma) vma->vm_private_data = (void *) (offset / gbufsize); meye_vm_open(vma); - up(&meye.lock); + mutex_unlock(&meye.lock); return 0; } @@ -1913,7 +1913,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev, goto outvideoreg; } - init_MUTEX(&meye.lock); + mutex_init(&meye.lock); init_waitqueue_head(&meye.proc_list); meye.picture.depth = 16; meye.picture.palette = VIDEO_PALETTE_YUV422; diff --git a/drivers/media/video/meye.h b/drivers/media/video/meye.h index e8cd897b0d20..0d09a0e3803c 100644 --- a/drivers/media/video/meye.h +++ b/drivers/media/video/meye.h @@ -260,6 +260,8 @@ /* private API definitions */ #include +#include + /* Enable jpg software correction */ #define MEYE_JPEG_CORRECTION 1 @@ -301,7 +303,7 @@ struct meye { /* list of buffers */ struct meye_grab_buffer grab_buffer[MEYE_MAX_BUFNBRS]; int vma_use_count[MEYE_MAX_BUFNBRS]; /* mmap count */ - struct semaphore lock; /* semaphore for open/mmap... */ + struct mutex lock; /* mutex for open/mmap... */ struct kfifo *grabq; /* queue for buffers to be grabbed */ spinlock_t grabq_lock; /* lock protecting the queue */ struct kfifo *doneq; /* queue for grabbed buffers */ diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 8416ceff524b..69a7eddf3a24 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -625,9 +625,9 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) } /* fixme: locke das setzen des inputs mit hilfe des mutexes - down(&dev->lock); + mutex_lock(&dev->lock); video_mux(dev,*i); - up(&dev->lock); + mutex_unlock(&dev->lock); */ /* fixme: check if streaming capture diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c index f3fc361bec97..15fd85acabda 100644 --- a/drivers/media/video/planb.c +++ b/drivers/media/video/planb.c @@ -48,7 +48,7 @@ #include #include #include -#include +#include #include "planb.h" #include "saa7196.h" @@ -329,12 +329,12 @@ static volatile struct dbdma_cmd *cmd_geo_setup( static inline void planb_lock(struct planb *pb) { - down(&pb->lock); + mutex_lock(&pb->lock); } static inline void planb_unlock(struct planb *pb) { - up(&pb->lock); + mutex_unlock(&pb->lock); } /***************/ @@ -2067,7 +2067,7 @@ static int init_planb(struct planb *pb) #endif pb->tab_size = PLANB_MAXLINES + 40; pb->suspend = 0; - init_MUTEX(&pb->lock); + mutex_init(&pb->lock); pb->ch1_cmd = 0; pb->ch2_cmd = 0; pb->mask = 0; diff --git a/drivers/media/video/planb.h b/drivers/media/video/planb.h index 8a0faad16118..79b6b561426e 100644 --- a/drivers/media/video/planb.h +++ b/drivers/media/video/planb.h @@ -174,7 +174,7 @@ struct planb { int user; unsigned int tab_size; int maxlines; - struct semaphore lock; + struct mutex lock; unsigned int irq; /* interrupt number */ volatile unsigned int intr_mask; diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 9e6448639480..05ca55939e77 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -30,6 +30,8 @@ #include #include #include +#include + #include @@ -44,7 +46,7 @@ struct pms_device struct video_picture picture; int height; int width; - struct semaphore lock; + struct mutex lock; }; struct i2c_info @@ -724,10 +726,10 @@ static int pms_do_ioctl(struct inode *inode, struct file *file, struct video_channel *v = arg; if(v->channel<0 || v->channel>3) return -EINVAL; - down(&pd->lock); + mutex_lock(&pd->lock); pms_videosource(v->channel&1); pms_vcrinput(v->channel>>1); - up(&pd->lock); + mutex_unlock(&pd->lock); return 0; } case VIDIOCGTUNER: @@ -761,7 +763,7 @@ static int pms_do_ioctl(struct inode *inode, struct file *file, struct video_tuner *v = arg; if(v->tuner) return -EINVAL; - down(&pd->lock); + mutex_lock(&pd->lock); switch(v->mode) { case VIDEO_MODE_AUTO: @@ -785,10 +787,10 @@ static int pms_do_ioctl(struct inode *inode, struct file *file, pms_format(2); break; default: - up(&pd->lock); + mutex_unlock(&pd->lock); return -EINVAL; } - up(&pd->lock); + mutex_unlock(&pd->lock); return 0; } case VIDIOCGPICT: @@ -809,12 +811,12 @@ static int pms_do_ioctl(struct inode *inode, struct file *file, * Now load the card. */ - down(&pd->lock); + mutex_lock(&pd->lock); pms_brightness(p->brightness>>8); pms_hue(p->hue>>8); pms_colour(p->colour>>8); pms_contrast(p->contrast>>8); - up(&pd->lock); + mutex_unlock(&pd->lock); return 0; } case VIDIOCSWIN: @@ -830,9 +832,9 @@ static int pms_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; pd->width=vw->width; pd->height=vw->height; - down(&pd->lock); + mutex_lock(&pd->lock); pms_resolution(pd->width, pd->height); - up(&pd->lock); /* Ok we figured out what to use from our wide choice */ + mutex_unlock(&pd->lock); /* Ok we figured out what to use from our wide choice */ return 0; } case VIDIOCGWIN: @@ -872,9 +874,9 @@ static ssize_t pms_read(struct file *file, char __user *buf, struct pms_device *pd=(struct pms_device *)v; int len; - down(&pd->lock); + mutex_lock(&pd->lock); len=pms_capture(pd, buf, (pd->picture.depth==16)?0:1,count); - up(&pd->lock); + mutex_unlock(&pd->lock); return len; } @@ -1029,7 +1031,7 @@ static int __init init_pms_cards(void) return -ENODEV; } memcpy(&pms_device, &pms_template, sizeof(pms_template)); - init_MUTEX(&pms_device.lock); + mutex_init(&pms_device.lock); pms_device.height=240; pms_device.width=320; pms_swsense(75); diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index 2ce010201308..dd830e0e5e96 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c @@ -46,6 +46,8 @@ #include #include #include +#include + #include "saa5246a.h" MODULE_AUTHOR("Michael Geng "); @@ -57,7 +59,7 @@ struct saa5246a_device u8 pgbuf[NUM_DAUS][VTX_VIRTUALSIZE]; int is_searching[NUM_DAUS]; struct i2c_client *client; - struct semaphore lock; + struct mutex lock; }; static struct video_device saa_template; /* Declared near bottom */ @@ -90,7 +92,7 @@ static int saa5246a_attach(struct i2c_adapter *adap, int addr, int kind) return -ENOMEM; } strlcpy(client->name, IF_NAME, I2C_NAME_SIZE); - init_MUTEX(&t->lock); + mutex_init(&t->lock); /* * Now create a video4linux device @@ -719,9 +721,9 @@ static int saa5246a_ioctl(struct inode *inode, struct file *file, int err; cmd = vtx_fix_command(cmd); - down(&t->lock); + mutex_lock(&t->lock); err = video_usercopy(inode, file, cmd, arg, do_saa5246a_ioctl); - up(&t->lock); + mutex_unlock(&t->lock); return err; } diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index 5694eb58c3a1..a9f3cf0b1e3c 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c @@ -56,6 +56,8 @@ #include #include #include +#include + #include #include @@ -105,7 +107,7 @@ struct saa5249_device int disp_mode; int virtual_mode; struct i2c_client *client; - struct semaphore lock; + struct mutex lock; }; @@ -158,7 +160,7 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind) return -ENOMEM; } strlcpy(client->name, IF_NAME, I2C_NAME_SIZE); - init_MUTEX(&t->lock); + mutex_init(&t->lock); /* * Now create a video4linux device @@ -619,9 +621,9 @@ static int saa5249_ioctl(struct inode *inode, struct file *file, int err; cmd = vtx_fix_command(cmd); - down(&t->lock); + mutex_lock(&t->lock); err = video_usercopy(inode,file,cmd,arg,do_saa5249_ioctl); - up(&t->lock); + mutex_unlock(&t->lock); return err; } diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index a7a6ab9298a9..d3c7345a5d22 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -609,12 +609,12 @@ static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) struct saa7134_dev *dev = saa7134->dev; int err; - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); dev->dmasound.read_count = 0; dev->dmasound.read_offset = 0; - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); if (pcm == NULL) @@ -932,7 +932,7 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum) chip->irq = dev->pci->irq; - init_MUTEX(&dev->dmasound.lock); + mutex_init(&dev->dmasound.lock); if ((err = snd_card_saa7134_new_mixer(chip)) < 0) goto __nodev; diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 028904bd94a2..e7c30665739e 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -613,7 +613,7 @@ static int saa7134_hwinit1(struct saa7134_dev *dev) saa_writel(SAA7134_IRQ1, 0); saa_writel(SAA7134_IRQ2, 0); - init_MUTEX(&dev->lock); + mutex_init(&dev->lock); spin_lock_init(&dev->slock); saa7134_track_gpio(dev,"pre-init"); diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index bd4c389d4c37..1d972edb3be6 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -89,7 +89,7 @@ static int ts_open(struct inode *inode, struct file *file) dprintk("open minor=%d\n",minor); err = -EBUSY; - if (down_trylock(&dev->empress_tsq.lock)) + if (!mutex_trylock(&dev->empress_tsq.lock)) goto done; if (dev->empress_users) goto done_up; @@ -99,7 +99,7 @@ static int ts_open(struct inode *inode, struct file *file) err = 0; done_up: - up(&dev->empress_tsq.lock); + mutex_unlock(&dev->empress_tsq.lock); done: return err; } @@ -110,7 +110,7 @@ static int ts_release(struct inode *inode, struct file *file) if (dev->empress_tsq.streaming) videobuf_streamoff(&dev->empress_tsq); - down(&dev->empress_tsq.lock); + mutex_lock(&dev->empress_tsq.lock); if (dev->empress_tsq.reading) videobuf_read_stop(&dev->empress_tsq); videobuf_mmap_free(&dev->empress_tsq); @@ -119,7 +119,7 @@ static int ts_release(struct inode *inode, struct file *file) /* stop the encoder */ ts_reset_encoder(dev); - up(&dev->empress_tsq.lock); + mutex_unlock(&dev->empress_tsq.lock); return 0; } diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c index 7448e386a804..80e34a5fdcc5 100644 --- a/drivers/media/video/saa7134/saa7134-oss.c +++ b/drivers/media/video/saa7134/saa7134-oss.c @@ -254,7 +254,7 @@ static int dsp_open(struct inode *inode, struct file *file) if (NULL == dev) return -ENODEV; - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); err = -EBUSY; if (dev->dmasound.users_dsp) goto fail1; @@ -270,13 +270,13 @@ static int dsp_open(struct inode *inode, struct file *file) if (0 != err) goto fail2; - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); return 0; fail2: dev->dmasound.users_dsp--; fail1: - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); return err; } @@ -284,13 +284,13 @@ static int dsp_release(struct inode *inode, struct file *file) { struct saa7134_dev *dev = file->private_data; - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); if (dev->dmasound.recording_on) dsp_rec_stop(dev); dsp_buffer_free(dev); dev->dmasound.users_dsp--; file->private_data = NULL; - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); return 0; } @@ -304,7 +304,7 @@ static ssize_t dsp_read(struct file *file, char __user *buffer, int err,ret = 0; add_wait_queue(&dev->dmasound.wq, &wait); - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); while (count > 0) { /* wait for data if needed */ if (0 == dev->dmasound.read_count) { @@ -328,12 +328,12 @@ static ssize_t dsp_read(struct file *file, char __user *buffer, ret = -EAGAIN; break; } - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); set_current_state(TASK_INTERRUPTIBLE); if (0 == dev->dmasound.read_count) schedule(); set_current_state(TASK_RUNNING); - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); if (signal_pending(current)) { if (0 == ret) ret = -EINTR; @@ -362,7 +362,7 @@ static ssize_t dsp_read(struct file *file, char __user *buffer, if (dev->dmasound.read_offset == dev->dmasound.bufsize) dev->dmasound.read_offset = 0; } - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); remove_wait_queue(&dev->dmasound.wq, &wait); return ret; } @@ -435,13 +435,13 @@ static int dsp_ioctl(struct inode *inode, struct file *file, case SNDCTL_DSP_STEREO: if (get_user(val, p)) return -EFAULT; - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); dev->dmasound.channels = val ? 2 : 1; if (dev->dmasound.recording_on) { dsp_rec_stop(dev); dsp_rec_start(dev); } - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); return put_user(dev->dmasound.channels-1, p); case SNDCTL_DSP_CHANNELS: @@ -449,13 +449,13 @@ static int dsp_ioctl(struct inode *inode, struct file *file, return -EFAULT; if (val != 1 && val != 2) return -EINVAL; - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); dev->dmasound.channels = val; if (dev->dmasound.recording_on) { dsp_rec_stop(dev); dsp_rec_start(dev); } - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); /* fall through */ case SOUND_PCM_READ_CHANNELS: return put_user(dev->dmasound.channels, p); @@ -478,13 +478,13 @@ static int dsp_ioctl(struct inode *inode, struct file *file, case AFMT_U16_BE: case AFMT_S16_LE: case AFMT_S16_BE: - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); dev->dmasound.afmt = val; if (dev->dmasound.recording_on) { dsp_rec_stop(dev); dsp_rec_start(dev); } - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); return put_user(dev->dmasound.afmt, p); default: return -EINVAL; @@ -509,10 +509,10 @@ static int dsp_ioctl(struct inode *inode, struct file *file, return 0; case SNDCTL_DSP_RESET: - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); if (dev->dmasound.recording_on) dsp_rec_stop(dev); - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); return 0; case SNDCTL_DSP_GETBLKSIZE: return put_user(dev->dmasound.blksize, p); @@ -556,10 +556,10 @@ static unsigned int dsp_poll(struct file *file, struct poll_table_struct *wait) poll_wait(file, &dev->dmasound.wq, wait); if (0 == dev->dmasound.read_count) { - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); if (!dev->dmasound.recording_on) dsp_rec_start(dev); - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); } else mask |= (POLLIN | POLLRDNORM); return mask; @@ -852,7 +852,7 @@ int saa7134_oss_init1(struct saa7134_dev *dev) return -1; /* general */ - init_MUTEX(&dev->dmasound.lock); + mutex_init(&dev->dmasound.lock); init_waitqueue_head(&dev->dmasound.wq); switch (dev->pci->device) { diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index e97426bc85df..72f389a51a13 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -460,17 +460,17 @@ static int res_get(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int return 1; /* is it free? */ - down(&dev->lock); + mutex_lock(&dev->lock); if (dev->resources & bit) { /* no, someone else uses it */ - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } /* it's free, grab it */ fh->resources |= bit; dev->resources |= bit; dprintk("res: get %d\n",bit); - up(&dev->lock); + mutex_unlock(&dev->lock); return 1; } @@ -492,11 +492,11 @@ void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits) if ((fh->resources & bits) != bits) BUG(); - down(&dev->lock); + mutex_lock(&dev->lock); fh->resources &= ~bits; dev->resources &= ~bits; dprintk("res: put %d\n",bits); - up(&dev->lock); + mutex_unlock(&dev->lock); } /* ------------------------------------------------------------------ */ @@ -1340,21 +1340,21 @@ video_poll(struct file *file, struct poll_table_struct *wait) if (!list_empty(&fh->cap.stream)) buf = list_entry(fh->cap.stream.next, struct videobuf_buffer, stream); } else { - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); if (UNSET == fh->cap.read_off) { /* need to capture a new frame */ if (res_locked(fh->dev,RESOURCE_VIDEO)) { - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return POLLERR; } if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field)) { - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return POLLERR; } fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); fh->cap.read_off = 0; } - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); buf = fh->cap.read_buf; } @@ -1561,14 +1561,14 @@ static int saa7134_s_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, if (0 != err) return err; - down(&dev->lock); + mutex_lock(&dev->lock); fh->win = f->fmt.win; fh->nclips = f->fmt.win.clipcount; if (fh->nclips > 8) fh->nclips = 8; if (copy_from_user(fh->clips,f->fmt.win.clips, sizeof(struct v4l2_clip)*fh->nclips)) { - up(&dev->lock); + mutex_unlock(&dev->lock); return -EFAULT; } @@ -1578,7 +1578,7 @@ static int saa7134_s_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, start_preview(dev,fh); spin_unlock_irqrestore(&dev->slock,flags); } - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; case V4L2_BUF_TYPE_VBI_CAPTURE: saa7134_vbi_fmt(dev,f); @@ -1612,9 +1612,9 @@ int saa7134_common_ioctl(struct saa7134_dev *dev, return get_control(dev,arg); case VIDIOC_S_CTRL: { - down(&dev->lock); + mutex_lock(&dev->lock); err = set_control(dev,NULL,arg); - up(&dev->lock); + mutex_unlock(&dev->lock); return err; } /* --- input switching --------------------------------------- */ @@ -1664,9 +1664,9 @@ int saa7134_common_ioctl(struct saa7134_dev *dev, return -EINVAL; if (NULL == card_in(dev,*i).name) return -EINVAL; - down(&dev->lock); + mutex_lock(&dev->lock); video_mux(dev,*i); - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } @@ -1766,7 +1766,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, if (i == TVNORMS) return -EINVAL; - down(&dev->lock); + mutex_lock(&dev->lock); if (res_check(fh, RESOURCE_OVERLAY)) { spin_lock_irqsave(&dev->slock,flags); stop_preview(dev,fh); @@ -1776,7 +1776,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, } else set_tvnorm(dev,&tvnorms[i]); saa7134_tvaudio_do_scan(dev); - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } @@ -1909,13 +1909,13 @@ static int video_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; if (1 == fh->radio && V4L2_TUNER_RADIO != f->type) return -EINVAL; - down(&dev->lock); + mutex_lock(&dev->lock); dev->ctl_freq = f->frequency; saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,f); saa7134_tvaudio_do_scan(dev); - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index ff39a63c7372..691c10be459d 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -364,7 +365,7 @@ struct saa7134_fh { /* dmasound dsp status */ struct saa7134_dmasound { - struct semaphore lock; + struct mutex lock; int minor_mixer; int minor_dsp; unsigned int users_dsp; @@ -428,7 +429,7 @@ struct saa7134_mpeg_ops { /* global device status */ struct saa7134_dev { struct list_head devlist; - struct semaphore lock; + struct mutex lock; spinlock_t slock; #ifdef VIDIOC_G_PRIORITY struct v4l2_prio_state prio; diff --git a/drivers/media/video/video-buf-dvb.c b/drivers/media/video/video-buf-dvb.c index 0a4004a4393c..caf3e7e2f219 100644 --- a/drivers/media/video/video-buf-dvb.c +++ b/drivers/media/video/video-buf-dvb.c @@ -96,7 +96,7 @@ static int videobuf_dvb_start_feed(struct dvb_demux_feed *feed) if (!demux->dmx.frontend) return -EINVAL; - down(&dvb->lock); + mutex_lock(&dvb->lock); dvb->nfeeds++; rc = dvb->nfeeds; @@ -110,7 +110,7 @@ static int videobuf_dvb_start_feed(struct dvb_demux_feed *feed) } out: - up(&dvb->lock); + mutex_unlock(&dvb->lock); return rc; } @@ -120,14 +120,14 @@ static int videobuf_dvb_stop_feed(struct dvb_demux_feed *feed) struct videobuf_dvb *dvb = demux->priv; int err = 0; - down(&dvb->lock); + mutex_lock(&dvb->lock); dvb->nfeeds--; if (0 == dvb->nfeeds && NULL != dvb->thread) { // FIXME: cx8802_cancel_buffers(dev); err = kthread_stop(dvb->thread); dvb->thread = NULL; } - up(&dvb->lock); + mutex_unlock(&dvb->lock); return err; } @@ -139,7 +139,7 @@ int videobuf_dvb_register(struct videobuf_dvb *dvb, { int result; - init_MUTEX(&dvb->lock); + mutex_init(&dvb->lock); /* register adapter */ result = dvb_register_adapter(&dvb->adapter, dvb->name, module); diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c index 9ef477523d27..cb1c228e29f8 100644 --- a/drivers/media/video/video-buf.c +++ b/drivers/media/video/video-buf.c @@ -385,7 +385,7 @@ void videobuf_queue_init(struct videobuf_queue* q, q->ops = ops; q->priv_data = priv; - init_MUTEX(&q->lock); + mutex_init(&q->lock); INIT_LIST_HEAD(&q->stream); } @@ -549,7 +549,7 @@ videobuf_reqbufs(struct videobuf_queue *q, if (!list_empty(&q->stream)) return -EBUSY; - down(&q->lock); + mutex_lock(&q->lock); count = req->count; if (count > VIDEO_MAX_FRAME) count = VIDEO_MAX_FRAME; @@ -566,7 +566,7 @@ videobuf_reqbufs(struct videobuf_queue *q, req->count = count; done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -592,7 +592,7 @@ videobuf_qbuf(struct videobuf_queue *q, unsigned long flags; int retval; - down(&q->lock); + mutex_lock(&q->lock); retval = -EBUSY; if (q->reading) goto done; @@ -652,7 +652,7 @@ videobuf_qbuf(struct videobuf_queue *q, retval = 0; done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -663,7 +663,7 @@ videobuf_dqbuf(struct videobuf_queue *q, struct videobuf_buffer *buf; int retval; - down(&q->lock); + mutex_lock(&q->lock); retval = -EBUSY; if (q->reading) goto done; @@ -693,7 +693,7 @@ videobuf_dqbuf(struct videobuf_queue *q, videobuf_status(b,buf,q->type); done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -704,7 +704,7 @@ int videobuf_streamon(struct videobuf_queue *q) unsigned long flags; int retval; - down(&q->lock); + mutex_lock(&q->lock); retval = -EBUSY; if (q->reading) goto done; @@ -721,7 +721,7 @@ int videobuf_streamon(struct videobuf_queue *q) spin_unlock_irqrestore(q->irqlock,flags); done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -729,7 +729,7 @@ int videobuf_streamoff(struct videobuf_queue *q) { int retval = -EINVAL; - down(&q->lock); + mutex_lock(&q->lock); if (!q->streaming) goto done; videobuf_queue_cancel(q); @@ -737,7 +737,7 @@ int videobuf_streamoff(struct videobuf_queue *q) retval = 0; done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -792,7 +792,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, unsigned size, nbufs, bytes; int retval; - down(&q->lock); + mutex_lock(&q->lock); nbufs = 1; size = 0; q->ops->buf_setup(q,&nbufs,&size); @@ -860,7 +860,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, } done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -922,7 +922,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, unsigned long flags; dprintk(2,"%s\n",__FUNCTION__); - down(&q->lock); + mutex_lock(&q->lock); retval = -EBUSY; if (q->streaming) goto done; @@ -996,7 +996,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, } done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -1007,7 +1007,7 @@ unsigned int videobuf_poll_stream(struct file *file, struct videobuf_buffer *buf = NULL; unsigned int rc = 0; - down(&q->lock); + mutex_lock(&q->lock); if (q->streaming) { if (!list_empty(&q->stream)) buf = list_entry(q->stream.next, @@ -1035,7 +1035,7 @@ unsigned int videobuf_poll_stream(struct file *file, buf->state == STATE_ERROR) rc = POLLIN|POLLRDNORM; } - up(&q->lock); + mutex_unlock(&q->lock); return rc; } @@ -1064,7 +1064,7 @@ videobuf_vm_close(struct vm_area_struct *vma) map->count--; if (0 == map->count) { dprintk(1,"munmap %p q=%p\n",map,q); - down(&q->lock); + mutex_lock(&q->lock); for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; @@ -1076,7 +1076,7 @@ videobuf_vm_close(struct vm_area_struct *vma) q->bufs[i]->baddr = 0; q->ops->buf_release(q,q->bufs[i]); } - up(&q->lock); + mutex_unlock(&q->lock); kfree(map); } return; @@ -1170,7 +1170,7 @@ int videobuf_mmap_mapper(struct videobuf_queue *q, unsigned int first,last,size,i; int retval; - down(&q->lock); + mutex_lock(&q->lock); retval = -EINVAL; if (!(vma->vm_flags & VM_WRITE)) { dprintk(1,"mmap app bug: PROT_WRITE please\n"); @@ -1238,7 +1238,7 @@ int videobuf_mmap_mapper(struct videobuf_queue *q, retval = 0; done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 908fbec776ac..75e3d41382f2 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -224,13 +224,13 @@ int video_exclusive_open(struct inode *inode, struct file *file) struct video_device *vfl = video_devdata(file); int retval = 0; - down(&vfl->lock); + mutex_lock(&vfl->lock); if (vfl->users) { retval = -EBUSY; } else { vfl->users++; } - up(&vfl->lock); + mutex_unlock(&vfl->lock); return retval; } @@ -328,7 +328,7 @@ int video_register_device(struct video_device *vfd, int type, int nr) sprintf(vfd->devfs_name, "v4l/%s%d", name_base, i - base); devfs_mk_cdev(MKDEV(VIDEO_MAJOR, vfd->minor), S_IFCHR | S_IRUSR | S_IWUSR, vfd->devfs_name); - init_MUTEX(&vfd->lock); + mutex_init(&vfd->lock); /* sysfs class */ memset(&vfd->class_dev, 0x00, sizeof(vfd->class_dev)); diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index c8fd8238904d..0229819d0aac 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -245,7 +246,7 @@ struct vino_framebuffer_queue { struct vino_framebuffer *buffer[VINO_FRAMEBUFFER_COUNT_MAX]; spinlock_t queue_lock; - struct semaphore queue_sem; + struct mutex queue_mutex; wait_queue_head_t frame_wait_queue; }; @@ -283,7 +284,7 @@ struct vino_channel_settings { /* the driver is currently processing the queue */ int capturing; - struct semaphore sem; + struct mutex mutex; spinlock_t capture_lock; unsigned int users; @@ -1131,11 +1132,11 @@ static void vino_queue_free(struct vino_framebuffer_queue *q) if (q->type != VINO_MEMORY_MMAP) return; - down(&q->queue_sem); + mutex_lock(&q->queue_mutex); vino_queue_free_with_count(q, q->length); - up(&q->queue_sem); + mutex_unlock(&q->queue_mutex); } static int vino_queue_init(struct vino_framebuffer_queue *q, @@ -1159,7 +1160,7 @@ static int vino_queue_init(struct vino_framebuffer_queue *q, if (*length < 1) return -EINVAL; - down(&q->queue_sem); + mutex_lock(&q->queue_mutex); if (*length > VINO_FRAMEBUFFER_COUNT_MAX) *length = VINO_FRAMEBUFFER_COUNT_MAX; @@ -1211,7 +1212,7 @@ static int vino_queue_init(struct vino_framebuffer_queue *q, q->magic = VINO_QUEUE_MAGIC; } - up(&q->queue_sem); + mutex_unlock(&q->queue_mutex); return ret; } @@ -4045,7 +4046,7 @@ static int vino_open(struct inode *inode, struct file *file) dprintk("open(): channel = %c\n", (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B'); - down(&vcs->sem); + mutex_lock(&vcs->mutex); if (vcs->users) { dprintk("open(): driver busy\n"); @@ -4062,7 +4063,7 @@ static int vino_open(struct inode *inode, struct file *file) vcs->users++; out: - up(&vcs->sem); + mutex_unlock(&vcs->mutex); dprintk("open(): %s!\n", ret ? "failed" : "complete"); @@ -4075,7 +4076,7 @@ static int vino_close(struct inode *inode, struct file *file) struct vino_channel_settings *vcs = video_get_drvdata(dev); dprintk("close():\n"); - down(&vcs->sem); + mutex_lock(&vcs->mutex); vcs->users--; @@ -4087,7 +4088,7 @@ static int vino_close(struct inode *inode, struct file *file) vino_queue_free(&vcs->fb_queue); } - up(&vcs->sem); + mutex_unlock(&vcs->mutex); return 0; } @@ -4130,7 +4131,7 @@ static int vino_mmap(struct file *file, struct vm_area_struct *vma) // TODO: reject mmap if already mapped - if (down_interruptible(&vcs->sem)) + if (mutex_lock_interruptible(&vcs->mutex)) return -EINTR; if (vcs->reading) { @@ -4214,7 +4215,7 @@ found: vma->vm_ops = &vino_vm_ops; out: - up(&vcs->sem); + mutex_unlock(&vcs->mutex); return ret; } @@ -4374,12 +4375,12 @@ static int vino_ioctl(struct inode *inode, struct file *file, struct vino_channel_settings *vcs = video_get_drvdata(dev); int ret; - if (down_interruptible(&vcs->sem)) + if (mutex_lock_interruptible(&vcs->mutex)) return -EINTR; ret = video_usercopy(inode, file, cmd, arg, vino_do_ioctl); - up(&vcs->sem); + mutex_unlock(&vcs->mutex); return ret; } @@ -4564,10 +4565,10 @@ static int vino_init_channel_settings(struct vino_channel_settings *vcs, vcs->capturing = 0; - init_MUTEX(&vcs->sem); + mutex_init(&vcs->mutex); spin_lock_init(&vcs->capture_lock); - init_MUTEX(&vcs->fb_queue.queue_sem); + mutex_init(&vcs->fb_queue.queue_mutex); spin_lock_init(&vcs->fb_queue.queue_lock); init_waitqueue_head(&vcs->fb_queue.frame_wait_queue); diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 965c8902fe60..1dd8efeff35a 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -17,6 +17,7 @@ #include /* need struct timeval */ #include #include +#include #endif #include /* need __user */ @@ -90,7 +91,7 @@ struct video_device /* for videodev.c intenal usage -- please don't touch */ int users; /* video_exclusive_{open|close} ... */ - struct semaphore lock; /* ... helper function uses these */ + struct mutex lock; /* ... helper function uses these */ char devfs_name[64]; /* devfs */ struct class_device class_dev; /* sysfs */ }; diff --git a/include/media/saa7146.h b/include/media/saa7146.h index 2bc634fcb7bb..fee579f10b32 100644 --- a/include/media/saa7146.h +++ b/include/media/saa7146.h @@ -11,6 +11,8 @@ #include /* for i2c subsystem */ #include /* for accessing devices */ #include +#include + #include /* for vmalloc() */ #include /* for vmalloc_to_page() */ @@ -112,7 +114,7 @@ struct saa7146_dev /* different device locks */ spinlock_t slock; - struct semaphore lock; + struct mutex lock; unsigned char __iomem *mem; /* pointer to mapped IO memory */ int revision; /* chip revision; needed for bug-workarounds*/ @@ -133,15 +135,16 @@ struct saa7146_dev void (*vv_callback)(struct saa7146_dev *dev, unsigned long status); /* i2c-stuff */ - struct semaphore i2c_lock; - u32 i2c_bitrate; - struct saa7146_dma d_i2c; /* pointer to i2c memory */ - wait_queue_head_t i2c_wq; - int i2c_op; + struct mutex i2c_lock; + + u32 i2c_bitrate; + struct saa7146_dma d_i2c; /* pointer to i2c memory */ + wait_queue_head_t i2c_wq; + int i2c_op; /* memories */ - struct saa7146_dma d_rps0; - struct saa7146_dma d_rps1; + struct saa7146_dma d_rps0; + struct saa7146_dma d_rps1; }; /* from saa7146_i2c.c */ @@ -150,7 +153,7 @@ int saa7146_i2c_transfer(struct saa7146_dev *saa, const struct i2c_msg *msgs, in /* from saa7146_core.c */ extern struct list_head saa7146_devices; -extern struct semaphore saa7146_devices_lock; +extern struct mutex saa7146_devices_lock; int saa7146_register_extension(struct saa7146_extension*); int saa7146_unregister_extension(struct saa7146_extension*); struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc); diff --git a/include/media/video-buf-dvb.h b/include/media/video-buf-dvb.h index ad0a07a3a895..b78d90fe629f 100644 --- a/include/media/video-buf-dvb.h +++ b/include/media/video-buf-dvb.h @@ -11,7 +11,7 @@ struct videobuf_dvb { struct videobuf_queue dvbq; /* video-buf-dvb state info */ - struct semaphore lock; + struct mutex lock; struct task_struct *thread; int nfeeds; diff --git a/include/media/video-buf.h b/include/media/video-buf.h index 8ecfd78e0027..d90dec5484ee 100644 --- a/include/media/video-buf.h +++ b/include/media/video-buf.h @@ -177,7 +177,7 @@ struct videobuf_queue_ops { }; struct videobuf_queue { - struct semaphore lock; + struct mutex lock; spinlock_t *irqlock; struct pci_dev *pci; -- cgit v1.2.3 From b4367e7451f19a3ae8b453e8b7ac0a1fdd9bca04 Mon Sep 17 00:00:00 2001 From: "Grant C. Likely" Date: Thu, 19 Jan 2006 01:12:32 -0700 Subject: [PATCH] powerpc: Move xparameters.h into xilinx virtex device specific path xparameters should not be needed by anything but virtex platform code. Move it from include/asm-ppc/ to platforms/4xx/xparameters/ This is preparing for work to remove xparameters from the dependancy tree for most c files. xparam changes should not cause a recompile of the world. Instead, drivers should get device info from the platform bus (populated by the boot code) Signed-off-by: Grant C. Likely Signed-off-by: Paul Mackerras --- arch/ppc/platforms/4xx/virtex-ii_pro.h | 2 +- arch/ppc/platforms/4xx/xparameters/xparameters.h | 18 ++++++++++++++++++ arch/ppc/syslib/xilinx_pic.c | 2 +- include/asm-ppc/xparameters.h | 18 ------------------ 4 files changed, 20 insertions(+), 20 deletions(-) create mode 100644 arch/ppc/platforms/4xx/xparameters/xparameters.h delete mode 100644 include/asm-ppc/xparameters.h (limited to 'include') diff --git a/arch/ppc/platforms/4xx/virtex-ii_pro.h b/arch/ppc/platforms/4xx/virtex-ii_pro.h index 9014c4887339..026130c8e72a 100644 --- a/arch/ppc/platforms/4xx/virtex-ii_pro.h +++ b/arch/ppc/platforms/4xx/virtex-ii_pro.h @@ -16,7 +16,7 @@ #define __ASM_VIRTEXIIPRO_H__ #include -#include +#include /* serial defines */ diff --git a/arch/ppc/platforms/4xx/xparameters/xparameters.h b/arch/ppc/platforms/4xx/xparameters/xparameters.h new file mode 100644 index 000000000000..fe4eac629139 --- /dev/null +++ b/arch/ppc/platforms/4xx/xparameters/xparameters.h @@ -0,0 +1,18 @@ +/* + * include/asm-ppc/xparameters.h + * + * This file includes the correct xparameters.h for the CONFIG'ed board + * + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * 2004 (c) MontaVista Software, Inc. This file is licensed under the terms + * of the GNU General Public License version 2. This program is licensed + * "as is" without any warranty of any kind, whether express or implied. + */ + +#include + +#if defined(CONFIG_XILINX_ML300) +#include +#endif diff --git a/arch/ppc/syslib/xilinx_pic.c b/arch/ppc/syslib/xilinx_pic.c index 47f04c71fe9c..848fb512f3f8 100644 --- a/arch/ppc/syslib/xilinx_pic.c +++ b/arch/ppc/syslib/xilinx_pic.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include diff --git a/include/asm-ppc/xparameters.h b/include/asm-ppc/xparameters.h deleted file mode 100644 index fe4eac629139..000000000000 --- a/include/asm-ppc/xparameters.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * include/asm-ppc/xparameters.h - * - * This file includes the correct xparameters.h for the CONFIG'ed board - * - * Author: MontaVista Software, Inc. - * source@mvista.com - * - * 2004 (c) MontaVista Software, Inc. This file is licensed under the terms - * of the GNU General Public License version 2. This program is licensed - * "as is" without any warranty of any kind, whether express or implied. - */ - -#include - -#if defined(CONFIG_XILINX_ML300) -#include -#endif -- cgit v1.2.3 From 1a42e53d175074f340a3f85042ed64cfc51be216 Mon Sep 17 00:00:00 2001 From: "Grant C. Likely" Date: Thu, 19 Jan 2006 01:12:48 -0700 Subject: [PATCH] powerpc: Migrate Xilinx Vertex support from the OCP bus to the platfom bus. This patch only deals with the serial port definitions as there is no support for any other xilinx IP cores in the kernel tree at the moment. Board specific configuration moved out of virtex.[ch] and into the xparameters.h wrapper. This also prepares for the transition to the flattened device tree model. When the bootloader provides a device tree generated from an xparameters.h files, the kernel will no longer need xparameters/*. The platform bus will get populated with data from the device tree, and the device drivers will be automatically connected to the devices. Only the bootloader (or ppcboot) will need xparameters directly. Signed-off-by: Grant C. Likely Signed-off-by: Paul Mackerras --- arch/ppc/boot/common/ns16550.c | 3 + arch/ppc/boot/simple/embed_config.c | 3 + arch/ppc/platforms/4xx/Kconfig | 5 -- arch/ppc/platforms/4xx/virtex.c | 88 +++++++++++------------- arch/ppc/platforms/4xx/virtex.h | 86 +++-------------------- arch/ppc/platforms/4xx/xparameters/xparameters.h | 21 +++++- include/asm-ppc/ppc_sys.h | 2 + 7 files changed, 80 insertions(+), 128 deletions(-) (limited to 'include') diff --git a/arch/ppc/boot/common/ns16550.c b/arch/ppc/boot/common/ns16550.c index 26818bbb6cff..4f00c93ac870 100644 --- a/arch/ppc/boot/common/ns16550.c +++ b/arch/ppc/boot/common/ns16550.c @@ -8,6 +8,9 @@ #include #include +#if defined(CONFIG_XILINX_VIRTEX) +#include +#endif #include "nonstdio.h" #include "serial.h" diff --git a/arch/ppc/boot/simple/embed_config.c b/arch/ppc/boot/simple/embed_config.c index 491a691d10cc..df24202073bf 100644 --- a/arch/ppc/boot/simple/embed_config.c +++ b/arch/ppc/boot/simple/embed_config.c @@ -21,6 +21,9 @@ #ifdef CONFIG_40x #include #endif +#ifdef CONFIG_XILINX_VIRTEX +#include +#endif extern unsigned long timebase_period_ns; /* For those boards that don't provide one. diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig index 203abab32cc3..057c7c2ab99d 100644 --- a/arch/ppc/platforms/4xx/Kconfig +++ b/arch/ppc/platforms/4xx/Kconfig @@ -172,11 +172,6 @@ config IBM_OCP depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || YUCCA || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT default y -config XILINX_OCP - bool - depends on XILINX_ML300 - default y - config IBM_EMAC4 bool depends on 440GX || 440SP || 440SPE diff --git a/arch/ppc/platforms/4xx/virtex.c b/arch/ppc/platforms/4xx/virtex.c index bbb12c0c0b2c..133a83147199 100644 --- a/arch/ppc/platforms/4xx/virtex.c +++ b/arch/ppc/platforms/4xx/virtex.c @@ -1,60 +1,56 @@ /* - * arch/ppc/platforms/4xx/virtex.c + * Virtex-II Pro & Virtex-4 FX common infrastructure * - * Author: MontaVista Software, Inc. - * source@mvista.com + * Maintainer: Grant Likely * - * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under the - * terms of the GNU General Public License version 2. This program is licensed - * "as is" without any warranty of any kind, whether express or implied. + * Copyright 2005 Secret Lab Technologies Ltd. + * Copyright 2005 General Dynamics Canada Ltd. + * Copyright 2005 Freescale Semiconductor Inc. + * + * 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. */ -#include #include -#include +#include +#include +#include +#include #include +#include + +#define XPAR_UART(num) { \ + .mapbase = XPAR_UARTNS550_##num##_BASEADDR + 3, \ + .irq = XPAR_INTC_0_UARTNS550_##num##_VEC_ID, \ + .iotype = UPIO_MEM, \ + .uartclk = XPAR_UARTNS550_##num##_CLOCK_FREQ_HZ, \ + .flags = UPF_BOOT_AUTOCONF, \ + .regshift = 2, \ + } -/* Have OCP take care of the serial ports. */ -struct ocp_def core_ocp[] = { +struct plat_serial8250_port serial_platform_data[] = { #ifdef XPAR_UARTNS550_0_BASEADDR - { .vendor = OCP_VENDOR_XILINX, - .function = OCP_FUNC_16550, - .index = 0, - .paddr = XPAR_UARTNS550_0_BASEADDR, - .irq = XPAR_INTC_0_UARTNS550_0_VEC_ID, - .pm = OCP_CPM_NA - }, + XPAR_UART(0), +#endif #ifdef XPAR_UARTNS550_1_BASEADDR - { .vendor = OCP_VENDOR_XILINX, - .function = OCP_FUNC_16550, - .index = 1, - .paddr = XPAR_UARTNS550_1_BASEADDR, - .irq = XPAR_INTC_0_UARTNS550_1_VEC_ID, - .pm = OCP_CPM_NA - }, + XPAR_UART(1), +#endif #ifdef XPAR_UARTNS550_2_BASEADDR - { .vendor = OCP_VENDOR_XILINX, - .function = OCP_FUNC_16550, - .index = 2, - .paddr = XPAR_UARTNS550_2_BASEADDR, - .irq = XPAR_INTC_0_UARTNS550_2_VEC_ID, - .pm = OCP_CPM_NA - }, + XPAR_UART(2), +#endif #ifdef XPAR_UARTNS550_3_BASEADDR - { .vendor = OCP_VENDOR_XILINX, - .function = OCP_FUNC_16550, - .index = 3, - .paddr = XPAR_UARTNS550_3_BASEADDR, - .irq = XPAR_INTC_0_UARTNS550_3_VEC_ID, - .pm = OCP_CPM_NA + XPAR_UART(3), +#endif + { }, /* terminated by empty record */ +}; + +struct platform_device ppc_sys_platform_devices[] = { + [VIRTEX_UART] = { + .name = "serial8250", + .id = 0, + .dev.platform_data = serial_platform_data, }, -#ifdef XPAR_UARTNS550_4_BASEADDR -#error Edit this file to add more devices. -#endif /* 4 */ -#endif /* 3 */ -#endif /* 2 */ -#endif /* 1 */ -#endif /* 0 */ - { .vendor = OCP_VENDOR_INVALID - } }; + diff --git a/arch/ppc/platforms/4xx/virtex.h b/arch/ppc/platforms/4xx/virtex.h index 049c767d33e7..1a01b81cff11 100644 --- a/arch/ppc/platforms/4xx/virtex.h +++ b/arch/ppc/platforms/4xx/virtex.h @@ -15,85 +15,21 @@ #ifndef __ASM_VIRTEX_H__ #define __ASM_VIRTEX_H__ -#include -#include - /* serial defines */ -#define RS_TABLE_SIZE 4 /* change this and add more devices below - if you have more then 4 16x50 UARTs */ - -#define BASE_BAUD (XPAR_UARTNS550_0_CLOCK_FREQ_HZ/16) - -/* The serial ports in the Virtex-II Pro have each I/O byte in the - * LSByte of a word. This means that iomem_reg_shift needs to be 2 to - * change the byte offsets into word offsets. In addition the base - * addresses need to have 3 added to them to get to the LSByte. - */ -#define STD_UART_OP(num) \ - { 0, BASE_BAUD, 0, XPAR_INTC_0_UARTNS550_##num##_VEC_ID, \ - ASYNC_BOOT_AUTOCONF, \ - .iomem_base = (u8 *)XPAR_UARTNS550_##num##_BASEADDR + 3, \ - .iomem_reg_shift = 2, \ - .io_type = SERIAL_IO_MEM}, - -#if defined(XPAR_INTC_0_UARTNS550_0_VEC_ID) -#define ML300_UART0 STD_UART_OP(0) -#else -#define ML300_UART0 -#endif - -#if defined(XPAR_INTC_0_UARTNS550_1_VEC_ID) -#define ML300_UART1 STD_UART_OP(1) -#else -#define ML300_UART1 -#endif - -#if defined(XPAR_INTC_0_UARTNS550_2_VEC_ID) -#define ML300_UART2 STD_UART_OP(2) -#else -#define ML300_UART2 -#endif - -#if defined(XPAR_INTC_0_UARTNS550_3_VEC_ID) -#define ML300_UART3 STD_UART_OP(3) -#else -#define ML300_UART3 -#endif - -#if defined(XPAR_INTC_0_UARTNS550_4_VEC_ID) -#error Edit this file to add more devices. -#elif defined(XPAR_INTC_0_UARTNS550_3_VEC_ID) -#define NR_SER_PORTS 4 -#elif defined(XPAR_INTC_0_UARTNS550_2_VEC_ID) -#define NR_SER_PORTS 3 -#elif defined(XPAR_INTC_0_UARTNS550_1_VEC_ID) -#define NR_SER_PORTS 2 -#elif defined(XPAR_INTC_0_UARTNS550_0_VEC_ID) -#define NR_SER_PORTS 1 -#else -#define NR_SER_PORTS 0 -#endif +#include -#if defined(CONFIG_UART0_TTYS0) -#define SERIAL_PORT_DFNS \ - ML300_UART0 \ - ML300_UART1 \ - ML300_UART2 \ - ML300_UART3 +/* Ugly, ugly, ugly! BASE_BAUD defined here to keep 8250.c happy. */ +#if !defined(BASE_BAUD) + #define BASE_BAUD (0) /* dummy value; not used */ #endif - -#if defined(CONFIG_UART0_TTYS1) -#define SERIAL_PORT_DFNS \ - ML300_UART1 \ - ML300_UART0 \ - ML300_UART2 \ - ML300_UART3 + +/* Device type enumeration for platform bus definitions */ +#ifndef __ASSEMBLY__ +enum ppc_sys_devices { + VIRTEX_UART, +}; #endif - -#define DCRN_CPMFR_BASE 0 - -#include - + #endif /* __ASM_VIRTEX_H__ */ #endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/4xx/xparameters/xparameters.h b/arch/ppc/platforms/4xx/xparameters/xparameters.h index fe4eac629139..7b7304379dd2 100644 --- a/arch/ppc/platforms/4xx/xparameters/xparameters.h +++ b/arch/ppc/platforms/4xx/xparameters/xparameters.h @@ -1,7 +1,8 @@ /* * include/asm-ppc/xparameters.h * - * This file includes the correct xparameters.h for the CONFIG'ed board + * This file includes the correct xparameters.h for the CONFIG'ed board plus + * fixups to translate board specific XPAR values to a common set of names * * Author: MontaVista Software, Inc. * source@mvista.com @@ -14,5 +15,21 @@ #include #if defined(CONFIG_XILINX_ML300) -#include + #include "xparameters_ml300.h" +#else + /* Add other board xparameter includes here before the #else */ + #error No xparameters_*.h file included +#endif + +#ifndef SERIAL_PORT_DFNS + /* zImage serial port definitions */ + #define RS_TABLE_SIZE 1 + #define SERIAL_PORT_DFNS { \ + .baud_base = XPAR_UARTNS550_0_CLOCK_FREQ_HZ/16, \ + .irq = XPAR_INTC_0_UARTNS550_0_VEC_ID, \ + .flags = ASYNC_BOOT_AUTOCONF, \ + .iomem_base = (u8 *)XPAR_UARTNS550_0_BASEADDR + 3, \ + .iomem_reg_shift = 2, \ + .io_type = SERIAL_IO_MEM, \ + }, #endif diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h index 83d8c77c124d..bdc4dde35edd 100644 --- a/include/asm-ppc/ppc_sys.h +++ b/include/asm-ppc/ppc_sys.h @@ -33,6 +33,8 @@ #include #elif defined(CONFIG_MPC10X_BRIDGE) #include +#elif defined(CONFIG_XILINX_VIRTEX) +#include #else #error "need definition of ppc_sys_devices" #endif -- cgit v1.2.3 From 909aeca664dd1fe55111dc4ec25c1bebe91674a2 Mon Sep 17 00:00:00 2001 From: "Grant C. Likely" Date: Thu, 19 Jan 2006 01:13:37 -0700 Subject: [PATCH] powerpc: Add support for Xilinx ML403 reference design Includes fix for Xilinx silicon errata 213 Signed-off-by: Grant C. Likely Signed-off-by: Paul Mackerras --- arch/ppc/boot/simple/Makefile | 1 + arch/ppc/boot/simple/embed_config.c | 4 +- arch/ppc/boot/simple/head.S | 7 + arch/ppc/platforms/4xx/Kconfig | 13 +- arch/ppc/platforms/4xx/Makefile | 2 + arch/ppc/platforms/4xx/xilinx_ml403.c | 177 +++++++++++++++++++++++ arch/ppc/platforms/4xx/xilinx_ml403.h | 49 +++++++ arch/ppc/platforms/4xx/xparameters/xparameters.h | 2 + include/asm-ppc/ibm4xx.h | 4 + 9 files changed, 255 insertions(+), 4 deletions(-) create mode 100644 arch/ppc/platforms/4xx/xilinx_ml403.c create mode 100644 arch/ppc/platforms/4xx/xilinx_ml403.h (limited to 'include') diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile index 9533f8de238f..28be01b99c44 100644 --- a/arch/ppc/boot/simple/Makefile +++ b/arch/ppc/boot/simple/Makefile @@ -192,6 +192,7 @@ boot-$(CONFIG_8xx) += embed_config.o boot-$(CONFIG_8260) += embed_config.o boot-$(CONFIG_EP405) += embed_config.o boot-$(CONFIG_XILINX_ML300) += embed_config.o +boot-$(CONFIG_XILINX_ML403) += embed_config.o boot-$(CONFIG_BSEIP) += iic.o boot-$(CONFIG_MBX) += iic.o pci.o qspan_pci.o boot-$(CONFIG_MV64X60) += misc-mv64x60.o diff --git a/arch/ppc/boot/simple/embed_config.c b/arch/ppc/boot/simple/embed_config.c index df24202073bf..3a51b1062940 100644 --- a/arch/ppc/boot/simple/embed_config.c +++ b/arch/ppc/boot/simple/embed_config.c @@ -745,7 +745,7 @@ embed_config(bd_t **bdp) } #endif /* WILLOW */ -#ifdef CONFIG_XILINX_ML300 +#if defined(CONFIG_XILINX_ML300) || defined(CONFIG_XILINX_ML403) void embed_config(bd_t ** bdp) { @@ -782,7 +782,7 @@ embed_config(bd_t ** bdp) timebase_period_ns = 1000000000 / bd->bi_tbfreq; /* see bi_tbfreq definition in arch/ppc/platforms/4xx/xilinx_ml300.h */ } -#endif /* CONFIG_XILINX_ML300 */ +#endif /* CONFIG_XILINX_ML300 || CONFIG_XILINX_ML403 */ #ifdef CONFIG_IBM_OPENBIOS /* This could possibly work for all treeboot roms. diff --git a/arch/ppc/boot/simple/head.S b/arch/ppc/boot/simple/head.S index 5e4adc298bf9..119b9dc89587 100644 --- a/arch/ppc/boot/simple/head.S +++ b/arch/ppc/boot/simple/head.S @@ -65,6 +65,13 @@ start_: */ #endif +#if defined(CONFIG_XILINX_VIRTEX_4_FX) + /* PPC errata 213: only for Virtex-4 FX */ + mfccr0 0 + oris 0,0,0x50000000@h + mtccr0 0 +#endif + mflr r3 /* Save our actual starting address. */ /* The following functions we call must not modify r3 or r4..... diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig index 057c7c2ab99d..174ddbc9758b 100644 --- a/arch/ppc/platforms/4xx/Kconfig +++ b/arch/ppc/platforms/4xx/Kconfig @@ -57,6 +57,10 @@ config XILINX_ML300 help This option enables support for the Xilinx ML300 evaluation board. +config XILINX_ML403 + bool "Xilinx-ML403" + help + This option enables support for the Xilinx ML403 evaluation board. endchoice choice @@ -208,9 +212,14 @@ config XILINX_VIRTEX_II_PRO depends on XILINX_ML300 default y +config XILINX_VIRTEX_4_FX + bool + depends on XILINX_ML403 + default y + config XILINX_VIRTEX bool - depends on XILINX_VIRTEX_II_PRO + depends on XILINX_VIRTEX_II_PRO || XILINX_VIRTEX_4_FX default y config STB03xxx @@ -220,7 +229,7 @@ config STB03xxx config EMBEDDEDBOOT bool - depends on EP405 || XILINX_ML300 + depends on EP405 || XILINX_ML300 || XILINX_ML403 default y config IBM_OPENBIOS diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile index be4163c8afe7..a04a0d0a0f5c 100644 --- a/arch/ppc/platforms/4xx/Makefile +++ b/arch/ppc/platforms/4xx/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_REDWOOD_6) += redwood6.o obj-$(CONFIG_SYCAMORE) += sycamore.o obj-$(CONFIG_WALNUT) += walnut.o obj-$(CONFIG_XILINX_ML300) += xilinx_ml300.o +obj-$(CONFIG_XILINX_ML403) += xilinx_ml403.o obj-$(CONFIG_405GP) += ibm405gp.o obj-$(CONFIG_REDWOOD_5) += ibmstb4.o @@ -27,3 +28,4 @@ obj-$(CONFIG_440SPE) += ppc440spe.o obj-$(CONFIG_405EP) += ibm405ep.o obj-$(CONFIG_405GPR) += ibm405gpr.o obj-$(CONFIG_XILINX_VIRTEX) += virtex.o + diff --git a/arch/ppc/platforms/4xx/xilinx_ml403.c b/arch/ppc/platforms/4xx/xilinx_ml403.c new file mode 100644 index 000000000000..4c0c7e4c1114 --- /dev/null +++ b/arch/ppc/platforms/4xx/xilinx_ml403.c @@ -0,0 +1,177 @@ +/* + * arch/ppc/platforms/4xx/xilinx_ml403.c + * + * Xilinx ML403 evaluation board initialization + * + * Author: Grant Likely + * + * 2005 (c) Secret Lab Technologies Ltd. + * 2002-2004 (c) MontaVista Software, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * As an overview of how the following functions (platform_init, + * ml403_map_io, ml403_setup_arch and ml403_init_IRQ) fit into the + * kernel startup procedure, here's a call tree: + * + * start_here arch/ppc/kernel/head_4xx.S + * early_init arch/ppc/kernel/setup.c + * machine_init arch/ppc/kernel/setup.c + * platform_init this file + * ppc4xx_init arch/ppc/syslib/ppc4xx_setup.c + * parse_bootinfo + * find_bootinfo + * "setup some default ppc_md pointers" + * MMU_init arch/ppc/mm/init.c + * *ppc_md.setup_io_mappings == ml403_map_io this file + * ppc4xx_map_io arch/ppc/syslib/ppc4xx_setup.c + * start_kernel init/main.c + * setup_arch arch/ppc/kernel/setup.c + * #if defined(CONFIG_KGDB) + * *ppc_md.kgdb_map_scc() == gen550_kgdb_map_scc + * #endif + * *ppc_md.setup_arch == ml403_setup_arch this file + * ppc4xx_setup_arch arch/ppc/syslib/ppc4xx_setup.c + * ppc4xx_find_bridges arch/ppc/syslib/ppc405_pci.c + * init_IRQ arch/ppc/kernel/irq.c + * *ppc_md.init_IRQ == ml403_init_IRQ this file + * ppc4xx_init_IRQ arch/ppc/syslib/ppc4xx_setup.c + * ppc4xx_pic_init arch/ppc/syslib/xilinx_pic.c + */ + +/* Board specifications structures */ +struct ppc_sys_spec *cur_ppc_sys_spec; +struct ppc_sys_spec ppc_sys_specs[] = { + { + /* Only one entry, always assume the same design */ + .ppc_sys_name = "Xilinx ML403 Reference Design", + .mask = 0x00000000, + .value = 0x00000000, + .num_devices = 1, + .device_list = (enum ppc_sys_devices[]) + { + VIRTEX_UART, + }, + }, +}; + +#if defined(XPAR_POWER_0_POWERDOWN_BASEADDR) + +static volatile unsigned *powerdown_base = + (volatile unsigned *) XPAR_POWER_0_POWERDOWN_BASEADDR; + +static void +xilinx_power_off(void) +{ + local_irq_disable(); + out_be32(powerdown_base, XPAR_POWER_0_POWERDOWN_VALUE); + while (1) ; +} +#endif + +void __init +ml403_map_io(void) +{ + ppc4xx_map_io(); + +#if defined(XPAR_POWER_0_POWERDOWN_BASEADDR) + powerdown_base = ioremap((unsigned long) powerdown_base, + XPAR_POWER_0_POWERDOWN_HIGHADDR - + XPAR_POWER_0_POWERDOWN_BASEADDR + 1); +#endif +} + +/* Early serial support functions */ +static void __init +ml403_early_serial_init(int num, struct plat_serial8250_port *pdata) +{ +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + struct uart_port serial_req; + + memset(&serial_req, 0, sizeof(serial_req)); + serial_req.mapbase = pdata->mapbase; + serial_req.membase = pdata->membase; + serial_req.irq = pdata->irq; + serial_req.uartclk = pdata->uartclk; + serial_req.regshift = pdata->regshift; + serial_req.iotype = pdata->iotype; + serial_req.flags = pdata->flags; + gen550_init(num, &serial_req); +#endif +} + +void __init +ml403_early_serial_map(void) +{ +#ifdef CONFIG_SERIAL_8250 + struct plat_serial8250_port *pdata; + int i = 0; + + pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(VIRTEX_UART); + while(pdata && pdata->flags) + { + pdata->membase = ioremap(pdata->mapbase, 0x100); + ml403_early_serial_init(i, pdata); + pdata++; + i++; + } +#endif /* CONFIG_SERIAL_8250 */ +} + +void __init +ml403_setup_arch(void) +{ + ml403_early_serial_map(); + ppc4xx_setup_arch(); /* calls ppc4xx_find_bridges() */ + + /* Identify the system */ + printk(KERN_INFO "Xilinx ML403 Reference System (Virtex-4 FX)\n"); +} + +/* Called after board_setup_irq from ppc4xx_init_IRQ(). */ +void __init +ml403_init_irq(void) +{ + ppc4xx_init_IRQ(); +} + +void __init +platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + ppc4xx_init(r3, r4, r5, r6, r7); + + identify_ppc_sys_by_id(mfspr(SPRN_PVR)); + + ppc_md.setup_arch = ml403_setup_arch; + ppc_md.setup_io_mappings = ml403_map_io; + ppc_md.init_IRQ = ml403_init_irq; + +#if defined(XPAR_POWER_0_POWERDOWN_BASEADDR) + ppc_md.power_off = xilinx_power_off; +#endif + +#ifdef CONFIG_KGDB + ppc_md.early_serial_map = ml403_early_serial_map; +#endif +} + diff --git a/arch/ppc/platforms/4xx/xilinx_ml403.h b/arch/ppc/platforms/4xx/xilinx_ml403.h new file mode 100644 index 000000000000..473596959902 --- /dev/null +++ b/arch/ppc/platforms/4xx/xilinx_ml403.h @@ -0,0 +1,49 @@ +/* + * arch/ppc/platforms/4xx/xilinx_ml403.h + * + * Include file that defines the Xilinx ML403 reference design + * + * Author: Grant Likely + * + * 2005 (c) Secret Lab Technologies Ltd. + * 2002-2004 (c) MontaVista Software, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#ifdef __KERNEL__ +#ifndef __ASM_XILINX_ML403_H__ +#define __ASM_XILINX_ML403_H__ + +/* ML403 has a Xilinx Virtex-4 FPGA with a PPC405 hard core */ +#include + +#ifndef __ASSEMBLY__ + +#include + +typedef struct board_info { + unsigned int bi_memsize; /* DRAM installed, in bytes */ + unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ + unsigned int bi_intfreq; /* Processor speed, in Hz */ + unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ + unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ +} bd_t; + +/* Some 4xx parts use a different timebase frequency from the internal clock. +*/ +#define bi_tbfreq bi_intfreq + +#endif /* !__ASSEMBLY__ */ + +/* We don't need anything mapped. Size of zero will accomplish that. */ +#define PPC4xx_ONB_IO_PADDR 0u +#define PPC4xx_ONB_IO_VADDR 0u +#define PPC4xx_ONB_IO_SIZE 0u + +#define PPC4xx_MACHINE_NAME "Xilinx ML403 Reference Design" + +#endif /* __ASM_XILINX_ML403_H__ */ +#endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/4xx/xparameters/xparameters.h b/arch/ppc/platforms/4xx/xparameters/xparameters.h index 7b7304379dd2..4cf21f256356 100644 --- a/arch/ppc/platforms/4xx/xparameters/xparameters.h +++ b/arch/ppc/platforms/4xx/xparameters/xparameters.h @@ -16,6 +16,8 @@ #if defined(CONFIG_XILINX_ML300) #include "xparameters_ml300.h" +#elif defined(CONFIG_XILINX_ML403) + #include "xparameters_ml403.h" #else /* Add other board xparameter includes here before the #else */ #error No xparameters_*.h file included diff --git a/include/asm-ppc/ibm4xx.h b/include/asm-ppc/ibm4xx.h index 6c28ae7807f4..38f99710752b 100644 --- a/include/asm-ppc/ibm4xx.h +++ b/include/asm-ppc/ibm4xx.h @@ -51,6 +51,10 @@ #include #endif +#if defined(CONFIG_XILINX_ML403) +#include +#endif + #ifndef __ASSEMBLY__ #ifdef CONFIG_40x -- cgit v1.2.3 From d7a5b2ffa1352f0310630934a56aecbdfb617b72 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 25 Jan 2006 21:31:28 +1300 Subject: [PATCH] powerpc: Always panic if lmb_alloc() fails Currently most callers of lmb_alloc() don't check if it worked or not, if it ever does weird bad things will probably happen. The few callers who do check just panic or BUG_ON. So make lmb_alloc() panic internally, to catch bugs at the source. The few callers who did check the result no longer need to. The only caller that did anything interesting with the return result was careful_allocation(). For it we create __lmb_alloc_base() which _doesn't_ panic automatically, a little messy, but passable. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 4 ---- arch/powerpc/mm/hash_utils_64.c | 1 - arch/powerpc/mm/lmb.c | 14 ++++++++++++++ arch/powerpc/mm/mem.c | 1 - arch/powerpc/mm/numa.c | 4 ++-- arch/powerpc/mm/stab.c | 4 ---- arch/powerpc/sysdev/dart_iommu.c | 2 -- include/asm-powerpc/lmb.h | 2 ++ 8 files changed, 18 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 294832a7e0a6..82d117c60d7f 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -831,10 +831,6 @@ void __init unflatten_device_tree(void) /* Allocate memory for the expanded device tree */ mem = lmb_alloc(size + 4, __alignof__(struct device_node)); - if (!mem) { - DBG("Couldn't allocate memory with lmb_alloc()!\n"); - panic("Couldn't allocate memory with lmb_alloc()!\n"); - } mem = (unsigned long) __va(mem); ((u32 *)mem)[size / 4] = 0xdeadbeef; diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 149351a84b94..95b4cd6b65e0 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -430,7 +430,6 @@ void __init htab_initialize(void) * the absolute address space. */ table = lmb_alloc(htab_size_bytes, htab_size_bytes); - BUG_ON(table == 0); DBG("Hash table allocated at %lx, size: %lx\n", table, htab_size_bytes); diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c index bbe3eac918e8..d9c76ce5fa8f 100644 --- a/arch/powerpc/mm/lmb.c +++ b/arch/powerpc/mm/lmb.c @@ -225,6 +225,20 @@ unsigned long __init lmb_alloc(unsigned long size, unsigned long align) unsigned long __init lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr) +{ + unsigned long alloc; + + alloc = __lmb_alloc_base(size, align, max_addr); + + if (alloc < 0) + panic("ERROR: Failed to allocate 0x%lx bytes below 0x%lx.\n", + size, max_addr); + + return alloc; +} + +unsigned long __init __lmb_alloc_base(unsigned long size, unsigned long align, + unsigned long max_addr) { long i, j; unsigned long base = 0; diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 550517c2dd42..6809cdba6e94 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -249,7 +249,6 @@ void __init do_init_bootmem(void) bootmap_pages = bootmem_bootmap_pages(total_pages); start = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE); - BUG_ON(!start); boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages); diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 2863a912bcd0..da5280f8cf42 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -570,11 +570,11 @@ static void __init *careful_allocation(int nid, unsigned long size, unsigned long end_pfn) { int new_nid; - unsigned long ret = lmb_alloc_base(size, align, end_pfn << PAGE_SHIFT); + unsigned long ret = __lmb_alloc_base(size, align, end_pfn << PAGE_SHIFT); /* retry over all memory */ if (!ret) - ret = lmb_alloc_base(size, align, lmb_end_of_DRAM()); + ret = __lmb_alloc_base(size, align, lmb_end_of_DRAM()); if (!ret) panic("numa.c: cannot allocate %lu bytes on node %d", diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c index 82e4951826bc..91d25fb27f89 100644 --- a/arch/powerpc/mm/stab.c +++ b/arch/powerpc/mm/stab.c @@ -247,10 +247,6 @@ void stabs_alloc(void) newstab = lmb_alloc_base(HW_PAGE_SIZE, HW_PAGE_SIZE, 1<> DART_PAGE_SHIFT) & DARTMAP_RPNMASK); diff --git a/include/asm-powerpc/lmb.h b/include/asm-powerpc/lmb.h index d3546c4c9f46..4fda8eaaeaf4 100644 --- a/include/asm-powerpc/lmb.h +++ b/include/asm-powerpc/lmb.h @@ -48,6 +48,8 @@ extern long __init lmb_reserve(unsigned long, unsigned long); extern unsigned long __init lmb_alloc(unsigned long, unsigned long); extern unsigned long __init lmb_alloc_base(unsigned long, unsigned long, unsigned long); +extern unsigned long __init __lmb_alloc_base(unsigned long, unsigned long, + unsigned long); extern unsigned long __init lmb_phys_mem_size(void); extern unsigned long __init lmb_end_of_DRAM(void); extern unsigned long __init lmb_abs_to_phys(unsigned long); -- cgit v1.2.3 From 3b9331dac16555e8788ae21723f2146c3f994ebb Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 25 Jan 2006 21:31:30 +1300 Subject: [PATCH] powerpc: Move LMB_ALLOC_ANYWHERE out of lmb.h LMB_ALLOC_ANYWHERE doesn't need to be part of the API, it's only used in lmb.c - so move it out of the header file. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/mm/lmb.c | 2 ++ include/asm-powerpc/lmb.h | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c index d9c76ce5fa8f..874cd103ce6e 100644 --- a/arch/powerpc/mm/lmb.c +++ b/arch/powerpc/mm/lmb.c @@ -31,6 +31,8 @@ #define DBG(fmt...) #endif +#define LMB_ALLOC_ANYWHERE 0 + struct lmb lmb; void lmb_dump_all(void) diff --git a/include/asm-powerpc/lmb.h b/include/asm-powerpc/lmb.h index 4fda8eaaeaf4..fbb7bde8fb0b 100644 --- a/include/asm-powerpc/lmb.h +++ b/include/asm-powerpc/lmb.h @@ -19,8 +19,6 @@ #define MAX_LMB_REGIONS 128 -#define LMB_ALLOC_ANYWHERE 0 - struct lmb_property { unsigned long base; unsigned long size; -- cgit v1.2.3 From 56b5c9737cdd8814a10f3022fc0cef8af9ea9ba5 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 25 Jan 2006 21:31:36 +1300 Subject: [PATCH] powerpc: Put parameter names in lmb.h prototypes Prototypes aren't so useful without parameter names, add them to lmb.h based on the names in lmb.c Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- include/asm-powerpc/lmb.h | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/asm-powerpc/lmb.h b/include/asm-powerpc/lmb.h index fbb7bde8fb0b..377ac1b23aa3 100644 --- a/include/asm-powerpc/lmb.h +++ b/include/asm-powerpc/lmb.h @@ -41,17 +41,16 @@ extern struct lmb lmb; extern void __init lmb_init(void); extern void __init lmb_analyze(void); -extern long __init lmb_add(unsigned long, unsigned long); -extern long __init lmb_reserve(unsigned long, unsigned long); -extern unsigned long __init lmb_alloc(unsigned long, unsigned long); -extern unsigned long __init lmb_alloc_base(unsigned long, unsigned long, - unsigned long); -extern unsigned long __init __lmb_alloc_base(unsigned long, unsigned long, - unsigned long); +extern long __init lmb_add(unsigned long base, unsigned long size); +extern long __init lmb_reserve(unsigned long base, unsigned long size); +extern unsigned long __init lmb_alloc(unsigned long size, unsigned long align); +extern unsigned long __init lmb_alloc_base(unsigned long size, + unsigned long align, unsigned long max_addr); +extern unsigned long __init __lmb_alloc_base(unsigned long size, + unsigned long align, unsigned long max_addr); extern unsigned long __init lmb_phys_mem_size(void); extern unsigned long __init lmb_end_of_DRAM(void); -extern unsigned long __init lmb_abs_to_phys(unsigned long); -extern void __init lmb_enforce_memory_limit(unsigned long); +extern void __init lmb_enforce_memory_limit(unsigned long memory_limit); extern void lmb_dump_all(void); -- cgit v1.2.3 From 4bf64e72bd499d2bf3509c2dc60d09c39f72c782 Mon Sep 17 00:00:00 2001 From: "Chen, Kenneth W" Date: Thu, 26 Jan 2006 16:58:52 -0800 Subject: [IA64] map ia64_hint definition to intel compiler intrinsic Map ia64_hint() to internal intel compiler intrinsic. Signed-off-by: Ken Chen Signed-off-by: Tony Luck --- include/asm-ia64/intel_intrin.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-ia64/intel_intrin.h b/include/asm-ia64/intel_intrin.h index a7122d850177..88261ce79860 100644 --- a/include/asm-ia64/intel_intrin.h +++ b/include/asm-ia64/intel_intrin.h @@ -122,7 +122,8 @@ __s64 _m64_popcnt(__s64 a); #define ia64_getreg __getReg #define ia64_setreg __setReg -#define ia64_hint(x) +#define ia64_hint __hint +#define ia64_hint_pause __hint_pause #define ia64_mux1_brcst 0 #define ia64_mux1_mix 8 -- cgit v1.2.3 From c583f66dc41cfa4055b6ac8f50cc1ebf362298f7 Mon Sep 17 00:00:00 2001 From: "Chen, Kenneth W" Date: Thu, 26 Jan 2006 17:08:47 -0800 Subject: [IA64] clean up asm/intel_intrin.h Include intrinsic header file from icc compiler. Remove duplicate definition from kernel source. Signed-off-by: HJ Lu Signed-off-by: Ken Chen Signed-off-by: Tony Luck --- include/asm-ia64/intel_intrin.h | 109 ++-------------------------------------- 1 file changed, 3 insertions(+), 106 deletions(-) (limited to 'include') diff --git a/include/asm-ia64/intel_intrin.h b/include/asm-ia64/intel_intrin.h index 88261ce79860..c7ac04945c12 100644 --- a/include/asm-ia64/intel_intrin.h +++ b/include/asm-ia64/intel_intrin.h @@ -5,113 +5,10 @@ * * Copyright (C) 2002,2003 Jun Nakajima * Copyright (C) 2002,2003 Suresh Siddha + * Copyright (C) 2005,2006 Hongjiu Lu * */ -#include - -void __lfetch(int lfhint, void *y); -void __lfetch_excl(int lfhint, void *y); -void __lfetch_fault(int lfhint, void *y); -void __lfetch_fault_excl(int lfhint, void *y); - -/* In the following, whichFloatReg should be an integer from 0-127 */ -void __ldfs(const int whichFloatReg, void *src); -void __ldfd(const int whichFloatReg, void *src); -void __ldfe(const int whichFloatReg, void *src); -void __ldf8(const int whichFloatReg, void *src); -void __ldf_fill(const int whichFloatReg, void *src); -void __stfs(void *dst, const int whichFloatReg); -void __stfd(void *dst, const int whichFloatReg); -void __stfe(void *dst, const int whichFloatReg); -void __stf8(void *dst, const int whichFloatReg); -void __stf_spill(void *dst, const int whichFloatReg); - -void __st1_rel(void *dst, const __s8 value); -void __st2_rel(void *dst, const __s16 value); -void __st4_rel(void *dst, const __s32 value); -void __st8_rel(void *dst, const __s64 value); -__u8 __ld1_acq(void *src); -__u16 __ld2_acq(void *src); -__u32 __ld4_acq(void *src); -__u64 __ld8_acq(void *src); - -__u64 __fetchadd4_acq(__u32 *addend, const int increment); -__u64 __fetchadd4_rel(__u32 *addend, const int increment); -__u64 __fetchadd8_acq(__u64 *addend, const int increment); -__u64 __fetchadd8_rel(__u64 *addend, const int increment); - -__u64 __getf_exp(double d); - -/* OS Related Itanium(R) Intrinsics */ - -/* The names to use for whichReg and whichIndReg below come from - the include file asm/ia64regs.h */ - -__u64 __getIndReg(const int whichIndReg, __s64 index); -__u64 __getReg(const int whichReg); - -void __setIndReg(const int whichIndReg, __s64 index, __u64 value); -void __setReg(const int whichReg, __u64 value); - -void __mf(void); -void __mfa(void); -void __synci(void); -void __itcd(__s64 pa); -void __itci(__s64 pa); -void __itrd(__s64 whichTransReg, __s64 pa); -void __itri(__s64 whichTransReg, __s64 pa); -void __ptce(__s64 va); -void __ptcl(__s64 va, __s64 pagesz); -void __ptcg(__s64 va, __s64 pagesz); -void __ptcga(__s64 va, __s64 pagesz); -void __ptri(__s64 va, __s64 pagesz); -void __ptrd(__s64 va, __s64 pagesz); -void __invala (void); -void __invala_gr(const int whichGeneralReg /* 0-127 */ ); -void __invala_fr(const int whichFloatReg /* 0-127 */ ); -void __nop(const int); -void __fc(__u64 *addr); -void __sum(int mask); -void __rum(int mask); -void __ssm(int mask); -void __rsm(int mask); -__u64 __thash(__s64); -__u64 __ttag(__s64); -__s64 __tpa(__s64); - -/* Intrinsics for implementing get/put_user macros */ -void __st_user(const char *tableName, __u64 addr, char size, char relocType, __u64 val); -void __ld_user(const char *tableName, __u64 addr, char size, char relocType); - -/* This intrinsic does not generate code, it creates a barrier across which - * the compiler will not schedule data access instructions. - */ -void __memory_barrier(void); - -void __isrlz(void); -void __dsrlz(void); - -__u64 _m64_mux1(__u64 a, const int n); -__u64 __thash(__u64); - -/* Lock and Atomic Operation Related Intrinsics */ -__u64 _InterlockedExchange8(volatile __u8 *trgt, __u8 value); -__u64 _InterlockedExchange16(volatile __u16 *trgt, __u16 value); -__s64 _InterlockedExchange(volatile __u32 *trgt, __u32 value); -__s64 _InterlockedExchange64(volatile __u64 *trgt, __u64 value); - -__u64 _InterlockedCompareExchange8_rel(volatile __u8 *dest, __u64 xchg, __u64 comp); -__u64 _InterlockedCompareExchange8_acq(volatile __u8 *dest, __u64 xchg, __u64 comp); -__u64 _InterlockedCompareExchange16_rel(volatile __u16 *dest, __u64 xchg, __u64 comp); -__u64 _InterlockedCompareExchange16_acq(volatile __u16 *dest, __u64 xchg, __u64 comp); -__u64 _InterlockedCompareExchange_rel(volatile __u32 *dest, __u64 xchg, __u64 comp); -__u64 _InterlockedCompareExchange_acq(volatile __u32 *dest, __u64 xchg, __u64 comp); -__u64 _InterlockedCompareExchange64_rel(volatile __u64 *dest, __u64 xchg, __u64 comp); -__u64 _InterlockedCompareExchange64_acq(volatile __u64 *dest, __u64 xchg, __u64 comp); - -__s64 _m64_dep_mi(const int v, __s64 s, const int p, const int len); -__s64 _m64_shrp(__s64 a, __s64 b, const int count); -__s64 _m64_popcnt(__s64 a); +#include #define ia64_barrier() __memory_barrier() @@ -131,7 +28,7 @@ __s64 _m64_popcnt(__s64 a); #define ia64_mux1_alt 10 #define ia64_mux1_rev 11 -#define ia64_mux1 _m64_mux1 +#define ia64_mux1(x,v) _m_to_int64(_m64_mux1(_m_from_int64(x), (v))) #define ia64_popcnt _m64_popcnt #define ia64_getf_exp __getf_exp #define ia64_shrp _m64_shrp -- cgit v1.2.3 From 9df79decc395b2f9484ff93a1383ba705ff34b10 Mon Sep 17 00:00:00 2001 From: "Chen, Kenneth W" Date: Thu, 26 Jan 2006 17:12:02 -0800 Subject: [IA64] add __builtin_trap definition for icc build Map __builtin_trap function to break 0 instruction. Signed-off-by: HJ Lu Signed-off-by: Ken Chen Signed-off-by: Tony Luck --- include/asm-ia64/intel_intrin.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/asm-ia64/intel_intrin.h b/include/asm-ia64/intel_intrin.h index c7ac04945c12..67a4bafdc306 100644 --- a/include/asm-ia64/intel_intrin.h +++ b/include/asm-ia64/intel_intrin.h @@ -152,4 +152,6 @@ do { \ } \ } while (0) +#define __builtin_trap() __break(0); + #endif /* _ASM_IA64_INTEL_INTRIN_H */ -- cgit v1.2.3 From 412e6a378260608bf28f29d4fa8a9241e0240a2d Mon Sep 17 00:00:00 2001 From: "Chen, Kenneth W" Date: Thu, 26 Jan 2006 17:19:46 -0800 Subject: [IA64] use icc defined constant Use icc defined constant instead of magic number. Signed-off-by: Ken Chen Signed-off-by: Tony Luck --- include/asm-ia64/intel_intrin.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/asm-ia64/intel_intrin.h b/include/asm-ia64/intel_intrin.h index 67a4bafdc306..d069b6acddce 100644 --- a/include/asm-ia64/intel_intrin.h +++ b/include/asm-ia64/intel_intrin.h @@ -22,11 +22,11 @@ #define ia64_hint __hint #define ia64_hint_pause __hint_pause -#define ia64_mux1_brcst 0 -#define ia64_mux1_mix 8 -#define ia64_mux1_shuf 9 -#define ia64_mux1_alt 10 -#define ia64_mux1_rev 11 +#define ia64_mux1_brcst _m64_mux1_brcst +#define ia64_mux1_mix _m64_mux1_mix +#define ia64_mux1_shuf _m64_mux1_shuf +#define ia64_mux1_alt _m64_mux1_alt +#define ia64_mux1_rev _m64_mux1_rev #define ia64_mux1(x,v) _m_to_int64(_m64_mux1(_m_from_int64(x), (v))) #define ia64_popcnt _m64_popcnt @@ -56,7 +56,7 @@ #define ia64_stf8 __stf8 #define ia64_stf_spill __stf_spill -#define ia64_mf __mf +#define ia64_mf __mf #define ia64_mfa __mfa #define ia64_fetchadd4_acq __fetchadd4_acq @@ -132,10 +132,10 @@ /* Values for lfhint in __lfetch and __lfetch_fault */ -#define ia64_lfhint_none 0 -#define ia64_lfhint_nt1 1 -#define ia64_lfhint_nt2 2 -#define ia64_lfhint_nta 3 +#define ia64_lfhint_none __lfhint_none +#define ia64_lfhint_nt1 __lfhint_nt1 +#define ia64_lfhint_nt2 __lfhint_nt2 +#define ia64_lfhint_nta __lfhint_nta #define ia64_lfetch __lfetch #define ia64_lfetch_excl __lfetch_excl -- cgit v1.2.3 From dcc1dd2366a7c355fd8b6543c52685b864a2044f Mon Sep 17 00:00:00 2001 From: Jack Steiner Date: Tue, 7 Feb 2006 09:24:14 -0800 Subject: [IA64-SGI] - Eliminate SN pio_phys_xxx macros. Move to assembly Rewrite the SN pio_phys_xxx macros in assembly language. This avoids issues with the Intel icc compiler. Function call overhead is not an issue - the functions reference PIOs and take 100's nsec to complete. In addition, the functions should likely be in assembly language anyway - they reference memory using physical addressing mode. One function executes with psr.ic disabled. Signed-off-by: Jack Steiner Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/Makefile | 3 +- arch/ia64/sn/kernel/pio_phys.S | 71 ++++++++++++++++++++++++++++++++++++++++++ include/asm-ia64/sn/rw_mmr.h | 56 +++------------------------------ 3 files changed, 78 insertions(+), 52 deletions(-) create mode 100644 arch/ia64/sn/kernel/pio_phys.S (limited to 'include') diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile index 3e9b4eea7418..ab9c48c88012 100644 --- a/arch/ia64/sn/kernel/Makefile +++ b/arch/ia64/sn/kernel/Makefile @@ -10,7 +10,8 @@ CPPFLAGS += -I$(srctree)/arch/ia64/sn/include obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \ - huberror.o io_init.o iomv.o klconflib.o sn2/ + huberror.o io_init.o iomv.o klconflib.o pio_phys.o \ + sn2/ obj-$(CONFIG_IA64_GENERIC) += machvec.o obj-$(CONFIG_SGI_TIOCX) += tiocx.o obj-$(CONFIG_IA64_SGI_SN_XP) += xp.o diff --git a/arch/ia64/sn/kernel/pio_phys.S b/arch/ia64/sn/kernel/pio_phys.S new file mode 100644 index 000000000000..3c7d48d6ecb8 --- /dev/null +++ b/arch/ia64/sn/kernel/pio_phys.S @@ -0,0 +1,71 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved. + * + * This file contains macros used to access MMR registers via + * uncached physical addresses. + * pio_phys_read_mmr - read an MMR + * pio_phys_write_mmr - write an MMR + * pio_atomic_phys_write_mmrs - atomically write 1 or 2 MMRs with psr.ic=0 + * Second MMR will be skipped if address is NULL + * + * Addresses passed to these routines should be uncached physical addresses + * ie., 0x80000.... + */ + + + +#include +#include + +GLOBAL_ENTRY(pio_phys_read_mmr) + .prologue + .regstk 1,0,0,0 + .body + mov r2=psr + rsm psr.i | psr.dt + ;; + srlz.d + ld8.acq r8=[r32] + ;; + mov psr.l=r2;; + srlz.d + br.ret.sptk.many rp +END(pio_phys_read_mmr) + +GLOBAL_ENTRY(pio_phys_write_mmr) + .prologue + .regstk 2,0,0,0 + .body + mov r2=psr + rsm psr.i | psr.dt + ;; + srlz.d + st8.rel [r32]=r33 + ;; + mov psr.l=r2;; + srlz.d + br.ret.sptk.many rp +END(pio_phys_write_mmr) + +GLOBAL_ENTRY(pio_atomic_phys_write_mmrs) + .prologue + .regstk 4,0,0,0 + .body + mov r2=psr + cmp.ne p9,p0=r34,r0; + rsm psr.i | psr.dt | psr.ic + ;; + srlz.d + st8.rel [r32]=r33 +(p9) st8.rel [r34]=r35 + ;; + mov psr.l=r2;; + srlz.d + br.ret.sptk.many rp +END(pio_atomic_phys_write_mmrs) + + diff --git a/include/asm-ia64/sn/rw_mmr.h b/include/asm-ia64/sn/rw_mmr.h index f40fd1a5510d..2d78f4c5a45e 100644 --- a/include/asm-ia64/sn/rw_mmr.h +++ b/include/asm-ia64/sn/rw_mmr.h @@ -3,15 +3,14 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2002-2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 2002-2006 Silicon Graphics, Inc. All Rights Reserved. */ #ifndef _ASM_IA64_SN_RW_MMR_H #define _ASM_IA64_SN_RW_MMR_H /* - * This file contains macros used to access MMR registers via - * uncached physical addresses. + * This file that access MMRs via uncached physical addresses. * pio_phys_read_mmr - read an MMR * pio_phys_write_mmr - write an MMR * pio_atomic_phys_write_mmrs - atomically write 1 or 2 MMRs with psr.ic=0 @@ -22,53 +21,8 @@ */ -extern inline long -pio_phys_read_mmr(volatile long *mmr) -{ - long val; - asm volatile - ("mov r2=psr;;" - "rsm psr.i | psr.dt;;" - "srlz.i;;" - "ld8.acq %0=[%1];;" - "mov psr.l=r2;;" - "srlz.i;;" - : "=r"(val) - : "r"(mmr) - : "r2"); - return val; -} - - - -extern inline void -pio_phys_write_mmr(volatile long *mmr, long val) -{ - asm volatile - ("mov r2=psr;;" - "rsm psr.i | psr.dt;;" - "srlz.i;;" - "st8.rel [%0]=%1;;" - "mov psr.l=r2;;" - "srlz.i;;" - :: "r"(mmr), "r"(val) - : "r2", "memory"); -} - -extern inline void -pio_atomic_phys_write_mmrs(volatile long *mmr1, long val1, volatile long *mmr2, long val2) -{ - asm volatile - ("mov r2=psr;;" - "rsm psr.i | psr.dt | psr.ic;;" - "cmp.ne p9,p0=%2,r0;" - "srlz.i;;" - "st8.rel [%0]=%1;" - "(p9) st8.rel [%2]=%3;;" - "mov psr.l=r2;;" - "srlz.i;;" - :: "r"(mmr1), "r"(val1), "r"(mmr2), "r"(val2) - : "p9", "r2", "memory"); -} +extern long pio_phys_read_mmr(volatile long *mmr); +extern void pio_phys_write_mmr(volatile long *mmr, long val); +extern void pio_atomic_phys_write_mmrs(volatile long *mmr1, long val1, volatile long *mmr2, long val2); #endif /* _ASM_IA64_SN_RW_MMR_H */ -- cgit v1.2.3 From dde44589bf9fac0168c6ce6d097c99c33b18074f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 2 Feb 2006 00:56:10 +0900 Subject: [PATCH] libata: implement ATA_FLAG_IN_EH port flag ATA_FLAG_IN_EH flag is set on entry to EH and cleared on completion. This patch just sets and clears the flag. Following patches will build normal qc execution / EH synchronization aroung this flag. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 9 +++++++++ include/linux/libata.h | 2 ++ 2 files changed, 11 insertions(+) (limited to 'include') diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 2d328b3af067..3a4f40b251fb 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -735,6 +735,11 @@ int ata_scsi_error(struct Scsi_Host *host) DPRINTK("ENTER\n"); + spin_lock_irqsave(&ap->host_set->lock, flags); + assert(!(ap->flags & ATA_FLAG_IN_EH)); + ap->flags |= ATA_FLAG_IN_EH; + spin_unlock_irqrestore(&ap->host_set->lock, flags); + ap = (struct ata_port *) &host->hostdata[0]; ap->ops->eng_timeout(ap); @@ -742,6 +747,10 @@ int ata_scsi_error(struct Scsi_Host *host) scsi_eh_flush_done_q(&ap->eh_done_q); + spin_lock_irqsave(&ap->host_set->lock, flags); + ap->flags &= ~ATA_FLAG_IN_EH; + spin_unlock_irqrestore(&ap->host_set->lock, flags); + DPRINTK("EXIT\n"); return 0; } diff --git a/include/linux/libata.h b/include/linux/libata.h index 474cdfa35d1e..55176df403a5 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -162,6 +162,8 @@ enum { ATA_FLAG_PIO_LBA48 = (1 << 13), /* Host DMA engine is LBA28 only */ ATA_FLAG_IRQ_MASK = (1 << 14), /* Mask IRQ in PIO xfers */ + ATA_FLAG_IN_EH = (1 << 15), /* EH in progress */ + ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ ATA_QCFLAG_SINGLE = (1 << 4), /* no s/g, just a single buffer */ -- cgit v1.2.3 From c18d06f89fd09ee0059c4899e615c471d59af66a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 2 Feb 2006 00:56:10 +0900 Subject: [PATCH] libata: EH / pio tasks synchronization This patch makes sure that pio tasks are flushed before proceeding with EH. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 56 +++++++++++++++++++++++++++++++++++++++++++--- include/linux/libata.h | 3 ++- 2 files changed, 55 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 249e67fab81f..9a785cf0c5b1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1074,19 +1074,66 @@ static unsigned int ata_pio_modes(const struct ata_device *adev) static inline void ata_queue_packet_task(struct ata_port *ap) { - queue_work(ata_wq, &ap->packet_task); + if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK)) + queue_work(ata_wq, &ap->packet_task); } static inline void ata_queue_pio_task(struct ata_port *ap) { - queue_work(ata_wq, &ap->pio_task); + if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK)) + queue_work(ata_wq, &ap->pio_task); } static inline void ata_queue_delayed_pio_task(struct ata_port *ap, unsigned long delay) { - queue_delayed_work(ata_wq, &ap->pio_task, delay); + if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK)) + queue_delayed_work(ata_wq, &ap->pio_task, delay); +} + +/** + * ata_flush_pio_tasks - Flush pio_task and packet_task + * @ap: the target ata_port + * + * After this function completes, pio_task and packet_task are + * guranteed not to be running or scheduled. + * + * LOCKING: + * Kernel thread context (may sleep) + */ + +static void ata_flush_pio_tasks(struct ata_port *ap) +{ + int tmp = 0; + unsigned long flags; + + DPRINTK("ENTER\n"); + + spin_lock_irqsave(&ap->host_set->lock, flags); + ap->flags |= ATA_FLAG_FLUSH_PIO_TASK; + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + DPRINTK("flush #1\n"); + flush_workqueue(ata_wq); + + /* + * At this point, if a task is running, it's guaranteed to see + * the FLUSH flag; thus, it will never queue pio tasks again. + * Cancel and flush. + */ + tmp |= cancel_delayed_work(&ap->pio_task); + tmp |= cancel_delayed_work(&ap->packet_task); + if (!tmp) { + DPRINTK("flush #2\n"); + flush_workqueue(ata_wq); + } + + spin_lock_irqsave(&ap->host_set->lock, flags); + ap->flags &= ~ATA_FLAG_FLUSH_PIO_TASK; + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + DPRINTK("EXIT\n"); } void ata_qc_complete_internal(struct ata_queued_cmd *qc) @@ -3767,6 +3814,9 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) DPRINTK("ENTER\n"); + ata_flush_pio_tasks(ap); + ap->hsm_task_state = HSM_ST_IDLE; + spin_lock_irqsave(&host_set->lock, flags); switch (qc->tf.protocol) { diff --git a/include/linux/libata.h b/include/linux/libata.h index 55176df403a5..f4cd1eb734a0 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -162,7 +162,8 @@ enum { ATA_FLAG_PIO_LBA48 = (1 << 13), /* Host DMA engine is LBA28 only */ ATA_FLAG_IRQ_MASK = (1 << 14), /* Mask IRQ in PIO xfers */ - ATA_FLAG_IN_EH = (1 << 15), /* EH in progress */ + ATA_FLAG_FLUSH_PIO_TASK = (1 << 15), /* Flush PIO task */ + ATA_FLAG_IN_EH = (1 << 16), /* EH in progress */ ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ -- cgit v1.2.3 From 7944ea9522ce0ea32d57894b3dc2540b0bdca66e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 2 Feb 2006 18:20:00 +0900 Subject: [PATCH] libata: add probeinit component operation to ata_drive_probe_reset() This patch adds probeinit component operation to ata_drive_probe_reset(). If present, this new operation is called before performing any reset. The operations's roll is to prepare @ap for following probe-reset operations. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 9 +++++++-- include/linux/libata.h | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 99f4bf6022ee..c36c5a9a4617 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2485,7 +2485,8 @@ int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes) if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) hardreset = sata_std_hardreset; - return ata_drive_probe_reset(ap, ata_std_softreset, hardreset, + return ata_drive_probe_reset(ap, NULL, + ata_std_softreset, hardreset, ata_std_postreset, classes); } @@ -2524,6 +2525,7 @@ static int do_probe_reset(struct ata_port *ap, ata_reset_fn_t reset, /** * ata_drive_probe_reset - Perform probe reset with given methods * @ap: port to reset + * @probeinit: probeinit method (can be NULL) * @softreset: softreset method (can be NULL) * @hardreset: hardreset method (can be NULL) * @postreset: postreset method (can be NULL) @@ -2552,12 +2554,15 @@ static int do_probe_reset(struct ata_port *ap, ata_reset_fn_t reset, * if classification fails, and any error code from reset * methods. */ -int ata_drive_probe_reset(struct ata_port *ap, +int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset, unsigned int *classes) { int rc = -EINVAL; + if (probeinit) + probeinit(ap); + if (softreset) { rc = do_probe_reset(ap, softreset, postreset, classes); if (rc == 0) diff --git a/include/linux/libata.h b/include/linux/libata.h index f4cd1eb734a0..e8f29cefc351 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -244,6 +244,7 @@ struct ata_queued_cmd; /* typedefs */ typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc); +typedef void (*ata_probeinit_fn_t)(struct ata_port *); typedef int (*ata_reset_fn_t)(struct ata_port *, int, unsigned int *); typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *); @@ -484,6 +485,7 @@ extern void __sata_phy_reset(struct ata_port *ap); extern void sata_phy_reset(struct ata_port *ap); extern void ata_bus_reset(struct ata_port *ap); extern int ata_drive_probe_reset(struct ata_port *ap, + ata_probeinit_fn_t probeinit, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset, unsigned int *classes); extern int ata_std_softreset(struct ata_port *ap, int verbose, -- cgit v1.2.3 From 8a19ac89edbe9b702c10fd2039b8cb2db4644a5f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 2 Feb 2006 18:20:00 +0900 Subject: [PATCH] libata: implement ata_std_probeinit() This patch implements the off-the-shelf probeinit component operation. Currently, all it does is waking up the PHY if it's a SATA port. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 16 +++++++++++++++- include/linux/libata.h | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index c36c5a9a4617..14cdbb336dd5 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2295,6 +2295,19 @@ static int sata_phy_resume(struct ata_port *ap) return -1; } +/** + * ata_std_probeinit - initialize probing + * @ap: port to be probed + * + * @ap is about to be probed. Initialize it. This function is + * to be used as standard callback for ata_drive_probe_reset(). + */ +extern void ata_std_probeinit(struct ata_port *ap) +{ + if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) + sata_phy_resume(ap); +} + /** * ata_std_softreset - reset host port via ATA SRST * @ap: port to reset @@ -2485,7 +2498,7 @@ int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes) if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) hardreset = sata_std_hardreset; - return ata_drive_probe_reset(ap, NULL, + return ata_drive_probe_reset(ap, ata_std_probeinit, ata_std_softreset, hardreset, ata_std_postreset, classes); } @@ -5535,6 +5548,7 @@ EXPORT_SYMBOL_GPL(ata_port_probe); EXPORT_SYMBOL_GPL(sata_phy_reset); EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); +EXPORT_SYMBOL_GPL(ata_std_probeinit); EXPORT_SYMBOL_GPL(ata_std_softreset); EXPORT_SYMBOL_GPL(sata_std_hardreset); EXPORT_SYMBOL_GPL(ata_std_postreset); diff --git a/include/linux/libata.h b/include/linux/libata.h index e8f29cefc351..68b3fe6f9a4d 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -488,6 +488,7 @@ extern int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset, unsigned int *classes); +extern void ata_std_probeinit(struct ata_port *ap); extern int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes); extern int sata_std_hardreset(struct ata_port *ap, int verbose, -- cgit v1.2.3 From 1965746bce49ddf001af52c7985e16343c768021 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 10 Feb 2006 15:47:36 +1100 Subject: [PATCH] powerpc: Move pSeries firmware feature setup into platforms/pseries Currently we have some stuff in firmware.h and kernel/firmware.c that is #ifdef CONFIG_PPC_PSERIES. Move it all into platforms/pseries. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/firmware.c | 25 -------- arch/powerpc/platforms/pseries/Makefile | 3 +- arch/powerpc/platforms/pseries/firmware.c | 103 ++++++++++++++++++++++++++++++ arch/powerpc/platforms/pseries/firmware.h | 17 +++++ arch/powerpc/platforms/pseries/setup.c | 45 +------------ include/asm-powerpc/firmware.h | 9 --- 6 files changed, 123 insertions(+), 79 deletions(-) create mode 100644 arch/powerpc/platforms/pseries/firmware.c create mode 100644 arch/powerpc/platforms/pseries/firmware.h (limited to 'include') diff --git a/arch/powerpc/kernel/firmware.c b/arch/powerpc/kernel/firmware.c index 65eae752a527..4d37a3cb80f6 100644 --- a/arch/powerpc/kernel/firmware.c +++ b/arch/powerpc/kernel/firmware.c @@ -18,28 +18,3 @@ #include unsigned long ppc64_firmware_features; - -#ifdef CONFIG_PPC_PSERIES -firmware_feature_t firmware_features_table[FIRMWARE_MAX_FEATURES] = { - {FW_FEATURE_PFT, "hcall-pft"}, - {FW_FEATURE_TCE, "hcall-tce"}, - {FW_FEATURE_SPRG0, "hcall-sprg0"}, - {FW_FEATURE_DABR, "hcall-dabr"}, - {FW_FEATURE_COPY, "hcall-copy"}, - {FW_FEATURE_ASR, "hcall-asr"}, - {FW_FEATURE_DEBUG, "hcall-debug"}, - {FW_FEATURE_PERF, "hcall-perf"}, - {FW_FEATURE_DUMP, "hcall-dump"}, - {FW_FEATURE_INTERRUPT, "hcall-interrupt"}, - {FW_FEATURE_MIGRATE, "hcall-migrate"}, - {FW_FEATURE_PERFMON, "hcall-perfmon"}, - {FW_FEATURE_CRQ, "hcall-crq"}, - {FW_FEATURE_VIO, "hcall-vio"}, - {FW_FEATURE_RDMA, "hcall-rdma"}, - {FW_FEATURE_LLAN, "hcall-lLAN"}, - {FW_FEATURE_BULK, "hcall-bulk"}, - {FW_FEATURE_XDABR, "hcall-xdabr"}, - {FW_FEATURE_MULTITCE, "hcall-multi-tce"}, - {FW_FEATURE_SPLPAR, "hcall-splpar"}, -}; -#endif diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 61616d144072..930898635c9f 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -1,5 +1,6 @@ obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ - setup.o iommu.o ras.o rtasd.o pci_dlpar.o + setup.o iommu.o ras.o rtasd.o pci_dlpar.o \ + firmware.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_XICS) += xics.o diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c new file mode 100644 index 000000000000..989f4bc136cb --- /dev/null +++ b/arch/powerpc/platforms/pseries/firmware.c @@ -0,0 +1,103 @@ +/* + * pSeries firmware setup code. + * + * Portions from arch/powerpc/platforms/pseries/setup.c: + * Copyright (C) 1995 Linus Torvalds + * Adapted from 'alpha' version by Gary Thomas + * Modified by Cort Dougan (cort@cs.nmt.edu) + * Modified by PPC64 Team, IBM Corp + * + * Portions from arch/powerpc/kernel/firmware.c + * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org) + * Modifications for ppc64: + * Copyright (C) 2003 Dave Engebretsen + * Copyright (C) 2005 Stephen Rothwell, IBM Corporation + * + * Copyright 2006 IBM Corporation. + * + * 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. + */ + +#undef DEBUG + +#include +#include + +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif + +typedef struct { + unsigned long val; + char * name; +} firmware_feature_t; + +static __initdata firmware_feature_t +firmware_features_table[FIRMWARE_MAX_FEATURES] = { + {FW_FEATURE_PFT, "hcall-pft"}, + {FW_FEATURE_TCE, "hcall-tce"}, + {FW_FEATURE_SPRG0, "hcall-sprg0"}, + {FW_FEATURE_DABR, "hcall-dabr"}, + {FW_FEATURE_COPY, "hcall-copy"}, + {FW_FEATURE_ASR, "hcall-asr"}, + {FW_FEATURE_DEBUG, "hcall-debug"}, + {FW_FEATURE_PERF, "hcall-perf"}, + {FW_FEATURE_DUMP, "hcall-dump"}, + {FW_FEATURE_INTERRUPT, "hcall-interrupt"}, + {FW_FEATURE_MIGRATE, "hcall-migrate"}, + {FW_FEATURE_PERFMON, "hcall-perfmon"}, + {FW_FEATURE_CRQ, "hcall-crq"}, + {FW_FEATURE_VIO, "hcall-vio"}, + {FW_FEATURE_RDMA, "hcall-rdma"}, + {FW_FEATURE_LLAN, "hcall-lLAN"}, + {FW_FEATURE_BULK, "hcall-bulk"}, + {FW_FEATURE_XDABR, "hcall-xdabr"}, + {FW_FEATURE_MULTITCE, "hcall-multi-tce"}, + {FW_FEATURE_SPLPAR, "hcall-splpar"}, +}; + +/* Build up the firmware features bitmask using the contents of + * device-tree/ibm,hypertas-functions. Ultimately this functionality may + * be moved into prom.c prom_init(). + */ +void __init fw_feature_init(void) +{ + struct device_node *dn; + char *hypertas, *s; + int len, i; + + DBG(" -> fw_feature_init()\n"); + + dn = of_find_node_by_path("/rtas"); + if (dn == NULL) { + printk(KERN_ERR "WARNING! Cannot find RTAS in device-tree!\n"); + goto out; + } + + hypertas = get_property(dn, "ibm,hypertas-functions", &len); + if (hypertas == NULL) + goto out; + + for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) { + for (i = 0; i < FIRMWARE_MAX_FEATURES; i++) { + /* check value against table of strings */ + if (!firmware_features_table[i].name || + strcmp(firmware_features_table[i].name, s)) + continue; + + /* we have a match */ + ppc64_firmware_features |= + firmware_features_table[i].val; + break; + } + } + +out: + of_node_put(dn); + DBG(" <- fw_feature_init()\n"); +} diff --git a/arch/powerpc/platforms/pseries/firmware.h b/arch/powerpc/platforms/pseries/firmware.h new file mode 100644 index 000000000000..714f56f55362 --- /dev/null +++ b/arch/powerpc/platforms/pseries/firmware.h @@ -0,0 +1,17 @@ +/* + * Copyright 2006 IBM Corporation. + * + * 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. + */ + +#ifndef _PSERIES_FIRMWARE_H +#define _PSERIES_FIRMWARE_H + +#include + +extern void __init fw_feature_init(void); + +#endif /* _PSERIES_FIRMWARE_H */ diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 984241bb776c..b5996a7060f4 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -60,7 +60,6 @@ #include #include #include "xics.h" -#include #include #include #include @@ -70,6 +69,7 @@ #include "plpar_wrappers.h" #include "ras.h" +#include "firmware.h" #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -262,49 +262,6 @@ static int __init pSeries_init_panel(void) } arch_initcall(pSeries_init_panel); - -/* Build up the firmware features bitmask using the contents of - * device-tree/ibm,hypertas-functions. Ultimately this functionality may - * be moved into prom.c prom_init(). - */ -static void __init fw_feature_init(void) -{ - struct device_node *dn; - char *hypertas, *s; - int len, i; - - DBG(" -> fw_feature_init()\n"); - - dn = of_find_node_by_path("/rtas"); - if (dn == NULL) { - printk(KERN_ERR "WARNING! Cannot find RTAS in device-tree!\n"); - goto out; - } - - hypertas = get_property(dn, "ibm,hypertas-functions", &len); - if (hypertas == NULL) - goto out; - - for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) { - for (i = 0; i < FIRMWARE_MAX_FEATURES; i++) { - /* check value against table of strings */ - if (!firmware_features_table[i].name || - strcmp(firmware_features_table[i].name, s)) - continue; - - /* we have a match */ - ppc64_firmware_features |= - firmware_features_table[i].val; - break; - } - } - -out: - of_node_put(dn); - DBG(" <- fw_feature_init()\n"); -} - - static void __init pSeries_discover_pic(void) { struct device_node *np; diff --git a/include/asm-powerpc/firmware.h b/include/asm-powerpc/firmware.h index f804b34cf06a..b7791a1b05db 100644 --- a/include/asm-powerpc/firmware.h +++ b/include/asm-powerpc/firmware.h @@ -89,15 +89,6 @@ static inline unsigned long firmware_has_feature(unsigned long feature) (FW_FEATURE_POSSIBLE & ppc64_firmware_features & feature); } -#ifdef CONFIG_PPC_PSERIES -typedef struct { - unsigned long val; - char * name; -} firmware_feature_t; - -extern firmware_feature_t firmware_features_table[]; -#endif - extern void system_reset_fwnmi(void); extern void machine_check_fwnmi(void); -- cgit v1.2.3 From 75288c78c69020a574d93770c3a941b785f3d93d Mon Sep 17 00:00:00 2001 From: Vitaly Bordug Date: Fri, 20 Jan 2006 22:22:34 +0300 Subject: [PATCH] ppc32: Make platform devices being able to assign functions Implemented by modification of the .name field of the platform device, when PDs with the same names are to be used within different drivers, as -> : Corresponding drivers should change the .name in struct device_driver to reflect upper of course. Added ppc_sys_device_disable/enable function set, making it easier to disable all the inexistent/not utilized platform device way pdevs. By the check of the "disabled" bit in the config field of ppc_sys_specs, disabled platform devices will be either added/removed from the bus, or simply not registered on it, depending on the time when disable/enable call asserted. The default behaviour when nothing is disabled/enabled will be "all devices are enabled", which is the same as before. Also helper platform_notify_map function added, making assignment of board-specific platform_info more consistent and generic. Signed-off-by: Vitaly Bordug Signed-off-by: Marcelo Tosatti Signed-off-by: Paul Mackerras --- arch/ppc/syslib/ppc_sys.c | 177 +++++++++++++++++++++++++++++++++++++++++++++- include/asm-ppc/mpc10x.h | 1 + include/asm-ppc/mpc52xx.h | 1 + include/asm-ppc/mpc8260.h | 1 + include/asm-ppc/mpc83xx.h | 1 + include/asm-ppc/mpc85xx.h | 1 + include/asm-ppc/mpc8xx.h | 1 + include/asm-ppc/ppc_sys.h | 32 +++++++++ 8 files changed, 212 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c index c0b93c4191ee..879783a41cfd 100644 --- a/arch/ppc/syslib/ppc_sys.c +++ b/arch/ppc/syslib/ppc_sys.c @@ -15,11 +15,22 @@ */ #include +#include #include int (*ppc_sys_device_fixup) (struct platform_device * pdev); static int ppc_sys_inited; +static int ppc_sys_func_inited; + +static const char *ppc_sys_func_names[] = { + [PPC_SYS_FUNC_DUMMY] = "dummy", + [PPC_SYS_FUNC_ETH] = "eth", + [PPC_SYS_FUNC_UART] = "uart", + [PPC_SYS_FUNC_HLDC] = "hldc", + [PPC_SYS_FUNC_USB] = "usb", + [PPC_SYS_FUNC_IRDA] = "irda", +}; void __init identify_ppc_sys_by_id(u32 id) { @@ -38,13 +49,13 @@ void __init identify_ppc_sys_by_id(u32 id) void __init identify_ppc_sys_by_name(char *name) { unsigned int i = 0; - while (ppc_sys_specs[i].ppc_sys_name[0]) - { + while (ppc_sys_specs[i].ppc_sys_name[0]) { if (!strcmp(ppc_sys_specs[i].ppc_sys_name, name)) break; i++; } cur_ppc_sys_spec = &ppc_sys_specs[i]; + return; } @@ -128,6 +139,165 @@ void ppc_sys_device_remove(enum ppc_sys_devices dev) } } +/* Platform-notify mapping + * Helper function for BSP code to assign board-specific platfom-divice bits + */ + +void platform_notify_map(const struct platform_notify_dev_map *map, + struct device *dev) +{ + struct platform_device *pdev; + int len, idx; + const char *s; + + /* do nothing if no device or no bus_id */ + if (!dev || !dev->bus_id) + return; + + /* call per device map */ + while (map->bus_id != NULL) { + idx = -1; + s = strrchr(dev->bus_id, '.'); + if (s != NULL) + idx = (int)simple_strtol(s + 1, NULL, 10); + else + s = dev->bus_id; + + len = s - dev->bus_id; + + if (!strncmp(dev->bus_id, map->bus_id, len)) { + pdev = container_of(dev, struct platform_device, dev); + map->rtn(pdev, idx); + } + map++; + } +} + +/* + Function assignment stuff. + Intended to work as follows: + the device name defined in foo_devices.c will be concatenated with :"func", + where func is string map of respective function from platfom_device_func enum + + The PPC_SYS_FUNC_DUMMY function is intended to remove all assignments, making the device to appear + in platform bus with unmodified name. + */ + +/* + Here we'll replace .name pointers with fixed-lenght strings + Hereby, this should be called *before* any func stuff triggeded. + */ +void ppc_sys_device_initfunc(void) +{ + int i; + const char *name; + static char new_names[NUM_PPC_SYS_DEVS][BUS_ID_SIZE]; + enum ppc_sys_devices cur_dev; + + /* If inited yet, do nothing */ + if (ppc_sys_func_inited) + return; + + for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) { + if ((cur_dev = cur_ppc_sys_spec->device_list[i]) < 0) + continue; + + if (ppc_sys_platform_devices[cur_dev].name) { + /*backup name */ + name = ppc_sys_platform_devices[cur_dev].name; + strlcpy(new_names[i], name, BUS_ID_SIZE); + ppc_sys_platform_devices[cur_dev].name = new_names[i]; + } + } + + ppc_sys_func_inited = 1; +} + +/*The "engine" of the func stuff. Here we either concat specified function string description + to the name, or remove it if PPC_SYS_FUNC_DUMMY parameter is passed here*/ +void ppc_sys_device_setfunc(enum ppc_sys_devices dev, + enum platform_device_func func) +{ + char *s; + char *name = (char *)ppc_sys_platform_devices[dev].name; + char tmp[BUS_ID_SIZE]; + + if (!ppc_sys_func_inited) { + printk(KERN_ERR "Unable to alter function - not inited!\n"); + return; + } + + if (ppc_sys_inited) { + platform_device_unregister(&ppc_sys_platform_devices[dev]); + } + + if ((s = (char *)strchr(name, ':')) != NULL) { /* reassign */ + /* Either change the name after ':' or remove func modifications */ + if (func != PPC_SYS_FUNC_DUMMY) + strlcpy(s + 1, ppc_sys_func_names[func], BUS_ID_SIZE); + else + *s = 0; + } else if (func != PPC_SYS_FUNC_DUMMY) { + /* do assignment if it is not just "clear" request */ + sprintf(tmp, "%s:%s", name, ppc_sys_func_names[func]); + strlcpy(name, tmp, BUS_ID_SIZE); + } + + if (ppc_sys_inited) { + platform_device_register(&ppc_sys_platform_devices[dev]); + } +} + +void ppc_sys_device_disable(enum ppc_sys_devices dev) +{ + BUG_ON(cur_ppc_sys_spec == NULL); + + /*Check if it is enabled*/ + if(!(cur_ppc_sys_spec->config[dev] & PPC_SYS_CONFIG_DISABLED)) { + if (ppc_sys_inited) { + platform_device_unregister(&ppc_sys_platform_devices[dev]); + } + cur_ppc_sys_spec->config[dev] |= PPC_SYS_CONFIG_DISABLED; + } +} + +void ppc_sys_device_enable(enum ppc_sys_devices dev) +{ + BUG_ON(cur_ppc_sys_spec == NULL); + + /*Check if it is disabled*/ + if(cur_ppc_sys_spec->config[dev] & PPC_SYS_CONFIG_DISABLED) { + if (ppc_sys_inited) { + platform_device_register(&ppc_sys_platform_devices[dev]); + } + cur_ppc_sys_spec->config[dev] &= ~PPC_SYS_CONFIG_DISABLED; + } + +} + +void ppc_sys_device_enable_all(void) +{ + enum ppc_sys_devices cur_dev; + int i; + + for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) { + cur_dev = cur_ppc_sys_spec->device_list[i]; + ppc_sys_device_enable(cur_dev); + } +} + +void ppc_sys_device_disable_all(void) +{ + enum ppc_sys_devices cur_dev; + int i; + + for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) { + cur_dev = cur_ppc_sys_spec->device_list[i]; + ppc_sys_device_disable(cur_dev); + } +} + + static int __init ppc_sys_init(void) { unsigned int i, dev_id, ret = 0; @@ -136,7 +306,8 @@ static int __init ppc_sys_init(void) for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) { dev_id = cur_ppc_sys_spec->device_list[i]; - if (dev_id != -1) { + if ((dev_id != -1) && + !(cur_ppc_sys_spec->config[dev_id] & PPC_SYS_CONFIG_DISABLED)) { if (ppc_sys_device_fixup != NULL) ppc_sys_device_fixup(&ppc_sys_platform_devices [dev_id]); diff --git a/include/asm-ppc/mpc10x.h b/include/asm-ppc/mpc10x.h index 77b1e092c206..976ad3d94f27 100644 --- a/include/asm-ppc/mpc10x.h +++ b/include/asm-ppc/mpc10x.h @@ -165,6 +165,7 @@ enum ppc_sys_devices { MPC10X_DMA1, MPC10X_UART0, MPC10X_UART1, + NUM_PPC_SYS_DEVS, }; int mpc10x_bridge_init(struct pci_controller *hose, diff --git a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h index a055e0756b9d..6167f74635f7 100644 --- a/include/asm-ppc/mpc52xx.h +++ b/include/asm-ppc/mpc52xx.h @@ -60,6 +60,7 @@ enum ppc_sys_devices { MPC52xx_ATA, MPC52xx_I2C1, MPC52xx_I2C2, + NUM_PPC_SYS_DEVS, }; diff --git a/include/asm-ppc/mpc8260.h b/include/asm-ppc/mpc8260.h index 321452695039..6ba69a86b9dd 100644 --- a/include/asm-ppc/mpc8260.h +++ b/include/asm-ppc/mpc8260.h @@ -83,6 +83,7 @@ enum ppc_sys_devices { MPC82xx_CPM_SMC2, MPC82xx_CPM_USB, MPC82xx_SEC1, + NUM_PPC_SYS_DEVS, }; #ifndef __ASSEMBLY__ diff --git a/include/asm-ppc/mpc83xx.h b/include/asm-ppc/mpc83xx.h index 7cdf60fa69b6..3c23fc43bfbc 100644 --- a/include/asm-ppc/mpc83xx.h +++ b/include/asm-ppc/mpc83xx.h @@ -108,6 +108,7 @@ enum ppc_sys_devices { MPC83xx_USB2_DR, MPC83xx_USB2_MPH, MPC83xx_MDIO, + NUM_PPC_SYS_DEVS, }; #endif /* CONFIG_83xx */ diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h index c8a96aa44fb7..f47002a60edf 100644 --- a/include/asm-ppc/mpc85xx.h +++ b/include/asm-ppc/mpc85xx.h @@ -139,6 +139,7 @@ enum ppc_sys_devices { MPC85xx_eTSEC4, MPC85xx_IIC2, MPC85xx_MDIO, + NUM_PPC_SYS_DEVS, }; /* Internal interrupts are all Level Sensitive, and Positive Polarity */ diff --git a/include/asm-ppc/mpc8xx.h b/include/asm-ppc/mpc8xx.h index 73ec9a6db0b1..3515a7fa6c89 100644 --- a/include/asm-ppc/mpc8xx.h +++ b/include/asm-ppc/mpc8xx.h @@ -111,6 +111,7 @@ enum ppc_sys_devices { MPC8xx_CPM_SMC1, MPC8xx_CPM_SMC2, MPC8xx_CPM_USB, + NUM_PPC_SYS_DEVS, }; #define PPC_PIN_SIZE (24 * 1024 * 1024) /* 24Mbytes of data pinned */ diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h index bdc4dde35edd..4b94f7059ebe 100644 --- a/include/asm-ppc/ppc_sys.h +++ b/include/asm-ppc/ppc_sys.h @@ -46,9 +46,26 @@ struct ppc_sys_spec { u32 value; u32 num_devices; char *ppc_sys_name; + u8 config[NUM_PPC_SYS_DEVS]; enum ppc_sys_devices *device_list; }; +struct platform_notify_dev_map { + const char *bus_id; + void (*rtn)(struct platform_device * pdev, int idx); +}; + +enum platform_device_func { + PPC_SYS_FUNC_DUMMY = 0, + PPC_SYS_FUNC_ETH = 1, + PPC_SYS_FUNC_UART = 2, + PPC_SYS_FUNC_HLDC = 3, + PPC_SYS_FUNC_USB = 4, + PPC_SYS_FUNC_IRDA = 5, +}; + +#define PPC_SYS_CONFIG_DISABLED 1 + /* describes all specific chips and which devices they have on them */ extern struct ppc_sys_spec ppc_sys_specs[]; extern struct ppc_sys_spec *cur_ppc_sys_spec; @@ -74,5 +91,20 @@ extern void *ppc_sys_get_pdata(enum ppc_sys_devices dev) __init; /* remove a device from the system */ extern void ppc_sys_device_remove(enum ppc_sys_devices dev); +/* Function assignment stuff */ +void ppc_sys_device_initfunc(void); +void ppc_sys_device_setfunc(enum ppc_sys_devices dev, + enum platform_device_func func); +void ppc_sys_device_set_func_all(enum platform_device_func func); + +void platform_notify_map(const struct platform_notify_dev_map *map, + struct device *dev); + +/* Enable / disable stuff */ +void ppc_sys_device_disable(enum ppc_sys_devices dev); +void ppc_sys_device_enable(enum ppc_sys_devices dev); +void ppc_sys_device_enable_all(void); +void ppc_sys_device_disable_all(void); + #endif /* __ASM_PPC_SYS_H */ #endif /* __KERNEL__ */ -- cgit v1.2.3 From 2ef9481e666b4654159ac9f847e6963809e3c470 Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Mon, 23 Jan 2006 10:58:20 -0600 Subject: [PATCH] powerpc: trivial: modify comments to refer to new location of files This patch removes all self references and fixes references to files in the now defunct arch/ppc64 tree. I think this accomplises everything wanted, though there might be a few references I missed. Signed-off-by: Jon Mason Signed-off-by: Paul Mackerras --- Documentation/powerpc/eeh-pci-error-recovery.txt | 15 ++++++++------- arch/powerpc/boot/install.sh | 2 -- arch/powerpc/kernel/entry_64.S | 4 +--- arch/powerpc/kernel/head_44x.S | 2 -- arch/powerpc/kernel/head_64.S | 2 -- arch/powerpc/kernel/head_8xx.S | 2 -- arch/powerpc/kernel/head_fsl_booke.S | 2 -- arch/powerpc/kernel/iomap.c | 2 -- arch/powerpc/kernel/iommu.c | 1 - arch/powerpc/kernel/irq.c | 2 -- arch/powerpc/kernel/kprobes.c | 1 - arch/powerpc/kernel/pci_iommu.c | 1 - arch/powerpc/kernel/process.c | 2 -- arch/powerpc/kernel/ptrace-common.h | 2 -- arch/powerpc/kernel/rtas-proc.c | 1 - arch/powerpc/kernel/rtas_pci.c | 2 -- arch/powerpc/kernel/signal_64.c | 2 -- arch/powerpc/kernel/vdso.c | 2 -- arch/powerpc/lib/copypage_64.S | 2 -- arch/powerpc/lib/copyuser_64.S | 2 -- arch/powerpc/lib/e2a.c | 4 +--- arch/powerpc/lib/memcpy_64.S | 2 -- arch/powerpc/lib/rheap.c | 2 -- arch/powerpc/mm/fault.c | 2 -- arch/powerpc/mm/hash_low_32.S | 2 -- arch/powerpc/mm/mmap.c | 2 -- arch/powerpc/mm/slb_low.S | 2 -- arch/powerpc/mm/tlb_64.c | 2 +- arch/powerpc/platforms/chrp/pegasos_eth.c | 2 -- arch/powerpc/platforms/chrp/setup.c | 2 -- arch/powerpc/platforms/chrp/time.c | 2 -- arch/powerpc/platforms/maple/time.c | 2 -- arch/powerpc/platforms/powermac/cpufreq_32.c | 2 -- arch/powerpc/platforms/powermac/feature.c | 2 -- arch/powerpc/platforms/powermac/nvram.c | 2 -- arch/powerpc/platforms/pseries/hvCall.S | 2 -- arch/powerpc/platforms/pseries/iommu.c | 2 -- arch/powerpc/platforms/pseries/pci.c | 2 -- arch/powerpc/sysdev/dcr.S | 2 -- arch/powerpc/sysdev/ipic.h | 2 -- arch/ppc/4xx_io/serial_sicc.c | 2 -- arch/ppc/amiga/amiints.c | 2 +- arch/ppc/amiga/bootinfo.c | 2 -- arch/ppc/amiga/cia.c | 2 -- arch/ppc/amiga/config.c | 2 -- arch/ppc/amiga/ints.c | 2 -- arch/ppc/boot/Makefile | 3 --- arch/ppc/boot/common/Makefile | 3 --- arch/ppc/boot/common/bootinfo.c | 2 -- arch/ppc/boot/common/misc-common.c | 2 -- arch/ppc/boot/common/serial_stub.c | 2 -- arch/ppc/boot/common/util.S | 2 -- arch/ppc/boot/include/mpc10x.h | 2 -- arch/ppc/boot/simple/cpc700_memory.c | 2 -- arch/ppc/boot/simple/head.S | 2 -- arch/ppc/boot/simple/misc-chestnut.c | 2 -- arch/ppc/boot/simple/misc-cpci690.c | 2 -- arch/ppc/boot/simple/misc-ev64260.c | 2 -- arch/ppc/boot/simple/misc-ev64360.c | 1 - arch/ppc/boot/simple/misc-katana.c | 2 -- arch/ppc/boot/simple/misc-mv64x60.c | 2 -- arch/ppc/boot/simple/misc-prep.c | 2 -- arch/ppc/boot/simple/misc-radstone_ppc7d.c | 2 -- arch/ppc/boot/simple/misc-spruce.c | 2 -- arch/ppc/boot/simple/misc.c | 2 -- arch/ppc/boot/simple/mpc10x_memory.c | 2 -- arch/ppc/boot/simple/mpc52xx_tty.c | 2 -- arch/ppc/boot/simple/mv64x60_tty.c | 2 -- arch/ppc/boot/simple/openbios.c | 2 -- arch/ppc/boot/simple/relocate.S | 2 -- arch/ppc/boot/utils/mkbugboot.c | 2 -- arch/ppc/kernel/head_44x.S | 2 -- arch/ppc/kernel/head_8xx.S | 2 -- arch/ppc/kernel/head_fsl_booke.S | 2 -- arch/ppc/kernel/traps.c | 2 -- arch/ppc/lib/rheap.c | 2 -- arch/ppc/math-emu/math.c | 2 -- arch/ppc/mm/fault.c | 2 -- arch/ppc/mm/hashtable.S | 2 -- arch/ppc/platforms/4xx/bamboo.c | 2 -- arch/ppc/platforms/4xx/bamboo.h | 2 -- arch/ppc/platforms/4xx/bubinga.h | 2 -- arch/ppc/platforms/4xx/cpci405.c | 2 -- arch/ppc/platforms/4xx/ebony.c | 2 -- arch/ppc/platforms/4xx/ebony.h | 2 -- arch/ppc/platforms/4xx/ep405.c | 2 -- arch/ppc/platforms/4xx/ep405.h | 2 -- arch/ppc/platforms/4xx/ibm405ep.c | 2 -- arch/ppc/platforms/4xx/ibm405ep.h | 2 -- arch/ppc/platforms/4xx/ibm405gp.h | 2 -- arch/ppc/platforms/4xx/ibm405gpr.c | 2 -- arch/ppc/platforms/4xx/ibm405gpr.h | 2 -- arch/ppc/platforms/4xx/ibm440ep.c | 2 -- arch/ppc/platforms/4xx/ibm440ep.h | 2 -- arch/ppc/platforms/4xx/ibm440gp.c | 2 -- arch/ppc/platforms/4xx/ibm440gp.h | 2 -- arch/ppc/platforms/4xx/ibm440gx.c | 2 -- arch/ppc/platforms/4xx/ibm440gx.h | 2 -- arch/ppc/platforms/4xx/ibm440sp.c | 2 -- arch/ppc/platforms/4xx/ibm440sp.h | 2 -- arch/ppc/platforms/4xx/ibmnp405h.c | 2 -- arch/ppc/platforms/4xx/ibmnp405h.h | 2 -- arch/ppc/platforms/4xx/ibmstb4.c | 2 -- arch/ppc/platforms/4xx/ibmstb4.h | 2 -- arch/ppc/platforms/4xx/ibmstbx25.c | 2 -- arch/ppc/platforms/4xx/ibmstbx25.h | 2 -- arch/ppc/platforms/4xx/luan.c | 2 -- arch/ppc/platforms/4xx/luan.h | 2 -- arch/ppc/platforms/4xx/ocotea.c | 2 -- arch/ppc/platforms/4xx/ocotea.h | 2 -- arch/ppc/platforms/4xx/ppc440spe.c | 2 -- arch/ppc/platforms/4xx/ppc440spe.h | 2 -- arch/ppc/platforms/4xx/redwood5.c | 2 -- arch/ppc/platforms/4xx/redwood5.h | 2 -- arch/ppc/platforms/4xx/redwood6.c | 2 -- arch/ppc/platforms/4xx/redwood6.h | 2 -- arch/ppc/platforms/4xx/sycamore.c | 2 -- arch/ppc/platforms/4xx/sycamore.h | 2 -- arch/ppc/platforms/4xx/walnut.c | 2 -- arch/ppc/platforms/4xx/walnut.h | 2 -- arch/ppc/platforms/4xx/xilinx_ml300.c | 2 -- arch/ppc/platforms/4xx/xilinx_ml300.h | 2 -- arch/ppc/platforms/4xx/yucca.c | 2 -- arch/ppc/platforms/4xx/yucca.h | 2 -- arch/ppc/platforms/83xx/mpc834x_sys.c | 2 -- arch/ppc/platforms/83xx/mpc834x_sys.h | 2 -- arch/ppc/platforms/85xx/mpc8540_ads.c | 2 -- arch/ppc/platforms/85xx/mpc8540_ads.h | 2 -- arch/ppc/platforms/85xx/mpc8555_cds.h | 2 -- arch/ppc/platforms/85xx/mpc8560_ads.c | 2 -- arch/ppc/platforms/85xx/mpc8560_ads.h | 2 -- arch/ppc/platforms/85xx/mpc85xx_ads_common.c | 2 -- arch/ppc/platforms/85xx/mpc85xx_ads_common.h | 2 -- arch/ppc/platforms/85xx/mpc85xx_cds_common.c | 2 -- arch/ppc/platforms/85xx/mpc85xx_cds_common.h | 2 -- arch/ppc/platforms/85xx/sbc8560.c | 2 -- arch/ppc/platforms/85xx/sbc8560.h | 2 -- arch/ppc/platforms/85xx/sbc85xx.c | 2 -- arch/ppc/platforms/85xx/sbc85xx.h | 2 -- arch/ppc/platforms/85xx/stx_gp3.c | 2 -- arch/ppc/platforms/85xx/stx_gp3.h | 2 -- arch/ppc/platforms/85xx/tqm85xx.c | 2 -- arch/ppc/platforms/85xx/tqm85xx.h | 2 -- arch/ppc/platforms/apus_setup.c | 2 -- arch/ppc/platforms/chestnut.c | 2 -- arch/ppc/platforms/chestnut.h | 2 -- arch/ppc/platforms/chrp_pegasos_eth.c | 2 -- arch/ppc/platforms/chrp_setup.c | 2 -- arch/ppc/platforms/chrp_time.c | 2 -- arch/ppc/platforms/cpci690.c | 2 -- arch/ppc/platforms/cpci690.h | 2 -- arch/ppc/platforms/ev64260.c | 2 -- arch/ppc/platforms/ev64260.h | 2 -- arch/ppc/platforms/ev64360.c | 2 -- arch/ppc/platforms/ev64360.h | 2 -- arch/ppc/platforms/gemini.h | 3 --- arch/ppc/platforms/gemini_prom.S | 2 -- arch/ppc/platforms/gemini_setup.c | 2 -- arch/ppc/platforms/hdpu.c | 3 --- arch/ppc/platforms/hdpu.h | 2 -- arch/ppc/platforms/katana.c | 2 -- arch/ppc/platforms/katana.h | 2 -- arch/ppc/platforms/lite5200.c | 2 -- arch/ppc/platforms/lite5200.h | 2 -- arch/ppc/platforms/lopec.c | 2 -- arch/ppc/platforms/mvme5100.c | 2 -- arch/ppc/platforms/pal4.h | 2 -- arch/ppc/platforms/pal4_pci.c | 2 -- arch/ppc/platforms/pal4_serial.h | 2 -- arch/ppc/platforms/pal4_setup.c | 2 -- arch/ppc/platforms/powerpmc250.c | 2 -- arch/ppc/platforms/pplus.c | 2 -- arch/ppc/platforms/pplus.h | 2 -- arch/ppc/platforms/pq2ads.c | 2 -- arch/ppc/platforms/prep_setup.c | 2 -- arch/ppc/platforms/prpmc750.c | 2 -- arch/ppc/platforms/prpmc800.c | 2 -- arch/ppc/platforms/radstone_ppc7d.c | 2 -- arch/ppc/platforms/radstone_ppc7d.h | 2 -- arch/ppc/platforms/sandpoint.c | 2 -- arch/ppc/platforms/sandpoint.h | 2 -- arch/ppc/platforms/sbc82xx.c | 2 -- arch/ppc/platforms/spruce.c | 2 -- arch/ppc/platforms/tqm8260_setup.c | 2 -- arch/ppc/syslib/cpc700.h | 2 -- arch/ppc/syslib/cpc700_pic.c | 2 -- arch/ppc/syslib/cpc710.h | 2 -- arch/ppc/syslib/gen550.h | 2 -- arch/ppc/syslib/gen550_dbg.c | 2 -- arch/ppc/syslib/gen550_kgdb.c | 2 -- arch/ppc/syslib/gt64260_pic.c | 2 -- arch/ppc/syslib/harrier.c | 2 -- arch/ppc/syslib/hawk_common.c | 2 -- arch/ppc/syslib/ibm440gp_common.c | 2 -- arch/ppc/syslib/ibm440gp_common.h | 2 -- arch/ppc/syslib/ibm440gx_common.c | 2 -- arch/ppc/syslib/ibm440gx_common.h | 2 -- arch/ppc/syslib/ibm440sp_common.c | 2 -- arch/ppc/syslib/ibm440sp_common.h | 2 -- arch/ppc/syslib/ibm44x_common.c | 2 -- arch/ppc/syslib/ibm44x_common.h | 2 -- arch/ppc/syslib/m8260_pci_erratum9.c | 2 -- arch/ppc/syslib/m8260_setup.c | 2 -- arch/ppc/syslib/m8xx_setup.c | 2 -- arch/ppc/syslib/mpc10x_common.c | 2 -- arch/ppc/syslib/mpc52xx_devices.c | 2 -- arch/ppc/syslib/mpc52xx_pci.c | 2 -- arch/ppc/syslib/mpc52xx_pci.h | 2 -- arch/ppc/syslib/mpc52xx_pic.c | 2 -- arch/ppc/syslib/mpc52xx_setup.c | 2 -- arch/ppc/syslib/mpc52xx_sys.c | 2 -- arch/ppc/syslib/mpc83xx_devices.c | 2 -- arch/ppc/syslib/mpc83xx_sys.c | 2 -- arch/ppc/syslib/mpc85xx_devices.c | 2 -- arch/ppc/syslib/mpc85xx_sys.c | 2 -- arch/ppc/syslib/mpc8xx_devices.c | 2 -- arch/ppc/syslib/mpc8xx_sys.c | 2 -- arch/ppc/syslib/mv64360_pic.c | 2 -- arch/ppc/syslib/mv64x60.c | 2 -- arch/ppc/syslib/mv64x60_dbg.c | 2 -- arch/ppc/syslib/mv64x60_win.c | 2 -- arch/ppc/syslib/open_pic.c | 2 -- arch/ppc/syslib/open_pic2.c | 2 -- arch/ppc/syslib/open_pic_defs.h | 2 -- arch/ppc/syslib/pci_auto.c | 2 -- arch/ppc/syslib/ppc4xx_dma.c | 2 -- arch/ppc/syslib/ppc4xx_pic.c | 2 -- arch/ppc/syslib/ppc4xx_sgdma.c | 2 -- arch/ppc/syslib/ppc83xx_setup.c | 2 -- arch/ppc/syslib/ppc83xx_setup.h | 2 -- arch/ppc/syslib/ppc85xx_common.c | 2 -- arch/ppc/syslib/ppc85xx_common.h | 2 -- arch/ppc/syslib/ppc85xx_setup.c | 2 -- arch/ppc/syslib/ppc85xx_setup.h | 2 -- arch/ppc/syslib/ppc_sys.c | 2 -- arch/ppc/syslib/pq2_devices.c | 2 -- arch/ppc/syslib/pq2_sys.c | 2 -- arch/ppc/syslib/prep_nvram.c | 2 -- arch/ppc/syslib/todc_time.c | 2 -- arch/ppc/syslib/xilinx_pic.c | 2 -- drivers/char/hvcs.c | 9 +++++---- include/asm-powerpc/paca.h | 2 +- include/asm-powerpc/rwsem.h | 2 +- include/asm-ppc/harrier.h | 2 -- include/asm-ppc/mpc10x.h | 2 -- include/asm-ppc/todc.h | 2 -- kernel/auditsc.c | 2 +- lib/extable.c | 1 - 248 files changed, 20 insertions(+), 498 deletions(-) (limited to 'include') diff --git a/Documentation/powerpc/eeh-pci-error-recovery.txt b/Documentation/powerpc/eeh-pci-error-recovery.txt index 67a11a36270c..3764dd4b12cb 100644 --- a/Documentation/powerpc/eeh-pci-error-recovery.txt +++ b/Documentation/powerpc/eeh-pci-error-recovery.txt @@ -121,7 +121,7 @@ accomplished. EEH must be enabled in the PHB's very early during the boot process, and if a PCI slot is hot-plugged. The former is performed by -eeh_init() in arch/ppc64/kernel/eeh.c, and the later by +eeh_init() in arch/powerpc/platforms/pseries/eeh.c, and the later by drivers/pci/hotplug/pSeries_pci.c calling in to the eeh.c code. EEH must be enabled before a PCI scan of the device can proceed. Current Power5 hardware will not work unless EEH is enabled; @@ -133,7 +133,7 @@ error. Given an arbitrary address, the routine pci_get_device_by_addr() will find the pci device associated with that address (if any). -The default include/asm-ppc64/io.h macros readb(), inb(), insb(), +The default include/asm-powerpc/io.h macros readb(), inb(), insb(), etc. include a check to see if the i/o read returned all-0xff's. If so, these make a call to eeh_dn_check_failure(), which in turn asks the firmware if the all-ff's value is the sign of a true EEH @@ -143,11 +143,12 @@ seen in /proc/ppc64/eeh (subject to change). Normally, almost all of these occur during boot, when the PCI bus is scanned, where a large number of 0xff reads are part of the bus scan procedure. -If a frozen slot is detected, code in arch/ppc64/kernel/eeh.c will -print a stack trace to syslog (/var/log/messages). This stack trace -has proven to be very useful to device-driver authors for finding -out at what point the EEH error was detected, as the error itself -usually occurs slightly beforehand. +If a frozen slot is detected, code in +arch/powerpc/platforms/pseries/eeh.c will print a stack trace to +syslog (/var/log/messages). This stack trace has proven to be very +useful to device-driver authors for finding out at what point the EEH +error was detected, as the error itself usually occurs slightly +beforehand. Next, it uses the Linux kernel notifier chain/work queue mechanism to allow any interested parties to find out about the failure. Device diff --git a/arch/powerpc/boot/install.sh b/arch/powerpc/boot/install.sh index eacce9590816..b002bfd56786 100644 --- a/arch/powerpc/boot/install.sh +++ b/arch/powerpc/boot/install.sh @@ -1,7 +1,5 @@ #!/bin/sh # -# arch/ppc64/boot/install.sh -# # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive # for more details. diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 388f861b8ed1..79a0c910f0d8 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/entry.S - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP @@ -374,7 +372,7 @@ _GLOBAL(ret_from_fork) * the fork code also. * * The code which creates the new task context is in 'copy_thread' - * in arch/ppc64/kernel/process.c + * in arch/powerpc/kernel/process.c */ .align 7 _GLOBAL(_switch) diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index 8b49679fad54..47c7fa148c9a 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/head_44x.S - * * Kernel execution entry point code. * * Copyright (c) 1995-1996 Gary Thomas diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 415659629394..7ebb73665e9d 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/head.S - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index bc6d1ac55235..28941f5ce673 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/except_8xx.S - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 0abd05f14f87..dd86bbed7627 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/head_fsl_booke.S - * * Kernel execution entry point code. * * Copyright (c) 1995-1996 Gary Thomas diff --git a/arch/powerpc/kernel/iomap.c b/arch/powerpc/kernel/iomap.c index 6160c8dbb7c5..fd8214caedee 100644 --- a/arch/powerpc/kernel/iomap.c +++ b/arch/powerpc/kernel/iomap.c @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/iomap.c - * * ppc64 "iomap" interface implementation. * * (C) Copyright 2004 Linus Torvalds diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 946f3219fd29..d9a7fdef59b9 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -1,5 +1,4 @@ /* - * arch/ppc64/kernel/iommu.c * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation * * Rewrite, cleanup, new allocation schemes, virtual merging: diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index d1fffce86df9..edb2b00edbd2 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/irq.c - * * Derived from arch/i386/kernel/irq.c * Copyright (C) 1992 Linus Torvalds * Adapted from arch/i386 by Gary Thomas diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index cfab48566db1..258039fb3016 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -1,6 +1,5 @@ /* * Kernel Probes (KProbes) - * arch/ppc64/kernel/kprobes.c * * 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 diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c index bdf15dbbf4f0..c336f3e31cff 100644 --- a/arch/powerpc/kernel/pci_iommu.c +++ b/arch/powerpc/kernel/pci_iommu.c @@ -1,5 +1,4 @@ /* - * arch/ppc64/kernel/pci_iommu.c * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation * * Rewrite, cleanup, new allocation schemes: diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 57703994a063..1201880cab40 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/process.c - * * Derived from "arch/i386/kernel/process.c" * Copyright (C) 1995 Linus Torvalds * diff --git a/arch/powerpc/kernel/ptrace-common.h b/arch/powerpc/kernel/ptrace-common.h index 5ccbdbe0d5c9..c42a860c8d25 100644 --- a/arch/powerpc/kernel/ptrace-common.h +++ b/arch/powerpc/kernel/ptrace-common.h @@ -1,6 +1,4 @@ /* - * linux/arch/ppc64/kernel/ptrace-common.h - * * Copyright (c) 2002 Stephen Rothwell, IBM Coproration * Extracted from ptrace.c and ptrace32.c * diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c index 7a95b8a28354..1f03fb28cc0a 100644 --- a/arch/powerpc/kernel/rtas-proc.c +++ b/arch/powerpc/kernel/rtas-proc.c @@ -1,5 +1,4 @@ /* - * arch/ppc64/kernel/rtas-proc.c * Copyright (C) 2000 Tilmann Bitterberg * (tilmann@bitterberg.de) * diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 5579f6559912..03afb79e27e5 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/rtas_pci.c - * * Copyright (C) 2001 Dave Engebretsen, IBM Corporation * Copyright (C) 2003 Anton Blanchard , IBM * diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 497a5d3df359..59b9c9cdd6a9 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -1,6 +1,4 @@ /* - * linux/arch/ppc64/kernel/signal.c - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index f0c47dab0903..b316fda58b89 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -1,6 +1,4 @@ /* - * linux/arch/ppc64/kernel/vdso.c - * * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp. * * diff --git a/arch/powerpc/lib/copypage_64.S b/arch/powerpc/lib/copypage_64.S index 40523b140109..f9837f44ac0b 100644 --- a/arch/powerpc/lib/copypage_64.S +++ b/arch/powerpc/lib/copypage_64.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/lib/copypage.S - * * Copyright (C) 2002 Paul Mackerras, IBM Corp. * * This program is free software; you can redistribute it and/or diff --git a/arch/powerpc/lib/copyuser_64.S b/arch/powerpc/lib/copyuser_64.S index 6d69ef39b7df..a6b54cb97c49 100644 --- a/arch/powerpc/lib/copyuser_64.S +++ b/arch/powerpc/lib/copyuser_64.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/lib/copyuser.S - * * Copyright (C) 2002 Paul Mackerras, IBM Corp. * * This program is free software; you can redistribute it and/or diff --git a/arch/powerpc/lib/e2a.c b/arch/powerpc/lib/e2a.c index d2b834887920..4f88f4cc21e8 100644 --- a/arch/powerpc/lib/e2a.c +++ b/arch/powerpc/lib/e2a.c @@ -1,9 +1,7 @@ /* - * arch/ppc64/lib/e2a.c - * * EBCDIC to ASCII conversion * - * This function moved here from arch/ppc64/kernel/viopath.c + * This function moved here from arch/powerpc/platforms/iseries/viopath.c * * (C) Copyright 2000-2004 IBM Corporation * diff --git a/arch/powerpc/lib/memcpy_64.S b/arch/powerpc/lib/memcpy_64.S index 9ccacdf5bcb9..fd66acfd3e3e 100644 --- a/arch/powerpc/lib/memcpy_64.S +++ b/arch/powerpc/lib/memcpy_64.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/lib/memcpy.S - * * Copyright (C) 2002 Paul Mackerras, IBM Corp. * * This program is free software; you can redistribute it and/or diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c index 42c5de2c898f..31e511856dc5 100644 --- a/arch/powerpc/lib/rheap.c +++ b/arch/powerpc/lib/rheap.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/rheap.c - * * A Remote Heap. Remote means that we don't touch the memory that the * heap points to. Normal heap implementations use the memory they manage * to place their list. We cannot do that because the memory we manage may diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index a4815d316722..ec4adcb4bc28 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -1,6 +1,4 @@ /* - * arch/ppc/mm/fault.c - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * diff --git a/arch/powerpc/mm/hash_low_32.S b/arch/powerpc/mm/hash_low_32.S index 12ccd7155bac..ea469eefa146 100644 --- a/arch/powerpc/mm/hash_low_32.S +++ b/arch/powerpc/mm/hash_low_32.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/hashtable.S - * * $Id: hashtable.S,v 1.6 1999/10/08 01:56:15 paulus Exp $ * * PowerPC version diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c index fe65f522aff3..972a8e884b9a 100644 --- a/arch/powerpc/mm/mmap.c +++ b/arch/powerpc/mm/mmap.c @@ -1,6 +1,4 @@ /* - * linux/arch/ppc64/mm/mmap.c - * * flexible mmap layout support * * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S index d1acee38f163..abfaabf667bf 100644 --- a/arch/powerpc/mm/slb_low.S +++ b/arch/powerpc/mm/slb_low.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/mm/slb_low.S - * * Low-level SLB routines * * Copyright (C) 2004 David Gibson , IBM diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c index bb3afb6e6317..f734b11566c2 100644 --- a/arch/powerpc/mm/tlb_64.c +++ b/arch/powerpc/mm/tlb_64.c @@ -36,7 +36,7 @@ DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); /* This is declared as we are using the more or less generic - * include/asm-ppc64/tlb.h file -- tgall + * include/asm-powerpc/tlb.h file -- tgall */ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur); diff --git a/arch/powerpc/platforms/chrp/pegasos_eth.c b/arch/powerpc/platforms/chrp/pegasos_eth.c index 29c86781c493..6ad4b1a72c96 100644 --- a/arch/powerpc/platforms/chrp/pegasos_eth.c +++ b/arch/powerpc/platforms/chrp/pegasos_eth.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/chrp_pegasos_eth.c - * * Copyright (C) 2005 Sven Luther * Thanks to : * Dale Farnsworth diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index e1fadbf49150..8bf4307e323d 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/setup.c - * * Copyright (C) 1995 Linus Torvalds * Adapted from 'alpha' version by Gary Thomas * Modified by Cort Dougan (cort@cs.nmt.edu) diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index 78df2e7ca88a..12c6f689b1aa 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/chrp_time.c - * * Copyright (C) 1991, 1992, 1995 Linus Torvalds * * Adapted for PowerPC (PReP) by Gary Thomas diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c index 50bc4eb85353..5e6981d17379 100644 --- a/arch/powerpc/platforms/maple/time.c +++ b/arch/powerpc/platforms/maple/time.c @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/maple_time.c - * * (c) Copyright 2004 Benjamin Herrenschmidt (benh@kernel.crashing.org), * IBM Corp. * diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c index 56fd4e05fede..cfd6527a0d7e 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_32.c +++ b/arch/powerpc/platforms/powermac/cpufreq_32.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pmac_cpufreq.c - * * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt * Copyright (C) 2004 John Steele Scott * diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index 558dd0692092..50ed8890dd33 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pmac_feature.c - * * Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au) * Ben. Herrenschmidt (benh@kernel.crashing.org) * diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c index 3ebd045a3350..5fd28995c74c 100644 --- a/arch/powerpc/platforms/powermac/nvram.c +++ b/arch/powerpc/platforms/powermac/nvram.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pmac_nvram.c - * * Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org) * * This program is free software; you can redistribute it and/or diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S index 176e8da76466..db7c19fe9297 100644 --- a/arch/powerpc/platforms/pseries/hvCall.S +++ b/arch/powerpc/platforms/pseries/hvCall.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/pSeries_hvCall.S - * * This file contains the generic code to perform a call to the * pSeries LPAR hypervisor. * NOTE: this file will go away when we move to inline this work. diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 48cfbfc43f99..57930e23cc74 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/pSeries_iommu.c - * * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation * * Rewrite, cleanup: diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index 999a9620b5ce..946ad59e3352 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/pSeries_pci.c - * * Copyright (C) 2001 Dave Engebretsen, IBM Corporation * Copyright (C) 2003 Anton Blanchard , IBM * diff --git a/arch/powerpc/sysdev/dcr.S b/arch/powerpc/sysdev/dcr.S index 895f10243a43..2078f39e2f17 100644 --- a/arch/powerpc/sysdev/dcr.S +++ b/arch/powerpc/sysdev/dcr.S @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/dcr.S - * * "Indirect" DCR access * * Copyright (c) 2004 Eugene Surovegin diff --git a/arch/powerpc/sysdev/ipic.h b/arch/powerpc/sysdev/ipic.h index a7ce7da8785c..a60c9d18bb7f 100644 --- a/arch/powerpc/sysdev/ipic.h +++ b/arch/powerpc/sysdev/ipic.h @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/ipic.h - * * IPIC private definitions and structure. * * Maintainer: Kumar Gala diff --git a/arch/ppc/4xx_io/serial_sicc.c b/arch/ppc/4xx_io/serial_sicc.c index 8ace2a1f3b48..4dc6aa2abfc1 100644 --- a/arch/ppc/4xx_io/serial_sicc.c +++ b/arch/ppc/4xx_io/serial_sicc.c @@ -1,6 +1,4 @@ /* - * arch/ppc/4xx_io/serial_sicc.c - * * Driver for IBM STB3xxx SICC serial port * * Based on drivers/char/serial_amba.c, by ARM Ltd. diff --git a/arch/ppc/amiga/amiints.c b/arch/ppc/amiga/amiints.c index 5f35cf3986f7..b2bba052ab93 100644 --- a/arch/ppc/amiga/amiints.c +++ b/arch/ppc/amiga/amiints.c @@ -1,5 +1,5 @@ /* - * arch/ppc/amiga/amiints.c -- Amiga Linux interrupt handling code + * Amiga Linux interrupt handling code * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive diff --git a/arch/ppc/amiga/bootinfo.c b/arch/ppc/amiga/bootinfo.c index e2e965661d03..efd869a3ed9b 100644 --- a/arch/ppc/amiga/bootinfo.c +++ b/arch/ppc/amiga/bootinfo.c @@ -1,6 +1,4 @@ /* - * arch/ppc/amiga/bootinfo.c - * * Extracted from arch/m68k/kernel/setup.c. * Should be properly generalized and put somewhere else. * Jesper diff --git a/arch/ppc/amiga/cia.c b/arch/ppc/amiga/cia.c index 4431c58f611a..9558f2f40e64 100644 --- a/arch/ppc/amiga/cia.c +++ b/arch/ppc/amiga/cia.c @@ -1,6 +1,4 @@ /* - * arch/ppc/amiga/cia.c - CIA support - * * Copyright (C) 1996 Roman Zippel * * The concept of some functions bases on the original Amiga OS function diff --git a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c index 60e2da1c92c0..bbe47c9bd707 100644 --- a/arch/ppc/amiga/config.c +++ b/arch/ppc/amiga/config.c @@ -1,8 +1,6 @@ #define m68k_debug_device debug_device /* - * arch/ppc/amiga/config.c - * * Copyright (C) 1993 Hamish Macdonald * * This file is subject to the terms and conditions of the GNU General Public diff --git a/arch/ppc/amiga/ints.c b/arch/ppc/amiga/ints.c index 5d318e498f06..083a17462190 100644 --- a/arch/ppc/amiga/ints.c +++ b/arch/ppc/amiga/ints.c @@ -1,6 +1,4 @@ /* - * arch/ppc/amiga/ints.c - * * Linux/m68k general interrupt handling code from arch/m68k/kernel/ints.c * Needed to drive the m68k emulating IRQ hardware on the PowerUp boards. */ diff --git a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile index efd8ce515d5f..f565699a9fe0 100644 --- a/arch/ppc/boot/Makefile +++ b/arch/ppc/boot/Makefile @@ -1,6 +1,3 @@ -# -# arch/ppc/boot/Makefile -# # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive # for more details. diff --git a/arch/ppc/boot/common/Makefile b/arch/ppc/boot/common/Makefile index f88d647d5dd4..a2e85e3beb88 100644 --- a/arch/ppc/boot/common/Makefile +++ b/arch/ppc/boot/common/Makefile @@ -1,6 +1,3 @@ -# -# arch/ppc/boot/common/Makefile -# # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive # for more details. diff --git a/arch/ppc/boot/common/bootinfo.c b/arch/ppc/boot/common/bootinfo.c index 9c6e528940e9..f4dc9b9fab9c 100644 --- a/arch/ppc/boot/common/bootinfo.c +++ b/arch/ppc/boot/common/bootinfo.c @@ -1,6 +1,4 @@ /* - * arch/ppc/common/bootinfo.c - * * General bootinfo record utilities * Author: Randy Vinson * diff --git a/arch/ppc/boot/common/misc-common.c b/arch/ppc/boot/common/misc-common.c index e79e6b3f276e..073830a8559a 100644 --- a/arch/ppc/boot/common/misc-common.c +++ b/arch/ppc/boot/common/misc-common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/common/misc-common.c - * * Misc. bootloader code (almost) all platforms can use * * Author: Johnnie Peters diff --git a/arch/ppc/boot/common/serial_stub.c b/arch/ppc/boot/common/serial_stub.c index 03dfaa01fa63..5cc9ae66a8ba 100644 --- a/arch/ppc/boot/common/serial_stub.c +++ b/arch/ppc/boot/common/serial_stub.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/common/serial_stub.c - * * This is a few stub routines to make the boot code cleaner looking when * there is no serial port support doesn't need to be closed, for example. * diff --git a/arch/ppc/boot/common/util.S b/arch/ppc/boot/common/util.S index 368ec035e6cd..0c5e43c4ae06 100644 --- a/arch/ppc/boot/common/util.S +++ b/arch/ppc/boot/common/util.S @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/common/util.S - * * Useful bootup functions, which are more easily done in asm than C. * * NOTE: Be very very careful about the registers you use here. diff --git a/arch/ppc/boot/include/mpc10x.h b/arch/ppc/boot/include/mpc10x.h index 6cd40ecabc74..6e5d540d8d3e 100644 --- a/arch/ppc/boot/include/mpc10x.h +++ b/arch/ppc/boot/include/mpc10x.h @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/include/mpc10.h - * * Common defines for the Motorola SPS MPC106/8240/107 Host bridge/Mem * ctrl/EPIC/etc. * diff --git a/arch/ppc/boot/simple/cpc700_memory.c b/arch/ppc/boot/simple/cpc700_memory.c index 8c75cf6c2383..d75420a45a59 100644 --- a/arch/ppc/boot/simple/cpc700_memory.c +++ b/arch/ppc/boot/simple/cpc700_memory.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/common/cpc700_memory.c - * * Find memory based upon settings in the CPC700 bridge * * Author: Dan Cox diff --git a/arch/ppc/boot/simple/head.S b/arch/ppc/boot/simple/head.S index 119b9dc89587..160da1006ff8 100644 --- a/arch/ppc/boot/simple/head.S +++ b/arch/ppc/boot/simple/head.S @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/head.S - * * Initial board bringup code for many different boards. * * Author: Tom Rini diff --git a/arch/ppc/boot/simple/misc-chestnut.c b/arch/ppc/boot/simple/misc-chestnut.c index 0dce7f3557e4..b94e142ad892 100644 --- a/arch/ppc/boot/simple/misc-chestnut.c +++ b/arch/ppc/boot/simple/misc-chestnut.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/misc-chestnut.c - * * Setup for the IBM Chestnut (ibm-750fxgx_eval) * * Author: Mark A. Greer diff --git a/arch/ppc/boot/simple/misc-cpci690.c b/arch/ppc/boot/simple/misc-cpci690.c index 26860300fa09..8a8614d11a32 100644 --- a/arch/ppc/boot/simple/misc-cpci690.c +++ b/arch/ppc/boot/simple/misc-cpci690.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/misc-cpci690.c - * * Add birec data for Force CPCI690 board. * * Author: Mark A. Greer diff --git a/arch/ppc/boot/simple/misc-ev64260.c b/arch/ppc/boot/simple/misc-ev64260.c index 52ece6937a7a..2678c224af22 100644 --- a/arch/ppc/boot/simple/misc-ev64260.c +++ b/arch/ppc/boot/simple/misc-ev64260.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/misc-ev64260.c - * * Host bridge init code for the Marvell/Galileo EV-64260-BP evaluation board * with a GT64260 onboard. * diff --git a/arch/ppc/boot/simple/misc-ev64360.c b/arch/ppc/boot/simple/misc-ev64360.c index cd1ccf2a1582..a212b5b988cb 100644 --- a/arch/ppc/boot/simple/misc-ev64360.c +++ b/arch/ppc/boot/simple/misc-ev64360.c @@ -1,5 +1,4 @@ /* - * arch/ppc/boot/simple/misc-ev64360.c * Copyright (C) 2005 Lee Nicks * * Based on arch/ppc/boot/simple/misc-katana.c from: diff --git a/arch/ppc/boot/simple/misc-katana.c b/arch/ppc/boot/simple/misc-katana.c index ec94a11bacac..d97f2ee6f04e 100644 --- a/arch/ppc/boot/simple/misc-katana.c +++ b/arch/ppc/boot/simple/misc-katana.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/misc-katana.c - * * Set up MPSC values to bootwrapper can prompt user. * * Author: Mark A. Greer diff --git a/arch/ppc/boot/simple/misc-mv64x60.c b/arch/ppc/boot/simple/misc-mv64x60.c index 258d4599fadc..71ff20fd494a 100644 --- a/arch/ppc/boot/simple/misc-mv64x60.c +++ b/arch/ppc/boot/simple/misc-mv64x60.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/misc-mv64x60.c - * * Relocate bridge's register base and call board specific routine. * * Author: Mark A. Greer diff --git a/arch/ppc/boot/simple/misc-prep.c b/arch/ppc/boot/simple/misc-prep.c index 75380ac41669..63def9d13d70 100644 --- a/arch/ppc/boot/simple/misc-prep.c +++ b/arch/ppc/boot/simple/misc-prep.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/misc-prep.c - * * Maintainer: Tom Rini * * In the past: Gary Thomas, Cort Dougan diff --git a/arch/ppc/boot/simple/misc-radstone_ppc7d.c b/arch/ppc/boot/simple/misc-radstone_ppc7d.c index 569e0d4feeaf..0f302ea9c3d1 100644 --- a/arch/ppc/boot/simple/misc-radstone_ppc7d.c +++ b/arch/ppc/boot/simple/misc-radstone_ppc7d.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/misc-radstone_ppc7d.c - * * Misc data for Radstone PPC7D board. * * Author: James Chapman diff --git a/arch/ppc/boot/simple/misc-spruce.c b/arch/ppc/boot/simple/misc-spruce.c index d012c39278fd..0cad2f557a1e 100644 --- a/arch/ppc/boot/simple/misc-spruce.c +++ b/arch/ppc/boot/simple/misc-spruce.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/spruce/misc.c - * * Misc. bootloader code for IBM Spruce reference platform * * Authors: Johnnie Peters diff --git a/arch/ppc/boot/simple/misc.c b/arch/ppc/boot/simple/misc.c index f415d6c62362..3d78571ad945 100644 --- a/arch/ppc/boot/simple/misc.c +++ b/arch/ppc/boot/simple/misc.c @@ -1,6 +1,4 @@ /* - * arch/ppc/simple/misc.c - * * Misc. bootloader code for many machines. This assumes you have are using * a 6xx/7xx/74xx CPU in your machine. This assumes the chunk of memory * below 8MB is free. Finally, it assumes you have a NS16550-style uart for diff --git a/arch/ppc/boot/simple/mpc10x_memory.c b/arch/ppc/boot/simple/mpc10x_memory.c index 20d92a34ceb8..c24290823f7f 100644 --- a/arch/ppc/boot/simple/mpc10x_memory.c +++ b/arch/ppc/boot/simple/mpc10x_memory.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/common/mpc10x_common.c - * * A routine to find out how much memory the machine has. * * Based on: diff --git a/arch/ppc/boot/simple/mpc52xx_tty.c b/arch/ppc/boot/simple/mpc52xx_tty.c index 3acc6b7c0727..1964493cf3bd 100644 --- a/arch/ppc/boot/simple/mpc52xx_tty.c +++ b/arch/ppc/boot/simple/mpc52xx_tty.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/mpc52xx_tty.c - * * Minimal serial functions needed to send messages out a MPC52xx * Programmable Serial Controller (PSC). * diff --git a/arch/ppc/boot/simple/mv64x60_tty.c b/arch/ppc/boot/simple/mv64x60_tty.c index b9c24d4c738b..0c52f5c784a2 100644 --- a/arch/ppc/boot/simple/mv64x60_tty.c +++ b/arch/ppc/boot/simple/mv64x60_tty.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/mv64x60_tty.c - * * Bootloader version of the embedded MPSC/UART driver for the Marvell 64x60. * Note: Due to a GT64260A erratum, DMA will be used for UART input (via SDMA). * diff --git a/arch/ppc/boot/simple/openbios.c b/arch/ppc/boot/simple/openbios.c index 81f11d8b30a7..3f2ed53f793a 100644 --- a/arch/ppc/boot/simple/openbios.c +++ b/arch/ppc/boot/simple/openbios.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/openbios.c - * * Copyright (c) 2005 DENX Software Engineering * Stefan Roese * diff --git a/arch/ppc/boot/simple/relocate.S b/arch/ppc/boot/simple/relocate.S index 555a216ccc49..7efddc507564 100644 --- a/arch/ppc/boot/simple/relocate.S +++ b/arch/ppc/boot/simple/relocate.S @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/relocate.S - * * This is the common part of the loader relocation and initialization * process. All of the board/processor specific initialization is * done before we get here. diff --git a/arch/ppc/boot/utils/mkbugboot.c b/arch/ppc/boot/utils/mkbugboot.c index 886122283f39..29115e01f60a 100644 --- a/arch/ppc/boot/utils/mkbugboot.c +++ b/arch/ppc/boot/utils/mkbugboot.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/utils/mkbugboot.c - * * Makes a Motorola PPCBUG ROM bootable image which can be flashed * into one of the FLASH banks on a Motorola PowerPlus board. * diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S index 677c571aa276..0d8b88219d38 100644 --- a/arch/ppc/kernel/head_44x.S +++ b/arch/ppc/kernel/head_44x.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/head_44x.S - * * Kernel execution entry point code. * * Copyright (c) 1995-1996 Gary Thomas diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S index c1e89ad0684d..ec53c7d65f2b 100644 --- a/arch/ppc/kernel/head_8xx.S +++ b/arch/ppc/kernel/head_8xx.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/except_8xx.S - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S index 0abd05f14f87..dd86bbed7627 100644 --- a/arch/ppc/kernel/head_fsl_booke.S +++ b/arch/ppc/kernel/head_fsl_booke.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/head_fsl_booke.S - * * Kernel execution entry point code. * * Copyright (c) 1995-1996 Gary Thomas diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 6d0a1838d94c..1c0d68026abd 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/traps.c - * * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * * This program is free software; you can redistribute it and/or diff --git a/arch/ppc/lib/rheap.c b/arch/ppc/lib/rheap.c index 42c5de2c898f..31e511856dc5 100644 --- a/arch/ppc/lib/rheap.c +++ b/arch/ppc/lib/rheap.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/rheap.c - * * A Remote Heap. Remote means that we don't touch the memory that the * heap points to. Normal heap implementations use the memory they manage * to place their list. We cannot do that because the memory we manage may diff --git a/arch/ppc/math-emu/math.c b/arch/ppc/math-emu/math.c index b7dff53a7103..589153472761 100644 --- a/arch/ppc/math-emu/math.c +++ b/arch/ppc/math-emu/math.c @@ -1,6 +1,4 @@ /* - * arch/ppc/math-emu/math.c - * * Copyright (C) 1999 Eddie C. Dost (ecd@atecom.com) */ diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c index ee5e9f25baf9..0217188ef465 100644 --- a/arch/ppc/mm/fault.c +++ b/arch/ppc/mm/fault.c @@ -1,6 +1,4 @@ /* - * arch/ppc/mm/fault.c - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * diff --git a/arch/ppc/mm/hashtable.S b/arch/ppc/mm/hashtable.S index 3ec87c91343e..f09fa88db35a 100644 --- a/arch/ppc/mm/hashtable.S +++ b/arch/ppc/mm/hashtable.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/hashtable.S - * * $Id: hashtable.S,v 1.6 1999/10/08 01:56:15 paulus Exp $ * * PowerPC version diff --git a/arch/ppc/platforms/4xx/bamboo.c b/arch/ppc/platforms/4xx/bamboo.c index 0ec53f049338..b940cfd646c2 100644 --- a/arch/ppc/platforms/4xx/bamboo.c +++ b/arch/ppc/platforms/4xx/bamboo.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/bamboo.c - * * Bamboo board specific routines * * Wade Farnsworth diff --git a/arch/ppc/platforms/4xx/bamboo.h b/arch/ppc/platforms/4xx/bamboo.h index 5c0192826494..31c0dd6a26cb 100644 --- a/arch/ppc/platforms/4xx/bamboo.h +++ b/arch/ppc/platforms/4xx/bamboo.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/bamboo.h - * * Bamboo board definitions * * Wade Farnsworth diff --git a/arch/ppc/platforms/4xx/bubinga.h b/arch/ppc/platforms/4xx/bubinga.h index b5380cfaf5c0..606aa9fa5caa 100644 --- a/arch/ppc/platforms/4xx/bubinga.h +++ b/arch/ppc/platforms/4xx/bubinga.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/bubinga.h - * * Bubinga board definitions * * Copyright (c) 2005 DENX Software Engineering diff --git a/arch/ppc/platforms/4xx/cpci405.c b/arch/ppc/platforms/4xx/cpci405.c index ff966773a0bf..6571e39fbe48 100644 --- a/arch/ppc/platforms/4xx/cpci405.c +++ b/arch/ppc/platforms/4xx/cpci405.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/cpci405.c - * * Board setup routines for the esd CPCI-405 cPCI Board. * * Author: Stefan Roese diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c index 9a828b623417..b4ecb9c79854 100644 --- a/arch/ppc/platforms/4xx/ebony.c +++ b/arch/ppc/platforms/4xx/ebony.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ebony.c - * * Ebony board specific routines * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h index b91ad4272dfe..27b2e77c7c83 100644 --- a/arch/ppc/platforms/4xx/ebony.h +++ b/arch/ppc/platforms/4xx/ebony.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/ebony.h - * * Ebony board definitions * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ep405.c b/arch/ppc/platforms/4xx/ep405.c index 26a07cdb30ec..6efa91ff9c07 100644 --- a/arch/ppc/platforms/4xx/ep405.c +++ b/arch/ppc/platforms/4xx/ep405.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ep405.c - * * Embedded Planet 405GP board * http://www.embeddedplanet.com * diff --git a/arch/ppc/platforms/4xx/ep405.h b/arch/ppc/platforms/4xx/ep405.h index ea3eb21338fb..9814fc431725 100644 --- a/arch/ppc/platforms/4xx/ep405.h +++ b/arch/ppc/platforms/4xx/ep405.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ep405.h - * * Embedded Planet 405GP board * http://www.embeddedplanet.com * diff --git a/arch/ppc/platforms/4xx/ibm405ep.c b/arch/ppc/platforms/4xx/ibm405ep.c index 093b28d27a41..55af769a6e70 100644 --- a/arch/ppc/platforms/4xx/ibm405ep.c +++ b/arch/ppc/platforms/4xx/ibm405ep.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/ibm405ep.c - * * Support for IBM PPC 405EP processors. * * Author: SAW (IBM), derived from ibmnp405l.c. diff --git a/arch/ppc/platforms/4xx/ibm405ep.h b/arch/ppc/platforms/4xx/ibm405ep.h index e051e3fe8c63..fe46640de152 100644 --- a/arch/ppc/platforms/4xx/ibm405ep.h +++ b/arch/ppc/platforms/4xx/ibm405ep.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm405ep.h - * * IBM PPC 405EP processor defines. * * Author: SAW (IBM), derived from ibm405gp.h. diff --git a/arch/ppc/platforms/4xx/ibm405gp.h b/arch/ppc/platforms/4xx/ibm405gp.h index b2b642e81af7..eaf0ef57028d 100644 --- a/arch/ppc/platforms/4xx/ibm405gp.h +++ b/arch/ppc/platforms/4xx/ibm405gp.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm405gp.h - * * Author: Armin Kuster akuster@mvista.com * * 2001 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/ibm405gpr.c b/arch/ppc/platforms/4xx/ibm405gpr.c index cd0d00d8e8ee..49da61f6854a 100644 --- a/arch/ppc/platforms/4xx/ibm405gpr.c +++ b/arch/ppc/platforms/4xx/ibm405gpr.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm405gpr.c - * * Author: Armin Kuster * * 2002 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/ibm405gpr.h b/arch/ppc/platforms/4xx/ibm405gpr.h index 45412fb4368f..e90c5dde01d3 100644 --- a/arch/ppc/platforms/4xx/ibm405gpr.h +++ b/arch/ppc/platforms/4xx/ibm405gpr.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm405gpr.h - * * Author: Armin Kuster * * 2002 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/ibm440ep.c b/arch/ppc/platforms/4xx/ibm440ep.c index 65ac0b9c2d05..1fed6638c81f 100644 --- a/arch/ppc/platforms/4xx/ibm440ep.c +++ b/arch/ppc/platforms/4xx/ibm440ep.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm440ep.c - * * PPC440EP I/O descriptions * * Wade Farnsworth diff --git a/arch/ppc/platforms/4xx/ibm440ep.h b/arch/ppc/platforms/4xx/ibm440ep.h index 97c80b8e3e10..61717e8a799e 100644 --- a/arch/ppc/platforms/4xx/ibm440ep.h +++ b/arch/ppc/platforms/4xx/ibm440ep.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm440ep.h - * * PPC440EP definitions * * Wade Farnsworth diff --git a/arch/ppc/platforms/4xx/ibm440gp.c b/arch/ppc/platforms/4xx/ibm440gp.c index d926245e8b3e..b67a72e5c6fe 100644 --- a/arch/ppc/platforms/4xx/ibm440gp.c +++ b/arch/ppc/platforms/4xx/ibm440gp.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm440gp.c - * * PPC440GP I/O descriptions * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ibm440gp.h b/arch/ppc/platforms/4xx/ibm440gp.h index ae1efc03b295..7b2763b6024f 100644 --- a/arch/ppc/platforms/4xx/ibm440gp.h +++ b/arch/ppc/platforms/4xx/ibm440gp.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm440gp.h - * * PPC440GP definitions * * Roland Dreier diff --git a/arch/ppc/platforms/4xx/ibm440gx.c b/arch/ppc/platforms/4xx/ibm440gx.c index d24c09ee7b18..685abffcb6ce 100644 --- a/arch/ppc/platforms/4xx/ibm440gx.c +++ b/arch/ppc/platforms/4xx/ibm440gx.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm440gx.c - * * PPC440GX I/O descriptions * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ibm440gx.h b/arch/ppc/platforms/4xx/ibm440gx.h index 0b59d8dcd03c..070a34efe1c7 100644 --- a/arch/ppc/platforms/4xx/ibm440gx.h +++ b/arch/ppc/platforms/4xx/ibm440gx.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/ibm440gx.h - * * PPC440GX definitions * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ibm440sp.c b/arch/ppc/platforms/4xx/ibm440sp.c index 71a0117d3597..de8f7ac5623c 100644 --- a/arch/ppc/platforms/4xx/ibm440sp.c +++ b/arch/ppc/platforms/4xx/ibm440sp.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm440sp.c - * * PPC440SP I/O descriptions * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ibm440sp.h b/arch/ppc/platforms/4xx/ibm440sp.h index c71e46a18b9e..77e8bb22c527 100644 --- a/arch/ppc/platforms/4xx/ibm440sp.h +++ b/arch/ppc/platforms/4xx/ibm440sp.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm440sp.h - * * PPC440SP definitions * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ibmnp405h.c b/arch/ppc/platforms/4xx/ibmnp405h.c index a477a78f4902..f1dcb0ac15b7 100644 --- a/arch/ppc/platforms/4xx/ibmnp405h.c +++ b/arch/ppc/platforms/4xx/ibmnp405h.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibmnp405h.c - * * Author: Armin Kuster * * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/ibmnp405h.h b/arch/ppc/platforms/4xx/ibmnp405h.h index e2c2b06128c8..2c683f6aaa66 100644 --- a/arch/ppc/platforms/4xx/ibmnp405h.h +++ b/arch/ppc/platforms/4xx/ibmnp405h.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibmnp405h.h - * * Author: Armin Kuster * * 2002 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/ibmstb4.c b/arch/ppc/platforms/4xx/ibmstb4.c index 7e33bb635443..799a2eccccc3 100644 --- a/arch/ppc/platforms/4xx/ibmstb4.c +++ b/arch/ppc/platforms/4xx/ibmstb4.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibmstb4.c - * * Author: Armin Kuster * * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/ibmstb4.h b/arch/ppc/platforms/4xx/ibmstb4.h index 9f21d4c88a3d..9de426597351 100644 --- a/arch/ppc/platforms/4xx/ibmstb4.h +++ b/arch/ppc/platforms/4xx/ibmstb4.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibmstb4.h - * * Author: Armin Kuster * * 2001 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/ibmstbx25.c b/arch/ppc/platforms/4xx/ibmstbx25.c index b895b9cca57d..090ddcbecc5e 100644 --- a/arch/ppc/platforms/4xx/ibmstbx25.c +++ b/arch/ppc/platforms/4xx/ibmstbx25.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibmstbx25.c - * * Author: Armin Kuster * * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/ibmstbx25.h b/arch/ppc/platforms/4xx/ibmstbx25.h index 9a2efc366e9c..6884a49d3482 100644 --- a/arch/ppc/platforms/4xx/ibmstbx25.h +++ b/arch/ppc/platforms/4xx/ibmstbx25.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibmstbx25.h - * * Author: Armin Kuster * * 2002 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/luan.c b/arch/ppc/platforms/4xx/luan.c index 21d29132aebd..5c37de28e135 100644 --- a/arch/ppc/platforms/4xx/luan.c +++ b/arch/ppc/platforms/4xx/luan.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/luan.c - * * Luan board specific routines * * Matt Porter diff --git a/arch/ppc/platforms/4xx/luan.h b/arch/ppc/platforms/4xx/luan.h index bbe7d0766db8..e0db6a810feb 100644 --- a/arch/ppc/platforms/4xx/luan.h +++ b/arch/ppc/platforms/4xx/luan.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/luan.h - * * Luan board definitions * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c index 4f355b6acab2..f841972f1fa9 100644 --- a/arch/ppc/platforms/4xx/ocotea.c +++ b/arch/ppc/platforms/4xx/ocotea.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ocotea.c - * * Ocotea board specific routines * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ocotea.h b/arch/ppc/platforms/4xx/ocotea.h index 33251153ac5f..7c799a9ff82b 100644 --- a/arch/ppc/platforms/4xx/ocotea.h +++ b/arch/ppc/platforms/4xx/ocotea.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/ocotea.h - * * Ocotea board definitions * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ppc440spe.c b/arch/ppc/platforms/4xx/ppc440spe.c index 6139a0b3393e..1be5d1c8e266 100644 --- a/arch/ppc/platforms/4xx/ppc440spe.c +++ b/arch/ppc/platforms/4xx/ppc440spe.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ppc440spe.c - * * PPC440SPe I/O descriptions * * Roland Dreier diff --git a/arch/ppc/platforms/4xx/ppc440spe.h b/arch/ppc/platforms/4xx/ppc440spe.h index 2216846973b8..d3a620ddcdee 100644 --- a/arch/ppc/platforms/4xx/ppc440spe.h +++ b/arch/ppc/platforms/4xx/ppc440spe.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm440spe.h - * * PPC440SPe definitions * * Roland Dreier diff --git a/arch/ppc/platforms/4xx/redwood5.c b/arch/ppc/platforms/4xx/redwood5.c index 611ac861804d..53da2b4f7c24 100644 --- a/arch/ppc/platforms/4xx/redwood5.c +++ b/arch/ppc/platforms/4xx/redwood5.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/redwood5.c - * * Support for the IBM redwood5 eval board file * * Author: Armin Kuster diff --git a/arch/ppc/platforms/4xx/redwood5.h b/arch/ppc/platforms/4xx/redwood5.h index 264e34fb3fbd..49edd4818970 100644 --- a/arch/ppc/platforms/4xx/redwood5.h +++ b/arch/ppc/platforms/4xx/redwood5.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/redwood5.h - * * Macros, definitions, and data structures specific to the IBM PowerPC * STB03xxx "Redwood" evaluation board. * diff --git a/arch/ppc/platforms/4xx/redwood6.c b/arch/ppc/platforms/4xx/redwood6.c index b13116691289..41b27d106fa3 100644 --- a/arch/ppc/platforms/4xx/redwood6.c +++ b/arch/ppc/platforms/4xx/redwood6.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/redwood6.c - * * Author: Armin Kuster * * 2002 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/redwood6.h b/arch/ppc/platforms/4xx/redwood6.h index 1814b9f5fc3a..1edcbe5c51c7 100644 --- a/arch/ppc/platforms/4xx/redwood6.h +++ b/arch/ppc/platforms/4xx/redwood6.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/redwood6.h - * * Macros, definitions, and data structures specific to the IBM PowerPC * STBx25xx "Redwood6" evaluation board. * diff --git a/arch/ppc/platforms/4xx/sycamore.c b/arch/ppc/platforms/4xx/sycamore.c index 281b4a2ffb96..bab31eb30687 100644 --- a/arch/ppc/platforms/4xx/sycamore.c +++ b/arch/ppc/platforms/4xx/sycamore.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/sycamore.c - * * Architecture- / platform-specific boot-time initialization code for * IBM PowerPC 4xx based boards. * diff --git a/arch/ppc/platforms/4xx/sycamore.h b/arch/ppc/platforms/4xx/sycamore.h index 1cd6c824fd62..dae01620227d 100644 --- a/arch/ppc/platforms/4xx/sycamore.h +++ b/arch/ppc/platforms/4xx/sycamore.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/sycamore.h - * * Sycamore board definitions * * Copyright (c) 2005 DENX Software Engineering diff --git a/arch/ppc/platforms/4xx/walnut.c b/arch/ppc/platforms/4xx/walnut.c index 74cb33182d9f..6bd77902b9a4 100644 --- a/arch/ppc/platforms/4xx/walnut.c +++ b/arch/ppc/platforms/4xx/walnut.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/walnut.c - * * Architecture- / platform-specific boot-time initialization code for * IBM PowerPC 4xx based boards. Adapted from original * code by Gary Thomas, Cort Dougan , and Dan Malek diff --git a/arch/ppc/platforms/4xx/walnut.h b/arch/ppc/platforms/4xx/walnut.h index dcf2691698c0..f13a577f0a41 100644 --- a/arch/ppc/platforms/4xx/walnut.h +++ b/arch/ppc/platforms/4xx/walnut.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/walnut.h - * * Walnut board definitions * * Copyright (c) 2005 DENX Software Engineering diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.c b/arch/ppc/platforms/4xx/xilinx_ml300.c index 267afb50607e..d97a7f269f97 100644 --- a/arch/ppc/platforms/4xx/xilinx_ml300.c +++ b/arch/ppc/platforms/4xx/xilinx_ml300.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/xilinx_ml300.c - * * Xilinx ML300 evaluation board initialization * * Author: MontaVista Software, Inc. diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.h b/arch/ppc/platforms/4xx/xilinx_ml300.h index ae8bf1353b01..3d57332ba820 100644 --- a/arch/ppc/platforms/4xx/xilinx_ml300.h +++ b/arch/ppc/platforms/4xx/xilinx_ml300.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/xilinx_ml300.h - * * Include file that defines the Xilinx ML300 evaluation board * * Author: MontaVista Software, Inc. diff --git a/arch/ppc/platforms/4xx/yucca.c b/arch/ppc/platforms/4xx/yucca.c index b065b8babcd3..f287dcdbffce 100644 --- a/arch/ppc/platforms/4xx/yucca.c +++ b/arch/ppc/platforms/4xx/yucca.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/yucca.c - * * Yucca board specific routines * * Roland Dreier (based on luan.c by Matt Porter) diff --git a/arch/ppc/platforms/4xx/yucca.h b/arch/ppc/platforms/4xx/yucca.h index 01a4afea1514..7ae23012237a 100644 --- a/arch/ppc/platforms/4xx/yucca.h +++ b/arch/ppc/platforms/4xx/yucca.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/yucca.h - * * Yucca board definitions * * Roland Dreier (based on luan.h by Matt Porter) diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c index 1a659bbc1860..11626dd9090f 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.c +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/83xx/mpc834x_sys.c - * * MPC834x SYS board specific routines * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h b/arch/ppc/platforms/83xx/mpc834x_sys.h index 2e514d316fb8..aa86c22cdd25 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.h +++ b/arch/ppc/platforms/83xx/mpc834x_sys.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/83xx/mpc834x_sys.h - * * MPC834X SYS common board definitions * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c index 408d64f18e1a..9b014df516b9 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.c +++ b/arch/ppc/platforms/85xx/mpc8540_ads.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/mpc8540_ads.c - * * MPC8540ADS board specific routines * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.h b/arch/ppc/platforms/85xx/mpc8540_ads.h index e48ca3a97397..0b5e7ff856f5 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.h +++ b/arch/ppc/platforms/85xx/mpc8540_ads.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/mpc8540_ads.h - * * MPC8540ADS board definitions * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/mpc8555_cds.h b/arch/ppc/platforms/85xx/mpc8555_cds.h index 1a8e6c67355d..9754dbd5d18c 100644 --- a/arch/ppc/platforms/85xx/mpc8555_cds.h +++ b/arch/ppc/platforms/85xx/mpc8555_cds.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/mpc8555_cds.h - * * MPC8555CDS board definitions * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c index 442c7ff195d3..0cb2e86470e2 100644 --- a/arch/ppc/platforms/85xx/mpc8560_ads.c +++ b/arch/ppc/platforms/85xx/mpc8560_ads.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/mpc8560_ads.c - * * MPC8560ADS board specific routines * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.h b/arch/ppc/platforms/85xx/mpc8560_ads.h index 143ae7eefa7c..c2247c21fc53 100644 --- a/arch/ppc/platforms/85xx/mpc8560_ads.h +++ b/arch/ppc/platforms/85xx/mpc8560_ads.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/mpc8560_ads.h - * * MPC8540ADS board definitions * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c index 17ce48fe3503..8fd9d763f58d 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/mpc85xx_ads_common.c - * * MPC85xx ADS board common routines * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h index 198a6a02cde8..de8d41aafe11 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/mpc85xx_ads_common.h - * * MPC85XX ADS common board definitions * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index 1801ab392e22..c9e0aeeca3d8 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platform/85xx/mpc85xx_cds_common.c - * * MPC85xx CDS board specific routines * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h index 5b588cfd0e41..62df54f61ae3 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/mpc85xx_cds_common.h - * * MPC85xx CDS board definitions * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c index 8a72221f816c..b73778ecf827 100644 --- a/arch/ppc/platforms/85xx/sbc8560.c +++ b/arch/ppc/platforms/85xx/sbc8560.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/sbc8560.c - * * Wind River SBC8560 board specific routines * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/sbc8560.h b/arch/ppc/platforms/85xx/sbc8560.h index 5e1b00c77da5..44ffaa2d2c87 100644 --- a/arch/ppc/platforms/85xx/sbc8560.h +++ b/arch/ppc/platforms/85xx/sbc8560.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/sbc8560.h - * * Wind River SBC8560 board definitions * * Copyright 2003 Motorola Inc. diff --git a/arch/ppc/platforms/85xx/sbc85xx.c b/arch/ppc/platforms/85xx/sbc85xx.c index c02f110219f5..d3ff280510ff 100644 --- a/arch/ppc/platforms/85xx/sbc85xx.c +++ b/arch/ppc/platforms/85xx/sbc85xx.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platform/85xx/sbc85xx.c - * * WindRiver PowerQUICC III SBC85xx board common routines * * Copyright 2002, 2003 Motorola Inc. diff --git a/arch/ppc/platforms/85xx/sbc85xx.h b/arch/ppc/platforms/85xx/sbc85xx.h index 7af93c691a6b..5dd8b6a98c9b 100644 --- a/arch/ppc/platforms/85xx/sbc85xx.h +++ b/arch/ppc/platforms/85xx/sbc85xx.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/sbc85xx.h - * * WindRiver PowerQUICC III SBC85xx common board definitions * * Copyright 2003 Motorola Inc. diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c index 061bb7cf2d9a..8d7baa9a397a 100644 --- a/arch/ppc/platforms/85xx/stx_gp3.c +++ b/arch/ppc/platforms/85xx/stx_gp3.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/stx_gp3.c - * * STx GP3 board specific routines * * Dan Malek diff --git a/arch/ppc/platforms/85xx/stx_gp3.h b/arch/ppc/platforms/85xx/stx_gp3.h index 2f25b5195152..3f71f8f59370 100644 --- a/arch/ppc/platforms/85xx/stx_gp3.h +++ b/arch/ppc/platforms/85xx/stx_gp3.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/stx8560_gp3.h - * * STx GP3 board definitions * * Dan Malek (dan@embeddededge.com) diff --git a/arch/ppc/platforms/85xx/tqm85xx.c b/arch/ppc/platforms/85xx/tqm85xx.c index a5e38ba62732..00af132262b3 100644 --- a/arch/ppc/platforms/85xx/tqm85xx.c +++ b/arch/ppc/platforms/85xx/tqm85xx.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/tqm85xx.c - * * TQM85xx (40/41/55/60) board specific routines * * Copyright (c) 2005 DENX Software Engineering diff --git a/arch/ppc/platforms/85xx/tqm85xx.h b/arch/ppc/platforms/85xx/tqm85xx.h index 3775eb363fde..612d80504f9b 100644 --- a/arch/ppc/platforms/85xx/tqm85xx.h +++ b/arch/ppc/platforms/85xx/tqm85xx.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/tqm85xx.h - * * TQM85xx (40/41/55/60) board definitions * * Copyright (c) 2005 DENX Software Engineering diff --git a/arch/ppc/platforms/apus_setup.c b/arch/ppc/platforms/apus_setup.c index c42c50073da5..fe0cdc04d436 100644 --- a/arch/ppc/platforms/apus_setup.c +++ b/arch/ppc/platforms/apus_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/apus_setup.c - * * Copyright (C) 1998, 1999 Jesper Skov * * Basically what is needed to replace functionality found in diff --git a/arch/ppc/platforms/chestnut.c b/arch/ppc/platforms/chestnut.c index aefcc0e7be57..f324f757cae1 100644 --- a/arch/ppc/platforms/chestnut.c +++ b/arch/ppc/platforms/chestnut.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/chestnut.c - * * Board setup routines for IBM Chestnut * * Author: diff --git a/arch/ppc/platforms/chestnut.h b/arch/ppc/platforms/chestnut.h index 0400b2be40ab..e00fd9f8bbd0 100644 --- a/arch/ppc/platforms/chestnut.h +++ b/arch/ppc/platforms/chestnut.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/chestnut.h - * * Definitions for IBM 750FXGX Eval (Chestnut) * * Author: diff --git a/arch/ppc/platforms/chrp_pegasos_eth.c b/arch/ppc/platforms/chrp_pegasos_eth.c index 108a6e265185..9305c8aa1373 100644 --- a/arch/ppc/platforms/chrp_pegasos_eth.c +++ b/arch/ppc/platforms/chrp_pegasos_eth.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/chrp_pegasos_eth.c - * * Copyright (C) 2005 Sven Luther * Thanks to : * Dale Farnsworth diff --git a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c index 48996b787378..f9fd3f4f8e2e 100644 --- a/arch/ppc/platforms/chrp_setup.c +++ b/arch/ppc/platforms/chrp_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/setup.c - * * Copyright (C) 1995 Linus Torvalds * Adapted from 'alpha' version by Gary Thomas * Modified by Cort Dougan (cort@cs.nmt.edu) diff --git a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c index 57753a55b580..c8627770af13 100644 --- a/arch/ppc/platforms/chrp_time.c +++ b/arch/ppc/platforms/chrp_time.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/chrp_time.c - * * Copyright (C) 1991, 1992, 1995 Linus Torvalds * * Adapted for PowerPC (PReP) by Gary Thomas diff --git a/arch/ppc/platforms/cpci690.c b/arch/ppc/platforms/cpci690.c index 6ca7bcac9474..55be550a0811 100644 --- a/arch/ppc/platforms/cpci690.c +++ b/arch/ppc/platforms/cpci690.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/cpci690.c - * * Board setup routines for the Force CPCI690 board. * * Author: Mark A. Greer diff --git a/arch/ppc/platforms/cpci690.h b/arch/ppc/platforms/cpci690.h index 49584c9cedf3..0fa5a4c31b67 100644 --- a/arch/ppc/platforms/cpci690.h +++ b/arch/ppc/platforms/cpci690.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/cpci690.h - * * Definitions for Force CPCI690 * * Author: Mark A. Greer diff --git a/arch/ppc/platforms/ev64260.c b/arch/ppc/platforms/ev64260.c index ffde8f6f6302..6444760caa3a 100644 --- a/arch/ppc/platforms/ev64260.c +++ b/arch/ppc/platforms/ev64260.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/ev64260.c - * * Board setup routines for the Marvell/Galileo EV-64260-BP Evaluation Board. * * Author: Mark A. Greer diff --git a/arch/ppc/platforms/ev64260.h b/arch/ppc/platforms/ev64260.h index bedffced3a02..44d90d56745a 100644 --- a/arch/ppc/platforms/ev64260.h +++ b/arch/ppc/platforms/ev64260.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/ev64260.h - * * Definitions for Marvell/Galileo EV-64260-BP Evaluation Board. * * Author: Mark A. Greer diff --git a/arch/ppc/platforms/ev64360.c b/arch/ppc/platforms/ev64360.c index b9d844f88c2b..b5f52eba4fc1 100644 --- a/arch/ppc/platforms/ev64360.c +++ b/arch/ppc/platforms/ev64360.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/ev64360.c - * * Board setup routines for the Marvell EV-64360-BP Evaluation Board. * * Author: Lee Nicks diff --git a/arch/ppc/platforms/ev64360.h b/arch/ppc/platforms/ev64360.h index 68eabe490397..b30f4722690a 100644 --- a/arch/ppc/platforms/ev64360.h +++ b/arch/ppc/platforms/ev64360.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/ev64360.h - * * Definitions for Marvell EV-64360-BP Evaluation Board. * * Author: Lee Nicks diff --git a/arch/ppc/platforms/gemini.h b/arch/ppc/platforms/gemini.h index 06de59248918..5528fd0a1216 100644 --- a/arch/ppc/platforms/gemini.h +++ b/arch/ppc/platforms/gemini.h @@ -1,7 +1,4 @@ /* - * arch/ppc/platforms/gemini.h - * - * * Onboard registers and descriptions for Synergy Microsystems' * "Gemini" boards. * diff --git a/arch/ppc/platforms/gemini_prom.S b/arch/ppc/platforms/gemini_prom.S index 8c5065d56505..b181f2108001 100644 --- a/arch/ppc/platforms/gemini_prom.S +++ b/arch/ppc/platforms/gemini_prom.S @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/gemini_prom.S - * * Not really prom support code (yet), but sort of anti-prom code. The current * bootloader does a number of things it shouldn't and doesn't do things that it * should. The stuff in here is mainly a hodge-podge collection of setup code diff --git a/arch/ppc/platforms/gemini_setup.c b/arch/ppc/platforms/gemini_setup.c index 729897c59033..0090ff154608 100644 --- a/arch/ppc/platforms/gemini_setup.c +++ b/arch/ppc/platforms/gemini_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/gemini_setup.c - * * Copyright (C) 1995 Linus Torvalds * Adapted from 'alpha' version by Gary Thomas * Modified by Cort Dougan (cort@cs.nmt.edu) diff --git a/arch/ppc/platforms/hdpu.c b/arch/ppc/platforms/hdpu.c index 50039a204c24..220674d883df 100644 --- a/arch/ppc/platforms/hdpu.c +++ b/arch/ppc/platforms/hdpu.c @@ -1,7 +1,4 @@ - /* - * arch/ppc/platforms/hdpu_setup.c - * * Board setup routines for the Sky Computers HDPU Compute Blade. * * Written by Brian Waite diff --git a/arch/ppc/platforms/hdpu.h b/arch/ppc/platforms/hdpu.h index 07c3cffb5c7b..f9e020b6970c 100644 --- a/arch/ppc/platforms/hdpu.h +++ b/arch/ppc/platforms/hdpu.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/hdpu.h - * * Definitions for Sky Computers HDPU board. * * Brian Waite diff --git a/arch/ppc/platforms/katana.c b/arch/ppc/platforms/katana.c index 6e58e30ceed1..d2766617c3cb 100644 --- a/arch/ppc/platforms/katana.c +++ b/arch/ppc/platforms/katana.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/katana.c - * * Board setup routines for the Artesyn Katana cPCI boards. * * Author: Tim Montgomery diff --git a/arch/ppc/platforms/katana.h b/arch/ppc/platforms/katana.h index 597257eff2ec..0a9b036526b1 100644 --- a/arch/ppc/platforms/katana.h +++ b/arch/ppc/platforms/katana.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/katana.h - * * Definitions for Artesyn Katana750i/3750 board. * * Author: Tim Montgomery diff --git a/arch/ppc/platforms/lite5200.c b/arch/ppc/platforms/lite5200.c index 7ed52dc340c9..5171b53bccb5 100644 --- a/arch/ppc/platforms/lite5200.c +++ b/arch/ppc/platforms/lite5200.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/lite5200.c - * * Platform support file for the Freescale LITE5200 based on MPC52xx. * A maximum of this file should be moved to syslib/mpc52xx_????? * so that new platform based on MPC52xx need a minimal platform file diff --git a/arch/ppc/platforms/lite5200.h b/arch/ppc/platforms/lite5200.h index c1de2aa47175..852a18e24d0b 100644 --- a/arch/ppc/platforms/lite5200.h +++ b/arch/ppc/platforms/lite5200.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/lite5200.h - * * Definitions for Freescale LITE5200 : MPC52xx Standard Development * Platform board support * diff --git a/arch/ppc/platforms/lopec.c b/arch/ppc/platforms/lopec.c index 06d247c23b82..c6445a727ca3 100644 --- a/arch/ppc/platforms/lopec.c +++ b/arch/ppc/platforms/lopec.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/lopec.c - * * Setup routines for the Motorola LoPEC. * * Author: Dan Cox diff --git a/arch/ppc/platforms/mvme5100.c b/arch/ppc/platforms/mvme5100.c index 108eb182dddc..c717cd92c028 100644 --- a/arch/ppc/platforms/mvme5100.c +++ b/arch/ppc/platforms/mvme5100.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/mvme5100.c - * * Board setup routines for the Motorola MVME5100. * * Author: Matt Porter diff --git a/arch/ppc/platforms/pal4.h b/arch/ppc/platforms/pal4.h index 641a11a31657..8569c423d887 100644 --- a/arch/ppc/platforms/pal4.h +++ b/arch/ppc/platforms/pal4.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pal4.h - * * Definitions for SBS Palomar IV board * * Author: Dan Cox diff --git a/arch/ppc/platforms/pal4_pci.c b/arch/ppc/platforms/pal4_pci.c index c3b1b757a48b..d81ae1c7e1cf 100644 --- a/arch/ppc/platforms/pal4_pci.c +++ b/arch/ppc/platforms/pal4_pci.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pal4_pci.c - * * PCI support for SBS Palomar IV * * Author: Dan Cox diff --git a/arch/ppc/platforms/pal4_serial.h b/arch/ppc/platforms/pal4_serial.h index a715c66e1adf..a75343224cfd 100644 --- a/arch/ppc/platforms/pal4_serial.h +++ b/arch/ppc/platforms/pal4_serial.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pal4_serial.h - * * Definitions for SBS PalomarIV serial support * * Author: Dan Cox diff --git a/arch/ppc/platforms/pal4_setup.c b/arch/ppc/platforms/pal4_setup.c index f93a3f871932..3c3d881df00d 100644 --- a/arch/ppc/platforms/pal4_setup.c +++ b/arch/ppc/platforms/pal4_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pal4_setup.c - * * Board setup routines for the SBS PalomarIV. * * Author: Dan Cox diff --git a/arch/ppc/platforms/powerpmc250.c b/arch/ppc/platforms/powerpmc250.c index e6b520e6e13f..c3a86be11fb7 100644 --- a/arch/ppc/platforms/powerpmc250.c +++ b/arch/ppc/platforms/powerpmc250.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/powerpmc250.c - * * Board setup routines for Force PowerPMC-250 Processor PMC * * Author: Troy Benjegerdes diff --git a/arch/ppc/platforms/pplus.c b/arch/ppc/platforms/pplus.c index 22bd40cfb092..de2761ebe0d9 100644 --- a/arch/ppc/platforms/pplus.c +++ b/arch/ppc/platforms/pplus.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pplus.c - * * Board and PCI setup routines for MCG PowerPlus * * Author: Randy Vinson diff --git a/arch/ppc/platforms/pplus.h b/arch/ppc/platforms/pplus.h index 90f0cb2d409f..a07cbbdd72c6 100644 --- a/arch/ppc/platforms/pplus.h +++ b/arch/ppc/platforms/pplus.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pplus.h - * * Definitions for Motorola MCG Falcon/Raven & HAWK North Bridge & Memory ctlr. * * Author: Mark A. Greerinclude/asm-ppc/hawk.h diff --git a/arch/ppc/platforms/pq2ads.c b/arch/ppc/platforms/pq2ads.c index 71c9fca1fe9b..3365fd788a7a 100644 --- a/arch/ppc/platforms/pq2ads.c +++ b/arch/ppc/platforms/pq2ads.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pq2ads.c - * * PQ2ADS platform support * * Author: Kumar Gala diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c index d06535802003..a0fc628ffb1e 100644 --- a/arch/ppc/platforms/prep_setup.c +++ b/arch/ppc/platforms/prep_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/setup.c - * * Copyright (C) 1995 Linus Torvalds * Adapted from 'alpha' version by Gary Thomas * Modified by Cort Dougan (cort@cs.nmt.edu) diff --git a/arch/ppc/platforms/prpmc750.c b/arch/ppc/platforms/prpmc750.c index 0bb14a5e824c..cdd9cfb13ee9 100644 --- a/arch/ppc/platforms/prpmc750.c +++ b/arch/ppc/platforms/prpmc750.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/prpmc750_setup.c - * * Board setup routines for Motorola PrPMC750 * * Author: Matt Porter diff --git a/arch/ppc/platforms/prpmc800.c b/arch/ppc/platforms/prpmc800.c index de7baefacd3a..e459a199fb1d 100644 --- a/arch/ppc/platforms/prpmc800.c +++ b/arch/ppc/platforms/prpmc800.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/prpmc800.c - * * Author: Dale Farnsworth * * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c index 872c0a3ba3c7..1b1e7c5ef152 100644 --- a/arch/ppc/platforms/radstone_ppc7d.c +++ b/arch/ppc/platforms/radstone_ppc7d.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/radstone_ppc7d.c - * * Board setup routines for the Radstone PPC7D boards. * * Author: James Chapman diff --git a/arch/ppc/platforms/radstone_ppc7d.h b/arch/ppc/platforms/radstone_ppc7d.h index 938375510be4..2bb093a0c03e 100644 --- a/arch/ppc/platforms/radstone_ppc7d.h +++ b/arch/ppc/platforms/radstone_ppc7d.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/radstone_ppc7d.h - * * Board definitions for the Radstone PPC7D boards. * * Author: James Chapman diff --git a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c index 9eeed3572309..6dc459decb2d 100644 --- a/arch/ppc/platforms/sandpoint.c +++ b/arch/ppc/platforms/sandpoint.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/sandpoint_setup.c - * * Board setup routines for the Motorola SPS Sandpoint Test Platform. * * Author: Mark A. Greer diff --git a/arch/ppc/platforms/sandpoint.h b/arch/ppc/platforms/sandpoint.h index f4e982cb69df..3b64e6418489 100644 --- a/arch/ppc/platforms/sandpoint.h +++ b/arch/ppc/platforms/sandpoint.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/sandpoint.h - * * Definitions for Motorola SPS Sandpoint Test Platform * * Author: Mark A. Greer diff --git a/arch/ppc/platforms/sbc82xx.c b/arch/ppc/platforms/sbc82xx.c index 74c9ff72c3dd..866807b4ad0b 100644 --- a/arch/ppc/platforms/sbc82xx.c +++ b/arch/ppc/platforms/sbc82xx.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/sbc82xx.c - * * SBC82XX platform support * * Author: Guy Streeter diff --git a/arch/ppc/platforms/spruce.c b/arch/ppc/platforms/spruce.c index 69e1de7971f2..3783deccd9b2 100644 --- a/arch/ppc/platforms/spruce.c +++ b/arch/ppc/platforms/spruce.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/spruce.c - * * Board and PCI setup routines for IBM Spruce * * Author: MontaVista Software diff --git a/arch/ppc/platforms/tqm8260_setup.c b/arch/ppc/platforms/tqm8260_setup.c index 3409139330b1..b766339f44ac 100644 --- a/arch/ppc/platforms/tqm8260_setup.c +++ b/arch/ppc/platforms/tqm8260_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/tqm8260_setup.c - * * TQM8260 platform support * * Author: Allen Curtis diff --git a/arch/ppc/syslib/cpc700.h b/arch/ppc/syslib/cpc700.h index f2c002531019..0a8a5d84390f 100644 --- a/arch/ppc/syslib/cpc700.h +++ b/arch/ppc/syslib/cpc700.h @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/cpc700.h - * * Header file for IBM CPC700 Host Bridge, et. al. * * Author: Mark A. Greer diff --git a/arch/ppc/syslib/cpc700_pic.c b/arch/ppc/syslib/cpc700_pic.c index 75fe8eb10693..5add0a919ef6 100644 --- a/arch/ppc/syslib/cpc700_pic.c +++ b/arch/ppc/syslib/cpc700_pic.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/cpc700_pic.c - * * Interrupt controller support for IBM Spruce * * Authors: Mark Greer, Matt Porter, and Johnnie Peters diff --git a/arch/ppc/syslib/cpc710.h b/arch/ppc/syslib/cpc710.h index cc0afd804029..5299bf8b5d01 100644 --- a/arch/ppc/syslib/cpc710.h +++ b/arch/ppc/syslib/cpc710.h @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/cpc710.h - * * Definitions for the IBM CPC710 PCI Host Bridge * * Author: Matt Porter diff --git a/arch/ppc/syslib/gen550.h b/arch/ppc/syslib/gen550.h index 039d249e19a8..5254d3cdbca6 100644 --- a/arch/ppc/syslib/gen550.h +++ b/arch/ppc/syslib/gen550.h @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/gen550.h - * * gen550 prototypes * * Matt Porter diff --git a/arch/ppc/syslib/gen550_dbg.c b/arch/ppc/syslib/gen550_dbg.c index 9ef0113c83d1..9fcff74bfdd0 100644 --- a/arch/ppc/syslib/gen550_dbg.c +++ b/arch/ppc/syslib/gen550_dbg.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/gen550_dbg.c - * * A library of polled 16550 serial routines. These are intended to * be used to support progress messages, xmon, kgdb, etc. on a * variety of platforms. diff --git a/arch/ppc/syslib/gen550_kgdb.c b/arch/ppc/syslib/gen550_kgdb.c index 7239d5d7ddcd..874078a7664d 100644 --- a/arch/ppc/syslib/gen550_kgdb.c +++ b/arch/ppc/syslib/gen550_kgdb.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/gen550_kgdb.c - * * Generic 16550 kgdb support intended to be useful on a variety * of platforms. To enable this support, it is necessary to set * the CONFIG_GEN550 option. Any virtual mapping of the serial diff --git a/arch/ppc/syslib/gt64260_pic.c b/arch/ppc/syslib/gt64260_pic.c index f97b3a9abd1e..dc3bd9ecbbf6 100644 --- a/arch/ppc/syslib/gt64260_pic.c +++ b/arch/ppc/syslib/gt64260_pic.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/gt64260_pic.c - * * Interrupt controller support for Galileo's GT64260. * * Author: Chris Zankel diff --git a/arch/ppc/syslib/harrier.c b/arch/ppc/syslib/harrier.c index a6b3f8645793..c1583f488325 100644 --- a/arch/ppc/syslib/harrier.c +++ b/arch/ppc/syslib/harrier.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/harrier.c - * * Motorola MCG Harrier northbridge/memory controller support * * Author: Dale Farnsworth diff --git a/arch/ppc/syslib/hawk_common.c b/arch/ppc/syslib/hawk_common.c index a9911dc3a82f..c5bf16b0d6a1 100644 --- a/arch/ppc/syslib/hawk_common.c +++ b/arch/ppc/syslib/hawk_common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/hawk_common.c - * * Common Motorola PowerPlus Platform--really Falcon/Raven or HAWK. * * Author: Mark A. Greer diff --git a/arch/ppc/syslib/ibm440gp_common.c b/arch/ppc/syslib/ibm440gp_common.c index 0d6be2d6dd67..fbaae5f6d834 100644 --- a/arch/ppc/syslib/ibm440gp_common.c +++ b/arch/ppc/syslib/ibm440gp_common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ibm440gp_common.c - * * PPC440GP system library * * Matt Porter diff --git a/arch/ppc/syslib/ibm440gp_common.h b/arch/ppc/syslib/ibm440gp_common.h index a054d83cb1ac..f48529f3c23d 100644 --- a/arch/ppc/syslib/ibm440gp_common.h +++ b/arch/ppc/syslib/ibm440gp_common.h @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/ibm440gp_common.h - * * PPC440GP system library * * Eugene Surovegin or diff --git a/arch/ppc/syslib/ibm440gx_common.c b/arch/ppc/syslib/ibm440gx_common.c index c36db279b43d..a7dd55f1c63e 100644 --- a/arch/ppc/syslib/ibm440gx_common.c +++ b/arch/ppc/syslib/ibm440gx_common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/ibm440gx_common.c - * * PPC440GX system library * * Eugene Surovegin or diff --git a/arch/ppc/syslib/ibm440gx_common.h b/arch/ppc/syslib/ibm440gx_common.h index e73aa0411d35..a2ab9fab8e34 100644 --- a/arch/ppc/syslib/ibm440gx_common.h +++ b/arch/ppc/syslib/ibm440gx_common.h @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/ibm440gx_common.h - * * PPC440GX system library * * Eugene Surovegin or diff --git a/arch/ppc/syslib/ibm440sp_common.c b/arch/ppc/syslib/ibm440sp_common.c index cdafda127d81..293e4138d172 100644 --- a/arch/ppc/syslib/ibm440sp_common.c +++ b/arch/ppc/syslib/ibm440sp_common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ibm440sp_common.c - * * PPC440SP/PPC440SPe system library * * Matt Porter diff --git a/arch/ppc/syslib/ibm440sp_common.h b/arch/ppc/syslib/ibm440sp_common.h index a21a9906dcc9..8077bf8ed118 100644 --- a/arch/ppc/syslib/ibm440sp_common.h +++ b/arch/ppc/syslib/ibm440sp_common.h @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ibm440sp_common.h - * * PPC440SP system library * * Matt Porter diff --git a/arch/ppc/syslib/ibm44x_common.c b/arch/ppc/syslib/ibm44x_common.c index 71db11d22158..14a981a5cea7 100644 --- a/arch/ppc/syslib/ibm44x_common.c +++ b/arch/ppc/syslib/ibm44x_common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ibm44x_common.c - * * PPC44x system library * * Matt Porter diff --git a/arch/ppc/syslib/ibm44x_common.h b/arch/ppc/syslib/ibm44x_common.h index b25a8995e4e9..f179db8634e0 100644 --- a/arch/ppc/syslib/ibm44x_common.h +++ b/arch/ppc/syslib/ibm44x_common.h @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/ibm44x_common.h - * * PPC44x system library * * Eugene Surovegin or diff --git a/arch/ppc/syslib/m8260_pci_erratum9.c b/arch/ppc/syslib/m8260_pci_erratum9.c index 1dc7e4e1d491..99e4bc0e42af 100644 --- a/arch/ppc/syslib/m8260_pci_erratum9.c +++ b/arch/ppc/syslib/m8260_pci_erratum9.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/mpc8260_pci9.c - * * Workaround for device erratum PCI 9. * See Motorola's "XPC826xA Family Device Errata Reference." * The erratum applies to all 8260 family Hip4 processors. It is scheduled diff --git a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c index 76a2aa4ce65e..b7a6cb2d8d52 100644 --- a/arch/ppc/syslib/m8260_setup.c +++ b/arch/ppc/syslib/m8260_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/m8260_setup.c - * * Copyright (C) 1995 Linus Torvalds * Adapted from 'alpha' version by Gary Thomas * Modified by Cort Dougan (cort@cs.nmt.edu) diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c index cdb73a23a538..dae9af78bde1 100644 --- a/arch/ppc/syslib/m8xx_setup.c +++ b/arch/ppc/syslib/m8xx_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/setup.c - * * Copyright (C) 1995 Linus Torvalds * Adapted from 'alpha' version by Gary Thomas * Modified by Cort Dougan (cort@cs.nmt.edu) diff --git a/arch/ppc/syslib/mpc10x_common.c b/arch/ppc/syslib/mpc10x_common.c index 3e039706bdbc..2fc7c4150a18 100644 --- a/arch/ppc/syslib/mpc10x_common.c +++ b/arch/ppc/syslib/mpc10x_common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mpc10x_common.c - * * Common routines for the Motorola SPS MPC106, MPC107 and MPC8240 Host bridge, * Mem ctlr, EPIC, etc. * diff --git a/arch/ppc/syslib/mpc52xx_devices.c b/arch/ppc/syslib/mpc52xx_devices.c index da3c74bfdc92..7487539a4e92 100644 --- a/arch/ppc/syslib/mpc52xx_devices.c +++ b/arch/ppc/syslib/mpc52xx_devices.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mpc52xx_devices.c - * * Freescale MPC52xx device descriptions * * diff --git a/arch/ppc/syslib/mpc52xx_pci.c b/arch/ppc/syslib/mpc52xx_pci.c index 313c96ec7eb1..9ec525f9fe98 100644 --- a/arch/ppc/syslib/mpc52xx_pci.c +++ b/arch/ppc/syslib/mpc52xx_pci.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mpc52xx_pci.c - * * PCI code for the Freescale MPC52xx embedded CPU. * * diff --git a/arch/ppc/syslib/mpc52xx_pci.h b/arch/ppc/syslib/mpc52xx_pci.h index 04b509a02530..77d47dbba85e 100644 --- a/arch/ppc/syslib/mpc52xx_pci.h +++ b/arch/ppc/syslib/mpc52xx_pci.h @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mpc52xx_pci.h - * * PCI Include file the Freescale MPC52xx embedded cpu chips * * diff --git a/arch/ppc/syslib/mpc52xx_pic.c b/arch/ppc/syslib/mpc52xx_pic.c index 4c4497e62517..c4406f9dc6a3 100644 --- a/arch/ppc/syslib/mpc52xx_pic.c +++ b/arch/ppc/syslib/mpc52xx_pic.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mpc52xx_pic.c - * * Programmable Interrupt Controller functions for the Freescale MPC52xx * embedded CPU. * diff --git a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c index a4a4b02227df..2ee48ce0a517 100644 --- a/arch/ppc/syslib/mpc52xx_setup.c +++ b/arch/ppc/syslib/mpc52xx_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mpc52xx_setup.c - * * Common code for the boards based on Freescale MPC52xx embedded CPU. * * diff --git a/arch/ppc/syslib/mpc52xx_sys.c b/arch/ppc/syslib/mpc52xx_sys.c index 9a0f90aa8aac..b4e6f978f057 100644 --- a/arch/ppc/syslib/mpc52xx_sys.c +++ b/arch/ppc/syslib/mpc52xx_sys.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mpc52xx_sys.c - * * Freescale MPC52xx system descriptions * * diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c index f9b95de70e23..1af2c000fcfa 100644 --- a/arch/ppc/syslib/mpc83xx_devices.c +++ b/arch/ppc/syslib/mpc83xx_devices.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/83xx/mpc83xx_devices.c - * * MPC83xx Device descriptions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/mpc83xx_sys.c b/arch/ppc/syslib/mpc83xx_sys.c index 82cf3ab77f4a..0498ae7e01e3 100644 --- a/arch/ppc/syslib/mpc83xx_sys.c +++ b/arch/ppc/syslib/mpc83xx_sys.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/83xx/mpc83xx_sys.c - * * MPC83xx System descriptions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c index 00e9b6ff2f6e..7735336f5b8f 100644 --- a/arch/ppc/syslib/mpc85xx_devices.c +++ b/arch/ppc/syslib/mpc85xx_devices.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/mpc85xx_devices.c - * * MPC85xx Device descriptions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/mpc85xx_sys.c b/arch/ppc/syslib/mpc85xx_sys.c index 397cfbcce5ea..d96a93dbcb5a 100644 --- a/arch/ppc/syslib/mpc85xx_sys.c +++ b/arch/ppc/syslib/mpc85xx_sys.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/mpc85xx_sys.c - * * MPC85xx System descriptions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/mpc8xx_devices.c b/arch/ppc/syslib/mpc8xx_devices.c index 92dc98b36bde..bd41ed83beb3 100644 --- a/arch/ppc/syslib/mpc8xx_devices.c +++ b/arch/ppc/syslib/mpc8xx_devices.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mpc8xx_devices.c - * * MPC8xx Device descriptions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/mpc8xx_sys.c b/arch/ppc/syslib/mpc8xx_sys.c index d3c617521603..eee213284855 100644 --- a/arch/ppc/syslib/mpc8xx_sys.c +++ b/arch/ppc/syslib/mpc8xx_sys.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/mpc8xx_sys.c - * * MPC8xx System descriptions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/mv64360_pic.c b/arch/ppc/syslib/mv64360_pic.c index 58b0aa813e85..5a19697060f0 100644 --- a/arch/ppc/syslib/mv64360_pic.c +++ b/arch/ppc/syslib/mv64360_pic.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/mv64360_pic.c - * * Interrupt controller support for Marvell's MV64360. * * Author: Rabeeh Khoury diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c index 1f01b7e2376b..3b039c30a439 100644 --- a/arch/ppc/syslib/mv64x60.c +++ b/arch/ppc/syslib/mv64x60.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mv64x60.c - * * Common routines for the Marvell/Galileo Discovery line of host bridges * (gt64260, mv64360, mv64460, ...). * diff --git a/arch/ppc/syslib/mv64x60_dbg.c b/arch/ppc/syslib/mv64x60_dbg.c index fa5b2e45e0ca..9cf18764a1a1 100644 --- a/arch/ppc/syslib/mv64x60_dbg.c +++ b/arch/ppc/syslib/mv64x60_dbg.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mv64x60_dbg.c - * * KGDB and progress routines for the Marvell/Galileo MV64x60 (Discovery). * * Author: Mark A. Greer diff --git a/arch/ppc/syslib/mv64x60_win.c b/arch/ppc/syslib/mv64x60_win.c index 5b827e2bbe22..4bf1ad17bf1a 100644 --- a/arch/ppc/syslib/mv64x60_win.c +++ b/arch/ppc/syslib/mv64x60_win.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mv64x60_win.c - * * Tables with info on how to manipulate the 32 & 64 bit windows on the * various types of Marvell bridge chips. * diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c index 894779712b46..38e5b93fbe41 100644 --- a/arch/ppc/syslib/open_pic.c +++ b/arch/ppc/syslib/open_pic.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling - * * Copyright (C) 1997 Geert Uytterhoeven * * This file is subject to the terms and conditions of the GNU General Public diff --git a/arch/ppc/syslib/open_pic2.c b/arch/ppc/syslib/open_pic2.c index 1c40049b9a45..bcbe40de26fe 100644 --- a/arch/ppc/syslib/open_pic2.c +++ b/arch/ppc/syslib/open_pic2.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling - * * Copyright (C) 1997 Geert Uytterhoeven * * This file is subject to the terms and conditions of the GNU General Public diff --git a/arch/ppc/syslib/open_pic_defs.h b/arch/ppc/syslib/open_pic_defs.h index 6c94e7131463..3a25de7cb572 100644 --- a/arch/ppc/syslib/open_pic_defs.h +++ b/arch/ppc/syslib/open_pic_defs.h @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/open_pic_defs.h -- OpenPIC definitions - * * Copyright (C) 1997 Geert Uytterhoeven * * This file is based on the following documentation: diff --git a/arch/ppc/syslib/pci_auto.c b/arch/ppc/syslib/pci_auto.c index d64207c2a972..ee20a86fcc4b 100644 --- a/arch/ppc/syslib/pci_auto.c +++ b/arch/ppc/syslib/pci_auto.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/pci_auto.c - * * PCI autoconfiguration library * * Author: Matt Porter diff --git a/arch/ppc/syslib/ppc4xx_dma.c b/arch/ppc/syslib/ppc4xx_dma.c index 05ccd598dd4e..b40b96a8c609 100644 --- a/arch/ppc/syslib/ppc4xx_dma.c +++ b/arch/ppc/syslib/ppc4xx_dma.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/ppc4xx_dma.c - * * IBM PPC4xx DMA engine core library * * Copyright 2000-2004 MontaVista Software Inc. diff --git a/arch/ppc/syslib/ppc4xx_pic.c b/arch/ppc/syslib/ppc4xx_pic.c index aa4165144ec2..fd9af0fc0e9f 100644 --- a/arch/ppc/syslib/ppc4xx_pic.c +++ b/arch/ppc/syslib/ppc4xx_pic.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ppc4xx_pic.c - * * Interrupt controller driver for PowerPC 4xx-based processors. * * Eugene Surovegin or diff --git a/arch/ppc/syslib/ppc4xx_sgdma.c b/arch/ppc/syslib/ppc4xx_sgdma.c index 9f76e8ee39ed..280ea010a9c8 100644 --- a/arch/ppc/syslib/ppc4xx_sgdma.c +++ b/arch/ppc/syslib/ppc4xx_sgdma.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/ppc4xx_sgdma.c - * * IBM PPC4xx DMA engine scatter/gather library * * Copyright 2002-2003 MontaVista Software Inc. diff --git a/arch/ppc/syslib/ppc83xx_setup.c b/arch/ppc/syslib/ppc83xx_setup.c index 7bada82527a8..26afd637dc81 100644 --- a/arch/ppc/syslib/ppc83xx_setup.c +++ b/arch/ppc/syslib/ppc83xx_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ppc83xx_setup.c - * * MPC83XX common board code * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/ppc83xx_setup.h b/arch/ppc/syslib/ppc83xx_setup.h index a122a7322e5e..478b011cd963 100644 --- a/arch/ppc/syslib/ppc83xx_setup.h +++ b/arch/ppc/syslib/ppc83xx_setup.h @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ppc83xx_setup.h - * * MPC83XX common board definitions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/ppc85xx_common.c b/arch/ppc/syslib/ppc85xx_common.c index 19ad537225e4..0145c968f9ad 100644 --- a/arch/ppc/syslib/ppc85xx_common.c +++ b/arch/ppc/syslib/ppc85xx_common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ppc85xx_common.c - * * MPC85xx support routines * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/ppc85xx_common.h b/arch/ppc/syslib/ppc85xx_common.h index 94edf32151dd..182744a1321c 100644 --- a/arch/ppc/syslib/ppc85xx_common.h +++ b/arch/ppc/syslib/ppc85xx_common.h @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ppc85xx_common.h - * * MPC85xx support routines * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c index e4dda43fdaa7..e70b34ee6275 100644 --- a/arch/ppc/syslib/ppc85xx_setup.c +++ b/arch/ppc/syslib/ppc85xx_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ppc85xx_setup.c - * * MPC85XX common board code * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/ppc85xx_setup.h b/arch/ppc/syslib/ppc85xx_setup.h index e340b0545fb5..f55b8032d3d9 100644 --- a/arch/ppc/syslib/ppc85xx_setup.h +++ b/arch/ppc/syslib/ppc85xx_setup.h @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ppc85xx_setup.h - * * MPC85XX common board definitions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c index 879783a41cfd..60c724e11584 100644 --- a/arch/ppc/syslib/ppc_sys.c +++ b/arch/ppc/syslib/ppc_sys.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ppc_sys.c - * * PPC System library functions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/pq2_devices.c b/arch/ppc/syslib/pq2_devices.c index 6ff3aab82fc3..0636aed7b827 100644 --- a/arch/ppc/syslib/pq2_devices.c +++ b/arch/ppc/syslib/pq2_devices.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/pq2_devices.c - * * PQ2 Device descriptions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/pq2_sys.c b/arch/ppc/syslib/pq2_sys.c index 36d6e2179940..75e64f1c144d 100644 --- a/arch/ppc/syslib/pq2_sys.c +++ b/arch/ppc/syslib/pq2_sys.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/pq2_devices.c - * * PQ2 System descriptions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/prep_nvram.c b/arch/ppc/syslib/prep_nvram.c index 2c6364d9641f..474dccbc4a8a 100644 --- a/arch/ppc/syslib/prep_nvram.c +++ b/arch/ppc/syslib/prep_nvram.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/prep_nvram.c - * * Copyright (C) 1998 Corey Minyard * * This reads the NvRAM on PReP compliant machines (generally from IBM or diff --git a/arch/ppc/syslib/todc_time.c b/arch/ppc/syslib/todc_time.c index 1323c641c19d..a8168b8e5683 100644 --- a/arch/ppc/syslib/todc_time.c +++ b/arch/ppc/syslib/todc_time.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/todc_time.c - * * Time of Day Clock support for the M48T35, M48T37, M48T59, and MC146818 * Real Time Clocks/Timekeepers. * diff --git a/arch/ppc/syslib/xilinx_pic.c b/arch/ppc/syslib/xilinx_pic.c index 848fb512f3f8..e672b600f315 100644 --- a/arch/ppc/syslib/xilinx_pic.c +++ b/arch/ppc/syslib/xilinx_pic.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/xilinx_pic.c - * * Interrupt controller driver for Xilinx Virtex-II Pro. * * Author: MontaVista Software, Inc. diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 831eb4e8d9d3..f7ac31856572 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c @@ -118,7 +118,7 @@ * the hvcs_final_close() function in order to get it out of the spinlock. * Rearranged hvcs_close(). Cleaned up some printks and did some housekeeping * on the changelog. Removed local CLC_LENGTH and used HVCS_CLC_LENGTH from - * arch/ppc64/hvcserver.h. + * include/asm-powerpc/hvcserver.h * * 1.3.2 -> 1.3.3 Replaced yield() in hvcs_close() with tty_wait_until_sent() to * prevent possible lockup with realtime scheduling as similarily pointed out by @@ -168,9 +168,10 @@ MODULE_VERSION(HVCS_DRIVER_VERSION); /* * The hcall interface involves putting 8 chars into each of two registers. - * We load up those 2 registers (in arch/ppc64/hvconsole.c) by casting char[16] - * to long[2]. It would work without __ALIGNED__, but a little (tiny) bit - * slower because an unaligned load is slower than aligned load. + * We load up those 2 registers (in arch/powerpc/platforms/pseries/hvconsole.c) + * by casting char[16] to long[2]. It would work without __ALIGNED__, but a + * little (tiny) bit slower because an unaligned load is slower than aligned + * load. */ #define __ALIGNED__ __attribute__((__aligned__(8))) diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h index c9add8f1ad94..ec94b51074fc 100644 --- a/include/asm-powerpc/paca.h +++ b/include/asm-powerpc/paca.h @@ -54,7 +54,7 @@ struct paca_struct { #endif /* CONFIG_PPC_ISERIES */ /* - * MAGIC: the spinlock functions in arch/ppc64/lib/locks.c + * MAGIC: the spinlock functions in arch/powerpc/lib/locks.c * load lock_token and paca_index with a single lwz * instruction. They must travel together and be properly * aligned. diff --git a/include/asm-powerpc/rwsem.h b/include/asm-powerpc/rwsem.h index 79bae4933b73..2c2fe9647595 100644 --- a/include/asm-powerpc/rwsem.h +++ b/include/asm-powerpc/rwsem.h @@ -4,7 +4,7 @@ #ifdef __KERNEL__ /* - * include/asm-ppc64/rwsem.h: R/W semaphores for PPC using the stuff + * include/asm-powerpc/rwsem.h: R/W semaphores for PPC using the stuff * in lib/rwsem.c. Adapted largely from include/asm-i386/rwsem.h * by Paul Mackerras . */ diff --git a/include/asm-ppc/harrier.h b/include/asm-ppc/harrier.h index 36c73ab7e43e..7acd7fc126ec 100644 --- a/include/asm-ppc/harrier.h +++ b/include/asm-ppc/harrier.h @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/harrier.h - * * Definitions for Motorola MCG Harrier North Bridge & Memory controller * * Author: Dale Farnsworth diff --git a/include/asm-ppc/mpc10x.h b/include/asm-ppc/mpc10x.h index 976ad3d94f27..b30a6a3b5bd2 100644 --- a/include/asm-ppc/mpc10x.h +++ b/include/asm-ppc/mpc10x.h @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/mpc10x.h - * * Common routines for the Motorola SPS MPC106/8240/107 Host bridge/Mem * ctlr/EPIC/etc. * diff --git a/include/asm-ppc/todc.h b/include/asm-ppc/todc.h index 84bae7d76814..937c7dbe6e5c 100644 --- a/include/asm-ppc/todc.h +++ b/include/asm-ppc/todc.h @@ -1,6 +1,4 @@ /* - * include/asm-ppc/todc.h - * * Definitions for the M48Txx and mc146818 series of Time of day/Real Time * Clock chips. * diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 685c25175d96..3e376202dd48 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -958,7 +958,7 @@ void audit_syscall_entry(struct task_struct *tsk, int arch, int major, * * i386 no * x86_64 no - * ppc64 yes (see arch/ppc64/kernel/misc.S) + * ppc64 yes (see arch/powerpc/platforms/iseries/misc.S) * * This also happens with vm86 emulation in a non-nested manner * (entries without exits), so this case must be caught. diff --git a/lib/extable.c b/lib/extable.c index 18df57c029df..01c08b5836f5 100644 --- a/lib/extable.c +++ b/lib/extable.c @@ -1,5 +1,4 @@ /* - * lib/extable.c * Derived from arch/ppc/mm/extable.c and arch/i386/mm/extable.c. * * Copyright (C) 2004 Paul Mackerras, IBM Corp. -- cgit v1.2.3 From 341963b909a01d2f38d86f5db8dd1f8c80bd6dbf Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Feb 2006 15:10:48 +0900 Subject: [PATCH] libata: add ATA_QCFLAG_EH_SCHEDULED Add ATA_QCFLAG_EH_SCHEDULED. If this flag is set, the qc is owned by EH and normal completion path is not allowed to finish it. This patch doesn't actually use this flag. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 33 ++++++++++++++++++++------------- drivers/scsi/libata-scsi.c | 2 +- drivers/scsi/libata.h | 1 + include/linux/libata.h | 1 + 4 files changed, 23 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 22db73932253..977a53dd1677 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3620,19 +3620,7 @@ void ata_qc_free(struct ata_queued_cmd *qc) } } -/** - * ata_qc_complete - Complete an active ATA command - * @qc: Command to complete - * @err_mask: ATA Status register contents - * - * Indicate to the mid and upper layers that an ATA - * command has completed, with either an ok or not-ok status. - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ - -void ata_qc_complete(struct ata_queued_cmd *qc) +inline void __ata_qc_complete(struct ata_queued_cmd *qc) { assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */ assert(qc->flags & ATA_QCFLAG_ACTIVE); @@ -3650,6 +3638,25 @@ void ata_qc_complete(struct ata_queued_cmd *qc) qc->complete_fn(qc); } +/** + * ata_qc_complete - Complete an active ATA command + * @qc: Command to complete + * @err_mask: ATA Status register contents + * + * Indicate to the mid and upper layers that an ATA + * command has completed, with either an ok or not-ok status. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +void ata_qc_complete(struct ata_queued_cmd *qc) +{ + if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED)) + return; + + __ata_qc_complete(qc); +} + static inline int ata_should_dma_map(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index b007bb409382..1df468eb2bf3 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -770,7 +770,7 @@ static void __ata_eh_qc_complete(struct ata_queued_cmd *qc) spin_lock_irqsave(&ap->host_set->lock, flags); qc->scsidone = ata_eh_scsidone; - ata_qc_complete(qc); + __ata_qc_complete(qc); assert(!ata_tag_valid(qc->tag)); spin_unlock_irqrestore(&ap->host_set->lock, flags); diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 9d76923a2253..1cd071a32e93 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -46,6 +46,7 @@ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); extern void ata_qc_free(struct ata_queued_cmd *qc); extern unsigned int ata_qc_issue(struct ata_queued_cmd *qc); +extern void __ata_qc_complete(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); extern void ata_dev_select(struct ata_port *ap, unsigned int device, unsigned int wait, unsigned int can_sleep); diff --git a/include/linux/libata.h b/include/linux/libata.h index 68b3fe6f9a4d..5c70a57f93ee 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -169,6 +169,7 @@ enum { ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ ATA_QCFLAG_SINGLE = (1 << 4), /* no s/g, just a single buffer */ ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE, + ATA_QCFLAG_EH_SCHEDULED = (1 << 5), /* EH scheduled */ /* various lengths of time */ ATA_TMOUT_EDD = 5 * HZ, /* heuristic */ -- cgit v1.2.3 From f29841e08fa20a7f2c8bc1b70306975299c66ee7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Feb 2006 15:10:48 +0900 Subject: [PATCH] libata: implement ata_scsi_timed_out() Implement ata_scsi_timed_out(), to be used as scsi_host_template->eh_timed_out callback for all libata drivers. Without this function, the following race exists. If a qc completes after SCSI timer expires but before libata EH kicks in, the qc gets completed but the scsicmd still gets passed to libata EH resulting in ->eng_timeout invocation with NULL qc, which none is handling properly. This patch makes sure that scmd and qc share the same lifetime. Original idea from Jeff Garzik . Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 1 + drivers/scsi/libata-scsi.c | 41 +++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 1 + 3 files changed, 43 insertions(+) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 977a53dd1677..d53e0bce2bec 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4913,6 +4913,7 @@ EXPORT_SYMBOL_GPL(ata_ratelimit); EXPORT_SYMBOL_GPL(ata_busy_sleep); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); +EXPORT_SYMBOL_GPL(ata_scsi_timed_out); EXPORT_SYMBOL_GPL(ata_scsi_error); EXPORT_SYMBOL_GPL(ata_scsi_slave_config); EXPORT_SYMBOL_GPL(ata_scsi_release); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 1df468eb2bf3..d67cc2fb5694 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -716,6 +716,47 @@ int ata_scsi_slave_config(struct scsi_device *sdev) return 0; /* scsi layer doesn't check return value, sigh */ } +/** + * ata_scsi_timed_out - SCSI layer time out callback + * @cmd: timed out SCSI command + * + * Handles SCSI layer timeout. We race with normal completion of + * the qc for @cmd. If the qc is already gone, we lose and let + * the scsi command finish (EH_HANDLED). Otherwise, the qc has + * timed out and EH should be invoked. Prevent ata_qc_complete() + * from finishing it by setting EH_SCHEDULED and return + * EH_NOT_HANDLED. + * + * LOCKING: + * Called from timer context + * + * RETURNS: + * EH_HANDLED or EH_NOT_HANDLED + */ +enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) +{ + struct Scsi_Host *host = cmd->device->host; + struct ata_port *ap = (struct ata_port *) &host->hostdata[0]; + unsigned long flags; + struct ata_queued_cmd *qc; + enum scsi_eh_timer_return ret = EH_HANDLED; + + DPRINTK("ENTER\n"); + + spin_lock_irqsave(&ap->host_set->lock, flags); + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc) { + assert(qc->scsicmd == cmd); + qc->flags |= ATA_QCFLAG_EH_SCHEDULED; + qc->err_mask |= AC_ERR_TIMEOUT; + ret = EH_NOT_HANDLED; + } + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + DPRINTK("EXIT, ret=%d\n", ret); + return ret; +} + /** * ata_scsi_error - SCSI layer error handler callback * @host: SCSI host on which error occurred diff --git a/include/linux/libata.h b/include/linux/libata.h index 5c70a57f93ee..c1e198655bb1 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -509,6 +509,7 @@ extern void ata_host_set_remove(struct ata_host_set *host_set); extern int ata_scsi_detect(struct scsi_host_template *sht); extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); +extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); extern int ata_scsi_error(struct Scsi_Host *host); extern void ata_eh_qc_complete(struct ata_queued_cmd *qc); extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); -- cgit v1.2.3 From 76014427e60f7ecfdc689dfbcb48e9760e1da4fb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 11 Feb 2006 15:13:49 +0900 Subject: [PATCH] libata: inline ata_qc_complete() This patch inlines ata_qc_complete() and uninlines __ata_qc_complete() as suggested by Jeff Garzik. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 23 ++--------------------- drivers/scsi/libata.h | 1 - include/linux/libata.h | 20 +++++++++++++++++++- 3 files changed, 21 insertions(+), 23 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 38e72c1dd689..fffbaa9dae76 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3621,7 +3621,7 @@ void ata_qc_free(struct ata_queued_cmd *qc) } } -inline void __ata_qc_complete(struct ata_queued_cmd *qc) +void __ata_qc_complete(struct ata_queued_cmd *qc) { assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */ assert(qc->flags & ATA_QCFLAG_ACTIVE); @@ -3639,25 +3639,6 @@ inline void __ata_qc_complete(struct ata_queued_cmd *qc) qc->complete_fn(qc); } -/** - * ata_qc_complete - Complete an active ATA command - * @qc: Command to complete - * @err_mask: ATA Status register contents - * - * Indicate to the mid and upper layers that an ATA - * command has completed, with either an ok or not-ok status. - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ -void ata_qc_complete(struct ata_queued_cmd *qc) -{ - if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED)) - return; - - __ata_qc_complete(qc); -} - static inline int ata_should_dma_map(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; @@ -4877,7 +4858,7 @@ EXPORT_SYMBOL_GPL(ata_device_add); EXPORT_SYMBOL_GPL(ata_host_set_remove); EXPORT_SYMBOL_GPL(ata_sg_init); EXPORT_SYMBOL_GPL(ata_sg_init_one); -EXPORT_SYMBOL_GPL(ata_qc_complete); +EXPORT_SYMBOL_GPL(__ata_qc_complete); EXPORT_SYMBOL_GPL(ata_qc_issue_prot); EXPORT_SYMBOL_GPL(ata_eng_timeout); EXPORT_SYMBOL_GPL(ata_tf_load); diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 1cd071a32e93..9d76923a2253 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -46,7 +46,6 @@ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); extern void ata_qc_free(struct ata_queued_cmd *qc); extern unsigned int ata_qc_issue(struct ata_queued_cmd *qc); -extern void __ata_qc_complete(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); extern void ata_dev_select(struct ata_port *ap, unsigned int device, unsigned int wait, unsigned int can_sleep); diff --git a/include/linux/libata.h b/include/linux/libata.h index c1e198655bb1..695d9ae6ec03 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -556,7 +556,7 @@ extern void ata_bmdma_start (struct ata_queued_cmd *qc); extern void ata_bmdma_stop(struct ata_queued_cmd *qc); extern u8 ata_bmdma_status(struct ata_port *ap); extern void ata_bmdma_irq_clear(struct ata_port *ap); -extern void ata_qc_complete(struct ata_queued_cmd *qc); +extern void __ata_qc_complete(struct ata_queued_cmd *qc); extern void ata_eng_timeout(struct ata_port *ap); extern void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, struct scsi_cmnd *cmd, @@ -756,6 +756,24 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) ata_tf_init(qc->ap, &qc->tf, qc->dev->devno); } +/** + * ata_qc_complete - Complete an active ATA command + * @qc: Command to complete + * @err_mask: ATA Status register contents + * + * Indicate to the mid and upper layers that an ATA + * command has completed, with either an ok or not-ok status. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +static inline void ata_qc_complete(struct ata_queued_cmd *qc) +{ + if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED)) + return; + + __ata_qc_complete(qc); +} /** * ata_irq_on - Enable interrupts on a port. -- cgit v1.2.3 From bef4a456b8dc8b3638f4d49a25a89e1467da9483 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 11 Feb 2006 19:11:13 +0900 Subject: [PATCH] libata: kill assert() macro libata assert() now has no user left. Kill it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- include/linux/libata.h | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'include') diff --git a/include/linux/libata.h b/include/linux/libata.h index 695d9ae6ec03..83a1f2ead861 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -62,16 +62,6 @@ #define BPRINTK(fmt, args...) if (ap->flags & ATA_FLAG_DEBUGMSG) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args) -#ifdef ATA_NDEBUG -#define assert(expr) -#else -#define assert(expr) \ - if(unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - /* NEW: debug levels */ #define HAVE_LIBATA_MSG 1 -- cgit v1.2.3 From 0e949ff304a7ca07db38c17fbbf3ead1085d7bbf Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Feb 2006 22:47:04 +0900 Subject: [PATCH] libata: implement ata_dev_id_c_string() ata_dev_id_c_string() reads ATA string from the specified offset of the given IDENTIFY PAGE and puts it in the specified buffer in trimmed and NULL-terminated form. The caller must supply a buffer which is one byte larger than the maximum size of the target ID string. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 29 +++++++++++++++++++++++++++++ include/linux/libata.h | 2 ++ 2 files changed, 31 insertions(+) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 9ddb568267e1..7e410299d67a 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -519,6 +519,34 @@ void ata_dev_id_string(const u16 *id, unsigned char *s, } } +/** + * ata_dev_id_c_string - Convert IDENTIFY DEVICE page into C string + * @id: IDENTIFY DEVICE results we will examine + * @s: string into which data is output + * @ofs: offset into identify device page + * @len: length of string to return. must be an odd number. + * + * This function is identical to ata_dev_id_string except that it + * trims trailing spaces and terminates the resulting string with + * null. @len must be actual maximum length (even number) + 1. + * + * LOCKING: + * caller. + */ +void ata_dev_id_c_string(const u16 *id, unsigned char *s, + unsigned int ofs, unsigned int len) +{ + unsigned char *p; + + WARN_ON(!(len & 1)); + + ata_dev_id_string(id, s, ofs, len - 1); + + p = s + strnlen(s, len - 1); + while (p > s && p[-1] == ' ') + p--; + *p = '\0'; +} /** * ata_noop_dev_select - Select device 0/1 on ATA bus @@ -4905,6 +4933,7 @@ EXPORT_SYMBOL_GPL(ata_scsi_release); EXPORT_SYMBOL_GPL(ata_host_intr); EXPORT_SYMBOL_GPL(ata_dev_classify); EXPORT_SYMBOL_GPL(ata_dev_id_string); +EXPORT_SYMBOL_GPL(ata_dev_id_c_string); EXPORT_SYMBOL_GPL(ata_dev_config); EXPORT_SYMBOL_GPL(ata_scsi_simulate); EXPORT_SYMBOL_GPL(ata_eh_qc_complete); diff --git a/include/linux/libata.h b/include/linux/libata.h index 83a1f2ead861..0853032673b7 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -540,6 +540,8 @@ extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, extern unsigned int ata_dev_classify(const struct ata_taskfile *tf); extern void ata_dev_id_string(const u16 *id, unsigned char *s, unsigned int ofs, unsigned int len); +extern void ata_dev_id_c_string(const u16 *id, unsigned char *s, + unsigned int ofs, unsigned int len); extern void ata_dev_config(struct ata_port *ap, unsigned int i); extern void ata_bmdma_setup (struct ata_queued_cmd *qc); extern void ata_bmdma_start (struct ata_queued_cmd *qc); -- cgit v1.2.3 From 3d2ca91095f8ab6dc0cb925374eec62fa5336764 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Feb 2006 22:47:04 +0900 Subject: [PATCH] libata: separate out ata_id_major_version() Separate out ATA major version calculation from ata_dev_identify() into ata_id_major_version(). It's preparation for splitting ata_dev_identify(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 6 +----- include/linux/ata.h | 10 ++++++++++ 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 4df5024c3888..d87854e199f6 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -927,7 +927,6 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) { struct ata_device *dev = &ap->device[device]; unsigned int major_version; - u16 tmp; unsigned long xfer_modes; unsigned int using_edd; struct ata_taskfile tf; @@ -1030,10 +1029,7 @@ retry: goto err_out_nosup; /* get major version */ - tmp = dev->id[ATA_ID_MAJOR_VER]; - for (major_version = 14; major_version >= 1; major_version--) - if (tmp & (1 << major_version)) - break; + major_version = ata_id_major_version(dev->id); /* * The exact sequence expected by certain pre-ATA4 drives is: diff --git a/include/linux/ata.h b/include/linux/ata.h index a8155ca4947f..b02a16c435e7 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -267,6 +267,16 @@ struct ata_taskfile { ((u64) (id)[(n) + 1] << 16) | \ ((u64) (id)[(n) + 0]) ) +static inline unsigned int ata_id_major_version(const u16 *id) +{ + unsigned int mver; + + for (mver = 14; mver >= 1; mver--) + if (id[ATA_ID_MAJOR_VER] & (1 << mver)) + break; + return mver; +} + static inline int ata_id_current_chs_valid(const u16 *id) { /* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command -- cgit v1.2.3 From 6e7846e9c548443c86cfbad9e4defb4bdcfc538b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Feb 2006 23:32:58 +0900 Subject: [PATCH] libata: move cdb_len for host to device cdb_len is per-device property. Sharing cdb_len on ap results in inaccurate configuration on revalidation and hotplugging. This patch makes cdb_len per-device. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 3 ++- drivers/scsi/libata-core.c | 19 ++++++++++++------- drivers/scsi/libata-scsi.c | 4 ++-- drivers/scsi/sata_sil24.c | 4 ++-- include/linux/libata.h | 2 +- 5 files changed, 19 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 24a54a5a91b8..23caa0c4019b 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -617,7 +617,8 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) ata_tf_to_fis(&qc->tf, pp->cmd_tbl, 0); if (is_atapi) { memset(pp->cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32); - memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, ap->cdb_len); + memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, + qc->dev->cdb_len); } n_elem = 0; diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 5e8a32052a1e..1a373b4d0e22 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -931,7 +931,7 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) unsigned int using_edd; struct ata_taskfile tf; unsigned int err_mask; - int rc; + int i, rc; if (!ata_dev_present(dev)) { DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n", @@ -1087,7 +1087,7 @@ retry: } - ap->host->max_cmd_len = 16; + dev->cdb_len = 16; } /* ATAPI-specific feature tests */ @@ -1100,8 +1100,7 @@ retry: printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id); goto err_out_nosup; } - ap->cdb_len = (unsigned int) rc; - ap->host->max_cmd_len = (unsigned char) ap->cdb_len; + dev->cdb_len = (unsigned int) rc; /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n", @@ -1109,6 +1108,12 @@ retry: ata_mode_string(xfer_modes)); } + ap->host->max_cmd_len = 0; + for (i = 0; i < ATA_MAX_DEVICES; i++) + ap->host->max_cmd_len = max_t(unsigned int, + ap->host->max_cmd_len, + ap->device[i].cdb_len); + DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap)); return; @@ -4203,7 +4208,7 @@ static void atapi_packet_task(void *_data) /* send SCSI cdb */ DPRINTK("send cdb\n"); - WARN_ON(ap->cdb_len < 12); + WARN_ON(qc->dev->cdb_len < 12); if (qc->tf.protocol == ATA_PROT_ATAPI_DMA || qc->tf.protocol == ATA_PROT_ATAPI_NODATA) { @@ -4217,12 +4222,12 @@ static void atapi_packet_task(void *_data) */ spin_lock_irqsave(&ap->host_set->lock, flags); ap->flags &= ~ATA_FLAG_NOINTR; - ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1); + ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1); if (qc->tf.protocol == ATA_PROT_ATAPI_DMA) ap->ops->bmdma_start(qc); /* initiate bmdma */ spin_unlock_irqrestore(&ap->host_set->lock, flags); } else { - ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1); + ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1); /* PIO commands are handled by polling */ ap->hsm_task_state = HSM_ST; diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index ebd7cf42550b..3628fedc9865 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -2146,7 +2146,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer)); qc->dma_dir = DMA_FROM_DEVICE; - memset(&qc->cdb, 0, ap->cdb_len); + memset(&qc->cdb, 0, qc->dev->cdb_len); qc->cdb[0] = REQUEST_SENSE; qc->cdb[4] = SCSI_SENSE_BUFFERSIZE; @@ -2248,7 +2248,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd) if (ata_check_atapi_dma(qc)) using_pio = 1; - memcpy(&qc->cdb, scsicmd, qc->ap->cdb_len); + memcpy(&qc->cdb, scsicmd, dev->cdb_len); qc->complete_fn = atapi_qc_complete; diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 228a7fabffff..24020c68903a 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -371,7 +371,7 @@ static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev) { void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; - if (ap->cdb_len == 16) + if (dev->cdb_len == 16) writel(PORT_CS_CDB16, port + PORT_CTRL_STAT); else writel(PORT_CS_CDB16, port + PORT_CTRL_CLR); @@ -543,7 +543,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) prb = &cb->atapi.prb; sge = cb->atapi.sge; memset(cb->atapi.cdb, 0, 32); - memcpy(cb->atapi.cdb, qc->cdb, ap->cdb_len); + memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len); if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) { if (qc->tf.flags & ATA_TFLAG_WRITE) diff --git a/include/linux/libata.h b/include/linux/libata.h index 0853032673b7..853c98859a9f 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -348,6 +348,7 @@ struct ata_device { unsigned int multi_count; /* sectors count for READ/WRITE MULTIPLE */ + unsigned int cdb_len; /* for CHS addressing */ u16 cylinders; /* Number of cylinders */ @@ -377,7 +378,6 @@ struct ata_port { unsigned int mwdma_mask; unsigned int udma_mask; unsigned int cbl; /* cable type; ATA_CBL_xxx */ - unsigned int cdb_len; struct ata_device device[ATA_MAX_DEVICES]; -- cgit v1.2.3 From b00eec1d58ee71131375bfeb86e64bceec3f5618 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Feb 2006 23:32:59 +0900 Subject: [PATCH] libata: add per-device max_sectors If a low level driver wants to control max_sectors, it had to adjust ap->host->max_sectors and set ATA_DFLAG_LOCK_SECTORS to tell ata_scsi_slave_config not to override the limit. This is not only cumbersome but also incorrect for hosts which support more than one devices per port. This patch adds per-device ->max_sectors. If the field is unset (zero), libata core layer will adjust ->max_sectors according to default rules. If the field is set, libata honors the setting. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 4 +--- drivers/scsi/libata-scsi.c | 18 +++++++++--------- drivers/scsi/sata_sil.c | 4 +--- include/linux/libata.h | 4 ++-- 4 files changed, 13 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 1a373b4d0e22..61cba39a6834 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1147,9 +1147,7 @@ void ata_dev_config(struct ata_port *ap, unsigned int i) printk(KERN_INFO "ata%u(%u): applying bridge limits\n", ap->id, i); ap->udma_mask &= ATA_UDMA5; - ap->host->max_sectors = ATA_MAX_SECTORS; - ap->host->hostt->max_sectors = ATA_MAX_SECTORS; - ap->device[i].flags |= ATA_DFLAG_LOCK_SECTORS; + ap->device[i].max_sectors = ATA_MAX_SECTORS; } if (ap->ops->dev_config) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 3628fedc9865..86da46502b3e 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -684,23 +684,23 @@ int ata_scsi_slave_config(struct scsi_device *sdev) if (sdev->id < ATA_MAX_DEVICES) { struct ata_port *ap; struct ata_device *dev; + unsigned int max_sectors; ap = (struct ata_port *) &sdev->host->hostdata[0]; dev = &ap->device[sdev->id]; - /* TODO: 1024 is an arbitrary number, not the + /* TODO: 2048 is an arbitrary number, not the * hardware maximum. This should be increased to * 65534 when Jens Axboe's patch for dynamically * determining max_sectors is merged. */ - if ((dev->flags & ATA_DFLAG_LBA48) && - ((dev->flags & ATA_DFLAG_LOCK_SECTORS) == 0)) { - /* - * do not overwrite sdev->host->max_sectors, since - * other drives on this host may not support LBA48 - */ - blk_queue_max_sectors(sdev->request_queue, 2048); - } + max_sectors = ATA_MAX_SECTORS; + if (dev->flags & ATA_DFLAG_LBA48) + max_sectors = 2048; + if (dev->max_sectors) + max_sectors = dev->max_sectors; + + blk_queue_max_sectors(sdev->request_queue, max_sectors); /* * SATA DMA transfers must be multiples of 4 byte, so diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 61c4ac7ff9db..6c482c8be254 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -354,9 +354,7 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) (quirks & SIL_QUIRK_MOD15WRITE))) { printk(KERN_INFO "ata%u(%u): applying Seagate errata fix (mod15write workaround)\n", ap->id, dev->devno); - ap->host->max_sectors = 15; - ap->host->hostt->max_sectors = 15; - dev->flags |= ATA_DFLAG_LOCK_SECTORS; + dev->max_sectors = 15; return; } diff --git a/include/linux/libata.h b/include/linux/libata.h index 853c98859a9f..afe46457124e 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -122,8 +122,7 @@ enum { /* struct ata_device stuff */ ATA_DFLAG_LBA48 = (1 << 0), /* device supports LBA48 */ ATA_DFLAG_PIO = (1 << 1), /* device currently in PIO mode */ - ATA_DFLAG_LOCK_SECTORS = (1 << 2), /* don't adjust max_sectors */ - ATA_DFLAG_LBA = (1 << 3), /* device supports LBA */ + ATA_DFLAG_LBA = (1 << 2), /* device supports LBA */ ATA_DEV_UNKNOWN = 0, /* unknown device */ ATA_DEV_ATA = 1, /* ATA device */ @@ -348,6 +347,7 @@ struct ata_device { unsigned int multi_count; /* sectors count for READ/WRITE MULTIPLE */ + unsigned int max_sectors; /* per-device max sectors */ unsigned int cdb_len; /* for CHS addressing */ -- cgit v1.2.3 From 6a62a04d4705df4f9f9bee39e889b9e920eeca47 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 13 Feb 2006 10:02:46 +0900 Subject: [PATCH] libata: rename ata_dev_id_[c_]string() This patch renames ata_dev_id_[c_]string() to ata_id_[c_]string(). All other functions which read data from ATA ID data start with ata_id and those two function names were getting too long. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 23 +++++++++++------------ drivers/scsi/libata-scsi.c | 12 ++++++------ drivers/scsi/sata_sil.c | 3 +-- include/linux/libata.h | 8 ++++---- 4 files changed, 22 insertions(+), 24 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index adc5b440c9bc..d694b20e81bf 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -486,7 +486,7 @@ ata_dev_try_classify(struct ata_port *ap, unsigned int device, u8 *r_err) } /** - * ata_dev_id_string - Convert IDENTIFY DEVICE page into string + * ata_id_string - Convert IDENTIFY DEVICE page into string * @id: IDENTIFY DEVICE results we will examine * @s: string into which data is output * @ofs: offset into identify device page @@ -500,8 +500,8 @@ ata_dev_try_classify(struct ata_port *ap, unsigned int device, u8 *r_err) * caller. */ -void ata_dev_id_string(const u16 *id, unsigned char *s, - unsigned int ofs, unsigned int len) +void ata_id_string(const u16 *id, unsigned char *s, + unsigned int ofs, unsigned int len) { unsigned int c; @@ -520,27 +520,27 @@ void ata_dev_id_string(const u16 *id, unsigned char *s, } /** - * ata_dev_id_c_string - Convert IDENTIFY DEVICE page into C string + * ata_id_c_string - Convert IDENTIFY DEVICE page into C string * @id: IDENTIFY DEVICE results we will examine * @s: string into which data is output * @ofs: offset into identify device page * @len: length of string to return. must be an odd number. * - * This function is identical to ata_dev_id_string except that it + * This function is identical to ata_id_string except that it * trims trailing spaces and terminates the resulting string with * null. @len must be actual maximum length (even number) + 1. * * LOCKING: * caller. */ -void ata_dev_id_c_string(const u16 *id, unsigned char *s, - unsigned int ofs, unsigned int len) +void ata_id_c_string(const u16 *id, unsigned char *s, + unsigned int ofs, unsigned int len) { unsigned char *p; WARN_ON(!(len & 1)); - ata_dev_id_string(id, s, ofs, len - 1); + ata_id_string(id, s, ofs, len - 1); p = s + strnlen(s, len - 1); while (p > s && p[-1] == ' ') @@ -2315,8 +2315,7 @@ static int ata_dma_blacklisted(const struct ata_device *dev) unsigned char model_num[41]; int i; - ata_dev_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, - sizeof(model_num)); + ata_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i++) if (!strcmp(ata_dma_blacklist[i], model_num)) @@ -4934,8 +4933,8 @@ EXPORT_SYMBOL_GPL(ata_scsi_slave_config); EXPORT_SYMBOL_GPL(ata_scsi_release); EXPORT_SYMBOL_GPL(ata_host_intr); EXPORT_SYMBOL_GPL(ata_dev_classify); -EXPORT_SYMBOL_GPL(ata_dev_id_string); -EXPORT_SYMBOL_GPL(ata_dev_id_c_string); +EXPORT_SYMBOL_GPL(ata_id_string); +EXPORT_SYMBOL_GPL(ata_id_c_string); EXPORT_SYMBOL_GPL(ata_dev_config); EXPORT_SYMBOL_GPL(ata_scsi_simulate); EXPORT_SYMBOL_GPL(ata_eh_qc_complete); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 86da46502b3e..538784e65cdc 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1567,8 +1567,8 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, if (buflen > 35) { memcpy(&rbuf[8], "ATA ", 8); - ata_dev_id_string(args->id, &rbuf[16], ATA_ID_PROD_OFS, 16); - ata_dev_id_string(args->id, &rbuf[32], ATA_ID_FW_REV_OFS, 4); + ata_id_string(args->id, &rbuf[16], ATA_ID_PROD_OFS, 16); + ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV_OFS, 4); if (rbuf[32] == 0 || rbuf[32] == ' ') memcpy(&rbuf[32], "n/a ", 4); } @@ -1642,8 +1642,8 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf, memcpy(rbuf, hdr, sizeof(hdr)); if (buflen > (ATA_SERNO_LEN + 4 - 1)) - ata_dev_id_string(args->id, (unsigned char *) &rbuf[4], - ATA_ID_SERNO_OFS, ATA_SERNO_LEN); + ata_id_string(args->id, (unsigned char *) &rbuf[4], + ATA_ID_SERNO_OFS, ATA_SERNO_LEN); return 0; } @@ -1806,8 +1806,8 @@ static int ata_dev_supports_fua(u16 *id) if (!ata_id_has_fua(id)) return 0; - ata_dev_id_c_string(id, model, ATA_ID_PROD_OFS, sizeof(model)); - ata_dev_id_c_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw)); + ata_id_c_string(id, model, ATA_ID_PROD_OFS, sizeof(model)); + ata_id_c_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw)); if (strcmp(model, "Maxtor")) return 1; diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 15346888faf2..e14ed4ebbeed 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -338,8 +338,7 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) unsigned int n, quirks = 0; unsigned char model_num[41]; - ata_dev_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, - sizeof(model_num)); + ata_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); for (n = 0; sil_blacklist[n].product; n++) if (!strcmp(sil_blacklist[n].product, model_num)) { diff --git a/include/linux/libata.h b/include/linux/libata.h index afe46457124e..0d6bf50ad029 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -538,10 +538,10 @@ extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, unsigned int n_elem); extern unsigned int ata_dev_classify(const struct ata_taskfile *tf); -extern void ata_dev_id_string(const u16 *id, unsigned char *s, - unsigned int ofs, unsigned int len); -extern void ata_dev_id_c_string(const u16 *id, unsigned char *s, - unsigned int ofs, unsigned int len); +extern void ata_id_string(const u16 *id, unsigned char *s, + unsigned int ofs, unsigned int len); +extern void ata_id_c_string(const u16 *id, unsigned char *s, + unsigned int ofs, unsigned int len); extern void ata_dev_config(struct ata_port *ap, unsigned int i); extern void ata_bmdma_setup (struct ata_queued_cmd *qc); extern void ata_bmdma_start (struct ata_queued_cmd *qc); -- cgit v1.2.3 From c6622f63db86fcbd41bf6fe05ddf2e00c1e51ced Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 24 Feb 2006 10:06:59 +1100 Subject: powerpc: Implement accurate task and CPU time accounting This implements accurate task and cpu time accounting for 64-bit powerpc kernels. Instead of accounting a whole jiffy of time to a task on a timer interrupt because that task happened to be running at the time, we now account time in units of timebase ticks according to the actual time spent by the task in user mode and kernel mode. We also count the time spent processing hardware and software interrupts accurately. This is conditional on CONFIG_VIRT_CPU_ACCOUNTING. If that is not set, we do tick-based approximate accounting as before. To get this accurate information, we read either the PURR (processor utilization of resources register) on POWER5 machines, or the timebase on other machines on * each entry to the kernel from usermode * each exit to usermode * transitions between process context, hard irq context and soft irq context in kernel mode * context switches. On POWER5 systems with shared-processor logical partitioning we also read both the PURR and the timebase at each timer interrupt and context switch in order to determine how much time has been taken by the hypervisor to run other partitions ("steal" time). Unfortunately, since we need values of the PURR on both threads at the same time to accurately calculate the steal time, and since we can only calculate steal time on a per-core basis, the apportioning of the steal time between idle time (time which we ceded to the hypervisor in the idle loop) and actual stolen time is somewhat approximate at the moment. This is all based quite heavily on what s390 does, and it uses the generic interfaces that were added by the s390 developers, i.e. account_system_time(), account_user_time(), etc. This patch doesn't add any new interfaces between the kernel and userspace, and doesn't change the units in which time is reported to userspace by things such as /proc/stat, /proc//stat, getrusage(), times(), etc. Internally the various task and cpu times are stored in timebase units, but they are converted to USER_HZ units (1/100th of a second) when reported to userspace. Some precision is therefore lost but there should not be any accumulating error, since the internal accumulation is at full precision. Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 15 +++ arch/powerpc/kernel/asm-offsets.c | 3 + arch/powerpc/kernel/entry_64.S | 7 +- arch/powerpc/kernel/head_64.S | 9 ++ arch/powerpc/kernel/irq.c | 30 +++-- arch/powerpc/kernel/process.c | 7 +- arch/powerpc/kernel/smp.c | 4 +- arch/powerpc/kernel/time.c | 236 +++++++++++++++++++++++++++++++++++++- include/asm-powerpc/cputable.h | 4 +- include/asm-powerpc/cputime.h | 202 ++++++++++++++++++++++++++++++++ include/asm-powerpc/irq.h | 6 +- include/asm-powerpc/paca.h | 5 + include/asm-powerpc/ppc_asm.h | 42 +++++++ include/asm-powerpc/system.h | 4 + include/asm-powerpc/time.h | 15 +++ include/asm-ppc/time.h | 5 + 16 files changed, 577 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index fb0dcb994b84..d112aed2999b 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -250,6 +250,21 @@ config PPC_STD_MMU_32 def_bool y depends on PPC_STD_MMU && PPC32 +config VIRT_CPU_ACCOUNTING + bool "Deterministic task and CPU time accounting" + depends on PPC64 + default y + help + Select this option to enable more accurate task and CPU time + accounting. This is done by reading a CPU counter on each + kernel entry and exit and on transitions within the kernel + between system, softirq and hardirq state, so there is a + small performance impact. This also enables accounting of + stolen time on logically-partitioned systems running on + IBM POWER5-based machines. + + If in doubt, say Y here. + config SMP depends on PPC_STD_MMU bool "Symmetric multi-processing support" diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 840aad43a98b..18810ac55bcc 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -137,6 +137,9 @@ int main(void) DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); DEFINE(PACALPPACAPTR, offsetof(struct paca_struct, lppaca_ptr)); DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); + DEFINE(PACA_STARTPURR, offsetof(struct paca_struct, startpurr)); + DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time)); + DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1)); diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 79a0c910f0d8..8f606c1889fa 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -61,6 +61,7 @@ system_call_common: std r12,_MSR(r1) std r0,GPR0(r1) std r10,GPR1(r1) + ACCOUNT_CPU_USER_ENTRY(r10, r11) std r2,GPR2(r1) std r3,GPR3(r1) std r4,GPR4(r1) @@ -168,8 +169,9 @@ syscall_error_cont: stdcx. r0,0,r1 /* to clear the reservation */ andi. r6,r8,MSR_PR ld r4,_LINK(r1) - beq- 1f /* only restore r13 if */ - ld r13,GPR13(r1) /* returning to usermode */ + beq- 1f + ACCOUNT_CPU_USER_EXIT(r11, r12) + ld r13,GPR13(r1) /* only restore r13 if returning to usermode */ 1: ld r2,GPR2(r1) li r12,MSR_RI andc r11,r10,r12 @@ -536,6 +538,7 @@ restore: * userspace */ beq 1f + ACCOUNT_CPU_USER_EXIT(r3, r4) REST_GPR(13, r1) 1: ld r3,_CTR(r1) diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 2b21ec499285..be3ae7733577 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -277,6 +277,7 @@ exception_marker: std r10,0(r1); /* make stack chain pointer */ \ std r0,GPR0(r1); /* save r0 in stackframe */ \ std r10,GPR1(r1); /* save r1 in stackframe */ \ + ACCOUNT_CPU_USER_ENTRY(r9, r10); \ std r2,GPR2(r1); /* save r2 in stackframe */ \ SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \ @@ -844,6 +845,14 @@ fast_exception_return: ld r11,_NIP(r1) andi. r3,r12,MSR_RI /* check if RI is set */ beq- unrecov_fer + +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + andi. r3,r12,MSR_PR + beq 2f + ACCOUNT_CPU_USER_EXIT(r3, r4) +2: +#endif + ld r3,_CCR(r1) ld r4,_LINK(r1) ld r5,_CTR(r1) diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index edb2b00edbd2..24dc8117b822 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -369,6 +369,7 @@ unsigned int real_irq_to_virt_slowpath(unsigned int real_irq) return NO_IRQ; } +#endif /* CONFIG_PPC64 */ #ifdef CONFIG_IRQSTACKS struct thread_info *softirq_ctx[NR_CPUS]; @@ -392,10 +393,24 @@ void irq_ctx_init(void) } } +static inline void do_softirq_onstack(void) +{ + struct thread_info *curtp, *irqtp; + + curtp = current_thread_info(); + irqtp = softirq_ctx[smp_processor_id()]; + irqtp->task = curtp->task; + call_do_softirq(irqtp); + irqtp->task = NULL; +} + +#else +#define do_softirq_onstack() __do_softirq() +#endif /* CONFIG_IRQSTACKS */ + void do_softirq(void) { unsigned long flags; - struct thread_info *curtp, *irqtp; if (in_interrupt()) return; @@ -403,19 +418,18 @@ void do_softirq(void) local_irq_save(flags); if (local_softirq_pending()) { - curtp = current_thread_info(); - irqtp = softirq_ctx[smp_processor_id()]; - irqtp->task = curtp->task; - call_do_softirq(irqtp); - irqtp->task = NULL; + account_system_vtime(current); + local_bh_disable(); + do_softirq_onstack(); + account_system_vtime(current); + __local_bh_enable(); } local_irq_restore(flags); } EXPORT_SYMBOL(do_softirq); -#endif /* CONFIG_IRQSTACKS */ - +#ifdef CONFIG_PPC64 static int __init setup_noirqdistrib(char *str) { distribute_irqs = 0; diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index dd774c3c9302..1770a066c217 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -45,9 +45,9 @@ #include #include #include +#include #ifdef CONFIG_PPC64 #include -#include #endif extern unsigned long _get_SP(void); @@ -328,6 +328,11 @@ struct task_struct *__switch_to(struct task_struct *prev, #endif local_irq_save(flags); + + account_system_vtime(current); + account_process_vtime(current); + calculate_steal_time(); + last = _switch(old_thread, new_thread); local_irq_restore(flags); diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 13595a64f013..805eaedbc308 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -541,7 +541,7 @@ int __devinit start_secondary(void *unused) smp_ops->take_timebase(); if (system_state > SYSTEM_BOOTING) - per_cpu(last_jiffy, cpu) = get_tb(); + snapshot_timebase(); spin_lock(&call_lock); cpu_set(cpu, cpu_online_map); @@ -573,6 +573,8 @@ void __init smp_cpus_done(unsigned int max_cpus) set_cpus_allowed(current, old_mask); + snapshot_timebases(); + dump_numa_cpu_topology(); } diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 2a7ddc579379..0b34db28916f 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -135,6 +136,220 @@ unsigned long tb_last_stamp; */ DEFINE_PER_CPU(unsigned long, last_jiffy); +#ifdef CONFIG_VIRT_CPU_ACCOUNTING +/* + * Factors for converting from cputime_t (timebase ticks) to + * jiffies, milliseconds, seconds, and clock_t (1/USER_HZ seconds). + * These are all stored as 0.64 fixed-point binary fractions. + */ +u64 __cputime_jiffies_factor; +u64 __cputime_msec_factor; +u64 __cputime_sec_factor; +u64 __cputime_clockt_factor; + +static void calc_cputime_factors(void) +{ + struct div_result res; + + div128_by_32(HZ, 0, tb_ticks_per_sec, &res); + __cputime_jiffies_factor = res.result_low; + div128_by_32(1000, 0, tb_ticks_per_sec, &res); + __cputime_msec_factor = res.result_low; + div128_by_32(1, 0, tb_ticks_per_sec, &res); + __cputime_sec_factor = res.result_low; + div128_by_32(USER_HZ, 0, tb_ticks_per_sec, &res); + __cputime_clockt_factor = res.result_low; +} + +/* + * Read the PURR on systems that have it, otherwise the timebase. + */ +static u64 read_purr(void) +{ + if (cpu_has_feature(CPU_FTR_PURR)) + return mfspr(SPRN_PURR); + return mftb(); +} + +/* + * Account time for a transition between system, hard irq + * or soft irq state. + */ +void account_system_vtime(struct task_struct *tsk) +{ + u64 now, delta; + unsigned long flags; + + local_irq_save(flags); + now = read_purr(); + delta = now - get_paca()->startpurr; + get_paca()->startpurr = now; + if (!in_interrupt()) { + delta += get_paca()->system_time; + get_paca()->system_time = 0; + } + account_system_time(tsk, 0, delta); + local_irq_restore(flags); +} + +/* + * Transfer the user and system times accumulated in the paca + * by the exception entry and exit code to the generic process + * user and system time records. + * Must be called with interrupts disabled. + */ +void account_process_vtime(struct task_struct *tsk) +{ + cputime_t utime; + + utime = get_paca()->user_time; + get_paca()->user_time = 0; + account_user_time(tsk, utime); +} + +static void account_process_time(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + account_process_vtime(current); + run_local_timers(); + if (rcu_pending(cpu)) + rcu_check_callbacks(cpu, user_mode(regs)); + scheduler_tick(); + run_posix_cpu_timers(current); +} + +#ifdef CONFIG_PPC_SPLPAR +/* + * Stuff for accounting stolen time. + */ +struct cpu_purr_data { + int initialized; /* thread is running */ + u64 tb0; /* timebase at origin time */ + u64 purr0; /* PURR at origin time */ + u64 tb; /* last TB value read */ + u64 purr; /* last PURR value read */ + u64 stolen; /* stolen time so far */ + spinlock_t lock; +}; + +static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data); + +static void snapshot_tb_and_purr(void *data) +{ + struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); + + p->tb0 = mftb(); + p->purr0 = mfspr(SPRN_PURR); + p->tb = p->tb0; + p->purr = 0; + wmb(); + p->initialized = 1; +} + +/* + * Called during boot when all cpus have come up. + */ +void snapshot_timebases(void) +{ + int cpu; + + if (!cpu_has_feature(CPU_FTR_PURR)) + return; + for_each_cpu(cpu) + spin_lock_init(&per_cpu(cpu_purr_data, cpu).lock); + on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1); +} + +void calculate_steal_time(void) +{ + u64 tb, purr, t0; + s64 stolen; + struct cpu_purr_data *p0, *pme, *phim; + int cpu; + + if (!cpu_has_feature(CPU_FTR_PURR)) + return; + cpu = smp_processor_id(); + pme = &per_cpu(cpu_purr_data, cpu); + if (!pme->initialized) + return; /* this can happen in early boot */ + p0 = &per_cpu(cpu_purr_data, cpu & ~1); + phim = &per_cpu(cpu_purr_data, cpu ^ 1); + spin_lock(&p0->lock); + tb = mftb(); + purr = mfspr(SPRN_PURR) - pme->purr0; + if (!phim->initialized || !cpu_online(cpu ^ 1)) { + stolen = (tb - pme->tb) - (purr - pme->purr); + } else { + t0 = pme->tb0; + if (phim->tb0 < t0) + t0 = phim->tb0; + stolen = phim->tb - t0 - phim->purr - purr - p0->stolen; + } + if (stolen > 0) { + account_steal_time(current, stolen); + p0->stolen += stolen; + } + pme->tb = tb; + pme->purr = purr; + spin_unlock(&p0->lock); +} + +/* + * Must be called before the cpu is added to the online map when + * a cpu is being brought up at runtime. + */ +static void snapshot_purr(void) +{ + int cpu; + u64 purr; + struct cpu_purr_data *p0, *pme, *phim; + unsigned long flags; + + if (!cpu_has_feature(CPU_FTR_PURR)) + return; + cpu = smp_processor_id(); + pme = &per_cpu(cpu_purr_data, cpu); + p0 = &per_cpu(cpu_purr_data, cpu & ~1); + phim = &per_cpu(cpu_purr_data, cpu ^ 1); + spin_lock_irqsave(&p0->lock, flags); + pme->tb = pme->tb0 = mftb(); + purr = mfspr(SPRN_PURR); + if (!phim->initialized) { + pme->purr = 0; + pme->purr0 = purr; + } else { + /* set p->purr and p->purr0 for no change in p0->stolen */ + pme->purr = phim->tb - phim->tb0 - phim->purr - p0->stolen; + pme->purr0 = purr - pme->purr; + } + pme->initialized = 1; + spin_unlock_irqrestore(&p0->lock, flags); +} + +#endif /* CONFIG_PPC_SPLPAR */ + +#else /* ! CONFIG_VIRT_CPU_ACCOUNTING */ +#define calc_cputime_factors() +#define account_process_time(regs) update_process_times(user_mode(regs)) +#define calculate_steal_time() do { } while (0) +#endif + +#if !(defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR)) +#define snapshot_purr() do { } while (0) +#endif + +/* + * Called when a cpu comes up after the system has finished booting, + * i.e. as a result of a hotplug cpu action. + */ +void snapshot_timebase(void) +{ + __get_cpu_var(last_jiffy) = get_tb(); + snapshot_purr(); +} + void __delay(unsigned long loops) { unsigned long start; @@ -382,6 +597,7 @@ static void iSeries_tb_recal(void) new_tb_ticks_per_jiffy, sign, tick_diff ); tb_ticks_per_jiffy = new_tb_ticks_per_jiffy; tb_ticks_per_sec = new_tb_ticks_per_sec; + calc_cputime_factors(); div128_by_32( XSEC_PER_SEC, 0, tb_ticks_per_sec, &divres ); do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; tb_to_xs = divres.result_low; @@ -430,6 +646,7 @@ void timer_interrupt(struct pt_regs * regs) irq_enter(); profile_tick(CPU_PROFILING, regs); + calculate_steal_time(); #ifdef CONFIG_PPC_ISERIES get_lppaca()->int_dword.fields.decr_int = 0; @@ -451,7 +668,7 @@ void timer_interrupt(struct pt_regs * regs) * is the case. */ if (!cpu_is_offline(cpu)) - update_process_times(user_mode(regs)); + account_process_time(regs); /* * No need to check whether cpu is offline here; boot_cpuid @@ -508,13 +725,27 @@ void wakeup_decrementer(void) void __init smp_space_timers(unsigned int max_cpus) { int i; + unsigned long half = tb_ticks_per_jiffy / 2; unsigned long offset = tb_ticks_per_jiffy / max_cpus; unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid); /* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */ previous_tb -= tb_ticks_per_jiffy; + /* + * The stolen time calculation for POWER5 shared-processor LPAR + * systems works better if the two threads' timebase interrupts + * are staggered by half a jiffy with respect to each other. + */ for_each_cpu(i) { - if (i != boot_cpuid) { + if (i == boot_cpuid) + continue; + if (i == (boot_cpuid ^ 1)) + per_cpu(last_jiffy, i) = + per_cpu(last_jiffy, boot_cpuid) - half; + else if (i & 1) + per_cpu(last_jiffy, i) = + per_cpu(last_jiffy, i ^ 1) + half; + else { previous_tb += offset; per_cpu(last_jiffy, i) = previous_tb; } @@ -706,6 +937,7 @@ void __init time_init(void) tb_ticks_per_sec = ppc_tb_freq; tb_ticks_per_usec = ppc_tb_freq / 1000000; tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000); + calc_cputime_factors(); /* * Calculate the length of each tick in ns. It will not be diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 90d005bb4d1c..99d12ff6346c 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -117,6 +117,7 @@ extern void do_cpu_ftr_fixups(unsigned long offset); #define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000) #define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0000100000000000) #define CPU_FTR_PAUSE_ZERO ASM_CONST(0x0000200000000000) +#define CPU_FTR_PURR ASM_CONST(0x0000400000000000) #else /* ensure on 32b processors the flags are available for compiling but * don't do anything */ @@ -132,6 +133,7 @@ extern void do_cpu_ftr_fixups(unsigned long offset); #define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0) #define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0) #define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0) +#define CPU_FTR_PURR ASM_CONST(0x0) #endif #ifndef __ASSEMBLY__ @@ -316,7 +318,7 @@ enum { CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | - CPU_FTR_MMCRA_SIHV, + CPU_FTR_MMCRA_SIHV | CPU_FTR_PURR, CPU_FTRS_CELL = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | diff --git a/include/asm-powerpc/cputime.h b/include/asm-powerpc/cputime.h index 6d68ad7e0ea3..a21185d47883 100644 --- a/include/asm-powerpc/cputime.h +++ b/include/asm-powerpc/cputime.h @@ -1 +1,203 @@ +/* + * Definitions for measuring cputime on powerpc machines. + * + * Copyright (C) 2006 Paul Mackerras, IBM Corp. + * + * 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. + * + * If we have CONFIG_VIRT_CPU_ACCOUNTING, we measure cpu time in + * the same units as the timebase. Otherwise we measure cpu time + * in jiffies using the generic definitions. + */ + +#ifndef __POWERPC_CPUTIME_H +#define __POWERPC_CPUTIME_H + +#ifndef CONFIG_VIRT_CPU_ACCOUNTING #include +#else + +#include +#include +#include +#include +#include + +typedef u64 cputime_t; +typedef u64 cputime64_t; + +#define cputime_zero ((cputime_t)0) +#define cputime_max ((~((cputime_t)0) >> 1) - 1) +#define cputime_add(__a, __b) ((__a) + (__b)) +#define cputime_sub(__a, __b) ((__a) - (__b)) +#define cputime_div(__a, __n) ((__a) / (__n)) +#define cputime_halve(__a) ((__a) >> 1) +#define cputime_eq(__a, __b) ((__a) == (__b)) +#define cputime_gt(__a, __b) ((__a) > (__b)) +#define cputime_ge(__a, __b) ((__a) >= (__b)) +#define cputime_lt(__a, __b) ((__a) < (__b)) +#define cputime_le(__a, __b) ((__a) <= (__b)) + +#define cputime64_zero ((cputime64_t)0) +#define cputime64_add(__a, __b) ((__a) + (__b)) +#define cputime_to_cputime64(__ct) (__ct) + +#ifdef __KERNEL__ + +/* + * Convert cputime <-> jiffies + */ +extern u64 __cputime_jiffies_factor; + +static inline unsigned long cputime_to_jiffies(const cputime_t ct) +{ + return mulhdu(ct, __cputime_jiffies_factor); +} + +static inline cputime_t jiffies_to_cputime(const unsigned long jif) +{ + cputime_t ct; + unsigned long sec; + + /* have to be a little careful about overflow */ + ct = jif % HZ; + sec = jif / HZ; + if (ct) { + ct *= tb_ticks_per_sec; + do_div(ct, HZ); + } + if (sec) + ct += (cputime_t) sec * tb_ticks_per_sec; + return ct; +} + +static inline u64 cputime64_to_jiffies64(const cputime_t ct) +{ + return mulhdu(ct, __cputime_jiffies_factor); +} + +/* + * Convert cputime <-> milliseconds + */ +extern u64 __cputime_msec_factor; + +static inline unsigned long cputime_to_msecs(const cputime_t ct) +{ + return mulhdu(ct, __cputime_msec_factor); +} + +static inline cputime_t msecs_to_cputime(const unsigned long ms) +{ + cputime_t ct; + unsigned long sec; + + /* have to be a little careful about overflow */ + ct = ms % 1000; + sec = ms / 1000; + if (ct) { + ct *= tb_ticks_per_sec; + do_div(ct, 1000); + } + if (sec) + ct += (cputime_t) sec * tb_ticks_per_sec; + return ct; +} + +/* + * Convert cputime <-> seconds + */ +extern u64 __cputime_sec_factor; + +static inline unsigned long cputime_to_secs(const cputime_t ct) +{ + return mulhdu(ct, __cputime_sec_factor); +} + +static inline cputime_t secs_to_cputime(const unsigned long sec) +{ + return (cputime_t) sec * tb_ticks_per_sec; +} + +/* + * Convert cputime <-> timespec + */ +static inline void cputime_to_timespec(const cputime_t ct, struct timespec *p) +{ + u64 x = ct; + unsigned int frac; + + frac = do_div(x, tb_ticks_per_sec); + p->tv_sec = x; + x = (u64) frac * 1000000000; + do_div(x, tb_ticks_per_sec); + p->tv_nsec = x; +} + +static inline cputime_t timespec_to_cputime(const struct timespec *p) +{ + cputime_t ct; + + ct = (u64) p->tv_nsec * tb_ticks_per_sec; + do_div(ct, 1000000000); + return ct + (u64) p->tv_sec * tb_ticks_per_sec; +} + +/* + * Convert cputime <-> timeval + */ +static inline void cputime_to_timeval(const cputime_t ct, struct timeval *p) +{ + u64 x = ct; + unsigned int frac; + + frac = do_div(x, tb_ticks_per_sec); + p->tv_sec = x; + x = (u64) frac * 1000000; + do_div(x, tb_ticks_per_sec); + p->tv_usec = x; +} + +static inline cputime_t timeval_to_cputime(const struct timeval *p) +{ + cputime_t ct; + + ct = (u64) p->tv_usec * tb_ticks_per_sec; + do_div(ct, 1000000); + return ct + (u64) p->tv_sec * tb_ticks_per_sec; +} + +/* + * Convert cputime <-> clock_t (units of 1/USER_HZ seconds) + */ +extern u64 __cputime_clockt_factor; + +static inline unsigned long cputime_to_clock_t(const cputime_t ct) +{ + return mulhdu(ct, __cputime_clockt_factor); +} + +static inline cputime_t clock_t_to_cputime(const unsigned long clk) +{ + cputime_t ct; + unsigned long sec; + + /* have to be a little careful about overflow */ + ct = clk % USER_HZ; + sec = clk / USER_HZ; + if (ct) { + ct *= tb_ticks_per_sec; + do_div(ct, USER_HZ); + } + if (sec) + ct += (cputime_t) sec * tb_ticks_per_sec; + return ct; +} + +#define cputime64_to_clock_t(ct) cputime_to_clock_t((cputime_t)(ct)) + +#endif /* __KERNEL__ */ +#endif /* CONFIG_VIRT_CPU_ACCOUNTING */ +#endif /* __POWERPC_CPUTIME_H */ diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h index 8eb7e857ec4c..51f87d9993b6 100644 --- a/include/asm-powerpc/irq.h +++ b/include/asm-powerpc/irq.h @@ -479,6 +479,10 @@ extern int distribute_irqs; struct irqaction; struct pt_regs; +#define __ARCH_HAS_DO_SOFTIRQ + +extern void __do_softirq(void); + #ifdef CONFIG_IRQSTACKS /* * Per-cpu stacks for handling hard and soft interrupts. @@ -491,8 +495,6 @@ extern void call_do_softirq(struct thread_info *tp); extern int call___do_IRQ(int irq, struct pt_regs *regs, struct thread_info *tp); -#define __ARCH_HAS_DO_SOFTIRQ - #else #define irq_ctx_init() diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h index ec94b51074fc..4465b95ebef0 100644 --- a/include/asm-powerpc/paca.h +++ b/include/asm-powerpc/paca.h @@ -96,6 +96,11 @@ struct paca_struct { u64 saved_r1; /* r1 save for RTAS calls */ u64 saved_msr; /* MSR saved here by enter_rtas */ u8 proc_enabled; /* irq soft-enable flag */ + + /* Stuff for accurate time accounting */ + u64 user_time; /* accumulated usermode TB ticks */ + u64 system_time; /* accumulated system TB ticks */ + u64 startpurr; /* PURR/TB value snapshot */ }; extern struct paca_struct paca[]; diff --git a/include/asm-powerpc/ppc_asm.h b/include/asm-powerpc/ppc_asm.h index ab8688d39024..dd1c0a913d5f 100644 --- a/include/asm-powerpc/ppc_asm.h +++ b/include/asm-powerpc/ppc_asm.h @@ -14,6 +14,48 @@ #define SZL (BITS_PER_LONG/8) +/* + * Stuff for accurate CPU time accounting. + * These macros handle transitions between user and system state + * in exception entry and exit and accumulate time to the + * user_time and system_time fields in the paca. + */ + +#ifndef CONFIG_VIRT_CPU_ACCOUNTING +#define ACCOUNT_CPU_USER_ENTRY(ra, rb) +#define ACCOUNT_CPU_USER_EXIT(ra, rb) +#else +#define ACCOUNT_CPU_USER_ENTRY(ra, rb) \ + beq 2f; /* if from kernel mode */ \ +BEGIN_FTR_SECTION; \ + mfspr ra,SPRN_PURR; /* get processor util. reg */ \ +END_FTR_SECTION_IFSET(CPU_FTR_PURR); \ +BEGIN_FTR_SECTION; \ + mftb ra; /* or get TB if no PURR */ \ +END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \ + ld rb,PACA_STARTPURR(r13); \ + std ra,PACA_STARTPURR(r13); \ + subf rb,rb,ra; /* subtract start value */ \ + ld ra,PACA_USER_TIME(r13); \ + add ra,ra,rb; /* add on to user time */ \ + std ra,PACA_USER_TIME(r13); \ +2: + +#define ACCOUNT_CPU_USER_EXIT(ra, rb) \ +BEGIN_FTR_SECTION; \ + mfspr ra,SPRN_PURR; /* get processor util. reg */ \ +END_FTR_SECTION_IFSET(CPU_FTR_PURR); \ +BEGIN_FTR_SECTION; \ + mftb ra; /* or get TB if no PURR */ \ +END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \ + ld rb,PACA_STARTPURR(r13); \ + std ra,PACA_STARTPURR(r13); \ + subf rb,rb,ra; /* subtract start value */ \ + ld ra,PACA_SYSTEM_TIME(r13); \ + add ra,ra,rb; /* add on to user time */ \ + std ra,PACA_SYSTEM_TIME(r13); +#endif + /* * Macros for storing registers into and loading registers from * exception frames. diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h index d9bf53653b10..41b7a5b3d701 100644 --- a/include/asm-powerpc/system.h +++ b/include/asm-powerpc/system.h @@ -424,5 +424,9 @@ static inline void create_function_call(unsigned long addr, void * func) create_branch(addr, func_addr, BRANCH_SET_LINK); } +#ifdef CONFIG_VIRT_CPU_ACCOUNTING +extern void account_system_vtime(struct task_struct *); +#endif + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_SYSTEM_H */ diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h index baddc9ab57ad..912118db13ae 100644 --- a/include/asm-powerpc/time.h +++ b/include/asm-powerpc/time.h @@ -41,6 +41,7 @@ extern time_t last_rtc_update; extern void generic_calibrate_decr(void); extern void wakeup_decrementer(void); +extern void snapshot_timebase(void); /* Some sane defaults: 125 MHz timebase, 1GHz processor */ extern unsigned long ppc_proc_freq; @@ -221,5 +222,19 @@ struct cpu_usage { DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array); +#ifdef CONFIG_VIRT_CPU_ACCOUNTING +extern void account_process_vtime(struct task_struct *tsk); +#else +#define account_process_vtime(tsk) do { } while (0) +#endif + +#if defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR) +extern void calculate_steal_time(void); +extern void snapshot_timebases(void); +#else +#define calculate_steal_time() do { } while (0) +#define snapshot_timebases() do { } while (0) +#endif + #endif /* __KERNEL__ */ #endif /* __PPC64_TIME_H */ diff --git a/include/asm-ppc/time.h b/include/asm-ppc/time.h index 321fb75b5f22..c86112323c9f 100644 --- a/include/asm-ppc/time.h +++ b/include/asm-ppc/time.h @@ -153,5 +153,10 @@ extern __inline__ unsigned binary_tbl(void) { ({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;}) unsigned mulhwu_scale_factor(unsigned, unsigned); + +#define account_process_vtime(tsk) do { } while (0) +#define calculate_steal_time() do { } while (0) +#define snapshot_timebases() do { } while (0) + #endif /* __ASM_TIME_H__ */ #endif /* __KERNEL__ */ -- cgit v1.2.3 From 20f4eb3e502d68b12224577ebcd2cd50cc6e14e4 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 20 Feb 2006 14:05:56 +1100 Subject: [PATCH] powerpc: Fixup for STRICT_MM_TYPECHECKS Currently ARCH=powerpc will not compile when STRICT_MM_TYPECHECKS is turned on and CONFIG_64K_PAGES is turned off. This corrects the problem. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- include/asm-powerpc/pgtable-4k.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/asm-powerpc/pgtable-4k.h b/include/asm-powerpc/pgtable-4k.h index e9590c06ad92..35f92813464c 100644 --- a/include/asm-powerpc/pgtable-4k.h +++ b/include/asm-powerpc/pgtable-4k.h @@ -62,9 +62,14 @@ /* shift to put page number into pte */ #define PTE_RPN_SHIFT (17) -#define __real_pte(e,p) ((real_pte_t)(e)) -#define __rpte_to_pte(r) (r) -#define __rpte_to_hidx(r,index) (pte_val((r)) >> 12) +#ifdef STRICT_MM_TYPECHECKS +#define __real_pte(e,p) ((real_pte_t){(e)}) +#define __rpte_to_pte(r) ((r).pte) +#else +#define __real_pte(e,p) (e) +#define __rpte_to_pte(r) (__pte(r)) +#endif +#define __rpte_to_hidx(r,index) (pte_val(__rpte_to_pte(r)) >> 12) #define pte_iterate_hashed_subpages(rpte, psize, va, index, shift) \ do { \ -- cgit v1.2.3 From 4f629d7db32decbadaab2abfa4d021fee94990ef Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Mon, 20 Feb 2006 10:40:28 +0100 Subject: [PATCH] powerpc: newline for ISYNC_ON_SMP Add a newline at the end of the ISYNC_ON_SMP string. Needed for a subsequent patch. Signed-off-by: Nick Piggin Signed-off-by: Paul Mackerras --- include/asm-powerpc/synch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-powerpc/synch.h b/include/asm-powerpc/synch.h index c90d9d9aae72..2cda3c38a9fa 100644 --- a/include/asm-powerpc/synch.h +++ b/include/asm-powerpc/synch.h @@ -15,7 +15,7 @@ #endif #ifdef CONFIG_SMP -#define ISYNC_ON_SMP "\n\tisync" +#define ISYNC_ON_SMP "\n\tisync\n" #define LWSYNC_ON_SMP __stringify(LWSYNC) "\n" #else #define ISYNC_ON_SMP -- cgit v1.2.3 From f055affb89f587a03f3411c3fd49ef31295c3d48 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Mon, 20 Feb 2006 10:41:40 +0100 Subject: [PATCH] powerpc: native atomic_add_unless Do atomic_add_unless natively instead of using cmpxchg. Improved register allocation idea from Joel Schopp. Signed-off-by: Nick Piggin Signed-off-by: Paul Mackerras --- include/asm-powerpc/atomic.h | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h index 147a38dcc766..bb3c0ab7e667 100644 --- a/include/asm-powerpc/atomic.h +++ b/include/asm-powerpc/atomic.h @@ -8,6 +8,7 @@ typedef struct { volatile int counter; } atomic_t; #ifdef __KERNEL__ +#include #include #include @@ -176,20 +177,29 @@ static __inline__ int atomic_dec_return(atomic_t *v) * Atomically adds @a to @v, so long as it was not @u. * Returns non-zero if @v was not @u, and zero otherwise. */ -#define atomic_add_unless(v, a, u) \ -({ \ - int c, old; \ - c = atomic_read(v); \ - for (;;) { \ - if (unlikely(c == (u))) \ - break; \ - old = atomic_cmpxchg((v), c, c + (a)); \ - if (likely(old == c)) \ - break; \ - c = old; \ - } \ - c != (u); \ -}) +static __inline__ int atomic_add_unless(atomic_t *v, int a, int u) +{ + int t; + + __asm__ __volatile__ ( + LWSYNC_ON_SMP +"1: lwarx %0,0,%1 # atomic_add_unless\n\ + cmpw 0,%0,%3 \n\ + beq- 2f \n\ + add %0,%2,%0 \n" + PPC405_ERR77(0,%2) +" stwcx. %0,0,%1 \n\ + bne- 1b \n" + ISYNC_ON_SMP +" subf %0,%2,%0 \n\ +2:" + : "=&r" (t) + : "r" (&v->counter), "r" (a), "r" (u) + : "cc", "memory"); + + return t != u; +} + #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) #define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0) -- cgit v1.2.3 From 0004fd59d57a5875db8897966c414a88b5dad481 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Mon, 27 Feb 2006 00:07:27 -0300 Subject: V4L/DVB (3291): Added support for xc3028 analogue tuner (Hauppauge HVR900, Terratec Hybrid XS) Added support for xc3028 to v4l which adds support for: * Terratec Hybrid XS (analogue) * Hauppauge HVR 900 (analogue) Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.tuner | 1 + drivers/media/video/Makefile | 2 +- drivers/media/video/em28xx/em28xx-cards.c | 4 ++-- drivers/media/video/tuner-core.c | 3 +++ drivers/media/video/tuner-types.c | 21 +++++++++++++++++++++ include/media/tuner.h | 3 +++ 6 files changed, 31 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index f6d0cf7b7922..de48438d5115 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -69,3 +69,4 @@ tuner=67 - Philips TD1316 Hybrid Tuner tuner=68 - Philips TUV1236D ATSC/NTSC dual in tuner=69 - Tena TNF 5335 MF tuner=70 - Samsung TCPN 2121P30A +tuner=71 - Xceive xc3028 diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index faf728366c4e..60e9c6e3f2b7 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -9,7 +9,7 @@ zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o zr36067-objs := zoran_procfs.o zoran_device.o \ zoran_driver.o zoran_card.o tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \ - mt20xx.o tda8290.o tea5767.o + mt20xx.o tda8290.o tea5767.o xc3028.o msp3400-objs := msp3400-driver.o msp3400-kthreads.o diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 703927e8da13..e9834c159aec 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -158,8 +158,8 @@ struct em28xx_board em28xx_boards[] = { .name = "Hauppauge WinTV HVR 900", .vchannels = 3, .norm = VIDEO_MODE_PAL, - .has_tuner = 0, .tda9887_conf = TDA9887_PRESENT, + .tuner_type = TUNER_XCEIVE_XC3028, .has_tuner = 1, .decoder = EM28XX_TVP5150, .input = {{ @@ -180,8 +180,8 @@ struct em28xx_board em28xx_boards[] = { .name = "Terratec Hybrid XS", .vchannels = 3, .norm = VIDEO_MODE_PAL, - .has_tuner = 0, .tda9887_conf = TDA9887_PRESENT, + .tuner_type = TUNER_XCEIVE_XC3028, .has_tuner = 1, .decoder = EM28XX_TVP5150, .input = {{ diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index e34f801c9a10..520f274c89e5 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -217,6 +217,9 @@ static void set_type(struct i2c_client *c, unsigned int type, i2c_master_send(c,buffer,4); default_tuner_init(c); break; + case TUNER_XCEIVE_XC3028: + xc3028_init(c); + break; default: default_tuner_init(c); break; diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index a90bc04cf807..a4384e6e5318 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -983,6 +983,23 @@ static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = { }, }; +/* ------------ TUNER_XCEIVE_XC3028 - Xceive xc3028 ------------ */ + +static struct tuner_range tuner_xceive_xc3028_ranges[] = { + { 16 * 140.25 /*MHz*/, 0x02, }, + { 16 * 463.25 /*MHz*/, 0x04, }, + { 16 * 999.99 , 0x01, }, +}; + +static struct tuner_params tuner_xceive_xc3028_params[] = { + { + .type = TUNER_XCEIVE_XC3028, + .ranges = tuner_xceive_xc3028_ranges, + .count = ARRAY_SIZE(tuner_xceive_xc3028_ranges), + }, +}; + + /* --------------------------------------------------------------------- */ struct tunertype tuners[] = { @@ -1350,6 +1367,10 @@ struct tunertype tuners[] = { .params = tuner_samsung_tcpn_2121p30a_params, .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_params), }, + [TUNER_XCEIVE_XC3028] = { /* Xceive 3028 */ + .name = "Xceive xc3028", + .params = tuner_xceive_xc3028_params, + }, }; unsigned const int tuner_count = ARRAY_SIZE(tuners); diff --git a/include/media/tuner.h b/include/media/tuner.h index a5beeac495c7..f51759c0d180 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -117,6 +117,8 @@ #define TUNER_TNF_5335MF 69 /* Sabrent Bt848 */ #define TUNER_SAMSUNG_TCPN_2121P30A 70 /* Hauppauge PVR-500MCE NTSC */ +#define TUNER_XCEIVE_XC3028 71 + /* tv card specific */ #define TDA9887_PRESENT (1<<0) #define TDA9887_PORT1_INACTIVE (1<<1) @@ -209,6 +211,7 @@ struct tuner { extern unsigned const int tuner_count; extern int microtune_init(struct i2c_client *c); +extern int xc3028_init(struct i2c_client *c); extern int tda8290_init(struct i2c_client *c); extern int tda8290_probe(struct i2c_client *c); extern int tea5767_tuner_init(struct i2c_client *c); -- cgit v1.2.3 From 749eef857948a3de789b7d0e3b96d92199d723cf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Feb 2006 00:07:40 -0300 Subject: V4L/DVB (3334): Added ET61X251 fourcc type Signed-off-by: Mauro Carvalho Chehab --- include/linux/videodev2.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 1dd8efeff35a..3f1504353472 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -326,6 +326,7 @@ struct v4l2_pix_format #define V4L2_PIX_FMT_SN9C10X v4l2_fourcc('S','9','1','0') /* SN9C10x compression */ #define V4L2_PIX_FMT_PWC1 v4l2_fourcc('P','W','C','1') /* pwc older webcam */ #define V4L2_PIX_FMT_PWC2 v4l2_fourcc('P','W','C','2') /* pwc newer webcam */ +#define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E','6','2','5') /* ET61X251 compression */ /* * F O R M A T E N U M E R A T I O N -- cgit v1.2.3 From 41f38b43e0bfbb2ba1ef3c778f376dad8820b214 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Feb 2006 00:08:49 -0300 Subject: V4L/DVB (3371): Add debug to ioctl arguments. Added a new function that allows printing ioctl arguments. This makes easier to include debug code under v4l ioctl handling. Also fixed some declarations on internal ioctl. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 524 ++++++++++++++++++++++++++++++++++++++ include/media/v4l2-common.h | 11 +- 2 files changed, 531 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index cd2c4475525e..a241bf7e92ca 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -362,6 +362,529 @@ void v4l_printk_ioctl(unsigned int cmd) } } +/* Common ioctl debug function. This function can be used by + external ioctl messages as well as internal V4L ioctl and its + arguments */ +void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) +{ + printk(s); + printk(": "); + v4l_printk_ioctl(cmd); + switch (cmd) { + case VIDIOC_INT_G_CHIP_IDENT: + { + enum v4l2_chip_ident *p=arg; + printk ("%s: chip ident=%d\n", s, *p); + break; + } + case VIDIOC_G_PRIORITY: + case VIDIOC_S_PRIORITY: + { + enum v4l2_priority *p=arg; + printk ("%s: priority=%d\n", s, *p); + break; + } + case VIDIOC_INT_S_TUNER_MODE: + { + enum v4l2_tuner_type *p=arg; + printk ("%s: tuner type=%d\n", s, *p); + break; + } + case DECODER_SET_VBI_BYPASS: + case DECODER_ENABLE_OUTPUT: + case DECODER_GET_STATUS: + case DECODER_SET_OUTPUT: + case DECODER_SET_INPUT: + case DECODER_SET_GPIO: + case DECODER_SET_NORM: + case VIDIOCCAPTURE: + case VIDIOCSYNC: + case VIDIOCSWRITEMODE: + case TUNER_SET_TYPE_ADDR: + case TUNER_SET_STANDBY: + case TDA9887_SET_CONFIG: + case AUDC_SET_INPUT: + case VIDIOC_OVERLAY_OLD: + case VIDIOC_STREAMOFF: + case VIDIOC_G_OUTPUT: + case VIDIOC_S_OUTPUT: + case VIDIOC_STREAMON: + case VIDIOC_G_INPUT: + case VIDIOC_OVERLAY: + case VIDIOC_S_INPUT: + { + int *p=arg; + printk ("%s: value=%d\n", s, *p); + break; + } + case MSP_SET_MATRIX: + { + struct msp_matrix *p=arg; + printk ("%s: input=%d, output=%d\n", s, p->input, p->output); + break; + } + case VIDIOC_G_AUDIO: + case VIDIOC_S_AUDIO: + case VIDIOC_ENUMAUDIO: + case VIDIOC_G_AUDIO_OLD: + { + struct v4l2_audio *p=arg; + + printk ("%s: index=%d, name=%s, capability=%d, mode=%d\n", + s,p->index, p->name,p->capability, p->mode); + break; + } + case VIDIOC_G_AUDOUT: + case VIDIOC_S_AUDOUT: + case VIDIOC_ENUMAUDOUT: + case VIDIOC_G_AUDOUT_OLD: + { + struct v4l2_audioout *p=arg; + printk ("%s: index=%d, name=%s, capability=%d, mode=%d\n", s, + p->index, p->name, p->capability,p->mode); + break; + } + case VIDIOC_QBUF: + case VIDIOC_DQBUF: + case VIDIOC_QUERYBUF: + { + struct v4l2_buffer *p=arg; + struct v4l2_timecode *tc=&p->timecode; + printk ("%s: %02ld:%02d:%02d.%08ld index=%d, type=%d, " + "bytesused=%d, flags=0x%08d, " + "field=%0d, sequence=%d, memory=%d, offset/userptr=0x%08lx,", + s, + (p->timestamp.tv_sec/3600), + (int)(p->timestamp.tv_sec/60)%60, + (int)(p->timestamp.tv_sec%60), + p->timestamp.tv_usec, + p->index,p->type,p->bytesused,p->flags, + p->field,p->sequence,p->memory,p->m.userptr); + printk ("%s: timecode= %02d:%02d:%02d type=%d, " + "flags=0x%08d, frames=%d, userbits=0x%08x", + s,tc->hours,tc->minutes,tc->seconds, + tc->type, tc->flags, tc->frames, (__u32) tc->userbits); + break; + } + case VIDIOC_QUERYCAP: + { + struct v4l2_capability *p=arg; + printk ("%s: driver=%s, card=%s, bus=%s, version=%d, " + "capabilities=%d\n", s, + p->driver,p->card,p->bus_info, + p->version, + p->capabilities); + break; + } + case VIDIOC_G_CTRL: + case VIDIOC_S_CTRL: + case VIDIOC_S_CTRL_OLD: + { + struct v4l2_control *p=arg; + printk ("%s: id=%d, value=%d\n", s, p->id, p->value); + break; + } + case VIDIOC_G_CROP: + case VIDIOC_S_CROP: + { + struct v4l2_crop *p=arg; + /*FIXME: Should also show rect structs */ + printk ("%s: type=%d\n", s, p->type); + break; + } + case VIDIOC_CROPCAP: + case VIDIOC_CROPCAP_OLD: + { + struct v4l2_cropcap *p=arg; + /*FIXME: Should also show rect structs */ + printk ("%s: type=%d\n", s, p->type); + break; + } + case VIDIOC_INT_DECODE_VBI_LINE: + { + struct v4l2_decode_vbi_line *p=arg; + printk ("%s: is_second_field=%d, ptr=0x%08lx, line=%d, " + "type=%d\n", s, + p->is_second_field,(unsigned long)p->p,p->line,p->type); + break; + } + case VIDIOC_ENUM_FMT: + { + struct v4l2_fmtdesc *p=arg; + printk ("%s: index=%d, type=%d, flags=%d, description=%s," + " pixelformat=%d\n", s, + p->index, p->type, p->flags,p->description, + p->pixelformat); + + break; + } + case VIDIOC_G_FMT: + case VIDIOC_S_FMT: + case VIDIOC_TRY_FMT: + { + struct v4l2_format *p=arg; + /* FIXME: Should be one dump per type*/ + printk ("%s: type=%d\n", s,p->type); + break; + } + case VIDIOC_G_FBUF: + case VIDIOC_S_FBUF: + { + struct v4l2_framebuffer *p=arg; + /*FIXME: should show also struct v4l2_pix_format p->fmt field */ + printk ("%s: capability=%d, flags=%d, base=0x%08lx\n", s, + p->capability,p->flags, (unsigned long)p->base); + break; + } + case VIDIOC_G_FREQUENCY: + case VIDIOC_S_FREQUENCY: + { + struct v4l2_frequency *p=arg; + printk ("%s: tuner=%d, type=%d, frequency=%d\n", s, + p->tuner,p->type,p->frequency); + break; + } + case VIDIOC_ENUMINPUT: + { + struct v4l2_input *p=arg; + printk ("%s: index=%d, name=%s, type=%d, audioset=%d, " + "tuner=%d, std=%lld, status=%d\n", s, + p->index,p->name,p->type,p->audioset, + p->tuner,p->std, + p->status); + break; + } + case VIDIOC_G_JPEGCOMP: + case VIDIOC_S_JPEGCOMP: + { + struct v4l2_jpegcompression *p=arg; + printk ("%s: quality=%d, APPn=%d, APP_len=%d, COM_len=%d," + " jpeg_markers=%d\n", s, + p->quality,p->APPn,p->APP_len, + p->COM_len,p->jpeg_markers); + break; + } + case VIDIOC_G_MODULATOR: + case VIDIOC_S_MODULATOR: + { + struct v4l2_modulator *p=arg; + printk ("%s: index=%d, name=%s, capability=%d, rangelow=%d," + " rangehigh=%d, txsubchans=%d\n", s, + p->index, p->name,p->capability,p->rangelow, + p->rangehigh,p->txsubchans); + break; + } + case VIDIOC_G_MPEGCOMP: + case VIDIOC_S_MPEGCOMP: + { + struct v4l2_mpeg_compression *p=arg; + /*FIXME: Several fields not shown */ + printk ("%s: ts_pid_pmt=%d, ts_pid_audio=%d, ts_pid_video=%d, " + "ts_pid_pcr=%d, ps_size=%d, au_sample_rate=%d, " + "au_pesid=%c, vi_frame_rate=%d, vi_frames_per_gop=%d, " + "vi_bframes_count=%d, vi_pesid=%c\n", s, + p->ts_pid_pmt,p->ts_pid_audio, p->ts_pid_video, + p->ts_pid_pcr, p->ps_size, p->au_sample_rate, + p->au_pesid, p->vi_frame_rate, + p->vi_frames_per_gop, p->vi_bframes_count, + p->vi_pesid); + break; + } + case VIDIOC_ENUMOUTPUT: + { + struct v4l2_output *p=arg; + printk ("%s: index=%d, name=%s,type=%d, audioset=%d, " + "modulator=%d, std=%lld\n", + s,p->index,p->name,p->type,p->audioset, + p->modulator,p->std); + break; + } + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *p=arg; + printk ("%s: id=%d, type=%d, name=%s, min/max=%d/%d," + " step=%d, default=%d, flags=0x%08x\n", s, + p->id,p->type,p->name,p->minimum,p->maximum, + p->step,p->default_value,p->flags); + break; + } + case VIDIOC_QUERYMENU: + { + struct v4l2_querymenu *p=arg; + printk ("%s: id=%d, index=%d, name=%s\n", s, + p->id,p->index,p->name); + break; + } + case VIDIOC_INT_G_REGISTER: + case VIDIOC_INT_S_REGISTER: + { + struct v4l2_register *p=arg; + printk ("%s: i2c_id=%d, reg=%lu, val=%d\n", s, + p->i2c_id,p->reg,p->val); + + break; + } + case VIDIOC_REQBUFS: + { + struct v4l2_requestbuffers *p=arg; + printk ("%s: count=%d, type=%d, memory=%d\n", s, + p->count,p->type,p->memory); + break; + } + case VIDIOC_INT_S_AUDIO_ROUTING: + case VIDIOC_INT_S_VIDEO_ROUTING: + case VIDIOC_INT_G_AUDIO_ROUTING: + case VIDIOC_INT_G_VIDEO_ROUTING: + { + struct v4l2_routing *p=arg; + printk ("%s: input=%d, output=%d\n", s, p->input, p->output); + break; + } + case VIDIOC_G_SLICED_VBI_CAP: + { + struct v4l2_sliced_vbi_cap *p=arg; + printk ("%s: service_set=%d\n", s, + p->service_set); + break; + } + case VIDIOC_INT_S_VBI_DATA: + case VIDIOC_INT_G_VBI_DATA: + { + struct v4l2_sliced_vbi_data *p=arg; + printk ("%s: id=%d, field=%d, line=%d\n", s, + p->id, p->field, p->line); + break; + } + case VIDIOC_ENUMSTD: + { + struct v4l2_standard *p=arg; + printk ("%s: index=%d, id=%lld, name=%s, fps=%d/%d, framelines=%d\n", s, + p->index, p->id, p->name, + p->frameperiod.numerator, + p->frameperiod.denominator, + p->framelines); + + break; + } + case VIDIOC_G_PARM: + case VIDIOC_S_PARM: + case VIDIOC_S_PARM_OLD: + { + struct v4l2_streamparm *p=arg; + printk ("%s: type=%d\n", s, p->type); + + break; + } + case VIDIOC_G_TUNER: + case VIDIOC_S_TUNER: + { + struct v4l2_tuner *p=arg; + printk ("%s: index=%d, name=%s, type=%d, capability=%d, " + "rangelow=%d, rangehigh=%d, signal=%d, afc=%d, " + "rxsubchans=%d, audmode=%d\n", s, + p->index, p->name, p->type, + p->capability, p->rangelow,p->rangehigh, + p->rxsubchans, p->audmode, p->signal, + p->afc); + break; + } + case VIDIOCGVBIFMT: + case VIDIOCSVBIFMT: + { + struct vbi_format *p=arg; + printk ("%s: sampling_rate=%d, samples_per_line=%d, " + "sample_format=%d, start=%d/%d, count=%d/%d, flags=%d\n", s, + p->sampling_rate,p->samples_per_line, + p->sample_format,p->start[0],p->start[1], + p->count[0],p->count[1],p->flags); + break; + } + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + { + struct video_audio *p=arg; + printk ("%s: audio=%d, volume=%d, bass=%d, treble=%d, " + "flags=%d, name=%s, mode=%d, balance=%d, step=%d\n", + s,p->audio,p->volume,p->bass, p->treble, + p->flags,p->name,p->mode,p->balance,p->step); + break; + } + case VIDIOCGFBUF: + case VIDIOCSFBUF: + { + struct video_buffer *p=arg; + printk ("%s: base=%08lx, height=%d, width=%d, depth=%d, " + "bytesperline=%d\n", s, + (unsigned long) p->base, p->height, p->width, + p->depth,p->bytesperline); + break; + } + case VIDIOCGCAP: + { + struct video_capability *p=arg; + printk ("%s: name=%s, type=%d, channels=%d, audios=%d, " + "maxwidth=%d, maxheight=%d, minwidth=%d, minheight=%d\n", + s,p->name,p->type,p->channels,p->audios, + p->maxwidth,p->maxheight,p->minwidth, + p->minheight); + + break; + } + case VIDIOCGCAPTURE: + case VIDIOCSCAPTURE: + { + struct video_capture *p=arg; + printk ("%s: x=%d, y=%d, width=%d, height=%d, decimation=%d," + " flags=%d\n", s, + p->x, p->y,p->width, p->height, + p->decimation,p->flags); + break; + } + case VIDIOCGCHAN: + case VIDIOCSCHAN: + { + struct video_channel *p=arg; + printk ("%s: channel=%d, name=%s, tuners=%d, flags=%d, " + "type=%d, norm=%d\n", s, + p->channel,p->name,p->tuners, + p->flags,p->type,p->norm); + + break; + } + case VIDIOCSMICROCODE: + { + struct video_code *p=arg; + printk ("%s: loadwhat=%s, datasize=%d\n", s, + p->loadwhat,p->datasize); + break; + } + case DECODER_GET_CAPABILITIES: + { + struct video_decoder_capability *p=arg; + printk ("%s: flags=%d, inputs=%d, outputs=%d\n", s, + p->flags,p->inputs,p->outputs); + break; + } + case DECODER_INIT: + { + struct video_decoder_init *p=arg; + printk ("%s: len=%c\n", s, p->len); + break; + } + case VIDIOCGPLAYINFO: + { + struct video_info *p=arg; + printk ("%s: frame_count=%d, h_size=%d, v_size=%d, " + "smpte_timecode=%d, picture_type=%d, " + "temporal_reference=%d, user_data=%s\n", s, + p->frame_count, p->h_size, + p->v_size, p->smpte_timecode, + p->picture_type, p->temporal_reference, + p->user_data); + break; + } + case VIDIOCKEY: + { + struct video_key *p=arg; + printk ("%s: key=%s, flags=%d\n", s, + p->key, p->flags); + break; + } + case VIDIOCGMBUF: + { + struct video_mbuf *p=arg; + printk ("%s: size=%d, frames=%d, offsets=0x%08lx\n", s, + p->size, + p->frames, + (unsigned long)p->offsets); + break; + } + case VIDIOCMCAPTURE: + { + struct video_mmap *p=arg; + printk ("%s: frame=%d, height=%d, width=%d, format=%d\n", s, + p->frame, + p->height, p->width, + p->format); + break; + } + case VIDIOCGPICT: + case VIDIOCSPICT: + case DECODER_SET_PICTURE: + { + struct video_picture *p=arg; + + printk ("%s: brightness=%d, hue=%d, colour=%d, contrast=%d," + " whiteness=%d, depth=%d, palette=%d\n", s, + p->brightness, p->hue, p->colour, + p->contrast, p->whiteness, p->depth, + p->palette); + break; + } + case VIDIOCSPLAYMODE: + { + struct video_play_mode *p=arg; + printk ("%s: mode=%d, p1=%d, p2=%d\n", s, + p->mode,p->p1,p->p2); + break; + } + case VIDIOCGTUNER: + case VIDIOCSTUNER: + { + struct video_tuner *p=arg; + printk ("%s: tuner=%d, name=%s, rangelow=%ld, rangehigh=%ld, " + "flags=%d, mode=%d, signal=%d\n", s, + p->tuner, p->name,p->rangelow, p->rangehigh, + p->flags,p->mode, p->signal); + break; + } + case VIDIOCGUNIT: + { + struct video_unit *p=arg; + printk ("%s: video=%d, vbi=%d, radio=%d, audio=%d, " + "teletext=%d\n", s, + p->video,p->vbi,p->radio,p->audio,p->teletext); + break; + } + case VIDIOCGWIN: + case VIDIOCSWIN: + { + struct video_window *p=arg; + printk ("%s: x=%d, y=%d, width=%d, height=%d, chromakey=%d," + " flags=%d, clipcount=%d\n", s, + p->x, p->y,p->width, p->height, + p->chromakey,p->flags, + p->clipcount); + break; + } + case VIDIOC_INT_AUDIO_CLOCK_FREQ: + case VIDIOC_INT_I2S_CLOCK_FREQ: + case VIDIOC_INT_S_STANDBY: + { + u32 *p=arg; + + printk ("%s: value=%d\n", s, *p); + break; + } + case VIDIOCGFREQ: + case VIDIOCSFREQ: + { + unsigned long *p=arg; + printk ("%s: value=%lu\n", s, *p); + break; + } + case VIDIOC_G_STD: + case VIDIOC_S_STD: + case VIDIOC_QUERYSTD: + { + v4l2_std_id *p=arg; + + printk ("%s: value=%llu\n", s, *p); + break; + } + } +} + /* ----------------------------------------------------------------- */ EXPORT_SYMBOL(v4l2_video_std_construct); @@ -376,6 +899,7 @@ EXPORT_SYMBOL(v4l2_prio_check); EXPORT_SYMBOL(v4l2_field_names); EXPORT_SYMBOL(v4l2_type_names); EXPORT_SYMBOL(v4l_printk_ioctl); +EXPORT_SYMBOL(v4l_printk_ioctl_arg); /* * Local variables: diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 234e9cf7e844..c44741e78f20 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -58,6 +58,9 @@ /* Prints the ioctl in a human-readable format */ extern void v4l_printk_ioctl(unsigned int cmd); +/* Prints the ioctl and arg in a human-readable format */ +extern void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg); + /* Use this macro for non-I2C drivers. Pass the driver name as the first arg. */ #define v4l_print_ioctl(name, cmd) \ do { \ @@ -185,11 +188,11 @@ struct msp_matrix { register contains invalid or erroneous data -EIO is returned. Note that you must fill in the 'id' member and the 'field' member (to determine whether CC data from the first or second field should be obtained). */ -#define VIDIOC_INT_G_VBI_DATA _IOWR('d', 106, struct v4l2_sliced_vbi_data *) +#define VIDIOC_INT_G_VBI_DATA _IOWR('d', 106, struct v4l2_sliced_vbi_data) /* Returns the chip identifier or V4L2_IDENT_UNKNOWN if no identification can be made. */ -#define VIDIOC_INT_G_CHIP_IDENT _IOR ('d', 107, enum v4l2_chip_ident *) +#define VIDIOC_INT_G_CHIP_IDENT _IOR ('d', 107, enum v4l2_chip_ident) /* Sets I2S speed in bps. This is used to provide a standard way to select I2S clock used by driving digital audio streams at some board designs. @@ -214,8 +217,8 @@ struct v4l2_routing { These four commands should only be sent directly to an i2c device, they should not be broadcast as the routing is very device specific. */ #define VIDIOC_INT_S_AUDIO_ROUTING _IOW ('d', 109, struct v4l2_routing) -#define VIDIOC_INT_G_AUDIO_ROUTING _IOR ('d', 110, struct v4l2_routing *) +#define VIDIOC_INT_G_AUDIO_ROUTING _IOR ('d', 110, struct v4l2_routing) #define VIDIOC_INT_S_VIDEO_ROUTING _IOW ('d', 111, struct v4l2_routing) -#define VIDIOC_INT_G_VIDEO_ROUTING _IOR ('d', 112, struct v4l2_routing *) +#define VIDIOC_INT_G_VIDEO_ROUTING _IOR ('d', 112, struct v4l2_routing) #endif /* V4L2_COMMON_H_ */ -- cgit v1.2.3 From f05cce863fa399dd79c5aa3896d608b8b86d8030 Mon Sep 17 00:00:00 2001 From: Andreas Oberritter Date: Mon, 27 Feb 2006 00:09:00 -0300 Subject: V4L/DVB (3375): Add AUDIO_GET_PTS and VIDEO_GET_PTS ioctls Add two new ioctls to read the 33 bit presentation time stamp from audio and video devices as defined in ITU T-REC-H.222.0 and ISO/IEC 13818-1. Acked-by: Johannes Stezenbach Signed-off-by: Andreas Oberritter Signed-off-by: Mauro Carvalho Chehab --- include/linux/dvb/audio.h | 13 +++++++++++++ include/linux/dvb/video.h | 13 +++++++++++++ 2 files changed, 26 insertions(+) (limited to 'include') diff --git a/include/linux/dvb/audio.h b/include/linux/dvb/audio.h index 2b8797084685..0874a67c6b92 100644 --- a/include/linux/dvb/audio.h +++ b/include/linux/dvb/audio.h @@ -121,4 +121,17 @@ typedef uint16_t audio_attributes_t; #define AUDIO_SET_ATTRIBUTES _IOW('o', 17, audio_attributes_t) #define AUDIO_SET_KARAOKE _IOW('o', 18, audio_karaoke_t) +/** + * AUDIO_GET_PTS + * + * Read the 33 bit presentation time stamp as defined + * in ITU T-REC-H.222.0 / ISO/IEC 13818-1. + * + * The PTS should belong to the currently played + * frame if possible, but may also be a value close to it + * like the PTS of the last decoded frame or the last PTS + * extracted by the PES parser. + */ +#define AUDIO_GET_PTS _IOR('o', 19, __u64) + #endif /* _DVBAUDIO_H_ */ diff --git a/include/linux/dvb/video.h b/include/linux/dvb/video.h index b1999bfeaa56..1f7fa0351daf 100644 --- a/include/linux/dvb/video.h +++ b/include/linux/dvb/video.h @@ -200,4 +200,17 @@ typedef uint16_t video_attributes_t; #define VIDEO_GET_SIZE _IOR('o', 55, video_size_t) #define VIDEO_GET_FRAME_RATE _IOR('o', 56, unsigned int) +/** + * VIDEO_GET_PTS + * + * Read the 33 bit presentation time stamp as defined + * in ITU T-REC-H.222.0 / ISO/IEC 13818-1. + * + * The PTS should belong to the currently played + * frame if possible, but may also be a value close to it + * like the PTS of the last decoded frame or the last PTS + * extracted by the PES parser. + */ +#define VIDEO_GET_PTS _IOR('o', 57, __u64) + #endif /*_DVBVIDEO_H_*/ -- cgit v1.2.3 From 7aa6ba41362a7f888ad11fdcfe51ca8d92226cd3 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Fri, 17 Feb 2006 05:18:43 -0500 Subject: [IA64-SGI] SN2-XP reduce kmalloc wrapper inlining Take advantage of kzalloc() as well as reduce the size of code generated for the error returns in xpc_setup_infrastructure(). Signed-off-by: Jes Sorensen Acked-by: Dean Nelson Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/xpc_channel.c | 102 +++++++++++++++++++++--------------- arch/ia64/sn/kernel/xpc_main.c | 1 - arch/ia64/sn/kernel/xpc_partition.c | 28 +++++++++- include/asm-ia64/sn/xpc.h | 22 -------- 4 files changed, 85 insertions(+), 68 deletions(-) (limited to 'include') diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c index cdf6856ce089..d0abddd9ffe6 100644 --- a/arch/ia64/sn/kernel/xpc_channel.c +++ b/arch/ia64/sn/kernel/xpc_channel.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -29,6 +28,31 @@ #include +/* + * Guarantee that the kzalloc'd memory is cacheline aligned. + */ +static void * +xpc_kzalloc_cacheline_aligned(size_t size, gfp_t flags, void **base) +{ + /* see if kzalloc will give us cachline aligned memory by default */ + *base = kzalloc(size, flags); + if (*base == NULL) { + return NULL; + } + if ((u64) *base == L1_CACHE_ALIGN((u64) *base)) { + return *base; + } + kfree(*base); + + /* nope, we'll have to do it ourselves */ + *base = kzalloc(size + L1_CACHE_BYTES, flags); + if (*base == NULL) { + return NULL; + } + return (void *) L1_CACHE_ALIGN((u64) *base); +} + + /* * Set up the initial values for the XPartition Communication channels. */ @@ -93,20 +117,19 @@ xpc_setup_infrastructure(struct xpc_partition *part) * Allocate all of the channel structures as a contiguous chunk of * memory. */ - part->channels = kmalloc(sizeof(struct xpc_channel) * XPC_NCHANNELS, + part->channels = kzalloc(sizeof(struct xpc_channel) * XPC_NCHANNELS, GFP_KERNEL); if (part->channels == NULL) { dev_err(xpc_chan, "can't get memory for channels\n"); return xpcNoMemory; } - memset(part->channels, 0, sizeof(struct xpc_channel) * XPC_NCHANNELS); part->nchannels = XPC_NCHANNELS; /* allocate all the required GET/PUT values */ - part->local_GPs = xpc_kmalloc_cacheline_aligned(XPC_GP_SIZE, + part->local_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE, GFP_KERNEL, &part->local_GPs_base); if (part->local_GPs == NULL) { kfree(part->channels); @@ -115,55 +138,51 @@ xpc_setup_infrastructure(struct xpc_partition *part) "values\n"); return xpcNoMemory; } - memset(part->local_GPs, 0, XPC_GP_SIZE); - part->remote_GPs = xpc_kmalloc_cacheline_aligned(XPC_GP_SIZE, + part->remote_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE, GFP_KERNEL, &part->remote_GPs_base); if (part->remote_GPs == NULL) { - kfree(part->channels); - part->channels = NULL; - kfree(part->local_GPs_base); - part->local_GPs = NULL; dev_err(xpc_chan, "can't get memory for remote get/put " "values\n"); + kfree(part->local_GPs_base); + part->local_GPs = NULL; + kfree(part->channels); + part->channels = NULL; return xpcNoMemory; } - memset(part->remote_GPs, 0, XPC_GP_SIZE); /* allocate all the required open and close args */ - part->local_openclose_args = xpc_kmalloc_cacheline_aligned( + part->local_openclose_args = xpc_kzalloc_cacheline_aligned( XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL, &part->local_openclose_args_base); if (part->local_openclose_args == NULL) { - kfree(part->channels); - part->channels = NULL; - kfree(part->local_GPs_base); - part->local_GPs = NULL; + dev_err(xpc_chan, "can't get memory for local connect args\n"); kfree(part->remote_GPs_base); part->remote_GPs = NULL; - dev_err(xpc_chan, "can't get memory for local connect args\n"); + kfree(part->local_GPs_base); + part->local_GPs = NULL; + kfree(part->channels); + part->channels = NULL; return xpcNoMemory; } - memset(part->local_openclose_args, 0, XPC_OPENCLOSE_ARGS_SIZE); - part->remote_openclose_args = xpc_kmalloc_cacheline_aligned( + part->remote_openclose_args = xpc_kzalloc_cacheline_aligned( XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL, &part->remote_openclose_args_base); if (part->remote_openclose_args == NULL) { - kfree(part->channels); - part->channels = NULL; - kfree(part->local_GPs_base); - part->local_GPs = NULL; - kfree(part->remote_GPs_base); - part->remote_GPs = NULL; + dev_err(xpc_chan, "can't get memory for remote connect args\n"); kfree(part->local_openclose_args_base); part->local_openclose_args = NULL; - dev_err(xpc_chan, "can't get memory for remote connect args\n"); + kfree(part->remote_GPs_base); + part->remote_GPs = NULL; + kfree(part->local_GPs_base); + part->local_GPs = NULL; + kfree(part->channels); + part->channels = NULL; return xpcNoMemory; } - memset(part->remote_openclose_args, 0, XPC_OPENCLOSE_ARGS_SIZE); xpc_initialize_channels(part, partid); @@ -186,18 +205,18 @@ xpc_setup_infrastructure(struct xpc_partition *part) ret = request_irq(SGI_XPC_NOTIFY, xpc_notify_IRQ_handler, SA_SHIRQ, part->IPI_owner, (void *) (u64) partid); if (ret != 0) { - kfree(part->channels); - part->channels = NULL; - kfree(part->local_GPs_base); - part->local_GPs = NULL; - kfree(part->remote_GPs_base); - part->remote_GPs = NULL; - kfree(part->local_openclose_args_base); - part->local_openclose_args = NULL; - kfree(part->remote_openclose_args_base); - part->remote_openclose_args = NULL; dev_err(xpc_chan, "can't register NOTIFY IRQ handler, " "errno=%d\n", -ret); + kfree(part->remote_openclose_args_base); + part->remote_openclose_args = NULL; + kfree(part->local_openclose_args_base); + part->local_openclose_args = NULL; + kfree(part->remote_GPs_base); + part->remote_GPs = NULL; + kfree(part->local_GPs_base); + part->local_GPs = NULL; + kfree(part->channels); + part->channels = NULL; return xpcLackOfResources; } @@ -446,22 +465,20 @@ xpc_allocate_local_msgqueue(struct xpc_channel *ch) for (nentries = ch->local_nentries; nentries > 0; nentries--) { nbytes = nentries * ch->msg_size; - ch->local_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes, + ch->local_msgqueue = xpc_kzalloc_cacheline_aligned(nbytes, GFP_KERNEL, &ch->local_msgqueue_base); if (ch->local_msgqueue == NULL) { continue; } - memset(ch->local_msgqueue, 0, nbytes); nbytes = nentries * sizeof(struct xpc_notify); - ch->notify_queue = kmalloc(nbytes, GFP_KERNEL); + ch->notify_queue = kzalloc(nbytes, GFP_KERNEL); if (ch->notify_queue == NULL) { kfree(ch->local_msgqueue_base); ch->local_msgqueue = NULL; continue; } - memset(ch->notify_queue, 0, nbytes); spin_lock_irqsave(&ch->lock, irq_flags); if (nentries < ch->local_nentries) { @@ -501,13 +518,12 @@ xpc_allocate_remote_msgqueue(struct xpc_channel *ch) for (nentries = ch->remote_nentries; nentries > 0; nentries--) { nbytes = nentries * ch->msg_size; - ch->remote_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes, + ch->remote_msgqueue = xpc_kzalloc_cacheline_aligned(nbytes, GFP_KERNEL, &ch->remote_msgqueue_base); if (ch->remote_msgqueue == NULL) { continue; } - memset(ch->remote_msgqueue, 0, nbytes); spin_lock_irqsave(&ch->lock, irq_flags); if (nentries < ch->remote_nentries) { diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c index 8cbf16432570..99b123a6421a 100644 --- a/arch/ia64/sn/kernel/xpc_main.c +++ b/arch/ia64/sn/kernel/xpc_main.c @@ -52,7 +52,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c index 88a730e6cfdb..94211429fd0c 100644 --- a/arch/ia64/sn/kernel/xpc_partition.c +++ b/arch/ia64/sn/kernel/xpc_partition.c @@ -80,6 +80,31 @@ char ____cacheline_aligned xpc_remote_copy_buffer[XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES]; +/* + * Guarantee that the kmalloc'd memory is cacheline aligned. + */ +static void * +xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base) +{ + /* see if kmalloc will give us cachline aligned memory by default */ + *base = kmalloc(size, flags); + if (*base == NULL) { + return NULL; + } + if ((u64) *base == L1_CACHE_ALIGN((u64) *base)) { + return *base; + } + kfree(*base); + + /* nope, we'll have to do it ourselves */ + *base = kmalloc(size + L1_CACHE_BYTES, flags); + if (*base == NULL) { + return NULL; + } + return (void *) L1_CACHE_ALIGN((u64) *base); +} + + /* * Given a nasid, get the physical address of the partition's reserved page * for that nasid. This function returns 0 on any error. @@ -1038,13 +1063,12 @@ xpc_discovery(void) remote_vars = (struct xpc_vars *) remote_rp; - discovered_nasids = kmalloc(sizeof(u64) * xp_nasid_mask_words, + discovered_nasids = kzalloc(sizeof(u64) * xp_nasid_mask_words, GFP_KERNEL); if (discovered_nasids == NULL) { kfree(remote_rp_base); return; } - memset(discovered_nasids, 0, sizeof(u64) * xp_nasid_mask_words); rp = (struct xpc_rsvd_page *) xpc_rsvd_page; diff --git a/include/asm-ia64/sn/xpc.h b/include/asm-ia64/sn/xpc.h index df7f5f4f3cde..aa3b8ace9030 100644 --- a/include/asm-ia64/sn/xpc.h +++ b/include/asm-ia64/sn/xpc.h @@ -1227,28 +1227,6 @@ xpc_map_bte_errors(bte_result_t error) -static inline void * -xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base) -{ - /* see if kmalloc will give us cachline aligned memory by default */ - *base = kmalloc(size, flags); - if (*base == NULL) { - return NULL; - } - if ((u64) *base == L1_CACHE_ALIGN((u64) *base)) { - return *base; - } - kfree(*base); - - /* nope, we'll have to do it ourselves */ - *base = kmalloc(size + L1_CACHE_BYTES, flags); - if (*base == NULL) { - return NULL; - } - return (void *) L1_CACHE_ALIGN((u64) *base); -} - - /* * Check to see if there is any channel activity to/from the specified * partition. -- cgit v1.2.3 From c67a848c3587296fe9794c95d1be7109c4c85461 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 17 Jan 2006 11:54:24 -0700 Subject: [SCSI] Neaten comments in scsi_cmnd.h Wrap these two comments at 80 columns Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- include/scsi/scsi_cmnd.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 7529f4388bb4..1ace1b9fe537 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -104,10 +104,10 @@ struct scsi_cmnd { working on */ #define SCSI_SENSE_BUFFERSIZE 96 - unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE]; /* obtained by REQUEST SENSE - * when CHECK CONDITION is - * received on original command - * (auto-sense) */ + unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE]; + /* obtained by REQUEST SENSE when + * CHECK CONDITION is received on original + * command (auto-sense) */ /* Low-level done function - can be used by low-level driver to point * to completion function. Not used by mid/upper level code. */ @@ -120,12 +120,12 @@ struct scsi_cmnd { struct scsi_pointer SCp; /* Scratchpad used by some host adapters */ unsigned char *host_scribble; /* The host adapter is allowed to - * call scsi_malloc and get some memory - * and hang it here. The host adapter - * is also expected to call scsi_free - * to release this memory. (The memory - * obtained by scsi_malloc is guaranteed - * to be at an address < 16Mb). */ + * call scsi_malloc and get some memory + * and hang it here. The host adapter + * is also expected to call scsi_free + * to release this memory. (The memory + * obtained by scsi_malloc is guaranteed + * to be at an address < 16Mb). */ int result; /* Status code from lower level driver */ -- cgit v1.2.3 From 5e3c34c1e988a0dfe177c38cf324e8e321c55ef5 Mon Sep 17 00:00:00 2001 From: Greg KH Date: Wed, 18 Jan 2006 16:17:46 -0800 Subject: [SCSI] Remove devfs support from the SCSI subsystem As devfs has been disabled from the kernel tree for a number of months now (5 to be exact), here's a patch against 2.6.16-rc1-git1 that removes support for it from the SCSI subsystem. The patch also removes the scsi_disk devfs_name field as it's no longer needed. Signed-off-by: Greg Kroah-Hartman Signed-off-by: James Bottomley --- drivers/scsi/osst.c | 24 ++---------------------- drivers/scsi/scsi.c | 3 --- drivers/scsi/scsi_scan.c | 6 +----- drivers/scsi/sd.c | 2 -- drivers/scsi/sg.c | 10 ++-------- drivers/scsi/sr.c | 2 -- drivers/scsi/st.c | 20 -------------------- include/scsi/scsi_device.h | 1 - 8 files changed, 5 insertions(+), 63 deletions(-) (limited to 'include') diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index d9946bd95492..b9f6084fdd9e 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -48,7 +48,6 @@ static const char * osst_version = "0.99.3"; #include #include #include -#include #include #include #include @@ -107,8 +106,6 @@ static struct osst_dev_parm { }; #endif -static char *osst_formats[ST_NBR_MODES] ={"", "l", "m", "a"}; - /* Some default definitions have been moved to osst_options.h */ #define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE) #define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE) @@ -5667,7 +5664,7 @@ static int osst_probe(struct device *dev) struct st_partstat * STps; struct osst_buffer * buffer; struct gendisk * drive; - int i, mode, dev_num; + int i, dev_num; if (SDp->type != TYPE_TAPE || !osst_supports(SDp)) return -ENODEV; @@ -5803,18 +5800,6 @@ static int osst_probe(struct device *dev) snprintf(name, 8, "%s%s", "n", tape_name(tpnt)); osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name); } - for (mode = 0; mode < ST_NBR_MODES; ++mode) { - /* Rewind entry */ - devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5)), - S_IFCHR | S_IRUGO | S_IWUGO, - "%s/ot%s", SDp->devfs_name, osst_formats[mode]); - - /* No-rewind entry */ - devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5) + 128), - S_IFCHR | S_IRUGO | S_IWUGO, - "%s/ot%sn", SDp->devfs_name, osst_formats[mode]); - } - drive->number = devfs_register_tape(SDp->devfs_name); sdev_printk(KERN_INFO, SDp, "osst :I: Attached OnStream %.5s tape as %s\n", @@ -5831,7 +5816,7 @@ static int osst_remove(struct device *dev) { struct scsi_device * SDp = to_scsi_device(dev); struct osst_tape * tpnt; - int i, mode; + int i; if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0)) return 0; @@ -5842,11 +5827,6 @@ static int osst_remove(struct device *dev) osst_sysfs_destroy(MKDEV(OSST_MAJOR, i)); osst_sysfs_destroy(MKDEV(OSST_MAJOR, i+128)); tpnt->device = NULL; - for (mode = 0; mode < ST_NBR_MODES; ++mode) { - devfs_remove("%s/ot%s", SDp->devfs_name, osst_formats[mode]); - devfs_remove("%s/ot%sn", SDp->devfs_name, osst_formats[mode]); - } - devfs_unregister_tape(tpnt->drive->number); put_disk(tpnt->drive); os_scsi_tapes[i] = NULL; osst_nr_dev--; diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 11b27ba0cd41..6913b0623167 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -48,7 +48,6 @@ #include #include #include -#include #include #include #include @@ -1247,7 +1246,6 @@ static int __init init_scsi(void) for_each_cpu(i) INIT_LIST_HEAD(&per_cpu(scsi_done_q, i)); - devfs_mk_dir("scsi"); printk(KERN_NOTICE "SCSI subsystem initialized\n"); return 0; @@ -1272,7 +1270,6 @@ static void __exit exit_scsi(void) scsi_exit_sysctl(); scsi_exit_hosts(); scsi_exit_devinfo(); - devfs_remove("scsi"); scsi_exit_procfs(); scsi_exit_queue(); } diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 74863da1d630..dfdbbd008630 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -687,12 +687,8 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) if (inq_result[7] & 0x10) sdev->sdtr = 1; - sprintf(sdev->devfs_name, "scsi/host%d/bus%d/target%d/lun%d", - sdev->host->host_no, sdev->channel, - sdev->id, sdev->lun); - /* - * End driverfs/devfs code. + * End sysfs code. */ if ((sdev->scsi_level >= SCSI_2) && (inq_result[7] & 2) && diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8ba2d988d051..76b4d14c0b3f 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1571,8 +1571,6 @@ static int sd_probe(struct device *dev) 'a' + m1, 'a' + m2, 'a' + m3); } - strcpy(gd->devfs_name, sdp->devfs_name); - gd->private_data = &sdkp->driver; gd->queue = sdkp->device->request_queue; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index ecf2f6010e76..06fc8ed720fc 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -44,7 +44,6 @@ static int sg_version_num = 30533; /* 2 digits for each component */ #include #include #include -#include #include #include #include @@ -1456,14 +1455,10 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf) k = error; sdp = sg_dev_arr[k]; - devfs_mk_cdev(MKDEV(SCSI_GENERIC_MAJOR, k), - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, - "%s/generic", scsidp->devfs_name); error = cdev_add(cdev, MKDEV(SCSI_GENERIC_MAJOR, k), 1); - if (error) { - devfs_remove("%s/generic", scsidp->devfs_name); + if (error) goto out; - } + sdp->cdev = cdev; if (sg_sysfs_valid) { struct class_device * sg_class_member; @@ -1553,7 +1548,6 @@ sg_remove(struct class_device *cl_dev, struct class_interface *cl_intf) class_device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, k)); cdev_del(sdp->cdev); sdp->cdev = NULL; - devfs_remove("%s/generic", scsidp->devfs_name); put_disk(sdp->disk); sdp->disk = NULL; if (NULL == sdp->headfp) diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index d8d12a1718bf..328837b7ccb9 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -573,8 +573,6 @@ static int sr_probe(struct device *dev) get_capabilities(cd); sr_vendor_init(cd); - snprintf(disk->devfs_name, sizeof(disk->devfs_name), - "%s/cd", sdev->devfs_name); disk->driverfs_dev = &sdev->sdev_gendev; set_capacity(disk, cd->capacity); disk->private_data = &cd->driver; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index f0606da19d02..31c6eefba9d6 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -35,7 +35,6 @@ static const char *verstr = "20050830"; #include #include #include -#include #include #include #include @@ -4053,21 +4052,6 @@ static int st_probe(struct device *dev) do_create_class_files(tpnt, dev_num, mode); } - for (mode = 0; mode < ST_NBR_MODES; ++mode) { - /* Make sure that the minor numbers corresponding to the four - first modes always get the same names */ - i = mode << (4 - ST_NBR_MODE_BITS); - /* Rewind entry */ - devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, 0)), - S_IFCHR | S_IRUGO | S_IWUGO, - "%s/mt%s", SDp->devfs_name, st_formats[i]); - /* No-rewind entry */ - devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, 1)), - S_IFCHR | S_IRUGO | S_IWUGO, - "%s/mt%sn", SDp->devfs_name, st_formats[i]); - } - disk->number = devfs_register_tape(SDp->devfs_name); - sdev_printk(KERN_WARNING, SDp, "Attached scsi tape %s", tape_name(tpnt)); printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B)\n", @@ -4121,13 +4105,9 @@ static int st_remove(struct device *dev) scsi_tapes[i] = NULL; st_nr_dev--; write_unlock(&st_dev_arr_lock); - devfs_unregister_tape(tpnt->disk->number); sysfs_remove_link(&tpnt->device->sdev_gendev.kobj, "tape"); for (mode = 0; mode < ST_NBR_MODES; ++mode) { - j = mode << (4 - ST_NBR_MODE_BITS); - devfs_remove("%s/mt%s", SDp->devfs_name, st_formats[j]); - devfs_remove("%s/mt%sn", SDp->devfs_name, st_formats[j]); for (j=0; j < 2; j++) { class_device_destroy(st_sysfs_class, MKDEV(SCSI_TAPE_MAJOR, diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 290e3b4d2aec..cde84b39bb65 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -73,7 +73,6 @@ struct scsi_device { unsigned sector_size; /* size in bytes */ void *hostdata; /* available to low-level driver */ - char devfs_name[256]; /* devfs junk */ char type; char scsi_level; char inq_periph_qual; /* PQ from INQUIRY data */ -- cgit v1.2.3 From 6ea3c0b2dac0d6a857d6bc010e544f4c901fff78 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 7 Feb 2006 07:54:46 -0700 Subject: [SCSI] Add spi_populate_*_msg functions Introduce new helpers: - spi_populate_width_msg() - spi_populate_sync_msg() - spi_populate_ppr_msg() and use them in drivers which already enable the SPI transport. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/53c700.c | 18 +++---------- drivers/scsi/aha152x.c | 7 +---- drivers/scsi/aic7xxx/aic79xx_core.c | 24 +++++------------ drivers/scsi/aic7xxx/aic7xxx_core.c | 24 +++++------------ drivers/scsi/ncr53c8xx.c | 25 ++++------------- drivers/scsi/scsi_transport_spi.c | 33 +++++++++++++++++++++++ drivers/scsi/sym53c8xx_2/sym_hipd.c | 53 +++++++++---------------------------- include/scsi/scsi_transport_spi.h | 4 +++ 8 files changed, 73 insertions(+), 115 deletions(-) (limited to 'include') diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 4ce7438608ec..6a0f9506ea00 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -238,14 +238,6 @@ static char *NCR_700_SBCL_to_phase[] = { "MSG IN", }; -static __u8 NCR_700_SDTR_msg[] = { - 0x01, /* Extended message */ - 0x03, /* Extended message Length */ - 0x01, /* SDTR Extended message */ - NCR_700_MIN_PERIOD, - NCR_700_MAX_OFFSET -}; - /* This translates the SDTR message offset and period to a value * which can be loaded into the SXFER_REG. * @@ -266,7 +258,7 @@ NCR_700_offset_period_to_sxfer(struct NCR_700_Host_Parameters *hostdata, return 0; if(period < hostdata->min_period) { - printk(KERN_WARNING "53c700: Period %dns is less than this chip's minimum, setting to %d\n", period*4, NCR_700_SDTR_msg[3]*4); + printk(KERN_WARNING "53c700: Period %dns is less than this chip's minimum, setting to %d\n", period*4, NCR_700_MIN_PERIOD*4); period = hostdata->min_period; } XFERP = (period*4 * hostdata->sync_clock)/1000 - 4; @@ -1434,11 +1426,9 @@ NCR_700_start_command(struct scsi_cmnd *SCp) if(hostdata->fast && NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC)) { - memcpy(&hostdata->msgout[count], NCR_700_SDTR_msg, - sizeof(NCR_700_SDTR_msg)); - hostdata->msgout[count+3] = spi_period(SCp->device->sdev_target); - hostdata->msgout[count+4] = spi_offset(SCp->device->sdev_target); - count += sizeof(NCR_700_SDTR_msg); + count += spi_populate_sync_msg(&hostdata->msgout[count], + spi_period(SCp->device->sdev_target), + spi_offset(SCp->device->sdev_target)); NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); } diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index cb2ee25f213f..67d78ed7119a 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -1708,12 +1708,7 @@ static void seldo_run(struct Scsi_Host *shpnt) ADDMSGO(BUS_DEVICE_RESET); } else if (SYNCNEG==0 && SYNCHRONOUS) { CURRENT_SC->SCp.phase |= syncneg; - ADDMSGO(EXTENDED_MESSAGE); - ADDMSGO(3); - ADDMSGO(EXTENDED_SDTR); - ADDMSGO(50); /* 200ns */ - ADDMSGO(8); /* 8 byte req/ack offset */ - + MSGOLEN += spi_populate_sync_msg(&MSGO(MSGOLEN), 50, 8); SYNCNEG=1; /* negotiation in progress */ } diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 342f77966a5b..b6266fd31688 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -3762,11 +3762,8 @@ ahd_construct_sdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, { if (offset == 0) period = AHD_ASYNC_XFER_PERIOD; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_SDTR_LEN; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_SDTR; - ahd->msgout_buf[ahd->msgout_index++] = period; - ahd->msgout_buf[ahd->msgout_index++] = offset; + ahd->msgout_index += spi_populate_sync_msg( + ahd->msgout_buf + ahd->msgout_index, period, offset); ahd->msgout_len += 5; if (bootverbose) { printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n", @@ -3783,10 +3780,8 @@ static void ahd_construct_wdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, u_int bus_width) { - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR_LEN; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR; - ahd->msgout_buf[ahd->msgout_index++] = bus_width; + ahd->msgout_index += spi_populate_width_msg( + ahd->msgout_buf + ahd->msgout_index, bus_width); ahd->msgout_len += 4; if (bootverbose) { printf("(%s:%c:%d:%d): Sending WDTR %x\n", @@ -3813,14 +3808,9 @@ ahd_construct_ppr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, ppr_options |= MSG_EXT_PPR_PCOMP_EN; if (offset == 0) period = AHD_ASYNC_XFER_PERIOD; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR_LEN; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR; - ahd->msgout_buf[ahd->msgout_index++] = period; - ahd->msgout_buf[ahd->msgout_index++] = 0; - ahd->msgout_buf[ahd->msgout_index++] = offset; - ahd->msgout_buf[ahd->msgout_index++] = bus_width; - ahd->msgout_buf[ahd->msgout_index++] = ppr_options; + ahd->msgout_index += spi_populate_ppr_msg( + ahd->msgout_buf + ahd->msgout_index, period, offset, + bus_width, ppr_options); ahd->msgout_len += 8; if (bootverbose) { printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, " diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index 58ac46103eb6..d37566978fba 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -2461,11 +2461,8 @@ ahc_construct_sdtr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, { if (offset == 0) period = AHC_ASYNC_XFER_PERIOD; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_SDTR_LEN; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_SDTR; - ahc->msgout_buf[ahc->msgout_index++] = period; - ahc->msgout_buf[ahc->msgout_index++] = offset; + ahc->msgout_index += spi_populate_sync_msg( + ahc->msgout_buf + ahc->msgout_index, period, offset); ahc->msgout_len += 5; if (bootverbose) { printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n", @@ -2482,10 +2479,8 @@ static void ahc_construct_wdtr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, u_int bus_width) { - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_WDTR_LEN; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_WDTR; - ahc->msgout_buf[ahc->msgout_index++] = bus_width; + ahc->msgout_index += spi_populate_width_msg( + ahc->msgout_buf + ahc->msgout_index, bus_width); ahc->msgout_len += 4; if (bootverbose) { printf("(%s:%c:%d:%d): Sending WDTR %x\n", @@ -2505,14 +2500,9 @@ ahc_construct_ppr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, { if (offset == 0) period = AHC_ASYNC_XFER_PERIOD; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_PPR_LEN; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_PPR; - ahc->msgout_buf[ahc->msgout_index++] = period; - ahc->msgout_buf[ahc->msgout_index++] = 0; - ahc->msgout_buf[ahc->msgout_index++] = offset; - ahc->msgout_buf[ahc->msgout_index++] = bus_width; - ahc->msgout_buf[ahc->msgout_index++] = ppr_options; + ahc->msgout_index += spi_populate_ppr_msg( + ahc->msgout_buf + ahc->msgout_index, period, offset, + bus_width, ppr_options); ahc->msgout_len += 8; if (bootverbose) { printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, " diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index abb1859bff09..22f913127f08 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -4105,17 +4105,11 @@ static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr) switch (nego) { case NS_SYNC: - msgptr[msglen++] = EXTENDED_MESSAGE; - msgptr[msglen++] = 3; - msgptr[msglen++] = EXTENDED_SDTR; - msgptr[msglen++] = tp->maxoffs ? tp->minsync : 0; - msgptr[msglen++] = tp->maxoffs; + msglen += spi_populate_sync_msg(msgptr + msglen, + tp->maxoffs ? tp->minsync : 0, tp->maxoffs); break; case NS_WIDE: - msgptr[msglen++] = EXTENDED_MESSAGE; - msgptr[msglen++] = 2; - msgptr[msglen++] = EXTENDED_WDTR; - msgptr[msglen++] = tp->usrwide; + msglen += spi_populate_width_msg(msgptr + msglen, tp->usrwide); break; } @@ -6989,12 +6983,7 @@ void ncr_int_sir (struct ncb *np) spi_offset(starget) = ofs; ncr_setsync(np, cp, scntl3, (fak<<5)|ofs); - np->msgout[0] = EXTENDED_MESSAGE; - np->msgout[1] = 3; - np->msgout[2] = EXTENDED_SDTR; - np->msgout[3] = per; - np->msgout[4] = ofs; - + spi_populate_sync_msg(np->msgout, per, ofs); cp->nego_status = NS_SYNC; if (DEBUG_FLAGS & DEBUG_NEGO) { @@ -7080,11 +7069,7 @@ void ncr_int_sir (struct ncb *np) spi_width(starget) = wide; ncr_setwide(np, cp, wide, 1); - - np->msgout[0] = EXTENDED_MESSAGE; - np->msgout[1] = 2; - np->msgout[2] = EXTENDED_WDTR; - np->msgout[3] = wide; + spi_populate_width_msg(np->msgout, wide); np->msgin [0] = NOP; diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 97f4be62f748..c0051a432a97 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -1051,6 +1051,39 @@ void spi_display_xfer_agreement(struct scsi_target *starget) } EXPORT_SYMBOL(spi_display_xfer_agreement); +int spi_populate_width_msg(unsigned char *msg, int width) +{ + msg[0] = EXTENDED_MESSAGE; + msg[1] = 2; + msg[2] = EXTENDED_WDTR; + msg[3] = width; + return 4; +} + +int spi_populate_sync_msg(unsigned char *msg, int period, int offset) +{ + msg[0] = EXTENDED_MESSAGE; + msg[1] = 3; + msg[2] = EXTENDED_SDTR; + msg[3] = period; + msg[4] = offset; + return 5; +} + +int spi_populate_ppr_msg(unsigned char *msg, int period, int offset, + int width, int options) +{ + msg[0] = EXTENDED_MESSAGE; + msg[1] = 6; + msg[2] = EXTENDED_PPR; + msg[3] = period; + msg[4] = 0; + msg[5] = offset; + msg[6] = width; + msg[7] = options; + return 8; +} + #ifdef CONFIG_SCSI_CONSTANTS static const char * const one_byte_msgs[] = { /* 0x00 */ "Command Complete", NULL, "Save Pointers", diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index f4854c33f48d..620b4726fbd9 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -40,7 +40,6 @@ #include #include /* for timeouts in units of HZ */ -#include #include "sym_glue.h" #include "sym_nvram.h" @@ -1430,29 +1429,18 @@ static int sym_prepare_nego(struct sym_hcb *np, struct sym_ccb *cp, u_char *msgp switch (nego) { case NS_SYNC: - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 3; - msgptr[msglen++] = M_X_SYNC_REQ; - msgptr[msglen++] = goal->period; - msgptr[msglen++] = goal->offset; + msglen += spi_populate_sync_msg(msgptr + msglen, goal->period, + goal->offset); break; case NS_WIDE: - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 2; - msgptr[msglen++] = M_X_WIDE_REQ; - msgptr[msglen++] = goal->width; + msglen += spi_populate_width_msg(msgptr + msglen, goal->width); break; case NS_PPR: - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 6; - msgptr[msglen++] = M_X_PPR_REQ; - msgptr[msglen++] = goal->period; - msgptr[msglen++] = 0; - msgptr[msglen++] = goal->offset; - msgptr[msglen++] = goal->width; - msgptr[msglen++] = (goal->iu ? PPR_OPT_IU : 0) | + msglen += spi_populate_ppr_msg(msgptr + msglen, goal->period, + goal->offset, goal->width, + (goal->iu ? PPR_OPT_IU : 0) | (goal->dt ? PPR_OPT_DT : 0) | - (goal->qas ? PPR_OPT_QAS : 0); + (goal->qas ? PPR_OPT_QAS : 0)); break; } @@ -3948,11 +3936,7 @@ sym_sync_nego_check(struct sym_hcb *np, int req, struct sym_ccb *cp) /* * It was a request. Prepare an answer message. */ - np->msgout[0] = M_EXTENDED; - np->msgout[1] = 3; - np->msgout[2] = M_X_SYNC_REQ; - np->msgout[3] = per; - np->msgout[4] = ofs; + spi_populate_sync_msg(np->msgout, per, ofs); if (DEBUG_FLAGS & DEBUG_NEGO) { sym_print_nego_msg(np, target, "sync msgout", np->msgout); @@ -4078,14 +4062,7 @@ sym_ppr_nego_check(struct sym_hcb *np, int req, int target) /* * It was a request. Prepare an answer message. */ - np->msgout[0] = M_EXTENDED; - np->msgout[1] = 6; - np->msgout[2] = M_X_PPR_REQ; - np->msgout[3] = per; - np->msgout[4] = 0; - np->msgout[5] = ofs; - np->msgout[6] = wide; - np->msgout[7] = opts; + spi_populate_ppr_msg(np->msgout, per, ofs, wide, opts); if (DEBUG_FLAGS & DEBUG_NEGO) { sym_print_nego_msg(np, target, "ppr msgout", np->msgout); @@ -4197,10 +4174,7 @@ sym_wide_nego_check(struct sym_hcb *np, int req, struct sym_ccb *cp) /* * It was a request. Prepare an answer message. */ - np->msgout[0] = M_EXTENDED; - np->msgout[1] = 2; - np->msgout[2] = M_X_WIDE_REQ; - np->msgout[3] = wide; + spi_populate_width_msg(np->msgout, wide); np->msgin [0] = M_NOOP; @@ -4245,11 +4219,8 @@ static void sym_wide_nego(struct sym_hcb *np, struct sym_tcb *tp, struct sym_ccb * a single SCSI command (Suggested by Justin Gibbs). */ if (tp->tgoal.offset) { - np->msgout[0] = M_EXTENDED; - np->msgout[1] = 3; - np->msgout[2] = M_X_SYNC_REQ; - np->msgout[3] = tp->tgoal.period; - np->msgout[4] = tp->tgoal.offset; + spi_populate_sync_msg(np->msgout, tp->tgoal.period, + tp->tgoal.offset); if (DEBUG_FLAGS & DEBUG_NEGO) { sym_print_nego_msg(np, cp->target, diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h index fb5a2ffae939..5e1d61913d4e 100644 --- a/include/scsi/scsi_transport_spi.h +++ b/include/scsi/scsi_transport_spi.h @@ -148,5 +148,9 @@ void spi_schedule_dv_device(struct scsi_device *); void spi_dv_device(struct scsi_device *); void spi_display_xfer_agreement(struct scsi_target *); int spi_print_msg(const unsigned char *); +int spi_populate_width_msg(unsigned char *msg, int width); +int spi_populate_sync_msg(unsigned char *msg, int period, int offset); +int spi_populate_ppr_msg(unsigned char *msg, int period, int offset, int width, + int options); #endif /* SCSI_TRANSPORT_SPI_H */ -- cgit v1.2.3 From a012564136a665f8d63443c057ba368572b483df Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 16 Feb 2006 13:31:47 +0100 Subject: [SCSI] sas: add support for enclosure and bad ID rphy attributes Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 53 +++++++++++++++++++++++++++++++++++++-- include/scsi/scsi_transport_sas.h | 2 ++ 2 files changed, 53 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 205542988e29..eab5c7c6f3c7 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Dell Inc. + * Copyright (C) 2005-2006 Dell Inc. * Released under GPL v2. * * Serial Attached SCSI (SAS) transport class. @@ -38,7 +38,7 @@ #define SAS_HOST_ATTRS 0 #define SAS_PORT_ATTRS 17 -#define SAS_RPORT_ATTRS 5 +#define SAS_RPORT_ATTRS 7 struct sas_internal { struct scsi_transport_template t; @@ -533,6 +533,53 @@ show_sas_rphy_device_type(struct class_device *cdev, char *buf) static SAS_CLASS_DEVICE_ATTR(rphy, device_type, S_IRUGO, show_sas_rphy_device_type, NULL); +static ssize_t +show_sas_rphy_enclosure_identifier(struct class_device *cdev, char *buf) +{ + struct sas_rphy *rphy = transport_class_to_rphy(cdev); + struct sas_phy *phy = dev_to_phy(rphy->dev.parent); + struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); + struct sas_internal *i = to_sas_internal(shost->transportt); + u64 identifier; + int error; + + /* + * Only devices behind an expander are supported, because the + * enclosure identifier is a SMP feature. + */ + if (phy->local_attached) + return -EINVAL; + + error = i->f->get_enclosure_identifier(rphy, &identifier); + if (error) + return error; + return sprintf(buf, "0x%llx\n", (unsigned long long)identifier); +} + +static SAS_CLASS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO, + show_sas_rphy_enclosure_identifier, NULL); + +static ssize_t +show_sas_rphy_bay_identifier(struct class_device *cdev, char *buf) +{ + struct sas_rphy *rphy = transport_class_to_rphy(cdev); + struct sas_phy *phy = dev_to_phy(rphy->dev.parent); + struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); + struct sas_internal *i = to_sas_internal(shost->transportt); + int val; + + if (phy->local_attached) + return -EINVAL; + + val = i->f->get_bay_identifier(rphy); + if (val < 0) + return val; + return sprintf(buf, "%d\n", val); +} + +static SAS_CLASS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO, + show_sas_rphy_bay_identifier, NULL); + sas_rphy_protocol_attr(identify.initiator_port_protocols, initiator_port_protocols); sas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols); @@ -845,6 +892,8 @@ sas_attach_transport(struct sas_function_template *ft) SETUP_RPORT_ATTRIBUTE(rphy_device_type); SETUP_RPORT_ATTRIBUTE(rphy_sas_address); SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier); + SETUP_RPORT_ATTRIBUTE(rphy_enclosure_identifier); + SETUP_RPORT_ATTRIBUTE(rphy_bay_identifier); i->rphy_attrs[count] = NULL; return &i->t; diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index b91400bfb02a..ccef5d2cf478 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -94,6 +94,8 @@ struct sas_rphy { /* The functions by which the transport class and the driver communicate */ struct sas_function_template { int (*get_linkerrors)(struct sas_phy *); + int (*get_enclosure_identifier)(struct sas_rphy *, u64 *); + int (*get_bay_identifier)(struct sas_rphy *); int (*phy_reset)(struct sas_phy *, int); }; -- cgit v1.2.3 From 1bfc5d9d5eb8e1a2efacc306bc55c248ed259a8e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 9 Feb 2006 15:26:18 -0500 Subject: [SCSI] Recognize missing LUNs for non-standard devices Some non-standard SCSI targets or protocols, such as USB UFI, report "no LUN present" by setting the Peripheral Device Type to 0x1f and the Peripheral Qualifier to 0 (not 3 as the standard requires) in the INQUIRY response. This patch (as650b) adds a new target flag and code to accomodate such targets. Signed-off-by: Alan Stern Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 13 +++++++++++++ include/scsi/scsi_device.h | 5 ++++- 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 803c7b9690c5..94b86d5b1469 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -853,6 +853,19 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, goto out_free_result; } + /* + * Non-standard SCSI targets may set the PDT to 0x1f (unknown or + * no device type) instead of using the Peripheral Qualifier to + * indicate that no LUN is present. For example, USB UFI does this. + */ + if (starget->pdt_1f_for_no_lun && (result[0] & 0x1f) == 0x1f) { + SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO + "scsi scan: peripheral device type" + " of 31, no device added\n")); + res = SCSI_SCAN_TARGET_PRESENT; + goto out_free_result; + } + res = scsi_add_lun(sdev, result, &bflags); if (res == SCSI_SCAN_LUN_PRESENT) { if (bflags & BLIST_KEY) { diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index cde84b39bb65..8d77da932d2c 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -167,7 +167,10 @@ struct scsi_target { unsigned int channel; unsigned int id; /* target id ... replace * scsi_device.id eventually */ - unsigned long create:1; /* signal that it needs to be added */ + unsigned int create:1; /* signal that it needs to be added */ + unsigned int pdt_1f_for_no_lun; /* PDT = 0x1f */ + /* means no lun present */ + char scsi_level; void *hostdata; /* available to low-level driver */ unsigned long starget_data[0]; /* for the transport */ -- cgit v1.2.3 From 1fa44ecad2b86475e038aed81b0bf333fa484f8b Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 23 Feb 2006 12:43:43 -0600 Subject: [SCSI] add execute_in_process_context() API We have several points in the SCSI stack (primarily for our device functions) where we need to guarantee process context, but (given the place where the last reference was released) we cannot guarantee this. This API gets around the issue by executing the function directly if the caller has process context, but scheduling a workqueue to execute in process context if the caller doesn't have it. Signed-off-by: James Bottomley --- include/linux/workqueue.h | 6 ++++++ kernel/workqueue.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) (limited to 'include') diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 86b111300231..957c21c16d62 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -20,6 +20,10 @@ struct work_struct { struct timer_list timer; }; +struct execute_work { + struct work_struct work; +}; + #define __WORK_INITIALIZER(n, f, d) { \ .entry = { &(n).entry, &(n).entry }, \ .func = (f), \ @@ -74,6 +78,8 @@ extern void init_workqueues(void); void cancel_rearming_delayed_work(struct work_struct *work); void cancel_rearming_delayed_workqueue(struct workqueue_struct *, struct work_struct *); +int execute_in_process_context(void (*fn)(void *), void *, + struct execute_work *); /* * Kill off a pending schedule_delayed_work(). Note that the work callback diff --git a/kernel/workqueue.c b/kernel/workqueue.c index b052e2c4c710..e9e464a90376 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -27,6 +27,7 @@ #include #include #include +#include /* * The per-CPU workqueue (if single thread, we always use the first @@ -476,6 +477,34 @@ void cancel_rearming_delayed_work(struct work_struct *work) } EXPORT_SYMBOL(cancel_rearming_delayed_work); +/** + * execute_in_process_context - reliably execute the routine with user context + * @fn: the function to execute + * @data: data to pass to the function + * @ew: guaranteed storage for the execute work structure (must + * be available when the work executes) + * + * Executes the function immediately if process context is available, + * otherwise schedules the function for delayed execution. + * + * Returns: 0 - function was executed + * 1 - function was scheduled for execution + */ +int execute_in_process_context(void (*fn)(void *data), void *data, + struct execute_work *ew) +{ + if (!in_interrupt()) { + fn(data); + return 0; + } + + INIT_WORK(&ew->work, fn, data); + schedule_work(&ew->work); + + return 1; +} +EXPORT_SYMBOL_GPL(execute_in_process_context); + int keventd_up(void) { return keventd_wq != NULL; -- cgit v1.2.3 From ffedb4522571ac170f941678d138a31bc0884ab4 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 23 Feb 2006 14:27:18 -0600 Subject: [SCSI] fix scsi process problems and clean up the target reap issues In order to use the new execute_in_process_context() API, you have to provide it with the work storage, which I do in SCSI in scsi_device and scsi_target, but which also means that we can no longer queue up the target reaps, so instead I moved the target to a state model which allows target_alloc to detect if we've received a dying target and wait for it to be gone. Hopefully, this should also solve the target namespace race. Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 58 ---------------------------------------------- drivers/scsi/scsi_scan.c | 49 ++++++++++++++++++++++++++------------- drivers/scsi/scsi_sysfs.c | 4 +++- include/scsi/scsi.h | 2 -- include/scsi/scsi_device.h | 10 ++++++++ 5 files changed, 46 insertions(+), 77 deletions(-) (limited to 'include') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index eab303d148d8..3042520c413c 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2257,61 +2257,3 @@ scsi_target_unblock(struct device *dev) device_for_each_child(dev, NULL, target_unblock); } EXPORT_SYMBOL_GPL(scsi_target_unblock); - - -struct work_queue_work { - struct work_struct work; - void (*fn)(void *); - void *data; -}; - -static void execute_in_process_context_work(void *data) -{ - void (*fn)(void *data); - struct work_queue_work *wqw = data; - - fn = wqw->fn; - data = wqw->data; - - kfree(wqw); - - fn(data); -} - -/** - * scsi_execute_in_process_context - reliably execute the routine with user context - * @fn: the function to execute - * @data: data to pass to the function - * - * Executes the function immediately if process context is available, - * otherwise schedules the function for delayed execution. - * - * Returns: 0 - function was executed - * 1 - function was scheduled for execution - * <0 - error - */ -int scsi_execute_in_process_context(void (*fn)(void *data), void *data) -{ - struct work_queue_work *wqw; - - if (!in_interrupt()) { - fn(data); - return 0; - } - - wqw = kmalloc(sizeof(struct work_queue_work), GFP_ATOMIC); - - if (unlikely(!wqw)) { - printk(KERN_ERR "Failed to allocate memory\n"); - WARN_ON(1); - return -ENOMEM; - } - - INIT_WORK(&wqw->work, execute_in_process_context_work, wqw); - wqw->fn = fn; - wqw->data = data; - schedule_work(&wqw->work); - - return 1; -} -EXPORT_SYMBOL_GPL(scsi_execute_in_process_context); diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 94b86d5b1469..84f01fd0c8fd 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -349,6 +349,8 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, starget->channel = channel; INIT_LIST_HEAD(&starget->siblings); INIT_LIST_HEAD(&starget->devices); + starget->state = STARGET_RUNNING; + retry: spin_lock_irqsave(shost->host_lock, flags); found_target = __scsi_find_target(parent, channel, id); @@ -381,8 +383,15 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, found_target->reap_ref++; spin_unlock_irqrestore(shost->host_lock, flags); put_device(parent); - kfree(starget); - return found_target; + if (found_target->state != STARGET_DEL) { + kfree(starget); + return found_target; + } + /* Unfortunately, we found a dying target; need to + * wait until it's dead before we can get a new one */ + put_device(&found_target->dev); + flush_scheduled_work(); + goto retry; } static void scsi_target_reap_usercontext(void *data) @@ -391,21 +400,13 @@ static void scsi_target_reap_usercontext(void *data) struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); unsigned long flags; + transport_remove_device(&starget->dev); + device_del(&starget->dev); + transport_destroy_device(&starget->dev); spin_lock_irqsave(shost->host_lock, flags); - - if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { - list_del_init(&starget->siblings); - spin_unlock_irqrestore(shost->host_lock, flags); - transport_remove_device(&starget->dev); - device_del(&starget->dev); - transport_destroy_device(&starget->dev); - put_device(&starget->dev); - return; - - } + list_del_init(&starget->siblings); spin_unlock_irqrestore(shost->host_lock, flags); - - return; + put_device(&starget->dev); } /** @@ -419,7 +420,23 @@ static void scsi_target_reap_usercontext(void *data) */ void scsi_target_reap(struct scsi_target *starget) { - scsi_execute_in_process_context(scsi_target_reap_usercontext, starget); + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + unsigned long flags; + + spin_lock_irqsave(shost->host_lock, flags); + + if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { + BUG_ON(starget->state == STARGET_DEL); + starget->state = STARGET_DEL; + spin_unlock_irqrestore(shost->host_lock, flags); + execute_in_process_context(scsi_target_reap_usercontext, + starget, &starget->ew); + return; + + } + spin_unlock_irqrestore(shost->host_lock, flags); + + return; } /** diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 902a5def8e62..89055494dfee 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -256,7 +256,9 @@ static void scsi_device_dev_release_usercontext(void *data) static void scsi_device_dev_release(struct device *dev) { - scsi_execute_in_process_context(scsi_device_dev_release_usercontext, dev); + struct scsi_device *sdp = to_scsi_device(dev); + execute_in_process_context(scsi_device_dev_release_usercontext, dev, + &sdp->ew); } static struct class sdev_class = { diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 9c331258bc27..c60b8ff2f5e4 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -433,6 +433,4 @@ struct scsi_lun { /* Used to obtain the PCI location of a device */ #define SCSI_IOCTL_GET_PCI 0x5387 -int scsi_execute_in_process_context(void (*fn)(void *data), void *data); - #endif /* _SCSI_SCSI_H */ diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 8d77da932d2c..1ec17ee12815 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -4,6 +4,7 @@ #include #include #include +#include #include struct request_queue; @@ -137,6 +138,8 @@ struct scsi_device { struct device sdev_gendev; struct class_device sdev_classdev; + struct execute_work ew; /* used to get process context on put */ + enum scsi_device_state sdev_state; unsigned long sdev_data[0]; } __attribute__((aligned(sizeof(unsigned long)))); @@ -153,6 +156,11 @@ struct scsi_device { #define scmd_printk(prefix, scmd, fmt, a...) \ dev_printk(prefix, &(scmd)->device->sdev_gendev, fmt, ##a) +enum scsi_target_state { + STARGET_RUNNING = 1, + STARGET_DEL, +}; + /* * scsi_target: representation of a scsi target, for now, this is only * used for single_lun devices. If no one has active IO to the target, @@ -172,6 +180,8 @@ struct scsi_target { /* means no lun present */ char scsi_level; + struct execute_work ew; + enum scsi_target_state state; void *hostdata; /* available to low-level driver */ unsigned long starget_data[0]; /* for the transport */ /* starget_data must be the last element!!!! */ -- cgit v1.2.3 From 7e6dff62dad539cbd608bb3b8b833193d13f00ac Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 2 Mar 2006 14:12:56 -0600 Subject: [SCSI] add 6.0 Gbit phy definitions to the sas transport class I don't think these exist in silicon yet, but the aic94xx driver has a register setting for them. Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 1 + include/scsi/scsi_transport_sas.h | 1 + 2 files changed, 2 insertions(+) (limited to 'include') diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index eab5c7c6f3c7..fed39abeff86 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -151,6 +151,7 @@ static struct { { SAS_SATA_SPINUP_HOLD, "Spin-up hold" }, { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" }, { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" }, + { SAS_LINK_RATE_6_0_GBPS, "6.0 Gbit" }, }; sas_bitfield_name_search(linkspeed, sas_linkspeed_names) diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index ccef5d2cf478..95e2132d485e 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -30,6 +30,7 @@ enum sas_linkrate { SAS_SATA_PORT_SELECTOR, SAS_LINK_RATE_1_5_GBPS, SAS_LINK_RATE_3_0_GBPS, + SAS_LINK_RATE_6_0_GBPS, SAS_LINK_VIRTUAL, }; -- cgit v1.2.3 From 597afd21401c85bdf9441830abf431c2be6fd45f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 1 Mar 2006 01:25:38 +0900 Subject: [PATCH] libata: seperate out ata_class_present() Seperate out ata_class_present() from ata_dev_present(). This is useful because new reset mechanism deals with classes[] directly. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- include/linux/libata.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/libata.h b/include/linux/libata.h index 66b6847225df..22e86cb2d166 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -645,10 +645,14 @@ static inline unsigned int ata_tag_valid(unsigned int tag) return (tag < ATA_MAX_QUEUE) ? 1 : 0; } +static inline unsigned int ata_class_present(unsigned int class) +{ + return class == ATA_DEV_ATA || class == ATA_DEV_ATAPI; +} + static inline unsigned int ata_dev_present(const struct ata_device *dev) { - return ((dev->class == ATA_DEV_ATA) || - (dev->class == ATA_DEV_ATAPI)); + return ata_class_present(dev->class); } static inline u8 ata_chk_status(struct ata_port *ap) -- cgit v1.2.3 From d9572b1d5e60b63e27e17f1f7771c5a26dd5d81e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 1 Mar 2006 16:09:35 +0900 Subject: [PATCH] libata: convert dev->id to pointer Convert dev->id from array to pointer. This is to accomodate revalidation. During revalidation, both old and new IDENTIFY pages should be accessible and single ->id array doesn't cut it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 20 +++++++++++++++++--- include/linux/libata.h | 2 +- 2 files changed, 18 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index e34b421eb2a3..fecda706d85f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -911,7 +911,7 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) * @dev: target device * @p_class: pointer to class of the target device (may be changed) * @post_reset: is this read ID post-reset? - * @id: buffer to fill IDENTIFY page into + * @p_id: read IDENTIFY page (newly allocated) * * Read ID data from the specified device. ATA_CMD_ID_ATA is * performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI @@ -926,12 +926,13 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) * 0 on success, -errno otherwise. */ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, - unsigned int *p_class, int post_reset, u16 *id) + unsigned int *p_class, int post_reset, u16 **p_id) { unsigned int class = *p_class; unsigned int using_edd; struct ata_taskfile tf; unsigned int err_mask = 0; + u16 *id; const char *reason; int rc; @@ -945,6 +946,13 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ + id = kmalloc(sizeof(id[0]) * ATA_ID_WORDS, GFP_KERNEL); + if (id == NULL) { + rc = -ENOMEM; + reason = "out of memory"; + goto err_out; + } + retry: ata_tf_init(ap, &tf, dev->devno); @@ -1035,11 +1043,13 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, } *p_class = class; + *p_id = id; return 0; err_out: printk(KERN_WARNING "ata%u: dev %u failed to IDENTIFY (%s)\n", ap->id, dev->devno, reason); + kfree(id); return rc; } @@ -1079,7 +1089,8 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) DPRINTK("ENTER, host %u, dev %u\n", ap->id, device); - rc = ata_dev_read_id(ap, dev, &dev->class, 1, dev->id); + WARN_ON(dev->id != NULL); + rc = ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id); if (rc) goto err_out; @@ -4732,11 +4743,14 @@ void ata_host_set_remove(struct ata_host_set *host_set) int ata_scsi_release(struct Scsi_Host *host) { struct ata_port *ap = (struct ata_port *) &host->hostdata[0]; + int i; DPRINTK("ENTER\n"); ap->ops->port_disable(ap); ata_host_remove(ap, 0); + for (i = 0; i < ATA_MAX_DEVICES; i++) + kfree(ap->device[i].id); DPRINTK("EXIT\n"); return 1; diff --git a/include/linux/libata.h b/include/linux/libata.h index 22e86cb2d166..9f273dd1958c 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -339,7 +339,7 @@ struct ata_device { unsigned long flags; /* ATA_DFLAG_xxx */ unsigned int class; /* ATA_DEV_xxx */ unsigned int devno; /* 0 or 1 */ - u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */ + u16 *id; /* IDENTIFY xxx DEVICE data */ u8 pio_mode; u8 dma_mode; u8 xfer_mode; -- cgit v1.2.3 From 4b2f3ededc035525038a7a9247074243dac6b351 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 1 Mar 2006 16:09:36 +0900 Subject: [PATCH] libata: fold ata_dev_config() into ata_dev_configure() ata_dev_config() needs to be done everytime a device is configured. Fold it into ata_dev_configure(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 48 ++++++++++++++++------------------------------ include/linux/libata.h | 1 - 2 files changed, 17 insertions(+), 32 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index ba26c66cc11b..10803f72c57d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1053,6 +1053,12 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, return rc; } +static inline u8 ata_dev_knobble(const struct ata_port *ap, + struct ata_device *dev) +{ + return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id))); +} + /** * ata_dev_configure - Configure the specified ATA/ATAPI device * @ap: Port on which target device resides @@ -1167,6 +1173,17 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev) ap->host->max_cmd_len, ap->device[i].cdb_len); + /* limit bridge transfers to udma5, 200 sectors */ + if (ata_dev_knobble(ap, dev)) { + printk(KERN_INFO "ata%u(%u): applying bridge limits\n", + ap->id, dev->devno); + ap->udma_mask &= ATA_UDMA5; + dev->max_sectors = ATA_MAX_SECTORS; + } + + if (ap->ops->dev_config) + ap->ops->dev_config(ap, dev); + DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap)); return 0; @@ -1177,35 +1194,6 @@ err_out_nosup: return rc; } - -static inline u8 ata_dev_knobble(const struct ata_port *ap, - struct ata_device *dev) -{ - return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id))); -} - -/** - * ata_dev_config - Run device specific handlers & check for SATA->PATA bridges - * @ap: Bus - * @i: Device - * - * LOCKING: - */ - -void ata_dev_config(struct ata_port *ap, unsigned int i) -{ - /* limit bridge transfers to udma5, 200 sectors */ - if (ata_dev_knobble(ap, &ap->device[i])) { - printk(KERN_INFO "ata%u(%u): applying bridge limits\n", - ap->id, i); - ap->udma_mask &= ATA_UDMA5; - ap->device[i].max_sectors = ATA_MAX_SECTORS; - } - - if (ap->ops->dev_config) - ap->ops->dev_config(ap, &ap->device[i]); -} - /** * ata_bus_probe - Reset and probe ATA bus * @ap: Bus to probe @@ -1266,7 +1254,6 @@ static int ata_bus_probe(struct ata_port *ap) continue; } - ata_dev_config(ap, i); found = 1; } @@ -4967,7 +4954,6 @@ EXPORT_SYMBOL_GPL(ata_host_intr); EXPORT_SYMBOL_GPL(ata_dev_classify); EXPORT_SYMBOL_GPL(ata_id_string); EXPORT_SYMBOL_GPL(ata_id_c_string); -EXPORT_SYMBOL_GPL(ata_dev_config); EXPORT_SYMBOL_GPL(ata_scsi_simulate); EXPORT_SYMBOL_GPL(ata_eh_qc_complete); EXPORT_SYMBOL_GPL(ata_eh_qc_retry); diff --git a/include/linux/libata.h b/include/linux/libata.h index 9f273dd1958c..86a504f0ef06 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -542,7 +542,6 @@ extern void ata_id_string(const u16 *id, unsigned char *s, unsigned int ofs, unsigned int len); extern void ata_id_c_string(const u16 *id, unsigned char *s, unsigned int ofs, unsigned int len); -extern void ata_dev_config(struct ata_port *ap, unsigned int i); extern void ata_bmdma_setup (struct ata_queued_cmd *qc); extern void ata_bmdma_start (struct ata_queued_cmd *qc); extern void ata_bmdma_stop(struct ata_queued_cmd *qc); -- cgit v1.2.3 From 623a3128aa2b86caa8e06e762e9e444177e4fa47 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 5 Mar 2006 17:55:58 +0900 Subject: [PATCH] libata: implement ata_dev_revalidate() ata_dev_revalidate() re-reads IDENTIFY PAGE of the given device and makes sure it's the same device as the configured one. Once it's verified that it's the same device, @dev is configured according to newly read IDENTIFY PAGE. Note that revalidation currently doesn't invoke transfer mode reconfiguration. Criteria for 'same device' * same class (of course) * same model string * same serial string * if ATA, same n_sectors (to catch geometry parameter changes) Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 115 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 2 + 2 files changed, 117 insertions(+) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d65aa86ddbb2..5d0adfa4610a 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2345,6 +2345,120 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, return rc; } +/** + * ata_dev_same_device - Determine whether new ID matches configured device + * @ap: port on which the device to compare against resides + * @dev: device to compare against + * @new_class: class of the new device + * @new_id: IDENTIFY page of the new device + * + * Compare @new_class and @new_id against @dev and determine + * whether @dev is the device indicated by @new_class and + * @new_id. + * + * LOCKING: + * None. + * + * RETURNS: + * 1 if @dev matches @new_class and @new_id, 0 otherwise. + */ +static int ata_dev_same_device(struct ata_port *ap, struct ata_device *dev, + unsigned int new_class, const u16 *new_id) +{ + const u16 *old_id = dev->id; + unsigned char model[2][41], serial[2][21]; + u64 new_n_sectors; + + if (dev->class != new_class) { + printk(KERN_INFO + "ata%u: dev %u class mismatch %d != %d\n", + ap->id, dev->devno, dev->class, new_class); + return 0; + } + + ata_id_c_string(old_id, model[0], ATA_ID_PROD_OFS, sizeof(model[0])); + ata_id_c_string(new_id, model[1], ATA_ID_PROD_OFS, sizeof(model[1])); + ata_id_c_string(old_id, serial[0], ATA_ID_SERNO_OFS, sizeof(serial[0])); + ata_id_c_string(new_id, serial[1], ATA_ID_SERNO_OFS, sizeof(serial[1])); + new_n_sectors = ata_id_n_sectors(new_id); + + if (strcmp(model[0], model[1])) { + printk(KERN_INFO + "ata%u: dev %u model number mismatch '%s' != '%s'\n", + ap->id, dev->devno, model[0], model[1]); + return 0; + } + + if (strcmp(serial[0], serial[1])) { + printk(KERN_INFO + "ata%u: dev %u serial number mismatch '%s' != '%s'\n", + ap->id, dev->devno, serial[0], serial[1]); + return 0; + } + + if (dev->class == ATA_DEV_ATA && dev->n_sectors != new_n_sectors) { + printk(KERN_INFO + "ata%u: dev %u n_sectors mismatch %llu != %llu\n", + ap->id, dev->devno, (unsigned long long)dev->n_sectors, + (unsigned long long)new_n_sectors); + return 0; + } + + return 1; +} + +/** + * ata_dev_revalidate - Revalidate ATA device + * @ap: port on which the device to revalidate resides + * @dev: device to revalidate + * @post_reset: is this revalidation after reset? + * + * Re-read IDENTIFY page and make sure @dev is still attached to + * the port. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, negative errno otherwise + */ +int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, + int post_reset) +{ + unsigned int class; + u16 *id; + int rc; + + if (!ata_dev_present(dev)) + return -ENODEV; + + class = dev->class; + id = NULL; + + /* allocate & read ID data */ + rc = ata_dev_read_id(ap, dev, &class, post_reset, &id); + if (rc) + goto fail; + + /* is the device still there? */ + if (!ata_dev_same_device(ap, dev, class, id)) { + rc = -ENODEV; + goto fail; + } + + kfree(dev->id); + dev->id = id; + + /* configure device according to the new ID */ + return ata_dev_configure(ap, dev, 0); + + fail: + printk(KERN_ERR "ata%u: dev %u revalidation failed (errno=%d)\n", + ap->id, dev->devno, rc); + kfree(id); + return rc; +} + static void ata_pr_blacklisted(const struct ata_port *ap, const struct ata_device *dev) { @@ -4964,6 +5078,7 @@ EXPORT_SYMBOL_GPL(sata_std_hardreset); EXPORT_SYMBOL_GPL(ata_std_postreset); EXPORT_SYMBOL_GPL(ata_std_probe_reset); EXPORT_SYMBOL_GPL(ata_drive_probe_reset); +EXPORT_SYMBOL_GPL(ata_dev_revalidate); EXPORT_SYMBOL_GPL(ata_port_disable); EXPORT_SYMBOL_GPL(ata_ratelimit); EXPORT_SYMBOL_GPL(ata_busy_sleep); diff --git a/include/linux/libata.h b/include/linux/libata.h index 86a504f0ef06..66dce58f1941 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -485,6 +485,8 @@ extern int ata_std_softreset(struct ata_port *ap, int verbose, extern int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class); extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes); +extern int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, + int post_reset); extern void ata_port_disable(struct ata_port *); extern void ata_std_ports(struct ata_ioports *ioaddr); #ifdef CONFIG_PCI -- cgit v1.2.3 From 42ab03609cca4ef5079e248296f015650c626899 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 4 Mar 2006 09:10:18 -0600 Subject: [PATCH] convert aic94xx over to using the sas transport end device Begin introducing the concept of sas remote devices that have an rphy embedded. The first one (this) is a simple end device. All that an end device really does is have port mode page parameters contained. The next and more complex piece will be expander remote devices. Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 199 +++++++++++++++++++++++++++++++------- include/scsi/scsi_transport_sas.h | 19 ++++ 2 files changed, 184 insertions(+), 34 deletions(-) (limited to 'include') diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 434f3954aa87..5de29b941c6b 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -39,6 +39,7 @@ #define SAS_HOST_ATTRS 0 #define SAS_PORT_ATTRS 17 #define SAS_RPORT_ATTRS 7 +#define SAS_END_DEV_ATTRS 3 struct sas_internal { struct scsi_transport_template t; @@ -47,9 +48,11 @@ struct sas_internal { struct class_device_attribute private_host_attrs[SAS_HOST_ATTRS]; struct class_device_attribute private_phy_attrs[SAS_PORT_ATTRS]; struct class_device_attribute private_rphy_attrs[SAS_RPORT_ATTRS]; + struct class_device_attribute private_end_dev_attrs[SAS_END_DEV_ATTRS]; struct transport_container phy_attr_cont; struct transport_container rphy_attr_cont; + struct transport_container end_dev_attr_cont; /* * The array of null terminated pointers to attributes @@ -58,6 +61,7 @@ struct sas_internal { struct class_device_attribute *host_attrs[SAS_HOST_ATTRS + 1]; struct class_device_attribute *phy_attrs[SAS_PORT_ATTRS + 1]; struct class_device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1]; + struct class_device_attribute *end_dev_attrs[SAS_END_DEV_ATTRS + 1]; }; #define to_sas_internal(tmpl) container_of(tmpl, struct sas_internal, t) @@ -588,6 +592,73 @@ sas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", unsigned long long); sas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); +/* only need 8 bytes of data plus header (4 or 8) */ +#define BUF_SIZE 64 + +int sas_read_port_mode_page(struct scsi_device *sdev) +{ + char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata; + struct sas_rphy *rphy = target_to_rphy(sdev->sdev_target); + struct sas_end_device *rdev; + struct scsi_mode_data mode_data; + int res, error; + + BUG_ON(rphy->identify.device_type != SAS_END_DEVICE); + + rdev = rphy_to_end_device(rphy); + + if (!buffer) + return -ENOMEM; + + res = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3, + &mode_data, NULL); + + error = -EINVAL; + if (!scsi_status_is_good(res)) + goto out; + + msdata = buffer + mode_data.header_length + + mode_data.block_descriptor_length; + + if (msdata - buffer > BUF_SIZE - 8) + goto out; + + error = 0; + + rdev->ready_led_meaning = msdata[2] & 0x10 ? 1 : 0; + rdev->I_T_nexus_loss_timeout = (msdata[4] << 8) + msdata[5]; + rdev->initiator_response_timeout = (msdata[6] << 8) + msdata[7]; + + out: + kfree(buffer); + return error; +} +EXPORT_SYMBOL(sas_read_port_mode_page); + +#define sas_end_dev_show_simple(field, name, format_string, cast) \ +static ssize_t \ +show_sas_end_dev_##name(struct class_device *cdev, char *buf) \ +{ \ + struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ + struct sas_end_device *rdev = rphy_to_end_device(rphy); \ + \ + return snprintf(buf, 20, format_string, cast rdev->field); \ +} + +#define sas_end_dev_simple_attr(field, name, format_string, type) \ + sas_end_dev_show_simple(field, name, format_string, (type)) \ +static SAS_CLASS_DEVICE_ATTR(end_dev, name, S_IRUGO, \ + show_sas_end_dev_##name, NULL) + +sas_end_dev_simple_attr(ready_led_meaning, ready_led_meaning, "%d\n", int); +sas_end_dev_simple_attr(I_T_nexus_loss_timeout, I_T_nexus_loss_timeout, + "%d\n", int); +sas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout, + "%d\n", int); + +static DECLARE_TRANSPORT_CLASS(sas_end_dev_class, + "sas_end_device", NULL, NULL, NULL); + static DECLARE_TRANSPORT_CLASS(sas_rphy_class, "sas_rphy", NULL, NULL, NULL); @@ -610,6 +681,31 @@ static int sas_rphy_match(struct attribute_container *cont, struct device *dev) return &i->rphy_attr_cont.ac == cont; } +static int sas_end_dev_match(struct attribute_container *cont, + struct device *dev) +{ + struct Scsi_Host *shost; + struct sas_internal *i; + struct sas_rphy *rphy; + + if (!scsi_is_sas_rphy(dev)) + return 0; + shost = dev_to_shost(dev->parent->parent); + rphy = dev_to_rphy(dev); + + if (!shost->transportt) + return 0; + if (shost->transportt->host_attrs.ac.class != + &sas_host_class.class) + return 0; + + i = to_sas_internal(shost->transportt); + return &i->end_dev_attr_cont.ac == cont && + rphy->identify.device_type == SAS_END_DEVICE && + /* FIXME: remove contained eventually */ + rphy->contained; +} + static void sas_rphy_release(struct device *dev) { struct sas_rphy *rphy = dev_to_rphy(dev); @@ -649,6 +745,40 @@ struct sas_rphy *sas_rphy_alloc(struct sas_phy *parent) } EXPORT_SYMBOL(sas_rphy_alloc); +/** + * sas_end_device_alloc - allocate an rphy for an end device + * + * Allocates an SAS remote PHY structure, connected to @parent. + * + * Returns: + * SAS PHY allocated or %NULL if the allocation failed. + */ +struct sas_rphy *sas_end_device_alloc(struct sas_phy *parent) +{ + struct Scsi_Host *shost = dev_to_shost(&parent->dev); + struct sas_end_device *rdev; + + rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); + if (!rdev) { + put_device(&parent->dev); + return NULL; + } + + device_initialize(&rdev->rphy.dev); + rdev->rphy.dev.parent = get_device(&parent->dev); + rdev->rphy.dev.release = sas_rphy_release; + sprintf(rdev->rphy.dev.bus_id, "rphy-%d:%d-%d", + shost->host_no, parent->port_identifier, parent->number); + rdev->rphy.identify.device_type = SAS_END_DEVICE; + /* FIXME: mark the rphy as being contained in a larger structure */ + rdev->rphy.contained = 1; + transport_setup_device(&rdev->rphy.dev); + + return &rdev->rphy; +} +EXPORT_SYMBOL(sas_end_device_alloc); + + /** * sas_rphy_add -- add a SAS remote PHY to the device hierachy * @rphy: The remote PHY to be added @@ -807,51 +937,35 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel, * Setup / Teardown code */ -#define SETUP_RPORT_ATTRIBUTE(field) \ - i->private_rphy_attrs[count] = class_device_attr_##field; \ - i->private_rphy_attrs[count].attr.mode = S_IRUGO; \ - i->private_rphy_attrs[count].store = NULL; \ - i->rphy_attrs[count] = &i->private_rphy_attrs[count]; \ - count++ +#define SETUP_TEMPLATE(attrb, field, perm, test) \ + i->private_##attrb[count] = class_device_attr_##field; \ + i->private_##attrb[count].attr.mode = perm; \ + i->private_##attrb[count].store = NULL; \ + i->attrb[count] = &i->private_##attrb[count]; \ + if (test) \ + count++ + + +#define SETUP_RPORT_ATTRIBUTE(field) \ + SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, 1) #define SETUP_OPTIONAL_RPORT_ATTRIBUTE(field, func) \ - i->private_rphy_attrs[count] = class_device_attr_##field; \ - i->private_rphy_attrs[count].attr.mode = S_IRUGO; \ - i->private_rphy_attrs[count].store = NULL; \ - i->rphy_attrs[count] = &i->private_rphy_attrs[count]; \ - if (i->f->func) \ - count++ + SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, i->f->func) #define SETUP_PORT_ATTRIBUTE(field) \ - i->private_phy_attrs[count] = class_device_attr_##field; \ - i->private_phy_attrs[count].attr.mode = S_IRUGO; \ - i->private_phy_attrs[count].store = NULL; \ - i->phy_attrs[count] = &i->private_phy_attrs[count]; \ - count++ + SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, 1) #define SETUP_OPTIONAL_PORT_ATTRIBUTE(field, func) \ - i->private_phy_attrs[count] = class_device_attr_##field; \ - i->private_phy_attrs[count].attr.mode = S_IRUGO; \ - i->private_phy_attrs[count].store = NULL; \ - i->phy_attrs[count] = &i->private_phy_attrs[count]; \ - if (i->f->func) \ - count++ + SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, i->f->func) #define SETUP_PORT_ATTRIBUTE_WRONLY(field) \ - i->private_phy_attrs[count] = class_device_attr_##field; \ - i->private_phy_attrs[count].attr.mode = S_IWUGO; \ - i->private_phy_attrs[count].show = NULL; \ - i->phy_attrs[count] = &i->private_phy_attrs[count]; \ - count++ + SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, 1) #define SETUP_OPTIONAL_PORT_ATTRIBUTE_WRONLY(field, func) \ - i->private_phy_attrs[count] = class_device_attr_##field; \ - i->private_phy_attrs[count].attr.mode = S_IWUGO; \ - i->private_phy_attrs[count].show = NULL; \ - i->phy_attrs[count] = &i->private_phy_attrs[count]; \ - if (i->f->func) \ - count++ + SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, i->f->func) +#define SETUP_END_DEV_ATTRIBUTE(field) \ + SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1) /** * sas_attach_transport -- instantiate SAS transport template @@ -885,6 +999,11 @@ sas_attach_transport(struct sas_function_template *ft) i->rphy_attr_cont.ac.match = sas_rphy_match; transport_container_register(&i->rphy_attr_cont); + i->end_dev_attr_cont.ac.class = &sas_end_dev_class.class; + i->end_dev_attr_cont.ac.attrs = &i->end_dev_attrs[0]; + i->end_dev_attr_cont.ac.match = sas_end_dev_match; + transport_container_register(&i->end_dev_attr_cont); + i->f = ft; count = 0; @@ -923,6 +1042,12 @@ sas_attach_transport(struct sas_function_template *ft) get_bay_identifier); i->rphy_attrs[count] = NULL; + count = 0; + SETUP_END_DEV_ATTRIBUTE(end_dev_ready_led_meaning); + SETUP_END_DEV_ATTRIBUTE(end_dev_I_T_nexus_loss_timeout); + SETUP_END_DEV_ATTRIBUTE(end_dev_initiator_response_timeout); + i->end_dev_attrs[count] = NULL; + return &i->t; } EXPORT_SYMBOL(sas_attach_transport); @@ -956,9 +1081,14 @@ static __init int sas_transport_init(void) error = transport_class_register(&sas_rphy_class); if (error) goto out_unregister_phy; + error = transport_class_register(&sas_end_dev_class); + if (error) + goto out_unregister_rphy; return 0; + out_unregister_rphy: + transport_class_unregister(&sas_rphy_class); out_unregister_phy: transport_class_unregister(&sas_phy_class); out_unregister_transport: @@ -973,6 +1103,7 @@ static void __exit sas_transport_exit(void) transport_class_unregister(&sas_host_class); transport_class_unregister(&sas_phy_class); transport_class_unregister(&sas_rphy_class); + transport_class_unregister(&sas_end_dev_class); } MODULE_AUTHOR("Christoph Hellwig"); diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index 95e2132d485e..8fded431cf46 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -82,6 +82,10 @@ struct sas_rphy { struct sas_identify identify; struct list_head list; u32 scsi_target_id; + /* temporary expedient: mark the rphy as being contained + * within a type specific rphy + * FIXME: pull this out when everything uses the containers */ + unsigned contained:1; }; #define dev_to_rphy(d) \ @@ -90,6 +94,19 @@ struct sas_rphy { dev_to_rphy((cdev)->dev) #define rphy_to_shost(rphy) \ dev_to_shost((rphy)->dev.parent) +#define target_to_rphy(targ) \ + dev_to_rphy((targ)->dev.parent) + +struct sas_end_device { + struct sas_rphy rphy; + /* flags */ + unsigned ready_led_meaning:1; + /* parameters */ + u16 I_T_nexus_loss_timeout; + u16 initiator_response_timeout; +}; +#define rphy_to_end_device(r) \ + container_of((r), struct sas_end_device, rphy) /* The functions by which the transport class and the driver communicate */ @@ -110,6 +127,7 @@ extern void sas_phy_delete(struct sas_phy *); extern int scsi_is_sas_phy(const struct device *); extern struct sas_rphy *sas_rphy_alloc(struct sas_phy *); +extern struct sas_rphy *sas_end_device_alloc(struct sas_phy *); void sas_rphy_free(struct sas_rphy *); extern int sas_rphy_add(struct sas_rphy *); extern void sas_rphy_delete(struct sas_rphy *); @@ -118,5 +136,6 @@ extern int scsi_is_sas_rphy(const struct device *); extern struct scsi_transport_template * sas_attach_transport(struct sas_function_template *); extern void sas_release_transport(struct scsi_transport_template *); +int sas_read_port_mode_page(struct scsi_device *); #endif /* SCSI_TRANSPORT_SAS_H */ -- cgit v1.2.3 From 780dfef37e2c941985b708f67aa0074edc922bea Mon Sep 17 00:00:00 2001 From: Chris Pascoe Date: Tue, 28 Feb 2006 08:34:59 -0300 Subject: V4L/DVB (3408): DViCO FusionHDTV DVB-T Hybrid and ZL10353-based FusionHDTV DVB-T Plus support Add support for the FE6600 tuner used on the DVB-T Hybrid board. Add support for the Zarlink ZL10353 DVB-T demodulator, which supersedes the MT352, used on the DViCO FusionHDTV DVB-T Hybrid and later model Plus boards. Signed-off-by: Chris Pascoe Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 1 + Documentation/video4linux/CARDLIST.tuner | 1 + drivers/media/dvb/frontends/Kconfig | 6 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/dvb-pll.c | 15 ++ drivers/media/dvb/frontends/dvb-pll.h | 2 + drivers/media/dvb/frontends/zl10353.c | 311 +++++++++++++++++++++++++++++ drivers/media/dvb/frontends/zl10353.h | 43 ++++ drivers/media/dvb/frontends/zl10353_priv.h | 42 ++++ drivers/media/video/cx88/Makefile | 1 + drivers/media/video/cx88/cx88-cards.c | 67 +++++++ drivers/media/video/cx88/cx88-dvb.c | 108 ++++++++-- drivers/media/video/cx88/cx88.h | 1 + drivers/media/video/tuner-types.c | 20 ++ include/media/tuner.h | 3 +- 15 files changed, 599 insertions(+), 23 deletions(-) create mode 100644 drivers/media/dvb/frontends/zl10353.c create mode 100644 drivers/media/dvb/frontends/zl10353.h create mode 100644 drivers/media/dvb/frontends/zl10353_priv.h (limited to 'include') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index d852ad4f93a2..3b39a91b24bd 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -44,3 +44,4 @@ 43 -> KWorld/VStream XPert DVB-T with cx22702 [17de:08a1] 44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50,18ac:db54] 45 -> KWorld HardwareMpegTV XPert [17de:0840] + 46 -> DViCO FusionHDTV DVB-T Hybrid [18ac:db40,18ac:db44] diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index de48438d5115..ab344c94c0a2 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -70,3 +70,4 @@ tuner=68 - Philips TUV1236D ATSC/NTSC dual in tuner=69 - Tena TNF 5335 MF tuner=70 - Samsung TCPN 2121P30A tuner=71 - Xceive xc3028 +tuner=72 - FE6600 diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index c676b1e23ab0..a1a894d81040 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -116,6 +116,12 @@ config DVB_MT352 help A DVB-T tuner module. Say Y when you want to support this frontend. +config DVB_ZL10353 + tristate "Zarlink ZL10353 based" + depends on DVB_CORE + help + A DVB-T tuner module. Say Y when you want to support this frontend. + config DVB_DIB3000MB tristate "DiBcom 3000M-B" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 1af769cd90c0..d09b6071fbaf 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_DVB_TDA1004X) += tda1004x.o obj-$(CONFIG_DVB_SP887X) += sp887x.o obj-$(CONFIG_DVB_NXT6000) += nxt6000.o obj-$(CONFIG_DVB_MT352) += mt352.o +obj-$(CONFIG_DVB_ZL10353) += zl10353.o obj-$(CONFIG_DVB_CX22702) += cx22702.o obj-$(CONFIG_DVB_TDA10021) += tda10021.o obj-$(CONFIG_DVB_STV0297) += stv0297.o diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 4f682534df42..8a4c904d3a27 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -404,6 +404,21 @@ struct dvb_pll_desc dvb_pll_philips_td1316 = { }; EXPORT_SYMBOL(dvb_pll_philips_td1316); +/* FE6600 used on DViCO Hybrid */ +struct dvb_pll_desc dvb_pll_unknown_fe6600 = { + .name = "FE6600", + .min = 44250000, + .max = 858000000, + .count = 4, + .entries = { + { 250000000, 36213333, 166667, 0xb4, 0x12 }, + { 455000000, 36213333, 166667, 0xfe, 0x11 }, + { 775500000, 36213333, 166667, 0xbc, 0x18 }, + { 999999999, 36213333, 166667, 0xf4, 0x18 }, + } +}; +EXPORT_SYMBOL(dvb_pll_unknown_fe6600); + /* ----------------------------------------------------------- */ /* code */ diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index 56c3cd76a7fa..8a7f0b941c38 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -42,6 +42,8 @@ extern struct dvb_pll_desc dvb_pll_samsung_tbmv; extern struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261; extern struct dvb_pll_desc dvb_pll_philips_td1316; +extern struct dvb_pll_desc dvb_pll_unknown_fe6600; + int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, u32 freq, int bandwidth); diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c new file mode 100644 index 000000000000..23846c4452ad --- /dev/null +++ b/drivers/media/dvb/frontends/zl10353.c @@ -0,0 +1,311 @@ +/* + * Driver for Zarlink DVB-T ZL10353 demodulator + * + * Copyright (C) 2006 Christopher Pascoe + * + * 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. 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.= + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "dvb_frontend.h" +#include "zl10353_priv.h" +#include "zl10353.h" + +struct zl10353_state { + struct i2c_adapter *i2c; + struct dvb_frontend frontend; + struct dvb_frontend_ops ops; + + struct zl10353_config config; +}; + +static int debug_regs = 0; + +static int zl10353_single_write(struct dvb_frontend *fe, u8 reg, u8 val) +{ + struct zl10353_state *state = fe->demodulator_priv; + u8 buf[2] = { reg, val }; + struct i2c_msg msg = { .addr = state->config.demod_address, .flags = 0, + .buf = buf, .len = 2 }; + int err = i2c_transfer(state->i2c, &msg, 1); + if (err != 1) { + printk("zl10353: write to reg %x failed (err = %d)!\n", reg, err); + return err; + } + return 0; +} + +int zl10353_write(struct dvb_frontend *fe, u8 *ibuf, int ilen) +{ + int err, i; + for (i = 0; i < ilen - 1; i++) + if ((err = zl10353_single_write(fe, ibuf[0] + i, ibuf[i + 1]))) + return err; + + return 0; +} + +static int zl10353_read_register(struct zl10353_state *state, u8 reg) +{ + int ret; + u8 b0[1] = { reg }; + u8 b1[1] = { 0 }; + struct i2c_msg msg[2] = { { .addr = state->config.demod_address, + .flags = 0, + .buf = b0, .len = 1 }, + { .addr = state->config.demod_address, + .flags = I2C_M_RD, + .buf = b1, .len = 1 } }; + + ret = i2c_transfer(state->i2c, msg, 2); + + if (ret != 2) { + printk("%s: readreg error (reg=%d, ret==%i)\n", + __FUNCTION__, reg, ret); + return ret; + } + + return b1[0]; +} + +void zl10353_dump_regs(struct dvb_frontend *fe) +{ + struct zl10353_state *state = fe->demodulator_priv; + char buf[52], buf2[4]; + int ret; + u8 reg; + + /* Dump all registers. */ + for (reg = 0; ; reg++) { + if (reg % 16 == 0) { + if (reg) + printk(KERN_DEBUG "%s\n", buf); + sprintf(buf, "%02x: ", reg); + } + ret = zl10353_read_register(state, reg); + if (ret >= 0) + sprintf(buf2, "%02x ", (u8)ret); + else + strcpy(buf2, "-- "); + strcat(buf, buf2); + if (reg == 0xff) + break; + } + printk(KERN_DEBUG "%s\n", buf); +} + +static int zl10353_sleep(struct dvb_frontend *fe) +{ + static u8 zl10353_softdown[] = { 0x50, 0x0C, 0x44 }; + + zl10353_write(fe, zl10353_softdown, sizeof(zl10353_softdown)); + return 0; +} + +static int zl10353_set_parameters(struct dvb_frontend *fe, + struct dvb_frontend_parameters *param) +{ + struct zl10353_state *state = fe->demodulator_priv; + u8 pllbuf[6] = { 0x67 }; + + /* These settings set "auto-everything" and start the FSM. */ + zl10353_single_write(fe, 0x55, 0x80); + udelay(200); + zl10353_single_write(fe, 0xEA, 0x01); + udelay(200); + zl10353_single_write(fe, 0xEA, 0x00); + + zl10353_single_write(fe, 0x56, 0x28); + zl10353_single_write(fe, 0x89, 0x20); + zl10353_single_write(fe, 0x5E, 0x00); + zl10353_single_write(fe, 0x65, 0x5A); + zl10353_single_write(fe, 0x66, 0xE9); + zl10353_single_write(fe, 0x62, 0x0A); + + state->config.pll_set(fe, param, pllbuf + 1); + zl10353_write(fe, pllbuf, sizeof(pllbuf)); + + zl10353_single_write(fe, 0x70, 0x01); + udelay(250); + zl10353_single_write(fe, 0xE4, 0x00); + zl10353_single_write(fe, 0xE5, 0x2A); + zl10353_single_write(fe, 0xE9, 0x02); + zl10353_single_write(fe, 0xE7, 0x40); + zl10353_single_write(fe, 0xE8, 0x10); + + return 0; +} + +static int zl10353_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct zl10353_state *state = fe->demodulator_priv; + int s6, s7, s8; + + if ((s6 = zl10353_read_register(state, STATUS_6)) < 0) + return -EREMOTEIO; + if ((s7 = zl10353_read_register(state, STATUS_7)) < 0) + return -EREMOTEIO; + if ((s8 = zl10353_read_register(state, STATUS_8)) < 0) + return -EREMOTEIO; + + *status = 0; + if (s6 & (1 << 2)) + *status |= FE_HAS_CARRIER; + if (s6 & (1 << 1)) + *status |= FE_HAS_VITERBI; + if (s6 & (1 << 5)) + *status |= FE_HAS_LOCK; + if (s7 & (1 << 4)) + *status |= FE_HAS_SYNC; + if (s8 & (1 << 6)) + *status |= FE_HAS_SIGNAL; + + if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) != + (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) + *status &= ~FE_HAS_LOCK; + + return 0; +} + +static int zl10353_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct zl10353_state *state = fe->demodulator_priv; + u8 _snr; + + if (debug_regs) + zl10353_dump_regs(fe); + + _snr = zl10353_read_register(state, SNR); + *snr = (_snr << 8) | _snr; + + return 0; +} + +static int zl10353_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings + *fe_tune_settings) +{ + fe_tune_settings->min_delay_ms = 1000; + fe_tune_settings->step_size = 0; + fe_tune_settings->max_drift = 0; + + return 0; +} + +static int zl10353_init(struct dvb_frontend *fe) +{ + struct zl10353_state *state = fe->demodulator_priv; + u8 zl10353_reset_attach[6] = { 0x50, 0x03, 0x64, 0x46, 0x15, 0x0F }; + int rc = 0; + + if (debug_regs) + zl10353_dump_regs(fe); + + /* Do a "hard" reset if not already done */ + if (zl10353_read_register(state, 0x50) != 0x03) { + rc = zl10353_write(fe, zl10353_reset_attach, + sizeof(zl10353_reset_attach)); + if (debug_regs) + zl10353_dump_regs(fe); + } + + return 0; +} + +static void zl10353_release(struct dvb_frontend *fe) +{ + struct zl10353_state *state = fe->demodulator_priv; + + kfree(state); +} + +static struct dvb_frontend_ops zl10353_ops; + +struct dvb_frontend *zl10353_attach(const struct zl10353_config *config, + struct i2c_adapter *i2c) +{ + struct zl10353_state *state = NULL; + + /* allocate memory for the internal state */ + state = kzalloc(sizeof(struct zl10353_state), GFP_KERNEL); + if (state == NULL) + goto error; + + /* setup the state */ + state->i2c = i2c; + memcpy(&state->config, config, sizeof(struct zl10353_config)); + memcpy(&state->ops, &zl10353_ops, sizeof(struct dvb_frontend_ops)); + + /* check if the demod is there */ + if (zl10353_read_register(state, CHIP_ID) != ID_ZL10353) + goto error; + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + + return &state->frontend; +error: + kfree(state); + return NULL; +} + +static struct dvb_frontend_ops zl10353_ops = { + + .info = { + .name = "Zarlink ZL10353 DVB-T", + .type = FE_OFDM, + .frequency_min = 174000000, + .frequency_max = 862000000, + .frequency_stepsize = 166667, + .frequency_tolerance = 0, + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | + FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | + FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | + FE_CAN_MUTE_TS + }, + + .release = zl10353_release, + + .init = zl10353_init, + .sleep = zl10353_sleep, + + .set_frontend = zl10353_set_parameters, + .get_tune_settings = zl10353_get_tune_settings, + + .read_status = zl10353_read_status, + .read_snr = zl10353_read_snr, +}; + +module_param(debug_regs, int, 0644); +MODULE_PARM_DESC(debug_regs, "Turn on/off frontend register dumps (default:off)."); + +MODULE_DESCRIPTION("Zarlink ZL10353 DVB-T demodulator driver"); +MODULE_AUTHOR("Chris Pascoe"); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(zl10353_attach); +EXPORT_SYMBOL(zl10353_write); diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h new file mode 100644 index 000000000000..5cc4ae718d8c --- /dev/null +++ b/drivers/media/dvb/frontends/zl10353.h @@ -0,0 +1,43 @@ +/* + * Driver for Zarlink DVB-T ZL10353 demodulator + * + * Copyright (C) 2006 Christopher Pascoe + * + * 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. 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.= + */ + +#ifndef ZL10353_H +#define ZL10353_H + +#include + +struct zl10353_config +{ + /* demodulator's I2C address */ + u8 demod_address; + + /* function which configures the PLL buffer (for secondary I2C + * connected tuner) or tunes the PLL (for direct connected tuner) */ + int (*pll_set)(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params, u8 *pllbuf); +}; + +extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config, + struct i2c_adapter *i2c); + +extern int zl10353_write(struct dvb_frontend *fe, u8 *ibuf, int ilen); + +#endif /* ZL10353_H */ diff --git a/drivers/media/dvb/frontends/zl10353_priv.h b/drivers/media/dvb/frontends/zl10353_priv.h new file mode 100644 index 000000000000..b72224bd7dde --- /dev/null +++ b/drivers/media/dvb/frontends/zl10353_priv.h @@ -0,0 +1,42 @@ +/* + * Driver for Zarlink DVB-T ZL10353 demodulator + * + * Copyright (C) 2006 Christopher Pascoe + * + * 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. 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.= + */ + +#ifndef _ZL10353_PRIV_ +#define _ZL10353_PRIV_ + +#define ID_ZL10353 0x14 + +enum zl10353_reg_addr { + INTERRUPT_0 = 0x00, + INTERRUPT_1 = 0x01, + INTERRUPT_2 = 0x02, + INTERRUPT_3 = 0x03, + INTERRUPT_4 = 0x04, + INTERRUPT_5 = 0x05, + STATUS_6 = 0x06, + STATUS_7 = 0x07, + STATUS_8 = 0x08, + STATUS_9 = 0x09, + SNR = 0x10, + CHIP_ID = 0x7F, +}; + +#endif /* _ZL10353_PRIV_ */ diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile index 2b902784facc..6482b9aa6a1f 100644 --- a/drivers/media/video/cx88/Makefile +++ b/drivers/media/video/cx88/Makefile @@ -17,6 +17,7 @@ extra-cflags-$(CONFIG_DVB_CX22702) += -DHAVE_CX22702=1 extra-cflags-$(CONFIG_DVB_OR51132) += -DHAVE_OR51132=1 extra-cflags-$(CONFIG_DVB_LGDT330X) += -DHAVE_LGDT330X=1 extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1 +extra-cflags-$(CONFIG_DVB_ZL10353) += -DHAVE_ZL10353=1 extra-cflags-$(CONFIG_DVB_NXT200X) += -DHAVE_NXT200X=1 extra-cflags-$(CONFIG_DVB_CX24123) += -DHAVE_CX24123=1 extra-cflags-$(CONFIG_VIDEO_CX88_VP3054)+= -DHAVE_VP3054_I2C=1 diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 44e27dc646ae..d91e5b3a64ef 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1071,6 +1071,27 @@ struct cx88_board cx88_boards[] = { .gpio2 = 0x00ff, }, }, + [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID] = { + .name = "DViCO FusionHDTV DVB-T Hybrid", + .tuner_type = TUNER_FE6600, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0000a75f, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x0000a75b, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x0000a75b, + }}, + .dvb = 1, + }, }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -1281,6 +1302,14 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x17de, .subdevice = 0x0840, .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, + },{ + .subvendor = 0x18ac, + .subdevice = 0xdb40, + .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID, + },{ + .subvendor = 0x18ac, + .subdevice = 0xdb44, + .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID, }, }; const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); @@ -1399,6 +1428,40 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data) core->has_radio = gdi_tuner[eeprom_data[0x0d]].fm; } +/* ----------------------------------------------------------------------- */ +/* some DViCO specific stuff */ + +static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core) +{ + struct i2c_msg msg = { .addr = 0x45, .flags = 0 }; + int i, err; + u8 init_bufs[13][5] = { + { 0x10, 0x00, 0x20, 0x01, 0x03 }, + { 0x10, 0x10, 0x01, 0x00, 0x21 }, + { 0x10, 0x10, 0x10, 0x00, 0xCA }, + { 0x10, 0x10, 0x12, 0x00, 0x08 }, + { 0x10, 0x10, 0x13, 0x00, 0x0A }, + { 0x10, 0x10, 0x16, 0x01, 0xC0 }, + { 0x10, 0x10, 0x22, 0x01, 0x3D }, + { 0x10, 0x10, 0x73, 0x01, 0x2E }, + { 0x10, 0x10, 0x72, 0x00, 0xC5 }, + { 0x10, 0x10, 0x71, 0x01, 0x97 }, + { 0x10, 0x10, 0x70, 0x00, 0x0F }, + { 0x10, 0x10, 0xB0, 0x00, 0x01 }, + { 0x03, 0x0C }, + }; + + for (i = 0; i < 13; i++) { + msg.buf = init_bufs[i]; + msg.len = (i != 12 ? 5 : 2); + err = i2c_transfer(&core->i2c_adap, &msg, 1); + if (err != 1) { + printk("dvico_fusionhdtv_hybrid_init buf %d failed (err = %d)!\n", i, err); + return; + } + } +} + /* ----------------------------------------------------------------------- */ void cx88_card_list(struct cx88_core *core, struct pci_dev *pci) @@ -1465,11 +1528,15 @@ void cx88_card_setup(struct cx88_core *core) case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: /* GPIO0:0 is hooked to mt352 reset pin */ cx_set(MO_GP0_IO, 0x00000101); cx_clear(MO_GP0_IO, 0x00000001); msleep(1); cx_set(MO_GP0_IO, 0x00000101); + if (0 == core->i2c_rc && + core->board == CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID) + dvico_fusionhdtv_hybrid_init(core); break; case CX88_BOARD_KWORLD_DVB_T: case CX88_BOARD_DNTV_LIVE_DVB_T: diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index e48aa3f6e500..2c97d3f7101a 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -40,6 +40,9 @@ # include "cx88-vp3054-i2c.h" # endif #endif +#ifdef HAVE_ZL10353 +# include "zl10353.h" +#endif #ifdef HAVE_CX22702 # include "cx22702.h" #endif @@ -111,6 +114,21 @@ static struct videobuf_queue_ops dvb_qops = { /* ------------------------------------------------------------------ */ +#if defined(HAVE_MT352) || defined(HAVE_ZL10353) +static int zarlink_pll_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params, + u8 *pllbuf) +{ + struct cx8802_dev *dev = fe->dvb->priv; + + pllbuf[0] = dev->core->pll_addr << 1; + dvb_pll_configure(dev->core->pll_desc, pllbuf + 1, + params->frequency, + params->u.ofdm.bandwidth); + return 0; +} +#endif + #ifdef HAVE_MT352 static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) { @@ -176,35 +194,22 @@ static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe) return 0; } -static int mt352_pll_set(struct dvb_frontend* fe, - struct dvb_frontend_parameters* params, - u8* pllbuf) -{ - struct cx8802_dev *dev= fe->dvb->priv; - - pllbuf[0] = dev->core->pll_addr << 1; - dvb_pll_configure(dev->core->pll_desc, pllbuf+1, - params->frequency, - params->u.ofdm.bandwidth); - return 0; -} - static struct mt352_config dvico_fusionhdtv = { .demod_address = 0x0F, .demod_init = dvico_fusionhdtv_demod_init, - .pll_set = mt352_pll_set, + .pll_set = zarlink_pll_set, }; static struct mt352_config dntv_live_dvbt_config = { .demod_address = 0x0f, .demod_init = dntv_live_dvbt_demod_init, - .pll_set = mt352_pll_set, + .pll_set = zarlink_pll_set, }; static struct mt352_config dvico_fusionhdtv_dual = { .demod_address = 0x0F, .demod_init = dvico_dual_demod_init, - .pll_set = mt352_pll_set, + .pll_set = zarlink_pll_set, }; #ifdef HAVE_VP3054_I2C @@ -294,6 +299,46 @@ static struct mt352_config dntv_live_dvbt_pro_config = { #endif #endif +#ifdef HAVE_ZL10353 +static int dvico_hybrid_tune_pll(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params, + u8 *pllbuf) +{ + struct cx8802_dev *dev= fe->dvb->priv; + struct i2c_msg msg = + { .addr = dev->core->pll_addr, .flags = 0, + .buf = pllbuf + 1, .len = 4 }; + int err; + + pllbuf[0] = dev->core->pll_addr << 1; + dvb_pll_configure(dev->core->pll_desc, pllbuf + 1, + params->frequency, + params->u.ofdm.bandwidth); + + if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { + printk(KERN_WARNING "cx88-dvb: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, pllbuf[0], pllbuf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + return 0; +} + +static struct zl10353_config dvico_fusionhdtv_hybrid = { + .demod_address = 0x0F, + .pll_set = dvico_hybrid_tune_pll, +}; + +static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = { + .demod_address = 0x0F, + .pll_set = zarlink_pll_set, +}; +#endif + #ifdef HAVE_CX22702 static struct cx22702_config connexant_refboard_config = { .demod_address = 0x43, @@ -500,16 +545,27 @@ static int dvb_register(struct cx8802_dev *dev) &dev->core->i2c_adap); break; #endif +#if defined(HAVE_MT352) || defined(HAVE_ZL10353) + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: + dev->core->pll_addr = 0x60; + dev->core->pll_desc = &dvb_pll_thomson_dtt7579; #ifdef HAVE_MT352 - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: - dev->core->pll_addr = 0x61; - dev->core->pll_desc = &dvb_pll_lg_z201; dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) + break; +#endif +#ifdef HAVE_ZL10353 + /* ZL10353 replaces MT352 on later cards */ + dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1, + &dev->core->i2c_adap); +#endif break; - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: - dev->core->pll_addr = 0x60; - dev->core->pll_desc = &dvb_pll_thomson_dtt7579; +#endif /* HAVE_MT352 || HAVE_ZL10353 */ +#ifdef HAVE_MT352 + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: + dev->core->pll_addr = 0x61; + dev->core->pll_desc = &dvb_pll_lg_z201; dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, &dev->core->i2c_adap); break; @@ -540,6 +596,14 @@ static int dvb_register(struct cx8802_dev *dev) &dev->core->i2c_adap); break; #endif +#ifdef HAVE_ZL10353 + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: + dev->core->pll_addr = 0x61; + dev->core->pll_desc = &dvb_pll_unknown_fe6600; + dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_hybrid, + &dev->core->i2c_adap); + break; +#endif #ifdef HAVE_OR51132 case CX88_BOARD_PCHDTV_HD3000: dev->dvb.frontend = or51132_attach(&pchdtv_hd3000, diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index a4cf2473eacf..21738b664bc9 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -189,6 +189,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_KWORLD_DVB_T_CX22702 43 #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44 #define CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT 45 +#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID 46 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 15761dd8607d..d10cfd400f2b 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -983,6 +983,22 @@ static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = { }, }; +/* ------------ TUNER_FE6600 - DViCO Hybrid PAL ------------ */ + +static struct tuner_range tuner_fe6600_ranges[] = { + { 16 * 160.00 /*MHz*/, 0xfe, 0x11, }, + { 16 * 442.00 /*MHz*/, 0xf6, 0x12, }, + { 16 * 999.99 , 0xf6, 0x18, }, +}; + +static struct tuner_params tuner_fe6600_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_fe6600_ranges, + .count = ARRAY_SIZE(tuner_fe6600_ranges), + }, +}; + /* --------------------------------------------------------------------- */ struct tunertype tuners[] = { @@ -1354,6 +1370,10 @@ struct tunertype tuners[] = { .name = "Xceive xc3028", /* see xc3028.c for details */ }, + [TUNER_FE6600] = { /* */ + .name = "FE6600", + .params = tuner_fe6600_params, + }, }; unsigned const int tuner_count = ARRAY_SIZE(tuners); diff --git a/include/media/tuner.h b/include/media/tuner.h index f51759c0d180..039c77e02d34 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -116,9 +116,10 @@ #define TUNER_PHILIPS_TUV1236D 68 /* ATI HDTV Wonder */ #define TUNER_TNF_5335MF 69 /* Sabrent Bt848 */ #define TUNER_SAMSUNG_TCPN_2121P30A 70 /* Hauppauge PVR-500MCE NTSC */ - #define TUNER_XCEIVE_XC3028 71 +#define TUNER_FE6600 72 /* DViCO FusionHDTV DVB-T Hybrid */ + /* tv card specific */ #define TDA9887_PRESENT (1<<0) #define TDA9887_PORT1_INACTIVE (1<<1) -- cgit v1.2.3 From 91ae3299d7d3493a25e5f26cbaceeb18e7760ef3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 1 Mar 2006 00:04:42 -0300 Subject: V4L/DVB (3411): FE6600 is a Thomson tuner - The tuner used in DViCO FusionHDTV DVB-T hybrid is made by Thomson - renamed tuner and dvb_pll structs accordingly Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.tuner | 2 +- drivers/media/dvb/frontends/dvb-pll.c | 6 +++--- drivers/media/dvb/frontends/dvb-pll.h | 2 +- drivers/media/video/cx88/cx88-cards.c | 2 +- drivers/media/video/cx88/cx88-dvb.c | 2 +- drivers/media/video/tuner-types.c | 16 ++++++++-------- include/media/tuner.h | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index ab344c94c0a2..603f165376fe 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -70,4 +70,4 @@ tuner=68 - Philips TUV1236D ATSC/NTSC dual in tuner=69 - Tena TNF 5335 MF tuner=70 - Samsung TCPN 2121P30A tuner=71 - Xceive xc3028 -tuner=72 - FE6600 +tuner=72 - Thomson FE6600 diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 8a4c904d3a27..b6e2c387a04c 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -405,8 +405,8 @@ struct dvb_pll_desc dvb_pll_philips_td1316 = { EXPORT_SYMBOL(dvb_pll_philips_td1316); /* FE6600 used on DViCO Hybrid */ -struct dvb_pll_desc dvb_pll_unknown_fe6600 = { - .name = "FE6600", +struct dvb_pll_desc dvb_pll_thomson_fe6600 = { + .name = "Thomson FE6600", .min = 44250000, .max = 858000000, .count = 4, @@ -417,7 +417,7 @@ struct dvb_pll_desc dvb_pll_unknown_fe6600 = { { 999999999, 36213333, 166667, 0xf4, 0x18 }, } }; -EXPORT_SYMBOL(dvb_pll_unknown_fe6600); +EXPORT_SYMBOL(dvb_pll_thomson_fe6600); /* ----------------------------------------------------------- */ /* code */ diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index 8a7f0b941c38..2b8461784989 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -42,7 +42,7 @@ extern struct dvb_pll_desc dvb_pll_samsung_tbmv; extern struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261; extern struct dvb_pll_desc dvb_pll_philips_td1316; -extern struct dvb_pll_desc dvb_pll_unknown_fe6600; +extern struct dvb_pll_desc dvb_pll_thomson_fe6600; int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, u32 freq, int bandwidth); diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index f655567a8ecd..c0d1f0b12829 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1073,7 +1073,7 @@ struct cx88_board cx88_boards[] = { }, [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID] = { .name = "DViCO FusionHDTV DVB-T Hybrid", - .tuner_type = TUNER_FE6600, + .tuner_type = TUNER_THOMSON_FE6600, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 2c97d3f7101a..a9fc2695b157 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -599,7 +599,7 @@ static int dvb_register(struct cx8802_dev *dev) #ifdef HAVE_ZL10353 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: dev->core->pll_addr = 0x61; - dev->core->pll_desc = &dvb_pll_unknown_fe6600; + dev->core->pll_desc = &dvb_pll_thomson_fe6600; dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_hybrid, &dev->core->i2c_adap); break; diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index d10cfd400f2b..db8b9873029b 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -983,19 +983,19 @@ static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = { }, }; -/* ------------ TUNER_FE6600 - DViCO Hybrid PAL ------------ */ +/* ------------ TUNER_THOMSON_FE6600 - DViCO Hybrid PAL ------------ */ -static struct tuner_range tuner_fe6600_ranges[] = { +static struct tuner_range tuner_thomson_fe6600_ranges[] = { { 16 * 160.00 /*MHz*/, 0xfe, 0x11, }, { 16 * 442.00 /*MHz*/, 0xf6, 0x12, }, { 16 * 999.99 , 0xf6, 0x18, }, }; -static struct tuner_params tuner_fe6600_params[] = { +static struct tuner_params tuner_thomson_fe6600_params[] = { { .type = TUNER_PARAM_TYPE_PAL, - .ranges = tuner_fe6600_ranges, - .count = ARRAY_SIZE(tuner_fe6600_ranges), + .ranges = tuner_thomson_fe6600_ranges, + .count = ARRAY_SIZE(tuner_thomson_fe6600_ranges), }, }; @@ -1370,9 +1370,9 @@ struct tunertype tuners[] = { .name = "Xceive xc3028", /* see xc3028.c for details */ }, - [TUNER_FE6600] = { /* */ - .name = "FE6600", - .params = tuner_fe6600_params, + [TUNER_THOMSON_FE6600] = { /* Thomson PAL / DVB-T */ + .name = "Thomson FE6600", + .params = tuner_thomson_fe6600_params, }, }; diff --git a/include/media/tuner.h b/include/media/tuner.h index 039c77e02d34..02d7d9a76fa2 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -118,7 +118,7 @@ #define TUNER_SAMSUNG_TCPN_2121P30A 70 /* Hauppauge PVR-500MCE NTSC */ #define TUNER_XCEIVE_XC3028 71 -#define TUNER_FE6600 72 /* DViCO FusionHDTV DVB-T Hybrid */ +#define TUNER_THOMSON_FE6600 72 /* DViCO FusionHDTV DVB-T Hybrid */ /* tv card specific */ #define TDA9887_PRESENT (1<<0) -- cgit v1.2.3 From 86e45b6bd6900c4a0b3666fb18b46e215f775c4f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 5 Mar 2006 15:29:09 +0900 Subject: [PATCH] libata: implement port_task Implement port_task. LLDD's can schedule a function to be executed with context after specified delay. libata core takes care of synchronization against EH. This is generalized form of pio_task and packet_task which are tied to PIO hsm implementation. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/libata-scsi.c | 2 ++ drivers/scsi/libata.h | 1 + include/linux/libata.h | 4 +++ 4 files changed, 84 insertions(+) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 5dbcf0cf4a10..d59d462130c1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -721,6 +721,81 @@ static unsigned int ata_pio_modes(const struct ata_device *adev) timing API will get this right anyway */ } +/** + * ata_port_queue_task - Queue port_task + * @ap: The ata_port to queue port_task for + * + * Schedule @fn(@data) for execution after @delay jiffies using + * port_task. There is one port_task per port and it's the + * user(low level driver)'s responsibility to make sure that only + * one task is active at any given time. + * + * libata core layer takes care of synchronization between + * port_task and EH. ata_port_queue_task() may be ignored for EH + * synchronization. + * + * LOCKING: + * Inherited from caller. + */ +void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data, + unsigned long delay) +{ + int rc; + + if (ap->flags & ATA_FLAG_FLUSH_PIO_TASK) + return; + + PREPARE_WORK(&ap->port_task, fn, data); + + if (!delay) + rc = queue_work(ata_wq, &ap->port_task); + else + rc = queue_delayed_work(ata_wq, &ap->port_task, delay); + + /* rc == 0 means that another user is using port task */ + WARN_ON(rc == 0); +} + +/** + * ata_port_flush_task - Flush port_task + * @ap: The ata_port to flush port_task for + * + * After this function completes, port_task is guranteed not to + * be running or scheduled. + * + * LOCKING: + * Kernel thread context (may sleep) + */ +void ata_port_flush_task(struct ata_port *ap) +{ + unsigned long flags; + + DPRINTK("ENTER\n"); + + spin_lock_irqsave(&ap->host_set->lock, flags); + ap->flags |= ATA_FLAG_FLUSH_PIO_TASK; + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + DPRINTK("flush #1\n"); + flush_workqueue(ata_wq); + + /* + * At this point, if a task is running, it's guaranteed to see + * the FLUSH flag; thus, it will never queue pio tasks again. + * Cancel and flush. + */ + if (!cancel_delayed_work(&ap->port_task)) { + DPRINTK("flush #2\n"); + flush_workqueue(ata_wq); + } + + spin_lock_irqsave(&ap->host_set->lock, flags); + ap->flags &= ~ATA_FLAG_FLUSH_PIO_TASK; + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + DPRINTK("EXIT\n"); +} + static inline void ata_queue_packet_task(struct ata_port *ap) { @@ -4617,6 +4692,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ap->active_tag = ATA_TAG_POISON; ap->last_ctl = 0xFF; + INIT_WORK(&ap->port_task, NULL, NULL); INIT_WORK(&ap->packet_task, atapi_packet_task, ap); INIT_WORK(&ap->pio_task, ata_pio_task, ap); INIT_LIST_HEAD(&ap->eh_done_q); @@ -5088,6 +5164,7 @@ EXPORT_SYMBOL_GPL(ata_dev_revalidate); EXPORT_SYMBOL_GPL(ata_port_disable); EXPORT_SYMBOL_GPL(ata_ratelimit); EXPORT_SYMBOL_GPL(ata_busy_sleep); +EXPORT_SYMBOL_GPL(ata_port_queue_task); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); EXPORT_SYMBOL_GPL(ata_scsi_timed_out); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index d0bd94abb413..ccedb4536977 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -785,6 +785,8 @@ int ata_scsi_error(struct Scsi_Host *host) WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL); spin_unlock_irqrestore(&ap->host_set->lock, flags); + ata_port_flush_task(ap); + ap->ops->eng_timeout(ap); WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q)); diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index d822eba05f3c..f4c48c91b63d 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -45,6 +45,7 @@ extern int libata_fua; extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, struct ata_device *dev); extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); +extern void ata_port_flush_task(struct ata_port *ap); extern void ata_qc_free(struct ata_queued_cmd *qc); extern unsigned int ata_qc_issue(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); diff --git a/include/linux/libata.h b/include/linux/libata.h index 66dce58f1941..3ad2570f663b 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -388,6 +388,8 @@ struct ata_port { struct ata_host_stats stats; struct ata_host_set *host_set; + struct work_struct port_task; + struct work_struct packet_task; struct work_struct pio_task; @@ -515,6 +517,8 @@ extern int ata_ratelimit(void); extern unsigned int ata_busy_sleep(struct ata_port *ap, unsigned long timeout_pat, unsigned long timeout); +extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), + void *data, unsigned long delay); /* * Default driver ops implementations -- cgit v1.2.3 From 507ceda00302c071029277652d9faa5a0a55419a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 5 Mar 2006 15:29:09 +0900 Subject: [PATCH] libata: kill unused pio_task and packet_task Kill unused pio_task and packet_task. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 68 ---------------------------------------------- include/linux/libata.h | 3 -- 2 files changed, 71 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 16a108d2f9a9..2974438d3bb7 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -796,71 +796,6 @@ void ata_port_flush_task(struct ata_port *ap) DPRINTK("EXIT\n"); } -static inline void -ata_queue_packet_task(struct ata_port *ap) -{ - if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK)) - queue_work(ata_wq, &ap->packet_task); -} - -static inline void -ata_queue_pio_task(struct ata_port *ap) -{ - if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK)) - queue_work(ata_wq, &ap->pio_task); -} - -static inline void -ata_queue_delayed_pio_task(struct ata_port *ap, unsigned long delay) -{ - if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK)) - queue_delayed_work(ata_wq, &ap->pio_task, delay); -} - -/** - * ata_flush_pio_tasks - Flush pio_task and packet_task - * @ap: the target ata_port - * - * After this function completes, pio_task and packet_task are - * guranteed not to be running or scheduled. - * - * LOCKING: - * Kernel thread context (may sleep) - */ - -static void ata_flush_pio_tasks(struct ata_port *ap) -{ - int tmp = 0; - unsigned long flags; - - DPRINTK("ENTER\n"); - - spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags |= ATA_FLAG_FLUSH_PIO_TASK; - spin_unlock_irqrestore(&ap->host_set->lock, flags); - - DPRINTK("flush #1\n"); - flush_workqueue(ata_wq); - - /* - * At this point, if a task is running, it's guaranteed to see - * the FLUSH flag; thus, it will never queue pio tasks again. - * Cancel and flush. - */ - tmp |= cancel_delayed_work(&ap->pio_task); - tmp |= cancel_delayed_work(&ap->packet_task); - if (!tmp) { - DPRINTK("flush #2\n"); - flush_workqueue(ata_wq); - } - - spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags &= ~ATA_FLAG_FLUSH_PIO_TASK; - spin_unlock_irqrestore(&ap->host_set->lock, flags); - - DPRINTK("EXIT\n"); -} - void ata_qc_complete_internal(struct ata_queued_cmd *qc) { struct completion *waiting = qc->private_data; @@ -3814,7 +3749,6 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) DPRINTK("ENTER\n"); - ata_flush_pio_tasks(ap); ap->hsm_task_state = HSM_ST_IDLE; spin_lock_irqsave(&host_set->lock, flags); @@ -4693,8 +4627,6 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ap->last_ctl = 0xFF; INIT_WORK(&ap->port_task, NULL, NULL); - INIT_WORK(&ap->packet_task, atapi_packet_task, ap); - INIT_WORK(&ap->pio_task, ata_pio_task, ap); INIT_LIST_HEAD(&ap->eh_done_q); for (i = 0; i < ATA_MAX_DEVICES; i++) diff --git a/include/linux/libata.h b/include/linux/libata.h index 3ad2570f663b..9ad020ac8591 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -390,9 +390,6 @@ struct ata_port { struct work_struct port_task; - struct work_struct packet_task; - - struct work_struct pio_task; unsigned int hsm_task_state; unsigned long pio_task_timeout; -- cgit v1.2.3 From 2e755f68ee23b03484fde18d978f910cc5479cb8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 5 Mar 2006 15:29:09 +0900 Subject: [PATCH] libata: rename ATA_FLAG_FLUSH_PIO_TASK to ATA_FLAG_FLUSH_PORT_TASK Rename ATA_FLAG_FLUSH_PIO_TASK to ATA_FLAG_FLUSH_PORT_TASK. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 6 +++--- include/linux/libata.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 2974438d3bb7..6d8aa86f2f6b 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -742,7 +742,7 @@ void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data, { int rc; - if (ap->flags & ATA_FLAG_FLUSH_PIO_TASK) + if (ap->flags & ATA_FLAG_FLUSH_PORT_TASK) return; PREPARE_WORK(&ap->port_task, fn, data); @@ -773,7 +773,7 @@ void ata_port_flush_task(struct ata_port *ap) DPRINTK("ENTER\n"); spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags |= ATA_FLAG_FLUSH_PIO_TASK; + ap->flags |= ATA_FLAG_FLUSH_PORT_TASK; spin_unlock_irqrestore(&ap->host_set->lock, flags); DPRINTK("flush #1\n"); @@ -790,7 +790,7 @@ void ata_port_flush_task(struct ata_port *ap) } spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags &= ~ATA_FLAG_FLUSH_PIO_TASK; + ap->flags &= ~ATA_FLAG_FLUSH_PORT_TASK; spin_unlock_irqrestore(&ap->host_set->lock, flags); DPRINTK("EXIT\n"); diff --git a/include/linux/libata.h b/include/linux/libata.h index 9ad020ac8591..15674923cc84 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -151,7 +151,7 @@ enum { ATA_FLAG_PIO_LBA48 = (1 << 13), /* Host DMA engine is LBA28 only */ ATA_FLAG_IRQ_MASK = (1 << 14), /* Mask IRQ in PIO xfers */ - ATA_FLAG_FLUSH_PIO_TASK = (1 << 15), /* Flush PIO task */ + ATA_FLAG_FLUSH_PORT_TASK = (1 << 15), /* Flush port task */ ATA_FLAG_IN_EH = (1 << 16), /* EH in progress */ ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ -- cgit v1.2.3 From 1da7b0d01b20bf21f3263d8d2f17fa49a214d773 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 6 Mar 2006 04:31:56 +0900 Subject: [PATCH] libata: improve xfer mask constants and update ata_mode_string() Add ATA_BITS_*, ATA_MASK_* macros and reorder xfer_mask fields such that higher transfer mode is placed at higher order bit. As thie reordering breaks ata_mode_string(), this patch also rewrites ata_mode_string(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 44 +++++++++++++++++--------------------------- include/linux/libata.h | 16 ++++++++++++---- 2 files changed, 29 insertions(+), 31 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 6d8aa86f2f6b..18418c82d6f6 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -232,6 +232,14 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc) } static const char * const xfer_mode_str[] = { + "PIO0", + "PIO1", + "PIO2", + "PIO3", + "PIO4", + "MWDMA0", + "MWDMA1", + "MWDMA2", "UDMA/16", "UDMA/25", "UDMA/33", @@ -240,49 +248,31 @@ static const char * const xfer_mode_str[] = { "UDMA/100", "UDMA/133", "UDMA7", - "MWDMA0", - "MWDMA1", - "MWDMA2", - "PIO0", - "PIO1", - "PIO2", - "PIO3", - "PIO4", }; /** - * ata_udma_string - convert UDMA bit offset to string - * @mask: mask of bits supported; only highest bit counts. + * ata_mode_string - convert xfer_mask to string + * @xfer_mask: mask of bits supported; only highest bit counts. * * Determine string which represents the highest speed - * (highest bit in @udma_mask). + * (highest bit in @modemask). * * LOCKING: * None. * * RETURNS: * Constant C string representing highest speed listed in - * @udma_mask, or the constant C string "". + * @mode_mask, or the constant C string "". */ -static const char *ata_mode_string(unsigned int mask) +static const char *ata_mode_string(unsigned int xfer_mask) { - int i; - - for (i = 7; i >= 0; i--) - if (mask & (1 << i)) - goto out; - for (i = ATA_SHIFT_MWDMA + 2; i >= ATA_SHIFT_MWDMA; i--) - if (mask & (1 << i)) - goto out; - for (i = ATA_SHIFT_PIO + 4; i >= ATA_SHIFT_PIO; i--) - if (mask & (1 << i)) - goto out; + int highbit; + highbit = fls(xfer_mask) - 1; + if (highbit >= 0 && highbit < ARRAY_SIZE(xfer_mode_str)) + return xfer_mode_str[highbit]; return ""; - -out: - return xfer_mode_str[i]; } /** diff --git a/include/linux/libata.h b/include/linux/libata.h index 15674923cc84..239408ecfddf 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -188,11 +188,19 @@ enum { PORT_DISABLED = 2, /* encoding various smaller bitmaps into a single - * unsigned long bitmap + * unsigned int bitmap */ - ATA_SHIFT_UDMA = 0, - ATA_SHIFT_MWDMA = 8, - ATA_SHIFT_PIO = 11, + ATA_BITS_PIO = 5, + ATA_BITS_MWDMA = 3, + ATA_BITS_UDMA = 8, + + ATA_SHIFT_PIO = 0, + ATA_SHIFT_MWDMA = ATA_SHIFT_PIO + ATA_BITS_PIO, + ATA_SHIFT_UDMA = ATA_SHIFT_MWDMA + ATA_BITS_MWDMA, + + ATA_MASK_PIO = ((1 << ATA_BITS_PIO) - 1) << ATA_SHIFT_PIO, + ATA_MASK_MWDMA = ((1 << ATA_BITS_MWDMA) - 1) << ATA_SHIFT_MWDMA, + ATA_MASK_UDMA = ((1 << ATA_BITS_UDMA) - 1) << ATA_SHIFT_UDMA, /* size of buffer to pad xfers ending on unaligned boundaries */ ATA_DMA_PAD_SZ = 4, -- cgit v1.2.3 From 044cc6c8ec311c4ddeebfcc31c53dea282de70b7 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Thu, 9 Mar 2006 14:27:13 -0800 Subject: [SCSI] qla2xxx: Add ISP54xx support. Chip is similar in form to our ISP24xx offering. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/ql2400.c | 27 +++++++++++++++++++++++++ drivers/scsi/qla2xxx/qla_attr.c | 8 ++++---- drivers/scsi/qla2xxx/qla_def.h | 12 +++++------ drivers/scsi/qla2xxx/qla_gs.c | 10 ++++------ drivers/scsi/qla2xxx/qla_init.c | 14 ++++++------- drivers/scsi/qla2xxx/qla_inline.h | 2 +- drivers/scsi/qla2xxx/qla_iocb.c | 6 +++--- drivers/scsi/qla2xxx/qla_isr.c | 16 +++++++-------- drivers/scsi/qla2xxx/qla_mbx.c | 42 +++++++++++++++++++-------------------- drivers/scsi/qla2xxx/qla_os.c | 18 ++++++++++------- include/linux/pci_ids.h | 2 ++ 11 files changed, 94 insertions(+), 63 deletions(-) (limited to 'include') diff --git a/drivers/scsi/qla2xxx/ql2400.c b/drivers/scsi/qla2xxx/ql2400.c index 6c7165f47e29..77914fcfa2bc 100644 --- a/drivers/scsi/qla2xxx/ql2400.c +++ b/drivers/scsi/qla2xxx/ql2400.c @@ -49,6 +49,18 @@ static struct qla_board_info qla_board_tbl[] = { .fw_info = qla_fw_tbl, .fw_fname = "ql2400_fw.bin", }, + { + .drv_name = qla_driver_name, + .isp_name = "ISP5422", + .fw_info = qla_fw_tbl, + .fw_fname = "ql2400_fw.bin", + }, + { + .drv_name = qla_driver_name, + .isp_name = "ISP5432", + .fw_info = qla_fw_tbl, + .fw_fname = "ql2400_fw.bin", + }, }; static struct pci_device_id qla24xx_pci_tbl[] = { @@ -66,6 +78,21 @@ static struct pci_device_id qla24xx_pci_tbl[] = { .subdevice = PCI_ANY_ID, .driver_data = (unsigned long)&qla_board_tbl[1], }, + { + .vendor = PCI_VENDOR_ID_QLOGIC, + .device = PCI_DEVICE_ID_QLOGIC_ISP5422, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = (unsigned long)&qla_board_tbl[2], + }, + { + .vendor = PCI_VENDOR_ID_QLOGIC, + .device = PCI_DEVICE_ID_QLOGIC_ISP5432, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = (unsigned long)&qla_board_tbl[3], + }, + {0, 0}, }; MODULE_DEVICE_TABLE(pci, qla24xx_pci_tbl); diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 92b3e13e9061..2b9e329a240c 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -50,7 +50,7 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off, ha->host_no); vfree(ha->fw_dump_buffer); - if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) free_pages((unsigned long)ha->fw_dump, ha->fw_dump_order); @@ -64,7 +64,7 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off, if ((ha->fw_dump || ha->fw_dumped) && !ha->fw_dump_reading) { ha->fw_dump_reading = 1; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) dump_size = FW_DUMP_SIZE_24XX; else { dump_size = FW_DUMP_SIZE_1M; @@ -138,7 +138,7 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off, return 0; /* Checksum NVRAM. */ - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { uint32_t *iter; uint32_t chksum; @@ -750,7 +750,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) pfc_host_stat = &ha->fc_host_stat; memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf, sizeof(stat_buf) / 4, mb_stat); } else { diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 00b7e82b99b3..e1a7769008ee 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2234,9 +2234,9 @@ typedef struct scsi_qla_host { #define DT_ISP6322 BIT_6 #define DT_ISP2422 BIT_7 #define DT_ISP2432 BIT_8 -#define DT_ISP2512 BIT_9 -#define DT_ISP2522 BIT_10 -#define DT_ISP_LAST (DT_ISP2522 << 1) +#define DT_ISP5422 BIT_9 +#define DT_ISP5432 BIT_10 +#define DT_ISP_LAST (DT_ISP5432 << 1) #define DT_OEM_001 BIT_29 #define DT_ISP2200A BIT_30 @@ -2252,13 +2252,13 @@ typedef struct scsi_qla_host { #define IS_QLA6322(ha) (DT_MASK(ha) & DT_ISP6322) #define IS_QLA2422(ha) (DT_MASK(ha) & DT_ISP2422) #define IS_QLA2432(ha) (DT_MASK(ha) & DT_ISP2432) -#define IS_QLA2512(ha) (DT_MASK(ha) & DT_ISP2512) -#define IS_QLA2522(ha) (DT_MASK(ha) & DT_ISP2522) +#define IS_QLA5422(ha) (DT_MASK(ha) & DT_ISP5422) +#define IS_QLA5432(ha) (DT_MASK(ha) & DT_ISP5432) #define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \ IS_QLA6312(ha) || IS_QLA6322(ha)) #define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha)) -#define IS_QLA25XX(ha) (IS_QLA2512(ha) || IS_QLA2522(ha)) +#define IS_QLA54XX(ha) (IS_QLA5422(ha) || IS_QLA5432(ha)) #define IS_OEM_001(ha) ((ha)->device_type & DT_OEM_001) #define HAS_EXTENDED_IDS(ha) ((ha)->device_type & DT_EXTENDED_IDS) diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index d620a8e8a614..2ebf259fccb2 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -126,7 +126,7 @@ qla2x00_chk_ms_status(scsi_qla_host_t *ha, ms_iocb_entry_t *ms_pkt, DEBUG2_3(printk("scsi(%ld): %s failed, error status (%x).\n", ha->host_no, routine, ms_pkt->entry_status)); } else { - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) comp_status = ((struct ct_entry_24xx *)ms_pkt)->comp_status; else @@ -1200,7 +1200,7 @@ qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size) ms_iocb_entry_t *ms_pkt = ha->ms_iocb; struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { ct_pkt->cmd_byte_count = cpu_to_le32(req_size); ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count; } else { @@ -1529,9 +1529,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) eiter = (struct ct_fdmi_port_attr *) (entries + size); eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); eiter->len = __constant_cpu_to_be16(4 + 4); - if (IS_QLA25XX(ha)) - eiter->a.sup_speed = __constant_cpu_to_be32(8); - else if (IS_QLA24XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) eiter->a.sup_speed = __constant_cpu_to_be32(4); else if (IS_QLA23XX(ha)) eiter->a.sup_speed = __constant_cpu_to_be32(2); @@ -1566,7 +1564,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) eiter = (struct ct_fdmi_port_attr *) (entries + size); eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); eiter->len = __constant_cpu_to_be16(4 + 4); - max_frame_size = IS_QLA24XX(ha) || IS_QLA25XX(ha) ? + max_frame_size = IS_QLA24XX(ha) || IS_QLA54XX(ha) ? (uint32_t) icb24->frame_payload_size: (uint32_t) ha->init_cb->frame_payload_size; eiter->a.max_frame_size = cpu_to_be32(max_frame_size); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index f49eb06d0dbd..e6a2292a2892 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -387,7 +387,7 @@ qla2x00_isp_firmware(scsi_qla_host_t *ha) /* Verify checksum of loaded RISC code. */ rval = qla2x00_verify_checksum(ha, - IS_QLA24XX(ha) || IS_QLA25XX(ha) ? RISC_SADDRESS : + IS_QLA24XX(ha) || IS_QLA54XX(ha) ? RISC_SADDRESS : *ha->brd_info->fw_info[0].fwstart); } @@ -822,7 +822,7 @@ qla2x00_resize_request_q(scsi_qla_host_t *ha) if (IS_QLA2100(ha) || IS_QLA2200(ha)) return; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) qla2x00_alloc_fw_dump(ha); /* Retrieve IOCB counts available to the firmware. */ @@ -2123,7 +2123,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) LIST_HEAD(new_fcports); /* If FL port exists, then SNS is present */ - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) loop_id = NPH_F_PORT; else loop_id = SNS_FL_PORT; @@ -2149,7 +2149,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) qla2x00_fdmi_register(ha); /* Ensure we are logged into the SNS. */ - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) loop_id = NPH_SNS; else loop_id = SIMPLE_NAME_SERVER; @@ -2640,7 +2640,7 @@ qla2x00_device_resync(scsi_qla_host_t *ha) if (ql2xprocessrscn && !IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) && !IS_QLA6322(ha) && - !IS_QLA24XX(ha) && !IS_QLA25XX(ha) && + !IS_QLA24XX(ha) && !IS_QLA54XX(ha) && ha->flags.init_done) { /* Handle port RSCN via asyncronous IOCBs */ rval2 = qla2x00_handle_port_rscn(ha, rscn_entry, @@ -3130,7 +3130,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) spin_lock_irqsave(&ha->hardware_lock, flags); - if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) { + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) { /* * Disable SRAM, Instruction RAM and GP RAM * parity. @@ -3146,7 +3146,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) spin_lock_irqsave(&ha->hardware_lock, flags); - if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) { + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) { /* Enable proper parity */ if (IS_QLA2300(ha)) /* SRAM parity */ diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index ecc3741a452e..45007ee58067 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -163,7 +163,7 @@ static inline int qla2x00_is_reserved_id(scsi_qla_host_t *, uint16_t); static inline int qla2x00_is_reserved_id(scsi_qla_host_t *ha, uint16_t loop_id) { - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) return (loop_id > NPH_LAST_HANDLE); return ((loop_id > ha->last_loop_id && loop_id < SNS_FIRST_LOOP_ID) || diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 6544b6d0891d..8f0f4a298357 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -466,7 +466,7 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, mrk->entry_type = MARKER_TYPE; mrk->modifier = type; if (type != MK_SYNC_ALL) { - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mrk24 = (struct mrk_entry_24xx *) mrk; mrk24->nport_handle = cpu_to_le16(loop_id); mrk24->lun[1] = LSB(lun); @@ -519,7 +519,7 @@ qla2x00_req_pkt(scsi_qla_host_t *ha) for (timer = HZ; timer; timer--) { if ((req_cnt + 2) >= ha->req_q_cnt) { /* Calculate number of free request entries. */ - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) cnt = (uint16_t)RD_REG_DWORD( ®->isp24.req_q_out); else @@ -593,7 +593,7 @@ qla2x00_isp_cmd(scsi_qla_host_t *ha) ha->request_ring_ptr++; /* Set chip new ring index. */ - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { WRT_REG_DWORD(®->isp24.req_q_in, ha->req_ring_index); RD_REG_DWORD_RELAXED(®->isp24.req_q_in); } else { diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index c15458c2bf32..2003dbb70579 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -343,7 +343,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) ha->isp_ops.fw_dump(ha, 1); - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (mb[1] == 0 && mb[2] == 0) { qla_printk(KERN_ERR, ha, "Unrecoverable Hardware Error: adapter " @@ -521,7 +521,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) */ if (ql2xprocessrscn && !IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) && - !IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA25XX(ha) && + !IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA54XX(ha) && ha->flags.init_done && mb[1] != 0xffff && ((ha->operating_mode == P2P && mb[1] != 0) || (ha->operating_mode != P2P && mb[1] != @@ -638,7 +638,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) "scsi(%ld): [R|Z]IO update completion.\n", ha->host_no)); - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) qla24xx_process_response_queue(ha); else qla2x00_process_response_queue(ha); @@ -810,7 +810,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) sts = (sts_entry_t *) pkt; sts24 = (struct sts_entry_24xx *) pkt; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { comp_status = le16_to_cpu(sts24->comp_status); scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK; } else { @@ -860,7 +860,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) fcport = sp->fcport; sense_len = rsp_info_len = resid_len = 0; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { sense_len = le32_to_cpu(sts24->sense_len); rsp_info_len = le32_to_cpu(sts24->rsp_data_len); resid_len = le32_to_cpu(sts24->rsp_residual_count); @@ -878,7 +878,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) /* Check for any FCP transport errors. */ if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) { /* Sense data lies beyond any FCP RESPONSE data. */ - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) sense_data += rsp_info_len; if (rsp_info_len > 3 && rsp_info[3]) { DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol " @@ -1117,7 +1117,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) case CS_TIMEOUT: cp->result = DID_BUS_BUSY << 16; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { DEBUG2(printk(KERN_INFO "scsi(%ld:%d:%d:%d): TIMEOUT status detected " "0x%x-0x%x\n", ha->host_no, cp->device->channel, @@ -1197,7 +1197,7 @@ qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt) } /* Move sense data. */ - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) host_to_fcp_swap(pkt->data, sizeof(pkt->data)); memcpy(sp->request_sense_ptr, pkt->data, sense_sz); DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz)); diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 584cc2f6dd35..267435f17482 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -91,7 +91,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) spin_lock_irqsave(&ha->hardware_lock, flags); /* Load mailbox registers. */ - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) optr = (uint16_t __iomem *)®->isp24.mailbox0; else optr = (uint16_t __iomem *)MAILBOX_REG(ha, ®->isp, 0); @@ -155,7 +155,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) WRT_REG_DWORD(®->isp24.hccr, HCCRX_SET_HOST_INT); else WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); @@ -179,7 +179,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) DEBUG3_11(printk("%s(%ld): cmd=%x POLLING MODE.\n", __func__, ha->host_no, command);) - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) WRT_REG_DWORD(®->isp24.hccr, HCCRX_SET_HOST_INT); else WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); @@ -237,7 +237,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) uint16_t mb0; uint32_t ictrl; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mb0 = RD_REG_WORD(®->isp24.mailbox0); ictrl = RD_REG_DWORD(®->isp24.ictrl); } else { @@ -334,7 +334,7 @@ qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr, DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); - if (MSW(risc_addr) || IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (MSW(risc_addr) || IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED; mcp->mb[8] = MSW(risc_addr); mcp->out_mb = MBX_8|MBX_0; @@ -348,7 +348,7 @@ qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr, mcp->mb[6] = MSW(MSD(req_dma)); mcp->mb[7] = LSW(MSD(req_dma)); mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mcp->mb[4] = MSW(risc_code_size); mcp->mb[5] = LSW(risc_code_size); mcp->out_mb |= MBX_5|MBX_4; @@ -399,7 +399,7 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr) mcp->mb[0] = MBC_EXECUTE_FIRMWARE; mcp->out_mb = MBX_0; mcp->in_mb = MBX_0; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mcp->mb[1] = MSW(risc_addr); mcp->mb[2] = LSW(risc_addr); mcp->mb[3] = 0; @@ -422,7 +422,7 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr) DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__, ha->host_no, rval, mcp->mb[0])); } else { - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { DEBUG11(printk("%s(%ld): done exchanges=%x.\n", __func__, ha->host_no, mcp->mb[1]);) } else { @@ -563,7 +563,7 @@ qla2x00_set_fw_options(scsi_qla_host_t *ha, uint16_t *fwopts) mcp->mb[3] = fwopts[3]; mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; mcp->in_mb = MBX_0; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mcp->in_mb |= MBX_1; } else { mcp->mb[10] = fwopts[10]; @@ -676,7 +676,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr) mcp->mb[0] = MBC_VERIFY_CHECKSUM; mcp->out_mb = MBX_0; mcp->in_mb = MBX_0; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mcp->mb[1] = MSW(risc_addr); mcp->mb[2] = LSW(risc_addr); mcp->out_mb |= MBX_2|MBX_1; @@ -693,7 +693,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr) if (rval != QLA_SUCCESS) { DEBUG2_3_11(printk("%s(%ld): failed=%x chk sum=%x.\n", __func__, - ha->host_no, rval, (IS_QLA24XX(ha) || IS_QLA25XX(ha) ? + ha->host_no, rval, (IS_QLA24XX(ha) || IS_QLA54XX(ha) ? (mcp->mb[2] << 16) | mcp->mb[1]: mcp->mb[1]));) } else { DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);) @@ -751,7 +751,7 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr, /* Mask reserved bits. */ sts_entry->entry_status &= - IS_QLA24XX(ha) || IS_QLA25XX(ha) ? RF_MASK_24XX :RF_MASK; + IS_QLA24XX(ha) || IS_QLA54XX(ha) ? RF_MASK_24XX :RF_MASK; } return rval; @@ -1091,7 +1091,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE)); mcp->mb[0] = MBC_GET_PORT_DATABASE; - if (opt != 0 && !IS_QLA24XX(ha) && !IS_QLA25XX(ha)) + if (opt != 0 && !IS_QLA24XX(ha) && !IS_QLA54XX(ha)) mcp->mb[0] = MBC_ENHANCED_GET_PORT_DATABASE; mcp->mb[2] = MSW(pd_dma); mcp->mb[3] = LSW(pd_dma); @@ -1099,7 +1099,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) mcp->mb[7] = LSW(MSD(pd_dma)); mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; mcp->in_mb = MBX_0; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mcp->mb[1] = fcport->loop_id; mcp->mb[10] = opt; mcp->out_mb |= MBX_10|MBX_1; @@ -1112,7 +1112,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) mcp->mb[1] = fcport->loop_id << 8 | opt; mcp->out_mb |= MBX_1; } - mcp->buf_size = (IS_QLA24XX(ha) || IS_QLA25XX(ha) ? + mcp->buf_size = (IS_QLA24XX(ha) || IS_QLA54XX(ha) ? PORT_DATABASE_24XX_SIZE : PORT_DATABASE_SIZE); mcp->flags = MBX_DMA_IN; mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); @@ -1120,7 +1120,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) if (rval != QLA_SUCCESS) goto gpd_error_out; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { pd24 = (struct port_database_24xx *) pd; /* Check for logged in state. */ @@ -1337,7 +1337,7 @@ qla2x00_lip_reset(scsi_qla_host_t *ha) DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);) - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mcp->mb[0] = MBC_LIP_FULL_LOGIN; mcp->mb[1] = BIT_0; mcp->mb[2] = 0xff; @@ -1866,7 +1866,7 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma, mcp->mb[0] = MBC_GET_ID_LIST; mcp->out_mb = MBX_0; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mcp->mb[2] = MSW(id_list_dma); mcp->mb[3] = LSW(id_list_dma); mcp->mb[6] = MSW(MSD(id_list_dma)); @@ -2057,7 +2057,7 @@ qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id, mcp->mb[7] = LSW(MSD(stat_buf_dma)); mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; mcp->in_mb = MBX_0; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mcp->mb[1] = loop_id; mcp->mb[4] = 0; mcp->mb[10] = 0; @@ -2324,7 +2324,7 @@ qla2x00_system_error(scsi_qla_host_t *ha) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) return QLA_FUNCTION_FAILED; DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); @@ -2434,7 +2434,7 @@ qla2x00_stop_firmware(scsi_qla_host_t *ha) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) return QLA_FUNCTION_FAILED; DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 757c4c43c453..131614751196 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1183,11 +1183,11 @@ qla2x00_set_isp_flags(scsi_qla_host_t *ha) case PCI_DEVICE_ID_QLOGIC_ISP2432: ha->device_type |= DT_ISP2432; break; - case PCI_DEVICE_ID_QLOGIC_ISP2512: - ha->device_type |= DT_ISP2512; + case PCI_DEVICE_ID_QLOGIC_ISP5422: + ha->device_type |= DT_ISP5422; break; - case PCI_DEVICE_ID_QLOGIC_ISP2522: - ha->device_type |= DT_ISP2522; + case PCI_DEVICE_ID_QLOGIC_ISP5432: + ha->device_type |= DT_ISP5432; break; } } @@ -1433,7 +1433,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) ha->gid_list_info_size = 6; if (IS_QLA2322(ha) || IS_QLA6322(ha)) ha->optrom_size = OPTROM_SIZE_2322; - } else if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { host->max_id = MAX_TARGETS_2200; ha->mbx_count = MAILBOX_REGISTER_COUNT; ha->request_q_length = REQUEST_ENTRY_CNT_24XX; @@ -1559,7 +1559,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) spin_lock_irqsave(&ha->hardware_lock, flags); reg = ha->iobase; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_HOST_INT); WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_RISC_INT); } else { @@ -2631,7 +2631,7 @@ qla2x00_request_firmware(scsi_qla_host_t *ha) blob = &qla_fw_blobs[FW_ISP2322]; } else if (IS_QLA6312(ha) || IS_QLA6322(ha)) { blob = &qla_fw_blobs[FW_ISP63XX]; - } else if (IS_QLA24XX(ha)) { + } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { blob = &qla_fw_blobs[FW_ISP24XX]; } @@ -2687,6 +2687,10 @@ static struct pci_device_id qla2xxx_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422, + PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432, + PCI_ANY_ID, PCI_ANY_ID, }, { 0 }, }; MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 82b83da25d77..1afac931351e 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -852,6 +852,8 @@ #define PCI_DEVICE_ID_QLOGIC_ISP2432 0x2432 #define PCI_DEVICE_ID_QLOGIC_ISP2512 0x2512 #define PCI_DEVICE_ID_QLOGIC_ISP2522 0x2522 +#define PCI_DEVICE_ID_QLOGIC_ISP5422 0x5422 +#define PCI_DEVICE_ID_QLOGIC_ISP5432 0x5432 #define PCI_VENDOR_ID_CYRIX 0x1078 #define PCI_DEVICE_ID_CYRIX_5510 0x0000 -- cgit v1.2.3 From c829c394165f981d49f05a9be228404d7a9398d4 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 13 Mar 2006 08:28:57 -0500 Subject: [SCSI] FC transport : Avoid device offline cases by stalling aborts until device unblocked This moves the eh_timed_out functionality from the scsi_host_template to the transport_template. Given that this is now a transport function, the EH_RESET_TIMER case no longer caps the timer reschedulings. The transport guarantees that this is not an infinite condition. Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 9 +++------ drivers/scsi/scsi_transport_fc.c | 37 +++++++++++++++++++++++++++++++++++++ include/scsi/scsi_host.h | 14 -------------- include/scsi/scsi_transport.h | 11 +++++++++++ 4 files changed, 51 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 5cc97b721661..9cf020622134 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -163,16 +164,12 @@ void scsi_times_out(struct scsi_cmnd *scmd) { scsi_log_completion(scmd, TIMEOUT_ERROR); - if (scmd->device->host->hostt->eh_timed_out) - switch (scmd->device->host->hostt->eh_timed_out(scmd)) { + if (scmd->device->host->transportt->eh_timed_out) + switch (scmd->device->host->transportt->eh_timed_out(scmd)) { case EH_HANDLED: __scsi_done(scmd); return; case EH_RESET_TIMER: - /* This allows a single retry even of a command - * with allowed == 0 */ - if (scmd->retries++ > scmd->allowed) - break; scsi_add_timer(scmd, scmd->timeout_per_command, scsi_times_out); return; diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 56012b2694d2..3c3baa9f5f28 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "scsi_priv.h" /* @@ -1090,6 +1091,40 @@ static int fc_rport_match(struct attribute_container *cont, } +/** + * fc_timed_out - FC Transport I/O timeout intercept handler + * + * @scmd: The SCSI command which timed out + * + * This routine protects against error handlers getting invoked while a + * rport is in a blocked state, typically due to a temporarily loss of + * connectivity. If the error handlers are allowed to proceed, requests + * to abort i/o, reset the target, etc will likely fail as there is no way + * to communicate with the device to perform the requested function. These + * failures may result in the midlayer taking the device offline, requiring + * manual intervention to restore operation. + * + * This routine, called whenever an i/o times out, validates the state of + * the underlying rport. If the rport is blocked, it returns + * EH_RESET_TIMER, which will continue to reschedule the timeout. + * Eventually, either the device will return, or devloss_tmo will fire, + * and when the timeout then fires, it will be handled normally. + * If the rport is not blocked, normal error handling continues. + * + * Notes: + * This routine assumes no locks are held on entry. + **/ +static enum scsi_eh_timer_return +fc_timed_out(struct scsi_cmnd *scmd) +{ + struct fc_rport *rport = starget_to_rport(scsi_target(scmd->device)); + + if (rport->port_state == FC_PORTSTATE_BLOCKED) + return EH_RESET_TIMER; + + return EH_NOT_HANDLED; +} + /* * Must be called with shost->host_lock held */ @@ -1146,6 +1181,8 @@ fc_attach_transport(struct fc_function_template *ft) /* Transport uses the shost workq for scsi scanning */ i->t.create_work_queue = 1; + i->t.eh_timed_out = fc_timed_out; + i->t.user_scan = fc_user_scan; /* diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 827992949c4b..a6cf3e535c0b 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -146,20 +146,6 @@ struct scsi_host_template { int (* eh_bus_reset_handler)(struct scsi_cmnd *); int (* eh_host_reset_handler)(struct scsi_cmnd *); - /* - * This is an optional routine to notify the host that the scsi - * timer just fired. The returns tell the timer routine what to - * do about this: - * - * EH_HANDLED: I fixed the error, please complete the command - * EH_RESET_TIMER: I need more time, reset the timer and - * begin counting again - * EH_NOT_HANDLED Begin normal error recovery - * - * Status: OPTIONAL - */ - enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); - /* * Before the mid layer attempts to scan for a new device where none * currently exists, it will call this entry in your driver. Should diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h index e7b1054adf86..b3657f111937 100644 --- a/include/scsi/scsi_transport.h +++ b/include/scsi/scsi_transport.h @@ -48,6 +48,17 @@ struct scsi_transport_template { * True if the transport wants to use a host-based work-queue */ unsigned int create_work_queue : 1; + + /* + * This is an optional routine that allows the transport to become + * involved when a scsi io timer fires. The return value tells the + * timer routine how to finish the io timeout handling: + * EH_HANDLED: I fixed the error, please complete the command + * EH_RESET_TIMER: I need more time, reset the timer and + * begin counting again + * EH_NOT_HANDLED Begin normal error recovery + */ + enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); }; #define transport_class_to_shost(tc) \ -- cgit v1.2.3 From 79cb1819e231f811211133a09a5382cb89d7ec67 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Mon, 13 Mar 2006 13:50:04 -0600 Subject: [SCSI] add preliminary expander support to the sas transport class This patch makes expanders appear as labelled objects with properties in the SAS tree. I've also modified the phy code to make expander phys appear labelled by host number, expander number and phy index. So, for my current config, you see something like this in sysfs: /sys/class/scsi_host/host1/device/phy-1:4/expander-1:0/phy-1-0:12/rphy-1:0-12/target1:0:1 And the expander properties are: jejb@sparkweed> cd /sys/class/sas_expander/expander-1\:0/ jejb@sparkweed> for f in *; do echo -n $f ": "; cat $f; done component_id : 29024 component_revision_id : 4 component_vendor_id : VITESSE device : cat: device: Is a directory level : 0 product_id : VSC7160 Eval Brd product_rev : 4 uevent : cat: uevent: Permission denied vendor_id : VITESSE Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 141 ++++++++++++++++++++++++++++++++++++-- include/scsi/scsi_transport_sas.h | 31 +++++++++ 2 files changed, 166 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 3eb11a175904..5a70d04352cc 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -40,6 +40,7 @@ #define SAS_PORT_ATTRS 17 #define SAS_RPORT_ATTRS 7 #define SAS_END_DEV_ATTRS 3 +#define SAS_EXPANDER_ATTRS 7 struct sas_internal { struct scsi_transport_template t; @@ -49,10 +50,12 @@ struct sas_internal { struct class_device_attribute private_phy_attrs[SAS_PORT_ATTRS]; struct class_device_attribute private_rphy_attrs[SAS_RPORT_ATTRS]; struct class_device_attribute private_end_dev_attrs[SAS_END_DEV_ATTRS]; + struct class_device_attribute private_expander_attrs[SAS_EXPANDER_ATTRS]; struct transport_container phy_attr_cont; struct transport_container rphy_attr_cont; struct transport_container end_dev_attr_cont; + struct transport_container expander_attr_cont; /* * The array of null terminated pointers to attributes @@ -62,6 +65,7 @@ struct sas_internal { struct class_device_attribute *phy_attrs[SAS_PORT_ATTRS + 1]; struct class_device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1]; struct class_device_attribute *end_dev_attrs[SAS_END_DEV_ATTRS + 1]; + struct class_device_attribute *expander_attrs[SAS_EXPANDER_ATTRS + 1]; }; #define to_sas_internal(tmpl) container_of(tmpl, struct sas_internal, t) @@ -69,6 +73,7 @@ struct sas_host_attrs { struct list_head rphy_list; struct mutex lock; u32 next_target_id; + u32 next_expander_id; }; #define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data) @@ -173,6 +178,7 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev, INIT_LIST_HEAD(&sas_host->rphy_list); mutex_init(&sas_host->lock); sas_host->next_target_id = 0; + sas_host->next_expander_id = 0; return 0; } @@ -407,7 +413,12 @@ struct sas_phy *sas_phy_alloc(struct device *parent, int number) device_initialize(&phy->dev); phy->dev.parent = get_device(parent); phy->dev.release = sas_phy_release; - sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number); + if (scsi_is_sas_expander_device(parent)) { + struct sas_rphy *rphy = dev_to_rphy(parent); + sprintf(phy->dev.bus_id, "phy-%d-%d:%d", shost->host_no, + rphy->scsi_target_id, number); + } else + sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number); transport_setup_device(&phy->dev); @@ -635,6 +646,9 @@ int sas_read_port_mode_page(struct scsi_device *sdev) } EXPORT_SYMBOL(sas_read_port_mode_page); +static DECLARE_TRANSPORT_CLASS(sas_end_dev_class, + "sas_end_device", NULL, NULL, NULL); + #define sas_end_dev_show_simple(field, name, format_string, cast) \ static ssize_t \ show_sas_end_dev_##name(struct class_device *cdev, char *buf) \ @@ -656,8 +670,33 @@ sas_end_dev_simple_attr(I_T_nexus_loss_timeout, I_T_nexus_loss_timeout, sas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout, "%d\n", int); -static DECLARE_TRANSPORT_CLASS(sas_end_dev_class, - "sas_end_device", NULL, NULL, NULL); +static DECLARE_TRANSPORT_CLASS(sas_expander_class, + "sas_expander", NULL, NULL, NULL); + +#define sas_expander_show_simple(field, name, format_string, cast) \ +static ssize_t \ +show_sas_expander_##name(struct class_device *cdev, char *buf) \ +{ \ + struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ + struct sas_expander_device *edev = rphy_to_expander_device(rphy); \ + \ + return snprintf(buf, 20, format_string, cast edev->field); \ +} + +#define sas_expander_simple_attr(field, name, format_string, type) \ + sas_expander_show_simple(field, name, format_string, (type)) \ +static SAS_CLASS_DEVICE_ATTR(expander, name, S_IRUGO, \ + show_sas_expander_##name, NULL) + +sas_expander_simple_attr(vendor_id, vendor_id, "%s\n", char *); +sas_expander_simple_attr(product_id, product_id, "%s\n", char *); +sas_expander_simple_attr(product_rev, product_rev, "%s\n", char *); +sas_expander_simple_attr(component_vendor_id, component_vendor_id, + "%s\n", char *); +sas_expander_simple_attr(component_id, component_id, "%u\n", unsigned int); +sas_expander_simple_attr(component_revision_id, component_revision_id, "%u\n", + unsigned int); +sas_expander_simple_attr(level, level, "%d\n", int); static DECLARE_TRANSPORT_CLASS(sas_rphy_class, "sas_rphy", NULL, NULL, NULL); @@ -706,6 +745,32 @@ static int sas_end_dev_match(struct attribute_container *cont, rphy->contained; } +static int sas_expander_match(struct attribute_container *cont, + struct device *dev) +{ + struct Scsi_Host *shost; + struct sas_internal *i; + struct sas_rphy *rphy; + + if (!scsi_is_sas_rphy(dev)) + return 0; + shost = dev_to_shost(dev->parent->parent); + rphy = dev_to_rphy(dev); + + if (!shost->transportt) + return 0; + if (shost->transportt->host_attrs.ac.class != + &sas_host_class.class) + return 0; + + i = to_sas_internal(shost->transportt); + return &i->expander_attr_cont.ac == cont && + (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE || + rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) && + /* FIXME: remove contained eventually */ + rphy->contained; +} + static void sas_rphy_release(struct device *dev) { struct sas_rphy *rphy = dev_to_rphy(dev); @@ -778,6 +843,46 @@ struct sas_rphy *sas_end_device_alloc(struct sas_phy *parent) } EXPORT_SYMBOL(sas_end_device_alloc); +/** + * sas_expander_alloc - allocate an rphy for an end device + * + * Allocates an SAS remote PHY structure, connected to @parent. + * + * Returns: + * SAS PHY allocated or %NULL if the allocation failed. + */ +struct sas_rphy *sas_expander_alloc(struct sas_phy *parent, + enum sas_device_type type) +{ + struct Scsi_Host *shost = dev_to_shost(&parent->dev); + struct sas_expander_device *rdev; + struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); + + BUG_ON(type != SAS_EDGE_EXPANDER_DEVICE && + type != SAS_FANOUT_EXPANDER_DEVICE); + + rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); + if (!rdev) { + put_device(&parent->dev); + return NULL; + } + + device_initialize(&rdev->rphy.dev); + rdev->rphy.dev.parent = get_device(&parent->dev); + rdev->rphy.dev.release = sas_rphy_release; + mutex_lock(&sas_host->lock); + rdev->rphy.scsi_target_id = sas_host->next_expander_id++; + mutex_unlock(&sas_host->lock); + sprintf(rdev->rphy.dev.bus_id, "expander-%d:%d", + shost->host_no, rdev->rphy.scsi_target_id); + rdev->rphy.identify.device_type = type; + /* FIXME: mark the rphy as being contained in a larger structure */ + rdev->rphy.contained = 1; + transport_setup_device(&rdev->rphy.dev); + + return &rdev->rphy; +} +EXPORT_SYMBOL(sas_expander_alloc); /** * sas_rphy_add -- add a SAS remote PHY to the device hierachy @@ -809,11 +914,10 @@ int sas_rphy_add(struct sas_rphy *rphy) (identify->target_port_protocols & (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA))) rphy->scsi_target_id = sas_host->next_target_id++; - else - rphy->scsi_target_id = -1; mutex_unlock(&sas_host->lock); - if (rphy->scsi_target_id != -1) { + if (identify->device_type == SAS_END_DEVICE && + rphy->scsi_target_id != -1) { scsi_scan_target(&rphy->dev, parent->port_identifier, rphy->scsi_target_id, ~0, 0); } @@ -967,6 +1071,9 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel, #define SETUP_END_DEV_ATTRIBUTE(field) \ SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1) +#define SETUP_EXPANDER_ATTRIBUTE(field) \ + SETUP_TEMPLATE(expander_attrs, expander_##field, S_IRUGO, 1) + /** * sas_attach_transport -- instantiate SAS transport template * @ft: SAS transport class function template @@ -1004,6 +1111,11 @@ sas_attach_transport(struct sas_function_template *ft) i->end_dev_attr_cont.ac.match = sas_end_dev_match; transport_container_register(&i->end_dev_attr_cont); + i->expander_attr_cont.ac.class = &sas_expander_class.class; + i->expander_attr_cont.ac.attrs = &i->expander_attrs[0]; + i->expander_attr_cont.ac.match = sas_expander_match; + transport_container_register(&i->expander_attr_cont); + i->f = ft; count = 0; @@ -1048,6 +1160,16 @@ sas_attach_transport(struct sas_function_template *ft) SETUP_END_DEV_ATTRIBUTE(end_dev_initiator_response_timeout); i->end_dev_attrs[count] = NULL; + count = 0; + SETUP_EXPANDER_ATTRIBUTE(vendor_id); + SETUP_EXPANDER_ATTRIBUTE(product_id); + SETUP_EXPANDER_ATTRIBUTE(product_rev); + SETUP_EXPANDER_ATTRIBUTE(component_vendor_id); + SETUP_EXPANDER_ATTRIBUTE(component_id); + SETUP_EXPANDER_ATTRIBUTE(component_revision_id); + SETUP_EXPANDER_ATTRIBUTE(level); + i->expander_attrs[count] = NULL; + return &i->t; } EXPORT_SYMBOL(sas_attach_transport); @@ -1064,6 +1186,7 @@ void sas_release_transport(struct scsi_transport_template *t) transport_container_unregister(&i->phy_attr_cont); transport_container_unregister(&i->rphy_attr_cont); transport_container_unregister(&i->end_dev_attr_cont); + transport_container_unregister(&i->expander_attr_cont); kfree(i); } @@ -1085,9 +1208,14 @@ static __init int sas_transport_init(void) error = transport_class_register(&sas_end_dev_class); if (error) goto out_unregister_rphy; + error = transport_class_register(&sas_expander_class); + if (error) + goto out_unregister_end_dev; return 0; + out_unregister_end_dev: + transport_class_unregister(&sas_end_dev_class); out_unregister_rphy: transport_class_unregister(&sas_rphy_class); out_unregister_phy: @@ -1105,6 +1233,7 @@ static void __exit sas_transport_exit(void) transport_class_unregister(&sas_phy_class); transport_class_unregister(&sas_rphy_class); transport_class_unregister(&sas_end_dev_class); + transport_class_unregister(&sas_expander_class); } MODULE_AUTHOR("Christoph Hellwig"); diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index 8fded431cf46..2943ccc22a43 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -108,6 +108,25 @@ struct sas_end_device { #define rphy_to_end_device(r) \ container_of((r), struct sas_end_device, rphy) +struct sas_expander_device { + int level; + + #define SAS_EXPANDER_VENDOR_ID_LEN 8 + char vendor_id[SAS_EXPANDER_VENDOR_ID_LEN+1]; + #define SAS_EXPANDER_PRODUCT_ID_LEN 16 + char product_id[SAS_EXPANDER_PRODUCT_ID_LEN+1]; + #define SAS_EXPANDER_PRODUCT_REV_LEN 4 + char product_rev[SAS_EXPANDER_PRODUCT_REV_LEN+1]; + #define SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN 8 + char component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN+1]; + u16 component_id; + u8 component_revision_id; + + struct sas_rphy rphy; + +}; +#define rphy_to_expander_device(r) \ + container_of((r), struct sas_expander_device, rphy) /* The functions by which the transport class and the driver communicate */ struct sas_function_template { @@ -128,6 +147,7 @@ extern int scsi_is_sas_phy(const struct device *); extern struct sas_rphy *sas_rphy_alloc(struct sas_phy *); extern struct sas_rphy *sas_end_device_alloc(struct sas_phy *); +extern struct sas_rphy *sas_expander_alloc(struct sas_phy *, enum sas_device_type); void sas_rphy_free(struct sas_rphy *); extern int sas_rphy_add(struct sas_rphy *); extern void sas_rphy_delete(struct sas_rphy *); @@ -138,4 +158,15 @@ sas_attach_transport(struct sas_function_template *); extern void sas_release_transport(struct scsi_transport_template *); int sas_read_port_mode_page(struct scsi_device *); +static inline int +scsi_is_sas_expander_device(struct device *dev) +{ + struct sas_rphy *rphy; + if (!scsi_is_sas_rphy(dev)) + return 0; + rphy = dev_to_rphy(dev); + return rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE || + rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE; +} + #endif /* SCSI_TRANSPORT_SAS_H */ -- cgit v1.2.3 From e935d5da8e5d12fabe5b632736c50eae0427e8c8 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Tue, 14 Mar 2006 09:18:18 -0700 Subject: [SCSI] drivers/base/bus.c - export reprobe Adding support for exposing hidden raid components for sg interface. The sdev->no_uld_attach flag will set set accordingly. The sas module supports adding/removing raid volumes using online storage management application interface. This patch was provided to me by Christoph Hellwig. Signed-off-by: Eric Moore Signed-off-by: Greg Kroah-Hartman Signed-off-by: James Bottomley --- drivers/base/bus.c | 22 ++++++++++++++++++++++ include/linux/device.h | 1 + 2 files changed, 23 insertions(+) (limited to 'include') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index c3141565d59d..48718b7f4fa0 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -536,6 +536,28 @@ void bus_rescan_devices(struct bus_type * bus) bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper); } +/** + * device_reprobe - remove driver for a device and probe for a new driver + * @dev: the device to reprobe + * + * This function detaches the attached driver (if any) for the given + * device and restarts the driver probing process. It is intended + * to use if probing criteria changed during a devices lifetime and + * driver attachment should change accordingly. + */ +void device_reprobe(struct device *dev) +{ + if (dev->driver) { + if (dev->parent) /* Needed for USB */ + down(&dev->parent->sem); + device_release_driver(dev); + if (dev->parent) + up(&dev->parent->sem); + } + + bus_rescan_devices_helper(dev, NULL); +} +EXPORT_SYMBOL_GPL(device_reprobe); struct bus_type * get_bus(struct bus_type * bus) { diff --git a/include/linux/device.h b/include/linux/device.h index 58df18d9cd3e..e8ac5bcfbec7 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -378,6 +378,7 @@ extern void device_bind_driver(struct device * dev); extern void device_release_driver(struct device * dev); extern int device_attach(struct device * dev); extern void driver_attach(struct device_driver * drv); +extern void device_reprobe(struct device *dev); /* -- cgit v1.2.3 From e28482c5b24006e9e4a867f9995baf358cbc1059 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 14 Mar 2006 14:24:55 -0600 Subject: [SCSI] add scsi_reprobe_device Original from Christoph Hellwig and Eric Moore. This version exports the scsi_reprobe_device() function as an inline. Signed-off-by: James Bottomley --- include/scsi/scsi_device.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 1ec17ee12815..f2193cd0d31f 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -293,6 +293,11 @@ extern int scsi_execute_async(struct scsi_device *sdev, void (*done)(void *, char *, int, int), gfp_t gfp); +static inline void scsi_device_reprobe(struct scsi_device *sdev) +{ + device_reprobe(&sdev->sdev_gendev); +} + static inline unsigned int sdev_channel(struct scsi_device *sdev) { return sdev->channel; -- cgit v1.2.3 From 243f196d572822214bb86522f28b30e096d67414 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Thu, 16 Mar 2006 14:10:19 +0000 Subject: [ARM] 3366/1: Allow the 16bpp mode configuration in the CLCD control register Patch from Catalin Marinas Starting with PL111, the 5551 or 565 modes can be configured in the primecell's control register directly. This patch detects the required mode and sets the correct value. Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- include/linux/amba/clcd.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/amba/clcd.h b/include/linux/amba/clcd.h index 6b8d73dc1ab0..9cf64b1b688b 100644 --- a/include/linux/amba/clcd.h +++ b/include/linux/amba/clcd.h @@ -54,6 +54,7 @@ #define CNTL_LCDBPP4 (2 << 1) #define CNTL_LCDBPP8 (3 << 1) #define CNTL_LCDBPP16 (4 << 1) +#define CNTL_LCDBPP16_565 (6 << 1) #define CNTL_LCDBPP24 (5 << 1) #define CNTL_LCDBW (1 << 4) #define CNTL_LCDTFT (1 << 5) @@ -209,7 +210,16 @@ static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs) val |= CNTL_LCDBPP8; break; case 16: - val |= CNTL_LCDBPP16; + /* + * PL110 cannot choose between 5551 and 565 modes in + * its control register + */ + if ((fb->dev->periphid & 0x000fffff) == 0x00041110) + val |= CNTL_LCDBPP16; + else if (fb->fb.var.green.length == 5) + val |= CNTL_LCDBPP16; + else + val |= CNTL_LCDBPP16_565; break; case 32: val |= CNTL_LCDBPP24; -- cgit v1.2.3 From 0f6be7b77ceaea01a35b37fab26f4ea3b01efe14 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 6 Mar 2006 12:51:29 +1100 Subject: [PATCH] powerpc: Better pmd_bad() and pud_bad() checks At present, the powerpc pmd_bad() and pud_bad() macros return false unless the given pmd or pud is zero. This patch makes these tests more thorough, checking if the given pmd or pud looks like a plausible pte page or pmd page pointer respectively. This can result in helpful error messages when messing with the pagetable code. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- include/asm-powerpc/pgtable.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-powerpc/pgtable.h b/include/asm-powerpc/pgtable.h index e38931379a72..8dc3eb54276f 100644 --- a/include/asm-powerpc/pgtable.h +++ b/include/asm-powerpc/pgtable.h @@ -188,9 +188,13 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot) #define pte_pfn(x) ((unsigned long)((pte_val(x)>>PTE_RPN_SHIFT))) #define pte_page(x) pfn_to_page(pte_pfn(x)) +#define PMD_BAD_BITS (PTE_TABLE_SIZE-1) +#define PUD_BAD_BITS (PMD_TABLE_SIZE-1) + #define pmd_set(pmdp, pmdval) (pmd_val(*(pmdp)) = (pmdval)) #define pmd_none(pmd) (!pmd_val(pmd)) -#define pmd_bad(pmd) (pmd_val(pmd) == 0) +#define pmd_bad(pmd) (!is_kernel_addr(pmd_val(pmd)) \ + || (pmd_val(pmd) & PMD_BAD_BITS)) #define pmd_present(pmd) (pmd_val(pmd) != 0) #define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0) #define pmd_page_kernel(pmd) (pmd_val(pmd) & ~PMD_MASKED_BITS) @@ -198,7 +202,8 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot) #define pud_set(pudp, pudval) (pud_val(*(pudp)) = (pudval)) #define pud_none(pud) (!pud_val(pud)) -#define pud_bad(pud) ((pud_val(pud)) == 0) +#define pud_bad(pud) (!is_kernel_addr(pud_val(pud)) \ + || (pud_val(pud) & PUD_BAD_BITS)) #define pud_present(pud) (pud_val(pud) != 0) #define pud_clear(pudp) (pud_val(*(pudp)) = 0) #define pud_page(pud) (pud_val(pud) & ~PUD_MASKED_BITS) -- cgit v1.2.3 From e33852228f74b8ccbed8595083bb725b70902ed7 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 8 Mar 2006 16:47:00 +0100 Subject: [PATCH] powerpc: add for_each_node_by_foo helpers Typical use for of_find_node_by_name and of_find_node_by_type is to iterate over all nodes of a given type/name. Add a helper macro to do that (in spirit of the list_for_each* macros). Signed-off-by: Christoph Hellwig Signed-off-by: Paul Mackerras --- include/asm-powerpc/prom.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include') diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index cbd297f44cce..782e13a070a1 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -126,8 +126,14 @@ extern struct device_node *find_all_nodes(void); /* New style node lookup */ extern struct device_node *of_find_node_by_name(struct device_node *from, const char *name); +#define for_each_node_by_name(dn, name) \ + for (dn = of_find_node_by_name(NULL, name); dn; \ + dn = of_find_node_by_name(dn, name)) extern struct device_node *of_find_node_by_type(struct device_node *from, const char *type); +#define for_each_node_by_type(dn, type) \ + for (dn = of_find_node_by_type(NULL, type); dn; \ + dn = of_find_node_by_type(dn, type)) extern struct device_node *of_find_compatible_node(struct device_node *from, const char *type, const char *compat); extern struct device_node *of_find_node_by_path(const char *path); -- cgit v1.2.3 From 5baba830e93732e802dc7e0a362eb730e1917f58 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 18 Mar 2006 14:10:35 -0600 Subject: [SCSI] add scsi_mode_select to scsi_lib.c This complements the scsi_mode_sense() function Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 81 +++++++++++++++++++++++++++++++++++++++++++++- include/scsi/scsi_device.h | 5 +++ 2 files changed, 85 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 9a05076f9cf4..ede158d08d9d 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1811,6 +1811,84 @@ void scsi_exit_queue(void) kmem_cache_destroy(sgp->slab); } } + +/** + * scsi_mode_select - issue a mode select + * @sdev: SCSI device to be queried + * @pf: Page format bit (1 == standard, 0 == vendor specific) + * @sp: Save page bit (0 == don't save, 1 == save) + * @modepage: mode page being requested + * @buffer: request buffer (may not be smaller than eight bytes) + * @len: length of request buffer. + * @timeout: command timeout + * @retries: number of retries before failing + * @data: returns a structure abstracting the mode header data + * @sense: place to put sense data (or NULL if no sense to be collected). + * must be SCSI_SENSE_BUFFERSIZE big. + * + * Returns zero if successful; negative error number or scsi + * status on error + * + */ +int +scsi_mode_select(struct scsi_device *sdev, int pf, int sp, int modepage, + unsigned char *buffer, int len, int timeout, int retries, + struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr) +{ + unsigned char cmd[10]; + unsigned char *real_buffer; + int ret; + + memset(cmd, 0, sizeof(cmd)); + cmd[1] = (pf ? 0x10 : 0) | (sp ? 0x01 : 0); + + if (sdev->use_10_for_ms) { + if (len > 65535) + return -EINVAL; + real_buffer = kmalloc(8 + len, GFP_KERNEL); + if (!real_buffer) + return -ENOMEM; + memcpy(real_buffer + 8, buffer, len); + len += 8; + real_buffer[0] = 0; + real_buffer[1] = 0; + real_buffer[2] = data->medium_type; + real_buffer[3] = data->device_specific; + real_buffer[4] = data->longlba ? 0x01 : 0; + real_buffer[5] = 0; + real_buffer[6] = data->block_descriptor_length >> 8; + real_buffer[7] = data->block_descriptor_length; + + cmd[0] = MODE_SELECT_10; + cmd[7] = len >> 8; + cmd[8] = len; + } else { + if (len > 255 || data->block_descriptor_length > 255 || + data->longlba) + return -EINVAL; + + real_buffer = kmalloc(4 + len, GFP_KERNEL); + if (!real_buffer) + return -ENOMEM; + memcpy(real_buffer + 4, buffer, len); + len += 4; + real_buffer[0] = 0; + real_buffer[1] = data->medium_type; + real_buffer[2] = data->device_specific; + real_buffer[3] = data->block_descriptor_length; + + + cmd[0] = MODE_SELECT; + cmd[4] = len; + } + + ret = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, real_buffer, len, + sshdr, timeout, retries); + kfree(real_buffer); + return ret; +} +EXPORT_SYMBOL_GPL(scsi_mode_select); + /** * scsi_mode_sense - issue a mode sense, falling back from 10 to * six bytes if necessary. @@ -1832,7 +1910,8 @@ void scsi_exit_queue(void) int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, unsigned char *buffer, int len, int timeout, int retries, - struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr) { + struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr) +{ unsigned char cmd[12]; int use_10_for_ms; int header_length; diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index f2193cd0d31f..895d212864cd 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -261,6 +261,11 @@ extern int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, unsigned char *buffer, int len, int timeout, int retries, struct scsi_mode_data *data, struct scsi_sense_hdr *); +extern int scsi_mode_select(struct scsi_device *sdev, int pf, int sp, + int modepage, unsigned char *buffer, int len, + int timeout, int retries, + struct scsi_mode_data *data, + struct scsi_sense_hdr *); extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries); extern int scsi_device_set_state(struct scsi_device *sdev, -- cgit v1.2.3 From 2f8600dff2b140096a7df781884e918a16aa90e0 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 18 Mar 2006 15:00:50 -0600 Subject: [SCSI] eliminate rphy allocation in favour of expander/end device allocation This allows the removal of the contained flag and also does a bit of class renaming (sas_rphy->sas_device). Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 72 +++++++++++++++------------------------ include/scsi/scsi_transport_sas.h | 5 --- 2 files changed, 27 insertions(+), 50 deletions(-) (limited to 'include') diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 5a70d04352cc..134c44c8538a 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -699,7 +699,7 @@ sas_expander_simple_attr(component_revision_id, component_revision_id, "%u\n", sas_expander_simple_attr(level, level, "%d\n", int); static DECLARE_TRANSPORT_CLASS(sas_rphy_class, - "sas_rphy", NULL, NULL, NULL); + "sas_device", NULL, NULL, NULL); static int sas_rphy_match(struct attribute_container *cont, struct device *dev) { @@ -740,9 +740,7 @@ static int sas_end_dev_match(struct attribute_container *cont, i = to_sas_internal(shost->transportt); return &i->end_dev_attr_cont.ac == cont && - rphy->identify.device_type == SAS_END_DEVICE && - /* FIXME: remove contained eventually */ - rphy->contained; + rphy->identify.device_type == SAS_END_DEVICE; } static int sas_expander_match(struct attribute_container *cont, @@ -766,49 +764,26 @@ static int sas_expander_match(struct attribute_container *cont, i = to_sas_internal(shost->transportt); return &i->expander_attr_cont.ac == cont && (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE || - rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) && - /* FIXME: remove contained eventually */ - rphy->contained; + rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE); } -static void sas_rphy_release(struct device *dev) +static void sas_expander_release(struct device *dev) { struct sas_rphy *rphy = dev_to_rphy(dev); + struct sas_expander_device *edev = rphy_to_expander_device(rphy); put_device(dev->parent); - kfree(rphy); + kfree(edev); } -/** - * sas_rphy_alloc -- allocates and initialize a SAS remote PHY structure - * @parent: SAS PHY this remote PHY is conneted to - * - * Allocates an SAS remote PHY structure, connected to @parent. - * - * Returns: - * SAS PHY allocated or %NULL if the allocation failed. - */ -struct sas_rphy *sas_rphy_alloc(struct sas_phy *parent) +static void sas_end_device_release(struct device *dev) { - struct Scsi_Host *shost = dev_to_shost(&parent->dev); - struct sas_rphy *rphy; - - rphy = kzalloc(sizeof(*rphy), GFP_KERNEL); - if (!rphy) { - put_device(&parent->dev); - return NULL; - } - - device_initialize(&rphy->dev); - rphy->dev.parent = get_device(&parent->dev); - rphy->dev.release = sas_rphy_release; - sprintf(rphy->dev.bus_id, "rphy-%d:%d-%d", - shost->host_no, parent->port_identifier, parent->number); - transport_setup_device(&rphy->dev); + struct sas_rphy *rphy = dev_to_rphy(dev); + struct sas_end_device *edev = rphy_to_end_device(rphy); - return rphy; + put_device(dev->parent); + kfree(edev); } -EXPORT_SYMBOL(sas_rphy_alloc); /** * sas_end_device_alloc - allocate an rphy for an end device @@ -831,12 +806,10 @@ struct sas_rphy *sas_end_device_alloc(struct sas_phy *parent) device_initialize(&rdev->rphy.dev); rdev->rphy.dev.parent = get_device(&parent->dev); - rdev->rphy.dev.release = sas_rphy_release; - sprintf(rdev->rphy.dev.bus_id, "rphy-%d:%d-%d", + rdev->rphy.dev.release = sas_end_device_release; + sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d-%d", shost->host_no, parent->port_identifier, parent->number); rdev->rphy.identify.device_type = SAS_END_DEVICE; - /* FIXME: mark the rphy as being contained in a larger structure */ - rdev->rphy.contained = 1; transport_setup_device(&rdev->rphy.dev); return &rdev->rphy; @@ -869,15 +842,13 @@ struct sas_rphy *sas_expander_alloc(struct sas_phy *parent, device_initialize(&rdev->rphy.dev); rdev->rphy.dev.parent = get_device(&parent->dev); - rdev->rphy.dev.release = sas_rphy_release; + rdev->rphy.dev.release = sas_expander_release; mutex_lock(&sas_host->lock); rdev->rphy.scsi_target_id = sas_host->next_expander_id++; mutex_unlock(&sas_host->lock); sprintf(rdev->rphy.dev.bus_id, "expander-%d:%d", shost->host_no, rdev->rphy.scsi_target_id); rdev->rphy.identify.device_type = type; - /* FIXME: mark the rphy as being contained in a larger structure */ - rdev->rphy.contained = 1; transport_setup_device(&rdev->rphy.dev); return &rdev->rphy; @@ -950,7 +921,17 @@ void sas_rphy_free(struct sas_rphy *rphy) put_device(rphy->dev.parent); put_device(rphy->dev.parent); put_device(rphy->dev.parent); - kfree(rphy); + if (rphy->identify.device_type == SAS_END_DEVICE) { + struct sas_end_device *edev = rphy_to_end_device(rphy); + + kfree(edev); + } else { + /* must be expander */ + struct sas_expander_device *edev = + rphy_to_expander_device(rphy); + + kfree(edev); + } } EXPORT_SYMBOL(sas_rphy_free); @@ -1003,7 +984,8 @@ EXPORT_SYMBOL(sas_rphy_delete); */ int scsi_is_sas_rphy(const struct device *dev) { - return dev->release == sas_rphy_release; + return dev->release == sas_end_device_release || + dev->release == sas_expander_release; } EXPORT_SYMBOL(scsi_is_sas_rphy); diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index 2943ccc22a43..93cfb4bf4211 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -82,10 +82,6 @@ struct sas_rphy { struct sas_identify identify; struct list_head list; u32 scsi_target_id; - /* temporary expedient: mark the rphy as being contained - * within a type specific rphy - * FIXME: pull this out when everything uses the containers */ - unsigned contained:1; }; #define dev_to_rphy(d) \ @@ -145,7 +141,6 @@ extern int sas_phy_add(struct sas_phy *); extern void sas_phy_delete(struct sas_phy *); extern int scsi_is_sas_phy(const struct device *); -extern struct sas_rphy *sas_rphy_alloc(struct sas_phy *); extern struct sas_rphy *sas_end_device_alloc(struct sas_phy *); extern struct sas_rphy *sas_expander_alloc(struct sas_phy *, enum sas_device_type); void sas_rphy_free(struct sas_rphy *); -- cgit v1.2.3 From 7abe53155b77c31028a7158883bc9aac705790da Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 20 Mar 2006 10:12:31 +0000 Subject: [ARM] Fix cosmetic typo in asm/irq.h The IRQ resource flags are IORESOURCE_IRQ not IRQRESOURCE_IRQ. Signed-off-by: Russell King --- include/asm-arm/irq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-arm/irq.h b/include/asm-arm/irq.h index 7772432d3fd7..60b5105c9c93 100644 --- a/include/asm-arm/irq.h +++ b/include/asm-arm/irq.h @@ -27,7 +27,7 @@ extern void enable_irq(unsigned int); /* * These correspond with the SA_TRIGGER_* defines, and therefore the - * IRQRESOURCE_IRQ_* defines. + * IORESOURCE_IRQ_* defines. */ #define __IRQT_RISEDGE (1 << 0) #define __IRQT_FALEDGE (1 << 1) -- cgit v1.2.3 From 33b9b3ee9709b19c4f02ab91571d53540d05c3d1 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 30 Jan 2006 14:29:21 -0800 Subject: IB: Add userspace support for resizing CQs Add support to uverbs to handle resizing userspace CQs (completion queues), including adding an ABI for marshalling requests and responses. The kernel midlayer already has ib_resize_cq(). Signed-off-by: Roland Dreier --- drivers/infiniband/core/uverbs.h | 3 ++- drivers/infiniband/core/uverbs_cmd.c | 42 ++++++++++++++++++++++++++++++++++- drivers/infiniband/core/uverbs_main.c | 3 ++- drivers/infiniband/core/verbs.c | 4 ++-- include/rdma/ib_user_verbs.h | 13 ++++++++++- include/rdma/ib_verbs.h | 5 +++-- 6 files changed, 62 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index f7eecbc6af6c..3207239819ce 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * Copyright (c) 2005 Mellanox Technologies. All rights reserved. * Copyright (c) 2005 Voltaire, Inc. All rights reserved. * Copyright (c) 2005 PathScale, Inc. All rights reserved. @@ -178,6 +178,7 @@ IB_UVERBS_DECLARE_CMD(reg_mr); IB_UVERBS_DECLARE_CMD(dereg_mr); IB_UVERBS_DECLARE_CMD(create_comp_channel); IB_UVERBS_DECLARE_CMD(create_cq); +IB_UVERBS_DECLARE_CMD(resize_cq); IB_UVERBS_DECLARE_CMD(poll_cq); IB_UVERBS_DECLARE_CMD(req_notify_cq); IB_UVERBS_DECLARE_CMD(destroy_cq); diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 407b6284d7d5..be1cef1b3116 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * Copyright (c) 2005 PathScale, Inc. All rights reserved. * * This software is available to you under a choice of one of two @@ -675,6 +675,46 @@ err: return ret; } +ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file, + const char __user *buf, int in_len, + int out_len) +{ + struct ib_uverbs_resize_cq cmd; + struct ib_uverbs_resize_cq_resp resp; + struct ib_udata udata; + struct ib_cq *cq; + int ret = -EINVAL; + + if (copy_from_user(&cmd, buf, sizeof cmd)) + return -EFAULT; + + INIT_UDATA(&udata, buf + sizeof cmd, + (unsigned long) cmd.response + sizeof resp, + in_len - sizeof cmd, out_len - sizeof resp); + + mutex_lock(&ib_uverbs_idr_mutex); + + cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); + if (!cq || cq->uobject->context != file->ucontext || !cq->device->resize_cq) + goto out; + + ret = cq->device->resize_cq(cq, cmd.cqe, &udata); + if (ret) + goto out; + + memset(&resp, 0, sizeof resp); + resp.cqe = cq->cqe; + + if (copy_to_user((void __user *) (unsigned long) cmd.response, + &resp, sizeof resp)) + ret = -EFAULT; + +out: + mutex_unlock(&ib_uverbs_idr_mutex); + + return ret ? ret : in_len; +} + ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len) diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 903f85a4bc0c..099fe6cde68c 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * Copyright (c) 2005 Mellanox Technologies. All rights reserved. * Copyright (c) 2005 Voltaire, Inc. All rights reserved. * Copyright (c) 2005 PathScale, Inc. All rights reserved. @@ -91,6 +91,7 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file, [IB_USER_VERBS_CMD_DEREG_MR] = ib_uverbs_dereg_mr, [IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL] = ib_uverbs_create_comp_channel, [IB_USER_VERBS_CMD_CREATE_CQ] = ib_uverbs_create_cq, + [IB_USER_VERBS_CMD_RESIZE_CQ] = ib_uverbs_resize_cq, [IB_USER_VERBS_CMD_POLL_CQ] = ib_uverbs_poll_cq, [IB_USER_VERBS_CMD_REQ_NOTIFY_CQ] = ib_uverbs_req_notify_cq, [IB_USER_VERBS_CMD_DESTROY_CQ] = ib_uverbs_destroy_cq, diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index c857361be449..8e0ba16bcbdd 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -5,7 +5,7 @@ * Copyright (c) 2004 Topspin Corporation. All rights reserved. * Copyright (c) 2004 Voltaire Corporation. All rights reserved. * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -326,7 +326,7 @@ int ib_resize_cq(struct ib_cq *cq, int cqe) { return cq->device->resize_cq ? - cq->device->resize_cq(cq, cqe) : -ENOSYS; + cq->device->resize_cq(cq, cqe, NULL) : -ENOSYS; } EXPORT_SYMBOL(ib_resize_cq); diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h index 5ff1490c08db..6ad1207e4235 100644 --- a/include/rdma/ib_user_verbs.h +++ b/include/rdma/ib_user_verbs.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * Copyright (c) 2005 PathScale, Inc. All rights reserved. * * This software is available to you under a choice of one of two @@ -265,6 +265,17 @@ struct ib_uverbs_create_cq_resp { __u32 cqe; }; +struct ib_uverbs_resize_cq { + __u64 response; + __u32 cq_handle; + __u32 cqe; + __u64 driver_data[0]; +}; + +struct ib_uverbs_resize_cq_resp { + __u32 cqe; +}; + struct ib_uverbs_poll_cq { __u64 response; __u32 cq_handle; diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 22fc886b9695..38fa6c082eae 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -5,7 +5,7 @@ * Copyright (c) 2004 Topspin Corporation. All rights reserved. * Copyright (c) 2004 Voltaire Corporation. All rights reserved. * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -880,7 +880,8 @@ struct ib_device { struct ib_ucontext *context, struct ib_udata *udata); int (*destroy_cq)(struct ib_cq *cq); - int (*resize_cq)(struct ib_cq *cq, int cqe); + int (*resize_cq)(struct ib_cq *cq, int cqe, + struct ib_udata *udata); int (*poll_cq)(struct ib_cq *cq, int num_entries, struct ib_wc *wc); int (*peek_cq)(struct ib_cq *cq, int wc_cnt); -- cgit v1.2.3 From c5bcbbb9fe00128d500c2f473d5ddc8d8c2c53a7 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 2 Feb 2006 09:47:14 -0800 Subject: IB: Allow userspace to set node description Expose a writable "node_desc" sysfs attribute for InfiniBand devices. This allows userspace to update the node description with information such as the node's hostname, so that IB network management software can tie its view to the real world. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/core/sysfs.c | 30 +++++++++++++++++++++++++++++- include/rdma/ib_verbs.h | 5 ++++- 2 files changed, 33 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index 5982d687a000..49601bb8475b 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -628,14 +628,42 @@ static ssize_t show_node_guid(struct class_device *cdev, char *buf) be16_to_cpu(((__be16 *) &dev->node_guid)[3])); } +static ssize_t show_node_desc(struct class_device *cdev, char *buf) +{ + struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); + + return sprintf(buf, "%.64s\n", dev->node_desc); +} + +static ssize_t set_node_desc(struct class_device *cdev, const char *buf, + size_t count) +{ + struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); + struct ib_device_modify desc = {}; + int ret; + + if (!dev->modify_device) + return -EIO; + + memcpy(desc.node_desc, buf, min_t(int, count, 64)); + ret = ib_modify_device(dev, IB_DEVICE_MODIFY_NODE_DESC, &desc); + if (ret) + return ret; + + return count; +} + static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL); static CLASS_DEVICE_ATTR(sys_image_guid, S_IRUGO, show_sys_image_guid, NULL); static CLASS_DEVICE_ATTR(node_guid, S_IRUGO, show_node_guid, NULL); +static CLASS_DEVICE_ATTR(node_desc, S_IRUGO | S_IWUSR, show_node_desc, + set_node_desc); static struct class_device_attribute *ib_class_attributes[] = { &class_device_attr_node_type, &class_device_attr_sys_image_guid, - &class_device_attr_node_guid + &class_device_attr_node_guid, + &class_device_attr_node_desc }; static struct class ib_class = { diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 38fa6c082eae..1d31c8cd5ce0 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -222,11 +222,13 @@ struct ib_port_attr { }; enum ib_device_modify_flags { - IB_DEVICE_MODIFY_SYS_IMAGE_GUID = 1 + IB_DEVICE_MODIFY_SYS_IMAGE_GUID = 1 << 0, + IB_DEVICE_MODIFY_NODE_DESC = 1 << 1 }; struct ib_device_modify { u64 sys_image_guid; + char node_desc[64]; }; enum ib_port_modify_flags { @@ -951,6 +953,7 @@ struct ib_device { u64 uverbs_cmd_mask; int uverbs_abi_ver; + char node_desc[64]; __be64 node_guid; u8 node_type; u8 phys_port_cnt; -- cgit v1.2.3 From d36f34aadf184d8cc4c240de2b6319ccea8334bb Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Thu, 2 Feb 2006 10:43:45 -0800 Subject: IB: Enable FMR pool user to set page size This patch allows the consumer to set the page size of "pages" mapped by the pool FMRs, which is a feature already existing in the base verbs API. On the cosmetic side it changes ib_fmr_attr.page_size field to be named page_shift. Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/infiniband/core/fmr_pool.c | 6 +++--- drivers/infiniband/hw/mthca/mthca_mr.c | 10 +++++----- include/rdma/ib_fmr_pool.h | 2 ++ include/rdma/ib_verbs.h | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c index d34a6f1c4f4c..838bf54458d2 100644 --- a/drivers/infiniband/core/fmr_pool.c +++ b/drivers/infiniband/core/fmr_pool.c @@ -278,9 +278,9 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd *pd, { struct ib_pool_fmr *fmr; struct ib_fmr_attr attr = { - .max_pages = params->max_pages_per_fmr, - .max_maps = IB_FMR_MAX_REMAPS, - .page_size = PAGE_SHIFT + .max_pages = params->max_pages_per_fmr, + .max_maps = IB_FMR_MAX_REMAPS, + .page_shift = params->page_shift }; for (i = 0; i < params->pool_size; ++i) { diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c index 653f1321a13f..0b48048ad0f8 100644 --- a/drivers/infiniband/hw/mthca/mthca_mr.c +++ b/drivers/infiniband/hw/mthca/mthca_mr.c @@ -491,7 +491,7 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd, int err = -ENOMEM; int i; - if (mr->attr.page_size < 12 || mr->attr.page_size >= 32) + if (mr->attr.page_shift < 12 || mr->attr.page_shift >= 32) return -EINVAL; /* For Arbel, all MTTs must fit in the same page. */ @@ -543,7 +543,7 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd, MTHCA_MPT_FLAG_REGION | access); - mpt_entry->page_size = cpu_to_be32(mr->attr.page_size - 12); + mpt_entry->page_size = cpu_to_be32(mr->attr.page_shift - 12); mpt_entry->key = cpu_to_be32(key); mpt_entry->pd = cpu_to_be32(pd); memset(&mpt_entry->start, 0, @@ -611,7 +611,7 @@ static inline int mthca_check_fmr(struct mthca_fmr *fmr, u64 *page_list, if (list_len > fmr->attr.max_pages) return -EINVAL; - page_mask = (1 << fmr->attr.page_size) - 1; + page_mask = (1 << fmr->attr.page_shift) - 1; /* We are getting page lists, so va must be page aligned. */ if (iova & page_mask) @@ -659,7 +659,7 @@ int mthca_tavor_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list, } mpt_entry.lkey = cpu_to_be32(key); - mpt_entry.length = cpu_to_be64(list_len * (1ull << fmr->attr.page_size)); + mpt_entry.length = cpu_to_be64(list_len * (1ull << fmr->attr.page_shift)); mpt_entry.start = cpu_to_be64(iova); __raw_writel((__force u32) mpt_entry.lkey, &fmr->mem.tavor.mpt->key); @@ -700,7 +700,7 @@ int mthca_arbel_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list, fmr->mem.arbel.mpt->key = cpu_to_be32(key); fmr->mem.arbel.mpt->lkey = cpu_to_be32(key); - fmr->mem.arbel.mpt->length = cpu_to_be64(list_len * (1ull << fmr->attr.page_size)); + fmr->mem.arbel.mpt->length = cpu_to_be64(list_len * (1ull << fmr->attr.page_shift)); fmr->mem.arbel.mpt->start = cpu_to_be64(iova); wmb(); diff --git a/include/rdma/ib_fmr_pool.h b/include/rdma/ib_fmr_pool.h index 86b7e93f198b..4ace54cd0cce 100644 --- a/include/rdma/ib_fmr_pool.h +++ b/include/rdma/ib_fmr_pool.h @@ -43,6 +43,7 @@ struct ib_fmr_pool; /** * struct ib_fmr_pool_param - Parameters for creating FMR pool * @max_pages_per_fmr:Maximum number of pages per map request. + * @page_shift: Log2 of sizeof "pages" mapped by this fmr * @access:Access flags for FMRs in pool. * @pool_size:Number of FMRs to allocate for pool. * @dirty_watermark:Flush is triggered when @dirty_watermark dirty @@ -55,6 +56,7 @@ struct ib_fmr_pool; */ struct ib_fmr_pool_param { int max_pages_per_fmr; + int page_shift; enum ib_access_flags access; int pool_size; int dirty_watermark; diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 1d31c8cd5ce0..61a4390ae9d8 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -651,7 +651,7 @@ struct ib_mw_bind { struct ib_fmr_attr { int max_pages; int max_maps; - u8 page_size; + u8 page_shift; }; struct ib_ucontext { -- cgit v1.2.3 From 8a51866f08103ba04894ce0f65eef567ddc3ed40 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 13 Feb 2006 12:48:12 -0800 Subject: IB: Add ib_modify_qp_is_ok() library function The in-kernel mthca driver contains a table of which attributes are valid for each queue pair state transition. It turns out that both other IB drivers -- ipath and ehca -- which are being prepared for merging have copied this table, errors and all. To forestall this code duplication, move this table and the code to check parameters against it into a midlayer library function, ib_modify_qp_is_ok(). Signed-off-by: Roland Dreier --- drivers/infiniband/core/verbs.c | 252 ++++++++++++++++++++++++++++++++++++++++ include/rdma/ib_verbs.h | 18 +++ 2 files changed, 270 insertions(+) (limited to 'include') diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 8e0ba16bcbdd..ca07a2be87d3 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -245,6 +245,258 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd, } EXPORT_SYMBOL(ib_create_qp); +static const struct { + int valid; + enum ib_qp_attr_mask req_param[IB_QPT_RAW_ETY + 1]; + enum ib_qp_attr_mask opt_param[IB_QPT_RAW_ETY + 1]; +} qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = { + [IB_QPS_RESET] = { + [IB_QPS_RESET] = { .valid = 1 }, + [IB_QPS_ERR] = { .valid = 1 }, + [IB_QPS_INIT] = { + .valid = 1, + .req_param = { + [IB_QPT_UD] = (IB_QP_PKEY_INDEX | + IB_QP_PORT | + IB_QP_QKEY), + [IB_QPT_UC] = (IB_QP_PKEY_INDEX | + IB_QP_PORT | + IB_QP_ACCESS_FLAGS), + [IB_QPT_RC] = (IB_QP_PKEY_INDEX | + IB_QP_PORT | + IB_QP_ACCESS_FLAGS), + [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + } + }, + }, + [IB_QPS_INIT] = { + [IB_QPS_RESET] = { .valid = 1 }, + [IB_QPS_ERR] = { .valid = 1 }, + [IB_QPS_INIT] = { + .valid = 1, + .opt_param = { + [IB_QPT_UD] = (IB_QP_PKEY_INDEX | + IB_QP_PORT | + IB_QP_QKEY), + [IB_QPT_UC] = (IB_QP_PKEY_INDEX | + IB_QP_PORT | + IB_QP_ACCESS_FLAGS), + [IB_QPT_RC] = (IB_QP_PKEY_INDEX | + IB_QP_PORT | + IB_QP_ACCESS_FLAGS), + [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + } + }, + [IB_QPS_RTR] = { + .valid = 1, + .req_param = { + [IB_QPT_UC] = (IB_QP_AV | + IB_QP_PATH_MTU | + IB_QP_DEST_QPN | + IB_QP_RQ_PSN), + [IB_QPT_RC] = (IB_QP_AV | + IB_QP_PATH_MTU | + IB_QP_DEST_QPN | + IB_QP_RQ_PSN | + IB_QP_MAX_DEST_RD_ATOMIC | + IB_QP_MIN_RNR_TIMER), + }, + .opt_param = { + [IB_QPT_UD] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + [IB_QPT_UC] = (IB_QP_ALT_PATH | + IB_QP_ACCESS_FLAGS | + IB_QP_PKEY_INDEX), + [IB_QPT_RC] = (IB_QP_ALT_PATH | + IB_QP_ACCESS_FLAGS | + IB_QP_PKEY_INDEX), + [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + } + } + }, + [IB_QPS_RTR] = { + [IB_QPS_RESET] = { .valid = 1 }, + [IB_QPS_ERR] = { .valid = 1 }, + [IB_QPS_RTS] = { + .valid = 1, + .req_param = { + [IB_QPT_UD] = IB_QP_SQ_PSN, + [IB_QPT_UC] = IB_QP_SQ_PSN, + [IB_QPT_RC] = (IB_QP_TIMEOUT | + IB_QP_RETRY_CNT | + IB_QP_RNR_RETRY | + IB_QP_SQ_PSN | + IB_QP_MAX_QP_RD_ATOMIC), + [IB_QPT_SMI] = IB_QP_SQ_PSN, + [IB_QPT_GSI] = IB_QP_SQ_PSN, + }, + .opt_param = { + [IB_QPT_UD] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + [IB_QPT_UC] = (IB_QP_CUR_STATE | + IB_QP_ALT_PATH | + IB_QP_ACCESS_FLAGS | + IB_QP_PATH_MIG_STATE), + [IB_QPT_RC] = (IB_QP_CUR_STATE | + IB_QP_ALT_PATH | + IB_QP_ACCESS_FLAGS | + IB_QP_MIN_RNR_TIMER | + IB_QP_PATH_MIG_STATE), + [IB_QPT_SMI] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + [IB_QPT_GSI] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + } + } + }, + [IB_QPS_RTS] = { + [IB_QPS_RESET] = { .valid = 1 }, + [IB_QPS_ERR] = { .valid = 1 }, + [IB_QPS_RTS] = { + .valid = 1, + .opt_param = { + [IB_QPT_UD] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + [IB_QPT_UC] = (IB_QP_ACCESS_FLAGS | + IB_QP_ALT_PATH | + IB_QP_PATH_MIG_STATE), + [IB_QPT_RC] = (IB_QP_ACCESS_FLAGS | + IB_QP_ALT_PATH | + IB_QP_PATH_MIG_STATE | + IB_QP_MIN_RNR_TIMER), + [IB_QPT_SMI] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + [IB_QPT_GSI] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + } + }, + [IB_QPS_SQD] = { + .valid = 1, + .opt_param = { + [IB_QPT_UD] = IB_QP_EN_SQD_ASYNC_NOTIFY, + [IB_QPT_UC] = IB_QP_EN_SQD_ASYNC_NOTIFY, + [IB_QPT_RC] = IB_QP_EN_SQD_ASYNC_NOTIFY, + [IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY, + [IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY + } + }, + }, + [IB_QPS_SQD] = { + [IB_QPS_RESET] = { .valid = 1 }, + [IB_QPS_ERR] = { .valid = 1 }, + [IB_QPS_RTS] = { + .valid = 1, + .opt_param = { + [IB_QPT_UD] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + [IB_QPT_UC] = (IB_QP_CUR_STATE | + IB_QP_ALT_PATH | + IB_QP_ACCESS_FLAGS | + IB_QP_PATH_MIG_STATE), + [IB_QPT_RC] = (IB_QP_CUR_STATE | + IB_QP_ALT_PATH | + IB_QP_ACCESS_FLAGS | + IB_QP_MIN_RNR_TIMER | + IB_QP_PATH_MIG_STATE), + [IB_QPT_SMI] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + [IB_QPT_GSI] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + } + }, + [IB_QPS_SQD] = { + .valid = 1, + .opt_param = { + [IB_QPT_UD] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + [IB_QPT_UC] = (IB_QP_AV | + IB_QP_CUR_STATE | + IB_QP_ALT_PATH | + IB_QP_ACCESS_FLAGS | + IB_QP_PKEY_INDEX | + IB_QP_PATH_MIG_STATE), + [IB_QPT_RC] = (IB_QP_PORT | + IB_QP_AV | + IB_QP_TIMEOUT | + IB_QP_RETRY_CNT | + IB_QP_RNR_RETRY | + IB_QP_MAX_QP_RD_ATOMIC | + IB_QP_MAX_DEST_RD_ATOMIC | + IB_QP_CUR_STATE | + IB_QP_ALT_PATH | + IB_QP_ACCESS_FLAGS | + IB_QP_PKEY_INDEX | + IB_QP_MIN_RNR_TIMER | + IB_QP_PATH_MIG_STATE), + [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + } + } + }, + [IB_QPS_SQE] = { + [IB_QPS_RESET] = { .valid = 1 }, + [IB_QPS_ERR] = { .valid = 1 }, + [IB_QPS_RTS] = { + .valid = 1, + .opt_param = { + [IB_QPT_UD] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + [IB_QPT_UC] = (IB_QP_CUR_STATE | + IB_QP_ACCESS_FLAGS), + [IB_QPT_SMI] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + [IB_QPT_GSI] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + } + } + }, + [IB_QPS_ERR] = { + [IB_QPS_RESET] = { .valid = 1 }, + [IB_QPS_ERR] = { .valid = 1 } + } +}; + +int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state, + enum ib_qp_type type, enum ib_qp_attr_mask mask) +{ + enum ib_qp_attr_mask req_param, opt_param; + + if (cur_state < 0 || cur_state > IB_QPS_ERR || + next_state < 0 || next_state > IB_QPS_ERR) + return 0; + + if (mask & IB_QP_CUR_STATE && + cur_state != IB_QPS_RTR && cur_state != IB_QPS_RTS && + cur_state != IB_QPS_SQD && cur_state != IB_QPS_SQE) + return 0; + + if (!qp_state_table[cur_state][next_state].valid) + return 0; + + req_param = qp_state_table[cur_state][next_state].req_param[type]; + opt_param = qp_state_table[cur_state][next_state].opt_param[type]; + + if ((mask & req_param) != req_param) + return 0; + + if (mask & ~(req_param | opt_param | IB_QP_STATE)) + return 0; + + return 1; +} +EXPORT_SYMBOL(ib_modify_qp_is_ok); + int ib_modify_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr, int qp_attr_mask) diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 61a4390ae9d8..010287c844e7 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -990,6 +990,24 @@ static inline int ib_copy_to_udata(struct ib_udata *udata, void *src, size_t len return copy_to_user(udata->outbuf, src, len) ? -EFAULT : 0; } +/** + * ib_modify_qp_is_ok - Check that the supplied attribute mask + * contains all required attributes and no attributes not allowed for + * the given QP state transition. + * @cur_state: Current QP state + * @next_state: Next QP state + * @type: QP type + * @mask: Mask of supplied QP attributes + * + * This function is a helper function that a low-level driver's + * modify_qp method can use to validate the consumer's input. It + * checks that cur_state and next_state are valid QP states, that a + * transition from cur_state to next_state is allowed by the IB spec, + * and that the attribute mask supplied is allowed for the transition. + */ +int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state, + enum ib_qp_type type, enum ib_qp_attr_mask mask); + int ib_register_event_handler (struct ib_event_handler *event_handler); int ib_unregister_event_handler(struct ib_event_handler *event_handler); void ib_dispatch_event(struct ib_event *event); -- cgit v1.2.3 From a74cd4af0bfa9578594acbb711a958104c93b772 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 13 Feb 2006 16:30:49 -0800 Subject: IB: Whitespace cleanups Remove trailing whitespace and fix indentation that with spaces instead of tabs. Signed-off-by: Roland Dreier --- drivers/infiniband/core/uverbs_cmd.c | 12 ++++++------ drivers/infiniband/core/uverbs_main.c | 1 - drivers/infiniband/core/verbs.c | 3 +-- include/rdma/ib_user_verbs.h | 4 ++-- 4 files changed, 9 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index be1cef1b3116..398c125d908c 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1134,8 +1134,8 @@ out: } ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, - const char __user *buf, int in_len, - int out_len) + const char __user *buf, int in_len, + int out_len) { struct ib_uverbs_post_send cmd; struct ib_uverbs_post_send_resp resp; @@ -1363,8 +1363,8 @@ err: } ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file, - const char __user *buf, int in_len, - int out_len) + const char __user *buf, int in_len, + int out_len) { struct ib_uverbs_post_recv cmd; struct ib_uverbs_post_recv_resp resp; @@ -1414,8 +1414,8 @@ out: } ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file, - const char __user *buf, int in_len, - int out_len) + const char __user *buf, int in_len, + int out_len) { struct ib_uverbs_post_srq_recv cmd; struct ib_uverbs_post_srq_recv_resp resp; diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 099fe6cde68c..335b6938a656 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -462,7 +462,6 @@ void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr) ib_uverbs_async_handler(uobj->uverbs_file, uobj->uobject.user_handle, event->event, &uobj->async_list, &uobj->async_events_reported); - } void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr) diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index ca07a2be87d3..c69334dc8012 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -574,8 +574,7 @@ int ib_destroy_cq(struct ib_cq *cq) } EXPORT_SYMBOL(ib_destroy_cq); -int ib_resize_cq(struct ib_cq *cq, - int cqe) +int ib_resize_cq(struct ib_cq *cq, int cqe) { return cq->device->resize_cq ? cq->device->resize_cq(cq, cqe, NULL) : -ENOSYS; diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h index 6ad1207e4235..fb94c08169ce 100644 --- a/include/rdma/ib_user_verbs.h +++ b/include/rdma/ib_user_verbs.h @@ -426,7 +426,7 @@ struct ib_uverbs_sge { }; struct ib_uverbs_send_wr { - __u64 wr_id; + __u64 wr_id; __u32 num_sge; __u32 opcode; __u32 send_flags; @@ -500,7 +500,7 @@ struct ib_uverbs_post_srq_recv_resp { struct ib_uverbs_global_route { __u8 dgid[16]; - __u32 flow_label; + __u32 flow_label; __u8 sgid_index; __u8 hop_limit; __u8 traffic_class; -- cgit v1.2.3 From 7ccc9a24e01258a31ee2b964215e4ddddd2a02c4 Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Mon, 13 Feb 2006 16:31:25 -0800 Subject: IB/uverbs: Support for query QP from userspace Add support to uverbs to handle querying userspace QPs (queue pairs), including adding an ABI for marshalling requests and responses. The kernel midlayer already has the underlying ib_query_qp() function. Signed-off-by: Dotan Barak Signed-off-by: Roland Dreier --- drivers/infiniband/core/uverbs.h | 1 + drivers/infiniband/core/uverbs_cmd.c | 100 ++++++++++++++++++++++++++++++++++ drivers/infiniband/core/uverbs_main.c | 1 + include/rdma/ib_user_verbs.h | 41 ++++++++++++++ 4 files changed, 143 insertions(+) (limited to 'include') diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index 3207239819ce..89c798eb5749 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h @@ -183,6 +183,7 @@ IB_UVERBS_DECLARE_CMD(poll_cq); IB_UVERBS_DECLARE_CMD(req_notify_cq); IB_UVERBS_DECLARE_CMD(destroy_cq); IB_UVERBS_DECLARE_CMD(create_qp); +IB_UVERBS_DECLARE_CMD(query_qp); IB_UVERBS_DECLARE_CMD(modify_qp); IB_UVERBS_DECLARE_CMD(destroy_qp); IB_UVERBS_DECLARE_CMD(post_send); diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 398c125d908c..4cbef8c06634 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -996,6 +996,106 @@ err_up: return ret; } +ssize_t ib_uverbs_query_qp(struct ib_uverbs_file *file, + const char __user *buf, int in_len, + int out_len) +{ + struct ib_uverbs_query_qp cmd; + struct ib_uverbs_query_qp_resp resp; + struct ib_qp *qp; + struct ib_qp_attr *attr; + struct ib_qp_init_attr *init_attr; + int ret; + + if (copy_from_user(&cmd, buf, sizeof cmd)) + return -EFAULT; + + attr = kmalloc(sizeof *attr, GFP_KERNEL); + init_attr = kmalloc(sizeof *init_attr, GFP_KERNEL); + if (!attr || !init_attr) { + ret = -ENOMEM; + goto out; + } + + mutex_lock(&ib_uverbs_idr_mutex); + + qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); + if (qp && qp->uobject->context == file->ucontext) + ret = ib_query_qp(qp, attr, cmd.attr_mask, init_attr); + else + ret = -EINVAL; + + mutex_unlock(&ib_uverbs_idr_mutex); + + if (ret) + goto out; + + memset(&resp, 0, sizeof resp); + + resp.qp_state = attr->qp_state; + resp.cur_qp_state = attr->cur_qp_state; + resp.path_mtu = attr->path_mtu; + resp.path_mig_state = attr->path_mig_state; + resp.qkey = attr->qkey; + resp.rq_psn = attr->rq_psn; + resp.sq_psn = attr->sq_psn; + resp.dest_qp_num = attr->dest_qp_num; + resp.qp_access_flags = attr->qp_access_flags; + resp.pkey_index = attr->pkey_index; + resp.alt_pkey_index = attr->alt_pkey_index; + resp.en_sqd_async_notify = attr->en_sqd_async_notify; + resp.max_rd_atomic = attr->max_rd_atomic; + resp.max_dest_rd_atomic = attr->max_dest_rd_atomic; + resp.min_rnr_timer = attr->min_rnr_timer; + resp.port_num = attr->port_num; + resp.timeout = attr->timeout; + resp.retry_cnt = attr->retry_cnt; + resp.rnr_retry = attr->rnr_retry; + resp.alt_port_num = attr->alt_port_num; + resp.alt_timeout = attr->alt_timeout; + + memcpy(resp.dest.dgid, attr->ah_attr.grh.dgid.raw, 16); + resp.dest.flow_label = attr->ah_attr.grh.flow_label; + resp.dest.sgid_index = attr->ah_attr.grh.sgid_index; + resp.dest.hop_limit = attr->ah_attr.grh.hop_limit; + resp.dest.traffic_class = attr->ah_attr.grh.traffic_class; + resp.dest.dlid = attr->ah_attr.dlid; + resp.dest.sl = attr->ah_attr.sl; + resp.dest.src_path_bits = attr->ah_attr.src_path_bits; + resp.dest.static_rate = attr->ah_attr.static_rate; + resp.dest.is_global = !!(attr->ah_attr.ah_flags & IB_AH_GRH); + resp.dest.port_num = attr->ah_attr.port_num; + + memcpy(resp.alt_dest.dgid, attr->alt_ah_attr.grh.dgid.raw, 16); + resp.alt_dest.flow_label = attr->alt_ah_attr.grh.flow_label; + resp.alt_dest.sgid_index = attr->alt_ah_attr.grh.sgid_index; + resp.alt_dest.hop_limit = attr->alt_ah_attr.grh.hop_limit; + resp.alt_dest.traffic_class = attr->alt_ah_attr.grh.traffic_class; + resp.alt_dest.dlid = attr->alt_ah_attr.dlid; + resp.alt_dest.sl = attr->alt_ah_attr.sl; + resp.alt_dest.src_path_bits = attr->alt_ah_attr.src_path_bits; + resp.alt_dest.static_rate = attr->alt_ah_attr.static_rate; + resp.alt_dest.is_global = !!(attr->alt_ah_attr.ah_flags & IB_AH_GRH); + resp.alt_dest.port_num = attr->alt_ah_attr.port_num; + + resp.max_send_wr = init_attr->cap.max_send_wr; + resp.max_recv_wr = init_attr->cap.max_recv_wr; + resp.max_send_sge = init_attr->cap.max_send_sge; + resp.max_recv_sge = init_attr->cap.max_recv_sge; + resp.max_inline_data = init_attr->cap.max_inline_data; + resp.sq_sig_all = !!init_attr->sq_sig_type; + + if (copy_to_user((void __user *) (unsigned long) cmd.response, + &resp, sizeof resp)) + ret = -EFAULT; + +out: + kfree(attr); + kfree(init_attr); + + return ret ? ret : in_len; +} + ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len) diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 335b6938a656..91e4750fa319 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -96,6 +96,7 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file, [IB_USER_VERBS_CMD_REQ_NOTIFY_CQ] = ib_uverbs_req_notify_cq, [IB_USER_VERBS_CMD_DESTROY_CQ] = ib_uverbs_destroy_cq, [IB_USER_VERBS_CMD_CREATE_QP] = ib_uverbs_create_qp, + [IB_USER_VERBS_CMD_QUERY_QP] = ib_uverbs_query_qp, [IB_USER_VERBS_CMD_MODIFY_QP] = ib_uverbs_modify_qp, [IB_USER_VERBS_CMD_DESTROY_QP] = ib_uverbs_destroy_qp, [IB_USER_VERBS_CMD_POST_SEND] = ib_uverbs_post_send, diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h index fb94c08169ce..58662c34a3de 100644 --- a/include/rdma/ib_user_verbs.h +++ b/include/rdma/ib_user_verbs.h @@ -370,6 +370,47 @@ struct ib_uverbs_qp_dest { __u8 port_num; }; +struct ib_uverbs_query_qp { + __u64 response; + __u32 qp_handle; + __u32 attr_mask; + __u64 driver_data[0]; +}; + +struct ib_uverbs_query_qp_resp { + struct ib_uverbs_qp_dest dest; + struct ib_uverbs_qp_dest alt_dest; + __u32 max_send_wr; + __u32 max_recv_wr; + __u32 max_send_sge; + __u32 max_recv_sge; + __u32 max_inline_data; + __u32 qkey; + __u32 rq_psn; + __u32 sq_psn; + __u32 dest_qp_num; + __u32 qp_access_flags; + __u16 pkey_index; + __u16 alt_pkey_index; + __u8 qp_state; + __u8 cur_qp_state; + __u8 path_mtu; + __u8 path_mig_state; + __u8 en_sqd_async_notify; + __u8 max_rd_atomic; + __u8 max_dest_rd_atomic; + __u8 min_rnr_timer; + __u8 port_num; + __u8 timeout; + __u8 retry_cnt; + __u8 rnr_retry; + __u8 alt_port_num; + __u8 alt_timeout; + __u8 sq_sig_all; + __u8 reserved[5]; + __u64 driver_data[0]; +}; + struct ib_uverbs_modify_qp { struct ib_uverbs_qp_dest dest; struct ib_uverbs_qp_dest alt_dest; -- cgit v1.2.3 From 8bdb0e8632e0f5061bd18b6934346cb609490135 Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Mon, 13 Feb 2006 16:31:57 -0800 Subject: IB/uverbs: Support for query SRQ from userspace Add support to uverbs to handle querying userspace SRQs (shared receive queues), including adding an ABI for marshalling requests and responses. The kernel midlayer already has the underlying ib_query_srq() function. Signed-off-by: Dotan Barak Signed-off-by: Roland Dreier --- drivers/infiniband/core/uverbs.h | 1 + drivers/infiniband/core/uverbs_cmd.c | 44 +++++++++++++++++++++++++++++++++++ drivers/infiniband/core/uverbs_main.c | 1 + include/rdma/ib_user_verbs.h | 15 ++++++++++++ 4 files changed, 61 insertions(+) (limited to 'include') diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index 89c798eb5749..3372d67ff139 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h @@ -195,6 +195,7 @@ IB_UVERBS_DECLARE_CMD(attach_mcast); IB_UVERBS_DECLARE_CMD(detach_mcast); IB_UVERBS_DECLARE_CMD(create_srq); IB_UVERBS_DECLARE_CMD(modify_srq); +IB_UVERBS_DECLARE_CMD(query_srq); IB_UVERBS_DECLARE_CMD(destroy_srq); #endif /* UVERBS_H */ diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 4cbef8c06634..38a66fbef36d 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -2,6 +2,7 @@ * Copyright (c) 2005 Topspin Communications. All rights reserved. * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * Copyright (c) 2005 PathScale, Inc. All rights reserved. + * Copyright (c) 2006 Mellanox Technologies. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -1923,6 +1924,49 @@ out: return ret ? ret : in_len; } +ssize_t ib_uverbs_query_srq(struct ib_uverbs_file *file, + const char __user *buf, + int in_len, int out_len) +{ + struct ib_uverbs_query_srq cmd; + struct ib_uverbs_query_srq_resp resp; + struct ib_srq_attr attr; + struct ib_srq *srq; + int ret; + + if (out_len < sizeof resp) + return -ENOSPC; + + if (copy_from_user(&cmd, buf, sizeof cmd)) + return -EFAULT; + + mutex_lock(&ib_uverbs_idr_mutex); + + srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); + if (srq && srq->uobject->context == file->ucontext) + ret = ib_query_srq(srq, &attr); + else + ret = -EINVAL; + + mutex_unlock(&ib_uverbs_idr_mutex); + + if (ret) + goto out; + + memset(&resp, 0, sizeof resp); + + resp.max_wr = attr.max_wr; + resp.max_sge = attr.max_sge; + resp.srq_limit = attr.srq_limit; + + if (copy_to_user((void __user *) (unsigned long) cmd.response, + &resp, sizeof resp)) + ret = -EFAULT; + +out: + return ret ? ret : in_len; +} + ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len) diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 91e4750fa319..ff092a0a94da 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -108,6 +108,7 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file, [IB_USER_VERBS_CMD_DETACH_MCAST] = ib_uverbs_detach_mcast, [IB_USER_VERBS_CMD_CREATE_SRQ] = ib_uverbs_create_srq, [IB_USER_VERBS_CMD_MODIFY_SRQ] = ib_uverbs_modify_srq, + [IB_USER_VERBS_CMD_QUERY_SRQ] = ib_uverbs_query_srq, [IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq, }; diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h index 58662c34a3de..0edd3a6fe8f5 100644 --- a/include/rdma/ib_user_verbs.h +++ b/include/rdma/ib_user_verbs.h @@ -2,6 +2,7 @@ * Copyright (c) 2005 Topspin Communications. All rights reserved. * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * Copyright (c) 2005 PathScale, Inc. All rights reserved. + * Copyright (c) 2006 Mellanox Technologies. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -613,6 +614,20 @@ struct ib_uverbs_modify_srq { __u64 driver_data[0]; }; +struct ib_uverbs_query_srq { + __u64 response; + __u32 srq_handle; + __u32 reserved; + __u64 driver_data[0]; +}; + +struct ib_uverbs_query_srq_resp { + __u32 max_wr; + __u32 max_sge; + __u32 srq_limit; + __u32 reserved; +}; + struct ib_uverbs_destroy_srq { __u64 response; __u32 srq_handle; -- cgit v1.2.3 From 4d9781c5ce1a517a07dbf03c37323c011037fe79 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 16 Feb 2006 09:26:19 -0800 Subject: IB/uverbs: Fix alignment of struct ib_uverbs_create_qp_resp The size of struct ib_uverbs_create_qp_resp is not even multiple of 8 bytes. This causes problems for low-level drivers that add private data after the structure: 32-bit userspace will look in the wrong place for a response from a 64-bit kernel. Fix this by adding a reserved field. Also, bump the ABI version because this changes the size of a structure. Pointed out by Hoang-Nam Nguyen . Signed-off-by: Roland Dreier --- include/rdma/ib_user_verbs.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h index 0edd3a6fe8f5..3bf4402f466a 100644 --- a/include/rdma/ib_user_verbs.h +++ b/include/rdma/ib_user_verbs.h @@ -44,7 +44,7 @@ * Increment this value if any changes that break userspace ABI * compatibility are made. */ -#define IB_USER_VERBS_ABI_VERSION 4 +#define IB_USER_VERBS_ABI_VERSION 5 enum { IB_USER_VERBS_CMD_GET_CONTEXT, @@ -350,6 +350,7 @@ struct ib_uverbs_create_qp_resp { __u32 max_send_sge; __u32 max_recv_sge; __u32 max_inline_data; + __u32 reserved; }; /* -- cgit v1.2.3 From abb6e9ba17eb133ab385d0f9017fa8afa809d52a Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Thu, 23 Feb 2006 12:13:51 -0800 Subject: IB/mthca: Return actual capacity from create_srq Have mthca's create_srq method return the actual capacity of the SRQ that gets created. Also update comments in to clarify that this is what is expected from ib_create_srq(). Signed-off-by: Dotan Barak Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_srq.c | 3 +++ include/rdma/ib_verbs.h | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index deb526ce013d..209d2bae2256 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -271,6 +271,9 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, srq->first_free = 0; srq->last_free = srq->max - 1; + attr->max_wr = srq->max; + attr->max_sge = srq->max_gs; + return 0; err_out_free_srq: diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 010287c844e7..c1ad6273ac6c 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -1100,7 +1100,9 @@ int ib_destroy_ah(struct ib_ah *ah); * ib_create_srq - Creates a SRQ associated with the specified protection * domain. * @pd: The protection domain associated with the SRQ. - * @srq_init_attr: A list of initial attributes required to create the SRQ. + * @srq_init_attr: A list of initial attributes required to create the + * SRQ. If SRQ creation succeeds, then the attributes are updated to + * the actual capabilities of the created SRQ. * * srq_attr->max_wr and srq_attr->max_sge are read the determine the * requested size of the SRQ, and set to the actual values allocated @@ -1159,7 +1161,9 @@ static inline int ib_post_srq_recv(struct ib_srq *srq, * ib_create_qp - Creates a QP associated with the specified protection * domain. * @pd: The protection domain associated with the QP. - * @qp_init_attr: A list of initial attributes required to create the QP. + * @qp_init_attr: A list of initial attributes required to create the + * QP. If QP creation succeeds, then the attributes are updated to + * the actual capabilities of the created QP. */ struct ib_qp *ib_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *qp_init_attr); -- cgit v1.2.3 From ea88fd16d6e85f4bc71b6053180b64f04be1ff14 Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Thu, 23 Feb 2006 12:36:18 -0800 Subject: IB/uverbs: Return actual capacity from create SRQ operation Pass actual capacity of created SRQ back to userspace, so that userspace can report accurate capacities. This requires an ABI bump, to change struct ib_uverbs_create_srq_resp. Signed-off-by: Dotan Barak Signed-off-by: Roland Dreier --- drivers/infiniband/core/uverbs_cmd.c | 2 ++ include/rdma/ib_user_verbs.h | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 38a66fbef36d..b157e5ff7dad 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1864,6 +1864,8 @@ retry: goto err_destroy; resp.srq_handle = uobj->uobject.id; + resp.max_wr = attr.attr.max_wr; + resp.max_sge = attr.attr.max_sge; if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h index 3bf4402f466a..338ed4333063 100644 --- a/include/rdma/ib_user_verbs.h +++ b/include/rdma/ib_user_verbs.h @@ -44,7 +44,7 @@ * Increment this value if any changes that break userspace ABI * compatibility are made. */ -#define IB_USER_VERBS_ABI_VERSION 5 +#define IB_USER_VERBS_ABI_VERSION 6 enum { IB_USER_VERBS_CMD_GET_CONTEXT, @@ -605,6 +605,9 @@ struct ib_uverbs_create_srq { struct ib_uverbs_create_srq_resp { __u32 srq_handle; + __u32 max_wr; + __u32 max_sge; + __u32 reserved; }; struct ib_uverbs_modify_srq { -- cgit v1.2.3 From f36e1793e25513380cae5958a9164d4cc4458ad0 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Fri, 3 Mar 2006 21:54:13 -0800 Subject: IB/umad: Add support for large RMPP transfers Add support for sending and receiving large RMPP transfers. The old code supports transfers only as large as a single contiguous kernel memory allocation. This patch uses linked list of memory buffers when sending and receiving data to avoid needing contiguous pages for larger transfers. Receive side: copy the arriving MADs in chunks instead of coalescing to one large buffer in kernel space. Send side: split a multipacket MAD buffer to a list of segments, (multipacket_list) and send these using a gather list of size 2. Also, save pointer to last sent segment, and retrieve requested segments by walking list starting at last sent segment. Finally, save pointer to last-acked segment. When retrying, retrieve segments for resending relative to this pointer. When updating last ack, start at this pointer. Signed-off-by: Jack Morgenstein Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/mad.c | 166 ++++++++++++++++++++++----- drivers/infiniband/core/mad_priv.h | 16 ++- drivers/infiniband/core/mad_rmpp.c | 148 ++++++++---------------- drivers/infiniband/core/user_mad.c | 225 +++++++++++++++++++++++++------------ include/rdma/ib_mad.h | 48 +++++--- 5 files changed, 376 insertions(+), 227 deletions(-) (limited to 'include') diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 445ad0dda213..16549add8e8f 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -31,7 +31,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * - * $Id: mad.c 2817 2005-07-07 11:29:26Z halr $ + * $Id: mad.c 5596 2006-03-03 01:00:07Z sean.hefty $ */ #include @@ -765,18 +765,67 @@ out: return ret; } -static int get_buf_length(int hdr_len, int data_len) +static int get_pad_size(int hdr_len, int data_len) { int seg_size, pad; seg_size = sizeof(struct ib_mad) - hdr_len; if (data_len && seg_size) { pad = seg_size - data_len % seg_size; - if (pad == seg_size) - pad = 0; + return pad == seg_size ? 0 : pad; } else - pad = seg_size; - return hdr_len + data_len + pad; + return seg_size; +} + +static void free_send_rmpp_list(struct ib_mad_send_wr_private *mad_send_wr) +{ + struct ib_rmpp_segment *s, *t; + + list_for_each_entry_safe(s, t, &mad_send_wr->rmpp_list, list) { + list_del(&s->list); + kfree(s); + } +} + +static int alloc_send_rmpp_list(struct ib_mad_send_wr_private *send_wr, + gfp_t gfp_mask) +{ + struct ib_mad_send_buf *send_buf = &send_wr->send_buf; + struct ib_rmpp_mad *rmpp_mad = send_buf->mad; + struct ib_rmpp_segment *seg = NULL; + int left, seg_size, pad; + + send_buf->seg_size = sizeof (struct ib_mad) - send_buf->hdr_len; + seg_size = send_buf->seg_size; + pad = send_wr->pad; + + /* Allocate data segments. */ + for (left = send_buf->data_len + pad; left > 0; left -= seg_size) { + seg = kmalloc(sizeof (*seg) + seg_size, gfp_mask); + if (!seg) { + printk(KERN_ERR "alloc_send_rmpp_segs: RMPP mem " + "alloc failed for len %zd, gfp %#x\n", + sizeof (*seg) + seg_size, gfp_mask); + free_send_rmpp_list(send_wr); + return -ENOMEM; + } + seg->num = ++send_buf->seg_count; + list_add_tail(&seg->list, &send_wr->rmpp_list); + } + + /* Zero any padding */ + if (pad) + memset(seg->data + seg_size - pad, 0, pad); + + rmpp_mad->rmpp_hdr.rmpp_version = send_wr->mad_agent_priv-> + agent.rmpp_version; + rmpp_mad->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_DATA; + ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE); + + send_wr->cur_seg = container_of(send_wr->rmpp_list.next, + struct ib_rmpp_segment, list); + send_wr->last_ack_seg = send_wr->cur_seg; + return 0; } struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, @@ -787,32 +836,40 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, { struct ib_mad_agent_private *mad_agent_priv; struct ib_mad_send_wr_private *mad_send_wr; - int buf_size; + int pad, message_size, ret, size; void *buf; mad_agent_priv = container_of(mad_agent, struct ib_mad_agent_private, agent); - buf_size = get_buf_length(hdr_len, data_len); + pad = get_pad_size(hdr_len, data_len); + message_size = hdr_len + data_len + pad; if ((!mad_agent->rmpp_version && - (rmpp_active || buf_size > sizeof(struct ib_mad))) || - (!rmpp_active && buf_size > sizeof(struct ib_mad))) + (rmpp_active || message_size > sizeof(struct ib_mad))) || + (!rmpp_active && message_size > sizeof(struct ib_mad))) return ERR_PTR(-EINVAL); - buf = kzalloc(sizeof *mad_send_wr + buf_size, gfp_mask); + size = rmpp_active ? hdr_len : sizeof(struct ib_mad); + buf = kzalloc(sizeof *mad_send_wr + size, gfp_mask); if (!buf) return ERR_PTR(-ENOMEM); - mad_send_wr = buf + buf_size; + mad_send_wr = buf + size; + INIT_LIST_HEAD(&mad_send_wr->rmpp_list); mad_send_wr->send_buf.mad = buf; + mad_send_wr->send_buf.hdr_len = hdr_len; + mad_send_wr->send_buf.data_len = data_len; + mad_send_wr->pad = pad; mad_send_wr->mad_agent_priv = mad_agent_priv; - mad_send_wr->sg_list[0].length = buf_size; + mad_send_wr->sg_list[0].length = hdr_len; mad_send_wr->sg_list[0].lkey = mad_agent->mr->lkey; + mad_send_wr->sg_list[1].length = sizeof(struct ib_mad) - hdr_len; + mad_send_wr->sg_list[1].lkey = mad_agent->mr->lkey; mad_send_wr->send_wr.wr_id = (unsigned long) mad_send_wr; mad_send_wr->send_wr.sg_list = mad_send_wr->sg_list; - mad_send_wr->send_wr.num_sge = 1; + mad_send_wr->send_wr.num_sge = 2; mad_send_wr->send_wr.opcode = IB_WR_SEND; mad_send_wr->send_wr.send_flags = IB_SEND_SIGNALED; mad_send_wr->send_wr.wr.ud.remote_qpn = remote_qpn; @@ -820,13 +877,11 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, mad_send_wr->send_wr.wr.ud.pkey_index = pkey_index; if (rmpp_active) { - struct ib_rmpp_mad *rmpp_mad = mad_send_wr->send_buf.mad; - rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(hdr_len - - IB_MGMT_RMPP_HDR + data_len); - rmpp_mad->rmpp_hdr.rmpp_version = mad_agent->rmpp_version; - rmpp_mad->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_DATA; - ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, - IB_MGMT_RMPP_FLAG_ACTIVE); + ret = alloc_send_rmpp_list(mad_send_wr, gfp_mask); + if (ret) { + kfree(buf); + return ERR_PTR(ret); + } } mad_send_wr->send_buf.mad_agent = mad_agent; @@ -835,14 +890,50 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, } EXPORT_SYMBOL(ib_create_send_mad); +void *ib_get_rmpp_segment(struct ib_mad_send_buf *send_buf, int seg_num) +{ + struct ib_mad_send_wr_private *mad_send_wr; + struct list_head *list; + + mad_send_wr = container_of(send_buf, struct ib_mad_send_wr_private, + send_buf); + list = &mad_send_wr->cur_seg->list; + + if (mad_send_wr->cur_seg->num < seg_num) { + list_for_each_entry(mad_send_wr->cur_seg, list, list) + if (mad_send_wr->cur_seg->num == seg_num) + break; + } else if (mad_send_wr->cur_seg->num > seg_num) { + list_for_each_entry_reverse(mad_send_wr->cur_seg, list, list) + if (mad_send_wr->cur_seg->num == seg_num) + break; + } + return mad_send_wr->cur_seg->data; +} +EXPORT_SYMBOL(ib_get_rmpp_segment); + +static inline void *ib_get_payload(struct ib_mad_send_wr_private *mad_send_wr) +{ + if (mad_send_wr->send_buf.seg_count) + return ib_get_rmpp_segment(&mad_send_wr->send_buf, + mad_send_wr->seg_num); + else + return mad_send_wr->send_buf.mad + + mad_send_wr->send_buf.hdr_len; +} + void ib_free_send_mad(struct ib_mad_send_buf *send_buf) { struct ib_mad_agent_private *mad_agent_priv; + struct ib_mad_send_wr_private *mad_send_wr; mad_agent_priv = container_of(send_buf->mad_agent, struct ib_mad_agent_private, agent); - kfree(send_buf->mad); + mad_send_wr = container_of(send_buf, struct ib_mad_send_wr_private, + send_buf); + free_send_rmpp_list(mad_send_wr); + kfree(send_buf->mad); if (atomic_dec_and_test(&mad_agent_priv->refcount)) wake_up(&mad_agent_priv->wait); } @@ -865,10 +956,17 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr) mad_agent = mad_send_wr->send_buf.mad_agent; sge = mad_send_wr->sg_list; - sge->addr = dma_map_single(mad_agent->device->dma_device, - mad_send_wr->send_buf.mad, sge->length, - DMA_TO_DEVICE); - pci_unmap_addr_set(mad_send_wr, mapping, sge->addr); + sge[0].addr = dma_map_single(mad_agent->device->dma_device, + mad_send_wr->send_buf.mad, + sge[0].length, + DMA_TO_DEVICE); + pci_unmap_addr_set(mad_send_wr, header_mapping, sge[0].addr); + + sge[1].addr = dma_map_single(mad_agent->device->dma_device, + ib_get_payload(mad_send_wr), + sge[1].length, + DMA_TO_DEVICE); + pci_unmap_addr_set(mad_send_wr, payload_mapping, sge[1].addr); spin_lock_irqsave(&qp_info->send_queue.lock, flags); if (qp_info->send_queue.count < qp_info->send_queue.max_active) { @@ -885,11 +983,14 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr) list_add_tail(&mad_send_wr->mad_list.list, list); } spin_unlock_irqrestore(&qp_info->send_queue.lock, flags); - if (ret) + if (ret) { dma_unmap_single(mad_agent->device->dma_device, - pci_unmap_addr(mad_send_wr, mapping), - sge->length, DMA_TO_DEVICE); - + pci_unmap_addr(mad_send_wr, header_mapping), + sge[0].length, DMA_TO_DEVICE); + dma_unmap_single(mad_agent->device->dma_device, + pci_unmap_addr(mad_send_wr, payload_mapping), + sge[1].length, DMA_TO_DEVICE); + } return ret; } @@ -1860,8 +1961,11 @@ static void ib_mad_send_done_handler(struct ib_mad_port_private *port_priv, retry: dma_unmap_single(mad_send_wr->send_buf.mad_agent->device->dma_device, - pci_unmap_addr(mad_send_wr, mapping), + pci_unmap_addr(mad_send_wr, header_mapping), mad_send_wr->sg_list[0].length, DMA_TO_DEVICE); + dma_unmap_single(mad_send_wr->send_buf.mad_agent->device->dma_device, + pci_unmap_addr(mad_send_wr, payload_mapping), + mad_send_wr->sg_list[1].length, DMA_TO_DEVICE); queued_send_wr = NULL; spin_lock_irqsave(&send_queue->lock, flags); list_del(&mad_list->list); diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h index 570f78682af3..a7125d4b5ccf 100644 --- a/drivers/infiniband/core/mad_priv.h +++ b/drivers/infiniband/core/mad_priv.h @@ -31,7 +31,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * - * $Id: mad_priv.h 2730 2005-06-28 16:43:03Z sean.hefty $ + * $Id: mad_priv.h 5596 2006-03-03 01:00:07Z sean.hefty $ */ #ifndef __IB_MAD_PRIV_H__ @@ -85,6 +85,12 @@ struct ib_mad_private { } mad; } __attribute__ ((packed)); +struct ib_rmpp_segment { + struct list_head list; + u32 num; + u8 data[0]; +}; + struct ib_mad_agent_private { struct list_head agent_list; struct ib_mad_agent agent; @@ -119,7 +125,8 @@ struct ib_mad_send_wr_private { struct list_head agent_list; struct ib_mad_agent_private *mad_agent_priv; struct ib_mad_send_buf send_buf; - DECLARE_PCI_UNMAP_ADDR(mapping) + DECLARE_PCI_UNMAP_ADDR(header_mapping) + DECLARE_PCI_UNMAP_ADDR(payload_mapping) struct ib_send_wr send_wr; struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG]; __be64 tid; @@ -130,11 +137,12 @@ struct ib_mad_send_wr_private { enum ib_wc_status status; /* RMPP control */ + struct list_head rmpp_list; + struct ib_rmpp_segment *last_ack_seg; + struct ib_rmpp_segment *cur_seg; int last_ack; int seg_num; int newwin; - int total_seg; - int data_offset; int pad; }; diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c index 3249e1d8c07b..bacfdd5bddad 100644 --- a/drivers/infiniband/core/mad_rmpp.c +++ b/drivers/infiniband/core/mad_rmpp.c @@ -111,14 +111,14 @@ static int data_offset(u8 mgmt_class) return IB_MGMT_RMPP_HDR; } -static void format_ack(struct ib_rmpp_mad *ack, +static void format_ack(struct ib_mad_send_buf *msg, struct ib_rmpp_mad *data, struct mad_rmpp_recv *rmpp_recv) { + struct ib_rmpp_mad *ack = msg->mad; unsigned long flags; - memcpy(&ack->mad_hdr, &data->mad_hdr, - data_offset(data->mad_hdr.mgmt_class)); + memcpy(ack, &data->mad_hdr, msg->hdr_len); ack->mad_hdr.method ^= IB_MGMT_METHOD_RESP; ack->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_ACK; @@ -135,16 +135,16 @@ static void ack_recv(struct mad_rmpp_recv *rmpp_recv, struct ib_mad_recv_wc *recv_wc) { struct ib_mad_send_buf *msg; - int ret; + int ret, hdr_len; + hdr_len = data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp, - recv_wc->wc->pkey_index, 1, IB_MGMT_RMPP_HDR, - IB_MGMT_RMPP_DATA, GFP_KERNEL); + recv_wc->wc->pkey_index, 1, hdr_len, + 0, GFP_KERNEL); if (!msg) return; - format_ack(msg->mad, (struct ib_rmpp_mad *) recv_wc->recv_buf.mad, - rmpp_recv); + format_ack(msg, (struct ib_rmpp_mad *) recv_wc->recv_buf.mad, rmpp_recv); msg->ah = rmpp_recv->ah; ret = ib_post_send_mad(msg, NULL); if (ret) @@ -156,16 +156,17 @@ static struct ib_mad_send_buf *alloc_response_msg(struct ib_mad_agent *agent, { struct ib_mad_send_buf *msg; struct ib_ah *ah; + int hdr_len; ah = ib_create_ah_from_wc(agent->qp->pd, recv_wc->wc, recv_wc->recv_buf.grh, agent->port_num); if (IS_ERR(ah)) return (void *) ah; + hdr_len = data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); msg = ib_create_send_mad(agent, recv_wc->wc->src_qp, recv_wc->wc->pkey_index, 1, - IB_MGMT_RMPP_HDR, IB_MGMT_RMPP_DATA, - GFP_KERNEL); + hdr_len, 0, GFP_KERNEL); if (IS_ERR(msg)) ib_destroy_ah(ah); else @@ -195,8 +196,7 @@ static void nack_recv(struct ib_mad_agent_private *agent, return; rmpp_mad = msg->mad; - memcpy(rmpp_mad, recv_wc->recv_buf.mad, - data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class)); + memcpy(rmpp_mad, recv_wc->recv_buf.mad, msg->hdr_len); rmpp_mad->mad_hdr.method ^= IB_MGMT_METHOD_RESP; rmpp_mad->rmpp_hdr.rmpp_version = IB_MGMT_RMPP_VERSION; @@ -433,44 +433,6 @@ static struct ib_mad_recv_wc * complete_rmpp(struct mad_rmpp_recv *rmpp_recv) return rmpp_wc; } -void ib_coalesce_recv_mad(struct ib_mad_recv_wc *mad_recv_wc, void *buf) -{ - struct ib_mad_recv_buf *seg_buf; - struct ib_rmpp_mad *rmpp_mad; - void *data; - int size, len, offset; - u8 flags; - - len = mad_recv_wc->mad_len; - if (len <= sizeof(struct ib_mad)) { - memcpy(buf, mad_recv_wc->recv_buf.mad, len); - return; - } - - offset = data_offset(mad_recv_wc->recv_buf.mad->mad_hdr.mgmt_class); - - list_for_each_entry(seg_buf, &mad_recv_wc->rmpp_list, list) { - rmpp_mad = (struct ib_rmpp_mad *)seg_buf->mad; - flags = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr); - - if (flags & IB_MGMT_RMPP_FLAG_FIRST) { - data = rmpp_mad; - size = sizeof(*rmpp_mad); - } else { - data = (void *) rmpp_mad + offset; - if (flags & IB_MGMT_RMPP_FLAG_LAST) - size = len; - else - size = sizeof(*rmpp_mad) - offset; - } - - memcpy(buf, data, size); - len -= size; - buf += size; - } -} -EXPORT_SYMBOL(ib_coalesce_recv_mad); - static struct ib_mad_recv_wc * continue_rmpp(struct ib_mad_agent_private *agent, struct ib_mad_recv_wc *mad_recv_wc) @@ -570,50 +532,33 @@ start_rmpp(struct ib_mad_agent_private *agent, return mad_recv_wc; } -static inline u64 get_seg_addr(struct ib_mad_send_wr_private *mad_send_wr) -{ - return mad_send_wr->sg_list[0].addr + mad_send_wr->data_offset + - (sizeof(struct ib_rmpp_mad) - mad_send_wr->data_offset) * - (mad_send_wr->seg_num - 1); -} - static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr) { struct ib_rmpp_mad *rmpp_mad; int timeout; - u32 paylen; + u32 paylen = 0; rmpp_mad = mad_send_wr->send_buf.mad; ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE); - rmpp_mad->rmpp_hdr.seg_num = cpu_to_be32(mad_send_wr->seg_num); + rmpp_mad->rmpp_hdr.seg_num = cpu_to_be32(++mad_send_wr->seg_num); if (mad_send_wr->seg_num == 1) { rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_FIRST; - paylen = mad_send_wr->total_seg * IB_MGMT_RMPP_DATA - + paylen = mad_send_wr->send_buf.seg_count * IB_MGMT_RMPP_DATA - mad_send_wr->pad; - rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen); - mad_send_wr->sg_list[0].length = sizeof(struct ib_rmpp_mad); - } else { - mad_send_wr->send_wr.num_sge = 2; - mad_send_wr->sg_list[0].length = mad_send_wr->data_offset; - mad_send_wr->sg_list[1].addr = get_seg_addr(mad_send_wr); - mad_send_wr->sg_list[1].length = sizeof(struct ib_rmpp_mad) - - mad_send_wr->data_offset; - mad_send_wr->sg_list[1].lkey = mad_send_wr->sg_list[0].lkey; - rmpp_mad->rmpp_hdr.paylen_newwin = 0; } - if (mad_send_wr->seg_num == mad_send_wr->total_seg) { + if (mad_send_wr->seg_num == mad_send_wr->send_buf.seg_count) { rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_LAST; paylen = IB_MGMT_RMPP_DATA - mad_send_wr->pad; - rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen); } + rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen); /* 2 seconds for an ACK until we can find the packet lifetime */ timeout = mad_send_wr->send_buf.timeout_ms; if (!timeout || timeout > 2000) mad_send_wr->timeout = msecs_to_jiffies(2000); - mad_send_wr->seg_num++; + return ib_send_mad(mad_send_wr); } @@ -629,7 +574,7 @@ static void abort_send(struct ib_mad_agent_private *agent, __be64 tid, if (!mad_send_wr) goto out; /* Unmatched send */ - if ((mad_send_wr->last_ack == mad_send_wr->total_seg) || + if ((mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count) || (!mad_send_wr->timeout) || (mad_send_wr->status != IB_WC_SUCCESS)) goto out; /* Send is already done */ @@ -645,6 +590,18 @@ out: spin_unlock_irqrestore(&agent->lock, flags); } +static inline void adjust_last_ack(struct ib_mad_send_wr_private *wr, + int seg_num) +{ + struct list_head *list; + + wr->last_ack = seg_num; + list = &wr->last_ack_seg->list; + list_for_each_entry(wr->last_ack_seg, list, list) + if (wr->last_ack_seg->num == seg_num) + break; +} + static void process_rmpp_ack(struct ib_mad_agent_private *agent, struct ib_mad_recv_wc *mad_recv_wc) { @@ -675,11 +632,12 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, if (!mad_send_wr) goto out; /* Unmatched ACK */ - if ((mad_send_wr->last_ack == mad_send_wr->total_seg) || + if ((mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count) || (!mad_send_wr->timeout) || (mad_send_wr->status != IB_WC_SUCCESS)) goto out; /* Send is already done */ - if (seg_num > mad_send_wr->total_seg || seg_num > mad_send_wr->newwin) { + if (seg_num > mad_send_wr->send_buf.seg_count || + seg_num > mad_send_wr->newwin) { spin_unlock_irqrestore(&agent->lock, flags); abort_send(agent, rmpp_mad->mad_hdr.tid, IB_MGMT_RMPP_STATUS_S2B); @@ -691,11 +649,11 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, goto out; /* Old ACK */ if (seg_num > mad_send_wr->last_ack) { - mad_send_wr->last_ack = seg_num; + adjust_last_ack(mad_send_wr, seg_num); mad_send_wr->retries = mad_send_wr->send_buf.retries; } mad_send_wr->newwin = newwin; - if (mad_send_wr->last_ack == mad_send_wr->total_seg) { + if (mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count) { /* If no response is expected, the ACK completes the send */ if (!mad_send_wr->send_buf.timeout_ms) { struct ib_mad_send_wc wc; @@ -714,7 +672,7 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, mad_send_wr->send_buf.timeout_ms); } else if (mad_send_wr->refcount == 1 && mad_send_wr->seg_num < mad_send_wr->newwin && - mad_send_wr->seg_num <= mad_send_wr->total_seg) { + mad_send_wr->seg_num < mad_send_wr->send_buf.seg_count) { /* Send failure will just result in a timeout/retry */ ret = send_next_seg(mad_send_wr); if (ret) @@ -838,31 +796,19 @@ out: int ib_send_rmpp_mad(struct ib_mad_send_wr_private *mad_send_wr) { struct ib_rmpp_mad *rmpp_mad; - int i, total_len, ret; + int ret; rmpp_mad = mad_send_wr->send_buf.mad; if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & IB_MGMT_RMPP_FLAG_ACTIVE)) return IB_RMPP_RESULT_UNHANDLED; - if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA) + if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA) { + mad_send_wr->seg_num = 1; return IB_RMPP_RESULT_INTERNAL; + } - if (mad_send_wr->send_wr.num_sge > 1) - return -EINVAL; /* TODO: support num_sge > 1 */ - - mad_send_wr->seg_num = 1; mad_send_wr->newwin = 1; - mad_send_wr->data_offset = data_offset(rmpp_mad->mad_hdr.mgmt_class); - - total_len = 0; - for (i = 0; i < mad_send_wr->send_wr.num_sge; i++) - total_len += mad_send_wr->send_wr.sg_list[i].length; - - mad_send_wr->total_seg = (total_len - mad_send_wr->data_offset) / - (sizeof(struct ib_rmpp_mad) - mad_send_wr->data_offset); - mad_send_wr->pad = total_len - IB_MGMT_RMPP_HDR - - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); /* We need to wait for the final ACK even if there isn't a response */ mad_send_wr->refcount += (mad_send_wr->timeout == 0); @@ -893,14 +839,14 @@ int ib_process_rmpp_send_wc(struct ib_mad_send_wr_private *mad_send_wr, if (!mad_send_wr->timeout) return IB_RMPP_RESULT_PROCESSED; /* Response received */ - if (mad_send_wr->last_ack == mad_send_wr->total_seg) { + if (mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count) { mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms); return IB_RMPP_RESULT_PROCESSED; /* Send done */ } - if (mad_send_wr->seg_num > mad_send_wr->newwin || - mad_send_wr->seg_num > mad_send_wr->total_seg) + if (mad_send_wr->seg_num == mad_send_wr->newwin || + mad_send_wr->seg_num == mad_send_wr->send_buf.seg_count) return IB_RMPP_RESULT_PROCESSED; /* Wait for ACK */ ret = send_next_seg(mad_send_wr); @@ -921,10 +867,12 @@ int ib_retry_rmpp(struct ib_mad_send_wr_private *mad_send_wr) IB_MGMT_RMPP_FLAG_ACTIVE)) return IB_RMPP_RESULT_UNHANDLED; /* RMPP not active */ - if (mad_send_wr->last_ack == mad_send_wr->total_seg) + if (mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count) return IB_RMPP_RESULT_PROCESSED; - mad_send_wr->seg_num = mad_send_wr->last_ack + 1; + mad_send_wr->seg_num = mad_send_wr->last_ack; + mad_send_wr->cur_seg = mad_send_wr->last_ack_seg; + ret = send_next_seg(mad_send_wr); if (ret) return IB_RMPP_RESULT_PROCESSED; diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index c908de8db5a9..fb6cd42601f9 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -31,7 +31,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * - * $Id: user_mad.c 4010 2005-11-09 23:11:56Z roland $ + * $Id: user_mad.c 5596 2006-03-03 01:00:07Z sean.hefty $ */ #include @@ -121,6 +121,7 @@ struct ib_umad_file { struct ib_umad_packet { struct ib_mad_send_buf *msg; + struct ib_mad_recv_wc *recv_wc; struct list_head list; int length; struct ib_user_mad mad; @@ -176,31 +177,32 @@ static int queue_packet(struct ib_umad_file *file, return ret; } +static int data_offset(u8 mgmt_class) +{ + if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM) + return IB_MGMT_SA_HDR; + else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && + (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) + return IB_MGMT_VENDOR_HDR; + else + return IB_MGMT_RMPP_HDR; +} + static void send_handler(struct ib_mad_agent *agent, struct ib_mad_send_wc *send_wc) { struct ib_umad_file *file = agent->context; - struct ib_umad_packet *timeout; struct ib_umad_packet *packet = send_wc->send_buf->context[0]; ib_destroy_ah(packet->msg->ah); ib_free_send_mad(packet->msg); if (send_wc->status == IB_WC_RESP_TIMEOUT_ERR) { - timeout = kzalloc(sizeof *timeout + IB_MGMT_MAD_HDR, GFP_KERNEL); - if (!timeout) - goto out; - - timeout->length = IB_MGMT_MAD_HDR; - timeout->mad.hdr.id = packet->mad.hdr.id; - timeout->mad.hdr.status = ETIMEDOUT; - memcpy(timeout->mad.data, packet->mad.data, - sizeof (struct ib_mad_hdr)); - - if (queue_packet(file, agent, timeout)) - kfree(timeout); + packet->length = IB_MGMT_MAD_HDR; + packet->mad.hdr.status = ETIMEDOUT; + if (!queue_packet(file, agent, packet)) + return; } -out: kfree(packet); } @@ -209,22 +211,20 @@ static void recv_handler(struct ib_mad_agent *agent, { struct ib_umad_file *file = agent->context; struct ib_umad_packet *packet; - int length; if (mad_recv_wc->wc->status != IB_WC_SUCCESS) - goto out; + goto err1; - length = mad_recv_wc->mad_len; - packet = kzalloc(sizeof *packet + length, GFP_KERNEL); + packet = kzalloc(sizeof *packet, GFP_KERNEL); if (!packet) - goto out; + goto err1; - packet->length = length; - - ib_coalesce_recv_mad(mad_recv_wc, packet->mad.data); + packet->length = mad_recv_wc->mad_len; + packet->recv_wc = mad_recv_wc; packet->mad.hdr.status = 0; - packet->mad.hdr.length = length + sizeof (struct ib_user_mad); + packet->mad.hdr.length = sizeof (struct ib_user_mad) + + mad_recv_wc->mad_len; packet->mad.hdr.qpn = cpu_to_be32(mad_recv_wc->wc->src_qp); packet->mad.hdr.lid = cpu_to_be16(mad_recv_wc->wc->slid); packet->mad.hdr.sl = mad_recv_wc->wc->sl; @@ -240,12 +240,79 @@ static void recv_handler(struct ib_mad_agent *agent, } if (queue_packet(file, agent, packet)) - kfree(packet); + goto err2; + return; -out: +err2: + kfree(packet); +err1: ib_free_recv_mad(mad_recv_wc); } +static ssize_t copy_recv_mad(char __user *buf, struct ib_umad_packet *packet, + size_t count) +{ + struct ib_mad_recv_buf *recv_buf; + int left, seg_payload, offset, max_seg_payload; + + /* We need enough room to copy the first (or only) MAD segment. */ + recv_buf = &packet->recv_wc->recv_buf; + if ((packet->length <= sizeof (*recv_buf->mad) && + count < sizeof (packet->mad) + packet->length) || + (packet->length > sizeof (*recv_buf->mad) && + count < sizeof (packet->mad) + sizeof (*recv_buf->mad))) + return -EINVAL; + + if (copy_to_user(buf, &packet->mad, sizeof (packet->mad))) + return -EFAULT; + + buf += sizeof (packet->mad); + seg_payload = min_t(int, packet->length, sizeof (*recv_buf->mad)); + if (copy_to_user(buf, recv_buf->mad, seg_payload)) + return -EFAULT; + + if (seg_payload < packet->length) { + /* + * Multipacket RMPP MAD message. Copy remainder of message. + * Note that last segment may have a shorter payload. + */ + if (count < sizeof (packet->mad) + packet->length) { + /* + * The buffer is too small, return the first RMPP segment, + * which includes the RMPP message length. + */ + return -ENOSPC; + } + offset = data_offset(recv_buf->mad->mad_hdr.mgmt_class); + max_seg_payload = sizeof (struct ib_mad) - offset; + + for (left = packet->length - seg_payload, buf += seg_payload; + left; left -= seg_payload, buf += seg_payload) { + recv_buf = container_of(recv_buf->list.next, + struct ib_mad_recv_buf, list); + seg_payload = min(left, max_seg_payload); + if (copy_to_user(buf, ((void *) recv_buf->mad) + offset, + seg_payload)) + return -EFAULT; + } + } + return sizeof (packet->mad) + packet->length; +} + +static ssize_t copy_send_mad(char __user *buf, struct ib_umad_packet *packet, + size_t count) +{ + ssize_t size = sizeof (packet->mad) + packet->length; + + if (count < size) + return -EINVAL; + + if (copy_to_user(buf, &packet->mad, size)) + return -EFAULT; + + return size; +} + static ssize_t ib_umad_read(struct file *filp, char __user *buf, size_t count, loff_t *pos) { @@ -253,7 +320,7 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf, struct ib_umad_packet *packet; ssize_t ret; - if (count < sizeof (struct ib_user_mad) + sizeof (struct ib_mad)) + if (count < sizeof (struct ib_user_mad)) return -EINVAL; spin_lock_irq(&file->recv_lock); @@ -276,28 +343,44 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf, spin_unlock_irq(&file->recv_lock); - if (count < packet->length + sizeof (struct ib_user_mad)) { - /* Return length needed (and first RMPP segment) if too small */ - if (copy_to_user(buf, &packet->mad, - sizeof (struct ib_user_mad) + sizeof (struct ib_mad))) - ret = -EFAULT; - else - ret = -ENOSPC; - } else if (copy_to_user(buf, &packet->mad, - packet->length + sizeof (struct ib_user_mad))) - ret = -EFAULT; + if (packet->recv_wc) + ret = copy_recv_mad(buf, packet, count); else - ret = packet->length + sizeof (struct ib_user_mad); + ret = copy_send_mad(buf, packet, count); + if (ret < 0) { /* Requeue packet */ spin_lock_irq(&file->recv_lock); list_add(&packet->list, &file->recv_list); spin_unlock_irq(&file->recv_lock); - } else + } else { + if (packet->recv_wc) + ib_free_recv_mad(packet->recv_wc); kfree(packet); + } return ret; } +static int copy_rmpp_mad(struct ib_mad_send_buf *msg, const char __user *buf) +{ + int left, seg; + + /* Copy class specific header */ + if ((msg->hdr_len > IB_MGMT_RMPP_HDR) && + copy_from_user(msg->mad + IB_MGMT_RMPP_HDR, buf + IB_MGMT_RMPP_HDR, + msg->hdr_len - IB_MGMT_RMPP_HDR)) + return -EFAULT; + + /* All headers are in place. Copy data segments. */ + for (seg = 1, left = msg->data_len, buf += msg->hdr_len; left > 0; + seg++, left -= msg->seg_size, buf += msg->seg_size) { + if (copy_from_user(ib_get_rmpp_segment(msg, seg), buf, + min(left, msg->seg_size))) + return -EFAULT; + } + return 0; +} + static ssize_t ib_umad_write(struct file *filp, const char __user *buf, size_t count, loff_t *pos) { @@ -309,14 +392,12 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, struct ib_rmpp_mad *rmpp_mad; u8 method; __be64 *tid; - int ret, length, hdr_len, copy_offset; - int rmpp_active, has_rmpp_header; + int ret, data_len, hdr_len, copy_offset, rmpp_active; if (count < sizeof (struct ib_user_mad) + IB_MGMT_RMPP_HDR) return -EINVAL; - length = count - sizeof (struct ib_user_mad); - packet = kmalloc(sizeof *packet + IB_MGMT_RMPP_HDR, GFP_KERNEL); + packet = kzalloc(sizeof *packet + IB_MGMT_RMPP_HDR, GFP_KERNEL); if (!packet) return -ENOMEM; @@ -363,35 +444,25 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, if (rmpp_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_ADM) { hdr_len = IB_MGMT_SA_HDR; copy_offset = IB_MGMT_RMPP_HDR; - has_rmpp_header = 1; + rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & + IB_MGMT_RMPP_FLAG_ACTIVE; } else if (rmpp_mad->mad_hdr.mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START && rmpp_mad->mad_hdr.mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END) { - hdr_len = IB_MGMT_VENDOR_HDR; - copy_offset = IB_MGMT_RMPP_HDR; - has_rmpp_header = 1; + hdr_len = IB_MGMT_VENDOR_HDR; + copy_offset = IB_MGMT_RMPP_HDR; + rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & + IB_MGMT_RMPP_FLAG_ACTIVE; } else { hdr_len = IB_MGMT_MAD_HDR; copy_offset = IB_MGMT_MAD_HDR; - has_rmpp_header = 0; - } - - if (has_rmpp_header) - rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & - IB_MGMT_RMPP_FLAG_ACTIVE; - else rmpp_active = 0; - - /* Validate that the management class can support RMPP */ - if (rmpp_active && !agent->rmpp_version) { - ret = -EINVAL; - goto err_ah; } + data_len = count - sizeof (struct ib_user_mad) - hdr_len; packet->msg = ib_create_send_mad(agent, be32_to_cpu(packet->mad.hdr.qpn), - 0, rmpp_active, - hdr_len, length - hdr_len, - GFP_KERNEL); + 0, rmpp_active, hdr_len, + data_len, GFP_KERNEL); if (IS_ERR(packet->msg)) { ret = PTR_ERR(packet->msg); goto err_ah; @@ -402,14 +473,21 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, packet->msg->retries = packet->mad.hdr.retries; packet->msg->context[0] = packet; - /* Copy MAD headers (RMPP header in place) */ + /* Copy MAD header. Any RMPP header is already in place. */ memcpy(packet->msg->mad, packet->mad.data, IB_MGMT_MAD_HDR); - /* Now, copy rest of message from user into send buffer */ - if (copy_from_user(packet->msg->mad + copy_offset, - buf + sizeof (struct ib_user_mad) + copy_offset, - length - copy_offset)) { - ret = -EFAULT; - goto err_msg; + buf += sizeof (struct ib_user_mad); + + if (!rmpp_active) { + if (copy_from_user(packet->msg->mad + copy_offset, + buf + copy_offset, + hdr_len + data_len - copy_offset)) { + ret = -EFAULT; + goto err_msg; + } + } else { + ret = copy_rmpp_mad(packet->msg, buf); + if (ret) + goto err_msg; } /* @@ -433,18 +511,14 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, goto err_msg; up_read(&file->port->mutex); - return count; err_msg: ib_free_send_mad(packet->msg); - err_ah: ib_destroy_ah(ah); - err_up: up_read(&file->port->mutex); - err: kfree(packet); return ret; @@ -627,8 +701,11 @@ static int ib_umad_close(struct inode *inode, struct file *filp) already_dead = file->agents_dead; file->agents_dead = 1; - list_for_each_entry_safe(packet, tmp, &file->recv_list, list) + list_for_each_entry_safe(packet, tmp, &file->recv_list, list) { + if (packet->recv_wc) + ib_free_recv_mad(packet->recv_wc); kfree(packet); + } list_del(&file->port_list); diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h index 2c133506742b..51ab8eddb295 100644 --- a/include/rdma/ib_mad.h +++ b/include/rdma/ib_mad.h @@ -33,7 +33,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * - * $Id: ib_mad.h 2775 2005-07-02 13:42:12Z halr $ + * $Id: ib_mad.h 5596 2006-03-03 01:00:07Z sean.hefty $ */ #if !defined( IB_MAD_H ) @@ -208,15 +208,23 @@ struct ib_class_port_info /** * ib_mad_send_buf - MAD data buffer and work request for sends. * @next: A pointer used to chain together MADs for posting. - * @mad: References an allocated MAD data buffer. + * @mad: References an allocated MAD data buffer for MADs that do not have + * RMPP active. For MADs using RMPP, references the common and management + * class specific headers. * @mad_agent: MAD agent that allocated the buffer. * @ah: The address handle to use when sending the MAD. * @context: User-controlled context fields. + * @hdr_len: Indicates the size of the data header of the MAD. This length + * includes the common MAD, RMPP, and class specific headers. + * @data_len: Indicates the total size of user-transferred data. + * @seg_count: The number of RMPP segments allocated for this send. + * @seg_size: Size of each RMPP segment. * @timeout_ms: Time to wait for a response. * @retries: Number of times to retry a request for a response. * * Users are responsible for initializing the MAD buffer itself, with the - * exception of specifying the payload length field in any RMPP MAD. + * exception of any RMPP header. Additional segment buffer space allocated + * beyond data_len is padding. */ struct ib_mad_send_buf { struct ib_mad_send_buf *next; @@ -224,6 +232,10 @@ struct ib_mad_send_buf { struct ib_mad_agent *mad_agent; struct ib_ah *ah; void *context[2]; + int hdr_len; + int data_len; + int seg_count; + int seg_size; int timeout_ms; int retries; }; @@ -299,7 +311,7 @@ typedef void (*ib_mad_snoop_handler)(struct ib_mad_agent *mad_agent, * @mad_recv_wc: Received work completion information on the received MAD. * * MADs received in response to a send request operation will be handed to - * the user after the send operation completes. All data buffers given + * the user before the send operation completes. All data buffers given * to registered agents through this routine are owned by the receiving * client, except for snooping agents. Clients snooping MADs should not * modify the data referenced by @mad_recv_wc. @@ -485,17 +497,6 @@ int ib_unregister_mad_agent(struct ib_mad_agent *mad_agent); int ib_post_send_mad(struct ib_mad_send_buf *send_buf, struct ib_mad_send_buf **bad_send_buf); -/** - * ib_coalesce_recv_mad - Coalesces received MAD data into a single buffer. - * @mad_recv_wc: Work completion information for a received MAD. - * @buf: User-provided data buffer to receive the coalesced buffers. The - * referenced buffer should be at least the size of the mad_len specified - * by @mad_recv_wc. - * - * This call copies a chain of received MAD segments into a single data buffer, - * removing duplicated headers. - */ -void ib_coalesce_recv_mad(struct ib_mad_recv_wc *mad_recv_wc, void *buf); /** * ib_free_recv_mad - Returns data buffers used to receive a MAD. @@ -590,9 +591,10 @@ int ib_process_mad_wc(struct ib_mad_agent *mad_agent, * with an initialized work request structure. Users may modify the returned * MAD data buffer before posting the send. * - * The returned data buffer will be cleared. Users are responsible for - * initializing the common MAD and any class specific headers. If @rmpp_active - * is set, the RMPP header will be initialized for sending. + * The returned MAD header, class specific headers, and any padding will be + * cleared. Users are responsible for initializing the common MAD header, + * any class specific header, and MAD data area. + * If @rmpp_active is set, the RMPP header will be initialized for sending. */ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, u32 remote_qpn, u16 pkey_index, @@ -600,6 +602,16 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, int hdr_len, int data_len, gfp_t gfp_mask); +/** + * ib_get_rmpp_segment - returns the data buffer for a given RMPP segment. + * @send_buf: Previously allocated send data buffer. + * @seg_num: number of segment to return + * + * This routine returns a pointer to the data buffer of an RMPP MAD. + * Users must provide synchronization to @send_buf around this call. + */ +void *ib_get_rmpp_segment(struct ib_mad_send_buf *send_buf, int seg_num); + /** * ib_free_send_mad - Returns data buffers used to send a MAD. * @send_buf: Previously allocated send data buffer. -- cgit v1.2.3 From d358788f3f30113e49882187d794832905e42592 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 20 Mar 2006 20:00:09 +0000 Subject: [SERIAL] kernel console should send CRLF not LFCR Glen Turner reported that writing LFCR rather than the more traditional CRLF causes issues with some terminals. Since this aflicts many serial drivers, extract the common code to a library function (uart_console_write) and arrange for each driver to supply a "putchar" function. Signed-off-by: Russell King --- drivers/serial/21285.c | 19 +++++++------------ drivers/serial/8250.c | 26 +++++++++----------------- drivers/serial/8250_early.c | 9 ++------- drivers/serial/amba-pl010.c | 24 ++++++++---------------- drivers/serial/amba-pl011.c | 20 +++++--------------- drivers/serial/at91_serial.c | 24 ++++++++---------------- drivers/serial/au1x00_uart.c | 26 +++++++++----------------- drivers/serial/clps711x.c | 24 ++++++++---------------- drivers/serial/dz.c | 12 +++++------- drivers/serial/imx.c | 26 +++++++++----------------- drivers/serial/ip22zilog.c | 11 +++-------- drivers/serial/m32r_sio.c | 26 +++++++++----------------- drivers/serial/mpc52xx_uart.c | 11 +++++------ drivers/serial/pmac_zilog.c | 23 +++++++++++------------ drivers/serial/pxa.c | 26 +++++++++----------------- drivers/serial/s3c2410.c | 26 ++++++++++---------------- drivers/serial/sa1100.c | 26 ++++++++++---------------- drivers/serial/serial_core.c | 21 +++++++++++++++++++++ drivers/serial/serial_lh7a40x.c | 17 +++++++---------- drivers/serial/serial_txx9.c | 26 +++++++++----------------- drivers/serial/sunsab.c | 10 +++------- drivers/serial/sunsu.c | 26 +++++++++----------------- drivers/serial/sunzilog.c | 13 ++++--------- drivers/serial/vr41xx_siu.c | 16 +++++++--------- include/linux/serial_core.h | 3 +++ 25 files changed, 190 insertions(+), 301 deletions(-) (limited to 'include') diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 8c5c276c5577..7572665a8855 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c @@ -375,23 +375,18 @@ static void serial21285_setup_ports(void) } #ifdef CONFIG_SERIAL_21285_CONSOLE +static void serial21285_console_putchar(struct uart_port *port, int ch) +{ + while (*CSR_UARTFLG & 0x20) + barrier(); + *CSR_UARTDR = ch; +} static void serial21285_console_write(struct console *co, const char *s, unsigned int count) { - int i; - - for (i = 0; i < count; i++) { - while (*CSR_UARTFLG & 0x20) - barrier(); - *CSR_UARTDR = s[i]; - if (s[i] == '\n') { - while (*CSR_UARTFLG & 0x20) - barrier(); - *CSR_UARTDR = '\r'; - } - } + uart_console_write(&serial21285_port, s, count, serial21285_console_putchar); } static void __init diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 7aca22c9976d..5996d3cd0ed8 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -2182,6 +2182,14 @@ static inline void wait_for_xmitr(struct uart_8250_port *up, int bits) } } +static void serial8250_console_putchar(struct uart_port *port, int ch) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + + wait_for_xmitr(up, UART_LSR_THRE); + serial_out(up, UART_TX, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -2193,7 +2201,6 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) { struct uart_8250_port *up = &serial8250_ports[co->index]; unsigned int ier; - int i; touch_nmi_watchdog(); @@ -2207,22 +2214,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) else serial_out(up, UART_IER, 0); - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(up, UART_LSR_THRE); - - /* - * Send the character out. - * If a LF, also do CR... - */ - serial_out(up, UART_TX, *s); - if (*s == 10) { - wait_for_xmitr(up, UART_LSR_THRE); - serial_out(up, UART_TX, 13); - } - } + uart_console_write(&up->port, s, count, serial8250_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c index 59ba5d993b4b..7e511199b4c5 100644 --- a/drivers/serial/8250_early.c +++ b/drivers/serial/8250_early.c @@ -74,7 +74,7 @@ static void __init wait_for_xmitr(struct uart_port *port) } } -static void __init putc(struct uart_port *port, unsigned char c) +static void __init putc(struct uart_port *port, int c) { wait_for_xmitr(port); serial_out(port, UART_TX, c); @@ -89,12 +89,7 @@ static void __init early_uart_write(struct console *console, const char *s, unsi ier = serial_in(port, UART_IER); serial_out(port, UART_IER, 0); - while (*s && count-- > 0) { - putc(port, *s); - if (*s == '\n') - putc(port, '\r'); - s++; - } + uart_console_write(port, s, count, putc); /* Wait for transmitter to become empty and restore the IER */ wait_for_xmitr(port); diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 321a3b3a5728..e04d5e82d9ae 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -591,12 +591,18 @@ static struct uart_amba_port amba_ports[UART_NR] = { #ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE +static void pl010_console_putchar(struct uart_port *port, int ch) +{ + while (!UART_TX_READY(UART_GET_FR(port))) + barrier(); + UART_PUT_CHAR(port, ch); +} + static void pl010_console_write(struct console *co, const char *s, unsigned int count) { struct uart_port *port = &amba_ports[co->index].port; unsigned int status, old_cr; - int i; /* * First save the CR then disable the interrupts @@ -604,21 +610,7 @@ pl010_console_write(struct console *co, const char *s, unsigned int count) old_cr = UART_GET_CR(port); UART_PUT_CR(port, UART01x_CR_UARTEN); - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - do { - status = UART_GET_FR(port); - } while (!UART_TX_READY(status)); - UART_PUT_CHAR(port, s[i]); - if (s[i] == '\n') { - do { - status = UART_GET_FR(port); - } while (!UART_TX_READY(status)); - UART_PUT_CHAR(port, '\r'); - } - } + uart_console_write(port, s, count, pl010_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index 034a029e356e..3d966cfc9a38 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -587,14 +587,12 @@ static struct uart_amba_port *amba_ports[UART_NR]; #ifdef CONFIG_SERIAL_AMBA_PL011_CONSOLE -static inline void -pl011_console_write_char(struct uart_amba_port *uap, char ch) +static void pl011_console_putchar(struct uart_port *port, int ch) { - unsigned int status; + struct uart_amba_port *uap = (struct uart_amba_port *)port; - do { - status = readw(uap->port.membase + UART01x_FR); - } while (status & UART01x_FR_TXFF); + while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) + barrier(); writew(ch, uap->port.membase + UART01x_DR); } @@ -603,7 +601,6 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) { struct uart_amba_port *uap = amba_ports[co->index]; unsigned int status, old_cr, new_cr; - int i; clk_enable(uap->clk); @@ -615,14 +612,7 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE; writew(new_cr, uap->port.membase + UART011_CR); - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - pl011_console_write_char(uap, s[i]); - if (s[i] == '\n') - pl011_console_write_char(uap, '\r'); - } + uart_console_write(&uap->port, s, count, pl011_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/at91_serial.c b/drivers/serial/at91_serial.c index 2113feb75c39..6547fe0cef96 100644 --- a/drivers/serial/at91_serial.c +++ b/drivers/serial/at91_serial.c @@ -711,6 +711,12 @@ void __init at91_register_uart(int idx, int port) } #ifdef CONFIG_SERIAL_AT91_CONSOLE +static void at91_console_putchar(struct uart_port *port, int ch) +{ + while (!(UART_GET_CSR(port) & AT91_US_TXRDY)) + barrier(); + UART_PUT_CHAR(port, ch); +} /* * Interrupts are disabled on entering @@ -718,7 +724,7 @@ void __init at91_register_uart(int idx, int port) static void at91_console_write(struct console *co, const char *s, u_int count) { struct uart_port *port = at91_ports + co->index; - unsigned int status, i, imr; + unsigned int status, imr; /* * First, save IMR and then disable interrupts @@ -726,21 +732,7 @@ static void at91_console_write(struct console *co, const char *s, u_int count) imr = UART_GET_IMR(port); /* get interrupt mask */ UART_PUT_IDR(port, AT91_US_RXRDY | AT91_US_TXRDY); - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - do { - status = UART_GET_CSR(port); - } while (!(status & AT91_US_TXRDY)); - UART_PUT_CHAR(port, s[i]); - if (s[i] == '\n') { - do { - status = UART_GET_CSR(port); - } while (!(status & AT91_US_TXRDY)); - UART_PUT_CHAR(port, '\r'); - } - } + uart_console_write(port, s, count, at91_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c index 344022fe53ef..29f94bbb79be 100644 --- a/drivers/serial/au1x00_uart.c +++ b/drivers/serial/au1x00_uart.c @@ -1121,6 +1121,14 @@ static inline void wait_for_xmitr(struct uart_8250_port *up) } } +static void au1x00_console_putchar(struct uart_port *port, int ch) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + + wait_for_xmitr(up); + serial_out(up, UART_TX, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -1132,7 +1140,6 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) { struct uart_8250_port *up = &serial8250_ports[co->index]; unsigned int ier; - int i; /* * First save the UER then disable the interrupts @@ -1140,22 +1147,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) ier = serial_in(up, UART_IER); serial_out(up, UART_IER, 0); - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(up); - - /* - * Send the character out. - * If a LF, also do CR... - */ - serial_out(up, UART_TX, *s); - if (*s == 10) { - wait_for_xmitr(up); - serial_out(up, UART_TX, 13); - } - } + uart_console_write(&up->port, s, count, au1x00_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index ce7b2e4ecd17..2691112c84ad 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c @@ -424,6 +424,13 @@ static struct uart_port clps711x_ports[UART_NR] = { }; #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE +static void clps711xuart_console_putchar(struct uart_port *port, int ch) +{ + while (clps_readl(SYSFLG(port)) & SYSFLG_UTXFF) + barrier(); + clps_writel(ch, UARTDR(port)); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -438,7 +445,6 @@ clps711xuart_console_write(struct console *co, const char *s, { struct uart_port *port = clps711x_ports + co->index; unsigned int status, syscon; - int i; /* * Ensure that the port is enabled. @@ -446,21 +452,7 @@ clps711xuart_console_write(struct console *co, const char *s, syscon = clps_readl(SYSCON(port)); clps_writel(syscon | SYSCON_UARTEN, SYSCON(port)); - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - do { - status = clps_readl(SYSFLG(port)); - } while (status & SYSFLG_UTXFF); - clps_writel(s[i], UARTDR(port)); - if (s[i] == '\n') { - do { - status = clps_readl(SYSFLG(port)); - } while (status & SYSFLG_UTXFF); - clps_writel('\r', UARTDR(port)); - } - } + uart_console_write(port, s, count, clps711xuart_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index ba5541de673b..bf71bad5c34f 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c @@ -674,11 +674,12 @@ static void dz_reset(struct dz_port *dport) } #ifdef CONFIG_SERIAL_DZ_CONSOLE -static void dz_console_put_char(struct dz_port *dport, unsigned char ch) +static void dz_console_putchar(struct uart_port *port, int ch) { + struct dz_port *dport = (struct dz_port *)uport; unsigned long flags; int loops = 2500; - unsigned short tmp = ch; + unsigned short tmp = (unsigned char)ch; /* this code sends stuff out to serial device - spinning its wheels and waiting. */ @@ -694,6 +695,7 @@ static void dz_console_put_char(struct dz_port *dport, unsigned char ch) spin_unlock_irqrestore(&dport->port.lock, flags); } + /* * ------------------------------------------------------------------- * dz_console_print () @@ -710,11 +712,7 @@ static void dz_console_print(struct console *cons, #ifdef DEBUG_DZ prom_printf((char *) str); #endif - while (count--) { - if (*str == '\n') - dz_console_put_char(dport, '\r'); - dz_console_put_char(dport, *str++); - } + uart_console_write(&dport->port, str, count, dz_console_putchar); } static int __init dz_console_setup(struct console *co, char *options) diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 4d53fb5ca87b..c3b7a6673e9c 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -743,6 +743,13 @@ static void __init imx_init_ports(void) } #ifdef CONFIG_SERIAL_IMX_CONSOLE +static void imx_console_putchar(struct uart_port *port, int ch) +{ + struct imx_port *sport = (struct imx_port *)port; + while ((UTS((u32)sport->port.membase) & UTS_TXFULL)) + barrier(); + URTX0((u32)sport->port.membase) = ch; +} /* * Interrupts are disabled on entering @@ -751,7 +758,7 @@ static void imx_console_write(struct console *co, const char *s, unsigned int count) { struct imx_port *sport = &imx_ports[co->index]; - unsigned int old_ucr1, old_ucr2, i; + unsigned int old_ucr1, old_ucr2; /* * First, save UCR1/2 and then disable interrupts @@ -764,22 +771,7 @@ imx_console_write(struct console *co, const char *s, unsigned int count) & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN); UCR2((u32)sport->port.membase) = old_ucr2 | UCR2_TXEN; - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - - while ((UTS((u32)sport->port.membase) & UTS_TXFULL)) - barrier(); - - URTX0((u32)sport->port.membase) = s[i]; - - if (s[i] == '\n') { - while ((UTS((u32)sport->port.membase) & UTS_TXFULL)) - barrier(); - URTX0((u32)sport->port.membase) = '\r'; - } - } + uart_console_write(&sport->port, s, count, imx_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index 193722d680cf..651772474ac1 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c @@ -967,8 +967,9 @@ static struct zilog_layout * __init get_zs(int chip) #define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */ #ifdef CONFIG_SERIAL_IP22_ZILOG_CONSOLE -static void ip22zilog_put_char(struct zilog_channel *channel, unsigned char ch) +static void ip22zilog_put_char(struct uart_port *port, int ch) { + struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); int loops = ZS_PUT_CHAR_MAX_DELAY; /* This is a timed polling loop so do not switch the explicit @@ -992,16 +993,10 @@ static void ip22zilog_console_write(struct console *con, const char *s, unsigned int count) { struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index]; - struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port); unsigned long flags; - int i; spin_lock_irqsave(&up->port.lock, flags); - for (i = 0; i < count; i++, s++) { - ip22zilog_put_char(channel, *s); - if (*s == 10) - ip22zilog_put_char(channel, 13); - } + uart_console_write(&up->port, s, count, ip22zilog_put_char); udelay(2); spin_unlock_irqrestore(&up->port.lock, flags); } diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c index 242a04104393..876bc5e027bb 100644 --- a/drivers/serial/m32r_sio.c +++ b/drivers/serial/m32r_sio.c @@ -1039,6 +1039,14 @@ static inline void wait_for_xmitr(struct uart_sio_port *up) } } +static void m32r_sio_console_putchar(struct uart_port *port, int ch) +{ + struct uart_sio_port *up = (struct uart_sio_port *)port; + + wait_for_xmitr(up); + sio_out(up, SIOTXB, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -1058,23 +1066,7 @@ static void m32r_sio_console_write(struct console *co, const char *s, ier = sio_in(up, SIOTRCR); sio_out(up, SIOTRCR, 0); - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(up); - - /* - * Send the character out. - * If a LF, also do CR... - */ - sio_out(up, SIOTXB, *s); - - if (*s == 10) { - wait_for_xmitr(up); - sio_out(up, SIOTXB, 13); - } - } + uart_console_write(&up->port, s, count, m32r_sio_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 61dd17d7bace..928e6cf12dca 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -603,15 +603,14 @@ mpc52xx_console_write(struct console *co, const char *s, unsigned int count) udelay(1); /* Write all the chars */ - for ( i=0 ; impc52xx_psc_buffer_8, *s); - + for (i = 0; i < count; i++, s++) { /* Line return handling */ - if ( *s++ == '\n' ) + if (*s == '\n') out_8(&psc->mpc52xx_psc_buffer_8, '\r'); + /* Send the char */ + out_8(&psc->mpc52xx_psc_buffer_8, *s); + /* Wait the TX buffer to be empty */ j = 20000; /* Maximum wait */ while (!(in_be16(&psc->mpc52xx_psc_status) & diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 9b7ed58cb53b..513ff8597707 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -1916,6 +1916,16 @@ static void __exit exit_pmz(void) #ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE +static void pmz_console_putchar(struct uart_port *port, int ch) +{ + struct uart_pmac_port *uap = (struct uart_pmac_port *)port; + + /* Wait for the transmit buffer to empty. */ + while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0) + udelay(5); + write_zsdata(uap, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -1924,7 +1934,6 @@ static void pmz_console_write(struct console *con, const char *s, unsigned int c { struct uart_pmac_port *uap = &pmz_ports[con->index]; unsigned long flags; - int i; if (ZS_IS_ASLEEP(uap)) return; @@ -1934,17 +1943,7 @@ static void pmz_console_write(struct console *con, const char *s, unsigned int c write_zsreg(uap, R1, uap->curregs[1] & ~TxINT_ENAB); write_zsreg(uap, R5, uap->curregs[5] | TxENABLE | RTS | DTR); - for (i = 0; i < count; i++) { - /* Wait for the transmit buffer to empty. */ - while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0) - udelay(5); - write_zsdata(uap, s[i]); - if (s[i] == 10) { - while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0) - udelay(5); - write_zsdata(uap, R13); - } - } + uart_console_write(&uap->port, s, count, pmz_console_putchar); /* Restore the values in the registers. */ write_zsreg(uap, R1, uap->curregs[1]); diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index 10535f00301f..77d4568ccc3a 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -619,6 +619,14 @@ static inline void wait_for_xmitr(struct uart_pxa_port *up) } } +static void serial_pxa_console_putchar(struct uart_port *port, int ch) +{ + struct uart_pxa_port *up = (struct uart_pxa_port *)port; + + wait_for_xmitr(up); + serial_out(up, UART_TX, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -630,7 +638,6 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count) { struct uart_pxa_port *up = &serial_pxa_ports[co->index]; unsigned int ier; - int i; /* * First save the IER then disable the interrupts @@ -638,22 +645,7 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count) ier = serial_in(up, UART_IER); serial_out(up, UART_IER, UART_IER_UUE); - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(up); - - /* - * Send the character out. - * If a LF, also do CR... - */ - serial_out(up, UART_TX, *s); - if (*s == 10) { - wait_for_xmitr(up); - serial_out(up, UART_TX, 13); - } - } + uart_console_write(&up->port, s, count, serial_pxa_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 7410e093a6b9..e4d701239702 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -1584,25 +1584,19 @@ s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon) } static void -s3c24xx_serial_console_write(struct console *co, const char *s, - unsigned int count) +s3c24xx_serial_console_putchar(struct uart_port *port, int ch) { - int i; unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); + while (!s3c24xx_serial_console_txrdy(port, ufcon)) + barrier(); + wr_regb(cons_uart, S3C2410_UTXH, ch); +} - for (i = 0; i < count; i++) { - while (!s3c24xx_serial_console_txrdy(cons_uart, ufcon)) - barrier(); - - wr_regb(cons_uart, S3C2410_UTXH, s[i]); - - if (s[i] == '\n') { - while (!s3c24xx_serial_console_txrdy(cons_uart, ufcon)) - barrier(); - - wr_regb(cons_uart, S3C2410_UTXH, '\r'); - } - } +static void +s3c24xx_serial_console_write(struct console *co, const char *s, + unsigned int count) +{ + uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar); } static void __init diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index 2c00b8625852..c2d9068b491d 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c @@ -689,6 +689,14 @@ void __init sa1100_register_uart(int idx, int port) #ifdef CONFIG_SERIAL_SA1100_CONSOLE +static void sa1100_console_putchar(struct uart_port *port, int ch) +{ + struct sa1100_port *sport = (struct sa1100_port *)port; + + while (!(UART_GET_UTSR1(sport) & UTSR1_TNF)) + barrier(); + UART_PUT_CHAR(sport, ch); +} /* * Interrupts are disabled on entering @@ -697,7 +705,7 @@ static void sa1100_console_write(struct console *co, const char *s, unsigned int count) { struct sa1100_port *sport = &sa1100_ports[co->index]; - unsigned int old_utcr3, status, i; + unsigned int old_utcr3, status; /* * First, save UTCR3 and then disable interrupts @@ -706,21 +714,7 @@ sa1100_console_write(struct console *co, const char *s, unsigned int count) UART_PUT_UTCR3(sport, (old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)) | UTCR3_TXE); - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - do { - status = UART_GET_UTSR1(sport); - } while (!(status & UTSR1_TNF)); - UART_PUT_CHAR(sport, s[i]); - if (s[i] == '\n') { - do { - status = UART_GET_UTSR1(sport); - } while (!(status & UTSR1_TNF)); - UART_PUT_CHAR(sport, '\r'); - } - } + uart_console_write(&sport->port, s, count, sa1100_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index cc1faa31d124..fcd7744c4253 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1754,6 +1754,27 @@ static int uart_read_proc(char *page, char **start, off_t off, #endif #ifdef CONFIG_SERIAL_CORE_CONSOLE +/* + * uart_console_write - write a console message to a serial port + * @port: the port to write the message + * @s: array of characters + * @count: number of characters in string to write + * @write: function to write character to port + */ +void uart_console_write(struct uart_port *port, const char *s, + unsigned int count, + void (*putchar)(struct uart_port *, int)) +{ + unsigned int i; + + for (i = 0; i < count; i++, s++) { + if (*s == '\n') + putchar(port, '\r'); + putchar(port, *s); + } +} +EXPORT_SYMBOL_GPL(uart_console_write); + /* * Check whether an invalid uart number has been specified, and * if so, search for the first available port that does have diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index 04186eaae227..aa521b8e0d4e 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c @@ -543,6 +543,12 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = { #else # define LH7A40X_CONSOLE &lh7a40x_console +static void lh7a40xuart_console_putchar(struct uart_port *port, int ch) +{ + while (UR(port, UART_R_STATUS) & nTxRdy) + ; + UR(port, UART_R_DATA) = ch; +} static void lh7a40xuart_console_write (struct console* co, const char* s, @@ -556,16 +562,7 @@ static void lh7a40xuart_console_write (struct console* co, UR (port, UART_R_INTEN) = 0; /* Disable all interrupts */ BIT_SET (port, UART_R_CON, UARTEN | SIRDIS); /* Enable UART */ - for (; count-- > 0; ++s) { - while (UR (port, UART_R_STATUS) & nTxRdy) - ; - UR (port, UART_R_DATA) = *s; - if (*s == '\n') { - while ((UR (port, UART_R_STATUS) & TxBusy)) - ; - UR (port, UART_R_DATA) = '\r'; - } - } + uart_console_write(port, s, count, lh7a40xuart_console_putchar); /* Wait until all characters are sent */ while (UR (port, UART_R_STATUS) & TxBusy) diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index ee98a867bc6d..1a259cee1a98 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c @@ -854,6 +854,14 @@ static inline void wait_for_xmitr(struct uart_txx9_port *up) } } +static void serial_txx9_console_putchar(struct uart_port *port, int ch) +{ + struct uart_txx9_port *up = (struct uart_txx9_port *)port; + + wait_for_xmitr(up); + sio_out(up, TXX9_SITFIFO, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -865,7 +873,6 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count) { struct uart_txx9_port *up = &serial_txx9_ports[co->index]; unsigned int ier, flcr; - int i; /* * First save the UER then disable the interrupts @@ -879,22 +886,7 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count) if (!(up->port.flags & UPF_CONS_FLOW) && (flcr & TXX9_SIFLCR_TES)) sio_out(up, TXX9_SIFLCR, flcr & ~TXX9_SIFLCR_TES); - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(up); - - /* - * Send the character out. - * If a LF, also do CR... - */ - sio_out(up, TXX9_SITFIFO, *s); - if (*s == 10) { - wait_for_xmitr(up); - sio_out(up, TXX9_SITFIFO, 13); - } - } + uart_console_write(&up->port, s, count, serial_txx9_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 85664228a0b6..be95eabd0394 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -861,8 +861,9 @@ static int num_channels; #ifdef CONFIG_SERIAL_SUNSAB_CONSOLE -static __inline__ void sunsab_console_putchar(struct uart_sunsab_port *up, char c) +static void sunsab_console_putchar(struct uart_port *port, int c) { + struct uart_sunsab_port *up = (struct uart_sunsab_port *)port; unsigned long flags; spin_lock_irqsave(&up->port.lock, flags); @@ -876,13 +877,8 @@ static __inline__ void sunsab_console_putchar(struct uart_sunsab_port *up, char static void sunsab_console_write(struct console *con, const char *s, unsigned n) { struct uart_sunsab_port *up = &sunsab_ports[con->index]; - int i; - for (i = 0; i < n; i++) { - if (*s == '\n') - sunsab_console_putchar(up, '\r'); - sunsab_console_putchar(up, *s++); - } + uart_console_write(&up->port, s, n, sunsab_console_putchar); sunsab_tec_wait(up); } diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 4e453fa966ae..9ca1d8b9364b 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1376,6 +1376,14 @@ static __inline__ void wait_for_xmitr(struct uart_sunsu_port *up) } } +static void sunsu_console_putchar(struct uart_port *port, int ch) +{ + struct uart_sunsu_port *up = (struct uart_sunsu_port *)port; + + wait_for_xmitr(up); + serial_out(up, UART_TX, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -1385,7 +1393,6 @@ static void sunsu_console_write(struct console *co, const char *s, { struct uart_sunsu_port *up = &sunsu_ports[co->index]; unsigned int ier; - int i; /* * First save the UER then disable the interrupts @@ -1393,22 +1400,7 @@ static void sunsu_console_write(struct console *co, const char *s, ier = serial_in(up, UART_IER); serial_out(up, UART_IER, 0); - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(up); - - /* - * Send the character out. - * If a LF, also do CR... - */ - serial_out(up, UART_TX, *s); - if (*s == 10) { - wait_for_xmitr(up); - serial_out(up, UART_TX, 13); - } - } + uart_console_write(&up->port, s, count, sunsu_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 5cc4d4c2935c..b0c46b9a5930 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -1252,8 +1252,9 @@ static struct zilog_layout __iomem * __init get_zs(int chip, int node) #define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */ -static void sunzilog_put_char(struct zilog_channel __iomem *channel, unsigned char ch) +static void sunzilog_putchar(struct uart_port *port, int ch) { + struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); int loops = ZS_PUT_CHAR_MAX_DELAY; /* This is a timed polling loop so do not switch the explicit @@ -1284,7 +1285,7 @@ static int sunzilog_serio_write(struct serio *serio, unsigned char ch) spin_lock_irqsave(&sunzilog_serio_lock, flags); - sunzilog_put_char(ZILOG_CHANNEL_FROM_PORT(&up->port), ch); + sunzilog_putchar(&up->port, ch); spin_unlock_irqrestore(&sunzilog_serio_lock, flags); @@ -1325,16 +1326,10 @@ static void sunzilog_console_write(struct console *con, const char *s, unsigned int count) { struct uart_sunzilog_port *up = &sunzilog_port_table[con->index]; - struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port); unsigned long flags; - int i; spin_lock_irqsave(&up->port.lock, flags); - for (i = 0; i < count; i++, s++) { - sunzilog_put_char(channel, *s); - if (*s == 10) - sunzilog_put_char(channel, 13); - } + uart_console_write(&up->port, s, count, sunzilog_putchar); udelay(2); spin_unlock_irqrestore(&up->port.lock, flags); } diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index d61494d185cd..3f88b8e81937 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c @@ -821,25 +821,23 @@ static void wait_for_xmitr(struct uart_port *port) } } +static void siu_console_putchar(struct uart_port *port, int ch) +{ + wait_for_xmitr(port); + siu_write(port, UART_TX, ch); +} + static void siu_console_write(struct console *con, const char *s, unsigned count) { struct uart_port *port; uint8_t ier; - unsigned i; port = &siu_uart_ports[con->index]; ier = siu_read(port, UART_IER); siu_write(port, UART_IER, 0); - for (i = 0; i < count && *s != '\0'; i++, s++) { - wait_for_xmitr(port); - siu_write(port, UART_TX, *s); - if (*s == '\n') { - wait_for_xmitr(port); - siu_write(port, UART_TX, '\r'); - } - } + uart_console_write(port, s, count, siu_console_putchar); wait_for_xmitr(port); siu_write(port, UART_IER, ier); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 4041122dabfc..f7434e5086f5 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -366,6 +366,9 @@ void uart_parse_options(char *options, int *baud, int *parity, int *bits, int uart_set_options(struct uart_port *port, struct console *co, int baud, int parity, int bits, int flow); struct tty_driver *uart_console_device(struct console *co, int *index); +void uart_console_write(struct uart_port *port, const char *s, + unsigned int count, + void (*putchar)(struct uart_port *, int)); /* * Port/driver registration/removal -- cgit v1.2.3 From 58383af629efb07e5a0694e445eda0c65b16e1de Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 6 Feb 2006 14:12:43 -0800 Subject: [PATCH] kobj_map semaphore to mutex conversion Convert the kobj_map code to use a mutex instead of a semaphore. It converts the single two users as well, genhd.c and char_dev.c. Signed-off-by: Jes Sorensen Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- block/genhd.c | 31 ++++++++++++++++--------------- drivers/base/map.c | 21 +++++++++++---------- fs/char_dev.c | 17 +++++++++-------- include/linux/kobj_map.h | 4 ++-- 4 files changed, 38 insertions(+), 35 deletions(-) (limited to 'include') diff --git a/block/genhd.c b/block/genhd.c index db57546a709d..64510fd88621 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -15,12 +15,13 @@ #include #include #include +#include #define MAX_PROBE_HASH 255 /* random */ static struct subsystem block_subsys; -static DECLARE_MUTEX(block_subsys_sem); +static DEFINE_MUTEX(block_subsys_lock); /* * Can be deleted altogether. Later. @@ -46,7 +47,7 @@ struct blkdev_info { /* * iterate over a list of blkdev_info structures. allows * the major_names array to be iterated over from outside this file - * must be called with the block_subsys_sem held + * must be called with the block_subsys_lock held */ void *get_next_blkdev(void *dev) { @@ -85,20 +86,20 @@ out: void *acquire_blkdev_list(void) { - down(&block_subsys_sem); + mutex_lock(&block_subsys_lock); return get_next_blkdev(NULL); } void release_blkdev_list(void *dev) { - up(&block_subsys_sem); + mutex_unlock(&block_subsys_lock); kfree(dev); } /* * Count the number of records in the blkdev_list. - * must be called with the block_subsys_sem held + * must be called with the block_subsys_lock held */ int count_blkdev_list(void) { @@ -118,7 +119,7 @@ int count_blkdev_list(void) /* * extract the major and name values from a blkdev_info struct * passed in as a void to *dev. Must be called with - * block_subsys_sem held + * block_subsys_lock held */ int get_blkdev_info(void *dev, int *major, char **name) { @@ -138,7 +139,7 @@ int register_blkdev(unsigned int major, const char *name) struct blk_major_name **n, *p; int index, ret = 0; - down(&block_subsys_sem); + mutex_lock(&block_subsys_lock); /* temporary */ if (major == 0) { @@ -183,7 +184,7 @@ int register_blkdev(unsigned int major, const char *name) kfree(p); } out: - up(&block_subsys_sem); + mutex_unlock(&block_subsys_lock); return ret; } @@ -197,7 +198,7 @@ int unregister_blkdev(unsigned int major, const char *name) int index = major_to_index(major); int ret = 0; - down(&block_subsys_sem); + mutex_lock(&block_subsys_lock); for (n = &major_names[index]; *n; n = &(*n)->next) if ((*n)->major == major) break; @@ -207,7 +208,7 @@ int unregister_blkdev(unsigned int major, const char *name) p = *n; *n = p->next; } - up(&block_subsys_sem); + mutex_unlock(&block_subsys_lock); kfree(p); return ret; @@ -301,7 +302,7 @@ static void *part_start(struct seq_file *part, loff_t *pos) struct list_head *p; loff_t l = *pos; - down(&block_subsys_sem); + mutex_lock(&block_subsys_lock); list_for_each(p, &block_subsys.kset.list) if (!l--) return list_entry(p, struct gendisk, kobj.entry); @@ -318,7 +319,7 @@ static void *part_next(struct seq_file *part, void *v, loff_t *pos) static void part_stop(struct seq_file *part, void *v) { - up(&block_subsys_sem); + mutex_unlock(&block_subsys_lock); } static int show_partition(struct seq_file *part, void *v) @@ -377,7 +378,7 @@ static struct kobject *base_probe(dev_t dev, int *part, void *data) static int __init genhd_device_init(void) { - bdev_map = kobj_map_init(base_probe, &block_subsys_sem); + bdev_map = kobj_map_init(base_probe, &block_subsys_lock); blk_dev_init(); subsystem_register(&block_subsys); return 0; @@ -611,7 +612,7 @@ static void *diskstats_start(struct seq_file *part, loff_t *pos) loff_t k = *pos; struct list_head *p; - down(&block_subsys_sem); + mutex_lock(&block_subsys_lock); list_for_each(p, &block_subsys.kset.list) if (!k--) return list_entry(p, struct gendisk, kobj.entry); @@ -628,7 +629,7 @@ static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos) static void diskstats_stop(struct seq_file *part, void *v) { - up(&block_subsys_sem); + mutex_unlock(&block_subsys_lock); } static int diskstats_show(struct seq_file *s, void *v) diff --git a/drivers/base/map.c b/drivers/base/map.c index b449dae6f0d3..e87017f36853 100644 --- a/drivers/base/map.c +++ b/drivers/base/map.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -25,7 +26,7 @@ struct kobj_map { int (*lock)(dev_t, void *); void *data; } *probes[255]; - struct semaphore *sem; + struct mutex *lock; }; int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, @@ -53,7 +54,7 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, p->range = range; p->data = data; } - down(domain->sem); + mutex_lock(domain->lock); for (i = 0, p -= n; i < n; i++, p++, index++) { struct probe **s = &domain->probes[index % 255]; while (*s && (*s)->range < range) @@ -61,7 +62,7 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, p->next = *s; *s = p; } - up(domain->sem); + mutex_unlock(domain->lock); return 0; } @@ -75,7 +76,7 @@ void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range) if (n > 255) n = 255; - down(domain->sem); + mutex_lock(domain->lock); for (i = 0; i < n; i++, index++) { struct probe **s; for (s = &domain->probes[index % 255]; *s; s = &(*s)->next) { @@ -88,7 +89,7 @@ void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range) } } } - up(domain->sem); + mutex_unlock(domain->lock); kfree(found); } @@ -99,7 +100,7 @@ struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index) unsigned long best = ~0UL; retry: - down(domain->sem); + mutex_lock(domain->lock); for (p = domain->probes[MAJOR(dev) % 255]; p; p = p->next) { struct kobject *(*probe)(dev_t, int *, void *); struct module *owner; @@ -120,7 +121,7 @@ retry: module_put(owner); continue; } - up(domain->sem); + mutex_unlock(domain->lock); kobj = probe(dev, index, data); /* Currently ->owner protects _only_ ->probe() itself. */ module_put(owner); @@ -128,11 +129,11 @@ retry: return kobj; goto retry; } - up(domain->sem); + mutex_unlock(domain->lock); return NULL; } -struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem) +struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct mutex *lock) { struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL); struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL); @@ -149,6 +150,6 @@ struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem) base->get = base_probe; for (i = 0; i < 255; i++) p->probes[i] = base; - p->sem = sem; + p->lock = lock; return p; } diff --git a/fs/char_dev.c b/fs/char_dev.c index 21195c481637..5c36345c9bf7 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -19,6 +19,7 @@ #include #include #include +#include #ifdef CONFIG_KMOD #include @@ -28,7 +29,7 @@ static struct kobj_map *cdev_map; #define MAX_PROBE_HASH 255 /* random */ -static DECLARE_MUTEX(chrdevs_lock); +static DEFINE_MUTEX(chrdevs_lock); static struct char_device_struct { struct char_device_struct *next; @@ -88,13 +89,13 @@ out: void *acquire_chrdev_list(void) { - down(&chrdevs_lock); + mutex_lock(&chrdevs_lock); return get_next_chrdev(NULL); } void release_chrdev_list(void *dev) { - up(&chrdevs_lock); + mutex_unlock(&chrdevs_lock); kfree(dev); } @@ -151,7 +152,7 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, memset(cd, 0, sizeof(struct char_device_struct)); - down(&chrdevs_lock); + mutex_lock(&chrdevs_lock); /* temporary */ if (major == 0) { @@ -186,10 +187,10 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, } cd->next = *cp; *cp = cd; - up(&chrdevs_lock); + mutex_unlock(&chrdevs_lock); return cd; out: - up(&chrdevs_lock); + mutex_unlock(&chrdevs_lock); kfree(cd); return ERR_PTR(ret); } @@ -200,7 +201,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct) struct char_device_struct *cd = NULL, **cp; int i = major_to_index(major); - down(&chrdevs_lock); + mutex_lock(&chrdevs_lock); for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next) if ((*cp)->major == major && (*cp)->baseminor == baseminor && @@ -210,7 +211,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct) cd = *cp; *cp = cd->next; } - up(&chrdevs_lock); + mutex_unlock(&chrdevs_lock); return cd; } diff --git a/include/linux/kobj_map.h b/include/linux/kobj_map.h index cbe7d8008042..bafe178a381f 100644 --- a/include/linux/kobj_map.h +++ b/include/linux/kobj_map.h @@ -1,6 +1,6 @@ #ifdef __KERNEL__ -#include +#include typedef struct kobject *kobj_probe_t(dev_t, int *, void *); struct kobj_map; @@ -9,6 +9,6 @@ int kobj_map(struct kobj_map *, dev_t, unsigned long, struct module *, kobj_probe_t *, int (*)(dev_t, void *), void *); void kobj_unmap(struct kobj_map *, dev_t, unsigned long); struct kobject *kobj_lookup(struct kobj_map *, dev_t, int *); -struct kobj_map *kobj_map_init(kobj_probe_t *, struct semaphore *); +struct kobj_map *kobj_map_init(kobj_probe_t *, struct mutex *); #endif -- cgit v1.2.3 From 9f28bb7e1d0188a993403ab39b774785892805e1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 20 Mar 2006 13:17:13 -0800 Subject: [PATCH] add EXPORT_SYMBOL_GPL_FUTURE() This patch adds the ability to mark symbols that will be changed in the future, so that kernel modules that don't include MODULE_LICENSE("GPL") and use the symbols, will be flagged and printed out to the system log. Signed-off-by: Greg Kroah-Hartman --- arch/m68knommu/kernel/vmlinux.lds.S | 10 ++++ arch/v850/kernel/vmlinux.lds.S | 8 ++++ include/asm-generic/vmlinux.lds.h | 14 ++++++ include/linux/module.h | 9 ++++ kernel/module.c | 49 +++++++++++++++++++- scripts/genksyms/keywords.c_shipped | 91 +++++++++++++++++++------------------ scripts/genksyms/keywords.gperf | 1 + 7 files changed, 135 insertions(+), 47 deletions(-) (limited to 'include') diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S index ac9de2661c0b..a331cc90797c 100644 --- a/arch/m68knommu/kernel/vmlinux.lds.S +++ b/arch/m68knommu/kernel/vmlinux.lds.S @@ -269,6 +269,11 @@ SECTIONS { *(__ksymtab_gpl) __stop___ksymtab_gpl = .; + /* Kernel symbol table: GPL-future symbols */ + __start___ksymtab_gpl_future = .; + *(__ksymtab_gpl_future) + __stop___ksymtab_gpl_future = .; + /* Kernel symbol table: Normal symbols */ __start___kcrctab = .; *(__kcrctab) @@ -279,6 +284,11 @@ SECTIONS { *(__kcrctab_gpl) __stop___kcrctab_gpl = .; + /* Kernel symbol table: GPL-future symbols */ + __start___kcrctab_gpl_future = .; + *(__kcrctab_gpl_future) + __stop___kcrctab_gpl_future = .; + /* Kernel symbol table: strings */ *(__ksymtab_strings) diff --git a/arch/v850/kernel/vmlinux.lds.S b/arch/v850/kernel/vmlinux.lds.S index 5be05f47109e..5b2ffcc6e2b2 100644 --- a/arch/v850/kernel/vmlinux.lds.S +++ b/arch/v850/kernel/vmlinux.lds.S @@ -64,6 +64,10 @@ ___start___ksymtab_gpl = .; \ *(__ksymtab_gpl) \ ___stop___ksymtab_gpl = .; \ + /* Kernel symbol table: GPL-future symbols */ \ + ___start___ksymtab_gpl_future = .; \ + *(__ksymtab_gpl_future) \ + ___stop___ksymtab_gpl_future = .; \ /* Kernel symbol table: strings */ \ *(__ksymtab_strings) \ /* Kernel symbol table: Normal symbols */ \ @@ -74,6 +78,10 @@ ___start___kcrctab_gpl = .; \ *(__kcrctab_gpl) \ ___stop___kcrctab_gpl = .; \ + /* Kernel symbol table: GPL-future symbols */ \ + ___start___kcrctab_gpl_future = .; \ + *(__kcrctab_gpl_future) \ + ___stop___kcrctab_gpl_future = .; \ /* Built-in module parameters */ \ . = ALIGN (4) ; \ ___start___param = .; \ diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 35de20cf8fac..9d11550b4818 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -58,6 +58,13 @@ VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \ } \ \ + /* Kernel symbol table: GPL-future-only symbols */ \ + __ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \ + VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .; \ + *(__ksymtab_gpl_future) \ + VMLINUX_SYMBOL(__stop___ksymtab_gpl_future) = .; \ + } \ + \ /* Kernel symbol table: Normal symbols */ \ __kcrctab : AT(ADDR(__kcrctab) - LOAD_OFFSET) { \ VMLINUX_SYMBOL(__start___kcrctab) = .; \ @@ -72,6 +79,13 @@ VMLINUX_SYMBOL(__stop___kcrctab_gpl) = .; \ } \ \ + /* Kernel symbol table: GPL-future-only symbols */ \ + __kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - LOAD_OFFSET) { \ + VMLINUX_SYMBOL(__start___kcrctab_gpl_future) = .; \ + *(__kcrctab_gpl_future) \ + VMLINUX_SYMBOL(__stop___kcrctab_gpl_future) = .; \ + } \ + \ /* Kernel symbol table: strings */ \ __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \ *(__ksymtab_strings) \ diff --git a/include/linux/module.h b/include/linux/module.h index 84d75f3a8aca..a25d5f61548c 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -198,6 +198,9 @@ void *__symbol_get_gpl(const char *symbol); #define EXPORT_SYMBOL_GPL(sym) \ __EXPORT_SYMBOL(sym, "_gpl") +#define EXPORT_SYMBOL_GPL_FUTURE(sym) \ + __EXPORT_SYMBOL(sym, "_gpl_future") + #endif struct module_ref @@ -255,6 +258,11 @@ struct module unsigned int num_gpl_syms; const unsigned long *gpl_crcs; + /* symbols that will be GPL-only in the near future. */ + const struct kernel_symbol *gpl_future_syms; + unsigned int num_gpl_future_syms; + const unsigned long *gpl_future_crcs; + /* Exception table */ unsigned int num_exentries; const struct exception_table_entry *extable; @@ -441,6 +449,7 @@ void module_remove_driver(struct device_driver *); #else /* !CONFIG_MODULES... */ #define EXPORT_SYMBOL(sym) #define EXPORT_SYMBOL_GPL(sym) +#define EXPORT_SYMBOL_GPL_FUTURE(sym) /* Given an address, look for it in the exception tables. */ static inline const struct exception_table_entry * diff --git a/kernel/module.c b/kernel/module.c index 2a892b20d68f..5ca99fbe9f44 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -126,8 +126,11 @@ extern const struct kernel_symbol __start___ksymtab[]; extern const struct kernel_symbol __stop___ksymtab[]; extern const struct kernel_symbol __start___ksymtab_gpl[]; extern const struct kernel_symbol __stop___ksymtab_gpl[]; +extern const struct kernel_symbol __start___ksymtab_gpl_future[]; +extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; extern const unsigned long __start___kcrctab[]; extern const unsigned long __start___kcrctab_gpl[]; +extern const unsigned long __start___kcrctab_gpl_future[]; #ifndef CONFIG_MODVERSIONS #define symversion(base, idx) NULL @@ -172,6 +175,22 @@ static unsigned long __find_symbol(const char *name, return ks->value; } } + ks = lookup_symbol(name, __start___ksymtab_gpl_future, + __stop___ksymtab_gpl_future); + if (ks) { + if (!gplok) { + printk(KERN_WARNING "Symbol %s is being used " + "by a non-GPL module, which will not " + "be allowed in the future\n", name); + printk(KERN_WARNING "Please see the file " + "Documentation/feature-removal-schedule.txt " + "in the kernel source tree for more " + "details.\n"); + } + *crc = symversion(__start___kcrctab_gpl_future, + (ks - __start___ksymtab_gpl_future)); + return ks->value; + } /* Now try modules. */ list_for_each_entry(mod, &modules, list) { @@ -191,6 +210,23 @@ static unsigned long __find_symbol(const char *name, return ks->value; } } + ks = lookup_symbol(name, mod->gpl_future_syms, + (mod->gpl_future_syms + + mod->num_gpl_future_syms)); + if (ks) { + if (!gplok) { + printk(KERN_WARNING "Symbol %s is being used " + "by a non-GPL module, which will not " + "be allowed in the future\n", name); + printk(KERN_WARNING "Please see the file " + "Documentation/feature-removal-schedule.txt " + "in the kernel source tree for more " + "details.\n"); + } + *crc = symversion(mod->gpl_future_crcs, + (ks - mod->gpl_future_syms)); + return ks->value; + } } DEBUGP("Failed to find symbol %s\n", name); return 0; @@ -1546,7 +1582,8 @@ static struct module *load_module(void __user *umod, char *secstrings, *args, *modmagic, *strtab = NULL; unsigned int i, symindex = 0, strindex = 0, setupindex, exindex, exportindex, modindex, obsparmindex, infoindex, gplindex, - crcindex, gplcrcindex, versindex, pcpuindex; + crcindex, gplcrcindex, versindex, pcpuindex, gplfutureindex, + gplfuturecrcindex; long arglen; struct module *mod; long err = 0; @@ -1627,8 +1664,10 @@ static struct module *load_module(void __user *umod, /* Optional sections */ exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab"); gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl"); + gplfutureindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl_future"); crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab"); gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl"); + gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future"); setupindex = find_sec(hdr, sechdrs, secstrings, "__param"); exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table"); obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm"); @@ -1784,10 +1823,16 @@ static struct module *load_module(void __user *umod, mod->gpl_syms = (void *)sechdrs[gplindex].sh_addr; if (gplcrcindex) mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr; + mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size / + sizeof(*mod->gpl_future_syms); + mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr; + if (gplfuturecrcindex) + mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr; #ifdef CONFIG_MODVERSIONS if ((mod->num_syms && !crcindex) || - (mod->num_gpl_syms && !gplcrcindex)) { + (mod->num_gpl_syms && !gplcrcindex) || + (mod->num_gpl_future_syms && !gplfuturecrcindex)) { printk(KERN_WARNING "%s: No versions for exported symbols." " Tainting kernel.\n", mod->name); add_taint(TAINT_FORCED_MODULE); diff --git a/scripts/genksyms/keywords.c_shipped b/scripts/genksyms/keywords.c_shipped index ee4647805c58..d8153f572e40 100644 --- a/scripts/genksyms/keywords.c_shipped +++ b/scripts/genksyms/keywords.c_shipped @@ -52,9 +52,9 @@ is_reserved_hash (register const char *str, register unsigned int len) 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, - 71, 71, 71, 71, 71, 71, 71, 71, 71, 15, - 71, 71, 71, 71, 71, 71, 15, 71, 71, 71, - 10, 71, 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, + 71, 71, 71, 71, 71, 71, 35, 71, 71, 71, + 5, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 71, 0, 71, 5, 5, 0, 10, 20, 71, 25, 71, 71, 20, 0, 20, 30, 25, 71, 10, 5, 0, 20, 15, 71, @@ -84,9 +84,9 @@ is_reserved_word (register const char *str, register unsigned int len) { enum { - TOTAL_KEYWORDS = 41, + TOTAL_KEYWORDS = 42, MIN_WORD_LENGTH = 3, - MAX_WORD_LENGTH = 17, + MAX_WORD_LENGTH = 24, MIN_HASH_VALUE = 3, MAX_HASH_VALUE = 70 }; @@ -94,104 +94,105 @@ is_reserved_word (register const char *str, register unsigned int len) static const struct resword wordlist[] = { {""}, {""}, {""}, -#line 24 "scripts/genksyms/keywords.gperf" +#line 25 "scripts/genksyms/keywords.gperf" {"asm", ASM_KEYW}, {""}, -#line 7 "scripts/genksyms/keywords.gperf" +#line 8 "scripts/genksyms/keywords.gperf" {"__asm", ASM_KEYW}, {""}, -#line 8 "scripts/genksyms/keywords.gperf" +#line 9 "scripts/genksyms/keywords.gperf" {"__asm__", ASM_KEYW}, {""}, -#line 21 "scripts/genksyms/keywords.gperf" +#line 22 "scripts/genksyms/keywords.gperf" {"_restrict", RESTRICT_KEYW}, -#line 50 "scripts/genksyms/keywords.gperf" +#line 51 "scripts/genksyms/keywords.gperf" {"__typeof__", TYPEOF_KEYW}, -#line 9 "scripts/genksyms/keywords.gperf" +#line 10 "scripts/genksyms/keywords.gperf" {"__attribute", ATTRIBUTE_KEYW}, -#line 11 "scripts/genksyms/keywords.gperf" +#line 12 "scripts/genksyms/keywords.gperf" {"__const", CONST_KEYW}, -#line 10 "scripts/genksyms/keywords.gperf" +#line 11 "scripts/genksyms/keywords.gperf" {"__attribute__", ATTRIBUTE_KEYW}, -#line 12 "scripts/genksyms/keywords.gperf" +#line 13 "scripts/genksyms/keywords.gperf" {"__const__", CONST_KEYW}, -#line 16 "scripts/genksyms/keywords.gperf" +#line 17 "scripts/genksyms/keywords.gperf" {"__signed__", SIGNED_KEYW}, -#line 42 "scripts/genksyms/keywords.gperf" +#line 43 "scripts/genksyms/keywords.gperf" {"static", STATIC_KEYW}, {""}, -#line 15 "scripts/genksyms/keywords.gperf" +#line 16 "scripts/genksyms/keywords.gperf" {"__signed", SIGNED_KEYW}, -#line 30 "scripts/genksyms/keywords.gperf" +#line 31 "scripts/genksyms/keywords.gperf" {"char", CHAR_KEYW}, {""}, -#line 43 "scripts/genksyms/keywords.gperf" +#line 44 "scripts/genksyms/keywords.gperf" {"struct", STRUCT_KEYW}, -#line 22 "scripts/genksyms/keywords.gperf" - {"__restrict__", RESTRICT_KEYW}, #line 23 "scripts/genksyms/keywords.gperf" + {"__restrict__", RESTRICT_KEYW}, +#line 24 "scripts/genksyms/keywords.gperf" {"restrict", RESTRICT_KEYW}, -#line 33 "scripts/genksyms/keywords.gperf" +#line 34 "scripts/genksyms/keywords.gperf" {"enum", ENUM_KEYW}, -#line 17 "scripts/genksyms/keywords.gperf" +#line 18 "scripts/genksyms/keywords.gperf" {"__volatile", VOLATILE_KEYW}, -#line 34 "scripts/genksyms/keywords.gperf" +#line 35 "scripts/genksyms/keywords.gperf" {"extern", EXTERN_KEYW}, -#line 18 "scripts/genksyms/keywords.gperf" +#line 19 "scripts/genksyms/keywords.gperf" {"__volatile__", VOLATILE_KEYW}, -#line 37 "scripts/genksyms/keywords.gperf" +#line 38 "scripts/genksyms/keywords.gperf" {"int", INT_KEYW}, - {""}, -#line 31 "scripts/genksyms/keywords.gperf" - {"const", CONST_KEYW}, +#line 7 "scripts/genksyms/keywords.gperf" + {"EXPORT_SYMBOL_GPL_FUTURE", EXPORT_SYMBOL_KEYW}, #line 32 "scripts/genksyms/keywords.gperf" + {"const", CONST_KEYW}, +#line 33 "scripts/genksyms/keywords.gperf" {"double", DOUBLE_KEYW}, {""}, -#line 13 "scripts/genksyms/keywords.gperf" +#line 14 "scripts/genksyms/keywords.gperf" {"__inline", INLINE_KEYW}, -#line 29 "scripts/genksyms/keywords.gperf" +#line 30 "scripts/genksyms/keywords.gperf" {"auto", AUTO_KEYW}, -#line 14 "scripts/genksyms/keywords.gperf" +#line 15 "scripts/genksyms/keywords.gperf" {"__inline__", INLINE_KEYW}, -#line 41 "scripts/genksyms/keywords.gperf" +#line 42 "scripts/genksyms/keywords.gperf" {"signed", SIGNED_KEYW}, {""}, -#line 46 "scripts/genksyms/keywords.gperf" +#line 47 "scripts/genksyms/keywords.gperf" {"unsigned", UNSIGNED_KEYW}, {""}, -#line 40 "scripts/genksyms/keywords.gperf" +#line 41 "scripts/genksyms/keywords.gperf" {"short", SHORT_KEYW}, -#line 49 "scripts/genksyms/keywords.gperf" +#line 50 "scripts/genksyms/keywords.gperf" {"typeof", TYPEOF_KEYW}, -#line 44 "scripts/genksyms/keywords.gperf" +#line 45 "scripts/genksyms/keywords.gperf" {"typedef", TYPEDEF_KEYW}, -#line 48 "scripts/genksyms/keywords.gperf" +#line 49 "scripts/genksyms/keywords.gperf" {"volatile", VOLATILE_KEYW}, {""}, -#line 35 "scripts/genksyms/keywords.gperf" +#line 36 "scripts/genksyms/keywords.gperf" {"float", FLOAT_KEYW}, {""}, {""}, -#line 39 "scripts/genksyms/keywords.gperf" +#line 40 "scripts/genksyms/keywords.gperf" {"register", REGISTER_KEYW}, -#line 47 "scripts/genksyms/keywords.gperf" +#line 48 "scripts/genksyms/keywords.gperf" {"void", VOID_KEYW}, {""}, -#line 36 "scripts/genksyms/keywords.gperf" +#line 37 "scripts/genksyms/keywords.gperf" {"inline", INLINE_KEYW}, {""}, #line 5 "scripts/genksyms/keywords.gperf" {"EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW}, {""}, -#line 20 "scripts/genksyms/keywords.gperf" +#line 21 "scripts/genksyms/keywords.gperf" {"_Bool", BOOL_KEYW}, {""}, #line 6 "scripts/genksyms/keywords.gperf" {"EXPORT_SYMBOL_GPL", EXPORT_SYMBOL_KEYW}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 38 "scripts/genksyms/keywords.gperf" +#line 39 "scripts/genksyms/keywords.gperf" {"long", LONG_KEYW}, {""}, {""}, {""}, {""}, {""}, -#line 45 "scripts/genksyms/keywords.gperf" +#line 46 "scripts/genksyms/keywords.gperf" {"union", UNION_KEYW} }; diff --git a/scripts/genksyms/keywords.gperf b/scripts/genksyms/keywords.gperf index b6bec765996e..c75e0c8d8f0c 100644 --- a/scripts/genksyms/keywords.gperf +++ b/scripts/genksyms/keywords.gperf @@ -4,6 +4,7 @@ struct resword { const char *name; int token; } %% EXPORT_SYMBOL, EXPORT_SYMBOL_KEYW EXPORT_SYMBOL_GPL, EXPORT_SYMBOL_KEYW +EXPORT_SYMBOL_GPL_FUTURE, EXPORT_SYMBOL_KEYW __asm, ASM_KEYW __asm__, ASM_KEYW __attribute, ATTRIBUTE_KEYW -- cgit v1.2.3 From 03e88ae1b13dfdc8bbaa59b8198e1ca53aad12ac Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 16 Feb 2006 13:50:23 -0800 Subject: [PATCH] fix module sysfs files reference counting The module files, refcnt, version, and srcversion did not properly increment the owner's module reference count, allowing the modules to be removed while the files were open, causing oopses. This patch fixes this, and also fixes the problem that the version and srcversion files were not showing up, unless CONFIG_MODULE_UNLOAD was enabled, which is not correct. Cc: Nathan Lynch Signed-off-by: Greg Kroah-Hartman --- include/linux/module.h | 1 + kernel/module.c | 77 ++++++++++++++++++++------------------------------ kernel/params.c | 10 ------- 3 files changed, 32 insertions(+), 56 deletions(-) (limited to 'include') diff --git a/include/linux/module.h b/include/linux/module.h index a25d5f61548c..70bd843c71cb 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -245,6 +245,7 @@ struct module /* Sysfs stuff. */ struct module_kobject mkobj; struct module_param_attrs *param_attrs; + struct module_attribute *modinfo_attrs; const char *version; const char *srcversion; diff --git a/kernel/module.c b/kernel/module.c index 5ca99fbe9f44..77764f22f021 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -429,7 +429,6 @@ static inline void percpu_modcopy(void *pcpudst, const void *src, } #endif /* CONFIG_SMP */ -#ifdef CONFIG_MODULE_UNLOAD #define MODINFO_ATTR(field) \ static void setup_modinfo_##field(struct module *mod, const char *s) \ { \ @@ -461,12 +460,7 @@ static struct module_attribute modinfo_##field = { \ MODINFO_ATTR(version); MODINFO_ATTR(srcversion); -static struct module_attribute *modinfo_attrs[] = { - &modinfo_version, - &modinfo_srcversion, - NULL, -}; - +#ifdef CONFIG_MODULE_UNLOAD /* Init the unload section of the module. */ static void module_unload_init(struct module *mod) { @@ -781,6 +775,15 @@ static inline void module_unload_init(struct module *mod) } #endif /* CONFIG_MODULE_UNLOAD */ +static struct module_attribute *modinfo_attrs[] = { + &modinfo_version, + &modinfo_srcversion, +#ifdef CONFIG_MODULE_UNLOAD + &refcnt, +#endif + NULL, +}; + #ifdef CONFIG_OBSOLETE_MODPARM /* Bounds checking done below */ static int obsparm_copy_string(const char *val, struct kernel_param *kp) @@ -1106,37 +1109,28 @@ static inline void remove_sect_attrs(struct module *mod) } #endif /* CONFIG_KALLSYMS */ - -#ifdef CONFIG_MODULE_UNLOAD -static inline int module_add_refcnt_attr(struct module *mod) -{ - return sysfs_create_file(&mod->mkobj.kobj, &refcnt.attr); -} -static void module_remove_refcnt_attr(struct module *mod) -{ - return sysfs_remove_file(&mod->mkobj.kobj, &refcnt.attr); -} -#else -static inline int module_add_refcnt_attr(struct module *mod) -{ - return 0; -} -static void module_remove_refcnt_attr(struct module *mod) -{ -} -#endif - -#ifdef CONFIG_MODULE_UNLOAD static int module_add_modinfo_attrs(struct module *mod) { struct module_attribute *attr; + struct module_attribute *temp_attr; int error = 0; int i; + mod->modinfo_attrs = kzalloc((sizeof(struct module_attribute) * + (ARRAY_SIZE(modinfo_attrs) + 1)), + GFP_KERNEL); + if (!mod->modinfo_attrs) + return -ENOMEM; + + temp_attr = mod->modinfo_attrs; for (i = 0; (attr = modinfo_attrs[i]) && !error; i++) { if (!attr->test || - (attr->test && attr->test(mod))) - error = sysfs_create_file(&mod->mkobj.kobj,&attr->attr); + (attr->test && attr->test(mod))) { + memcpy(temp_attr, attr, sizeof(*temp_attr)); + temp_attr->attr.owner = mod; + error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr); + ++temp_attr; + } } return error; } @@ -1146,12 +1140,16 @@ static void module_remove_modinfo_attrs(struct module *mod) struct module_attribute *attr; int i; - for (i = 0; (attr = modinfo_attrs[i]); i++) { + for (i = 0; (attr = &mod->modinfo_attrs[i]); i++) { + /* pick a field to test for end of list */ + if (!attr->attr.name) + break; sysfs_remove_file(&mod->mkobj.kobj,&attr->attr); - attr->free(mod); + if (attr->free) + attr->free(mod); } + kfree(mod->modinfo_attrs); } -#endif static int mod_sysfs_setup(struct module *mod, struct kernel_param *kparam, @@ -1169,19 +1167,13 @@ static int mod_sysfs_setup(struct module *mod, if (err) goto out; - err = module_add_refcnt_attr(mod); - if (err) - goto out_unreg; - err = module_param_sysfs_setup(mod, kparam, num_params); if (err) goto out_unreg; -#ifdef CONFIG_MODULE_UNLOAD err = module_add_modinfo_attrs(mod); if (err) goto out_unreg; -#endif return 0; @@ -1193,10 +1185,7 @@ out: static void mod_kobject_remove(struct module *mod) { -#ifdef CONFIG_MODULE_UNLOAD module_remove_modinfo_attrs(mod); -#endif - module_remove_refcnt_attr(mod); module_param_sysfs_remove(mod); kobject_unregister(&mod->mkobj.kobj); @@ -1474,7 +1463,6 @@ static char *get_modinfo(Elf_Shdr *sechdrs, return NULL; } -#ifdef CONFIG_MODULE_UNLOAD static void setup_modinfo(struct module *mod, Elf_Shdr *sechdrs, unsigned int infoindex) { @@ -1489,7 +1477,6 @@ static void setup_modinfo(struct module *mod, Elf_Shdr *sechdrs, attr->attr.name)); } } -#endif #ifdef CONFIG_KALLSYMS int is_exported(const char *name, const struct module *mod) @@ -1803,10 +1790,8 @@ static struct module *load_module(void __user *umod, if (strcmp(mod->name, "driverloader") == 0) add_taint(TAINT_PROPRIETARY_MODULE); -#ifdef CONFIG_MODULE_UNLOAD /* Set up MODINFO_ATTR fields */ setup_modinfo(mod, sechdrs, infoindex); -#endif /* Fix up syms, so that st_value is a pointer to location. */ err = simplify_symbols(sechdrs, symindex, strtab, versindex, pcpuindex, diff --git a/kernel/params.c b/kernel/params.c index c76ad25e6a21..a29150582310 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -638,13 +638,8 @@ static ssize_t module_attr_show(struct kobject *kobj, if (!attribute->show) return -EIO; - if (!try_module_get(mk->mod)) - return -ENODEV; - ret = attribute->show(attribute, mk->mod, buf); - module_put(mk->mod); - return ret; } @@ -662,13 +657,8 @@ static ssize_t module_attr_store(struct kobject *kobj, if (!attribute->store) return -EIO; - if (!try_module_get(mk->mod)) - return -ENODEV; - ret = attribute->store(attribute, mk->mod, buf, len); - module_put(mk->mod); - return ret; } -- cgit v1.2.3 From 4f2928d0a439553f0288d9483faf417430629635 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Fri, 24 Feb 2006 11:05:45 +0100 Subject: [PATCH] Driver core: add macros notice(), dev_notice() Both usb.h and device.h have collections of convenience macros for printk() with the KERN_ERR, KERN_WARNING, and KERN_NOTICE severity levels. This patch adds macros for the KERN_NOTICE level which was so far uncatered for. These macros already exist privately in drivers/isdn/gigaset/gigaset.h (currently in the process of being submitted for the kernel tree) but they really belong with their brothers and sisters in include/linux/{device,usb}.h. Signed-off-by: Tilman Schmidt Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index 58df18d9cd3e..5b595fdfb672 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -424,6 +424,8 @@ extern void firmware_unregister(struct subsystem *); dev_printk(KERN_INFO , dev , format , ## arg) #define dev_warn(dev, format, arg...) \ dev_printk(KERN_WARNING , dev , format , ## arg) +#define dev_notice(dev, format, arg...) \ + dev_printk(KERN_NOTICE , dev , format , ## arg) /* Create alias, so I can be autoloaded. */ #define MODULE_ALIAS_CHARDEV(major,minor) \ -- cgit v1.2.3 From 22f98c0cd7e003b896ee52ded945081307118745 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 4 Mar 2006 13:15:31 +0100 Subject: [PATCH] Kobject: kobject.h: fix a typo It shouldn't cause real harm, but it hurts my eyes. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- include/linux/kobject.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/kobject.h b/include/linux/kobject.h index c374b5fa8d3b..7ece63f8abbd 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -255,7 +255,7 @@ struct subsys_attribute { extern int subsys_create_file(struct subsystem * , struct subsys_attribute *); extern void subsys_remove_file(struct subsystem * , struct subsys_attribute *); -#if defined(CONFIG_HOTPLUG) & defined(CONFIG_NET) +#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET) void kobject_uevent(struct kobject *kobj, enum kobject_action action); int add_uevent_var(char **envp, int num_envp, int *cur_index, -- cgit v1.2.3 From dd308bc355a1aa4f202fe9a3133b6c676cb9606c Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 7 Mar 2006 21:41:59 +1100 Subject: [PATCH] debugfs: Add debugfs_create_blob() helper for exporting binary data I wanted to export a binary blob via debugfs, and although it was pretty easy it seems like it'd be easier if there was a helper for it. It's a pity we need the wrapper struct but I can't see a cleaner way to do it. Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/file.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/debugfs.h | 15 +++++++++++++++ 2 files changed, 61 insertions(+) (limited to 'include') diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index d575452cd9f7..40c4fc973fad 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -251,3 +251,49 @@ struct dentry *debugfs_create_bool(const char *name, mode_t mode, } EXPORT_SYMBOL_GPL(debugfs_create_bool); +static ssize_t read_file_blob(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct debugfs_blob_wrapper *blob = file->private_data; + return simple_read_from_buffer(user_buf, count, ppos, blob->data, + blob->size); +} + +static struct file_operations fops_blob = { + .read = read_file_blob, + .open = default_open, +}; + +/** + * debugfs_create_blob - create a file in the debugfs filesystem that is + * used to read and write a binary blob. + * + * @name: a pointer to a string containing the name of the file to create. + * @mode: the permission that the file should have + * @parent: a pointer to the parent dentry for this file. This should be a + * directory dentry if set. If this paramater is NULL, then the + * file will be created in the root of the debugfs filesystem. + * @blob: a pointer to a struct debugfs_blob_wrapper which contains a pointer + * to the blob data and the size of the data. + * + * This function creates a file in debugfs with the given name that exports + * @blob->data as a binary blob. If the @mode variable is so set it can be + * read from. Writing is not supported. + * + * This function will return a pointer to a dentry if it succeeds. This + * pointer must be passed to the debugfs_remove() function when the file is + * to be removed (no automatic cleanup happens if your module is unloaded, + * you are responsible here.) If an error occurs, NULL will be returned. + * + * If debugfs is not enabled in the kernel, the value -ENODEV will be + * returned. It is not wise to check for this value, but rather, check for + * NULL or !NULL instead as to eliminate the need for #ifdef in the calling + * code. + */ +struct dentry *debugfs_create_blob(const char *name, mode_t mode, + struct dentry *parent, + struct debugfs_blob_wrapper *blob) +{ + return debugfs_create_file(name, mode, parent, blob, &fops_blob); +} +EXPORT_SYMBOL_GPL(debugfs_create_blob); diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index a5fa6a6eede8..4b0428e335be 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -21,6 +21,11 @@ struct file_operations; +struct debugfs_blob_wrapper { + void *data; + unsigned long size; +}; + #if defined(CONFIG_DEBUG_FS) struct dentry *debugfs_create_file(const char *name, mode_t mode, struct dentry *parent, void *data, @@ -39,6 +44,9 @@ struct dentry *debugfs_create_u32(const char *name, mode_t mode, struct dentry *debugfs_create_bool(const char *name, mode_t mode, struct dentry *parent, u32 *value); +struct dentry *debugfs_create_blob(const char *name, mode_t mode, + struct dentry *parent, + struct debugfs_blob_wrapper *blob); #else #include @@ -94,6 +102,13 @@ static inline struct dentry *debugfs_create_bool(const char *name, mode_t mode, return ERR_PTR(-ENODEV); } +static inline struct dentry *debugfs_create_blob(const char *name, mode_t mode, + struct dentry *parent, + struct debugfs_blob_wrapper *blob) +{ + return ERR_PTR(-ENODEV); +} + #endif #endif -- cgit v1.2.3 From 7423172a50968de1905a61413c52bb070a62f5ce Mon Sep 17 00:00:00 2001 From: Jun'ichi Nomura Date: Mon, 13 Mar 2006 17:14:25 -0500 Subject: [PATCH] kobject_add_dir Adding kobject_add_dir() function which creates a subdirectory for a given kobject. Signed-off-by: Jun'ichi Nomura Signed-off-by: Greg Kroah-Hartman --- include/linux/kobject.h | 2 ++ lib/kobject.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) (limited to 'include') diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 7ece63f8abbd..4cb1214ec290 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -80,6 +80,8 @@ extern void kobject_unregister(struct kobject *); extern struct kobject * kobject_get(struct kobject *); extern void kobject_put(struct kobject *); +extern struct kobject *kobject_add_dir(struct kobject *, const char *); + extern char * kobject_get_path(struct kobject *, gfp_t); struct kobj_type { diff --git a/lib/kobject.c b/lib/kobject.c index 36668c8c3ea1..25204a41a9b0 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -385,6 +385,44 @@ void kobject_put(struct kobject * kobj) } +static void dir_release(struct kobject *kobj) +{ + kfree(kobj); +} + +static struct kobj_type dir_ktype = { + .release = dir_release, + .sysfs_ops = NULL, + .default_attrs = NULL, +}; + +/** + * kobject_add_dir - add sub directory of object. + * @parent: object in which a directory is created. + * @name: directory name. + * + * Add a plain directory object as child of given object. + */ +struct kobject *kobject_add_dir(struct kobject *parent, const char *name) +{ + struct kobject *k; + + if (!parent) + return NULL; + + k = kzalloc(sizeof(*k), GFP_KERNEL); + if (!k) + return NULL; + + k->parent = parent; + k->ktype = &dir_ktype; + kobject_set_name(k, name); + kobject_register(k); + + return k; +} +EXPORT_SYMBOL_GPL(kobject_add_dir); + /** * kset_init - initialize a kset for use * @k: kset -- cgit v1.2.3 From a29d642a4aa99c5234314ab2523281139226c231 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 7 Mar 2006 23:53:25 -0800 Subject: [PATCH] get_cpu_sysdev() signedness fix Doing (int < NR_CPUS) doesn't dtrt if it's negative.. Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/base/cpu.c | 2 +- include/linux/cpu.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 07a7f97e1de9..29f3d7504da1 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -141,7 +141,7 @@ int __devinit register_cpu(struct cpu *cpu, int num, struct node *root) return error; } -struct sys_device *get_cpu_sysdev(int cpu) +struct sys_device *get_cpu_sysdev(unsigned cpu) { if (cpu < NR_CPUS) return cpu_sys_devices[cpu]; diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 0ed1d4853c69..d612b89dce33 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -32,7 +32,7 @@ struct cpu { }; extern int register_cpu(struct cpu *, int, struct node *); -extern struct sys_device *get_cpu_sysdev(int cpu); +extern struct sys_device *get_cpu_sysdev(unsigned cpu); #ifdef CONFIG_HOTPLUG_CPU extern void unregister_cpu(struct cpu *, struct node *); #endif -- cgit v1.2.3 From e266a12492f7ca9142882710bff92e902b7c95c8 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 8 Nov 2005 21:05:43 +0100 Subject: [PATCH] USB: drivers/usb/core/message.c: make usb_get_string() static After the removal of usb-midi.c, there's no longer any external user of usb_get_string(). Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 5 ++--- include/linux/usb.h | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 7135e542679d..2f6009b0cffc 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -631,8 +631,8 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char * Returns the number of bytes received on success, or else the status code * returned by the underlying usb_control_msg() call. */ -int usb_get_string(struct usb_device *dev, unsigned short langid, - unsigned char index, void *buf, int size) +static int usb_get_string(struct usb_device *dev, unsigned short langid, + unsigned char index, void *buf, int size) { int i; int result; @@ -1488,7 +1488,6 @@ EXPORT_SYMBOL(usb_sg_wait); // synchronous control message convenience routines EXPORT_SYMBOL(usb_get_descriptor); EXPORT_SYMBOL(usb_get_status); -EXPORT_SYMBOL(usb_get_string); EXPORT_SYMBOL(usb_string); // synchronous calls that also maintain usbcore state diff --git a/include/linux/usb.h b/include/linux/usb.h index 827cc6de5f5c..130d125fda12 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1018,8 +1018,6 @@ extern int usb_get_descriptor(struct usb_device *dev, unsigned char desctype, unsigned char descindex, void *buf, int size); extern int usb_get_status(struct usb_device *dev, int type, int target, void *data); -extern int usb_get_string(struct usb_device *dev, - unsigned short langid, unsigned char index, void *buf, int size); extern int usb_string(struct usb_device *dev, int index, char *buf, size_t size); -- cgit v1.2.3 From 80cb9aee01245b38325dd84f1359b14a3f01f10d Mon Sep 17 00:00:00 2001 From: Randy Vinson Date: Fri, 20 Jan 2006 13:53:38 -0800 Subject: [PATCH] USB: EHCI for Freescale 83xx Adding a Host Mode USB driver for the Freescale 83xx. This driver supports both the Dual-Role (DR) controller and the Multi-Port-Host (MPH) controller present in the Freescale MPC8349. It has been tested with the MPC8349CDS reference system. This driver depends on platform support code for setting up the pins on the device package in a manner appropriate for the board in use. Note that this patch requires selecting the EHCI controller option under the USB Host menu. Signed-off-by: Randy Vinson Signed-off-by: Greg Kroah-Hartman --- drivers/usb/Kconfig | 1 + drivers/usb/host/Kconfig | 2 +- drivers/usb/host/ehci-fsl.c | 357 ++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/ehci-fsl.h | 37 +++++ drivers/usb/host/ehci-hcd.c | 8 +- include/linux/fsl_devices.h | 27 ++++ 6 files changed, 430 insertions(+), 2 deletions(-) create mode 100644 drivers/usb/host/ehci-fsl.c create mode 100644 drivers/usb/host/ehci-fsl.h (limited to 'include') diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 85dacc92545a..7772e28a303f 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -11,6 +11,7 @@ config USB_ARCH_HAS_HCD boolean default y if USB_ARCH_HAS_OHCI default y if ARM # SL-811 + default y if PPC_83xx default PCI # many non-PCI SOC chips embed OHCI diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index be3fd9bce573..a45293673906 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -6,7 +6,7 @@ comment "USB Host Controller Drivers" config USB_EHCI_HCD tristate "EHCI HCD (USB 2.0) support" - depends on USB && PCI + depends on USB && (PCI || PPC_83xx) ---help--- The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c new file mode 100644 index 000000000000..c6012d6cd527 --- /dev/null +++ b/drivers/usb/host/ehci-fsl.c @@ -0,0 +1,357 @@ +/* + * (C) Copyright David Brownell 2000-2002 + * Copyright (c) 2005 MontaVista Software + * + * 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. 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. + * + * Ported to 834x by Randy Vinson using code provided + * by Hunter Wu. + */ + +#include +#include + +#include "ehci-fsl.h" + +/* FIXME: Power Managment is un-ported so temporarily disable it */ +#undef CONFIG_PM + +/* PCI-based HCs are common, but plenty of non-PCI HCs are used too */ + +/* configure so an HC device and id are always provided */ +/* always called with process context; sleeping is OK */ + +/** + * usb_hcd_fsl_probe - initialize FSL-based HCDs + * @drvier: Driver to be used for this HCD + * @pdev: USB Host Controller being probed + * Context: !in_interrupt() + * + * Allocates basic resources for this USB host controller. + * + */ +int usb_hcd_fsl_probe(const struct hc_driver *driver, + struct platform_device *pdev) +{ + struct fsl_usb2_platform_data *pdata; + struct usb_hcd *hcd; + struct resource *res; + int irq; + int retval; + unsigned int temp; + + pr_debug("initializing FSL-SOC USB Controller\n"); + + /* Need platform data for setup */ + pdata = (struct fsl_usb2_platform_data *)pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, + "No platform data for %s.\n", pdev->dev.bus_id); + return -ENODEV; + } + + /* + * This is a host mode driver, verify that we're supposed to be + * in host mode. + */ + if (!((pdata->operating_mode == FSL_USB2_DR_HOST) || + (pdata->operating_mode == FSL_USB2_MPH_HOST))) { + dev_err(&pdev->dev, + "Non Host Mode configured for %s. Wrong driver linked.\n", + pdev->dev.bus_id); + return -ENODEV; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(&pdev->dev, + "Found HC with no IRQ. Check %s setup!\n", + pdev->dev.bus_id); + return -ENODEV; + } + irq = res->start; + + hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id); + if (!hcd) { + retval = -ENOMEM; + goto err1; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, + "Found HC with no register addr. Check %s setup!\n", + pdev->dev.bus_id); + retval = -ENODEV; + goto err2; + } + hcd->rsrc_start = res->start; + hcd->rsrc_len = res->end - res->start + 1; + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, + driver->description)) { + dev_dbg(&pdev->dev, "controller already in use\n"); + retval = -EBUSY; + goto err2; + } + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + + if (hcd->regs == NULL) { + dev_dbg(&pdev->dev, "error mapping memory\n"); + retval = -EFAULT; + goto err3; + } + + /* Enable USB controller */ + temp = in_be32(hcd->regs + 0x500); + out_be32(hcd->regs + 0x500, temp | 0x4); + + /* Set to Host mode */ + temp = in_le32(hcd->regs + 0x1a8); + out_le32(hcd->regs + 0x1a8, temp | 0x3); + + retval = usb_add_hcd(hcd, irq, SA_SHIRQ); + if (retval != 0) + goto err4; + return retval; + + err4: + iounmap(hcd->regs); + err3: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + err2: + usb_put_hcd(hcd); + err1: + dev_err(&pdev->dev, "init %s fail, %d\n", pdev->dev.bus_id, retval); + return retval; +} + +/* may be called without controller electrically present */ +/* may be called with controller, bus, and devices active */ + +/** + * usb_hcd_fsl_remove - shutdown processing for FSL-based HCDs + * @dev: USB Host Controller being removed + * Context: !in_interrupt() + * + * Reverses the effect of usb_hcd_fsl_probe(). + * + */ +void usb_hcd_fsl_remove(struct usb_hcd *hcd, struct platform_device *pdev) +{ + usb_remove_hcd(hcd); + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + usb_put_hcd(hcd); +} + +static void mpc83xx_setup_phy(struct ehci_hcd *ehci, + enum fsl_usb2_phy_modes phy_mode, + unsigned int port_offset) +{ + u32 portsc = readl(&ehci->regs->port_status[port_offset]); + portsc &= ~PORT_PTS_MSK; + switch (phy_mode) { + case FSL_USB2_PHY_ULPI: + portsc |= PORT_PTS_ULPI; + break; + case FSL_USB2_PHY_SERIAL: + portsc |= PORT_PTS_SERIAL; + break; + case FSL_USB2_PHY_UTMI_WIDE: + portsc |= PORT_PTS_PTW; + /* fall through */ + case FSL_USB2_PHY_UTMI: + portsc |= PORT_PTS_UTMI; + break; + case FSL_USB2_PHY_NONE: + break; + } + writel(portsc, &ehci->regs->port_status[port_offset]); +} + +static void mpc83xx_usb_setup(struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + struct fsl_usb2_platform_data *pdata; + void __iomem *non_ehci = hcd->regs; + + pdata = + (struct fsl_usb2_platform_data *)hcd->self.controller-> + platform_data; + /* Enable PHY interface in the control reg. */ + out_be32(non_ehci + FSL_SOC_USB_CTRL, 0x00000004); + out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b); + + if (pdata->operating_mode == FSL_USB2_DR_HOST) + mpc83xx_setup_phy(ehci, pdata->phy_mode, 0); + + if (pdata->operating_mode == FSL_USB2_MPH_HOST) { + if (pdata->port_enables & FSL_USB2_PORT0_ENABLED) + mpc83xx_setup_phy(ehci, pdata->phy_mode, 0); + if (pdata->port_enables & FSL_USB2_PORT1_ENABLED) + mpc83xx_setup_phy(ehci, pdata->phy_mode, 1); + } + + /* put controller in host mode. */ + writel(0x00000003, non_ehci + FSL_SOC_USB_USBMODE); + out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c); + out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040); + out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); +} + +/* called after powerup, by probe or system-pm "wakeup" */ +static int ehci_fsl_reinit(struct ehci_hcd *ehci) +{ + mpc83xx_usb_setup(ehci_to_hcd(ehci)); + ehci_port_power(ehci, 0); + + return 0; +} + +/* called during probe() after chip reset completes */ +static int ehci_fsl_setup(struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + int retval; + + /* EHCI registers start at offset 0x100 */ + ehci->caps = hcd->regs + 0x100; + ehci->regs = hcd->regs + 0x100 + + HC_LENGTH(readl(&ehci->caps->hc_capbase)); + dbg_hcs_params(ehci, "reset"); + dbg_hcc_params(ehci, "reset"); + + /* cache this readonly data; minimize chip reads */ + ehci->hcs_params = readl(&ehci->caps->hcs_params); + + retval = ehci_halt(ehci); + if (retval) + return retval; + + /* data structure init */ + retval = ehci_init(hcd); + if (retval) + return retval; + + ehci->is_tdi_rh_tt = 1; + + ehci->sbrn = 0x20; + + ehci_reset(ehci); + + retval = ehci_fsl_reinit(ehci); + return retval; +} + +static const struct hc_driver ehci_fsl_hc_driver = { + .description = hcd_name, + .product_desc = "Freescale On-Chip EHCI Host Controller", + .hcd_priv_size = sizeof(struct ehci_hcd), + + /* + * generic hardware linkage + */ + .irq = ehci_irq, + .flags = HCD_USB2, + + /* + * basic lifecycle operations + */ + .reset = ehci_fsl_setup, + .start = ehci_run, +#ifdef CONFIG_PM + .suspend = ehci_bus_suspend, + .resume = ehci_bus_resume, +#endif + .stop = ehci_stop, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ehci_urb_enqueue, + .urb_dequeue = ehci_urb_dequeue, + .endpoint_disable = ehci_endpoint_disable, + + /* + * scheduling support + */ + .get_frame_number = ehci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ehci_hub_status_data, + .hub_control = ehci_hub_control, + .bus_suspend = ehci_bus_suspend, + .bus_resume = ehci_bus_resume, +}; + +static int ehci_fsl_drv_probe(struct platform_device *pdev) +{ + if (usb_disabled()) + return -ENODEV; + + return usb_hcd_fsl_probe(&ehci_fsl_hc_driver, pdev); +} + +static int ehci_fsl_drv_remove(struct platform_device *pdev) +{ + struct usb_hcd *hcd = platform_get_drvdata(pdev); + + usb_hcd_fsl_remove(hcd, pdev); + + return 0; +} + +static struct platform_driver ehci_fsl_dr_driver = { + .probe = ehci_fsl_drv_probe, + .remove = ehci_fsl_drv_remove, + .driver = { + .name = "fsl-usb2-dr", + }, +}; + +static struct platform_driver ehci_fsl_mph_driver = { + .probe = ehci_fsl_drv_probe, + .remove = ehci_fsl_drv_remove, + .driver = { + .name = "fsl-usb2-mph", + }, +}; + +static int __init ehci_fsl_init(void) +{ + int retval; + + pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", + hcd_name, + sizeof(struct ehci_qh), sizeof(struct ehci_qtd), + sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); + + retval = platform_driver_register(&ehci_fsl_dr_driver); + if (retval) + return retval; + + return platform_driver_register(&ehci_fsl_mph_driver); +} + +static void __exit ehci_fsl_cleanup(void) +{ + platform_driver_unregister(&ehci_fsl_mph_driver); + platform_driver_unregister(&ehci_fsl_dr_driver); +} + +module_init(ehci_fsl_init); +module_exit(ehci_fsl_cleanup); diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h new file mode 100644 index 000000000000..caac0d1967d0 --- /dev/null +++ b/drivers/usb/host/ehci-fsl.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2005 freescale semiconductor + * Copyright (c) 2005 MontaVista Software + * + * 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. 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. + */ +#ifndef _EHCI_FSL_H +#define _EHCI_FSL_H + +/* offsets for the non-ehci registers in the FSL SOC USB controller */ +#define FSL_SOC_USB_ULPIVP 0x170 +#define FSL_SOC_USB_PORTSC1 0x184 +#define PORT_PTS_MSK (3<<30) +#define PORT_PTS_UTMI (0<<30) +#define PORT_PTS_ULPI (2<<30) +#define PORT_PTS_SERIAL (3<<30) +#define PORT_PTS_PTW (1<<28) +#define FSL_SOC_USB_PORTSC2 0x188 +#define FSL_SOC_USB_USBMODE 0x1a8 +#define FSL_SOC_USB_SNOOP1 0x400 /* NOTE: big-endian */ +#define FSL_SOC_USB_SNOOP2 0x404 /* NOTE: big-endian */ +#define FSL_SOC_USB_AGECNTTHRSH 0x408 /* NOTE: big-endian */ +#define FSL_SOC_USB_SICTRL 0x40c /* NOTE: big-endian */ +#define FSL_SOC_USB_PRICTRL 0x410 /* NOTE: big-endian */ +#define FSL_SOC_USB_CTRL 0x500 /* NOTE: big-endian */ +#endif /* _EHCI_FSL_H */ diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 9dd3d14c64f3..8730babb5771 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -891,6 +891,12 @@ MODULE_LICENSE ("GPL"); #include "ehci-pci.c" #endif -#if !defined(CONFIG_PCI) +#ifdef CONFIG_PPC_83xx +#include "ehci-fsl.c" +#endif + +#if !(defined(CONFIG_PCI) || \ + defined(CONFIG_PPC_83xx) \ + ) #error "missing bus glue for ehci-hcd" #endif diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index a9f1cfd096ff..a3a0e078f79d 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h @@ -83,5 +83,32 @@ struct fsl_i2c_platform_data { #define FSL_I2C_DEV_SEPARATE_DFSRR 0x00000001 #define FSL_I2C_DEV_CLOCK_5200 0x00000002 + +enum fsl_usb2_operating_modes { + FSL_USB2_MPH_HOST, + FSL_USB2_DR_HOST, + FSL_USB2_DR_DEVICE, + FSL_USB2_DR_OTG, +}; + +enum fsl_usb2_phy_modes { + FSL_USB2_PHY_NONE, + FSL_USB2_PHY_ULPI, + FSL_USB2_PHY_UTMI, + FSL_USB2_PHY_UTMI_WIDE, + FSL_USB2_PHY_SERIAL, +}; + +struct fsl_usb2_platform_data { + /* board specific information */ + enum fsl_usb2_operating_modes operating_mode; + enum fsl_usb2_phy_modes phy_mode; + unsigned int port_enables; +}; + +/* Flags in fsl_usb2_mph_platform_data */ +#define FSL_USB2_PORT0_ENABLED 0x00000001 +#define FSL_USB2_PORT1_ENABLED 0x00000002 + #endif /* _FSL_DEVICE_H_ */ #endif /* __KERNEL__ */ -- cgit v1.2.3 From 76fa9a240de4294a097235c9ddd470c21eb3449e Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Fri, 20 Jan 2006 14:06:09 -0800 Subject: [PATCH] USB: EHCI for AU1200 ALCHEMY: Add EHCI support for AU1200 Updated by removing the OHCI support Signed-off-by: Jordan Crouse Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- arch/mips/au1000/common/cputable.c | 2 +- arch/mips/au1000/common/platform.c | 2 - drivers/usb/Kconfig | 9 +- drivers/usb/host/Kconfig | 2 +- drivers/usb/host/ehci-au1xxx.c | 297 +++++++++++++++++++++ drivers/usb/host/ehci-hcd.c | 11 +- include/asm-mips/mach-mips/cpu-feature-overrides.h | 4 + 7 files changed, 319 insertions(+), 8 deletions(-) create mode 100644 drivers/usb/host/ehci-au1xxx.c (limited to 'include') diff --git a/arch/mips/au1000/common/cputable.c b/arch/mips/au1000/common/cputable.c index 4dbde82c8215..d8df5fdb045f 100644 --- a/arch/mips/au1000/common/cputable.c +++ b/arch/mips/au1000/common/cputable.c @@ -38,7 +38,7 @@ struct cpu_spec cpu_specs[] = { { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1 }, { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1 }, { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0 }, - { 0xffffffff, 0x04030201, "Au1200 AC", 0, 1 }, + { 0xffffffff, 0x04030201, "Au1200 AC", 1, 0 }, { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0 }, }; diff --git a/arch/mips/au1000/common/platform.c b/arch/mips/au1000/common/platform.c index 48d3f54f88f8..1fb3dbdb93be 100644 --- a/arch/mips/au1000/common/platform.c +++ b/arch/mips/au1000/common/platform.c @@ -278,9 +278,7 @@ static struct platform_device *au1xxx_platform_devices[] __initdata = { &au1100_lcd_device, #endif #ifdef CONFIG_SOC_AU1200 -#if 0 /* fixme */ &au1xxx_usb_ehci_device, -#endif &au1xxx_usb_gdt_device, &au1xxx_usb_otg_device, &au1200_lcd_device, diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 7772e28a303f..0e865975899f 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -10,8 +10,8 @@ menu "USB support" config USB_ARCH_HAS_HCD boolean default y if USB_ARCH_HAS_OHCI + default y if USB_ARCH_HAS_EHCI default y if ARM # SL-811 - default y if PPC_83xx default PCI # many non-PCI SOC chips embed OHCI @@ -31,6 +31,13 @@ config USB_ARCH_HAS_OHCI # more: default PCI +# some non-PCI hcds implement EHCI +config USB_ARCH_HAS_EHCI + boolean + default y if PPC_83xx + default y if SOC_AU1200 + default PCI + # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. config USB tristate "Support for Host-side USB" diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index a45293673906..e27b79a3c05f 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -6,7 +6,7 @@ comment "USB Host Controller Drivers" config USB_EHCI_HCD tristate "EHCI HCD (USB 2.0) support" - depends on USB && (PCI || PPC_83xx) + depends on USB && USB_ARCH_HAS_EHCI ---help--- The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c new file mode 100644 index 000000000000..63eadeec1324 --- /dev/null +++ b/drivers/usb/host/ehci-au1xxx.c @@ -0,0 +1,297 @@ +/* + * EHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 2000-2004 David Brownell + * + * Bus Glue for AMD Alchemy Au1xxx + * + * Based on "ohci-au1xxx.c" by Matt Porter + * + * Modified for AMD Alchemy Au1200 EHC + * by K.Boge + * + * This file is licenced under the GPL. + */ + +#include +#include + +#ifndef CONFIG_SOC_AU1200 +#error "this Alchemy chip doesn't have EHCI" +#else /* Au1200 */ + +#define USB_HOST_CONFIG (USB_MSR_BASE + USB_MSR_MCFG) +#define USB_MCFG_PFEN (1<<31) +#define USB_MCFG_RDCOMB (1<<30) +#define USB_MCFG_SSDEN (1<<23) +#define USB_MCFG_PHYPLLEN (1<<19) +#define USB_MCFG_EHCCLKEN (1<<17) +#define USB_MCFG_UCAM (1<<7) +#define USB_MCFG_EBMEN (1<<3) +#define USB_MCFG_EMEMEN (1<<2) + +#define USBH_ENABLE_CE (USB_MCFG_PHYPLLEN | USB_MCFG_EHCCLKEN) + +#ifdef CONFIG_DMA_COHERENT +#define USBH_ENABLE_INIT (USBH_ENABLE_CE \ + | USB_MCFG_PFEN | USB_MCFG_RDCOMB \ + | USB_MCFG_SSDEN | USB_MCFG_UCAM \ + | USB_MCFG_EBMEN | USB_MCFG_EMEMEN) +#else +#define USBH_ENABLE_INIT (USBH_ENABLE_CE \ + | USB_MCFG_PFEN | USB_MCFG_RDCOMB \ + | USB_MCFG_SSDEN \ + | USB_MCFG_EBMEN | USB_MCFG_EMEMEN) +#endif +#define USBH_DISABLE (USB_MCFG_EBMEN | USB_MCFG_EMEMEN) + +#endif /* Au1200 */ + +extern int usb_disabled(void); + +/*-------------------------------------------------------------------------*/ + +static void au1xxx_start_ehc(struct platform_device *dev) +{ + pr_debug(__FILE__ ": starting Au1xxx EHCI USB Controller\n"); + + /* write HW defaults again in case Yamon cleared them */ + if (au_readl(USB_HOST_CONFIG) == 0) { + au_writel(0x00d02000, USB_HOST_CONFIG); + au_readl(USB_HOST_CONFIG); + udelay(1000); + } + /* enable host controller */ + au_writel(USBH_ENABLE_CE | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); + au_readl(USB_HOST_CONFIG); + udelay(1000); + au_writel(USBH_ENABLE_INIT | au_readl(USB_HOST_CONFIG), + USB_HOST_CONFIG); + au_readl(USB_HOST_CONFIG); + udelay(1000); + + pr_debug(__FILE__ ": Clock to USB host has been enabled\n"); +} + +static void au1xxx_stop_ehc(struct platform_device *dev) +{ + pr_debug(__FILE__ ": stopping Au1xxx EHCI USB Controller\n"); + + /* Disable mem */ + au_writel(~USBH_DISABLE & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); + udelay(1000); + /* Disable clock */ + au_writel(~USB_MCFG_EHCCLKEN & au_readl(USB_HOST_CONFIG), + USB_HOST_CONFIG); + au_readl(USB_HOST_CONFIG); +} + +/*-------------------------------------------------------------------------*/ + +/* configure so an HC device and id are always provided */ +/* always called with process context; sleeping is OK */ + +/** + * usb_ehci_au1xxx_probe - initialize Au1xxx-based HCDs + * Context: !in_interrupt() + * + * Allocates basic resources for this USB host controller, and + * then invokes the start() method for the HCD associated with it + * through the hotplug entry's driver_data. + * + */ +int usb_ehci_au1xxx_probe(const struct hc_driver *driver, + struct usb_hcd **hcd_out, struct platform_device *dev) +{ + int retval; + struct usb_hcd *hcd; + struct ehci_hcd *ehci; + +#if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT) + + /* Au1200 AB USB does not support coherent memory */ + if (!(read_c0_prid() & 0xff)) { + pr_info("%s: this is chip revision AB!\n", dev->dev.name); + pr_info("%s: update your board or re-configure the kernel\n", + dev->dev.name); + return -ENODEV; + } +#endif + + au1xxx_start_ehc(dev); + + if (dev->resource[1].flags != IORESOURCE_IRQ) { + pr_debug("resource[1] is not IORESOURCE_IRQ"); + retval = -ENOMEM; + } + hcd = usb_create_hcd(driver, &dev->dev, "Au1xxx"); + if (!hcd) + return -ENOMEM; + hcd->rsrc_start = dev->resource[0].start; + hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; + + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { + pr_debug("request_mem_region failed"); + retval = -EBUSY; + goto err1; + } + + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + if (!hcd->regs) { + pr_debug("ioremap failed"); + retval = -ENOMEM; + goto err2; + } + + ehci = hcd_to_ehci(hcd); + ehci->caps = hcd->regs; + ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase)); + /* cache this readonly data; minimize chip reads */ + ehci->hcs_params = readl(&ehci->caps->hcs_params); + + /* ehci_hcd_init(hcd_to_ehci(hcd)); */ + + retval = + usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT | SA_SHIRQ); + if (retval == 0) + return retval; + + au1xxx_stop_ehc(dev); + iounmap(hcd->regs); +err2: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); +err1: + usb_put_hcd(hcd); + return retval; +} + +/* may be called without controller electrically present */ +/* may be called with controller, bus, and devices active */ + +/** + * usb_ehci_hcd_au1xxx_remove - shutdown processing for Au1xxx-based HCDs + * @dev: USB Host Controller being removed + * Context: !in_interrupt() + * + * Reverses the effect of usb_ehci_hcd_au1xxx_probe(), first invoking + * the HCD's stop() method. It is always called from a thread + * context, normally "rmmod", "apmd", or something similar. + * + */ +void usb_ehci_au1xxx_remove(struct usb_hcd *hcd, struct platform_device *dev) +{ + usb_remove_hcd(hcd); + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + usb_put_hcd(hcd); + au1xxx_stop_ehc(dev); +} + +/*-------------------------------------------------------------------------*/ + +static const struct hc_driver ehci_au1xxx_hc_driver = { + .description = hcd_name, + .product_desc = "Au1xxx EHCI", + .hcd_priv_size = sizeof(struct ehci_hcd), + + /* + * generic hardware linkage + */ + .irq = ehci_irq, + .flags = HCD_MEMORY | HCD_USB2, + + /* + * basic lifecycle operations + */ + .reset = ehci_init, + .start = ehci_run, + .stop = ehci_stop, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ehci_urb_enqueue, + .urb_dequeue = ehci_urb_dequeue, + .endpoint_disable = ehci_endpoint_disable, + + /* + * scheduling support + */ + .get_frame_number = ehci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ehci_hub_status_data, + .hub_control = ehci_hub_control, +#ifdef CONFIG_PM + .hub_suspend = ehci_hub_suspend, + .hub_resume = ehci_hub_resume, +#endif +}; + +/*-------------------------------------------------------------------------*/ + +static int ehci_hcd_au1xxx_drv_probe(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct usb_hcd *hcd = NULL; + int ret; + + pr_debug("In ehci_hcd_au1xxx_drv_probe\n"); + + if (usb_disabled()) + return -ENODEV; + + ret = usb_ehci_au1xxx_probe(&ehci_au1xxx_hc_driver, &hcd, pdev); + return ret; +} + +static int ehci_hcd_au1xxx_drv_remove(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct usb_hcd *hcd = dev_get_drvdata(dev); + + usb_ehci_au1xxx_remove(hcd, pdev); + return 0; +} + + /*TBD*/ +/*static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct usb_hcd *hcd = dev_get_drvdata(dev); + + return 0; +} +static int ehci_hcd_au1xxx_drv_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct usb_hcd *hcd = dev_get_drvdata(dev); + + return 0; +} +*/ +static struct device_driver ehci_hcd_au1xxx_driver = { + .name = "au1xxx-ehci", + .bus = &platform_bus_type, + .probe = ehci_hcd_au1xxx_drv_probe, + .remove = ehci_hcd_au1xxx_drv_remove, + /*.suspend = ehci_hcd_au1xxx_drv_suspend, */ + /*.resume = ehci_hcd_au1xxx_drv_resume, */ +}; + +static int __init ehci_hcd_au1xxx_init(void) +{ + pr_debug(DRIVER_INFO " (Au1xxx)\n"); + + return driver_register(&ehci_hcd_au1xxx_driver); +} + +static void __exit ehci_hcd_au1xxx_cleanup(void) +{ + driver_unregister(&ehci_hcd_au1xxx_driver); +} + +module_init(ehci_hcd_au1xxx_init); +module_exit(ehci_hcd_au1xxx_cleanup); diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 8730babb5771..79f2d8b9bfb6 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -889,14 +889,19 @@ MODULE_LICENSE ("GPL"); #ifdef CONFIG_PCI #include "ehci-pci.c" +#define EHCI_BUS_GLUED #endif #ifdef CONFIG_PPC_83xx #include "ehci-fsl.c" +#define EHCI_BUS_GLUED #endif -#if !(defined(CONFIG_PCI) || \ - defined(CONFIG_PPC_83xx) \ - ) +#ifdef CONFIG_SOC_AU1X00 +#include "ehci-au1xxx.c" +#define EHCI_BUS_GLUED +#endif + +#ifndef EHCI_BUS_GLUED #error "missing bus glue for ehci-hcd" #endif diff --git a/include/asm-mips/mach-mips/cpu-feature-overrides.h b/include/asm-mips/mach-mips/cpu-feature-overrides.h index 9f92aed17754..e06af6c86f86 100644 --- a/include/asm-mips/mach-mips/cpu-feature-overrides.h +++ b/include/asm-mips/mach-mips/cpu-feature-overrides.h @@ -29,7 +29,11 @@ /* #define cpu_has_prefetch ? */ #define cpu_has_mcheck 1 /* #define cpu_has_ejtag ? */ +#ifdef CONFIG_CPU_HAS_LLSC #define cpu_has_llsc 1 +#else +#define cpu_has_llsc 0 +#endif /* #define cpu_has_vtag_icache ? */ /* #define cpu_has_dc_aliases ? */ /* #define cpu_has_ic_fills_f_dc ? */ -- cgit v1.2.3 From 329af28b141ab4ae847aff1362864c4cc332641f Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sat, 18 Feb 2006 12:31:05 -0800 Subject: [PATCH] USB: gadget driver section fixups This adds __init section annotations to gadget driver bind() routines to remove calls from .text into .init sections (for endpoint autoconfig). Likewise it adds __exit section annotations to their unbind() routines. The specification of the gadget driver register/unregister functions is updated to explicitly allow use of those sections. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/ether.c | 4 ++-- drivers/usb/gadget/file_storage.c | 4 ++-- drivers/usb/gadget/serial.c | 6 +++--- drivers/usb/gadget/zero.c | 6 +++--- include/linux/usb_gadget.h | 7 +++++-- 5 files changed, 15 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 3d2603e31808..0d9d9bbb73f0 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -2125,7 +2125,7 @@ eth_req_free (struct usb_ep *ep, struct usb_request *req) } -static void +static void __exit eth_unbind (struct usb_gadget *gadget) { struct eth_dev *dev = get_gadget_data (gadget); @@ -2532,7 +2532,7 @@ static struct usb_gadget_driver eth_driver = { .function = (char *) driver_desc, .bind = eth_bind, - .unbind = eth_unbind, + .unbind = __exit_p(eth_unbind), .setup = eth_setup, .disconnect = eth_disconnect, diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index de59c58896d6..cf3be299e353 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -3678,7 +3678,7 @@ static void lun_release(struct device *dev) kref_put(&fsg->ref, fsg_release); } -static void fsg_unbind(struct usb_gadget *gadget) +static void __exit fsg_unbind(struct usb_gadget *gadget) { struct fsg_dev *fsg = get_gadget_data(gadget); int i; @@ -4064,7 +4064,7 @@ static struct usb_gadget_driver fsg_driver = { #endif .function = (char *) longname, .bind = fsg_bind, - .unbind = fsg_unbind, + .unbind = __exit_p(fsg_unbind), .disconnect = fsg_disconnect, .setup = fsg_setup, .suspend = fsg_suspend, diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index ba9acd531024..548feaac4553 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -369,7 +369,7 @@ static struct usb_gadget_driver gs_gadget_driver = { #endif /* CONFIG_USB_GADGET_DUALSPEED */ .function = GS_LONG_NAME, .bind = gs_bind, - .unbind = gs_unbind, + .unbind = __exit_p(gs_unbind), .setup = gs_setup, .disconnect = gs_disconnect, .driver = { @@ -1413,7 +1413,7 @@ requeue: * Called on module load. Allocates and initializes the device * structure and a control request. */ -static int gs_bind(struct usb_gadget *gadget) +static int __init gs_bind(struct usb_gadget *gadget) { int ret; struct usb_ep *ep; @@ -1538,7 +1538,7 @@ autoconf_fail: * Called on module unload. Frees the control request and device * structure. */ -static void gs_unbind(struct usb_gadget *gadget) +static void __exit gs_unbind(struct usb_gadget *gadget) { struct gs_dev *dev = get_gadget_data(gadget); diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 5e9fe8a70543..44d8e5e77da7 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -1119,7 +1119,7 @@ zero_autoresume (unsigned long _dev) /*-------------------------------------------------------------------------*/ -static void +static void __exit zero_unbind (struct usb_gadget *gadget) { struct zero_dev *dev = get_gadget_data (gadget); @@ -1136,7 +1136,7 @@ zero_unbind (struct usb_gadget *gadget) set_gadget_data (gadget, NULL); } -static int +static int __init zero_bind (struct usb_gadget *gadget) { struct zero_dev *dev; @@ -1288,7 +1288,7 @@ static struct usb_gadget_driver zero_driver = { #endif .function = (char *) longname, .bind = zero_bind, - .unbind = zero_unbind, + .unbind = __exit_p(zero_unbind), .setup = zero_setup, .disconnect = zero_disconnect, diff --git a/include/linux/usb_gadget.h b/include/linux/usb_gadget.h index ff81117eb733..1d78870ed8af 100644 --- a/include/linux/usb_gadget.h +++ b/include/linux/usb_gadget.h @@ -801,7 +801,9 @@ struct usb_gadget_driver { * Call this in your gadget driver's module initialization function, * to tell the underlying usb controller driver about your driver. * The driver's bind() function will be called to bind it to a - * gadget. This function must be called in a context that can sleep. + * gadget before this registration call returns. It's expected that + * the bind() functions will be in init sections. + * This function must be called in a context that can sleep. */ int usb_gadget_register_driver (struct usb_gadget_driver *driver); @@ -814,7 +816,8 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver); * going away. If the controller is connected to a USB host, * it will first disconnect(). The driver is also requested * to unbind() and clean up any device state, before this procedure - * finally returns. + * finally returns. It's expected that the unbind() functions + * will in in exit sections, so may not be linked in some kernels. * This function must be called in a context that can sleep. */ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver); -- cgit v1.2.3 From 955189efb44742890f33c91df478877af25246da Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Mon, 20 Mar 2006 16:54:09 -0800 Subject: [IPV6]: ADDRCONF: Use our standard algorithm for randomized ifid. RFC 3041 describes an algorithm to generate random interface identifier. In RFC 3041bis, it is allowed to use different algorithm than one described in RFC 3041. So, let's use our standard pseudo random algorithm to simplify our implementation. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- include/net/if_inet6.h | 3 --- net/ipv6/Kconfig | 7 ++++--- net/ipv6/addrconf.c | 45 +-------------------------------------------- 3 files changed, 5 insertions(+), 50 deletions(-) (limited to 'include') diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index eb8afe3499a9..e459e1a0ae4a 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h @@ -180,11 +180,8 @@ struct inet6_dev #ifdef CONFIG_IPV6_PRIVACY u8 rndid[8]; - u8 entropy[8]; struct timer_list regen_timer; struct inet6_ifaddr *tempaddr_list; - __u8 work_eui64[8]; - __u8 work_digest[16]; #endif struct neigh_parms *nd_parms; diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index ab7a9124f985..f925f206d8ff 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig @@ -6,8 +6,6 @@ config IPV6 tristate "The IPv6 protocol" default m - select CRYPTO if IPV6_PRIVACY - select CRYPTO_MD5 if IPV6_PRIVACY ---help--- This is complemental support for the IP version 6. You will still be able to do traditional IPv4 networking as well. @@ -22,7 +20,7 @@ config IPV6 module will be called ipv6. config IPV6_PRIVACY - bool "IPv6: Privacy Extensions (RFC 3041) support" + bool "IPv6: Privacy Extensions support" depends on IPV6 ---help--- Privacy Extensions for Stateless Address Autoconfiguration in IPv6 @@ -30,6 +28,9 @@ config IPV6_PRIVACY pseudo-random global-scope unicast address(es) will assigned to your interface(s). + We use our standard pseudo random algorithm to generate randomized + interface identifier, instead of one described in RFC 3041. + By default, kernel do not generate temporary addresses. To use temporary addresses, do diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 441eeacfc851..c92f3d6a8f13 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -78,8 +78,6 @@ #ifdef CONFIG_IPV6_PRIVACY #include -#include -#include #endif #include @@ -110,8 +108,6 @@ static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpad static void ipv6_regen_rndid(unsigned long data); static int desync_factor = MAX_DESYNC_FACTOR * HZ; -static struct crypto_tfm *md5_tfm; -static DEFINE_SPINLOCK(md5_tfm_lock); #endif static int ipv6_count_addresses(struct inet6_dev *idev); @@ -371,8 +367,6 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) in6_dev_hold(ndev); #ifdef CONFIG_IPV6_PRIVACY - get_random_bytes(ndev->rndid, sizeof(ndev->rndid)); - get_random_bytes(ndev->entropy, sizeof(ndev->entropy)); init_timer(&ndev->regen_timer); ndev->regen_timer.function = ipv6_regen_rndid; ndev->regen_timer.data = (unsigned long) ndev; @@ -1376,34 +1370,9 @@ static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev) /* (re)generation of randomized interface identifier (RFC 3041 3.2, 3.5) */ static int __ipv6_regen_rndid(struct inet6_dev *idev) { - struct net_device *dev; - struct scatterlist sg[2]; - - sg_set_buf(&sg[0], idev->entropy, 8); - sg_set_buf(&sg[1], idev->work_eui64, 8); - - dev = idev->dev; - - if (ipv6_generate_eui64(idev->work_eui64, dev)) { - printk(KERN_INFO - "__ipv6_regen_rndid(idev=%p): cannot get EUI64 identifier; use random bytes.\n", - idev); - get_random_bytes(idev->work_eui64, sizeof(idev->work_eui64)); - } regen: - spin_lock(&md5_tfm_lock); - if (unlikely(md5_tfm == NULL)) { - spin_unlock(&md5_tfm_lock); - return -1; - } - crypto_digest_init(md5_tfm); - crypto_digest_update(md5_tfm, sg, 2); - crypto_digest_final(md5_tfm, idev->work_digest); - spin_unlock(&md5_tfm_lock); - - memcpy(idev->rndid, &idev->work_digest[0], 8); + get_random_bytes(idev->rndid, sizeof(idev->rndid)); idev->rndid[0] &= ~0x02; - memcpy(idev->entropy, &idev->work_digest[8], 8); /* * : @@ -3759,13 +3728,6 @@ int __init addrconf_init(void) register_netdevice_notifier(&ipv6_dev_notf); -#ifdef CONFIG_IPV6_PRIVACY - md5_tfm = crypto_alloc_tfm("md5", 0); - if (unlikely(md5_tfm == NULL)) - printk(KERN_WARNING - "failed to load transform for md5\n"); -#endif - addrconf_verify(0); rtnetlink_links[PF_INET6] = inet6_rtnetlink_table; #ifdef CONFIG_SYSCTL @@ -3828,11 +3790,6 @@ void __exit addrconf_cleanup(void) rtnl_unlock(); -#ifdef CONFIG_IPV6_PRIVACY - crypto_free_tfm(md5_tfm); - md5_tfm = NULL; -#endif - #ifdef CONFIG_PROC_FS proc_net_remove("if_inet6"); #endif -- cgit v1.2.3 From 65f5c7c1143fb8eed5bc7e7d8c926346e00fe3c0 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Mon, 20 Mar 2006 16:55:08 -0800 Subject: [IPV6]: ROUTE: Add accept_ra_defrtr sysctl. This controls whether we accept default router information in RAs. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 6 ++++++ include/linux/ipv6.h | 2 ++ include/linux/sysctl.h | 1 + net/ipv6/addrconf.c | 11 +++++++++++ net/ipv6/ndisc.c | 7 ++++++- 5 files changed, 26 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 26364d06ae92..8001faa76ea2 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -717,6 +717,12 @@ accept_ra - BOOLEAN Functional default: enabled if local forwarding is disabled. disabled if local forwarding is enabled. +accept_ra_defrtr - BOOLEAN + Learn default router in Router Advertisement. + + Functional default: enabled if accept_ra is enabled. + disabled if accept_ra is disabled. + accept_redirects - BOOLEAN Accept Redirects. diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 9c8f4c9ed429..c5131a02869a 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -145,6 +145,7 @@ struct ipv6_devconf { __s32 max_desync_factor; #endif __s32 max_addresses; + __s32 accept_ra_defrtr; void *sysctl; }; @@ -167,6 +168,7 @@ enum { DEVCONF_MAX_DESYNC_FACTOR, DEVCONF_MAX_ADDRESSES, DEVCONF_FORCE_MLD_VERSION, + DEVCONF_ACCEPT_RA_DEFRTR, DEVCONF_MAX }; diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index bac61db26456..0f494137d037 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -531,6 +531,7 @@ enum { NET_IPV6_MAX_DESYNC_FACTOR=15, NET_IPV6_MAX_ADDRESSES=16, NET_IPV6_FORCE_MLD_VERSION=17, + NET_IPV6_ACCEPT_RA_DEFRTR=18, __NET_IPV6_MAX }; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 8a8895ef09a7..fbcdcc6ba93b 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -165,6 +165,7 @@ struct ipv6_devconf ipv6_devconf = { .max_desync_factor = MAX_DESYNC_FACTOR, #endif .max_addresses = IPV6_MAX_ADDRESSES, + .accept_ra_defrtr = 1, }; static struct ipv6_devconf ipv6_devconf_dflt = { @@ -186,6 +187,7 @@ static struct ipv6_devconf ipv6_devconf_dflt = { .max_desync_factor = MAX_DESYNC_FACTOR, #endif .max_addresses = IPV6_MAX_ADDRESSES, + .accept_ra_defrtr = 1, }; /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ @@ -3116,6 +3118,7 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor; #endif array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses; + array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr; } static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, @@ -3568,6 +3571,14 @@ static struct addrconf_sysctl_table .mode = 0644, .proc_handler = &proc_dointvec, }, + { + .ctl_name = NET_IPV6_ACCEPT_RA_DEFRTR, + .procname = "accept_ra_defrtr", + .data = &ipv6_devconf.accept_ra_defrtr, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, { .ctl_name = 0, /* sentinel */ } diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index cb8856b1d951..e17116796059 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1019,7 +1019,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw; struct neighbour *neigh = NULL; struct inet6_dev *in6_dev; - struct rt6_info *rt; + struct rt6_info *rt = NULL; int lifetime; struct ndisc_options ndopts; int optlen; @@ -1081,6 +1081,9 @@ static void ndisc_router_discovery(struct sk_buff *skb) (ra_msg->icmph.icmp6_addrconf_other ? IF_RA_OTHERCONF : 0); + if (!in6_dev->cnf.accept_ra_defrtr) + goto skip_defrtr; + lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime); rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev); @@ -1128,6 +1131,8 @@ static void ndisc_router_discovery(struct sk_buff *skb) rt->u.dst.metrics[RTAX_HOPLIMIT-1] = ra_msg->icmph.icmp6_hop_limit; } +skip_defrtr: + /* * Update Reachable Time and Retrans Timer */ -- cgit v1.2.3 From c4fd30eb18666972230689eb30e8f90844bce635 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Mon, 20 Mar 2006 16:55:26 -0800 Subject: [IPV6]: ADDRCONF: Add accept_ra_pinfo sysctl. This controls whether we accept Prefix Information in RAs. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 10 ++++++++-- include/linux/ipv6.h | 2 ++ include/linux/sysctl.h | 1 + net/ipv6/addrconf.c | 11 +++++++++++ net/ipv6/ndisc.c | 2 +- 5 files changed, 23 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 8001faa76ea2..404afacb468d 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -723,6 +723,12 @@ accept_ra_defrtr - BOOLEAN Functional default: enabled if accept_ra is enabled. disabled if accept_ra is disabled. +accept_ra_pinfo - BOOLEAN + Learn Prefix Inforamtion in Router Advertisement. + + Functional default: enabled if accept_ra is enabled. + disabled if accept_ra is disabled. + accept_redirects - BOOLEAN Accept Redirects. @@ -733,8 +739,8 @@ autoconf - BOOLEAN Autoconfigure addresses using Prefix Information in Router Advertisements. - Functional default: enabled if accept_ra is enabled. - disabled if accept_ra is disabled. + Functional default: enabled if accept_ra_pinfo is enabled. + disabled if accept_ra_pinfo is disabled. dad_transmits - INTEGER The amount of Duplicate Address Detection probes to send. diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index c5131a02869a..2c3b799480c5 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -146,6 +146,7 @@ struct ipv6_devconf { #endif __s32 max_addresses; __s32 accept_ra_defrtr; + __s32 accept_ra_pinfo; void *sysctl; }; @@ -169,6 +170,7 @@ enum { DEVCONF_MAX_ADDRESSES, DEVCONF_FORCE_MLD_VERSION, DEVCONF_ACCEPT_RA_DEFRTR, + DEVCONF_ACCEPT_RA_PINFO, DEVCONF_MAX }; diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 0f494137d037..09378ea505bd 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -532,6 +532,7 @@ enum { NET_IPV6_MAX_ADDRESSES=16, NET_IPV6_FORCE_MLD_VERSION=17, NET_IPV6_ACCEPT_RA_DEFRTR=18, + NET_IPV6_ACCEPT_RA_PINFO=19, __NET_IPV6_MAX }; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index fbcdcc6ba93b..631b51d0ccbc 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -166,6 +166,7 @@ struct ipv6_devconf ipv6_devconf = { #endif .max_addresses = IPV6_MAX_ADDRESSES, .accept_ra_defrtr = 1, + .accept_ra_pinfo = 1, }; static struct ipv6_devconf ipv6_devconf_dflt = { @@ -188,6 +189,7 @@ static struct ipv6_devconf ipv6_devconf_dflt = { #endif .max_addresses = IPV6_MAX_ADDRESSES, .accept_ra_defrtr = 1, + .accept_ra_pinfo = 1, }; /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ @@ -3119,6 +3121,7 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, #endif array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses; array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr; + array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo; } static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, @@ -3579,6 +3582,14 @@ static struct addrconf_sysctl_table .mode = 0644, .proc_handler = &proc_dointvec, }, + { + .ctl_name = NET_IPV6_ACCEPT_RA_PINFO, + .procname = "accept_ra_pinfo", + .data = &ipv6_devconf.accept_ra_pinfo, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, { .ctl_name = 0, /* sentinel */ } diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index e17116796059..3b56be85234e 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1191,7 +1191,7 @@ skip_defrtr: NEIGH_UPDATE_F_ISROUTER); } - if (ndopts.nd_opts_pi) { + if (in6_dev->cnf.accept_ra_pinfo && ndopts.nd_opts_pi) { struct nd_opt_hdr *p; for (p = ndopts.nd_opts_pi; p; -- cgit v1.2.3 From 554cfb7ee5d4f2d0edb280e66e4a2db1906a8300 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Mon, 20 Mar 2006 17:00:26 -0800 Subject: [IPV6]: ROUTE: Eliminate lock for default route pointer. And prepare for more advanced router selection. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- include/net/ip6_route.h | 2 - net/ipv6/ip6_fib.c | 1 - net/ipv6/route.c | 197 +++++++++++++++++------------------------------- 3 files changed, 69 insertions(+), 131 deletions(-) (limited to 'include') diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 1f2e428ca364..01acca06d6dd 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -91,8 +91,6 @@ extern struct rt6_info * rt6_add_dflt_router(struct in6_addr *gwaddr, extern void rt6_purge_dflt_routers(void); -extern void rt6_reset_dflt_pointer(struct rt6_info *rt); - extern void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr, struct neighbour *neigh, diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 1bf6d9a769e6..2cb6149349bf 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -1105,7 +1105,6 @@ static int fib6_age(struct rt6_info *rt, void *arg) if (rt->rt6i_flags&RTF_EXPIRES && rt->rt6i_expires) { if (time_after(now, rt->rt6i_expires)) { RT6_TRACE("expiring %p\n", rt); - rt6_reset_dflt_pointer(rt); return -1; } gc_args.more++; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 6a4019a4ca89..f71e2365b43d 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -74,6 +74,9 @@ #define CLONE_OFFLINK_ROUTE 0 +#define RT6_SELECT_F_IFACE 0x1 +#define RT6_SELECT_F_REACHABLE 0x2 + static int ip6_rt_max_size = 4096; static int ip6_rt_gc_min_interval = HZ / 2; static int ip6_rt_gc_timeout = 60*HZ; @@ -216,148 +219,89 @@ static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt, } /* - * pointer to the last default router chosen. BH is disabled locally. + * Default Router Selection (RFC 2461 6.3.6) */ -static struct rt6_info *rt6_dflt_pointer; -static DEFINE_SPINLOCK(rt6_dflt_lock); +static int inline rt6_check_dev(struct rt6_info *rt, int oif) +{ + struct net_device *dev = rt->rt6i_dev; + if (!oif || dev->ifindex == oif) + return 2; + if ((dev->flags & IFF_LOOPBACK) && + rt->rt6i_idev && rt->rt6i_idev->dev->ifindex == oif) + return 1; + return 0; +} -void rt6_reset_dflt_pointer(struct rt6_info *rt) +static int inline rt6_check_neigh(struct rt6_info *rt) { - spin_lock_bh(&rt6_dflt_lock); - if (rt == NULL || rt == rt6_dflt_pointer) { - RT6_TRACE("reset default router: %p->NULL\n", rt6_dflt_pointer); - rt6_dflt_pointer = NULL; + struct neighbour *neigh = rt->rt6i_nexthop; + int m = 0; + if (neigh) { + read_lock_bh(&neigh->lock); + if (neigh->nud_state & NUD_VALID) + m = 1; + read_unlock_bh(&neigh->lock); } - spin_unlock_bh(&rt6_dflt_lock); + return m; } -/* Default Router Selection (RFC 2461 6.3.6) */ -static struct rt6_info *rt6_best_dflt(struct rt6_info *rt, int oif) +static int rt6_score_route(struct rt6_info *rt, int oif, + int strict) { - struct rt6_info *match = NULL; - struct rt6_info *sprt; - int mpri = 0; + int m = rt6_check_dev(rt, oif); + if (!m && (strict & RT6_SELECT_F_IFACE)) + return -1; + if (rt6_check_neigh(rt)) + m |= 4; + else if (strict & RT6_SELECT_F_REACHABLE) + return -1; + return m; +} - for (sprt = rt; sprt; sprt = sprt->u.next) { - struct neighbour *neigh; - int m = 0; +static struct rt6_info *rt6_select(struct rt6_info **head, int oif, + int strict) +{ + struct rt6_info *match = NULL, *last = NULL; + struct rt6_info *rt, *rt0 = *head; + u32 metric; + int mpri = -1; - if (!oif || - (sprt->rt6i_dev && - sprt->rt6i_dev->ifindex == oif)) - m += 8; + RT6_TRACE("%s(head=%p(*head=%p), oif=%d)\n", + __FUNCTION__, head, head ? *head : NULL, oif); - if (rt6_check_expired(sprt)) + for (rt = rt0, metric = rt0->rt6i_metric; + rt && rt->rt6i_metric == metric; + rt = rt->u.next) { + int m; + + if (rt6_check_expired(rt)) continue; - if (sprt == rt6_dflt_pointer) - m += 4; - - if ((neigh = sprt->rt6i_nexthop) != NULL) { - read_lock_bh(&neigh->lock); - switch (neigh->nud_state) { - case NUD_REACHABLE: - m += 3; - break; - - case NUD_STALE: - case NUD_DELAY: - case NUD_PROBE: - m += 2; - break; - - case NUD_NOARP: - case NUD_PERMANENT: - m += 1; - break; - - case NUD_INCOMPLETE: - default: - read_unlock_bh(&neigh->lock); - continue; - } - read_unlock_bh(&neigh->lock); - } else { + last = rt; + + m = rt6_score_route(rt, oif, strict); + if (m < 0) continue; - } - if (m > mpri || m >= 12) { - match = sprt; + if (m > mpri) { + match = rt; mpri = m; - if (m >= 12) { - /* we choose the last default router if it - * is in (probably) reachable state. - * If route changed, we should do pmtu - * discovery. --yoshfuji - */ - break; - } } } - spin_lock(&rt6_dflt_lock); - if (!match) { - /* - * No default routers are known to be reachable. - * SHOULD round robin - */ - if (rt6_dflt_pointer) { - for (sprt = rt6_dflt_pointer->u.next; - sprt; sprt = sprt->u.next) { - if (sprt->u.dst.obsolete <= 0 && - sprt->u.dst.error == 0 && - !rt6_check_expired(sprt)) { - match = sprt; - break; - } - } - for (sprt = rt; - !match && sprt; - sprt = sprt->u.next) { - if (sprt->u.dst.obsolete <= 0 && - sprt->u.dst.error == 0 && - !rt6_check_expired(sprt)) { - match = sprt; - break; - } - if (sprt == rt6_dflt_pointer) - break; - } - } - } - - if (match) { - if (rt6_dflt_pointer != match) - RT6_TRACE("changed default router: %p->%p\n", - rt6_dflt_pointer, match); - rt6_dflt_pointer = match; + if (!match && + (strict & RT6_SELECT_F_REACHABLE) && + last && last != rt0) { + /* no entries matched; do round-robin */ + *head = rt0->u.next; + rt0->u.next = last->u.next; + last->u.next = rt0; } - spin_unlock(&rt6_dflt_lock); - if (!match) { - /* - * Last Resort: if no default routers found, - * use addrconf default route. - * We don't record this route. - */ - for (sprt = ip6_routing_table.leaf; - sprt; sprt = sprt->u.next) { - if (!rt6_check_expired(sprt) && - (sprt->rt6i_flags & RTF_DEFAULT) && - (!oif || - (sprt->rt6i_dev && - sprt->rt6i_dev->ifindex == oif))) { - match = sprt; - break; - } - } - if (!match) { - /* no default route. give up. */ - match = &ip6_null_entry; - } - } + RT6_TRACE("%s() => %p, score=%d\n", + __FUNCTION__, match, mpri); - return match; + return (match ? match : &ip6_null_entry); } struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, @@ -542,7 +486,7 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) int attempts = 3; int err; - strict = ipv6_addr_type(&fl->fl6_dst) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL); + strict = ipv6_addr_type(&fl->fl6_dst) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL) ? RT6_SELECT_F_IFACE : 0; relookup: read_lock_bh(&rt6_lock); @@ -558,8 +502,9 @@ restart: goto out; } if (rt->rt6i_flags & RTF_DEFAULT) { - if (rt->rt6i_metric >= IP6_RT_PRIO_ADDRCONF) - rt = rt6_best_dflt(rt, fl->oif); + rt = rt6_select(&fn->leaf, fl->oif, strict | RT6_SELECT_F_REACHABLE); + if (rt == &ip6_null_entry) + rt = rt6_select(&fn->leaf, fl->oif, strict); } else { rt = rt6_device_match(rt, fl->oif, strict); BACKTRACK(); @@ -1025,8 +970,6 @@ int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct write_lock_bh(&rt6_lock); - rt6_reset_dflt_pointer(NULL); - err = fib6_del(rt, nlh, _rtattr, req); dst_release(&rt->u.dst); @@ -1341,8 +1284,6 @@ restart: if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) { dst_hold(&rt->u.dst); - rt6_reset_dflt_pointer(NULL); - read_unlock_bh(&rt6_lock); ip6_del_rt(rt, NULL, NULL, NULL); -- cgit v1.2.3 From ebacaaa0fdf4402cdf4c8e569f54af36b6f0aa2d Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Mon, 20 Mar 2006 17:04:53 -0800 Subject: [IPV6]: ROUTE: Add support for Router Preference (RFC4191). Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- include/linux/icmpv6.h | 11 +++++++++-- include/linux/ipv6_route.h | 8 ++++++++ include/net/ip6_route.h | 3 ++- net/ipv6/Kconfig | 11 +++++++++++ net/ipv6/ndisc.c | 12 +++++++++++- net/ipv6/route.c | 11 ++++++++--- 6 files changed, 49 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h index 0cf6c8b12caf..c771a7db9871 100644 --- a/include/linux/icmpv6.h +++ b/include/linux/icmpv6.h @@ -40,14 +40,16 @@ struct icmp6hdr { struct icmpv6_nd_ra { __u8 hop_limit; #if defined(__LITTLE_ENDIAN_BITFIELD) - __u8 reserved:6, + __u8 reserved:4, + router_pref:2, other:1, managed:1; #elif defined(__BIG_ENDIAN_BITFIELD) __u8 managed:1, other:1, - reserved:6; + router_pref:2, + reserved:4; #else #error "Please fix " #endif @@ -70,8 +72,13 @@ struct icmp6hdr { #define icmp6_addrconf_managed icmp6_dataun.u_nd_ra.managed #define icmp6_addrconf_other icmp6_dataun.u_nd_ra.other #define icmp6_rt_lifetime icmp6_dataun.u_nd_ra.rt_lifetime +#define icmp6_router_pref icmp6_dataun.u_nd_ra.router_pref }; +#define ICMPV6_ROUTER_PREF_LOW 0x3 +#define ICMPV6_ROUTER_PREF_MEDIUM 0x0 +#define ICMPV6_ROUTER_PREF_HIGH 0x1 +#define ICMPV6_ROUTER_PREF_INVALID 0x2 #define ICMPV6_DEST_UNREACH 1 #define ICMPV6_PKT_TOOBIG 2 diff --git a/include/linux/ipv6_route.h b/include/linux/ipv6_route.h index d7c41d1d706a..f4b085c91608 100644 --- a/include/linux/ipv6_route.h +++ b/include/linux/ipv6_route.h @@ -27,8 +27,16 @@ #define RTF_FLOW 0x02000000 /* flow significant route */ #define RTF_POLICY 0x04000000 /* policy route */ +#define RTF_PREF(pref) ((pref) << 27) +#define RTF_PREF_MASK 0x18000000 + #define RTF_LOCAL 0x80000000 +#ifdef __KERNEL__ +#define IPV6_EXTRACT_PREF(flag) (((flag) & RTF_PREF_MASK) >> 27) +#define IPV6_DECODE_PREF(pref) ((pref) ^ 2) /* 1:low,2:med,3:high */ +#endif + struct in6_rtmsg { struct in6_addr rtmsg_dst; struct in6_addr rtmsg_src; diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 01acca06d6dd..50161322b828 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -87,7 +87,8 @@ extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, extern struct rt6_info * rt6_get_dflt_router(struct in6_addr *addr, struct net_device *dev); extern struct rt6_info * rt6_add_dflt_router(struct in6_addr *gwaddr, - struct net_device *dev); + struct net_device *dev, + unsigned int pref); extern void rt6_purge_dflt_routers(void); diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index f925f206d8ff..c456ead8a4a3 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig @@ -38,6 +38,17 @@ config IPV6_PRIVACY See for details. +config IPV6_ROUTER_PREF + bool "IPv6: Router Preference (RFC 4191) support" + depends on IPV6 + ---help--- + Router Preference is an optional extension to the Router + Advertisement message to improve the ability of hosts + to pick more appropriate router, especially when the hosts + is placed in a multi-homed network. + + If unsure, say N. + config INET6_AH tristate "IPv6: AH transformation" depends on IPV6 diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 3b56be85234e..966ab6b3022e 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1023,6 +1023,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) int lifetime; struct ndisc_options ndopts; int optlen; + unsigned int pref = 0; __u8 * opt = (__u8 *)(ra_msg + 1); @@ -1086,6 +1087,13 @@ static void ndisc_router_discovery(struct sk_buff *skb) lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime); +#ifdef CONFIG_IPV6_ROUTER_PREF + pref = ra_msg->icmph.icmp6_router_pref; + /* 10b is handled as if it were 00b (medium) */ + if (pref == ICMPV6_ROUTER_PREF_INVALID) + pref = ICMPV6_ROUTER_PREF_MEDIUM; +#endif + rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev); if (rt) @@ -1101,7 +1109,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) ND_PRINTK3(KERN_DEBUG "ICMPv6 RA: adding default router.\n"); - rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev); + rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev, pref); if (rt == NULL) { ND_PRINTK0(KERN_ERR "ICMPv6 RA: %s() failed to add default route.\n", @@ -1120,6 +1128,8 @@ static void ndisc_router_discovery(struct sk_buff *skb) return; } neigh->flags |= NTF_ROUTER; + } else if (rt) { + rt->rt6i_flags |= (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref); } if (rt) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 6a068e7f81f1..a7030fed1a18 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -251,8 +251,11 @@ static int rt6_score_route(struct rt6_info *rt, int oif, int m = rt6_check_dev(rt, oif); if (!m && (strict & RT6_SELECT_F_IFACE)) return -1; +#ifdef CONFIG_IPV6_ROUTER_PREF + m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2; +#endif if (rt6_check_neigh(rt)) - m |= 4; + m |= 16; else if (strict & RT6_SELECT_F_REACHABLE) return -1; return m; @@ -1256,7 +1259,8 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d } struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, - struct net_device *dev) + struct net_device *dev, + unsigned int pref) { struct in6_rtmsg rtmsg; @@ -1264,7 +1268,8 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, rtmsg.rtmsg_type = RTMSG_NEWROUTE; ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr); rtmsg.rtmsg_metric = 1024; - rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | RTF_UP | RTF_EXPIRES; + rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | RTF_UP | RTF_EXPIRES | + RTF_PREF(pref); rtmsg.rtmsg_ifindex = dev->ifindex; -- cgit v1.2.3 From 930d6ff2e2a5f1538448d3b0b2652a8f0c0f6cba Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Mon, 20 Mar 2006 17:05:30 -0800 Subject: [IPV6]: ROUTE: Add accept_ra_rtr_pref sysctl. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 6 ++++++ include/linux/ipv6.h | 4 ++++ include/linux/sysctl.h | 1 + net/ipv6/addrconf.c | 19 +++++++++++++++++++ net/ipv6/ndisc.c | 3 ++- 5 files changed, 32 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 404afacb468d..87bbd774c2b2 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -729,6 +729,12 @@ accept_ra_pinfo - BOOLEAN Functional default: enabled if accept_ra is enabled. disabled if accept_ra is disabled. +accept_ra_rtr_pref - BOOLEAN + Accept Router Preference in RA. + + Functional default: enabled if accept_ra is enabled. + disabled if accept_ra is disabled. + accept_redirects - BOOLEAN Accept Redirects. diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 2c3b799480c5..108b75dccd9f 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -147,6 +147,9 @@ struct ipv6_devconf { __s32 max_addresses; __s32 accept_ra_defrtr; __s32 accept_ra_pinfo; +#ifdef CONFIG_IPV6_ROUTER_PREF + __s32 accept_ra_rtr_pref; +#endif void *sysctl; }; @@ -171,6 +174,7 @@ enum { DEVCONF_FORCE_MLD_VERSION, DEVCONF_ACCEPT_RA_DEFRTR, DEVCONF_ACCEPT_RA_PINFO, + DEVCONF_ACCEPT_RA_RTR_PREF, DEVCONF_MAX }; diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 09378ea505bd..236f537b38d2 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -533,6 +533,7 @@ enum { NET_IPV6_FORCE_MLD_VERSION=17, NET_IPV6_ACCEPT_RA_DEFRTR=18, NET_IPV6_ACCEPT_RA_PINFO=19, + NET_IPV6_ACCEPT_RA_RTR_PREF=20, __NET_IPV6_MAX }; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 631b51d0ccbc..51edba5fea26 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -167,6 +167,9 @@ struct ipv6_devconf ipv6_devconf = { .max_addresses = IPV6_MAX_ADDRESSES, .accept_ra_defrtr = 1, .accept_ra_pinfo = 1, +#ifdef CONFIG_IPV6_ROUTER_PREF + .accept_ra_rtr_pref = 1, +#endif }; static struct ipv6_devconf ipv6_devconf_dflt = { @@ -190,6 +193,9 @@ static struct ipv6_devconf ipv6_devconf_dflt = { .max_addresses = IPV6_MAX_ADDRESSES, .accept_ra_defrtr = 1, .accept_ra_pinfo = 1, +#ifdef CONFIG_IPV6_ROUTER_PREF + .accept_ra_rtr_pref = 1, +#endif }; /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ @@ -3122,6 +3128,9 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses; array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr; array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo; +#ifdef CONFIG_IPV6_ROUTER_PREF + array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref; +#endif } static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, @@ -3590,6 +3599,16 @@ static struct addrconf_sysctl_table .mode = 0644, .proc_handler = &proc_dointvec, }, +#ifdef CONFIG_IPV6_ROUTER_PREF + { + .ctl_name = NET_IPV6_ACCEPT_RA_RTR_PREF, + .procname = "accept_ra_rtr_pref", + .data = &ipv6_devconf.accept_ra_rtr_pref, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#endif { .ctl_name = 0, /* sentinel */ } diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 966ab6b3022e..f4462ee33024 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1090,7 +1090,8 @@ static void ndisc_router_discovery(struct sk_buff *skb) #ifdef CONFIG_IPV6_ROUTER_PREF pref = ra_msg->icmph.icmp6_router_pref; /* 10b is handled as if it were 00b (medium) */ - if (pref == ICMPV6_ROUTER_PREF_INVALID) + if (pref == ICMPV6_ROUTER_PREF_INVALID || + in6_dev->cnf.accept_ra_rtr_pref) pref = ICMPV6_ROUTER_PREF_MEDIUM; #endif -- cgit v1.2.3 From 52e1635631b342803aecaf81a362c1464e3da2e5 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Mon, 20 Mar 2006 17:05:47 -0800 Subject: [IPV6]: ROUTE: Add router_probe_interval sysctl. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 6 ++++++ include/linux/ipv6.h | 2 ++ include/linux/sysctl.h | 1 + net/ipv6/addrconf.c | 12 ++++++++++++ net/ipv6/route.c | 2 +- 5 files changed, 22 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 87bbd774c2b2..88efed0a533f 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -789,6 +789,12 @@ mtu - INTEGER Default Maximum Transfer Unit Default: 1280 (IPv6 required minimum) +router_probe_interval - INTEGER + Minimum interval (in seconds) between Router Probing described + in RFC4191. + + Default: 60 + router_solicitation_delay - INTEGER Number of seconds to wait after interface is brought up before sending Router Solicitations. diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 108b75dccd9f..c609cc702375 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -149,6 +149,7 @@ struct ipv6_devconf { __s32 accept_ra_pinfo; #ifdef CONFIG_IPV6_ROUTER_PREF __s32 accept_ra_rtr_pref; + __s32 rtr_probe_interval; #endif void *sysctl; }; @@ -175,6 +176,7 @@ enum { DEVCONF_ACCEPT_RA_DEFRTR, DEVCONF_ACCEPT_RA_PINFO, DEVCONF_ACCEPT_RA_RTR_PREF, + DEVCONF_RTR_PROBE_INTERVAL, DEVCONF_MAX }; diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 236f537b38d2..f49488ffefef 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -534,6 +534,7 @@ enum { NET_IPV6_ACCEPT_RA_DEFRTR=18, NET_IPV6_ACCEPT_RA_PINFO=19, NET_IPV6_ACCEPT_RA_RTR_PREF=20, + NET_IPV6_RTR_PROBE_INTERVAL=21, __NET_IPV6_MAX }; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 51edba5fea26..e7add61e6e39 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -169,6 +169,7 @@ struct ipv6_devconf ipv6_devconf = { .accept_ra_pinfo = 1, #ifdef CONFIG_IPV6_ROUTER_PREF .accept_ra_rtr_pref = 1, + .rtr_probe_interval = 60 * HZ, #endif }; @@ -195,6 +196,7 @@ static struct ipv6_devconf ipv6_devconf_dflt = { .accept_ra_pinfo = 1, #ifdef CONFIG_IPV6_ROUTER_PREF .accept_ra_rtr_pref = 1, + .rtr_probe_interval = 60 * HZ, #endif }; @@ -3130,6 +3132,7 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo; #ifdef CONFIG_IPV6_ROUTER_PREF array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref; + array[DEVCONF_RTR_PROBE_INTERVAL] = cnf->rtr_probe_interval; #endif } @@ -3608,6 +3611,15 @@ static struct addrconf_sysctl_table .mode = 0644, .proc_handler = &proc_dointvec, }, + { + .ctl_name = NET_IPV6_RTR_PROBE_INTERVAL, + .procname = "router_probe_interval", + .data = &ipv6_devconf.rtr_probe_interval, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + .strategy = &sysctl_jiffies, + }, #endif { .ctl_name = 0, /* sentinel */ diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 8ba8900c0a5f..c797b9bbb7d1 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -234,7 +234,7 @@ static void rt6_probe(struct rt6_info *rt) return; read_lock_bh(&neigh->lock); if (!(neigh->nud_state & NUD_VALID) && - time_after(jiffies, neigh->updated + 60 * HZ)) { + time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) { struct in6_addr mcaddr; struct in6_addr *target; -- cgit v1.2.3 From 70ceb4f53929f73746be72f73707cd9f8753e2fc Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Mon, 20 Mar 2006 17:06:24 -0800 Subject: [IPV6]: ROUTE: Add experimental support for Route Information Option in RA (RFC4191). Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- include/linux/ipv6_route.h | 2 + include/net/ip6_route.h | 21 +++++++ include/net/ndisc.h | 2 + net/ipv6/Kconfig | 8 +++ net/ipv6/ndisc.c | 25 ++++++++- net/ipv6/route.c | 134 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 191 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/ipv6_route.h b/include/linux/ipv6_route.h index f4b085c91608..b323ff577967 100644 --- a/include/linux/ipv6_route.h +++ b/include/linux/ipv6_route.h @@ -23,6 +23,8 @@ #define RTF_NONEXTHOP 0x00200000 /* route with no nexthop */ #define RTF_EXPIRES 0x00400000 +#define RTF_ROUTEINFO 0x00800000 /* route information - RA */ + #define RTF_CACHE 0x01000000 /* cache entry */ #define RTF_FLOW 0x02000000 /* flow significant route */ #define RTF_POLICY 0x04000000 /* policy route */ diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 50161322b828..a398ae5e30f9 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -7,6 +7,23 @@ #define IP6_RT_PRIO_KERN 512 #define IP6_RT_FLOW_MASK 0x00ff +struct route_info { + __u8 type; + __u8 length; + __u8 prefix_len; +#if defined(__BIG_ENDIAN_BITFIELD) + __u8 reserved_h:3, + route_pref:2, + reserved_l:3; +#elif defined(__LITTLE_ENDIAN_BITFIELD) + __u8 reserved_l:3, + route_pref:2, + reserved_h:3; +#endif + __u32 lifetime; + __u8 prefix[0]; /* 0,8 or 16 */ +}; + #ifdef __KERNEL__ #include @@ -92,6 +109,10 @@ extern struct rt6_info * rt6_add_dflt_router(struct in6_addr *gwaddr, extern void rt6_purge_dflt_routers(void); +extern int rt6_route_rcv(struct net_device *dev, + u8 *opt, int len, + struct in6_addr *gwaddr); + extern void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr, struct neighbour *neigh, diff --git a/include/net/ndisc.h b/include/net/ndisc.h index bbac87eeb422..91fa271a0064 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h @@ -22,6 +22,8 @@ enum { ND_OPT_PREFIX_INFO = 3, /* RFC2461 */ ND_OPT_REDIRECT_HDR = 4, /* RFC2461 */ ND_OPT_MTU = 5, /* RFC2461 */ + __ND_OPT_ARRAY_MAX, + ND_OPT_ROUTE_INFO = 24, /* RFC4191 */ __ND_OPT_MAX }; diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index c456ead8a4a3..e6f83b6a2b76 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig @@ -49,6 +49,14 @@ config IPV6_ROUTER_PREF If unsure, say N. +config IPV6_ROUTE_INFO + bool "IPv6: Route Information (RFC 4191) support (EXPERIMENTAL)" + depends on IPV6_ROUTER_PREF && EXPERIMENTAL + ---help--- + This is experimental support of Route Information. + + If unsure, say N. + config INET6_AH tristate "IPv6: AH transformation" depends on IPV6 diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index f4462ee33024..1f6256909674 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -156,7 +156,11 @@ struct neigh_table nd_tbl = { /* ND options */ struct ndisc_options { - struct nd_opt_hdr *nd_opt_array[__ND_OPT_MAX]; + struct nd_opt_hdr *nd_opt_array[__ND_OPT_ARRAY_MAX]; +#ifdef CONFIG_IPV6_ROUTE_INFO + struct nd_opt_hdr *nd_opts_ri; + struct nd_opt_hdr *nd_opts_ri_end; +#endif }; #define nd_opts_src_lladdr nd_opt_array[ND_OPT_SOURCE_LL_ADDR] @@ -255,6 +259,13 @@ static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, if (ndopts->nd_opt_array[nd_opt->nd_opt_type] == 0) ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt; break; +#ifdef CONFIG_IPV6_ROUTE_INFO + case ND_OPT_ROUTE_INFO: + ndopts->nd_opts_ri_end = nd_opt; + if (!ndopts->nd_opts_ri) + ndopts->nd_opts_ri = nd_opt; + break; +#endif default: /* * Unknown options must be silently ignored, @@ -1202,6 +1213,18 @@ skip_defrtr: NEIGH_UPDATE_F_ISROUTER); } +#ifdef CONFIG_IPV6_ROUTE_INFO + if (ndopts.nd_opts_ri) { + struct nd_opt_hdr *p; + for (p = ndopts.nd_opts_ri; + p; + p = ndisc_next_option(p, ndopts.nd_opts_ri_end)) { + rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3, + &skb->nh.ipv6h->saddr); + } + } +#endif + if (in6_dev->cnf.accept_ra_pinfo && ndopts.nd_opts_pi) { struct nd_opt_hdr *p; for (p = ndopts.nd_opts_pi; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c797b9bbb7d1..0f30ee3d94ea 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -98,6 +98,14 @@ static int ip6_pkt_discard_out(struct sk_buff *skb); static void ip6_link_failure(struct sk_buff *skb); static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu); +#ifdef CONFIG_IPV6_ROUTE_INFO +static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixlen, + struct in6_addr *gwaddr, int ifindex, + unsigned pref); +static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixlen, + struct in6_addr *gwaddr, int ifindex); +#endif + static struct dst_ops ip6_dst_ops = { .family = AF_INET6, .protocol = __constant_htons(ETH_P_IPV6), @@ -346,6 +354,84 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif, return (match ? match : &ip6_null_entry); } +#ifdef CONFIG_IPV6_ROUTE_INFO +int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, + struct in6_addr *gwaddr) +{ + struct route_info *rinfo = (struct route_info *) opt; + struct in6_addr prefix_buf, *prefix; + unsigned int pref; + u32 lifetime; + struct rt6_info *rt; + + if (len < sizeof(struct route_info)) { + return -EINVAL; + } + + /* Sanity check for prefix_len and length */ + if (rinfo->length > 3) { + return -EINVAL; + } else if (rinfo->prefix_len > 128) { + return -EINVAL; + } else if (rinfo->prefix_len > 64) { + if (rinfo->length < 2) { + return -EINVAL; + } + } else if (rinfo->prefix_len > 0) { + if (rinfo->length < 1) { + return -EINVAL; + } + } + + pref = rinfo->route_pref; + if (pref == ICMPV6_ROUTER_PREF_INVALID) + pref = ICMPV6_ROUTER_PREF_MEDIUM; + + lifetime = htonl(rinfo->lifetime); + if (lifetime == 0xffffffff) { + /* infinity */ + } else if (lifetime > 0x7fffffff/HZ) { + /* Avoid arithmetic overflow */ + lifetime = 0x7fffffff/HZ - 1; + } + + if (rinfo->length == 3) + prefix = (struct in6_addr *)rinfo->prefix; + else { + /* this function is safe */ + ipv6_addr_prefix(&prefix_buf, + (struct in6_addr *)rinfo->prefix, + rinfo->prefix_len); + prefix = &prefix_buf; + } + + rt = rt6_get_route_info(prefix, rinfo->prefix_len, gwaddr, dev->ifindex); + + if (rt && !lifetime) { + ip6_del_rt(rt, NULL, NULL, NULL); + rt = NULL; + } + + if (!rt && lifetime) + rt = rt6_add_route_info(prefix, rinfo->prefix_len, gwaddr, dev->ifindex, + pref); + else if (rt) + rt->rt6i_flags = RTF_ROUTEINFO | + (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref); + + if (rt) { + if (lifetime == 0xffffffff) { + rt->rt6i_flags &= ~RTF_EXPIRES; + } else { + rt->rt6i_expires = jiffies + HZ * lifetime; + rt->rt6i_flags |= RTF_EXPIRES; + } + dst_release(&rt->u.dst); + } + return 0; +} +#endif + struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, int oif, int strict) { @@ -1277,6 +1363,54 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) return rt; } +#ifdef CONFIG_IPV6_ROUTE_INFO +static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixlen, + struct in6_addr *gwaddr, int ifindex) +{ + struct fib6_node *fn; + struct rt6_info *rt = NULL; + + write_lock_bh(&rt6_lock); + fn = fib6_locate(&ip6_routing_table, prefix ,prefixlen, NULL, 0); + if (!fn) + goto out; + + for (rt = fn->leaf; rt; rt = rt->u.next) { + if (rt->rt6i_dev->ifindex != ifindex) + continue; + if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY)) + continue; + if (!ipv6_addr_equal(&rt->rt6i_gateway, gwaddr)) + continue; + dst_hold(&rt->u.dst); + break; + } +out: + write_unlock_bh(&rt6_lock); + return rt; +} + +static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixlen, + struct in6_addr *gwaddr, int ifindex, + unsigned pref) +{ + struct in6_rtmsg rtmsg; + + memset(&rtmsg, 0, sizeof(rtmsg)); + rtmsg.rtmsg_type = RTMSG_NEWROUTE; + ipv6_addr_copy(&rtmsg.rtmsg_dst, prefix); + rtmsg.rtmsg_dst_len = prefixlen; + ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr); + rtmsg.rtmsg_metric = 1024; + rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO | RTF_UP | RTF_PREF(pref); + rtmsg.rtmsg_ifindex = ifindex; + + ip6_route_add(&rtmsg, NULL, NULL, NULL); + + return rt6_get_route_info(prefix, prefixlen, gwaddr, ifindex); +} +#endif + struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *dev) { struct rt6_info *rt; -- cgit v1.2.3 From 09c884d4c3b45cda904c2291d4723074ff523611 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Mon, 20 Mar 2006 17:07:03 -0800 Subject: [IPV6]: ROUTE: Add accept_ra_rt_info_max_plen sysctl. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 9 +++++++++ include/linux/ipv6.h | 4 ++++ include/linux/sysctl.h | 1 + net/ipv6/addrconf.c | 19 +++++++++++++++++++ net/ipv6/ndisc.c | 4 +++- 5 files changed, 36 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 88efed0a533f..35aed1c6dd98 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -729,6 +729,15 @@ accept_ra_pinfo - BOOLEAN Functional default: enabled if accept_ra is enabled. disabled if accept_ra is disabled. +accept_ra_rt_info_max_plen - INTEGER + Maximum prefix length of Route Information in RA. + + Route Information w/ prefix larger than or equal to this + variable shall be ignored. + + Functional default: 0 if accept_ra_rtr_pref is enabled. + -1 if accept_ra_rtr_pref is disabled. + accept_ra_rtr_pref - BOOLEAN Accept Router Preference in RA. diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index c609cc702375..1263d8cb3c18 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -150,6 +150,9 @@ struct ipv6_devconf { #ifdef CONFIG_IPV6_ROUTER_PREF __s32 accept_ra_rtr_pref; __s32 rtr_probe_interval; +#ifdef CONFIG_IPV6_ROUTE_INFO + __s32 accept_ra_rt_info_max_plen; +#endif #endif void *sysctl; }; @@ -177,6 +180,7 @@ enum { DEVCONF_ACCEPT_RA_PINFO, DEVCONF_ACCEPT_RA_RTR_PREF, DEVCONF_RTR_PROBE_INTERVAL, + DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN, DEVCONF_MAX }; diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index f49488ffefef..8ad4beab2888 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -535,6 +535,7 @@ enum { NET_IPV6_ACCEPT_RA_PINFO=19, NET_IPV6_ACCEPT_RA_RTR_PREF=20, NET_IPV6_RTR_PROBE_INTERVAL=21, + NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN=22, __NET_IPV6_MAX }; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e7add61e6e39..eb82cd5df8c6 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -170,6 +170,9 @@ struct ipv6_devconf ipv6_devconf = { #ifdef CONFIG_IPV6_ROUTER_PREF .accept_ra_rtr_pref = 1, .rtr_probe_interval = 60 * HZ, +#ifdef CONFIG_IPV6_ROUTE_INFO + .accept_ra_rt_info_max_plen = 0, +#endif #endif }; @@ -197,6 +200,9 @@ static struct ipv6_devconf ipv6_devconf_dflt = { #ifdef CONFIG_IPV6_ROUTER_PREF .accept_ra_rtr_pref = 1, .rtr_probe_interval = 60 * HZ, +#ifdef CONFIG_IPV6_ROUTE_INFO + .accept_ra_rt_info_max_plen = 0, +#endif #endif }; @@ -3133,6 +3139,9 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, #ifdef CONFIG_IPV6_ROUTER_PREF array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref; array[DEVCONF_RTR_PROBE_INTERVAL] = cnf->rtr_probe_interval; +#ifdef CONFIV_IPV6_ROUTE_INFO + array[DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN] = cnf->accept_ra_rt_info_max_plen; +#endif #endif } @@ -3620,6 +3629,16 @@ static struct addrconf_sysctl_table .proc_handler = &proc_dointvec_jiffies, .strategy = &sysctl_jiffies, }, +#ifdef CONFIV_IPV6_ROUTE_INFO + { + .ctl_name = NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN, + .procname = "accept_ra_rt_info_max_plen", + .data = &ipv6_devconf.accept_ra_rt_info_max_plen, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#endif #endif { .ctl_name = 0, /* sentinel */ diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 1f6256909674..dfa20d3be9b6 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1214,11 +1214,13 @@ skip_defrtr: } #ifdef CONFIG_IPV6_ROUTE_INFO - if (ndopts.nd_opts_ri) { + if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) { struct nd_opt_hdr *p; for (p = ndopts.nd_opts_ri; p; p = ndisc_next_option(p, ndopts.nd_opts_ri_end)) { + if (((struct route_info *)p)->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen) + continue; rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3, &skb->nh.ipv6h->saddr); } -- cgit v1.2.3 From b00055aacdb172c05067612278ba27265fcd05ce Mon Sep 17 00:00:00 2001 From: Stefan Rompf Date: Mon, 20 Mar 2006 17:09:11 -0800 Subject: [NET] core: add RFC2863 operstate this patch adds a dormant flag to network devices, RFC2863 operstate derived from these flags and possibility for userspace interaction. It allows drivers to signal that a device is unusable for user traffic without disabling queueing (and therefore the possibility for protocol establishment traffic to flow) and a userspace supplicant (WPA, 802.1X) to mark a device unusable without changes to the driver. It is the result of our long discussion. However I must admit that it represents what Jamal and I agreed on with compromises towards Krzysztof, but Thomas and Krzysztof still disagree with some parts. Anyway I think it should be applied. Signed-off-by: Stefan Rompf Signed-off-by: David S. Miller --- include/linux/if.h | 26 +++++++++++++++++++++--- include/linux/netdevice.h | 35 +++++++++++++++++++++++++++++++-- include/linux/rtnetlink.h | 2 ++ net/core/dev.c | 14 ++++++++++--- net/core/link_watch.c | 40 +++++++++++++++++++++++++++++++++++++ net/core/net-sysfs.c | 41 ++++++++++++++++++++++++++++++++++++++ net/core/rtnetlink.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 200 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/linux/if.h b/include/linux/if.h index 12c6f6d157c3..374e20ad8b0d 100644 --- a/include/linux/if.h +++ b/include/linux/if.h @@ -33,7 +33,7 @@ #define IFF_LOOPBACK 0x8 /* is a loopback net */ #define IFF_POINTOPOINT 0x10 /* interface is has p-p link */ #define IFF_NOTRAILERS 0x20 /* avoid use of trailers */ -#define IFF_RUNNING 0x40 /* interface running and carrier ok */ +#define IFF_RUNNING 0x40 /* interface RFC2863 OPER_UP */ #define IFF_NOARP 0x80 /* no ARP protocol */ #define IFF_PROMISC 0x100 /* receive all packets */ #define IFF_ALLMULTI 0x200 /* receive all multicast packets*/ @@ -43,12 +43,16 @@ #define IFF_MULTICAST 0x1000 /* Supports multicast */ -#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_MASTER|IFF_SLAVE|IFF_RUNNING) - #define IFF_PORTSEL 0x2000 /* can set media type */ #define IFF_AUTOMEDIA 0x4000 /* auto media select active */ #define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/ +#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ +#define IFF_DORMANT 0x20000 /* driver signals dormant */ + +#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|\ + IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT) + /* Private (from user) interface flags (netdevice->priv_flags). */ #define IFF_802_1Q_VLAN 0x1 /* 802.1Q VLAN device. */ #define IFF_EBRIDGE 0x2 /* Ethernet bridging device. */ @@ -83,6 +87,22 @@ #define IF_PROTO_FR_ETH_PVC 0x200B #define IF_PROTO_RAW 0x200C /* RAW Socket */ +/* RFC 2863 operational status */ +enum { + IF_OPER_UNKNOWN, + IF_OPER_NOTPRESENT, + IF_OPER_DOWN, + IF_OPER_LOWERLAYERDOWN, + IF_OPER_TESTING, + IF_OPER_DORMANT, + IF_OPER_UP, +}; + +/* link modes */ +enum { + IF_LINK_MODE_DEFAULT, + IF_LINK_MODE_DORMANT, /* limit upward transition to dormant */ +}; /* * Device mapping structure. I'd just gone off and designed a diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7fda03d338d1..b825be201bce 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -230,7 +230,8 @@ enum netdev_state_t __LINK_STATE_SCHED, __LINK_STATE_NOCARRIER, __LINK_STATE_RX_SCHED, - __LINK_STATE_LINKWATCH_PENDING + __LINK_STATE_LINKWATCH_PENDING, + __LINK_STATE_DORMANT, }; @@ -335,11 +336,14 @@ struct net_device */ - unsigned short flags; /* interface flags (a la BSD) */ + unsigned int flags; /* interface flags (a la BSD) */ unsigned short gflags; unsigned short priv_flags; /* Like 'flags' but invisible to userspace. */ unsigned short padded; /* How much padding added by alloc_netdev() */ + unsigned char operstate; /* RFC2863 operstate */ + unsigned char link_mode; /* mapping policy to operstate */ + unsigned mtu; /* interface MTU value */ unsigned short type; /* interface hardware type */ unsigned short hard_header_len; /* hardware hdr length */ @@ -714,6 +718,10 @@ static inline void dev_put(struct net_device *dev) /* Carrier loss detection, dial on demand. The functions netif_carrier_on * and _off may be called from IRQ context, but it is caller * who is responsible for serialization of these calls. + * + * The name carrier is inappropriate, these functions should really be + * called netif_lowerlayer_*() because they represent the state of any + * kind of lower layer not just hardware media. */ extern void linkwatch_fire_event(struct net_device *dev); @@ -729,6 +737,29 @@ extern void netif_carrier_on(struct net_device *dev); extern void netif_carrier_off(struct net_device *dev); +static inline void netif_dormant_on(struct net_device *dev) +{ + if (!test_and_set_bit(__LINK_STATE_DORMANT, &dev->state)) + linkwatch_fire_event(dev); +} + +static inline void netif_dormant_off(struct net_device *dev) +{ + if (test_and_clear_bit(__LINK_STATE_DORMANT, &dev->state)) + linkwatch_fire_event(dev); +} + +static inline int netif_dormant(const struct net_device *dev) +{ + return test_bit(__LINK_STATE_DORMANT, &dev->state); +} + + +static inline int netif_oper_up(const struct net_device *dev) { + return (dev->operstate == IF_OPER_UP || + dev->operstate == IF_OPER_UNKNOWN /* backward compat */); +} + /* Hot-plugging. */ static inline int netif_device_present(struct net_device *dev) { diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index d50482ba27fe..edccefb45188 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -733,6 +733,8 @@ enum #define IFLA_MAP IFLA_MAP IFLA_WEIGHT, #define IFLA_WEIGHT IFLA_WEIGHT + IFLA_OPERSTATE, + IFLA_LINKMODE, __IFLA_MAX }; diff --git a/net/core/dev.c b/net/core/dev.c index ef56c035d44e..8763c99fcb84 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2174,12 +2174,20 @@ unsigned dev_get_flags(const struct net_device *dev) flags = (dev->flags & ~(IFF_PROMISC | IFF_ALLMULTI | - IFF_RUNNING)) | + IFF_RUNNING | + IFF_LOWER_UP | + IFF_DORMANT)) | (dev->gflags & (IFF_PROMISC | IFF_ALLMULTI)); - if (netif_running(dev) && netif_carrier_ok(dev)) - flags |= IFF_RUNNING; + if (netif_running(dev)) { + if (netif_oper_up(dev)) + flags |= IFF_RUNNING; + if (netif_carrier_ok(dev)) + flags |= IFF_LOWER_UP; + if (netif_dormant(dev)) + flags |= IFF_DORMANT; + } return flags; } diff --git a/net/core/link_watch.c b/net/core/link_watch.c index d43d1201275c..e82a451d330b 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -49,6 +49,45 @@ struct lw_event { /* Avoid kmalloc() for most systems */ static struct lw_event singleevent; +static unsigned char default_operstate(const struct net_device *dev) +{ + if (!netif_carrier_ok(dev)) + return (dev->ifindex != dev->iflink ? + IF_OPER_LOWERLAYERDOWN : IF_OPER_DOWN); + + if (netif_dormant(dev)) + return IF_OPER_DORMANT; + + return IF_OPER_UP; +} + + +static void rfc2863_policy(struct net_device *dev) +{ + unsigned char operstate = default_operstate(dev); + + if (operstate == dev->operstate) + return; + + write_lock_bh(&dev_base_lock); + + switch(dev->link_mode) { + case IF_LINK_MODE_DORMANT: + if (operstate == IF_OPER_UP) + operstate = IF_OPER_DORMANT; + break; + + case IF_LINK_MODE_DEFAULT: + default: + break; + }; + + dev->operstate = operstate; + + write_unlock_bh(&dev_base_lock); +} + + /* Must be called with the rtnl semaphore held */ void linkwatch_run_queue(void) { @@ -74,6 +113,7 @@ void linkwatch_run_queue(void) */ clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state); + rfc2863_policy(dev); if (dev->flags & IFF_UP) { if (netif_carrier_ok(dev)) { WARN_ON(dev->qdisc_sleeping == &noop_qdisc); diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index e8b2acbc8ea2..21b68464cabb 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -91,6 +91,7 @@ NETDEVICE_SHOW(iflink, fmt_dec); NETDEVICE_SHOW(ifindex, fmt_dec); NETDEVICE_SHOW(features, fmt_long_hex); NETDEVICE_SHOW(type, fmt_dec); +NETDEVICE_SHOW(link_mode, fmt_dec); /* use same locking rules as GIFHWADDR ioctl's */ static ssize_t format_addr(char *buf, const unsigned char *addr, int len) @@ -133,6 +134,43 @@ static ssize_t show_carrier(struct class_device *dev, char *buf) return -EINVAL; } +static ssize_t show_dormant(struct class_device *dev, char *buf) +{ + struct net_device *netdev = to_net_dev(dev); + + if (netif_running(netdev)) + return sprintf(buf, fmt_dec, !!netif_dormant(netdev)); + + return -EINVAL; +} + +static const char *operstates[] = { + "unknown", + "notpresent", /* currently unused */ + "down", + "lowerlayerdown", + "testing", /* currently unused */ + "dormant", + "up" +}; + +static ssize_t show_operstate(struct class_device *dev, char *buf) +{ + const struct net_device *netdev = to_net_dev(dev); + unsigned char operstate; + + read_lock(&dev_base_lock); + operstate = netdev->operstate; + if (!netif_running(netdev)) + operstate = IF_OPER_DOWN; + read_unlock(&dev_base_lock); + + if (operstate >= sizeof(operstates)) + return -EINVAL; /* should not happen */ + + return sprintf(buf, "%s\n", operstates[operstate]); +} + /* read-write attributes */ NETDEVICE_SHOW(mtu, fmt_dec); @@ -190,9 +228,12 @@ static struct class_device_attribute net_class_attributes[] = { __ATTR(ifindex, S_IRUGO, show_ifindex, NULL), __ATTR(features, S_IRUGO, show_features, NULL), __ATTR(type, S_IRUGO, show_type, NULL), + __ATTR(link_mode, S_IRUGO, show_link_mode, NULL), __ATTR(address, S_IRUGO, show_address, NULL), __ATTR(broadcast, S_IRUGO, show_broadcast, NULL), __ATTR(carrier, S_IRUGO, show_carrier, NULL), + __ATTR(dormant, S_IRUGO, show_dormant, NULL), + __ATTR(operstate, S_IRUGO, show_operstate, NULL), __ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu), __ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags), __ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len, diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index eca2976abb25..1c15a907066f 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -179,6 +179,33 @@ rtattr_failure: } +static void set_operstate(struct net_device *dev, unsigned char transition) +{ + unsigned char operstate = dev->operstate; + + switch(transition) { + case IF_OPER_UP: + if ((operstate == IF_OPER_DORMANT || + operstate == IF_OPER_UNKNOWN) && + !netif_dormant(dev)) + operstate = IF_OPER_UP; + break; + + case IF_OPER_DORMANT: + if (operstate == IF_OPER_UP || + operstate == IF_OPER_UNKNOWN) + operstate = IF_OPER_DORMANT; + break; + }; + + if (dev->operstate != operstate) { + write_lock_bh(&dev_base_lock); + dev->operstate = operstate; + write_unlock_bh(&dev_base_lock); + netdev_state_change(dev); + } +} + static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, int type, u32 pid, u32 seq, u32 change, unsigned int flags) @@ -208,6 +235,13 @@ static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, RTA_PUT(skb, IFLA_WEIGHT, sizeof(weight), &weight); } + if (1) { + u8 operstate = netif_running(dev)?dev->operstate:IF_OPER_DOWN; + u8 link_mode = dev->link_mode; + RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate); + RTA_PUT(skb, IFLA_LINKMODE, sizeof(link_mode), &link_mode); + } + if (1) { struct rtnl_link_ifmap map = { .mem_start = dev->mem_start, @@ -399,6 +433,22 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) dev->weight = *((u32 *) RTA_DATA(ida[IFLA_WEIGHT - 1])); } + if (ida[IFLA_OPERSTATE - 1]) { + if (ida[IFLA_OPERSTATE - 1]->rta_len != RTA_LENGTH(sizeof(u8))) + goto out; + + set_operstate(dev, *((u8 *) RTA_DATA(ida[IFLA_OPERSTATE - 1]))); + } + + if (ida[IFLA_LINKMODE - 1]) { + if (ida[IFLA_LINKMODE - 1]->rta_len != RTA_LENGTH(sizeof(u8))) + goto out; + + write_lock_bh(&dev_base_lock); + dev->link_mode = *((u8 *) RTA_DATA(ida[IFLA_LINKMODE - 1])); + write_unlock_bh(&dev_base_lock); + } + if (ifm->ifi_index >= 0 && ida[IFLA_IFNAME - 1]) { char ifname[IFNAMSIZ]; -- cgit v1.2.3 From 77d2ca350018c507815f5d38a40ffb597eb9ae25 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 20 Mar 2006 17:12:12 -0800 Subject: [NET]: Reduce size of struct sk_buff on 64 bit architectures Move skb->nf_mark next to skb->tc_index to remove a 4 byte hole between skb->nfmark and skb->nfct and another one between skb->users and skb->head when CONFIG_NETFILTER, CONFIG_NET_SCHED and CONFIG_NET_CLS_ACT are enabled. For all other combinations the size stays the same. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/skbuff.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index ad7cc22bd424..838ce0fdcef7 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -270,7 +270,6 @@ struct sk_buff { void (*destructor)(struct sk_buff *skb); #ifdef CONFIG_NETFILTER - __u32 nfmark; struct nf_conntrack *nfct; #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) struct sk_buff *nfct_reasm; @@ -278,6 +277,7 @@ struct sk_buff { #ifdef CONFIG_BRIDGE_NETFILTER struct nf_bridge_info *nf_bridge; #endif + __u32 nfmark; #endif /* CONFIG_NETFILTER */ #ifdef CONFIG_NET_SCHED __u16 tc_index; /* traffic control index */ -- cgit v1.2.3 From 5ee956125a780baf15f2c1d09f2cbf8adcf598fe Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 20 Mar 2006 17:14:12 -0800 Subject: [NETFILTER] NAT sequence adjustment: Save eight bytes per conntrack This patch reduces the size of 'struct ip_conntrack' on systems with NAT by eight bytes. The sequence number delta values can be int16_t, since we only support one sequence number modification per window anyway, and one such modification is not going to exceed 32kB ;) Signed-off-by: Harald Welte Signed-off-by: David S. Miller --- include/linux/netfilter_ipv4/ip_nat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/netfilter_ipv4/ip_nat.h b/include/linux/netfilter_ipv4/ip_nat.h index 41a107de17cf..e9f5ed1d9f68 100644 --- a/include/linux/netfilter_ipv4/ip_nat.h +++ b/include/linux/netfilter_ipv4/ip_nat.h @@ -23,7 +23,7 @@ struct ip_nat_seq { * modification (if any) */ u_int32_t correction_pos; /* sequence number offset before and after last modification */ - int32_t offset_before, offset_after; + int16_t offset_before, offset_after; }; /* Single range specification. */ -- cgit v1.2.3 From 0af5f6c1eba4a18e6b2ed518b589927d778c6c16 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 20 Mar 2006 17:15:11 -0800 Subject: [NETFILTER] nfnetlink_log: add sequence numbers for log events By using a sequence number for every logged netfilter event, we can determine from userspace whether logging information was lots somewhere downstream. The user has a choice of either having per-instance local sequence counters, or using a global sequence counter, or both. Signed-off-by: Harald Welte Signed-off-by: David S. Miller --- include/linux/netfilter/nfnetlink_log.h | 6 +++++ net/netfilter/nfnetlink_log.c | 46 +++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) (limited to 'include') diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h index b04b03880595..a7497c7436df 100644 --- a/include/linux/netfilter/nfnetlink_log.h +++ b/include/linux/netfilter/nfnetlink_log.h @@ -47,6 +47,8 @@ enum nfulnl_attr_type { NFULA_PAYLOAD, /* opaque data payload */ NFULA_PREFIX, /* string prefix */ NFULA_UID, /* user id of socket */ + NFULA_SEQ, /* instance-local sequence number */ + NFULA_SEQ_GLOBAL, /* global sequence number */ __NFULA_MAX }; @@ -77,6 +79,7 @@ enum nfulnl_attr_config { NFULA_CFG_NLBUFSIZ, /* u_int32_t buffer size */ NFULA_CFG_TIMEOUT, /* u_int32_t in 1/100 s */ NFULA_CFG_QTHRESH, /* u_int32_t */ + NFULA_CFG_FLAGS, /* u_int16_t */ __NFULA_CFG_MAX }; #define NFULA_CFG_MAX (__NFULA_CFG_MAX -1) @@ -85,4 +88,7 @@ enum nfulnl_attr_config { #define NFULNL_COPY_META 0x01 #define NFULNL_COPY_PACKET 0x02 +#define NFULNL_CFG_F_SEQ 0x0001 +#define NFULNL_CFG_F_SEQ_GLOBAL 0x0002 + #endif /* _NFNETLINK_LOG_H */ diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 3b3c781b40c0..54cbbaa712dc 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -11,6 +11,10 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * + * 2006-01-26 Harald Welte + * - Add optional local and global sequence number to detect lost + * events from userspace + * */ #include #include @@ -68,11 +72,14 @@ struct nfulnl_instance { unsigned int nlbufsiz; /* netlink buffer allocation size */ unsigned int qthreshold; /* threshold of the queue */ u_int32_t copy_range; + u_int32_t seq; /* instance-local sequential counter */ u_int16_t group_num; /* number of this queue */ + u_int16_t flags; u_int8_t copy_mode; }; static DEFINE_RWLOCK(instances_lock); +static atomic_t global_seq; #define INSTANCE_BUCKETS 16 static struct hlist_head instance_table[INSTANCE_BUCKETS]; @@ -310,6 +317,16 @@ nfulnl_set_qthresh(struct nfulnl_instance *inst, u_int32_t qthresh) return 0; } +static int +nfulnl_set_flags(struct nfulnl_instance *inst, u_int16_t flags) +{ + spin_lock_bh(&inst->lock); + inst->flags = ntohs(flags); + spin_unlock_bh(&inst->lock); + + return 0; +} + static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size, unsigned int pkt_size) { @@ -377,6 +394,8 @@ static void nfulnl_timer(unsigned long data) spin_unlock_bh(&inst->lock); } +/* This is an inline function, we don't really care about a long + * list of arguments */ static inline int __build_packet_message(struct nfulnl_instance *inst, const struct sk_buff *skb, @@ -515,6 +534,17 @@ __build_packet_message(struct nfulnl_instance *inst, read_unlock_bh(&skb->sk->sk_callback_lock); } + /* local sequence number */ + if (inst->flags & NFULNL_CFG_F_SEQ) { + tmp_uint = htonl(inst->seq++); + NFA_PUT(inst->skb, NFULA_SEQ, sizeof(tmp_uint), &tmp_uint); + } + /* global sequence number */ + if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) { + tmp_uint = atomic_inc_return(&global_seq); + NFA_PUT(inst->skb, NFULA_SEQ_GLOBAL, sizeof(tmp_uint), &tmp_uint); + } + if (data_len) { struct nfattr *nfa; int size = NFA_LENGTH(data_len); @@ -607,6 +637,11 @@ nfulnl_log_packet(unsigned int pf, spin_lock_bh(&inst->lock); + if (inst->flags & NFULNL_CFG_F_SEQ) + size += NFA_SPACE(sizeof(u_int32_t)); + if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) + size += NFA_SPACE(sizeof(u_int32_t)); + qthreshold = inst->qthreshold; /* per-rule qthreshold overrides per-instance */ if (qthreshold > li->u.ulog.qthreshold) @@ -736,10 +771,14 @@ static const int nfula_min[NFULA_MAX] = { [NFULA_TIMESTAMP-1] = sizeof(struct nfulnl_msg_packet_timestamp), [NFULA_IFINDEX_INDEV-1] = sizeof(u_int32_t), [NFULA_IFINDEX_OUTDEV-1]= sizeof(u_int32_t), + [NFULA_IFINDEX_PHYSINDEV-1] = sizeof(u_int32_t), + [NFULA_IFINDEX_PHYSOUTDEV-1] = sizeof(u_int32_t), [NFULA_HWADDR-1] = sizeof(struct nfulnl_msg_packet_hw), [NFULA_PAYLOAD-1] = 0, [NFULA_PREFIX-1] = 0, [NFULA_UID-1] = sizeof(u_int32_t), + [NFULA_SEQ-1] = sizeof(u_int32_t), + [NFULA_SEQ_GLOBAL-1] = sizeof(u_int32_t), }; static const int nfula_cfg_min[NFULA_CFG_MAX] = { @@ -748,6 +787,7 @@ static const int nfula_cfg_min[NFULA_CFG_MAX] = { [NFULA_CFG_TIMEOUT-1] = sizeof(u_int32_t), [NFULA_CFG_QTHRESH-1] = sizeof(u_int32_t), [NFULA_CFG_NLBUFSIZ-1] = sizeof(u_int32_t), + [NFULA_CFG_FLAGS-1] = sizeof(u_int16_t), }; static int @@ -859,6 +899,12 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, nfulnl_set_qthresh(inst, ntohl(qthresh)); } + if (nfula[NFULA_CFG_FLAGS-1]) { + u_int16_t flags = + *(u_int16_t *)NFA_DATA(nfula[NFULA_CFG_FLAGS-1]); + nfulnl_set_flags(inst, ntohl(flags)); + } + out_put: instance_put(inst); return ret; -- cgit v1.2.3 From d8dcffee860d6b63996923b10f07c91d3d6c2fab Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 20 Mar 2006 17:18:05 -0800 Subject: [LIST]: Introduce list_for_each_entry_safe_from For iterate over list of given type from existing point safe against removal of list entry. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/linux/list.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'include') diff --git a/include/linux/list.h b/include/linux/list.h index 47208bd99f9e..beb6e48e116f 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -437,6 +437,19 @@ static inline void list_splice_init(struct list_head *list, &pos->member != (head); \ pos = n, n = list_entry(n->member.next, typeof(*n), member)) +/** + * list_for_each_entry_safe_from - iterate over list of given type + * from existing point safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe_from(pos, n, head, member) \ + for (n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + /** * list_for_each_entry_safe_reverse - iterate backwards over list of given type safe against * removal of list entry -- cgit v1.2.3 From e229c2fb3370a0c4ebac06cad67ce1cb35abcfe6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 20 Mar 2006 17:19:17 -0800 Subject: [LIST]: Introduce list_for_each_entry_from For iterating over list of given type continuing from existing point. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/linux/list.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'include') diff --git a/include/linux/list.h b/include/linux/list.h index beb6e48e116f..67258b47e9ca 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -410,6 +410,17 @@ static inline void list_splice_init(struct list_head *list, prefetch(pos->member.next), &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member)) +/** + * list_for_each_entry_from - iterate over list of given type + * continuing from existing point + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_from(pos, head, member) \ + for (; prefetch(pos->member.next), &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + /** * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry * @pos: the type * to use as a loop counter. -- cgit v1.2.3 From 2a91aa3967398fb94eccc8da67c82bce9f67afdf Mon Sep 17 00:00:00 2001 From: Andrea Bittau Date: Mon, 20 Mar 2006 17:41:47 -0800 Subject: [DCCP] CCID2: Initial CCID2 (TCP-Like) implementation Original work by Andrea Bittau, Arnaldo Melo cleaned up and fixed several issues on the merge process. For now CCID2 was turned the default for all SOCK_DCCP connections, but this will be remedied soon with the merge of the feature negotiation code. Signed-off-by: Andrea Bittau Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/linux/dccp.h | 8 +- net/dccp/Kconfig | 4 + net/dccp/ccids/Kconfig | 39 ++- net/dccp/ccids/Makefile | 4 + net/dccp/ccids/ccid2.c | 838 ++++++++++++++++++++++++++++++++++++++++++++++++ net/dccp/ccids/ccid2.h | 69 ++++ net/dccp/ipv4.c | 1 + 7 files changed, 957 insertions(+), 6 deletions(-) create mode 100644 net/dccp/ccids/ccid2.c create mode 100644 net/dccp/ccids/ccid2.h (limited to 'include') diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 088529f54965..268b4579d7e5 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -314,9 +314,9 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb) /* initial values for each feature */ #define DCCPF_INITIAL_SEQUENCE_WINDOW 100 -/* FIXME: for now we're using CCID 3 (TFRC) */ -#define DCCPF_INITIAL_CCID 3 -#define DCCPF_INITIAL_SEND_ACK_VECTOR 0 +/* FIXME: for now we're using CCID 2 (TCP-Like) */ +#define DCCPF_INITIAL_CCID 2 +#define DCCPF_INITIAL_SEND_ACK_VECTOR 1 /* FIXME: for now we're default to 1 but it should really be 0 */ #define DCCPF_INITIAL_SEND_NDP_COUNT 1 @@ -430,6 +430,8 @@ struct dccp_sock { struct timeval dccps_timestamp_time; __u32 dccps_timestamp_echo; __u32 dccps_packet_size; + __u16 dccps_l_ack_ratio; + __u16 dccps_r_ack_ratio; unsigned long dccps_ndp_count; __u32 dccps_mss_cache; struct dccp_options dccps_options; diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig index 187ac182e24b..24a6981e209a 100644 --- a/net/dccp/Kconfig +++ b/net/dccp/Kconfig @@ -24,6 +24,10 @@ config INET_DCCP_DIAG def_tristate y if (IP_DCCP = y && INET_DIAG = y) def_tristate m +config IP_DCCP_ACKVEC + depends on IP_DCCP + def_bool N + source "net/dccp/ccids/Kconfig" menu "DCCP Kernel Hacking" diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig index 7684d83946a4..422af197171d 100644 --- a/net/dccp/ccids/Kconfig +++ b/net/dccp/ccids/Kconfig @@ -1,6 +1,34 @@ menu "DCCP CCIDs Configuration (EXPERIMENTAL)" depends on IP_DCCP && EXPERIMENTAL +config IP_DCCP_CCID2 + tristate "CCID2 (TCP) (EXPERIMENTAL)" + depends on IP_DCCP + select IP_DCCP_ACKVEC + ---help--- + CCID 2, TCP-like Congestion Control, denotes Additive Increase, + Multiplicative Decrease (AIMD) congestion control with behavior + modelled directly on TCP, including congestion window, slow start, + timeouts, and so forth [RFC 2581]. CCID 2 achieves maximum + bandwidth over the long term, consistent with the use of end-to-end + congestion control, but halves its congestion window in response to + each congestion event. This leads to the abrupt rate changes + typical of TCP. Applications should use CCID 2 if they prefer + maximum bandwidth utilization to steadiness of rate. This is often + the case for applications that are not playing their data directly + to the user. For example, a hypothetical application that + transferred files over DCCP, using application-level retransmissions + for lost packets, would prefer CCID 2 to CCID 3. On-line games may + also prefer CCID 2. + + CCID 2 is further described in: + http://www.icir.org/kohler/dccp/draft-ietf-dccp-ccid2-10.txt + + This text was extracted from: + http://www.icir.org/kohler/dccp/draft-ietf-dccp-spec-13.txt + + If in doubt, say M. + config IP_DCCP_CCID3 tristate "CCID3 (TFRC) (EXPERIMENTAL)" depends on IP_DCCP @@ -15,10 +43,15 @@ config IP_DCCP_CCID3 suitable than CCID 2 for applications such streaming media where a relatively smooth sending rate is of importance. - CCID 3 is further described in [CCID 3 PROFILE]. The TFRC - congestion control algorithms were initially described in RFC 3448. + CCID 3 is further described in: + + http://www.icir.org/kohler/dccp/draft-ietf-dccp-ccid3-11.txt. + + The TFRC congestion control algorithms were initially described in + RFC 3448. - This text was extracted from draft-ietf-dccp-spec-11.txt. + This text was extracted from: + http://www.icir.org/kohler/dccp/draft-ietf-dccp-spec-13.txt If in doubt, say M. diff --git a/net/dccp/ccids/Makefile b/net/dccp/ccids/Makefile index 956f79f50743..438f20bccff7 100644 --- a/net/dccp/ccids/Makefile +++ b/net/dccp/ccids/Makefile @@ -2,4 +2,8 @@ obj-$(CONFIG_IP_DCCP_CCID3) += dccp_ccid3.o dccp_ccid3-y := ccid3.o +obj-$(CONFIG_IP_DCCP_CCID2) += dccp_ccid2.o + +dccp_ccid2-y := ccid2.o + obj-y += lib/ diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c new file mode 100644 index 000000000000..4a7b87512560 --- /dev/null +++ b/net/dccp/ccids/ccid2.c @@ -0,0 +1,838 @@ +/* + * net/dccp/ccids/ccid2.c + * + * Copyright (c) 2005, 2006 Andrea Bittau + * + * Changes to meet Linux coding standards, and DCCP infrastructure fixes. + * + * Copyright (c) 2006 Arnaldo Carvalho de Melo + * + * 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. 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. + */ + +/* + * This implementation should follow: draft-ietf-dccp-ccid2-10.txt + * + * BUGS: + * - sequence number wrapping + * - jiffies wrapping + */ + +#include +#include "../ccid.h" +#include "../dccp.h" +#include "ccid2.h" + +static int ccid2_debug; + +#if 0 +#define CCID2_DEBUG +#endif + +#ifdef CCID2_DEBUG +#define ccid2_pr_debug(format, a...) \ + do { if (ccid2_debug) \ + printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \ + } while (0) +#else +#define ccid2_pr_debug(format, a...) +#endif + +static const int ccid2_seq_len = 128; + +static inline struct ccid2_hc_tx_sock *ccid2_hc_tx_sk(const struct sock *sk) +{ + return dccp_sk(sk)->dccps_hc_tx_ccid_private; +} + +static inline struct ccid2_hc_rx_sock *ccid2_hc_rx_sk(const struct sock *sk) +{ + return dccp_sk(sk)->dccps_hc_rx_ccid_private; +} + +#ifdef CCID2_DEBUG +static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx) +{ + int len = 0; + struct ccid2_seq *seqp; + int pipe = 0; + + seqp = hctx->ccid2hctx_seqh; + + /* there is data in the chain */ + if (seqp != hctx->ccid2hctx_seqt) { + seqp = seqp->ccid2s_prev; + len++; + if (!seqp->ccid2s_acked) + pipe++; + + while (seqp != hctx->ccid2hctx_seqt) { + struct ccid2_seq *prev; + + prev = seqp->ccid2s_prev; + len++; + if (!prev->ccid2s_acked) + pipe++; + + /* packets are sent sequentially */ + BUG_ON(seqp->ccid2s_seq <= prev->ccid2s_seq); + BUG_ON(seqp->ccid2s_sent < prev->ccid2s_sent); + BUG_ON(len > ccid2_seq_len); + + seqp = prev; + } + } + + BUG_ON(pipe != hctx->ccid2hctx_pipe); + ccid2_pr_debug("len of chain=%d\n", len); + + do { + seqp = seqp->ccid2s_prev; + len++; + BUG_ON(len > ccid2_seq_len); + } while(seqp != hctx->ccid2hctx_seqh); + + BUG_ON(len != ccid2_seq_len); + ccid2_pr_debug("total len=%d\n", len); +} +#else +#define ccid2_hc_tx_check_sanity(hctx) do {} while (0) +#endif + +static int ccid2_hc_tx_send_packet(struct sock *sk, + struct sk_buff *skb, int len) +{ + struct ccid2_hc_tx_sock *hctx; + + switch (DCCP_SKB_CB(skb)->dccpd_type) { + case 0: /* XXX data packets from userland come through like this */ + case DCCP_PKT_DATA: + case DCCP_PKT_DATAACK: + break; + /* No congestion control on other packets */ + default: + return 0; + } + + hctx = ccid2_hc_tx_sk(sk); + + ccid2_pr_debug("pipe=%d cwnd=%d\n", hctx->ccid2hctx_pipe, + hctx->ccid2hctx_cwnd); + + if (hctx->ccid2hctx_pipe < hctx->ccid2hctx_cwnd) { + /* OK we can send... make sure previous packet was sent off */ + if (!hctx->ccid2hctx_sendwait) { + hctx->ccid2hctx_sendwait = 1; + return 0; + } + } + + return 100; /* XXX */ +} + +static void ccid2_change_l_ack_ratio(struct sock *sk, int val) +{ + struct dccp_sock *dp = dccp_sk(sk); + /* + * XXX I don't really agree with val != 2. If cwnd is 1, ack ratio + * should be 1... it shouldn't be allowed to become 2. + * -sorbo. + */ + if (val != 2) { + struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); + int max = hctx->ccid2hctx_cwnd / 2; + + /* round up */ + if (hctx->ccid2hctx_cwnd & 1) + max++; + + if (val > max) + val = max; + } + + ccid2_pr_debug("changing local ack ratio to %d\n", val); + WARN_ON(val <= 0); + dp->dccps_l_ack_ratio = val; +} + +static void ccid2_change_cwnd(struct sock *sk, int val) +{ + struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); + + if (val == 0) + val = 1; + + /* XXX do we need to change ack ratio? */ + ccid2_pr_debug("change cwnd to %d\n", val); + + BUG_ON(val < 1); + hctx->ccid2hctx_cwnd = val; +} + +static void ccid2_start_rto_timer(struct sock *sk); + +static void ccid2_hc_tx_rto_expire(unsigned long data) +{ + struct sock *sk = (struct sock *)data; + struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); + long s; + + /* XXX I don't think i'm locking correctly + * -sorbo. + */ + bh_lock_sock(sk); + if (sock_owned_by_user(sk)) { + sk_reset_timer(sk, &hctx->ccid2hctx_rtotimer, + jiffies + HZ / 5); + goto out; + } + + ccid2_pr_debug("RTO_EXPIRE\n"); + + ccid2_hc_tx_check_sanity(hctx); + + /* back-off timer */ + hctx->ccid2hctx_rto <<= 1; + + s = hctx->ccid2hctx_rto / HZ; + if (s > 60) + hctx->ccid2hctx_rto = 60 * HZ; + + ccid2_start_rto_timer(sk); + + /* adjust pipe, cwnd etc */ + hctx->ccid2hctx_pipe = 0; + hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd >> 1; + if (hctx->ccid2hctx_ssthresh < 2) + hctx->ccid2hctx_ssthresh = 2; + ccid2_change_cwnd(sk, 1); + + /* clear state about stuff we sent */ + hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqh; + hctx->ccid2hctx_ssacks = 0; + hctx->ccid2hctx_acks = 0; + hctx->ccid2hctx_sent = 0; + + /* clear ack ratio state. */ + hctx->ccid2hctx_arsent = 0; + hctx->ccid2hctx_ackloss = 0; + hctx->ccid2hctx_rpseq = 0; + hctx->ccid2hctx_rpdupack = -1; + ccid2_change_l_ack_ratio(sk, 1); + ccid2_hc_tx_check_sanity(hctx); +out: + bh_unlock_sock(sk); +/* sock_put(sk); */ +} + +static void ccid2_start_rto_timer(struct sock *sk) +{ + struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); + + ccid2_pr_debug("setting RTO timeout=%ld\n", hctx->ccid2hctx_rto); + + BUG_ON(timer_pending(&hctx->ccid2hctx_rtotimer)); + sk_reset_timer(sk, &hctx->ccid2hctx_rtotimer, + jiffies + hctx->ccid2hctx_rto); +} + +static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len) +{ + struct dccp_sock *dp = dccp_sk(sk); + struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); + u64 seq; + + ccid2_hc_tx_check_sanity(hctx); + + BUG_ON(!hctx->ccid2hctx_sendwait); + hctx->ccid2hctx_sendwait = 0; + hctx->ccid2hctx_pipe++; + BUG_ON(hctx->ccid2hctx_pipe < 0); + + /* There is an issue. What if another packet is sent between + * packet_send() and packet_sent(). Then the sequence number would be + * wrong. + * -sorbo. + */ + seq = dp->dccps_gss; + + hctx->ccid2hctx_seqh->ccid2s_seq = seq; + hctx->ccid2hctx_seqh->ccid2s_acked = 0; + hctx->ccid2hctx_seqh->ccid2s_sent = jiffies; + hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqh->ccid2s_next; + + ccid2_pr_debug("cwnd=%d pipe=%d\n", hctx->ccid2hctx_cwnd, + hctx->ccid2hctx_pipe); + + if (hctx->ccid2hctx_seqh == hctx->ccid2hctx_seqt) { + /* XXX allocate more space */ + WARN_ON(1); + } + + hctx->ccid2hctx_sent++; + + /* Ack Ratio. Need to maintain a concept of how many windows we sent */ + hctx->ccid2hctx_arsent++; + /* We had an ack loss in this window... */ + if (hctx->ccid2hctx_ackloss) { + if (hctx->ccid2hctx_arsent >= hctx->ccid2hctx_cwnd) { + hctx->ccid2hctx_arsent = 0; + hctx->ccid2hctx_ackloss = 0; + } + } + /* No acks lost up to now... */ + else { + /* decrease ack ratio if enough packets were sent */ + if (dp->dccps_l_ack_ratio > 1) { + /* XXX don't calculate denominator each time */ + int denom; + + denom = dp->dccps_l_ack_ratio * dp->dccps_l_ack_ratio - + dp->dccps_l_ack_ratio; + denom = hctx->ccid2hctx_cwnd * hctx->ccid2hctx_cwnd / denom; + + if (hctx->ccid2hctx_arsent >= denom) { + ccid2_change_l_ack_ratio(sk, dp->dccps_l_ack_ratio - 1); + hctx->ccid2hctx_arsent = 0; + } + } + /* we can't increase ack ratio further [1] */ + else { + hctx->ccid2hctx_arsent = 0; /* or maybe set it to cwnd*/ + } + } + + /* setup RTO timer */ + if (!timer_pending(&hctx->ccid2hctx_rtotimer)) { + ccid2_start_rto_timer(sk); + } +#ifdef CCID2_DEBUG + ccid2_pr_debug("pipe=%d\n", hctx->ccid2hctx_pipe); + ccid2_pr_debug("Sent: seq=%llu\n", seq); + do { + struct ccid2_seq *seqp = hctx->ccid2hctx_seqt; + + while (seqp != hctx->ccid2hctx_seqh) { + ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n", + seqp->ccid2s_seq, seqp->ccid2s_acked, + seqp->ccid2s_sent); + seqp = seqp->ccid2s_next; + } + } while(0); + ccid2_pr_debug("=========\n"); + ccid2_hc_tx_check_sanity(hctx); +#endif +} + +/* XXX Lame code duplication! + * returns -1 if none was found. + * else returns the next offset to use in the function call. + */ +static int ccid2_ackvector(struct sock *sk, struct sk_buff *skb, int offset, + unsigned char **vec, unsigned char *veclen) +{ + const struct dccp_hdr *dh = dccp_hdr(skb); + unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb); + unsigned char *opt_ptr; + const unsigned char *opt_end = (unsigned char *)dh + + (dh->dccph_doff * 4); + unsigned char opt, len; + unsigned char *value; + + BUG_ON(offset < 0); + options += offset; + opt_ptr = options; + if (opt_ptr >= opt_end) + return -1; + + while (opt_ptr != opt_end) { + opt = *opt_ptr++; + len = 0; + value = NULL; + + /* Check if this isn't a single byte option */ + if (opt > DCCPO_MAX_RESERVED) { + if (opt_ptr == opt_end) + goto out_invalid_option; + + len = *opt_ptr++; + if (len < 3) + goto out_invalid_option; + /* + * Remove the type and len fields, leaving + * just the value size + */ + len -= 2; + value = opt_ptr; + opt_ptr += len; + + if (opt_ptr > opt_end) + goto out_invalid_option; + } + + switch (opt) { + case DCCPO_ACK_VECTOR_0: + case DCCPO_ACK_VECTOR_1: + *vec = value; + *veclen = len; + return offset + (opt_ptr - options); + break; + } + } + + return -1; + +out_invalid_option: + BUG_ON(1); /* should never happen... options were previously parsed ! */ + return -1; +} + +static void ccid2_hc_tx_kill_rto_timer(struct ccid2_hc_tx_sock *hctx) +{ + if (del_timer(&hctx->ccid2hctx_rtotimer)) + ccid2_pr_debug("deleted RTO timer\n"); +} + +static inline void ccid2_new_ack(struct sock *sk, + struct ccid2_seq *seqp, + unsigned int *maxincr) +{ + struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); + + /* slow start */ + if (hctx->ccid2hctx_cwnd < hctx->ccid2hctx_ssthresh) { + hctx->ccid2hctx_acks = 0; + + /* We can increase cwnd at most maxincr [ack_ratio/2] */ + if (*maxincr) { + /* increase every 2 acks */ + hctx->ccid2hctx_ssacks++; + if (hctx->ccid2hctx_ssacks == 2) { + ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd + 1); + hctx->ccid2hctx_ssacks = 0; + *maxincr = *maxincr - 1; + } + } + /* increased cwnd enough for this single ack */ + else { + hctx->ccid2hctx_ssacks = 0; + } + } + else { + hctx->ccid2hctx_ssacks = 0; + hctx->ccid2hctx_acks++; + + if (hctx->ccid2hctx_acks >= hctx->ccid2hctx_cwnd) { + ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd + 1); + hctx->ccid2hctx_acks = 0; + } + } + + /* update RTO */ + if (hctx->ccid2hctx_srtt == -1 || + (jiffies - hctx->ccid2hctx_lastrtt) >= hctx->ccid2hctx_srtt) { + unsigned long r = jiffies - seqp->ccid2s_sent; + int s; + + /* first measurement */ + if (hctx->ccid2hctx_srtt == -1) { + ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n", + r, jiffies, seqp->ccid2s_seq); + hctx->ccid2hctx_srtt = r; + hctx->ccid2hctx_rttvar = r >> 1; + } + else { + /* RTTVAR */ + long tmp = hctx->ccid2hctx_srtt - r; + if (tmp < 0) + tmp *= -1; + + tmp >>= 2; + hctx->ccid2hctx_rttvar *= 3; + hctx->ccid2hctx_rttvar >>= 2; + hctx->ccid2hctx_rttvar += tmp; + + /* SRTT */ + hctx->ccid2hctx_srtt *= 7; + hctx->ccid2hctx_srtt >>= 3; + tmp = r >> 3; + hctx->ccid2hctx_srtt += tmp; + } + s = hctx->ccid2hctx_rttvar << 2; + /* clock granularity is 1 when based on jiffies */ + if (!s) + s = 1; + hctx->ccid2hctx_rto = hctx->ccid2hctx_srtt + s; + + /* must be at least a second */ + s = hctx->ccid2hctx_rto / HZ; + /* DCCP doesn't require this [but I like it cuz my code sux] */ +#if 1 + if (s < 1) + hctx->ccid2hctx_rto = HZ; +#endif + /* max 60 seconds */ + if (s > 60) + hctx->ccid2hctx_rto = HZ * 60; + + hctx->ccid2hctx_lastrtt = jiffies; + + ccid2_pr_debug("srtt: %ld rttvar: %ld rto: %ld (HZ=%d) R=%lu\n", + hctx->ccid2hctx_srtt, hctx->ccid2hctx_rttvar, + hctx->ccid2hctx_rto, HZ, r); + hctx->ccid2hctx_sent = 0; + } + + /* we got a new ack, so re-start RTO timer */ + ccid2_hc_tx_kill_rto_timer(hctx); + ccid2_start_rto_timer(sk); +} + +static void ccid2_hc_tx_dec_pipe(struct ccid2_hc_tx_sock *hctx) +{ + hctx->ccid2hctx_pipe--; + BUG_ON(hctx->ccid2hctx_pipe < 0); + + if (hctx->ccid2hctx_pipe == 0) + ccid2_hc_tx_kill_rto_timer(hctx); +} + +static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) +{ + struct dccp_sock *dp = dccp_sk(sk); + struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); + u64 ackno, seqno; + struct ccid2_seq *seqp; + unsigned char *vector; + unsigned char veclen; + int offset = 0; + int done = 0; + int loss = 0; + unsigned int maxincr = 0; + + ccid2_hc_tx_check_sanity(hctx); + /* check reverse path congestion */ + seqno = DCCP_SKB_CB(skb)->dccpd_seq; + + /* XXX this whole "algorithm" is broken. Need to fix it to keep track + * of the seqnos of the dupacks so that rpseq and rpdupack are correct + * -sorbo. + */ + /* need to bootstrap */ + if (hctx->ccid2hctx_rpdupack == -1) { + hctx->ccid2hctx_rpdupack = 0; + hctx->ccid2hctx_rpseq = seqno; + } + else { + /* check if packet is consecutive */ + if ((hctx->ccid2hctx_rpseq + 1) == seqno) { + hctx->ccid2hctx_rpseq++; + } + /* it's a later packet */ + else if (after48(seqno, hctx->ccid2hctx_rpseq)) { + hctx->ccid2hctx_rpdupack++; + + /* check if we got enough dupacks */ + if (hctx->ccid2hctx_rpdupack >= + hctx->ccid2hctx_numdupack) { + + hctx->ccid2hctx_rpdupack = -1; /* XXX lame */ + hctx->ccid2hctx_rpseq = 0; + + ccid2_change_l_ack_ratio(sk, dp->dccps_l_ack_ratio << 1); + } + } + } + + /* check forward path congestion */ + /* still didn't send out new data packets */ + if (hctx->ccid2hctx_seqh == hctx->ccid2hctx_seqt) + return; + + switch (DCCP_SKB_CB(skb)->dccpd_type) { + case DCCP_PKT_ACK: + case DCCP_PKT_DATAACK: + break; + + default: + return; + } + + ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq; + seqp = hctx->ccid2hctx_seqh->ccid2s_prev; + + /* If in slow-start, cwnd can increase at most Ack Ratio / 2 packets for + * this single ack. I round up. + * -sorbo. + */ + maxincr = dp->dccps_l_ack_ratio >> 1; + maxincr++; + + /* go through all ack vectors */ + while ((offset = ccid2_ackvector(sk, skb, offset, + &vector, &veclen)) != -1) { + /* go through this ack vector */ + while (veclen--) { + const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK; + u64 ackno_end_rl; + + dccp_set_seqno(&ackno_end_rl, ackno - rl); + ccid2_pr_debug("ackvec start:%llu end:%llu\n", ackno, + ackno_end_rl); + /* if the seqno we are analyzing is larger than the + * current ackno, then move towards the tail of our + * seqnos. + */ + while (after48(seqp->ccid2s_seq, ackno)) { + if (seqp == hctx->ccid2hctx_seqt) { + done = 1; + break; + } + seqp = seqp->ccid2s_prev; + } + if (done) + break; + + /* check all seqnos in the range of the vector + * run length + */ + while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) { + const u8 state = (*vector & + DCCP_ACKVEC_STATE_MASK) >> 6; + + /* new packet received or marked */ + if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED && + !seqp->ccid2s_acked) { + if (state == + DCCP_ACKVEC_STATE_ECN_MARKED) { + loss = 1; + } + else { + ccid2_new_ack(sk, seqp, + &maxincr); + } + + seqp->ccid2s_acked = 1; + ccid2_pr_debug("Got ack for %llu\n", + seqp->ccid2s_seq); + ccid2_hc_tx_dec_pipe(hctx); + } + if (seqp == hctx->ccid2hctx_seqt) { + done = 1; + break; + } + seqp = seqp->ccid2s_next; + } + if (done) + break; + + + dccp_set_seqno(&ackno, ackno_end_rl - 1); + vector++; + } + if (done) + break; + } + + /* The state about what is acked should be correct now + * Check for NUMDUPACK + */ + seqp = hctx->ccid2hctx_seqh->ccid2s_prev; + done = 0; + while (1) { + if (seqp->ccid2s_acked) { + done++; + if (done == hctx->ccid2hctx_numdupack) { + break; + } + } + if (seqp == hctx->ccid2hctx_seqt) { + break; + } + seqp = seqp->ccid2s_prev; + } + + /* If there are at least 3 acknowledgements, anything unacknowledged + * below the last sequence number is considered lost + */ + if (done == hctx->ccid2hctx_numdupack) { + struct ccid2_seq *last_acked = seqp; + + /* check for lost packets */ + while (1) { + if (!seqp->ccid2s_acked) { + loss = 1; + ccid2_hc_tx_dec_pipe(hctx); + } + if (seqp == hctx->ccid2hctx_seqt) + break; + seqp = seqp->ccid2s_prev; + } + + hctx->ccid2hctx_seqt = last_acked; + } + + /* trim acked packets in tail */ + while (hctx->ccid2hctx_seqt != hctx->ccid2hctx_seqh) { + if (!hctx->ccid2hctx_seqt->ccid2s_acked) + break; + + hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqt->ccid2s_next; + } + + if (loss) { + /* XXX do bit shifts guarantee a 0 as the new bit? */ + ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd >> 1); + hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd; + if (hctx->ccid2hctx_ssthresh < 2) + hctx->ccid2hctx_ssthresh = 2; + } + + ccid2_hc_tx_check_sanity(hctx); +} + +static int ccid2_hc_tx_init(struct sock *sk) +{ + struct dccp_sock *dp = dccp_sk(sk); + struct ccid2_hc_tx_sock *hctx; + int seqcount = ccid2_seq_len; + int i; + + dp->dccps_hc_tx_ccid_private = kzalloc(sizeof(*hctx), gfp_any()); + if (dp->dccps_hc_tx_ccid_private == NULL) + return -ENOMEM; + + hctx = ccid2_hc_tx_sk(sk); + + /* XXX init variables with proper values */ + hctx->ccid2hctx_cwnd = 1; + hctx->ccid2hctx_ssthresh = 10; + hctx->ccid2hctx_numdupack = 3; + + /* XXX init ~ to window size... */ + hctx->ccid2hctx_seqbuf = kmalloc(sizeof(*hctx->ccid2hctx_seqbuf) * + seqcount, gfp_any()); + if (hctx->ccid2hctx_seqbuf == NULL) { + kfree(dp->dccps_hc_tx_ccid_private); + dp->dccps_hc_tx_ccid_private = NULL; + return -ENOMEM; + } + for (i = 0; i < (seqcount - 1); i++) { + hctx->ccid2hctx_seqbuf[i].ccid2s_next = + &hctx->ccid2hctx_seqbuf[i + 1]; + hctx->ccid2hctx_seqbuf[i + 1].ccid2s_prev = + &hctx->ccid2hctx_seqbuf[i]; + } + hctx->ccid2hctx_seqbuf[seqcount - 1].ccid2s_next = + hctx->ccid2hctx_seqbuf; + hctx->ccid2hctx_seqbuf->ccid2s_prev = + &hctx->ccid2hctx_seqbuf[seqcount - 1]; + + hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqbuf; + hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqh; + hctx->ccid2hctx_sent = 0; + hctx->ccid2hctx_rto = 3 * HZ; + hctx->ccid2hctx_srtt = -1; + hctx->ccid2hctx_rttvar = -1; + hctx->ccid2hctx_lastrtt = 0; + hctx->ccid2hctx_rpdupack = -1; + + hctx->ccid2hctx_rtotimer.function = &ccid2_hc_tx_rto_expire; + hctx->ccid2hctx_rtotimer.data = (unsigned long)sk; + init_timer(&hctx->ccid2hctx_rtotimer); + + ccid2_hc_tx_check_sanity(hctx); + return 0; +} + +static void ccid2_hc_tx_exit(struct sock *sk) +{ + struct dccp_sock *dp = dccp_sk(sk); + struct ccid2_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; + + ccid2_hc_tx_kill_rto_timer(hctx); + + kfree(hctx->ccid2hctx_seqbuf); + + kfree(dp->dccps_hc_tx_ccid_private); + dp->dccps_hc_tx_ccid_private = NULL; +} + +static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) +{ + const struct dccp_sock *dp = dccp_sk(sk); + struct ccid2_hc_rx_sock *hcrx = ccid2_hc_rx_sk(sk); + + switch (DCCP_SKB_CB(skb)->dccpd_type) { + case DCCP_PKT_DATA: + case DCCP_PKT_DATAACK: + hcrx->ccid2hcrx_data++; + if (hcrx->ccid2hcrx_data >= dp->dccps_r_ack_ratio) { + dccp_send_ack(sk); + hcrx->ccid2hcrx_data = 0; + } + break; + } +} + +static int ccid2_hc_rx_init(struct sock *sk) +{ + struct dccp_sock *dp = dccp_sk(sk); + dp->dccps_hc_rx_ccid_private = kzalloc(sizeof(struct ccid2_hc_rx_sock), + gfp_any()); + return dp->dccps_hc_rx_ccid_private == NULL ? -ENOMEM : 0; +} + +static void ccid2_hc_rx_exit(struct sock *sk) +{ + struct dccp_sock *dp = dccp_sk(sk); + + kfree(dp->dccps_hc_rx_ccid_private); + dp->dccps_hc_rx_ccid_private = NULL; +} + +static struct ccid ccid2 = { + .ccid_id = 2, + .ccid_name = "ccid2", + .ccid_owner = THIS_MODULE, + .ccid_hc_tx_init = ccid2_hc_tx_init, + .ccid_hc_tx_exit = ccid2_hc_tx_exit, + .ccid_hc_tx_send_packet = ccid2_hc_tx_send_packet, + .ccid_hc_tx_packet_sent = ccid2_hc_tx_packet_sent, + .ccid_hc_tx_packet_recv = ccid2_hc_tx_packet_recv, + .ccid_hc_rx_init = ccid2_hc_rx_init, + .ccid_hc_rx_exit = ccid2_hc_rx_exit, + .ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv, +}; + +module_param(ccid2_debug, int, 0444); +MODULE_PARM_DESC(ccid2_debug, "Enable debug messages"); + +static __init int ccid2_module_init(void) +{ + return ccid_register(&ccid2); +} +module_init(ccid2_module_init); + +static __exit void ccid2_module_exit(void) +{ + ccid_unregister(&ccid2); +} +module_exit(ccid2_module_exit); + +MODULE_AUTHOR("Andrea Bittau "); +MODULE_DESCRIPTION("DCCP TCP CCID2 CCID"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("net-dccp-ccid-2"); diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h new file mode 100644 index 000000000000..0b08c90955a9 --- /dev/null +++ b/net/dccp/ccids/ccid2.h @@ -0,0 +1,69 @@ +/* + * net/dccp/ccids/ccid2.h + * + * Copyright (c) 2005 Andrea Bittau + * + * 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. 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. + */ +#ifndef _DCCP_CCID2_H_ +#define _DCCP_CCID2_H_ + +struct ccid2_seq { + u64 ccid2s_seq; + unsigned long ccid2s_sent; + int ccid2s_acked; + struct ccid2_seq *ccid2s_prev; + struct ccid2_seq *ccid2s_next; +}; + +/** struct ccid2_hc_tx_sock - CCID2 TX half connection + * + * @ccid2hctx_ssacks - ACKs recv in slow start + * @ccid2hctx_acks - ACKS recv in AI phase + * @ccid2hctx_sent - packets sent in this window + * @ccid2hctx_lastrtt -time RTT was last measured + * @ccid2hctx_arsent - packets sent [ack ratio] + * @ccid2hctx_ackloss - ack was lost in this win + * @ccid2hctx_rpseq - last consecutive seqno + * @ccid2hctx_rpdupack - dupacks since rpseq +*/ +struct ccid2_hc_tx_sock { + int ccid2hctx_cwnd; + int ccid2hctx_ssacks; + int ccid2hctx_acks; + int ccid2hctx_ssthresh; + int ccid2hctx_pipe; + int ccid2hctx_numdupack; + struct ccid2_seq *ccid2hctx_seqbuf; + struct ccid2_seq *ccid2hctx_seqh; + struct ccid2_seq *ccid2hctx_seqt; + long ccid2hctx_rto; + long ccid2hctx_srtt; + long ccid2hctx_rttvar; + int ccid2hctx_sent; + unsigned long ccid2hctx_lastrtt; + struct timer_list ccid2hctx_rtotimer; + unsigned long ccid2hctx_arsent; + int ccid2hctx_ackloss; + u64 ccid2hctx_rpseq; + int ccid2hctx_rpdupack; + int ccid2hctx_sendwait; +}; + +struct ccid2_hc_rx_sock { + int ccid2hcrx_data; +}; + +#endif /* _DCCP_CCID2_H_ */ diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 2ab6f0e6cd62..38321ad81875 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -1081,6 +1081,7 @@ int dccp_v4_init_sock(struct sock *sk) dp->dccps_mss_cache = 536; dp->dccps_role = DCCP_ROLE_UNDEFINED; dp->dccps_service = DCCP_SERVICE_INVALID_VALUE; + dp->dccps_l_ack_ratio = dp->dccps_r_ack_ratio = 1; return 0; } -- cgit v1.2.3 From afe00251dd9b53d51de91ff0099961f42bbf3754 Mon Sep 17 00:00:00 2001 From: Andrea Bittau Date: Mon, 20 Mar 2006 17:43:56 -0800 Subject: [DCCP]: Initial feature negotiation implementation Still needs more work, but boots and doesn't crashes, even does some negotiation! 18:38:52.174934 127.0.0.1.43458 > 127.0.0.1.5001: request 18:38:52.218526 127.0.0.1.5001 > 127.0.0.1.43458: response 18:38:52.185398 127.0.0.1.43458 > 127.0.0.1.5001: :-) Signed-off-by: Andrea Bittau Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/linux/dccp.h | 35 +++- net/dccp/Makefile | 2 +- net/dccp/feat.c | 554 +++++++++++++++++++++++++++++++++++++++++++++++++++ net/dccp/feat.h | 28 +++ net/dccp/input.c | 3 + net/dccp/ipv4.c | 19 +- net/dccp/minisocks.c | 4 + net/dccp/options.c | 139 ++++++++++++- net/dccp/output.c | 4 + net/dccp/proto.c | 53 +++++ net/dccp/timer.c | 12 ++ 11 files changed, 847 insertions(+), 6 deletions(-) create mode 100644 net/dccp/feat.c create mode 100644 net/dccp/feat.h (limited to 'include') diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 268b4579d7e5..f91c8a62406d 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -154,6 +154,10 @@ enum { DCCPO_MANDATORY = 1, DCCPO_MIN_RESERVED = 3, DCCPO_MAX_RESERVED = 31, + DCCPO_CHANGE_L = 32, + DCCPO_CONFIRM_L = 33, + DCCPO_CHANGE_R = 34, + DCCPO_CONFIRM_R = 35, DCCPO_NDP_COUNT = 37, DCCPO_ACK_VECTOR_0 = 38, DCCPO_ACK_VECTOR_1 = 39, @@ -168,7 +172,9 @@ enum { /* DCCP features */ enum { DCCPF_RESERVED = 0, + DCCPF_CCID = 1, DCCPF_SEQUENCE_WINDOW = 3, + DCCPF_ACK_RATIO = 5, DCCPF_SEND_ACK_VECTOR = 6, DCCPF_SEND_NDP_COUNT = 7, /* 10-127 reserved */ @@ -176,9 +182,18 @@ enum { DCCPF_MAX_CCID_SPECIFIC = 255, }; +/* this structure is argument to DCCP_SOCKOPT_CHANGE_X */ +struct dccp_so_feat { + __u8 dccpsf_feat; + __u8 *dccpsf_val; + __u8 dccpsf_len; +}; + /* DCCP socket options */ #define DCCP_SOCKOPT_PACKET_SIZE 1 #define DCCP_SOCKOPT_SERVICE 2 +#define DCCP_SOCKOPT_CHANGE_L 3 +#define DCCP_SOCKOPT_CHANGE_R 4 #define DCCP_SOCKOPT_CCID_RX_INFO 128 #define DCCP_SOCKOPT_CCID_TX_INFO 192 @@ -314,8 +329,8 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb) /* initial values for each feature */ #define DCCPF_INITIAL_SEQUENCE_WINDOW 100 -/* FIXME: for now we're using CCID 2 (TCP-Like) */ #define DCCPF_INITIAL_CCID 2 +#define DCCPF_INITIAL_ACK_RATIO 2 #define DCCPF_INITIAL_SEND_ACK_VECTOR 1 /* FIXME: for now we're default to 1 but it should really be 0 */ #define DCCPF_INITIAL_SEND_NDP_COUNT 1 @@ -335,6 +350,24 @@ struct dccp_options { __u8 dccpo_tx_ccid; __u8 dccpo_send_ack_vector; __u8 dccpo_send_ndp_count; + __u8 dccpo_ack_ratio; + struct list_head dccpo_pending; + struct list_head dccpo_conf; +}; + +struct dccp_opt_conf { + __u8 *dccpoc_val; + __u8 dccpoc_len; +}; + +struct dccp_opt_pend { + struct list_head dccpop_node; + __u8 dccpop_type; + __u8 dccpop_feat; + __u8 *dccpop_val; + __u8 dccpop_len; + int dccpop_conf; + struct dccp_opt_conf *dccpop_sc; }; extern void __dccp_options_init(struct dccp_options *dccpo); diff --git a/net/dccp/Makefile b/net/dccp/Makefile index 87b27fff6e3b..5736acea1c86 100644 --- a/net/dccp/Makefile +++ b/net/dccp/Makefile @@ -4,7 +4,7 @@ dccp_ipv6-y := ipv6.o obj-$(CONFIG_IP_DCCP) += dccp.o -dccp-y := ccid.o input.o ipv4.o minisocks.o options.o output.o proto.o \ +dccp-y := ccid.o feat.o input.o ipv4.o minisocks.o options.o output.o proto.o \ timer.o dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o diff --git a/net/dccp/feat.c b/net/dccp/feat.c new file mode 100644 index 000000000000..99d7b7f9efa9 --- /dev/null +++ b/net/dccp/feat.c @@ -0,0 +1,554 @@ +/* + * net/dccp/feat.c + * + * An implementation of the DCCP protocol + * Andrea Bittau + * + * 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. + */ + +#include +#include + +#include "dccp.h" +#include "feat.h" + +#define DCCP_FEAT_SP_NOAGREE (-123) + +int dccp_feat_change(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len, + gfp_t gfp) +{ + struct dccp_sock *dp = dccp_sk(sk); + struct dccp_opt_pend *opt; + + dccp_pr_debug("feat change type=%d feat=%d\n", type, feature); + + /* check if that feature is already being negotiated */ + list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, + dccpop_node) { + /* ok we found a negotiation for this option already */ + if (opt->dccpop_feat == feature && opt->dccpop_type == type) { + dccp_pr_debug("Replacing old\n"); + /* replace */ + BUG_ON(opt->dccpop_val == NULL); + kfree(opt->dccpop_val); + opt->dccpop_val = val; + opt->dccpop_len = len; + opt->dccpop_conf = 0; + return 0; + } + } + + /* negotiation for a new feature */ + opt = kmalloc(sizeof(*opt), gfp); + if (opt == NULL) + return -ENOMEM; + + opt->dccpop_type = type; + opt->dccpop_feat = feature; + opt->dccpop_len = len; + opt->dccpop_val = val; + opt->dccpop_conf = 0; + opt->dccpop_sc = NULL; + + BUG_ON(opt->dccpop_val == NULL); + + list_add_tail(&opt->dccpop_node, &dp->dccps_options.dccpo_pending); + return 0; +} + +EXPORT_SYMBOL_GPL(dccp_feat_change); + +/* XXX taking only u8 vals */ +static int dccp_feat_update(struct sock *sk, u8 type, u8 feat, u8 val) +{ + /* FIXME implement */ + dccp_pr_debug("changing [%d] feat %d to %d\n", type, feat, val); + return 0; +} + +static int dccp_feat_reconcile(struct sock *sk, struct dccp_opt_pend *opt, + u8 *rpref, u8 rlen) +{ + struct dccp_sock *dp = dccp_sk(sk); + u8 *spref, slen, *res = NULL; + int i, j, rc, agree = 1; + + BUG_ON(rpref == NULL); + + /* check if we are the black sheep */ + if (dp->dccps_role == DCCP_ROLE_CLIENT) { + spref = rpref; + slen = rlen; + rpref = opt->dccpop_val; + rlen = opt->dccpop_len; + } else { + spref = opt->dccpop_val; + slen = opt->dccpop_len; + } + /* + * Now we have server preference list in spref and client preference in + * rpref + */ + BUG_ON(spref == NULL); + BUG_ON(rpref == NULL); + + /* FIXME sanity check vals */ + + /* Are values in any order? XXX Lame "algorithm" here */ + /* XXX assume values are 1 byte */ + for (i = 0; i < slen; i++) { + for (j = 0; j < rlen; j++) { + if (spref[i] == rpref[j]) { + res = &spref[i]; + break; + } + } + if (res) + break; + } + + /* we didn't agree on anything */ + if (res == NULL) { + /* confirm previous value */ + switch (opt->dccpop_feat) { + case DCCPF_CCID: + /* XXX did i get this right? =P */ + if (opt->dccpop_type == DCCPO_CHANGE_L) + res = &dp->dccps_options.dccpo_tx_ccid; + else + res = &dp->dccps_options.dccpo_rx_ccid; + break; + + default: + WARN_ON(1); /* XXX implement res */ + return -EFAULT; + } + + dccp_pr_debug("Don't agree... reconfirming %d\n", *res); + agree = 0; /* this is used for mandatory options... */ + } + + /* need to put result and our preference list */ + /* XXX assume 1 byte vals */ + rlen = 1 + opt->dccpop_len; + rpref = kmalloc(rlen, GFP_ATOMIC); + if (rpref == NULL) + return -ENOMEM; + + *rpref = *res; + memcpy(&rpref[1], opt->dccpop_val, opt->dccpop_len); + + /* put it in the "confirm queue" */ + if (opt->dccpop_sc == NULL) { + opt->dccpop_sc = kmalloc(sizeof(*opt->dccpop_sc), GFP_ATOMIC); + if (opt->dccpop_sc == NULL) { + kfree(rpref); + return -ENOMEM; + } + } else { + /* recycle the confirm slot */ + BUG_ON(opt->dccpop_sc->dccpoc_val == NULL); + kfree(opt->dccpop_sc->dccpoc_val); + dccp_pr_debug("recycling confirm slot\n"); + } + memset(opt->dccpop_sc, 0, sizeof(*opt->dccpop_sc)); + + opt->dccpop_sc->dccpoc_val = rpref; + opt->dccpop_sc->dccpoc_len = rlen; + + /* update the option on our side [we are about to send the confirm] */ + rc = dccp_feat_update(sk, opt->dccpop_type, opt->dccpop_feat, *res); + if (rc) { + kfree(opt->dccpop_sc->dccpoc_val); + kfree(opt->dccpop_sc); + opt->dccpop_sc = 0; + return rc; + } + + dccp_pr_debug("Will confirm %d\n", *rpref); + + /* say we want to change to X but we just got a confirm X, suppress our + * change + */ + if (!opt->dccpop_conf) { + if (*opt->dccpop_val == *res) + opt->dccpop_conf = 1; + dccp_pr_debug("won't ask for change of same feature\n"); + } + + return agree ? 0 : DCCP_FEAT_SP_NOAGREE; /* used for mandatory opts */ +} + +static int dccp_feat_sp(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) +{ + struct dccp_sock *dp = dccp_sk(sk); + struct dccp_opt_pend *opt; + int rc = 1; + u8 t; + + /* + * We received a CHANGE. We gotta match it against our own preference + * list. If we got a CHANGE_R it means it's a change for us, so we need + * to compare our CHANGE_L list. + */ + if (type == DCCPO_CHANGE_L) + t = DCCPO_CHANGE_R; + else + t = DCCPO_CHANGE_L; + + /* find our preference list for this feature */ + list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, + dccpop_node) { + if (opt->dccpop_type != t || opt->dccpop_feat != feature) + continue; + + /* find the winner from the two preference lists */ + rc = dccp_feat_reconcile(sk, opt, val, len); + break; + } + + /* We didn't deal with the change. This can happen if we have no + * preference list for the feature. In fact, it just shouldn't + * happen---if we understand a feature, we should have a preference list + * with at least the default value. + */ + BUG_ON(rc == 1); + + return rc; +} + +static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) +{ + struct dccp_opt_pend *opt; + struct dccp_sock *dp = dccp_sk(sk); + u8 *copy; + int rc; + + /* NN features must be change L */ + if (type == DCCPO_CHANGE_R) { + dccp_pr_debug("received CHANGE_R %d for NN feat %d\n", + type, feature); + return -EFAULT; + } + + /* XXX sanity check opt val */ + + /* copy option so we can confirm it */ + opt = kzalloc(sizeof(*opt), GFP_ATOMIC); + if (opt == NULL) + return -ENOMEM; + + copy = kmalloc(len, GFP_ATOMIC); + if (copy == NULL) { + kfree(opt); + return -ENOMEM; + } + memcpy(copy, val, len); + + opt->dccpop_type = DCCPO_CONFIRM_R; /* NN can only confirm R */ + opt->dccpop_feat = feature; + opt->dccpop_val = copy; + opt->dccpop_len = len; + + /* change feature */ + rc = dccp_feat_update(sk, type, feature, *val); + if (rc) { + kfree(opt->dccpop_val); + kfree(opt); + return rc; + } + + dccp_pr_debug("Confirming NN feature %d (val=%d)\n", feature, *copy); + list_add_tail(&opt->dccpop_node, &dp->dccps_options.dccpo_conf); + + return 0; +} + +static void dccp_feat_empty_confirm(struct sock *sk, u8 type, u8 feature) +{ + struct dccp_sock *dp = dccp_sk(sk); + /* XXX check if other confirms for that are queued and recycle slot */ + struct dccp_opt_pend *opt = kzalloc(sizeof(*opt), GFP_ATOMIC); + + if (opt == NULL) { + /* XXX what do we do? Ignoring should be fine. It's a change + * after all =P + */ + return; + } + + opt->dccpop_type = type == DCCPO_CHANGE_L ? DCCPO_CONFIRM_R : + DCCPO_CONFIRM_L; + opt->dccpop_feat = feature; + opt->dccpop_val = 0; + opt->dccpop_len = 0; + + /* change feature */ + dccp_pr_debug("Empty confirm feature %d type %d\n", feature, type); + list_add_tail(&opt->dccpop_node, &dp->dccps_options.dccpo_conf); +} + +static void dccp_feat_flush_confirm(struct sock *sk) +{ + struct dccp_sock *dp = dccp_sk(sk); + /* Check if there is anything to confirm in the first place */ + int yes = !list_empty(&dp->dccps_options.dccpo_conf); + + if (!yes) { + struct dccp_opt_pend *opt; + + list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, + dccpop_node) { + if (opt->dccpop_conf) { + yes = 1; + break; + } + } + } + + if (!yes) + return; + + /* OK there is something to confirm... */ + /* XXX check if packet is in flight? Send delayed ack?? */ + if (sk->sk_state == DCCP_OPEN) + dccp_send_ack(sk); +} + +int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) +{ + int rc; + + dccp_pr_debug("got feat change type=%d feat=%d\n", type, feature); + + /* figure out if it's SP or NN feature */ + switch (feature) { + /* deal with SP features */ + case DCCPF_CCID: + rc = dccp_feat_sp(sk, type, feature, val, len); + break; + + /* deal with NN features */ + case DCCPF_ACK_RATIO: + rc = dccp_feat_nn(sk, type, feature, val, len); + break; + + /* XXX implement other features */ + default: + rc = -EFAULT; + break; + } + + /* check if there were problems changing features */ + if (rc) { + /* If we don't agree on SP, we sent a confirm for old value. + * However we propagate rc to caller in case option was + * mandatory + */ + if (rc != DCCP_FEAT_SP_NOAGREE) + dccp_feat_empty_confirm(sk, type, feature); + } + + /* generate the confirm [if required] */ + dccp_feat_flush_confirm(sk); + + return rc; +} + +EXPORT_SYMBOL_GPL(dccp_feat_change_recv); + +int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature, + u8 *val, u8 len) +{ + u8 t; + struct dccp_opt_pend *opt; + struct dccp_sock *dp = dccp_sk(sk); + int rc = 1; + int all_confirmed = 1; + + dccp_pr_debug("got feat confirm type=%d feat=%d\n", type, feature); + + /* XXX sanity check type & feat */ + + /* locate our change request */ + t = type == DCCPO_CONFIRM_L ? DCCPO_CHANGE_R : DCCPO_CHANGE_L; + + list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, + dccpop_node) { + if (!opt->dccpop_conf && opt->dccpop_type == t && + opt->dccpop_feat == feature) { + /* we found it */ + /* XXX do sanity check */ + + opt->dccpop_conf = 1; + + /* We got a confirmation---change the option */ + dccp_feat_update(sk, opt->dccpop_type, + opt->dccpop_feat, *val); + + dccp_pr_debug("feat %d type %d confirmed %d\n", + feature, type, *val); + rc = 0; + break; + } + + if (!opt->dccpop_conf) + all_confirmed = 0; + } + + /* fix re-transmit timer */ + /* XXX gotta make sure that no option negotiation occurs during + * connection shutdown. Consider that the CLOSEREQ is sent and timer is + * on. if all options are confirmed it might kill timer which should + * remain alive until close is received. + */ + if (all_confirmed) { + dccp_pr_debug("clear feat negotiation timer %p\n", sk); + inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS); + } + + if (rc) + dccp_pr_debug("feat %d type %d never requested\n", + feature, type); + return 0; +} + +EXPORT_SYMBOL_GPL(dccp_feat_confirm_recv); + +void dccp_feat_clean(struct sock *sk) +{ + struct dccp_sock *dp = dccp_sk(sk); + struct dccp_opt_pend *opt, *next; + + list_for_each_entry_safe(opt, next, &dp->dccps_options.dccpo_pending, + dccpop_node) { + BUG_ON(opt->dccpop_val == NULL); + kfree(opt->dccpop_val); + + if (opt->dccpop_sc != NULL) { + BUG_ON(opt->dccpop_sc->dccpoc_val == NULL); + kfree(opt->dccpop_sc->dccpoc_val); + kfree(opt->dccpop_sc); + } + + kfree(opt); + } + INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending); + + list_for_each_entry_safe(opt, next, &dp->dccps_options.dccpo_conf, + dccpop_node) { + BUG_ON(opt == NULL); + if (opt->dccpop_val != NULL) + kfree(opt->dccpop_val); + kfree(opt); + } + INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); +} + +EXPORT_SYMBOL_GPL(dccp_feat_clean); + +/* this is to be called only when a listening sock creates its child. It is + * assumed by the function---the confirm is not duplicated, but rather it is + * "passed on". + */ +int dccp_feat_clone(struct sock *oldsk, struct sock *newsk) +{ + struct dccp_sock *olddp = dccp_sk(oldsk); + struct dccp_sock *newdp = dccp_sk(newsk); + struct dccp_opt_pend *opt; + int rc = 0; + + INIT_LIST_HEAD(&newdp->dccps_options.dccpo_pending); + INIT_LIST_HEAD(&newdp->dccps_options.dccpo_conf); + + list_for_each_entry(opt, &olddp->dccps_options.dccpo_pending, + dccpop_node) { + struct dccp_opt_pend *newopt; + /* copy the value of the option */ + u8 *val = kmalloc(opt->dccpop_len, GFP_ATOMIC); + + if (val == NULL) + goto out_clean; + memcpy(val, opt->dccpop_val, opt->dccpop_len); + + newopt = kmalloc(sizeof(*newopt), GFP_ATOMIC); + if (newopt == NULL) { + kfree(val); + goto out_clean; + } + + /* insert the option */ + memcpy(newopt, opt, sizeof(*newopt)); + newopt->dccpop_val = val; + list_add_tail(&newopt->dccpop_node, + &newdp->dccps_options.dccpo_pending); + + /* XXX what happens with backlogs and multiple connections at + * once... + */ + /* the master socket no longer needs to worry about confirms */ + opt->dccpop_sc = 0; /* it's not a memleak---new socket has it */ + + /* reset state for a new socket */ + opt->dccpop_conf = 0; + } + + /* XXX not doing anything about the conf queue */ + +out: + return rc; + +out_clean: + dccp_feat_clean(newsk); + rc = -ENOMEM; + goto out; +} + +EXPORT_SYMBOL_GPL(dccp_feat_clone); + +static int __dccp_feat_init(struct sock *sk, u8 type, u8 feat, u8 *val, u8 len) +{ + int rc = -ENOMEM; + u8 *copy = kmalloc(len, GFP_KERNEL); + + if (copy != NULL) { + memcpy(copy, val, len); + rc = dccp_feat_change(sk, type, feat, copy, len, GFP_KERNEL); + if (rc) + kfree(copy); + } + return rc; +} + +int dccp_feat_init(struct sock *sk) +{ + struct dccp_sock *dp = dccp_sk(sk); + int rc; + + INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending); + INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); + + /* CCID L */ + rc = __dccp_feat_init(sk, DCCPO_CHANGE_L, DCCPF_CCID, + &dp->dccps_options.dccpo_tx_ccid, 1); + if (rc) + goto out; + + /* CCID R */ + rc = __dccp_feat_init(sk, DCCPO_CHANGE_R, DCCPF_CCID, + &dp->dccps_options.dccpo_rx_ccid, 1); + if (rc) + goto out; + + /* Ack ratio */ + rc = __dccp_feat_init(sk, DCCPO_CHANGE_L, DCCPF_ACK_RATIO, + &dp->dccps_options.dccpo_ack_ratio, 1); +out: + return rc; +} + +EXPORT_SYMBOL_GPL(dccp_feat_init); diff --git a/net/dccp/feat.h b/net/dccp/feat.h new file mode 100644 index 000000000000..67da06265f14 --- /dev/null +++ b/net/dccp/feat.h @@ -0,0 +1,28 @@ +#ifndef _DCCP_FEAT_H +#define _DCCP_FEAT_H +/* + * net/dccp/feat.h + * + * An implementation of the DCCP protocol + * Copyright (c) 2005 Andrea Bittau + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include + +struct sock; + +extern int dccp_feat_change(struct sock *sk, u8 type, u8 feature, + u8 *val, u8 len, gfp_t gfp); +extern int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature, + u8 *val, u8 len); +extern int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature, + u8 *val, u8 len); +extern void dccp_feat_clean(struct sock *sk); +extern int dccp_feat_clone(struct sock *oldsk, struct sock *newsk); +extern int dccp_feat_init(struct sock *sk); + +#endif /* _DCCP_FEAT_H */ diff --git a/net/dccp/input.c b/net/dccp/input.c index b6cba72b44e8..4b6d43d8b920 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -300,6 +300,9 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, goto out_invalid_packet; } + if (dccp_parse_options(sk, skb)) + goto out_invalid_packet; + if (dp->dccps_options.dccpo_send_ack_vector && dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, DCCP_SKB_CB(skb)->dccpd_seq, diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 38321ad81875..fcfb486f90c2 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -28,6 +28,7 @@ #include "ackvec.h" #include "ccid.h" #include "dccp.h" +#include "feat.h" struct inet_hashinfo __cacheline_aligned dccp_hashinfo = { .lhash_lock = RW_LOCK_UNLOCKED, @@ -535,7 +536,8 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) if (req == NULL) goto drop; - /* FIXME: process options */ + if (dccp_parse_options(sk, skb)) + goto drop; dccp_openreq_init(req, &dp, skb); @@ -1049,6 +1051,8 @@ int dccp_v4_init_sock(struct sock *sk) * setsockopt(CCIDs-I-want/accept). -acme */ if (likely(!dccp_ctl_socket_init)) { + int rc; + if (dp->dccps_options.dccpo_send_ack_vector) { dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_KERNEL); if (dp->dccps_hc_rx_ackvec == NULL) @@ -1069,8 +1073,16 @@ int dccp_v4_init_sock(struct sock *sk) dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; return -ENOMEM; } - } else + + rc = dccp_feat_init(sk); + if (rc) + return rc; + } else { + /* control socket doesn't need feat nego */ + INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending); + INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); dccp_ctl_socket_init = 0; + } dccp_init_xmit_timers(sk); icsk->icsk_rto = DCCP_TIMEOUT_INIT; @@ -1118,6 +1130,9 @@ int dccp_v4_destroy_sock(struct sock *sk) ccid_exit(dp->dccps_hc_tx_ccid, sk); dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; + /* clean up feature negotiation state */ + dccp_feat_clean(sk); + return 0; } diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index a60a3e948c36..9e1de5919ee5 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -22,6 +22,7 @@ #include "ackvec.h" #include "ccid.h" #include "dccp.h" +#include "feat.h" struct inet_timewait_death_row dccp_death_row = { .sysctl_max_tw_buckets = NR_FILE * 2, @@ -114,6 +115,9 @@ struct sock *dccp_create_openreq_child(struct sock *sk, newicsk->icsk_rto = DCCP_TIMEOUT_INIT; do_gettimeofday(&newdp->dccps_epoch); + if (dccp_feat_clone(sk, newsk)) + goto out_free; + if (newdp->dccps_options.dccpo_send_ack_vector) { newdp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_ATOMIC); diff --git a/net/dccp/options.c b/net/dccp/options.c index 0a76426c9aea..7f99306c8e99 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -21,12 +21,14 @@ #include "ackvec.h" #include "ccid.h" #include "dccp.h" +#include "feat.h" /* stores the default values for new connection. may be changed with sysctl */ static const struct dccp_options dccpo_default_values = { .dccpo_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW, .dccpo_rx_ccid = DCCPF_INITIAL_CCID, .dccpo_tx_ccid = DCCPF_INITIAL_CCID, + .dccpo_ack_ratio = DCCPF_INITIAL_ACK_RATIO, .dccpo_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR, .dccpo_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT, }; @@ -69,6 +71,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) unsigned char opt, len; unsigned char *value; u32 elapsed_time; + int rc; + int mandatory = 0; memset(opt_recv, 0, sizeof(*opt_recv)); @@ -100,6 +104,11 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) switch (opt) { case DCCPO_PADDING: break; + case DCCPO_MANDATORY: + if (mandatory) + goto out_invalid_option; + mandatory = 1; + break; case DCCPO_NDP_COUNT: if (len > 3) goto out_invalid_option; @@ -108,6 +117,31 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) dccp_pr_debug("%sNDP count=%d\n", debug_prefix, opt_recv->dccpor_ndp); break; + case DCCPO_CHANGE_L: + /* fall through */ + case DCCPO_CHANGE_R: + if (len < 2) + goto out_invalid_option; + rc = dccp_feat_change_recv(sk, opt, *value, value + 1, + len - 1); + /* + * When there is a change error, change_recv is + * responsible for dealing with it. i.e. reply with an + * empty confirm. + * If the change was mandatory, then we need to die. + */ + if (rc && mandatory) + goto out_invalid_option; + break; + case DCCPO_CONFIRM_L: + /* fall through */ + case DCCPO_CONFIRM_R: + if (len < 2) + goto out_invalid_option; + if (dccp_feat_confirm_recv(sk, opt, *value, + value + 1, len - 1)) + goto out_invalid_option; + break; case DCCPO_ACK_VECTOR_0: case DCCPO_ACK_VECTOR_1: if (pkt_type == DCCP_PKT_DATA) @@ -208,6 +242,9 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) sk, opt, len); break; } + + if (opt != DCCPO_MANDATORY) + mandatory = 0; } return 0; @@ -356,7 +393,7 @@ void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb) { struct timeval tv; u32 now; - + dccp_timestamp(sk, &tv); now = timeval_usecs(&tv) / 10; /* yes this will overflow but that is the point as we want a @@ -402,7 +439,7 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk, tstamp_echo = htonl(dp->dccps_timestamp_echo); memcpy(to, &tstamp_echo, 4); to += 4; - + if (elapsed_time_len == 2) { const u16 var16 = htons((u16)elapsed_time); memcpy(to, &var16, 2); @@ -421,6 +458,93 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk, dp->dccps_timestamp_time.tv_usec = 0; } +static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat, + u8 *val, u8 len) +{ + u8 *to; + + if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 3 > DCCP_MAX_OPT_LEN) { + LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small" + " to insert feature %d option!\n", feat); + return -1; + } + + DCCP_SKB_CB(skb)->dccpd_opt_len += len + 3; + + to = skb_push(skb, len + 3); + *to++ = type; + *to++ = len + 3; + *to++ = feat; + + if (len) + memcpy(to, val, len); + dccp_pr_debug("option %d feat %d len %d\n", type, feat, len); + + return 0; +} + +static void dccp_insert_feat(struct sock *sk, struct sk_buff *skb) +{ + struct dccp_sock *dp = dccp_sk(sk); + struct dccp_opt_pend *opt, *next; + int change = 0; + + /* confirm any options [NN opts] */ + list_for_each_entry_safe(opt, next, &dp->dccps_options.dccpo_conf, + dccpop_node) { + dccp_insert_feat_opt(skb, opt->dccpop_type, + opt->dccpop_feat, opt->dccpop_val, + opt->dccpop_len); + /* fear empty confirms */ + if (opt->dccpop_val) + kfree(opt->dccpop_val); + kfree(opt); + } + INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); + + /* see which features we need to send */ + list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, + dccpop_node) { + /* see if we need to send any confirm */ + if (opt->dccpop_sc) { + dccp_insert_feat_opt(skb, opt->dccpop_type + 1, + opt->dccpop_feat, + opt->dccpop_sc->dccpoc_val, + opt->dccpop_sc->dccpoc_len); + + BUG_ON(!opt->dccpop_sc->dccpoc_val); + kfree(opt->dccpop_sc->dccpoc_val); + kfree(opt->dccpop_sc); + opt->dccpop_sc = NULL; + } + + /* any option not confirmed, re-send it */ + if (!opt->dccpop_conf) { + dccp_insert_feat_opt(skb, opt->dccpop_type, + opt->dccpop_feat, opt->dccpop_val, + opt->dccpop_len); + change++; + } + } + + /* Retransmit timer. + * If this is the master listening sock, we don't set a timer on it. It + * should be fine because if the dude doesn't receive our RESPONSE + * [which will contain the CHANGE] he will send another REQUEST which + * will "retrnasmit" the change. + */ + if (change && dp->dccps_role != DCCP_ROLE_LISTEN) { + dccp_pr_debug("reset feat negotiation timer %p\n", sk); + + /* XXX don't reset the timer on re-transmissions. I.e. reset it + * only when sending new stuff i guess. Currently the timer + * never backs off because on re-transmission it just resets it! + */ + inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, + inet_csk(sk)->icsk_rto, DCCP_RTO_MAX); + } +} + void dccp_insert_options(struct sock *sk, struct sk_buff *skb) { struct dccp_sock *dp = dccp_sk(sk); @@ -447,6 +571,17 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb) dp->dccps_hc_tx_insert_options = 0; } + /* Feature negotiation */ + switch(DCCP_SKB_CB(skb)->dccpd_type) { + /* Data packets can't do feat negotiation */ + case DCCP_PKT_DATA: + case DCCP_PKT_DATAACK: + break; + default: + dccp_insert_feat(sk, skb); + break; + } + /* XXX: insert other options when appropriate */ if (DCCP_SKB_CB(skb)->dccpd_opt_len != 0) { diff --git a/net/dccp/output.c b/net/dccp/output.c index efd7ffb903a1..0cc2bcf56522 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -64,6 +64,10 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) case DCCP_PKT_DATAACK: break; + case DCCP_PKT_REQUEST: + set_ack = 0; + /* fall through */ + case DCCP_PKT_SYNC: case DCCP_PKT_SYNCACK: ackno = dcb->dccpd_seq; diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 81ad24953710..1a8cf8ecfe63 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -37,6 +37,7 @@ #include "ccid.h" #include "dccp.h" +#include "feat.h" DEFINE_SNMP_STAT(struct dccp_mib, dccp_statistics) __read_mostly; @@ -255,6 +256,39 @@ static int dccp_setsockopt_service(struct sock *sk, const u32 service, return 0; } +/* byte 1 is feature. the rest is the preference list */ +static int dccp_setsockopt_change(struct sock *sk, int type, + struct dccp_so_feat __user *optval) +{ + struct dccp_so_feat opt; + u8 *val; + int rc; + + if (copy_from_user(&opt, optval, sizeof(opt))) + return -EFAULT; + + val = kmalloc(opt.dccpsf_len, GFP_KERNEL); + if (!val) + return -ENOMEM; + + if (copy_from_user(val, opt.dccpsf_val, opt.dccpsf_len)) { + rc = -EFAULT; + goto out_free_val; + } + + rc = dccp_feat_change(sk, type, opt.dccpsf_feat, val, opt.dccpsf_len, + GFP_KERNEL); + if (rc) + goto out_free_val; + +out: + return rc; + +out_free_val: + kfree(val); + goto out; +} + int dccp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) { @@ -284,6 +318,25 @@ int dccp_setsockopt(struct sock *sk, int level, int optname, case DCCP_SOCKOPT_PACKET_SIZE: dp->dccps_packet_size = val; break; + + case DCCP_SOCKOPT_CHANGE_L: + if (optlen != sizeof(struct dccp_so_feat)) + err = -EINVAL; + else + err = dccp_setsockopt_change(sk, DCCPO_CHANGE_L, + (struct dccp_so_feat *) + optval); + break; + + case DCCP_SOCKOPT_CHANGE_R: + if (optlen != sizeof(struct dccp_so_feat)) + err = -EINVAL; + else + err = dccp_setsockopt_change(sk, DCCPO_CHANGE_R, + (struct dccp_so_feat *) + optval); + break; + default: err = -ENOPROTOOPT; break; diff --git a/net/dccp/timer.c b/net/dccp/timer.c index aa34b576e228..d7c786608ec6 100644 --- a/net/dccp/timer.c +++ b/net/dccp/timer.c @@ -141,6 +141,17 @@ static void dccp_retransmit_timer(struct sock *sk) { struct inet_connection_sock *icsk = inet_csk(sk); + /* retransmit timer is used for feature negotiation throughout + * connection. In this case, no packet is re-transmitted, but rather an + * ack is generated and pending changes are splaced into its options. + */ + if (sk->sk_send_head == NULL) { + dccp_pr_debug("feat negotiation retransmit timeout %p\n", sk); + if (sk->sk_state == DCCP_OPEN) + dccp_send_ack(sk); + goto backoff; + } + /* * sk->sk_send_head has to have one skb with * DCCP_SKB_CB(skb)->dccpd_type set to one of the retransmittable DCCP @@ -177,6 +188,7 @@ static void dccp_retransmit_timer(struct sock *sk) goto out; } +backoff: icsk->icsk_backoff++; icsk->icsk_retransmits++; -- cgit v1.2.3 From d4d2c558fd3e1f5e386b153f194aa8f0be496c77 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 17:47:20 -0800 Subject: [TG3]: Add support for 5714S and 5715S Add support for 5714S and 5715S. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 35 ++++++++++++++++++++++++++++++++++- include/linux/pci_ids.h | 2 ++ 2 files changed, 36 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 6c6c5498899f..b0de6b2754cc 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -223,8 +223,12 @@ static struct pci_device_id tg3_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S, @@ -2680,6 +2684,12 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) err |= tg3_readphy(tp, MII_BMSR, &bmsr); err |= tg3_readphy(tp, MII_BMSR, &bmsr); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) { + if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP) + bmsr |= BMSR_LSTATUS; + else + bmsr &= ~BMSR_LSTATUS; + } err |= tg3_readphy(tp, MII_BMCR, &bmcr); @@ -2748,6 +2758,13 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) bmcr = new_bmcr; err |= tg3_readphy(tp, MII_BMSR, &bmsr); err |= tg3_readphy(tp, MII_BMSR, &bmsr); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == + ASIC_REV_5714) { + if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP) + bmsr |= BMSR_LSTATUS; + else + bmsr &= ~BMSR_LSTATUS; + } tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; } } @@ -5585,6 +5602,9 @@ static int tg3_reset_hw(struct tg3 *tp) tg3_abort_hw(tp, 1); } + if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) + tg3_phy_reset(tp); + err = tg3_chip_reset(tp); if (err) return err; @@ -6097,6 +6117,17 @@ static int tg3_reset_hw(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG; } + if ((tp->tg3_flags2 & TG3_FLG2_MII_SERDES) && + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)) { + u32 tmp; + + tmp = tr32(SERDES_RX_CTRL); + tw32(SERDES_RX_CTRL, tmp | SERDES_RX_SIG_DETECT); + tp->grc_local_ctrl &= ~GRC_LCLCTRL_USE_EXT_SIG_DETECT; + tp->grc_local_ctrl |= GRC_LCLCTRL_USE_SIG_DETECT; + tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl); + } + err = tg3_setup_phy(tp, 1); if (err) return err; @@ -6476,7 +6507,9 @@ static int tg3_open(struct net_device *dev) if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_AX) && - (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_BX)) { + (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_BX) && + !((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) && + (tp->pdev_peer == tp->pdev))) { /* All MSI supporting chips should support tagged * status. Assert that this is the case. */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 751eea58bde8..a3a09cceb026 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1857,12 +1857,14 @@ #define PCI_DEVICE_ID_TIGON3_5705M 0x165d #define PCI_DEVICE_ID_TIGON3_5705M_2 0x165e #define PCI_DEVICE_ID_TIGON3_5714 0x1668 +#define PCI_DEVICE_ID_TIGON3_5714S 0x1669 #define PCI_DEVICE_ID_TIGON3_5780 0x166a #define PCI_DEVICE_ID_TIGON3_5780S 0x166b #define PCI_DEVICE_ID_TIGON3_5705F 0x166e #define PCI_DEVICE_ID_TIGON3_5750 0x1676 #define PCI_DEVICE_ID_TIGON3_5751 0x1677 #define PCI_DEVICE_ID_TIGON3_5715 0x1678 +#define PCI_DEVICE_ID_TIGON3_5715S 0x1679 #define PCI_DEVICE_ID_TIGON3_5750M 0x167c #define PCI_DEVICE_ID_TIGON3_5751M 0x167d #define PCI_DEVICE_ID_TIGON3_5751F 0x167e -- cgit v1.2.3 From 5d424d5a674f782d0659a3b66d951f412901faee Mon Sep 17 00:00:00 2001 From: John Heffner Date: Mon, 20 Mar 2006 17:53:41 -0800 Subject: [TCP]: MTU probing Implementation of packetization layer path mtu discovery for TCP, based on the internet-draft currently found at . Signed-off-by: John Heffner Signed-off-by: David S. Miller --- include/linux/sysctl.h | 2 + include/net/inet_connection_sock.h | 13 ++ include/net/tcp.h | 9 ++ net/ipv4/sysctl_net_ipv4.c | 16 +++ net/ipv4/tcp_input.c | 49 ++++++++ net/ipv4/tcp_ipv4.c | 1 + net/ipv4/tcp_output.c | 236 ++++++++++++++++++++++++++++++++++--- net/ipv4/tcp_timer.c | 36 +++--- net/ipv6/tcp_ipv6.c | 1 + 9 files changed, 326 insertions(+), 37 deletions(-) (limited to 'include') diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 8ad4beab2888..6e8880ea49e7 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -397,6 +397,8 @@ enum NET_TCP_CONG_CONTROL=110, NET_TCP_ABC=111, NET_IPV4_IPFRAG_MAX_DIST=112, + NET_TCP_MTU_PROBING=113, + NET_TCP_BASE_MSS=114, }; enum { diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index fa587c94e9d0..b3abe33f4e5f 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -72,6 +72,7 @@ struct inet_connection_sock_af_ops { * @icsk_probes_out: unanswered 0 window probes * @icsk_ext_hdr_len: Network protocol overhead (IP/IPv6 options) * @icsk_ack: Delayed ACK control data + * @icsk_mtup; MTU probing control data */ struct inet_connection_sock { /* inet_sock has to be the first member! */ @@ -104,6 +105,18 @@ struct inet_connection_sock { __u16 last_seg_size; /* Size of last incoming segment */ __u16 rcv_mss; /* MSS used for delayed ACK decisions */ } icsk_ack; + struct { + int enabled; + + /* Range of MTUs to search */ + int search_high; + int search_low; + + /* Information on the current probe. */ + int probe_size; + __u32 probe_seq_start; + __u32 probe_seq_end; + } icsk_mtup; u32 icsk_ca_priv[16]; #define ICSK_CA_PRIV_SIZE (16 * sizeof(u32)) }; diff --git a/include/net/tcp.h b/include/net/tcp.h index 77f21c65bbca..16879fa560de 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -60,6 +60,9 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); /* Minimal RCV_MSS. */ #define TCP_MIN_RCVMSS 536U +/* The least MTU to use for probing */ +#define TCP_BASE_MSS 512 + /* After receiving this amount of duplicate ACKs fast retransmit starts. */ #define TCP_FASTRETRANS_THRESH 3 @@ -219,6 +222,8 @@ extern int sysctl_tcp_nometrics_save; extern int sysctl_tcp_moderate_rcvbuf; extern int sysctl_tcp_tso_win_divisor; extern int sysctl_tcp_abc; +extern int sysctl_tcp_mtu_probing; +extern int sysctl_tcp_base_mss; extern atomic_t tcp_memory_allocated; extern atomic_t tcp_sockets_allocated; @@ -447,6 +452,10 @@ extern int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, extern void tcp_initialize_rcv_mss(struct sock *sk); +extern int tcp_mtu_to_mss(struct sock *sk, int pmtu); +extern int tcp_mss_to_mtu(struct sock *sk, int mss); +extern void tcp_mtup_init(struct sock *sk); + static inline void __tcp_fast_path_on(struct tcp_sock *tp, u32 snd_wnd) { tp->pred_flags = htonl((tp->tcp_header_len << 26) | diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 16984d4a8a06..ebf2e0b363c4 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -664,6 +664,22 @@ ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = &proc_dointvec, }, + { + .ctl_name = NET_TCP_MTU_PROBING, + .procname = "tcp_mtu_probing", + .data = &sysctl_tcp_mtu_probing, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = NET_TCP_BASE_MSS, + .procname = "tcp_base_mss", + .data = &sysctl_tcp_base_mss, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, { .ctl_name = 0 } }; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index e9a54ae7d690..0ac388e3d01d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1891,6 +1891,34 @@ static void tcp_try_to_open(struct sock *sk, struct tcp_sock *tp, int flag) } } +static void tcp_mtup_probe_failed(struct sock *sk) +{ + struct inet_connection_sock *icsk = inet_csk(sk); + + icsk->icsk_mtup.search_high = icsk->icsk_mtup.probe_size - 1; + icsk->icsk_mtup.probe_size = 0; +} + +static void tcp_mtup_probe_success(struct sock *sk, struct sk_buff *skb) +{ + struct tcp_sock *tp = tcp_sk(sk); + struct inet_connection_sock *icsk = inet_csk(sk); + + /* FIXME: breaks with very large cwnd */ + tp->prior_ssthresh = tcp_current_ssthresh(sk); + tp->snd_cwnd = tp->snd_cwnd * + tcp_mss_to_mtu(sk, tp->mss_cache) / + icsk->icsk_mtup.probe_size; + tp->snd_cwnd_cnt = 0; + tp->snd_cwnd_stamp = tcp_time_stamp; + tp->rcv_ssthresh = tcp_current_ssthresh(sk); + + icsk->icsk_mtup.search_low = icsk->icsk_mtup.probe_size; + icsk->icsk_mtup.probe_size = 0; + tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); +} + + /* Process an event, which can update packets-in-flight not trivially. * Main goal of this function is to calculate new estimate for left_out, * taking into account both packets sitting in receiver's buffer and @@ -2023,6 +2051,17 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una, return; } + /* MTU probe failure: don't reduce cwnd */ + if (icsk->icsk_ca_state < TCP_CA_CWR && + icsk->icsk_mtup.probe_size && + tp->snd_una == icsk->icsk_mtup.probe_seq_start) { + tcp_mtup_probe_failed(sk); + /* Restores the reduction we did in tcp_mtup_probe() */ + tp->snd_cwnd++; + tcp_simple_retransmit(sk); + return; + } + /* Otherwise enter Recovery state */ if (IsReno(tp)) @@ -2243,6 +2282,13 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p) tp->retrans_stamp = 0; } + /* MTU probing checks */ + if (icsk->icsk_mtup.probe_size) { + if (!after(icsk->icsk_mtup.probe_seq_end, TCP_SKB_CB(skb)->end_seq)) { + tcp_mtup_probe_success(sk, skb); + } + } + if (sacked) { if (sacked & TCPCB_RETRANS) { if(sacked & TCPCB_SACKED_RETRANS) @@ -4101,6 +4147,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, if (tp->rx_opt.sack_ok && sysctl_tcp_fack) tp->rx_opt.sack_ok |= 2; + tcp_mtup_init(sk); tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); tcp_initialize_rcv_mss(sk); @@ -4211,6 +4258,7 @@ discard: if (tp->ecn_flags&TCP_ECN_OK) sock_set_flag(sk, SOCK_NO_LARGESEND); + tcp_mtup_init(sk); tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); tcp_initialize_rcv_mss(sk); @@ -4399,6 +4447,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, */ tp->lsndtime = tcp_time_stamp; + tcp_mtup_init(sk); tcp_initialize_rcv_mss(sk); tcp_init_buffer_space(sk); tcp_fast_path_on(tp); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 233bdf259965..57e7a26e8213 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -900,6 +900,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, inet_csk(newsk)->icsk_ext_hdr_len = newinet->opt->optlen; newinet->id = newtp->write_seq ^ jiffies; + tcp_mtup_init(newsk); tcp_sync_mss(newsk, dst_mtu(dst)); newtp->advmss = dst_metric(dst, RTAX_ADVMSS); tcp_initialize_rcv_mss(newsk); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 9f498a6c8895..8197b5e12f1f 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -51,6 +51,12 @@ int sysctl_tcp_retrans_collapse = 1; */ int sysctl_tcp_tso_win_divisor = 3; +int sysctl_tcp_mtu_probing = 0; +int sysctl_tcp_base_mss = 512; + +EXPORT_SYMBOL(sysctl_tcp_mtu_probing); +EXPORT_SYMBOL(sysctl_tcp_base_mss); + static void update_send_head(struct sock *sk, struct tcp_sock *tp, struct sk_buff *skb) { @@ -681,6 +687,62 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len) return 0; } +/* Not accounting for SACKs here. */ +int tcp_mtu_to_mss(struct sock *sk, int pmtu) +{ + struct tcp_sock *tp = tcp_sk(sk); + struct inet_connection_sock *icsk = inet_csk(sk); + int mss_now; + + /* Calculate base mss without TCP options: + It is MMS_S - sizeof(tcphdr) of rfc1122 + */ + mss_now = pmtu - icsk->icsk_af_ops->net_header_len - sizeof(struct tcphdr); + + /* Clamp it (mss_clamp does not include tcp options) */ + if (mss_now > tp->rx_opt.mss_clamp) + mss_now = tp->rx_opt.mss_clamp; + + /* Now subtract optional transport overhead */ + mss_now -= icsk->icsk_ext_hdr_len; + + /* Then reserve room for full set of TCP options and 8 bytes of data */ + if (mss_now < 48) + mss_now = 48; + + /* Now subtract TCP options size, not including SACKs */ + mss_now -= tp->tcp_header_len - sizeof(struct tcphdr); + + return mss_now; +} + +/* Inverse of above */ +int tcp_mss_to_mtu(struct sock *sk, int mss) +{ + struct tcp_sock *tp = tcp_sk(sk); + struct inet_connection_sock *icsk = inet_csk(sk); + int mtu; + + mtu = mss + + tp->tcp_header_len + + icsk->icsk_ext_hdr_len + + icsk->icsk_af_ops->net_header_len; + + return mtu; +} + +void tcp_mtup_init(struct sock *sk) +{ + struct tcp_sock *tp = tcp_sk(sk); + struct inet_connection_sock *icsk = inet_csk(sk); + + icsk->icsk_mtup.enabled = sysctl_tcp_mtu_probing > 1; + icsk->icsk_mtup.search_high = tp->rx_opt.mss_clamp + sizeof(struct tcphdr) + + icsk->icsk_af_ops->net_header_len; + icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, sysctl_tcp_base_mss); + icsk->icsk_mtup.probe_size = 0; +} + /* This function synchronize snd mss to current pmtu/exthdr set. tp->rx_opt.user_mss is mss set by user by TCP_MAXSEG. It does NOT counts @@ -708,25 +770,12 @@ unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu) { struct tcp_sock *tp = tcp_sk(sk); struct inet_connection_sock *icsk = inet_csk(sk); - /* Calculate base mss without TCP options: - It is MMS_S - sizeof(tcphdr) of rfc1122 - */ - int mss_now = (pmtu - icsk->icsk_af_ops->net_header_len - - sizeof(struct tcphdr)); + int mss_now; - /* Clamp it (mss_clamp does not include tcp options) */ - if (mss_now > tp->rx_opt.mss_clamp) - mss_now = tp->rx_opt.mss_clamp; + if (icsk->icsk_mtup.search_high > pmtu) + icsk->icsk_mtup.search_high = pmtu; - /* Now subtract optional transport overhead */ - mss_now -= icsk->icsk_ext_hdr_len; - - /* Then reserve room for full set of TCP options and 8 bytes of data */ - if (mss_now < 48) - mss_now = 48; - - /* Now subtract TCP options size, not including SACKs */ - mss_now -= tp->tcp_header_len - sizeof(struct tcphdr); + mss_now = tcp_mtu_to_mss(sk, pmtu); /* Bound mss with half of window */ if (tp->max_window && mss_now > (tp->max_window>>1)) @@ -734,6 +783,8 @@ unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu) /* And store cached results */ icsk->icsk_pmtu_cookie = pmtu; + if (icsk->icsk_mtup.enabled) + mss_now = min(mss_now, tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low)); tp->mss_cache = mss_now; return mss_now; @@ -1063,6 +1114,140 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_ return 1; } +/* Create a new MTU probe if we are ready. + * Returns 0 if we should wait to probe (no cwnd available), + * 1 if a probe was sent, + * -1 otherwise */ +static int tcp_mtu_probe(struct sock *sk) +{ + struct tcp_sock *tp = tcp_sk(sk); + struct inet_connection_sock *icsk = inet_csk(sk); + struct sk_buff *skb, *nskb, *next; + int len; + int probe_size; + unsigned int pif; + int copy; + int mss_now; + + /* Not currently probing/verifying, + * not in recovery, + * have enough cwnd, and + * not SACKing (the variable headers throw things off) */ + if (!icsk->icsk_mtup.enabled || + icsk->icsk_mtup.probe_size || + inet_csk(sk)->icsk_ca_state != TCP_CA_Open || + tp->snd_cwnd < 11 || + tp->rx_opt.eff_sacks) + return -1; + + /* Very simple search strategy: just double the MSS. */ + mss_now = tcp_current_mss(sk, 0); + probe_size = 2*tp->mss_cache; + if (probe_size > tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_high)) { + /* TODO: set timer for probe_converge_event */ + return -1; + } + + /* Have enough data in the send queue to probe? */ + len = 0; + if ((skb = sk->sk_send_head) == NULL) + return -1; + while ((len += skb->len) < probe_size && !tcp_skb_is_last(sk, skb)) + skb = skb->next; + if (len < probe_size) + return -1; + + /* Receive window check. */ + if (after(TCP_SKB_CB(skb)->seq + probe_size, tp->snd_una + tp->snd_wnd)) { + if (tp->snd_wnd < probe_size) + return -1; + else + return 0; + } + + /* Do we need to wait to drain cwnd? */ + pif = tcp_packets_in_flight(tp); + if (pif + 2 > tp->snd_cwnd) { + /* With no packets in flight, don't stall. */ + if (pif == 0) + return -1; + else + return 0; + } + + /* We're allowed to probe. Build it now. */ + if ((nskb = sk_stream_alloc_skb(sk, probe_size, GFP_ATOMIC)) == NULL) + return -1; + sk_charge_skb(sk, nskb); + + skb = sk->sk_send_head; + __skb_insert(nskb, skb->prev, skb, &sk->sk_write_queue); + sk->sk_send_head = nskb; + + TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(skb)->seq; + TCP_SKB_CB(nskb)->end_seq = TCP_SKB_CB(skb)->seq + probe_size; + TCP_SKB_CB(nskb)->flags = TCPCB_FLAG_ACK; + TCP_SKB_CB(nskb)->sacked = 0; + nskb->csum = 0; + if (skb->ip_summed == CHECKSUM_HW) + nskb->ip_summed = CHECKSUM_HW; + + len = 0; + while (len < probe_size) { + next = skb->next; + + copy = min_t(int, skb->len, probe_size - len); + if (nskb->ip_summed) + skb_copy_bits(skb, 0, skb_put(nskb, copy), copy); + else + nskb->csum = skb_copy_and_csum_bits(skb, 0, + skb_put(nskb, copy), copy, nskb->csum); + + if (skb->len <= copy) { + /* We've eaten all the data from this skb. + * Throw it away. */ + TCP_SKB_CB(nskb)->flags |= TCP_SKB_CB(skb)->flags; + __skb_unlink(skb, &sk->sk_write_queue); + sk_stream_free_skb(sk, skb); + } else { + TCP_SKB_CB(nskb)->flags |= TCP_SKB_CB(skb)->flags & + ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH); + if (!skb_shinfo(skb)->nr_frags) { + skb_pull(skb, copy); + if (skb->ip_summed != CHECKSUM_HW) + skb->csum = csum_partial(skb->data, skb->len, 0); + } else { + __pskb_trim_head(skb, copy); + tcp_set_skb_tso_segs(sk, skb, mss_now); + } + TCP_SKB_CB(skb)->seq += copy; + } + + len += copy; + skb = next; + } + tcp_init_tso_segs(sk, nskb, nskb->len); + + /* We're ready to send. If this fails, the probe will + * be resegmented into mss-sized pieces by tcp_write_xmit(). */ + TCP_SKB_CB(nskb)->when = tcp_time_stamp; + if (!tcp_transmit_skb(sk, nskb, 1, GFP_ATOMIC)) { + /* Decrement cwnd here because we are sending + * effectively two packets. */ + tp->snd_cwnd--; + update_send_head(sk, tp, nskb); + + icsk->icsk_mtup.probe_size = tcp_mss_to_mtu(sk, nskb->len); + icsk->icsk_mtup.probe_seq_start = TCP_SKB_CB(nskb)->seq; + icsk->icsk_mtup.probe_seq_end = TCP_SKB_CB(nskb)->end_seq; + + return 1; + } + + return -1; +} + + /* This routine writes packets to the network. It advances the * send_head. This happens as incoming acks open up the remote * window for us. @@ -1076,6 +1261,7 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle) struct sk_buff *skb; unsigned int tso_segs, sent_pkts; int cwnd_quota; + int result; /* If we are closed, the bytes will have to remain here. * In time closedown will finish, we empty the write queue and all @@ -1085,6 +1271,14 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle) return 0; sent_pkts = 0; + + /* Do MTU probing. */ + if ((result = tcp_mtu_probe(sk)) == 0) { + return 0; + } else if (result > 0) { + sent_pkts = 1; + } + while ((skb = sk->sk_send_head)) { unsigned int limit; @@ -1455,9 +1649,15 @@ void tcp_simple_retransmit(struct sock *sk) int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) { struct tcp_sock *tp = tcp_sk(sk); + struct inet_connection_sock *icsk = inet_csk(sk); unsigned int cur_mss = tcp_current_mss(sk, 0); int err; + /* Inconslusive MTU probe */ + if (icsk->icsk_mtup.probe_size) { + icsk->icsk_mtup.probe_size = 0; + } + /* Do not sent more than we queued. 1/4 is reserved for possible * copying overhead: fragmentation, tunneling, mangling etc. */ @@ -1883,6 +2083,7 @@ static void tcp_connect_init(struct sock *sk) if (tp->rx_opt.user_mss) tp->rx_opt.mss_clamp = tp->rx_opt.user_mss; tp->max_window = 0; + tcp_mtup_init(sk); tcp_sync_mss(sk, dst_mtu(dst)); if (!tp->window_clamp) @@ -2180,3 +2381,4 @@ EXPORT_SYMBOL(tcp_make_synack); EXPORT_SYMBOL(tcp_simple_retransmit); EXPORT_SYMBOL(tcp_sync_mss); EXPORT_SYMBOL(sysctl_tcp_tso_win_divisor); +EXPORT_SYMBOL(tcp_mtup_init); diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index e1880959614a..7c1bde3cd6cb 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -119,8 +119,10 @@ static int tcp_orphan_retries(struct sock *sk, int alive) /* A write timeout has occurred. Process the after effects. */ static int tcp_write_timeout(struct sock *sk) { - const struct inet_connection_sock *icsk = inet_csk(sk); + struct inet_connection_sock *icsk = inet_csk(sk); + struct tcp_sock *tp = tcp_sk(sk); int retry_until; + int mss; if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { if (icsk->icsk_retransmits) @@ -128,25 +130,19 @@ static int tcp_write_timeout(struct sock *sk) retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries; } else { if (icsk->icsk_retransmits >= sysctl_tcp_retries1) { - /* NOTE. draft-ietf-tcpimpl-pmtud-01.txt requires pmtu black - hole detection. :-( - - It is place to make it. It is not made. I do not want - to make it. It is disgusting. It does not work in any - case. Let me to cite the same draft, which requires for - us to implement this: - - "The one security concern raised by this memo is that ICMP black holes - are often caused by over-zealous security administrators who block - all ICMP messages. It is vitally important that those who design and - deploy security systems understand the impact of strict filtering on - upper-layer protocols. The safest web site in the world is worthless - if most TCP implementations cannot transfer data from it. It would - be far nicer to have all of the black holes fixed rather than fixing - all of the TCP implementations." - - Golden words :-). - */ + /* Black hole detection */ + if (sysctl_tcp_mtu_probing) { + if (!icsk->icsk_mtup.enabled) { + icsk->icsk_mtup.enabled = 1; + tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); + } else { + mss = min(sysctl_tcp_base_mss, + tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low)/2); + mss = max(mss, 68 - tp->tcp_header_len); + icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, mss); + tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); + } + } dst_negative_advice(&sk->sk_dst_cache); } diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index ca9cf6853755..14de50380f4e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -987,6 +987,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen + newnp->opt->opt_flen); + tcp_mtup_init(newsk); tcp_sync_mss(newsk, dst_mtu(dst)); newtp->advmss = dst_metric(dst, RTAX_ADVMSS); tcp_initialize_rcv_mss(newsk); -- cgit v1.2.3 From dc808fe28db59fadf4ec32d53f62477fa28f3be8 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 20 Mar 2006 17:56:32 -0800 Subject: [NETFILTER] nf_conntrack: clean up to reduce size of 'struct nf_conn' This patch moves all helper related data fields of 'struct nf_conn' into a separate structure 'struct nf_conn_help'. This new structure is only present in conntrack entries for which we actually have a helper loaded. Also, this patch cleans up the nf_conntrack 'features' mechanism to resemble what the original idea was: Just glue the feature-specific data structures at the end of 'struct nf_conn', and explicitly re-calculate the pointer to it when needed rather than keeping pointers around. Saves 20 bytes per conntrack on my x86_64 box. A non-helped conntrack is 276 bytes. We still need to save another 20 bytes in order to fit into to target of 256bytes. Signed-off-by: Harald Welte Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack.h | 56 +++++++----- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 22 ++--- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 39 ++++---- net/netfilter/nf_conntrack_core.c | 119 +++++++++++-------------- net/netfilter/nf_conntrack_ftp.c | 2 +- net/netfilter/nf_conntrack_netlink.c | 39 ++++---- net/netfilter/nf_conntrack_standalone.c | 1 - net/netfilter/xt_helper.c | 8 +- 8 files changed, 148 insertions(+), 138 deletions(-) (limited to 'include') diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 6d075ca16e6e..2743c156caa0 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -67,6 +67,18 @@ do { \ struct nf_conntrack_helper; +/* nf_conn feature for connections that have a helper */ +struct nf_conn_help { + /* Helper. if any */ + struct nf_conntrack_helper *helper; + + union nf_conntrack_help help; + + /* Current number of expected connections */ + unsigned int expecting; +}; + + #include struct nf_conn { @@ -81,6 +93,9 @@ struct nf_conn /* Have we seen traffic both ways yet? (bitset) */ unsigned long status; + /* If we were expected by an expectation, this will be it */ + struct nf_conn *master; + /* Timer function; drops refcnt when it goes off. */ struct timer_list timeout; @@ -88,38 +103,22 @@ struct nf_conn /* Accounting Information (same cache line as other written members) */ struct ip_conntrack_counter counters[IP_CT_DIR_MAX]; #endif - /* If we were expected by an expectation, this will be it */ - struct nf_conn *master; - - /* Current number of expected connections */ - unsigned int expecting; /* Unique ID that identifies this conntrack*/ unsigned int id; - /* Helper. if any */ - struct nf_conntrack_helper *helper; - /* features - nat, helper, ... used by allocating system */ u_int32_t features; - /* Storage reserved for other modules: */ - - union nf_conntrack_proto proto; - #if defined(CONFIG_NF_CONNTRACK_MARK) u_int32_t mark; #endif - /* These members are dynamically allocated. */ - - union nf_conntrack_help *help; + /* Storage reserved for other modules: */ + union nf_conntrack_proto proto; - /* Layer 3 dependent members. (ex: NAT) */ - union { - struct nf_conntrack_ipv4 *ipv4; - } l3proto; - void *data[0]; + /* features dynamically at the end: helper, nat (both optional) */ + char data[0]; }; struct nf_conntrack_expect @@ -373,10 +372,23 @@ nf_conntrack_expect_event(enum ip_conntrack_expect_events event, #define NF_CT_F_NUM 4 extern int -nf_conntrack_register_cache(u_int32_t features, const char *name, size_t size, - int (*init_conntrack)(struct nf_conn *, u_int32_t)); +nf_conntrack_register_cache(u_int32_t features, const char *name, size_t size); extern void nf_conntrack_unregister_cache(u_int32_t features); +/* valid combinations: + * basic: nf_conn, nf_conn .. nf_conn_help + * nat: nf_conn .. nf_conn_nat, nf_conn .. nf_conn_nat, nf_conn help + */ +static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct) +{ + unsigned int offset = sizeof(struct nf_conn); + + if (!(ct->features & NF_CT_F_HELP)) + return NULL; + + return (struct nf_conn_help *) ((void *)ct + offset); +} + #endif /* __KERNEL__ */ #endif /* _NF_CONNTRACK_H */ diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 6c8624a54933..cb9c661f3f33 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -141,19 +141,21 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum, { struct nf_conn *ct; enum ip_conntrack_info ctinfo; + struct nf_conn_help *help; /* This is where we call the helper: as the packet goes out. */ ct = nf_ct_get(*pskb, &ctinfo); - if (ct && ct->helper) { - unsigned int ret; - ret = ct->helper->help(pskb, - (*pskb)->nh.raw - (*pskb)->data - + (*pskb)->nh.iph->ihl*4, - ct, ctinfo); - if (ret != NF_ACCEPT) - return ret; - } - return NF_ACCEPT; + if (!ct) + return NF_ACCEPT; + + help = nfct_help(ct); + if (!help || !help->helper) + return NF_ACCEPT; + + return help->helper->help(pskb, + (*pskb)->nh.raw - (*pskb)->data + + (*pskb)->nh.iph->ihl*4, + ct, ctinfo); } static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index ac702a29dd16..ac35f9526368 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -179,31 +179,36 @@ static unsigned int ipv6_confirm(unsigned int hooknum, int (*okfn)(struct sk_buff *)) { struct nf_conn *ct; + struct nf_conn_help *help; enum ip_conntrack_info ctinfo; + unsigned int ret, protoff; + unsigned int extoff = (u8*)((*pskb)->nh.ipv6h + 1) + - (*pskb)->data; + unsigned char pnum = (*pskb)->nh.ipv6h->nexthdr; + /* This is where we call the helper: as the packet goes out. */ ct = nf_ct_get(*pskb, &ctinfo); - if (ct && ct->helper) { - unsigned int ret, protoff; - unsigned int extoff = (u8*)((*pskb)->nh.ipv6h + 1) - - (*pskb)->data; - unsigned char pnum = (*pskb)->nh.ipv6h->nexthdr; - - protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum, - (*pskb)->len - extoff); - if (protoff < 0 || protoff > (*pskb)->len || - pnum == NEXTHDR_FRAGMENT) { - DEBUGP("proto header not found\n"); - return NF_ACCEPT; - } + if (!ct) + goto out; - ret = ct->helper->help(pskb, protoff, ct, ctinfo); - if (ret != NF_ACCEPT) - return ret; + help = nfct_help(ct); + if (!help || !help->helper) + goto out; + + protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum, + (*pskb)->len - extoff); + if (protoff < 0 || protoff > (*pskb)->len || + pnum == NEXTHDR_FRAGMENT) { + DEBUGP("proto header not found\n"); + return NF_ACCEPT; } + ret = help->helper->help(pskb, protoff, ct, ctinfo); + if (ret != NF_ACCEPT) + return ret; +out: /* We've seen it coming out the other side: confirm it */ - return nf_conntrack_confirm(pskb); } diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index d622ddf08bb0..dc68d0022218 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -3,7 +3,7 @@ extension. */ /* (C) 1999-2001 Paul `Rusty' Russell - * (C) 2002-2005 Netfilter Core Team + * (C) 2002-2006 Netfilter Core Team * (C) 2003,2004 USAGI/WIDE Project * * This program is free software; you can redistribute it and/or modify @@ -20,6 +20,9 @@ * - generalize L3 protocol denendent part. * 23 Mar 2004: Yasuyuki Kozakai @USAGI * - add support various size of conntrack structures. + * 26 Jan 2006: Harald Welte + * - restructure nf_conn (introduce nf_conn_help) + * - redesign 'features' how they were originally intended * * Derived from net/ipv4/netfilter/ip_conntrack_core.c */ @@ -55,7 +58,7 @@ #include #include -#define NF_CONNTRACK_VERSION "0.4.1" +#define NF_CONNTRACK_VERSION "0.5.0" #if 0 #define DEBUGP printk @@ -259,21 +262,8 @@ static inline u_int32_t hash_conntrack(const struct nf_conntrack_tuple *tuple) nf_conntrack_hash_rnd); } -/* Initialize "struct nf_conn" which has spaces for helper */ -static int -init_conntrack_for_helper(struct nf_conn *conntrack, u_int32_t features) -{ - - conntrack->help = (union nf_conntrack_help *) - (((unsigned long)conntrack->data - + (__alignof__(union nf_conntrack_help) - 1)) - & (~((unsigned long)(__alignof__(union nf_conntrack_help) -1)))); - return 0; -} - int nf_conntrack_register_cache(u_int32_t features, const char *name, - size_t size, - int (*init)(struct nf_conn *, u_int32_t)) + size_t size) { int ret = 0; char *cache_name; @@ -296,8 +286,7 @@ int nf_conntrack_register_cache(u_int32_t features, const char *name, DEBUGP("nf_conntrack_register_cache: already resisterd.\n"); if ((!strncmp(nf_ct_cache[features].name, name, NF_CT_FEATURES_NAMELEN)) - && nf_ct_cache[features].size == size - && nf_ct_cache[features].init_conntrack == init) { + && nf_ct_cache[features].size == size) { DEBUGP("nf_conntrack_register_cache: reusing.\n"); nf_ct_cache[features].use++; ret = 0; @@ -340,7 +329,6 @@ int nf_conntrack_register_cache(u_int32_t features, const char *name, write_lock_bh(&nf_ct_cache_lock); nf_ct_cache[features].use = 1; nf_ct_cache[features].size = size; - nf_ct_cache[features].init_conntrack = init; nf_ct_cache[features].cachep = cachep; nf_ct_cache[features].name = cache_name; write_unlock_bh(&nf_ct_cache_lock); @@ -377,7 +365,6 @@ void nf_conntrack_unregister_cache(u_int32_t features) name = nf_ct_cache[features].name; nf_ct_cache[features].cachep = NULL; nf_ct_cache[features].name = NULL; - nf_ct_cache[features].init_conntrack = NULL; nf_ct_cache[features].size = 0; write_unlock_bh(&nf_ct_cache_lock); @@ -432,11 +419,15 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, /* nf_conntrack_expect helper functions */ void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) { + struct nf_conn_help *master_help = nfct_help(exp->master); + + NF_CT_ASSERT(master_help); ASSERT_WRITE_LOCK(&nf_conntrack_lock); NF_CT_ASSERT(!timer_pending(&exp->timeout)); + list_del(&exp->list); NF_CT_STAT_INC(expect_delete); - exp->master->expecting--; + master_help->expecting--; nf_conntrack_expect_put(exp); } @@ -508,9 +499,10 @@ find_expectation(const struct nf_conntrack_tuple *tuple) void nf_ct_remove_expectations(struct nf_conn *ct) { struct nf_conntrack_expect *i, *tmp; + struct nf_conn_help *help = nfct_help(ct); /* Optimization: most connection never expect any others. */ - if (ct->expecting == 0) + if (!help || help->expecting == 0) return; list_for_each_entry_safe(i, tmp, &nf_conntrack_expect_list, list) { @@ -713,6 +705,7 @@ __nf_conntrack_confirm(struct sk_buff **pskb) conntrack_tuple_cmp, struct nf_conntrack_tuple_hash *, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, NULL)) { + struct nf_conn_help *help; /* Remove from unconfirmed list */ list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); @@ -726,7 +719,8 @@ __nf_conntrack_confirm(struct sk_buff **pskb) set_bit(IPS_CONFIRMED_BIT, &ct->status); NF_CT_STAT_INC(insert); write_unlock_bh(&nf_conntrack_lock); - if (ct->helper) + help = nfct_help(ct); + if (help && help->helper) nf_conntrack_event_cache(IPCT_HELPER, *pskb); #ifdef CONFIG_NF_NAT_NEEDED if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) || @@ -842,8 +836,9 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, { struct nf_conn *conntrack = NULL; u_int32_t features = 0; + struct nf_conntrack_helper *helper; - if (!nf_conntrack_hash_rnd_initted) { + if (unlikely(!nf_conntrack_hash_rnd_initted)) { get_random_bytes(&nf_conntrack_hash_rnd, 4); nf_conntrack_hash_rnd_initted = 1; } @@ -863,8 +858,11 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, /* find features needed by this conntrack. */ features = l3proto->get_features(orig); + + /* FIXME: protect helper list per RCU */ read_lock_bh(&nf_conntrack_lock); - if (__nf_ct_helper_find(repl) != NULL) + helper = __nf_ct_helper_find(repl); + if (helper) features |= NF_CT_F_HELP; read_unlock_bh(&nf_conntrack_lock); @@ -872,7 +870,7 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, read_lock_bh(&nf_ct_cache_lock); - if (!nf_ct_cache[features].use) { + if (unlikely(!nf_ct_cache[features].use)) { DEBUGP("nf_conntrack_alloc: not supported features = 0x%x\n", features); goto out; @@ -886,12 +884,10 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, memset(conntrack, 0, nf_ct_cache[features].size); conntrack->features = features; - if (nf_ct_cache[features].init_conntrack && - nf_ct_cache[features].init_conntrack(conntrack, features) < 0) { - DEBUGP("nf_conntrack_alloc: failed to init\n"); - kmem_cache_free(nf_ct_cache[features].cachep, conntrack); - conntrack = NULL; - goto out; + if (helper) { + struct nf_conn_help *help = nfct_help(conntrack); + NF_CT_ASSERT(help); + help->helper = helper; } atomic_set(&conntrack->ct_general.use, 1); @@ -972,11 +968,8 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, #endif nf_conntrack_get(&conntrack->master->ct_general); NF_CT_STAT_INC(expect_new); - } else { - conntrack->helper = __nf_ct_helper_find(&repl_tuple); - + } else NF_CT_STAT_INC(new); - } /* Overload tuple linked list to put us in unconfirmed list. */ list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed); @@ -1206,14 +1199,16 @@ void nf_conntrack_expect_put(struct nf_conntrack_expect *exp) static void nf_conntrack_expect_insert(struct nf_conntrack_expect *exp) { + struct nf_conn_help *master_help = nfct_help(exp->master); + atomic_inc(&exp->use); - exp->master->expecting++; + master_help->expecting++; list_add(&exp->list, &nf_conntrack_expect_list); init_timer(&exp->timeout); exp->timeout.data = (unsigned long)exp; exp->timeout.function = expectation_timed_out; - exp->timeout.expires = jiffies + exp->master->helper->timeout * HZ; + exp->timeout.expires = jiffies + master_help->helper->timeout * HZ; add_timer(&exp->timeout); exp->id = ++nf_conntrack_expect_next_id; @@ -1239,10 +1234,12 @@ static void evict_oldest_expect(struct nf_conn *master) static inline int refresh_timer(struct nf_conntrack_expect *i) { + struct nf_conn_help *master_help = nfct_help(i->master); + if (!del_timer(&i->timeout)) return 0; - i->timeout.expires = jiffies + i->master->helper->timeout*HZ; + i->timeout.expires = jiffies + master_help->helper->timeout*HZ; add_timer(&i->timeout); return 1; } @@ -1251,8 +1248,11 @@ int nf_conntrack_expect_related(struct nf_conntrack_expect *expect) { struct nf_conntrack_expect *i; struct nf_conn *master = expect->master; + struct nf_conn_help *master_help = nfct_help(master); int ret; + NF_CT_ASSERT(master_help); + DEBUGP("nf_conntrack_expect_related %p\n", related_to); DEBUGP("tuple: "); NF_CT_DUMP_TUPLE(&expect->tuple); DEBUGP("mask: "); NF_CT_DUMP_TUPLE(&expect->mask); @@ -1271,8 +1271,8 @@ int nf_conntrack_expect_related(struct nf_conntrack_expect *expect) } } /* Will be over limit? */ - if (master->helper->max_expected && - master->expecting >= master->helper->max_expected) + if (master_help->helper->max_expected && + master_help->expecting >= master_help->helper->max_expected) evict_oldest_expect(master); nf_conntrack_expect_insert(expect); @@ -1283,24 +1283,6 @@ out: return ret; } -/* Alter reply tuple (maybe alter helper). This is for NAT, and is - implicitly racy: see __nf_conntrack_confirm */ -void nf_conntrack_alter_reply(struct nf_conn *conntrack, - const struct nf_conntrack_tuple *newreply) -{ - write_lock_bh(&nf_conntrack_lock); - /* Should be unconfirmed, so not in hash table yet */ - NF_CT_ASSERT(!nf_ct_is_confirmed(conntrack)); - - DEBUGP("Altering reply tuple of %p to ", conntrack); - NF_CT_DUMP_TUPLE(newreply); - - conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply; - if (!conntrack->master && conntrack->expecting == 0) - conntrack->helper = __nf_ct_helper_find(newreply); - write_unlock_bh(&nf_conntrack_lock); -} - int nf_conntrack_helper_register(struct nf_conntrack_helper *me) { int ret; @@ -1308,9 +1290,8 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me) ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help", sizeof(struct nf_conn) - + sizeof(union nf_conntrack_help) - + __alignof__(union nf_conntrack_help), - init_conntrack_for_helper); + + sizeof(struct nf_conn_help) + + __alignof__(struct nf_conn_help)); if (ret < 0) { printk(KERN_ERR "nf_conntrack_helper_reigster: Unable to create slab cache for conntracks\n"); return ret; @@ -1338,9 +1319,12 @@ __nf_conntrack_helper_find_byname(const char *name) static inline int unhelp(struct nf_conntrack_tuple_hash *i, const struct nf_conntrack_helper *me) { - if (nf_ct_tuplehash_to_ctrack(i)->helper == me) { - nf_conntrack_event(IPCT_HELPER, nf_ct_tuplehash_to_ctrack(i)); - nf_ct_tuplehash_to_ctrack(i)->helper = NULL; + struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i); + struct nf_conn_help *help = nfct_help(ct); + + if (help && help->helper == me) { + nf_conntrack_event(IPCT_HELPER, ct); + help->helper = NULL; } return 0; } @@ -1356,7 +1340,8 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) /* Get rid of expectations */ list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) { - if (exp->master->helper == me && del_timer(&exp->timeout)) { + struct nf_conn_help *help = nfct_help(exp->master); + if (help->helper == me && del_timer(&exp->timeout)) { nf_ct_unlink_expect(exp); nf_conntrack_expect_put(exp); } @@ -1697,7 +1682,7 @@ int __init nf_conntrack_init(void) } ret = nf_conntrack_register_cache(NF_CT_F_BASIC, "nf_conntrack:basic", - sizeof(struct nf_conn), NULL); + sizeof(struct nf_conn)); if (ret < 0) { printk(KERN_ERR "Unable to create nf_conn slab cache\n"); goto err_free_hash; diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 6f210f399762..cd191b0d4ac7 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -440,7 +440,7 @@ static int help(struct sk_buff **pskb, u32 seq; int dir = CTINFO2DIR(ctinfo); unsigned int matchlen, matchoff; - struct ip_ct_ftp_master *ct_ftp_info = &ct->help->ct_ftp_info; + struct ip_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info; struct nf_conntrack_expect *exp; struct nf_conntrack_man cmd = {}; diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 9ff3463037e1..aef3cb41131f 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -2,7 +2,7 @@ * protocol helpers and general trouble making from userspace. * * (C) 2001 by Jay Schulist - * (C) 2002-2005 by Harald Welte + * (C) 2002-2006 by Harald Welte * (C) 2003 by Patrick Mchardy * (C) 2005 by Pablo Neira Ayuso * @@ -44,7 +44,7 @@ MODULE_LICENSE("GPL"); -static char __initdata version[] = "0.92"; +static char __initdata version[] = "0.93"; #if 0 #define DEBUGP printk @@ -165,15 +165,16 @@ static inline int ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct) { struct nfattr *nest_helper; + const struct nf_conn_help *help = nfct_help(ct); - if (!ct->helper) + if (!help || !help->helper) return 0; nest_helper = NFA_NEST(skb, CTA_HELP); - NFA_PUT(skb, CTA_HELP_NAME, strlen(ct->helper->name), ct->helper->name); + NFA_PUT(skb, CTA_HELP_NAME, strlen(help->helper->name), help->helper->name); - if (ct->helper->to_nfattr) - ct->helper->to_nfattr(skb, ct); + if (help->helper->to_nfattr) + help->helper->to_nfattr(skb, ct); NFA_NEST_END(skb, nest_helper); @@ -903,11 +904,17 @@ static inline int ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[]) { struct nf_conntrack_helper *helper; + struct nf_conn_help *help = nfct_help(ct); char *helpname; int err; DEBUGP("entered %s\n", __FUNCTION__); + if (!help) { + /* FIXME: we need to reallocate and rehash */ + return -EBUSY; + } + /* don't change helper of sibling connections */ if (ct->master) return -EINVAL; @@ -924,18 +931,18 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[]) return -EINVAL; } - if (ct->helper) { + if (help->helper) { if (!helper) { /* we had a helper before ... */ nf_ct_remove_expectations(ct); - ct->helper = NULL; + help->helper = NULL; } else { /* need to zero data of old helper */ - memset(&ct->help, 0, sizeof(ct->help)); + memset(&help->help, 0, sizeof(help->help)); } } - ct->helper = helper; + help->helper = helper; return 0; } @@ -1050,14 +1057,9 @@ ctnetlink_create_conntrack(struct nfattr *cda[], ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); #endif - ct->helper = nf_ct_helper_find_get(rtuple); - add_timer(&ct->timeout); nf_conntrack_hash_insert(ct); - if (ct->helper) - nf_ct_helper_put(ct->helper); - DEBUGP("conntrack with id %u inserted\n", ct->id); return 0; @@ -1417,7 +1419,8 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, } list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) { - if (exp->master->helper == h + struct nf_conn_help *m_help = nfct_help(exp->master); + if (m_help->helper == h && del_timer(&exp->timeout)) { nf_ct_unlink_expect(exp); nf_conntrack_expect_put(exp); @@ -1452,6 +1455,7 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3) struct nf_conntrack_tuple_hash *h = NULL; struct nf_conntrack_expect *exp; struct nf_conn *ct; + struct nf_conn_help *help; int err = 0; DEBUGP("entered %s\n", __FUNCTION__); @@ -1472,8 +1476,9 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3) if (!h) return -ENOENT; ct = nf_ct_tuplehash_to_ctrack(h); + help = nfct_help(ct); - if (!ct->helper) { + if (!help || !help->helper) { /* such conntrack hasn't got any helper, abort */ err = -EINVAL; goto out; diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 617599aeeead..290d5a0c559b 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -839,7 +839,6 @@ EXPORT_SYMBOL(nf_conntrack_l3proto_unregister); EXPORT_SYMBOL(nf_conntrack_protocol_register); EXPORT_SYMBOL(nf_conntrack_protocol_unregister); EXPORT_SYMBOL(nf_ct_invert_tuplepr); -EXPORT_SYMBOL(nf_conntrack_alter_reply); EXPORT_SYMBOL(nf_conntrack_destroyed); EXPORT_SYMBOL(need_conntrack); EXPORT_SYMBOL(nf_conntrack_helper_register); diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c index 38b6715e1db4..0ddb32363d06 100644 --- a/net/netfilter/xt_helper.c +++ b/net/netfilter/xt_helper.c @@ -96,6 +96,7 @@ match(const struct sk_buff *skb, { const struct xt_helper_info *info = matchinfo; struct nf_conn *ct; + struct nf_conn_help *master_help; enum ip_conntrack_info ctinfo; int ret = info->invert; @@ -111,7 +112,8 @@ match(const struct sk_buff *skb, } read_lock_bh(&nf_conntrack_lock); - if (!ct->master->helper) { + master_help = nfct_help(ct->master); + if (!master_help || !master_help->helper) { DEBUGP("xt_helper: master ct %p has no helper\n", exp->expectant); goto out_unlock; @@ -123,8 +125,8 @@ match(const struct sk_buff *skb, if (info->name[0] == '\0') ret ^= 1; else - ret ^= !strncmp(ct->master->helper->name, info->name, - strlen(ct->master->helper->name)); + ret ^= !strncmp(master_help->helper->name, info->name, + strlen(master_help->helper->name)); out_unlock: read_unlock_bh(&nf_conntrack_lock); return ret; -- cgit v1.2.3 From ba66c6e8b292997467128506f39fa6607e959050 Mon Sep 17 00:00:00 2001 From: Ian McDonald Date: Mon, 20 Mar 2006 17:56:56 -0800 Subject: [DCCP]: Set the default CCID according to kernel config selection Now CCID2 is the default, as stated in the RFC drafts, but we allow a config where just CCID3 is built, where CCID3 becomes the default. Signed-off-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/dccp.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/dccp.h b/include/linux/dccp.h index f91c8a62406d..a70d1a27e7fc 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -329,9 +329,18 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb) /* initial values for each feature */ #define DCCPF_INITIAL_SEQUENCE_WINDOW 100 -#define DCCPF_INITIAL_CCID 2 #define DCCPF_INITIAL_ACK_RATIO 2 + +#if defined(CONFIG_IP_DCCP_CCID2) || defined(CONFIG_IP_DCCP_CCID2_MODULE) +#define DCCPF_INITIAL_CCID 2 #define DCCPF_INITIAL_SEND_ACK_VECTOR 1 +#elif defined(CONFIG_IP_DCCP_CCID3) || defined(CONFIG_IP_DCCP_CCID3_MODULE) +#define DCCPF_INITIAL_CCID 3 +#define DCCPF_INITIAL_SEND_ACK_VECTOR 0 +#else +#error "At least one CCID must be built as the default" +#endif + /* FIXME: for now we're default to 1 but it should really be 0 */ #define DCCPF_INITIAL_SEND_NDP_COUNT 1 -- cgit v1.2.3 From 37f9f7334b86ffc3b8a1921842ae33cb9aa22ee3 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 20 Mar 2006 17:59:06 -0800 Subject: [NETFILTER]: xt_tables: add centralized error checking Introduce new functions for common match/target checks (private data size, valid hooks, valid tables and valid protocols) to get more consistent error reporting and to avoid each module duplicating them. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter/x_tables.h | 23 +++++++++--- net/netfilter/x_tables.c | 72 ++++++++++++++++++++++++++++++++++---- 2 files changed, 84 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 6500d4e59d46..b9c37e1e6730 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -92,8 +92,6 @@ struct xt_match const char name[XT_FUNCTION_MAXNAMELEN-1]; - u_int8_t revision; - /* Return true or false: return FALSE and set *hotdrop = 1 to force immediate packet drop. */ /* Arguments changed since 2.6.9, as this must now handle @@ -120,6 +118,12 @@ struct xt_match /* Set this to THIS_MODULE if you are a module, otherwise NULL */ struct module *me; + + char *table; + unsigned int matchsize; + unsigned int hooks; + unsigned short proto; + u_int8_t revision; }; /* Registration hooks for targets. */ @@ -129,8 +133,6 @@ struct xt_target const char name[XT_FUNCTION_MAXNAMELEN-1]; - u_int8_t revision; - /* Returns verdict. Argument order changed since 2.6.9, as this must now handle non-linear skbs, using skb_copy_bits and skb_ip_make_writable. */ @@ -156,6 +158,12 @@ struct xt_target /* Set this to THIS_MODULE if you are a module, otherwise NULL */ struct module *me; + + char *table; + unsigned int targetsize; + unsigned int hooks; + unsigned short proto; + u_int8_t revision; }; /* Furniture shopping... */ @@ -207,6 +215,13 @@ extern void xt_unregister_target(int af, struct xt_target *target); extern int xt_register_match(int af, struct xt_match *target); extern void xt_unregister_match(int af, struct xt_match *target); +extern int xt_check_match(const struct xt_match *match, unsigned short family, + unsigned int size, const char *table, unsigned int hook, + unsigned short proto, int inv_proto); +extern int xt_check_target(const struct xt_target *target, unsigned short family, + unsigned int size, const char *table, unsigned int hook, + unsigned short proto, int inv_proto); + extern int xt_register_table(struct xt_table *table, struct xt_table_info *bootstrap, struct xt_table_info *newinfo); diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index d7817afc6b96..750b92829766 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -52,6 +52,12 @@ enum { MATCH, }; +static const char *xt_prefix[NPROTO] = { + [AF_INET] = "ip", + [AF_INET6] = "ip6", + [NF_ARP] = "arp", +}; + /* Registration hooks for targets. */ int xt_register_target(int af, struct xt_target *target) @@ -158,18 +164,12 @@ struct xt_target *xt_find_target(int af, const char *name, u8 revision) } EXPORT_SYMBOL(xt_find_target); -static const char *xt_prefix[NPROTO] = { - [AF_INET] = "ipt_%s", - [AF_INET6] = "ip6t_%s", - [NF_ARP] = "arpt_%s", -}; - struct xt_target *xt_request_find_target(int af, const char *name, u8 revision) { struct xt_target *target; target = try_then_request_module(xt_find_target(af, name, revision), - xt_prefix[af], name); + "%st_%s", xt_prefix[af], name); if (IS_ERR(target) || !target) return NULL; return target; @@ -237,6 +237,64 @@ int xt_find_revision(int af, const char *name, u8 revision, int target, } EXPORT_SYMBOL_GPL(xt_find_revision); +int xt_check_match(const struct xt_match *match, unsigned short family, + unsigned int size, const char *table, unsigned int hook_mask, + unsigned short proto, int inv_proto) +{ + if (XT_ALIGN(match->matchsize) != size) { + printk("%s_tables: %s match: invalid size %Zu != %u\n", + xt_prefix[family], match->name, + XT_ALIGN(match->matchsize), size); + return -EINVAL; + } + if (match->table && strcmp(match->table, table)) { + printk("%s_tables: %s match: only valid in %s table, not %s\n", + xt_prefix[family], match->name, match->table, table); + return -EINVAL; + } + if (match->hooks && (hook_mask & ~match->hooks) != 0) { + printk("%s_tables: %s match: bad hook_mask %u\n", + xt_prefix[family], match->name, hook_mask); + return -EINVAL; + } + if (match->proto && (match->proto != proto || inv_proto)) { + printk("%s_tables: %s match: only valid for protocol %u\n", + xt_prefix[family], match->name, match->proto); + return -EINVAL; + } + return 0; +} +EXPORT_SYMBOL_GPL(xt_check_match); + +int xt_check_target(const struct xt_target *target, unsigned short family, + unsigned int size, const char *table, unsigned int hook_mask, + unsigned short proto, int inv_proto) +{ + if (XT_ALIGN(target->targetsize) != size) { + printk("%s_tables: %s target: invalid size %Zu != %u\n", + xt_prefix[family], target->name, + XT_ALIGN(target->targetsize), size); + return -EINVAL; + } + if (target->table && strcmp(target->table, table)) { + printk("%s_tables: %s target: only valid in %s table, not %s\n", + xt_prefix[family], target->name, target->table, table); + return -EINVAL; + } + if (target->hooks && (hook_mask & ~target->hooks) != 0) { + printk("%s_tables: %s target: bad hook_mask %u\n", + xt_prefix[family], target->name, hook_mask); + return -EINVAL; + } + if (target->proto && (target->proto != proto || inv_proto)) { + printk("%s_tables: %s target: only valid for protocol %u\n", + xt_prefix[family], target->name, target->proto); + return -EINVAL; + } + return 0; +} +EXPORT_SYMBOL_GPL(xt_check_target); + struct xt_table_info *xt_alloc_table_info(unsigned int size) { struct xt_table_info *newinfo; -- cgit v1.2.3 From 1c524830d0b39472f0278989bf1119750a5e234d Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 20 Mar 2006 18:02:15 -0800 Subject: [NETFILTER]: x_tables: pass registered match/target data to match/target functions This allows to make decisions based on the revision (and address family with a follow-up patch) at runtime. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter/x_tables.h | 10 ++++++++-- net/ipv4/netfilter/arp_tables.c | 5 +++-- net/ipv4/netfilter/ip_tables.c | 13 +++++++------ net/ipv6/netfilter/ip6_tables.c | 11 ++++++----- net/sched/act_ipt.c | 10 ++++++---- 5 files changed, 30 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index b9c37e1e6730..2fdbc4a446bf 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -100,6 +100,7 @@ struct xt_match int (*match)(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, + const struct xt_match *match, const void *matchinfo, int offset, unsigned int protoff, @@ -109,12 +110,14 @@ struct xt_match /* Should return true or false. */ int (*checkentry)(const char *tablename, const void *ip, + const struct xt_match *match, void *matchinfo, unsigned int matchinfosize, unsigned int hook_mask); /* Called when entry of this type deleted. */ - void (*destroy)(void *matchinfo, unsigned int matchinfosize); + void (*destroy)(const struct xt_match *match, void *matchinfo, + unsigned int matchinfosize); /* Set this to THIS_MODULE if you are a module, otherwise NULL */ struct module *me; @@ -140,6 +143,7 @@ struct xt_target const struct net_device *in, const struct net_device *out, unsigned int hooknum, + const struct xt_target *target, const void *targinfo, void *userdata); @@ -149,12 +153,14 @@ struct xt_target /* Should return true or false. */ int (*checkentry)(const char *tablename, const void *entry, + const struct xt_target *target, void *targinfo, unsigned int targinfosize, unsigned int hook_mask); /* Called when entry of this type deleted. */ - void (*destroy)(void *targinfo, unsigned int targinfosize); + void (*destroy)(const struct xt_target *target, void *targinfo, + unsigned int targinfosize); /* Set this to THIS_MODULE if you are a module, otherwise NULL */ struct module *me; diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 6162d0e328ec..87b3b7920101 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -300,6 +300,7 @@ unsigned int arpt_do_table(struct sk_buff **pskb, verdict = t->u.kernel.target->target(pskb, in, out, hook, + t->u.kernel.target, t->data, userdata); @@ -491,7 +492,7 @@ static inline int check_entry(struct arpt_entry *e, const char *name, unsigned i goto out; } } else if (t->u.kernel.target->checkentry - && !t->u.kernel.target->checkentry(name, e, t->data, + && !t->u.kernel.target->checkentry(name, e, target, t->data, t->u.target_size - sizeof(*t), e->comefrom)) { @@ -560,7 +561,7 @@ static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i) t = arpt_get_target(e); if (t->u.kernel.target->destroy) - t->u.kernel.target->destroy(t->data, + t->u.kernel.target->destroy(t->u.kernel.target, t->data, t->u.target_size - sizeof(*t)); module_put(t->u.kernel.target->me); return 0; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 62f8d639ab9c..2381a4aa71d0 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -197,8 +197,8 @@ int do_match(struct ipt_entry_match *m, int *hotdrop) { /* Stop iteration if it doesn't match */ - if (!m->u.kernel.match->match(skb, in, out, m->data, offset, - skb->nh.iph->ihl*4, hotdrop)) + if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data, + offset, skb->nh.iph->ihl*4, hotdrop)) return 1; else return 0; @@ -305,6 +305,7 @@ ipt_do_table(struct sk_buff **pskb, verdict = t->u.kernel.target->target(pskb, in, out, hook, + t->u.kernel.target, t->data, userdata); @@ -464,7 +465,7 @@ cleanup_match(struct ipt_entry_match *m, unsigned int *i) return 1; if (m->u.kernel.match->destroy) - m->u.kernel.match->destroy(m->data, + m->u.kernel.match->destroy(m->u.kernel.match, m->data, m->u.match_size - sizeof(*m)); module_put(m->u.kernel.match->me); return 0; @@ -517,7 +518,7 @@ check_match(struct ipt_entry_match *m, goto err; if (m->u.kernel.match->checkentry - && !m->u.kernel.match->checkentry(name, ip, m->data, + && !m->u.kernel.match->checkentry(name, ip, match, m->data, m->u.match_size - sizeof(*m), hookmask)) { duprintf("ip_tables: check failed for `%s'.\n", @@ -578,7 +579,7 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size, goto cleanup_matches; } } else if (t->u.kernel.target->checkentry - && !t->u.kernel.target->checkentry(name, e, t->data, + && !t->u.kernel.target->checkentry(name, e, target, t->data, t->u.target_size - sizeof(*t), e->comefrom)) { @@ -652,7 +653,7 @@ cleanup_entry(struct ipt_entry *e, unsigned int *i) IPT_MATCH_ITERATE(e, cleanup_match, NULL); t = ipt_get_target(e); if (t->u.kernel.target->destroy) - t->u.kernel.target->destroy(t->data, + t->u.kernel.target->destroy(t->u.kernel.target, t->data, t->u.target_size - sizeof(*t)); module_put(t->u.kernel.target->me); return 0; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index e2e8d0140d7b..1b32a2d1e9e0 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -251,7 +251,7 @@ int do_match(struct ip6t_entry_match *m, int *hotdrop) { /* Stop iteration if it doesn't match */ - if (!m->u.kernel.match->match(skb, in, out, m->data, + if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data, offset, protoff, hotdrop)) return 1; else @@ -373,6 +373,7 @@ ip6t_do_table(struct sk_buff **pskb, verdict = t->u.kernel.target->target(pskb, in, out, hook, + t->u.kernel.target, t->data, userdata); @@ -531,7 +532,7 @@ cleanup_match(struct ip6t_entry_match *m, unsigned int *i) return 1; if (m->u.kernel.match->destroy) - m->u.kernel.match->destroy(m->data, + m->u.kernel.match->destroy(m->u.kernel.match, m->data, m->u.match_size - sizeof(*m)); module_put(m->u.kernel.match->me); return 0; @@ -584,7 +585,7 @@ check_match(struct ip6t_entry_match *m, goto err; if (m->u.kernel.match->checkentry - && !m->u.kernel.match->checkentry(name, ipv6, m->data, + && !m->u.kernel.match->checkentry(name, ipv6, match, m->data, m->u.match_size - sizeof(*m), hookmask)) { duprintf("ip_tables: check failed for `%s'.\n", @@ -645,7 +646,7 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size, goto cleanup_matches; } } else if (t->u.kernel.target->checkentry - && !t->u.kernel.target->checkentry(name, e, t->data, + && !t->u.kernel.target->checkentry(name, e, target, t->data, t->u.target_size - sizeof(*t), e->comefrom)) { @@ -719,7 +720,7 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i) IP6T_MATCH_ITERATE(e, cleanup_match, NULL); t = ip6t_get_target(e); if (t->u.kernel.target->destroy) - t->u.kernel.target->destroy(t->data, + t->u.kernel.target->destroy(t->u.kernel.target, t->data, t->u.target_size - sizeof(*t)); module_put(t->u.kernel.target->me); return 0; diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 39a22a3ffe78..6056d20ef429 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c @@ -70,7 +70,8 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook) t->u.kernel.target = target; if (t->u.kernel.target->checkentry - && !t->u.kernel.target->checkentry(table, NULL, t->data, + && !t->u.kernel.target->checkentry(table, NULL, + t->u.kernel.target, t->data, t->u.target_size - sizeof(*t), hook)) { DPRINTK("ipt_init_target: check failed for `%s'.\n", @@ -86,7 +87,7 @@ static void ipt_destroy_target(struct ipt_entry_target *t) { if (t->u.kernel.target->destroy) - t->u.kernel.target->destroy(t->data, + t->u.kernel.target->destroy(t->u.kernel.target, t->data, t->u.target_size - sizeof(*t)); module_put(t->u.kernel.target->me); } @@ -224,8 +225,9 @@ tcf_ipt(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) /* iptables targets take a double skb pointer in case the skb * needs to be replaced. We don't own the skb, so this must not * happen. The pskb_expand_head above should make sure of this */ - ret = p->t->u.kernel.target->target(&skb, skb->dev, NULL, - p->hook, p->t->data, NULL); + ret = p->t->u.kernel.target->target(&skb, skb->dev, NULL, p->hook, + p->t->u.kernel.target, p->t->data, + NULL); switch (ret) { case NF_ACCEPT: result = TC_ACT_OK; -- cgit v1.2.3 From f2ffd9eeda82b476c034d733be08ecf6a87d2edf Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 20 Mar 2006 18:03:16 -0800 Subject: [NETFILTER]: Move ip6_masked_addrcmp to include/net/ipv6.h Replace netfilter's ip6_masked_addrcmp by a more efficient version in include/net/ipv6.h to make it usable without module dependencies. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/ipv6.h | 12 ++++++++++++ net/ipv6/netfilter/ip6_tables.c | 22 ++++------------------ net/ipv6/netfilter/ip6t_policy.c | 3 ++- 3 files changed, 18 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 3b1d963d396c..c893a1ce4b39 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -282,6 +282,18 @@ static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr return memcmp((const void *) a1, (const void *) a2, sizeof(struct in6_addr)); } +static inline int +ipv6_masked_addr_cmp(const struct in6_addr *a1, const struct in6_addr *m, + const struct in6_addr *a2) +{ + unsigned int i; + + for (i = 0; i < 4; i++) + if ((a1->s6_addr32[i] ^ a2->s6_addr32[i]) & m->s6_addr32[i]) + return 1; + return 0; +} + static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2) { memcpy((void *) a1, (const void *) a2, sizeof(struct in6_addr)); diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index b75f8fdc3afe..d74ec335743e 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -94,19 +94,6 @@ do { \ #define up(x) do { printk("UP:%u:" #x "\n", __LINE__); up(x); } while(0) #endif -int -ip6_masked_addrcmp(const struct in6_addr *addr1, const struct in6_addr *mask, - const struct in6_addr *addr2) -{ - int i; - for( i = 0; i < 16; i++){ - if((addr1->s6_addr[i] & mask->s6_addr[i]) != - (addr2->s6_addr[i] & mask->s6_addr[i])) - return 1; - } - return 0; -} - /* Check for an extension */ int ip6t_ext_hdr(u8 nexthdr) @@ -135,10 +122,10 @@ ip6_packet_match(const struct sk_buff *skb, #define FWINV(bool,invflg) ((bool) ^ !!(ip6info->invflags & invflg)) - if (FWINV(ip6_masked_addrcmp(&ipv6->saddr, &ip6info->smsk, - &ip6info->src), IP6T_INV_SRCIP) - || FWINV(ip6_masked_addrcmp(&ipv6->daddr, &ip6info->dmsk, - &ip6info->dst), IP6T_INV_DSTIP)) { + if (FWINV(ipv6_masked_addr_cmp(&ipv6->saddr, &ip6info->smsk, + &ip6info->src), IP6T_INV_SRCIP) + || FWINV(ipv6_masked_addr_cmp(&ipv6->daddr, &ip6info->dmsk, + &ip6info->dst), IP6T_INV_DSTIP)) { dprintf("Source or dest mismatch.\n"); /* dprintf("SRC: %u. Mask: %u. Target: %u.%s\n", ip->saddr, @@ -1526,7 +1513,6 @@ EXPORT_SYMBOL(ip6t_unregister_table); EXPORT_SYMBOL(ip6t_do_table); EXPORT_SYMBOL(ip6t_ext_hdr); EXPORT_SYMBOL(ipv6_find_hdr); -EXPORT_SYMBOL(ip6_masked_addrcmp); module_init(init); module_exit(fini); diff --git a/net/ipv6/netfilter/ip6t_policy.c b/net/ipv6/netfilter/ip6t_policy.c index b2f30072ca6e..f2a59970e007 100644 --- a/net/ipv6/netfilter/ip6t_policy.c +++ b/net/ipv6/netfilter/ip6t_policy.c @@ -27,7 +27,8 @@ static inline int match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e) { #define MATCH_ADDR(x,y,z) (!e->match.x || \ - ((!ip6_masked_addrcmp(&e->x.a6, &e->y.a6, z)) \ + ((!ipv6_masked_addr_cmp(&e->x.a6, &e->y.a6, \ + z)) \ ^ e->invert.x)) #define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x)) -- cgit v1.2.3 From c4b885139203d37f76662c37ae645fe8e0f4e4e5 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 20 Mar 2006 18:03:40 -0800 Subject: [NETFILTER]: x_tables: replace IPv4/IPv6 policy match by address family independant version Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter/x_tables.h | 4 + include/linux/netfilter/xt_policy.h | 58 ++++++++ include/linux/netfilter_ipv4/ipt_policy.h | 69 +++------- include/linux/netfilter_ipv6/ip6t_policy.h | 69 +++------- net/ipv4/netfilter/Kconfig | 10 -- net/ipv4/netfilter/Makefile | 1 - net/ipv4/netfilter/ipt_policy.c | 174 ------------------------ net/ipv6/netfilter/Kconfig | 10 -- net/ipv6/netfilter/Makefile | 1 - net/ipv6/netfilter/ip6t_policy.c | 174 ------------------------ net/netfilter/Kconfig | 10 ++ net/netfilter/Makefile | 1 + net/netfilter/xt_policy.c | 209 +++++++++++++++++++++++++++++ 13 files changed, 314 insertions(+), 476 deletions(-) create mode 100644 include/linux/netfilter/xt_policy.h delete mode 100644 net/ipv4/netfilter/ipt_policy.c delete mode 100644 net/ipv6/netfilter/ip6t_policy.c create mode 100644 net/netfilter/xt_policy.c (limited to 'include') diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 2fdbc4a446bf..46a0f974f87c 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -126,6 +126,8 @@ struct xt_match unsigned int matchsize; unsigned int hooks; unsigned short proto; + + unsigned short family; u_int8_t revision; }; @@ -169,6 +171,8 @@ struct xt_target unsigned int targetsize; unsigned int hooks; unsigned short proto; + + unsigned short family; u_int8_t revision; }; diff --git a/include/linux/netfilter/xt_policy.h b/include/linux/netfilter/xt_policy.h new file mode 100644 index 000000000000..a8132ec076fb --- /dev/null +++ b/include/linux/netfilter/xt_policy.h @@ -0,0 +1,58 @@ +#ifndef _XT_POLICY_H +#define _XT_POLICY_H + +#define XT_POLICY_MAX_ELEM 4 + +enum xt_policy_flags +{ + XT_POLICY_MATCH_IN = 0x1, + XT_POLICY_MATCH_OUT = 0x2, + XT_POLICY_MATCH_NONE = 0x4, + XT_POLICY_MATCH_STRICT = 0x8, +}; + +enum xt_policy_modes +{ + XT_POLICY_MODE_TRANSPORT, + XT_POLICY_MODE_TUNNEL +}; + +struct xt_policy_spec +{ + u_int8_t saddr:1, + daddr:1, + proto:1, + mode:1, + spi:1, + reqid:1; +}; + +union xt_policy_addr +{ + struct in_addr a4; + struct in6_addr a6; +}; + +struct xt_policy_elem +{ + union xt_policy_addr saddr; + union xt_policy_addr smask; + union xt_policy_addr daddr; + union xt_policy_addr dmask; + u_int32_t spi; + u_int32_t reqid; + u_int8_t proto; + u_int8_t mode; + + struct xt_policy_spec match; + struct xt_policy_spec invert; +}; + +struct xt_policy_info +{ + struct xt_policy_elem pol[XT_POLICY_MAX_ELEM]; + u_int16_t flags; + u_int16_t len; +}; + +#endif /* _XT_POLICY_H */ diff --git a/include/linux/netfilter_ipv4/ipt_policy.h b/include/linux/netfilter_ipv4/ipt_policy.h index a3f6eff39d33..b9478a255301 100644 --- a/include/linux/netfilter_ipv4/ipt_policy.h +++ b/include/linux/netfilter_ipv4/ipt_policy.h @@ -1,58 +1,21 @@ #ifndef _IPT_POLICY_H #define _IPT_POLICY_H -#define IPT_POLICY_MAX_ELEM 4 - -enum ipt_policy_flags -{ - IPT_POLICY_MATCH_IN = 0x1, - IPT_POLICY_MATCH_OUT = 0x2, - IPT_POLICY_MATCH_NONE = 0x4, - IPT_POLICY_MATCH_STRICT = 0x8, -}; - -enum ipt_policy_modes -{ - IPT_POLICY_MODE_TRANSPORT, - IPT_POLICY_MODE_TUNNEL -}; - -struct ipt_policy_spec -{ - u_int8_t saddr:1, - daddr:1, - proto:1, - mode:1, - spi:1, - reqid:1; -}; - -union ipt_policy_addr -{ - struct in_addr a4; - struct in6_addr a6; -}; - -struct ipt_policy_elem -{ - union ipt_policy_addr saddr; - union ipt_policy_addr smask; - union ipt_policy_addr daddr; - union ipt_policy_addr dmask; - u_int32_t spi; - u_int32_t reqid; - u_int8_t proto; - u_int8_t mode; - - struct ipt_policy_spec match; - struct ipt_policy_spec invert; -}; - -struct ipt_policy_info -{ - struct ipt_policy_elem pol[IPT_POLICY_MAX_ELEM]; - u_int16_t flags; - u_int16_t len; -}; +#define IPT_POLICY_MAX_ELEM XT_POLICY_MAX_ELEM + +/* ipt_policy_flags */ +#define IPT_POLICY_MATCH_IN XT_POLICY_MATCH_IN +#define IPT_POLICY_MATCH_OUT XT_POLICY_MATCH_OUT +#define IPT_POLICY_MATCH_NONE XT_POLICY_MATCH_NONE +#define IPT_POLICY_MATCH_STRICT XT_POLICY_MATCH_STRICT + +/* ipt_policy_modes */ +#define IPT_POLICY_MODE_TRANSPORT XT_POLICY_MODE_TRANSPORT +#define IPT_POLICY_MODE_TUNNEL XT_POLICY_MODE_TUNNEL + +#define ipt_policy_spec xt_policy_spec +#define ipt_policy_addr xt_policy_addr +#define ipt_policy_elem xt_policy_elem +#define ipt_policy_info xt_policy_info #endif /* _IPT_POLICY_H */ diff --git a/include/linux/netfilter_ipv6/ip6t_policy.h b/include/linux/netfilter_ipv6/ip6t_policy.h index 671bd818300f..6bab3163d2fb 100644 --- a/include/linux/netfilter_ipv6/ip6t_policy.h +++ b/include/linux/netfilter_ipv6/ip6t_policy.h @@ -1,58 +1,21 @@ #ifndef _IP6T_POLICY_H #define _IP6T_POLICY_H -#define IP6T_POLICY_MAX_ELEM 4 - -enum ip6t_policy_flags -{ - IP6T_POLICY_MATCH_IN = 0x1, - IP6T_POLICY_MATCH_OUT = 0x2, - IP6T_POLICY_MATCH_NONE = 0x4, - IP6T_POLICY_MATCH_STRICT = 0x8, -}; - -enum ip6t_policy_modes -{ - IP6T_POLICY_MODE_TRANSPORT, - IP6T_POLICY_MODE_TUNNEL -}; - -struct ip6t_policy_spec -{ - u_int8_t saddr:1, - daddr:1, - proto:1, - mode:1, - spi:1, - reqid:1; -}; - -union ip6t_policy_addr -{ - struct in_addr a4; - struct in6_addr a6; -}; - -struct ip6t_policy_elem -{ - union ip6t_policy_addr saddr; - union ip6t_policy_addr smask; - union ip6t_policy_addr daddr; - union ip6t_policy_addr dmask; - u_int32_t spi; - u_int32_t reqid; - u_int8_t proto; - u_int8_t mode; - - struct ip6t_policy_spec match; - struct ip6t_policy_spec invert; -}; - -struct ip6t_policy_info -{ - struct ip6t_policy_elem pol[IP6T_POLICY_MAX_ELEM]; - u_int16_t flags; - u_int16_t len; -}; +#define IP6T_POLICY_MAX_ELEM XT_POLICY_MAX_ELEM + +/* ip6t_policy_flags */ +#define IP6T_POLICY_MATCH_IN XT_POLICY_MATCH_IN +#define IP6T_POLICY_MATCH_OUT XT_POLICY_MATCH_OUT +#define IP6T_POLICY_MATCH_NONE XT_POLICY_MATCH_NONE +#define IP6T_POLICY_MATCH_STRICT XT_POLICY_MATCH_STRICT + +/* ip6t_policy_modes */ +#define IP6T_POLICY_MODE_TRANSPORT XT_POLICY_MODE_TRANSPORT +#define IP6T_POLICY_MODE_TUNNEL XT_POLICY_MODE_TUNNEL + +#define ip6t_policy_spec xt_policy_spec +#define ip6t_policy_addr xt_policy_addr +#define ip6t_policy_elem xt_policy_elem +#define ip6t_policy_info xt_policy_info #endif /* _IP6T_POLICY_H */ diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index db783036e4d8..933ee7a9efdf 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -303,16 +303,6 @@ config IP_NF_MATCH_HASHLIMIT destination IP' or `500pps from any given source IP' with a single IPtables rule. -config IP_NF_MATCH_POLICY - tristate "IPsec policy match support" - depends on IP_NF_IPTABLES && XFRM - help - Policy matching allows you to match packets based on the - IPsec policy that was used during decapsulation/will - be used during encapsulation. - - To compile it as a module, choose M here. If unsure, say N. - # `filter', generic and specific targets config IP_NF_FILTER tristate "Packet filtering" diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index e5c5b3202f02..3fe80924ac54 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -57,7 +57,6 @@ obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o -obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o # targets obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o diff --git a/net/ipv4/netfilter/ipt_policy.c b/net/ipv4/netfilter/ipt_policy.c deleted file mode 100644 index b73f590b226b..000000000000 --- a/net/ipv4/netfilter/ipt_policy.c +++ /dev/null @@ -1,174 +0,0 @@ -/* IP tables module for matching IPsec policy - * - * Copyright (c) 2004,2005 Patrick McHardy, - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -MODULE_AUTHOR("Patrick McHardy "); -MODULE_DESCRIPTION("IPtables IPsec policy matching module"); -MODULE_LICENSE("GPL"); - - -static inline int -match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e) -{ -#define MATCH_ADDR(x,y,z) (!e->match.x || \ - ((e->x.a4.s_addr == (e->y.a4.s_addr & (z))) \ - ^ e->invert.x)) -#define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x)) - - return MATCH_ADDR(saddr, smask, x->props.saddr.a4) && - MATCH_ADDR(daddr, dmask, x->id.daddr.a4) && - MATCH(proto, x->id.proto) && - MATCH(mode, x->props.mode) && - MATCH(spi, x->id.spi) && - MATCH(reqid, x->props.reqid); -} - -static int -match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info) -{ - const struct ipt_policy_elem *e; - struct sec_path *sp = skb->sp; - int strict = info->flags & IPT_POLICY_MATCH_STRICT; - int i, pos; - - if (sp == NULL) - return -1; - if (strict && info->len != sp->len) - return 0; - - for (i = sp->len - 1; i >= 0; i--) { - pos = strict ? i - sp->len + 1 : 0; - if (pos >= info->len) - return 0; - e = &info->pol[pos]; - - if (match_xfrm_state(sp->x[i].xvec, e)) { - if (!strict) - return 1; - } else if (strict) - return 0; - } - - return strict ? 1 : 0; -} - -static int -match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info) -{ - const struct ipt_policy_elem *e; - struct dst_entry *dst = skb->dst; - int strict = info->flags & IPT_POLICY_MATCH_STRICT; - int i, pos; - - if (dst->xfrm == NULL) - return -1; - - for (i = 0; dst && dst->xfrm; dst = dst->child, i++) { - pos = strict ? i : 0; - if (pos >= info->len) - return 0; - e = &info->pol[pos]; - - if (match_xfrm_state(dst->xfrm, e)) { - if (!strict) - return 1; - } else if (strict) - return 0; - } - - return strict ? i == info->len : 0; -} - -static int match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const struct xt_match *match, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - const struct ipt_policy_info *info = matchinfo; - int ret; - - if (info->flags & IPT_POLICY_MATCH_IN) - ret = match_policy_in(skb, info); - else - ret = match_policy_out(skb, info); - - if (ret < 0) - ret = info->flags & IPT_POLICY_MATCH_NONE ? 1 : 0; - else if (info->flags & IPT_POLICY_MATCH_NONE) - ret = 0; - - return ret; -} - -static int checkentry(const char *tablename, const void *ip_void, - const struct xt_match *match, - void *matchinfo, unsigned int matchsize, - unsigned int hook_mask) -{ - struct ipt_policy_info *info = matchinfo; - - if (!(info->flags & (IPT_POLICY_MATCH_IN|IPT_POLICY_MATCH_OUT))) { - printk(KERN_ERR "ipt_policy: neither incoming nor " - "outgoing policy selected\n"); - return 0; - } - if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN) - && info->flags & IPT_POLICY_MATCH_OUT) { - printk(KERN_ERR "ipt_policy: output policy not valid in " - "PRE_ROUTING and INPUT\n"); - return 0; - } - if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT) - && info->flags & IPT_POLICY_MATCH_IN) { - printk(KERN_ERR "ipt_policy: input policy not valid in " - "POST_ROUTING and OUTPUT\n"); - return 0; - } - if (info->len > IPT_POLICY_MAX_ELEM) { - printk(KERN_ERR "ipt_policy: too many policy elements\n"); - return 0; - } - - return 1; -} - -static struct ipt_match policy_match = { - .name = "policy", - .match = match, - .matchsize = sizeof(struct ipt_policy_info), - .checkentry = checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ipt_register_match(&policy_match); -} - -static void __exit fini(void) -{ - ipt_unregister_match(&policy_match); -} - -module_init(init); -module_exit(fini); diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 2d6f8ecbc27b..98f78759f1ab 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig @@ -133,16 +133,6 @@ config IP6_NF_MATCH_EUI64 To compile it as a module, choose M here. If unsure, say N. -config IP6_NF_MATCH_POLICY - tristate "IPsec policy match support" - depends on IP6_NF_IPTABLES && XFRM - help - Policy matching allows you to match packets based on the - IPsec policy that was used during decapsulation/will - be used during encapsulation. - - To compile it as a module, choose M here. If unsure, say N. - # The targets config IP6_NF_FILTER tristate "Packet filtering" diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index db6073c94163..8436a1a1731f 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile @@ -9,7 +9,6 @@ obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o -obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o diff --git a/net/ipv6/netfilter/ip6t_policy.c b/net/ipv6/netfilter/ip6t_policy.c deleted file mode 100644 index f2a59970e007..000000000000 --- a/net/ipv6/netfilter/ip6t_policy.c +++ /dev/null @@ -1,174 +0,0 @@ -/* IP tables module for matching IPsec policy - * - * Copyright (c) 2004,2005 Patrick McHardy, - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -MODULE_AUTHOR("Patrick McHardy "); -MODULE_DESCRIPTION("IPtables IPsec policy matching module"); -MODULE_LICENSE("GPL"); - - -static inline int -match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e) -{ -#define MATCH_ADDR(x,y,z) (!e->match.x || \ - ((!ipv6_masked_addr_cmp(&e->x.a6, &e->y.a6, \ - z)) \ - ^ e->invert.x)) -#define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x)) - - return MATCH_ADDR(saddr, smask, (struct in6_addr *)&x->props.saddr.a6) && - MATCH_ADDR(daddr, dmask, (struct in6_addr *)&x->id.daddr.a6) && - MATCH(proto, x->id.proto) && - MATCH(mode, x->props.mode) && - MATCH(spi, x->id.spi) && - MATCH(reqid, x->props.reqid); -} - -static int -match_policy_in(const struct sk_buff *skb, const struct ip6t_policy_info *info) -{ - const struct ip6t_policy_elem *e; - struct sec_path *sp = skb->sp; - int strict = info->flags & IP6T_POLICY_MATCH_STRICT; - int i, pos; - - if (sp == NULL) - return -1; - if (strict && info->len != sp->len) - return 0; - - for (i = sp->len - 1; i >= 0; i--) { - pos = strict ? i - sp->len + 1 : 0; - if (pos >= info->len) - return 0; - e = &info->pol[pos]; - - if (match_xfrm_state(sp->x[i].xvec, e)) { - if (!strict) - return 1; - } else if (strict) - return 0; - } - - return strict ? 1 : 0; -} - -static int -match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info) -{ - const struct ip6t_policy_elem *e; - struct dst_entry *dst = skb->dst; - int strict = info->flags & IP6T_POLICY_MATCH_STRICT; - int i, pos; - - if (dst->xfrm == NULL) - return -1; - - for (i = 0; dst && dst->xfrm; dst = dst->child, i++) { - pos = strict ? i : 0; - if (pos >= info->len) - return 0; - e = &info->pol[pos]; - - if (match_xfrm_state(dst->xfrm, e)) { - if (!strict) - return 1; - } else if (strict) - return 0; - } - - return strict ? i == info->len : 0; -} - -static int match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const struct xt_match *match, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - const struct ip6t_policy_info *info = matchinfo; - int ret; - - if (info->flags & IP6T_POLICY_MATCH_IN) - ret = match_policy_in(skb, info); - else - ret = match_policy_out(skb, info); - - if (ret < 0) - ret = info->flags & IP6T_POLICY_MATCH_NONE ? 1 : 0; - else if (info->flags & IP6T_POLICY_MATCH_NONE) - ret = 0; - - return ret; -} - -static int checkentry(const char *tablename, const void *ip_void, - const struct xt_match *match, void *matchinfo, - unsigned int matchsize, unsigned int hook_mask) -{ - struct ip6t_policy_info *info = matchinfo; - - if (!(info->flags & (IP6T_POLICY_MATCH_IN|IP6T_POLICY_MATCH_OUT))) { - printk(KERN_ERR "ip6t_policy: neither incoming nor " - "outgoing policy selected\n"); - return 0; - } - if (hook_mask & (1 << NF_IP6_PRE_ROUTING | 1 << NF_IP6_LOCAL_IN) - && info->flags & IP6T_POLICY_MATCH_OUT) { - printk(KERN_ERR "ip6t_policy: output policy not valid in " - "PRE_ROUTING and INPUT\n"); - return 0; - } - if (hook_mask & (1 << NF_IP6_POST_ROUTING | 1 << NF_IP6_LOCAL_OUT) - && info->flags & IP6T_POLICY_MATCH_IN) { - printk(KERN_ERR "ip6t_policy: input policy not valid in " - "POST_ROUTING and OUTPUT\n"); - return 0; - } - if (info->len > IP6T_POLICY_MAX_ELEM) { - printk(KERN_ERR "ip6t_policy: too many policy elements\n"); - return 0; - } - - return 1; -} - -static struct ip6t_match policy_match = { - .name = "policy", - .match = match, - .matchsize = sizeof(struct ip6t_policy_info), - .checkentry = checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ip6t_register_match(&policy_match); -} - -static void __exit fini(void) -{ - ip6t_unregister_match(&policy_match); -} - -module_init(init); -module_exit(fini); diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index a8e5544da93e..174027809148 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -279,6 +279,16 @@ config NETFILTER_XT_MATCH_MARK To compile it as a module, choose M here. If unsure, say N. +config NETFILTER_XT_MATCH_POLICY + tristate 'IPsec "policy" match support' + depends on NETFILTER_XTABLES && XFRM + help + Policy matching allows you to match packets based on the + IPsec policy that was used during decapsulation/will + be used during encapsulation. + + To compile it as a module, choose M here. If unsure, say N. + config NETFILTER_XT_MATCH_PHYSDEV tristate '"physdev" match support' depends on NETFILTER_XTABLES && BRIDGE_NETFILTER diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 746172ebc91b..9558727f5e79 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o +obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c new file mode 100644 index 000000000000..1ec22082f04d --- /dev/null +++ b/net/netfilter/xt_policy.c @@ -0,0 +1,209 @@ +/* IP tables module for matching IPsec policy + * + * Copyright (c) 2004,2005 Patrick McHardy, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +MODULE_AUTHOR("Patrick McHardy "); +MODULE_DESCRIPTION("Xtables IPsec policy matching module"); +MODULE_LICENSE("GPL"); + +static inline int +xt_addr_cmp(const union xt_policy_addr *a1, const union xt_policy_addr *m, + const union xt_policy_addr *a2, unsigned short family) +{ + switch (family) { + case AF_INET: + return (a1->a4.s_addr ^ a2->a4.s_addr) & m->a4.s_addr; + case AF_INET6: + return ipv6_masked_addr_cmp(&a1->a6, &m->a6, &a2->a6); + } + return 0; +} + +static inline int +match_xfrm_state(struct xfrm_state *x, const struct xt_policy_elem *e, + unsigned short family) +{ +#define MATCH_ADDR(x,y,z) (!e->match.x || \ + (xt_addr_cmp(&e->x, &e->y, z, family) \ + ^ e->invert.x)) +#define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x)) + + return MATCH_ADDR(saddr, smask, (union xt_policy_addr *)&x->props.saddr) && + MATCH_ADDR(daddr, dmask, (union xt_policy_addr *)&x->id.daddr.a4) && + MATCH(proto, x->id.proto) && + MATCH(mode, x->props.mode) && + MATCH(spi, x->id.spi) && + MATCH(reqid, x->props.reqid); +} + +static int +match_policy_in(const struct sk_buff *skb, const struct xt_policy_info *info, + unsigned short family) +{ + const struct xt_policy_elem *e; + struct sec_path *sp = skb->sp; + int strict = info->flags & XT_POLICY_MATCH_STRICT; + int i, pos; + + if (sp == NULL) + return -1; + if (strict && info->len != sp->len) + return 0; + + for (i = sp->len - 1; i >= 0; i--) { + pos = strict ? i - sp->len + 1 : 0; + if (pos >= info->len) + return 0; + e = &info->pol[pos]; + + if (match_xfrm_state(sp->x[i].xvec, e, family)) { + if (!strict) + return 1; + } else if (strict) + return 0; + } + + return strict ? 1 : 0; +} + +static int +match_policy_out(const struct sk_buff *skb, const struct xt_policy_info *info, + unsigned short family) +{ + const struct xt_policy_elem *e; + struct dst_entry *dst = skb->dst; + int strict = info->flags & XT_POLICY_MATCH_STRICT; + int i, pos; + + if (dst->xfrm == NULL) + return -1; + + for (i = 0; dst && dst->xfrm; dst = dst->child, i++) { + pos = strict ? i : 0; + if (pos >= info->len) + return 0; + e = &info->pol[pos]; + + if (match_xfrm_state(dst->xfrm, e, family)) { + if (!strict) + return 1; + } else if (strict) + return 0; + } + + return strict ? i == info->len : 0; +} + +static int match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const struct xt_match *match, + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop) +{ + const struct xt_policy_info *info = matchinfo; + int ret; + + if (info->flags & XT_POLICY_MATCH_IN) + ret = match_policy_in(skb, info, match->family); + else + ret = match_policy_out(skb, info, match->family); + + if (ret < 0) + ret = info->flags & XT_POLICY_MATCH_NONE ? 1 : 0; + else if (info->flags & XT_POLICY_MATCH_NONE) + ret = 0; + + return ret; +} + +static int checkentry(const char *tablename, const void *ip_void, + const struct xt_match *match, + void *matchinfo, unsigned int matchsize, + unsigned int hook_mask) +{ + struct xt_policy_info *info = matchinfo; + + if (!(info->flags & (XT_POLICY_MATCH_IN|XT_POLICY_MATCH_OUT))) { + printk(KERN_ERR "xt_policy: neither incoming nor " + "outgoing policy selected\n"); + return 0; + } + /* hook values are equal for IPv4 and IPv6 */ + if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN) + && info->flags & XT_POLICY_MATCH_OUT) { + printk(KERN_ERR "xt_policy: output policy not valid in " + "PRE_ROUTING and INPUT\n"); + return 0; + } + if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT) + && info->flags & XT_POLICY_MATCH_IN) { + printk(KERN_ERR "xt_policy: input policy not valid in " + "POST_ROUTING and OUTPUT\n"); + return 0; + } + if (info->len > XT_POLICY_MAX_ELEM) { + printk(KERN_ERR "xt_policy: too many policy elements\n"); + return 0; + } + return 1; +} + +static struct xt_match policy_match = { + .name = "policy", + .family = AF_INET, + .match = match, + .matchsize = sizeof(struct xt_policy_info), + .checkentry = checkentry, + .me = THIS_MODULE, +}; + +static struct xt_match policy6_match = { + .name = "policy", + .family = AF_INET6, + .match = match, + .matchsize = sizeof(struct xt_policy_info), + .checkentry = checkentry, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + int ret; + + ret = xt_register_match(AF_INET, &policy_match); + if (ret) + return ret; + ret = xt_register_match(AF_INET6, &policy6_match); + if (ret) + xt_unregister_match(AF_INET, &policy_match); + return ret; +} + +static void __exit fini(void) +{ + xt_unregister_match(AF_INET6, &policy6_match); + xt_unregister_match(AF_INET, &policy_match); +} + +module_init(init); +module_exit(fini); +MODULE_ALIAS("ipt_policy"); +MODULE_ALIAS("ip6t_policy"); -- cgit v1.2.3 From a24276924875802853b5bdc12c56d29f1c1bbc79 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 20 Mar 2006 18:03:59 -0800 Subject: [NETFILTER]: ctnetlink: avoid unneccessary event message generation Avoid unneccessary event message generation by checking for netlink listeners before building a message. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter/nfnetlink.h | 1 + net/ipv4/netfilter/ip_conntrack_netlink.c | 7 ++++--- net/netfilter/nf_conntrack_netlink.c | 7 ++++--- net/netfilter/nfnetlink.c | 6 ++++++ 4 files changed, 15 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index 934a2479f160..9f5b12cf489b 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h @@ -164,6 +164,7 @@ extern void nfattr_parse(struct nfattr *tb[], int maxattr, __res; \ }) +extern int nfnetlink_has_listeners(unsigned int group); extern int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo); extern int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags); diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index e0b5926c76f9..5ce2e3fc2c7f 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -327,9 +327,10 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, group = NFNLGRP_CONNTRACK_UPDATE; } else return NOTIFY_DONE; - - /* FIXME: Check if there are any listeners before, don't hurt performance */ - + + if (!nfnetlink_has_listeners(group)) + return NOTIFY_DONE; + skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); if (!skb) return NOTIFY_DONE; diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index aef3cb41131f..5eadf009bb15 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -338,9 +338,10 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, group = NFNLGRP_CONNTRACK_UPDATE; } else return NOTIFY_DONE; - - /* FIXME: Check if there are any listeners before, don't hurt performance */ - + + if (!nfnetlink_has_listeners(group)) + return NOTIFY_DONE; + skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); if (!skb) return NOTIFY_DONE; diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index f6063e8f0050..b88e82a1a987 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -191,6 +191,12 @@ nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys, return 0; } +int nfnetlink_has_listeners(unsigned int group) +{ + return netlink_has_listeners(nfnl, group); +} +EXPORT_SYMBOL_GPL(nfnetlink_has_listeners); + int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo) { gfp_t allocation = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; -- cgit v1.2.3 From 4277a083ecd2c8771058641132bcecea04ca6608 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 20 Mar 2006 18:52:01 -0800 Subject: [NETLINK]: Add netlink_has_listeners for avoiding unneccessary event message generation Keep a bitmask of multicast groups with subscribed listeners to let netlink users check for listeners before generating multicast messages. Queries don't perform any locking, which may result in false positives, it is guaranteed however that any new subscriptions are visible before bind() or setsockopt() return. Signed-off-by: Patrick McHardy ACKed-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/linux/netlink.h | 1 + net/netlink/af_netlink.c | 52 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/netlink.h b/include/linux/netlink.h index c256ebe2a7b4..f8f3d1c927f8 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -151,6 +151,7 @@ struct netlink_skb_parms extern struct sock *netlink_kernel_create(int unit, unsigned int groups, void (*input)(struct sock *sk, int len), struct module *module); extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err); +extern int netlink_has_listeners(struct sock *sk, unsigned int group); extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock); extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid, __u32 group, gfp_t allocation); diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 59dc7d140600..d00a9034cb5f 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -106,6 +106,7 @@ struct nl_pid_hash { struct netlink_table { struct nl_pid_hash hash; struct hlist_head mc_list; + unsigned long *listeners; unsigned int nl_nonroot; unsigned int groups; struct module *module; @@ -296,6 +297,24 @@ static inline int nl_pid_hash_dilute(struct nl_pid_hash *hash, int len) static const struct proto_ops netlink_ops; +static void +netlink_update_listeners(struct sock *sk) +{ + struct netlink_table *tbl = &nl_table[sk->sk_protocol]; + struct hlist_node *node; + unsigned long mask; + unsigned int i; + + for (i = 0; i < NLGRPSZ(tbl->groups)/sizeof(unsigned long); i++) { + mask = 0; + sk_for_each_bound(sk, node, &tbl->mc_list) + mask |= nlk_sk(sk)->groups[i]; + tbl->listeners[i] = mask; + } + /* this function is only called with the netlink table "grabbed", which + * makes sure updates are visible before bind or setsockopt return. */ +} + static int netlink_insert(struct sock *sk, u32 pid) { struct nl_pid_hash *hash = &nl_table[sk->sk_protocol].hash; @@ -456,12 +475,14 @@ static int netlink_release(struct socket *sock) if (nlk->module) module_put(nlk->module); + netlink_table_grab(); if (nlk->flags & NETLINK_KERNEL_SOCKET) { - netlink_table_grab(); + kfree(nl_table[sk->sk_protocol].listeners); nl_table[sk->sk_protocol].module = NULL; nl_table[sk->sk_protocol].registered = 0; - netlink_table_ungrab(); - } + } else if (nlk->subscriptions) + netlink_update_listeners(sk); + netlink_table_ungrab(); kfree(nlk->groups); nlk->groups = NULL; @@ -589,6 +610,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len hweight32(nladdr->nl_groups) - hweight32(nlk->groups[0])); nlk->groups[0] = (nlk->groups[0] & ~0xffffffffUL) | nladdr->nl_groups; + netlink_update_listeners(sk); netlink_table_ungrab(); return 0; @@ -807,6 +829,17 @@ retry: return netlink_sendskb(sk, skb, ssk->sk_protocol); } +int netlink_has_listeners(struct sock *sk, unsigned int group) +{ + int res = 0; + + BUG_ON(!(nlk_sk(sk)->flags & NETLINK_KERNEL_SOCKET)); + if (group - 1 < nl_table[sk->sk_protocol].groups) + res = test_bit(group - 1, nl_table[sk->sk_protocol].listeners); + return res; +} +EXPORT_SYMBOL_GPL(netlink_has_listeners); + static __inline__ int netlink_broadcast_deliver(struct sock *sk, struct sk_buff *skb) { struct netlink_sock *nlk = nlk_sk(sk); @@ -1011,6 +1044,7 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname, else __clear_bit(val - 1, nlk->groups); netlink_update_subscriptions(sk, subscriptions); + netlink_update_listeners(sk); netlink_table_ungrab(); err = 0; break; @@ -1237,6 +1271,7 @@ netlink_kernel_create(int unit, unsigned int groups, struct socket *sock; struct sock *sk; struct netlink_sock *nlk; + unsigned long *listeners = NULL; if (!nl_table) return NULL; @@ -1250,6 +1285,13 @@ netlink_kernel_create(int unit, unsigned int groups, if (__netlink_create(sock, unit) < 0) goto out_sock_release; + if (groups < 32) + groups = 32; + + listeners = kzalloc(NLGRPSZ(groups), GFP_KERNEL); + if (!listeners) + goto out_sock_release; + sk = sock->sk; sk->sk_data_ready = netlink_data_ready; if (input) @@ -1262,7 +1304,8 @@ netlink_kernel_create(int unit, unsigned int groups, nlk->flags |= NETLINK_KERNEL_SOCKET; netlink_table_grab(); - nl_table[unit].groups = groups < 32 ? 32 : groups; + nl_table[unit].groups = groups; + nl_table[unit].listeners = listeners; nl_table[unit].module = module; nl_table[unit].registered = 1; netlink_table_ungrab(); @@ -1270,6 +1313,7 @@ netlink_kernel_create(int unit, unsigned int groups, return sk; out_sock_release: + kfree(listeners); sock_release(sock); return NULL; } -- cgit v1.2.3 From f8cd54884e675dfaf0c86cc7c088adb6ca9d7638 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 20 Mar 2006 19:15:11 -0800 Subject: [IPSEC]: Sync series - core changes This patch provides the core functionality needed for sync events for ipsec. Derived work of Krisztian KOVACS Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/linux/sysctl.h | 2 ++ include/linux/xfrm.h | 30 ++++++++++++++++++ include/net/xfrm.h | 44 ++++++++++++++++++++++++++- net/core/sysctl_net_core.c | 23 ++++++++++++++ net/xfrm/xfrm_state.c | 76 +++++++++++++++++++++++++++++++++++++++++++++- net/xfrm/xfrm_user.c | 4 ++- 6 files changed, 176 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 6e8880ea49e7..b686548f32e0 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -261,6 +261,8 @@ enum NET_CORE_DEV_WEIGHT=17, NET_CORE_SOMAXCONN=18, NET_CORE_BUDGET=19, + NET_CORE_AEVENT_ETIME=20, + NET_CORE_AEVENT_RSEQTH=21, }; /* /proc/sys/net/ethernet */ diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index 82fbb758e28f..b54a12940ef6 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h @@ -156,6 +156,10 @@ enum { XFRM_MSG_FLUSHPOLICY, #define XFRM_MSG_FLUSHPOLICY XFRM_MSG_FLUSHPOLICY + XFRM_MSG_NEWAE, +#define XFRM_MSG_NEWAE XFRM_MSG_NEWAE + XFRM_MSG_GETAE, +#define XFRM_MSG_GETAE XFRM_MSG_GETAE __XFRM_MSG_MAX }; #define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1) @@ -194,6 +198,21 @@ struct xfrm_encap_tmpl { xfrm_address_t encap_oa; }; +/* AEVENT flags */ +enum xfrm_ae_ftype_t { + XFRM_AE_UNSPEC, + XFRM_AE_RTHR=1, /* replay threshold*/ + XFRM_AE_RVAL=2, /* replay value */ + XFRM_AE_LVAL=4, /* lifetime value */ + XFRM_AE_ETHR=8, /* expiry timer threshold */ + XFRM_AE_CR=16, /* Event cause is replay update */ + XFRM_AE_CE=32, /* Event cause is timer expiry */ + XFRM_AE_CU=64, /* Event cause is policy update */ + __XFRM_AE_MAX + +#define XFRM_AE_MAX (__XFRM_AE_MAX - 1) +}; + /* Netlink message attributes. */ enum xfrm_attr_type_t { XFRMA_UNSPEC, @@ -205,6 +224,10 @@ enum xfrm_attr_type_t { XFRMA_SA, XFRMA_POLICY, XFRMA_SEC_CTX, /* struct xfrm_sec_ctx */ + XFRMA_LTIME_VAL, + XFRMA_REPLAY_VAL, + XFRMA_REPLAY_THRESH, + XFRMA_ETIMER_THRESH, __XFRMA_MAX #define XFRMA_MAX (__XFRMA_MAX - 1) @@ -235,6 +258,11 @@ struct xfrm_usersa_id { __u8 proto; }; +struct xfrm_aevent_id { + __u32 flags; + struct xfrm_usersa_id sa_id; +}; + struct xfrm_userspi_info { struct xfrm_usersa_info info; __u32 min; @@ -306,6 +334,8 @@ enum xfrm_nlgroups { #define XFRMNLGRP_SA XFRMNLGRP_SA XFRMNLGRP_POLICY, #define XFRMNLGRP_POLICY XFRMNLGRP_POLICY + XFRMNLGRP_AEVENTS, +#define XFRMNLGRP_AEVENTS XFRMNLGRP_AEVENTS __XFRMNLGRP_MAX }; #define XFRMNLGRP_MAX (__XFRMNLGRP_MAX - 1) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 8d362c49b8a9..bc005e62e434 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -20,6 +20,10 @@ #define XFRM_ALIGN8(len) (((len) + 7) & ~7) +extern struct sock *xfrm_nl; +extern u32 sysctl_xfrm_aevent_etime; +extern u32 sysctl_xfrm_aevent_rseqth; + extern struct semaphore xfrm_cfg_sem; /* Organization of SPD aka "XFRM rules" @@ -135,6 +139,16 @@ struct xfrm_state /* State for replay detection */ struct xfrm_replay_state replay; + /* Replay detection state at the time we sent the last notification */ + struct xfrm_replay_state preplay; + + /* Replay detection notification settings */ + u32 replay_maxage; + u32 replay_maxdiff; + + /* Replay detection notification timer */ + struct timer_list rtimer; + /* Statistics */ struct xfrm_stats stats; @@ -169,6 +183,7 @@ struct km_event u32 hard; u32 proto; u32 byid; + u32 aevent; } data; u32 seq; @@ -305,7 +320,21 @@ struct xfrm_policy struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH]; }; -#define XFRM_KM_TIMEOUT 30 +#define XFRM_KM_TIMEOUT 30 +/* which seqno */ +#define XFRM_REPLAY_SEQ 1 +#define XFRM_REPLAY_OSEQ 2 +#define XFRM_REPLAY_SEQ_MASK 3 +/* what happened */ +#define XFRM_REPLAY_UPDATE XFRM_AE_CR +#define XFRM_REPLAY_TIMEOUT XFRM_AE_CE + +/* default aevent timeout in units of 100ms */ +#define XFRM_AE_ETIME 10 +/* Async Event timer multiplier */ +#define XFRM_AE_ETH_M 10 +/* default seq threshold size */ +#define XFRM_AE_SEQT_SIZE 2 struct xfrm_mgr { @@ -865,6 +894,7 @@ extern int xfrm_state_delete(struct xfrm_state *x); extern void xfrm_state_flush(u8 proto); extern int xfrm_replay_check(struct xfrm_state *x, u32 seq); extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq); +extern void xfrm_replay_notify(struct xfrm_state *x, int event); extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb); extern int xfrm_state_mtu(struct xfrm_state *x, int mtu); extern int xfrm_init_state(struct xfrm_state *x); @@ -965,4 +995,16 @@ static inline int xfrm_policy_id2dir(u32 index) return index & 7; } +static inline int xfrm_aevent_is_on(void) +{ + return netlink_has_listeners(xfrm_nl,XFRMNLGRP_AEVENTS); +} + +static inline void xfrm_aevent_doreplay(struct xfrm_state *x) +{ + if (xfrm_aevent_is_on()) + xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); +} + + #endif /* _NET_XFRM_H */ diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 2f278c8e4743..710453656721 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -26,6 +26,11 @@ extern int sysctl_core_destroy_delay; extern char sysctl_divert_version[]; #endif /* CONFIG_NET_DIVERT */ +#ifdef CONFIG_XFRM +extern u32 sysctl_xfrm_aevent_etime; +extern u32 sysctl_xfrm_aevent_rseqth; +#endif + ctl_table core_table[] = { #ifdef CONFIG_NET { @@ -111,6 +116,24 @@ ctl_table core_table[] = { .proc_handler = &proc_dostring }, #endif /* CONFIG_NET_DIVERT */ +#ifdef CONFIG_XFRM + { + .ctl_name = NET_CORE_AEVENT_ETIME, + .procname = "xfrm_aevent_etime", + .data = &sysctl_xfrm_aevent_etime, + .maxlen = sizeof(u32), + .mode = 0644, + .proc_handler = &proc_dointvec + }, + { + .ctl_name = NET_CORE_AEVENT_RSEQTH, + .procname = "xfrm_aevent_rseqth", + .data = &sysctl_xfrm_aevent_rseqth, + .maxlen = sizeof(u32), + .mode = 0644, + .proc_handler = &proc_dointvec + }, +#endif /* CONFIG_XFRM */ #endif /* CONFIG_NET */ { .ctl_name = NET_CORE_SOMAXCONN, diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index c656cbaf35e8..8eaee499cad5 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -20,6 +20,8 @@ #include #include +u32 sysctl_xfrm_aevent_etime = XFRM_AE_ETIME; +u32 sysctl_xfrm_aevent_rseqth = XFRM_AE_SEQT_SIZE; /* Each xfrm_state may be linked to two tables: 1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl) @@ -62,6 +64,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) { if (del_timer(&x->timer)) BUG(); + if (del_timer(&x->rtimer)) + BUG(); kfree(x->aalg); kfree(x->ealg); kfree(x->calg); @@ -190,11 +194,16 @@ struct xfrm_state *xfrm_state_alloc(void) init_timer(&x->timer); x->timer.function = xfrm_timer_handler; x->timer.data = (unsigned long)x; + init_timer(&x->rtimer); + x->rtimer.function = xfrm_replay_timer_handler; + x->rtimer.data = (unsigned long)x; x->curlft.add_time = (unsigned long)xtime.tv_sec; x->lft.soft_byte_limit = XFRM_INF; x->lft.soft_packet_limit = XFRM_INF; x->lft.hard_byte_limit = XFRM_INF; x->lft.hard_packet_limit = XFRM_INF; + x->replay_maxage = 0; + x->replay_maxdiff = 0; spin_lock_init(&x->lock); } return x; @@ -228,6 +237,8 @@ static int __xfrm_state_delete(struct xfrm_state *x) spin_unlock(&xfrm_state_lock); if (del_timer(&x->timer)) __xfrm_state_put(x); + if (del_timer(&x->rtimer)) + __xfrm_state_put(x); /* The number two in this test is the reference * mentioned in the comment below plus the reference @@ -426,6 +437,10 @@ static void __xfrm_state_insert(struct xfrm_state *x) if (!mod_timer(&x->timer, jiffies + HZ)) xfrm_state_hold(x); + if (x->replay_maxage && + !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) + xfrm_state_hold(x); + wake_up(&km_waitq); } @@ -762,6 +777,62 @@ out: } EXPORT_SYMBOL(xfrm_state_walk); + +void xfrm_replay_notify(struct xfrm_state *x, int event) +{ + struct km_event c; + /* we send notify messages in case + * 1. we updated on of the sequence numbers, and the seqno difference + * is at least x->replay_maxdiff, in this case we also update the + * timeout of our timer function + * 2. if x->replay_maxage has elapsed since last update, + * and there were changes + * + * The state structure must be locked! + */ + + switch (event) { + case XFRM_REPLAY_UPDATE: + if (x->replay_maxdiff && + (x->replay.seq - x->preplay.seq < x->replay_maxdiff) && + (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) + return; + + break; + + case XFRM_REPLAY_TIMEOUT: + if ((x->replay.seq == x->preplay.seq) && + (x->replay.bitmap == x->preplay.bitmap) && + (x->replay.oseq == x->preplay.oseq)) + return; + + break; + } + + memcpy(&x->preplay, &x->replay, sizeof(struct xfrm_replay_state)); + c.event = XFRM_MSG_NEWAE; + c.data.aevent = event; + km_state_notify(x, &c); + +resched: + if (x->replay_maxage && + !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) + xfrm_state_hold(x); + +} + +static void xfrm_replay_timer_handler(unsigned long data) +{ + struct xfrm_state *x = (struct xfrm_state*)data; + + spin_lock(&x->lock); + + if (xfrm_aevent_is_on() && x->km.state == XFRM_STATE_VALID) + xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT); + + spin_unlock(&x->lock); +} + int xfrm_replay_check(struct xfrm_state *x, u32 seq) { u32 diff; @@ -805,6 +876,9 @@ void xfrm_replay_advance(struct xfrm_state *x, u32 seq) diff = x->replay.seq - seq; x->replay.bitmap |= (1U << diff); } + + if (xfrm_aevent_is_on()) + xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); } EXPORT_SYMBOL(xfrm_replay_advance); @@ -835,7 +909,7 @@ void km_state_notify(struct xfrm_state *x, struct km_event *c) EXPORT_SYMBOL(km_policy_notify); EXPORT_SYMBOL(km_state_notify); -static void km_state_expired(struct xfrm_state *x, int hard) +void km_state_expired(struct xfrm_state *x, int hard) { struct km_event c; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 7de17559249a..6f643e58e044 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -28,7 +28,7 @@ #include #include -static struct sock *xfrm_nl; +struct sock *xfrm_nl; static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type) { @@ -1618,3 +1618,5 @@ module_init(xfrm_user_init); module_exit(xfrm_user_exit); MODULE_LICENSE("GPL"); MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM); +EXPORT_SYMBOL(xfrm_nl); + -- cgit v1.2.3 From 980ebd25794f0f87ac32844e2c73e9e81f0a72ba Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 20 Mar 2006 19:16:40 -0800 Subject: [IPSEC]: Sync series - acquire insert This introduces a feature similar to the one described in RFC 2367: " ... the application needing an SA sends a PF_KEY SADB_ACQUIRE message down to the Key Engine, which then either returns an error or sends a similar SADB_ACQUIRE message up to one or more key management applications capable of creating such SAs. ... ... The third is where an application-layer consumer of security associations (e.g. an OSPFv2 or RIPv2 daemon) needs a security association. Send an SADB_ACQUIRE message from a user process to the kernel. The kernel returns an SADB_ACQUIRE message to registered sockets. The user-level consumer waits for an SADB_UPDATE or SADB_ADD message for its particular type, and then can use that association by using SADB_GET messages. " An app such as OSPF could then use ipsec KM to get keys Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/net/xfrm.h | 2 +- net/xfrm/xfrm_state.c | 5 +++-- net/xfrm/xfrm_user.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index bc005e62e434..30a940b147b0 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -214,10 +214,10 @@ extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo); extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo); extern void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c); extern void km_state_notify(struct xfrm_state *x, struct km_event *c); - #define XFRM_ACQ_EXPIRES 30 struct xfrm_tmpl; +extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); struct xfrm_state_afinfo { unsigned short family; rwlock_t lock; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 8eaee499cad5..a613b5c7d409 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -57,7 +57,7 @@ static int __xfrm_state_delete(struct xfrm_state *x); static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family); static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); -static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); +int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); static void km_state_expired(struct xfrm_state *x, int hard); static void xfrm_state_gc_destroy(struct xfrm_state *x) @@ -925,7 +925,7 @@ void km_state_expired(struct xfrm_state *x, int hard) * We send to all registered managers regardless of failure * We are happy with one success */ -static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol) +int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol) { int err = -EINVAL, acqret; struct xfrm_mgr *km; @@ -939,6 +939,7 @@ static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_polic read_unlock(&xfrm_km_lock); return err; } +EXPORT_SYMBOL(km_query); int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport) { diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index e230ba5328d3..d6e6527fd8d7 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1232,6 +1232,58 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **x return 0; } +static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) +{ + struct xfrm_policy *xp; + struct xfrm_user_tmpl *ut; + int i; + struct rtattr *rt = xfrma[XFRMA_TMPL-1]; + + struct xfrm_user_acquire *ua = NLMSG_DATA(nlh); + struct xfrm_state *x = xfrm_state_alloc(); + int err = -ENOMEM; + + if (!x) + return err; + + err = verify_newpolicy_info(&ua->policy); + if (err) { + printk("BAD policy passed\n"); + kfree(x); + return err; + } + + /* build an XP */ + xp = xfrm_policy_construct(&ua->policy, (struct rtattr **) xfrma, &err); if (!xp) { + kfree(x); + return err; + } + + memcpy(&x->id, &ua->id, sizeof(ua->id)); + memcpy(&x->props.saddr, &ua->saddr, sizeof(ua->saddr)); + memcpy(&x->sel, &ua->sel, sizeof(ua->sel)); + + ut = RTA_DATA(rt); + /* extract the templates and for each call km_key */ + for (i = 0; i < xp->xfrm_nr; i++, ut++) { + struct xfrm_tmpl *t = &xp->xfrm_vec[i]; + memcpy(&x->id, &t->id, sizeof(x->id)); + x->props.mode = t->mode; + x->props.reqid = t->reqid; + x->props.family = ut->family; + t->aalgos = ua->aalgos; + t->ealgos = ua->ealgos; + t->calgos = ua->calgos; + err = km_query(x, t, xp); + + } + + kfree(x); + kfree(xp); + + return 0; +} + #define XMSGSIZE(type) NLMSG_LENGTH(sizeof(struct type)) @@ -1243,6 +1295,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userspi_info), + [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_acquire), [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info), [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info), [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush), @@ -1266,6 +1319,7 @@ static struct xfrm_link { [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy, .dump = xfrm_dump_policy }, [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi }, + [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_acquire }, [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = { .doit = xfrm_flush_sa }, -- cgit v1.2.3 From 53bc6b4d29c07664f3abe029b7e6878a1067899a Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 20 Mar 2006 19:17:03 -0800 Subject: [IPSEC]: Sync series - SA expires This patch allows a user to insert SA expires. This is useful to do on an HA backup for the case of byte counts but may not be very useful for the case of time based expiry. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/net/xfrm.h | 3 +++ net/xfrm/xfrm_state.c | 17 ++++++++++------- net/xfrm/xfrm_user.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 30a940b147b0..d409c9d5e293 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -218,6 +218,9 @@ extern void km_state_notify(struct xfrm_state *x, struct km_event *c); struct xfrm_tmpl; extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); +extern void km_state_expired(struct xfrm_state *x, int hard, u32 pid); +extern int __xfrm_state_delete(struct xfrm_state *x); + struct xfrm_state_afinfo { unsigned short family; rwlock_t lock; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index a613b5c7d409..7784adbb3362 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -52,13 +52,13 @@ static DEFINE_SPINLOCK(xfrm_state_gc_lock); static int xfrm_state_gc_flush_bundles; -static int __xfrm_state_delete(struct xfrm_state *x); +int __xfrm_state_delete(struct xfrm_state *x); static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family); static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); -static void km_state_expired(struct xfrm_state *x, int hard); +void km_state_expired(struct xfrm_state *x, int hard, u32 pid); static void xfrm_state_gc_destroy(struct xfrm_state *x) { @@ -157,7 +157,7 @@ static void xfrm_timer_handler(unsigned long data) x->km.dying = warn; if (warn) - km_state_expired(x, 0); + km_state_expired(x, 0, 0); resched: if (next != LONG_MAX && !mod_timer(&x->timer, jiffies + make_jiffies(next))) @@ -172,7 +172,7 @@ expired: goto resched; } if (!__xfrm_state_delete(x) && x->id.spi) - km_state_expired(x, 1); + km_state_expired(x, 1, 0); out: spin_unlock(&x->lock); @@ -221,7 +221,7 @@ void __xfrm_state_destroy(struct xfrm_state *x) } EXPORT_SYMBOL(__xfrm_state_destroy); -static int __xfrm_state_delete(struct xfrm_state *x) +int __xfrm_state_delete(struct xfrm_state *x) { int err = -ESRCH; @@ -260,6 +260,7 @@ static int __xfrm_state_delete(struct xfrm_state *x) return err; } +EXPORT_SYMBOL(__xfrm_state_delete); int xfrm_state_delete(struct xfrm_state *x) { @@ -595,7 +596,7 @@ int xfrm_state_check_expire(struct xfrm_state *x) (x->curlft.bytes >= x->lft.soft_byte_limit || x->curlft.packets >= x->lft.soft_packet_limit)) { x->km.dying = 1; - km_state_expired(x, 0); + km_state_expired(x, 0, 0); } return 0; } @@ -909,11 +910,12 @@ void km_state_notify(struct xfrm_state *x, struct km_event *c) EXPORT_SYMBOL(km_policy_notify); EXPORT_SYMBOL(km_state_notify); -void km_state_expired(struct xfrm_state *x, int hard) +void km_state_expired(struct xfrm_state *x, int hard, u32 pid) { struct km_event c; c.data.hard = hard; + c.pid = pid; c.event = XFRM_MSG_EXPIRE; km_state_notify(x, &c); @@ -921,6 +923,7 @@ void km_state_expired(struct xfrm_state *x, int hard) wake_up(&km_waitq); } +EXPORT_SYMBOL(km_state_expired); /* * We send to all registered managers regardless of failure * We are happy with one success diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index d6e6527fd8d7..2dc1e69b2cb7 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1232,6 +1232,34 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **x return 0; } +static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) +{ + struct xfrm_state *x; + int err; + struct xfrm_user_expire *ue = NLMSG_DATA(nlh); + struct xfrm_usersa_info *p = &ue->state; + + x = xfrm_state_lookup(&p->id.daddr, p->id.spi, p->id.proto, p->family); + err = -ENOENT; + + if (x == NULL) + return err; + + err = -EINVAL; + + spin_lock_bh(&x->lock); + if (x->km.state != XFRM_STATE_VALID) + goto out; + km_state_expired(x, ue->hard, current->pid); + + if (ue->hard) + __xfrm_state_delete(x); +out: + spin_unlock_bh(&x->lock); + xfrm_state_put(x); + return err; +} + static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) { struct xfrm_policy *xp; @@ -1296,6 +1324,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userspi_info), [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_acquire), + [XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_expire), [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info), [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info), [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush), @@ -1320,6 +1349,7 @@ static struct xfrm_link { .dump = xfrm_dump_policy }, [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi }, [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_acquire }, + [XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_sa_expire }, [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = { .doit = xfrm_flush_sa }, -- cgit v1.2.3 From 6c5c8ca7ff20523e427b955aa84cef407934710f Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 20 Mar 2006 19:17:25 -0800 Subject: [IPSEC]: Sync series - policy expires This is similar to the SA expire insertion patch - only it inserts expires for SP. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/net/xfrm.h | 2 +- net/xfrm/xfrm_policy.c | 4 ++-- net/xfrm/xfrm_state.c | 3 ++- net/xfrm/xfrm_user.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 60 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index d409c9d5e293..156f52ef8a91 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -957,7 +957,7 @@ extern void xfrm_init_pmtu(struct dst_entry *dst); extern wait_queue_head_t km_waitq; extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport); -extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard); +extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid); extern void xfrm_input_init(void); extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index ae62054a9fc4..453551ec87a1 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -203,7 +203,7 @@ static void xfrm_policy_timer(unsigned long data) } if (warn) - km_policy_expired(xp, dir, 0); + km_policy_expired(xp, dir, 0, 0); if (next != LONG_MAX && !mod_timer(&xp->timer, jiffies + make_jiffies(next))) xfrm_pol_hold(xp); @@ -216,7 +216,7 @@ out: expired: read_unlock(&xp->lock); if (!xfrm_policy_delete(xp, dir)) - km_policy_expired(xp, dir, 1); + km_policy_expired(xp, dir, 1, 0); xfrm_pol_put(xp); } diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 7784adbb3362..8df547d7d61c 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -961,11 +961,12 @@ int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport) } EXPORT_SYMBOL(km_new_mapping); -void km_policy_expired(struct xfrm_policy *pol, int dir, int hard) +void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid) { struct km_event c; c.data.hard = hard; + c.pid = pid; c.event = XFRM_MSG_POLEXPIRE; km_policy_notify(pol, dir, &c); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 2dc1e69b2cb7..b46ee7d4dae7 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1222,7 +1222,7 @@ out: static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) { - struct km_event c; +struct km_event c; xfrm_policy_flush(); c.event = nlh->nlmsg_type; @@ -1232,6 +1232,58 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **x return 0; } +static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) +{ + struct xfrm_policy *xp; + struct xfrm_user_polexpire *up = NLMSG_DATA(nlh); + struct xfrm_userpolicy_info *p = &up->pol; + int err = -ENOENT; + + if (p->index) + xp = xfrm_policy_byid(p->dir, p->index, 0); + else { + struct rtattr **rtattrs = (struct rtattr **)xfrma; + struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1]; + struct xfrm_policy tmp; + + err = verify_sec_ctx_len(rtattrs); + if (err) + return err; + + memset(&tmp, 0, sizeof(struct xfrm_policy)); + if (rt) { + struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt); + + if ((err = security_xfrm_policy_alloc(&tmp, uctx))) + return err; + } + xp = xfrm_policy_bysel_ctx(p->dir, &p->sel, tmp.security, 0); + security_xfrm_policy_free(&tmp); + } + + if (xp == NULL) + return err; + read_lock(&xp->lock); + if (xp->dead) { + read_unlock(&xp->lock); + goto out; + } + + read_unlock(&xp->lock); + err = 0; + if (up->hard) { + xfrm_policy_delete(xp, p->dir); + } else { + // reset the timers here? + printk("Dont know what to do with soft policy expire\n"); + } + km_policy_expired(xp, p->dir, up->hard, current->pid); + +out: + xfrm_pol_put(xp); + return err; +} + static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) { struct xfrm_state *x; @@ -1327,6 +1379,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { [XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_expire), [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info), [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info), + [XFRM_MSG_POLEXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_polexpire), [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush), [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = NLMSG_LENGTH(0), [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), @@ -1352,6 +1405,7 @@ static struct xfrm_link { [XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_sa_expire }, [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, + [XFRM_MSG_POLEXPIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_pol_expire}, [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = { .doit = xfrm_flush_sa }, [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy }, [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = { .doit = xfrm_new_ae }, -- cgit v1.2.3 From 91f0ebf7b6d5cb2b6e818d48587566144821babe Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 20 Mar 2006 19:21:44 -0800 Subject: [DCCP] CCID: Improve CCID infrastructure 1. No need for ->ccid_init nor ->ccid_exit, this is what module_{init,exit} does and anynways neither ccid2 nor ccid3 were using it. 2. Rename struct ccid to struct ccid_operations and introduce struct ccid with a pointer to ccid_operations and rigth after it the rx or tx private state. 3. Remove the pointer to the state of the half connections from struct dccp_sock, now its derived thru ccid_priv() from the ccid pointer. Now we also can implement the setsockopt for changing the CCID easily as no ccid init routines can affect struct dccp_sock in any way that prevents other CCIDs from working if a CCID switch operation is asked by apps. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/linux/dccp.h | 2 - net/dccp/ccid.c | 188 ++++++++++++++++++++++++++++++++++++++++--------- net/dccp/ccid.h | 115 +++++++++++++----------------- net/dccp/ccids/ccid2.c | 55 +++------------ net/dccp/ccids/ccid2.h | 16 +++++ net/dccp/ccids/ccid3.c | 34 ++------- net/dccp/ccids/ccid3.h | 5 +- net/dccp/input.c | 8 --- net/dccp/ipv4.c | 24 +++---- net/dccp/minisocks.c | 25 +++---- 10 files changed, 260 insertions(+), 212 deletions(-) (limited to 'include') diff --git a/include/linux/dccp.h b/include/linux/dccp.h index a70d1a27e7fc..bdd756cc60b1 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -478,8 +478,6 @@ struct dccp_sock { __u32 dccps_mss_cache; struct dccp_options dccps_options; struct dccp_ackvec *dccps_hc_rx_ackvec; - void *dccps_hc_rx_ccid_private; - void *dccps_hc_tx_ccid_private; struct ccid *dccps_hc_rx_ccid; struct ccid *dccps_hc_tx_ccid; struct dccp_options_received dccps_options_received; diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c index 06b191a5740b..ff05e59043cd 100644 --- a/net/dccp/ccid.c +++ b/net/dccp/ccid.c @@ -13,7 +13,7 @@ #include "ccid.h" -static struct ccid *ccids[CCID_MAX]; +static struct ccid_operations *ccids[CCID_MAX]; #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) static atomic_t ccids_lockct = ATOMIC_INIT(0); static DEFINE_SPINLOCK(ccids_lock); @@ -55,82 +55,202 @@ static inline void ccids_read_unlock(void) #define ccids_read_unlock() do { } while(0) #endif -int ccid_register(struct ccid *ccid) +static kmem_cache_t *ccid_kmem_cache_create(int obj_size, const char *fmt,...) { - int err; + kmem_cache_t *slab; + char slab_name_fmt[32], *slab_name; + va_list args; + + va_start(args, fmt); + vsnprintf(slab_name_fmt, sizeof(slab_name_fmt), fmt, args); + va_end(args); + + slab_name = kstrdup(slab_name_fmt, GFP_KERNEL); + if (slab_name == NULL) + return NULL; + slab = kmem_cache_create(slab_name, sizeof(struct ccid) + obj_size, 0, + SLAB_HWCACHE_ALIGN, NULL, NULL); + if (slab == NULL) + kfree(slab_name); + return slab; +} + +static void ccid_kmem_cache_destroy(kmem_cache_t *slab) +{ + if (slab != NULL) { + const char *name = kmem_cache_name(slab); + + kmem_cache_destroy(slab); + kfree(name); + } +} + +int ccid_register(struct ccid_operations *ccid_ops) +{ + int err = -ENOBUFS; + + ccid_ops->ccid_hc_rx_slab = + ccid_kmem_cache_create(ccid_ops->ccid_hc_rx_obj_size, + "%s_hc_rx_sock", + ccid_ops->ccid_name); + if (ccid_ops->ccid_hc_rx_slab == NULL) + goto out; + + ccid_ops->ccid_hc_tx_slab = + ccid_kmem_cache_create(ccid_ops->ccid_hc_tx_obj_size, + "%s_hc_tx_sock", + ccid_ops->ccid_name); + if (ccid_ops->ccid_hc_tx_slab == NULL) + goto out_free_rx_slab; ccids_write_lock(); err = -EEXIST; - if (ccids[ccid->ccid_id] == NULL) { - ccids[ccid->ccid_id] = ccid; + if (ccids[ccid_ops->ccid_id] == NULL) { + ccids[ccid_ops->ccid_id] = ccid_ops; err = 0; } ccids_write_unlock(); - if (err == 0) - pr_info("CCID: Registered CCID %d (%s)\n", - ccid->ccid_id, ccid->ccid_name); + if (err != 0) + goto out_free_tx_slab; + + pr_info("CCID: Registered CCID %d (%s)\n", + ccid_ops->ccid_id, ccid_ops->ccid_name); +out: return err; +out_free_tx_slab: + ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab); + ccid_ops->ccid_hc_tx_slab = NULL; + goto out; +out_free_rx_slab: + ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab); + ccid_ops->ccid_hc_rx_slab = NULL; + goto out; } EXPORT_SYMBOL_GPL(ccid_register); -int ccid_unregister(struct ccid *ccid) +int ccid_unregister(struct ccid_operations *ccid_ops) { ccids_write_lock(); - ccids[ccid->ccid_id] = NULL; + ccids[ccid_ops->ccid_id] = NULL; ccids_write_unlock(); + + ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab); + ccid_ops->ccid_hc_tx_slab = NULL; + ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab); + ccid_ops->ccid_hc_rx_slab = NULL; + pr_info("CCID: Unregistered CCID %d (%s)\n", - ccid->ccid_id, ccid->ccid_name); + ccid_ops->ccid_id, ccid_ops->ccid_name); return 0; } EXPORT_SYMBOL_GPL(ccid_unregister); -struct ccid *ccid_init(unsigned char id, struct sock *sk) +struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, gfp_t gfp) { - struct ccid *ccid; + struct ccid_operations *ccid_ops; + struct ccid *ccid = NULL; + ccids_read_lock(); #ifdef CONFIG_KMOD - if (ccids[id] == NULL) + if (ccids[id] == NULL) { + /* We only try to load if in process context */ + ccids_read_unlock(); + if (gfp & GFP_ATOMIC) + goto out; request_module("net-dccp-ccid-%d", id); + ccids_read_lock(); + } #endif - ccids_read_lock(); + ccid_ops = ccids[id]; + if (ccid_ops == NULL) + goto out_unlock; - ccid = ccids[id]; - if (ccid == NULL) - goto out; + if (!try_module_get(ccid_ops->ccid_owner)) + goto out_unlock; - if (!try_module_get(ccid->ccid_owner)) - goto out_err; + ccids_read_unlock(); - if (ccid->ccid_init != NULL && ccid->ccid_init(sk) != 0) + ccid = kmem_cache_alloc(rx ? ccid_ops->ccid_hc_rx_slab : + ccid_ops->ccid_hc_tx_slab, gfp); + if (ccid == NULL) goto out_module_put; + ccid->ccid_ops = ccid_ops; + if (rx) { + memset(ccid + 1, 0, ccid_ops->ccid_hc_rx_obj_size); + if (ccid->ccid_ops->ccid_hc_rx_init != NULL && + ccid->ccid_ops->ccid_hc_rx_init(ccid, sk) != 0) + goto out_free_ccid; + } else { + memset(ccid + 1, 0, ccid_ops->ccid_hc_tx_obj_size); + if (ccid->ccid_ops->ccid_hc_tx_init != NULL && + ccid->ccid_ops->ccid_hc_tx_init(ccid, sk) != 0) + goto out_free_ccid; + } out: - ccids_read_unlock(); return ccid; -out_module_put: - module_put(ccid->ccid_owner); -out_err: +out_unlock: + ccids_read_unlock(); + goto out; +out_free_ccid: + kmem_cache_free(rx ? ccid_ops->ccid_hc_rx_slab : + ccid_ops->ccid_hc_tx_slab, ccid); ccid = NULL; +out_module_put: + module_put(ccid_ops->ccid_owner); goto out; } -EXPORT_SYMBOL_GPL(ccid_init); +EXPORT_SYMBOL_GPL(ccid_new); -void ccid_exit(struct ccid *ccid, struct sock *sk) +struct ccid *ccid_hc_rx_new(unsigned char id, struct sock *sk, gfp_t gfp) { + return ccid_new(id, sk, 1, gfp); +} + +EXPORT_SYMBOL_GPL(ccid_hc_rx_new); + +struct ccid *ccid_hc_tx_new(unsigned char id,struct sock *sk, gfp_t gfp) +{ + return ccid_new(id, sk, 0, gfp); +} + +EXPORT_SYMBOL_GPL(ccid_hc_tx_new); + +static void ccid_delete(struct ccid *ccid, struct sock *sk, int rx) +{ + struct ccid_operations *ccid_ops; + if (ccid == NULL) return; + ccid_ops = ccid->ccid_ops; + if (rx) { + if (ccid_ops->ccid_hc_rx_exit != NULL) + ccid_ops->ccid_hc_rx_exit(sk); + kmem_cache_free(ccid_ops->ccid_hc_rx_slab, ccid); + } else { + if (ccid_ops->ccid_hc_tx_exit != NULL) + ccid_ops->ccid_hc_tx_exit(sk); + kmem_cache_free(ccid_ops->ccid_hc_tx_slab, ccid); + } ccids_read_lock(); + if (ccids[ccid_ops->ccid_id] != NULL) + module_put(ccid_ops->ccid_owner); + ccids_read_unlock(); +} - if (ccids[ccid->ccid_id] != NULL) { - if (ccid->ccid_exit != NULL) - ccid->ccid_exit(sk); - module_put(ccid->ccid_owner); - } +void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk) +{ + ccid_delete(ccid, sk, 1); +} - ccids_read_unlock(); +EXPORT_SYMBOL_GPL(ccid_hc_rx_delete); + +void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk) +{ + ccid_delete(ccid, sk, 0); } -EXPORT_SYMBOL_GPL(ccid_exit); +EXPORT_SYMBOL_GPL(ccid_hc_tx_delete); diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h index de681c6ad081..3dec50d49731 100644 --- a/net/dccp/ccid.h +++ b/net/dccp/ccid.h @@ -23,14 +23,16 @@ struct tcp_info; -struct ccid { +struct ccid_operations { unsigned char ccid_id; const char *ccid_name; struct module *ccid_owner; - int (*ccid_init)(struct sock *sk); - void (*ccid_exit)(struct sock *sk); - int (*ccid_hc_rx_init)(struct sock *sk); - int (*ccid_hc_tx_init)(struct sock *sk); + kmem_cache_t *ccid_hc_rx_slab; + __u32 ccid_hc_rx_obj_size; + kmem_cache_t *ccid_hc_tx_slab; + __u32 ccid_hc_tx_obj_size; + int (*ccid_hc_rx_init)(struct ccid *ccid, struct sock *sk); + int (*ccid_hc_tx_init)(struct ccid *ccid, struct sock *sk); void (*ccid_hc_rx_exit)(struct sock *sk); void (*ccid_hc_tx_exit)(struct sock *sk); void (*ccid_hc_rx_packet_recv)(struct sock *sk, @@ -67,75 +69,58 @@ struct ccid { int __user *optlen); }; -extern int ccid_register(struct ccid *ccid); -extern int ccid_unregister(struct ccid *ccid); +extern int ccid_register(struct ccid_operations *ccid_ops); +extern int ccid_unregister(struct ccid_operations *ccid_ops); -extern struct ccid *ccid_init(unsigned char id, struct sock *sk); -extern void ccid_exit(struct ccid *ccid, struct sock *sk); +struct ccid { + struct ccid_operations *ccid_ops; + char ccid_priv[0]; +}; -static inline void __ccid_get(struct ccid *ccid) +static inline void *ccid_priv(const struct ccid *ccid) { - __module_get(ccid->ccid_owner); + return (void *)ccid->ccid_priv; } +extern struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, + gfp_t gfp); + +extern struct ccid *ccid_hc_rx_new(unsigned char id, struct sock *sk, + gfp_t gfp); +extern struct ccid *ccid_hc_tx_new(unsigned char id, struct sock *sk, + gfp_t gfp); + +extern void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk); +extern void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk); + static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk, struct sk_buff *skb, int len) { int rc = 0; - if (ccid->ccid_hc_tx_send_packet != NULL) - rc = ccid->ccid_hc_tx_send_packet(sk, skb, len); + if (ccid->ccid_ops->ccid_hc_tx_send_packet != NULL) + rc = ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb, len); return rc; } static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk, int more, int len) { - if (ccid->ccid_hc_tx_packet_sent != NULL) - ccid->ccid_hc_tx_packet_sent(sk, more, len); -} - -static inline int ccid_hc_rx_init(struct ccid *ccid, struct sock *sk) -{ - int rc = 0; - if (ccid->ccid_hc_rx_init != NULL) - rc = ccid->ccid_hc_rx_init(sk); - return rc; -} - -static inline int ccid_hc_tx_init(struct ccid *ccid, struct sock *sk) -{ - int rc = 0; - if (ccid->ccid_hc_tx_init != NULL) - rc = ccid->ccid_hc_tx_init(sk); - return rc; -} - -static inline void ccid_hc_rx_exit(struct ccid *ccid, struct sock *sk) -{ - if (ccid != NULL && ccid->ccid_hc_rx_exit != NULL && - dccp_sk(sk)->dccps_hc_rx_ccid_private != NULL) - ccid->ccid_hc_rx_exit(sk); -} - -static inline void ccid_hc_tx_exit(struct ccid *ccid, struct sock *sk) -{ - if (ccid != NULL && ccid->ccid_hc_tx_exit != NULL && - dccp_sk(sk)->dccps_hc_tx_ccid_private != NULL) - ccid->ccid_hc_tx_exit(sk); + if (ccid->ccid_ops->ccid_hc_tx_packet_sent != NULL) + ccid->ccid_ops->ccid_hc_tx_packet_sent(sk, more, len); } static inline void ccid_hc_rx_packet_recv(struct ccid *ccid, struct sock *sk, struct sk_buff *skb) { - if (ccid->ccid_hc_rx_packet_recv != NULL) - ccid->ccid_hc_rx_packet_recv(sk, skb); + if (ccid->ccid_ops->ccid_hc_rx_packet_recv != NULL) + ccid->ccid_ops->ccid_hc_rx_packet_recv(sk, skb); } static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk, struct sk_buff *skb) { - if (ccid->ccid_hc_tx_packet_recv != NULL) - ccid->ccid_hc_tx_packet_recv(sk, skb); + if (ccid->ccid_ops->ccid_hc_tx_packet_recv != NULL) + ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb); } static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk, @@ -144,8 +129,8 @@ static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk, unsigned char* value) { int rc = 0; - if (ccid->ccid_hc_tx_parse_options != NULL) - rc = ccid->ccid_hc_tx_parse_options(sk, option, len, idx, + if (ccid->ccid_ops->ccid_hc_tx_parse_options != NULL) + rc = ccid->ccid_ops->ccid_hc_tx_parse_options(sk, option, len, idx, value); return rc; } @@ -156,37 +141,37 @@ static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk, unsigned char* value) { int rc = 0; - if (ccid->ccid_hc_rx_parse_options != NULL) - rc = ccid->ccid_hc_rx_parse_options(sk, option, len, idx, value); + if (ccid->ccid_ops->ccid_hc_rx_parse_options != NULL) + rc = ccid->ccid_ops->ccid_hc_rx_parse_options(sk, option, len, idx, value); return rc; } static inline void ccid_hc_tx_insert_options(struct ccid *ccid, struct sock *sk, struct sk_buff *skb) { - if (ccid->ccid_hc_tx_insert_options != NULL) - ccid->ccid_hc_tx_insert_options(sk, skb); + if (ccid->ccid_ops->ccid_hc_tx_insert_options != NULL) + ccid->ccid_ops->ccid_hc_tx_insert_options(sk, skb); } static inline void ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk, struct sk_buff *skb) { - if (ccid->ccid_hc_rx_insert_options != NULL) - ccid->ccid_hc_rx_insert_options(sk, skb); + if (ccid->ccid_ops->ccid_hc_rx_insert_options != NULL) + ccid->ccid_ops->ccid_hc_rx_insert_options(sk, skb); } static inline void ccid_hc_rx_get_info(struct ccid *ccid, struct sock *sk, struct tcp_info *info) { - if (ccid->ccid_hc_rx_get_info != NULL) - ccid->ccid_hc_rx_get_info(sk, info); + if (ccid->ccid_ops->ccid_hc_rx_get_info != NULL) + ccid->ccid_ops->ccid_hc_rx_get_info(sk, info); } static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk, struct tcp_info *info) { - if (ccid->ccid_hc_tx_get_info != NULL) - ccid->ccid_hc_tx_get_info(sk, info); + if (ccid->ccid_ops->ccid_hc_tx_get_info != NULL) + ccid->ccid_ops->ccid_hc_tx_get_info(sk, info); } static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk, @@ -194,8 +179,8 @@ static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk, u32 __user *optval, int __user *optlen) { int rc = -ENOPROTOOPT; - if (ccid->ccid_hc_rx_getsockopt != NULL) - rc = ccid->ccid_hc_rx_getsockopt(sk, optname, len, + if (ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL) + rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len, optval, optlen); return rc; } @@ -205,8 +190,8 @@ static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk, u32 __user *optval, int __user *optlen) { int rc = -ENOPROTOOPT; - if (ccid->ccid_hc_tx_getsockopt != NULL) - rc = ccid->ccid_hc_tx_getsockopt(sk, optname, len, + if (ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL) + rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len, optval, optlen); return rc; } diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 3328d23c4be7..b40c4569a820 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -52,16 +52,6 @@ static int ccid2_debug; static const int ccid2_seq_len = 128; -static inline struct ccid2_hc_tx_sock *ccid2_hc_tx_sk(const struct sock *sk) -{ - return dccp_sk(sk)->dccps_hc_tx_ccid_private; -} - -static inline struct ccid2_hc_rx_sock *ccid2_hc_rx_sk(const struct sock *sk) -{ - return dccp_sk(sk)->dccps_hc_rx_ccid_private; -} - #ifdef CCID2_DEBUG static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx) { @@ -707,19 +697,12 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) ccid2_hc_tx_check_sanity(hctx); } -static int ccid2_hc_tx_init(struct sock *sk) +static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); - struct ccid2_hc_tx_sock *hctx; + struct ccid2_hc_tx_sock *hctx = ccid_priv(ccid); int seqcount = ccid2_seq_len; int i; - dp->dccps_hc_tx_ccid_private = kzalloc(sizeof(*hctx), gfp_any()); - if (dp->dccps_hc_tx_ccid_private == NULL) - return -ENOMEM; - - hctx = ccid2_hc_tx_sk(sk); - /* XXX init variables with proper values */ hctx->ccid2hctx_cwnd = 1; hctx->ccid2hctx_ssthresh = 10; @@ -728,11 +711,9 @@ static int ccid2_hc_tx_init(struct sock *sk) /* XXX init ~ to window size... */ hctx->ccid2hctx_seqbuf = kmalloc(sizeof(*hctx->ccid2hctx_seqbuf) * seqcount, gfp_any()); - if (hctx->ccid2hctx_seqbuf == NULL) { - kfree(dp->dccps_hc_tx_ccid_private); - dp->dccps_hc_tx_ccid_private = NULL; + if (hctx->ccid2hctx_seqbuf == NULL) return -ENOMEM; - } + for (i = 0; i < (seqcount - 1); i++) { hctx->ccid2hctx_seqbuf[i].ccid2s_next = &hctx->ccid2hctx_seqbuf[i + 1]; @@ -763,15 +744,11 @@ static int ccid2_hc_tx_init(struct sock *sk) static void ccid2_hc_tx_exit(struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); ccid2_hc_tx_kill_rto_timer(sk); - kfree(hctx->ccid2hctx_seqbuf); - - kfree(dp->dccps_hc_tx_ccid_private); - dp->dccps_hc_tx_ccid_private = NULL; + hctx->ccid2hctx_seqbuf = NULL; } static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) @@ -791,33 +768,17 @@ static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) } } -static int ccid2_hc_rx_init(struct sock *sk) -{ - struct dccp_sock *dp = dccp_sk(sk); - dp->dccps_hc_rx_ccid_private = kzalloc(sizeof(struct ccid2_hc_rx_sock), - gfp_any()); - return dp->dccps_hc_rx_ccid_private == NULL ? -ENOMEM : 0; -} - -static void ccid2_hc_rx_exit(struct sock *sk) -{ - struct dccp_sock *dp = dccp_sk(sk); - - kfree(dp->dccps_hc_rx_ccid_private); - dp->dccps_hc_rx_ccid_private = NULL; -} - -static struct ccid ccid2 = { +static struct ccid_operations ccid2 = { .ccid_id = 2, .ccid_name = "ccid2", .ccid_owner = THIS_MODULE, + .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock), .ccid_hc_tx_init = ccid2_hc_tx_init, .ccid_hc_tx_exit = ccid2_hc_tx_exit, .ccid_hc_tx_send_packet = ccid2_hc_tx_send_packet, .ccid_hc_tx_packet_sent = ccid2_hc_tx_packet_sent, .ccid_hc_tx_packet_recv = ccid2_hc_tx_packet_recv, - .ccid_hc_rx_init = ccid2_hc_rx_init, - .ccid_hc_rx_exit = ccid2_hc_rx_exit, + .ccid_hc_rx_obj_size = sizeof(struct ccid2_hc_rx_sock), .ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv, }; diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h index 0b08c90955a9..451a87464fa5 100644 --- a/net/dccp/ccids/ccid2.h +++ b/net/dccp/ccids/ccid2.h @@ -20,6 +20,13 @@ #ifndef _DCCP_CCID2_H_ #define _DCCP_CCID2_H_ +#include +#include +#include +#include "../ccid.h" + +struct sock; + struct ccid2_seq { u64 ccid2s_seq; unsigned long ccid2s_sent; @@ -66,4 +73,13 @@ struct ccid2_hc_rx_sock { int ccid2hcrx_data; }; +static inline struct ccid2_hc_tx_sock *ccid2_hc_tx_sk(const struct sock *sk) +{ + return ccid_priv(dccp_sk(sk)->dccps_hc_tx_ccid); +} + +static inline struct ccid2_hc_rx_sock *ccid2_hc_rx_sk(const struct sock *sk) +{ + return ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid); +} #endif /* _DCCP_CCID2_H_ */ diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index f9e16db09bef..0587f52e4af1 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -647,17 +647,10 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, return rc; } -static int ccid3_hc_tx_init(struct sock *sk) +static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk) { struct dccp_sock *dp = dccp_sk(sk); - struct ccid3_hc_tx_sock *hctx; - - dp->dccps_hc_tx_ccid_private = kmalloc(sizeof(*hctx), gfp_any()); - if (dp->dccps_hc_tx_ccid_private == NULL) - return -ENOMEM; - - hctx = ccid3_hc_tx_sk(sk); - memset(hctx, 0, sizeof(*hctx)); + struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid); if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE && dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE) @@ -680,7 +673,6 @@ static int ccid3_hc_tx_init(struct sock *sk) static void ccid3_hc_tx_exit(struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); BUG_ON(hctx == NULL); @@ -690,9 +682,6 @@ static void ccid3_hc_tx_exit(struct sock *sk) /* Empty packet history */ dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist); - - kfree(dp->dccps_hc_tx_ccid_private); - dp->dccps_hc_tx_ccid_private = NULL; } /* @@ -1039,20 +1028,13 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) } } -static int ccid3_hc_rx_init(struct sock *sk) +static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk) { struct dccp_sock *dp = dccp_sk(sk); - struct ccid3_hc_rx_sock *hcrx; + struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid); ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); - dp->dccps_hc_rx_ccid_private = kmalloc(sizeof(*hcrx), gfp_any()); - if (dp->dccps_hc_rx_ccid_private == NULL) - return -ENOMEM; - - hcrx = ccid3_hc_rx_sk(sk); - memset(hcrx, 0, sizeof(*hcrx)); - if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE && dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE) hcrx->ccid3hcrx_s = dp->dccps_packet_size; @@ -1071,7 +1053,6 @@ static int ccid3_hc_rx_init(struct sock *sk) static void ccid3_hc_rx_exit(struct sock *sk) { struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); - struct dccp_sock *dp = dccp_sk(sk); BUG_ON(hcrx == NULL); @@ -1082,9 +1063,6 @@ static void ccid3_hc_rx_exit(struct sock *sk) /* Empty loss interval history */ dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist); - - kfree(dp->dccps_hc_rx_ccid_private); - dp->dccps_hc_rx_ccid_private = NULL; } static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info) @@ -1170,10 +1148,11 @@ static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len, return 0; } -static struct ccid ccid3 = { +static struct ccid_operations ccid3 = { .ccid_id = 3, .ccid_name = "ccid3", .ccid_owner = THIS_MODULE, + .ccid_hc_tx_obj_size = sizeof(struct ccid3_hc_tx_sock), .ccid_hc_tx_init = ccid3_hc_tx_init, .ccid_hc_tx_exit = ccid3_hc_tx_exit, .ccid_hc_tx_send_packet = ccid3_hc_tx_send_packet, @@ -1181,6 +1160,7 @@ static struct ccid ccid3 = { .ccid_hc_tx_packet_recv = ccid3_hc_tx_packet_recv, .ccid_hc_tx_insert_options = ccid3_hc_tx_insert_options, .ccid_hc_tx_parse_options = ccid3_hc_tx_parse_options, + .ccid_hc_rx_obj_size = sizeof(struct ccid3_hc_rx_sock), .ccid_hc_rx_init = ccid3_hc_rx_init, .ccid_hc_rx_exit = ccid3_hc_rx_exit, .ccid_hc_rx_insert_options = ccid3_hc_rx_insert_options, diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index 0bde4583d091..f18b96d4e5a2 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -41,6 +41,7 @@ #include #include #include +#include "../ccid.h" #define TFRC_MIN_PACKET_SIZE 16 #define TFRC_STD_PACKET_SIZE 256 @@ -135,12 +136,12 @@ struct ccid3_hc_rx_sock { static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk) { - return dccp_sk(sk)->dccps_hc_tx_ccid_private; + return ccid_priv(dccp_sk(sk)->dccps_hc_tx_ccid); } static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk) { - return dccp_sk(sk)->dccps_hc_rx_ccid_private; + return ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid); } #endif /* _DCCP_CCID3_H_ */ diff --git a/net/dccp/input.c b/net/dccp/input.c index 4b6d43d8b920..67691a0592af 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -324,14 +324,6 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, dccp_set_seqno(&dp->dccps_swl, max48(dp->dccps_swl, dp->dccps_isr)); - if (ccid_hc_rx_init(dp->dccps_hc_rx_ccid, sk) != 0 || - ccid_hc_tx_init(dp->dccps_hc_tx_ccid, sk) != 0) { - ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk); - ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk); - /* FIXME: send appropriate RESET code */ - goto out_invalid_packet; - } - dccp_sync_mss(sk, icsk->icsk_pmtu_cookie); /* diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index fcfb486f90c2..aa7708fed32e 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -1058,14 +1058,16 @@ int dccp_v4_init_sock(struct sock *sk) if (dp->dccps_hc_rx_ackvec == NULL) return -ENOMEM; } - dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_rx_ccid, - sk); - dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_tx_ccid, - sk); - if (dp->dccps_hc_rx_ccid == NULL || - dp->dccps_hc_tx_ccid == NULL) { - ccid_exit(dp->dccps_hc_rx_ccid, sk); - ccid_exit(dp->dccps_hc_tx_ccid, sk); + dp->dccps_hc_rx_ccid = + ccid_hc_rx_new(dp->dccps_options.dccpo_rx_ccid, + sk, GFP_KERNEL); + dp->dccps_hc_tx_ccid = + ccid_hc_tx_new(dp->dccps_options.dccpo_tx_ccid, + sk, GFP_KERNEL); + if (unlikely(dp->dccps_hc_rx_ccid == NULL || + dp->dccps_hc_tx_ccid == NULL)) { + ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); + ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); if (dp->dccps_options.dccpo_send_ack_vector) { dccp_ackvec_free(dp->dccps_hc_rx_ackvec); dp->dccps_hc_rx_ackvec = NULL; @@ -1120,14 +1122,12 @@ int dccp_v4_destroy_sock(struct sock *sk) kfree(dp->dccps_service_list); dp->dccps_service_list = NULL; - ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk); - ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk); if (dp->dccps_options.dccpo_send_ack_vector) { dccp_ackvec_free(dp->dccps_hc_rx_ackvec); dp->dccps_hc_rx_ackvec = NULL; } - ccid_exit(dp->dccps_hc_rx_ccid, sk); - ccid_exit(dp->dccps_hc_tx_ccid, sk); + ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); + ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; /* clean up feature negotiation state */ diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 9e1de5919ee5..5324fcacb34d 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -121,23 +121,21 @@ struct sock *dccp_create_openreq_child(struct sock *sk, if (newdp->dccps_options.dccpo_send_ack_vector) { newdp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_ATOMIC); - /* - * XXX: We're using the same CCIDs set on the parent, - * i.e. sk_clone copied the master sock and left the - * CCID pointers for this child, that is why we do the - * __ccid_get calls. - */ if (unlikely(newdp->dccps_hc_rx_ackvec == NULL)) goto out_free; } - if (unlikely(ccid_hc_rx_init(newdp->dccps_hc_rx_ccid, - newsk) != 0 || - ccid_hc_tx_init(newdp->dccps_hc_tx_ccid, - newsk) != 0)) { + newdp->dccps_hc_rx_ccid = + ccid_hc_rx_new(newdp->dccps_options.dccpo_rx_ccid, + newsk, GFP_ATOMIC); + newdp->dccps_hc_tx_ccid = + ccid_hc_tx_new(newdp->dccps_options.dccpo_tx_ccid, + newsk, GFP_ATOMIC); + if (unlikely(newdp->dccps_hc_rx_ccid == NULL || + newdp->dccps_hc_tx_ccid == NULL)) { dccp_ackvec_free(newdp->dccps_hc_rx_ackvec); - ccid_hc_rx_exit(newdp->dccps_hc_rx_ccid, newsk); - ccid_hc_tx_exit(newdp->dccps_hc_tx_ccid, newsk); + ccid_hc_rx_delete(newdp->dccps_hc_rx_ccid, newsk); + ccid_hc_tx_delete(newdp->dccps_hc_tx_ccid, newsk); out_free: /* It is still raw copy of parent, so invalidate * destructor and make plain sk_free() */ @@ -146,9 +144,6 @@ out_free: return NULL; } - __ccid_get(newdp->dccps_hc_rx_ccid); - __ccid_get(newdp->dccps_hc_tx_ccid); - /* * Step 3: Process LISTEN state * -- cgit v1.2.3 From a193a4abdd1f742a57f3f70b6a83c3e536876e97 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 20 Mar 2006 19:23:05 -0800 Subject: [NETFILTER]: Fix skb->nf_bridge lifetime issues The bridge netfilter code simulates the NF_IP_PRE_ROUTING hook and skips the real hook by registering with high priority and returning NF_STOP if skb->nf_bridge is present and the BRNF_NF_BRIDGE_PREROUTING flag is not set. The flag is only set during the simulated hook. Because skb->nf_bridge is only freed when the packet is destroyed, the packet will not only skip the first invocation of NF_IP_PRE_ROUTING, but in the case of tunnel devices on top of the bridge also all further ones. Forwarded packets from a bridge encapsulated by a tunnel device and sent as locally outgoing packet will also still have the incorrect bridge information from the input path attached. We already have nf_reset calls on all RX/TX paths of tunnel devices, so simply reset the nf_bridge field there too. As an added bonus, the bridge information for locally delivered packets is now also freed when the packet is queued to a socket. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/skbuff.h | 24 ++++++++++++++---------- net/ipv4/netfilter/ipt_REJECT.c | 4 ---- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 838ce0fdcef7..1a2611030d36 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1351,16 +1351,6 @@ static inline void nf_conntrack_put_reasm(struct sk_buff *skb) kfree_skb(skb); } #endif -static inline void nf_reset(struct sk_buff *skb) -{ - nf_conntrack_put(skb->nfct); - skb->nfct = NULL; -#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) - nf_conntrack_put_reasm(skb->nfct_reasm); - skb->nfct_reasm = NULL; -#endif -} - #ifdef CONFIG_BRIDGE_NETFILTER static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge) { @@ -1373,6 +1363,20 @@ static inline void nf_bridge_get(struct nf_bridge_info *nf_bridge) atomic_inc(&nf_bridge->use); } #endif /* CONFIG_BRIDGE_NETFILTER */ +static inline void nf_reset(struct sk_buff *skb) +{ + nf_conntrack_put(skb->nfct); + skb->nfct = NULL; +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + nf_conntrack_put_reasm(skb->nfct_reasm); + skb->nfct_reasm = NULL; +#endif +#ifdef CONFIG_BRIDGE_NETFILTER + nf_bridge_put(skb->nf_bridge); + skb->nf_bridge = NULL; +#endif +} + #else /* CONFIG_NETFILTER */ static inline void nf_reset(struct sk_buff *skb) {} #endif /* CONFIG_NETFILTER */ diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 26ea6c19f5bd..9d3b3579f27c 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -154,10 +154,6 @@ static void send_reset(struct sk_buff *oldskb, int hook) /* This packet will not be the same as the other: clear nf fields */ nf_reset(nskb); nskb->nfmark = 0; -#ifdef CONFIG_BRIDGE_NETFILTER - nf_bridge_put(nskb->nf_bridge); - nskb->nf_bridge = NULL; -#endif tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl); -- cgit v1.2.3 From 60fe62e789076ae7c13f7ffb35fec4b24802530d Mon Sep 17 00:00:00 2001 From: Andrea Bittau Date: Mon, 20 Mar 2006 19:23:32 -0800 Subject: [DCCP]: sparse endianness annotations This also fixes the layout of dccp_hdr short sequence numbers, problem was not fatal now as we only support long (48 bits) sequence numbers. Signed-off-by: Andrea Bittau Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/dccp.h | 52 ++++++++++++++++++++------------------------------ net/dccp/ccids/ccid3.c | 6 +++--- net/dccp/dccp.h | 23 ++++++---------------- net/dccp/ipv4.c | 12 ++++++------ net/dccp/ipv6.c | 4 ++-- net/dccp/options.c | 27 +++++++++++++------------- net/dccp/proto.c | 6 +++--- 7 files changed, 54 insertions(+), 76 deletions(-) (limited to 'include') diff --git a/include/linux/dccp.h b/include/linux/dccp.h index bdd756cc60b1..496dbad8e896 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -18,7 +18,7 @@ * @dccph_seq - sequence number high or low order 24 bits, depends on dccph_x */ struct dccp_hdr { - __u16 dccph_sport, + __be16 dccph_sport, dccph_dport; __u8 dccph_doff; #if defined(__LITTLE_ENDIAN_BITFIELD) @@ -32,18 +32,18 @@ struct dccp_hdr { #endif __u16 dccph_checksum; #if defined(__LITTLE_ENDIAN_BITFIELD) - __u32 dccph_x:1, + __u8 dccph_x:1, dccph_type:4, - dccph_reserved:3, - dccph_seq:24; + dccph_reserved:3; #elif defined(__BIG_ENDIAN_BITFIELD) - __u32 dccph_reserved:3, + __u8 dccph_reserved:3, dccph_type:4, - dccph_x:1, - dccph_seq:24; + dccph_x:1; #else #error "Adjust your defines" #endif + __u8 dccph_seq2; + __be16 dccph_seq; }; /** @@ -52,7 +52,7 @@ struct dccp_hdr { * @dccph_seq_low - low 24 bits of a 48 bit seq packet */ struct dccp_hdr_ext { - __u32 dccph_seq_low; + __be32 dccph_seq_low; }; /** @@ -62,7 +62,7 @@ struct dccp_hdr_ext { * @dccph_req_options - list of options (must be a multiple of 32 bits */ struct dccp_hdr_request { - __u32 dccph_req_service; + __be32 dccph_req_service; }; /** * struct dccp_hdr_ack_bits - acknowledgment bits common to most packets @@ -71,9 +71,9 @@ struct dccp_hdr_request { * @dccph_resp_ack_nr_low - 48 bit ack number low order bits, contains GSR */ struct dccp_hdr_ack_bits { - __u32 dccph_reserved1:8, - dccph_ack_nr_high:24; - __u32 dccph_ack_nr_low; + __be16 dccph_reserved1; + __be16 dccph_ack_nr_high; + __be32 dccph_ack_nr_low; }; /** * struct dccp_hdr_response - Conection initiation response header @@ -85,7 +85,7 @@ struct dccp_hdr_ack_bits { */ struct dccp_hdr_response { struct dccp_hdr_ack_bits dccph_resp_ack; - __u32 dccph_resp_service; + __be32 dccph_resp_service; }; /** @@ -269,16 +269,12 @@ static inline unsigned int dccp_basic_hdr_len(const struct sk_buff *skb) static inline __u64 dccp_hdr_seq(const struct sk_buff *skb) { const struct dccp_hdr *dh = dccp_hdr(skb); -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u64 seq_nr = ntohl(dh->dccph_seq << 8); -#elif defined(__BIG_ENDIAN_BITFIELD) - __u64 seq_nr = ntohl(dh->dccph_seq); -#else -#error "Adjust your defines" -#endif + __u64 seq_nr = ntohs(dh->dccph_seq); if (dh->dccph_x != 0) seq_nr = (seq_nr << 32) + ntohl(dccp_hdrx(skb)->dccph_seq_low); + else + seq_nr += (u32)dh->dccph_seq2 << 16; return seq_nr; } @@ -296,13 +292,7 @@ static inline struct dccp_hdr_ack_bits *dccp_hdr_ack_bits(const struct sk_buff * static inline u64 dccp_hdr_ack_seq(const struct sk_buff *skb) { const struct dccp_hdr_ack_bits *dhack = dccp_hdr_ack_bits(skb); -#if defined(__LITTLE_ENDIAN_BITFIELD) - return (((u64)ntohl(dhack->dccph_ack_nr_high << 8)) << 32) + ntohl(dhack->dccph_ack_nr_low); -#elif defined(__BIG_ENDIAN_BITFIELD) - return (((u64)ntohl(dhack->dccph_ack_nr_high)) << 32) + ntohl(dhack->dccph_ack_nr_low); -#else -#error "Adjust your defines" -#endif + return ((u64)ntohs(dhack->dccph_ack_nr_high) << 32) + ntohl(dhack->dccph_ack_nr_low); } static inline struct dccp_hdr_response *dccp_hdr_response(struct sk_buff *skb) @@ -387,7 +377,7 @@ struct dccp_request_sock { struct inet_request_sock dreq_inet_rsk; __u64 dreq_iss; __u64 dreq_isr; - __u32 dreq_service; + __be32 dreq_service; }; static inline struct dccp_request_sock *dccp_rsk(const struct request_sock *req) @@ -415,13 +405,13 @@ enum dccp_role { struct dccp_service_list { __u32 dccpsl_nr; - __u32 dccpsl_list[0]; + __be32 dccpsl_list[0]; }; #define DCCP_SERVICE_INVALID_VALUE htonl((__u32)-1) static inline int dccp_list_has_service(const struct dccp_service_list *sl, - const u32 service) + const __be32 service) { if (likely(sl != NULL)) { u32 i = sl->dccpsl_nr; @@ -467,7 +457,7 @@ struct dccp_sock { __u64 dccps_gss; __u64 dccps_gsr; __u64 dccps_gar; - __u32 dccps_service; + __be32 dccps_service; struct dccp_service_list *dccps_service_list; struct timeval dccps_timestamp_time; __u32 dccps_timestamp_echo; diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 0587f52e4af1..86201631fb6e 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -615,7 +615,7 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, __FUNCTION__, dccp_role(sk), sk); rc = -EINVAL; } else { - opt_recv->ccid3or_loss_event_rate = ntohl(*(u32 *)value); + opt_recv->ccid3or_loss_event_rate = ntohl(*(__be32 *)value); ccid3_pr_debug("%s, sk=%p, LOSS_EVENT_RATE=%u\n", dccp_role(sk), sk, opt_recv->ccid3or_loss_event_rate); @@ -636,7 +636,7 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, __FUNCTION__, dccp_role(sk), sk); rc = -EINVAL; } else { - opt_recv->ccid3or_receive_rate = ntohl(*(u32 *)value); + opt_recv->ccid3or_receive_rate = ntohl(*(__be32 *)value); ccid3_pr_debug("%s, sk=%p, RECEIVE_RATE=%u\n", dccp_role(sk), sk, opt_recv->ccid3or_receive_rate); @@ -777,7 +777,7 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk) static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) { const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); - u32 x_recv, pinv; + __be32 x_recv, pinv; BUG_ON(hcrx == NULL); diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 93f26dd6e6cb..1764adb4f15e 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -262,7 +262,7 @@ extern int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); extern int dccp_v4_checksum(const struct sk_buff *skb, - const u32 saddr, const u32 daddr); + const __be32 saddr, const __be32 daddr); extern int dccp_v4_send_reset(struct sock *sk, enum dccp_reset_codes code); @@ -270,7 +270,7 @@ extern void dccp_send_close(struct sock *sk, const int active); extern int dccp_invalid_packet(struct sk_buff *skb); static inline int dccp_bad_service_code(const struct sock *sk, - const __u32 service) + const __be32 service) { const struct dccp_sock *dp = dccp_sk(sk); @@ -334,27 +334,16 @@ static inline void dccp_hdr_set_seq(struct dccp_hdr *dh, const u64 gss) { struct dccp_hdr_ext *dhx = (struct dccp_hdr_ext *)((void *)dh + sizeof(*dh)); - -#if defined(__LITTLE_ENDIAN_BITFIELD) - dh->dccph_seq = htonl((gss >> 32)) >> 8; -#elif defined(__BIG_ENDIAN_BITFIELD) - dh->dccph_seq = htonl((gss >> 32)); -#else -#error "Adjust your defines" -#endif + dh->dccph_seq2 = 0; + dh->dccph_seq = htons((gss >> 32) & 0xfffff); dhx->dccph_seq_low = htonl(gss & 0xffffffff); } static inline void dccp_hdr_set_ack(struct dccp_hdr_ack_bits *dhack, const u64 gsr) { -#if defined(__LITTLE_ENDIAN_BITFIELD) - dhack->dccph_ack_nr_high = htonl((gsr >> 32)) >> 8; -#elif defined(__BIG_ENDIAN_BITFIELD) - dhack->dccph_ack_nr_high = htonl((gsr >> 32)); -#else -#error "Adjust your defines" -#endif + dhack->dccph_reserved1 = 0; + dhack->dccph_ack_nr_high = htons(gsr >> 32); dhack->dccph_ack_nr_low = htonl(gsr & 0xffffffff); } diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index aa7708fed32e..be5ce57b8046 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -498,9 +498,9 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) struct dccp_sock dp; struct request_sock *req; struct dccp_request_sock *dreq; - const __u32 saddr = skb->nh.iph->saddr; - const __u32 daddr = skb->nh.iph->daddr; - const __u32 service = dccp_hdr_request(skb)->dccph_req_service; + const __be32 saddr = skb->nh.iph->saddr; + const __be32 daddr = skb->nh.iph->daddr; + const __be32 service = dccp_hdr_request(skb)->dccph_req_service; struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY; @@ -662,8 +662,8 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) return sk; } -int dccp_v4_checksum(const struct sk_buff *skb, const u32 saddr, - const u32 daddr) +int dccp_v4_checksum(const struct sk_buff *skb, const __be32 saddr, + const __be32 daddr) { const struct dccp_hdr* dh = dccp_hdr(skb); int checksum_len; @@ -683,7 +683,7 @@ int dccp_v4_checksum(const struct sk_buff *skb, const u32 saddr, } static int dccp_v4_verify_checksum(struct sk_buff *skb, - const u32 saddr, const u32 daddr) + const __be32 saddr, const __be32 daddr) { struct dccp_hdr *dh = dccp_hdr(skb); int checksum_len; diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 80c4d048869e..ad5a1c66362d 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -264,7 +264,7 @@ failure: } static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) + int type, int code, int offset, __be32 info) { struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data; const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset); @@ -678,7 +678,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) struct dccp_request_sock *dreq; struct inet6_request_sock *ireq6; struct ipv6_pinfo *np = inet6_sk(sk); - const __u32 service = dccp_hdr_request(skb)->dccph_req_service; + const __be32 service = dccp_hdr_request(skb)->dccph_req_service; struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY; diff --git a/net/dccp/options.c b/net/dccp/options.c index 7f99306c8e99..7d73b33a6043 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -155,7 +155,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) if (len != 4) goto out_invalid_option; - opt_recv->dccpor_timestamp = ntohl(*(u32 *)value); + opt_recv->dccpor_timestamp = ntohl(*(__be32 *)value); dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp; dccp_timestamp(sk, &dp->dccps_timestamp_time); @@ -169,7 +169,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) if (len != 4 && len != 6 && len != 8) goto out_invalid_option; - opt_recv->dccpor_timestamp_echo = ntohl(*(u32 *)value); + opt_recv->dccpor_timestamp_echo = ntohl(*(__be32 *)value); dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, ackno=%llu, ", debug_prefix, @@ -183,9 +183,9 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) break; if (len == 6) - elapsed_time = ntohs(*(u16 *)(value + 4)); + elapsed_time = ntohs(*(__be16 *)(value + 4)); else - elapsed_time = ntohl(*(u32 *)(value + 4)); + elapsed_time = ntohl(*(__be32 *)(value + 4)); /* Give precedence to the biggest ELAPSED_TIME */ if (elapsed_time > opt_recv->dccpor_elapsed_time) @@ -199,9 +199,9 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) continue; if (len == 2) - elapsed_time = ntohs(*(u16 *)value); + elapsed_time = ntohs(*(__be16 *)value); else - elapsed_time = ntohl(*(u32 *)value); + elapsed_time = ntohl(*(__be32 *)value); if (elapsed_time > opt_recv->dccpor_elapsed_time) opt_recv->dccpor_elapsed_time = elapsed_time; @@ -358,10 +358,10 @@ void dccp_insert_option_elapsed_time(struct sock *sk, *to++ = len; if (elapsed_time_len == 2) { - const u16 var16 = htons((u16)elapsed_time); + const __be16 var16 = htons((u16)elapsed_time); memcpy(to, &var16, 2); } else { - const u32 var32 = htonl(elapsed_time); + const __be32 var32 = htonl(elapsed_time); memcpy(to, &var32, 4); } @@ -392,14 +392,13 @@ EXPORT_SYMBOL_GPL(dccp_timestamp); void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb) { struct timeval tv; - u32 now; + __be32 now; dccp_timestamp(sk, &tv); - now = timeval_usecs(&tv) / 10; + now = htonl(timeval_usecs(&tv) / 10); /* yes this will overflow but that is the point as we want a * 10 usec 32 bit timer which mean it wraps every 11.9 hours */ - now = htonl(now); dccp_insert_option(sk, skb, DCCPO_TIMESTAMP, &now, sizeof(now)); } @@ -414,7 +413,7 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk, "CLIENT TX opt: " : "server TX opt: "; #endif struct timeval now; - u32 tstamp_echo; + __be32 tstamp_echo; u32 elapsed_time; int len, elapsed_time_len; unsigned char *to; @@ -441,10 +440,10 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk, to += 4; if (elapsed_time_len == 2) { - const u16 var16 = htons((u16)elapsed_time); + const __be16 var16 = htons((u16)elapsed_time); memcpy(to, &var16, 2); } else if (elapsed_time_len == 4) { - const u32 var32 = htonl(elapsed_time); + const __be32 var32 = htonl(elapsed_time); memcpy(to, &var32, 4); } diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 1a8cf8ecfe63..53735ee2bbd1 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -221,7 +221,7 @@ int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg) EXPORT_SYMBOL_GPL(dccp_ioctl); -static int dccp_setsockopt_service(struct sock *sk, const u32 service, +static int dccp_setsockopt_service(struct sock *sk, const __be32 service, char __user *optval, int optlen) { struct dccp_sock *dp = dccp_sk(sk); @@ -349,7 +349,7 @@ int dccp_setsockopt(struct sock *sk, int level, int optname, EXPORT_SYMBOL_GPL(dccp_setsockopt); static int dccp_getsockopt_service(struct sock *sk, int len, - u32 __user *optval, + __be32 __user *optval, int __user *optlen) { const struct dccp_sock *dp = dccp_sk(sk); @@ -404,7 +404,7 @@ int dccp_getsockopt(struct sock *sk, int level, int optname, break; case DCCP_SOCKOPT_SERVICE: return dccp_getsockopt_service(sk, len, - (u32 __user *)optval, optlen); + (__be32 __user *)optval, optlen); case 128 ... 191: return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname, len, (u32 __user *)optval, optlen); -- cgit v1.2.3 From 93ce20928f6e197707add8f670ae0cd029107e8f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 20 Mar 2006 19:23:58 -0800 Subject: [DCCP]: Make CCID2 be the default As per the draft. This fixes the build when netfilter dccp components are built and dccp isn't. Thanks to Reuben Farrelly for reporting this. The following changesets will introduce /proc/sys/net/dccp/defaults/ to give more flexibility to DCCP developers and testers while apps doesn't use setsockopt to specify the desired CCID, etc. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/linux/dccp.h | 9 --------- 1 file changed, 9 deletions(-) (limited to 'include') diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 496dbad8e896..e35f680f909b 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -320,17 +320,8 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb) /* initial values for each feature */ #define DCCPF_INITIAL_SEQUENCE_WINDOW 100 #define DCCPF_INITIAL_ACK_RATIO 2 - -#if defined(CONFIG_IP_DCCP_CCID2) || defined(CONFIG_IP_DCCP_CCID2_MODULE) #define DCCPF_INITIAL_CCID 2 #define DCCPF_INITIAL_SEND_ACK_VECTOR 1 -#elif defined(CONFIG_IP_DCCP_CCID3) || defined(CONFIG_IP_DCCP_CCID3_MODULE) -#define DCCPF_INITIAL_CCID 3 -#define DCCPF_INITIAL_SEND_ACK_VECTOR 0 -#else -#error "At least one CCID must be built as the default" -#endif - /* FIXME: for now we're default to 1 but it should really be 0 */ #define DCCPF_INITIAL_SEND_NDP_COUNT 1 -- cgit v1.2.3 From e55d912f5b75723159348a7fc7692f869a86636a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 20 Mar 2006 19:25:02 -0800 Subject: [DCCP] feat: Introduce sysctls for the default features [root@qemu ~]# for a in /proc/sys/net/dccp/default/* ; do echo $a ; cat $a ; done /proc/sys/net/dccp/default/ack_ratio 2 /proc/sys/net/dccp/default/rx_ccid 3 /proc/sys/net/dccp/default/send_ackvec 1 /proc/sys/net/dccp/default/send_ndp 1 /proc/sys/net/dccp/default/seq_window 100 /proc/sys/net/dccp/default/tx_ccid 3 [root@qemu ~]# So if wanting to test ccid3 as the tx CCID one can just do: [root@qemu ~]# echo 3 > /proc/sys/net/dccp/default/tx_ccid [root@qemu ~]# echo 2 > /proc/sys/net/dccp/default/rx_ccid [root@qemu ~]# cat /proc/sys/net/dccp/default/[tr]x_ccid 2 3 [root@qemu ~]# Of course we also need the setsockopt for each app to tell its preferences, but for testing or defining something other than CCID2 as the default for apps that don't explicitely set their preference the sysctl interface is handy. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/linux/sysctl.h | 16 +++++++ net/dccp/Makefile | 2 + net/dccp/dccp.h | 14 ++++++ net/dccp/options.c | 22 +++++---- net/dccp/proto.c | 9 +++- net/dccp/sysctl.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 176 insertions(+), 11 deletions(-) create mode 100644 net/dccp/sysctl.c (limited to 'include') diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index b686548f32e0..dfcf449afc7c 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -211,6 +211,7 @@ enum NET_SCTP=17, NET_LLC=18, NET_NETFILTER=19, + NET_DCCP=20, }; /* /proc/sys/kernel/random */ @@ -571,6 +572,21 @@ enum { __NET_NEIGH_MAX }; +/* /proc/sys/net/dccp */ +enum { + NET_DCCP_DEFAULT=1, +}; + +/* /proc/sys/net/dccp/default */ +enum { + NET_DCCP_DEFAULT_SEQ_WINDOW = 1, + NET_DCCP_DEFAULT_RX_CCID = 2, + NET_DCCP_DEFAULT_TX_CCID = 3, + NET_DCCP_DEFAULT_ACK_RATIO = 4, + NET_DCCP_DEFAULT_SEND_ACKVEC = 5, + NET_DCCP_DEFAULT_SEND_NDP = 6, +}; + /* /proc/sys/net/ipx */ enum { NET_IPX_PPROP_BROADCASTING=1, diff --git a/net/dccp/Makefile b/net/dccp/Makefile index 5736acea1c86..7af0569fe4cb 100644 --- a/net/dccp/Makefile +++ b/net/dccp/Makefile @@ -11,6 +11,8 @@ dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o +dccp-$(CONFIG_SYSCTL) += sysctl.o + dccp_diag-y := diag.o obj-y += ccids/ diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 1764adb4f15e..f059541f5a1d 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -433,4 +433,18 @@ static inline void timeval_sub_usecs(struct timeval *tv, } } +#ifdef CONFIG_SYSCTL +extern int dccp_sysctl_init(void); +extern void dccp_sysctl_exit(void); +#else +static inline int dccp_sysctl_init(void) +{ + return 0; +} + +static inline void dccp_sysctl_exit(void) +{ +} +#endif + #endif /* _DCCP_H */ diff --git a/net/dccp/options.c b/net/dccp/options.c index 7d73b33a6043..3ecd319c0f59 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -23,19 +23,21 @@ #include "dccp.h" #include "feat.h" -/* stores the default values for new connection. may be changed with sysctl */ -static const struct dccp_options dccpo_default_values = { - .dccpo_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW, - .dccpo_rx_ccid = DCCPF_INITIAL_CCID, - .dccpo_tx_ccid = DCCPF_INITIAL_CCID, - .dccpo_ack_ratio = DCCPF_INITIAL_ACK_RATIO, - .dccpo_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR, - .dccpo_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT, -}; +int dccp_feat_default_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW; +int dccp_feat_default_rx_ccid = DCCPF_INITIAL_CCID; +int dccp_feat_default_tx_ccid = DCCPF_INITIAL_CCID; +int dccp_feat_default_ack_ratio = DCCPF_INITIAL_ACK_RATIO; +int dccp_feat_default_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR; +int dccp_feat_default_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT; void dccp_options_init(struct dccp_options *dccpo) { - memcpy(dccpo, &dccpo_default_values, sizeof(*dccpo)); + dccpo->dccpo_sequence_window = dccp_feat_default_sequence_window; + dccpo->dccpo_rx_ccid = dccp_feat_default_rx_ccid; + dccpo->dccpo_tx_ccid = dccp_feat_default_tx_ccid; + dccpo->dccpo_ack_ratio = dccp_feat_default_ack_ratio; + dccpo->dccpo_send_ack_vector = dccp_feat_default_send_ack_vector; + dccpo->dccpo_send_ndp_count = dccp_feat_default_send_ndp_count; } static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len) diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 53735ee2bbd1..6403e9306ddb 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -934,11 +934,17 @@ static int __init dccp_init(void) if (rc) goto out_unregister_protosw; - rc = dccp_ctl_sock_init(); + rc = dccp_sysctl_init(); if (rc) goto out_ackvec_exit; + + rc = dccp_ctl_sock_init(); + if (rc) + goto out_sysctl_exit; out: return rc; +out_sysctl_exit: + dccp_sysctl_exit(); out_ackvec_exit: dccp_ackvec_exit(); out_unregister_protosw: @@ -983,6 +989,7 @@ static void __exit dccp_fini(void) kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep); proto_unregister(&dccp_prot); dccp_ackvec_exit(); + dccp_sysctl_exit(); } module_init(dccp_init); diff --git a/net/dccp/sysctl.c b/net/dccp/sysctl.c new file mode 100644 index 000000000000..64c89e9c229e --- /dev/null +++ b/net/dccp/sysctl.c @@ -0,0 +1,124 @@ +/* + * net/dccp/sysctl.c + * + * An implementation of the DCCP protocol + * Arnaldo Carvalho de Melo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License v2 + * as published by the Free Software Foundation. + */ + +#include +#include +#include + +#ifndef CONFIG_SYSCTL +#error This file should not be compiled without CONFIG_SYSCTL defined +#endif + +extern int dccp_feat_default_sequence_window; +extern int dccp_feat_default_rx_ccid; +extern int dccp_feat_default_tx_ccid; +extern int dccp_feat_default_ack_ratio; +extern int dccp_feat_default_send_ack_vector; +extern int dccp_feat_default_send_ndp_count; + +static struct ctl_table dccp_default_table[] = { + { + .ctl_name = NET_DCCP_DEFAULT_SEQ_WINDOW, + .procname = "seq_window", + .data = &dccp_feat_default_sequence_window, + .maxlen = sizeof(dccp_feat_default_sequence_window), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = NET_DCCP_DEFAULT_RX_CCID, + .procname = "rx_ccid", + .data = &dccp_feat_default_rx_ccid, + .maxlen = sizeof(dccp_feat_default_rx_ccid), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = NET_DCCP_DEFAULT_TX_CCID, + .procname = "tx_ccid", + .data = &dccp_feat_default_tx_ccid, + .maxlen = sizeof(dccp_feat_default_tx_ccid), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = NET_DCCP_DEFAULT_ACK_RATIO, + .procname = "ack_ratio", + .data = &dccp_feat_default_ack_ratio, + .maxlen = sizeof(dccp_feat_default_ack_ratio), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = NET_DCCP_DEFAULT_SEND_ACKVEC, + .procname = "send_ackvec", + .data = &dccp_feat_default_send_ack_vector, + .maxlen = sizeof(dccp_feat_default_send_ack_vector), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .ctl_name = NET_DCCP_DEFAULT_SEND_NDP, + .procname = "send_ndp", + .data = &dccp_feat_default_send_ndp_count, + .maxlen = sizeof(dccp_feat_default_send_ndp_count), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { .ctl_name = 0, } +}; + +static struct ctl_table dccp_table[] = { + { + .ctl_name = NET_DCCP_DEFAULT, + .procname = "default", + .mode = 0555, + .child = dccp_default_table, + }, + { .ctl_name = 0, }, +}; + +static struct ctl_table dccp_dir_table[] = { + { + .ctl_name = NET_DCCP, + .procname = "dccp", + .mode = 0555, + .child = dccp_table, + }, + { .ctl_name = 0, }, +}; + +static struct ctl_table dccp_root_table[] = { + { + .ctl_name = CTL_NET, + .procname = "net", + .mode = 0555, + .child = dccp_dir_table, + }, + { .ctl_name = 0, }, +}; + +static struct ctl_table_header *dccp_table_header; + +int __init dccp_sysctl_init(void) +{ + dccp_table_header = register_sysctl_table(dccp_root_table, 1); + + return dccp_table_header != NULL ? 0 : -ENOMEM; +} + +void dccp_sysctl_exit(void) +{ + if (dccp_table_header != NULL) { + unregister_sysctl_table(dccp_table_header); + dccp_table_header = NULL; + } +} -- cgit v1.2.3 From 4bf07ef3fd5db2df7d1899fcf9c67d2263ead2e2 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 20 Mar 2006 21:25:50 -0800 Subject: [XFRM]: Rearrange struct xfrm_aevent_id for better compatibility. struct xfrm_aevent_id needs to be 32-bit + 64-bit align friendly. Based upon suggestions from Yoshifuji. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/linux/xfrm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index b54a12940ef6..6b42cc474c01 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h @@ -259,8 +259,8 @@ struct xfrm_usersa_id { }; struct xfrm_aevent_id { - __u32 flags; struct xfrm_usersa_id sa_id; + __u32 flags; }; struct xfrm_userspi_info { -- cgit v1.2.3 From 231d06ae826664b83369166449144304859a62fa Mon Sep 17 00:00:00 2001 From: Jörn Engel Date: Mon, 20 Mar 2006 21:28:35 -0800 Subject: [NET]: Uninline kfree_skb and allow NULL argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit o Uninline kfree_skb, which saves some 15k of object code on my notebook. o Allow kfree_skb to be called with a NULL argument. Subsequent patches can remove conditional from drivers and further reduce source and object size. Signed-off-by: Jörn Engel Signed-off-by: David S. Miller --- include/linux/skbuff.h | 17 +---------------- net/core/skbuff.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 1a2611030d36..75c963103b9f 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -304,6 +304,7 @@ struct sk_buff { #include +extern void kfree_skb(struct sk_buff *skb); extern void __kfree_skb(struct sk_buff *skb); extern struct sk_buff *__alloc_skb(unsigned int size, gfp_t priority, int fclone); @@ -403,22 +404,6 @@ static inline struct sk_buff *skb_get(struct sk_buff *skb) * atomic change. */ -/** - * kfree_skb - free an sk_buff - * @skb: buffer to free - * - * Drop a reference to the buffer and free it if the usage count has - * hit zero. - */ -static inline void kfree_skb(struct sk_buff *skb) -{ - if (likely(atomic_read(&skb->users) == 1)) - smp_rmb(); - else if (likely(!atomic_dec_and_test(&skb->users))) - return; - __kfree_skb(skb); -} - /** * skb_cloned - is the buffer a clone * @skb: buffer to check diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 2144952d1c6c..01abf1e8990b 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -355,6 +355,24 @@ void __kfree_skb(struct sk_buff *skb) kfree_skbmem(skb); } +/** + * kfree_skb - free an sk_buff + * @skb: buffer to free + * + * Drop a reference to the buffer and free it if the usage count has + * hit zero. + */ +void kfree_skb(struct sk_buff *skb) +{ + if (unlikely(!skb)) + return; + if (likely(atomic_read(&skb->users) == 1)) + smp_rmb(); + else if (likely(!atomic_dec_and_test(&skb->users))) + return; + __kfree_skb(skb); +} + /** * skb_clone - duplicate an sk_buff * @skb: buffer to clone @@ -1799,6 +1817,7 @@ void __init skb_init(void) EXPORT_SYMBOL(___pskb_trim); EXPORT_SYMBOL(__kfree_skb); +EXPORT_SYMBOL(kfree_skb); EXPORT_SYMBOL(__pskb_pull_tail); EXPORT_SYMBOL(__alloc_skb); EXPORT_SYMBOL(pskb_copy); -- cgit v1.2.3 From 1d541ddd74802cfa0eb8a3864668851f6cd79bdf Mon Sep 17 00:00:00 2001 From: Benjamin LaHaise Date: Mon, 20 Mar 2006 21:31:51 -0800 Subject: [AF_UNIX]: scm: better initialization Instead of doing a memset then initialization of the fields of the scm structure, just initialize all the members explicitly. Prevent reloading of current on x86 and x86-64 by storing the value in a local variable for subsequent dereferences. This is worth a ~7KB/s increase in af_unix bandwidth. Note that we avoid the issues surrounding potentially uninitialized members of the ucred structure by constructing a struct ucred instead of assigning the members individually, which forces the compiler to zero any padding. [ I modified the patch not to use the aggregate assignment since gcc-3.4.x and earlier cannot optimize that properly at all even though gcc-4.0.x and later can -DaveM ] Signed-off-by: Benjamin LaHaise Signed-off-by: David S. Miller --- include/net/scm.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/net/scm.h b/include/net/scm.h index c3fa3d5ab606..540619cb7160 100644 --- a/include/net/scm.h +++ b/include/net/scm.h @@ -37,10 +37,12 @@ static __inline__ void scm_destroy(struct scm_cookie *scm) static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) { - memset(scm, 0, sizeof(*scm)); - scm->creds.uid = current->uid; - scm->creds.gid = current->gid; - scm->creds.pid = current->tgid; + struct task_struct *p = current; + scm->creds.uid = p->uid; + scm->creds.gid = p->gid; + scm->creds.pid = p->tgid; + scm->fp = NULL; + scm->seq = 0; if (msg->msg_controllen <= 0) return 0; return __scm_send(sock, msg, scm); -- cgit v1.2.3 From 0e7b13685f9a06949ea3070c97c0f0085a08cd37 Mon Sep 17 00:00:00 2001 From: John Heffner Date: Mon, 20 Mar 2006 21:32:58 -0800 Subject: [TCP] mtu probing: move tcp-specific data out of inet_connection_sock This moves some TCP-specific MTU probing state out of inet_connection_sock back to tcp_sock. Signed-off-by: John Heffner Signed-off-by: David S. Miller --- include/linux/tcp.h | 6 ++++++ include/net/inet_connection_sock.h | 2 -- net/ipv4/tcp_input.c | 4 ++-- net/ipv4/tcp_output.c | 4 ++-- 4 files changed, 10 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/linux/tcp.h b/include/linux/tcp.h index f2bb2396853f..542d39596bd8 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -343,6 +343,12 @@ struct tcp_sock { __u32 seq; __u32 time; } rcvq_space; + +/* TCP-specific MTU probe information. */ + struct { + __u32 probe_seq_start; + __u32 probe_seq_end; + } mtu_probe; }; static inline struct tcp_sock *tcp_sk(const struct sock *sk) diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index b3abe33f4e5f..4e5a9ff99fc3 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -114,8 +114,6 @@ struct inet_connection_sock { /* Information on the current probe. */ int probe_size; - __u32 probe_seq_start; - __u32 probe_seq_end; } icsk_mtup; u32 icsk_ca_priv[16]; #define ICSK_CA_PRIV_SIZE (16 * sizeof(u32)) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 0ac388e3d01d..195d83584558 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2054,7 +2054,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una, /* MTU probe failure: don't reduce cwnd */ if (icsk->icsk_ca_state < TCP_CA_CWR && icsk->icsk_mtup.probe_size && - tp->snd_una == icsk->icsk_mtup.probe_seq_start) { + tp->snd_una == tp->mtu_probe.probe_seq_start) { tcp_mtup_probe_failed(sk); /* Restores the reduction we did in tcp_mtup_probe() */ tp->snd_cwnd++; @@ -2284,7 +2284,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p) /* MTU probing checks */ if (icsk->icsk_mtup.probe_size) { - if (!after(icsk->icsk_mtup.probe_seq_end, TCP_SKB_CB(skb)->end_seq)) { + if (!after(tp->mtu_probe.probe_seq_end, TCP_SKB_CB(skb)->end_seq)) { tcp_mtup_probe_success(sk, skb); } } diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 8197b5e12f1f..518e568b53f3 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1238,8 +1238,8 @@ static int tcp_mtu_probe(struct sock *sk) update_send_head(sk, tp, nskb); icsk->icsk_mtup.probe_size = tcp_mss_to_mtu(sk, nskb->len); - icsk->icsk_mtup.probe_seq_start = TCP_SKB_CB(nskb)->seq; - icsk->icsk_mtup.probe_seq_end = TCP_SKB_CB(nskb)->end_seq; + tp->mtu_probe.probe_seq_start = TCP_SKB_CB(nskb)->seq; + tp->mtu_probe.probe_seq_end = TCP_SKB_CB(nskb)->end_seq; return 1; } -- cgit v1.2.3 From c4d9390941aee136fd35bb38eb1d6de4e3b1487d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 20 Mar 2006 22:01:03 -0800 Subject: [ICSK]: Introduce inet_csk_ctl_sock_create Consolidating open coded sequences in tcp and dccp, v4 and v6. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/net/inet_connection_sock.h | 4 ++++ net/dccp/ipv4.c | 26 ++------------------------ net/dccp/ipv6.c | 27 +++------------------------ net/ipv4/inet_connection_sock.c | 19 +++++++++++++++++++ net/ipv4/tcp_ipv4.c | 13 +------------ net/ipv6/tcp_ipv6.c | 13 ++----------- 6 files changed, 31 insertions(+), 71 deletions(-) (limited to 'include') diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 4e5a9ff99fc3..363a067403ee 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -321,4 +321,8 @@ extern void inet_csk_listen_stop(struct sock *sk); extern void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr); +extern int inet_csk_ctl_sock_create(struct socket **sock, + unsigned short family, + unsigned short type, + unsigned char protocol); #endif /* _INET_CONNECTION_SOCK_H */ diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index f53bce590ade..7098f1055f4a 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -1099,29 +1099,6 @@ static struct inet_protosw dccp_v4_protosw = { .flags = INET_PROTOSW_ICSK, }; -static char dccp_v4_ctl_socket_err_msg[] __initdata = - KERN_ERR "DCCP: Failed to create the control socket.\n"; - -static int __init dccp_v4_ctl_sock_init(void) -{ - int rc = sock_create_kern(PF_INET, SOCK_DCCP, IPPROTO_DCCP, - &dccp_v4_ctl_socket); - if (rc < 0) - printk(dccp_v4_ctl_socket_err_msg); - else { - dccp_v4_ctl_socket->sk->sk_allocation = GFP_ATOMIC; - inet_sk(dccp_v4_ctl_socket->sk)->uc_ttl = -1; - - /* Unhash it so that IP input processing does not even - * see it, we do not wish this socket to see incoming - * packets. - */ - dccp_v4_ctl_socket->sk->sk_prot->unhash(dccp_v4_ctl_socket->sk); - } - - return rc; -} - static int __init dccp_v4_init(void) { int err = proto_register(&dccp_v4_prot, 1); @@ -1135,7 +1112,8 @@ static int __init dccp_v4_init(void) inet_register_protosw(&dccp_v4_protosw); - err = dccp_v4_ctl_sock_init(); + err = inet_csk_ctl_sock_create(&dccp_v4_ctl_socket, PF_INET, + SOCK_DCCP, IPPROTO_DCCP); if (err) goto out_unregister_protosw; out: diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 3c9f0836404f..6bd9979334a2 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -1229,29 +1229,6 @@ static struct inet_protosw dccp_v6_protosw = { .flags = INET_PROTOSW_ICSK, }; -static char dccp_v6_ctl_socket_err_msg[] __initdata = - KERN_ERR "DCCP: Failed to create the control socket.\n"; - -static int __init dccp_v6_ctl_sock_init(void) -{ - int rc = sock_create_kern(PF_INET6, SOCK_DCCP, IPPROTO_DCCP, - &dccp_v6_ctl_socket); - if (rc < 0) - printk(dccp_v6_ctl_socket_err_msg); - else { - dccp_v6_ctl_socket->sk->sk_allocation = GFP_ATOMIC; - inet_sk(dccp_v6_ctl_socket->sk)->uc_ttl = -1; - - /* Unhash it so that IP input processing does not even - * see it, we do not wish this socket to see incoming - * packets. - */ - dccp_v6_ctl_socket->sk->sk_prot->unhash(dccp_v6_ctl_socket->sk); - } - - return rc; -} - static int __init dccp_v6_init(void) { int err = proto_register(&dccp_v6_prot, 1); @@ -1265,7 +1242,9 @@ static int __init dccp_v6_init(void) inet6_register_protosw(&dccp_v6_protosw); - if (dccp_v6_ctl_sock_init() != 0) + err = inet_csk_ctl_sock_create(&dccp_v6_ctl_socket, PF_INET6, + SOCK_DCCP, IPPROTO_DCCP); + if (err != 0) goto out_unregister_protosw; out: return err; diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index ae20281d8deb..359f48cec99a 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -648,3 +648,22 @@ void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr) } EXPORT_SYMBOL_GPL(inet_csk_addr2sockaddr); + +int inet_csk_ctl_sock_create(struct socket **sock, unsigned short family, + unsigned short type, unsigned char protocol) +{ + int rc = sock_create_kern(family, type, protocol, sock); + + if (rc == 0) { + (*sock)->sk->sk_allocation = GFP_ATOMIC; + inet_sk((*sock)->sk)->uc_ttl = -1; + /* + * Unhash it so that IP input processing does not even see it, + * we do not wish this socket to see incoming packets. + */ + (*sock)->sk->sk_prot->unhash((*sock)->sk); + } + return rc; +} + +EXPORT_SYMBOL_GPL(inet_csk_ctl_sock_create); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 57e7a26e8213..4eb903db1b12 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1828,21 +1828,10 @@ struct proto tcp_prot = { .rsk_prot = &tcp_request_sock_ops, }; - - void __init tcp_v4_init(struct net_proto_family *ops) { - int err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_TCP, &tcp_socket); - if (err < 0) + if (inet_csk_ctl_sock_create(&tcp_socket, PF_INET, SOCK_RAW, IPPROTO_TCP) < 0) panic("Failed to create the TCP control socket.\n"); - tcp_socket->sk->sk_allocation = GFP_ATOMIC; - inet_sk(tcp_socket->sk)->uc_ttl = -1; - - /* Unhash it so that IP input processing does not even - * see it, we do not wish this socket to see incoming - * packets. - */ - tcp_socket->sk->sk_prot->unhash(tcp_socket->sk); } EXPORT_SYMBOL(ipv4_specific); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 14de50380f4e..af6a0c60f903 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1605,21 +1605,12 @@ static struct inet_protosw tcpv6_protosw = { void __init tcpv6_init(void) { - int err; - /* register inet6 protocol */ if (inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP) < 0) printk(KERN_ERR "tcpv6_init: Could not register protocol\n"); inet6_register_protosw(&tcpv6_protosw); - err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_TCP, &tcp6_socket); - if (err < 0) + if (inet_csk_ctl_sock_create(&tcp6_socket, PF_INET6, SOCK_RAW, + IPPROTO_TCP) < 0) panic("Failed to create the TCPv6 control socket.\n"); - tcp6_socket->sk->sk_allocation = GFP_ATOMIC; - - /* Unhash it so that IP input processing does not even - * see it, we do not wish this socket to see incoming - * packets. - */ - tcp6_socket->sk->sk_prot->unhash(tcp6_socket->sk); } -- cgit v1.2.3 From 0ac81ae34ec8898e7eb1388fe21e3cee7b626a88 Mon Sep 17 00:00:00 2001 From: David Basden Date: Mon, 20 Mar 2006 22:21:10 -0800 Subject: [IRDA]: TOIM3232 dongle support Here goes a patch for supporting TOIM3232 based serial IrDA dongles. The code is based on the tekram dongle code. It's been tested with a TOIM3232 based IRWave 320S dongle. It may work for TOIM4232 dongles, although it's not been tested. Signed-off-by: David Basden Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller --- drivers/net/irda/Kconfig | 8 + drivers/net/irda/Makefile | 1 + drivers/net/irda/toim3232-sir.c | 375 ++++++++++++++++++++++++++++++++++++++++ include/linux/irda.h | 1 + 4 files changed, 385 insertions(+) create mode 100644 drivers/net/irda/toim3232-sir.c (limited to 'include') diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig index c81fe1c382d5..5e6d00752990 100644 --- a/drivers/net/irda/Kconfig +++ b/drivers/net/irda/Kconfig @@ -64,6 +64,14 @@ config TEKRAM_DONGLE dongles you will have to start irattach like this: "irattach -d tekram". +config TOIM3232_DONGLE + tristate "TOIM3232 IrDa dongle" + depends on DONGLE && IRDA + help + Say Y here if you want to build support for the Vishay/Temic + TOIM3232 and TOIM4232 based dongles. + To compile it as a module, choose M here. + config LITELINK_DONGLE tristate "Parallax LiteLink dongle" depends on DONGLE && IRDA diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile index 72cbfdc9cfcc..27ab75f20799 100644 --- a/drivers/net/irda/Makefile +++ b/drivers/net/irda/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_OLD_BELKIN_DONGLE) += old_belkin-sir.o obj-$(CONFIG_MCP2120_DONGLE) += mcp2120-sir.o obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o +obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o # The SIR helper module sir-dev-objs := sir_dev.o sir_dongle.o sir_kthread.o diff --git a/drivers/net/irda/toim3232-sir.c b/drivers/net/irda/toim3232-sir.c new file mode 100644 index 000000000000..f6e5fed6a36d --- /dev/null +++ b/drivers/net/irda/toim3232-sir.c @@ -0,0 +1,375 @@ +/********************************************************************* + * + * Filename: toim3232-sir.c + * Version: 1.0 + * Description: Implementation of dongles based on the Vishay/Temic + * TOIM3232 SIR Endec chipset. Currently only the + * IRWave IR320ST-2 is tested, although it should work + * with any TOIM3232 or TOIM4232 chipset based RS232 + * dongle with minimal modification. + * Based heavily on the Tekram driver (tekram.c), + * with thanks to Dag Brattli and Martin Diehl. + * Status: Experimental. + * Author: David Basden + * Created at: Thu Feb 09 23:47:32 2006 + * + * Copyright (c) 2006 David Basden. + * Copyright (c) 1998-1999 Dag Brattli, + * Copyright (c) 2002 Martin Diehl, + * 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. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +/* + * This driver has currently only been tested on the IRWave IR320ST-2 + * + * PROTOCOL: + * + * The protocol for talking to the TOIM3232 is quite easy, and is + * designed to interface with RS232 with only level convertors. The + * BR/~D line on the chip is brought high to signal 'command mode', + * where a command byte is sent to select the baudrate of the RS232 + * interface and the pulse length of the IRDA output. When BR/~D + * is brought low, the dongle then changes to the selected baudrate, + * and the RS232 interface is used for data until BR/~D is brought + * high again. The initial speed for the TOIMx323 after RESET is + * 9600 baud. The baudrate for command-mode is the last selected + * baud-rate, or 9600 after a RESET. + * + * The dongle I have (below) adds some extra hardware on the front end, + * but this is mostly directed towards pariasitic power from the RS232 + * line rather than changing very much about how to communicate with + * the TOIM3232. + * + * The protocol to talk to the TOIM4232 chipset seems to be almost + * identical to the TOIM3232 (and the 4232 datasheet is more detailed) + * so this code will probably work on that as well, although I haven't + * tested it on that hardware. + * + * Target dongle variations that might be common: + * + * DTR and RTS function: + * The data sheet for the 4232 has a sample implementation that hooks the + * DTR and RTS lines to the RESET and BaudRate/~Data lines of the + * chip (through line-converters). Given both DTR and RTS would have to + * be held low in normal operation, and the TOIMx232 requires +5V to + * signal ground, most dongle designers would almost certainly choose + * an implementation that kept at least one of DTR or RTS high in + * normal operation to provide power to the dongle, but will likely + * vary between designs. + * + * User specified command bits: + * There are two user-controllable output lines from the TOIMx232 that + * can be set low or high by setting the appropriate bits in the + * high-nibble of the command byte (when setting speed and pulse length). + * These might be used to switch on and off added hardware or extra + * dongle features. + * + * + * Target hardware: IRWave IR320ST-2 + * + * The IRWave IR320ST-2 is a simple dongle based on the Vishay/Temic + * TOIM3232 SIR Endec and the Vishay/Temic TFDS4500 SIR IRDA transciever. + * It uses a hex inverter and some discrete components to buffer and + * line convert the RS232 down to 5V. + * + * The dongle is powered through a voltage regulator, fed by a large + * capacitor. To switch the dongle on, DTR is brought high to charge + * the capacitor and drive the voltage regulator. DTR isn't associated + * with any control lines on the TOIM3232. Parisitic power is also taken + * from the RTS, TD and RD lines when brought high, but through resistors. + * When DTR is low, the circuit might lose power even with RTS high. + * + * RTS is inverted and attached to the BR/~D input pin. When RTS + * is high, BR/~D is low, and the TOIM3232 is in the normal 'data' mode. + * RTS is brought low, BR/~D is high, and the TOIM3232 is in 'command + * mode'. + * + * For some unknown reason, the RESET line isn't actually connected + * to anything. This means to reset the dongle to get it to a known + * state (9600 baud) you must drop DTR and RTS low, wait for the power + * capacitor to discharge, and then bring DTR (and RTS for data mode) + * high again, and wait for the capacitor to charge, the power supply + * to stabilise, and the oscillator clock to stabilise. + * + * Fortunately, if the current baudrate is known, the chipset can + * easily change speed by entering command mode without having to + * reset the dongle first. + * + * Major Components: + * + * - Vishay/Temic TOIM3232 SIR Endec to change RS232 pulse timings + * to IRDA pulse timings + * - 3.6864MHz crystal to drive TOIM3232 clock oscillator + * - DM74lS04M Inverting Hex line buffer for RS232 input buffering + * and level conversion + * - PJ2951AC 150mA voltage regulator + * - Vishay/Temic TFDS4500 SIR IRDA front-end transceiver + * + */ + +#include +#include +#include + +#include + +#include "sir-dev.h" + +MODULE_PARM(toim3232delay, "i"); +MODULE_PARM_DESC(toim3232delay, "toim3232 dongle write complete delay"); +static int toim3232delay = 150; /* default is 150 ms */ + +#if 0 +MODULE_PARM(toim3232flipdtr, "i"); +MODULE_PARM_DESC(toim3232flipdtr, "toim3232 dongle invert DTR (Reset)"); +static int toim3232flipdtr = 0; /* default is DTR high to reset */ + +MODULE_PARM(toim3232fliptrs, "i"); +MODULE_PARM_DESC(toim3232fliprts, "toim3232 dongle invert RTS (BR/D)"); +static int toim3232fliprts = 0; /* default is RTS high for baud change */ +#endif + +static int toim3232_open(struct sir_dev *); +static int toim3232_close(struct sir_dev *); +static int toim3232_change_speed(struct sir_dev *, unsigned); +static int toim3232_reset(struct sir_dev *); + +#define TOIM3232_115200 0x00 +#define TOIM3232_57600 0x01 +#define TOIM3232_38400 0x02 +#define TOIM3232_19200 0x03 +#define TOIM3232_9600 0x06 +#define TOIM3232_2400 0x0A + +#define TOIM3232_PW 0x10 /* Pulse select bit */ + +static struct dongle_driver toim3232 = { + .owner = THIS_MODULE, + .driver_name = "Vishay TOIM3232", + .type = IRDA_TOIM3232_DONGLE, + .open = toim3232_open, + .close = toim3232_close, + .reset = toim3232_reset, + .set_speed = toim3232_change_speed, +}; + +static int __init toim3232_sir_init(void) +{ + if (toim3232delay < 1 || toim3232delay > 500) + toim3232delay = 200; + IRDA_DEBUG(1, "%s - using %d ms delay\n", + toim3232.driver_name, toim3232delay); + return irda_register_dongle(&toim3232); +} + +static void __exit toim3232_sir_cleanup(void) +{ + irda_unregister_dongle(&toim3232); +} + +static int toim3232_open(struct sir_dev *dev) +{ + struct qos_info *qos = &dev->qos; + + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); + + /* Pull the lines high to start with. + * + * For the IR320ST-2, we need to charge the main supply capacitor to + * switch the device on. We keep DTR high throughout to do this. + * When RTS, TD and RD are high, they will also trickle-charge the + * cap. RTS is high for data transmission, and low for baud rate select. + * -- DGB + */ + sirdev_set_dtr_rts(dev, TRUE, TRUE); + + /* The TOI3232 supports many speeds between 1200bps and 115000bps. + * We really only care about those supported by the IRDA spec, but + * 38400 seems to be implemented in many places */ + qos->baud_rate.bits &= IR_2400|IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; + + /* From the tekram driver. Not sure what a reasonable value is -- DGB */ + qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */ + irda_qos_bits_to_value(qos); + + /* irda thread waits 50 msec for power settling */ + + return 0; +} + +static int toim3232_close(struct sir_dev *dev) +{ + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); + + /* Power off dongle */ + sirdev_set_dtr_rts(dev, FALSE, FALSE); + + return 0; +} + +/* + * Function toim3232change_speed (dev, state, speed) + * + * Set the speed for the TOIM3232 based dongle. Warning, this + * function must be called with a process context! + * + * Algorithm + * 1. keep DTR high but clear RTS to bring into baud programming mode + * 2. wait at least 7us to enter programming mode + * 3. send control word to set baud rate and timing + * 4. wait at least 1us + * 5. bring RTS high to enter DATA mode (RS232 is passed through to transceiver) + * 6. should take effect immediately (although probably worth waiting) + */ + +#define TOIM3232_STATE_WAIT_SPEED (SIRDEV_STATE_DONGLE_SPEED + 1) + +static int toim3232_change_speed(struct sir_dev *dev, unsigned speed) +{ + unsigned state = dev->fsm.substate; + unsigned delay = 0; + u8 byte; + static int ret = 0; + + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); + + switch(state) { + case SIRDEV_STATE_DONGLE_SPEED: + + /* Figure out what we are going to send as a control byte */ + switch (speed) { + case 2400: + byte = TOIM3232_PW|TOIM3232_2400; + break; + default: + speed = 9600; + ret = -EINVAL; + /* fall thru */ + case 9600: + byte = TOIM3232_PW|TOIM3232_9600; + break; + case 19200: + byte = TOIM3232_PW|TOIM3232_19200; + break; + case 38400: + byte = TOIM3232_PW|TOIM3232_38400; + break; + case 57600: + byte = TOIM3232_PW|TOIM3232_57600; + break; + case 115200: + byte = TOIM3232_115200; + break; + } + + /* Set DTR, Clear RTS: Go into baud programming mode */ + sirdev_set_dtr_rts(dev, TRUE, FALSE); + + /* Wait at least 7us */ + udelay(14); + + /* Write control byte */ + sirdev_raw_write(dev, &byte, 1); + + dev->speed = speed; + + state = TOIM3232_STATE_WAIT_SPEED; + delay = toim3232delay; + break; + + case TOIM3232_STATE_WAIT_SPEED: + /* Have transmitted control byte * Wait for 'at least 1us' */ + udelay(14); + + /* Set DTR, Set RTS: Go into normal data mode */ + sirdev_set_dtr_rts(dev, TRUE, TRUE); + + /* Wait (TODO: check this is needed) */ + udelay(50); + break; + + default: + printk(KERN_ERR "%s - undefined state %d\n", __FUNCTION__, state); + ret = -EINVAL; + break; + } + + dev->fsm.substate = state; + return (delay > 0) ? delay : ret; +} + +/* + * Function toim3232reset (driver) + * + * This function resets the toim3232 dongle. Warning, this function + * must be called with a process context!! + * + * What we should do is: + * 0. Pull RESET high + * 1. Wait for at least 7us + * 2. Pull RESET low + * 3. Wait for at least 7us + * 4. Pull BR/~D high + * 5. Wait for at least 7us + * 6. Send control byte to set baud rate + * 7. Wait at least 1us after stop bit + * 8. Pull BR/~D low + * 9. Should then be in data mode + * + * Because the IR320ST-2 doesn't have the RESET line connected for some reason, + * we'll have to do something else. + * + * The default speed after a RESET is 9600, so lets try just bringing it up in + * data mode after switching it off, waiting for the supply capacitor to + * discharge, and then switch it back on. This isn't actually pulling RESET + * high, but it seems to have the same effect. + * + * This behaviour will probably work on dongles that have the RESET line connected, + * but if not, add a flag for the IR320ST-2, and implment the above-listed proper + * behaviour. + * + * RTS is inverted and then fed to BR/~D, so to put it in programming mode, we + * need to have pull RTS low + */ + +static int toim3232_reset(struct sir_dev *dev) +{ + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); + + /* Switch off both DTR and RTS to switch off dongle */ + sirdev_set_dtr_rts(dev, FALSE, FALSE); + + /* Should sleep a while. This might be evil doing it this way.*/ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(msecs_to_jiffies(50)); + + /* Set DTR, Set RTS (data mode) */ + sirdev_set_dtr_rts(dev, TRUE, TRUE); + + /* Wait at least 10 ms for power to stabilize again */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(msecs_to_jiffies(10)); + + /* Speed should now be 9600 */ + dev->speed = 9600; + + return 0; +} + +MODULE_AUTHOR("David Basden "); +MODULE_DESCRIPTION("Vishay/Temic TOIM3232 based dongle driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("irda-dongle-12"); /* IRDA_TOIM3232_DONGLE */ + +module_init(toim3232_sir_init); +module_exit(toim3232_sir_cleanup); diff --git a/include/linux/irda.h b/include/linux/irda.h index 95dee174cdc5..09d8f105a5a8 100644 --- a/include/linux/irda.h +++ b/include/linux/irda.h @@ -76,6 +76,7 @@ typedef enum { IRDA_MCP2120_DONGLE = 9, IRDA_ACT200L_DONGLE = 10, IRDA_MA600_DONGLE = 11, + IRDA_TOIM3232_DONGLE = 12, } IRDA_DONGLE; /* Protocol types to be used for SOCK_DGRAM */ -- cgit v1.2.3 From 6756ae4b4e97aba48c042b4aa6b77a18f507d2cb Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 20 Mar 2006 22:23:58 -0800 Subject: [NET]: Convert RTNL to mutex. This patch turns the RTNL from a semaphore to a new 2.6.16 mutex and gets rid of some of the leftover legacy. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/8139too.c | 2 +- include/linux/rtnetlink.h | 20 +++++++------------- net/core/dev.c | 8 ++++---- net/core/link_watch.c | 4 ++-- net/core/netpoll.c | 6 +++--- net/core/rtnetlink.c | 28 +++++++++++++++++----------- net/ipv4/igmp.c | 24 ++++++++++++------------ net/ipv4/ipconfig.c | 10 +++++----- 8 files changed, 51 insertions(+), 51 deletions(-) (limited to 'include') diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index e58d4c50c2e1..f5ee064ab6b2 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -1605,7 +1605,7 @@ static void rtl8139_thread (void *_data) if (tp->watchdog_fired) { tp->watchdog_fired = 0; rtl8139_tx_timeout_task(_data); - } else if (rtnl_shlock_nowait() == 0) { + } else if (rtnl_trylock()) { rtl8139_thread_iter (dev, tp, tp->mmio_addr); rtnl_unlock (); } else { diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index edccefb45188..d263853a8f1c 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -907,6 +907,7 @@ struct tcamsg #ifdef __KERNEL__ #include +#include extern size_t rtattr_strlcpy(char *dest, const struct rtattr *rta, size_t size); static __inline__ int rtattr_strcmp(const struct rtattr *rta, const char *str) @@ -1038,24 +1039,17 @@ __rta_reserve(struct sk_buff *skb, int attrtype, int attrlen) extern void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change); -extern struct semaphore rtnl_sem; - -#define rtnl_shlock() down(&rtnl_sem) -#define rtnl_shlock_nowait() down_trylock(&rtnl_sem) - -#define rtnl_shunlock() do { up(&rtnl_sem); \ - if (rtnl && rtnl->sk_receive_queue.qlen) \ - rtnl->sk_data_ready(rtnl, 0); \ - } while(0) - +/* RTNL is used as a global lock for all changes to network configuration */ extern void rtnl_lock(void); -extern int rtnl_lock_interruptible(void); extern void rtnl_unlock(void); +extern int rtnl_trylock(void); + extern void rtnetlink_init(void); +extern void __rtnl_unlock(void); #define ASSERT_RTNL() do { \ - if (unlikely(down_trylock(&rtnl_sem) == 0)) { \ - up(&rtnl_sem); \ + if (unlikely(rtnl_trylock())) { \ + rtnl_unlock(); \ printk(KERN_ERR "RTNL: assertion failed at %s (%d)\n", \ __FILE__, __LINE__); \ dump_stack(); \ diff --git a/net/core/dev.c b/net/core/dev.c index 8763c99fcb84..be1d896cc5b9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2466,9 +2466,9 @@ int dev_ioctl(unsigned int cmd, void __user *arg) */ if (cmd == SIOCGIFCONF) { - rtnl_shlock(); + rtnl_lock(); ret = dev_ifconf((char __user *) arg); - rtnl_shunlock(); + rtnl_unlock(); return ret; } if (cmd == SIOCGIFNAME) @@ -2877,7 +2877,7 @@ static void netdev_wait_allrefs(struct net_device *dev) rebroadcast_time = warning_time = jiffies; while (atomic_read(&dev->refcnt) != 0) { if (time_after(jiffies, rebroadcast_time + 1 * HZ)) { - rtnl_shlock(); + rtnl_lock(); /* Rebroadcast unregister notification */ notifier_call_chain(&netdev_chain, @@ -2894,7 +2894,7 @@ static void netdev_wait_allrefs(struct net_device *dev) linkwatch_run_queue(); } - rtnl_shunlock(); + __rtnl_unlock(); rebroadcast_time = jiffies; } diff --git a/net/core/link_watch.c b/net/core/link_watch.c index e82a451d330b..341de44c7ed1 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -139,9 +139,9 @@ static void linkwatch_event(void *dummy) linkwatch_nextevent = jiffies + HZ; clear_bit(LW_RUNNING, &linkwatch_flags); - rtnl_shlock(); + rtnl_lock(); linkwatch_run_queue(); - rtnl_shunlock(); + rtnl_unlock(); } diff --git a/net/core/netpoll.c b/net/core/netpoll.c index ea51f8d02eb8..e8e05cebd95a 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -669,14 +669,14 @@ int netpoll_setup(struct netpoll *np) printk(KERN_INFO "%s: device %s not up yet, forcing it\n", np->name, np->dev_name); - rtnl_shlock(); + rtnl_lock(); if (dev_change_flags(ndev, ndev->flags | IFF_UP) < 0) { printk(KERN_ERR "%s: failed to open %s\n", np->name, np->dev_name); - rtnl_shunlock(); + rtnl_unlock(); goto release; } - rtnl_shunlock(); + rtnl_unlock(); atleast = jiffies + HZ/10; atmost = jiffies + 4*HZ; diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 1c15a907066f..ae10d3740faa 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -51,25 +52,31 @@ #include #include -DECLARE_MUTEX(rtnl_sem); +static DEFINE_MUTEX(rtnl_mutex); void rtnl_lock(void) { - rtnl_shlock(); + mutex_lock(&rtnl_mutex); } -int rtnl_lock_interruptible(void) +void __rtnl_unlock(void) { - return down_interruptible(&rtnl_sem); + mutex_unlock(&rtnl_mutex); } - + void rtnl_unlock(void) { - rtnl_shunlock(); - + mutex_unlock(&rtnl_mutex); + if (rtnl && rtnl->sk_receive_queue.qlen) + rtnl->sk_data_ready(rtnl, 0); netdev_run_todo(); } +int rtnl_trylock(void) +{ + return mutex_trylock(&rtnl_mutex); +} + int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len) { memset(tb, 0, sizeof(struct rtattr*)*maxattr); @@ -625,9 +632,9 @@ static void rtnetlink_rcv(struct sock *sk, int len) unsigned int qlen = 0; do { - rtnl_lock(); + mutex_lock(&rtnl_mutex); netlink_run_queue(sk, &qlen, &rtnetlink_rcv_msg); - up(&rtnl_sem); + mutex_unlock(&rtnl_mutex); netdev_run_todo(); } while (qlen); @@ -704,6 +711,5 @@ EXPORT_SYMBOL(rtnetlink_links); EXPORT_SYMBOL(rtnetlink_put_metrics); EXPORT_SYMBOL(rtnl); EXPORT_SYMBOL(rtnl_lock); -EXPORT_SYMBOL(rtnl_lock_interruptible); -EXPORT_SYMBOL(rtnl_sem); +EXPORT_SYMBOL(rtnl_trylock); EXPORT_SYMBOL(rtnl_unlock); diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 64ce52bf0485..3ec502f19da0 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1730,7 +1730,7 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr) if (!MULTICAST(addr)) return -EINVAL; - rtnl_shlock(); + rtnl_lock(); in_dev = ip_mc_find_dev(imr); @@ -1763,7 +1763,7 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr) ip_mc_inc_group(in_dev, addr); err = 0; done: - rtnl_shunlock(); + rtnl_unlock(); return err; } @@ -1837,7 +1837,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct if (!MULTICAST(addr)) return -EINVAL; - rtnl_shlock(); + rtnl_lock(); imr.imr_multiaddr.s_addr = mreqs->imr_multiaddr; imr.imr_address.s_addr = mreqs->imr_interface; @@ -1947,7 +1947,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 1, &mreqs->imr_sourceaddr, 1); done: - rtnl_shunlock(); + rtnl_unlock(); if (leavegroup) return ip_mc_leave_group(sk, &imr); return err; @@ -1970,7 +1970,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex) msf->imsf_fmode != MCAST_EXCLUDE) return -EINVAL; - rtnl_shlock(); + rtnl_lock(); imr.imr_multiaddr.s_addr = msf->imsf_multiaddr; imr.imr_address.s_addr = msf->imsf_interface; @@ -2030,7 +2030,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex) pmc->sfmode = msf->imsf_fmode; err = 0; done: - rtnl_shunlock(); + rtnl_unlock(); if (leavegroup) err = ip_mc_leave_group(sk, &imr); return err; @@ -2050,7 +2050,7 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf, if (!MULTICAST(addr)) return -EINVAL; - rtnl_shlock(); + rtnl_lock(); imr.imr_multiaddr.s_addr = msf->imsf_multiaddr; imr.imr_address.s_addr = msf->imsf_interface; @@ -2072,7 +2072,7 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf, goto done; msf->imsf_fmode = pmc->sfmode; psl = pmc->sflist; - rtnl_shunlock(); + rtnl_unlock(); if (!psl) { len = 0; count = 0; @@ -2091,7 +2091,7 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf, return -EFAULT; return 0; done: - rtnl_shunlock(); + rtnl_unlock(); return err; } @@ -2112,7 +2112,7 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf, if (!MULTICAST(addr)) return -EINVAL; - rtnl_shlock(); + rtnl_lock(); err = -EADDRNOTAVAIL; @@ -2125,7 +2125,7 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf, goto done; gsf->gf_fmode = pmc->sfmode; psl = pmc->sflist; - rtnl_shunlock(); + rtnl_unlock(); count = psl ? psl->sl_count : 0; copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc; gsf->gf_numsrc = count; @@ -2146,7 +2146,7 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf, } return 0; done: - rtnl_shunlock(); + rtnl_unlock(); return err; } diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index bb3613ec448c..cb8a92f18ef6 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -186,7 +186,7 @@ static int __init ic_open_devs(void) unsigned short oflags; last = &ic_first_dev; - rtnl_shlock(); + rtnl_lock(); /* bring loopback device up first */ if (dev_change_flags(&loopback_dev, loopback_dev.flags | IFF_UP) < 0) @@ -215,7 +215,7 @@ static int __init ic_open_devs(void) continue; } if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) { - rtnl_shunlock(); + rtnl_unlock(); return -1; } d->dev = dev; @@ -232,7 +232,7 @@ static int __init ic_open_devs(void) dev->name, able, d->xid)); } } - rtnl_shunlock(); + rtnl_unlock(); *last = NULL; @@ -251,7 +251,7 @@ static void __init ic_close_devs(void) struct ic_device *d, *next; struct net_device *dev; - rtnl_shlock(); + rtnl_lock(); next = ic_first_dev; while ((d = next)) { next = d->next; @@ -262,7 +262,7 @@ static void __init ic_close_devs(void) } kfree(d); } - rtnl_shunlock(); + rtnl_unlock(); } /* -- cgit v1.2.3 From c5ecd62c25400a3c6856e009f84257d5bd03f03b Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 20 Mar 2006 22:25:41 -0800 Subject: [NET]: Move destructor from neigh->ops to neigh_params struct neigh_ops currently has a destructor field, which no in-kernel drivers outside of infiniband use. The infiniband/ulp/ipoib in-tree driver stashes some info in the neighbour structure (the results of the second-stage lookup from ARP results to real link-level path), and it uses neigh->ops->destructor to get a callback so it can clean up this extra info when a neighbour is freed. We've run into problems with this: since the destructor is in an ops field that is shared between neighbours that may belong to different net devices, there's no way to set/clear it safely. The following patch moves this field to neigh_parms where it can be safely set, together with its twin neigh_setup. Two additional patches in the patch series update ipoib to use this new interface. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier Signed-off-by: David S. Miller --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 16 +--------------- include/net/neighbour.h | 2 +- net/core/neighbour.c | 4 ++-- 3 files changed, 4 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index c3b5f79d1168..9d9cecd4753b 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -247,7 +247,6 @@ static void path_free(struct net_device *dev, struct ipoib_path *path) if (neigh->ah) ipoib_put_ah(neigh->ah); *to_ipoib_neigh(neigh->neighbour) = NULL; - neigh->neighbour->ops->destructor = NULL; kfree(neigh); } @@ -530,7 +529,6 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) err: *to_ipoib_neigh(skb->dst->neighbour) = NULL; list_del(&neigh->list); - neigh->neighbour->ops->destructor = NULL; kfree(neigh); ++priv->stats.tx_dropped; @@ -769,21 +767,9 @@ static void ipoib_neigh_destructor(struct neighbour *n) ipoib_put_ah(ah); } -static int ipoib_neigh_setup(struct neighbour *neigh) -{ - /* - * Is this kosher? I can't find anybody in the kernel that - * sets neigh->destructor, so we should be able to set it here - * without trouble. - */ - neigh->ops->destructor = ipoib_neigh_destructor; - - return 0; -} - static int ipoib_neigh_setup_dev(struct net_device *dev, struct neigh_parms *parms) { - parms->neigh_setup = ipoib_neigh_setup; + parms->neigh_destructor = ipoib_neigh_destructor; return 0; } diff --git a/include/net/neighbour.h b/include/net/neighbour.h index 6fa9ae190741..b0666d66293f 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h @@ -68,6 +68,7 @@ struct neigh_parms struct net_device *dev; struct neigh_parms *next; int (*neigh_setup)(struct neighbour *); + void (*neigh_destructor)(struct neighbour *); struct neigh_table *tbl; void *sysctl_table; @@ -145,7 +146,6 @@ struct neighbour struct neigh_ops { int family; - void (*destructor)(struct neighbour *); void (*solicit)(struct neighbour *, struct sk_buff*); void (*error_report)(struct neighbour *, struct sk_buff*); int (*output)(struct sk_buff*); diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 6ba1cdea18e8..0c8666872d10 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -586,8 +586,8 @@ void neigh_destroy(struct neighbour *neigh) kfree(hh); } - if (neigh->ops && neigh->ops->destructor) - (neigh->ops->destructor)(neigh); + if (neigh->parms->neigh_destructor) + (neigh->parms->neigh_destructor)(neigh); skb_queue_purge(&neigh->arp_queue); -- cgit v1.2.3 From 99cae7fca1311573f2777b8ceaa8a5abd6e9b04e Mon Sep 17 00:00:00 2001 From: Alpt Date: Mon, 20 Mar 2006 22:26:17 -0800 Subject: [NET] rtnetlink: Add RTPROT entry for Netsukuku. The Netsukuku daemon is using the same number to mark its routes, you can see it here: http://hinezumilabs.org/cgi-bin/viewcvs.cgi/netsukuku/src/krnl_route.h?rev=HEAD&content-type=text/vnd.viewcvs-markup Signed-off-by: David S. Miller --- include/linux/rtnetlink.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index d263853a8f1c..d572d5376319 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -199,6 +199,7 @@ enum #define RTPROT_BIRD 12 /* BIRD */ #define RTPROT_DNROUTED 13 /* DECnet routing daemon */ #define RTPROT_XORP 14 /* XORP */ +#define RTPROT_NTK 15 /* Netsukuku */ /* rtm_scope -- cgit v1.2.3 From d9ab5ad12b0d865bdb1b750d81192d34465541e9 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 22:27:35 -0800 Subject: [TG3]: Add 5787 and 5754 basic support Add basic support for 2 new chips 5787 and 5754. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 27 +++++++++++++++++++++++++-- drivers/net/tg3.h | 6 +++++- include/linux/pci_ids.h | 4 ++++ 3 files changed, 34 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index d4f5b58e1dd4..e6ed940d7714 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -221,6 +221,14 @@ static struct pci_device_id tg3_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S, @@ -4388,6 +4396,10 @@ static int tg3_chip_reset(struct tg3 *tp) tp->nvram_lock_cnt = 0; } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + tw32(GRC_FASTBOOT_PC, 0); + /* * We must avoid the readl() that normally takes place. * It locks machines, causes machine checks, and other @@ -6018,6 +6030,10 @@ static int tg3_reset_hw(struct tg3 *tp) } } + /* Enable host coalescing bug fix */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + val |= (1 << 29); + tw32_f(WDMAC_MODE, val); udelay(40); @@ -8326,6 +8342,9 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, if (!err) tg3_nvram_unlock(tp); + if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) + tg3_phy_reset(tp); + if (tg3_test_registers(tp) != 0) { etest->flags |= ETH_TEST_FL_FAILED; data[2] = 1; @@ -9681,6 +9700,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) tp->tg3_flags2 |= TG3_FLG2_5750_PLUS; @@ -9693,7 +9713,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE; if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0) @@ -9903,7 +9924,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG; - if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) + if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787)) tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG; tp->coalesce_mode = 0; @@ -10628,6 +10650,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) case PHY_ID_BCM5752: return "5752"; case PHY_ID_BCM5714: return "5714"; case PHY_ID_BCM5780: return "5780"; + case PHY_ID_BCM5787: return "5787"; case PHY_ID_BCM8002: return "8002/serdes"; case 0: return "serdes"; default: return "unknown"; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 7e3b613afb29..8d32fbe0d303 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -138,6 +138,7 @@ #define ASIC_REV_5752 0x06 #define ASIC_REV_5780 0x08 #define ASIC_REV_5714 0x09 +#define ASIC_REV_5787 0x0b #define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8) #define CHIPREV_5700_AX 0x70 #define CHIPREV_5700_BX 0x71 @@ -1393,6 +1394,7 @@ #define GRC_MDI_CTRL 0x00006844 #define GRC_SEEPROM_DELAY 0x00006848 /* 0x684c --> 0x6c00 unused */ +#define GRC_FASTBOOT_PC 0x00006894 /* 5752, 5755, 5787 */ /* 0x6c00 --> 0x7000 unused */ @@ -2247,6 +2249,7 @@ struct tg3 { #define PHY_ID_BCM5752 0x60008100 #define PHY_ID_BCM5714 0x60008340 #define PHY_ID_BCM5780 0x60008350 +#define PHY_ID_BCM5787 0xbc050ce0 #define PHY_ID_BCM8002 0x60010140 #define PHY_ID_INVALID 0xffffffff #define PHY_ID_REV_MASK 0x0000000f @@ -2271,7 +2274,8 @@ struct tg3 { (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \ (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \ (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5714 || \ - (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM8002) + (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM5787 || \ + (X) == PHY_ID_BCM8002) struct tg3_hw_stats *hw_stats; dma_addr_t stats_mapping; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index a3a09cceb026..b9810ddf435a 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1861,14 +1861,18 @@ #define PCI_DEVICE_ID_TIGON3_5780 0x166a #define PCI_DEVICE_ID_TIGON3_5780S 0x166b #define PCI_DEVICE_ID_TIGON3_5705F 0x166e +#define PCI_DEVICE_ID_TIGON3_5754M 0x1672 #define PCI_DEVICE_ID_TIGON3_5750 0x1676 #define PCI_DEVICE_ID_TIGON3_5751 0x1677 #define PCI_DEVICE_ID_TIGON3_5715 0x1678 #define PCI_DEVICE_ID_TIGON3_5715S 0x1679 +#define PCI_DEVICE_ID_TIGON3_5754 0x167a #define PCI_DEVICE_ID_TIGON3_5750M 0x167c #define PCI_DEVICE_ID_TIGON3_5751M 0x167d #define PCI_DEVICE_ID_TIGON3_5751F 0x167e +#define PCI_DEVICE_ID_TIGON3_5787M 0x1693 #define PCI_DEVICE_ID_TIGON3_5782 0x1696 +#define PCI_DEVICE_ID_TIGON3_5787 0x169b #define PCI_DEVICE_ID_TIGON3_5788 0x169c #define PCI_DEVICE_ID_TIGON3_5789 0x169d #define PCI_DEVICE_ID_TIGON3_5702X 0x16a6 -- cgit v1.2.3 From 153330618691694af64f39fb56c9de051862380e Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 20 Mar 2006 22:32:28 -0800 Subject: [NET]: dev_put/dev_hold cleanup Get rid of the old __dev_put macro that is just a hold over from pre 2.6 kernel. And turn dev_hold into an inline instead of a macro. Signed-off-by: Stephen Hemminger Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 2 +- include/linux/netdevice.h | 6 ++++-- net/ipv4/igmp.c | 2 +- net/ipv4/ipmr.c | 4 ++-- net/sched/sch_generic.c | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index f39de16e6b97..49cd096a3c3d 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -920,7 +920,7 @@ e1000_remove(struct pci_dev *pdev) unregister_netdev(netdev); #ifdef CONFIG_E1000_NAPI for (i = 0; i < adapter->num_rx_queues; i++) - __dev_put(&adapter->polling_netdev[i]); + dev_put(&adapter->polling_netdev[i]); #endif if (!e1000_check_phy_reset_block(&adapter->hw)) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index b825be201bce..950dc55e5192 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -712,8 +712,10 @@ static inline void dev_put(struct net_device *dev) atomic_dec(&dev->refcnt); } -#define __dev_put(dev) atomic_dec(&(dev)->refcnt) -#define dev_hold(dev) atomic_inc(&(dev)->refcnt) +static inline void dev_hold(struct net_device *dev) +{ + atomic_inc(&dev->refcnt); +} /* Carrier loss detection, dial on demand. The functions netif_carrier_on * and _off may be called from IRQ context, but it is caller diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 3ec502f19da0..d512239a1473 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1382,7 +1382,7 @@ static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr) dev = ip_dev_find(imr->imr_address.s_addr); if (!dev) return NULL; - __dev_put(dev); + dev_put(dev); } if (!dev && !ip_route_output_key(&rt, &fl)) { diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 5c94c222e3f3..717ab7d6d7b6 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -415,10 +415,10 @@ static int vif_add(struct vifctl *vifc, int mrtsock) return -ENOBUFS; break; case 0: - dev=ip_dev_find(vifc->vifc_lcl_addr.s_addr); + dev = ip_dev_find(vifc->vifc_lcl_addr.s_addr); if (!dev) return -EADDRNOTAVAIL; - __dev_put(dev); + dev_put(dev); break; default: return -EINVAL; diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 99ceb91f0150..31eb83717c26 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -234,7 +234,7 @@ static void dev_watchdog_down(struct net_device *dev) { spin_lock_bh(&dev->xmit_lock); if (del_timer(&dev->watchdog_timer)) - __dev_put(dev); + dev_put(dev); spin_unlock_bh(&dev->xmit_lock); } -- cgit v1.2.3 From 4a3e2f711a00a1feb72ae12fdc749da10179d185 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Mon, 20 Mar 2006 22:33:17 -0800 Subject: [NET] sem2mutex: net/ Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- include/net/xfrm.h | 3 ++- net/atm/ioctl.c | 15 ++++++++------- net/bluetooth/rfcomm/core.c | 8 +++++--- net/core/dev.c | 7 ++++--- net/core/flow.c | 7 ++++--- net/ipv4/ipcomp.c | 17 +++++++++-------- net/ipv4/netfilter/ip_queue.c | 11 ++++++----- net/ipv4/xfrm4_tunnel.c | 11 ++++++----- net/ipv6/ipcomp6.c | 15 ++++++++------- net/ipv6/netfilter/ip6_queue.c | 11 ++++++----- net/ipv6/xfrm6_tunnel.c | 11 ++++++----- net/key/af_key.c | 4 ++-- net/netfilter/nf_sockopt.c | 25 +++++++++++++------------ net/socket.c | 31 ++++++++++++++++--------------- net/sunrpc/cache.c | 17 +++++++++-------- net/sunrpc/sched.c | 11 ++++++----- net/unix/garbage.c | 7 ++++--- net/xfrm/xfrm_policy.c | 4 ++-- net/xfrm/xfrm_user.c | 4 ++-- 19 files changed, 118 insertions(+), 101 deletions(-) (limited to 'include') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 156f52ef8a91..786371365f2b 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -24,7 +25,7 @@ extern struct sock *xfrm_nl; extern u32 sysctl_xfrm_aevent_etime; extern u32 sysctl_xfrm_aevent_rseqth; -extern struct semaphore xfrm_cfg_sem; +extern struct mutex xfrm_cfg_mutex; /* Organization of SPD aka "XFRM rules" ------------------------------------ diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c index eb109af7eb4a..851cfa6312af 100644 --- a/net/atm/ioctl.c +++ b/net/atm/ioctl.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "resources.h" @@ -25,22 +26,22 @@ #include "common.h" -static DECLARE_MUTEX(ioctl_mutex); +static DEFINE_MUTEX(ioctl_mutex); static LIST_HEAD(ioctl_list); void register_atm_ioctl(struct atm_ioctl *ioctl) { - down(&ioctl_mutex); + mutex_lock(&ioctl_mutex); list_add_tail(&ioctl->list, &ioctl_list); - up(&ioctl_mutex); + mutex_unlock(&ioctl_mutex); } void deregister_atm_ioctl(struct atm_ioctl *ioctl) { - down(&ioctl_mutex); + mutex_lock(&ioctl_mutex); list_del(&ioctl->list); - up(&ioctl_mutex); + mutex_unlock(&ioctl_mutex); } EXPORT_SYMBOL(register_atm_ioctl); @@ -137,7 +138,7 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) error = -ENOIOCTLCMD; - down(&ioctl_mutex); + mutex_lock(&ioctl_mutex); list_for_each(pos, &ioctl_list) { struct atm_ioctl * ic = list_entry(pos, struct atm_ioctl, list); if (try_module_get(ic->owner)) { @@ -147,7 +148,7 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) break; } } - up(&ioctl_mutex); + mutex_unlock(&ioctl_mutex); if (error != -ENOIOCTLCMD) goto done; diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 5b4253c61f62..e99010ce8bb2 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -37,6 +37,8 @@ #include #include #include +#include + #include #include #include @@ -57,9 +59,9 @@ static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU; static struct task_struct *rfcomm_thread; -static DECLARE_MUTEX(rfcomm_sem); -#define rfcomm_lock() down(&rfcomm_sem); -#define rfcomm_unlock() up(&rfcomm_sem); +static DEFINE_MUTEX(rfcomm_mutex); +#define rfcomm_lock() mutex_lock(&rfcomm_mutex) +#define rfcomm_unlock() mutex_unlock(&rfcomm_mutex) static unsigned long rfcomm_event; diff --git a/net/core/dev.c b/net/core/dev.c index ee044097f7f2..08dec6eb922b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -81,6 +81,7 @@ #include #include #include +#include #include #include #include @@ -2931,7 +2932,7 @@ static void netdev_wait_allrefs(struct net_device *dev) * 2) Since we run with the RTNL semaphore not held, we can sleep * safely in order to wait for the netdev refcnt to drop to zero. */ -static DECLARE_MUTEX(net_todo_run_mutex); +static DEFINE_MUTEX(net_todo_run_mutex); void netdev_run_todo(void) { struct list_head list = LIST_HEAD_INIT(list); @@ -2939,7 +2940,7 @@ void netdev_run_todo(void) /* Need to guard against multiple cpu's getting out of order. */ - down(&net_todo_run_mutex); + mutex_lock(&net_todo_run_mutex); /* Not safe to do outside the semaphore. We must not return * until all unregister events invoked by the local processor @@ -2996,7 +2997,7 @@ void netdev_run_todo(void) } out: - up(&net_todo_run_mutex); + mutex_unlock(&net_todo_run_mutex); } /** diff --git a/net/core/flow.c b/net/core/flow.c index c4f25385029f..55789f832eda 100644 --- a/net/core/flow.c +++ b/net/core/flow.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -287,11 +288,11 @@ static void flow_cache_flush_per_cpu(void *data) void flow_cache_flush(void) { struct flow_flush_info info; - static DECLARE_MUTEX(flow_flush_sem); + static DEFINE_MUTEX(flow_flush_sem); /* Don't want cpus going down or up during this. */ lock_cpu_hotplug(); - down(&flow_flush_sem); + mutex_lock(&flow_flush_sem); atomic_set(&info.cpuleft, num_online_cpus()); init_completion(&info.completion); @@ -301,7 +302,7 @@ void flow_cache_flush(void) local_bh_enable(); wait_for_completion(&info.completion); - up(&flow_flush_sem); + mutex_unlock(&flow_flush_sem); unlock_cpu_hotplug(); } diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index d64e2ec8da7b..c95020f7c81e 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -36,7 +37,7 @@ struct ipcomp_tfms { int users; }; -static DECLARE_MUTEX(ipcomp_resource_sem); +static DEFINE_MUTEX(ipcomp_resource_mutex); static void **ipcomp_scratches; static int ipcomp_scratch_users; static LIST_HEAD(ipcomp_tfms_list); @@ -253,7 +254,7 @@ error: } /* - * Must be protected by xfrm_cfg_sem. State and tunnel user references are + * Must be protected by xfrm_cfg_mutex. State and tunnel user references are * always incremented on success. */ static int ipcomp_tunnel_attach(struct xfrm_state *x) @@ -411,9 +412,9 @@ static void ipcomp_destroy(struct xfrm_state *x) if (!ipcd) return; xfrm_state_delete_tunnel(x); - down(&ipcomp_resource_sem); + mutex_lock(&ipcomp_resource_mutex); ipcomp_free_data(ipcd); - up(&ipcomp_resource_sem); + mutex_unlock(&ipcomp_resource_mutex); kfree(ipcd); } @@ -440,14 +441,14 @@ static int ipcomp_init_state(struct xfrm_state *x) if (x->props.mode) x->props.header_len += sizeof(struct iphdr); - down(&ipcomp_resource_sem); + mutex_lock(&ipcomp_resource_mutex); if (!ipcomp_alloc_scratches()) goto error; ipcd->tfms = ipcomp_alloc_tfms(x->calg->alg_name); if (!ipcd->tfms) goto error; - up(&ipcomp_resource_sem); + mutex_unlock(&ipcomp_resource_mutex); if (x->props.mode) { err = ipcomp_tunnel_attach(x); @@ -464,10 +465,10 @@ out: return err; error_tunnel: - down(&ipcomp_resource_sem); + mutex_lock(&ipcomp_resource_mutex); error: ipcomp_free_data(ipcd); - up(&ipcomp_resource_sem); + mutex_unlock(&ipcomp_resource_mutex); kfree(ipcd); goto out; } diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 08f80e2ea2aa..1655866c55b9 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -61,7 +62,7 @@ static unsigned int queue_dropped = 0; static unsigned int queue_user_dropped = 0; static struct sock *ipqnl; static LIST_HEAD(queue_list); -static DECLARE_MUTEX(ipqnl_sem); +static DEFINE_MUTEX(ipqnl_mutex); static void ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict) @@ -539,7 +540,7 @@ ipq_rcv_sk(struct sock *sk, int len) struct sk_buff *skb; unsigned int qlen; - down(&ipqnl_sem); + mutex_lock(&ipqnl_mutex); for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) { skb = skb_dequeue(&sk->sk_receive_queue); @@ -547,7 +548,7 @@ ipq_rcv_sk(struct sock *sk, int len) kfree_skb(skb); } - up(&ipqnl_sem); + mutex_unlock(&ipqnl_mutex); } static int @@ -708,8 +709,8 @@ cleanup_sysctl: cleanup_ipqnl: sock_release(ipqnl->sk_socket); - down(&ipqnl_sem); - up(&ipqnl_sem); + mutex_lock(&ipqnl_mutex); + mutex_unlock(&ipqnl_mutex); cleanup_netlink_notifier: netlink_unregister_notifier(&ipq_nl_notifier); diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c index afbb0d4cc305..b08d56b117f8 100644 --- a/net/ipv4/xfrm4_tunnel.c +++ b/net/ipv4/xfrm4_tunnel.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -26,19 +27,19 @@ static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, s } static struct xfrm_tunnel *ipip_handler; -static DECLARE_MUTEX(xfrm4_tunnel_sem); +static DEFINE_MUTEX(xfrm4_tunnel_mutex); int xfrm4_tunnel_register(struct xfrm_tunnel *handler) { int ret; - down(&xfrm4_tunnel_sem); + mutex_lock(&xfrm4_tunnel_mutex); ret = 0; if (ipip_handler != NULL) ret = -EINVAL; if (!ret) ipip_handler = handler; - up(&xfrm4_tunnel_sem); + mutex_unlock(&xfrm4_tunnel_mutex); return ret; } @@ -49,13 +50,13 @@ int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler) { int ret; - down(&xfrm4_tunnel_sem); + mutex_lock(&xfrm4_tunnel_mutex); ret = 0; if (ipip_handler != handler) ret = -EINVAL; if (!ret) ipip_handler = NULL; - up(&xfrm4_tunnel_sem); + mutex_unlock(&xfrm4_tunnel_mutex); synchronize_net(); diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 6107592fbd8c..3c7b324cd20c 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -50,6 +50,7 @@ #include #include #include +#include struct ipcomp6_tfms { struct list_head list; @@ -57,7 +58,7 @@ struct ipcomp6_tfms { int users; }; -static DECLARE_MUTEX(ipcomp6_resource_sem); +static DEFINE_MUTEX(ipcomp6_resource_mutex); static void **ipcomp6_scratches; static int ipcomp6_scratch_users; static LIST_HEAD(ipcomp6_tfms_list); @@ -405,9 +406,9 @@ static void ipcomp6_destroy(struct xfrm_state *x) if (!ipcd) return; xfrm_state_delete_tunnel(x); - down(&ipcomp6_resource_sem); + mutex_lock(&ipcomp6_resource_mutex); ipcomp6_free_data(ipcd); - up(&ipcomp6_resource_sem); + mutex_unlock(&ipcomp6_resource_mutex); kfree(ipcd); xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr); @@ -436,14 +437,14 @@ static int ipcomp6_init_state(struct xfrm_state *x) if (x->props.mode) x->props.header_len += sizeof(struct ipv6hdr); - down(&ipcomp6_resource_sem); + mutex_lock(&ipcomp6_resource_mutex); if (!ipcomp6_alloc_scratches()) goto error; ipcd->tfms = ipcomp6_alloc_tfms(x->calg->alg_name); if (!ipcd->tfms) goto error; - up(&ipcomp6_resource_sem); + mutex_unlock(&ipcomp6_resource_mutex); if (x->props.mode) { err = ipcomp6_tunnel_attach(x); @@ -459,10 +460,10 @@ static int ipcomp6_init_state(struct xfrm_state *x) out: return err; error_tunnel: - down(&ipcomp6_resource_sem); + mutex_lock(&ipcomp6_resource_mutex); error: ipcomp6_free_data(ipcd); - up(&ipcomp6_resource_sem); + mutex_unlock(&ipcomp6_resource_mutex); kfree(ipcd); goto out; diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index af0635084df8..344eab3b5da8 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -65,7 +66,7 @@ static unsigned int queue_dropped = 0; static unsigned int queue_user_dropped = 0; static struct sock *ipqnl; static LIST_HEAD(queue_list); -static DECLARE_MUTEX(ipqnl_sem); +static DEFINE_MUTEX(ipqnl_mutex); static void ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict) @@ -537,7 +538,7 @@ ipq_rcv_sk(struct sock *sk, int len) struct sk_buff *skb; unsigned int qlen; - down(&ipqnl_sem); + mutex_lock(&ipqnl_mutex); for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) { skb = skb_dequeue(&sk->sk_receive_queue); @@ -545,7 +546,7 @@ ipq_rcv_sk(struct sock *sk, int len) kfree_skb(skb); } - up(&ipqnl_sem); + mutex_unlock(&ipqnl_mutex); } static int @@ -704,8 +705,8 @@ cleanup_sysctl: cleanup_ipqnl: sock_release(ipqnl->sk_socket); - down(&ipqnl_sem); - up(&ipqnl_sem); + mutex_lock(&ipqnl_mutex); + mutex_unlock(&ipqnl_mutex); cleanup_netlink_notifier: netlink_unregister_notifier(&ipq_nl_notifier); diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 8cfc58b96fc2..08f9abbdf1d7 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef CONFIG_IPV6_XFRM6_TUNNEL_DEBUG # define X6TDEBUG 3 @@ -357,19 +358,19 @@ static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *dec } static struct xfrm6_tunnel *xfrm6_tunnel_handler; -static DECLARE_MUTEX(xfrm6_tunnel_sem); +static DEFINE_MUTEX(xfrm6_tunnel_mutex); int xfrm6_tunnel_register(struct xfrm6_tunnel *handler) { int ret; - down(&xfrm6_tunnel_sem); + mutex_lock(&xfrm6_tunnel_mutex); ret = 0; if (xfrm6_tunnel_handler != NULL) ret = -EINVAL; if (!ret) xfrm6_tunnel_handler = handler; - up(&xfrm6_tunnel_sem); + mutex_unlock(&xfrm6_tunnel_mutex); return ret; } @@ -380,13 +381,13 @@ int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler) { int ret; - down(&xfrm6_tunnel_sem); + mutex_lock(&xfrm6_tunnel_mutex); ret = 0; if (xfrm6_tunnel_handler != handler) ret = -EINVAL; if (!ret) xfrm6_tunnel_handler = NULL; - up(&xfrm6_tunnel_sem); + mutex_unlock(&xfrm6_tunnel_mutex); synchronize_net(); diff --git a/net/key/af_key.c b/net/key/af_key.c index 520fe70d0993..859582275cab 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -3080,9 +3080,9 @@ static int pfkey_sendmsg(struct kiocb *kiocb, if (!hdr) goto out; - down(&xfrm_cfg_sem); + mutex_lock(&xfrm_cfg_mutex); err = pfkey_process(sk, skb, hdr); - up(&xfrm_cfg_sem); + mutex_unlock(&xfrm_cfg_mutex); out: if (err && hdr && pfkey_error(hdr, err, sk) == 0) diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c index 61a833a9caa6..0e5c5e204799 100644 --- a/net/netfilter/nf_sockopt.c +++ b/net/netfilter/nf_sockopt.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "nf_internals.h" @@ -11,7 +12,7 @@ /* Sockopts only registered and called from user context, so net locking would be overkill. Also, [gs]etsockopt calls may sleep. */ -static DECLARE_MUTEX(nf_sockopt_mutex); +static DEFINE_MUTEX(nf_sockopt_mutex); static LIST_HEAD(nf_sockopts); /* Do exclusive ranges overlap? */ @@ -26,7 +27,7 @@ int nf_register_sockopt(struct nf_sockopt_ops *reg) struct list_head *i; int ret = 0; - if (down_interruptible(&nf_sockopt_mutex) != 0) + if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0) return -EINTR; list_for_each(i, &nf_sockopts) { @@ -48,7 +49,7 @@ int nf_register_sockopt(struct nf_sockopt_ops *reg) list_add(®->list, &nf_sockopts); out: - up(&nf_sockopt_mutex); + mutex_unlock(&nf_sockopt_mutex); return ret; } EXPORT_SYMBOL(nf_register_sockopt); @@ -57,18 +58,18 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg) { /* No point being interruptible: we're probably in cleanup_module() */ restart: - down(&nf_sockopt_mutex); + mutex_lock(&nf_sockopt_mutex); if (reg->use != 0) { /* To be woken by nf_sockopt call... */ /* FIXME: Stuart Young's name appears gratuitously. */ set_current_state(TASK_UNINTERRUPTIBLE); reg->cleanup_task = current; - up(&nf_sockopt_mutex); + mutex_unlock(&nf_sockopt_mutex); schedule(); goto restart; } list_del(®->list); - up(&nf_sockopt_mutex); + mutex_unlock(&nf_sockopt_mutex); } EXPORT_SYMBOL(nf_unregister_sockopt); @@ -80,7 +81,7 @@ static int nf_sockopt(struct sock *sk, int pf, int val, struct nf_sockopt_ops *ops; int ret; - if (down_interruptible(&nf_sockopt_mutex) != 0) + if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0) return -EINTR; list_for_each(i, &nf_sockopts) { @@ -90,7 +91,7 @@ static int nf_sockopt(struct sock *sk, int pf, int val, if (val >= ops->get_optmin && val < ops->get_optmax) { ops->use++; - up(&nf_sockopt_mutex); + mutex_unlock(&nf_sockopt_mutex); ret = ops->get(sk, val, opt, len); goto out; } @@ -98,22 +99,22 @@ static int nf_sockopt(struct sock *sk, int pf, int val, if (val >= ops->set_optmin && val < ops->set_optmax) { ops->use++; - up(&nf_sockopt_mutex); + mutex_unlock(&nf_sockopt_mutex); ret = ops->set(sk, val, opt, *len); goto out; } } } } - up(&nf_sockopt_mutex); + mutex_unlock(&nf_sockopt_mutex); return -ENOPROTOOPT; out: - down(&nf_sockopt_mutex); + mutex_lock(&nf_sockopt_mutex); ops->use--; if (ops->cleanup_task) wake_up_process(ops->cleanup_task); - up(&nf_sockopt_mutex); + mutex_unlock(&nf_sockopt_mutex); return ret; } diff --git a/net/socket.c b/net/socket.c index 510ae18d220a..e3c21d5ec288 100644 --- a/net/socket.c +++ b/net/socket.c @@ -68,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -826,36 +827,36 @@ static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf, * with module unload. */ -static DECLARE_MUTEX(br_ioctl_mutex); +static DEFINE_MUTEX(br_ioctl_mutex); static int (*br_ioctl_hook)(unsigned int cmd, void __user *arg) = NULL; void brioctl_set(int (*hook)(unsigned int, void __user *)) { - down(&br_ioctl_mutex); + mutex_lock(&br_ioctl_mutex); br_ioctl_hook = hook; - up(&br_ioctl_mutex); + mutex_unlock(&br_ioctl_mutex); } EXPORT_SYMBOL(brioctl_set); -static DECLARE_MUTEX(vlan_ioctl_mutex); +static DEFINE_MUTEX(vlan_ioctl_mutex); static int (*vlan_ioctl_hook)(void __user *arg); void vlan_ioctl_set(int (*hook)(void __user *)) { - down(&vlan_ioctl_mutex); + mutex_lock(&vlan_ioctl_mutex); vlan_ioctl_hook = hook; - up(&vlan_ioctl_mutex); + mutex_unlock(&vlan_ioctl_mutex); } EXPORT_SYMBOL(vlan_ioctl_set); -static DECLARE_MUTEX(dlci_ioctl_mutex); +static DEFINE_MUTEX(dlci_ioctl_mutex); static int (*dlci_ioctl_hook)(unsigned int, void __user *); void dlci_ioctl_set(int (*hook)(unsigned int, void __user *)) { - down(&dlci_ioctl_mutex); + mutex_lock(&dlci_ioctl_mutex); dlci_ioctl_hook = hook; - up(&dlci_ioctl_mutex); + mutex_unlock(&dlci_ioctl_mutex); } EXPORT_SYMBOL(dlci_ioctl_set); @@ -899,10 +900,10 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) if (!br_ioctl_hook) request_module("bridge"); - down(&br_ioctl_mutex); + mutex_lock(&br_ioctl_mutex); if (br_ioctl_hook) err = br_ioctl_hook(cmd, argp); - up(&br_ioctl_mutex); + mutex_unlock(&br_ioctl_mutex); break; case SIOCGIFVLAN: case SIOCSIFVLAN: @@ -910,10 +911,10 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) if (!vlan_ioctl_hook) request_module("8021q"); - down(&vlan_ioctl_mutex); + mutex_lock(&vlan_ioctl_mutex); if (vlan_ioctl_hook) err = vlan_ioctl_hook(argp); - up(&vlan_ioctl_mutex); + mutex_unlock(&vlan_ioctl_mutex); break; case SIOCGIFDIVERT: case SIOCSIFDIVERT: @@ -927,9 +928,9 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) request_module("dlci"); if (dlci_ioctl_hook) { - down(&dlci_ioctl_mutex); + mutex_lock(&dlci_ioctl_mutex); err = dlci_ioctl_hook(cmd, argp); - up(&dlci_ioctl_mutex); + mutex_unlock(&dlci_ioctl_mutex); } break; default: diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index dcaa0c4453ff..0acccfeeb284 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -532,7 +533,7 @@ void cache_clean_deferred(void *owner) */ static DEFINE_SPINLOCK(queue_lock); -static DECLARE_MUTEX(queue_io_sem); +static DEFINE_MUTEX(queue_io_mutex); struct cache_queue { struct list_head list; @@ -561,7 +562,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) if (count == 0) return 0; - down(&queue_io_sem); /* protect against multiple concurrent + mutex_lock(&queue_io_mutex); /* protect against multiple concurrent * readers on this file */ again: spin_lock(&queue_lock); @@ -574,7 +575,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) } if (rp->q.list.next == &cd->queue) { spin_unlock(&queue_lock); - up(&queue_io_sem); + mutex_unlock(&queue_io_mutex); BUG_ON(rp->offset); return 0; } @@ -621,11 +622,11 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) } if (err == -EAGAIN) goto again; - up(&queue_io_sem); + mutex_unlock(&queue_io_mutex); return err ? err : count; } -static char write_buf[8192]; /* protected by queue_io_sem */ +static char write_buf[8192]; /* protected by queue_io_mutex */ static ssize_t cache_write(struct file *filp, const char __user *buf, size_t count, @@ -639,10 +640,10 @@ cache_write(struct file *filp, const char __user *buf, size_t count, if (count >= sizeof(write_buf)) return -EINVAL; - down(&queue_io_sem); + mutex_lock(&queue_io_mutex); if (copy_from_user(write_buf, buf, count)) { - up(&queue_io_sem); + mutex_unlock(&queue_io_mutex); return -EFAULT; } write_buf[count] = '\0'; @@ -651,7 +652,7 @@ cache_write(struct file *filp, const char __user *buf, size_t count, else err = -EINVAL; - up(&queue_io_sem); + mutex_unlock(&queue_io_mutex); return err ? err : count; } diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index e838d042f7f5..dff07795bd16 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -62,7 +63,7 @@ static LIST_HEAD(all_tasks); /* * rpciod-related stuff */ -static DECLARE_MUTEX(rpciod_sema); +static DEFINE_MUTEX(rpciod_mutex); static unsigned int rpciod_users; static struct workqueue_struct *rpciod_workqueue; @@ -1047,7 +1048,7 @@ rpciod_up(void) struct workqueue_struct *wq; int error = 0; - down(&rpciod_sema); + mutex_lock(&rpciod_mutex); dprintk("rpciod_up: users %d\n", rpciod_users); rpciod_users++; if (rpciod_workqueue) @@ -1070,14 +1071,14 @@ rpciod_up(void) rpciod_workqueue = wq; error = 0; out: - up(&rpciod_sema); + mutex_unlock(&rpciod_mutex); return error; } void rpciod_down(void) { - down(&rpciod_sema); + mutex_lock(&rpciod_mutex); dprintk("rpciod_down sema %d\n", rpciod_users); if (rpciod_users) { if (--rpciod_users) @@ -1094,7 +1095,7 @@ rpciod_down(void) destroy_workqueue(rpciod_workqueue); rpciod_workqueue = NULL; out: - up(&rpciod_sema); + mutex_unlock(&rpciod_mutex); } #ifdef RPC_DEBUG diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 411802bd4d37..746c2f4a5fa6 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -76,6 +76,7 @@ #include #include #include +#include #include #include @@ -169,7 +170,7 @@ static void maybe_unmark_and_push(struct sock *x) void unix_gc(void) { - static DECLARE_MUTEX(unix_gc_sem); + static DEFINE_MUTEX(unix_gc_sem); int i; struct sock *s; struct sk_buff_head hitlist; @@ -179,7 +180,7 @@ void unix_gc(void) * Avoid a recursive GC. */ - if (down_trylock(&unix_gc_sem)) + if (!mutex_trylock(&unix_gc_sem)) return; spin_lock(&unix_table_lock); @@ -308,5 +309,5 @@ void unix_gc(void) */ __skb_queue_purge(&hitlist); - up(&unix_gc_sem); + mutex_unlock(&unix_gc_sem); } diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index b46079263e8b..f5eae9febd26 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -26,8 +26,8 @@ #include #include -DECLARE_MUTEX(xfrm_cfg_sem); -EXPORT_SYMBOL(xfrm_cfg_sem); +DEFINE_MUTEX(xfrm_cfg_mutex); +EXPORT_SYMBOL(xfrm_cfg_mutex); static DEFINE_RWLOCK(xfrm_policy_lock); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 7b1acd995168..4a7120a7e10f 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1486,9 +1486,9 @@ static void xfrm_netlink_rcv(struct sock *sk, int len) unsigned int qlen = 0; do { - down(&xfrm_cfg_sem); + mutex_lock(&xfrm_cfg_mutex); netlink_run_queue(sk, &qlen, &xfrm_user_rcv_msg); - up(&xfrm_cfg_sem); + mutex_unlock(&xfrm_cfg_mutex); } while (qlen); } -- cgit v1.2.3 From 57b47a53ec4a67691ba32cff5768e8d78fa6c67f Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 20 Mar 2006 22:35:41 -0800 Subject: [NET]: sem2mutex part 2 Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- include/linux/sunrpc/svcsock.h | 2 +- include/net/af_unix.h | 3 +- net/atm/common.c | 4 +- net/atm/resources.c | 32 +++++++------- net/atm/resources.h | 3 +- net/bridge/netfilter/ebtables.c | 91 ++++++++++++++++++++------------------- net/ipv4/ipvs/ip_vs_app.c | 19 ++++---- net/ipv4/netfilter/arp_tables.c | 2 +- net/ipv4/netfilter/ip_tables.c | 2 +- net/ipv6/netfilter/ip6_tables.c | 2 +- net/netfilter/nf_conntrack_core.c | 16 ++++--- net/sunrpc/svcsock.c | 8 ++-- net/unix/af_unix.c | 22 +++++----- 13 files changed, 107 insertions(+), 99 deletions(-) (limited to 'include') diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h index d33c6face032..b4acb3d37c3f 100644 --- a/include/linux/sunrpc/svcsock.h +++ b/include/linux/sunrpc/svcsock.h @@ -36,7 +36,7 @@ struct svc_sock { struct list_head sk_deferred; /* deferred requests that need to * be revisted */ - struct semaphore sk_sem; /* to serialize sending data */ + struct mutex sk_mutex; /* to serialize sending data */ int (*sk_recvfrom)(struct svc_rqst *rqstp); int (*sk_sendto)(struct svc_rqst *rqstp); diff --git a/include/net/af_unix.h b/include/net/af_unix.h index bfc1779fc753..427dac94bc7e 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -4,6 +4,7 @@ #include #include #include +#include #include extern void unix_inflight(struct file *fp); @@ -71,7 +72,7 @@ struct unix_sock { struct unix_address *addr; struct dentry *dentry; struct vfsmount *mnt; - struct semaphore readsem; + struct mutex readlock; struct sock *peer; struct sock *other; struct sock *gc_tree; diff --git a/net/atm/common.c b/net/atm/common.c index 6656b111cc05..ae002220fa99 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -451,12 +451,12 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci) dev = try_then_request_module(atm_dev_lookup(itf), "atm-device-%d", itf); } else { dev = NULL; - down(&atm_dev_mutex); + mutex_lock(&atm_dev_mutex); if (!list_empty(&atm_devs)) { dev = list_entry(atm_devs.next, struct atm_dev, dev_list); atm_dev_hold(dev); } - up(&atm_dev_mutex); + mutex_unlock(&atm_dev_mutex); } if (!dev) return -ENODEV; diff --git a/net/atm/resources.c b/net/atm/resources.c index 224190537c90..18ac80698f83 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -18,6 +18,8 @@ #include #include #include +#include + #include /* for struct sock */ #include "common.h" @@ -26,7 +28,7 @@ LIST_HEAD(atm_devs); -DECLARE_MUTEX(atm_dev_mutex); +DEFINE_MUTEX(atm_dev_mutex); static struct atm_dev *__alloc_atm_dev(const char *type) { @@ -65,9 +67,9 @@ struct atm_dev *atm_dev_lookup(int number) { struct atm_dev *dev; - down(&atm_dev_mutex); + mutex_lock(&atm_dev_mutex); dev = __atm_dev_lookup(number); - up(&atm_dev_mutex); + mutex_unlock(&atm_dev_mutex); return dev; } @@ -83,11 +85,11 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, type); return NULL; } - down(&atm_dev_mutex); + mutex_lock(&atm_dev_mutex); if (number != -1) { if ((inuse = __atm_dev_lookup(number))) { atm_dev_put(inuse); - up(&atm_dev_mutex); + mutex_unlock(&atm_dev_mutex); kfree(dev); return NULL; } @@ -112,12 +114,12 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, printk(KERN_ERR "atm_dev_register: " "atm_proc_dev_register failed for dev %s\n", type); - up(&atm_dev_mutex); + mutex_unlock(&atm_dev_mutex); kfree(dev); return NULL; } list_add_tail(&dev->dev_list, &atm_devs); - up(&atm_dev_mutex); + mutex_unlock(&atm_dev_mutex); return dev; } @@ -133,9 +135,9 @@ void atm_dev_deregister(struct atm_dev *dev) * with same number can appear, such we need deregister proc, * release async all vccs and remove them from vccs list too */ - down(&atm_dev_mutex); + mutex_lock(&atm_dev_mutex); list_del(&dev->dev_list); - up(&atm_dev_mutex); + mutex_unlock(&atm_dev_mutex); atm_dev_release_vccs(dev); atm_proc_dev_deregister(dev); @@ -196,16 +198,16 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg) return -EFAULT; if (get_user(len, &iobuf->length)) return -EFAULT; - down(&atm_dev_mutex); + mutex_lock(&atm_dev_mutex); list_for_each(p, &atm_devs) size += sizeof(int); if (size > len) { - up(&atm_dev_mutex); + mutex_unlock(&atm_dev_mutex); return -E2BIG; } tmp_buf = kmalloc(size, GFP_ATOMIC); if (!tmp_buf) { - up(&atm_dev_mutex); + mutex_unlock(&atm_dev_mutex); return -ENOMEM; } tmp_p = tmp_buf; @@ -213,7 +215,7 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg) dev = list_entry(p, struct atm_dev, dev_list); *tmp_p++ = dev->number; } - up(&atm_dev_mutex); + mutex_unlock(&atm_dev_mutex); error = ((copy_to_user(buf, tmp_buf, size)) || put_user(size, &iobuf->length)) ? -EFAULT : 0; @@ -400,13 +402,13 @@ static __inline__ void *dev_get_idx(loff_t left) void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos) { - down(&atm_dev_mutex); + mutex_lock(&atm_dev_mutex); return *pos ? dev_get_idx(*pos) : (void *) 1; } void atm_dev_seq_stop(struct seq_file *seq, void *v) { - up(&atm_dev_mutex); + mutex_unlock(&atm_dev_mutex); } void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) diff --git a/net/atm/resources.h b/net/atm/resources.h index b7fb82a93b42..ac7222fee7a8 100644 --- a/net/atm/resources.h +++ b/net/atm/resources.h @@ -8,10 +8,11 @@ #include #include +#include extern struct list_head atm_devs; -extern struct semaphore atm_dev_mutex; +extern struct mutex atm_dev_mutex; int atm_dev_ioctl(unsigned int cmd, void __user *arg); diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index cbd4020cc84d..4b178b4a2a95 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -35,6 +35,7 @@ #define ASSERT_READ_LOCK(x) #define ASSERT_WRITE_LOCK(x) #include +#include #if 0 /* use this for remote debugging @@ -81,7 +82,7 @@ static void print_string(char *str) -static DECLARE_MUTEX(ebt_mutex); +static DEFINE_MUTEX(ebt_mutex); static LIST_HEAD(ebt_tables); static LIST_HEAD(ebt_targets); static LIST_HEAD(ebt_matches); @@ -296,18 +297,18 @@ letscontinue: /* If it succeeds, returns element and locks mutex */ static inline void * find_inlist_lock_noload(struct list_head *head, const char *name, int *error, - struct semaphore *mutex) + struct mutex *mutex) { void *ret; - *error = down_interruptible(mutex); + *error = mutex_lock_interruptible(mutex); if (*error != 0) return NULL; ret = list_named_find(head, name); if (!ret) { *error = -ENOENT; - up(mutex); + mutex_unlock(mutex); } return ret; } @@ -317,7 +318,7 @@ find_inlist_lock_noload(struct list_head *head, const char *name, int *error, #else static void * find_inlist_lock(struct list_head *head, const char *name, const char *prefix, - int *error, struct semaphore *mutex) + int *error, struct mutex *mutex) { void *ret; @@ -331,25 +332,25 @@ find_inlist_lock(struct list_head *head, const char *name, const char *prefix, #endif static inline struct ebt_table * -find_table_lock(const char *name, int *error, struct semaphore *mutex) +find_table_lock(const char *name, int *error, struct mutex *mutex) { return find_inlist_lock(&ebt_tables, name, "ebtable_", error, mutex); } static inline struct ebt_match * -find_match_lock(const char *name, int *error, struct semaphore *mutex) +find_match_lock(const char *name, int *error, struct mutex *mutex) { return find_inlist_lock(&ebt_matches, name, "ebt_", error, mutex); } static inline struct ebt_watcher * -find_watcher_lock(const char *name, int *error, struct semaphore *mutex) +find_watcher_lock(const char *name, int *error, struct mutex *mutex) { return find_inlist_lock(&ebt_watchers, name, "ebt_", error, mutex); } static inline struct ebt_target * -find_target_lock(const char *name, int *error, struct semaphore *mutex) +find_target_lock(const char *name, int *error, struct mutex *mutex) { return find_inlist_lock(&ebt_targets, name, "ebt_", error, mutex); } @@ -369,10 +370,10 @@ ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e, return ret; m->u.match = match; if (!try_module_get(match->me)) { - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); return -ENOENT; } - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); if (match->check && match->check(name, hookmask, e, m->data, m->match_size) != 0) { BUGPRINT("match->check failed\n"); @@ -398,10 +399,10 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e, return ret; w->u.watcher = watcher; if (!try_module_get(watcher->me)) { - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); return -ENOENT; } - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); if (watcher->check && watcher->check(name, hookmask, e, w->data, w->watcher_size) != 0) { BUGPRINT("watcher->check failed\n"); @@ -638,11 +639,11 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, if (!target) goto cleanup_watchers; if (!try_module_get(target->me)) { - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); ret = -ENOENT; goto cleanup_watchers; } - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); t->u.target = target; if (t->u.target == &ebt_standard_target) { @@ -1015,7 +1016,7 @@ static int do_replace(void __user *user, unsigned int len) t->private = newinfo; write_unlock_bh(&t->lock); - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); /* so, a user can change the chains while having messed up her counter allocation. Only reason why this is done is because this way the lock is held only once, while this doesn't bring the kernel into a @@ -1045,7 +1046,7 @@ static int do_replace(void __user *user, unsigned int len) return ret; free_unlock: - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); free_iterate: EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, ebt_cleanup_entry, NULL); @@ -1068,69 +1069,69 @@ int ebt_register_target(struct ebt_target *target) { int ret; - ret = down_interruptible(&ebt_mutex); + ret = mutex_lock_interruptible(&ebt_mutex); if (ret != 0) return ret; if (!list_named_insert(&ebt_targets, target)) { - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); return -EEXIST; } - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); return 0; } void ebt_unregister_target(struct ebt_target *target) { - down(&ebt_mutex); + mutex_lock(&ebt_mutex); LIST_DELETE(&ebt_targets, target); - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); } int ebt_register_match(struct ebt_match *match) { int ret; - ret = down_interruptible(&ebt_mutex); + ret = mutex_lock_interruptible(&ebt_mutex); if (ret != 0) return ret; if (!list_named_insert(&ebt_matches, match)) { - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); return -EEXIST; } - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); return 0; } void ebt_unregister_match(struct ebt_match *match) { - down(&ebt_mutex); + mutex_lock(&ebt_mutex); LIST_DELETE(&ebt_matches, match); - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); } int ebt_register_watcher(struct ebt_watcher *watcher) { int ret; - ret = down_interruptible(&ebt_mutex); + ret = mutex_lock_interruptible(&ebt_mutex); if (ret != 0) return ret; if (!list_named_insert(&ebt_watchers, watcher)) { - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); return -EEXIST; } - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); return 0; } void ebt_unregister_watcher(struct ebt_watcher *watcher) { - down(&ebt_mutex); + mutex_lock(&ebt_mutex); LIST_DELETE(&ebt_watchers, watcher); - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); } int ebt_register_table(struct ebt_table *table) @@ -1178,7 +1179,7 @@ int ebt_register_table(struct ebt_table *table) table->private = newinfo; rwlock_init(&table->lock); - ret = down_interruptible(&ebt_mutex); + ret = mutex_lock_interruptible(&ebt_mutex); if (ret != 0) goto free_chainstack; @@ -1194,10 +1195,10 @@ int ebt_register_table(struct ebt_table *table) goto free_unlock; } list_prepend(&ebt_tables, table); - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); return 0; free_unlock: - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); free_chainstack: if (newinfo->chainstack) { for_each_cpu(i) @@ -1218,9 +1219,9 @@ void ebt_unregister_table(struct ebt_table *table) BUGPRINT("Request to unregister NULL table!!!\n"); return; } - down(&ebt_mutex); + mutex_lock(&ebt_mutex); LIST_DELETE(&ebt_tables, table); - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); vfree(table->private->entries); if (table->private->chainstack) { for_each_cpu(i) @@ -1281,7 +1282,7 @@ static int update_counters(void __user *user, unsigned int len) write_unlock_bh(&t->lock); ret = 0; unlock_mutex: - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); free_tmp: vfree(tmp); return ret; @@ -1328,7 +1329,7 @@ static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase) return 0; } -/* called with ebt_mutex down */ +/* called with ebt_mutex locked */ static int copy_everything_to_user(struct ebt_table *t, void __user *user, int *len, int cmd) { @@ -1440,7 +1441,7 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) case EBT_SO_GET_INIT_INFO: if (*len != sizeof(struct ebt_replace)){ ret = -EINVAL; - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); break; } if (cmd == EBT_SO_GET_INFO) { @@ -1452,7 +1453,7 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) tmp.entries_size = t->table->entries_size; tmp.valid_hooks = t->table->valid_hooks; } - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); if (copy_to_user(user, &tmp, *len) != 0){ BUGPRINT("c2u Didn't work\n"); ret = -EFAULT; @@ -1464,11 +1465,11 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) case EBT_SO_GET_ENTRIES: case EBT_SO_GET_INIT_ENTRIES: ret = copy_everything_to_user(t, user, len, cmd); - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); break; default: - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); ret = -EINVAL; } @@ -1484,9 +1485,9 @@ static int __init init(void) { int ret; - down(&ebt_mutex); + mutex_lock(&ebt_mutex); list_named_insert(&ebt_targets, &ebt_standard_target); - up(&ebt_mutex); + mutex_unlock(&ebt_mutex); if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0) return ret; diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c index 9b176a942ac5..e7752334d296 100644 --- a/net/ipv4/ipvs/ip_vs_app.c +++ b/net/ipv4/ipvs/ip_vs_app.c @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -40,7 +41,7 @@ EXPORT_SYMBOL(register_ip_vs_app_inc); /* ipvs application list head */ static LIST_HEAD(ip_vs_app_list); -static DECLARE_MUTEX(__ip_vs_app_mutex); +static DEFINE_MUTEX(__ip_vs_app_mutex); /* @@ -173,11 +174,11 @@ register_ip_vs_app_inc(struct ip_vs_app *app, __u16 proto, __u16 port) { int result; - down(&__ip_vs_app_mutex); + mutex_lock(&__ip_vs_app_mutex); result = ip_vs_app_inc_new(app, proto, port); - up(&__ip_vs_app_mutex); + mutex_unlock(&__ip_vs_app_mutex); return result; } @@ -191,11 +192,11 @@ int register_ip_vs_app(struct ip_vs_app *app) /* increase the module use count */ ip_vs_use_count_inc(); - down(&__ip_vs_app_mutex); + mutex_lock(&__ip_vs_app_mutex); list_add(&app->a_list, &ip_vs_app_list); - up(&__ip_vs_app_mutex); + mutex_unlock(&__ip_vs_app_mutex); return 0; } @@ -209,7 +210,7 @@ void unregister_ip_vs_app(struct ip_vs_app *app) { struct ip_vs_app *inc, *nxt; - down(&__ip_vs_app_mutex); + mutex_lock(&__ip_vs_app_mutex); list_for_each_entry_safe(inc, nxt, &app->incs_list, a_list) { ip_vs_app_inc_release(inc); @@ -217,7 +218,7 @@ void unregister_ip_vs_app(struct ip_vs_app *app) list_del(&app->a_list); - up(&__ip_vs_app_mutex); + mutex_unlock(&__ip_vs_app_mutex); /* decrease the module use count */ ip_vs_use_count_dec(); @@ -498,7 +499,7 @@ static struct ip_vs_app *ip_vs_app_idx(loff_t pos) static void *ip_vs_app_seq_start(struct seq_file *seq, loff_t *pos) { - down(&__ip_vs_app_mutex); + mutex_lock(&__ip_vs_app_mutex); return *pos ? ip_vs_app_idx(*pos - 1) : SEQ_START_TOKEN; } @@ -530,7 +531,7 @@ static void *ip_vs_app_seq_next(struct seq_file *seq, void *v, loff_t *pos) static void ip_vs_app_seq_stop(struct seq_file *seq, void *v) { - up(&__ip_vs_app_mutex); + mutex_unlock(&__ip_vs_app_mutex); } static int ip_vs_app_seq_show(struct seq_file *seq, void *v) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 9423bd0f070a..f7efb3f27bf5 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index cf5b9db05371..39705f9bc154 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index d74ec335743e..5a2063bda676 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index dc68d0022218..f6498234e264 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -185,7 +185,7 @@ static struct { DEFINE_RWLOCK(nf_ct_cache_lock); /* This avoids calling kmem_cache_create() with same name simultaneously */ -DECLARE_MUTEX(nf_ct_cache_mutex); +static DEFINE_MUTEX(nf_ct_cache_mutex); extern struct nf_conntrack_protocol nf_conntrack_generic_protocol; struct nf_conntrack_protocol * @@ -278,7 +278,7 @@ int nf_conntrack_register_cache(u_int32_t features, const char *name, return -EINVAL; } - down(&nf_ct_cache_mutex); + mutex_lock(&nf_ct_cache_mutex); write_lock_bh(&nf_ct_cache_lock); /* e.g: multiple helpers are loaded */ @@ -294,7 +294,7 @@ int nf_conntrack_register_cache(u_int32_t features, const char *name, ret = -EBUSY; write_unlock_bh(&nf_ct_cache_lock); - up(&nf_ct_cache_mutex); + mutex_unlock(&nf_ct_cache_mutex); return ret; } write_unlock_bh(&nf_ct_cache_lock); @@ -338,7 +338,7 @@ int nf_conntrack_register_cache(u_int32_t features, const char *name, out_free_name: kfree(cache_name); out_up_mutex: - up(&nf_ct_cache_mutex); + mutex_unlock(&nf_ct_cache_mutex); return ret; } @@ -353,12 +353,12 @@ void nf_conntrack_unregister_cache(u_int32_t features) * slab cache. */ DEBUGP("nf_conntrack_unregister_cache: 0x%04x\n", features); - down(&nf_ct_cache_mutex); + mutex_lock(&nf_ct_cache_mutex); write_lock_bh(&nf_ct_cache_lock); if (--nf_ct_cache[features].use > 0) { write_unlock_bh(&nf_ct_cache_lock); - up(&nf_ct_cache_mutex); + mutex_unlock(&nf_ct_cache_mutex); return; } cachep = nf_ct_cache[features].cachep; @@ -373,7 +373,7 @@ void nf_conntrack_unregister_cache(u_int32_t features) kmem_cache_destroy(cachep); kfree(name); - up(&nf_ct_cache_mutex); + mutex_unlock(&nf_ct_cache_mutex); } int @@ -1408,6 +1408,8 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, #include #include +#include + /* Generic function for tcp/udp/sctp/dccp and alike. This needs to be * in ip_conntrack_core, since we don't want the protocols to autoload diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 50580620e897..a27905a0ad27 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -1296,13 +1296,13 @@ svc_send(struct svc_rqst *rqstp) xb->page_len + xb->tail[0].iov_len; - /* Grab svsk->sk_sem to serialize outgoing data. */ - down(&svsk->sk_sem); + /* Grab svsk->sk_mutex to serialize outgoing data. */ + mutex_lock(&svsk->sk_mutex); if (test_bit(SK_DEAD, &svsk->sk_flags)) len = -ENOTCONN; else len = svsk->sk_sendto(rqstp); - up(&svsk->sk_sem); + mutex_unlock(&svsk->sk_mutex); svc_sock_release(rqstp); if (len == -ECONNREFUSED || len == -ENOTCONN || len == -EAGAIN) @@ -1351,7 +1351,7 @@ svc_setup_socket(struct svc_serv *serv, struct socket *sock, svsk->sk_lastrecv = get_seconds(); INIT_LIST_HEAD(&svsk->sk_deferred); INIT_LIST_HEAD(&svsk->sk_ready); - sema_init(&svsk->sk_sem, 1); + mutex_init(&svsk->sk_mutex); /* Initialize the socket */ if (sock->type == SOCK_DGRAM) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 2b00460f2886..2b4cc2eea5b3 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -566,7 +566,7 @@ static struct sock * unix_create1(struct socket *sock) u->mnt = NULL; spin_lock_init(&u->lock); atomic_set(&u->inflight, sock ? 0 : -1); - init_MUTEX(&u->readsem); /* single task reading lock */ + mutex_init(&u->readlock); /* single task reading lock */ init_waitqueue_head(&u->peer_wait); unix_insert_socket(unix_sockets_unbound, sk); out: @@ -623,7 +623,7 @@ static int unix_autobind(struct socket *sock) struct unix_address * addr; int err; - down(&u->readsem); + mutex_lock(&u->readlock); err = 0; if (u->addr) @@ -661,7 +661,7 @@ retry: spin_unlock(&unix_table_lock); err = 0; -out: up(&u->readsem); +out: mutex_unlock(&u->readlock); return err; } @@ -744,7 +744,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) goto out; addr_len = err; - down(&u->readsem); + mutex_lock(&u->readlock); err = -EINVAL; if (u->addr) @@ -816,7 +816,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) out_unlock: spin_unlock(&unix_table_lock); out_up: - up(&u->readsem); + mutex_unlock(&u->readlock); out: return err; @@ -1545,7 +1545,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, msg->msg_namelen = 0; - down(&u->readsem); + mutex_lock(&u->readlock); skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) @@ -1600,7 +1600,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, out_free: skb_free_datagram(sk,skb); out_unlock: - up(&u->readsem); + mutex_unlock(&u->readlock); out: return err; } @@ -1676,7 +1676,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, memset(&tmp_scm, 0, sizeof(tmp_scm)); } - down(&u->readsem); + mutex_lock(&u->readlock); do { @@ -1700,7 +1700,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, err = -EAGAIN; if (!timeo) break; - up(&u->readsem); + mutex_unlock(&u->readlock); timeo = unix_stream_data_wait(sk, timeo); @@ -1708,7 +1708,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, err = sock_intr_errno(timeo); goto out; } - down(&u->readsem); + mutex_lock(&u->readlock); continue; } @@ -1774,7 +1774,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, } } while (size); - up(&u->readsem); + mutex_unlock(&u->readlock); scm_recv(sock, msg, siocb->scm, flags); out: return copied ? : err; -- cgit v1.2.3 From abd596a4b68b6526c2676233e10602dd9660e9d7 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Mon, 20 Mar 2006 22:39:47 -0800 Subject: [IPV4] ARP: Alloc acceptance of unsolicited ARP via netdevice sysctl. Signed-off-by: Neil Horman Signed-off-by: David S. Miller --- include/linux/inetdevice.h | 1 + include/linux/sysctl.h | 1 + net/ipv4/arp.c | 20 ++++++++++---------- net/ipv4/devinet.c | 8 ++++++++ 4 files changed, 20 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index fd7af86151b1..92297ff24e85 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -25,6 +25,7 @@ struct ipv4_devconf int arp_filter; int arp_announce; int arp_ignore; + int arp_accept; int medium_id; int no_xfrm; int no_policy; diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index dfcf449afc7c..8754568a75d7 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -456,6 +456,7 @@ enum NET_IPV4_CONF_ARP_ANNOUNCE=18, NET_IPV4_CONF_ARP_IGNORE=19, NET_IPV4_CONF_PROMOTE_SECONDARIES=20, + NET_IPV4_CONF_ARP_ACCEPT=21, __NET_IPV4_CONF_MAX }; diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index accdefedfed7..041dadde31af 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -879,16 +879,16 @@ static int arp_process(struct sk_buff *skb) n = __neigh_lookup(&arp_tbl, &sip, dev, 0); -#ifdef CONFIG_IP_ACCEPT_UNSOLICITED_ARP - /* Unsolicited ARP is not accepted by default. - It is possible, that this option should be enabled for some - devices (strip is candidate) - */ - if (n == NULL && - arp->ar_op == htons(ARPOP_REPLY) && - inet_addr_type(sip) == RTN_UNICAST) - n = __neigh_lookup(&arp_tbl, &sip, dev, -1); -#endif + if (ipv4_devconf.arp_accept) { + /* Unsolicited ARP is not accepted by default. + It is possible, that this option should be enabled for some + devices (strip is candidate) + */ + if (n == NULL && + arp->ar_op == htons(ARPOP_REPLY) && + inet_addr_type(sip) == RTN_UNICAST) + n = __neigh_lookup(&arp_tbl, &sip, dev, -1); + } if (n) { int state = NUD_REACHABLE; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 3ffa60dadc0c..44fdf1413e2c 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1393,6 +1393,14 @@ static struct devinet_sysctl_table { .mode = 0644, .proc_handler = &proc_dointvec, }, + { + .ctl_name = NET_IPV4_CONF_ARP_ACCEPT, + .procname = "arp_accept", + .data = &ipv4_devconf.arp_accept, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, { .ctl_name = NET_IPV4_CONF_NOXFRM, .procname = "disable_xfrm", -- cgit v1.2.3 From 15d99e02babae8bc20b836917ace07d93e318149 Mon Sep 17 00:00:00 2001 From: Rick Jones Date: Mon, 20 Mar 2006 22:40:29 -0800 Subject: [TCP]: sysctl to allow TCP window > 32767 sans wscale Back in the dark ages, we had to be conservative and only allow 15-bit window fields if the window scale option was not negotiated. Some ancient stacks used a signed 16-bit quantity for the window field of the TCP header and would get confused. Those days are long gone, so we can use the full 16-bits by default now. There is a sysctl added so that we can still interact with such old stacks Signed-off-by: Rick Jones Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 7 +++++++ include/linux/sysctl.h | 1 + include/net/tcp.h | 1 + net/ipv4/sysctl_net_ipv4.c | 9 ++++++++- net/ipv4/tcp_output.c | 23 +++++++++++++++++------ 5 files changed, 34 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 651298ba019a..f12007b80a46 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -355,6 +355,13 @@ somaxconn - INTEGER Defaults to 128. See also tcp_max_syn_backlog for additional tuning for TCP sockets. +tcp_workaround_signed_windows - BOOLEAN + If set, assume no receipt of a window scaling option means the + remote TCP is broken and treats the window as a signed quantity. + If unset, assume the remote TCP is not broken even if we do + not receive a window scaling option from them. + Default: 0 + IP Variables: ip_local_port_range - 2 INTEGERS diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 8754568a75d7..76eaeff76f82 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -402,6 +402,7 @@ enum NET_IPV4_IPFRAG_MAX_DIST=112, NET_TCP_MTU_PROBING=113, NET_TCP_BASE_MSS=114, + NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS=115, }; enum { diff --git a/include/net/tcp.h b/include/net/tcp.h index 16879fa560de..457e224de468 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -224,6 +224,7 @@ extern int sysctl_tcp_tso_win_divisor; extern int sysctl_tcp_abc; extern int sysctl_tcp_mtu_probing; extern int sysctl_tcp_base_mss; +extern int sysctl_tcp_workaround_signed_windows; extern atomic_t tcp_memory_allocated; extern atomic_t tcp_sockets_allocated; diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index ebf2e0b363c4..6b6c3adfcf00 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -680,7 +680,14 @@ ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = &proc_dointvec, }, - + { + .ctl_name = NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS, + .procname = "tcp_workaround_signed_windows", + .data = &sysctl_tcp_workaround_signed_windows, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec + }, { .ctl_name = 0 } }; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 518e568b53f3..9d79546d384e 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -45,6 +45,11 @@ /* People can turn this off for buggy TCP's found in printers etc. */ int sysctl_tcp_retrans_collapse = 1; +/* People can turn this on to work with those rare, broken TCPs that + * interpret the window field as a signed quantity. + */ +int sysctl_tcp_workaround_signed_windows = 0; + /* This limits the percentage of the congestion window which we * will allow a single TSO frame to consume. Building TSO frames * which are too large can cause TCP streams to be bursty. @@ -177,12 +182,18 @@ void tcp_select_initial_window(int __space, __u32 mss, space = (space / mss) * mss; /* NOTE: offering an initial window larger than 32767 - * will break some buggy TCP stacks. We try to be nice. - * If we are not window scaling, then this truncates - * our initial window offering to 32k. There should also - * be a sysctl option to stop being nice. + * will break some buggy TCP stacks. If the admin tells us + * it is likely we could be speaking with such a buggy stack + * we will truncate our initial window offering to 32K-1 + * unless the remote has sent us a window scaling option, + * which we interpret as a sign the remote TCP is not + * misinterpreting the window field as a signed quantity. */ - (*rcv_wnd) = min(space, MAX_TCP_WINDOW); + if (sysctl_tcp_workaround_signed_windows) + (*rcv_wnd) = min(space, MAX_TCP_WINDOW); + else + (*rcv_wnd) = space; + (*rcv_wscale) = 0; if (wscale_ok) { /* Set window scaling on max possible window @@ -241,7 +252,7 @@ static u16 tcp_select_window(struct sock *sk) /* Make sure we do not exceed the maximum possible * scaled window. */ - if (!tp->rx_opt.rcv_wscale) + if (!tp->rx_opt.rcv_wscale && sysctl_tcp_workaround_signed_windows) new_win = min(new_win, MAX_TCP_WINDOW); else new_win = min(new_win, (65535U << tp->rx_opt.rcv_wscale)); -- cgit v1.2.3 From be33690d8fcf40377f16193c463681170eb6b295 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 20 Mar 2006 22:40:54 -0800 Subject: [XFRM]: Fix aevent related crash When xfrm_user isn't loaded xfrm_nl is NULL, which makes IPsec crash because xfrm_aevent_is_on passes the NULL pointer to netlink_has_listeners as socket. A second problem is that the xfrm_nl pointer is not cleared when the socket is releases at module unload time. Protect references of xfrm_nl from outside of xfrm_user by RCU, check that the socket is present in xfrm_aevent_is_on and set it to NULL when unloading xfrm_user. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/xfrm.h | 10 +++++++++- net/xfrm/xfrm_user.c | 15 +++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 786371365f2b..61b7504fc2ba 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1001,7 +1001,15 @@ static inline int xfrm_policy_id2dir(u32 index) static inline int xfrm_aevent_is_on(void) { - return netlink_has_listeners(xfrm_nl,XFRMNLGRP_AEVENTS); + struct sock *nlsk; + int ret = 0; + + rcu_read_lock(); + nlsk = rcu_dereference(xfrm_nl); + if (nlsk) + ret = netlink_has_listeners(nlsk, XFRMNLGRP_AEVENTS); + rcu_read_unlock(); + return ret; } static inline void xfrm_aevent_doreplay(struct xfrm_state *x) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 4a7120a7e10f..81d1005830f4 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1947,12 +1947,15 @@ static struct xfrm_mgr netlink_mgr = { static int __init xfrm_user_init(void) { + struct sock *nlsk; + printk(KERN_INFO "Initializing IPsec netlink socket\n"); - xfrm_nl = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX, - xfrm_netlink_rcv, THIS_MODULE); - if (xfrm_nl == NULL) + nlsk = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX, + xfrm_netlink_rcv, THIS_MODULE); + if (nlsk == NULL) return -ENOMEM; + rcu_assign_pointer(xfrm_nl, nlsk); xfrm_register_km(&netlink_mgr); @@ -1961,8 +1964,12 @@ static int __init xfrm_user_init(void) static void __exit xfrm_user_exit(void) { + struct sock *nlsk = xfrm_nl; + xfrm_unregister_km(&netlink_mgr); - sock_release(xfrm_nl->sk_socket); + rcu_assign_pointer(xfrm_nl, NULL); + synchronize_rcu(); + sock_release(nlsk->sk_socket); } module_init(xfrm_user_init); -- cgit v1.2.3 From 2c7946a7bf45ae86736ab3b43d0085e43947945c Mon Sep 17 00:00:00 2001 From: Catherine Zhang Date: Mon, 20 Mar 2006 22:41:23 -0800 Subject: [SECURITY]: TCP/UDP getpeersec This patch implements an application of the LSM-IPSec networking controls whereby an application can determine the label of the security association its TCP or UDP sockets are currently connected to via getsockopt and the auxiliary data mechanism of recvmsg. Patch purpose: This patch enables a security-aware application to retrieve the security context of an IPSec security association a particular TCP or UDP socket is using. The application can then use this security context to determine the security context for processing on behalf of the peer at the other end of this connection. In the case of UDP, the security context is for each individual packet. An example application is the inetd daemon, which could be modified to start daemons running at security contexts dependent on the remote client. Patch design approach: - Design for TCP The patch enables the SELinux LSM to set the peer security context for a socket based on the security context of the IPSec security association. The application may retrieve this context using getsockopt. When called, the kernel determines if the socket is a connected (TCP_ESTABLISHED) TCP socket and, if so, uses the dst_entry cache on the socket to retrieve the security associations. If a security association has a security context, the context string is returned, as for UNIX domain sockets. - Design for UDP Unlike TCP, UDP is connectionless. This requires a somewhat different API to retrieve the peer security context. With TCP, the peer security context stays the same throughout the connection, thus it can be retrieved at any time between when the connection is established and when it is torn down. With UDP, each read/write can have different peer and thus the security context might change every time. As a result the security context retrieval must be done TOGETHER with the packet retrieval. The solution is to build upon the existing Unix domain socket API for retrieving user credentials. Linux offers the API for obtaining user credentials via ancillary messages (i.e., out of band/control messages that are bundled together with a normal message). Patch implementation details: - Implementation for TCP The security context can be retrieved by applications using getsockopt with the existing SO_PEERSEC flag. As an example (ignoring error checking): getsockopt(sockfd, SOL_SOCKET, SO_PEERSEC, optbuf, &optlen); printf("Socket peer context is: %s\n", optbuf); The SELinux function, selinux_socket_getpeersec, is extended to check for labeled security associations for connected (TCP_ESTABLISHED == sk->sk_state) TCP sockets only. If so, the socket has a dst_cache of struct dst_entry values that may refer to security associations. If these have security associations with security contexts, the security context is returned. getsockopt returns a buffer that contains a security context string or the buffer is unmodified. - Implementation for UDP To retrieve the security context, the application first indicates to the kernel such desire by setting the IP_PASSSEC option via getsockopt. Then the application retrieves the security context using the auxiliary data mechanism. An example server application for UDP should look like this: toggle = 1; toggle_len = sizeof(toggle); setsockopt(sockfd, SOL_IP, IP_PASSSEC, &toggle, &toggle_len); recvmsg(sockfd, &msg_hdr, 0); if (msg_hdr.msg_controllen > sizeof(struct cmsghdr)) { cmsg_hdr = CMSG_FIRSTHDR(&msg_hdr); if (cmsg_hdr->cmsg_len <= CMSG_LEN(sizeof(scontext)) && cmsg_hdr->cmsg_level == SOL_IP && cmsg_hdr->cmsg_type == SCM_SECURITY) { memcpy(&scontext, CMSG_DATA(cmsg_hdr), sizeof(scontext)); } } ip_setsockopt is enhanced with a new socket option IP_PASSSEC to allow a server socket to receive security context of the peer. A new ancillary message type SCM_SECURITY. When the packet is received we get the security context from the sec_path pointer which is contained in the sk_buff, and copy it to the ancillary message space. An additional LSM hook, selinux_socket_getpeersec_udp, is defined to retrieve the security context from the SELinux space. The existing function, selinux_socket_getpeersec does not suit our purpose, because the security context is copied directly to user space, rather than to kernel space. Testing: We have tested the patch by setting up TCP and UDP connections between applications on two machines using the IPSec policies that result in labeled security associations being built. For TCP, we can then extract the peer security context using getsockopt on either end. For UDP, the receiving end can retrieve the security context using the auxiliary data mechanism of recvmsg. Signed-off-by: Catherine Zhang Acked-by: James Morris Acked-by: Herbert Xu Signed-off-by: David S. Miller --- include/linux/in.h | 1 + include/linux/security.h | 25 +++++++++++---- include/linux/socket.h | 1 + net/core/sock.c | 2 +- net/ipv4/ip_sockglue.c | 31 ++++++++++++++++++- security/dummy.c | 10 ++++-- security/selinux/hooks.c | 46 +++++++++++++++++++++++----- security/selinux/include/xfrm.h | 2 ++ security/selinux/xfrm.c | 68 +++++++++++++++++++++++++++++++++++++++++ 9 files changed, 169 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/include/linux/in.h b/include/linux/in.h index ba355384016a..94f557fa4636 100644 --- a/include/linux/in.h +++ b/include/linux/in.h @@ -72,6 +72,7 @@ struct in_addr { #define IP_FREEBIND 15 #define IP_IPSEC_POLICY 16 #define IP_XFRM_POLICY 17 +#define IP_PASSSEC 18 /* BSD compatibility */ #define IP_RECVRETOPTS IP_RETOPTS diff --git a/include/linux/security.h b/include/linux/security.h index 7cbef482e13a..b18eb8cfa639 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1286,7 +1286,8 @@ struct security_operations { int (*socket_setsockopt) (struct socket * sock, int level, int optname); int (*socket_shutdown) (struct socket * sock, int how); int (*socket_sock_rcv_skb) (struct sock * sk, struct sk_buff * skb); - int (*socket_getpeersec) (struct socket *sock, char __user *optval, int __user *optlen, unsigned len); + int (*socket_getpeersec_stream) (struct socket *sock, char __user *optval, int __user *optlen, unsigned len); + int (*socket_getpeersec_dgram) (struct sk_buff *skb, char **secdata, u32 *seclen); int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority); void (*sk_free_security) (struct sock *sk); unsigned int (*sk_getsid) (struct sock *sk, struct flowi *fl, u8 dir); @@ -2741,10 +2742,16 @@ static inline int security_sock_rcv_skb (struct sock * sk, return security_ops->socket_sock_rcv_skb (sk, skb); } -static inline int security_socket_getpeersec(struct socket *sock, char __user *optval, - int __user *optlen, unsigned len) +static inline int security_socket_getpeersec_stream(struct socket *sock, char __user *optval, + int __user *optlen, unsigned len) { - return security_ops->socket_getpeersec(sock, optval, optlen, len); + return security_ops->socket_getpeersec_stream(sock, optval, optlen, len); +} + +static inline int security_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, + u32 *seclen) +{ + return security_ops->socket_getpeersec_dgram(skb, secdata, seclen); } static inline int security_sk_alloc(struct sock *sk, int family, gfp_t priority) @@ -2863,8 +2870,14 @@ static inline int security_sock_rcv_skb (struct sock * sk, return 0; } -static inline int security_socket_getpeersec(struct socket *sock, char __user *optval, - int __user *optlen, unsigned len) +static inline int security_socket_getpeersec_stream(struct socket *sock, char __user *optval, + int __user *optlen, unsigned len) +{ + return -ENOPROTOOPT; +} + +static inline int security_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, + u32 *seclen) { return -ENOPROTOOPT; } diff --git a/include/linux/socket.h b/include/linux/socket.h index b02dda4ee83d..9ab2ddd80221 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -150,6 +150,7 @@ __KINLINE struct cmsghdr * cmsg_nxthdr (struct msghdr *__msg, struct cmsghdr *__ #define SCM_RIGHTS 0x01 /* rw: access rights (array of int) */ #define SCM_CREDENTIALS 0x02 /* rw: struct ucred */ +#define SCM_SECURITY 0x03 /* rw: security label */ struct ucred { __u32 pid; diff --git a/net/core/sock.c b/net/core/sock.c index 6e00811d44bc..5038a5a7bd84 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -616,7 +616,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname, break; case SO_PEERSEC: - return security_socket_getpeersec(sock, optval, optlen, len); + return security_socket_getpeersec_stream(sock, optval, optlen, len); default: return(-ENOPROTOOPT); diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 2bf8d782f678..b5c4f61518e8 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -50,6 +50,7 @@ #define IP_CMSG_TOS 4 #define IP_CMSG_RECVOPTS 8 #define IP_CMSG_RETOPTS 16 +#define IP_CMSG_PASSSEC 32 /* * SOL_IP control messages. @@ -109,6 +110,19 @@ static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb) put_cmsg(msg, SOL_IP, IP_RETOPTS, opt->optlen, opt->__data); } +static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb) +{ + char *secdata; + u32 seclen; + int err; + + err = security_socket_getpeersec_dgram(skb, &secdata, &seclen); + if (err) + return; + + put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata); +} + void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) { @@ -138,6 +152,11 @@ void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) if (flags & 1) ip_cmsg_recv_retopts(msg, skb); + if ((flags>>=1) == 0) + return; + + if (flags & 1) + ip_cmsg_recv_security(msg, skb); } int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc) @@ -393,7 +412,8 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, (1<= sizeof(int)) { @@ -478,6 +498,12 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, else inet->cmsg_flags &= ~IP_CMSG_RETOPTS; break; + case IP_PASSSEC: + if (val) + inet->cmsg_flags |= IP_CMSG_PASSSEC; + else + inet->cmsg_flags &= ~IP_CMSG_PASSSEC; + break; case IP_TOS: /* This sets both TOS and Precedence */ if (sk->sk_type == SOCK_STREAM) { val &= ~3; @@ -932,6 +958,9 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, case IP_RETOPTS: val = (inet->cmsg_flags & IP_CMSG_RETOPTS) != 0; break; + case IP_PASSSEC: + val = (inet->cmsg_flags & IP_CMSG_PASSSEC) != 0; + break; case IP_TOS: val = inet->tos; break; diff --git a/security/dummy.c b/security/dummy.c index f1a5bd98bf10..a326d6e0b6d7 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -763,8 +763,14 @@ static int dummy_socket_sock_rcv_skb (struct sock *sk, struct sk_buff *skb) return 0; } -static int dummy_socket_getpeersec(struct socket *sock, char __user *optval, - int __user *optlen, unsigned len) +static int dummy_socket_getpeersec_stream(struct socket *sock, char __user *optval, + int __user *optlen, unsigned len) +{ + return -ENOPROTOOPT; +} + +static int dummy_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, + u32 *seclen) { return -ENOPROTOOPT; } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b65c201e9ff5..5b16196f2823 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3318,24 +3318,38 @@ out: return err; } -static int selinux_socket_getpeersec(struct socket *sock, char __user *optval, - int __user *optlen, unsigned len) +static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval, + int __user *optlen, unsigned len) { int err = 0; char *scontext; u32 scontext_len; struct sk_security_struct *ssec; struct inode_security_struct *isec; + u32 peer_sid = 0; isec = SOCK_INODE(sock)->i_security; - if (isec->sclass != SECCLASS_UNIX_STREAM_SOCKET) { + + /* if UNIX_STREAM check peer_sid, if TCP check dst for labelled sa */ + if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET) { + ssec = sock->sk->sk_security; + peer_sid = ssec->peer_sid; + } + else if (isec->sclass == SECCLASS_TCP_SOCKET) { + peer_sid = selinux_socket_getpeer_stream(sock->sk); + + if (peer_sid == SECSID_NULL) { + err = -ENOPROTOOPT; + goto out; + } + } + else { err = -ENOPROTOOPT; goto out; } - ssec = sock->sk->sk_security; - - err = security_sid_to_context(ssec->peer_sid, &scontext, &scontext_len); + err = security_sid_to_context(peer_sid, &scontext, &scontext_len); + if (err) goto out; @@ -3356,6 +3370,23 @@ out: return err; } +static int selinux_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, u32 *seclen) +{ + int err = 0; + u32 peer_sid = selinux_socket_getpeer_dgram(skb); + + if (peer_sid == SECSID_NULL) + return -EINVAL; + + err = security_sid_to_context(peer_sid, secdata, seclen); + if (err) + return err; + + return 0; +} + + + static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) { return sk_alloc_security(sk, family, priority); @@ -4344,7 +4375,8 @@ static struct security_operations selinux_ops = { .socket_setsockopt = selinux_socket_setsockopt, .socket_shutdown = selinux_socket_shutdown, .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb, - .socket_getpeersec = selinux_socket_getpeersec, + .socket_getpeersec_stream = selinux_socket_getpeersec_stream, + .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram, .sk_alloc_security = selinux_sk_alloc_security, .sk_free_security = selinux_sk_free_security, .sk_getsid = selinux_sk_getsid_security, diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index 8e87996c6dd5..a7f388bff3f2 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h @@ -39,6 +39,8 @@ static inline u32 selinux_no_sk_sid(struct flowi *fl) #ifdef CONFIG_SECURITY_NETWORK_XFRM int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb); int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb); +u32 selinux_socket_getpeer_stream(struct sock *sk); +u32 selinux_socket_getpeer_dgram(struct sk_buff *skb); #else static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb) { diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index b2af7ca496c1..dfab6c886698 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c @@ -224,6 +224,74 @@ void selinux_xfrm_state_free(struct xfrm_state *x) kfree(ctx); } +/* + * SELinux internal function to retrieve the context of a connected + * (sk->sk_state == TCP_ESTABLISHED) TCP socket based on its security + * association used to connect to the remote socket. + * + * Retrieve via getsockopt SO_PEERSEC. + */ +u32 selinux_socket_getpeer_stream(struct sock *sk) +{ + struct dst_entry *dst, *dst_test; + u32 peer_sid = SECSID_NULL; + + if (sk->sk_state != TCP_ESTABLISHED) + goto out; + + dst = sk_dst_get(sk); + if (!dst) + goto out; + + for (dst_test = dst; dst_test != 0; + dst_test = dst_test->child) { + struct xfrm_state *x = dst_test->xfrm; + + if (x && selinux_authorizable_xfrm(x)) { + struct xfrm_sec_ctx *ctx = x->security; + peer_sid = ctx->ctx_sid; + break; + } + } + dst_release(dst); + +out: + return peer_sid; +} + +/* + * SELinux internal function to retrieve the context of a UDP packet + * based on its security association used to connect to the remote socket. + * + * Retrieve via setsockopt IP_PASSSEC and recvmsg with control message + * type SCM_SECURITY. + */ +u32 selinux_socket_getpeer_dgram(struct sk_buff *skb) +{ + struct sec_path *sp; + + if (skb == NULL) + return SECSID_NULL; + + if (skb->sk->sk_protocol != IPPROTO_UDP) + return SECSID_NULL; + + sp = skb->sp; + if (sp) { + int i; + + for (i = sp->len-1; i >= 0; i--) { + struct xfrm_state *x = sp->x[i].xvec; + if (selinux_authorizable_xfrm(x)) { + struct xfrm_sec_ctx *ctx = x->security; + return ctx->ctx_sid; + } + } + } + + return SECSID_NULL; +} + /* * LSM hook that controls access to unlabelled packets. If * a xfrm_state is authorizable (defined by macro) then it was -- cgit v1.2.3 From c4ea94ab3710eb2434abe2eab1a479c2dc01f8ac Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Mon, 20 Mar 2006 22:42:39 -0800 Subject: [DECnet]: Endian annotation and fixes for DECnet. The typedef for dn_address has been removed in favour of using __le16 or __u16 directly as appropriate. All the DECnet header files are updated accordingly. The byte ordering of dn_eth2dn() and dn_dn2eth() are both changed since just about all their callers wanted network order rather than host order, so the conversion is now done in the functions themselves. Several missed endianess conversions have been picked up during the conversion process. The nh_gw field in struct dn_fib_info has been changed from a 32 bit field to 16 bits as it ought to be. One or two cases of using htons rather than dn_htons in the routing code have been found and fixed. There are still a few warnings to fix, but this patch deals with the important cases. Signed-off-by: Steven Whitehouse Signed-off-by: Patrick Caulfield Signed-off-by: David S. Miller --- include/linux/dn.h | 44 ++++++++--------- include/net/dn.h | 105 ++++++++++++++++++++--------------------- include/net/dn_dev.h | 88 +++++++++++++++++----------------- include/net/dn_fib.h | 22 ++++----- include/net/dn_neigh.h | 4 +- include/net/dn_nsp.h | 72 ++++++++++++++-------------- include/net/dn_route.h | 12 ++--- include/net/flow.h | 8 ++-- net/decnet/af_decnet.c | 16 +++---- net/decnet/dn_dev.c | 34 ++++++------- net/decnet/dn_fib.c | 8 ++-- net/decnet/dn_neigh.c | 24 +++++----- net/decnet/dn_nsp_in.c | 28 +++++------ net/decnet/dn_nsp_out.c | 38 +++++++-------- net/decnet/dn_route.c | 57 +++++++++++----------- net/decnet/dn_rules.c | 18 +++---- net/decnet/dn_table.c | 12 ++--- net/decnet/sysctl_net_decnet.c | 12 ++--- 18 files changed, 302 insertions(+), 300 deletions(-) (limited to 'include') diff --git a/include/linux/dn.h b/include/linux/dn.h index 782cae49e64c..10b6a6fd5837 100644 --- a/include/linux/dn.h +++ b/include/linux/dn.h @@ -71,17 +71,17 @@ struct dn_naddr { - unsigned short a_len; - unsigned char a_addr[DN_MAXADDL]; + __le16 a_len; + __u8 a_addr[DN_MAXADDL]; /* Two bytes little endian */ }; struct sockaddr_dn { - unsigned short sdn_family; - unsigned char sdn_flags; - unsigned char sdn_objnum; - unsigned short sdn_objnamel; - unsigned char sdn_objname[DN_MAXOBJL]; + __u16 sdn_family; + __u8 sdn_flags; + __u8 sdn_objnum; + __le16 sdn_objnamel; + __u8 sdn_objname[DN_MAXOBJL]; struct dn_naddr sdn_add; }; #define sdn_nodeaddrl sdn_add.a_len /* Node address length */ @@ -93,38 +93,38 @@ struct sockaddr_dn * DECnet set/get DSO_CONDATA, DSO_DISDATA (optional data) structure */ struct optdata_dn { - unsigned short opt_status; /* Extended status return */ + __le16 opt_status; /* Extended status return */ #define opt_sts opt_status - unsigned short opt_optl; /* Length of user data */ - unsigned char opt_data[16]; /* User data */ + __le16 opt_optl; /* Length of user data */ + __u8 opt_data[16]; /* User data */ }; struct accessdata_dn { - unsigned char acc_accl; - unsigned char acc_acc[DN_MAXACCL]; - unsigned char acc_passl; - unsigned char acc_pass[DN_MAXACCL]; - unsigned char acc_userl; - unsigned char acc_user[DN_MAXACCL]; + __u8 acc_accl; + __u8 acc_acc[DN_MAXACCL]; + __u8 acc_passl; + __u8 acc_pass[DN_MAXACCL]; + __u8 acc_userl; + __u8 acc_user[DN_MAXACCL]; }; /* * DECnet logical link information structure */ struct linkinfo_dn { - unsigned short idn_segsize; /* Segment size for link */ - unsigned char idn_linkstate; /* Logical link state */ + __le16 idn_segsize; /* Segment size for link */ + __u8 idn_linkstate; /* Logical link state */ }; /* * Ethernet address format (for DECnet) */ union etheraddress { - unsigned char dne_addr[6]; /* Full ethernet address */ + __u8 dne_addr[6]; /* Full ethernet address */ struct { - unsigned char dne_hiord[4]; /* DECnet HIORD prefix */ - unsigned char dne_nodeaddr[2]; /* DECnet node address */ + __u8 dne_hiord[4]; /* DECnet HIORD prefix */ + __u8 dne_nodeaddr[2]; /* DECnet node address */ } dne_remote; }; @@ -133,7 +133,7 @@ union etheraddress { * DECnet physical socket address format */ struct dn_addr { - unsigned short dna_family; /* AF_DECnet */ + __le16 dna_family; /* AF_DECnet */ union etheraddress dna_netaddr; /* DECnet ethernet address */ }; diff --git a/include/net/dn.h b/include/net/dn.h index a4b6168e1e25..465b78302782 100644 --- a/include/net/dn.h +++ b/include/net/dn.h @@ -6,10 +6,8 @@ #include #include -typedef unsigned short dn_address; - -#define dn_ntohs(x) le16_to_cpu((unsigned short)(x)) -#define dn_htons(x) cpu_to_le16((unsigned short)(x)) +#define dn_ntohs(x) le16_to_cpu(x) +#define dn_htons(x) cpu_to_le16(x) struct dn_scp /* Session Control Port */ { @@ -31,36 +29,36 @@ struct dn_scp /* Session Control Port */ #define DN_CL 15 /* Closed */ #define DN_CN 16 /* Closed Notification */ - unsigned short addrloc; - unsigned short addrrem; - unsigned short numdat; - unsigned short numoth; - unsigned short numoth_rcv; - unsigned short numdat_rcv; - unsigned short ackxmt_dat; - unsigned short ackxmt_oth; - unsigned short ackrcv_dat; - unsigned short ackrcv_oth; - unsigned char flowrem_sw; - unsigned char flowloc_sw; + __le16 addrloc; + __le16 addrrem; + __u16 numdat; + __u16 numoth; + __u16 numoth_rcv; + __u16 numdat_rcv; + __u16 ackxmt_dat; + __u16 ackxmt_oth; + __u16 ackrcv_dat; + __u16 ackrcv_oth; + __u8 flowrem_sw; + __u8 flowloc_sw; #define DN_SEND 2 #define DN_DONTSEND 1 #define DN_NOCHANGE 0 - unsigned short flowrem_dat; - unsigned short flowrem_oth; - unsigned short flowloc_dat; - unsigned short flowloc_oth; - unsigned char services_rem; - unsigned char services_loc; - unsigned char info_rem; - unsigned char info_loc; - - unsigned short segsize_rem; - unsigned short segsize_loc; - - unsigned char nonagle; - unsigned char multi_ireq; - unsigned char accept_mode; + __u16 flowrem_dat; + __u16 flowrem_oth; + __u16 flowloc_dat; + __u16 flowloc_oth; + __u8 services_rem; + __u8 services_loc; + __u8 info_rem; + __u8 info_loc; + + __u16 segsize_rem; + __u16 segsize_loc; + + __u8 nonagle; + __u8 multi_ireq; + __u8 accept_mode; unsigned long seg_total; /* Running total of current segment */ struct optdata_dn conndata_in; @@ -160,40 +158,41 @@ static inline struct dn_scp *DN_SK(struct sock *sk) */ #define DN_SKB_CB(skb) ((struct dn_skb_cb *)(skb)->cb) struct dn_skb_cb { - unsigned short dst; - unsigned short src; - unsigned short hops; - unsigned short dst_port; - unsigned short src_port; - unsigned char services; - unsigned char info; - unsigned char rt_flags; - unsigned char nsp_flags; - unsigned short segsize; - unsigned short segnum; - unsigned short xmit_count; + __le16 dst; + __le16 src; + __u16 hops; + __le16 dst_port; + __le16 src_port; + __u8 services; + __u8 info; + __u8 rt_flags; + __u8 nsp_flags; + __u16 segsize; + __u16 segnum; + __u16 xmit_count; unsigned long stamp; int iif; }; -static inline dn_address dn_eth2dn(unsigned char *ethaddr) +static inline __le16 dn_eth2dn(unsigned char *ethaddr) { - return ethaddr[4] | (ethaddr[5] << 8); + return dn_htons(ethaddr[4] | (ethaddr[5] << 8)); } -static inline dn_address dn_saddr2dn(struct sockaddr_dn *saddr) +static inline __le16 dn_saddr2dn(struct sockaddr_dn *saddr) { - return *(dn_address *)saddr->sdn_nodeaddr; + return *(__le16 *)saddr->sdn_nodeaddr; } -static inline void dn_dn2eth(unsigned char *ethaddr, dn_address addr) +static inline void dn_dn2eth(unsigned char *ethaddr, __le16 addr) { + __u16 a = dn_ntohs(addr); ethaddr[0] = 0xAA; ethaddr[1] = 0x00; ethaddr[2] = 0x04; ethaddr[3] = 0x00; - ethaddr[4] = (unsigned char)(addr & 0xff); - ethaddr[5] = (unsigned char)(addr >> 8); + ethaddr[4] = (__u8)(a & 0xff); + ethaddr[5] = (__u8)(a >> 8); } static inline void dn_sk_ports_copy(struct flowi *fl, struct dn_scp *scp) @@ -202,7 +201,7 @@ static inline void dn_sk_ports_copy(struct flowi *fl, struct dn_scp *scp) fl->uli_u.dnports.dport = scp->addrrem; fl->uli_u.dnports.objnum = scp->addr.sdn_objnum; if (fl->uli_u.dnports.objnum == 0) { - fl->uli_u.dnports.objnamel = scp->addr.sdn_objnamel; + fl->uli_u.dnports.objnamel = (__u8)dn_ntohs(scp->addr.sdn_objnamel); memcpy(fl->uli_u.dnports.objname, scp->addr.sdn_objname, 16); } } @@ -217,7 +216,7 @@ extern unsigned dn_mss_from_pmtu(struct net_device *dev, int mtu); extern struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr); extern struct sock *dn_find_by_skb(struct sk_buff *skb); #define DN_ASCBUF_LEN 9 -extern char *dn_addr2asc(dn_address, char *); +extern char *dn_addr2asc(__u16, char *); extern int dn_destroy_timer(struct sock *sk); extern int dn_sockaddr2username(struct sockaddr_dn *addr, unsigned char *buf, unsigned char type); @@ -226,7 +225,7 @@ extern int dn_username2sockaddr(unsigned char *data, int len, struct sockaddr_dn extern void dn_start_slow_timer(struct sock *sk); extern void dn_stop_slow_timer(struct sock *sk); -extern dn_address decnet_address; +extern __le16 decnet_address; extern int decnet_debug_level; extern int decnet_time_wait; extern int decnet_dn_count; diff --git a/include/net/dn_dev.h b/include/net/dn_dev.h index 5a86e78081bf..cee46821dc53 100644 --- a/include/net/dn_dev.h +++ b/include/net/dn_dev.h @@ -7,11 +7,11 @@ struct dn_dev; struct dn_ifaddr { struct dn_ifaddr *ifa_next; struct dn_dev *ifa_dev; - dn_address ifa_local; - dn_address ifa_address; - unsigned char ifa_flags; - unsigned char ifa_scope; - char ifa_label[IFNAMSIZ]; + __le16 ifa_local; + __le16 ifa_address; + __u8 ifa_flags; + __u8 ifa_scope; + char ifa_label[IFNAMSIZ]; }; #define DN_DEV_S_RU 0 /* Run - working normally */ @@ -91,7 +91,7 @@ struct dn_dev { struct timer_list timer; unsigned long t3; struct neigh_parms *neigh_parms; - unsigned char addr[ETH_ALEN]; + __u8 addr[ETH_ALEN]; struct neighbour *router; /* Default router on circuit */ struct neighbour *peer; /* Peer on pointopoint links */ unsigned long uptime; /* Time device went up in jiffies */ @@ -99,56 +99,56 @@ struct dn_dev { struct dn_short_packet { - unsigned char msgflg; - unsigned short dstnode; - unsigned short srcnode; - unsigned char forward; + __u8 msgflg; + __le16 dstnode; + __le16 srcnode; + __u8 forward; } __attribute__((packed)); struct dn_long_packet { - unsigned char msgflg; - unsigned char d_area; - unsigned char d_subarea; - unsigned char d_id[6]; - unsigned char s_area; - unsigned char s_subarea; - unsigned char s_id[6]; - unsigned char nl2; - unsigned char visit_ct; - unsigned char s_class; - unsigned char pt; + __u8 msgflg; + __u8 d_area; + __u8 d_subarea; + __u8 d_id[6]; + __u8 s_area; + __u8 s_subarea; + __u8 s_id[6]; + __u8 nl2; + __u8 visit_ct; + __u8 s_class; + __u8 pt; } __attribute__((packed)); /*------------------------- DRP - Routing messages ---------------------*/ struct endnode_hello_message { - unsigned char msgflg; - unsigned char tiver[3]; - unsigned char id[6]; - unsigned char iinfo; - unsigned short blksize; - unsigned char area; - unsigned char seed[8]; - unsigned char neighbor[6]; - unsigned short timer; - unsigned char mpd; - unsigned char datalen; - unsigned char data[2]; + __u8 msgflg; + __u8 tiver[3]; + __u8 id[6]; + __u8 iinfo; + __le16 blksize; + __u8 area; + __u8 seed[8]; + __u8 neighbor[6]; + __le16 timer; + __u8 mpd; + __u8 datalen; + __u8 data[2]; } __attribute__((packed)); struct rtnode_hello_message { - unsigned char msgflg; - unsigned char tiver[3]; - unsigned char id[6]; - unsigned char iinfo; - unsigned short blksize; - unsigned char priority; - unsigned char area; - unsigned short timer; - unsigned char mpd; + __u8 msgflg; + __u8 tiver[3]; + __u8 id[6]; + __u8 iinfo; + __le16 blksize; + __u8 priority; + __u8 area; + __le16 timer; + __u8 mpd; } __attribute__((packed)); @@ -169,12 +169,12 @@ extern void dn_dev_down(struct net_device *); extern int dn_dev_set_default(struct net_device *dev, int force); extern struct net_device *dn_dev_get_default(void); -extern int dn_dev_bind_default(dn_address *addr); +extern int dn_dev_bind_default(__le16 *addr); extern int register_dnaddr_notifier(struct notifier_block *nb); extern int unregister_dnaddr_notifier(struct notifier_block *nb); -static inline int dn_dev_islocal(struct net_device *dev, dn_address addr) +static inline int dn_dev_islocal(struct net_device *dev, __le16 addr) { struct dn_dev *dn_db = dev->dn_ptr; struct dn_ifaddr *ifa; diff --git a/include/net/dn_fib.h b/include/net/dn_fib.h index cd3c96d9601b..a15dcf0d5c1e 100644 --- a/include/net/dn_fib.h +++ b/include/net/dn_fib.h @@ -37,7 +37,7 @@ struct dn_fib_nh { int nh_weight; int nh_power; int nh_oif; - u32 nh_gw; + __le16 nh_gw; }; struct dn_fib_info { @@ -48,7 +48,7 @@ struct dn_fib_info { int fib_dead; unsigned fib_flags; int fib_protocol; - dn_address fib_prefsrc; + __le16 fib_prefsrc; __u32 fib_priority; __u32 fib_metrics[RTAX_MAX]; #define dn_fib_mtu fib_metrics[RTAX_MTU-1] @@ -71,15 +71,15 @@ struct dn_fib_info { #define DN_FIB_RES_OIF(res) (DN_FIB_RES_NH(res).nh_oif) typedef struct { - u16 datum; + __le16 datum; } dn_fib_key_t; typedef struct { - u16 datum; + __le16 datum; } dn_fib_hash_t; typedef struct { - u16 datum; + __u16 datum; } dn_fib_idx_t; struct dn_fib_node { @@ -126,11 +126,11 @@ extern int dn_fib_semantic_match(int type, struct dn_fib_info *fi, const struct flowi *fl, struct dn_fib_res *res); extern void dn_fib_release_info(struct dn_fib_info *fi); -extern u16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type); +extern __le16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type); extern void dn_fib_flush(void); extern void dn_fib_select_multipath(const struct flowi *fl, struct dn_fib_res *res); -extern int dn_fib_sync_down(dn_address local, struct net_device *dev, +extern int dn_fib_sync_down(__le16 local, struct net_device *dev, int force); extern int dn_fib_sync_up(struct net_device *dev); @@ -148,8 +148,8 @@ extern void dn_fib_table_cleanup(void); extern void dn_fib_rules_init(void); extern void dn_fib_rules_cleanup(void); extern void dn_fib_rule_put(struct dn_fib_rule *); -extern __u16 dn_fib_rules_policy(__u16 saddr, struct dn_fib_res *res, unsigned *flags); -extern unsigned dnet_addr_type(__u16 addr); +extern __le16 dn_fib_rules_policy(__le16 saddr, struct dn_fib_res *res, unsigned *flags); +extern unsigned dnet_addr_type(__le16 addr); extern int dn_fib_lookup(const struct flowi *fl, struct dn_fib_res *res); /* @@ -194,10 +194,10 @@ extern struct dn_fib_table *dn_fib_tables[]; #endif /* CONFIG_DECNET_ROUTER */ -static inline u16 dnet_make_mask(int n) +static inline __le16 dnet_make_mask(int n) { if (n) - return htons(~((1<<(16-n))-1)); + return dn_htons(~((1<<(16-n))-1)); return 0; } diff --git a/include/net/dn_neigh.h b/include/net/dn_neigh.h index 4b1eb038d637..4cb4ae7fb81f 100644 --- a/include/net/dn_neigh.h +++ b/include/net/dn_neigh.h @@ -7,13 +7,13 @@ */ struct dn_neigh { struct neighbour n; - dn_address addr; + __le16 addr; unsigned long flags; #define DN_NDFLAG_R1 0x0001 /* Router L1 */ #define DN_NDFLAG_R2 0x0002 /* Router L2 */ #define DN_NDFLAG_P3 0x0004 /* Phase III Node */ unsigned long blksize; - unsigned char priority; + __u8 priority; }; extern void dn_neigh_init(void); diff --git a/include/net/dn_nsp.h b/include/net/dn_nsp.h index e6182b86262b..96e816b6974d 100644 --- a/include/net/dn_nsp.h +++ b/include/net/dn_nsp.h @@ -72,77 +72,77 @@ extern struct sk_buff *dn_alloc_send_skb(struct sock *sk, size_t *size, int nobl struct nsp_data_seg_msg { - unsigned char msgflg; - unsigned short dstaddr; - unsigned short srcaddr; + __u8 msgflg; + __le16 dstaddr; + __le16 srcaddr; } __attribute__((packed)); struct nsp_data_opt_msg { - unsigned short acknum; - unsigned short segnum; - unsigned short lsflgs; + __le16 acknum; + __le16 segnum; + __le16 lsflgs; } __attribute__((packed)); struct nsp_data_opt_msg1 { - unsigned short acknum; - unsigned short segnum; + __le16 acknum; + __le16 segnum; } __attribute__((packed)); /* Acknowledgment Message (data/other data) */ struct nsp_data_ack_msg { - unsigned char msgflg; - unsigned short dstaddr; - unsigned short srcaddr; - unsigned short acknum; + __u8 msgflg; + __le16 dstaddr; + __le16 srcaddr; + __le16 acknum; } __attribute__((packed)); /* Connect Acknowledgment Message */ struct nsp_conn_ack_msg { - unsigned char msgflg; - unsigned short dstaddr; + __u8 msgflg; + __le16 dstaddr; } __attribute__((packed)); /* Connect Initiate/Retransmit Initiate/Connect Confirm */ struct nsp_conn_init_msg { - unsigned char msgflg; + __u8 msgflg; #define NSP_CI 0x18 /* Connect Initiate */ #define NSP_RCI 0x68 /* Retrans. Conn Init */ - unsigned short dstaddr; - unsigned short srcaddr; - unsigned char services; + __le16 dstaddr; + __le16 srcaddr; + __u8 services; #define NSP_FC_NONE 0x00 /* Flow Control None */ #define NSP_FC_SRC 0x04 /* Seg Req. Count */ #define NSP_FC_SCMC 0x08 /* Sess. Control Mess */ #define NSP_FC_MASK 0x0c /* FC type mask */ - unsigned char info; - unsigned short segsize; + __u8 info; + __le16 segsize; } __attribute__((packed)); /* Disconnect Initiate/Disconnect Confirm */ struct nsp_disconn_init_msg { - unsigned char msgflg; - unsigned short dstaddr; - unsigned short srcaddr; - unsigned short reason; + __u8 msgflg; + __le16 dstaddr; + __le16 srcaddr; + __le16 reason; } __attribute__((packed)); struct srcobj_fmt { - char format; - unsigned char task; - unsigned short grpcode; - unsigned short usrcode; - char dlen; + __u8 format; + __u8 task; + __le16 grpcode; + __le16 usrcode; + __u8 dlen; } __attribute__((packed)); /* @@ -150,7 +150,7 @@ struct srcobj_fmt * numbers used in NSP. Similar in operation to the functions * of the same name in TCP. */ -static __inline__ int dn_before(unsigned short seq1, unsigned short seq2) +static __inline__ int dn_before(__u16 seq1, __u16 seq2) { seq1 &= 0x0fff; seq2 &= 0x0fff; @@ -159,7 +159,7 @@ static __inline__ int dn_before(unsigned short seq1, unsigned short seq2) } -static __inline__ int dn_after(unsigned short seq1, unsigned short seq2) +static __inline__ int dn_after(__u16 seq1, __u16 seq2) { seq1 &= 0x0fff; seq2 &= 0x0fff; @@ -167,23 +167,23 @@ static __inline__ int dn_after(unsigned short seq1, unsigned short seq2) return (int)((seq2 - seq1) & 0x0fff) > 2048; } -static __inline__ int dn_equal(unsigned short seq1, unsigned short seq2) +static __inline__ int dn_equal(__u16 seq1, __u16 seq2) { return ((seq1 ^ seq2) & 0x0fff) == 0; } -static __inline__ int dn_before_or_equal(unsigned short seq1, unsigned short seq2) +static __inline__ int dn_before_or_equal(__u16 seq1, __u16 seq2) { return (dn_before(seq1, seq2) || dn_equal(seq1, seq2)); } -static __inline__ void seq_add(unsigned short *seq, unsigned short off) +static __inline__ void seq_add(__u16 *seq, __u16 off) { (*seq) += off; (*seq) &= 0x0fff; } -static __inline__ int seq_next(unsigned short seq1, unsigned short seq2) +static __inline__ int seq_next(__u16 seq1, __u16 seq2) { return dn_equal(seq1 + 1, seq2); } @@ -191,7 +191,7 @@ static __inline__ int seq_next(unsigned short seq1, unsigned short seq2) /* * Can we delay the ack ? */ -static __inline__ int sendack(unsigned short seq) +static __inline__ int sendack(__u16 seq) { return (int)((seq & 0x1000) ? 0 : 1); } diff --git a/include/net/dn_route.h b/include/net/dn_route.h index 5122da3f2eb3..76f957e258b0 100644 --- a/include/net/dn_route.h +++ b/include/net/dn_route.h @@ -71,12 +71,12 @@ struct dn_route { struct dn_route *rt_next; } u; - __u16 rt_saddr; - __u16 rt_daddr; - __u16 rt_gateway; - __u16 rt_local_src; /* Source used for forwarding packets */ - __u16 rt_src_map; - __u16 rt_dst_map; + __le16 rt_saddr; + __le16 rt_daddr; + __le16 rt_gateway; + __le16 rt_local_src; /* Source used for forwarding packets */ + __le16 rt_src_map; + __le16 rt_dst_map; unsigned rt_flags; unsigned rt_type; diff --git a/include/net/flow.h b/include/net/flow.h index ec7eb86eb203..04d89f763451 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -30,8 +30,8 @@ struct flowi { } ip6_u; struct { - __u16 daddr; - __u16 saddr; + __le16 daddr; + __le16 saddr; __u32 fwmark; __u8 scope; } dn_u; @@ -64,8 +64,8 @@ struct flowi { } icmpt; struct { - __u16 sport; - __u16 dport; + __le16 sport; + __le16 dport; __u8 objnum; __u8 objnamel; /* Not 16 bits since max val is 16 */ __u8 objname[16]; /* Not zero terminated */ diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index ce4aaf94860d..824981eed225 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -172,7 +172,7 @@ static struct hlist_head *dn_find_list(struct sock *sk) /* * Valid ports are those greater than zero and not already in use. */ -static int check_port(unsigned short port) +static int check_port(__le16 port) { struct sock *sk; struct hlist_node *node; @@ -661,7 +661,7 @@ disc_reject: } } -char *dn_addr2asc(dn_address addr, char *buf) +char *dn_addr2asc(__u16 addr, char *buf) { unsigned short node, area; @@ -801,7 +801,7 @@ static int dn_auto_bind(struct socket *sock) /* End of compatibility stuff */ scp->addr.sdn_add.a_len = dn_htons(2); - rv = dn_dev_bind_default((dn_address *)scp->addr.sdn_add.a_addr); + rv = dn_dev_bind_default((__le16 *)scp->addr.sdn_add.a_addr); if (rv == 0) { rv = dn_hash_sock(sk); if (rv) @@ -1021,7 +1021,7 @@ static void dn_user_copy(struct sk_buff *skb, struct optdata_dn *opt) opt->opt_optl = *ptr++; opt->opt_status = 0; memcpy(opt->opt_data, ptr, opt->opt_optl); - skb_pull(skb, opt->opt_optl + 1); + skb_pull(skb, dn_ntohs(opt->opt_optl) + 1); } @@ -1121,8 +1121,8 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags) skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &(DN_SK(newsk)->addr), &type)); skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &(DN_SK(newsk)->peer), &type)); - *(dn_address *)(DN_SK(newsk)->peer.sdn_add.a_addr) = cb->src; - *(dn_address *)(DN_SK(newsk)->addr.sdn_add.a_addr) = cb->dst; + *(__le16 *)(DN_SK(newsk)->peer.sdn_add.a_addr) = cb->src; + *(__le16 *)(DN_SK(newsk)->addr.sdn_add.a_addr) = cb->dst; menuver = *skb->data; skb_pull(skb, 1); @@ -1365,7 +1365,7 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char __us if (optlen != sizeof(struct optdata_dn)) return -EINVAL; - if (u.opt.opt_optl > 16) + if (dn_ntohs(u.opt.opt_optl) > 16) return -EINVAL; memcpy(&scp->conndata_out, &u.opt, optlen); @@ -1378,7 +1378,7 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char __us if (optlen != sizeof(struct optdata_dn)) return -EINVAL; - if (u.opt.opt_optl > 16) + if (dn_ntohs(u.opt.opt_optl) > 16) return -EINVAL; memcpy(&scp->discdata_out, &u.opt, optlen); diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index efbead83ba7f..cc7b9d9255ef 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -64,7 +64,7 @@ extern struct neigh_table dn_neigh_table; /* * decnet_address is kept in network order. */ -dn_address decnet_address = 0; +__le16 decnet_address = 0; static DEFINE_RWLOCK(dndev_lock); static struct net_device *decnet_default_device; @@ -439,7 +439,7 @@ static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int de *ifap = ifa1->ifa_next; if (dn_db->dev->type == ARPHRD_ETHER) { - if (ifa1->ifa_local != dn_htons(dn_eth2dn(dev->dev_addr))) { + if (ifa1->ifa_local != dn_eth2dn(dev->dev_addr)) { dn_dn2eth(mac_addr, ifa1->ifa_local); dev_mc_delete(dev, mac_addr, ETH_ALEN, 0); } @@ -470,7 +470,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa) } if (dev->type == ARPHRD_ETHER) { - if (ifa->ifa_local != dn_htons(dn_eth2dn(dev->dev_addr))) { + if (ifa->ifa_local != dn_eth2dn(dev->dev_addr)) { dn_dn2eth(mac_addr, ifa->ifa_local); dev_mc_add(dev, mac_addr, ETH_ALEN, 0); dev_mc_upload(dev); @@ -561,7 +561,7 @@ int dn_dev_ioctl(unsigned int cmd, void __user *arg) switch(cmd) { case SIOCGIFADDR: - *((dn_address *)sdn->sdn_nodeaddr) = ifa->ifa_local; + *((__le16 *)sdn->sdn_nodeaddr) = ifa->ifa_local; goto rarok; case SIOCSIFADDR: @@ -804,7 +804,7 @@ done: return skb->len; } -static int dn_dev_get_first(struct net_device *dev, dn_address *addr) +static int dn_dev_get_first(struct net_device *dev, __le16 *addr) { struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr; struct dn_ifaddr *ifa; @@ -830,7 +830,7 @@ out: * a sensible default. Eventually the routing code will take care of all the * nasties for us I hope. */ -int dn_dev_bind_default(dn_address *addr) +int dn_dev_bind_default(__le16 *addr) { struct net_device *dev; int rv; @@ -853,7 +853,7 @@ static void dn_send_endnode_hello(struct net_device *dev, struct dn_ifaddr *ifa) { struct endnode_hello_message *msg; struct sk_buff *skb = NULL; - unsigned short int *pktlen; + __le16 *pktlen; struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr; if ((skb = dn_alloc_skb(NULL, sizeof(*msg), GFP_ATOMIC)) == NULL) @@ -882,7 +882,7 @@ static void dn_send_endnode_hello(struct net_device *dev, struct dn_ifaddr *ifa) msg->datalen = 0x02; memset(msg->data, 0xAA, 2); - pktlen = (unsigned short *)skb_push(skb,2); + pktlen = (__le16 *)skb_push(skb,2); *pktlen = dn_htons(skb->len - 2); skb->nh.raw = skb->data; @@ -926,7 +926,7 @@ static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa) size_t size; unsigned char *ptr; unsigned char *i1, *i2; - unsigned short *pktlen; + __le16 *pktlen; char *src; if (mtu2blksize(dev) < (26 + 7)) @@ -955,11 +955,11 @@ static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa) ptr += ETH_ALEN; *ptr++ = dn_db->parms.forwarding == 1 ? DN_RT_INFO_L1RT : DN_RT_INFO_L2RT; - *((unsigned short *)ptr) = dn_htons(mtu2blksize(dev)); + *((__le16 *)ptr) = dn_htons(mtu2blksize(dev)); ptr += 2; *ptr++ = dn_db->parms.priority; /* Priority */ *ptr++ = 0; /* Area: Reserved */ - *((unsigned short *)ptr) = dn_htons((unsigned short)dn_db->parms.t3); + *((__le16 *)ptr) = dn_htons((unsigned short)dn_db->parms.t3); ptr += 2; *ptr++ = 0; /* MPD: Reserved */ i1 = ptr++; @@ -974,7 +974,7 @@ static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa) skb_trim(skb, (27 + *i2)); - pktlen = (unsigned short *)skb_push(skb, 2); + pktlen = (__le16 *)skb_push(skb, 2); *pktlen = dn_htons(skb->len - 2); skb->nh.raw = skb->data; @@ -1016,7 +1016,7 @@ static void dn_send_ptp_hello(struct net_device *dev, struct dn_ifaddr *ifa) ptr = skb_put(skb, 2 + 4 + tdlen); *ptr++ = DN_RT_PKT_HELO; - *((dn_address *)ptr) = ifa->ifa_local; + *((__le16 *)ptr) = ifa->ifa_local; ptr += 2; *ptr++ = tdlen; @@ -1150,7 +1150,7 @@ struct dn_dev *dn_dev_create(struct net_device *dev, int *err) void dn_dev_up(struct net_device *dev) { struct dn_ifaddr *ifa; - dn_address addr = decnet_address; + __le16 addr = decnet_address; int maybe_default = 0; struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr; @@ -1173,7 +1173,7 @@ void dn_dev_up(struct net_device *dev) if (dev->type == ARPHRD_ETHER) { if (memcmp(dev->dev_addr, dn_hiord, 4) != 0) return; - addr = dn_htons(dn_eth2dn(dev->dev_addr)); + addr = dn_eth2dn(dev->dev_addr); maybe_default = 1; } @@ -1385,8 +1385,8 @@ static int dn_dev_seq_show(struct seq_file *seq, void *v) mtu2blksize(dev), dn_db->parms.priority, dn_db->parms.state, dn_db->parms.name, - dn_db->router ? dn_addr2asc(dn_ntohs(*(dn_address *)dn_db->router->primary_key), router_buf) : "", - dn_db->peer ? dn_addr2asc(dn_ntohs(*(dn_address *)dn_db->peer->primary_key), peer_buf) : ""); + dn_db->router ? dn_addr2asc(dn_ntohs(*(__le16 *)dn_db->router->primary_key), router_buf) : "", + dn_db->peer ? dn_addr2asc(dn_ntohs(*(__le16 *)dn_db->peer->primary_key), peer_buf) : ""); } return 0; } diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c index 99bc061759c3..bd4ce8681a12 100644 --- a/net/decnet/dn_fib.c +++ b/net/decnet/dn_fib.c @@ -143,11 +143,11 @@ static inline struct dn_fib_info *dn_fib_find_info(const struct dn_fib_info *nfi return NULL; } -u16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type) +__le16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type) { while(RTA_OK(attr,attrlen)) { if (attr->rta_type == type) - return *(u16*)RTA_DATA(attr); + return *(__le16*)RTA_DATA(attr); attr = RTA_NEXT(attr, attrlen); } @@ -565,7 +565,7 @@ int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb) return skb->len; } -static void fib_magic(int cmd, int type, __u16 dst, int dst_len, struct dn_ifaddr *ifa) +static void fib_magic(int cmd, int type, __le16 dst, int dst_len, struct dn_ifaddr *ifa) { struct dn_fib_table *tb; struct { @@ -684,7 +684,7 @@ static int dn_fib_dnaddr_event(struct notifier_block *this, unsigned long event, return NOTIFY_DONE; } -int dn_fib_sync_down(dn_address local, struct net_device *dev, int force) +int dn_fib_sync_down(__le16 local, struct net_device *dev, int force) { int ret = 0; int scope = RT_SCOPE_NOWHERE; diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index 33ab256cfd4a..7c8692c26bfe 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c @@ -95,7 +95,7 @@ static struct neigh_ops dn_phase3_ops = { struct neigh_table dn_neigh_table = { .family = PF_DECnet, .entry_size = sizeof(struct dn_neigh), - .key_len = sizeof(dn_address), + .key_len = sizeof(__le16), .hash = dn_neigh_hash, .constructor = dn_neigh_construct, .id = "dn_neigh_cache", @@ -123,7 +123,7 @@ struct neigh_table dn_neigh_table = { static u32 dn_neigh_hash(const void *pkey, const struct net_device *dev) { - return jhash_2words(*(dn_address *)pkey, 0, dn_neigh_table.hash_rnd); + return jhash_2words(*(__u16 *)pkey, 0, dn_neigh_table.hash_rnd); } static int dn_neigh_construct(struct neighbour *neigh) @@ -249,14 +249,14 @@ static int dn_long_output(struct sk_buff *skb) data = skb_push(skb, sizeof(struct dn_long_packet) + 3); lp = (struct dn_long_packet *)(data+3); - *((unsigned short *)data) = dn_htons(skb->len - 2); + *((__le16 *)data) = dn_htons(skb->len - 2); *(data + 2) = 1 | DN_RT_F_PF; /* Padding */ lp->msgflg = DN_RT_PKT_LONG|(cb->rt_flags&(DN_RT_F_IE|DN_RT_F_RQR|DN_RT_F_RTS)); lp->d_area = lp->d_subarea = 0; - dn_dn2eth(lp->d_id, dn_ntohs(cb->dst)); + dn_dn2eth(lp->d_id, cb->dst); lp->s_area = lp->s_subarea = 0; - dn_dn2eth(lp->s_id, dn_ntohs(cb->src)); + dn_dn2eth(lp->s_id, cb->src); lp->nl2 = 0; lp->visit_ct = cb->hops & 0x3f; lp->s_class = 0; @@ -293,7 +293,7 @@ static int dn_short_output(struct sk_buff *skb) } data = skb_push(skb, sizeof(struct dn_short_packet) + 2); - *((unsigned short *)data) = dn_htons(skb->len - 2); + *((__le16 *)data) = dn_htons(skb->len - 2); sp = (struct dn_short_packet *)(data+2); sp->msgflg = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS)); @@ -335,7 +335,7 @@ static int dn_phase3_output(struct sk_buff *skb) } data = skb_push(skb, sizeof(struct dn_short_packet) + 2); - *((unsigned short *)data) = dn_htons(skb->len - 2); + *((__le16 *)data) = dn_htons(skb->len - 2); sp = (struct dn_short_packet *)(data + 2); sp->msgflg = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS)); @@ -373,9 +373,9 @@ int dn_neigh_router_hello(struct sk_buff *skb) struct neighbour *neigh; struct dn_neigh *dn; struct dn_dev *dn_db; - dn_address src; + __le16 src; - src = dn_htons(dn_eth2dn(msg->id)); + src = dn_eth2dn(msg->id); neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1); @@ -409,7 +409,7 @@ int dn_neigh_router_hello(struct sk_buff *skb) } /* Only use routers in our area */ - if ((dn_ntohs(src)>>10) == dn_ntohs((decnet_address)>>10)) { + if ((dn_ntohs(src)>>10) == (dn_ntohs((decnet_address))>>10)) { if (!dn_db->router) { dn_db->router = neigh_clone(neigh); } else { @@ -433,9 +433,9 @@ int dn_neigh_endnode_hello(struct sk_buff *skb) struct endnode_hello_message *msg = (struct endnode_hello_message *)skb->data; struct neighbour *neigh; struct dn_neigh *dn; - dn_address src; + __le16 src; - src = dn_htons(dn_eth2dn(msg->id)); + src = dn_eth2dn(msg->id); neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1); diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c index 44bda85e678f..547523b41c81 100644 --- a/net/decnet/dn_nsp_in.c +++ b/net/decnet/dn_nsp_in.c @@ -85,7 +85,7 @@ static void dn_log_martian(struct sk_buff *skb, const char *msg) if (decnet_log_martians && net_ratelimit()) { char *devname = skb->dev ? skb->dev->name : "???"; struct dn_skb_cb *cb = DN_SKB_CB(skb); - printk(KERN_INFO "DECnet: Martian packet (%s) dev=%s src=0x%04hx dst=0x%04hx srcport=0x%04hx dstport=0x%04hx\n", msg, devname, cb->src, cb->dst, cb->src_port, cb->dst_port); + printk(KERN_INFO "DECnet: Martian packet (%s) dev=%s src=0x%04hx dst=0x%04hx srcport=0x%04hx dstport=0x%04hx\n", msg, devname, dn_ntohs(cb->src), dn_ntohs(cb->dst), dn_ntohs(cb->src_port), dn_ntohs(cb->dst_port)); } } @@ -128,7 +128,7 @@ static void dn_ack(struct sock *sk, struct sk_buff *skb, unsigned short ack) */ static int dn_process_ack(struct sock *sk, struct sk_buff *skb, int oth) { - unsigned short *ptr = (unsigned short *)skb->data; + __le16 *ptr = (__le16 *)skb->data; int len = 0; unsigned short ack; @@ -346,7 +346,7 @@ static void dn_nsp_conn_conf(struct sock *sk, struct sk_buff *skb) ptr = skb->data; cb->services = *ptr++; cb->info = *ptr++; - cb->segsize = dn_ntohs(*(__u16 *)ptr); + cb->segsize = dn_ntohs(*(__le16 *)ptr); if ((scp->state == DN_CI) || (scp->state == DN_CD)) { scp->persist = 0; @@ -363,7 +363,7 @@ static void dn_nsp_conn_conf(struct sock *sk, struct sk_buff *skb) if (skb->len > 0) { unsigned char dlen = *skb->data; if ((dlen <= 16) && (dlen <= skb->len)) { - scp->conndata_in.opt_optl = dlen; + scp->conndata_in.opt_optl = dn_htons((__u16)dlen); memcpy(scp->conndata_in.opt_data, skb->data + 1, dlen); } } @@ -397,17 +397,17 @@ static void dn_nsp_disc_init(struct sock *sk, struct sk_buff *skb) if (skb->len < 2) goto out; - reason = dn_ntohs(*(__u16 *)skb->data); + reason = dn_ntohs(*(__le16 *)skb->data); skb_pull(skb, 2); - scp->discdata_in.opt_status = reason; + scp->discdata_in.opt_status = dn_htons(reason); scp->discdata_in.opt_optl = 0; memset(scp->discdata_in.opt_data, 0, 16); if (skb->len > 0) { unsigned char dlen = *skb->data; if ((dlen <= 16) && (dlen <= skb->len)) { - scp->discdata_in.opt_optl = dlen; + scp->discdata_in.opt_optl = dn_htons((__u16)dlen); memcpy(scp->discdata_in.opt_data, skb->data + 1, dlen); } } @@ -464,7 +464,7 @@ static void dn_nsp_disc_conf(struct sock *sk, struct sk_buff *skb) if (skb->len != 2) goto out; - reason = dn_ntohs(*(__u16 *)skb->data); + reason = dn_ntohs(*(__le16 *)skb->data); sk->sk_state = TCP_CLOSE; @@ -513,7 +513,7 @@ static void dn_nsp_linkservice(struct sock *sk, struct sk_buff *skb) if (skb->len != 4) goto out; - segnum = dn_ntohs(*(__u16 *)ptr); + segnum = dn_ntohs(*(__le16 *)ptr); ptr += 2; lsflags = *(unsigned char *)ptr++; fcval = *ptr; @@ -621,7 +621,7 @@ static void dn_nsp_otherdata(struct sock *sk, struct sk_buff *skb) if (skb->len < 2) goto out; - cb->segnum = segnum = dn_ntohs(*(__u16 *)skb->data); + cb->segnum = segnum = dn_ntohs(*(__le16 *)skb->data); skb_pull(skb, 2); if (seq_next(scp->numoth_rcv, segnum)) { @@ -649,7 +649,7 @@ static void dn_nsp_data(struct sock *sk, struct sk_buff *skb) if (skb->len < 2) goto out; - cb->segnum = segnum = dn_ntohs(*(__u16 *)skb->data); + cb->segnum = segnum = dn_ntohs(*(__le16 *)skb->data); skb_pull(skb, 2); if (seq_next(scp->numdat_rcv, segnum)) { @@ -760,7 +760,7 @@ static int dn_nsp_rx_packet(struct sk_buff *skb) /* * Grab the destination address. */ - cb->dst_port = *(unsigned short *)ptr; + cb->dst_port = *(__le16 *)ptr; cb->src_port = 0; ptr += 2; @@ -768,7 +768,7 @@ static int dn_nsp_rx_packet(struct sk_buff *skb) * If not a connack, grab the source address too. */ if (pskb_may_pull(skb, 5)) { - cb->src_port = *(unsigned short *)ptr; + cb->src_port = *(__le16 *)ptr; ptr += 2; skb_pull(skb, 5); } @@ -778,7 +778,7 @@ static int dn_nsp_rx_packet(struct sk_buff *skb) * Swap src & dst and look up in the normal way. */ if (unlikely(cb->rt_flags & DN_RT_F_RTS)) { - unsigned short tmp = cb->dst_port; + __le16 tmp = cb->dst_port; cb->dst_port = cb->src_port; cb->src_port = tmp; tmp = cb->dst; diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c index c96c767b1f74..c2e21cd89b3c 100644 --- a/net/decnet/dn_nsp_out.c +++ b/net/decnet/dn_nsp_out.c @@ -287,26 +287,26 @@ int dn_nsp_xmit_timeout(struct sock *sk) return 0; } -static inline unsigned char *dn_mk_common_header(struct dn_scp *scp, struct sk_buff *skb, unsigned char msgflag, int len) +static inline __le16 *dn_mk_common_header(struct dn_scp *scp, struct sk_buff *skb, unsigned char msgflag, int len) { unsigned char *ptr = skb_push(skb, len); BUG_ON(len < 5); *ptr++ = msgflag; - *((unsigned short *)ptr) = scp->addrrem; + *((__le16 *)ptr) = scp->addrrem; ptr += 2; - *((unsigned short *)ptr) = scp->addrloc; + *((__le16 *)ptr) = scp->addrloc; ptr += 2; - return ptr; + return (__le16 __force *)ptr; } -static unsigned short *dn_mk_ack_header(struct sock *sk, struct sk_buff *skb, unsigned char msgflag, int hlen, int other) +static __le16 *dn_mk_ack_header(struct sock *sk, struct sk_buff *skb, unsigned char msgflag, int hlen, int other) { struct dn_scp *scp = DN_SK(sk); unsigned short acknum = scp->numdat_rcv & 0x0FFF; unsigned short ackcrs = scp->numoth_rcv & 0x0FFF; - unsigned short *ptr; + __le16 *ptr; BUG_ON(hlen < 9); @@ -325,7 +325,7 @@ static unsigned short *dn_mk_ack_header(struct sock *sk, struct sk_buff *skb, un /* Set "cross subchannel" bit in ackcrs */ ackcrs |= 0x2000; - ptr = (unsigned short *)dn_mk_common_header(scp, skb, msgflag, hlen); + ptr = (__le16 *)dn_mk_common_header(scp, skb, msgflag, hlen); *ptr++ = dn_htons(acknum); *ptr++ = dn_htons(ackcrs); @@ -333,11 +333,11 @@ static unsigned short *dn_mk_ack_header(struct sock *sk, struct sk_buff *skb, un return ptr; } -static unsigned short *dn_nsp_mk_data_header(struct sock *sk, struct sk_buff *skb, int oth) +static __le16 *dn_nsp_mk_data_header(struct sock *sk, struct sk_buff *skb, int oth) { struct dn_scp *scp = DN_SK(sk); struct dn_skb_cb *cb = DN_SKB_CB(skb); - unsigned short *ptr = dn_mk_ack_header(sk, skb, cb->nsp_flags, 11, oth); + __le16 *ptr = dn_mk_ack_header(sk, skb, cb->nsp_flags, 11, oth); if (unlikely(oth)) { cb->segnum = scp->numoth; @@ -524,9 +524,9 @@ void dn_send_conn_conf(struct sock *sk, gfp_t gfp) struct dn_scp *scp = DN_SK(sk); struct sk_buff *skb = NULL; struct nsp_conn_init_msg *msg; - unsigned char len = scp->conndata_out.opt_optl; + __u8 len = (__u8)dn_ntohs(scp->conndata_out.opt_optl); - if ((skb = dn_alloc_skb(sk, 50 + scp->conndata_out.opt_optl, gfp)) == NULL) + if ((skb = dn_alloc_skb(sk, 50 + dn_ntohs(scp->conndata_out.opt_optl), gfp)) == NULL) return; msg = (struct nsp_conn_init_msg *)skb_put(skb, sizeof(*msg)); @@ -553,7 +553,7 @@ void dn_send_conn_conf(struct sock *sk, gfp_t gfp) static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg, unsigned short reason, gfp_t gfp, struct dst_entry *dst, - int ddl, unsigned char *dd, __u16 rem, __u16 loc) + int ddl, unsigned char *dd, __le16 rem, __le16 loc) { struct sk_buff *skb = NULL; int size = 7 + ddl + ((msgflg == NSP_DISCINIT) ? 1 : 0); @@ -561,7 +561,7 @@ static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg, if ((dst == NULL) || (rem == 0)) { if (net_ratelimit()) - printk(KERN_DEBUG "DECnet: dn_nsp_do_disc: BUG! Please report this to SteveW@ACM.org rem=%u dst=%p\n", (unsigned)rem, dst); + printk(KERN_DEBUG "DECnet: dn_nsp_do_disc: BUG! Please report this to SteveW@ACM.org rem=%u dst=%p\n", dn_ntohs(rem), dst); return; } @@ -570,11 +570,11 @@ static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg, msg = skb_put(skb, size); *msg++ = msgflg; - *(__u16 *)msg = rem; + *(__le16 *)msg = rem; msg += 2; - *(__u16 *)msg = loc; + *(__le16 *)msg = loc; msg += 2; - *(__u16 *)msg = dn_htons(reason); + *(__le16 *)msg = dn_htons(reason); msg += 2; if (msgflg == NSP_DISCINIT) *msg++ = ddl; @@ -600,10 +600,10 @@ void dn_nsp_send_disc(struct sock *sk, unsigned char msgflg, int ddl = 0; if (msgflg == NSP_DISCINIT) - ddl = scp->discdata_out.opt_optl; + ddl = dn_ntohs(scp->discdata_out.opt_optl); if (reason == 0) - reason = scp->discdata_out.opt_status; + reason = dn_ntohs(scp->discdata_out.opt_status); dn_nsp_do_disc(sk, msgflg, reason, gfp, sk->sk_dst_cache, ddl, scp->discdata_out.opt_data, scp->addrrem, scp->addrloc); @@ -708,7 +708,7 @@ void dn_nsp_send_conninit(struct sock *sk, unsigned char msgflg) if (aux > 0) memcpy(skb_put(skb, aux), scp->accessdata.acc_acc, aux); - aux = scp->conndata_out.opt_optl; + aux = (__u8)dn_ntohs(scp->conndata_out.opt_optl); *skb_put(skb, 1) = aux; if (aux > 0) memcpy(skb_put(skb,aux), scp->conndata_out.opt_data, aux); diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 3407f190afe8..d7037fe3cafe 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -133,9 +133,9 @@ static struct dst_ops dn_dst_ops = { .entries = ATOMIC_INIT(0), }; -static __inline__ unsigned dn_hash(unsigned short src, unsigned short dst) +static __inline__ unsigned dn_hash(__le16 src, __le16 dst) { - unsigned short tmp = src ^ dst; + __u16 tmp = (__u16 __force)(src ^ dst); tmp ^= (tmp >> 3); tmp ^= (tmp >> 5); tmp ^= (tmp >> 10); @@ -379,9 +379,9 @@ static int dn_return_short(struct sk_buff *skb) { struct dn_skb_cb *cb; unsigned char *ptr; - dn_address *src; - dn_address *dst; - dn_address tmp; + __le16 *src; + __le16 *dst; + __le16 tmp; /* Add back headers */ skb_push(skb, skb->data - skb->nh.raw); @@ -394,9 +394,9 @@ static int dn_return_short(struct sk_buff *skb) ptr = skb->data + 2; *ptr++ = (cb->rt_flags & ~DN_RT_F_RQR) | DN_RT_F_RTS; - dst = (dn_address *)ptr; + dst = (__le16 *)ptr; ptr += 2; - src = (dn_address *)ptr; + src = (__le16 *)ptr; ptr += 2; *ptr = 0; /* Zero hop count */ @@ -475,7 +475,8 @@ static int dn_route_rx_packet(struct sk_buff *skb) struct dn_skb_cb *cb = DN_SKB_CB(skb); printk(KERN_DEBUG "DECnet: dn_route_rx_packet: rt_flags=0x%02x dev=%s len=%d src=0x%04hx dst=0x%04hx err=%d type=%d\n", - (int)cb->rt_flags, devname, skb->len, cb->src, cb->dst, + (int)cb->rt_flags, devname, skb->len, + dn_ntohs(cb->src), dn_ntohs(cb->dst), err, skb->pkt_type); } @@ -505,7 +506,7 @@ static int dn_route_rx_long(struct sk_buff *skb) /* Destination info */ ptr += 2; - cb->dst = dn_htons(dn_eth2dn(ptr)); + cb->dst = dn_eth2dn(ptr); if (memcmp(ptr, dn_hiord_addr, 4) != 0) goto drop_it; ptr += 6; @@ -513,7 +514,7 @@ static int dn_route_rx_long(struct sk_buff *skb) /* Source info */ ptr += 2; - cb->src = dn_htons(dn_eth2dn(ptr)); + cb->src = dn_eth2dn(ptr); if (memcmp(ptr, dn_hiord_addr, 4) != 0) goto drop_it; ptr += 6; @@ -541,9 +542,9 @@ static int dn_route_rx_short(struct sk_buff *skb) skb_pull(skb, 5); skb->h.raw = skb->data; - cb->dst = *(dn_address *)ptr; + cb->dst = *(__le16 *)ptr; ptr += 2; - cb->src = *(dn_address *)ptr; + cb->src = *(__le16 *)ptr; ptr += 2; cb->hops = *ptr & 0x3f; @@ -575,7 +576,7 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type { struct dn_skb_cb *cb; unsigned char flags = 0; - __u16 len = dn_ntohs(*(__u16 *)skb->data); + __u16 len = dn_ntohs(*(__le16 *)skb->data); struct dn_dev *dn = (struct dn_dev *)dev->dn_ptr; unsigned char padlen = 0; @@ -782,7 +783,7 @@ static int dn_rt_bug(struct sk_buff *skb) struct dn_skb_cb *cb = DN_SKB_CB(skb); printk(KERN_DEBUG "dn_rt_bug: skb from:%04x to:%04x\n", - cb->src, cb->dst); + dn_ntohs(cb->src), dn_ntohs(cb->dst)); } kfree_skb(skb); @@ -823,7 +824,7 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res) return 0; } -static inline int dn_match_addr(__u16 addr1, __u16 addr2) +static inline int dn_match_addr(__le16 addr1, __le16 addr2) { __u16 tmp = dn_ntohs(addr1) ^ dn_ntohs(addr2); int match = 16; @@ -834,9 +835,9 @@ static inline int dn_match_addr(__u16 addr1, __u16 addr2) return match; } -static __u16 dnet_select_source(const struct net_device *dev, __u16 daddr, int scope) +static __le16 dnet_select_source(const struct net_device *dev, __le16 daddr, int scope) { - __u16 saddr = 0; + __le16 saddr = 0; struct dn_dev *dn_db = dev->dn_ptr; struct dn_ifaddr *ifa; int best_match = 0; @@ -861,14 +862,14 @@ static __u16 dnet_select_source(const struct net_device *dev, __u16 daddr, int s return saddr; } -static inline __u16 __dn_fib_res_prefsrc(struct dn_fib_res *res) +static inline __le16 __dn_fib_res_prefsrc(struct dn_fib_res *res) { return dnet_select_source(DN_FIB_RES_DEV(*res), DN_FIB_RES_GW(*res), res->scope); } -static inline __u16 dn_fib_rules_map_destination(__u16 daddr, struct dn_fib_res *res) +static inline __le16 dn_fib_rules_map_destination(__le16 daddr, struct dn_fib_res *res) { - __u16 mask = dnet_make_mask(res->prefixlen); + __le16 mask = dnet_make_mask(res->prefixlen); return (daddr&~mask)|res->fi->fib_nh->nh_gw; } @@ -892,12 +893,13 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old struct dn_fib_res res = { .fi = NULL, .type = RTN_UNICAST }; int err; int free_res = 0; - __u16 gateway = 0; + __le16 gateway = 0; if (decnet_debug_level & 16) printk(KERN_DEBUG "dn_route_output_slow: dst=%04x src=%04x mark=%d" - " iif=%d oif=%d\n", oldflp->fld_dst, oldflp->fld_src, + " iif=%d oif=%d\n", dn_ntohs(oldflp->fld_dst), + dn_ntohs(oldflp->fld_src), oldflp->fld_fwmark, loopback_dev.ifindex, oldflp->oif); /* If we have an output interface, verify its a DECnet device */ @@ -961,8 +963,9 @@ source_ok: if (decnet_debug_level & 16) printk(KERN_DEBUG "dn_route_output_slow: initial checks complete." - " dst=%o4x src=%04x oif=%d try_hard=%d\n", fl.fld_dst, - fl.fld_src, fl.oif, try_hard); + " dst=%o4x src=%04x oif=%d try_hard=%d\n", + dn_ntohs(fl.fld_dst), dn_ntohs(fl.fld_src), + fl.oif, try_hard); /* * N.B. If the kernel is compiled without router support then @@ -1218,8 +1221,8 @@ static int dn_route_input_slow(struct sk_buff *skb) struct neighbour *neigh = NULL; unsigned hash; int flags = 0; - __u16 gateway = 0; - __u16 local_src = 0; + __le16 gateway = 0; + __le16 local_src = 0; struct flowi fl = { .nl_u = { .dn_u = { .daddr = cb->dst, .saddr = cb->src, @@ -1266,7 +1269,7 @@ static int dn_route_input_slow(struct sk_buff *skb) res.type = RTN_LOCAL; flags |= RTCF_DIRECTSRC; } else { - __u16 src_map = fl.fld_src; + __le16 src_map = fl.fld_src; free_res = 1; out_dev = DN_FIB_RES_DEV(res); diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index 1060de70bc0c..f2c299dfe030 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c @@ -46,11 +46,11 @@ struct dn_fib_rule unsigned char r_action; unsigned char r_dst_len; unsigned char r_src_len; - dn_address r_src; - dn_address r_srcmask; - dn_address r_dst; - dn_address r_dstmask; - dn_address r_srcmap; + __le16 r_src; + __le16 r_srcmask; + __le16 r_dst; + __le16 r_dstmask; + __le16 r_srcmap; u8 r_flags; #ifdef CONFIG_DECNET_ROUTE_FWMARK u32 r_fwmark; @@ -208,8 +208,8 @@ int dn_fib_lookup(const struct flowi *flp, struct dn_fib_res *res) { struct dn_fib_rule *r, *policy; struct dn_fib_table *tb; - dn_address saddr = flp->fld_src; - dn_address daddr = flp->fld_dst; + __le16 saddr = flp->fld_src; + __le16 daddr = flp->fld_dst; int err; read_lock(&dn_fib_rules_lock); @@ -259,7 +259,7 @@ int dn_fib_lookup(const struct flowi *flp, struct dn_fib_res *res) return -ESRCH; } -unsigned dnet_addr_type(__u16 addr) +unsigned dnet_addr_type(__le16 addr) { struct flowi fl = { .nl_u = { .dn_u = { .daddr = addr } } }; struct dn_fib_res res; @@ -277,7 +277,7 @@ unsigned dnet_addr_type(__u16 addr) return ret; } -__u16 dn_fib_rules_policy(__u16 saddr, struct dn_fib_res *res, unsigned *flags) +__le16 dn_fib_rules_policy(__le16 saddr, struct dn_fib_res *res, unsigned *flags) { struct dn_fib_rule *r = res->r; diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c index 6f8b5658cb4e..0ebc46af1bdd 100644 --- a/net/decnet/dn_table.c +++ b/net/decnet/dn_table.c @@ -46,7 +46,7 @@ struct dn_zone u32 dz_hashmask; #define DZ_HASHMASK(dz) ((dz)->dz_hashmask) int dz_order; - u16 dz_mask; + __le16 dz_mask; #define DZ_MASK(dz) ((dz)->dz_mask) }; @@ -84,14 +84,14 @@ static int dn_fib_hash_zombies; static inline dn_fib_idx_t dn_hash(dn_fib_key_t key, struct dn_zone *dz) { - u16 h = ntohs(key.datum)>>(16 - dz->dz_order); + u16 h = dn_ntohs(key.datum)>>(16 - dz->dz_order); h ^= (h >> 10); h ^= (h >> 6); h &= DZ_HASHMASK(dz); return *(dn_fib_idx_t *)&h; } -static inline dn_fib_key_t dz_key(u16 dst, struct dn_zone *dz) +static inline dn_fib_key_t dz_key(__le16 dst, struct dn_zone *dz) { dn_fib_key_t k; k.datum = dst & DZ_MASK(dz); @@ -250,7 +250,7 @@ static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct dn_kern for_nexthops(fi) { int attrlen = nhlen - sizeof(struct rtnexthop); - dn_address gw; + __le16 gw; if (attrlen < 0 || (nhlen -= nhp->rtnh_len) < 0) return -EINVAL; @@ -457,7 +457,7 @@ static int dn_fib_table_insert(struct dn_fib_table *tb, struct rtmsg *r, struct dz_key_0(key); if (rta->rta_dst) { - dn_address dst; + __le16 dst; memcpy(&dst, rta->rta_dst, 2); if (dst & ~DZ_MASK(dz)) return -EINVAL; @@ -593,7 +593,7 @@ static int dn_fib_table_delete(struct dn_fib_table *tb, struct rtmsg *r, struct dz_key_0(key); if (rta->rta_dst) { - dn_address dst; + __le16 dst; memcpy(&dst, rta->rta_dst, 2); if (dst & ~DZ_MASK(dz)) return -EINVAL; diff --git a/net/decnet/sysctl_net_decnet.c b/net/decnet/sysctl_net_decnet.c index 0e9d2c571165..bda5920215fd 100644 --- a/net/decnet/sysctl_net_decnet.c +++ b/net/decnet/sysctl_net_decnet.c @@ -86,9 +86,9 @@ static void strip_it(char *str) * Simple routine to parse an ascii DECnet address * into a network order address. */ -static int parse_addr(dn_address *addr, char *str) +static int parse_addr(__le16 *addr, char *str) { - dn_address area, node; + __u16 area, node; while(*str && !ISNUM(*str)) str++; @@ -139,7 +139,7 @@ static int dn_node_address_strategy(ctl_table *table, int __user *name, int nlen void **context) { size_t len; - dn_address addr; + __le16 addr; if (oldval && oldlenp) { if (get_user(len, oldlenp)) @@ -147,14 +147,14 @@ static int dn_node_address_strategy(ctl_table *table, int __user *name, int nlen if (len) { if (len != sizeof(unsigned short)) return -EINVAL; - if (put_user(decnet_address, (unsigned short __user *)oldval)) + if (put_user(decnet_address, (__le16 __user *)oldval)) return -EFAULT; } } if (newval && newlen) { if (newlen != sizeof(unsigned short)) return -EINVAL; - if (get_user(addr, (unsigned short __user *)newval)) + if (get_user(addr, (__le16 __user *)newval)) return -EFAULT; dn_dev_devices_off(); @@ -173,7 +173,7 @@ static int dn_node_address_handler(ctl_table *table, int write, { char addr[DN_ASCBUF_LEN]; size_t len; - dn_address dnaddr; + __le16 dnaddr; if (!*lenp || (*ppos && !write)) { *lenp = 0; -- cgit v1.2.3 From cbb042f9e1292434e3cacb90e67d8d381aeac5a9 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 20 Mar 2006 22:43:56 -0800 Subject: [NET]: Replace skb_pull/skb_postpull_rcsum with skb_pull_rcsum We're now starting to have quite a number of places that do skb_pull followed immediately by an skb_postpull_rcsum. We can merge these two operations into one function with skb_pull_rcsum. This makes sense since most pull operations on receive skb's need to update the checksum. I've decided to make this out-of-line since it is fairly big and the fast path where hardware checksums are enabled need to call csum_partial anyway. Since this is a brand new function we get to add an extra check on the len argument. As it is most callers of skb_pull ignore its return value which essentially means that there is no check on the len argument. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- drivers/net/ppp_generic.c | 4 ++-- drivers/net/pppoe.c | 3 +-- include/linux/skbuff.h | 4 +++- net/802/psnap.c | 3 +-- net/8021q/vlan_dev.c | 6 ++---- net/bridge/br_netfilter.c | 6 ++---- net/core/skbuff.c | 21 +++++++++++++++++++++ 7 files changed, 32 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 0245e40b51a1..f608c12e3e8b 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1691,8 +1691,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) || ppp->npmode[npi] != NPMODE_PASS) { kfree_skb(skb); } else { - skb_pull(skb, 2); /* chop off protocol */ - skb_postpull_rcsum(skb, skb->data - 2, 2); + /* chop off protocol */ + skb_pull_rcsum(skb, 2); skb->dev = ppp->dev; skb->protocol = htons(npindex_to_ethertype[npi]); skb->mac.raw = skb->data; diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 9369f811075d..475dc930380f 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -337,8 +337,7 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb) if (sk->sk_state & PPPOX_BOUND) { struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw; int len = ntohs(ph->length); - skb_pull(skb, sizeof(struct pppoe_hdr)); - skb_postpull_rcsum(skb, ph, sizeof(*ph)); + skb_pull_rcsum(skb, sizeof(struct pppoe_hdr)); if (pskb_trim_rcsum(skb, len)) goto abort_kfree; diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 75c963103b9f..613b9513f8b9 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1159,12 +1159,14 @@ static inline int skb_linearize(struct sk_buff *skb, gfp_t gfp) */ static inline void skb_postpull_rcsum(struct sk_buff *skb, - const void *start, int len) + const void *start, unsigned int len) { if (skb->ip_summed == CHECKSUM_HW) skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0)); } +unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len); + /** * pskb_trim_rcsum - trim received skb and update checksum * @skb: buffer to trim diff --git a/net/802/psnap.c b/net/802/psnap.c index 34e42968b477..97c95eec79ed 100644 --- a/net/802/psnap.c +++ b/net/802/psnap.c @@ -61,8 +61,7 @@ static int snap_rcv(struct sk_buff *skb, struct net_device *dev, /* Pass the frame on. */ u8 *hdr = skb->data; skb->h.raw += 5; - skb_pull(skb, 5); - skb_postpull_rcsum(skb, hdr, 5); + skb_pull_rcsum(skb, 5); rc = proto->rcvfunc(skb, dev, &snap_packet_type, orig_dev); } else { skb->sk = NULL; diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 0f604d227da2..da9cfe927158 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -163,10 +163,8 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, stats->rx_packets++; stats->rx_bytes += skb->len; - skb_pull(skb, VLAN_HLEN); /* take off the VLAN header (4 bytes currently) */ - - /* Need to correct hardware checksum */ - skb_postpull_rcsum(skb, vhdr, VLAN_HLEN); + /* Take off the VLAN header (4 bytes currently) */ + skb_pull_rcsum(skb, VLAN_HLEN); /* Ok, lets check to make sure the device (dev) we * came in on is what this VLAN is attached to. diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index e060aad8624d..6787bc5197f7 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -425,8 +425,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, if (skb->protocol == __constant_htons(ETH_P_8021Q)) { u8 *vhdr = skb->data; - skb_pull(skb, VLAN_HLEN); - skb_postpull_rcsum(skb, vhdr, VLAN_HLEN); + skb_pull_rcsum(skb, VLAN_HLEN); skb->nh.raw += VLAN_HLEN; } return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); @@ -444,8 +443,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, if (skb->protocol == __constant_htons(ETH_P_8021Q)) { u8 *vhdr = skb->data; - skb_pull(skb, VLAN_HLEN); - skb_postpull_rcsum(skb, vhdr, VLAN_HLEN); + skb_pull_rcsum(skb, VLAN_HLEN); skb->nh.raw += VLAN_HLEN; } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 01abf1e8990b..2960c8b82b23 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1795,6 +1795,27 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, return 0; } +/** + * skb_pull_rcsum - pull skb and update receive checksum + * @skb: buffer to update + * @start: start of data before pull + * @len: length of data pulled + * + * This function performs an skb_pull on the packet and updates + * update the CHECKSUM_HW checksum. It should be used on receive + * path processing instead of skb_pull unless you know that the + * checksum difference is zero (e.g., a valid IP header) or you + * are setting ip_summed to CHECKSUM_NONE. + */ +unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) +{ + BUG_ON(len > skb->len); + skb->len -= len; + BUG_ON(skb->len < skb->data_len); + skb_postpull_rcsum(skb, skb->data, len); + return skb->data += len; +} + void __init skb_init(void) { skbuff_head_cache = kmem_cache_create("skbuff_head_cache", -- cgit v1.2.3 From 3fdadf7d27e3fbcf72930941884387d1f4936f04 Mon Sep 17 00:00:00 2001 From: Dmitry Mishin Date: Mon, 20 Mar 2006 22:45:21 -0800 Subject: [NET]: {get|set}sockopt compatibility layer This patch extends {get|set}sockopt compatibility layer in order to move protocol specific parts to their place and avoid huge universal net/compat.c file in the future. Signed-off-by: Dmitry Mishin Signed-off-by: David S. Miller --- include/linux/net.h | 4 + include/linux/netfilter.h | 9 ++ include/net/inet_connection_sock.h | 6 ++ include/net/ip.h | 4 + include/net/ipv6.h | 10 +++ include/net/sctp/structs.h | 10 +++ include/net/sock.h | 12 +++ include/net/tcp.h | 6 ++ net/compat.c | 95 +++++++++++++++++---- net/core/sock.c | 28 +++++++ net/dccp/dccp.h | 8 ++ net/dccp/ipv4.c | 12 +++ net/dccp/ipv6.c | 16 ++++ net/dccp/proto.c | 67 ++++++++++++--- net/ipv4/af_inet.c | 12 +++ net/ipv4/ip_sockglue.c | 142 +++++++++++++++++++++++++++----- net/ipv4/raw.c | 50 ++++++++++-- net/ipv4/tcp.c | 77 +++++++++++++++--- net/ipv4/tcp_ipv4.c | 8 ++ net/ipv4/udp.c | 51 ++++++++++-- net/ipv6/af_inet6.c | 12 +++ net/ipv6/ipv6_sockglue.c | 163 ++++++++++++++++++++++++++++++------- net/ipv6/ipv6_syms.c | 4 + net/ipv6/raw.c | 112 +++++++++++++++++++------ net/ipv6/tcp_ipv6.c | 12 +++ net/ipv6/udp.c | 52 ++++++++++-- net/netfilter/nf_sockopt.c | 69 ++++++++++++++++ net/sctp/ipv6.c | 8 ++ net/sctp/protocol.c | 8 ++ 29 files changed, 928 insertions(+), 139 deletions(-) (limited to 'include') diff --git a/include/linux/net.h b/include/linux/net.h index 28195a2d8ff0..152fa6551fd8 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -149,6 +149,10 @@ struct proto_ops { int optname, char __user *optval, int optlen); int (*getsockopt)(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen); + int (*compat_setsockopt)(struct socket *sock, int level, + int optname, char __user *optval, int optlen); + int (*compat_getsockopt)(struct socket *sock, int level, + int optname, char __user *optval, int __user *optlen); int (*sendmsg) (struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len); int (*recvmsg) (struct kiocb *iocb, struct socket *sock, diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 468896939843..412e52ca9720 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -80,10 +80,14 @@ struct nf_sockopt_ops int set_optmin; int set_optmax; int (*set)(struct sock *sk, int optval, void __user *user, unsigned int len); + int (*compat_set)(struct sock *sk, int optval, + void __user *user, unsigned int len); int get_optmin; int get_optmax; int (*get)(struct sock *sk, int optval, void __user *user, int *len); + int (*compat_get)(struct sock *sk, int optval, + void __user *user, int *len); /* Number of users inside set() or get(). */ unsigned int use; @@ -246,6 +250,11 @@ int nf_setsockopt(struct sock *sk, int pf, int optval, char __user *opt, int nf_getsockopt(struct sock *sk, int pf, int optval, char __user *opt, int *len); +int compat_nf_setsockopt(struct sock *sk, int pf, int optval, + char __user *opt, int len); +int compat_nf_getsockopt(struct sock *sk, int pf, int optval, + char __user *opt, int *len); + /* Packet queuing */ struct nf_queue_handler { int (*outfn)(struct sk_buff *skb, struct nf_info *info, diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 363a067403ee..ae61331366f0 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -50,6 +50,12 @@ struct inet_connection_sock_af_ops { char __user *optval, int optlen); int (*getsockopt)(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen); + int (*compat_setsockopt)(struct sock *sk, + int level, int optname, + char __user *optval, int optlen); + int (*compat_getsockopt)(struct sock *sk, + int level, int optname, + char __user *optval, int __user *optlen); void (*addr2sockaddr)(struct sock *sk, struct sockaddr *); int sockaddr_len; }; diff --git a/include/net/ip.h b/include/net/ip.h index fab3d5b3ab1c..8fe6156ca9b0 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -356,6 +356,10 @@ extern void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb); extern int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc); extern int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen); extern int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen); +extern int compat_ip_setsockopt(struct sock *sk, int level, + int optname, char __user *optval, int optlen); +extern int compat_ip_getsockopt(struct sock *sk, int level, + int optname, char __user *optval, int __user *optlen); extern int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *)); extern int ip_recv_error(struct sock *sk, struct msghdr *msg, int len); diff --git a/include/net/ipv6.h b/include/net/ipv6.h index c893a1ce4b39..6d6f0634ae41 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -520,6 +520,16 @@ extern int ipv6_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen); +extern int compat_ipv6_setsockopt(struct sock *sk, + int level, + int optname, + char __user *optval, + int optlen); +extern int compat_ipv6_getsockopt(struct sock *sk, + int level, + int optname, + char __user *optval, + int __user *optlen); extern void ipv6_packet_init(void); diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 072f407848a6..eba99f375517 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -514,6 +514,16 @@ struct sctp_af { int optname, char __user *optval, int __user *optlen); + int (*compat_setsockopt) (struct sock *sk, + int level, + int optname, + char __user *optval, + int optlen); + int (*compat_getsockopt) (struct sock *sk, + int level, + int optname, + char __user *optval, + int __user *optlen); struct dst_entry *(*get_dst) (struct sctp_association *asoc, union sctp_addr *daddr, union sctp_addr *saddr); diff --git a/include/net/sock.h b/include/net/sock.h index f63d0d56712c..ec226f31dc2a 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -520,6 +520,14 @@ struct proto { int (*getsockopt)(struct sock *sk, int level, int optname, char __user *optval, int __user *option); + int (*compat_setsockopt)(struct sock *sk, + int level, + int optname, char __user *optval, + int optlen); + int (*compat_getsockopt)(struct sock *sk, + int level, + int optname, char __user *optval, + int __user *option); int (*sendmsg)(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len); int (*recvmsg)(struct kiocb *iocb, struct sock *sk, @@ -816,6 +824,10 @@ extern int sock_common_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size, int flags); extern int sock_common_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen); +extern int compat_sock_common_getsockopt(struct socket *sock, int level, + int optname, char __user *optval, int __user *optlen); +extern int compat_sock_common_setsockopt(struct socket *sock, int level, + int optname, char __user *optval, int optlen); extern void sk_common_release(struct sock *sk); diff --git a/include/net/tcp.h b/include/net/tcp.h index 457e224de468..9418f4d1afbb 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -353,6 +353,12 @@ extern int tcp_getsockopt(struct sock *sk, int level, extern int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen); +extern int compat_tcp_getsockopt(struct sock *sk, + int level, int optname, + char __user *optval, int __user *optlen); +extern int compat_tcp_setsockopt(struct sock *sk, + int level, int optname, + char __user *optval, int optlen); extern void tcp_set_keepalive(struct sock *sk, int val); extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, diff --git a/net/compat.c b/net/compat.c index e593dace2fdb..13177a1a4b39 100644 --- a/net/compat.c +++ b/net/compat.c @@ -416,7 +416,7 @@ struct compat_sock_fprog { compat_uptr_t filter; /* struct sock_filter * */ }; -static int do_set_attach_filter(int fd, int level, int optname, +static int do_set_attach_filter(struct socket *sock, int level, int optname, char __user *optval, int optlen) { struct compat_sock_fprog __user *fprog32 = (struct compat_sock_fprog __user *)optval; @@ -432,11 +432,12 @@ static int do_set_attach_filter(int fd, int level, int optname, __put_user(compat_ptr(ptr), &kfprog->filter)) return -EFAULT; - return sys_setsockopt(fd, level, optname, (char __user *)kfprog, + return sock_setsockopt(sock, level, optname, (char __user *)kfprog, sizeof(struct sock_fprog)); } -static int do_set_sock_timeout(int fd, int level, int optname, char __user *optval, int optlen) +static int do_set_sock_timeout(struct socket *sock, int level, + int optname, char __user *optval, int optlen) { struct compat_timeval __user *up = (struct compat_timeval __user *) optval; struct timeval ktime; @@ -451,30 +452,61 @@ static int do_set_sock_timeout(int fd, int level, int optname, char __user *optv return -EFAULT; old_fs = get_fs(); set_fs(KERNEL_DS); - err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime)); + err = sock_setsockopt(sock, level, optname, (char *) &ktime, sizeof(ktime)); set_fs(old_fs); return err; } +static int compat_sock_setsockopt(struct socket *sock, int level, int optname, + char __user *optval, int optlen) +{ + if (optname == SO_ATTACH_FILTER) + return do_set_attach_filter(sock, level, optname, + optval, optlen); + if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) + return do_set_sock_timeout(sock, level, optname, optval, optlen); + + return sock_setsockopt(sock, level, optname, optval, optlen); +} + asmlinkage long compat_sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen) { + int err; + struct socket *sock; + /* SO_SET_REPLACE seems to be the same in all levels */ if (optname == IPT_SO_SET_REPLACE) return do_netfilter_replace(fd, level, optname, optval, optlen); - if (level == SOL_SOCKET && optname == SO_ATTACH_FILTER) - return do_set_attach_filter(fd, level, optname, - optval, optlen); - if (level == SOL_SOCKET && - (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) - return do_set_sock_timeout(fd, level, optname, optval, optlen); - return sys_setsockopt(fd, level, optname, optval, optlen); + if (optlen < 0) + return -EINVAL; + + if ((sock = sockfd_lookup(fd, &err))!=NULL) + { + err = security_socket_setsockopt(sock,level,optname); + if (err) { + sockfd_put(sock); + return err; + } + + if (level == SOL_SOCKET) + err = compat_sock_setsockopt(sock, level, + optname, optval, optlen); + else if (sock->ops->compat_setsockopt) + err = sock->ops->compat_setsockopt(sock, level, + optname, optval, optlen); + else + err = sock->ops->setsockopt(sock, level, + optname, optval, optlen); + sockfd_put(sock); + } + return err; } -static int do_get_sock_timeout(int fd, int level, int optname, +static int do_get_sock_timeout(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { struct compat_timeval __user *up; @@ -490,7 +522,7 @@ static int do_get_sock_timeout(int fd, int level, int optname, len = sizeof(ktime); old_fs = get_fs(); set_fs(KERNEL_DS); - err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len); + err = sock_getsockopt(sock, level, optname, (char *) &ktime, &len); set_fs(old_fs); if (!err) { @@ -503,15 +535,42 @@ static int do_get_sock_timeout(int fd, int level, int optname, return err; } -asmlinkage long compat_sys_getsockopt(int fd, int level, int optname, +static int compat_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { - if (level == SOL_SOCKET && - (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) - return do_get_sock_timeout(fd, level, optname, optval, optlen); - return sys_getsockopt(fd, level, optname, optval, optlen); + if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) + return do_get_sock_timeout(sock, level, optname, optval, optlen); + return sock_getsockopt(sock, level, optname, optval, optlen); } +asmlinkage long compat_sys_getsockopt(int fd, int level, int optname, + char __user *optval, int __user *optlen) +{ + int err; + struct socket *sock; + + if ((sock = sockfd_lookup(fd, &err))!=NULL) + { + err = security_socket_getsockopt(sock, level, + optname); + if (err) { + sockfd_put(sock); + return err; + } + + if (level == SOL_SOCKET) + err = compat_sock_getsockopt(sock, level, + optname, optval, optlen); + else if (sock->ops->compat_getsockopt) + err = sock->ops->compat_getsockopt(sock, level, + optname, optval, optlen); + else + err = sock->ops->getsockopt(sock, level, + optname, optval, optlen); + sockfd_put(sock); + } + return err; +} /* Argument list sizes for compat_sys_socketcall */ #define AL(x) ((x) * sizeof(u32)) static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), diff --git a/net/core/sock.c b/net/core/sock.c index 5038a5a7bd84..dd63cdea3fe7 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1385,6 +1385,20 @@ int sock_common_getsockopt(struct socket *sock, int level, int optname, EXPORT_SYMBOL(sock_common_getsockopt); +#ifdef CONFIG_COMPAT +int compat_sock_common_getsockopt(struct socket *sock, int level, + int optname, char __user *optval, int __user *optlen) +{ + struct sock *sk = sock->sk; + + if (sk->sk_prot->compat_setsockopt) + return sk->sk_prot->compat_getsockopt(sk, level, + optname, optval, optlen); + return sk->sk_prot->getsockopt(sk, level, optname, optval, optlen); +} +EXPORT_SYMBOL(compat_sock_common_getsockopt); +#endif + int sock_common_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size, int flags) { @@ -1414,6 +1428,20 @@ int sock_common_setsockopt(struct socket *sock, int level, int optname, EXPORT_SYMBOL(sock_common_setsockopt); +#ifdef CONFIG_COMPAT +int compat_sock_common_setsockopt(struct socket *sock, + int level, int optname, char __user *optval, int optlen) +{ + struct sock *sk = sock->sk; + + if (sk->sk_prot->compat_setsockopt) + return sk->sk_prot->compat_setsockopt(sk, level, + optname, optval, optlen); + return sk->sk_prot->setsockopt(sk, level, optname, optval, optlen); +} +EXPORT_SYMBOL(compat_sock_common_setsockopt); +#endif + void sk_common_release(struct sock *sk) { if (sk->sk_prot->destroy) diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 34e70fb89d4a..47de17208d7a 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -192,6 +192,14 @@ extern int dccp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen); extern int dccp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen); +#ifdef CONFIG_COMPAT +extern int compat_dccp_getsockopt(struct sock *sk, + int level, int optname, + char __user *optval, int __user *optlen); +extern int compat_dccp_setsockopt(struct sock *sk, + int level, int optname, + char __user *optval, int optlen); +#endif extern int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg); extern int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t size); diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 80d450ba6219..8a33c8498d9c 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -994,6 +994,10 @@ static struct inet_connection_sock_af_ops dccp_ipv4_af_ops = { .net_header_len = sizeof(struct iphdr), .setsockopt = ip_setsockopt, .getsockopt = ip_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_ip_setsockopt, + .compat_getsockopt = compat_ip_getsockopt, +#endif .addr2sockaddr = inet_csk_addr2sockaddr, .sockaddr_len = sizeof(struct sockaddr_in), }; @@ -1040,6 +1044,10 @@ static struct proto dccp_v4_prot = { .init = dccp_v4_init_sock, .setsockopt = dccp_setsockopt, .getsockopt = dccp_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_dccp_setsockopt, + .compat_getsockopt = compat_dccp_getsockopt, +#endif .sendmsg = dccp_sendmsg, .recvmsg = dccp_recvmsg, .backlog_rcv = dccp_v4_do_rcv, @@ -1079,6 +1087,10 @@ static const struct proto_ops inet_dccp_ops = { .shutdown = inet_shutdown, .setsockopt = sock_common_setsockopt, .getsockopt = sock_common_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_sock_common_setsockopt, + .compat_getsockopt = compat_sock_common_getsockopt, +#endif .sendmsg = inet_sendmsg, .recvmsg = sock_common_recvmsg, .mmap = sock_no_mmap, diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 7c8233f6d3c2..89106c7d3247 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -1114,6 +1114,10 @@ static struct inet_connection_sock_af_ops dccp_ipv6_af_ops = { .net_header_len = sizeof(struct ipv6hdr), .setsockopt = ipv6_setsockopt, .getsockopt = ipv6_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_ipv6_setsockopt, + .compat_getsockopt = compat_ipv6_getsockopt, +#endif .addr2sockaddr = inet6_csk_addr2sockaddr, .sockaddr_len = sizeof(struct sockaddr_in6) }; @@ -1130,6 +1134,10 @@ static struct inet_connection_sock_af_ops dccp_ipv6_mapped = { .net_header_len = sizeof(struct iphdr), .setsockopt = ipv6_setsockopt, .getsockopt = ipv6_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_ipv6_setsockopt, + .compat_getsockopt = compat_ipv6_getsockopt, +#endif .addr2sockaddr = inet6_csk_addr2sockaddr, .sockaddr_len = sizeof(struct sockaddr_in6) }; @@ -1167,6 +1175,10 @@ static struct proto dccp_v6_prot = { .init = dccp_v6_init_sock, .setsockopt = dccp_setsockopt, .getsockopt = dccp_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_dccp_setsockopt, + .compat_getsockopt = compat_dccp_getsockopt, +#endif .sendmsg = dccp_sendmsg, .recvmsg = dccp_recvmsg, .backlog_rcv = dccp_v6_do_rcv, @@ -1204,6 +1216,10 @@ static struct proto_ops inet6_dccp_ops = { .shutdown = inet_shutdown, .setsockopt = sock_common_setsockopt, .getsockopt = sock_common_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_sock_common_setsockopt, + .compat_getsockopt = compat_sock_common_getsockopt, +#endif .sendmsg = inet_sendmsg, .recvmsg = sock_common_recvmsg, .mmap = sock_no_mmap, diff --git a/net/dccp/proto.c b/net/dccp/proto.c index baccaf35ffbd..59b214995f28 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -455,18 +455,13 @@ out_free_val: goto out; } -int dccp_setsockopt(struct sock *sk, int level, int optname, - char __user *optval, int optlen) +static int do_dccp_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen) { struct dccp_sock *dp; int err; int val; - if (level != SOL_DCCP) - return inet_csk(sk)->icsk_af_ops->setsockopt(sk, level, - optname, optval, - optlen); - if (optlen < sizeof(int)) return -EINVAL; @@ -512,8 +507,34 @@ int dccp_setsockopt(struct sock *sk, int level, int optname, return err; } +int dccp_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen) +{ + if (level != SOL_DCCP) + return inet_csk(sk)->icsk_af_ops->setsockopt(sk, level, + optname, optval, + optlen); + return do_dccp_setsockopt(sk, level, optname, optval, optlen); +} EXPORT_SYMBOL_GPL(dccp_setsockopt); +#ifdef CONFIG_COMPAT +int compat_dccp_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen) +{ + if (level != SOL_DCCP) { + if (inet_csk(sk)->icsk_af_ops->compat_setsockopt) + return inet_csk(sk)->icsk_af_ops->compat_setsockopt(sk, + level, optname, optval, optlen); + else + return inet_csk(sk)->icsk_af_ops->setsockopt(sk, + level, optname, optval, optlen); + } + return do_dccp_setsockopt(sk, level, optname, optval, optlen); +} +EXPORT_SYMBOL_GPL(compat_dccp_setsockopt); +#endif + static int dccp_getsockopt_service(struct sock *sk, int len, __be32 __user *optval, int __user *optlen) @@ -545,16 +566,12 @@ out: return err; } -int dccp_getsockopt(struct sock *sk, int level, int optname, +static int do_dccp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) { struct dccp_sock *dp; int val, len; - if (level != SOL_DCCP) - return inet_csk(sk)->icsk_af_ops->getsockopt(sk, level, - optname, optval, - optlen); if (get_user(len, optlen)) return -EFAULT; @@ -587,8 +604,34 @@ int dccp_getsockopt(struct sock *sk, int level, int optname, return 0; } +int dccp_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) +{ + if (level != SOL_DCCP) + return inet_csk(sk)->icsk_af_ops->getsockopt(sk, level, + optname, optval, + optlen); + return do_dccp_getsockopt(sk, level, optname, optval, optlen); +} EXPORT_SYMBOL_GPL(dccp_getsockopt); +#ifdef CONFIG_COMPAT +int compat_dccp_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) +{ + if (level != SOL_DCCP) { + if (inet_csk(sk)->icsk_af_ops->compat_setsockopt) + return inet_csk(sk)->icsk_af_ops->compat_getsockopt(sk, + level, optname, optval, optlen); + else + return inet_csk(sk)->icsk_af_ops->getsockopt(sk, + level, optname, optval, optlen); + } + return do_dccp_getsockopt(sk, level, optname, optval, optlen); +} +EXPORT_SYMBOL_GPL(compat_dccp_getsockopt); +#endif + int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len) { diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 97c276f95b35..454e523b506a 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -802,6 +802,10 @@ const struct proto_ops inet_stream_ops = { .shutdown = inet_shutdown, .setsockopt = sock_common_setsockopt, .getsockopt = sock_common_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_sock_common_setsockopt, + .compat_getsockopt = compat_sock_common_getsockopt, +#endif .sendmsg = inet_sendmsg, .recvmsg = sock_common_recvmsg, .mmap = sock_no_mmap, @@ -823,6 +827,10 @@ const struct proto_ops inet_dgram_ops = { .shutdown = inet_shutdown, .setsockopt = sock_common_setsockopt, .getsockopt = sock_common_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_sock_common_setsockopt, + .compat_getsockopt = compat_sock_common_getsockopt, +#endif .sendmsg = inet_sendmsg, .recvmsg = sock_common_recvmsg, .mmap = sock_no_mmap, @@ -848,6 +856,10 @@ static const struct proto_ops inet_sockraw_ops = { .shutdown = inet_shutdown, .setsockopt = sock_common_setsockopt, .getsockopt = sock_common_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_sock_common_setsockopt, + .compat_getsockopt = compat_sock_common_getsockopt, +#endif .sendmsg = inet_sendmsg, .recvmsg = sock_common_recvmsg, .mmap = sock_no_mmap, diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index b5c4f61518e8..49ff1cd4e1c9 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -399,14 +399,12 @@ out: * an IP socket. */ -int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) +static int do_ip_setsockopt(struct sock *sk, int level, + int optname, char __user *optval, int optlen) { struct inet_sock *inet = inet_sk(sk); int val=0,err; - if (level != SOL_IP) - return -ENOPROTOOPT; - if (((1< (MRT_BASE + 10)) +#endif + ) { + lock_sock(sk); + err = nf_setsockopt(sk, PF_INET, optname, optval, optlen); + release_sock(sk); + } +#endif + return err; +} + +#ifdef CONFIG_COMPAT +int compat_ip_setsockopt(struct sock *sk, int level, + int optname, char __user *optval, int optlen) +{ + int err; + + if (level != SOL_IP) + return -ENOPROTOOPT; + + err = do_ip_setsockopt(sk, level, optname, optval, optlen); +#ifdef CONFIG_NETFILTER + /* we need to exclude all possible ENOPROTOOPTs except default case */ + if (err == -ENOPROTOOPT && optname != IP_HDRINCL && + optname != IP_IPSEC_POLICY && optname != IP_XFRM_POLICY +#ifdef CONFIG_IP_MROUTE + && (optname < MRT_BASE || optname > (MRT_BASE + 10)) +#endif + ) { + lock_sock(sk); + err = compat_nf_setsockopt(sk, PF_INET, + optname, optval, optlen); + release_sock(sk); + } +#endif + return err; +} +#endif + /* * Get the options. Note for future reference. The GET of IP options gets the * _received_ ones. The set sets the _sent_ ones. */ -int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) +static int do_ip_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) { struct inet_sock *inet = inet_sk(sk); int val; @@ -1080,17 +1127,8 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, val = inet->freebind; break; default: -#ifdef CONFIG_NETFILTER - val = nf_getsockopt(sk, PF_INET, optname, optval, - &len); - release_sock(sk); - if (val >= 0) - val = put_user(len, optlen); - return val; -#else release_sock(sk); return -ENOPROTOOPT; -#endif } release_sock(sk); @@ -1111,7 +1149,73 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, return 0; } +int ip_getsockopt(struct sock *sk, int level, + int optname, char __user *optval, int __user *optlen) +{ + int err; + + err = do_ip_getsockopt(sk, level, optname, optval, optlen); +#ifdef CONFIG_NETFILTER + /* we need to exclude all possible ENOPROTOOPTs except default case */ + if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS +#ifdef CONFIG_IP_MROUTE + && (optname < MRT_BASE || optname > MRT_BASE+10) +#endif + ) { + int len; + + if(get_user(len,optlen)) + return -EFAULT; + + lock_sock(sk); + err = nf_getsockopt(sk, PF_INET, optname, optval, + &len); + release_sock(sk); + if (err >= 0) + err = put_user(len, optlen); + return err; + } +#endif + return err; +} + +#ifdef CONFIG_COMPAT +int compat_ip_getsockopt(struct sock *sk, int level, + int optname, char __user *optval, int __user *optlen) +{ + int err; + + err = do_ip_getsockopt(sk, level, optname, optval, optlen); +#ifdef CONFIG_NETFILTER + /* we need to exclude all possible ENOPROTOOPTs except default case */ + if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS +#ifdef CONFIG_IP_MROUTE + && (optname < MRT_BASE || optname > MRT_BASE+10) +#endif + ) { + int len; + + if(get_user(len,optlen)) + return -EFAULT; + + lock_sock(sk); + err = compat_nf_getsockopt(sk, PF_INET, + optname, optval, &len); + release_sock(sk); + if (err >= 0) + err = put_user(len, optlen); + return err; + } +#endif + return err; +} +#endif + EXPORT_SYMBOL(ip_cmsg_recv); EXPORT_SYMBOL(ip_getsockopt); EXPORT_SYMBOL(ip_setsockopt); +#ifdef CONFIG_COMPAT +EXPORT_SYMBOL(compat_ip_getsockopt); +EXPORT_SYMBOL(compat_ip_setsockopt); +#endif diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index f29a12da5109..f1b02b34fc0a 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -660,12 +660,9 @@ static int raw_geticmpfilter(struct sock *sk, char __user *optval, int __user *o out: return ret; } -static int raw_setsockopt(struct sock *sk, int level, int optname, +static int do_raw_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) { - if (level != SOL_RAW) - return ip_setsockopt(sk, level, optname, optval, optlen); - if (optname == ICMP_FILTER) { if (inet_sk(sk)->num != IPPROTO_ICMP) return -EOPNOTSUPP; @@ -675,12 +672,28 @@ static int raw_setsockopt(struct sock *sk, int level, int optname, return -ENOPROTOOPT; } -static int raw_getsockopt(struct sock *sk, int level, int optname, - char __user *optval, int __user *optlen) +static int raw_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen) { if (level != SOL_RAW) - return ip_getsockopt(sk, level, optname, optval, optlen); + return ip_setsockopt(sk, level, optname, optval, optlen); + return do_raw_setsockopt(sk, level, optname, optval, optlen); +} +#ifdef CONFIG_COMPAT +static int compat_raw_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen) +{ + if (level != SOL_RAW) + return compat_ip_setsockopt(sk, level, + optname, optval, optlen); + return do_raw_setsockopt(sk, level, optname, optval, optlen); +} +#endif + +static int do_raw_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) +{ if (optname == ICMP_FILTER) { if (inet_sk(sk)->num != IPPROTO_ICMP) return -EOPNOTSUPP; @@ -690,6 +703,25 @@ static int raw_getsockopt(struct sock *sk, int level, int optname, return -ENOPROTOOPT; } +static int raw_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) +{ + if (level != SOL_RAW) + return ip_getsockopt(sk, level, optname, optval, optlen); + return do_raw_getsockopt(sk, level, optname, optval, optlen); +} + +#ifdef CONFIG_COMPAT +static int compat_raw_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) +{ + if (level != SOL_RAW) + return compat_ip_getsockopt(sk, level, + optname, optval, optlen); + return do_raw_getsockopt(sk, level, optname, optval, optlen); +} +#endif + static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg) { switch (cmd) { @@ -728,6 +760,10 @@ struct proto raw_prot = { .init = raw_init, .setsockopt = raw_setsockopt, .getsockopt = raw_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_raw_setsockopt, + .compat_getsockopt = compat_raw_getsockopt, +#endif .sendmsg = raw_sendmsg, .recvmsg = raw_recvmsg, .bind = raw_bind, diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 00aa80e93243..31b0123a9699 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1687,18 +1687,14 @@ int tcp_disconnect(struct sock *sk, int flags) /* * Socket option code for TCP. */ -int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, - int optlen) +static int do_tcp_setsockopt(struct sock *sk, int level, + int optname, char __user *optval, int optlen) { struct tcp_sock *tp = tcp_sk(sk); struct inet_connection_sock *icsk = inet_csk(sk); int val; int err = 0; - if (level != SOL_TCP) - return icsk->icsk_af_ops->setsockopt(sk, level, optname, - optval, optlen); - /* This is a string value all the others are int's */ if (optname == TCP_CONGESTION) { char name[TCP_CA_NAME_MAX]; @@ -1871,6 +1867,35 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, return err; } +int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, + int optlen) +{ + struct inet_connection_sock *icsk = inet_csk(sk); + + if (level != SOL_TCP) + return icsk->icsk_af_ops->setsockopt(sk, level, optname, + optval, optlen); + return do_tcp_setsockopt(sk, level, optname, optval, optlen); +} + +#ifdef CONFIG_COMPAT +int compat_tcp_setsockopt(struct sock *sk, int level, + int optname, char __user *optval, int optlen) +{ + struct inet_connection_sock *icsk = inet_csk(sk); + + if (level != SOL_TCP) { + if (icsk->icsk_af_ops->compat_setsockopt) + return icsk->icsk_af_ops->compat_setsockopt(sk, + level, optname, optval, optlen); + else + return icsk->icsk_af_ops->setsockopt(sk, + level, optname, optval, optlen); + } + return do_tcp_setsockopt(sk, level, optname, optval, optlen); +} +#endif + /* Return information about state of tcp endpoint in API format. */ void tcp_get_info(struct sock *sk, struct tcp_info *info) { @@ -1931,17 +1956,13 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info) EXPORT_SYMBOL_GPL(tcp_get_info); -int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, - int __user *optlen) +static int do_tcp_getsockopt(struct sock *sk, int level, + int optname, char __user *optval, int __user *optlen) { struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); int val, len; - if (level != SOL_TCP) - return icsk->icsk_af_ops->getsockopt(sk, level, optname, - optval, optlen); - if (get_user(len, optlen)) return -EFAULT; @@ -2025,6 +2046,34 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, return 0; } +int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, + int __user *optlen) +{ + struct inet_connection_sock *icsk = inet_csk(sk); + + if (level != SOL_TCP) + return icsk->icsk_af_ops->getsockopt(sk, level, optname, + optval, optlen); + return do_tcp_getsockopt(sk, level, optname, optval, optlen); +} + +#ifdef CONFIG_COMPAT +int compat_tcp_getsockopt(struct sock *sk, int level, + int optname, char __user *optval, int __user *optlen) +{ + struct inet_connection_sock *icsk = inet_csk(sk); + + if (level != SOL_TCP) { + if (icsk->icsk_af_ops->compat_getsockopt) + return icsk->icsk_af_ops->compat_getsockopt(sk, + level, optname, optval, optlen); + else + return icsk->icsk_af_ops->getsockopt(sk, + level, optname, optval, optlen); + } + return do_tcp_getsockopt(sk, level, optname, optval, optlen); +} +#endif extern void __skb_cb_too_small_for_tcp(int, int); extern struct tcp_congestion_ops tcp_reno; @@ -2142,3 +2191,7 @@ EXPORT_SYMBOL(tcp_sendpage); EXPORT_SYMBOL(tcp_setsockopt); EXPORT_SYMBOL(tcp_shutdown); EXPORT_SYMBOL(tcp_statistics); +#ifdef CONFIG_COMPAT +EXPORT_SYMBOL(compat_tcp_setsockopt); +EXPORT_SYMBOL(compat_tcp_getsockopt); +#endif diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 4eb903db1b12..249ef6c88959 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1226,6 +1226,10 @@ struct inet_connection_sock_af_ops ipv4_specific = { .net_header_len = sizeof(struct iphdr), .setsockopt = ip_setsockopt, .getsockopt = ip_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_ip_setsockopt, + .compat_getsockopt = compat_ip_getsockopt, +#endif .addr2sockaddr = inet_csk_addr2sockaddr, .sockaddr_len = sizeof(struct sockaddr_in), }; @@ -1808,6 +1812,10 @@ struct proto tcp_prot = { .shutdown = tcp_shutdown, .setsockopt = tcp_setsockopt, .getsockopt = tcp_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_tcp_setsockopt, + .compat_getsockopt = compat_tcp_getsockopt, +#endif .sendmsg = tcp_sendmsg, .recvmsg = tcp_recvmsg, .backlog_rcv = tcp_v4_do_rcv, diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 00840474a449..0b0721bd45c6 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1207,16 +1207,13 @@ static int udp_destroy_sock(struct sock *sk) /* * Socket option code for UDP */ -static int udp_setsockopt(struct sock *sk, int level, int optname, +static int do_udp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) { struct udp_sock *up = udp_sk(sk); int val; int err = 0; - if (level != SOL_UDP) - return ip_setsockopt(sk, level, optname, optval, optlen); - if(optlensk_type != SOCK_RAW) - return udp_prot.setsockopt(sk, level, optname, optval, optlen); - - if(level!=SOL_IPV6) - goto out; - if (optval == NULL) val=0; else if (get_user(val, (int __user *) optval)) @@ -613,17 +607,9 @@ done: retv = xfrm_user_policy(sk, optname, optval, optlen); break; -#ifdef CONFIG_NETFILTER - default: - retv = nf_setsockopt(sk, PF_INET6, optname, optval, - optlen); - break; -#endif - } release_sock(sk); -out: return retv; e_inval: @@ -631,6 +617,65 @@ e_inval: return -EINVAL; } +int ipv6_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen) +{ + int err; + + if (level == SOL_IP && sk->sk_type != SOCK_RAW) + return udp_prot.setsockopt(sk, level, optname, optval, optlen); + + if (level != SOL_IPV6) + return -ENOPROTOOPT; + + err = do_ipv6_setsockopt(sk, level, optname, optval, optlen); +#ifdef CONFIG_NETFILTER + /* we need to exclude all possible ENOPROTOOPTs except default case */ + if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY && + optname != IPV6_XFRM_POLICY) { + lock_sock(sk); + err = nf_setsockopt(sk, PF_INET6, optname, optval, + optlen); + release_sock(sk); + } +#endif + return err; +} + + +#ifdef CONFIG_COMPAT +int compat_ipv6_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen) +{ + int err; + + if (level == SOL_IP && sk->sk_type != SOCK_RAW) { + if (udp_prot.compat_setsockopt) + return udp_prot.compat_setsockopt(sk, level, + optname, optval, optlen); + else + return udp_prot.setsockopt(sk, level, + optname, optval, optlen); + } + + if (level != SOL_IPV6) + return -ENOPROTOOPT; + + err = do_ipv6_setsockopt(sk, level, optname, optval, optlen); +#ifdef CONFIG_NETFILTER + /* we need to exclude all possible ENOPROTOOPTs except default case */ + if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY && + optname != IPV6_XFRM_POLICY) { + lock_sock(sk); + err = compat_nf_setsockopt(sk, PF_INET6, optname, optval, + optlen); + release_sock(sk); + } +#endif + return err; +} +#endif + static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr, char __user *optval, int len) { @@ -642,17 +687,13 @@ static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr, return len; } -int ipv6_getsockopt(struct sock *sk, int level, int optname, +static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) { struct ipv6_pinfo *np = inet6_sk(sk); int len; int val; - if (level == SOL_IP && sk->sk_type != SOCK_RAW) - return udp_prot.getsockopt(sk, level, optname, optval, optlen); - if(level!=SOL_IPV6) - return -ENOPROTOOPT; if (get_user(len, optlen)) return -EFAULT; switch (optname) { @@ -842,17 +883,7 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname, break; default: -#ifdef CONFIG_NETFILTER - lock_sock(sk); - val = nf_getsockopt(sk, PF_INET6, optname, optval, - &len); - release_sock(sk); - if (val >= 0) - val = put_user(len, optlen); - return val; -#else return -EINVAL; -#endif } len = min_t(unsigned int, sizeof(int), len); if(put_user(len, optlen)) @@ -862,6 +893,78 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname, return 0; } +int ipv6_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) +{ + int err; + + if (level == SOL_IP && sk->sk_type != SOCK_RAW) + return udp_prot.getsockopt(sk, level, optname, optval, optlen); + + if(level != SOL_IPV6) + return -ENOPROTOOPT; + + err = do_ipv6_getsockopt(sk, level, optname, optval, optlen); +#ifdef CONFIG_NETFILTER + /* we need to exclude all possible EINVALs except default case */ + if (err == -ENOPROTOOPT && optname != IPV6_ADDRFORM && + optname != MCAST_MSFILTER) { + int len; + + if (get_user(len, optlen)) + return -EFAULT; + + lock_sock(sk); + err = nf_getsockopt(sk, PF_INET6, optname, optval, + &len); + release_sock(sk); + if (err >= 0) + err = put_user(len, optlen); + } +#endif + return err; +} + +#ifdef CONFIG_COMPAT +int compat_ipv6_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) +{ + int err; + + if (level == SOL_IP && sk->sk_type != SOCK_RAW) { + if (udp_prot.compat_getsockopt) + return udp_prot.compat_getsockopt(sk, level, + optname, optval, optlen); + else + return udp_prot.getsockopt(sk, level, + optname, optval, optlen); + } + + if(level != SOL_IPV6) + return -ENOPROTOOPT; + + err = do_ipv6_getsockopt(sk, level, optname, optval, optlen); +#ifdef CONFIG_NETFILTER + /* we need to exclude all possible EINVALs except default case */ + if (err == -ENOPROTOOPT && optname != IPV6_ADDRFORM && + optname != MCAST_MSFILTER) { + int len; + + if (get_user(len, optlen)) + return -EFAULT; + + lock_sock(sk); + err = compat_nf_getsockopt(sk, PF_INET6, optname, optval, + &len); + release_sock(sk); + if (err >= 0) + err = put_user(len, optlen); + } +#endif + return err; +} +#endif + void __init ipv6_packet_init(void) { dev_add_pack(&ipv6_packet_type); diff --git a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c index 16482785bdfd..61419e11e35d 100644 --- a/net/ipv6/ipv6_syms.c +++ b/net/ipv6/ipv6_syms.c @@ -18,6 +18,10 @@ EXPORT_SYMBOL(ip6_route_output); EXPORT_SYMBOL(addrconf_lock); EXPORT_SYMBOL(ipv6_setsockopt); EXPORT_SYMBOL(ipv6_getsockopt); +#ifdef CONFIG_COMPAT +EXPORT_SYMBOL(compat_ipv6_setsockopt); +EXPORT_SYMBOL(compat_ipv6_getsockopt); +#endif EXPORT_SYMBOL(inet6_register_protosw); EXPORT_SYMBOL(inet6_unregister_protosw); EXPORT_SYMBOL(inet6_add_protocol); diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index ae20a0ec9bd8..8de5a8e59149 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -859,29 +859,12 @@ static int rawv6_geticmpfilter(struct sock *sk, int level, int optname, } -static int rawv6_setsockopt(struct sock *sk, int level, int optname, +static int do_rawv6_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) { struct raw6_sock *rp = raw6_sk(sk); int val; - switch(level) { - case SOL_RAW: - break; - - case SOL_ICMPV6: - if (inet_sk(sk)->num != IPPROTO_ICMPV6) - return -EOPNOTSUPP; - return rawv6_seticmpfilter(sk, level, optname, optval, - optlen); - case SOL_IPV6: - if (optname == IPV6_CHECKSUM) - break; - default: - return ipv6_setsockopt(sk, level, optname, optval, - optlen); - }; - if (get_user(val, (int __user *)optval)) return -EFAULT; @@ -906,12 +889,9 @@ static int rawv6_setsockopt(struct sock *sk, int level, int optname, } } -static int rawv6_getsockopt(struct sock *sk, int level, int optname, - char __user *optval, int __user *optlen) +static int rawv6_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen) { - struct raw6_sock *rp = raw6_sk(sk); - int val, len; - switch(level) { case SOL_RAW: break; @@ -919,15 +899,47 @@ static int rawv6_getsockopt(struct sock *sk, int level, int optname, case SOL_ICMPV6: if (inet_sk(sk)->num != IPPROTO_ICMPV6) return -EOPNOTSUPP; - return rawv6_geticmpfilter(sk, level, optname, optval, + return rawv6_seticmpfilter(sk, level, optname, optval, optlen); case SOL_IPV6: if (optname == IPV6_CHECKSUM) break; default: - return ipv6_getsockopt(sk, level, optname, optval, + return ipv6_setsockopt(sk, level, optname, optval, optlen); }; + return do_rawv6_setsockopt(sk, level, optname, optval, optlen); +} + +#ifdef CONFIG_COMPAT +static int compat_rawv6_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen) +{ + switch(level) { + case SOL_RAW: + break; + + case SOL_ICMPV6: + if (inet_sk(sk)->num != IPPROTO_ICMPV6) + return -EOPNOTSUPP; + return rawv6_seticmpfilter(sk, level, optname, optval, + optlen); + case SOL_IPV6: + if (optname == IPV6_CHECKSUM) + break; + default: + return compat_ipv6_setsockopt(sk, level, + optname, optval, optlen); + }; + return do_rawv6_setsockopt(sk, level, optname, optval, optlen); +} +#endif + +static int do_rawv6_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) +{ + struct raw6_sock *rp = raw6_sk(sk); + int val, len; if (get_user(len,optlen)) return -EFAULT; @@ -953,6 +965,52 @@ static int rawv6_getsockopt(struct sock *sk, int level, int optname, return 0; } +static int rawv6_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) +{ + switch(level) { + case SOL_RAW: + break; + + case SOL_ICMPV6: + if (inet_sk(sk)->num != IPPROTO_ICMPV6) + return -EOPNOTSUPP; + return rawv6_geticmpfilter(sk, level, optname, optval, + optlen); + case SOL_IPV6: + if (optname == IPV6_CHECKSUM) + break; + default: + return ipv6_getsockopt(sk, level, optname, optval, + optlen); + }; + return do_rawv6_getsockopt(sk, level, optname, optval, optlen); +} + +#ifdef CONFIG_COMPAT +static int compat_rawv6_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) +{ + switch(level) { + case SOL_RAW: + break; + + case SOL_ICMPV6: + if (inet_sk(sk)->num != IPPROTO_ICMPV6) + return -EOPNOTSUPP; + return rawv6_geticmpfilter(sk, level, optname, optval, + optlen); + case SOL_IPV6: + if (optname == IPV6_CHECKSUM) + break; + default: + return compat_ipv6_getsockopt(sk, level, + optname, optval, optlen); + }; + return do_rawv6_getsockopt(sk, level, optname, optval, optlen); +} +#endif + static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) { switch(cmd) { @@ -1008,6 +1066,10 @@ struct proto rawv6_prot = { .destroy = inet6_destroy_sock, .setsockopt = rawv6_setsockopt, .getsockopt = rawv6_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_rawv6_setsockopt, + .compat_getsockopt = compat_rawv6_getsockopt, +#endif .sendmsg = rawv6_sendmsg, .recvmsg = rawv6_recvmsg, .bind = rawv6_bind, diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index af6a0c60f903..2f8975e0150a 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1308,6 +1308,10 @@ static struct inet_connection_sock_af_ops ipv6_specific = { .setsockopt = ipv6_setsockopt, .getsockopt = ipv6_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_ipv6_setsockopt, + .compat_getsockopt = compat_ipv6_getsockopt, +#endif .addr2sockaddr = inet6_csk_addr2sockaddr, .sockaddr_len = sizeof(struct sockaddr_in6) }; @@ -1327,6 +1331,10 @@ static struct inet_connection_sock_af_ops ipv6_mapped = { .setsockopt = ipv6_setsockopt, .getsockopt = ipv6_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_ipv6_setsockopt, + .compat_getsockopt = compat_ipv6_getsockopt, +#endif .addr2sockaddr = inet6_csk_addr2sockaddr, .sockaddr_len = sizeof(struct sockaddr_in6) }; @@ -1566,6 +1574,10 @@ struct proto tcpv6_prot = { .shutdown = tcp_shutdown, .setsockopt = tcp_setsockopt, .getsockopt = tcp_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_tcp_setsockopt, + .compat_getsockopt = compat_tcp_getsockopt, +#endif .sendmsg = tcp_sendmsg, .recvmsg = tcp_recvmsg, .backlog_rcv = tcp_v6_do_rcv, diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index c47648892c04..538ada00646a 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -880,16 +880,13 @@ static int udpv6_destroy_sock(struct sock *sk) /* * Socket option code for UDP */ -static int udpv6_setsockopt(struct sock *sk, int level, int optname, +static int do_udpv6_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) { struct udp_sock *up = udp_sk(sk); int val; int err = 0; - if (level != SOL_UDP) - return ipv6_setsockopt(sk, level, optname, optval, optlen); - if(optlenpf == pf) { + if (get) { + if (val >= ops->get_optmin + && val < ops->get_optmax) { + ops->use++; + mutex_unlock(&nf_sockopt_mutex); + if (ops->compat_get) + ret = ops->compat_get(sk, + val, opt, len); + else + ret = ops->get(sk, + val, opt, len); + goto out; + } + } else { + if (val >= ops->set_optmin + && val < ops->set_optmax) { + ops->use++; + mutex_unlock(&nf_sockopt_mutex); + if (ops->compat_set) + ret = ops->compat_set(sk, + val, opt, *len); + else + ret = ops->set(sk, + val, opt, *len); + goto out; + } + } + } + } + mutex_unlock(&nf_sockopt_mutex); + return -ENOPROTOOPT; + + out: + mutex_lock(&nf_sockopt_mutex); + ops->use--; + if (ops->cleanup_task) + wake_up_process(ops->cleanup_task); + mutex_unlock(&nf_sockopt_mutex); + return ret; +} + +int compat_nf_setsockopt(struct sock *sk, int pf, + int val, char __user *opt, int len) +{ + return compat_nf_sockopt(sk, pf, val, opt, &len, 0); +} +EXPORT_SYMBOL(compat_nf_setsockopt); + +int compat_nf_getsockopt(struct sock *sk, int pf, + int val, char __user *opt, int *len) +{ + return compat_nf_sockopt(sk, pf, val, opt, len, 1); +} +EXPORT_SYMBOL(compat_nf_getsockopt); +#endif diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 2e266129a764..bbee14d01c9b 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -875,6 +875,10 @@ static const struct proto_ops inet6_seqpacket_ops = { .shutdown = inet_shutdown, .setsockopt = sock_common_setsockopt, .getsockopt = sock_common_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_sock_common_setsockopt, + .compat_getsockopt = compat_sock_common_getsockopt, +#endif .sendmsg = inet_sendmsg, .recvmsg = sock_common_recvmsg, .mmap = sock_no_mmap, @@ -914,6 +918,10 @@ static struct sctp_af sctp_ipv6_specific = { .sctp_xmit = sctp_v6_xmit, .setsockopt = ipv6_setsockopt, .getsockopt = ipv6_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_ipv6_setsockopt, + .compat_getsockopt = compat_ipv6_getsockopt, +#endif .get_dst = sctp_v6_get_dst, .get_saddr = sctp_v6_get_saddr, .copy_addrlist = sctp_v6_copy_addrlist, diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index de693b43c8ea..d90f5491870f 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -845,6 +845,10 @@ static const struct proto_ops inet_seqpacket_ops = { .shutdown = inet_shutdown, /* Looks harmless. */ .setsockopt = sock_common_setsockopt, /* IP_SOL IP_OPTION is a problem. */ .getsockopt = sock_common_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_sock_common_setsockopt, + .compat_getsockopt = compat_sock_common_getsockopt, +#endif .sendmsg = inet_sendmsg, .recvmsg = sock_common_recvmsg, .mmap = sock_no_mmap, @@ -883,6 +887,10 @@ static struct sctp_af sctp_ipv4_specific = { .sctp_xmit = sctp_v4_xmit, .setsockopt = ip_setsockopt, .getsockopt = ip_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_ip_setsockopt, + .compat_getsockopt = compat_ip_getsockopt, +#endif .get_dst = sctp_v4_get_dst, .get_saddr = sctp_v4_get_saddr, .copy_addrlist = sctp_v4_copy_addrlist, -- cgit v1.2.3 From dec73ff0293d59076d1fd8f4a264898ecfc457ec Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 20 Mar 2006 22:46:16 -0800 Subject: [ICSK] compat: Introduce inet_csk_compat_[gs]etsockopt Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/net/inet_connection_sock.h | 5 +++++ net/dccp/proto.c | 23 +++++++---------------- net/ipv4/inet_connection_sock.c | 30 ++++++++++++++++++++++++++++++ net/ipv4/tcp.c | 26 ++++++-------------------- 4 files changed, 48 insertions(+), 36 deletions(-) (limited to 'include') diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index ae61331366f0..9bf73fe50948 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -331,4 +331,9 @@ extern int inet_csk_ctl_sock_create(struct socket **sock, unsigned short family, unsigned short type, unsigned char protocol); + +extern int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen); +extern int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen); #endif /* _INET_CONNECTION_SOCK_H */ diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 59b214995f28..6d7aef9647de 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -522,14 +522,10 @@ EXPORT_SYMBOL_GPL(dccp_setsockopt); int compat_dccp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) { - if (level != SOL_DCCP) { - if (inet_csk(sk)->icsk_af_ops->compat_setsockopt) - return inet_csk(sk)->icsk_af_ops->compat_setsockopt(sk, - level, optname, optval, optlen); - else - return inet_csk(sk)->icsk_af_ops->setsockopt(sk, - level, optname, optval, optlen); - } + if (level != SOL_DCCP) + return inet_csk_compat_setsockopt(sk, level, optname, + optval, optlen); + return do_dccp_setsockopt(sk, level, optname, optval, optlen); } EXPORT_SYMBOL_GPL(compat_dccp_setsockopt); @@ -619,14 +615,9 @@ EXPORT_SYMBOL_GPL(dccp_getsockopt); int compat_dccp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) { - if (level != SOL_DCCP) { - if (inet_csk(sk)->icsk_af_ops->compat_setsockopt) - return inet_csk(sk)->icsk_af_ops->compat_getsockopt(sk, - level, optname, optval, optlen); - else - return inet_csk(sk)->icsk_af_ops->getsockopt(sk, - level, optname, optval, optlen); - } + if (level != SOL_DCCP) + return inet_csk_compat_getsockopt(sk, level, optname, + optval, optlen); return do_dccp_getsockopt(sk, level, optname, optval, optlen); } EXPORT_SYMBOL_GPL(compat_dccp_getsockopt); diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 359f48cec99a..9f6b44ca28a8 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -667,3 +667,33 @@ int inet_csk_ctl_sock_create(struct socket **sock, unsigned short family, } EXPORT_SYMBOL_GPL(inet_csk_ctl_sock_create); + +#ifdef CONFIG_COMPAT +int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) +{ + const struct inet_csk *icsk = inet_csk(sk); + + if (icsk->icsk_af_ops->compat_getsockopt != NULL) + return icsk->icsk_af_ops->compat_getsockopt(sk, level, optname, + optval, optlen); + return icsk->icsk_af_ops->getsockopt(sk, level, optname, + optval, optlen); +} + +EXPORT_SYMBOL_GPL(inet_csk_compat_getsockopt); + +int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen) +{ + const struct inet_csk *icsk = inet_csk(sk); + + if (icsk->icsk_af_ops->compat_setsockopt != NULL) + return icsk->icsk_af_ops->compat_setsockopt(sk, level, optname, + optval, optlen); + return icsk->icsk_af_ops->setsockopt(sk, level, optname, + optval, optlen); +} + +EXPORT_SYMBOL_GPL(inet_csk_compat_setsockopt); +#endif diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 31b0123a9699..89da253e33f0 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1882,16 +1882,9 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int compat_tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) { - struct inet_connection_sock *icsk = inet_csk(sk); - - if (level != SOL_TCP) { - if (icsk->icsk_af_ops->compat_setsockopt) - return icsk->icsk_af_ops->compat_setsockopt(sk, - level, optname, optval, optlen); - else - return icsk->icsk_af_ops->setsockopt(sk, - level, optname, optval, optlen); - } + if (level != SOL_TCP) + return inet_csk_compat_setsockopt(sk, level, optname, + optval, optlen); return do_tcp_setsockopt(sk, level, optname, optval, optlen); } #endif @@ -2061,16 +2054,9 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int compat_tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) { - struct inet_connection_sock *icsk = inet_csk(sk); - - if (level != SOL_TCP) { - if (icsk->icsk_af_ops->compat_getsockopt) - return icsk->icsk_af_ops->compat_getsockopt(sk, - level, optname, optval, optlen); - else - return icsk->icsk_af_ops->getsockopt(sk, - level, optname, optval, optlen); - } + if (level != SOL_TCP) + return inet_csk_compat_getsockopt(sk, level, optname, + optval, optlen); return do_tcp_getsockopt(sk, level, optname, optval, optlen); } #endif -- cgit v1.2.3 From a4bf3902427a128455b8de299ff0918072b2e974 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 20 Mar 2006 22:50:58 -0800 Subject: [DCCP] minisock: Rename struct dccp_options to struct dccp_minisock This will later be included in struct dccp_request_sock so that we can have per connection feature negotiation state while in the 3way handshake, when we clone the DCCP_ROLE_LISTEN socket (in dccp_create_openreq_child) we'll just copy this state from dreq_minisock to dccps_minisock. Also the feature negotiation and option parsing code will mostly touch dccps_minisock, which will simplify some stuff. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/linux/dccp.h | 43 +++++++++++++++++----------- net/dccp/dccp.h | 11 ++++--- net/dccp/diag.c | 2 +- net/dccp/feat.c | 81 ++++++++++++++++++++++++---------------------------- net/dccp/input.c | 8 +++--- net/dccp/minisocks.c | 9 +++--- net/dccp/options.c | 30 +++++++++---------- net/dccp/proto.c | 23 +++++++-------- 8 files changed, 104 insertions(+), 103 deletions(-) (limited to 'include') diff --git a/include/linux/dccp.h b/include/linux/dccp.h index e35f680f909b..676333b9fad0 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -328,21 +328,24 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb) #define DCCP_NDP_LIMIT 0xFFFFFF /** - * struct dccp_options - option values for a DCCP connection - * @dccpo_sequence_window - Sequence Window Feature (section 7.5.2) - * @dccpo_ccid - Congestion Control Id (CCID) (section 10) - * @dccpo_send_ack_vector - Send Ack Vector Feature (section 11.5) - * @dccpo_send_ndp_count - Send NDP Count Feature (7.7.2) + * struct dccp_minisock - Minimal DCCP connection representation + * + * Will be used to pass the state from dccp_request_sock to dccp_sock. + * + * @dccpms_sequence_window - Sequence Window Feature (section 7.5.2) + * @dccpms_ccid - Congestion Control Id (CCID) (section 10) + * @dccpms_send_ack_vector - Send Ack Vector Feature (section 11.5) + * @dccpms_send_ndp_count - Send NDP Count Feature (7.7.2) */ -struct dccp_options { - __u64 dccpo_sequence_window; - __u8 dccpo_rx_ccid; - __u8 dccpo_tx_ccid; - __u8 dccpo_send_ack_vector; - __u8 dccpo_send_ndp_count; - __u8 dccpo_ack_ratio; - struct list_head dccpo_pending; - struct list_head dccpo_conf; +struct dccp_minisock { + __u64 dccpms_sequence_window; + __u8 dccpms_rx_ccid; + __u8 dccpms_tx_ccid; + __u8 dccpms_send_ack_vector; + __u8 dccpms_send_ndp_count; + __u8 dccpms_ack_ratio; + struct list_head dccpms_pending; + struct list_head dccpms_conf; }; struct dccp_opt_conf { @@ -360,8 +363,9 @@ struct dccp_opt_pend { struct dccp_opt_conf *dccpop_sc; }; -extern void __dccp_options_init(struct dccp_options *dccpo); -extern void dccp_options_init(struct dccp_options *dccpo); +extern void __dccp_minisock_init(struct dccp_minisock *dmsk); +extern void dccp_minisock_init(struct dccp_minisock *dmsk); + extern int dccp_parse_options(struct sock *sk, struct sk_buff *skb); struct dccp_request_sock { @@ -457,7 +461,7 @@ struct dccp_sock { __u16 dccps_r_ack_ratio; unsigned long dccps_ndp_count; __u32 dccps_mss_cache; - struct dccp_options dccps_options; + struct dccp_minisock dccps_minisock; struct dccp_ackvec *dccps_hc_rx_ackvec; struct ccid *dccps_hc_rx_ccid; struct ccid *dccps_hc_tx_ccid; @@ -473,6 +477,11 @@ static inline struct dccp_sock *dccp_sk(const struct sock *sk) return (struct dccp_sock *)sk; } +static inline struct dccp_minisock *dccp_msk(const struct sock *sk) +{ + return (struct dccp_minisock *)&dccp_sk(sk)->dccps_minisock; +} + static inline int dccp_service_not_initialized(const struct sock *sk) { return dccp_sk(sk)->dccps_service == DCCP_SERVICE_INVALID_VALUE; diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 47de17208d7a..1fe509148689 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -303,14 +303,13 @@ static inline void dccp_hdr_set_ack(struct dccp_hdr_ack_bits *dhack, static inline void dccp_update_gsr(struct sock *sk, u64 seq) { struct dccp_sock *dp = dccp_sk(sk); + const struct dccp_minisock *dmsk = dccp_msk(sk); dp->dccps_gsr = seq; dccp_set_seqno(&dp->dccps_swl, - (dp->dccps_gsr + 1 - - (dp->dccps_options.dccpo_sequence_window / 4))); + dp->dccps_gsr + 1 - (dmsk->dccpms_sequence_window / 4)); dccp_set_seqno(&dp->dccps_swh, - (dp->dccps_gsr + - (3 * dp->dccps_options.dccpo_sequence_window) / 4)); + dp->dccps_gsr + (3 * dmsk->dccpms_sequence_window) / 4); } static inline void dccp_update_gss(struct sock *sk, u64 seq) @@ -320,7 +319,7 @@ static inline void dccp_update_gss(struct sock *sk, u64 seq) dp->dccps_awh = dp->dccps_gss = seq; dccp_set_seqno(&dp->dccps_awl, (dp->dccps_gss - - dp->dccps_options.dccpo_sequence_window + 1)); + dccp_msk(sk)->dccpms_sequence_window + 1)); } static inline int dccp_ack_pending(const struct sock *sk) @@ -328,7 +327,7 @@ static inline int dccp_ack_pending(const struct sock *sk) const struct dccp_sock *dp = dccp_sk(sk); return dp->dccps_timestamp_echo != 0 || #ifdef CONFIG_IP_DCCP_ACKVEC - (dp->dccps_options.dccpo_send_ack_vector && + (dccp_msk(sk)->dccpms_send_ack_vector && dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) || #endif inet_csk_ack_scheduled(sk); diff --git a/net/dccp/diag.c b/net/dccp/diag.c index 3f78c00e3822..0f25dc395967 100644 --- a/net/dccp/diag.c +++ b/net/dccp/diag.c @@ -30,7 +30,7 @@ static void dccp_get_info(struct sock *sk, struct tcp_info *info) info->tcpi_backoff = icsk->icsk_backoff; info->tcpi_pmtu = icsk->icsk_pmtu_cookie; - if (dp->dccps_options.dccpo_send_ack_vector) + if (dccp_msk(sk)->dccpms_send_ack_vector) info->tcpi_options |= TCPI_OPT_SACK; ccid_hc_rx_get_info(dp->dccps_hc_rx_ccid, sk, info); diff --git a/net/dccp/feat.c b/net/dccp/feat.c index ed0851fa3cb3..b09064c4643d 100644 --- a/net/dccp/feat.c +++ b/net/dccp/feat.c @@ -22,7 +22,7 @@ int dccp_feat_change(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len, gfp_t gfp) { - struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); struct dccp_opt_pend *opt; dccp_pr_debug("feat change type=%d feat=%d\n", type, feature); @@ -30,8 +30,7 @@ int dccp_feat_change(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len, /* XXX sanity check feat change request */ /* check if that feature is already being negotiated */ - list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, - dccpop_node) { + list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { /* ok we found a negotiation for this option already */ if (opt->dccpop_feat == feature && opt->dccpop_type == type) { dccp_pr_debug("Replacing old\n"); @@ -59,7 +58,7 @@ int dccp_feat_change(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len, BUG_ON(opt->dccpop_val == NULL); - list_add_tail(&opt->dccpop_node, &dp->dccps_options.dccpo_pending); + list_add_tail(&opt->dccpop_node, &dmsk->dccpms_pending); return 0; } @@ -68,10 +67,10 @@ EXPORT_SYMBOL_GPL(dccp_feat_change); static int dccp_feat_update_ccid(struct sock *sk, u8 type, u8 new_ccid_nr) { struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); /* figure out if we are changing our CCID or the peer's */ const int rx = type == DCCPO_CHANGE_R; - const u8 ccid_nr = rx ? dp->dccps_options.dccpo_rx_ccid : - dp->dccps_options.dccpo_tx_ccid; + const u8 ccid_nr = rx ? dmsk->dccpms_rx_ccid : dmsk->dccpms_tx_ccid; struct ccid *new_ccid; /* Check if nothing is being changed. */ @@ -85,11 +84,11 @@ static int dccp_feat_update_ccid(struct sock *sk, u8 type, u8 new_ccid_nr) if (rx) { ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); dp->dccps_hc_rx_ccid = new_ccid; - dp->dccps_options.dccpo_rx_ccid = new_ccid_nr; + dmsk->dccpms_rx_ccid = new_ccid_nr; } else { ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); dp->dccps_hc_tx_ccid = new_ccid; - dp->dccps_options.dccpo_tx_ccid = new_ccid_nr; + dmsk->dccpms_tx_ccid = new_ccid_nr; } return 0; @@ -159,9 +158,9 @@ static int dccp_feat_reconcile(struct sock *sk, struct dccp_opt_pend *opt, case DCCPF_CCID: /* XXX did i get this right? =P */ if (opt->dccpop_type == DCCPO_CHANGE_L) - res = &dp->dccps_options.dccpo_tx_ccid; + res = &dccp_msk(sk)->dccpms_tx_ccid; else - res = &dp->dccps_options.dccpo_rx_ccid; + res = &dccp_msk(sk)->dccpms_rx_ccid; break; default: @@ -226,7 +225,7 @@ static int dccp_feat_reconcile(struct sock *sk, struct dccp_opt_pend *opt, static int dccp_feat_sp(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) { - struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); struct dccp_opt_pend *opt; int rc = 1; u8 t; @@ -242,8 +241,7 @@ static int dccp_feat_sp(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) t = DCCPO_CHANGE_L; /* find our preference list for this feature */ - list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, - dccpop_node) { + list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { if (opt->dccpop_type != t || opt->dccpop_feat != feature) continue; @@ -265,7 +263,7 @@ static int dccp_feat_sp(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) { struct dccp_opt_pend *opt; - struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); u8 *copy; int rc; @@ -304,14 +302,14 @@ static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) } dccp_pr_debug("Confirming NN feature %d (val=%d)\n", feature, *copy); - list_add_tail(&opt->dccpop_node, &dp->dccps_options.dccpo_conf); + list_add_tail(&opt->dccpop_node, &dmsk->dccpms_conf); return 0; } static void dccp_feat_empty_confirm(struct sock *sk, u8 type, u8 feature) { - struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); /* XXX check if other confirms for that are queued and recycle slot */ struct dccp_opt_pend *opt = kzalloc(sizeof(*opt), GFP_ATOMIC); @@ -330,20 +328,19 @@ static void dccp_feat_empty_confirm(struct sock *sk, u8 type, u8 feature) /* change feature */ dccp_pr_debug("Empty confirm feature %d type %d\n", feature, type); - list_add_tail(&opt->dccpop_node, &dp->dccps_options.dccpo_conf); + list_add_tail(&opt->dccpop_node, &dmsk->dccpms_conf); } static void dccp_feat_flush_confirm(struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); /* Check if there is anything to confirm in the first place */ - int yes = !list_empty(&dp->dccps_options.dccpo_conf); + int yes = !list_empty(&dmsk->dccpms_conf); if (!yes) { struct dccp_opt_pend *opt; - list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, - dccpop_node) { + list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { if (opt->dccpop_conf) { yes = 1; break; @@ -407,7 +404,7 @@ int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature, { u8 t; struct dccp_opt_pend *opt; - struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); int rc = 1; int all_confirmed = 1; @@ -418,8 +415,7 @@ int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature, /* locate our change request */ t = type == DCCPO_CONFIRM_L ? DCCPO_CHANGE_R : DCCPO_CHANGE_L; - list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, - dccpop_node) { + list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { if (!opt->dccpop_conf && opt->dccpop_type == t && opt->dccpop_feat == feature) { /* we found it */ @@ -462,10 +458,10 @@ EXPORT_SYMBOL_GPL(dccp_feat_confirm_recv); void dccp_feat_clean(struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); struct dccp_opt_pend *opt, *next; - list_for_each_entry_safe(opt, next, &dp->dccps_options.dccpo_pending, + list_for_each_entry_safe(opt, next, &dmsk->dccpms_pending, dccpop_node) { BUG_ON(opt->dccpop_val == NULL); kfree(opt->dccpop_val); @@ -478,16 +474,15 @@ void dccp_feat_clean(struct sock *sk) kfree(opt); } - INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending); + INIT_LIST_HEAD(&dmsk->dccpms_pending); - list_for_each_entry_safe(opt, next, &dp->dccps_options.dccpo_conf, - dccpop_node) { + list_for_each_entry_safe(opt, next, &dmsk->dccpms_conf, dccpop_node) { BUG_ON(opt == NULL); if (opt->dccpop_val != NULL) kfree(opt->dccpop_val); kfree(opt); } - INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); + INIT_LIST_HEAD(&dmsk->dccpms_conf); } EXPORT_SYMBOL_GPL(dccp_feat_clean); @@ -498,16 +493,15 @@ EXPORT_SYMBOL_GPL(dccp_feat_clean); */ int dccp_feat_clone(struct sock *oldsk, struct sock *newsk) { - struct dccp_sock *olddp = dccp_sk(oldsk); - struct dccp_sock *newdp = dccp_sk(newsk); + struct dccp_minisock *olddmsk = dccp_msk(oldsk); + struct dccp_minisock *newdmsk = dccp_msk(newsk); struct dccp_opt_pend *opt; int rc = 0; - INIT_LIST_HEAD(&newdp->dccps_options.dccpo_pending); - INIT_LIST_HEAD(&newdp->dccps_options.dccpo_conf); + INIT_LIST_HEAD(&newdmsk->dccpms_pending); + INIT_LIST_HEAD(&newdmsk->dccpms_conf); - list_for_each_entry(opt, &olddp->dccps_options.dccpo_pending, - dccpop_node) { + list_for_each_entry(opt, &olddmsk->dccpms_pending, dccpop_node) { struct dccp_opt_pend *newopt; /* copy the value of the option */ u8 *val = kmalloc(opt->dccpop_len, GFP_ATOMIC); @@ -525,8 +519,7 @@ int dccp_feat_clone(struct sock *oldsk, struct sock *newsk) /* insert the option */ memcpy(newopt, opt, sizeof(*newopt)); newopt->dccpop_val = val; - list_add_tail(&newopt->dccpop_node, - &newdp->dccps_options.dccpo_pending); + list_add_tail(&newopt->dccpop_node, &newdmsk->dccpms_pending); /* XXX what happens with backlogs and multiple connections at * once... @@ -567,27 +560,27 @@ static int __dccp_feat_init(struct sock *sk, u8 type, u8 feat, u8 *val, u8 len) int dccp_feat_init(struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); int rc; - INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending); - INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); + INIT_LIST_HEAD(&dmsk->dccpms_pending); + INIT_LIST_HEAD(&dmsk->dccpms_conf); /* CCID L */ rc = __dccp_feat_init(sk, DCCPO_CHANGE_L, DCCPF_CCID, - &dp->dccps_options.dccpo_tx_ccid, 1); + &dmsk->dccpms_tx_ccid, 1); if (rc) goto out; /* CCID R */ rc = __dccp_feat_init(sk, DCCPO_CHANGE_R, DCCPF_CCID, - &dp->dccps_options.dccpo_rx_ccid, 1); + &dmsk->dccpms_rx_ccid, 1); if (rc) goto out; /* Ack ratio */ rc = __dccp_feat_init(sk, DCCPO_CHANGE_L, DCCPF_ACK_RATIO, - &dp->dccps_options.dccpo_ack_ratio, 1); + &dmsk->dccpms_ack_ratio, 1); out: return rc; } diff --git a/net/dccp/input.c b/net/dccp/input.c index f53e3fc77262..bfc53665516b 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -60,7 +60,7 @@ static void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb) { struct dccp_sock *dp = dccp_sk(sk); - if (dp->dccps_options.dccpo_send_ack_vector) + if (dccp_msk(sk)->dccpms_send_ack_vector) dccp_ackvec_check_rcv_ackno(dp->dccps_hc_rx_ackvec, sk, DCCP_SKB_CB(skb)->dccpd_ack_seq); } @@ -246,7 +246,7 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) dccp_event_ack_recv(sk, skb); - if (dp->dccps_options.dccpo_send_ack_vector && + if (dccp_msk(sk)->dccpms_send_ack_vector && dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_ACKVEC_STATE_RECEIVED)) @@ -302,7 +302,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, if (dccp_parse_options(sk, skb)) goto out_invalid_packet; - if (dp->dccps_options.dccpo_send_ack_vector && + if (dccp_msk(sk)->dccpms_send_ack_vector && dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_ACKVEC_STATE_RECEIVED)) @@ -486,7 +486,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) dccp_event_ack_recv(sk, skb); - if (dp->dccps_options.dccpo_send_ack_vector && + if (dccp_msk(sk)->dccpms_send_ack_vector && dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_ACKVEC_STATE_RECEIVED)) diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 5324fcacb34d..c0349e5b0551 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -107,6 +107,7 @@ struct sock *dccp_create_openreq_child(struct sock *sk, const struct dccp_request_sock *dreq = dccp_rsk(req); struct inet_connection_sock *newicsk = inet_csk(sk); struct dccp_sock *newdp = dccp_sk(newsk); + struct dccp_minisock *newdmsk = dccp_msk(newsk); newdp->dccps_role = DCCP_ROLE_SERVER; newdp->dccps_hc_rx_ackvec = NULL; @@ -118,7 +119,7 @@ struct sock *dccp_create_openreq_child(struct sock *sk, if (dccp_feat_clone(sk, newsk)) goto out_free; - if (newdp->dccps_options.dccpo_send_ack_vector) { + if (newdmsk->dccpms_send_ack_vector) { newdp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_ATOMIC); if (unlikely(newdp->dccps_hc_rx_ackvec == NULL)) @@ -126,10 +127,10 @@ struct sock *dccp_create_openreq_child(struct sock *sk, } newdp->dccps_hc_rx_ccid = - ccid_hc_rx_new(newdp->dccps_options.dccpo_rx_ccid, + ccid_hc_rx_new(newdmsk->dccpms_rx_ccid, newsk, GFP_ATOMIC); newdp->dccps_hc_tx_ccid = - ccid_hc_tx_new(newdp->dccps_options.dccpo_tx_ccid, + ccid_hc_tx_new(newdmsk->dccpms_tx_ccid, newsk, GFP_ATOMIC); if (unlikely(newdp->dccps_hc_rx_ccid == NULL || newdp->dccps_hc_tx_ccid == NULL)) { @@ -153,7 +154,7 @@ out_free: */ /* See dccp_v4_conn_request */ - newdp->dccps_options.dccpo_sequence_window = req->rcv_wnd; + newdmsk->dccpms_sequence_window = req->rcv_wnd; newdp->dccps_gar = newdp->dccps_isr = dreq->dreq_isr; dccp_update_gsr(newsk, dreq->dreq_isr); diff --git a/net/dccp/options.c b/net/dccp/options.c index 6e85550cc6f0..e9feb2a0c770 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -30,14 +30,14 @@ int dccp_feat_default_ack_ratio = DCCPF_INITIAL_ACK_RATIO; int dccp_feat_default_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR; int dccp_feat_default_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT; -void dccp_options_init(struct dccp_options *dccpo) +void dccp_minisock_init(struct dccp_minisock *dmsk) { - dccpo->dccpo_sequence_window = dccp_feat_default_sequence_window; - dccpo->dccpo_rx_ccid = dccp_feat_default_rx_ccid; - dccpo->dccpo_tx_ccid = dccp_feat_default_tx_ccid; - dccpo->dccpo_ack_ratio = dccp_feat_default_ack_ratio; - dccpo->dccpo_send_ack_vector = dccp_feat_default_send_ack_vector; - dccpo->dccpo_send_ndp_count = dccp_feat_default_send_ndp_count; + dmsk->dccpms_sequence_window = dccp_feat_default_sequence_window; + dmsk->dccpms_rx_ccid = dccp_feat_default_rx_ccid; + dmsk->dccpms_tx_ccid = dccp_feat_default_tx_ccid; + dmsk->dccpms_ack_ratio = dccp_feat_default_ack_ratio; + dmsk->dccpms_send_ack_vector = dccp_feat_default_send_ack_vector; + dmsk->dccpms_send_ndp_count = dccp_feat_default_send_ndp_count; } static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len) @@ -151,7 +151,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) if (pkt_type == DCCP_PKT_DATA) break; - if (dp->dccps_options.dccpo_send_ack_vector && + if (dccp_msk(sk)->dccpms_send_ack_vector && dccp_ackvec_parse(sk, skb, opt, value, len)) goto out_invalid_option; break; @@ -472,12 +472,12 @@ static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat, static int dccp_insert_options_feat(struct sock *sk, struct sk_buff *skb) { struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); struct dccp_opt_pend *opt, *next; int change = 0; /* confirm any options [NN opts] */ - list_for_each_entry_safe(opt, next, &dp->dccps_options.dccpo_conf, - dccpop_node) { + list_for_each_entry_safe(opt, next, &dmsk->dccpms_conf, dccpop_node) { dccp_insert_feat_opt(skb, opt->dccpop_type, opt->dccpop_feat, opt->dccpop_val, opt->dccpop_len); @@ -486,11 +486,10 @@ static int dccp_insert_options_feat(struct sock *sk, struct sk_buff *skb) kfree(opt->dccpop_val); kfree(opt); } - INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); + INIT_LIST_HEAD(&dmsk->dccpms_conf); /* see which features we need to send */ - list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, - dccpop_node) { + list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { /* see if we need to send any confirm */ if (opt->dccpop_sc) { dccp_insert_feat_opt(skb, opt->dccpop_type + 1, @@ -536,15 +535,16 @@ static int dccp_insert_options_feat(struct sock *sk, struct sk_buff *skb) int dccp_insert_options(struct sock *sk, struct sk_buff *skb) { struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); DCCP_SKB_CB(skb)->dccpd_opt_len = 0; - if (dp->dccps_options.dccpo_send_ndp_count && + if (dmsk->dccpms_send_ndp_count && dccp_insert_option_ndp(sk, skb)) return -1; if (!dccp_packet_without_ack(skb)) { - if (dp->dccps_options.dccpo_send_ack_vector && + if (dmsk->dccpms_send_ack_vector && dccp_ackvec_pending(dp->dccps_hc_rx_ackvec) && dccp_insert_option_ackvec(sk, skb)) return -1; diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 8a6d0a83047c..ede969074967 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -166,9 +166,10 @@ EXPORT_SYMBOL_GPL(dccp_unhash); int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) { struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); struct inet_connection_sock *icsk = inet_csk(sk); - dccp_options_init(&dp->dccps_options); + dccp_minisock_init(&dp->dccps_minisock); do_gettimeofday(&dp->dccps_epoch); /* @@ -184,22 +185,20 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) if (rc) return rc; - if (dp->dccps_options.dccpo_send_ack_vector) { + if (dmsk->dccpms_send_ack_vector) { dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_KERNEL); if (dp->dccps_hc_rx_ackvec == NULL) return -ENOMEM; } - dp->dccps_hc_rx_ccid = - ccid_hc_rx_new(dp->dccps_options.dccpo_rx_ccid, - sk, GFP_KERNEL); - dp->dccps_hc_tx_ccid = - ccid_hc_tx_new(dp->dccps_options.dccpo_tx_ccid, - sk, GFP_KERNEL); + dp->dccps_hc_rx_ccid = ccid_hc_rx_new(dmsk->dccpms_rx_ccid, + sk, GFP_KERNEL); + dp->dccps_hc_tx_ccid = ccid_hc_tx_new(dmsk->dccpms_tx_ccid, + sk, GFP_KERNEL); if (unlikely(dp->dccps_hc_rx_ccid == NULL || dp->dccps_hc_tx_ccid == NULL)) { ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); - if (dp->dccps_options.dccpo_send_ack_vector) { + if (dmsk->dccpms_send_ack_vector) { dccp_ackvec_free(dp->dccps_hc_rx_ackvec); dp->dccps_hc_rx_ackvec = NULL; } @@ -208,8 +207,8 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) } } else { /* control socket doesn't need feat nego */ - INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending); - INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); + INIT_LIST_HEAD(&dmsk->dccpms_pending); + INIT_LIST_HEAD(&dmsk->dccpms_conf); } dccp_init_xmit_timers(sk); @@ -247,7 +246,7 @@ int dccp_destroy_sock(struct sock *sk) kfree(dp->dccps_service_list); dp->dccps_service_list = NULL; - if (dp->dccps_options.dccpo_send_ack_vector) { + if (dccp_msk(sk)->dccpms_send_ack_vector) { dccp_ackvec_free(dp->dccps_hc_rx_ackvec); dp->dccps_hc_rx_ackvec = NULL; } -- cgit v1.2.3 From c8b2a6c50cacc98c924233a9e474c74c0370b6b8 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 20 Mar 2006 22:53:42 -0800 Subject: [SPARC]: Fixup SO_PEERSEC value on 32-bit sparc. Sparc64 and Sparc32 have to have identical socket call numbering in order to handle compat layer stuff properly. Signed-off-by: David S. Miller --- include/asm-sparc/socket.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-sparc/socket.h b/include/asm-sparc/socket.h index 09575b608adb..4e0ce3a35ea9 100644 --- a/include/asm-sparc/socket.h +++ b/include/asm-sparc/socket.h @@ -47,7 +47,7 @@ #define SO_TIMESTAMP 0x001d #define SCM_TIMESTAMP SO_TIMESTAMP -#define SO_PEERSEC 0x100e +#define SO_PEERSEC 0x001e /* Security levels - as per NRL IPv6 - don't actually do anything */ #define SO_SECURITY_AUTHENTICATION 0x5001 -- cgit v1.2.3 From fdeabdefb227be9aa932f59a23ddb47e003e643e Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 20 Mar 2006 22:58:21 -0800 Subject: [BRIDGE]: netfilter inline cleanup Move nf_bridge_alloc from header file to the one place it is used and optimize it. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/linux/netfilter_bridge.h | 27 --------------------------- net/bridge/br_netfilter.c | 25 +++++++++++++++++++++---- 2 files changed, 21 insertions(+), 31 deletions(-) (limited to 'include') diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h index de4d397865ce..a75b84bb9a88 100644 --- a/include/linux/netfilter_bridge.h +++ b/include/linux/netfilter_bridge.h @@ -47,22 +47,6 @@ enum nf_br_hook_priorities { #define BRNF_BRIDGED 0x08 #define BRNF_NF_BRIDGE_PREROUTING 0x10 -static inline -struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb) -{ - struct nf_bridge_info **nf_bridge = &(skb->nf_bridge); - - if ((*nf_bridge = kmalloc(sizeof(**nf_bridge), GFP_ATOMIC)) != NULL) { - atomic_set(&(*nf_bridge)->use, 1); - (*nf_bridge)->mask = 0; - (*nf_bridge)->physindev = (*nf_bridge)->physoutdev = NULL; -#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) - (*nf_bridge)->netoutdev = NULL; -#endif - } - - return *nf_bridge; -} /* Only used in br_forward.c */ static inline @@ -77,17 +61,6 @@ void nf_bridge_maybe_copy_header(struct sk_buff *skb) } } -static inline -void nf_bridge_save_header(struct sk_buff *skb) -{ - int header_size = 16; - - if (skb->protocol == __constant_htons(ETH_P_8021Q)) - header_size = 18; - - memcpy(skb->nf_bridge->data, skb->data - header_size, header_size); -} - /* This is called by the IP fragmenting code and it ensures there is * enough room for the encapsulating header (if there is one). */ static inline diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 6fc9ecc4eb39..f29450b788be 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -113,6 +113,25 @@ static inline struct net_device *bridge_parent(const struct net_device *dev) return port ? port->br->dev : NULL; } +static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb) +{ + skb->nf_bridge = kzalloc(sizeof(struct nf_bridge_info), GFP_ATOMIC); + if (likely(skb->nf_bridge)) + atomic_set(&(skb->nf_bridge->use), 1); + + return skb->nf_bridge; +} + +static inline void nf_bridge_save_header(struct sk_buff *skb) +{ + int header_size = 16; + + if (skb->protocol == htons(ETH_P_8021Q)) + header_size = 18; + + memcpy(skb->nf_bridge->data, skb->data - header_size, header_size); +} + /* PF_BRIDGE/PRE_ROUTING *********************************************/ /* Undo the changes made for ip6tables PREROUTING and continue the * bridge PRE_ROUTING hook. */ @@ -371,7 +390,6 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook, { struct ipv6hdr *hdr; u32 pkt_len; - struct nf_bridge_info *nf_bridge; if (skb->len < sizeof(struct ipv6hdr)) goto inhdr_error; @@ -400,7 +418,7 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook, goto inhdr_error; nf_bridge_put(skb->nf_bridge); - if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) + if (!nf_bridge_alloc(skb)) return NF_DROP; if (!setup_pre_routing(skb)) return NF_DROP; @@ -428,7 +446,6 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, struct iphdr *iph; __u32 len; struct sk_buff *skb = *pskb; - struct nf_bridge_info *nf_bridge; if (skb->protocol == htons(ETH_P_IPV6) || IS_VLAN_IPV6(skb)) { #ifdef CONFIG_SYSCTL @@ -485,7 +502,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, } nf_bridge_put(skb->nf_bridge); - if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) + if (!nf_bridge_alloc(skb)) return NF_DROP; if (!setup_pre_routing(skb)) return NF_DROP; -- cgit v1.2.3 From f4ad2b162d653e4a6e57d598119e3820c65fef71 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 20 Mar 2006 22:59:36 -0800 Subject: [LLC]: llc_mac_hdr_init const arguments Cleanup of LLC. llc_mac_hdr_init can take constant arguments, and it is defined twice once in llc_output.h that is otherwise unused. Signed-off-by: Stephen Hemminger Acked-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/net/llc.h | 2 +- net/llc/llc_c_ac.c | 1 - net/llc/llc_output.c | 3 ++- net/llc/llc_output.h | 20 -------------------- net/llc/llc_s_ac.c | 2 +- 5 files changed, 4 insertions(+), 24 deletions(-) delete mode 100644 net/llc/llc_output.h (limited to 'include') diff --git a/include/net/llc.h b/include/net/llc.h index 1adb2ef3f6f7..f5024583fc8b 100644 --- a/include/net/llc.h +++ b/include/net/llc.h @@ -71,7 +71,7 @@ extern int llc_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev); extern int llc_mac_hdr_init(struct sk_buff *skb, - unsigned char *sa, unsigned char *da); + const unsigned char *sa, const unsigned char *da); extern void llc_add_pack(int type, void (*handler)(struct llc_sap *sap, struct sk_buff *skb)); diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index 8169f24ed33e..860140caa6e0 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c @@ -27,7 +27,6 @@ #include #include -#include "llc_output.h" static int llc_conn_ac_inc_vs_by_1(struct sock *sk, struct sk_buff *skb); static void llc_process_tmr_ev(struct sock *sk, struct sk_buff *skb); diff --git a/net/llc/llc_output.c b/net/llc/llc_output.c index b4d55b6abb67..b4e668e0e12c 100644 --- a/net/llc/llc_output.c +++ b/net/llc/llc_output.c @@ -30,7 +30,8 @@ * Fills MAC header fields, depending on MAC type. Returns 0, If MAC type * is a valid type and initialization completes correctly 1, otherwise. */ -int llc_mac_hdr_init(struct sk_buff *skb, unsigned char *sa, unsigned char *da) +int llc_mac_hdr_init(struct sk_buff *skb, + const unsigned char *sa, const unsigned char *da) { int rc = 0; diff --git a/net/llc/llc_output.h b/net/llc/llc_output.h deleted file mode 100644 index 179edf753f00..000000000000 --- a/net/llc/llc_output.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef LLC_OUTPUT_H -#define LLC_OUTPUT_H -/* - * Copyright (c) 1997 by Procom Technology, Inc. - * 2001-2003 by Arnaldo Carvalho de Melo - * - * This program can be redistributed or modified under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation. - * This program is distributed without any warranty or implied warranty - * of merchantability or fitness for a particular purpose. - * - * See the GNU General Public License version 2 for more details. - */ - -struct sk_buff; - -int llc_mac_hdr_init(struct sk_buff *skb, unsigned char *sa, unsigned char *da); - -#endif /* LLC_OUTPUT_H */ diff --git a/net/llc/llc_s_ac.c b/net/llc/llc_s_ac.c index bb3580fb8cfe..ac3d93b210d2 100644 --- a/net/llc/llc_s_ac.c +++ b/net/llc/llc_s_ac.c @@ -24,7 +24,7 @@ #include #include #include -#include "llc_output.h" + /** * llc_sap_action_unit_data_ind - forward UI PDU to network layer -- cgit v1.2.3 From 5e35941d990123f155b02d5663e51a24f816b6f3 Mon Sep 17 00:00:00 2001 From: Jing Min Zhao Date: Mon, 20 Mar 2006 23:41:17 -0800 Subject: [NETFILTER]: Add H.323 conntrack/NAT helper Signed-off-by: Jing Min Zhao Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter_ipv4/ip_conntrack.h | 2 + include/linux/netfilter_ipv4/ip_conntrack_h323.h | 30 + net/ipv4/netfilter/Kconfig | 26 + net/ipv4/netfilter/Makefile | 5 + net/ipv4/netfilter/ip_conntrack_helper_h323.c | 1731 ++++++++++++++++++ net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c | 870 +++++++++ net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h | 98 + .../netfilter/ip_conntrack_helper_h323_types.c | 1926 ++++++++++++++++++++ .../netfilter/ip_conntrack_helper_h323_types.h | 938 ++++++++++ net/ipv4/netfilter/ip_nat_helper_h323.c | 605 ++++++ 10 files changed, 6231 insertions(+) create mode 100644 include/linux/netfilter_ipv4/ip_conntrack_h323.h create mode 100644 net/ipv4/netfilter/ip_conntrack_helper_h323.c create mode 100644 net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c create mode 100644 net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h create mode 100644 net/ipv4/netfilter/ip_conntrack_helper_h323_types.c create mode 100644 net/ipv4/netfilter/ip_conntrack_helper_h323_types.h create mode 100644 net/ipv4/netfilter/ip_nat_helper_h323.c (limited to 'include') diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h index 215765f043e6..f32d75c4f4cf 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack.h +++ b/include/linux/netfilter_ipv4/ip_conntrack.h @@ -29,6 +29,7 @@ union ip_conntrack_expect_proto { }; /* Add protocol helper include file here */ +#include #include #include #include @@ -37,6 +38,7 @@ union ip_conntrack_expect_proto { /* per conntrack: application helper private data */ union ip_conntrack_help { /* insert conntrack helper private data (master) here */ + struct ip_ct_h323_master ct_h323_info; struct ip_ct_pptp_master ct_pptp_info; struct ip_ct_ftp_master ct_ftp_info; struct ip_ct_irc_master ct_irc_info; diff --git a/include/linux/netfilter_ipv4/ip_conntrack_h323.h b/include/linux/netfilter_ipv4/ip_conntrack_h323.h new file mode 100644 index 000000000000..0987cea53840 --- /dev/null +++ b/include/linux/netfilter_ipv4/ip_conntrack_h323.h @@ -0,0 +1,30 @@ +#ifndef _IP_CONNTRACK_H323_H +#define _IP_CONNTRACK_H323_H + +#ifdef __KERNEL__ + +#define RAS_PORT 1719 +#define Q931_PORT 1720 +#define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */ + +/* This structure exists only once per master */ +struct ip_ct_h323_master { + + /* Original and NATed Q.931 or H.245 signal ports */ + u_int16_t sig_port[IP_CT_DIR_MAX]; + + /* Original and NATed RTP ports */ + u_int16_t rtp_port[H323_RTP_CHANNEL_MAX][IP_CT_DIR_MAX]; + + union { + /* RAS connection timeout */ + u_int32_t timeout; + + /* Next TPKT length (for separate TPKT header and data) */ + u_int16_t tpkt_len[IP_CT_DIR_MAX]; + }; +}; + +#endif + +#endif diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 933ee7a9efdf..882b842c25d4 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -168,6 +168,26 @@ config IP_NF_PPTP If you want to compile it as a module, say M here and read Documentation/modules.txt. If unsure, say `N'. +config IP_NF_H323 + tristate 'H.323 protocol support' + depends on IP_NF_CONNTRACK + help + H.323 is a VoIP signalling protocol from ITU-T. As one of the most + important VoIP protocols, it is widely used by voice hardware and + software including voice gateways, IP phones, Netmeeting, OpenPhone, + Gnomemeeting, etc. + + With this module you can support H.323 on a connection tracking/NAT + firewall. + + This module supports RAS, Fast-start, H.245 tunnelling, RTP/RTCP + and T.120 based data and applications including audio, video, FAX, + chat, whiteboard, file transfer, etc. For more information, please + see http://nath323.sourceforge.net/. + + If you want to compile it as a module, say 'M' here and read + Documentation/modules.txt. If unsure, say 'N'. + config IP_NF_QUEUE tristate "IP Userspace queueing via NETLINK (OBSOLETE)" help @@ -484,6 +504,12 @@ config IP_NF_NAT_PPTP default IP_NF_NAT if IP_NF_PPTP=y default m if IP_NF_PPTP=m +config IP_NF_NAT_H323 + tristate + depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n + default IP_NF_NAT if IP_NF_H323=y + default m if IP_NF_H323=m + # mangle + specific targets config IP_NF_MANGLE tristate "Packet mangling" diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 3fe80924ac54..f2cd9a6c5b91 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -10,6 +10,9 @@ iptable_nat-objs := ip_nat_rule.o ip_nat_standalone.o ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o +ip_conntrack_h323-objs := ip_conntrack_helper_h323.o ip_conntrack_helper_h323_asn1.o +ip_nat_h323-objs := ip_nat_helper_h323.o + # connection tracking obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o obj-$(CONFIG_IP_NF_NAT) += ip_nat.o @@ -22,6 +25,7 @@ obj-$(CONFIG_IP_NF_CONNTRACK_NETLINK) += ip_conntrack_netlink.o obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o # connection tracking helpers +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o @@ -30,6 +34,7 @@ obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o # NAT helpers +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c new file mode 100644 index 000000000000..20da6730b860 --- /dev/null +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c @@ -0,0 +1,1731 @@ +/* + * H.323 connection tracking helper + * + * Copyright (c) 2006 Jing Min Zhao + * + * This source code is licensed under General Public License version 2. + * + * Based on the 'brute force' H.323 connection tracking module by + * Jozsef Kadlecsik + * + * For more information, please see http://nath323.sourceforge.net/ + * + * Changes: + * 2006-02-01 - initial version 0.1 + * + * 2006-02-20 - version 0.2 + * 1. Changed source format to follow kernel conventions + * 2. Deleted some unnecessary structures + * 3. Minor fixes + * + * 2006-03-10 - version 0.3 + * 1. Added support for multiple TPKTs in one packet (suggested by + * Patrick McHardy) + * 2. Avoid excessive stack usage (based on Patrick McHardy's patch) + * 3. Added support for non-linear skb (based on Patrick McHardy's patch) + * 4. Fixed missing H.245 module owner (Patrick McHardy) + * 5. Avoid long RAS expectation chains (Patrick McHardy) + * 6. Fixed incorrect __exit attribute (Patrick McHardy) + * 7. Eliminated unnecessary return code + * 8. Fixed incorrect use of NAT data from conntrack code (suggested by + * Patrick McHardy) + * 9. Fixed TTL calculation error in RCF + * 10. Added TTL support in RRQ + * 11. Better support for separate TPKT header and data + * + * 2006-03-15 - version 0.4 + * 1. Added support for T.120 channels + * 2. Added parameter gkrouted_only (suggested by Patrick McHardy) + * 3. Splitted ASN.1 code and data (suggested by Patrick McHardy) + * 4. Sort ASN.1 data to avoid forwarding declarations (suggested by + * Patrick McHardy) + * 5. Reset next TPKT data length in get_tpkt_data() + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ip_conntrack_helper_h323_asn1.h" + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(format, args...) +#endif + +/* Parameters */ +static int gkrouted_only = 1; +module_param(gkrouted_only, int, 0600); +MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper"); + +/* Hooks for NAT */ +int (*set_h245_addr_hook) (struct sk_buff ** pskb, + unsigned char **data, int dataoff, + H245_TransportAddress * addr, + u_int32_t ip, u_int16_t port); +int (*set_h225_addr_hook) (struct sk_buff ** pskb, + unsigned char **data, int dataoff, + TransportAddress * addr, + u_int32_t ip, u_int16_t port); +int (*set_sig_addr_hook) (struct sk_buff ** pskb, + struct ip_conntrack * ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, + TransportAddress * addr, int count); +int (*set_ras_addr_hook) (struct sk_buff ** pskb, + struct ip_conntrack * ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, + TransportAddress * addr, int count); +int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb, + struct ip_conntrack * ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H245_TransportAddress * addr, + u_int16_t port, u_int16_t rtp_port, + struct ip_conntrack_expect * rtp_exp, + struct ip_conntrack_expect * rtcp_exp); +int (*nat_t120_hook) (struct sk_buff ** pskb, + struct ip_conntrack * ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H245_TransportAddress * addr, u_int16_t port, + struct ip_conntrack_expect * exp); +int (*nat_h245_hook) (struct sk_buff ** pskb, + struct ip_conntrack * ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + TransportAddress * addr, u_int16_t port, + struct ip_conntrack_expect * exp); +int (*nat_q931_hook) (struct sk_buff ** pskb, + struct ip_conntrack * ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, TransportAddress * addr, int idx, + u_int16_t port, struct ip_conntrack_expect * exp); + + +static DEFINE_SPINLOCK(ip_h323_lock); +static char *h323_buffer; + +/****************************************************************************/ +static int get_tpkt_data(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int *datalen, int *dataoff) +{ + struct ip_ct_h323_master *info = &ct->help.ct_h323_info; + int dir = CTINFO2DIR(ctinfo); + struct tcphdr _tcph, *th; + int tcpdatalen; + int tcpdataoff; + unsigned char *tpkt; + int tpktlen; + int tpktoff; + + /* Get TCP header */ + th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4, + sizeof(_tcph), &_tcph); + if (th == NULL) + return 0; + + /* Get TCP data offset */ + tcpdataoff = (*pskb)->nh.iph->ihl * 4 + th->doff * 4; + + /* Get TCP data length */ + tcpdatalen = (*pskb)->len - tcpdataoff; + if (tcpdatalen <= 0) /* No TCP data */ + goto clear_out; + + if (*data == NULL) { /* first TPKT */ + /* Get first TPKT pointer */ + tpkt = skb_header_pointer(*pskb, tcpdataoff, tcpdatalen, + h323_buffer); + BUG_ON(tpkt == NULL); + + /* Validate TPKT identifier */ + if (tcpdatalen < 4 || tpkt[0] != 0x03 || tpkt[1] != 0) { + /* Netmeeting sends TPKT header and data separately */ + if (info->tpkt_len[dir] > 0) { + DEBUGP("ip_ct_h323: previous packet " + "indicated separate TPKT data of %hu " + "bytes\n", info->tpkt_len[dir]); + if (info->tpkt_len[dir] <= tcpdatalen) { + /* Yes, there was a TPKT header + * received */ + *data = tpkt; + *datalen = info->tpkt_len[dir]; + *dataoff = 0; + goto out; + } + + /* Fragmented TPKT */ + if (net_ratelimit()) + printk("ip_ct_h323: " + "fragmented TPKT\n"); + goto clear_out; + } + + /* It is not even a TPKT */ + return 0; + } + tpktoff = 0; + } else { /* Next TPKT */ + tpktoff = *dataoff + *datalen; + tcpdatalen -= tpktoff; + if (tcpdatalen <= 4) /* No more TPKT */ + goto clear_out; + tpkt = *data + *datalen; + + /* Validate TPKT identifier */ + if (tpkt[0] != 0x03 || tpkt[1] != 0) + goto clear_out; + } + + /* Validate TPKT length */ + tpktlen = tpkt[2] * 256 + tpkt[3]; + if (tpktlen > tcpdatalen) { + if (tcpdatalen == 4) { /* Separate TPKT header */ + /* Netmeeting sends TPKT header and data separately */ + DEBUGP("ip_ct_h323: separate TPKT header indicates " + "there will be TPKT data of %hu bytes\n", + tpktlen - 4); + info->tpkt_len[dir] = tpktlen - 4; + return 0; + } + + if (net_ratelimit()) + printk("ip_ct_h323: incomplete TPKT (fragmented?)\n"); + goto clear_out; + } + + /* This is the encapsulated data */ + *data = tpkt + 4; + *datalen = tpktlen - 4; + *dataoff = tpktoff + 4; + + out: + /* Clear TPKT length */ + info->tpkt_len[dir] = 0; + return 1; + + clear_out: + info->tpkt_len[dir] = 0; + return 0; +} + +/****************************************************************************/ +int get_h245_addr(unsigned char *data, H245_TransportAddress * addr, + u_int32_t * ip, u_int16_t * port) +{ + unsigned char *p; + + if (addr->choice != eH245_TransportAddress_unicastAddress || + addr->unicastAddress.choice != eUnicastAddress_iPAddress) + return 0; + + p = data + addr->unicastAddress.iPAddress.network; + *ip = htonl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3])); + *port = (p[4] << 8) | (p[5]); + + return 1; +} + +/****************************************************************************/ +static int expect_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H245_TransportAddress * addr) +{ + int dir = CTINFO2DIR(ctinfo); + int ret = 0; + u_int32_t ip; + u_int16_t port; + u_int16_t rtp_port; + struct ip_conntrack_expect *rtp_exp; + struct ip_conntrack_expect *rtcp_exp; + + /* Read RTP or RTCP address */ + if (!get_h245_addr(*data, addr, &ip, &port) || + ip != ct->tuplehash[dir].tuple.src.ip || port == 0) + return 0; + + /* RTP port is even */ + rtp_port = port & (~1); + + /* Create expect for RTP */ + if ((rtp_exp = ip_conntrack_expect_alloc(ct)) == NULL) + return -1; + rtp_exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip; + rtp_exp->tuple.src.u.udp.port = 0; + rtp_exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip; + rtp_exp->tuple.dst.u.udp.port = htons(rtp_port); + rtp_exp->tuple.dst.protonum = IPPROTO_UDP; + rtp_exp->mask.src.ip = 0xFFFFFFFF; + rtp_exp->mask.src.u.udp.port = 0; + rtp_exp->mask.dst.ip = 0xFFFFFFFF; + rtp_exp->mask.dst.u.udp.port = 0xFFFF; + rtp_exp->mask.dst.protonum = 0xFF; + rtp_exp->flags = 0; + + /* Create expect for RTCP */ + if ((rtcp_exp = ip_conntrack_expect_alloc(ct)) == NULL) { + ip_conntrack_expect_put(rtp_exp); + return -1; + } + rtcp_exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip; + rtcp_exp->tuple.src.u.udp.port = 0; + rtcp_exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip; + rtcp_exp->tuple.dst.u.udp.port = htons(rtp_port + 1); + rtcp_exp->tuple.dst.protonum = IPPROTO_UDP; + rtcp_exp->mask.src.ip = 0xFFFFFFFF; + rtcp_exp->mask.src.u.udp.port = 0; + rtcp_exp->mask.dst.ip = 0xFFFFFFFF; + rtcp_exp->mask.dst.u.udp.port = 0xFFFF; + rtcp_exp->mask.dst.protonum = 0xFF; + rtcp_exp->flags = 0; + + if (ct->tuplehash[dir].tuple.src.ip != + ct->tuplehash[!dir].tuple.dst.ip && nat_rtp_rtcp_hook) { + /* NAT needed */ + ret = nat_rtp_rtcp_hook(pskb, ct, ctinfo, data, dataoff, + addr, port, rtp_port, rtp_exp, + rtcp_exp); + } else { /* Conntrack only */ + rtp_exp->expectfn = NULL; + rtcp_exp->expectfn = NULL; + + if (ip_conntrack_expect_related(rtp_exp) == 0) { + if (ip_conntrack_expect_related(rtcp_exp) == 0) { + DEBUGP("ip_ct_h323: expect RTP " + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(rtp_exp->tuple.src.ip), + ntohs(rtp_exp->tuple.src.u.udp.port), + NIPQUAD(rtp_exp->tuple.dst.ip), + ntohs(rtp_exp->tuple.dst.u.udp.port)); + DEBUGP("ip_ct_h323: expect RTCP " + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(rtcp_exp->tuple.src.ip), + ntohs(rtcp_exp->tuple.src.u.udp.port), + NIPQUAD(rtcp_exp->tuple.dst.ip), + ntohs(rtcp_exp->tuple.dst.u.udp.port)); + } else { + ip_conntrack_unexpect_related(rtp_exp); + ret = -1; + } + } else + ret = -1; + } + + ip_conntrack_expect_put(rtp_exp); + ip_conntrack_expect_put(rtcp_exp); + + return ret; +} + +/****************************************************************************/ +static int expect_t120(struct sk_buff **pskb, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H245_TransportAddress * addr) +{ + int dir = CTINFO2DIR(ctinfo); + int ret = 0; + u_int32_t ip; + u_int16_t port; + struct ip_conntrack_expect *exp = NULL; + + /* Read T.120 address */ + if (!get_h245_addr(*data, addr, &ip, &port) || + ip != ct->tuplehash[dir].tuple.src.ip || port == 0) + return 0; + + /* Create expect for T.120 connections */ + if ((exp = ip_conntrack_expect_alloc(ct)) == NULL) + return -1; + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip; + exp->tuple.src.u.tcp.port = 0; + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip; + exp->tuple.dst.u.tcp.port = htons(port); + exp->tuple.dst.protonum = IPPROTO_TCP; + exp->mask.src.ip = 0xFFFFFFFF; + exp->mask.src.u.tcp.port = 0; + exp->mask.dst.ip = 0xFFFFFFFF; + exp->mask.dst.u.tcp.port = 0xFFFF; + exp->mask.dst.protonum = 0xFF; + exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple channels */ + + if (ct->tuplehash[dir].tuple.src.ip != + ct->tuplehash[!dir].tuple.dst.ip && nat_t120_hook) { + /* NAT needed */ + ret = nat_t120_hook(pskb, ct, ctinfo, data, dataoff, addr, + port, exp); + } else { /* Conntrack only */ + exp->expectfn = NULL; + if (ip_conntrack_expect_related(exp) == 0) { + DEBUGP("ip_ct_h323: expect T.120 " + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(exp->tuple.src.ip), + ntohs(exp->tuple.src.u.tcp.port), + NIPQUAD(exp->tuple.dst.ip), + ntohs(exp->tuple.dst.u.tcp.port)); + } else + ret = -1; + } + + ip_conntrack_expect_put(exp); + + return ret; +} + +/****************************************************************************/ +static int process_h245_channel(struct sk_buff **pskb, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H2250LogicalChannelParameters * channel) +{ + int ret; + + if (channel->options & eH2250LogicalChannelParameters_mediaChannel) { + /* RTP */ + ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, + &channel->mediaChannel); + if (ret < 0) + return -1; + } + + if (channel-> + options & eH2250LogicalChannelParameters_mediaControlChannel) { + /* RTCP */ + ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, + &channel->mediaControlChannel); + if (ret < 0) + return -1; + } + + return 0; +} + +/****************************************************************************/ +static int process_olc(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + OpenLogicalChannel * olc) +{ + int ret; + + DEBUGP("ip_ct_h323: OpenLogicalChannel\n"); + + if (olc->forwardLogicalChannelParameters.multiplexParameters.choice == + eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters) + { + ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff, + &olc-> + forwardLogicalChannelParameters. + multiplexParameters. + h2250LogicalChannelParameters); + if (ret < 0) + return -1; + } + + if ((olc->options & + eOpenLogicalChannel_reverseLogicalChannelParameters) && + (olc->reverseLogicalChannelParameters.options & + eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters) + && (olc->reverseLogicalChannelParameters.multiplexParameters. + choice == + eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)) + { + ret = + process_h245_channel(pskb, ct, ctinfo, data, dataoff, + &olc-> + reverseLogicalChannelParameters. + multiplexParameters. + h2250LogicalChannelParameters); + if (ret < 0) + return -1; + } + + if ((olc->options & eOpenLogicalChannel_separateStack) && + olc->forwardLogicalChannelParameters.dataType.choice == + eDataType_data && + olc->forwardLogicalChannelParameters.dataType.data.application. + choice == eDataApplicationCapability_application_t120 && + olc->forwardLogicalChannelParameters.dataType.data.application. + t120.choice == eDataProtocolCapability_separateLANStack && + olc->separateStack.networkAddress.choice == + eNetworkAccessParameters_networkAddress_localAreaAddress) { + ret = expect_t120(pskb, ct, ctinfo, data, dataoff, + &olc->separateStack.networkAddress. + localAreaAddress); + if (ret < 0) + return -1; + } + + return 0; +} + +/****************************************************************************/ +static int process_olca(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + OpenLogicalChannelAck * olca) +{ + H2250LogicalChannelAckParameters *ack; + int ret; + + DEBUGP("ip_ct_h323: OpenLogicalChannelAck\n"); + + if ((olca->options & + eOpenLogicalChannelAck_reverseLogicalChannelParameters) && + (olca->reverseLogicalChannelParameters.options & + eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters) + && (olca->reverseLogicalChannelParameters.multiplexParameters. + choice == + eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)) + { + ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff, + &olca-> + reverseLogicalChannelParameters. + multiplexParameters. + h2250LogicalChannelParameters); + if (ret < 0) + return -1; + } + + if ((olca->options & + eOpenLogicalChannelAck_forwardMultiplexAckParameters) && + (olca->forwardMultiplexAckParameters.choice == + eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters)) + { + ack = &olca->forwardMultiplexAckParameters. + h2250LogicalChannelAckParameters; + if (ack->options & + eH2250LogicalChannelAckParameters_mediaChannel) { + /* RTP */ + ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, + &ack->mediaChannel); + if (ret < 0) + return -1; + } + + if (ack->options & + eH2250LogicalChannelAckParameters_mediaControlChannel) { + /* RTCP */ + ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, + &ack->mediaControlChannel); + if (ret < 0) + return -1; + } + } + + return 0; +} + +/****************************************************************************/ +static int process_h245(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + MultimediaSystemControlMessage * mscm) +{ + switch (mscm->choice) { + case eMultimediaSystemControlMessage_request: + if (mscm->request.choice == + eRequestMessage_openLogicalChannel) { + return process_olc(pskb, ct, ctinfo, data, dataoff, + &mscm->request.openLogicalChannel); + } + DEBUGP("ip_ct_h323: H.245 Request %d\n", + mscm->request.choice); + break; + case eMultimediaSystemControlMessage_response: + if (mscm->response.choice == + eResponseMessage_openLogicalChannelAck) { + return process_olca(pskb, ct, ctinfo, data, dataoff, + &mscm->response. + openLogicalChannelAck); + } + DEBUGP("ip_ct_h323: H.245 Response %d\n", + mscm->response.choice); + break; + default: + DEBUGP("ip_ct_h323: H.245 signal %d\n", mscm->choice); + break; + } + + return 0; +} + +/****************************************************************************/ +static int h245_help(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo) +{ + static MultimediaSystemControlMessage mscm; + unsigned char *data = NULL; + int datalen; + int dataoff; + int ret; + + /* Until there's been traffic both ways, don't look in packets. */ + if (ctinfo != IP_CT_ESTABLISHED + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { + return NF_ACCEPT; + } + DEBUGP("ip_ct_h245: skblen = %u\n", (*pskb)->len); + + spin_lock_bh(&ip_h323_lock); + + /* Process each TPKT */ + while (get_tpkt_data(pskb, ct, ctinfo, &data, &datalen, &dataoff)) { + DEBUGP("ip_ct_h245: TPKT %u.%u.%u.%u->%u.%u.%u.%u, len=%d\n", + NIPQUAD((*pskb)->nh.iph->saddr), + NIPQUAD((*pskb)->nh.iph->daddr), datalen); + + /* Decode H.245 signal */ + ret = DecodeMultimediaSystemControlMessage(data, datalen, + &mscm); + if (ret < 0) { + if (net_ratelimit()) + printk("ip_ct_h245: decoding error: %s\n", + ret == H323_ERROR_BOUND ? + "out of bound" : "out of range"); + /* We don't drop when decoding error */ + break; + } + + /* Process H.245 signal */ + if (process_h245(pskb, ct, ctinfo, &data, dataoff, &mscm) < 0) + goto drop; + } + + spin_unlock_bh(&ip_h323_lock); + return NF_ACCEPT; + + drop: + spin_unlock_bh(&ip_h323_lock); + if (net_ratelimit()) + printk("ip_ct_h245: packet dropped\n"); + return NF_DROP; +} + +/****************************************************************************/ +static struct ip_conntrack_helper ip_conntrack_helper_h245 = { + .name = "H.245", + .me = THIS_MODULE, + .max_expected = H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */ , + .timeout = 240, + .tuple = {.dst = {.protonum = IPPROTO_TCP}}, + .mask = {.src = {.u = {0xFFFF}}, + .dst = {.protonum = 0xFF}}, + .help = h245_help +}; + +/****************************************************************************/ +void ip_conntrack_h245_expect(struct ip_conntrack *new, + struct ip_conntrack_expect *this) +{ + write_lock_bh(&ip_conntrack_lock); + new->helper = &ip_conntrack_helper_h245; + write_unlock_bh(&ip_conntrack_lock); +} + +/****************************************************************************/ +static int get_h225_addr(unsigned char *data, TransportAddress * addr, + u_int32_t * ip, u_int16_t * port) +{ + unsigned char *p; + + if (addr->choice != eTransportAddress_ipAddress) + return 0; + + p = data + addr->ipAddress.ip; + *ip = htonl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3])); + *port = (p[4] << 8) | (p[5]); + + return 1; +} + +/****************************************************************************/ +static int expect_h245(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + TransportAddress * addr) +{ + int dir = CTINFO2DIR(ctinfo); + int ret = 0; + u_int32_t ip; + u_int16_t port; + struct ip_conntrack_expect *exp = NULL; + + /* Read h245Address */ + if (!get_h225_addr(*data, addr, &ip, &port) || + ip != ct->tuplehash[dir].tuple.src.ip || port == 0) + return 0; + + /* Create expect for h245 connection */ + if ((exp = ip_conntrack_expect_alloc(ct)) == NULL) + return -1; + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip; + exp->tuple.src.u.tcp.port = 0; + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip; + exp->tuple.dst.u.tcp.port = htons(port); + exp->tuple.dst.protonum = IPPROTO_TCP; + exp->mask.src.ip = 0xFFFFFFFF; + exp->mask.src.u.tcp.port = 0; + exp->mask.dst.ip = 0xFFFFFFFF; + exp->mask.dst.u.tcp.port = 0xFFFF; + exp->mask.dst.protonum = 0xFF; + exp->flags = 0; + + if (ct->tuplehash[dir].tuple.src.ip != + ct->tuplehash[!dir].tuple.dst.ip && nat_h245_hook) { + /* NAT needed */ + ret = nat_h245_hook(pskb, ct, ctinfo, data, dataoff, addr, + port, exp); + } else { /* Conntrack only */ + exp->expectfn = ip_conntrack_h245_expect; + + if (ip_conntrack_expect_related(exp) == 0) { + DEBUGP("ip_ct_q931: expect H.245 " + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(exp->tuple.src.ip), + ntohs(exp->tuple.src.u.tcp.port), + NIPQUAD(exp->tuple.dst.ip), + ntohs(exp->tuple.dst.u.tcp.port)); + } else + ret = -1; + } + + ip_conntrack_expect_put(exp); + + return ret; +} + +/****************************************************************************/ +static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + Setup_UUIE * setup) +{ + int dir = CTINFO2DIR(ctinfo); + int ret; + int i; + u_int32_t ip; + u_int16_t port; + + DEBUGP("ip_ct_q931: Setup\n"); + + if (setup->options & eSetup_UUIE_h245Address) { + ret = expect_h245(pskb, ct, ctinfo, data, dataoff, + &setup->h245Address); + if (ret < 0) + return -1; + } + + if ((setup->options & eSetup_UUIE_destCallSignalAddress) && + (set_h225_addr_hook) && + get_h225_addr(*data, &setup->destCallSignalAddress, &ip, &port) && + ip != ct->tuplehash[!dir].tuple.src.ip) { + DEBUGP("ip_ct_q931: set destCallSignalAddress " + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(ip), port, + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip), + ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port)); + ret = set_h225_addr_hook(pskb, data, dataoff, + &setup->destCallSignalAddress, + ct->tuplehash[!dir].tuple.src.ip, + ntohs(ct->tuplehash[!dir].tuple.src. + u.tcp.port)); + if (ret < 0) + return -1; + } + + if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) && + (set_h225_addr_hook) && + get_h225_addr(*data, &setup->sourceCallSignalAddress, &ip, &port) + && ip != ct->tuplehash[!dir].tuple.dst.ip) { + DEBUGP("ip_ct_q931: set sourceCallSignalAddress " + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(ip), port, + NIPQUAD(ct->tuplehash[!dir].tuple.dst.ip), + ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port)); + ret = set_h225_addr_hook(pskb, data, dataoff, + &setup->sourceCallSignalAddress, + ct->tuplehash[!dir].tuple.dst.ip, + ntohs(ct->tuplehash[!dir].tuple.dst. + u.tcp.port)); + if (ret < 0) + return -1; + } + + if (setup->options & eSetup_UUIE_fastStart) { + for (i = 0; i < setup->fastStart.count; i++) { + ret = process_olc(pskb, ct, ctinfo, data, dataoff, + &setup->fastStart.item[i]); + if (ret < 0) + return -1; + } + } + + return 0; +} + +/****************************************************************************/ +static int process_callproceeding(struct sk_buff **pskb, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + CallProceeding_UUIE * callproc) +{ + int ret; + int i; + + DEBUGP("ip_ct_q931: CallProceeding\n"); + + if (callproc->options & eCallProceeding_UUIE_h245Address) { + ret = expect_h245(pskb, ct, ctinfo, data, dataoff, + &callproc->h245Address); + if (ret < 0) + return -1; + } + + if (callproc->options & eCallProceeding_UUIE_fastStart) { + for (i = 0; i < callproc->fastStart.count; i++) { + ret = process_olc(pskb, ct, ctinfo, data, dataoff, + &callproc->fastStart.item[i]); + if (ret < 0) + return -1; + } + } + + return 0; +} + +/****************************************************************************/ +static int process_connect(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + Connect_UUIE * connect) +{ + int ret; + int i; + + DEBUGP("ip_ct_q931: Connect\n"); + + if (connect->options & eConnect_UUIE_h245Address) { + ret = expect_h245(pskb, ct, ctinfo, data, dataoff, + &connect->h245Address); + if (ret < 0) + return -1; + } + + if (connect->options & eConnect_UUIE_fastStart) { + for (i = 0; i < connect->fastStart.count; i++) { + ret = process_olc(pskb, ct, ctinfo, data, dataoff, + &connect->fastStart.item[i]); + if (ret < 0) + return -1; + } + } + + return 0; +} + +/****************************************************************************/ +static int process_alerting(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + Alerting_UUIE * alert) +{ + int ret; + int i; + + DEBUGP("ip_ct_q931: Alerting\n"); + + if (alert->options & eAlerting_UUIE_h245Address) { + ret = expect_h245(pskb, ct, ctinfo, data, dataoff, + &alert->h245Address); + if (ret < 0) + return -1; + } + + if (alert->options & eAlerting_UUIE_fastStart) { + for (i = 0; i < alert->fastStart.count; i++) { + ret = process_olc(pskb, ct, ctinfo, data, dataoff, + &alert->fastStart.item[i]); + if (ret < 0) + return -1; + } + } + + return 0; +} + +/****************************************************************************/ +static int process_information(struct sk_buff **pskb, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + Information_UUIE * info) +{ + int ret; + int i; + + DEBUGP("ip_ct_q931: Information\n"); + + if (info->options & eInformation_UUIE_fastStart) { + for (i = 0; i < info->fastStart.count; i++) { + ret = process_olc(pskb, ct, ctinfo, data, dataoff, + &info->fastStart.item[i]); + if (ret < 0) + return -1; + } + } + + return 0; +} + +/****************************************************************************/ +static int process_facility(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + Facility_UUIE * facility) +{ + int ret; + int i; + + DEBUGP("ip_ct_q931: Facility\n"); + + if (facility->options & eFacility_UUIE_h245Address) { + ret = expect_h245(pskb, ct, ctinfo, data, dataoff, + &facility->h245Address); + if (ret < 0) + return -1; + } + + if (facility->options & eFacility_UUIE_fastStart) { + for (i = 0; i < facility->fastStart.count; i++) { + ret = process_olc(pskb, ct, ctinfo, data, dataoff, + &facility->fastStart.item[i]); + if (ret < 0) + return -1; + } + } + + return 0; +} + +/****************************************************************************/ +static int process_progress(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + Progress_UUIE * progress) +{ + int ret; + int i; + + DEBUGP("ip_ct_q931: Progress\n"); + + if (progress->options & eProgress_UUIE_h245Address) { + ret = expect_h245(pskb, ct, ctinfo, data, dataoff, + &progress->h245Address); + if (ret < 0) + return -1; + } + + if (progress->options & eProgress_UUIE_fastStart) { + for (i = 0; i < progress->fastStart.count; i++) { + ret = process_olc(pskb, ct, ctinfo, data, dataoff, + &progress->fastStart.item[i]); + if (ret < 0) + return -1; + } + } + + return 0; +} + +/****************************************************************************/ +static int process_q931(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, Q931 * q931) +{ + H323_UU_PDU *pdu = &q931->UUIE.h323_uu_pdu; + int i; + int ret = 0; + + switch (pdu->h323_message_body.choice) { + case eH323_UU_PDU_h323_message_body_setup: + ret = process_setup(pskb, ct, ctinfo, data, dataoff, + &pdu->h323_message_body.setup); + break; + case eH323_UU_PDU_h323_message_body_callProceeding: + ret = process_callproceeding(pskb, ct, ctinfo, data, dataoff, + &pdu->h323_message_body. + callProceeding); + break; + case eH323_UU_PDU_h323_message_body_connect: + ret = process_connect(pskb, ct, ctinfo, data, dataoff, + &pdu->h323_message_body.connect); + break; + case eH323_UU_PDU_h323_message_body_alerting: + ret = process_alerting(pskb, ct, ctinfo, data, dataoff, + &pdu->h323_message_body.alerting); + break; + case eH323_UU_PDU_h323_message_body_information: + ret = process_information(pskb, ct, ctinfo, data, dataoff, + &pdu->h323_message_body. + information); + break; + case eH323_UU_PDU_h323_message_body_facility: + ret = process_facility(pskb, ct, ctinfo, data, dataoff, + &pdu->h323_message_body.facility); + break; + case eH323_UU_PDU_h323_message_body_progress: + ret = process_progress(pskb, ct, ctinfo, data, dataoff, + &pdu->h323_message_body.progress); + break; + default: + DEBUGP("ip_ct_q931: Q.931 signal %d\n", + pdu->h323_message_body.choice); + break; + } + + if (ret < 0) + return -1; + + if (pdu->options & eH323_UU_PDU_h245Control) { + for (i = 0; i < pdu->h245Control.count; i++) { + ret = process_h245(pskb, ct, ctinfo, data, dataoff, + &pdu->h245Control.item[i]); + if (ret < 0) + return -1; + } + } + + return 0; +} + +/****************************************************************************/ +static int q931_help(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo) +{ + static Q931 q931; + unsigned char *data = NULL; + int datalen; + int dataoff; + int ret; + + /* Until there's been traffic both ways, don't look in packets. */ + if (ctinfo != IP_CT_ESTABLISHED + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { + return NF_ACCEPT; + } + DEBUGP("ip_ct_q931: skblen = %u\n", (*pskb)->len); + + spin_lock_bh(&ip_h323_lock); + + /* Process each TPKT */ + while (get_tpkt_data(pskb, ct, ctinfo, &data, &datalen, &dataoff)) { + DEBUGP("ip_ct_q931: TPKT %u.%u.%u.%u->%u.%u.%u.%u, len=%d\n", + NIPQUAD((*pskb)->nh.iph->saddr), + NIPQUAD((*pskb)->nh.iph->daddr), datalen); + + /* Decode Q.931 signal */ + ret = DecodeQ931(data, datalen, &q931); + if (ret < 0) { + if (net_ratelimit()) + printk("ip_ct_q931: decoding error: %s\n", + ret == H323_ERROR_BOUND ? + "out of bound" : "out of range"); + /* We don't drop when decoding error */ + break; + } + + /* Process Q.931 signal */ + if (process_q931(pskb, ct, ctinfo, &data, dataoff, &q931) < 0) + goto drop; + } + + spin_unlock_bh(&ip_h323_lock); + return NF_ACCEPT; + + drop: + spin_unlock_bh(&ip_h323_lock); + if (net_ratelimit()) + printk("ip_ct_q931: packet dropped\n"); + return NF_DROP; +} + +/****************************************************************************/ +static struct ip_conntrack_helper ip_conntrack_helper_q931 = { + .name = "Q.931", + .me = THIS_MODULE, + .max_expected = H323_RTP_CHANNEL_MAX * 4 + 4 /* T.120 and H.245 */ , + .timeout = 240, + .tuple = {.src = {.u = {__constant_htons(Q931_PORT)}}, + .dst = {.protonum = IPPROTO_TCP}}, + .mask = {.src = {.u = {0xFFFF}}, + .dst = {.protonum = 0xFF}}, + .help = q931_help +}; + +/****************************************************************************/ +void ip_conntrack_q931_expect(struct ip_conntrack *new, + struct ip_conntrack_expect *this) +{ + write_lock_bh(&ip_conntrack_lock); + new->helper = &ip_conntrack_helper_q931; + write_unlock_bh(&ip_conntrack_lock); +} + +/****************************************************************************/ +static unsigned char *get_udp_data(struct sk_buff **pskb, int *datalen) +{ + struct udphdr _uh, *uh; + int dataoff; + + uh = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4, sizeof(_uh), + &_uh); + if (uh == NULL) + return NULL; + dataoff = (*pskb)->nh.iph->ihl * 4 + sizeof(_uh); + if (dataoff >= (*pskb)->len) + return NULL; + *datalen = (*pskb)->len - dataoff; + return skb_header_pointer(*pskb, dataoff, *datalen, h323_buffer); +} + +/****************************************************************************/ +static struct ip_conntrack_expect *find_expect(struct ip_conntrack *ct, + u_int32_t ip, u_int16_t port) +{ + struct ip_conntrack_expect *exp; + struct ip_conntrack_tuple tuple; + + tuple.src.ip = 0; + tuple.src.u.tcp.port = 0; + tuple.dst.ip = ip; + tuple.dst.u.tcp.port = htons(port); + tuple.dst.protonum = IPPROTO_TCP; + + exp = __ip_conntrack_expect_find(&tuple); + if (exp->master == ct) + return exp; + return NULL; +} + +/****************************************************************************/ +static int set_expect_timeout(struct ip_conntrack_expect *exp, + unsigned timeout) +{ + if (!exp || !del_timer(&exp->timeout)) + return 0; + + exp->timeout.expires = jiffies + timeout * HZ; + add_timer(&exp->timeout); + + return 1; +} + +/****************************************************************************/ +static int expect_q931(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, + TransportAddress * addr, int count) +{ + struct ip_ct_h323_master *info = &ct->help.ct_h323_info; + int dir = CTINFO2DIR(ctinfo); + int ret = 0; + int i; + u_int32_t ip; + u_int16_t port; + struct ip_conntrack_expect *exp; + + /* Look for the first related address */ + for (i = 0; i < count; i++) { + if (get_h225_addr(*data, &addr[i], &ip, &port) && + ip == ct->tuplehash[dir].tuple.src.ip && port != 0) + break; + } + + if (i >= count) /* Not found */ + return 0; + + /* Create expect for Q.931 */ + if ((exp = ip_conntrack_expect_alloc(ct)) == NULL) + return -1; + exp->tuple.src.ip = gkrouted_only ? /* only accept calls from GK? */ + ct->tuplehash[!dir].tuple.src.ip : 0; + exp->tuple.src.u.tcp.port = 0; + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip; + exp->tuple.dst.u.tcp.port = htons(port); + exp->tuple.dst.protonum = IPPROTO_TCP; + exp->mask.src.ip = gkrouted_only ? 0xFFFFFFFF : 0; + exp->mask.src.u.tcp.port = 0; + exp->mask.dst.ip = 0xFFFFFFFF; + exp->mask.dst.u.tcp.port = 0xFFFF; + exp->mask.dst.protonum = 0xFF; + exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple calls */ + + if (nat_q931_hook) { /* Need NAT */ + ret = nat_q931_hook(pskb, ct, ctinfo, data, addr, i, + port, exp); + } else { /* Conntrack only */ + exp->expectfn = ip_conntrack_q931_expect; + + if (ip_conntrack_expect_related(exp) == 0) { + DEBUGP("ip_ct_ras: expect Q.931 " + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(exp->tuple.src.ip), + ntohs(exp->tuple.src.u.tcp.port), + NIPQUAD(exp->tuple.dst.ip), + ntohs(exp->tuple.dst.u.tcp.port)); + + /* Save port for looking up expect in processing RCF */ + info->sig_port[dir] = port; + } else + ret = -1; + } + + ip_conntrack_expect_put(exp); + + return ret; +} + +/****************************************************************************/ +static int process_grq(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, GatekeeperRequest * grq) +{ + DEBUGP("ip_ct_ras: GRQ\n"); + + if (set_ras_addr_hook) /* NATed */ + return set_ras_addr_hook(pskb, ct, ctinfo, data, + &grq->rasAddress, 1); + return 0; +} + +/* Declare before using */ +static void ip_conntrack_ras_expect(struct ip_conntrack *new, + struct ip_conntrack_expect *this); + +/****************************************************************************/ +static int process_gcf(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, GatekeeperConfirm * gcf) +{ + int dir = CTINFO2DIR(ctinfo); + int ret = 0; + u_int32_t ip; + u_int16_t port; + struct ip_conntrack_expect *exp; + + DEBUGP("ip_ct_ras: GCF\n"); + + if (!get_h225_addr(*data, &gcf->rasAddress, &ip, &port)) + return 0; + + /* Registration port is the same as discovery port */ + if (ip == ct->tuplehash[dir].tuple.src.ip && + port == ntohs(ct->tuplehash[dir].tuple.src.u.udp.port)) + return 0; + + /* Avoid RAS expectation loops. A GCF is never expected. */ + if (test_bit(IPS_EXPECTED_BIT, &ct->status)) + return 0; + + /* Need new expect */ + if ((exp = ip_conntrack_expect_alloc(ct)) == NULL) + return -1; + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip; + exp->tuple.src.u.tcp.port = 0; + exp->tuple.dst.ip = ip; + exp->tuple.dst.u.tcp.port = htons(port); + exp->tuple.dst.protonum = IPPROTO_UDP; + exp->mask.src.ip = 0xFFFFFFFF; + exp->mask.src.u.tcp.port = 0; + exp->mask.dst.ip = 0xFFFFFFFF; + exp->mask.dst.u.tcp.port = 0xFFFF; + exp->mask.dst.protonum = 0xFF; + exp->flags = 0; + exp->expectfn = ip_conntrack_ras_expect; + if (ip_conntrack_expect_related(exp) == 0) { + DEBUGP("ip_ct_ras: expect RAS " + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(exp->tuple.src.ip), + ntohs(exp->tuple.src.u.tcp.port), + NIPQUAD(exp->tuple.dst.ip), + ntohs(exp->tuple.dst.u.tcp.port)); + } else + ret = -1; + + ip_conntrack_expect_put(exp); + + return ret; +} + +/****************************************************************************/ +static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, RegistrationRequest * rrq) +{ + struct ip_ct_h323_master *info = &ct->help.ct_h323_info; + int ret; + + DEBUGP("ip_ct_ras: RRQ\n"); + + ret = expect_q931(pskb, ct, ctinfo, data, + rrq->callSignalAddress.item, + rrq->callSignalAddress.count); + if (ret < 0) + return -1; + + if (set_ras_addr_hook) { + ret = set_ras_addr_hook(pskb, ct, ctinfo, data, + rrq->rasAddress.item, + rrq->rasAddress.count); + if (ret < 0) + return -1; + } + + if (rrq->options & eRegistrationRequest_timeToLive) { + DEBUGP("ip_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive); + info->timeout = rrq->timeToLive; + } else + info->timeout = 0; + + return 0; +} + +/****************************************************************************/ +static int process_rcf(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, RegistrationConfirm * rcf) +{ + struct ip_ct_h323_master *info = &ct->help.ct_h323_info; + int dir = CTINFO2DIR(ctinfo); + int ret; + struct ip_conntrack_expect *exp; + + DEBUGP("ip_ct_ras: RCF\n"); + + if (set_sig_addr_hook) { + ret = set_sig_addr_hook(pskb, ct, ctinfo, data, + rcf->callSignalAddress.item, + rcf->callSignalAddress.count); + if (ret < 0) + return -1; + } + + if (rcf->options & eRegistrationConfirm_timeToLive) { + DEBUGP("ip_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive); + info->timeout = rcf->timeToLive; + } + + if (info->timeout > 0) { + DEBUGP + ("ip_ct_ras: set RAS connection timeout to %u seconds\n", + info->timeout); + ip_ct_refresh_acct(ct, ctinfo, NULL, info->timeout * HZ); + + /* Set expect timeout */ + read_lock_bh(&ip_conntrack_lock); + exp = find_expect(ct, ct->tuplehash[dir].tuple.dst.ip, + info->sig_port[!dir]); + if (exp) { + DEBUGP("ip_ct_ras: set Q.931 expect " + "(%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu) " + "timeout to %u seconds\n", + NIPQUAD(exp->tuple.src.ip), + ntohs(exp->tuple.src.u.tcp.port), + NIPQUAD(exp->tuple.dst.ip), + ntohs(exp->tuple.dst.u.tcp.port), + info->timeout); + set_expect_timeout(exp, info->timeout); + } + read_unlock_bh(&ip_conntrack_lock); + } + + return 0; +} + +/****************************************************************************/ +static int process_urq(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, UnregistrationRequest * urq) +{ + struct ip_ct_h323_master *info = &ct->help.ct_h323_info; + int dir = CTINFO2DIR(ctinfo); + int ret; + + DEBUGP("ip_ct_ras: URQ\n"); + + if (set_sig_addr_hook) { + ret = set_sig_addr_hook(pskb, ct, ctinfo, data, + urq->callSignalAddress.item, + urq->callSignalAddress.count); + if (ret < 0) + return -1; + } + + /* Clear old expect */ + ip_ct_remove_expectations(ct); + info->sig_port[dir] = 0; + info->sig_port[!dir] = 0; + + /* Give it 30 seconds for UCF or URJ */ + ip_ct_refresh_acct(ct, ctinfo, NULL, 30 * HZ); + + return 0; +} + +/****************************************************************************/ +static int process_arq(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, AdmissionRequest * arq) +{ + struct ip_ct_h323_master *info = &ct->help.ct_h323_info; + int dir = CTINFO2DIR(ctinfo); + u_int32_t ip; + u_int16_t port; + + DEBUGP("ip_ct_ras: ARQ\n"); + + if ((arq->options & eAdmissionRequest_destCallSignalAddress) && + get_h225_addr(*data, &arq->destCallSignalAddress, &ip, &port) && + ip == ct->tuplehash[dir].tuple.src.ip && + port == info->sig_port[dir] && set_h225_addr_hook) { + /* Answering ARQ */ + return set_h225_addr_hook(pskb, data, 0, + &arq->destCallSignalAddress, + ct->tuplehash[!dir].tuple.dst.ip, + info->sig_port[!dir]); + } + + if ((arq->options & eAdmissionRequest_srcCallSignalAddress) && + get_h225_addr(*data, &arq->srcCallSignalAddress, &ip, &port) && + ip == ct->tuplehash[dir].tuple.src.ip && set_h225_addr_hook) { + /* Calling ARQ */ + return set_h225_addr_hook(pskb, data, 0, + &arq->srcCallSignalAddress, + ct->tuplehash[!dir].tuple.dst.ip, + port); + } + + return 0; +} + +/****************************************************************************/ +static int process_acf(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, AdmissionConfirm * acf) +{ + int dir = CTINFO2DIR(ctinfo); + int ret = 0; + u_int32_t ip; + u_int16_t port; + struct ip_conntrack_expect *exp; + + DEBUGP("ip_ct_ras: ACF\n"); + + if (!get_h225_addr(*data, &acf->destCallSignalAddress, &ip, &port)) + return 0; + + if (ip == ct->tuplehash[dir].tuple.dst.ip) { /* Answering ACF */ + if (set_sig_addr_hook) + return set_sig_addr_hook(pskb, ct, ctinfo, data, + &acf->destCallSignalAddress, + 1); + return 0; + } + + /* Need new expect */ + if ((exp = ip_conntrack_expect_alloc(ct)) == NULL) + return -1; + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip; + exp->tuple.src.u.tcp.port = 0; + exp->tuple.dst.ip = ip; + exp->tuple.dst.u.tcp.port = htons(port); + exp->tuple.dst.protonum = IPPROTO_TCP; + exp->mask.src.ip = 0xFFFFFFFF; + exp->mask.src.u.tcp.port = 0; + exp->mask.dst.ip = 0xFFFFFFFF; + exp->mask.dst.u.tcp.port = 0xFFFF; + exp->mask.dst.protonum = 0xFF; + exp->flags = IP_CT_EXPECT_PERMANENT; + exp->expectfn = ip_conntrack_q931_expect; + + if (ip_conntrack_expect_related(exp) == 0) { + DEBUGP("ip_ct_ras: expect Q.931 " + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(exp->tuple.src.ip), + ntohs(exp->tuple.src.u.tcp.port), + NIPQUAD(exp->tuple.dst.ip), + ntohs(exp->tuple.dst.u.tcp.port)); + } else + ret = -1; + + ip_conntrack_expect_put(exp); + + return ret; +} + +/****************************************************************************/ +static int process_lrq(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, LocationRequest * lrq) +{ + DEBUGP("ip_ct_ras: LRQ\n"); + + if (set_ras_addr_hook) + return set_ras_addr_hook(pskb, ct, ctinfo, data, + &lrq->replyAddress, 1); + return 0; +} + +/****************************************************************************/ +static int process_lcf(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, LocationConfirm * lcf) +{ + int dir = CTINFO2DIR(ctinfo); + int ret = 0; + u_int32_t ip; + u_int16_t port; + struct ip_conntrack_expect *exp = NULL; + + DEBUGP("ip_ct_ras: LCF\n"); + + if (!get_h225_addr(*data, &lcf->callSignalAddress, &ip, &port)) + return 0; + + /* Need new expect for call signal */ + if ((exp = ip_conntrack_expect_alloc(ct)) == NULL) + return -1; + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip; + exp->tuple.src.u.tcp.port = 0; + exp->tuple.dst.ip = ip; + exp->tuple.dst.u.tcp.port = htons(port); + exp->tuple.dst.protonum = IPPROTO_TCP; + exp->mask.src.ip = 0xFFFFFFFF; + exp->mask.src.u.tcp.port = 0; + exp->mask.dst.ip = 0xFFFFFFFF; + exp->mask.dst.u.tcp.port = 0xFFFF; + exp->mask.dst.protonum = 0xFF; + exp->flags = IP_CT_EXPECT_PERMANENT; + exp->expectfn = ip_conntrack_q931_expect; + + if (ip_conntrack_expect_related(exp) == 0) { + DEBUGP("ip_ct_ras: expect Q.931 " + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(exp->tuple.src.ip), + ntohs(exp->tuple.src.u.tcp.port), + NIPQUAD(exp->tuple.dst.ip), + ntohs(exp->tuple.dst.u.tcp.port)); + } else + ret = -1; + + ip_conntrack_expect_put(exp); + + /* Ignore rasAddress */ + + return ret; +} + +/****************************************************************************/ +static int process_irr(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, InfoRequestResponse * irr) +{ + int ret; + + DEBUGP("ip_ct_ras: IRR\n"); + + if (set_ras_addr_hook) { + ret = set_ras_addr_hook(pskb, ct, ctinfo, data, + &irr->rasAddress, 1); + if (ret < 0) + return -1; + } + + if (set_sig_addr_hook) { + ret = set_sig_addr_hook(pskb, ct, ctinfo, data, + irr->callSignalAddress.item, + irr->callSignalAddress.count); + if (ret < 0) + return -1; + } + + return 0; +} + +/****************************************************************************/ +static int process_ras(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, RasMessage * ras) +{ + switch (ras->choice) { + case eRasMessage_gatekeeperRequest: + return process_grq(pskb, ct, ctinfo, data, + &ras->gatekeeperRequest); + case eRasMessage_gatekeeperConfirm: + return process_gcf(pskb, ct, ctinfo, data, + &ras->gatekeeperConfirm); + case eRasMessage_registrationRequest: + return process_rrq(pskb, ct, ctinfo, data, + &ras->registrationRequest); + case eRasMessage_registrationConfirm: + return process_rcf(pskb, ct, ctinfo, data, + &ras->registrationConfirm); + case eRasMessage_unregistrationRequest: + return process_urq(pskb, ct, ctinfo, data, + &ras->unregistrationRequest); + case eRasMessage_admissionRequest: + return process_arq(pskb, ct, ctinfo, data, + &ras->admissionRequest); + case eRasMessage_admissionConfirm: + return process_acf(pskb, ct, ctinfo, data, + &ras->admissionConfirm); + case eRasMessage_locationRequest: + return process_lrq(pskb, ct, ctinfo, data, + &ras->locationRequest); + case eRasMessage_locationConfirm: + return process_lcf(pskb, ct, ctinfo, data, + &ras->locationConfirm); + case eRasMessage_infoRequestResponse: + return process_irr(pskb, ct, ctinfo, data, + &ras->infoRequestResponse); + default: + DEBUGP("ip_ct_ras: RAS message %d\n", ras->choice); + break; + } + + return 0; +} + +/****************************************************************************/ +static int ras_help(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo) +{ + static RasMessage ras; + unsigned char *data; + int datalen = 0; + int ret; + + DEBUGP("ip_ct_ras: skblen = %u\n", (*pskb)->len); + + spin_lock_bh(&ip_h323_lock); + + /* Get UDP data */ + data = get_udp_data(pskb, &datalen); + if (data == NULL) + goto accept; + DEBUGP("ip_ct_ras: RAS message %u.%u.%u.%u->%u.%u.%u.%u, len=%d\n", + NIPQUAD((*pskb)->nh.iph->saddr), + NIPQUAD((*pskb)->nh.iph->daddr), datalen); + + /* Decode RAS message */ + ret = DecodeRasMessage(data, datalen, &ras); + if (ret < 0) { + if (net_ratelimit()) + printk("ip_ct_ras: decoding error: %s\n", + ret == H323_ERROR_BOUND ? + "out of bound" : "out of range"); + goto accept; + } + + /* Process RAS message */ + if (process_ras(pskb, ct, ctinfo, &data, &ras) < 0) + goto drop; + + accept: + spin_unlock_bh(&ip_h323_lock); + return NF_ACCEPT; + + drop: + spin_unlock_bh(&ip_h323_lock); + if (net_ratelimit()) + printk("ip_ct_ras: packet dropped\n"); + return NF_DROP; +} + +/****************************************************************************/ +static struct ip_conntrack_helper ip_conntrack_helper_ras = { + .name = "RAS", + .me = THIS_MODULE, + .max_expected = 32, + .timeout = 240, + .tuple = {.src = {.u = {__constant_htons(RAS_PORT)}}, + .dst = {.protonum = IPPROTO_UDP}}, + .mask = {.src = {.u = {0xFFFE}}, + .dst = {.protonum = 0xFF}}, + .help = ras_help, +}; + +/****************************************************************************/ +static void ip_conntrack_ras_expect(struct ip_conntrack *new, + struct ip_conntrack_expect *this) +{ + write_lock_bh(&ip_conntrack_lock); + new->helper = &ip_conntrack_helper_ras; + write_unlock_bh(&ip_conntrack_lock); +} + +/****************************************************************************/ +/* Not __exit - called from init() */ +static void fini(void) +{ + ip_conntrack_helper_unregister(&ip_conntrack_helper_ras); + ip_conntrack_helper_unregister(&ip_conntrack_helper_q931); + kfree(h323_buffer); + DEBUGP("ip_ct_h323: fini\n"); +} + +/****************************************************************************/ +static int __init init(void) +{ + int ret; + + h323_buffer = kmalloc(65536, GFP_KERNEL); + if (!h323_buffer) + return -ENOMEM; + if ((ret = ip_conntrack_helper_register(&ip_conntrack_helper_q931)) || + (ret = ip_conntrack_helper_register(&ip_conntrack_helper_ras))) { + fini(); + return ret; + } + + DEBUGP("ip_ct_h323: init success\n"); + return 0; +} + +/****************************************************************************/ +module_init(init); +module_exit(fini); + +EXPORT_SYMBOL(get_h245_addr); +EXPORT_SYMBOL(get_h225_addr); +EXPORT_SYMBOL(ip_conntrack_h245_expect); +EXPORT_SYMBOL(ip_conntrack_q931_expect); +EXPORT_SYMBOL(set_h245_addr_hook); +EXPORT_SYMBOL(set_h225_addr_hook); +EXPORT_SYMBOL(set_sig_addr_hook); +EXPORT_SYMBOL(set_ras_addr_hook); +EXPORT_SYMBOL(nat_rtp_rtcp_hook); +EXPORT_SYMBOL(nat_t120_hook); +EXPORT_SYMBOL(nat_h245_hook); +EXPORT_SYMBOL(nat_q931_hook); + +MODULE_AUTHOR("Jing Min Zhao "); +MODULE_DESCRIPTION("H.323 connection tracking helper"); +MODULE_LICENSE("GPL"); diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c new file mode 100644 index 000000000000..afa525129b51 --- /dev/null +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c @@ -0,0 +1,870 @@ +/**************************************************************************** + * ip_conntrack_helper_h323_asn1.c - BER and PER decoding library for H.323 + * conntrack/NAT module. + * + * Copyright (c) 2006 by Jing Min Zhao + * + * This source code is licensed under General Public License version 2. + * + * See ip_conntrack_helper_h323_asn1.h for details. + * + ****************************************************************************/ + +#ifdef __KERNEL__ +#include +#else +#include +#endif +#include "ip_conntrack_helper_h323_asn1.h" + +/* Trace Flag */ +#ifndef H323_TRACE +#define H323_TRACE 0 +#endif + +#if H323_TRACE +#define TAB_SIZE 4 +#define IFTHEN(cond, act) if(cond){act;} +#ifdef __KERNEL__ +#define PRINT printk +#else +#define PRINT printf +#endif +#define FNAME(name) name, +#else +#define IFTHEN(cond, act) +#define PRINT(fmt, args...) +#define FNAME(name) +#endif + +/* ASN.1 Types */ +#define NUL 0 +#define BOOL 1 +#define OID 2 +#define INT 3 +#define ENUM 4 +#define BITSTR 5 +#define NUMSTR 6 +#define NUMDGT 6 +#define TBCDSTR 6 +#define OCTSTR 7 +#define PRTSTR 7 +#define IA5STR 7 +#define GENSTR 7 +#define BMPSTR 8 +#define SEQ 9 +#define SET 9 +#define SEQOF 10 +#define SETOF 10 +#define CHOICE 11 + +/* Constraint Types */ +#define FIXD 0 +/* #define BITS 1-8 */ +#define BYTE 9 +#define WORD 10 +#define CONS 11 +#define SEMI 12 +#define UNCO 13 + +/* ASN.1 Type Attributes */ +#define SKIP 0 +#define STOP 1 +#define DECODE 2 +#define EXT 4 +#define OPEN 8 +#define OPT 16 + + +/* ASN.1 Field Structure */ +typedef struct field_t { +#if H323_TRACE + char *name; +#endif + unsigned char type; + unsigned char sz; + unsigned char lb; + unsigned char ub; + unsigned short attr; + unsigned short offset; + struct field_t *fields; +} field_t; + +/* Bit Stream */ +typedef struct { + unsigned char *buf; + unsigned char *beg; + unsigned char *end; + unsigned char *cur; + unsigned bit; +} bitstr_t; + +/* Tool Functions */ +#define INC_BIT(bs) if((++bs->bit)>7){bs->cur++;bs->bit=0;} +#define INC_BITS(bs,b) if((bs->bit+=b)>7){bs->cur+=bs->bit>>3;bs->bit&=7;} +#define BYTE_ALIGN(bs) if(bs->bit){bs->cur++;bs->bit=0;} +#define CHECK_BOUND(bs,n) if(bs->cur+(n)>bs->end)return(H323_ERROR_BOUND) +static unsigned get_len(bitstr_t * bs); +static unsigned get_bit(bitstr_t * bs); +static unsigned get_bits(bitstr_t * bs, unsigned b); +static unsigned get_bitmap(bitstr_t * bs, unsigned b); +static unsigned get_uint(bitstr_t * bs, int b); + +/* Decoder Functions */ +static int decode_nul(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_bool(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_oid(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_int(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_enum(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_seq(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level); +static int decode_choice(bitstr_t * bs, field_t * f, char *base, int level); + +/* Decoder Functions Vector */ +typedef int (*decoder_t) (bitstr_t *, field_t *, char *, int); +static decoder_t Decoders[] = { + decode_nul, + decode_bool, + decode_oid, + decode_int, + decode_enum, + decode_bitstr, + decode_numstr, + decode_octstr, + decode_bmpstr, + decode_seq, + decode_seqof, + decode_choice, +}; + +/**************************************************************************** + * H.323 Types + ****************************************************************************/ +#include "ip_conntrack_helper_h323_types.c" + +/**************************************************************************** + * Functions + ****************************************************************************/ +/* Assume bs is aligned && v < 16384 */ +unsigned get_len(bitstr_t * bs) +{ + unsigned v; + + v = *bs->cur++; + + if (v & 0x80) { + v &= 0x3f; + v <<= 8; + v += *bs->cur++; + } + + return v; +} + +/****************************************************************************/ +unsigned get_bit(bitstr_t * bs) +{ + unsigned b = (*bs->cur) & (0x80 >> bs->bit); + + INC_BIT(bs); + + return b; +} + +/****************************************************************************/ +/* Assume b <= 8 */ +unsigned get_bits(bitstr_t * bs, unsigned b) +{ + unsigned v, l; + + v = (*bs->cur) & (0xffU >> bs->bit); + l = b + bs->bit; + + if (l < 8) { + v >>= 8 - l; + bs->bit = l; + } else if (l == 8) { + bs->cur++; + bs->bit = 0; + } else { /* l > 8 */ + + v <<= 8; + v += *(++bs->cur); + v >>= 16 - l; + bs->bit = l - 8; + } + + return v; +} + +/****************************************************************************/ +/* Assume b <= 32 */ +unsigned get_bitmap(bitstr_t * bs, unsigned b) +{ + unsigned v, l, shift, bytes; + + if (!b) + return 0; + + l = bs->bit + b; + + if (l < 8) { + v = (unsigned) (*bs->cur) << (bs->bit + 24); + bs->bit = l; + } else if (l == 8) { + v = (unsigned) (*bs->cur++) << (bs->bit + 24); + bs->bit = 0; + } else { + for (bytes = l >> 3, shift = 24, v = 0; bytes; + bytes--, shift -= 8) + v |= (unsigned) (*bs->cur++) << shift; + + if (l < 32) { + v |= (unsigned) (*bs->cur) << shift; + v <<= bs->bit; + } else if (l > 32) { + v <<= bs->bit; + v |= (*bs->cur) >> (8 - bs->bit); + } + + bs->bit = l & 0x7; + } + + v &= 0xffffffff << (32 - b); + + return v; +} + +/**************************************************************************** + * Assume bs is aligned and sizeof(unsigned int) == 4 + ****************************************************************************/ +unsigned get_uint(bitstr_t * bs, int b) +{ + unsigned v = 0; + + switch (b) { + case 4: + v |= *bs->cur++; + v <<= 8; + case 3: + v |= *bs->cur++; + v <<= 8; + case 2: + v |= *bs->cur++; + v <<= 8; + case 1: + v |= *bs->cur++; + break; + } + return v; +} + +/****************************************************************************/ +int decode_nul(bitstr_t * bs, field_t * f, char *base, int level) +{ + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_bool(bitstr_t * bs, field_t * f, char *base, int level) +{ + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + INC_BIT(bs); + + CHECK_BOUND(bs, 0); + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_oid(bitstr_t * bs, field_t * f, char *base, int level) +{ + int len; + + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + BYTE_ALIGN(bs); + CHECK_BOUND(bs, 1); + len = *bs->cur++; + bs->cur += len; + + CHECK_BOUND(bs, 0); + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_int(bitstr_t * bs, field_t * f, char *base, int level) +{ + unsigned len; + + PRINT("%*.s%s", level * TAB_SIZE, " ", f->name); + + switch (f->sz) { + case BYTE: /* Range == 256 */ + BYTE_ALIGN(bs); + bs->cur++; + break; + case WORD: /* 257 <= Range <= 64K */ + BYTE_ALIGN(bs); + bs->cur += 2; + break; + case CONS: /* 64K < Range < 4G */ + len = get_bits(bs, 2) + 1; + BYTE_ALIGN(bs); + if (base && (f->attr & DECODE)) { /* timeToLive */ + unsigned v = get_uint(bs, len) + f->lb; + PRINT(" = %u", v); + *((unsigned *) (base + f->offset)) = v; + } + bs->cur += len; + break; + case UNCO: + BYTE_ALIGN(bs); + CHECK_BOUND(bs, 2); + len = get_len(bs); + bs->cur += len; + break; + default: /* 2 <= Range <= 255 */ + INC_BITS(bs, f->sz); + break; + } + + PRINT("\n"); + + CHECK_BOUND(bs, 0); + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_enum(bitstr_t * bs, field_t * f, char *base, int level) +{ + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + if ((f->attr & EXT) && get_bit(bs)) { + INC_BITS(bs, 7); + } else { + INC_BITS(bs, f->sz); + } + + CHECK_BOUND(bs, 0); + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level) +{ + unsigned len; + + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + BYTE_ALIGN(bs); + switch (f->sz) { + case FIXD: /* fixed length > 16 */ + len = f->lb; + break; + case WORD: /* 2-byte length */ + CHECK_BOUND(bs, 2); + len = (*bs->cur++) << 8; + len += (*bs->cur++) + f->lb; + break; + case SEMI: + CHECK_BOUND(bs, 2); + len = get_len(bs); + break; + default: + len = 0; + break; + } + + bs->cur += len >> 3; + bs->bit = len & 7; + + CHECK_BOUND(bs, 0); + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level) +{ + unsigned len; + + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + /* 2 <= Range <= 255 */ + len = get_bits(bs, f->sz) + f->lb; + + BYTE_ALIGN(bs); + INC_BITS(bs, (len << 2)); + + CHECK_BOUND(bs, 0); + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level) +{ + unsigned len; + + PRINT("%*.s%s", level * TAB_SIZE, " ", f->name); + + switch (f->sz) { + case FIXD: /* Range == 1 */ + if (f->lb > 2) { + BYTE_ALIGN(bs); + if (base && (f->attr & DECODE)) { + /* The IP Address */ + IFTHEN(f->lb == 4, + PRINT(" = %d.%d.%d.%d:%d", + bs->cur[0], bs->cur[1], + bs->cur[2], bs->cur[3], + bs->cur[4] * 256 + bs->cur[5])); + *((unsigned *) (base + f->offset)) = + bs->cur - bs->buf; + } + } + len = f->lb; + break; + case BYTE: /* Range == 256 */ + BYTE_ALIGN(bs); + CHECK_BOUND(bs, 1); + len = (*bs->cur++) + f->lb; + break; + case SEMI: + BYTE_ALIGN(bs); + CHECK_BOUND(bs, 2); + len = get_len(bs) + f->lb; + break; + default: /* 2 <= Range <= 255 */ + len = get_bits(bs, f->sz) + f->lb; + BYTE_ALIGN(bs); + break; + } + + bs->cur += len; + + PRINT("\n"); + + CHECK_BOUND(bs, 0); + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level) +{ + unsigned len; + + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + switch (f->sz) { + case BYTE: /* Range == 256 */ + BYTE_ALIGN(bs); + CHECK_BOUND(bs, 1); + len = (*bs->cur++) + f->lb; + break; + default: /* 2 <= Range <= 255 */ + len = get_bits(bs, f->sz) + f->lb; + BYTE_ALIGN(bs); + break; + } + + bs->cur += len << 1; + + CHECK_BOUND(bs, 0); + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_seq(bitstr_t * bs, field_t * f, char *base, int level) +{ + unsigned ext, bmp, i, opt, len = 0, bmp2, bmp2_len; + int err; + field_t *son; + unsigned char *beg = NULL; + + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + /* Decode? */ + base = (base && (f->attr & DECODE)) ? base + f->offset : NULL; + + /* Extensible? */ + ext = (f->attr & EXT) ? get_bit(bs) : 0; + + /* Get fields bitmap */ + bmp = get_bitmap(bs, f->sz); + if (base) + *(unsigned *) base = bmp; + + /* Decode the root components */ + for (i = opt = 0, son = f->fields; i < f->lb; i++, son++) { + if (son->attr & STOP) { + PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", + son->name); + return H323_ERROR_STOP; + } + + if (son->attr & OPT) { /* Optional component */ + if (!((0x80000000U >> (opt++)) & bmp)) /* Not exist */ + continue; + } + + /* Decode */ + if (son->attr & OPEN) { /* Open field */ + CHECK_BOUND(bs, 2); + len = get_len(bs); + CHECK_BOUND(bs, len); + if (!base) { + PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, + " ", son->name); + bs->cur += len; + continue; + } + beg = bs->cur; + + /* Decode */ + if ((err = (Decoders[son->type]) (bs, son, base, + level + 1)) > + H323_ERROR_STOP) + return err; + + bs->cur = beg + len; + bs->bit = 0; + } else if ((err = (Decoders[son->type]) (bs, son, base, + level + 1))) + return err; + } + + /* No extension? */ + if (!ext) + return H323_ERROR_NONE; + + /* Get the extension bitmap */ + bmp2_len = get_bits(bs, 7) + 1; + CHECK_BOUND(bs, (bmp2_len + 7) >> 3); + bmp2 = get_bitmap(bs, bmp2_len); + bmp |= bmp2 >> f->sz; + if (base) + *(unsigned *) base = bmp; + BYTE_ALIGN(bs); + + /* Decode the extension components */ + for (opt = 0; opt < bmp2_len; opt++, i++, son++) { + if (son->attr & STOP) { + PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", + son->name); + return H323_ERROR_STOP; + } + + if (!((0x80000000 >> opt) & bmp2)) /* Not present */ + continue; + + /* Check Range */ + if (i >= f->ub) { /* Newer Version? */ + CHECK_BOUND(bs, 2); + len = get_len(bs); + CHECK_BOUND(bs, len); + bs->cur += len; + continue; + } + + CHECK_BOUND(bs, 2); + len = get_len(bs); + CHECK_BOUND(bs, len); + if (!base || !(son->attr & DECODE)) { + PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", + son->name); + bs->cur += len; + continue; + } + beg = bs->cur; + + if ((err = (Decoders[son->type]) (bs, son, base, + level + 1)) > + H323_ERROR_STOP) + return err; + + bs->cur = beg + len; + bs->bit = 0; + } + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level) +{ + unsigned count, effective_count = 0, i, len = 0; + int err; + field_t *son; + unsigned char *beg = NULL; + + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + /* Decode? */ + base = (base && (f->attr & DECODE)) ? base + f->offset : NULL; + + /* Decode item count */ + switch (f->sz) { + case BYTE: + BYTE_ALIGN(bs); + CHECK_BOUND(bs, 1); + count = *bs->cur++; + break; + case WORD: + BYTE_ALIGN(bs); + CHECK_BOUND(bs, 2); + count = *bs->cur++; + count <<= 8; + count = *bs->cur++; + break; + case SEMI: + BYTE_ALIGN(bs); + CHECK_BOUND(bs, 2); + count = get_len(bs); + break; + default: + count = get_bits(bs, f->sz); + break; + } + count += f->lb; + + /* Write Count */ + if (base) { + effective_count = count > f->ub ? f->ub : count; + *(unsigned *) base = effective_count; + base += sizeof(unsigned); + } + + /* Decode nested field */ + son = f->fields; + if (base) + base -= son->offset; + for (i = 0; i < count; i++) { + if (son->attr & OPEN) { + BYTE_ALIGN(bs); + len = get_len(bs); + CHECK_BOUND(bs, len); + if (!base || !(son->attr & DECODE)) { + PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, + " ", son->name); + bs->cur += len; + continue; + } + beg = bs->cur; + + if ((err = (Decoders[son->type]) (bs, son, + i < + effective_count ? + base : NULL, + level + 1)) > + H323_ERROR_STOP) + return err; + + bs->cur = beg + len; + bs->bit = 0; + } else + if ((err = (Decoders[son->type]) (bs, son, + i < effective_count ? + base : NULL, + level + 1))) + return err; + + if (base) + base += son->offset; + } + + return H323_ERROR_NONE; +} + + +/****************************************************************************/ +int decode_choice(bitstr_t * bs, field_t * f, char *base, int level) +{ + unsigned type, ext, len = 0; + int err; + field_t *son; + unsigned char *beg = NULL; + + PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); + + /* Decode? */ + base = (base && (f->attr & DECODE)) ? base + f->offset : NULL; + + /* Decode the choice index number */ + if ((f->attr & EXT) && get_bit(bs)) { + ext = 1; + type = get_bits(bs, 7) + f->lb; + } else { + ext = 0; + type = get_bits(bs, f->sz); + } + + /* Check Range */ + if (type >= f->ub) { /* Newer version? */ + BYTE_ALIGN(bs); + len = get_len(bs); + CHECK_BOUND(bs, len); + bs->cur += len; + return H323_ERROR_NONE; + } + + /* Write Type */ + if (base) + *(unsigned *) base = type; + + /* Transfer to son level */ + son = &f->fields[type]; + if (son->attr & STOP) { + PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", son->name); + return H323_ERROR_STOP; + } + + if (ext || (son->attr & OPEN)) { + BYTE_ALIGN(bs); + len = get_len(bs); + CHECK_BOUND(bs, len); + if (!base || !(son->attr & DECODE)) { + PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", + son->name); + bs->cur += len; + return H323_ERROR_NONE; + } + beg = bs->cur; + + if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) > + H323_ERROR_STOP) + return err; + + bs->cur = beg + len; + bs->bit = 0; + } else if ((err = (Decoders[son->type]) (bs, son, base, level + 1))) + return err; + + return H323_ERROR_NONE; +} + +/****************************************************************************/ +int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras) +{ + static field_t ras_message = { + FNAME("RasMessage") CHOICE, 5, 24, 32, DECODE | EXT, + 0, _RasMessage + }; + bitstr_t bs; + + bs.buf = bs.beg = bs.cur = buf; + bs.end = buf + sz; + bs.bit = 0; + + return decode_choice(&bs, &ras_message, (char *) ras, 0); +} + +/****************************************************************************/ +static int DecodeH323_UserInformation(unsigned char *buf, unsigned char *beg, + size_t sz, H323_UserInformation * uuie) +{ + static field_t h323_userinformation = { + FNAME("H323-UserInformation") SEQ, 1, 2, 2, DECODE | EXT, + 0, _H323_UserInformation + }; + bitstr_t bs; + + bs.buf = buf; + bs.beg = bs.cur = beg; + bs.end = beg + sz; + bs.bit = 0; + + return decode_seq(&bs, &h323_userinformation, (char *) uuie, 0); +} + +/****************************************************************************/ +int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz, + MultimediaSystemControlMessage * + mscm) +{ + static field_t multimediasystemcontrolmessage = { + FNAME("MultimediaSystemControlMessage") CHOICE, 2, 4, 4, + DECODE | EXT, 0, _MultimediaSystemControlMessage + }; + bitstr_t bs; + + bs.buf = bs.beg = bs.cur = buf; + bs.end = buf + sz; + bs.bit = 0; + + return decode_choice(&bs, &multimediasystemcontrolmessage, + (char *) mscm, 0); +} + +/****************************************************************************/ +int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931) +{ + unsigned char *p = buf; + int len; + + if (!p || sz < 1) + return H323_ERROR_BOUND; + + /* Protocol Discriminator */ + if (*p != 0x08) { + PRINT("Unknown Protocol Discriminator\n"); + return H323_ERROR_RANGE; + } + p++; + sz--; + + /* CallReferenceValue */ + if (sz < 1) + return H323_ERROR_BOUND; + len = *p++; + sz--; + if (sz < len) + return H323_ERROR_BOUND; + p += len; + sz -= len; + + /* Message Type */ + if (sz < 1) + return H323_ERROR_BOUND; + q931->MessageType = *p++; + PRINT("MessageType = %02X\n", q931->MessageType); + if (*p & 0x80) { + p++; + sz--; + } + + /* Decode Information Elements */ + while (sz > 0) { + if (*p == 0x7e) { /* UserUserIE */ + if (sz < 3) + break; + p++; + len = *p++ << 8; + len |= *p++; + sz -= 3; + if (sz < len) + break; + p++; + len--; + return DecodeH323_UserInformation(buf, p, len, + &q931->UUIE); + } + p++; + sz--; + if (sz < 1) + break; + len = *p++; + if (sz < len) + break; + p += len; + sz -= len; + } + + PRINT("Q.931 UUIE not found\n"); + + return H323_ERROR_BOUND; +} diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h new file mode 100644 index 000000000000..0bd828081c0c --- /dev/null +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h @@ -0,0 +1,98 @@ +/**************************************************************************** + * ip_conntrack_helper_h323_asn1.h - BER and PER decoding library for H.323 + * conntrack/NAT module. + * + * Copyright (c) 2006 by Jing Min Zhao + * + * This source code is licensed under General Public License version 2. + * + * + * This library is based on H.225 version 4, H.235 version 2 and H.245 + * version 7. It is extremely optimized to decode only the absolutely + * necessary objects in a signal for Linux kernel NAT module use, so don't + * expect it to be a full ASN.1 library. + * + * Features: + * + * 1. Small. The total size of code plus data is less than 20 KB (IA32). + * 2. Fast. Decoding Netmeeting's Setup signal 1 million times on a PIII 866 + * takes only 3.9 seconds. + * 3. No memory allocation. It uses a static object. No need to initialize or + * cleanup. + * 4. Thread safe. + * 5. Support embedded architectures that has no misaligned memory access + * support. + * + * Limitations: + * + * 1. At most 30 faststart entries. Actually this is limited by ethernet's MTU. + * If a Setup signal contains more than 30 faststart, the packet size will + * very likely exceed the MTU size, then the TPKT will be fragmented. I + * don't know how to handle this in a Netfilter module. Anybody can help? + * Although I think 30 is enough for most of the cases. + * 2. IPv4 addresses only. + * + ****************************************************************************/ + +#ifndef _IP_CONNTRACK_HELPER_H323_ASN1_H_ +#define _IP_CONNTRACK_HELPER_H323_ASN1_H_ + +/***************************************************************************** + * H.323 Types + ****************************************************************************/ +#include "ip_conntrack_helper_h323_types.h" + +typedef struct { + enum { + Q931_NationalEscape = 0x00, + Q931_Alerting = 0x01, + Q931_CallProceeding = 0x02, + Q931_Connect = 0x07, + Q931_ConnectAck = 0x0F, + Q931_Progress = 0x03, + Q931_Setup = 0x05, + Q931_SetupAck = 0x0D, + Q931_Resume = 0x26, + Q931_ResumeAck = 0x2E, + Q931_ResumeReject = 0x22, + Q931_Suspend = 0x25, + Q931_SuspendAck = 0x2D, + Q931_SuspendReject = 0x21, + Q931_UserInformation = 0x20, + Q931_Disconnect = 0x45, + Q931_Release = 0x4D, + Q931_ReleaseComplete = 0x5A, + Q931_Restart = 0x46, + Q931_RestartAck = 0x4E, + Q931_Segment = 0x60, + Q931_CongestionCtrl = 0x79, + Q931_Information = 0x7B, + Q931_Notify = 0x6E, + Q931_Status = 0x7D, + Q931_StatusEnquiry = 0x75, + Q931_Facility = 0x62 + } MessageType; + H323_UserInformation UUIE; +} Q931; + +/***************************************************************************** + * Decode Functions Return Codes + ****************************************************************************/ + +#define H323_ERROR_NONE 0 /* Decoded successfully */ +#define H323_ERROR_STOP 1 /* Decoding stopped, not really an error */ +#define H323_ERROR_BOUND -1 +#define H323_ERROR_RANGE -2 + + +/***************************************************************************** + * Decode Functions + ****************************************************************************/ + +int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras); +int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931); +int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz, + MultimediaSystemControlMessage * + mscm); + +#endif diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c new file mode 100644 index 000000000000..022c47b9f6c9 --- /dev/null +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c @@ -0,0 +1,1926 @@ +/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006 + * + * Copyright (c) 2006 Jing Min Zhao + * + * This source code is licensed under General Public License version 2. + */ + +static field_t _TransportAddress_ipAddress[] = { /* SEQUENCE */ + {FNAME("ip") OCTSTR, FIXD, 4, 0, DECODE, + offsetof(TransportAddress_ipAddress, ip), NULL}, + {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _TransportAddress_ipSourceRoute_route[] = { /* SEQUENCE OF */ + {FNAME("item") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, +}; + +static field_t _TransportAddress_ipSourceRoute_routing[] = { /* CHOICE */ + {FNAME("strict") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("loose") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _TransportAddress_ipSourceRoute[] = { /* SEQUENCE */ + {FNAME("ip") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, + {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL}, + {FNAME("route") SEQOF, SEMI, 0, 0, SKIP, 0, + _TransportAddress_ipSourceRoute_route}, + {FNAME("routing") CHOICE, 1, 2, 2, SKIP | EXT, 0, + _TransportAddress_ipSourceRoute_routing}, +}; + +static field_t _TransportAddress_ipxAddress[] = { /* SEQUENCE */ + {FNAME("node") OCTSTR, FIXD, 6, 0, SKIP, 0, NULL}, + {FNAME("netnum") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, + {FNAME("port") OCTSTR, FIXD, 2, 0, SKIP, 0, NULL}, +}; + +static field_t _TransportAddress_ip6Address[] = { /* SEQUENCE */ + {FNAME("ip") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, + {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H221NonStandard[] = { /* SEQUENCE */ + {FNAME("t35CountryCode") INT, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("t35Extension") INT, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("manufacturerCode") INT, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _NonStandardIdentifier[] = { /* CHOICE */ + {FNAME("object") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("h221NonStandard") SEQ, 0, 3, 3, SKIP | EXT, 0, + _H221NonStandard}, +}; + +static field_t _NonStandardParameter[] = { /* SEQUENCE */ + {FNAME("nonStandardIdentifier") CHOICE, 1, 2, 2, SKIP | EXT, 0, + _NonStandardIdentifier}, + {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _TransportAddress[] = { /* CHOICE */ + {FNAME("ipAddress") SEQ, 0, 2, 2, DECODE, + offsetof(TransportAddress, ipAddress), _TransportAddress_ipAddress}, + {FNAME("ipSourceRoute") SEQ, 0, 4, 4, SKIP | EXT, 0, + _TransportAddress_ipSourceRoute}, + {FNAME("ipxAddress") SEQ, 0, 3, 3, SKIP, 0, + _TransportAddress_ipxAddress}, + {FNAME("ip6Address") SEQ, 0, 2, 2, SKIP | EXT, 0, + _TransportAddress_ip6Address}, + {FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, + {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL}, + {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, + _NonStandardParameter}, +}; + +static field_t _AliasAddress[] = { /* CHOICE */ + {FNAME("dialedDigits") NUMDGT, 7, 1, 0, SKIP, 0, NULL}, + {FNAME("h323-ID") BMPSTR, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("url-ID") IA5STR, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("transportID") CHOICE, 3, 7, 7, SKIP | EXT, 0, NULL}, + {FNAME("email-ID") IA5STR, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("partyNumber") CHOICE, 3, 5, 5, SKIP | EXT, 0, NULL}, + {FNAME("mobileUIM") CHOICE, 1, 2, 2, SKIP | EXT, 0, NULL}, +}; + +static field_t _Setup_UUIE_sourceAddress[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _VendorIdentifier[] = { /* SEQUENCE */ + {FNAME("vendor") SEQ, 0, 3, 3, SKIP | EXT, 0, _H221NonStandard}, + {FNAME("productId") OCTSTR, BYTE, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("versionId") OCTSTR, BYTE, 1, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _GatekeeperInfo[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, +}; + +static field_t _H310Caps[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H320Caps[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H321Caps[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H322Caps[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H323Caps[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H324Caps[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _VoiceCaps[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _T120OnlyCaps[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _SupportedProtocols[] = { /* CHOICE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP, 0, + _NonStandardParameter}, + {FNAME("h310") SEQ, 1, 1, 3, SKIP | EXT, 0, _H310Caps}, + {FNAME("h320") SEQ, 1, 1, 3, SKIP | EXT, 0, _H320Caps}, + {FNAME("h321") SEQ, 1, 1, 3, SKIP | EXT, 0, _H321Caps}, + {FNAME("h322") SEQ, 1, 1, 3, SKIP | EXT, 0, _H322Caps}, + {FNAME("h323") SEQ, 1, 1, 3, SKIP | EXT, 0, _H323Caps}, + {FNAME("h324") SEQ, 1, 1, 3, SKIP | EXT, 0, _H324Caps}, + {FNAME("voice") SEQ, 1, 1, 3, SKIP | EXT, 0, _VoiceCaps}, + {FNAME("t120-only") SEQ, 1, 1, 3, SKIP | EXT, 0, _T120OnlyCaps}, + {FNAME("nonStandardProtocol") SEQ, 2, 3, 3, SKIP | EXT, 0, NULL}, + {FNAME("t38FaxAnnexbOnly") SEQ, 2, 5, 5, SKIP | EXT, 0, NULL}, +}; + +static field_t _GatewayInfo_protocol[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 4, 9, 11, SKIP | EXT, 0, _SupportedProtocols}, +}; + +static field_t _GatewayInfo[] = { /* SEQUENCE */ + {FNAME("protocol") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _GatewayInfo_protocol}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, +}; + +static field_t _McuInfo[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("protocol") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _TerminalInfo[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, +}; + +static field_t _EndpointType[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("vendor") SEQ, 2, 3, 3, SKIP | EXT | OPT, 0, + _VendorIdentifier}, + {FNAME("gatekeeper") SEQ, 1, 1, 1, SKIP | EXT | OPT, 0, + _GatekeeperInfo}, + {FNAME("gateway") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, _GatewayInfo}, + {FNAME("mcu") SEQ, 1, 1, 2, SKIP | EXT | OPT, 0, _McuInfo}, + {FNAME("terminal") SEQ, 1, 1, 1, SKIP | EXT | OPT, 0, _TerminalInfo}, + {FNAME("mc") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("undefinedNode") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("set") BITSTR, FIXD, 32, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedTunnelledProtocols") SEQOF, SEMI, 0, 0, SKIP | OPT, + 0, NULL}, +}; + +static field_t _Setup_UUIE_destinationAddress[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _Setup_UUIE_destExtraCallInfo[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _Setup_UUIE_destExtraCRV[] = { /* SEQUENCE OF */ + {FNAME("item") INT, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _Setup_UUIE_conferenceGoal[] = { /* CHOICE */ + {FNAME("create") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("join") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("invite") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("capability-negotiation") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("callIndependentSupplementaryService") NUL, FIXD, 0, 0, SKIP, + 0, NULL}, +}; + +static field_t _Q954Details[] = { /* SEQUENCE */ + {FNAME("conferenceCalling") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("threePartyService") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _QseriesOptions[] = { /* SEQUENCE */ + {FNAME("q932Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("q951Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("q952Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("q953Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("q955Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("q956Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("q957Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("q954Info") SEQ, 0, 2, 2, SKIP | EXT, 0, _Q954Details}, +}; + +static field_t _CallType[] = { /* CHOICE */ + {FNAME("pointToPoint") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("oneToN") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("nToOne") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("nToN") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H245_NonStandardIdentifier_h221NonStandard[] = { /* SEQUENCE */ + {FNAME("t35CountryCode") INT, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("t35Extension") INT, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("manufacturerCode") INT, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H245_NonStandardIdentifier[] = { /* CHOICE */ + {FNAME("object") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("h221NonStandard") SEQ, 0, 3, 3, SKIP, 0, + _H245_NonStandardIdentifier_h221NonStandard}, +}; + +static field_t _H245_NonStandardParameter[] = { /* SEQUENCE */ + {FNAME("nonStandardIdentifier") CHOICE, 1, 2, 2, SKIP, 0, + _H245_NonStandardIdentifier}, + {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H261VideoCapability[] = { /* SEQUENCE */ + {FNAME("qcifMPI") INT, 2, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("cifMPI") INT, 2, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("temporalSpatialTradeOffCapability") BOOL, FIXD, 0, 0, SKIP, 0, + NULL}, + {FNAME("maxBitRate") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("stillImageTransmission") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H262VideoCapability[] = { /* SEQUENCE */ + {FNAME("profileAndLevel-SPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("profileAndLevel-MPatLL") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("profileAndLevel-MPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("profileAndLevel-MPatH-14") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("profileAndLevel-MPatHL") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("profileAndLevel-SNRatLL") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("profileAndLevel-SNRatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("profileAndLevel-SpatialatH-14") BOOL, FIXD, 0, 0, SKIP, 0, + NULL}, + {FNAME("profileAndLevel-HPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("profileAndLevel-HPatH-14") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("profileAndLevel-HPatHL") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("videoBitRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("vbvBufferSize") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("samplesPerLine") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("linesPerFrame") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("framesPerSecond") INT, 4, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("luminanceSampleRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H263VideoCapability[] = { /* SEQUENCE */ + {FNAME("sqcifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("qcifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("cifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("cif4MPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("cif16MPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("maxBitRate") INT, CONS, 1, 0, SKIP, 0, NULL}, + {FNAME("unrestrictedVector") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("arithmeticCoding") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("advancedPrediction") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("pbFrames") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("temporalSpatialTradeOffCapability") BOOL, FIXD, 0, 0, SKIP, 0, + NULL}, + {FNAME("hrd-B") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("bppMaxKb") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("slowSqcifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("slowQcifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("slowCifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("slowCif4MPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("slowCif16MPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("errorCompensation") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("enhancementLayerInfo") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("h263Options") SEQ, 5, 29, 31, SKIP | EXT | OPT, 0, NULL}, +}; + +static field_t _IS11172VideoCapability[] = { /* SEQUENCE */ + {FNAME("constrainedBitstream") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("videoBitRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("vbvBufferSize") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("samplesPerLine") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("linesPerFrame") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("pictureRate") INT, 4, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("luminanceSampleRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _VideoCapability[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, + _H245_NonStandardParameter}, + {FNAME("h261VideoCapability") SEQ, 2, 5, 6, SKIP | EXT, 0, + _H261VideoCapability}, + {FNAME("h262VideoCapability") SEQ, 6, 17, 18, SKIP | EXT, 0, + _H262VideoCapability}, + {FNAME("h263VideoCapability") SEQ, 7, 13, 21, SKIP | EXT, 0, + _H263VideoCapability}, + {FNAME("is11172VideoCapability") SEQ, 6, 7, 8, SKIP | EXT, 0, + _IS11172VideoCapability}, + {FNAME("genericVideoCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL}, +}; + +static field_t _AudioCapability_g7231[] = { /* SEQUENCE */ + {FNAME("maxAl-sduAudioFrames") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("silenceSuppression") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _IS11172AudioCapability[] = { /* SEQUENCE */ + {FNAME("audioLayer1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioLayer2") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioLayer3") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioSampling32k") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioSampling44k1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioSampling48k") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("singleChannel") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("twoChannels") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("bitRate") INT, WORD, 1, 0, SKIP, 0, NULL}, +}; + +static field_t _IS13818AudioCapability[] = { /* SEQUENCE */ + {FNAME("audioLayer1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioLayer2") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioLayer3") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioSampling16k") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioSampling22k05") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioSampling24k") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioSampling32k") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioSampling44k1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("audioSampling48k") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("singleChannel") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("twoChannels") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("threeChannels2-1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("threeChannels3-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("fourChannels2-0-2-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("fourChannels2-2") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("fourChannels3-1") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("fiveChannels3-0-2-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("fiveChannels3-2") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("lowFrequencyEnhancement") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("multilingual") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("bitRate") INT, WORD, 1, 0, SKIP, 0, NULL}, +}; + +static field_t _AudioCapability[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, + _H245_NonStandardParameter}, + {FNAME("g711Alaw64k") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g711Alaw56k") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g711Ulaw64k") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g711Ulaw56k") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g722-64k") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g722-56k") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g722-48k") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g7231") SEQ, 0, 2, 2, SKIP, 0, _AudioCapability_g7231}, + {FNAME("g728") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g729") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g729AnnexA") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("is11172AudioCapability") SEQ, 0, 9, 9, SKIP | EXT, 0, + _IS11172AudioCapability}, + {FNAME("is13818AudioCapability") SEQ, 0, 21, 21, SKIP | EXT, 0, + _IS13818AudioCapability}, + {FNAME("g729wAnnexB") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g729AnnexAwAnnexB") INT, BYTE, 1, 0, SKIP, 0, NULL}, + {FNAME("g7231AnnexCCapability") SEQ, 1, 3, 3, SKIP | EXT, 0, NULL}, + {FNAME("gsmFullRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL}, + {FNAME("gsmHalfRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL}, + {FNAME("gsmEnhancedFullRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL}, + {FNAME("genericAudioCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL}, + {FNAME("g729Extensions") SEQ, 1, 8, 8, SKIP | EXT, 0, NULL}, +}; + +static field_t _DataProtocolCapability[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, + _H245_NonStandardParameter}, + {FNAME("v14buffered") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("v42lapm") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("hdlcFrameTunnelling") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("h310SeparateVCStack") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("h310SingleVCStack") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("transparent") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("segmentationAndReassembly") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("hdlcFrameTunnelingwSAR") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("v120") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("separateLANStack") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("v76wCompression") CHOICE, 2, 3, 3, SKIP | EXT, 0, NULL}, + {FNAME("tcp") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("udp") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _T84Profile_t84Restricted[] = { /* SEQUENCE */ + {FNAME("qcif") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("cif") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("ccir601Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("ccir601Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("hdtvSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("hdtvProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("g3FacsMH200x100") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("g3FacsMH200x200") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("g4FacsMMR200x100") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("g4FacsMMR200x200") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("jbig200x200Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("jbig200x200Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("jbig300x300Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("jbig300x300Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("digPhotoLow") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("digPhotoMedSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("digPhotoMedProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("digPhotoHighSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("digPhotoHighProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _T84Profile[] = { /* CHOICE */ + {FNAME("t84Unrestricted") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("t84Restricted") SEQ, 0, 19, 19, SKIP | EXT, 0, + _T84Profile_t84Restricted}, +}; + +static field_t _DataApplicationCapability_application_t84[] = { /* SEQUENCE */ + {FNAME("t84Protocol") CHOICE, 3, 7, 14, SKIP | EXT, 0, + _DataProtocolCapability}, + {FNAME("t84Profile") CHOICE, 1, 2, 2, SKIP, 0, _T84Profile}, +}; + +static field_t _DataApplicationCapability_application_nlpid[] = { /* SEQUENCE */ + {FNAME("nlpidProtocol") CHOICE, 3, 7, 14, SKIP | EXT, 0, + _DataProtocolCapability}, + {FNAME("nlpidData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _DataApplicationCapability_application[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, + _H245_NonStandardParameter}, + {FNAME("t120") CHOICE, 3, 7, 14, DECODE | EXT, + offsetof(DataApplicationCapability_application, t120), + _DataProtocolCapability}, + {FNAME("dsm-cc") CHOICE, 3, 7, 14, SKIP | EXT, 0, + _DataProtocolCapability}, + {FNAME("userData") CHOICE, 3, 7, 14, SKIP | EXT, 0, + _DataProtocolCapability}, + {FNAME("t84") SEQ, 0, 2, 2, SKIP, 0, + _DataApplicationCapability_application_t84}, + {FNAME("t434") CHOICE, 3, 7, 14, SKIP | EXT, 0, + _DataProtocolCapability}, + {FNAME("h224") CHOICE, 3, 7, 14, SKIP | EXT, 0, + _DataProtocolCapability}, + {FNAME("nlpid") SEQ, 0, 2, 2, SKIP, 0, + _DataApplicationCapability_application_nlpid}, + {FNAME("dsvdControl") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("h222DataPartitioning") CHOICE, 3, 7, 14, SKIP | EXT, 0, + _DataProtocolCapability}, + {FNAME("t30fax") CHOICE, 3, 7, 14, SKIP | EXT, 0, NULL}, + {FNAME("t140") CHOICE, 3, 7, 14, SKIP | EXT, 0, NULL}, + {FNAME("t38fax") SEQ, 0, 2, 2, SKIP, 0, NULL}, + {FNAME("genericDataCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL}, +}; + +static field_t _DataApplicationCapability[] = { /* SEQUENCE */ + {FNAME("application") CHOICE, 4, 10, 14, DECODE | EXT, + offsetof(DataApplicationCapability, application), + _DataApplicationCapability_application}, + {FNAME("maxBitRate") INT, CONS, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _EncryptionMode[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, + _H245_NonStandardParameter}, + {FNAME("h233Encryption") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _DataType[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, + _H245_NonStandardParameter}, + {FNAME("nullData") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("videoData") CHOICE, 3, 5, 6, SKIP | EXT, 0, _VideoCapability}, + {FNAME("audioData") CHOICE, 4, 14, 22, SKIP | EXT, 0, + _AudioCapability}, + {FNAME("data") SEQ, 0, 2, 2, DECODE | EXT, offsetof(DataType, data), + _DataApplicationCapability}, + {FNAME("encryptionData") CHOICE, 1, 2, 2, SKIP | EXT, 0, + _EncryptionMode}, + {FNAME("h235Control") SEQ, 0, 2, 2, SKIP, 0, NULL}, + {FNAME("h235Media") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL}, + {FNAME("multiplexedStream") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL}, +}; + +static field_t _H222LogicalChannelParameters[] = { /* SEQUENCE */ + {FNAME("resourceID") INT, WORD, 0, 0, SKIP, 0, NULL}, + {FNAME("subChannelID") INT, WORD, 0, 0, SKIP, 0, NULL}, + {FNAME("pcr-pid") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("programDescriptors") OCTSTR, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("streamDescriptors") OCTSTR, SEMI, 0, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _H223LogicalChannelParameters_adaptationLayerType_al3[] = { /* SEQUENCE */ + {FNAME("controlFieldOctets") INT, 2, 0, 0, SKIP, 0, NULL}, + {FNAME("sendBufferSize") INT, CONS, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H223LogicalChannelParameters_adaptationLayerType[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, + _H245_NonStandardParameter}, + {FNAME("al1Framed") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("al1NotFramed") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("al2WithoutSequenceNumbers") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("al2WithSequenceNumbers") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("al3") SEQ, 0, 2, 2, SKIP, 0, + _H223LogicalChannelParameters_adaptationLayerType_al3}, + {FNAME("al1M") SEQ, 0, 7, 8, SKIP | EXT, 0, NULL}, + {FNAME("al2M") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL}, + {FNAME("al3M") SEQ, 0, 5, 6, SKIP | EXT, 0, NULL}, +}; + +static field_t _H223LogicalChannelParameters[] = { /* SEQUENCE */ + {FNAME("adaptationLayerType") CHOICE, 3, 6, 9, SKIP | EXT, 0, + _H223LogicalChannelParameters_adaptationLayerType}, + {FNAME("segmentableFlag") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CRCLength[] = { /* CHOICE */ + {FNAME("crc8bit") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("crc16bit") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("crc32bit") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _V76HDLCParameters[] = { /* SEQUENCE */ + {FNAME("crcLength") CHOICE, 2, 3, 3, SKIP | EXT, 0, _CRCLength}, + {FNAME("n401") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("loopbackTestProcedure") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _V76LogicalChannelParameters_suspendResume[] = { /* CHOICE */ + {FNAME("noSuspendResume") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("suspendResumewAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("suspendResumewoAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _V76LogicalChannelParameters_mode_eRM_recovery[] = { /* CHOICE */ + {FNAME("rej") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("sREJ") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("mSREJ") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _V76LogicalChannelParameters_mode_eRM[] = { /* SEQUENCE */ + {FNAME("windowSize") INT, 7, 1, 0, SKIP, 0, NULL}, + {FNAME("recovery") CHOICE, 2, 3, 3, SKIP | EXT, 0, + _V76LogicalChannelParameters_mode_eRM_recovery}, +}; + +static field_t _V76LogicalChannelParameters_mode[] = { /* CHOICE */ + {FNAME("eRM") SEQ, 0, 2, 2, SKIP | EXT, 0, + _V76LogicalChannelParameters_mode_eRM}, + {FNAME("uNERM") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _V75Parameters[] = { /* SEQUENCE */ + {FNAME("audioHeaderPresent") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _V76LogicalChannelParameters[] = { /* SEQUENCE */ + {FNAME("hdlcParameters") SEQ, 0, 3, 3, SKIP | EXT, 0, + _V76HDLCParameters}, + {FNAME("suspendResume") CHOICE, 2, 3, 3, SKIP | EXT, 0, + _V76LogicalChannelParameters_suspendResume}, + {FNAME("uIH") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("mode") CHOICE, 1, 2, 2, SKIP | EXT, 0, + _V76LogicalChannelParameters_mode}, + {FNAME("v75Parameters") SEQ, 0, 1, 1, SKIP | EXT, 0, _V75Parameters}, +}; + +static field_t _H2250LogicalChannelParameters_nonStandard[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter}, +}; + +static field_t _UnicastAddress_iPAddress[] = { /* SEQUENCE */ + {FNAME("network") OCTSTR, FIXD, 4, 0, DECODE, + offsetof(UnicastAddress_iPAddress, network), NULL}, + {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _UnicastAddress_iPXAddress[] = { /* SEQUENCE */ + {FNAME("node") OCTSTR, FIXD, 6, 0, SKIP, 0, NULL}, + {FNAME("netnum") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, + {FNAME("tsapIdentifier") OCTSTR, FIXD, 2, 0, SKIP, 0, NULL}, +}; + +static field_t _UnicastAddress_iP6Address[] = { /* SEQUENCE */ + {FNAME("network") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, + {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _UnicastAddress_iPSourceRouteAddress_routing[] = { /* CHOICE */ + {FNAME("strict") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("loose") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _UnicastAddress_iPSourceRouteAddress_route[] = { /* SEQUENCE OF */ + {FNAME("item") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, +}; + +static field_t _UnicastAddress_iPSourceRouteAddress[] = { /* SEQUENCE */ + {FNAME("routing") CHOICE, 1, 2, 2, SKIP, 0, + _UnicastAddress_iPSourceRouteAddress_routing}, + {FNAME("network") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, + {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL}, + {FNAME("route") SEQOF, SEMI, 0, 0, SKIP, 0, + _UnicastAddress_iPSourceRouteAddress_route}, +}; + +static field_t _UnicastAddress[] = { /* CHOICE */ + {FNAME("iPAddress") SEQ, 0, 2, 2, DECODE | EXT, + offsetof(UnicastAddress, iPAddress), _UnicastAddress_iPAddress}, + {FNAME("iPXAddress") SEQ, 0, 3, 3, SKIP | EXT, 0, + _UnicastAddress_iPXAddress}, + {FNAME("iP6Address") SEQ, 0, 2, 2, SKIP | EXT, 0, + _UnicastAddress_iP6Address}, + {FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, + {FNAME("iPSourceRouteAddress") SEQ, 0, 4, 4, SKIP | EXT, 0, + _UnicastAddress_iPSourceRouteAddress}, + {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL}, + {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, NULL}, +}; + +static field_t _MulticastAddress_iPAddress[] = { /* SEQUENCE */ + {FNAME("network") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL}, + {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _MulticastAddress_iP6Address[] = { /* SEQUENCE */ + {FNAME("network") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, + {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _MulticastAddress[] = { /* CHOICE */ + {FNAME("iPAddress") SEQ, 0, 2, 2, SKIP | EXT, 0, + _MulticastAddress_iPAddress}, + {FNAME("iP6Address") SEQ, 0, 2, 2, SKIP | EXT, 0, + _MulticastAddress_iP6Address}, + {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL}, + {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, NULL}, +}; + +static field_t _H245_TransportAddress[] = { /* CHOICE */ + {FNAME("unicastAddress") CHOICE, 3, 5, 7, DECODE | EXT, + offsetof(H245_TransportAddress, unicastAddress), _UnicastAddress}, + {FNAME("multicastAddress") CHOICE, 1, 2, 4, SKIP | EXT, 0, + _MulticastAddress}, +}; + +static field_t _H2250LogicalChannelParameters[] = { /* SEQUENCE */ + {FNAME("nonStandard") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _H2250LogicalChannelParameters_nonStandard}, + {FNAME("sessionID") INT, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("associatedSessionID") INT, 8, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("mediaChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT, + offsetof(H2250LogicalChannelParameters, mediaChannel), + _H245_TransportAddress}, + {FNAME("mediaGuaranteedDelivery") BOOL, FIXD, 0, 0, SKIP | OPT, 0, + NULL}, + {FNAME("mediaControlChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT, + offsetof(H2250LogicalChannelParameters, mediaControlChannel), + _H245_TransportAddress}, + {FNAME("mediaControlGuaranteedDelivery") BOOL, FIXD, 0, 0, STOP | OPT, + 0, NULL}, + {FNAME("silenceSuppression") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("destination") SEQ, 0, 2, 2, STOP | EXT | OPT, 0, NULL}, + {FNAME("dynamicRTPPayloadType") INT, 5, 96, 0, STOP | OPT, 0, NULL}, + {FNAME("mediaPacketization") CHOICE, 0, 1, 2, STOP | EXT | OPT, 0, + NULL}, + {FNAME("transportCapability") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, + NULL}, + {FNAME("redundancyEncoding") SEQ, 1, 2, 2, STOP | EXT | OPT, 0, NULL}, + {FNAME("source") SEQ, 0, 2, 2, SKIP | EXT | OPT, 0, NULL}, +}; + +static field_t _OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */ + {FNAME("h222LogicalChannelParameters") SEQ, 3, 5, 5, SKIP | EXT, 0, + _H222LogicalChannelParameters}, + {FNAME("h223LogicalChannelParameters") SEQ, 0, 2, 2, SKIP | EXT, 0, + _H223LogicalChannelParameters}, + {FNAME("v76LogicalChannelParameters") SEQ, 0, 5, 5, SKIP | EXT, 0, + _V76LogicalChannelParameters}, + {FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT, + offsetof + (OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters, + h2250LogicalChannelParameters), _H2250LogicalChannelParameters}, + {FNAME("none") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _OpenLogicalChannel_forwardLogicalChannelParameters[] = { /* SEQUENCE */ + {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("dataType") CHOICE, 3, 6, 9, DECODE | EXT, + offsetof(OpenLogicalChannel_forwardLogicalChannelParameters, + dataType), _DataType}, + {FNAME("multiplexParameters") CHOICE, 2, 3, 5, DECODE | EXT, + offsetof(OpenLogicalChannel_forwardLogicalChannelParameters, + multiplexParameters), + _OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters}, + {FNAME("forwardLogicalChannelDependency") INT, WORD, 1, 0, SKIP | OPT, + 0, NULL}, + {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */ + {FNAME("h223LogicalChannelParameters") SEQ, 0, 2, 2, SKIP | EXT, 0, + _H223LogicalChannelParameters}, + {FNAME("v76LogicalChannelParameters") SEQ, 0, 5, 5, SKIP | EXT, 0, + _V76LogicalChannelParameters}, + {FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT, + offsetof + (OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters, + h2250LogicalChannelParameters), _H2250LogicalChannelParameters}, +}; + +static field_t _OpenLogicalChannel_reverseLogicalChannelParameters[] = { /* SEQUENCE */ + {FNAME("dataType") CHOICE, 3, 6, 9, SKIP | EXT, 0, _DataType}, + {FNAME("multiplexParameters") CHOICE, 1, 2, 3, DECODE | EXT | OPT, + offsetof(OpenLogicalChannel_reverseLogicalChannelParameters, + multiplexParameters), + _OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters}, + {FNAME("reverseLogicalChannelDependency") INT, WORD, 1, 0, SKIP | OPT, + 0, NULL}, + {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _NetworkAccessParameters_distribution[] = { /* CHOICE */ + {FNAME("unicast") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("multicast") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _Q2931Address_address[] = { /* CHOICE */ + {FNAME("internationalNumber") NUMSTR, 4, 1, 0, SKIP, 0, NULL}, + {FNAME("nsapAddress") OCTSTR, 5, 1, 0, SKIP, 0, NULL}, +}; + +static field_t _Q2931Address[] = { /* SEQUENCE */ + {FNAME("address") CHOICE, 1, 2, 2, SKIP | EXT, 0, + _Q2931Address_address}, + {FNAME("subaddress") OCTSTR, 5, 1, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _NetworkAccessParameters_networkAddress[] = { /* CHOICE */ + {FNAME("q2931Address") SEQ, 1, 2, 2, SKIP | EXT, 0, _Q2931Address}, + {FNAME("e164Address") NUMDGT, 7, 1, 0, SKIP, 0, NULL}, + {FNAME("localAreaAddress") CHOICE, 1, 2, 2, DECODE | EXT, + offsetof(NetworkAccessParameters_networkAddress, localAreaAddress), + _H245_TransportAddress}, +}; + +static field_t _NetworkAccessParameters[] = { /* SEQUENCE */ + {FNAME("distribution") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0, + _NetworkAccessParameters_distribution}, + {FNAME("networkAddress") CHOICE, 2, 3, 3, DECODE | EXT, + offsetof(NetworkAccessParameters, networkAddress), + _NetworkAccessParameters_networkAddress}, + {FNAME("associateConference") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("externalReference") OCTSTR, 8, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("t120SetupProcedure") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0, + NULL}, +}; + +static field_t _OpenLogicalChannel[] = { /* SEQUENCE */ + {FNAME("forwardLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("forwardLogicalChannelParameters") SEQ, 1, 3, 5, DECODE | EXT, + offsetof(OpenLogicalChannel, forwardLogicalChannelParameters), + _OpenLogicalChannel_forwardLogicalChannelParameters}, + {FNAME("reverseLogicalChannelParameters") SEQ, 1, 2, 4, + DECODE | EXT | OPT, offsetof(OpenLogicalChannel, + reverseLogicalChannelParameters), + _OpenLogicalChannel_reverseLogicalChannelParameters}, + {FNAME("separateStack") SEQ, 2, 4, 5, DECODE | EXT | OPT, + offsetof(OpenLogicalChannel, separateStack), + _NetworkAccessParameters}, + {FNAME("encryptionSync") SEQ, 2, 4, 4, STOP | EXT | OPT, 0, NULL}, +}; + +static field_t _Setup_UUIE_fastStart[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, + sizeof(OpenLogicalChannel), _OpenLogicalChannel} + , +}; + +static field_t _Setup_UUIE[] = { /* SEQUENCE */ + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(Setup_UUIE, h245Address), _TransportAddress}, + {FNAME("sourceAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _Setup_UUIE_sourceAddress}, + {FNAME("sourceInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType}, + {FNAME("destinationAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _Setup_UUIE_destinationAddress}, + {FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(Setup_UUIE, destCallSignalAddress), _TransportAddress}, + {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _Setup_UUIE_destExtraCallInfo}, + {FNAME("destExtraCRV") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _Setup_UUIE_destExtraCRV}, + {FNAME("activeMC") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, + {FNAME("conferenceGoal") CHOICE, 2, 3, 5, SKIP | EXT, 0, + _Setup_UUIE_conferenceGoal}, + {FNAME("callServices") SEQ, 0, 8, 8, SKIP | EXT | OPT, 0, + _QseriesOptions}, + {FNAME("callType") CHOICE, 2, 4, 4, SKIP | EXT, 0, _CallType}, + {FNAME("sourceCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(Setup_UUIE, sourceCallSignalAddress), _TransportAddress}, + {FNAME("remoteExtensionAddress") CHOICE, 1, 2, 7, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, + {FNAME("h245SecurityCapability") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, + offsetof(Setup_UUIE, fastStart), _Setup_UUIE_fastStart}, + {FNAME("mediaWaitForConnect") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("canOverlapSend") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, + {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("connectionParameters") SEQ, 0, 3, 3, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("language") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("symmetricOperationRequired") NUL, FIXD, 0, 0, SKIP | OPT, 0, + NULL}, + {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL}, + {FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL}, + {FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("neededFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("desiredFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("supportedFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("parallelH245Control") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("additionalSourceAddresses") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + NULL}, +}; + +static field_t _CallProceeding_UUIE_fastStart[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, + sizeof(OpenLogicalChannel), _OpenLogicalChannel} + , +}; + +static field_t _CallProceeding_UUIE[] = { /* SEQUENCE */ + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, + _EndpointType}, + {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(CallProceeding_UUIE, h245Address), _TransportAddress}, + {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, + {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, + offsetof(CallProceeding_UUIE, fastStart), + _CallProceeding_UUIE_fastStart}, + {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL}, +}; + +static field_t _Connect_UUIE_fastStart[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, + sizeof(OpenLogicalChannel), _OpenLogicalChannel} + , +}; + +static field_t _Connect_UUIE[] = { /* SEQUENCE */ + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(Connect_UUIE, h245Address), _TransportAddress}, + {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, + _EndpointType}, + {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, + {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, + {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, + offsetof(Connect_UUIE, fastStart), _Connect_UUIE_fastStart}, + {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("language") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("connectedAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL}, +}; + +static field_t _Alerting_UUIE_fastStart[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, + sizeof(OpenLogicalChannel), _OpenLogicalChannel} + , +}; + +static field_t _Alerting_UUIE[] = { /* SEQUENCE */ + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, + _EndpointType}, + {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(Alerting_UUIE, h245Address), _TransportAddress}, + {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, + {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, + offsetof(Alerting_UUIE, fastStart), _Alerting_UUIE_fastStart}, + {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("alertingAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL}, +}; + +static field_t _Information_UUIE_fastStart[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, + sizeof(OpenLogicalChannel), _OpenLogicalChannel} + , +}; + +static field_t _Information_UUIE[] = { /* SEQUENCE */ + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, + offsetof(Information_UUIE, fastStart), _Information_UUIE_fastStart}, + {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL}, +}; + +static field_t _ReleaseCompleteReason[] = { /* CHOICE */ + {FNAME("noBandwidth") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("gatekeeperResources") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("unreachableDestination") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("destinationRejection") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("invalidRevision") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("noPermission") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("unreachableGatekeeper") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("gatewayResources") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("badFormatAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("adaptiveBusy") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("inConf") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("undefinedReason") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("facilityCallDeflection") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("securityDenied") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("calledPartyNotRegistered") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("callerNotRegistered") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("newConnectionNeeded") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("nonStandardReason") SEQ, 0, 2, 2, SKIP, 0, NULL}, + {FNAME("replaceWithConferenceInvite") OCTSTR, FIXD, 16, 0, SKIP, 0, + NULL}, + {FNAME("genericDataReason") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("neededFeatureNotSupported") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("tunnelledSignallingRejected") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _ReleaseComplete_UUIE[] = { /* SEQUENCE */ + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("reason") CHOICE, 4, 12, 22, SKIP | EXT | OPT, 0, + _ReleaseCompleteReason}, + {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("busyAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL}, + {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL}, +}; + +static field_t _Facility_UUIE_alternativeAliasAddress[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _FacilityReason[] = { /* CHOICE */ + {FNAME("routeCallToGatekeeper") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("callForwarded") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("routeCallToMC") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("undefinedReason") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("conferenceListChoice") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("startH245") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("noH245") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("newTokens") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("featureSetUpdate") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("forwardedElements") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("transportedInformation") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _Facility_UUIE_fastStart[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, + sizeof(OpenLogicalChannel), _OpenLogicalChannel} + , +}; + +static field_t _Facility_UUIE[] = { /* SEQUENCE */ + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("alternativeAddress") CHOICE, 3, 7, 7, SKIP | EXT | OPT, 0, + _TransportAddress}, + {FNAME("alternativeAliasAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _Facility_UUIE_alternativeAliasAddress}, + {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL}, + {FNAME("reason") CHOICE, 2, 4, 11, DECODE | EXT, + offsetof(Facility_UUIE, reason), _FacilityReason}, + {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL}, + {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("remoteExtensionAddress") CHOICE, 1, 2, 7, SKIP | EXT | OPT, 0, + NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("conferences") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(Facility_UUIE, h245Address), _TransportAddress}, + {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, + offsetof(Facility_UUIE, fastStart), _Facility_UUIE_fastStart}, + {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL}, + {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT | OPT, 0, NULL}, + {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0, + NULL}, +}; + +static field_t _CallIdentifier[] = { /* SEQUENCE */ + {FNAME("guid") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, +}; + +static field_t _SecurityServiceMode[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _NonStandardParameter}, + {FNAME("none") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("default") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _SecurityCapabilities[] = { /* SEQUENCE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("encryption") CHOICE, 2, 3, 3, SKIP | EXT, 0, + _SecurityServiceMode}, + {FNAME("authenticaton") CHOICE, 2, 3, 3, SKIP | EXT, 0, + _SecurityServiceMode}, + {FNAME("integrity") CHOICE, 2, 3, 3, SKIP | EXT, 0, + _SecurityServiceMode}, +}; + +static field_t _H245Security[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _NonStandardParameter}, + {FNAME("noSecurity") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("tls") SEQ, 1, 4, 4, SKIP | EXT, 0, _SecurityCapabilities}, + {FNAME("ipsec") SEQ, 1, 4, 4, SKIP | EXT, 0, _SecurityCapabilities}, +}; + +static field_t _DHset[] = { /* SEQUENCE */ + {FNAME("halfkey") BITSTR, WORD, 0, 0, SKIP, 0, NULL}, + {FNAME("modSize") BITSTR, WORD, 0, 0, SKIP, 0, NULL}, + {FNAME("generator") BITSTR, WORD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _TypedCertificate[] = { /* SEQUENCE */ + {FNAME("type") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("certificate") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _H235_NonStandardParameter[] = { /* SEQUENCE */ + {FNAME("nonStandardIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _ClearToken[] = { /* SEQUENCE */ + {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("timeStamp") INT, CONS, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("password") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("dhkey") SEQ, 0, 3, 3, SKIP | EXT | OPT, 0, _DHset}, + {FNAME("challenge") OCTSTR, 7, 8, 0, SKIP | OPT, 0, NULL}, + {FNAME("random") INT, UNCO, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("certificate") SEQ, 0, 2, 2, SKIP | EXT | OPT, 0, + _TypedCertificate}, + {FNAME("generalID") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP | OPT, 0, + _H235_NonStandardParameter}, + {FNAME("eckasdhkey") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0, NULL}, + {FNAME("sendersID") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _Progress_UUIE_tokens[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 8, 9, 11, SKIP | EXT, 0, _ClearToken}, +}; + +static field_t _Params[] = { /* SEQUENCE */ + {FNAME("ranInt") INT, UNCO, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("iv8") OCTSTR, FIXD, 8, 0, SKIP | OPT, 0, NULL}, + {FNAME("iv16") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _CryptoH323Token_cryptoEPPwdHash_token[] = { /* SEQUENCE */ + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoH323Token_cryptoEPPwdHash[] = { /* SEQUENCE */ + {FNAME("alias") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, + {FNAME("timeStamp") INT, CONS, 1, 0, SKIP, 0, NULL}, + {FNAME("token") SEQ, 0, 3, 3, SKIP, 0, + _CryptoH323Token_cryptoEPPwdHash_token}, +}; + +static field_t _CryptoH323Token_cryptoGKPwdHash_token[] = { /* SEQUENCE */ + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoH323Token_cryptoGKPwdHash[] = { /* SEQUENCE */ + {FNAME("gatekeeperId") BMPSTR, 7, 1, 0, SKIP, 0, NULL}, + {FNAME("timeStamp") INT, CONS, 1, 0, SKIP, 0, NULL}, + {FNAME("token") SEQ, 0, 3, 3, SKIP, 0, + _CryptoH323Token_cryptoGKPwdHash_token}, +}; + +static field_t _CryptoH323Token_cryptoEPPwdEncr[] = { /* SEQUENCE */ + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoH323Token_cryptoGKPwdEncr[] = { /* SEQUENCE */ + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoH323Token_cryptoEPCert[] = { /* SEQUENCE */ + {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL}, + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoH323Token_cryptoGKCert[] = { /* SEQUENCE */ + {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL}, + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoH323Token_cryptoFastStart[] = { /* SEQUENCE */ + {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL}, + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoToken_cryptoEncryptedToken_token[] = { /* SEQUENCE */ + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoToken_cryptoEncryptedToken[] = { /* SEQUENCE */ + {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("token") SEQ, 0, 3, 3, SKIP, 0, + _CryptoToken_cryptoEncryptedToken_token}, +}; + +static field_t _CryptoToken_cryptoSignedToken_token[] = { /* SEQUENCE */ + {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL}, + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoToken_cryptoSignedToken[] = { /* SEQUENCE */ + {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("token") SEQ, 0, 4, 4, SKIP, 0, + _CryptoToken_cryptoSignedToken_token}, +}; + +static field_t _CryptoToken_cryptoHashedToken_token[] = { /* SEQUENCE */ + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoToken_cryptoHashedToken[] = { /* SEQUENCE */ + {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("hashedVals") SEQ, 8, 9, 11, SKIP | EXT, 0, _ClearToken}, + {FNAME("token") SEQ, 0, 3, 3, SKIP, 0, + _CryptoToken_cryptoHashedToken_token}, +}; + +static field_t _CryptoToken_cryptoPwdEncr[] = { /* SEQUENCE */ + {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params}, + {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _CryptoToken[] = { /* CHOICE */ + {FNAME("cryptoEncryptedToken") SEQ, 0, 2, 2, SKIP, 0, + _CryptoToken_cryptoEncryptedToken}, + {FNAME("cryptoSignedToken") SEQ, 0, 2, 2, SKIP, 0, + _CryptoToken_cryptoSignedToken}, + {FNAME("cryptoHashedToken") SEQ, 0, 3, 3, SKIP, 0, + _CryptoToken_cryptoHashedToken}, + {FNAME("cryptoPwdEncr") SEQ, 0, 3, 3, SKIP, 0, + _CryptoToken_cryptoPwdEncr}, +}; + +static field_t _CryptoH323Token[] = { /* CHOICE */ + {FNAME("cryptoEPPwdHash") SEQ, 0, 3, 3, SKIP, 0, + _CryptoH323Token_cryptoEPPwdHash}, + {FNAME("cryptoGKPwdHash") SEQ, 0, 3, 3, SKIP, 0, + _CryptoH323Token_cryptoGKPwdHash}, + {FNAME("cryptoEPPwdEncr") SEQ, 0, 3, 3, SKIP, 0, + _CryptoH323Token_cryptoEPPwdEncr}, + {FNAME("cryptoGKPwdEncr") SEQ, 0, 3, 3, SKIP, 0, + _CryptoH323Token_cryptoGKPwdEncr}, + {FNAME("cryptoEPCert") SEQ, 0, 4, 4, SKIP, 0, + _CryptoH323Token_cryptoEPCert}, + {FNAME("cryptoGKCert") SEQ, 0, 4, 4, SKIP, 0, + _CryptoH323Token_cryptoGKCert}, + {FNAME("cryptoFastStart") SEQ, 0, 4, 4, SKIP, 0, + _CryptoH323Token_cryptoFastStart}, + {FNAME("nestedcryptoToken") CHOICE, 2, 4, 4, SKIP | EXT, 0, + _CryptoToken}, +}; + +static field_t _Progress_UUIE_cryptoTokens[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 3, 8, 8, SKIP | EXT, 0, _CryptoH323Token}, +}; + +static field_t _Progress_UUIE_fastStart[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT, + sizeof(OpenLogicalChannel), _OpenLogicalChannel} + , +}; + +static field_t _Progress_UUIE[] = { /* SEQUENCE */ + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, + _EndpointType}, + {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(Progress_UUIE, h245Address), _TransportAddress}, + {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, + _CallIdentifier}, + {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0, + _H245Security}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _Progress_UUIE_tokens}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _Progress_UUIE_cryptoTokens}, + {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT, + offsetof(Progress_UUIE, fastStart), _Progress_UUIE_fastStart}, + {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _H323_UU_PDU_h323_message_body[] = { /* CHOICE */ + {FNAME("setup") SEQ, 7, 13, 39, DECODE | EXT, + offsetof(H323_UU_PDU_h323_message_body, setup), _Setup_UUIE}, + {FNAME("callProceeding") SEQ, 1, 3, 12, DECODE | EXT, + offsetof(H323_UU_PDU_h323_message_body, callProceeding), + _CallProceeding_UUIE}, + {FNAME("connect") SEQ, 1, 4, 19, DECODE | EXT, + offsetof(H323_UU_PDU_h323_message_body, connect), _Connect_UUIE}, + {FNAME("alerting") SEQ, 1, 3, 17, DECODE | EXT, + offsetof(H323_UU_PDU_h323_message_body, alerting), _Alerting_UUIE}, + {FNAME("information") SEQ, 0, 1, 7, DECODE | EXT, + offsetof(H323_UU_PDU_h323_message_body, information), + _Information_UUIE}, + {FNAME("releaseComplete") SEQ, 1, 2, 11, SKIP | EXT, 0, + _ReleaseComplete_UUIE}, + {FNAME("facility") SEQ, 3, 5, 21, DECODE | EXT, + offsetof(H323_UU_PDU_h323_message_body, facility), _Facility_UUIE}, + {FNAME("progress") SEQ, 5, 8, 11, DECODE | EXT, + offsetof(H323_UU_PDU_h323_message_body, progress), _Progress_UUIE}, + {FNAME("empty") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("status") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL}, + {FNAME("statusInquiry") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL}, + {FNAME("setupAcknowledge") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL}, + {FNAME("notify") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL}, +}; + +static field_t _RequestMessage[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("masterSlaveDetermination") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, + {FNAME("terminalCapabilitySet") SEQ, 3, 5, 5, STOP | EXT, 0, NULL}, + {FNAME("openLogicalChannel") SEQ, 1, 3, 5, DECODE | EXT, + offsetof(RequestMessage, openLogicalChannel), _OpenLogicalChannel}, + {FNAME("closeLogicalChannel") SEQ, 0, 2, 3, STOP | EXT, 0, NULL}, + {FNAME("requestChannelClose") SEQ, 0, 1, 3, STOP | EXT, 0, NULL}, + {FNAME("multiplexEntrySend") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, + {FNAME("requestMultiplexEntry") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("requestMode") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, + {FNAME("roundTripDelayRequest") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("maintenanceLoopRequest") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("communicationModeRequest") SEQ, 0, 0, 0, STOP | EXT, 0, NULL}, + {FNAME("conferenceRequest") CHOICE, 3, 8, 16, STOP | EXT, 0, NULL}, + {FNAME("multilinkRequest") CHOICE, 3, 5, 5, STOP | EXT, 0, NULL}, + {FNAME("logicalChannelRateRequest") SEQ, 0, 3, 3, STOP | EXT, 0, + NULL}, +}; + +static field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */ + {FNAME("h222LogicalChannelParameters") SEQ, 3, 5, 5, SKIP | EXT, 0, + _H222LogicalChannelParameters}, + {FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT, + offsetof + (OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters, + h2250LogicalChannelParameters), _H2250LogicalChannelParameters}, +}; + +static field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters[] = { /* SEQUENCE */ + {FNAME("reverseLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("multiplexParameters") CHOICE, 0, 1, 2, DECODE | EXT | OPT, + offsetof(OpenLogicalChannelAck_reverseLogicalChannelParameters, + multiplexParameters), + _OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters}, + {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _H2250LogicalChannelAckParameters_nonStandard[] = { /* SEQUENCE OF */ + {FNAME("item") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter}, +}; + +static field_t _H2250LogicalChannelAckParameters[] = { /* SEQUENCE */ + {FNAME("nonStandard") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _H2250LogicalChannelAckParameters_nonStandard}, + {FNAME("sessionID") INT, 8, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("mediaChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT, + offsetof(H2250LogicalChannelAckParameters, mediaChannel), + _H245_TransportAddress}, + {FNAME("mediaControlChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT, + offsetof(H2250LogicalChannelAckParameters, mediaControlChannel), + _H245_TransportAddress}, + {FNAME("dynamicRTPPayloadType") INT, 5, 96, 0, SKIP | OPT, 0, NULL}, + {FNAME("flowControlToZero") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL}, +}; + +static field_t _OpenLogicalChannelAck_forwardMultiplexAckParameters[] = { /* CHOICE */ + {FNAME("h2250LogicalChannelAckParameters") SEQ, 5, 5, 7, DECODE | EXT, + offsetof(OpenLogicalChannelAck_forwardMultiplexAckParameters, + h2250LogicalChannelAckParameters), + _H2250LogicalChannelAckParameters}, +}; + +static field_t _OpenLogicalChannelAck[] = { /* SEQUENCE */ + {FNAME("forwardLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("reverseLogicalChannelParameters") SEQ, 2, 3, 4, + DECODE | EXT | OPT, offsetof(OpenLogicalChannelAck, + reverseLogicalChannelParameters), + _OpenLogicalChannelAck_reverseLogicalChannelParameters}, + {FNAME("separateStack") SEQ, 2, 4, 5, SKIP | EXT | OPT, 0, NULL}, + {FNAME("forwardMultiplexAckParameters") CHOICE, 0, 1, 1, + DECODE | EXT | OPT, offsetof(OpenLogicalChannelAck, + forwardMultiplexAckParameters), + _OpenLogicalChannelAck_forwardMultiplexAckParameters}, + {FNAME("encryptionSync") SEQ, 2, 4, 4, STOP | EXT | OPT, 0, NULL}, +}; + +static field_t _ResponseMessage[] = { /* CHOICE */ + {FNAME("nonStandard") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("masterSlaveDeterminationAck") SEQ, 0, 1, 1, STOP | EXT, 0, + NULL}, + {FNAME("masterSlaveDeterminationReject") SEQ, 0, 1, 1, STOP | EXT, 0, + NULL}, + {FNAME("terminalCapabilitySetAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("terminalCapabilitySetReject") SEQ, 0, 2, 2, STOP | EXT, 0, + NULL}, + {FNAME("openLogicalChannelAck") SEQ, 1, 2, 5, DECODE | EXT, + offsetof(ResponseMessage, openLogicalChannelAck), + _OpenLogicalChannelAck}, + {FNAME("openLogicalChannelReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, + {FNAME("closeLogicalChannelAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("requestChannelCloseAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("requestChannelCloseReject") SEQ, 0, 2, 2, STOP | EXT, 0, + NULL}, + {FNAME("multiplexEntrySendAck") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, + {FNAME("multiplexEntrySendReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, + {FNAME("requestMultiplexEntryAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("requestMultiplexEntryReject") SEQ, 0, 2, 2, STOP | EXT, 0, + NULL}, + {FNAME("requestModeAck") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, + {FNAME("requestModeReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, + {FNAME("roundTripDelayResponse") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("maintenanceLoopAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("maintenanceLoopReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL}, + {FNAME("communicationModeResponse") CHOICE, 0, 1, 1, STOP | EXT, 0, + NULL}, + {FNAME("conferenceResponse") CHOICE, 3, 8, 16, STOP | EXT, 0, NULL}, + {FNAME("multilinkResponse") CHOICE, 3, 5, 5, STOP | EXT, 0, NULL}, + {FNAME("logicalChannelRateAcknowledge") SEQ, 0, 3, 3, STOP | EXT, 0, + NULL}, + {FNAME("logicalChannelRateReject") SEQ, 1, 4, 4, STOP | EXT, 0, NULL}, +}; + +static field_t _MultimediaSystemControlMessage[] = { /* CHOICE */ + {FNAME("request") CHOICE, 4, 11, 15, DECODE | EXT, + offsetof(MultimediaSystemControlMessage, request), _RequestMessage}, + {FNAME("response") CHOICE, 5, 19, 24, DECODE | EXT, + offsetof(MultimediaSystemControlMessage, response), + _ResponseMessage}, + {FNAME("command") CHOICE, 3, 7, 12, STOP | EXT, 0, NULL}, + {FNAME("indication") CHOICE, 4, 14, 23, STOP | EXT, 0, NULL}, +}; + +static field_t _H323_UU_PDU_h245Control[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 2, 4, 4, DECODE | OPEN | EXT, + sizeof(MultimediaSystemControlMessage), + _MultimediaSystemControlMessage} + , +}; + +static field_t _H323_UU_PDU[] = { /* SEQUENCE */ + {FNAME("h323-message-body") CHOICE, 3, 7, 13, DECODE | EXT, + offsetof(H323_UU_PDU, h323_message_body), + _H323_UU_PDU_h323_message_body}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("h4501SupplementaryService") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + NULL}, + {FNAME("h245Tunneling") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("h245Control") SEQOF, SEMI, 0, 4, DECODE | OPT, + offsetof(H323_UU_PDU, h245Control), _H323_UU_PDU_h245Control}, + {FNAME("nonStandardControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("callLinkage") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL}, + {FNAME("tunnelledSignallingMessage") SEQ, 2, 4, 4, STOP | EXT | OPT, + 0, NULL}, + {FNAME("provisionalRespToH245Tunneling") NUL, FIXD, 0, 0, STOP | OPT, + 0, NULL}, + {FNAME("stimulusControl") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _H323_UserInformation[] = { /* SEQUENCE */ + {FNAME("h323-uu-pdu") SEQ, 1, 2, 11, DECODE | EXT, + offsetof(H323_UserInformation, h323_uu_pdu), _H323_UU_PDU}, + {FNAME("user-data") SEQ, 0, 2, 2, STOP | EXT | OPT, 0, NULL}, +}; + +static field_t _GatekeeperRequest[] = { /* SEQUENCE */ + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT, + offsetof(GatekeeperRequest, rasAddress), _TransportAddress}, + {FNAME("endpointType") SEQ, 6, 8, 10, STOP | EXT, 0, NULL}, + {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, + {FNAME("callServices") SEQ, 0, 8, 8, STOP | EXT | OPT, 0, NULL}, + {FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("authenticationCapability") SEQOF, SEMI, 0, 0, STOP | OPT, 0, + NULL}, + {FNAME("algorithmOIDs") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrity") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("supportsAltGK") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _GatekeeperConfirm[] = { /* SEQUENCE */ + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT, + offsetof(GatekeeperConfirm, rasAddress), _TransportAddress}, + {FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("authenticationMode") CHOICE, 3, 7, 8, STOP | EXT | OPT, 0, + NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("algorithmOID") OID, BYTE, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrity") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _RegistrationRequest_callSignalAddress[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, + sizeof(TransportAddress), _TransportAddress} + , +}; + +static field_t _RegistrationRequest_rasAddress[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, + sizeof(TransportAddress), _TransportAddress} + , +}; + +static field_t _RegistrationRequest_terminalAlias[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _RegistrationRequest[] = { /* SEQUENCE */ + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("discoveryComplete") BOOL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE, + offsetof(RegistrationRequest, callSignalAddress), + _RegistrationRequest_callSignalAddress}, + {FNAME("rasAddress") SEQOF, SEMI, 0, 10, DECODE, + offsetof(RegistrationRequest, rasAddress), + _RegistrationRequest_rasAddress}, + {FNAME("terminalType") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType}, + {FNAME("terminalAlias") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _RegistrationRequest_terminalAlias}, + {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("endpointVendor") SEQ, 2, 3, 3, SKIP | EXT, 0, + _VendorIdentifier}, + {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("timeToLive") INT, CONS, 1, 0, DECODE | OPT, + offsetof(RegistrationRequest, timeToLive), NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("keepAlive") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, + {FNAME("willSupplyUUIEs") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("maintainConnection") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT, + 0, NULL}, + {FNAME("additiveRegistration") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("terminalAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0, + NULL}, + {FNAME("supportsAltGK") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("usageReportingCapability") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, + NULL}, + {FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("supportedH248Packages") SEQOF, SEMI, 0, 0, STOP | OPT, 0, + NULL}, + {FNAME("callCreditCapability") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, + NULL}, + {FNAME("capacityReportingCapability") SEQ, 0, 1, 1, STOP | EXT | OPT, + 0, NULL}, + {FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _RegistrationConfirm_callSignalAddress[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, + sizeof(TransportAddress), _TransportAddress} + , +}; + +static field_t _RegistrationConfirm_terminalAlias[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _RegistrationConfirm[] = { /* SEQUENCE */ + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE, + offsetof(RegistrationConfirm, callSignalAddress), + _RegistrationConfirm_callSignalAddress}, + {FNAME("terminalAlias") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _RegistrationConfirm_terminalAlias}, + {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL}, + {FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL}, + {FNAME("timeToLive") INT, CONS, 1, 0, DECODE | OPT, + offsetof(RegistrationConfirm, timeToLive), NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("willRespondToIRR") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("preGrantedARQ") SEQ, 0, 4, 8, STOP | EXT | OPT, 0, NULL}, + {FNAME("maintainConnection") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("supportsAdditiveRegistration") NUL, FIXD, 0, 0, STOP | OPT, 0, + NULL}, + {FNAME("terminalAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0, + NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("usageSpec") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("featureServerAlias") CHOICE, 1, 2, 7, STOP | EXT | OPT, 0, + NULL}, + {FNAME("capacityReportingSpec") SEQ, 0, 1, 1, STOP | EXT | OPT, 0, + NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _UnregistrationRequest_callSignalAddress[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, + sizeof(TransportAddress), _TransportAddress} + , +}; + +static field_t _UnregistrationRequest[] = { /* SEQUENCE */ + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE, + offsetof(UnregistrationRequest, callSignalAddress), + _UnregistrationRequest_callSignalAddress}, + {FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, + {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("reason") CHOICE, 2, 4, 5, STOP | EXT | OPT, 0, NULL}, + {FNAME("endpointAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0, + NULL}, + {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _CallModel[] = { /* CHOICE */ + {FNAME("direct") NUL, FIXD, 0, 0, SKIP, 0, NULL}, + {FNAME("gatekeeperRouted") NUL, FIXD, 0, 0, SKIP, 0, NULL}, +}; + +static field_t _AdmissionRequest_destinationInfo[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _AdmissionRequest_destExtraCallInfo[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _AdmissionRequest_srcInfo[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _AdmissionRequest[] = { /* SEQUENCE */ + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("callType") CHOICE, 2, 4, 4, SKIP | EXT, 0, _CallType}, + {FNAME("callModel") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0, _CallModel}, + {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL}, + {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _AdmissionRequest_destinationInfo}, + {FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(AdmissionRequest, destCallSignalAddress), + _TransportAddress}, + {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, + _AdmissionRequest_destExtraCallInfo}, + {FNAME("srcInfo") SEQOF, SEMI, 0, 0, SKIP, 0, + _AdmissionRequest_srcInfo}, + {FNAME("srcCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT, + offsetof(AdmissionRequest, srcCallSignalAddress), _TransportAddress}, + {FNAME("bandWidth") INT, CONS, 0, 0, STOP, 0, NULL}, + {FNAME("callReferenceValue") INT, WORD, 0, 0, STOP, 0, NULL}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("callServices") SEQ, 0, 8, 8, STOP | EXT | OPT, 0, NULL}, + {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, STOP, 0, NULL}, + {FNAME("activeMC") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("answerCall") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("canMapAlias") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("callIdentifier") SEQ, 0, 1, 1, STOP | EXT, 0, NULL}, + {FNAME("srcAlternatives") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("destAlternatives") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("transportQOS") CHOICE, 2, 3, 3, STOP | EXT | OPT, 0, NULL}, + {FNAME("willSupplyUUIEs") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("callLinkage") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL}, + {FNAME("gatewayDataRate") SEQ, 2, 3, 3, STOP | EXT | OPT, 0, NULL}, + {FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL}, + {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL}, + {FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("desiredTunnelledProtocol") SEQ, 1, 2, 2, STOP | EXT | OPT, 0, + NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _AdmissionConfirm[] = { /* SEQUENCE */ + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("bandWidth") INT, CONS, 0, 0, SKIP, 0, NULL}, + {FNAME("callModel") CHOICE, 1, 2, 2, SKIP | EXT, 0, _CallModel}, + {FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT, + offsetof(AdmissionConfirm, destCallSignalAddress), + _TransportAddress}, + {FNAME("irrFrequency") INT, WORD, 1, 0, STOP | OPT, 0, NULL}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("destinationType") SEQ, 6, 8, 10, STOP | EXT | OPT, 0, NULL}, + {FNAME("remoteExtensionAddress") SEQOF, SEMI, 0, 0, STOP | OPT, 0, + NULL}, + {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("transportQOS") CHOICE, 2, 3, 3, STOP | EXT | OPT, 0, NULL}, + {FNAME("willRespondToIRR") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("uuiesRequested") SEQ, 0, 9, 13, STOP | EXT, 0, NULL}, + {FNAME("language") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT, + 0, NULL}, + {FNAME("useSpecifiedTransport") CHOICE, 1, 2, 2, STOP | EXT | OPT, 0, + NULL}, + {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL}, + {FNAME("usageSpec") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("supportedProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _LocationRequest_destinationInfo[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress}, +}; + +static field_t _LocationRequest[] = { /* SEQUENCE */ + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL}, + {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, SKIP, 0, + _LocationRequest_destinationInfo}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("replyAddress") CHOICE, 3, 7, 7, DECODE | EXT, + offsetof(LocationRequest, replyAddress), _TransportAddress}, + {FNAME("sourceInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("canMapAlias") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("desiredTunnelledProtocol") SEQ, 1, 2, 2, STOP | EXT | OPT, 0, + NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("hopCount") INT, 8, 1, 0, STOP | OPT, 0, NULL}, + {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL}, +}; + +static field_t _LocationConfirm[] = { /* SEQUENCE */ + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("callSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT, + offsetof(LocationConfirm, callSignalAddress), _TransportAddress}, + {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT, + offsetof(LocationConfirm, rasAddress), _TransportAddress}, + {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("destinationType") SEQ, 6, 8, 10, STOP | EXT | OPT, 0, NULL}, + {FNAME("remoteExtensionAddress") SEQOF, SEMI, 0, 0, STOP | OPT, 0, + NULL}, + {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT, + 0, NULL}, + {FNAME("supportedProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL}, + {FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _InfoRequestResponse_callSignalAddress[] = { /* SEQUENCE OF */ + {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT, + sizeof(TransportAddress), _TransportAddress} + , +}; + +static field_t _InfoRequestResponse[] = { /* SEQUENCE */ + {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0, + _NonStandardParameter}, + {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL}, + {FNAME("endpointType") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType}, + {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL}, + {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT, + offsetof(InfoRequestResponse, rasAddress), _TransportAddress}, + {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE, + offsetof(InfoRequestResponse, callSignalAddress), + _InfoRequestResponse_callSignalAddress}, + {FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("perCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, + {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL}, + {FNAME("needResponse") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL}, + {FNAME("irrStatus") CHOICE, 2, 4, 4, STOP | EXT | OPT, 0, NULL}, + {FNAME("unsolicited") BOOL, FIXD, 0, 0, STOP, 0, NULL}, + {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL}, +}; + +static field_t _RasMessage[] = { /* CHOICE */ + {FNAME("gatekeeperRequest") SEQ, 4, 8, 18, DECODE | EXT, + offsetof(RasMessage, gatekeeperRequest), _GatekeeperRequest}, + {FNAME("gatekeeperConfirm") SEQ, 2, 5, 14, DECODE | EXT, + offsetof(RasMessage, gatekeeperConfirm), _GatekeeperConfirm}, + {FNAME("gatekeeperReject") SEQ, 2, 5, 11, STOP | EXT, 0, NULL}, + {FNAME("registrationRequest") SEQ, 3, 10, 31, DECODE | EXT, + offsetof(RasMessage, registrationRequest), _RegistrationRequest}, + {FNAME("registrationConfirm") SEQ, 3, 7, 24, DECODE | EXT, + offsetof(RasMessage, registrationConfirm), _RegistrationConfirm}, + {FNAME("registrationReject") SEQ, 2, 5, 11, STOP | EXT, 0, NULL}, + {FNAME("unregistrationRequest") SEQ, 3, 5, 15, DECODE | EXT, + offsetof(RasMessage, unregistrationRequest), _UnregistrationRequest}, + {FNAME("unregistrationConfirm") SEQ, 1, 2, 6, STOP | EXT, 0, NULL}, + {FNAME("unregistrationReject") SEQ, 1, 3, 8, STOP | EXT, 0, NULL}, + {FNAME("admissionRequest") SEQ, 7, 16, 34, DECODE | EXT, + offsetof(RasMessage, admissionRequest), _AdmissionRequest}, + {FNAME("admissionConfirm") SEQ, 2, 6, 27, DECODE | EXT, + offsetof(RasMessage, admissionConfirm), _AdmissionConfirm}, + {FNAME("admissionReject") SEQ, 1, 3, 11, STOP | EXT, 0, NULL}, + {FNAME("bandwidthRequest") SEQ, 2, 7, 18, STOP | EXT, 0, NULL}, + {FNAME("bandwidthConfirm") SEQ, 1, 3, 8, STOP | EXT, 0, NULL}, + {FNAME("bandwidthReject") SEQ, 1, 4, 9, STOP | EXT, 0, NULL}, + {FNAME("disengageRequest") SEQ, 1, 6, 19, STOP | EXT, 0, NULL}, + {FNAME("disengageConfirm") SEQ, 1, 2, 9, STOP | EXT, 0, NULL}, + {FNAME("disengageReject") SEQ, 1, 3, 8, STOP | EXT, 0, NULL}, + {FNAME("locationRequest") SEQ, 2, 5, 17, DECODE | EXT, + offsetof(RasMessage, locationRequest), _LocationRequest}, + {FNAME("locationConfirm") SEQ, 1, 4, 19, DECODE | EXT, + offsetof(RasMessage, locationConfirm), _LocationConfirm}, + {FNAME("locationReject") SEQ, 1, 3, 10, STOP | EXT, 0, NULL}, + {FNAME("infoRequest") SEQ, 2, 4, 15, STOP | EXT, 0, NULL}, + {FNAME("infoRequestResponse") SEQ, 3, 8, 16, DECODE | EXT, + offsetof(RasMessage, infoRequestResponse), _InfoRequestResponse}, + {FNAME("nonStandardMessage") SEQ, 0, 2, 7, STOP | EXT, 0, NULL}, + {FNAME("unknownMessageResponse") SEQ, 0, 1, 5, STOP | EXT, 0, NULL}, + {FNAME("requestInProgress") SEQ, 4, 6, 6, STOP | EXT, 0, NULL}, + {FNAME("resourcesAvailableIndicate") SEQ, 4, 9, 11, STOP | EXT, 0, + NULL}, + {FNAME("resourcesAvailableConfirm") SEQ, 4, 6, 7, STOP | EXT, 0, + NULL}, + {FNAME("infoRequestAck") SEQ, 4, 5, 5, STOP | EXT, 0, NULL}, + {FNAME("infoRequestNak") SEQ, 5, 7, 7, STOP | EXT, 0, NULL}, + {FNAME("serviceControlIndication") SEQ, 8, 10, 10, STOP | EXT, 0, + NULL}, + {FNAME("serviceControlResponse") SEQ, 7, 8, 8, STOP | EXT, 0, NULL}, +}; diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h new file mode 100644 index 000000000000..cc98f7aa5abe --- /dev/null +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h @@ -0,0 +1,938 @@ +/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006 + * + * Copyright (c) 2006 Jing Min Zhao + * + * This source code is licensed under General Public License version 2. + */ + +typedef struct TransportAddress_ipAddress { /* SEQUENCE */ + int options; /* No use */ + unsigned ip; +} TransportAddress_ipAddress; + +typedef struct TransportAddress { /* CHOICE */ + enum { + eTransportAddress_ipAddress, + eTransportAddress_ipSourceRoute, + eTransportAddress_ipxAddress, + eTransportAddress_ip6Address, + eTransportAddress_netBios, + eTransportAddress_nsap, + eTransportAddress_nonStandardAddress, + } choice; + union { + TransportAddress_ipAddress ipAddress; + }; +} TransportAddress; + +typedef struct DataProtocolCapability { /* CHOICE */ + enum { + eDataProtocolCapability_nonStandard, + eDataProtocolCapability_v14buffered, + eDataProtocolCapability_v42lapm, + eDataProtocolCapability_hdlcFrameTunnelling, + eDataProtocolCapability_h310SeparateVCStack, + eDataProtocolCapability_h310SingleVCStack, + eDataProtocolCapability_transparent, + eDataProtocolCapability_segmentationAndReassembly, + eDataProtocolCapability_hdlcFrameTunnelingwSAR, + eDataProtocolCapability_v120, + eDataProtocolCapability_separateLANStack, + eDataProtocolCapability_v76wCompression, + eDataProtocolCapability_tcp, + eDataProtocolCapability_udp, + } choice; +} DataProtocolCapability; + +typedef struct DataApplicationCapability_application { /* CHOICE */ + enum { + eDataApplicationCapability_application_nonStandard, + eDataApplicationCapability_application_t120, + eDataApplicationCapability_application_dsm_cc, + eDataApplicationCapability_application_userData, + eDataApplicationCapability_application_t84, + eDataApplicationCapability_application_t434, + eDataApplicationCapability_application_h224, + eDataApplicationCapability_application_nlpid, + eDataApplicationCapability_application_dsvdControl, + eDataApplicationCapability_application_h222DataPartitioning, + eDataApplicationCapability_application_t30fax, + eDataApplicationCapability_application_t140, + eDataApplicationCapability_application_t38fax, + eDataApplicationCapability_application_genericDataCapability, + } choice; + union { + DataProtocolCapability t120; + }; +} DataApplicationCapability_application; + +typedef struct DataApplicationCapability { /* SEQUENCE */ + int options; /* No use */ + DataApplicationCapability_application application; +} DataApplicationCapability; + +typedef struct DataType { /* CHOICE */ + enum { + eDataType_nonStandard, + eDataType_nullData, + eDataType_videoData, + eDataType_audioData, + eDataType_data, + eDataType_encryptionData, + eDataType_h235Control, + eDataType_h235Media, + eDataType_multiplexedStream, + } choice; + union { + DataApplicationCapability data; + }; +} DataType; + +typedef struct UnicastAddress_iPAddress { /* SEQUENCE */ + int options; /* No use */ + unsigned network; +} UnicastAddress_iPAddress; + +typedef struct UnicastAddress { /* CHOICE */ + enum { + eUnicastAddress_iPAddress, + eUnicastAddress_iPXAddress, + eUnicastAddress_iP6Address, + eUnicastAddress_netBios, + eUnicastAddress_iPSourceRouteAddress, + eUnicastAddress_nsap, + eUnicastAddress_nonStandardAddress, + } choice; + union { + UnicastAddress_iPAddress iPAddress; + }; +} UnicastAddress; + +typedef struct H245_TransportAddress { /* CHOICE */ + enum { + eH245_TransportAddress_unicastAddress, + eH245_TransportAddress_multicastAddress, + } choice; + union { + UnicastAddress unicastAddress; + }; +} H245_TransportAddress; + +typedef struct H2250LogicalChannelParameters { /* SEQUENCE */ + enum { + eH2250LogicalChannelParameters_nonStandard = (1 << 31), + eH2250LogicalChannelParameters_associatedSessionID = + (1 << 30), + eH2250LogicalChannelParameters_mediaChannel = (1 << 29), + eH2250LogicalChannelParameters_mediaGuaranteedDelivery = + (1 << 28), + eH2250LogicalChannelParameters_mediaControlChannel = + (1 << 27), + eH2250LogicalChannelParameters_mediaControlGuaranteedDelivery + = (1 << 26), + eH2250LogicalChannelParameters_silenceSuppression = (1 << 25), + eH2250LogicalChannelParameters_destination = (1 << 24), + eH2250LogicalChannelParameters_dynamicRTPPayloadType = + (1 << 23), + eH2250LogicalChannelParameters_mediaPacketization = (1 << 22), + eH2250LogicalChannelParameters_transportCapability = + (1 << 21), + eH2250LogicalChannelParameters_redundancyEncoding = (1 << 20), + eH2250LogicalChannelParameters_source = (1 << 19), + } options; + H245_TransportAddress mediaChannel; + H245_TransportAddress mediaControlChannel; +} H2250LogicalChannelParameters; + +typedef struct OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters { /* CHOICE */ + enum { + eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters, + eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters, + eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters, + eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters, + eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_none, + } choice; + union { + H2250LogicalChannelParameters h2250LogicalChannelParameters; + }; +} OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters; + +typedef struct OpenLogicalChannel_forwardLogicalChannelParameters { /* SEQUENCE */ + enum { + eOpenLogicalChannel_forwardLogicalChannelParameters_portNumber + = (1 << 31), + eOpenLogicalChannel_forwardLogicalChannelParameters_forwardLogicalChannelDependency + = (1 << 30), + eOpenLogicalChannel_forwardLogicalChannelParameters_replacementFor + = (1 << 29), + } options; + DataType dataType; + OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters + multiplexParameters; +} OpenLogicalChannel_forwardLogicalChannelParameters; + +typedef struct OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */ + enum { + eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters, + eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters, + eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters, + } choice; + union { + H2250LogicalChannelParameters h2250LogicalChannelParameters; + }; +} OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters; + +typedef struct OpenLogicalChannel_reverseLogicalChannelParameters { /* SEQUENCE */ + enum { + eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters + = (1 << 31), + eOpenLogicalChannel_reverseLogicalChannelParameters_reverseLogicalChannelDependency + = (1 << 30), + eOpenLogicalChannel_reverseLogicalChannelParameters_replacementFor + = (1 << 29), + } options; + OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters + multiplexParameters; +} OpenLogicalChannel_reverseLogicalChannelParameters; + +typedef struct NetworkAccessParameters_networkAddress { /* CHOICE */ + enum { + eNetworkAccessParameters_networkAddress_q2931Address, + eNetworkAccessParameters_networkAddress_e164Address, + eNetworkAccessParameters_networkAddress_localAreaAddress, + } choice; + union { + H245_TransportAddress localAreaAddress; + }; +} NetworkAccessParameters_networkAddress; + +typedef struct NetworkAccessParameters { /* SEQUENCE */ + enum { + eNetworkAccessParameters_distribution = (1 << 31), + eNetworkAccessParameters_externalReference = (1 << 30), + eNetworkAccessParameters_t120SetupProcedure = (1 << 29), + } options; + NetworkAccessParameters_networkAddress networkAddress; +} NetworkAccessParameters; + +typedef struct OpenLogicalChannel { /* SEQUENCE */ + enum { + eOpenLogicalChannel_reverseLogicalChannelParameters = + (1 << 31), + eOpenLogicalChannel_separateStack = (1 << 30), + eOpenLogicalChannel_encryptionSync = (1 << 29), + } options; + OpenLogicalChannel_forwardLogicalChannelParameters + forwardLogicalChannelParameters; + OpenLogicalChannel_reverseLogicalChannelParameters + reverseLogicalChannelParameters; + NetworkAccessParameters separateStack; +} OpenLogicalChannel; + +typedef struct Setup_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} Setup_UUIE_fastStart; + +typedef struct Setup_UUIE { /* SEQUENCE */ + enum { + eSetup_UUIE_h245Address = (1 << 31), + eSetup_UUIE_sourceAddress = (1 << 30), + eSetup_UUIE_destinationAddress = (1 << 29), + eSetup_UUIE_destCallSignalAddress = (1 << 28), + eSetup_UUIE_destExtraCallInfo = (1 << 27), + eSetup_UUIE_destExtraCRV = (1 << 26), + eSetup_UUIE_callServices = (1 << 25), + eSetup_UUIE_sourceCallSignalAddress = (1 << 24), + eSetup_UUIE_remoteExtensionAddress = (1 << 23), + eSetup_UUIE_callIdentifier = (1 << 22), + eSetup_UUIE_h245SecurityCapability = (1 << 21), + eSetup_UUIE_tokens = (1 << 20), + eSetup_UUIE_cryptoTokens = (1 << 19), + eSetup_UUIE_fastStart = (1 << 18), + eSetup_UUIE_mediaWaitForConnect = (1 << 17), + eSetup_UUIE_canOverlapSend = (1 << 16), + eSetup_UUIE_endpointIdentifier = (1 << 15), + eSetup_UUIE_multipleCalls = (1 << 14), + eSetup_UUIE_maintainConnection = (1 << 13), + eSetup_UUIE_connectionParameters = (1 << 12), + eSetup_UUIE_language = (1 << 11), + eSetup_UUIE_presentationIndicator = (1 << 10), + eSetup_UUIE_screeningIndicator = (1 << 9), + eSetup_UUIE_serviceControl = (1 << 8), + eSetup_UUIE_symmetricOperationRequired = (1 << 7), + eSetup_UUIE_capacity = (1 << 6), + eSetup_UUIE_circuitInfo = (1 << 5), + eSetup_UUIE_desiredProtocols = (1 << 4), + eSetup_UUIE_neededFeatures = (1 << 3), + eSetup_UUIE_desiredFeatures = (1 << 2), + eSetup_UUIE_supportedFeatures = (1 << 1), + eSetup_UUIE_parallelH245Control = (1 << 0), + } options; + TransportAddress h245Address; + TransportAddress destCallSignalAddress; + TransportAddress sourceCallSignalAddress; + Setup_UUIE_fastStart fastStart; +} Setup_UUIE; + +typedef struct CallProceeding_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} CallProceeding_UUIE_fastStart; + +typedef struct CallProceeding_UUIE { /* SEQUENCE */ + enum { + eCallProceeding_UUIE_h245Address = (1 << 31), + eCallProceeding_UUIE_callIdentifier = (1 << 30), + eCallProceeding_UUIE_h245SecurityMode = (1 << 29), + eCallProceeding_UUIE_tokens = (1 << 28), + eCallProceeding_UUIE_cryptoTokens = (1 << 27), + eCallProceeding_UUIE_fastStart = (1 << 26), + eCallProceeding_UUIE_multipleCalls = (1 << 25), + eCallProceeding_UUIE_maintainConnection = (1 << 24), + eCallProceeding_UUIE_fastConnectRefused = (1 << 23), + eCallProceeding_UUIE_featureSet = (1 << 22), + } options; + TransportAddress h245Address; + CallProceeding_UUIE_fastStart fastStart; +} CallProceeding_UUIE; + +typedef struct Connect_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} Connect_UUIE_fastStart; + +typedef struct Connect_UUIE { /* SEQUENCE */ + enum { + eConnect_UUIE_h245Address = (1 << 31), + eConnect_UUIE_callIdentifier = (1 << 30), + eConnect_UUIE_h245SecurityMode = (1 << 29), + eConnect_UUIE_tokens = (1 << 28), + eConnect_UUIE_cryptoTokens = (1 << 27), + eConnect_UUIE_fastStart = (1 << 26), + eConnect_UUIE_multipleCalls = (1 << 25), + eConnect_UUIE_maintainConnection = (1 << 24), + eConnect_UUIE_language = (1 << 23), + eConnect_UUIE_connectedAddress = (1 << 22), + eConnect_UUIE_presentationIndicator = (1 << 21), + eConnect_UUIE_screeningIndicator = (1 << 20), + eConnect_UUIE_fastConnectRefused = (1 << 19), + eConnect_UUIE_serviceControl = (1 << 18), + eConnect_UUIE_capacity = (1 << 17), + eConnect_UUIE_featureSet = (1 << 16), + } options; + TransportAddress h245Address; + Connect_UUIE_fastStart fastStart; +} Connect_UUIE; + +typedef struct Alerting_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} Alerting_UUIE_fastStart; + +typedef struct Alerting_UUIE { /* SEQUENCE */ + enum { + eAlerting_UUIE_h245Address = (1 << 31), + eAlerting_UUIE_callIdentifier = (1 << 30), + eAlerting_UUIE_h245SecurityMode = (1 << 29), + eAlerting_UUIE_tokens = (1 << 28), + eAlerting_UUIE_cryptoTokens = (1 << 27), + eAlerting_UUIE_fastStart = (1 << 26), + eAlerting_UUIE_multipleCalls = (1 << 25), + eAlerting_UUIE_maintainConnection = (1 << 24), + eAlerting_UUIE_alertingAddress = (1 << 23), + eAlerting_UUIE_presentationIndicator = (1 << 22), + eAlerting_UUIE_screeningIndicator = (1 << 21), + eAlerting_UUIE_fastConnectRefused = (1 << 20), + eAlerting_UUIE_serviceControl = (1 << 19), + eAlerting_UUIE_capacity = (1 << 18), + eAlerting_UUIE_featureSet = (1 << 17), + } options; + TransportAddress h245Address; + Alerting_UUIE_fastStart fastStart; +} Alerting_UUIE; + +typedef struct Information_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} Information_UUIE_fastStart; + +typedef struct Information_UUIE { /* SEQUENCE */ + enum { + eInformation_UUIE_callIdentifier = (1 << 31), + eInformation_UUIE_tokens = (1 << 30), + eInformation_UUIE_cryptoTokens = (1 << 29), + eInformation_UUIE_fastStart = (1 << 28), + eInformation_UUIE_fastConnectRefused = (1 << 27), + eInformation_UUIE_circuitInfo = (1 << 26), + } options; + Information_UUIE_fastStart fastStart; +} Information_UUIE; + +typedef struct FacilityReason { /* CHOICE */ + enum { + eFacilityReason_routeCallToGatekeeper, + eFacilityReason_callForwarded, + eFacilityReason_routeCallToMC, + eFacilityReason_undefinedReason, + eFacilityReason_conferenceListChoice, + eFacilityReason_startH245, + eFacilityReason_noH245, + eFacilityReason_newTokens, + eFacilityReason_featureSetUpdate, + eFacilityReason_forwardedElements, + eFacilityReason_transportedInformation, + } choice; +} FacilityReason; + +typedef struct Facility_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} Facility_UUIE_fastStart; + +typedef struct Facility_UUIE { /* SEQUENCE */ + enum { + eFacility_UUIE_alternativeAddress = (1 << 31), + eFacility_UUIE_alternativeAliasAddress = (1 << 30), + eFacility_UUIE_conferenceID = (1 << 29), + eFacility_UUIE_callIdentifier = (1 << 28), + eFacility_UUIE_destExtraCallInfo = (1 << 27), + eFacility_UUIE_remoteExtensionAddress = (1 << 26), + eFacility_UUIE_tokens = (1 << 25), + eFacility_UUIE_cryptoTokens = (1 << 24), + eFacility_UUIE_conferences = (1 << 23), + eFacility_UUIE_h245Address = (1 << 22), + eFacility_UUIE_fastStart = (1 << 21), + eFacility_UUIE_multipleCalls = (1 << 20), + eFacility_UUIE_maintainConnection = (1 << 19), + eFacility_UUIE_fastConnectRefused = (1 << 18), + eFacility_UUIE_serviceControl = (1 << 17), + eFacility_UUIE_circuitInfo = (1 << 16), + eFacility_UUIE_featureSet = (1 << 15), + eFacility_UUIE_destinationInfo = (1 << 14), + eFacility_UUIE_h245SecurityMode = (1 << 13), + } options; + FacilityReason reason; + TransportAddress h245Address; + Facility_UUIE_fastStart fastStart; +} Facility_UUIE; + +typedef struct Progress_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} Progress_UUIE_fastStart; + +typedef struct Progress_UUIE { /* SEQUENCE */ + enum { + eProgress_UUIE_h245Address = (1 << 31), + eProgress_UUIE_h245SecurityMode = (1 << 30), + eProgress_UUIE_tokens = (1 << 29), + eProgress_UUIE_cryptoTokens = (1 << 28), + eProgress_UUIE_fastStart = (1 << 27), + eProgress_UUIE_multipleCalls = (1 << 26), + eProgress_UUIE_maintainConnection = (1 << 25), + eProgress_UUIE_fastConnectRefused = (1 << 24), + } options; + TransportAddress h245Address; + Progress_UUIE_fastStart fastStart; +} Progress_UUIE; + +typedef struct H323_UU_PDU_h323_message_body { /* CHOICE */ + enum { + eH323_UU_PDU_h323_message_body_setup, + eH323_UU_PDU_h323_message_body_callProceeding, + eH323_UU_PDU_h323_message_body_connect, + eH323_UU_PDU_h323_message_body_alerting, + eH323_UU_PDU_h323_message_body_information, + eH323_UU_PDU_h323_message_body_releaseComplete, + eH323_UU_PDU_h323_message_body_facility, + eH323_UU_PDU_h323_message_body_progress, + eH323_UU_PDU_h323_message_body_empty, + eH323_UU_PDU_h323_message_body_status, + eH323_UU_PDU_h323_message_body_statusInquiry, + eH323_UU_PDU_h323_message_body_setupAcknowledge, + eH323_UU_PDU_h323_message_body_notify, + } choice; + union { + Setup_UUIE setup; + CallProceeding_UUIE callProceeding; + Connect_UUIE connect; + Alerting_UUIE alerting; + Information_UUIE information; + Facility_UUIE facility; + Progress_UUIE progress; + }; +} H323_UU_PDU_h323_message_body; + +typedef struct RequestMessage { /* CHOICE */ + enum { + eRequestMessage_nonStandard, + eRequestMessage_masterSlaveDetermination, + eRequestMessage_terminalCapabilitySet, + eRequestMessage_openLogicalChannel, + eRequestMessage_closeLogicalChannel, + eRequestMessage_requestChannelClose, + eRequestMessage_multiplexEntrySend, + eRequestMessage_requestMultiplexEntry, + eRequestMessage_requestMode, + eRequestMessage_roundTripDelayRequest, + eRequestMessage_maintenanceLoopRequest, + eRequestMessage_communicationModeRequest, + eRequestMessage_conferenceRequest, + eRequestMessage_multilinkRequest, + eRequestMessage_logicalChannelRateRequest, + } choice; + union { + OpenLogicalChannel openLogicalChannel; + }; +} RequestMessage; + +typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */ + enum { + eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters, + eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters, + } choice; + union { + H2250LogicalChannelParameters h2250LogicalChannelParameters; + }; +} OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters; + +typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters { /* SEQUENCE */ + enum { + eOpenLogicalChannelAck_reverseLogicalChannelParameters_portNumber + = (1 << 31), + eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters + = (1 << 30), + eOpenLogicalChannelAck_reverseLogicalChannelParameters_replacementFor + = (1 << 29), + } options; + OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters + multiplexParameters; +} OpenLogicalChannelAck_reverseLogicalChannelParameters; + +typedef struct H2250LogicalChannelAckParameters { /* SEQUENCE */ + enum { + eH2250LogicalChannelAckParameters_nonStandard = (1 << 31), + eH2250LogicalChannelAckParameters_sessionID = (1 << 30), + eH2250LogicalChannelAckParameters_mediaChannel = (1 << 29), + eH2250LogicalChannelAckParameters_mediaControlChannel = + (1 << 28), + eH2250LogicalChannelAckParameters_dynamicRTPPayloadType = + (1 << 27), + eH2250LogicalChannelAckParameters_flowControlToZero = + (1 << 26), + eH2250LogicalChannelAckParameters_portNumber = (1 << 25), + } options; + H245_TransportAddress mediaChannel; + H245_TransportAddress mediaControlChannel; +} H2250LogicalChannelAckParameters; + +typedef struct OpenLogicalChannelAck_forwardMultiplexAckParameters { /* CHOICE */ + enum { + eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters, + } choice; + union { + H2250LogicalChannelAckParameters + h2250LogicalChannelAckParameters; + }; +} OpenLogicalChannelAck_forwardMultiplexAckParameters; + +typedef struct OpenLogicalChannelAck { /* SEQUENCE */ + enum { + eOpenLogicalChannelAck_reverseLogicalChannelParameters = + (1 << 31), + eOpenLogicalChannelAck_separateStack = (1 << 30), + eOpenLogicalChannelAck_forwardMultiplexAckParameters = + (1 << 29), + eOpenLogicalChannelAck_encryptionSync = (1 << 28), + } options; + OpenLogicalChannelAck_reverseLogicalChannelParameters + reverseLogicalChannelParameters; + OpenLogicalChannelAck_forwardMultiplexAckParameters + forwardMultiplexAckParameters; +} OpenLogicalChannelAck; + +typedef struct ResponseMessage { /* CHOICE */ + enum { + eResponseMessage_nonStandard, + eResponseMessage_masterSlaveDeterminationAck, + eResponseMessage_masterSlaveDeterminationReject, + eResponseMessage_terminalCapabilitySetAck, + eResponseMessage_terminalCapabilitySetReject, + eResponseMessage_openLogicalChannelAck, + eResponseMessage_openLogicalChannelReject, + eResponseMessage_closeLogicalChannelAck, + eResponseMessage_requestChannelCloseAck, + eResponseMessage_requestChannelCloseReject, + eResponseMessage_multiplexEntrySendAck, + eResponseMessage_multiplexEntrySendReject, + eResponseMessage_requestMultiplexEntryAck, + eResponseMessage_requestMultiplexEntryReject, + eResponseMessage_requestModeAck, + eResponseMessage_requestModeReject, + eResponseMessage_roundTripDelayResponse, + eResponseMessage_maintenanceLoopAck, + eResponseMessage_maintenanceLoopReject, + eResponseMessage_communicationModeResponse, + eResponseMessage_conferenceResponse, + eResponseMessage_multilinkResponse, + eResponseMessage_logicalChannelRateAcknowledge, + eResponseMessage_logicalChannelRateReject, + } choice; + union { + OpenLogicalChannelAck openLogicalChannelAck; + }; +} ResponseMessage; + +typedef struct MultimediaSystemControlMessage { /* CHOICE */ + enum { + eMultimediaSystemControlMessage_request, + eMultimediaSystemControlMessage_response, + eMultimediaSystemControlMessage_command, + eMultimediaSystemControlMessage_indication, + } choice; + union { + RequestMessage request; + ResponseMessage response; + }; +} MultimediaSystemControlMessage; + +typedef struct H323_UU_PDU_h245Control { /* SEQUENCE OF */ + int count; + MultimediaSystemControlMessage item[4]; +} H323_UU_PDU_h245Control; + +typedef struct H323_UU_PDU { /* SEQUENCE */ + enum { + eH323_UU_PDU_nonStandardData = (1 << 31), + eH323_UU_PDU_h4501SupplementaryService = (1 << 30), + eH323_UU_PDU_h245Tunneling = (1 << 29), + eH323_UU_PDU_h245Control = (1 << 28), + eH323_UU_PDU_nonStandardControl = (1 << 27), + eH323_UU_PDU_callLinkage = (1 << 26), + eH323_UU_PDU_tunnelledSignallingMessage = (1 << 25), + eH323_UU_PDU_provisionalRespToH245Tunneling = (1 << 24), + eH323_UU_PDU_stimulusControl = (1 << 23), + eH323_UU_PDU_genericData = (1 << 22), + } options; + H323_UU_PDU_h323_message_body h323_message_body; + H323_UU_PDU_h245Control h245Control; +} H323_UU_PDU; + +typedef struct H323_UserInformation { /* SEQUENCE */ + enum { + eH323_UserInformation_user_data = (1 << 31), + } options; + H323_UU_PDU h323_uu_pdu; +} H323_UserInformation; + +typedef struct GatekeeperRequest { /* SEQUENCE */ + enum { + eGatekeeperRequest_nonStandardData = (1 << 31), + eGatekeeperRequest_gatekeeperIdentifier = (1 << 30), + eGatekeeperRequest_callServices = (1 << 29), + eGatekeeperRequest_endpointAlias = (1 << 28), + eGatekeeperRequest_alternateEndpoints = (1 << 27), + eGatekeeperRequest_tokens = (1 << 26), + eGatekeeperRequest_cryptoTokens = (1 << 25), + eGatekeeperRequest_authenticationCapability = (1 << 24), + eGatekeeperRequest_algorithmOIDs = (1 << 23), + eGatekeeperRequest_integrity = (1 << 22), + eGatekeeperRequest_integrityCheckValue = (1 << 21), + eGatekeeperRequest_supportsAltGK = (1 << 20), + eGatekeeperRequest_featureSet = (1 << 19), + eGatekeeperRequest_genericData = (1 << 18), + } options; + TransportAddress rasAddress; +} GatekeeperRequest; + +typedef struct GatekeeperConfirm { /* SEQUENCE */ + enum { + eGatekeeperConfirm_nonStandardData = (1 << 31), + eGatekeeperConfirm_gatekeeperIdentifier = (1 << 30), + eGatekeeperConfirm_alternateGatekeeper = (1 << 29), + eGatekeeperConfirm_authenticationMode = (1 << 28), + eGatekeeperConfirm_tokens = (1 << 27), + eGatekeeperConfirm_cryptoTokens = (1 << 26), + eGatekeeperConfirm_algorithmOID = (1 << 25), + eGatekeeperConfirm_integrity = (1 << 24), + eGatekeeperConfirm_integrityCheckValue = (1 << 23), + eGatekeeperConfirm_featureSet = (1 << 22), + eGatekeeperConfirm_genericData = (1 << 21), + } options; + TransportAddress rasAddress; +} GatekeeperConfirm; + +typedef struct RegistrationRequest_callSignalAddress { /* SEQUENCE OF */ + int count; + TransportAddress item[10]; +} RegistrationRequest_callSignalAddress; + +typedef struct RegistrationRequest_rasAddress { /* SEQUENCE OF */ + int count; + TransportAddress item[10]; +} RegistrationRequest_rasAddress; + +typedef struct RegistrationRequest { /* SEQUENCE */ + enum { + eRegistrationRequest_nonStandardData = (1 << 31), + eRegistrationRequest_terminalAlias = (1 << 30), + eRegistrationRequest_gatekeeperIdentifier = (1 << 29), + eRegistrationRequest_alternateEndpoints = (1 << 28), + eRegistrationRequest_timeToLive = (1 << 27), + eRegistrationRequest_tokens = (1 << 26), + eRegistrationRequest_cryptoTokens = (1 << 25), + eRegistrationRequest_integrityCheckValue = (1 << 24), + eRegistrationRequest_keepAlive = (1 << 23), + eRegistrationRequest_endpointIdentifier = (1 << 22), + eRegistrationRequest_willSupplyUUIEs = (1 << 21), + eRegistrationRequest_maintainConnection = (1 << 20), + eRegistrationRequest_alternateTransportAddresses = (1 << 19), + eRegistrationRequest_additiveRegistration = (1 << 18), + eRegistrationRequest_terminalAliasPattern = (1 << 17), + eRegistrationRequest_supportsAltGK = (1 << 16), + eRegistrationRequest_usageReportingCapability = (1 << 15), + eRegistrationRequest_multipleCalls = (1 << 14), + eRegistrationRequest_supportedH248Packages = (1 << 13), + eRegistrationRequest_callCreditCapability = (1 << 12), + eRegistrationRequest_capacityReportingCapability = (1 << 11), + eRegistrationRequest_capacity = (1 << 10), + eRegistrationRequest_featureSet = (1 << 9), + eRegistrationRequest_genericData = (1 << 8), + } options; + RegistrationRequest_callSignalAddress callSignalAddress; + RegistrationRequest_rasAddress rasAddress; + unsigned timeToLive; +} RegistrationRequest; + +typedef struct RegistrationConfirm_callSignalAddress { /* SEQUENCE OF */ + int count; + TransportAddress item[10]; +} RegistrationConfirm_callSignalAddress; + +typedef struct RegistrationConfirm { /* SEQUENCE */ + enum { + eRegistrationConfirm_nonStandardData = (1 << 31), + eRegistrationConfirm_terminalAlias = (1 << 30), + eRegistrationConfirm_gatekeeperIdentifier = (1 << 29), + eRegistrationConfirm_alternateGatekeeper = (1 << 28), + eRegistrationConfirm_timeToLive = (1 << 27), + eRegistrationConfirm_tokens = (1 << 26), + eRegistrationConfirm_cryptoTokens = (1 << 25), + eRegistrationConfirm_integrityCheckValue = (1 << 24), + eRegistrationConfirm_willRespondToIRR = (1 << 23), + eRegistrationConfirm_preGrantedARQ = (1 << 22), + eRegistrationConfirm_maintainConnection = (1 << 21), + eRegistrationConfirm_serviceControl = (1 << 20), + eRegistrationConfirm_supportsAdditiveRegistration = (1 << 19), + eRegistrationConfirm_terminalAliasPattern = (1 << 18), + eRegistrationConfirm_supportedPrefixes = (1 << 17), + eRegistrationConfirm_usageSpec = (1 << 16), + eRegistrationConfirm_featureServerAlias = (1 << 15), + eRegistrationConfirm_capacityReportingSpec = (1 << 14), + eRegistrationConfirm_featureSet = (1 << 13), + eRegistrationConfirm_genericData = (1 << 12), + } options; + RegistrationConfirm_callSignalAddress callSignalAddress; + unsigned timeToLive; +} RegistrationConfirm; + +typedef struct UnregistrationRequest_callSignalAddress { /* SEQUENCE OF */ + int count; + TransportAddress item[10]; +} UnregistrationRequest_callSignalAddress; + +typedef struct UnregistrationRequest { /* SEQUENCE */ + enum { + eUnregistrationRequest_endpointAlias = (1 << 31), + eUnregistrationRequest_nonStandardData = (1 << 30), + eUnregistrationRequest_endpointIdentifier = (1 << 29), + eUnregistrationRequest_alternateEndpoints = (1 << 28), + eUnregistrationRequest_gatekeeperIdentifier = (1 << 27), + eUnregistrationRequest_tokens = (1 << 26), + eUnregistrationRequest_cryptoTokens = (1 << 25), + eUnregistrationRequest_integrityCheckValue = (1 << 24), + eUnregistrationRequest_reason = (1 << 23), + eUnregistrationRequest_endpointAliasPattern = (1 << 22), + eUnregistrationRequest_supportedPrefixes = (1 << 21), + eUnregistrationRequest_alternateGatekeeper = (1 << 20), + eUnregistrationRequest_genericData = (1 << 19), + } options; + UnregistrationRequest_callSignalAddress callSignalAddress; +} UnregistrationRequest; + +typedef struct AdmissionRequest { /* SEQUENCE */ + enum { + eAdmissionRequest_callModel = (1 << 31), + eAdmissionRequest_destinationInfo = (1 << 30), + eAdmissionRequest_destCallSignalAddress = (1 << 29), + eAdmissionRequest_destExtraCallInfo = (1 << 28), + eAdmissionRequest_srcCallSignalAddress = (1 << 27), + eAdmissionRequest_nonStandardData = (1 << 26), + eAdmissionRequest_callServices = (1 << 25), + eAdmissionRequest_canMapAlias = (1 << 24), + eAdmissionRequest_callIdentifier = (1 << 23), + eAdmissionRequest_srcAlternatives = (1 << 22), + eAdmissionRequest_destAlternatives = (1 << 21), + eAdmissionRequest_gatekeeperIdentifier = (1 << 20), + eAdmissionRequest_tokens = (1 << 19), + eAdmissionRequest_cryptoTokens = (1 << 18), + eAdmissionRequest_integrityCheckValue = (1 << 17), + eAdmissionRequest_transportQOS = (1 << 16), + eAdmissionRequest_willSupplyUUIEs = (1 << 15), + eAdmissionRequest_callLinkage = (1 << 14), + eAdmissionRequest_gatewayDataRate = (1 << 13), + eAdmissionRequest_capacity = (1 << 12), + eAdmissionRequest_circuitInfo = (1 << 11), + eAdmissionRequest_desiredProtocols = (1 << 10), + eAdmissionRequest_desiredTunnelledProtocol = (1 << 9), + eAdmissionRequest_featureSet = (1 << 8), + eAdmissionRequest_genericData = (1 << 7), + } options; + TransportAddress destCallSignalAddress; + TransportAddress srcCallSignalAddress; +} AdmissionRequest; + +typedef struct AdmissionConfirm { /* SEQUENCE */ + enum { + eAdmissionConfirm_irrFrequency = (1 << 31), + eAdmissionConfirm_nonStandardData = (1 << 30), + eAdmissionConfirm_destinationInfo = (1 << 29), + eAdmissionConfirm_destExtraCallInfo = (1 << 28), + eAdmissionConfirm_destinationType = (1 << 27), + eAdmissionConfirm_remoteExtensionAddress = (1 << 26), + eAdmissionConfirm_alternateEndpoints = (1 << 25), + eAdmissionConfirm_tokens = (1 << 24), + eAdmissionConfirm_cryptoTokens = (1 << 23), + eAdmissionConfirm_integrityCheckValue = (1 << 22), + eAdmissionConfirm_transportQOS = (1 << 21), + eAdmissionConfirm_willRespondToIRR = (1 << 20), + eAdmissionConfirm_uuiesRequested = (1 << 19), + eAdmissionConfirm_language = (1 << 18), + eAdmissionConfirm_alternateTransportAddresses = (1 << 17), + eAdmissionConfirm_useSpecifiedTransport = (1 << 16), + eAdmissionConfirm_circuitInfo = (1 << 15), + eAdmissionConfirm_usageSpec = (1 << 14), + eAdmissionConfirm_supportedProtocols = (1 << 13), + eAdmissionConfirm_serviceControl = (1 << 12), + eAdmissionConfirm_multipleCalls = (1 << 11), + eAdmissionConfirm_featureSet = (1 << 10), + eAdmissionConfirm_genericData = (1 << 9), + } options; + TransportAddress destCallSignalAddress; +} AdmissionConfirm; + +typedef struct LocationRequest { /* SEQUENCE */ + enum { + eLocationRequest_endpointIdentifier = (1 << 31), + eLocationRequest_nonStandardData = (1 << 30), + eLocationRequest_sourceInfo = (1 << 29), + eLocationRequest_canMapAlias = (1 << 28), + eLocationRequest_gatekeeperIdentifier = (1 << 27), + eLocationRequest_tokens = (1 << 26), + eLocationRequest_cryptoTokens = (1 << 25), + eLocationRequest_integrityCheckValue = (1 << 24), + eLocationRequest_desiredProtocols = (1 << 23), + eLocationRequest_desiredTunnelledProtocol = (1 << 22), + eLocationRequest_featureSet = (1 << 21), + eLocationRequest_genericData = (1 << 20), + eLocationRequest_hopCount = (1 << 19), + eLocationRequest_circuitInfo = (1 << 18), + } options; + TransportAddress replyAddress; +} LocationRequest; + +typedef struct LocationConfirm { /* SEQUENCE */ + enum { + eLocationConfirm_nonStandardData = (1 << 31), + eLocationConfirm_destinationInfo = (1 << 30), + eLocationConfirm_destExtraCallInfo = (1 << 29), + eLocationConfirm_destinationType = (1 << 28), + eLocationConfirm_remoteExtensionAddress = (1 << 27), + eLocationConfirm_alternateEndpoints = (1 << 26), + eLocationConfirm_tokens = (1 << 25), + eLocationConfirm_cryptoTokens = (1 << 24), + eLocationConfirm_integrityCheckValue = (1 << 23), + eLocationConfirm_alternateTransportAddresses = (1 << 22), + eLocationConfirm_supportedProtocols = (1 << 21), + eLocationConfirm_multipleCalls = (1 << 20), + eLocationConfirm_featureSet = (1 << 19), + eLocationConfirm_genericData = (1 << 18), + eLocationConfirm_circuitInfo = (1 << 17), + eLocationConfirm_serviceControl = (1 << 16), + } options; + TransportAddress callSignalAddress; + TransportAddress rasAddress; +} LocationConfirm; + +typedef struct InfoRequestResponse_callSignalAddress { /* SEQUENCE OF */ + int count; + TransportAddress item[10]; +} InfoRequestResponse_callSignalAddress; + +typedef struct InfoRequestResponse { /* SEQUENCE */ + enum { + eInfoRequestResponse_nonStandardData = (1 << 31), + eInfoRequestResponse_endpointAlias = (1 << 30), + eInfoRequestResponse_perCallInfo = (1 << 29), + eInfoRequestResponse_tokens = (1 << 28), + eInfoRequestResponse_cryptoTokens = (1 << 27), + eInfoRequestResponse_integrityCheckValue = (1 << 26), + eInfoRequestResponse_needResponse = (1 << 25), + eInfoRequestResponse_capacity = (1 << 24), + eInfoRequestResponse_irrStatus = (1 << 23), + eInfoRequestResponse_unsolicited = (1 << 22), + eInfoRequestResponse_genericData = (1 << 21), + } options; + TransportAddress rasAddress; + InfoRequestResponse_callSignalAddress callSignalAddress; +} InfoRequestResponse; + +typedef struct RasMessage { /* CHOICE */ + enum { + eRasMessage_gatekeeperRequest, + eRasMessage_gatekeeperConfirm, + eRasMessage_gatekeeperReject, + eRasMessage_registrationRequest, + eRasMessage_registrationConfirm, + eRasMessage_registrationReject, + eRasMessage_unregistrationRequest, + eRasMessage_unregistrationConfirm, + eRasMessage_unregistrationReject, + eRasMessage_admissionRequest, + eRasMessage_admissionConfirm, + eRasMessage_admissionReject, + eRasMessage_bandwidthRequest, + eRasMessage_bandwidthConfirm, + eRasMessage_bandwidthReject, + eRasMessage_disengageRequest, + eRasMessage_disengageConfirm, + eRasMessage_disengageReject, + eRasMessage_locationRequest, + eRasMessage_locationConfirm, + eRasMessage_locationReject, + eRasMessage_infoRequest, + eRasMessage_infoRequestResponse, + eRasMessage_nonStandardMessage, + eRasMessage_unknownMessageResponse, + eRasMessage_requestInProgress, + eRasMessage_resourcesAvailableIndicate, + eRasMessage_resourcesAvailableConfirm, + eRasMessage_infoRequestAck, + eRasMessage_infoRequestNak, + eRasMessage_serviceControlIndication, + eRasMessage_serviceControlResponse, + } choice; + union { + GatekeeperRequest gatekeeperRequest; + GatekeeperConfirm gatekeeperConfirm; + RegistrationRequest registrationRequest; + RegistrationConfirm registrationConfirm; + UnregistrationRequest unregistrationRequest; + AdmissionRequest admissionRequest; + AdmissionConfirm admissionConfirm; + LocationRequest locationRequest; + LocationConfirm locationConfirm; + InfoRequestResponse infoRequestResponse; + }; +} RasMessage; diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c new file mode 100644 index 000000000000..a0bc883928c0 --- /dev/null +++ b/net/ipv4/netfilter/ip_nat_helper_h323.c @@ -0,0 +1,605 @@ +/* + * H.323 extension for NAT alteration. + * + * Copyright (c) 2006 Jing Min Zhao + * + * This source code is licensed under General Public License version 2. + * + * Based on the 'brute force' H.323 NAT module by + * Jozsef Kadlecsik + * + * Changes: + * 2006-02-01 - initial version 0.1 + * + * 2006-02-20 - version 0.2 + * 1. Changed source format to follow kernel conventions + * 2. Deleted some unnecessary structures + * 3. Minor fixes + * + * 2006-03-10 - version 0.3 + * 1. Added support for multiple TPKTs in one packet (suggested by + * Patrick McHardy) + * 2. Added support for non-linear skb (based on Patrick McHardy's patch) + * 3. Eliminated unnecessary return code + * + * 2006-03-15 - version 0.4 + * 1. Added support for T.120 channels + * 2. Added parameter gkrouted_only (suggested by Patrick McHardy) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ip_conntrack_helper_h323_asn1.h" + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(format, args...) +#endif + +extern int get_h245_addr(unsigned char *data, H245_TransportAddress * addr, + u_int32_t * ip, u_int16_t * port); +extern int get_h225_addr(unsigned char *data, TransportAddress * addr, + u_int32_t * ip, u_int16_t * port); +extern void ip_conntrack_h245_expect(struct ip_conntrack *new, + struct ip_conntrack_expect *this); +extern void ip_conntrack_q931_expect(struct ip_conntrack *new, + struct ip_conntrack_expect *this); +extern int (*set_h245_addr_hook) (struct sk_buff ** pskb, + unsigned char **data, int dataoff, + H245_TransportAddress * addr, + u_int32_t ip, u_int16_t port); +extern int (*set_h225_addr_hook) (struct sk_buff ** pskb, + unsigned char **data, int dataoff, + TransportAddress * addr, + u_int32_t ip, u_int16_t port); +extern int (*set_sig_addr_hook) (struct sk_buff ** pskb, + struct ip_conntrack * ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, + TransportAddress * addr, int count); +extern int (*set_ras_addr_hook) (struct sk_buff ** pskb, + struct ip_conntrack * ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, + TransportAddress * addr, int count); +extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb, + struct ip_conntrack * ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H245_TransportAddress * addr, + u_int16_t port, u_int16_t rtp_port, + struct ip_conntrack_expect * rtp_exp, + struct ip_conntrack_expect * rtcp_exp); +extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H245_TransportAddress * addr, u_int16_t port, + struct ip_conntrack_expect * exp); +extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + TransportAddress * addr, u_int16_t port, + struct ip_conntrack_expect * exp); +extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, TransportAddress * addr, + int idx, u_int16_t port, + struct ip_conntrack_expect * exp); + + +/****************************************************************************/ +static int set_addr(struct sk_buff **pskb, + unsigned char **data, int dataoff, + unsigned int addroff, u_int32_t ip, u_int16_t port) +{ + enum ip_conntrack_info ctinfo; + struct ip_conntrack *ct = ip_conntrack_get(*pskb, &ctinfo); + struct { + u_int32_t ip; + u_int16_t port; + } __attribute__ ((__packed__)) buf; + struct tcphdr _tcph, *th; + + buf.ip = ip; + buf.port = htons(port); + addroff += dataoff; + + if ((*pskb)->nh.iph->protocol == IPPROTO_TCP) { + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, + addroff, sizeof(buf), + (char *) &buf, sizeof(buf))) { + if (net_ratelimit()) + printk("ip_nat_h323: ip_nat_mangle_tcp_packet" + " error\n"); + return -1; + } + + /* Relocate data pointer */ + th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4, + sizeof(_tcph), &_tcph); + if (th == NULL) + return -1; + *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 + + th->doff * 4 + dataoff; + } else { + if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo, + addroff, sizeof(buf), + (char *) &buf, sizeof(buf))) { + if (net_ratelimit()) + printk("ip_nat_h323: ip_nat_mangle_udp_packet" + " error\n"); + return -1; + } + /* ip_nat_mangle_udp_packet uses skb_make_writable() to copy + * or pull everything in a linear buffer, so we can safely + * use the skb pointers now */ + *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 + + sizeof(struct udphdr); + } + + return 0; +} + +/****************************************************************************/ +static int set_h225_addr(struct sk_buff **pskb, + unsigned char **data, int dataoff, + TransportAddress * addr, + u_int32_t ip, u_int16_t port) +{ + return set_addr(pskb, data, dataoff, addr->ipAddress.ip, ip, port); +} + +/****************************************************************************/ +static int set_h245_addr(struct sk_buff **pskb, + unsigned char **data, int dataoff, + H245_TransportAddress * addr, + u_int32_t ip, u_int16_t port) +{ + return set_addr(pskb, data, dataoff, + addr->unicastAddress.iPAddress.network, ip, port); +} + +/****************************************************************************/ +static int set_sig_addr(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, + TransportAddress * addr, int count) +{ + struct ip_ct_h323_master *info = &ct->help.ct_h323_info; + int dir = CTINFO2DIR(ctinfo); + int i; + u_int32_t ip; + u_int16_t port; + + for (i = 0; i < count; i++) { + if (get_h225_addr(*data, &addr[i], &ip, &port)) { + if (ip == ct->tuplehash[dir].tuple.src.ip && + port == info->sig_port[dir]) { + /* GW->GK */ + + /* Fix for Gnomemeeting */ + if (i > 0 && + get_h225_addr(*data, &addr[0], + &ip, &port) && + (ntohl(ip) & 0xff000000) == 0x7f000000) + i = 0; + + DEBUGP + ("ip_nat_ras: set signal address " + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(ip), port, + NIPQUAD(ct->tuplehash[!dir].tuple.dst. + ip), info->sig_port[!dir]); + return set_h225_addr(pskb, data, 0, &addr[i], + ct->tuplehash[!dir]. + tuple.dst.ip, + info->sig_port[!dir]); + } else if (ip == ct->tuplehash[dir].tuple.dst.ip && + port == info->sig_port[dir]) { + /* GK->GW */ + DEBUGP + ("ip_nat_ras: set signal address " + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(ip), port, + NIPQUAD(ct->tuplehash[!dir].tuple.src. + ip), info->sig_port[!dir]); + return set_h225_addr(pskb, data, 0, &addr[i], + ct->tuplehash[!dir]. + tuple.src.ip, + info->sig_port[!dir]); + } + } + } + + return 0; +} + +/****************************************************************************/ +static int set_ras_addr(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, + TransportAddress * addr, int count) +{ + int dir = CTINFO2DIR(ctinfo); + int i; + u_int32_t ip; + u_int16_t port; + + for (i = 0; i < count; i++) { + if (get_h225_addr(*data, &addr[i], &ip, &port) && + ip == ct->tuplehash[dir].tuple.src.ip && + port == ntohs(ct->tuplehash[dir].tuple.src.u.udp.port)) { + DEBUGP("ip_nat_ras: set rasAddress " + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(ip), port, + NIPQUAD(ct->tuplehash[!dir].tuple.dst.ip), + ntohs(ct->tuplehash[!dir].tuple.dst.u.udp. + port)); + return set_h225_addr(pskb, data, 0, &addr[i], + ct->tuplehash[!dir].tuple.dst.ip, + ntohs(ct->tuplehash[!dir].tuple. + dst.u.udp.port)); + } + } + + return 0; +} + +/****************************************************************************/ +static int nat_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H245_TransportAddress * addr, + u_int16_t port, u_int16_t rtp_port, + struct ip_conntrack_expect *rtp_exp, + struct ip_conntrack_expect *rtcp_exp) +{ + struct ip_ct_h323_master *info = &ct->help.ct_h323_info; + int dir = CTINFO2DIR(ctinfo); + int i; + u_int16_t nated_port; + + /* Set expectations for NAT */ + rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port; + rtp_exp->expectfn = ip_nat_follow_master; + rtp_exp->dir = !dir; + rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port; + rtcp_exp->expectfn = ip_nat_follow_master; + rtcp_exp->dir = !dir; + + /* Lookup existing expects */ + for (i = 0; i < H323_RTP_CHANNEL_MAX; i++) { + if (info->rtp_port[i][dir] == rtp_port) { + /* Expected */ + + /* Use allocated ports first. This will refresh + * the expects */ + rtp_exp->tuple.dst.u.udp.port = + htons(info->rtp_port[i][dir]); + rtcp_exp->tuple.dst.u.udp.port = + htons(info->rtp_port[i][dir] + 1); + break; + } else if (info->rtp_port[i][dir] == 0) { + /* Not expected */ + break; + } + } + + /* Run out of expectations */ + if (i >= H323_RTP_CHANNEL_MAX) { + if (net_ratelimit()) + printk("ip_nat_h323: out of expectations\n"); + return 0; + } + + /* Try to get a pair of ports. */ + for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port); + nated_port != 0; nated_port += 2) { + rtp_exp->tuple.dst.u.udp.port = htons(nated_port); + if (ip_conntrack_expect_related(rtp_exp) == 0) { + rtcp_exp->tuple.dst.u.udp.port = + htons(nated_port + 1); + if (ip_conntrack_expect_related(rtcp_exp) == 0) + break; + ip_conntrack_unexpect_related(rtp_exp); + } + } + + if (nated_port == 0) { /* No port available */ + if (net_ratelimit()) + printk("ip_nat_h323: out of RTP ports\n"); + return 0; + } + + /* Modify signal */ + if (set_h245_addr(pskb, data, dataoff, addr, + ct->tuplehash[!dir].tuple.dst.ip, + (port & 1) ? nated_port + 1 : nated_port) == 0) { + /* Save ports */ + info->rtp_port[i][dir] = rtp_port; + info->rtp_port[i][!dir] = nated_port; + } else { + ip_conntrack_unexpect_related(rtp_exp); + ip_conntrack_unexpect_related(rtcp_exp); + return -1; + } + + /* Success */ + DEBUGP("ip_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(rtp_exp->tuple.src.ip), + ntohs(rtp_exp->tuple.src.u.udp.port), + NIPQUAD(rtp_exp->tuple.dst.ip), + ntohs(rtp_exp->tuple.dst.u.udp.port)); + DEBUGP("ip_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(rtcp_exp->tuple.src.ip), + ntohs(rtcp_exp->tuple.src.u.udp.port), + NIPQUAD(rtcp_exp->tuple.dst.ip), + ntohs(rtcp_exp->tuple.dst.u.udp.port)); + + return 0; +} + +/****************************************************************************/ +static int nat_t120(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H245_TransportAddress * addr, u_int16_t port, + struct ip_conntrack_expect *exp) +{ + int dir = CTINFO2DIR(ctinfo); + u_int16_t nated_port = port; + + /* Set expectations for NAT */ + exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; + exp->expectfn = ip_nat_follow_master; + exp->dir = !dir; + + /* Try to get same port: if not, try to change it. */ + for (; nated_port != 0; nated_port++) { + exp->tuple.dst.u.tcp.port = htons(nated_port); + if (ip_conntrack_expect_related(exp) == 0) + break; + } + + if (nated_port == 0) { /* No port available */ + if (net_ratelimit()) + printk("ip_nat_h323: out of TCP ports\n"); + return 0; + } + + /* Modify signal */ + if (set_h245_addr(pskb, data, dataoff, addr, + ct->tuplehash[!dir].tuple.dst.ip, nated_port) < 0) { + ip_conntrack_unexpect_related(exp); + return -1; + } + + DEBUGP("ip_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port), + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port)); + + return 0; +} + +/**************************************************************************** + * This conntrack expect function replaces ip_conntrack_h245_expect() + * which was set by ip_conntrack_helper_h323.c. It calls both + * ip_nat_follow_master() and ip_conntrack_h245_expect() + ****************************************************************************/ +static void ip_nat_h245_expect(struct ip_conntrack *new, + struct ip_conntrack_expect *this) +{ + ip_nat_follow_master(new, this); + ip_conntrack_h245_expect(new, this); +} + +/****************************************************************************/ +static int nat_h245(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + TransportAddress * addr, u_int16_t port, + struct ip_conntrack_expect *exp) +{ + struct ip_ct_h323_master *info = &ct->help.ct_h323_info; + int dir = CTINFO2DIR(ctinfo); + u_int16_t nated_port = port; + + /* Set expectations for NAT */ + exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; + exp->expectfn = ip_nat_h245_expect; + exp->dir = !dir; + + /* Check existing expects */ + if (info->sig_port[dir] == port) + nated_port = info->sig_port[!dir]; + + /* Try to get same port: if not, try to change it. */ + for (; nated_port != 0; nated_port++) { + exp->tuple.dst.u.tcp.port = htons(nated_port); + if (ip_conntrack_expect_related(exp) == 0) + break; + } + + if (nated_port == 0) { /* No port available */ + if (net_ratelimit()) + printk("ip_nat_q931: out of TCP ports\n"); + return 0; + } + + /* Modify signal */ + if (set_h225_addr(pskb, data, dataoff, addr, + ct->tuplehash[!dir].tuple.dst.ip, + nated_port) == 0) { + /* Save ports */ + info->sig_port[dir] = port; + info->sig_port[!dir] = nated_port; + } else { + ip_conntrack_unexpect_related(exp); + return -1; + } + + DEBUGP("ip_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port), + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port)); + + return 0; +} + +/**************************************************************************** + * This conntrack expect function replaces ip_conntrack_q931_expect() + * which was set by ip_conntrack_helper_h323.c. + ****************************************************************************/ +static void ip_nat_q931_expect(struct ip_conntrack *new, + struct ip_conntrack_expect *this) +{ + struct ip_nat_range range; + + if (this->tuple.src.ip != 0) { /* Only accept calls from GK */ + ip_nat_follow_master(new, this); + goto out; + } + + /* This must be a fresh one. */ + BUG_ON(new->status & IPS_NAT_DONE_MASK); + + /* Change src to where master sends to */ + range.flags = IP_NAT_RANGE_MAP_IPS; + range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.ip; + + /* hook doesn't matter, but it has to do source manip */ + ip_nat_setup_info(new, &range, NF_IP_POST_ROUTING); + + /* For DST manip, map port here to where it's expected. */ + range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); + range.min = range.max = this->saved_proto; + range.min_ip = range.max_ip = + new->master->tuplehash[!this->dir].tuple.src.ip; + + /* hook doesn't matter, but it has to do destination manip */ + ip_nat_setup_info(new, &range, NF_IP_PRE_ROUTING); + + out: + ip_conntrack_q931_expect(new, this); +} + +/****************************************************************************/ +static int nat_q931(struct sk_buff **pskb, struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, TransportAddress * addr, int idx, + u_int16_t port, struct ip_conntrack_expect *exp) +{ + struct ip_ct_h323_master *info = &ct->help.ct_h323_info; + int dir = CTINFO2DIR(ctinfo); + u_int16_t nated_port = port; + u_int32_t ip; + + /* Set expectations for NAT */ + exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; + exp->expectfn = ip_nat_q931_expect; + exp->dir = !dir; + + /* Check existing expects */ + if (info->sig_port[dir] == port) + nated_port = info->sig_port[!dir]; + + /* Try to get same port: if not, try to change it. */ + for (; nated_port != 0; nated_port++) { + exp->tuple.dst.u.tcp.port = htons(nated_port); + if (ip_conntrack_expect_related(exp) == 0) + break; + } + + if (nated_port == 0) { /* No port available */ + if (net_ratelimit()) + printk("ip_nat_ras: out of TCP ports\n"); + return 0; + } + + /* Modify signal */ + if (set_h225_addr(pskb, data, 0, &addr[idx], + ct->tuplehash[!dir].tuple.dst.ip, + nated_port) == 0) { + /* Save ports */ + info->sig_port[dir] = port; + info->sig_port[!dir] = nated_port; + + /* Fix for Gnomemeeting */ + if (idx > 0 && + get_h225_addr(*data, &addr[0], &ip, &port) && + (ntohl(ip) & 0xff000000) == 0x7f000000) { + set_h225_addr_hook(pskb, data, 0, &addr[0], + ct->tuplehash[!dir].tuple.dst.ip, + info->sig_port[!dir]); + } + } else { + ip_conntrack_unexpect_related(exp); + return -1; + } + + /* Success */ + DEBUGP("ip_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port), + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port)); + + return 0; +} + +/****************************************************************************/ +static int __init init(void) +{ + BUG_ON(set_h245_addr_hook != NULL); + BUG_ON(set_h225_addr_hook != NULL); + BUG_ON(set_sig_addr_hook != NULL); + BUG_ON(set_ras_addr_hook != NULL); + BUG_ON(nat_rtp_rtcp_hook != NULL); + BUG_ON(nat_t120_hook != NULL); + BUG_ON(nat_h245_hook != NULL); + BUG_ON(nat_q931_hook != NULL); + + set_h245_addr_hook = set_h245_addr; + set_h225_addr_hook = set_h225_addr; + set_sig_addr_hook = set_sig_addr; + set_ras_addr_hook = set_ras_addr; + nat_rtp_rtcp_hook = nat_rtp_rtcp; + nat_t120_hook = nat_t120; + nat_h245_hook = nat_h245; + nat_q931_hook = nat_q931; + + DEBUGP("ip_nat_h323: init success\n"); + return 0; +} + +/****************************************************************************/ +static void __exit fini(void) +{ + set_h245_addr_hook = NULL; + set_h225_addr_hook = NULL; + set_sig_addr_hook = NULL; + set_ras_addr_hook = NULL; + nat_rtp_rtcp_hook = NULL; + nat_t120_hook = NULL; + nat_h245_hook = NULL; + nat_q931_hook = NULL; + synchronize_net(); +} + +/****************************************************************************/ +module_init(init); +module_exit(fini); + +MODULE_AUTHOR("Jing Min Zhao "); +MODULE_DESCRIPTION("H.323 NAT helper"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From f10b7897ee29649fa7f0ccdc8d859ccd6ce7dbfd Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 25 Jan 2006 22:34:01 +1100 Subject: [CRYPTO] api: Align tfm context as wide as possible Since tfm contexts can contain arbitrary types we should provide at least natural alignment (__attribute__ ((__aligned__))) for them. In particular, this is needed on the Xscale which is a 32-bit architecture with a u64 type that requires 64-bit alignment. This problem was reported by Ronen Shitrit. The crypto_tfm structure's size was 44 bytes on 32-bit architectures and 80 bytes on 64-bit architectures. So adding this requirement only means that we have to add an extra 4 bytes on 32-bit architectures. On i386 the natural alignment is 16 bytes which also benefits the VIA Padlock as it no longer has to manually align its context structure to 128 bits. Signed-off-by: Herbert Xu --- crypto/api.c | 2 +- drivers/crypto/padlock-aes.c | 6 +++++- include/linux/crypto.h | 10 +++++++++- 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/crypto/api.c b/crypto/api.c index e26156f71839..34e02caffc2a 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -165,7 +165,7 @@ static unsigned int crypto_ctxsize(struct crypto_alg *alg, int flags) break; } - return len + alg->cra_alignmask; + return len + (alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1)); } struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags) diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index 0c08c58252be..5158a9db4bc5 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c @@ -284,7 +284,11 @@ aes_hw_extkey_available(uint8_t key_len) static inline struct aes_ctx *aes_ctx(void *ctx) { - return (struct aes_ctx *)ALIGN((unsigned long)ctx, PADLOCK_ALIGNMENT); + unsigned long align = PADLOCK_ALIGNMENT; + + if (align <= crypto_tfm_ctx_alignment()) + align = 1; + return (struct aes_ctx *)ALIGN((unsigned long)ctx, align); } static int diff --git a/include/linux/crypto.h b/include/linux/crypto.h index d88bf8aa8b47..0ab1bc1152ca 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -229,6 +229,8 @@ struct crypto_tfm { } crt_u; struct crypto_alg *__crt_alg; + + char __crt_ctx[] __attribute__ ((__aligned__)); }; /* @@ -301,7 +303,13 @@ static inline unsigned int crypto_tfm_alg_alignmask(struct crypto_tfm *tfm) static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm) { - return (void *)&tfm[1]; + return tfm->__crt_ctx; +} + +static inline unsigned int crypto_tfm_ctx_alignment(void) +{ + struct crypto_tfm *tfm; + return __alignof__(tfm->__crt_ctx); } /* -- cgit v1.2.3 From e87dddeb92618d9dbb8b9f946a193739a4447609 Mon Sep 17 00:00:00 2001 From: Peter Horton Date: Sun, 12 Feb 2006 17:10:25 +0000 Subject: [MIPS] Add early console for Cobalt. Signed-off-by: Peter Horton Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + arch/mips/cobalt/Kconfig | 7 ++++++ arch/mips/cobalt/Makefile | 2 ++ arch/mips/cobalt/console.c | 43 +++++++++++++++++++++++++++++++++++ arch/mips/cobalt/setup.c | 13 ++++------- include/asm-mips/mach-cobalt/cobalt.h | 2 ++ 6 files changed, 60 insertions(+), 8 deletions(-) create mode 100644 arch/mips/cobalt/Kconfig create mode 100644 arch/mips/cobalt/console.c (limited to 'include') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 3a0f89d2c8dc..9d1e78f9c060 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -790,6 +790,7 @@ source "arch/mips/tx4927/Kconfig" source "arch/mips/tx4938/Kconfig" source "arch/mips/vr41xx/Kconfig" source "arch/mips/philips/pnx8550/common/Kconfig" +source "arch/mips/cobalt/Kconfig" endmenu diff --git a/arch/mips/cobalt/Kconfig b/arch/mips/cobalt/Kconfig new file mode 100644 index 000000000000..7c42b088d16c --- /dev/null +++ b/arch/mips/cobalt/Kconfig @@ -0,0 +1,7 @@ +config EARLY_PRINTK + bool "Early console support" + depends on MIPS_COBALT + help + Provide early console support by direct access to the + on board UART. The UART must have been previously + initialised by the boot loader. diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile index 3b6b7579d1de..720e757b2b64 100644 --- a/arch/mips/cobalt/Makefile +++ b/arch/mips/cobalt/Makefile @@ -4,4 +4,6 @@ obj-y := irq.o int-handler.o reset.o setup.o +obj-$(CONFIG_EARLY_PRINTK) += console.o + EXTRA_AFLAGS := $(CFLAGS) diff --git a/arch/mips/cobalt/console.c b/arch/mips/cobalt/console.c new file mode 100644 index 000000000000..45c2d27c7564 --- /dev/null +++ b/arch/mips/cobalt/console.c @@ -0,0 +1,43 @@ +/* + * (C) P. Horton 2006 + */ + +#include +#include +#include +#include +#include +#include +#include + +static void putchar(int c) +{ + if(c == '\n') + putchar('\r'); + + while(!(COBALT_UART[UART_LSR] & UART_LSR_THRE)) + ; + + COBALT_UART[UART_TX] = c; +} + +static void cons_write(struct console *c, const char *s, unsigned n) +{ + while(n-- && *s) + putchar(*s++); +} + +static struct console cons_info = +{ + .name = "uart", + .write = cons_write, + .flags = CON_PRINTBUFFER | CON_BOOT, + .index = -1, +}; + +void __init cobalt_early_console(void) +{ + register_console(&cons_info); + + printk("Cobalt: early console registered\n"); +} diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c index b9713a723053..4f9ea1210023 100644 --- a/arch/mips/cobalt/setup.c +++ b/arch/mips/cobalt/setup.c @@ -31,6 +31,7 @@ extern void cobalt_machine_restart(char *command); extern void cobalt_machine_halt(void); extern void cobalt_machine_power_off(void); +extern void cobalt_early_console(void); int cobalt_board_id; @@ -109,14 +110,6 @@ void __init plat_setup(void) /* I/O port resource must include UART and LCD/buttons */ ioport_resource.end = 0x0fffffff; - /* - * This is a prom style console. We just poke at the - * UART to make it talk. - * Only use this console if you really screw up and can't - * get to the stage of setting up a real serial console. - */ - /*ns16550_setup_console();*/ - /* request I/O space for devices used on all i[345]86 PCs */ for (i = 0; i < COBALT_IO_RESOURCES; i++) request_resource(&ioport_resource, cobalt_io_resources + i); @@ -136,6 +129,10 @@ void __init plat_setup(void) #ifdef CONFIG_SERIAL_8250 if (cobalt_board_id > COBALT_BRD_ID_RAQ1) { +#ifdef CONFIG_EARLY_PRINTK + cobalt_early_console(); +#endif + uart.line = 0; uart.type = PORT_UNKNOWN; uart.uartclk = 18432000; diff --git a/include/asm-mips/mach-cobalt/cobalt.h b/include/asm-mips/mach-cobalt/cobalt.h index 78e1df2095fb..b3c5ecbec03c 100644 --- a/include/asm-mips/mach-cobalt/cobalt.h +++ b/include/asm-mips/mach-cobalt/cobalt.h @@ -113,4 +113,6 @@ do { \ # define COBALT_KEY_SELECT (1 << 7) # define COBALT_KEY_MASK 0xfe +#define COBALT_UART ((volatile unsigned char *) CKSEG1ADDR(0x1c800000)) + #endif /* __ASM_COBALT_H */ -- cgit v1.2.3 From bbad8123f3a40a7b262e8e52d0bc10da67d719bb Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 15 Feb 2006 13:06:34 +0000 Subject: [MIPS] MIPS64 R2 optimizations for 64-bit endianess swapping. Signed-off-by: Ralf Baechle --- include/asm-mips/byteorder.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'include') diff --git a/include/asm-mips/byteorder.h b/include/asm-mips/byteorder.h index 584f8128fffd..aefc02f16fd8 100644 --- a/include/asm-mips/byteorder.h +++ b/include/asm-mips/byteorder.h @@ -39,6 +39,24 @@ static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x) } #define __arch__swab32(x) ___arch__swab32(x) +#ifdef CONFIG_CPU_MIPS64_R2 + +static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 x) +{ + __asm__( + " dsbh %0, %1 \n" + " dshd %0, %0 \n" + " drotr %0, %0, 32 \n" + : "=r" (x) + : "r" (x)); + + return x; +} + +#define __arch__swab64(x) ___arch__swab64(x) + +#endif /* CONFIG_CPU_MIPS64_R2 */ + #endif /* CONFIG_CPU_MIPSR2 */ #if !defined(__STRICT_ANSI__) || defined(__KERNEL__) -- cgit v1.2.3 From 37caa934af02bc01d0e1366a49e1c89360fa0f29 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Wed, 15 Feb 2006 18:25:48 +0900 Subject: [MIPS] sc-rm7k.c cleanup Use blast_scache_range, blast_inv_scache_range for rm7k scache routine. Output code should be logically same. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/mm/sc-rm7k.c | 25 +++++++++---------------- include/asm-mips/r4kcache.h | 1 + 2 files changed, 10 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c index 9e8ff8badb19..3b6cc9ba1b05 100644 --- a/arch/mips/mm/sc-rm7k.c +++ b/arch/mips/mm/sc-rm7k.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -43,14 +44,7 @@ static void rm7k_sc_wback_inv(unsigned long addr, unsigned long size) /* Catch bad driver code */ BUG_ON(size == 0); - a = addr & ~(sc_lsize - 1); - end = (addr + size - 1) & ~(sc_lsize - 1); - while (1) { - flush_scache_line(a); /* Hit_Writeback_Inv_SD */ - if (a == end) - break; - a += sc_lsize; - } + blast_scache_range(addr, addr + size); if (!rm7k_tcache_enabled) return; @@ -74,14 +68,7 @@ static void rm7k_sc_inv(unsigned long addr, unsigned long size) /* Catch bad driver code */ BUG_ON(size == 0); - a = addr & ~(sc_lsize - 1); - end = (addr + size - 1) & ~(sc_lsize - 1); - while (1) { - invalidate_scache_line(a); /* Hit_Invalidate_SD */ - if (a == end) - break; - a += sc_lsize; - } + blast_inv_scache_range(addr, addr + size); if (!rm7k_tcache_enabled) return; @@ -143,11 +130,17 @@ struct bcache_ops rm7k_sc_ops = { void __init rm7k_sc_init(void) { + struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int config = read_c0_config(); if ((config & RM7K_CONF_SC)) return; + c->scache.linesz = sc_lsize; + c->scache.ways = 4; + c->scache.waybit= ffs(scache_size / c->scache.ways) - 1; + c->scache.waysize = scache_size / c->scache.ways; + c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways); printk(KERN_INFO "Secondary cache size %dK, linesize %d bytes.\n", (scache_size >> 10), sc_lsize); diff --git a/include/asm-mips/r4kcache.h b/include/asm-mips/r4kcache.h index 0bcb79a58ee9..90c374700977 100644 --- a/include/asm-mips/r4kcache.h +++ b/include/asm-mips/r4kcache.h @@ -303,5 +303,6 @@ __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, ) __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, ) /* blast_inv_dcache_range */ __BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, ) +__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, ) #endif /* _ASM_R4KCACHE_H */ -- cgit v1.2.3 From a8433137ea9143bb3a2bc18a3407b5a130fdb868 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Fri, 17 Feb 2006 01:36:24 +0900 Subject: [MIPS] Make I/O helpers more customizable 1. Move ioswab*() and __mem_ioswab*() to mangle-port.h. This gets rid of CONFIG_SGI_IP22 from include/asm-mips/io.h. 2. Pass a virtual address to *ioswab*(). Then we can provide mach-specific *ioswab*() and can do every evil thing based on its argument. It could be useful on machines which have regions with different endian conversion scheme. 3. Call __swizzle_addr*() _after_ adding mips_io_port_base. This unifies the meaning of the argument of __swizzle_addr*() (always virtual address). Then mach-specific __swizzle_addr*() can do every evil thing based on the argument. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- include/asm-mips/io.h | 69 +++++------------------------ include/asm-mips/mach-generic/mangle-port.h | 36 +++++++++++++++ include/asm-mips/mach-ip27/mangle-port.h | 9 ++++ include/asm-mips/mach-ip32/mangle-port.h | 9 ++++ 4 files changed, 66 insertions(+), 57 deletions(-) (limited to 'include') diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h index ba1d7bbc15d2..546a17e56a9b 100644 --- a/include/asm-mips/io.h +++ b/include/asm-mips/io.h @@ -40,56 +40,13 @@ * hardware. An example use would be for flash memory that's used for * execute in place. */ -# define __raw_ioswabb(x) (x) -# define __raw_ioswabw(x) (x) -# define __raw_ioswabl(x) (x) -# define __raw_ioswabq(x) (x) -# define ____raw_ioswabq(x) (x) +# define __raw_ioswabb(a,x) (x) +# define __raw_ioswabw(a,x) (x) +# define __raw_ioswabl(a,x) (x) +# define __raw_ioswabq(a,x) (x) +# define ____raw_ioswabq(a,x) (x) -/* - * Sane hardware offers swapping of PCI/ISA I/O space accesses in hardware; - * less sane hardware forces software to fiddle with this... - * - * Regardless, if the host bus endianness mismatches that of PCI/ISA, then - * you can't have the numerical value of data and byte addresses within - * multibyte quantities both preserved at the same time. Hence two - * variations of functions: non-prefixed ones that preserve the value - * and prefixed ones that preserve byte addresses. The latters are - * typically used for moving raw data between a peripheral and memory (cf. - * string I/O functions), hence the "__mem_" prefix. - */ -#if defined(CONFIG_SWAP_IO_SPACE) - -# define ioswabb(x) (x) -# define __mem_ioswabb(x) (x) -# ifdef CONFIG_SGI_IP22 -/* - * IP22 seems braindead enough to swap 16bits values in hardware, but - * not 32bits. Go figure... Can't tell without documentation. - */ -# define ioswabw(x) (x) -# define __mem_ioswabw(x) le16_to_cpu(x) -# else -# define ioswabw(x) le16_to_cpu(x) -# define __mem_ioswabw(x) (x) -# endif -# define ioswabl(x) le32_to_cpu(x) -# define __mem_ioswabl(x) (x) -# define ioswabq(x) le64_to_cpu(x) -# define __mem_ioswabq(x) (x) - -#else - -# define ioswabb(x) (x) -# define __mem_ioswabb(x) (x) -# define ioswabw(x) (x) -# define __mem_ioswabw(x) cpu_to_le16(x) -# define ioswabl(x) (x) -# define __mem_ioswabl(x) cpu_to_le32(x) -# define ioswabq(x) (x) -# define __mem_ioswabq(x) cpu_to_le32(x) - -#endif +/* ioswab[bwlq], __mem_ioswab[bwlq] are defined in mangle-port.h */ #define IO_SPACE_LIMIT 0xffff @@ -346,7 +303,7 @@ static inline void pfx##write##bwlq(type val, \ \ __mem = (void *)__swizzle_addr_##bwlq((unsigned long)(mem)); \ \ - __val = pfx##ioswab##bwlq(val); \ + __val = pfx##ioswab##bwlq(__mem, val); \ \ if (sizeof(type) != sizeof(u64) || sizeof(u64) == sizeof(long)) \ *__mem = __val; \ @@ -401,7 +358,7 @@ static inline type pfx##read##bwlq(const volatile void __iomem *mem) \ BUG(); \ } \ \ - return pfx##ioswab##bwlq(__val); \ + return pfx##ioswab##bwlq(__mem, __val); \ } #define __BUILD_IOPORT_SINGLE(pfx, bwlq, type, p, slow) \ @@ -411,10 +368,9 @@ static inline void pfx##out##bwlq##p(type val, unsigned long port) \ volatile type *__addr; \ type __val; \ \ - port = __swizzle_addr_##bwlq(port); \ - __addr = (void *)(mips_io_port_base + port); \ + __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \ \ - __val = pfx##ioswab##bwlq(val); \ + __val = pfx##ioswab##bwlq(__addr, val); \ \ /* Really, we want this to be atomic */ \ BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \ @@ -428,15 +384,14 @@ static inline type pfx##in##bwlq##p(unsigned long port) \ volatile type *__addr; \ type __val; \ \ - port = __swizzle_addr_##bwlq(port); \ - __addr = (void *)(mips_io_port_base + port); \ + __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \ \ BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \ \ __val = *__addr; \ slow; \ \ - return pfx##ioswab##bwlq(__val); \ + return pfx##ioswab##bwlq(__addr, __val); \ } #define __BUILD_MEMORY_PFX(bus, bwlq, type) \ diff --git a/include/asm-mips/mach-generic/mangle-port.h b/include/asm-mips/mach-generic/mangle-port.h index 4a98d83b8ec7..6e1b0c075de7 100644 --- a/include/asm-mips/mach-generic/mangle-port.h +++ b/include/asm-mips/mach-generic/mangle-port.h @@ -13,4 +13,40 @@ #define __swizzle_addr_l(port) (port) #define __swizzle_addr_q(port) (port) +/* + * Sane hardware offers swapping of PCI/ISA I/O space accesses in hardware; + * less sane hardware forces software to fiddle with this... + * + * Regardless, if the host bus endianness mismatches that of PCI/ISA, then + * you can't have the numerical value of data and byte addresses within + * multibyte quantities both preserved at the same time. Hence two + * variations of functions: non-prefixed ones that preserve the value + * and prefixed ones that preserve byte addresses. The latters are + * typically used for moving raw data between a peripheral and memory (cf. + * string I/O functions), hence the "__mem_" prefix. + */ +#if defined(CONFIG_SWAP_IO_SPACE) + +# define ioswabb(a,x) (x) +# define __mem_ioswabb(a,x) (x) +# define ioswabw(a,x) le16_to_cpu(x) +# define __mem_ioswabw(a,x) (x) +# define ioswabl(a,x) le32_to_cpu(x) +# define __mem_ioswabl(a,x) (x) +# define ioswabq(a,x) le64_to_cpu(x) +# define __mem_ioswabq(a,x) (x) + +#else + +# define ioswabb(a,x) (x) +# define __mem_ioswabb(a,x) (x) +# define ioswabw(a,x) (x) +# define __mem_ioswabw(a,x) cpu_to_le16(x) +# define ioswabl(a,x) (x) +# define __mem_ioswabl(a,x) cpu_to_le32(x) +# define ioswabq(a,x) (x) +# define __mem_ioswabq(a,x) cpu_to_le32(x) + +#endif + #endif /* __ASM_MACH_GENERIC_MANGLE_PORT_H */ diff --git a/include/asm-mips/mach-ip27/mangle-port.h b/include/asm-mips/mach-ip27/mangle-port.h index f76c44880451..d615312a451a 100644 --- a/include/asm-mips/mach-ip27/mangle-port.h +++ b/include/asm-mips/mach-ip27/mangle-port.h @@ -13,4 +13,13 @@ #define __swizzle_addr_l(port) (port) #define __swizzle_addr_q(port) (port) +# define ioswabb(a,x) (x) +# define __mem_ioswabb(a,x) (x) +# define ioswabw(a,x) (x) +# define __mem_ioswabw(a,x) cpu_to_le16(x) +# define ioswabl(a,x) (x) +# define __mem_ioswabl(a,x) cpu_to_le32(x) +# define ioswabq(a,x) (x) +# define __mem_ioswabq(a,x) cpu_to_le32(x) + #endif /* __ASM_MACH_IP27_MANGLE_PORT_H */ diff --git a/include/asm-mips/mach-ip32/mangle-port.h b/include/asm-mips/mach-ip32/mangle-port.h index 6e25b52ed8f2..81320eb55324 100644 --- a/include/asm-mips/mach-ip32/mangle-port.h +++ b/include/asm-mips/mach-ip32/mangle-port.h @@ -14,4 +14,13 @@ #define __swizzle_addr_l(port) (port) #define __swizzle_addr_q(port) (port) +# define ioswabb(a,x) (x) +# define __mem_ioswabb(a,x) (x) +# define ioswabw(a,x) (x) +# define __mem_ioswabw(a,x) cpu_to_le16(x) +# define ioswabl(a,x) (x) +# define __mem_ioswabl(a,x) cpu_to_le32(x) +# define ioswabq(a,x) (x) +# define __mem_ioswabq(a,x) cpu_to_le32(x) + #endif /* __ASM_MACH_IP32_MANGLE_PORT_H */ -- cgit v1.2.3 From 9c6031cc93626a194a9ef32d62b078ef1b396c45 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Sun, 19 Feb 2006 23:46:44 +0900 Subject: [MIPS] Signal cleanup Move function prototypes to asm/signal.h to detect trivial errors and add some __user tags to get rid of sparse warnings. Generated code should not be changed. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/kernel/process.c | 16 ---------------- arch/mips/kernel/signal.c | 6 +++--- arch/mips/kernel/signal32.c | 24 ++++++++++++------------ arch/mips/kernel/signal_n32.c | 2 +- include/asm-mips/signal.h | 20 +++++++++++++++++++- 5 files changed, 35 insertions(+), 33 deletions(-) (limited to 'include') diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 092679c2dca9..a8f435d82940 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -60,17 +60,9 @@ ATTRIB_NORET void cpu_idle(void) } } -extern void do_signal(struct pt_regs *regs); -extern void do_signal32(struct pt_regs *regs); - /* * Native o32 and N64 ABI without DSP ASE */ -extern int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, - int signr, sigset_t *set); -extern int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, - int signr, sigset_t *set, siginfo_t *info); - struct mips_abi mips_abi = { .do_signal = do_signal, #ifdef CONFIG_TRAD_SIGNALS @@ -83,11 +75,6 @@ struct mips_abi mips_abi = { /* * o32 compatibility on 64-bit kernels, without DSP ASE */ -extern int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, - int signr, sigset_t *set); -extern int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, - int signr, sigset_t *set, siginfo_t *info); - struct mips_abi mips_abi_32 = { .do_signal = do_signal32, .setup_frame = setup_frame_32, @@ -99,9 +86,6 @@ struct mips_abi mips_abi_32 = { /* * N32 on 64-bit kernels, without DSP ASE */ -extern int setup_rt_frame_n32(struct k_sigaction * ka, struct pt_regs *regs, - int signr, sigset_t *set, siginfo_t *info); - struct mips_abi mips_abi_n32 = { .do_signal = do_signal, .setup_rt_frame = setup_rt_frame_n32 diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index c974cc9b30eb..402efd27c79e 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -100,8 +100,8 @@ _sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) } #ifdef CONFIG_TRAD_SIGNALS -asmlinkage int sys_sigaction(int sig, const struct sigaction *act, - struct sigaction *oact) +asmlinkage int sys_sigaction(int sig, const struct sigaction __user *act, + struct sigaction __user *oact) { struct k_sigaction new_ka, old_ka; int ret; @@ -331,7 +331,7 @@ int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, /* Create the ucontext. */ err |= __put_user(0, &frame->rs_uc.uc_flags); err |= __put_user(NULL, &frame->rs_uc.uc_link); - err |= __put_user((void *)current->sas_ss_sp, + err |= __put_user((void __user *)current->sas_ss_sp, &frame->rs_uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->regs[29]), &frame->rs_uc.uc_stack.ss_flags); diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index f2791a1e7609..1c7241ba6924 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -163,7 +163,7 @@ static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t __user *ubuf) return err; } -static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t *ubuf) +static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t __user *ubuf) { int err = 0; unsigned long sig[4]; @@ -195,10 +195,10 @@ save_static_function(sys32_sigsuspend); __attribute_used__ noinline static int _sys32_sigsuspend(nabi_no_regargs struct pt_regs regs) { - compat_sigset_t *uset; + compat_sigset_t __user *uset; sigset_t newset; - uset = (compat_sigset_t *) regs.regs[4]; + uset = (compat_sigset_t __user *) regs.regs[4]; if (get_sigset(&newset, uset)) return -EFAULT; sigdelsetmask(&newset, ~_BLOCKABLE); @@ -219,7 +219,7 @@ save_static_function(sys32_rt_sigsuspend); __attribute_used__ noinline static int _sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) { - compat_sigset_t *uset; + compat_sigset_t __user *uset; sigset_t newset; size_t sigsetsize; @@ -228,7 +228,7 @@ _sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) if (sigsetsize != sizeof(compat_sigset_t)) return -EINVAL; - uset = (compat_sigset_t *) regs.regs[4]; + uset = (compat_sigset_t __user *) regs.regs[4]; if (get_sigset(&newset, uset)) return -EFAULT; sigdelsetmask(&newset, ~_BLOCKABLE); @@ -245,8 +245,8 @@ _sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) return -ERESTARTNOHAND; } -asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act, - struct sigaction32 *oact) +asmlinkage int sys32_sigaction(int sig, const struct sigaction32 __user *act, + struct sigaction32 __user *oact) { struct k_sigaction new_ka, old_ka; int ret; @@ -301,7 +301,7 @@ asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs) if (!access_ok(VERIFY_READ, uss, sizeof(*uss))) return -EFAULT; err |= __get_user(sp, &uss->ss_sp); - kss.ss_sp = (void *) (long) sp; + kss.ss_sp = (void __user *) (long) sp; err |= __get_user(kss.ss_size, &uss->ss_size); err |= __get_user(kss.ss_flags, &uss->ss_flags); if (err) @@ -316,7 +316,7 @@ asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs) if (!ret && uoss) { if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss))) return -EFAULT; - sp = (int) (long) koss.ss_sp; + sp = (int) (unsigned long) koss.ss_sp; err |= __put_user(sp, &uoss->ss_sp); err |= __put_user(koss.ss_size, &uoss->ss_size); err |= __put_user(koss.ss_flags, &uoss->ss_flags); @@ -527,7 +527,7 @@ _sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) /* The ucontext contains a stack32_t, so we must convert! */ if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) goto badframe; - st.ss_sp = (void *)(long) sp; + st.ss_sp = (void __user *)(long) sp; if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size)) goto badframe; if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags)) @@ -868,7 +868,7 @@ no_signal: } } -asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act, +asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, struct sigaction32 __user *oact, unsigned int sigsetsize) { @@ -912,7 +912,7 @@ out: return ret; } -asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set, +asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, compat_sigset_t __user *oset, unsigned int sigsetsize) { sigset_t old_set, new_set; diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c index 3e168c08a3a8..220e6deb3aa4 100644 --- a/arch/mips/kernel/signal_n32.c +++ b/arch/mips/kernel/signal_n32.c @@ -141,7 +141,7 @@ _sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) /* The ucontext contains a stack32_t, so we must convert! */ if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) goto badframe; - st.ss_sp = (void *)(long) sp; + st.ss_sp = (void __user *)(long) sp; if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size)) goto badframe; if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags)) diff --git a/include/asm-mips/signal.h b/include/asm-mips/signal.h index 6fe903e09c62..d8349e4b55ee 100644 --- a/include/asm-mips/signal.h +++ b/include/asm-mips/signal.h @@ -147,16 +147,34 @@ struct k_sigaction { /* IRIX compatible stack_t */ typedef struct sigaltstack { - void *ss_sp; + void __user *ss_sp; size_t ss_size; int ss_flags; } stack_t; #ifdef __KERNEL__ #include +#include #define ptrace_signal_deliver(regs, cookie) do { } while (0) +struct pt_regs; +extern void do_signal(struct pt_regs *regs); +extern void do_signal32(struct pt_regs *regs); + +extern int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, + int signr, sigset_t *set); +extern int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, + int signr, sigset_t *set, siginfo_t *info); + +extern int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, + int signr, sigset_t *set); +extern int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, + int signr, sigset_t *set, siginfo_t *info); + +extern int setup_rt_frame_n32(struct k_sigaction * ka, struct pt_regs *regs, + int signr, sigset_t *set, siginfo_t *info); + #endif /* __KERNEL__ */ #endif /* _ASM_SIGNAL_H */ -- cgit v1.2.3 From 219ac73a7ad17a3ae3d5c07b4fc8c280645a073a Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 21 Feb 2006 16:05:11 +0900 Subject: [MIPS] Further sparsification for 32-bit compat code. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/kernel/linux32.c | 170 +++++++++++++++++++++++---------------------- arch/mips/kernel/syscall.c | 2 +- include/asm-mips/compat.h | 8 +-- 3 files changed, 92 insertions(+), 88 deletions(-) (limited to 'include') diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 396592467da8..1e8d24823d39 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -69,7 +69,7 @@ * Revalidate the inode. This is required for proper NFS attribute caching. */ -int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf) +int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf) { struct compat_stat tmp; @@ -125,7 +125,7 @@ out: } -asmlinkage int sys_truncate64(const char *path, unsigned int high, +asmlinkage int sys_truncate64(const char __user *path, unsigned int high, unsigned int low) { if ((int)high < 0) @@ -169,6 +169,7 @@ sysn32_waitid(int which, compat_pid_t pid, struct rusage ru; long ret; mm_segment_t old_fs = get_fs(); + int si_signo; if (!access_ok(VERIFY_WRITE, uinfo, sizeof(*uinfo))) return -EFAULT; @@ -178,7 +179,9 @@ sysn32_waitid(int which, compat_pid_t pid, uru ? (struct rusage __user *) &ru : NULL); set_fs (old_fs); - if (ret < 0 || uinfo->si_signo == 0) + if (__get_user(si_signo, &uinfo->si_signo)) + return -EFAULT; + if (ret < 0 || si_signo == 0) return ret; if (uru) @@ -202,14 +205,14 @@ struct sysinfo32 { char _f[8]; }; -asmlinkage int sys32_sysinfo(struct sysinfo32 *info) +asmlinkage int sys32_sysinfo(struct sysinfo32 __user *info) { struct sysinfo s; int ret, err; mm_segment_t old_fs = get_fs (); set_fs (KERNEL_DS); - ret = sys_sysinfo(&s); + ret = sys_sysinfo((struct sysinfo __user *)&s); set_fs (old_fs); err = put_user (s.uptime, &info->uptime); err |= __put_user (s.loads[0], &info->loads[0]); @@ -239,11 +242,11 @@ struct rlimit32 { }; #ifdef __MIPSEB__ -asmlinkage long sys32_truncate64(const char * path, unsigned long __dummy, +asmlinkage long sys32_truncate64(const char __user * path, unsigned long __dummy, int length_hi, int length_lo) #endif #ifdef __MIPSEL__ -asmlinkage long sys32_truncate64(const char * path, unsigned long __dummy, +asmlinkage long sys32_truncate64(const char __user * path, unsigned long __dummy, int length_lo, int length_hi) #endif { @@ -271,7 +274,7 @@ asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy, } static inline long -get_tv32(struct timeval *o, struct compat_timeval *i) +get_tv32(struct timeval *o, struct compat_timeval __user *i) { return (!access_ok(VERIFY_READ, i, sizeof(*i)) || (__get_user(o->tv_sec, &i->tv_sec) | @@ -279,7 +282,7 @@ get_tv32(struct timeval *o, struct compat_timeval *i) } static inline long -put_tv32(struct compat_timeval *o, struct timeval *i) +put_tv32(struct compat_timeval __user *o, struct timeval *i) { return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || (__put_user(i->tv_sec, &o->tv_sec) | @@ -289,7 +292,7 @@ put_tv32(struct compat_timeval *o, struct timeval *i) extern struct timezone sys_tz; asmlinkage int -sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz) +sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) { if (tv) { struct timeval ktv; @@ -304,7 +307,7 @@ sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz) return 0; } -static inline long get_ts32(struct timespec *o, struct compat_timeval *i) +static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i) { long usec; @@ -319,7 +322,7 @@ static inline long get_ts32(struct timespec *o, struct compat_timeval *i) } asmlinkage int -sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz) +sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) { struct timespec kts; struct timezone ktz; @@ -337,7 +340,7 @@ sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz) } asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high, - unsigned int offset_low, loff_t * result, + unsigned int offset_low, loff_t __user * result, unsigned int origin) { return sys_llseek(fd, offset_high, offset_low, result, origin); @@ -347,12 +350,12 @@ asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high, lseek back to original location. They fail just like lseek does on non-seekable files. */ -asmlinkage ssize_t sys32_pread(unsigned int fd, char * buf, +asmlinkage ssize_t sys32_pread(unsigned int fd, char __user * buf, size_t count, u32 unused, u64 a4, u64 a5) { ssize_t ret; struct file * file; - ssize_t (*read)(struct file *, char *, size_t, loff_t *); + ssize_t (*read)(struct file *, char __user *, size_t, loff_t *); loff_t pos; ret = -EBADF; @@ -382,12 +385,12 @@ bad_file: return ret; } -asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char * buf, +asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char __user * buf, size_t count, u32 unused, u64 a4, u64 a5) { ssize_t ret; struct file * file; - ssize_t (*write)(struct file *, const char *, size_t, loff_t *); + ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *); loff_t pos; ret = -EBADF; @@ -420,14 +423,14 @@ bad_file: } asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid, - struct compat_timespec *interval) + struct compat_timespec __user *interval) { struct timespec t; int ret; mm_segment_t old_fs = get_fs (); set_fs (KERNEL_DS); - ret = sys_sched_rr_get_interval(pid, &t); + ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t); set_fs (old_fs); if (put_user (t.tv_sec, &interval->tv_sec) || __put_user (t.tv_nsec, &interval->tv_nsec)) @@ -545,7 +548,7 @@ struct ipc_kludge32 { }; static int -do_sys32_semctl(int first, int second, int third, void *uptr) +do_sys32_semctl(int first, int second, int third, void __user *uptr) { union semun fourth; u32 pad; @@ -556,12 +559,12 @@ do_sys32_semctl(int first, int second, int third, void *uptr) if (!uptr) return -EINVAL; err = -EFAULT; - if (get_user (pad, (u32 *)uptr)) + if (get_user (pad, (u32 __user *)uptr)) return err; if ((third & ~IPC_64) == SETVAL) fourth.val = (int)pad; else - fourth.__pad = (void *)A(pad); + fourth.__pad = (void __user *)A(pad); switch (third & ~IPC_64) { case IPC_INFO: case IPC_RMID: @@ -579,14 +582,14 @@ do_sys32_semctl(int first, int second, int third, void *uptr) case IPC_STAT: case SEM_STAT: - fourth.__pad = &s; + fourth.__pad = (struct semid64_ds __user *)&s; old_fs = get_fs(); set_fs(KERNEL_DS); err = sys_semctl(first, second, third | IPC_64, fourth); set_fs(old_fs); if (third & IPC_64) { - struct semid64_ds32 *usp64 = (struct semid64_ds32 *) A(pad); + struct semid64_ds32 __user *usp64 = (struct semid64_ds32 __user *) A(pad); if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) { err = -EFAULT; @@ -603,7 +606,7 @@ do_sys32_semctl(int first, int second, int third, void *uptr) err2 |= __put_user(s.sem_ctime, &usp64->sem_ctime); err2 |= __put_user(s.sem_nsems, &usp64->sem_nsems); } else { - struct semid_ds32 *usp32 = (struct semid_ds32 *) A(pad); + struct semid_ds32 __user *usp32 = (struct semid_ds32 __user *) A(pad); if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) { err = -EFAULT; @@ -633,9 +636,9 @@ do_sys32_semctl(int first, int second, int third, void *uptr) } static int -do_sys32_msgsnd (int first, int second, int third, void *uptr) +do_sys32_msgsnd (int first, int second, int third, void __user *uptr) { - struct msgbuf32 *up = (struct msgbuf32 *)uptr; + struct msgbuf32 __user *up = (struct msgbuf32 __user *)uptr; struct msgbuf *p; mm_segment_t old_fs; int err; @@ -654,7 +657,7 @@ do_sys32_msgsnd (int first, int second, int third, void *uptr) goto out; old_fs = get_fs (); set_fs (KERNEL_DS); - err = sys_msgsnd (first, p, second, third); + err = sys_msgsnd (first, (struct msgbuf __user *)p, second, third); set_fs (old_fs); out: kfree (p); @@ -664,15 +667,15 @@ out: static int do_sys32_msgrcv (int first, int second, int msgtyp, int third, - int version, void *uptr) + int version, void __user *uptr) { - struct msgbuf32 *up; + struct msgbuf32 __user *up; struct msgbuf *p; mm_segment_t old_fs; int err; if (!version) { - struct ipc_kludge32 *uipck = (struct ipc_kludge32 *)uptr; + struct ipc_kludge32 __user *uipck = (struct ipc_kludge32 __user *)uptr; struct ipc_kludge32 ipck; err = -EINVAL; @@ -681,7 +684,7 @@ do_sys32_msgrcv (int first, int second, int msgtyp, int third, err = -EFAULT; if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge32))) goto out; - uptr = (void *)AA(ipck.msgp); + uptr = (void __user *)AA(ipck.msgp); msgtyp = ipck.msgtyp; } @@ -693,11 +696,11 @@ do_sys32_msgrcv (int first, int second, int msgtyp, int third, goto out; old_fs = get_fs (); set_fs (KERNEL_DS); - err = sys_msgrcv (first, p, second + 4, msgtyp, third); + err = sys_msgrcv (first, (struct msgbuf __user *)p, second + 4, msgtyp, third); set_fs (old_fs); if (err < 0) goto free_then_out; - up = (struct msgbuf32 *)uptr; + up = (struct msgbuf32 __user *)uptr; if (put_user (p->mtype, &up->mtype) || __copy_to_user (&up->mtext, p->mtext, err)) err = -EFAULT; @@ -708,19 +711,19 @@ out: } static int -do_sys32_msgctl (int first, int second, void *uptr) +do_sys32_msgctl (int first, int second, void __user *uptr) { int err = -EINVAL, err2; struct msqid64_ds m; - struct msqid_ds32 *up32 = (struct msqid_ds32 *)uptr; - struct msqid64_ds32 *up64 = (struct msqid64_ds32 *)uptr; + struct msqid_ds32 __user *up32 = (struct msqid_ds32 __user *)uptr; + struct msqid64_ds32 __user *up64 = (struct msqid64_ds32 __user *)uptr; mm_segment_t old_fs; switch (second & ~IPC_64) { case IPC_INFO: case IPC_RMID: case MSG_INFO: - err = sys_msgctl (first, second, (struct msqid_ds *)uptr); + err = sys_msgctl (first, second, (struct msqid_ds __user *)uptr); break; case IPC_SET: @@ -747,7 +750,7 @@ do_sys32_msgctl (int first, int second, void *uptr) break; old_fs = get_fs(); set_fs(KERNEL_DS); - err = sys_msgctl(first, second | IPC_64, (struct msqid_ds *)&m); + err = sys_msgctl(first, second | IPC_64, (struct msqid_ds __user *)&m); set_fs(old_fs); break; @@ -755,7 +758,7 @@ do_sys32_msgctl (int first, int second, void *uptr) case MSG_STAT: old_fs = get_fs(); set_fs(KERNEL_DS); - err = sys_msgctl(first, second | IPC_64, (struct msqid_ds *)&m); + err = sys_msgctl(first, second | IPC_64, (struct msqid_ds __user *)&m); set_fs(old_fs); if (second & IPC_64) { if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) { @@ -809,10 +812,10 @@ do_sys32_msgctl (int first, int second, void *uptr) } static int -do_sys32_shmat (int first, int second, int third, int version, void *uptr) +do_sys32_shmat (int first, int second, int third, int version, void __user *uptr) { unsigned long raddr; - u32 *uaddr = (u32 *)A((u32)third); + u32 __user *uaddr = (u32 __user *)A((u32)third); int err = -EINVAL; if (version == 1) @@ -831,11 +834,11 @@ struct shm_info32 { }; static int -do_sys32_shmctl (int first, int second, void *uptr) +do_sys32_shmctl (int first, int second, void __user *uptr) { - struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr; - struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr; - struct shm_info32 *uip = (struct shm_info32 *)uptr; + struct shmid64_ds32 __user *up64 = (struct shmid64_ds32 __user *)uptr; + struct shmid_ds32 __user *up32 = (struct shmid_ds32 __user *)uptr; + struct shm_info32 __user *uip = (struct shm_info32 __user *)uptr; int err = -EFAULT, err2; struct shmid64_ds s64; mm_segment_t old_fs; @@ -848,7 +851,7 @@ do_sys32_shmctl (int first, int second, void *uptr) case IPC_RMID: case SHM_LOCK: case SHM_UNLOCK: - err = sys_shmctl(first, second, (struct shmid_ds *)uptr); + err = sys_shmctl(first, second, (struct shmid_ds __user *)uptr); break; case IPC_SET: if (second & IPC_64) { @@ -864,7 +867,7 @@ do_sys32_shmctl (int first, int second, void *uptr) break; old_fs = get_fs(); set_fs(KERNEL_DS); - err = sys_shmctl(first, second & ~IPC_64, &s); + err = sys_shmctl(first, second & ~IPC_64, (struct shmid_ds __user *)&s); set_fs(old_fs); break; @@ -872,7 +875,7 @@ do_sys32_shmctl (int first, int second, void *uptr) case SHM_STAT: old_fs = get_fs(); set_fs(KERNEL_DS); - err = sys_shmctl(first, second | IPC_64, (void *) &s64); + err = sys_shmctl(first, second | IPC_64, (void __user *) &s64); set_fs(old_fs); if (err < 0) break; @@ -922,7 +925,7 @@ do_sys32_shmctl (int first, int second, void *uptr) case SHM_INFO: old_fs = get_fs(); set_fs(KERNEL_DS); - err = sys_shmctl(first, second, (void *)&si); + err = sys_shmctl(first, second, (void __user *)&si); set_fs(old_fs); if (err < 0) break; @@ -944,11 +947,11 @@ do_sys32_shmctl (int first, int second, void *uptr) return err; } -static int sys32_semtimedop(int semid, struct sembuf *tsems, int nsems, - const struct compat_timespec *timeout32) +static int sys32_semtimedop(int semid, struct sembuf __user *tsems, int nsems, + const struct compat_timespec __user *timeout32) { struct compat_timespec t32; - struct timespec *t64 = compat_alloc_user_space(sizeof(*t64)); + struct timespec __user *t64 = compat_alloc_user_space(sizeof(*t64)); if (copy_from_user(&t32, timeout32, sizeof(t32))) return -EFAULT; @@ -971,11 +974,11 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) switch (call) { case SEMOP: /* struct sembuf is the same on 32 and 64bit :)) */ - err = sys_semtimedop (first, (struct sembuf *)AA(ptr), second, + err = sys_semtimedop (first, (struct sembuf __user *)AA(ptr), second, NULL); break; case SEMTIMEDOP: - err = sys32_semtimedop (first, (struct sembuf *)AA(ptr), second, + err = sys32_semtimedop (first, (struct sembuf __user *)AA(ptr), second, (const struct compat_timespec __user *)AA(fifth)); break; case SEMGET: @@ -983,36 +986,36 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) break; case SEMCTL: err = do_sys32_semctl (first, second, third, - (void *)AA(ptr)); + (void __user *)AA(ptr)); break; case MSGSND: err = do_sys32_msgsnd (first, second, third, - (void *)AA(ptr)); + (void __user *)AA(ptr)); break; case MSGRCV: err = do_sys32_msgrcv (first, second, fifth, third, - version, (void *)AA(ptr)); + version, (void __user *)AA(ptr)); break; case MSGGET: err = sys_msgget ((key_t) first, second); break; case MSGCTL: - err = do_sys32_msgctl (first, second, (void *)AA(ptr)); + err = do_sys32_msgctl (first, second, (void __user *)AA(ptr)); break; case SHMAT: err = do_sys32_shmat (first, second, third, - version, (void *)AA(ptr)); + version, (void __user *)AA(ptr)); break; case SHMDT: - err = sys_shmdt ((char *)A(ptr)); + err = sys_shmdt ((char __user *)A(ptr)); break; case SHMGET: err = sys_shmget (first, (unsigned)second, third); break; case SHMCTL: - err = do_sys32_shmctl (first, second, (void *)AA(ptr)); + err = do_sys32_shmctl (first, second, (void __user *)AA(ptr)); break; default: err = -EINVAL; @@ -1023,7 +1026,7 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) } asmlinkage long sys32_shmat(int shmid, char __user *shmaddr, - int shmflg, int32_t *addr) + int shmflg, int32_t __user *addr) { unsigned long raddr; int err; @@ -1048,12 +1051,13 @@ struct sysctl_args32 #ifdef CONFIG_SYSCTL -asmlinkage long sys32_sysctl(struct sysctl_args32 *args) +asmlinkage long sys32_sysctl(struct sysctl_args32 __user *args) { struct sysctl_args32 tmp; int error; - size_t oldlen, *oldlenp = NULL; - unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7; + size_t oldlen; + size_t __user *oldlenp = NULL; + unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7; if (copy_from_user(&tmp, args, sizeof(tmp))) return -EFAULT; @@ -1065,20 +1069,20 @@ asmlinkage long sys32_sysctl(struct sysctl_args32 *args) basically copy the whole sysctl.c here, and glibc's __sysctl uses rw memory for the structure anyway. */ - if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) || - put_user(oldlen, (size_t *)addr)) + if (get_user(oldlen, (u32 __user *)A(tmp.oldlenp)) || + put_user(oldlen, (size_t __user *)addr)) return -EFAULT; - oldlenp = (size_t *)addr; + oldlenp = (size_t __user *)addr; } lock_kernel(); - error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval), - oldlenp, (void *)A(tmp.newval), tmp.newlen); + error = do_sysctl((int __user *)A(tmp.name), tmp.nlen, (void __user *)A(tmp.oldval), + oldlenp, (void __user *)A(tmp.newval), tmp.newlen); unlock_kernel(); if (oldlenp) { if (!error) { - if (get_user(oldlen, (size_t *)addr) || - put_user(oldlen, (u32 *)A(tmp.oldlenp))) + if (get_user(oldlen, (size_t __user *)addr) || + put_user(oldlen, (u32 __user *)A(tmp.oldlenp))) error = -EFAULT; } copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)); @@ -1088,7 +1092,7 @@ asmlinkage long sys32_sysctl(struct sysctl_args32 *args) #endif /* CONFIG_SYSCTL */ -asmlinkage long sys32_newuname(struct new_utsname * name) +asmlinkage long sys32_newuname(struct new_utsname __user * name) { int ret = 0; @@ -1123,9 +1127,9 @@ struct ustat32 { char f_fpack[6]; }; -extern asmlinkage long sys_ustat(dev_t dev, struct ustat * ubuf); +extern asmlinkage long sys_ustat(dev_t dev, struct ustat __user * ubuf); -asmlinkage int sys32_ustat(dev_t dev, struct ustat32 * ubuf32) +asmlinkage int sys32_ustat(dev_t dev, struct ustat32 __user * ubuf32) { int err; struct ustat tmp; @@ -1133,7 +1137,7 @@ asmlinkage int sys32_ustat(dev_t dev, struct ustat32 * ubuf32) mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); - err = sys_ustat(dev, &tmp); + err = sys_ustat(dev, (struct ustat __user *)&tmp); set_fs (old_fs); if (err) @@ -1166,7 +1170,7 @@ struct timex32 { extern int do_adjtimex(struct timex *); -asmlinkage int sys32_adjtimex(struct timex32 *utp) +asmlinkage int sys32_adjtimex(struct timex32 __user *utp) { struct timex txc; int ret; @@ -1222,7 +1226,7 @@ asmlinkage int sys32_adjtimex(struct timex32 *utp) return ret; } -asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, +asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, s32 count) { mm_segment_t old_fs = get_fs(); @@ -1233,7 +1237,7 @@ asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, return -EFAULT; set_fs(KERNEL_DS); - ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count); + ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count); set_fs(old_fs); if (offset && put_user(of, offset)) @@ -1263,7 +1267,7 @@ static unsigned char socketcall_nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), * it is set by the callees. */ -asmlinkage long sys32_socketcall(int call, unsigned int *args32) +asmlinkage long sys32_socketcall(int call, unsigned int __user *args32) { unsigned int a[6]; unsigned int a0,a1; @@ -1285,7 +1289,7 @@ asmlinkage long sys32_socketcall(int call, unsigned int *args32) struct sockaddr __user *addr, int __user *addr_len); extern asmlinkage long sys_shutdown(int fd, int how); extern asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen); - extern asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int *optlen); + extern asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen); extern asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags); extern asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flags); @@ -1405,7 +1409,7 @@ _sys32_clone(nabi_no_regargs struct pt_regs regs) newsp = regs.regs[5]; if (!newsp) newsp = regs.regs[29]; - parent_tidptr = (int *) regs.regs[6]; + parent_tidptr = (int __user *) regs.regs[6]; /* Use __dummy4 instead of getting it off the stack, so that syscall() works. */ diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 1da2eeb3ef9e..55f2bc09529c 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -345,7 +345,7 @@ asmlinkage int sys_ipc (uint call, int first, int second, union semun fourth; if (!ptr) return -EINVAL; - if (get_user(fourth.__pad, (void *__user *) ptr)) + if (get_user(fourth.__pad, (void __user *__user *) ptr)) return -EFAULT; return sys_semctl (first, second, third, fourth); } diff --git a/include/asm-mips/compat.h b/include/asm-mips/compat.h index 35d2604fe69c..0012bd804d2d 100644 --- a/include/asm-mips/compat.h +++ b/include/asm-mips/compat.h @@ -128,17 +128,17 @@ typedef u32 compat_sigset_word; */ typedef u32 compat_uptr_t; -static inline void *compat_ptr(compat_uptr_t uptr) +static inline void __user *compat_ptr(compat_uptr_t uptr) { - return (void *)(long)uptr; + return (void __user *)(long)uptr; } -static inline void *compat_alloc_user_space(long len) +static inline void __user *compat_alloc_user_space(long len) { struct pt_regs *regs = (struct pt_regs *) ((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1; - return (void *) (regs->regs[29] - len); + return (void __user *) (regs->regs[29] - len); } #if defined (__MIPSEL__) #define __COMPAT_ENDIAN_SWAP__ 1 -- cgit v1.2.3 From 8145095cd8fd466980ea6401f26a52e462275222 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 22 Feb 2006 23:06:55 +0000 Subject: [MIPS] Remove CONFIG_BUILD_ELF64. This option is no longer usable with supported compilers. It will be replaced by usage of -msym32 in a separate patch. Signed-off-by: Ralf Baechle --- arch/mips/Makefile | 27 +++++++++------------------ arch/mips/configs/bigsur_defconfig | 1 - arch/mips/configs/ip27_defconfig | 1 - arch/mips/configs/ip32_defconfig | 1 - arch/mips/configs/ocelot_c_defconfig | 1 - arch/mips/configs/ocelot_g_defconfig | 1 - arch/mips/configs/sb1250-swarm_defconfig | 1 - arch/mips/kernel/setup.c | 11 ----------- arch/mips/mm/tlbex.c | 13 ------------- include/asm-mips/mmu_context.h | 7 +------ include/asm-mips/sn/mapped_kernel.h | 4 ---- include/asm-mips/stackframe.h | 20 +++----------------- 12 files changed, 13 insertions(+), 75 deletions(-) (limited to 'include') diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 3d8dac681c63..c626dd5942f6 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -70,18 +70,20 @@ CHECKFLAGS-$(CONFIG_CPU_LITTLE_ENDIAN) += -D__MIPSEL__ CHECKFLAGS = $(CHECKFLAGS-y) -ifdef CONFIG_BUILD_ELF64 -gas-abi = 64 -ld-emul = $(64bit-emul) -vmlinux-32 = vmlinux.32 -vmlinux-64 = vmlinux -else +ifdef CONFIG_32BIT gas-abi = 32 ld-emul = $(32bit-emul) vmlinux-32 = vmlinux vmlinux-64 = vmlinux.64 +endif -cflags-$(CONFIG_64BIT) += $(call cc-option,-mno-explicit-relocs) +ifdef CONFIG_64BIT +gas-abi = 64 +ld-emul = $(64bit-emul) +vmlinux-32 = vmlinux.32 +vmlinux-64 = vmlinux + +cflags-y += $(call cc-option,-mno-explicit-relocs) endif # @@ -630,7 +632,6 @@ endif ifdef CONFIG_SGI_IP27 core-$(CONFIG_SGI_IP27) += arch/mips/sgi-ip27/ cflags-$(CONFIG_SGI_IP27) += -Iinclude/asm-mips/mach-ip27 -ifdef CONFIG_BUILD_ELF64 ifdef CONFIG_MAPPED_KERNEL load-$(CONFIG_SGI_IP27) += 0xc00000004001c000 OBJCOPYFLAGS := --change-addresses=0x3fffffff80000000 @@ -639,16 +640,6 @@ else load-$(CONFIG_SGI_IP27) += 0xa80000000001c000 OBJCOPYFLAGS := --change-addresses=0x57ffffff80000000 endif -else -ifdef CONFIG_MAPPED_KERNEL -load-$(CONFIG_SGI_IP27) += 0xffffffffc001c000 -OBJCOPYFLAGS := --change-addresses=0xc000000080000000 -dataoffset-$(CONFIG_SGI_IP27) += 0x01000000 -else -load-$(CONFIG_SGI_IP27) += 0xffffffff8001c000 -OBJCOPYFLAGS := --change-addresses=0xa800000080000000 -endif -endif endif # diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig index 6fd353779813..e39f1da62976 100644 --- a/arch/mips/configs/bigsur_defconfig +++ b/arch/mips/configs/bigsur_defconfig @@ -247,7 +247,6 @@ CONFIG_MMU=y # CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set -CONFIG_BUILD_ELF64=y CONFIG_MIPS32_COMPAT=y CONFIG_COMPAT=y CONFIG_MIPS32_O32=y diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig index 58c22cd344d3..009ec9d97738 100644 --- a/arch/mips/configs/ip27_defconfig +++ b/arch/mips/configs/ip27_defconfig @@ -234,7 +234,6 @@ CONFIG_MMU=y # CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set -CONFIG_BUILD_ELF64=y CONFIG_MIPS32_COMPAT=y CONFIG_COMPAT=y CONFIG_MIPS32_O32=y diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig index a34db6e82b27..54afa2556f5f 100644 --- a/arch/mips/configs/ip32_defconfig +++ b/arch/mips/configs/ip32_defconfig @@ -224,7 +224,6 @@ CONFIG_MMU=y # CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=y -# CONFIG_BUILD_ELF64 is not set CONFIG_MIPS32_COMPAT=y CONFIG_COMPAT=y CONFIG_MIPS32_O32=y diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig index e8d6bb3551a2..a8fc4c6c10c9 100644 --- a/arch/mips/configs/ocelot_c_defconfig +++ b/arch/mips/configs/ocelot_c_defconfig @@ -220,7 +220,6 @@ CONFIG_MMU=y # CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set -# CONFIG_BUILD_ELF64 is not set CONFIG_MIPS32_COMPAT=y CONFIG_COMPAT=y CONFIG_MIPS32_O32=y diff --git a/arch/mips/configs/ocelot_g_defconfig b/arch/mips/configs/ocelot_g_defconfig index b6126ad4d06d..dab6c896fbb7 100644 --- a/arch/mips/configs/ocelot_g_defconfig +++ b/arch/mips/configs/ocelot_g_defconfig @@ -223,7 +223,6 @@ CONFIG_MMU=y # CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set -# CONFIG_BUILD_ELF64 is not set CONFIG_MIPS32_COMPAT=y CONFIG_COMPAT=y CONFIG_MIPS32_O32=y diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig index 52048c906079..6481fb2426f6 100644 --- a/arch/mips/configs/sb1250-swarm_defconfig +++ b/arch/mips/configs/sb1250-swarm_defconfig @@ -247,7 +247,6 @@ CONFIG_MMU=y # CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set -# CONFIG_BUILD_ELF64 is not set CONFIG_MIPS32_COMPAT=y CONFIG_COMPAT=y CONFIG_MIPS32_O32=y diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index d9293c558e41..0cb3b6097e0e 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -447,21 +447,10 @@ static inline void resource_init(void) { int i; -#if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64) - /* - * The 64bit code in 32bit object format trick can't represent - * 64bit wide relocations for linker script symbols. - */ - code_resource.start = CPHYSADDR(&_text); - code_resource.end = CPHYSADDR(&_etext) - 1; - data_resource.start = CPHYSADDR(&_etext); - data_resource.end = CPHYSADDR(&_edata) - 1; -#else code_resource.start = virt_to_phys(&_text); code_resource.end = virt_to_phys(&_etext) - 1; data_resource.start = virt_to_phys(&_etext); data_resource.end = virt_to_phys(&_edata) - 1; -#endif /* * Request address space for all standard RAM. diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index ac4f4bfaae50..599b3c297186 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -951,7 +951,6 @@ build_get_pmde64(u32 **p, struct label **l, struct reloc **r, /* No i_nop needed here, since the next insn doesn't touch TMP. */ #ifdef CONFIG_SMP -# ifdef CONFIG_BUILD_ELF64 /* * 64 bit SMP running in XKPHYS has smp_processor_id() << 3 * stored in CONTEXT. @@ -962,18 +961,6 @@ build_get_pmde64(u32 **p, struct label **l, struct reloc **r, i_daddu(p, ptr, ptr, tmp); i_dmfc0(p, tmp, C0_BADVADDR); i_ld(p, ptr, rel_lo(pgdc), ptr); -# else - /* - * 64 bit SMP running in compat space has the lower part of - * &pgd_current[smp_processor_id()] stored in CONTEXT. - */ - if (!in_compat_space_p(pgdc)) - panic("Invalid page directory address!"); - - i_dmfc0(p, ptr, C0_CONTEXT); - i_dsra(p, ptr, ptr, 23); - i_ld(p, ptr, 0, ptr); -# endif #else i_LA_mostly(p, ptr, pgdc); i_ld(p, ptr, rel_lo(pgdc), ptr); diff --git a/include/asm-mips/mmu_context.h b/include/asm-mips/mmu_context.h index 19cdf7642e66..61cf22588137 100644 --- a/include/asm-mips/mmu_context.h +++ b/include/asm-mips/mmu_context.h @@ -33,12 +33,7 @@ extern unsigned long pgd_current[]; write_c0_context((unsigned long) smp_processor_id() << 25); \ TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir) #endif -#if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64) -#define TLBMISS_HANDLER_SETUP() \ - write_c0_context((unsigned long) &pgd_current[smp_processor_id()] << 23); \ - TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir) -#endif -#if defined(CONFIG_64BIT) && defined(CONFIG_BUILD_ELF64) +#ifdef CONFIG_64BIT #define TLBMISS_HANDLER_SETUP() \ write_c0_context((unsigned long) smp_processor_id() << 26); \ TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir) diff --git a/include/asm-mips/sn/mapped_kernel.h b/include/asm-mips/sn/mapped_kernel.h index 3a17846df849..59edb20f8ec5 100644 --- a/include/asm-mips/sn/mapped_kernel.h +++ b/include/asm-mips/sn/mapped_kernel.h @@ -23,11 +23,7 @@ #include #include -#ifdef CONFIG_BUILD_ELF64 #define REP_BASE CAC_BASE -#else -#define REP_BASE CKSEG0 -#endif #ifdef CONFIG_MAPPED_KERNEL diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h index a8919dcc93c8..2acf3e844f00 100644 --- a/include/asm-mips/stackframe.h +++ b/include/asm-mips/stackframe.h @@ -63,17 +63,7 @@ addu k1, k0 LONG_L k1, %lo(kernelsp)(k1) #endif -#if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64) - MFC0 k1, CP0_CONTEXT - dsra k1, 23 - lui k0, %hi(pgd_current) - addiu k0, %lo(pgd_current) - dsubu k1, k0 - lui k0, %hi(kernelsp) - daddu k1, k0 - LONG_L k1, %lo(kernelsp)(k1) -#endif -#if defined(CONFIG_64BIT) && defined(CONFIG_BUILD_ELF64) +#ifdef CONFIG_64BIT MFC0 k1, CP0_CONTEXT lui k0, %highest(kernelsp) dsrl k1, 23 @@ -91,11 +81,7 @@ mfc0 \temp, CP0_CONTEXT srl \temp, 23 #endif -#if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64) - lw \temp, TI_CPU(gp) - dsll \temp, 3 -#endif -#if defined(CONFIG_64BIT) && defined(CONFIG_BUILD_ELF64) +#ifdef CONFIG_64BIT MFC0 \temp, CP0_CONTEXT dsrl \temp, 23 #endif @@ -103,7 +89,7 @@ .endm #else .macro get_saved_sp /* Uniprocessor variation */ -#if defined(CONFIG_64BIT) && defined(CONFIG_BUILD_ELF64) +#ifdef CONFIG_64BIT lui k1, %highest(kernelsp) daddiu k1, %higher(kernelsp) dsll k1, k1, 16 -- cgit v1.2.3 From 0cea043b56443aef8a77539cdd79451f5d55009d Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 3 Mar 2006 09:42:05 +0000 Subject: [MIPS] Reformat __xchg(). Signed-off-by: Ralf Baechle --- include/asm-mips/system.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h index ddae9bae31af..4097fac5ac3c 100644 --- a/include/asm-mips/system.h +++ b/include/asm-mips/system.h @@ -286,10 +286,10 @@ extern void __xchg_called_with_bad_pointer(void); static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) { switch (size) { - case 4: - return __xchg_u32(ptr, x); - case 8: - return __xchg_u64(ptr, x); + case 4: + return __xchg_u32(ptr, x); + case 8: + return __xchg_u64(ptr, x); } __xchg_called_with_bad_pointer(); return x; -- cgit v1.2.3 From a3dddd560ee936495466d85ecc97490d171e8d31 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 11 Mar 2006 08:18:41 +0000 Subject: [MIPS] War on whitespace: cleanup initial spaces followed by tabs. Signed-off-by: Ralf Baechle --- arch/mips/au1000/common/dbdma.c | 4 ++-- arch/mips/au1000/common/dma.c | 2 +- arch/mips/au1000/common/platform.c | 4 ++-- arch/mips/au1000/common/setup.c | 2 +- arch/mips/au1000/common/time.c | 2 +- arch/mips/dec/prom/memory.c | 2 +- arch/mips/jazz/int-handler.S | 12 ++++++------ arch/mips/kernel/cpu-probe.c | 6 +++--- arch/mips/kernel/gdb-low.S | 2 +- arch/mips/kernel/signal-common.h | 10 +++++----- arch/mips/kernel/signal32.c | 10 +++++----- arch/mips/kernel/traps.c | 2 +- arch/mips/lasat/image/romscript.normal | 5 +++-- arch/mips/mips-boards/generic/mipsIRQ.S | 2 +- arch/mips/mips-boards/sim/sim_IRQ.c | 2 +- arch/mips/mips-boards/sim/sim_irq.S | 2 +- arch/mips/mips-boards/sim/sim_smp.c | 2 +- arch/mips/mm/c-r3k.c | 18 +++++++++--------- arch/mips/momentum/jaguar_atx/reset.c | 2 +- arch/mips/momentum/jaguar_atx/setup.c | 2 +- arch/mips/momentum/ocelot_3/reset.c | 2 +- arch/mips/momentum/ocelot_c/reset.c | 2 +- arch/mips/pci/fixup-vr4133.c | 2 +- arch/mips/pci/ops-ddb5477.c | 4 ++-- arch/mips/pci/ops-tx4938.c | 16 ++++++++-------- arch/mips/pci/pci-bcm1480.c | 2 +- arch/mips/pci/pci-bcm1480ht.c | 2 +- arch/mips/pci/pci-ip27.c | 12 ++++++------ arch/mips/philips/pnx8550/common/int.c | 2 +- arch/mips/sgi-ip27/ip27-memory.c | 4 ++-- arch/mips/sgi-ip32/ip32-setup.c | 2 +- .../tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c | 4 ++-- arch/mips/tx4938/toshiba_rbtx4938/setup.c | 2 +- arch/mips/vr41xx/common/bcu.c | 6 +++--- include/asm-mips/pgtable-32.h | 2 +- include/asm-mips/sn/klconfig.h | 2 +- include/asm-mips/sn/sn0/hubio.h | 12 ++++++------ include/asm-mips/thread_info.h | 2 +- 38 files changed, 87 insertions(+), 86 deletions(-) (limited to 'include') diff --git a/arch/mips/au1000/common/dbdma.c b/arch/mips/au1000/common/dbdma.c index d00e8247d6c2..6ee090bd86c9 100644 --- a/arch/mips/au1000/common/dbdma.c +++ b/arch/mips/au1000/common/dbdma.c @@ -214,7 +214,7 @@ au1xxx_ddma_add_device(dbdev_tab_t *dev) if ( NULL != p ) { memcpy(p, dev, sizeof(dbdev_tab_t)); - p->dev_id = DSCR_DEV2CUSTOM_ID(new_id,dev->dev_id); + p->dev_id = DSCR_DEV2CUSTOM_ID(new_id,dev->dev_id); ret = p->dev_id; new_id++; #if 0 @@ -260,7 +260,7 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, spin_lock_irqsave(&au1xxx_dbdma_spin_lock, flags); if (!(stp->dev_flags & DEV_FLAGS_INUSE) || (stp->dev_flags & DEV_FLAGS_ANYUSE)) { - /* Got source */ + /* Got source */ stp->dev_flags |= DEV_FLAGS_INUSE; if (!(dtp->dev_flags & DEV_FLAGS_INUSE) || (dtp->dev_flags & DEV_FLAGS_ANYUSE)) { diff --git a/arch/mips/au1000/common/dma.c b/arch/mips/au1000/common/dma.c index 1905c6b104f2..1d82f2277517 100644 --- a/arch/mips/au1000/common/dma.c +++ b/arch/mips/au1000/common/dma.c @@ -174,7 +174,7 @@ int request_au1000_dma(int dev_id, const char *dev_str, return -EINVAL; #else if (dev_id < 0 || dev_id >= DMA_NUM_DEV) - return -EINVAL; + return -EINVAL; #endif for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++) { diff --git a/arch/mips/au1000/common/platform.c b/arch/mips/au1000/common/platform.c index 48d3f54f88f8..d7a8f0a811fe 100644 --- a/arch/mips/au1000/common/platform.c +++ b/arch/mips/au1000/common/platform.c @@ -264,7 +264,7 @@ static struct resource smc91x_resources[] = { static struct platform_device smc91x_device = { .name = "smc91x", - .id = -1, + .id = -1, .num_resources = ARRAY_SIZE(smc91x_resources), .resource = smc91x_resources, }; @@ -288,7 +288,7 @@ static struct platform_device *au1xxx_platform_devices[] __initdata = { &au1xxx_mmc_device, #endif #ifdef CONFIG_MIPS_DB1200 - &smc91x_device, + &smc91x_device, #endif }; diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c index eb155c071aa6..1080558c8100 100644 --- a/arch/mips/au1000/common/setup.c +++ b/arch/mips/au1000/common/setup.c @@ -90,7 +90,7 @@ void __init plat_setup(void) else { /* Clear to obtain best system bus performance */ clear_c0_config(1<<19); /* Clear Config[OD] */ - } + } argptr = prom_getcmdline(); diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c index 883d3f3d8c53..f85f1524b366 100644 --- a/arch/mips/au1000/common/time.c +++ b/arch/mips/au1000/common/time.c @@ -359,7 +359,7 @@ static unsigned long do_fast_cp0_gettimeoffset(void) : "hi", "lo", GCC_REG_ACCUM); /* - * Due to possible jiffies inconsistencies, we need to check + * Due to possible jiffies inconsistencies, we need to check * the result so that we'll get a timer that is monotonic. */ if (res >= USECS_PER_JIFFY) diff --git a/arch/mips/dec/prom/memory.c b/arch/mips/dec/prom/memory.c index 83d4556c3cb5..81cb5a76cfb7 100644 --- a/arch/mips/dec/prom/memory.c +++ b/arch/mips/dec/prom/memory.c @@ -45,7 +45,7 @@ static inline void pmax_setup_memory_region(void) */ for (memory_page = (unsigned char *)CKSEG1 + CHUNK_SIZE; mem_err == 0 && memory_page < (unsigned char *)CKSEG1 + 0x1e00000; - memory_page += CHUNK_SIZE) { + memory_page += CHUNK_SIZE) { dummy = *memory_page; } memcpy((void *)(CKSEG0 + 0x80), &old_handler, 0x80); diff --git a/arch/mips/jazz/int-handler.S b/arch/mips/jazz/int-handler.S index 4dbcf91db884..dc752c67b528 100644 --- a/arch/mips/jazz/int-handler.S +++ b/arch/mips/jazz/int-handler.S @@ -248,17 +248,17 @@ loc_call: /* and t2,s1 sh t2,JAZZ_IO_IRQ_ENABLE - nor s1,zero,s1 + nor s1,zero,s1 jal do_IRQ - /* - * Reenable interrupt - */ + /* + * Reenable interrupt + */ lhu t2,JAZZ_IO_IRQ_ENABLE - or t2,s1 + or t2,s1 sh t2,JAZZ_IO_IRQ_ENABLE - j ret_from_irq + j ret_from_irq /* * "Jump extender" to reach spurious_interrupt diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 292f8b243a5e..58b3b14873cb 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -291,7 +291,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c) * for documentation. Commented out because it shares * it's c0_prid id number with the TX3900. */ - c->cputype = CPU_R4650; + c->cputype = CPU_R4650; c->isa_level = MIPS_CPU_ISA_III; c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC; c->tlbsize = 48; @@ -604,7 +604,7 @@ static inline void cpu_probe_alchemy(struct cpuinfo_mips *c) case PRID_IMP_AU1_REV2: switch ((c->processor_id >> 24) & 0xff) { case 0: - c->cputype = CPU_AU1000; + c->cputype = CPU_AU1000; break; case 1: c->cputype = CPU_AU1500; @@ -705,7 +705,7 @@ __init void cpu_probe(void) break; case PRID_COMP_PHILIPS: cpu_probe_philips(c); - break; + break; default: c->cputype = CPU_UNKNOWN; } diff --git a/arch/mips/kernel/gdb-low.S b/arch/mips/kernel/gdb-low.S index 83b8986f9401..235ad9f6bd35 100644 --- a/arch/mips/kernel/gdb-low.S +++ b/arch/mips/kernel/gdb-low.S @@ -41,7 +41,7 @@ */ .align 5 NESTED(trap_low, GDB_FR_SIZE, sp) - .set noat + .set noat .set noreorder mfc0 k0, CP0_STATUS diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h index 36bfc2588aa3..3ca786215d48 100644 --- a/arch/mips/kernel/signal-common.h +++ b/arch/mips/kernel/signal-common.h @@ -166,11 +166,11 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) sp = regs->regs[29]; /* - * FPU emulator may have it's own trampoline active just - * above the user stack, 16-bytes before the next lowest - * 16 byte boundary. Try to avoid trashing it. - */ - sp -= 32; + * FPU emulator may have it's own trampoline active just + * above the user stack, 16-bytes before the next lowest + * 16 byte boundary. Try to avoid trashing it. + */ + sp -= 32; /* This is the X/Open sanctioned signal stack switching. */ if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0)) diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 1c7241ba6924..f32a22997c3d 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -624,11 +624,11 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, sp = regs->regs[29]; /* - * FPU emulator may have it's own trampoline active just - * above the user stack, 16-bytes before the next lowest - * 16 byte boundary. Try to avoid trashing it. - */ - sp -= 32; + * FPU emulator may have it's own trampoline active just + * above the user stack, 16-bytes before the next lowest + * 16 byte boundary. Try to avoid trashing it. + */ + sp -= 32; /* This is the X/Open sanctioned signal stack switching. */ if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0)) diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 005debbfbe84..bed0eb6cf55d 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -576,7 +576,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) } #endif /* - * Unimplemented operation exception. If we've got the full + * Unimplemented operation exception. If we've got the full * software emulator on-board, let's use it... * * Force FPU to dump state into task/thread context. We're diff --git a/arch/mips/lasat/image/romscript.normal b/arch/mips/lasat/image/romscript.normal index ca22336f6c36..988f8ad189cb 100644 --- a/arch/mips/lasat/image/romscript.normal +++ b/arch/mips/lasat/image/romscript.normal @@ -16,7 +16,8 @@ SECTIONS _image_start = ADDR(.data); _image_size = SIZEOF(.data); - .other : { - *(.*) + .other : + { + *(.*) } } diff --git a/arch/mips/mips-boards/generic/mipsIRQ.S b/arch/mips/mips-boards/generic/mipsIRQ.S index a397ecb872d6..ddd5c73a2971 100644 --- a/arch/mips/mips-boards/generic/mipsIRQ.S +++ b/arch/mips/mips-boards/generic/mipsIRQ.S @@ -98,7 +98,7 @@ and s0, s1 #if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) - .set mips32 + .set mips32 clz a0, s0 .set mips0 negu a0 diff --git a/arch/mips/mips-boards/sim/sim_IRQ.c b/arch/mips/mips-boards/sim/sim_IRQ.c index 9987a85aabeb..5b84c7fe1022 100644 --- a/arch/mips/mips-boards/sim/sim_IRQ.c +++ b/arch/mips/mips-boards/sim/sim_IRQ.c @@ -96,7 +96,7 @@ andi a0, s0, CAUSEF_IP3 # delay slot, check hw1 interrupt #else beq a0, zero, 1f # delay slot, check hw3 interrupt - andi a0, s0, CAUSEF_IP5 + andi a0, s0, CAUSEF_IP5 #endif /* Wheee, combined hardware level zero interrupt. */ diff --git a/arch/mips/mips-boards/sim/sim_irq.S b/arch/mips/mips-boards/sim/sim_irq.S index 835f0387fcd4..da52297a2216 100644 --- a/arch/mips/mips-boards/sim/sim_irq.S +++ b/arch/mips/mips-boards/sim/sim_irq.S @@ -42,7 +42,7 @@ and s0, s1 #if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) - .set mips32 + .set mips32 clz a0, s0 .set mips0 negu a0 diff --git a/arch/mips/mips-boards/sim/sim_smp.c b/arch/mips/mips-boards/sim/sim_smp.c index 19824359f5de..a9f0c2bfe4ad 100644 --- a/arch/mips/mips-boards/sim/sim_smp.c +++ b/arch/mips/mips-boards/sim/sim_smp.c @@ -115,7 +115,7 @@ void prom_prepare_cpus(unsigned int max_cpus) #ifdef CONFIG_MIPS_MT_SMTC void mipsmt_prepare_cpus(int c); /* - * As noted above, we can assume a single CPU for now + * As noted above, we can assume a single CPU for now * but it may be multithreaded. */ diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c index 27f4fa25e8c9..9dd1352d5748 100644 --- a/arch/mips/mm/c-r3k.c +++ b/arch/mips/mm/c-r3k.c @@ -129,7 +129,7 @@ static void r3k_flush_icache_range(unsigned long start, unsigned long end) "sb\t$0, 0x014(%0)\n\t" "sb\t$0, 0x018(%0)\n\t" "sb\t$0, 0x01c(%0)\n\t" - "sb\t$0, 0x020(%0)\n\t" + "sb\t$0, 0x020(%0)\n\t" "sb\t$0, 0x024(%0)\n\t" "sb\t$0, 0x028(%0)\n\t" "sb\t$0, 0x02c(%0)\n\t" @@ -145,7 +145,7 @@ static void r3k_flush_icache_range(unsigned long start, unsigned long end) "sb\t$0, 0x054(%0)\n\t" "sb\t$0, 0x058(%0)\n\t" "sb\t$0, 0x05c(%0)\n\t" - "sb\t$0, 0x060(%0)\n\t" + "sb\t$0, 0x060(%0)\n\t" "sb\t$0, 0x064(%0)\n\t" "sb\t$0, 0x068(%0)\n\t" "sb\t$0, 0x06c(%0)\n\t" @@ -182,31 +182,31 @@ static void r3k_flush_dcache_range(unsigned long start, unsigned long end) "sb\t$0, 0x004(%0)\n\t" "sb\t$0, 0x008(%0)\n\t" "sb\t$0, 0x00c(%0)\n\t" - "sb\t$0, 0x010(%0)\n\t" + "sb\t$0, 0x010(%0)\n\t" "sb\t$0, 0x014(%0)\n\t" "sb\t$0, 0x018(%0)\n\t" "sb\t$0, 0x01c(%0)\n\t" - "sb\t$0, 0x020(%0)\n\t" + "sb\t$0, 0x020(%0)\n\t" "sb\t$0, 0x024(%0)\n\t" "sb\t$0, 0x028(%0)\n\t" "sb\t$0, 0x02c(%0)\n\t" - "sb\t$0, 0x030(%0)\n\t" + "sb\t$0, 0x030(%0)\n\t" "sb\t$0, 0x034(%0)\n\t" "sb\t$0, 0x038(%0)\n\t" "sb\t$0, 0x03c(%0)\n\t" - "sb\t$0, 0x040(%0)\n\t" + "sb\t$0, 0x040(%0)\n\t" "sb\t$0, 0x044(%0)\n\t" "sb\t$0, 0x048(%0)\n\t" "sb\t$0, 0x04c(%0)\n\t" - "sb\t$0, 0x050(%0)\n\t" + "sb\t$0, 0x050(%0)\n\t" "sb\t$0, 0x054(%0)\n\t" "sb\t$0, 0x058(%0)\n\t" "sb\t$0, 0x05c(%0)\n\t" - "sb\t$0, 0x060(%0)\n\t" + "sb\t$0, 0x060(%0)\n\t" "sb\t$0, 0x064(%0)\n\t" "sb\t$0, 0x068(%0)\n\t" "sb\t$0, 0x06c(%0)\n\t" - "sb\t$0, 0x070(%0)\n\t" + "sb\t$0, 0x070(%0)\n\t" "sb\t$0, 0x074(%0)\n\t" "sb\t$0, 0x078(%0)\n\t" "sb\t$0, 0x07c(%0)\n\t" diff --git a/arch/mips/momentum/jaguar_atx/reset.c b/arch/mips/momentum/jaguar_atx/reset.c index c4236b1e59fa..ce9fb2e3d952 100644 --- a/arch/mips/momentum/jaguar_atx/reset.c +++ b/arch/mips/momentum/jaguar_atx/reset.c @@ -32,7 +32,7 @@ void momenco_jaguar_restart(char *command) #else void *nvram = (void*) 0xfc807000; #endif - /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */ + /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */ writeb(0x84, nvram + 0xff7); /* wait for the watchdog to go off */ diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c index 2699917b640a..3784c898db1a 100644 --- a/arch/mips/momentum/jaguar_atx/setup.c +++ b/arch/mips/momentum/jaguar_atx/setup.c @@ -461,7 +461,7 @@ void __init plat_setup(void) unsigned int tbControl; tbControl = 0 << 26 | /* post trigger delay 0 */ - 0x2 << 16 | /* sequential trace mode */ + 0x2 << 16 | /* sequential trace mode */ // 0x0 << 16 | /* non-sequential trace mode */ // 0xf << 4 | /* watchpoints disabled */ 2 << 2 | /* armed */ diff --git a/arch/mips/momentum/ocelot_3/reset.c b/arch/mips/momentum/ocelot_3/reset.c index 72b4423c0864..9d86d2468376 100644 --- a/arch/mips/momentum/ocelot_3/reset.c +++ b/arch/mips/momentum/ocelot_3/reset.c @@ -34,7 +34,7 @@ void momenco_ocelot_restart(char *command) /* base address of timekeeper portion of part */ void *nvram = (void *) 0xfc807000L; - /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */ + /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */ writeb(0x84, nvram + 0xff7); /* wait for the watchdog to go off */ diff --git a/arch/mips/momentum/ocelot_c/reset.c b/arch/mips/momentum/ocelot_c/reset.c index 6a2489f3b9a0..9dcd154c7767 100644 --- a/arch/mips/momentum/ocelot_c/reset.c +++ b/arch/mips/momentum/ocelot_c/reset.c @@ -34,7 +34,7 @@ void momenco_ocelot_restart(char *command) 0xfc807000; #endif - /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */ + /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */ writeb(0x84, nvram + 0xff7); /* wait for the watchdog to go off */ diff --git a/arch/mips/pci/fixup-vr4133.c b/arch/mips/pci/fixup-vr4133.c index 03a0ff2fc993..a8a47b494b23 100644 --- a/arch/mips/pci/fixup-vr4133.c +++ b/arch/mips/pci/fixup-vr4133.c @@ -45,7 +45,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev) /* * we have to open the bridges' windows down to 0 because otherwise - * we cannot access ISA south bridge I/O registers that get mapped from + * we cannot access ISA south bridge I/O registers that get mapped from * 0. for example, 8259 PIC would be unaccessible without that */ if(dev->vendor == PCI_VENDOR_ID_INTEL && dev->device == PCI_DEVICE_ID_INTEL_S21152BB) { diff --git a/arch/mips/pci/ops-ddb5477.c b/arch/mips/pci/ops-ddb5477.c index 0406b50a37d8..8e57d4c5d90f 100644 --- a/arch/mips/pci/ops-ddb5477.c +++ b/arch/mips/pci/ops-ddb5477.c @@ -253,9 +253,9 @@ static int write_config_byte(struct pci_config_swap *swap, static int prefix##_##rw##_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 star val) \ { \ if (size == 1) \ - return rw##_config_byte(pciswap, bus, devfn, where, (u8 star)val); \ + return rw##_config_byte(pciswap, bus, devfn, where, (u8 star)val); \ else if (size == 2) \ - return rw##_config_word(pciswap, bus, devfn, where, (u16 star)val); \ + return rw##_config_word(pciswap, bus, devfn, where, (u16 star)val); \ /* Size must be 4 */ \ return rw##_config_dword(pciswap, bus, devfn, where, val); \ } diff --git a/arch/mips/pci/ops-tx4938.c b/arch/mips/pci/ops-tx4938.c index 4c0dcfce5297..0ff083489efd 100644 --- a/arch/mips/pci/ops-tx4938.c +++ b/arch/mips/pci/ops-tx4938.c @@ -34,16 +34,16 @@ struct resource pci_mem_resource = { }; struct resource tx4938_pcic1_pci_io_resource = { - .name = "PCI1 IO", - .start = 0, - .end = 0, - .flags = IORESOURCE_IO + .name = "PCI1 IO", + .start = 0, + .end = 0, + .flags = IORESOURCE_IO }; struct resource tx4938_pcic1_pci_mem_resource = { - .name = "PCI1 mem", - .start = 0, - .end = 0, - .flags = IORESOURCE_MEM + .name = "PCI1 mem", + .start = 0, + .end = 0, + .flags = IORESOURCE_MEM }; static int mkaddr(int bus, int dev_fn, int where, int *flagsp) diff --git a/arch/mips/pci/pci-bcm1480.c b/arch/mips/pci/pci-bcm1480.c index ca975e7d32ff..f4ef1a35ca18 100644 --- a/arch/mips/pci/pci-bcm1480.c +++ b/arch/mips/pci/pci-bcm1480.c @@ -100,7 +100,7 @@ static int bcm1480_pci_can_access(struct pci_bus *bus, int devfn) if (bus->number == 0) { devno = PCI_SLOT(devfn); - if (bcm1480_bus_status & PCI_DEVICE_MODE) + if (bcm1480_bus_status & PCI_DEVICE_MODE) return 0; else return 1; diff --git a/arch/mips/pci/pci-bcm1480ht.c b/arch/mips/pci/pci-bcm1480ht.c index aca4a2e7a1c6..a3eebe5890a7 100644 --- a/arch/mips/pci/pci-bcm1480ht.c +++ b/arch/mips/pci/pci-bcm1480ht.c @@ -95,7 +95,7 @@ static int bcm1480ht_can_access(struct pci_bus *bus, int devfn) if (bus->number == 0) { devno = PCI_SLOT(devfn); - if (bcm1480ht_bus_status & PCI_DEVICE_MODE) + if (bcm1480ht_bus_status & PCI_DEVICE_MODE) return 0; } return 1; diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index efc96ce99eeb..6002d2a6a262 100644 --- a/arch/mips/pci/pci-ip27.c +++ b/arch/mips/pci/pci-ip27.c @@ -379,18 +379,18 @@ int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) bridge = (bridge_t *) RAW_NODE_SWIN_BASE(nasid, widget_id); /* - * Clear all pending interrupts. - */ + * Clear all pending interrupts. + */ bridge->b_int_rst_stat = BRIDGE_IRR_ALL_CLR; /* - * Until otherwise set up, assume all interrupts are from slot 0 - */ + * Until otherwise set up, assume all interrupts are from slot 0 + */ bridge->b_int_device = 0x0; /* - * swap pio's to pci mem and io space (big windows) - */ + * swap pio's to pci mem and io space (big windows) + */ bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP | BRIDGE_CTRL_MEM_SWAP; diff --git a/arch/mips/philips/pnx8550/common/int.c b/arch/mips/philips/pnx8550/common/int.c index 546144988bf5..c500e2d41f2c 100644 --- a/arch/mips/philips/pnx8550/common/int.c +++ b/arch/mips/philips/pnx8550/common/int.c @@ -251,7 +251,7 @@ void __init arch_init_irq(void) if (gic_int_line == (PNX8550_INT_GPIO0 - PNX8550_INT_GIC_MIN)) { /* PCI INT through gpio 8, which is setup in * pnx8550_setup.c and routed to GPIO - * Interrupt Level 0 (GPIO Connection 58). + * Interrupt Level 0 (GPIO Connection 58). * Set it active low. */ PNX8550_GIC_REQ(gic_int_line) = 0x1E020000; diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c index ef20d9ac0ba3..ed93a9792959 100644 --- a/arch/mips/sgi-ip27/ip27-memory.c +++ b/arch/mips/sgi-ip27/ip27-memory.c @@ -540,8 +540,8 @@ void __init mem_init(void) struct page *end, *p; /* - * This will free up the bootmem, ie, slot 0 memory. - */ + * This will free up the bootmem, ie, slot 0 memory. + */ totalram_pages += free_all_bootmem_node(NODE_DATA(node)); /* diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c index 2c38770b1e1b..2f50c79b7887 100644 --- a/arch/mips/sgi-ip32/ip32-setup.c +++ b/arch/mips/sgi-ip32/ip32-setup.c @@ -98,7 +98,7 @@ void __init plat_setup(void) board_timer_setup = ip32_timer_setup; #ifdef CONFIG_SERIAL_8250 - { + { static struct uart_port o2_serial[2]; memset(o2_serial, 0, sizeof(o2_serial)); diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c index e19e2be70f76..efe50562f0ce 100644 --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c @@ -70,10 +70,10 @@ void __init prom_init(void) if ((read_c0_prid() & 0xff) == PRID_REV_TX4927) { mips_machtype = MACH_TOSHIBA_RBTX4927; - toshiba_name = "TX4927"; + toshiba_name = "TX4927"; } else { mips_machtype = MACH_TOSHIBA_RBTX4937; - toshiba_name = "TX4937"; + toshiba_name = "TX4937"; } msize = tx4927_get_mem_size(); diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c index 5c7ace982a49..9166cd4557eb 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/setup.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c @@ -684,7 +684,7 @@ void __init tx4938_board_setup(void) for (i = 0; i < 8; i++) { if (!(tx4938_ebuscptr->cr[i] & 0x8)) continue; /* disabled */ - rbtx4938_ce_base[i] = (unsigned long)TX4938_EBUSC_BA(i); + rbtx4938_ce_base[i] = (unsigned long)TX4938_EBUSC_BA(i); txboard_add_phys_region(rbtx4938_ce_base[i], TX4938_EBUSC_SIZE(i)); } diff --git a/arch/mips/vr41xx/common/bcu.c b/arch/mips/vr41xx/common/bcu.c index de0c1b35f11c..ff272b2e8395 100644 --- a/arch/mips/vr41xx/common/bcu.c +++ b/arch/mips/vr41xx/common/bcu.c @@ -183,11 +183,11 @@ static inline unsigned long calculate_tclock(uint16_t clkspeed, unsigned long pc switch (current_cpu_data.cputype) { case CPU_VR4111: if (!(clkspeed & DIV2B)) - tclock = pclock / 2; + tclock = pclock / 2; else if (!(clkspeed & DIV3B)) - tclock = pclock / 3; + tclock = pclock / 3; else if (!(clkspeed & DIV4B)) - tclock = pclock / 4; + tclock = pclock / 4; break; case CPU_VR4121: tclock = pclock / DIVT(clkspeed); diff --git a/include/asm-mips/pgtable-32.h b/include/asm-mips/pgtable-32.h index 0cff64ce0fb8..4d6bc45df594 100644 --- a/include/asm-mips/pgtable-32.h +++ b/include/asm-mips/pgtable-32.h @@ -206,7 +206,7 @@ pfn_pte(unsigned long pfn, pgprot_t prot) /* fixme */ #define pte_to_pgoff(_pte) (((_pte).pte_high >> 6) + ((_pte).pte_high & 0x3f)) #define pgoff_to_pte(off) \ - ((pte_t){(((off) & 0x3f) + ((off) << 6) + _PAGE_FILE)}) + ((pte_t){(((off) & 0x3f) + ((off) << 6) + _PAGE_FILE)}) #else #define pte_to_pgoff(_pte) \ diff --git a/include/asm-mips/sn/klconfig.h b/include/asm-mips/sn/klconfig.h index d028e28d6239..9709ff701d9b 100644 --- a/include/asm-mips/sn/klconfig.h +++ b/include/asm-mips/sn/klconfig.h @@ -99,7 +99,7 @@ typedef s32 klconf_off_t; #define ENABLE_BOARD 0x01 #define FAILED_BOARD 0x02 #define DUPLICATE_BOARD 0x04 /* Boards like midplanes/routers which - are discovered twice. Use one of them */ + are discovered twice. Use one of them */ #define VISITED_BOARD 0x08 /* Used for compact hub numbering. */ #define LOCAL_MASTER_IO6 0x10 /* master io6 for that node */ #define GLOBAL_MASTER_IO6 0x20 diff --git a/include/asm-mips/sn/sn0/hubio.h b/include/asm-mips/sn/sn0/hubio.h index 80cf6a52ed3b..f314da21b970 100644 --- a/include/asm-mips/sn/sn0/hubio.h +++ b/include/asm-mips/sn/sn0/hubio.h @@ -229,7 +229,7 @@ typedef union hubii_ilcsr_u { icsr_llp_en: 1, /* LLP enable bit */ icsr_rsvd2: 1, /* reserver */ icsr_wrm_reset: 1, /* Warm reset bit */ - icsr_rsvd1: 2, /* Data ready offset */ + icsr_rsvd1: 2, /* Data ready offset */ icsr_null_to: 6; /* Null timeout */ } icsr_fields_s; @@ -274,9 +274,9 @@ typedef union io_perf_sel { u64 perf_sel_reg; struct { u64 perf_rsvd : 48, - perf_icct : 8, - perf_ippr1 : 4, - perf_ippr0 : 4; + perf_icct : 8, + perf_ippr1 : 4, + perf_ippr0 : 4; } perf_sel_bits; } io_perf_sel_t; @@ -287,8 +287,8 @@ typedef union io_perf_cnt { u64 perf_cnt; struct { u64 perf_rsvd1 : 32, - perf_rsvd2 : 12, - perf_cnt : 20; + perf_rsvd2 : 12, + perf_cnt : 20; } perf_cnt_bits; } io_perf_cnt_t; diff --git a/include/asm-mips/thread_info.h b/include/asm-mips/thread_info.h index fa193f861e71..f8d97dafd2f4 100644 --- a/include/asm-mips/thread_info.h +++ b/include/asm-mips/thread_info.h @@ -31,7 +31,7 @@ struct thread_info { int preempt_count; /* 0 => preemptable, <0 => BUG */ mm_segment_t addr_limit; /* thread address space: - 0-0xBFFFFFFF for user-thead + 0-0xBFFFFFFF for user-thead 0-0xFFFFFFFF for kernel-thread */ struct restart_block restart_block; -- cgit v1.2.3 From f3629be8388a679590eb919919ee63e2715ec25e Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 11 Mar 2006 17:02:01 -0300 Subject: V4L/DVB (3445): LG TALN series: add PAL / SECAM support - added tuner_lg_taln_pal_secam_ranges - renamed tuner 66 from TUNER_LG_NTSC_TALN_MINI to TUNER_LG_TALN - updated FlyTV mini Asus Digimatrix with new tuner Thanks-to: Rickard Osser Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.tuner | 2 +- drivers/media/video/saa7134/saa7134-cards.c | 2 +- drivers/media/video/tuner-types.c | 26 ++++++++++++++++++-------- include/media/tuner.h | 2 +- 4 files changed, 21 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index 44069338b531..1bcdac67dd8c 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -64,7 +64,7 @@ tuner=62 - Philips TEA5767HN FM Radio tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner tuner=64 - LG TDVS-H062F/TUA6034 tuner=65 - Ymec TVF66T5-B/DFF -tuner=66 - LG NTSC (TALN mini series) +tuner=66 - LG TALN series tuner=67 - Philips TD1316 Hybrid Tuner tuner=68 - Philips TUV1236D ATSC/NTSC dual in tuner=69 - Tena TNF 5335 and similar models diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index e9172e114974..f9265419ccb9 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2028,7 +2028,7 @@ struct saa7134_board saa7134_boards[] = { [SAA7134_BOARD_FLYTV_DIGIMATRIX] = { .name = "FlyTV mini Asus Digimatrix", .audio_clock = 0x00200000, - .tuner_type = TUNER_LG_NTSC_TALN_MINI, + .tuner_type = TUNER_LG_TALN, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index ae6a2cf91c9b..72e0f01db563 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -903,17 +903,27 @@ static struct tuner_params tuner_ymec_tvf66t5_b_dff_params[] = { /* ------------ TUNER_LG_NTSC_TALN_MINI - LGINNOTEK NTSC ------------ */ -static struct tuner_range tuner_lg_taln_mini_ntsc_ranges[] = { +static struct tuner_range tuner_lg_taln_ntsc_ranges[] = { { 16 * 137.25 /*MHz*/, 0x8e, 0x01, }, { 16 * 373.25 /*MHz*/, 0x8e, 0x02, }, { 16 * 999.99 , 0x8e, 0x08, }, }; -static struct tuner_params tuner_lg_taln_mini_params[] = { +static struct tuner_range tuner_lg_taln_pal_secam_ranges[] = { + { 16 * 150.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 425.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x08, }, +}; + +static struct tuner_params tuner_lg_taln_params[] = { { .type = TUNER_PARAM_TYPE_NTSC, - .ranges = tuner_lg_taln_mini_ntsc_ranges, - .count = ARRAY_SIZE(tuner_lg_taln_mini_ntsc_ranges), + .ranges = tuner_lg_taln_ntsc_ranges, + .count = ARRAY_SIZE(tuner_lg_taln_ntsc_ranges), + },{ + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_lg_taln_pal_secam_ranges, + .count = ARRAY_SIZE(tuner_lg_taln_pal_secam_ranges), }, }; @@ -1354,10 +1364,10 @@ struct tunertype tuners[] = { .params = tuner_ymec_tvf66t5_b_dff_params, .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_params), }, - [TUNER_LG_NTSC_TALN_MINI] = { /* LGINNOTEK NTSC */ - .name = "LG NTSC (TALN mini series)", - .params = tuner_lg_taln_mini_params, - .count = ARRAY_SIZE(tuner_lg_taln_mini_params), + [TUNER_LG_TALN] = { /* LGINNOTEK NTSC / PAL / SECAM */ + .name = "LG TALN series", + .params = tuner_lg_taln_params, + .count = ARRAY_SIZE(tuner_lg_taln_params), }, [TUNER_PHILIPS_TD1316] = { /* Philips PAL */ .name = "Philips TD1316 Hybrid Tuner", diff --git a/include/media/tuner.h b/include/media/tuner.h index 02d7d9a76fa2..017fed7d5e4d 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -110,7 +110,7 @@ #define TUNER_LG_TDVS_H062F 64 /* DViCO FusionHDTV 5 */ #define TUNER_YMEC_TVF66T5_B_DFF 65 /* Acorp Y878F */ -#define TUNER_LG_NTSC_TALN_MINI 66 +#define TUNER_LG_TALN 66 #define TUNER_PHILIPS_TD1316 67 #define TUNER_PHILIPS_TUV1236D 68 /* ATI HDTV Wonder */ -- cgit v1.2.3 From f5762e441d5022ecc5b66b5fe54e41e2ac5d02be Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 13 Mar 2006 13:31:31 -0300 Subject: V4L/DVB (3513): Remove saa711x driver Now, em28xx uses saa7115 instead of saa711x. saa7115 driver is capable of handling saa 7113, 7114 and 7115. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Makefile | 2 +- drivers/media/video/em28xx/em28xx-video.c | 218 ++---------------------------- drivers/media/video/saa7115.c | 76 +++++++++-- include/media/v4l2-common.h | 1 + 4 files changed, 78 insertions(+), 219 deletions(-) (limited to 'include') diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 51721574d9cf..00080224f281 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -44,7 +44,7 @@ obj-$(CONFIG_VIDEO_MEYE) += meye.o obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/ obj-$(CONFIG_VIDEO_CX88) += cx88/ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ -obj-$(CONFIG_VIDEO_EM28XX) += saa711x.o tvp5150.o +obj-$(CONFIG_VIDEO_EM28XX) += saa7115.o tvp5150.o obj-$(CONFIG_VIDEO_AUDIO_DECODER) += wm8775.o cs53l32a.o obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 78f0f7a706ea..780342f7b239 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -101,23 +101,6 @@ static struct em28xx_tvnorm tvnorms[] = { } }; -static const unsigned char saa7114_i2c_init[] = { - 0x00,0x00,0x01,0x08,0x02,0xc4,0x03,0x30,0x04,0x90,0x05,0x90,0x06,0xeb,0x07,0xe0, - 0x08,0x88,0x09,0x40,0x0a,0x80,0x0b,0x44,0x0c,0x40,0x0d,0x00,0x0e,0x81,0x0f,0x2a, - 0x10,0x06,0x11,0x00,0x12,0xc8,0x13,0x80,0x14,0x00,0x15,0x11,0x16,0x01,0x17,0x42, - 0x18,0x40,0x19,0x80,0x40,0x00,0x41,0xff,0x42,0xff,0x43,0xff,0x44,0xff,0x45,0xff, - 0x46,0xff,0x47,0xff,0x48,0xff,0x49,0xff,0x4a,0xff,0x4b,0xff,0x4c,0xff,0x4d,0xff, - 0x4e,0xff,0x4f,0xff,0x50,0xff,0x51,0xff,0x52,0xff,0x53,0xff,0x54,0x5f,0x55,0xff, - 0x56,0xff,0x57,0xff,0x58,0x00,0x59,0x47,0x5a,0x03,0x5b,0x03,0x5d,0x3e,0x5e,0x00, - 0x80,0x1c,0x83,0x01,0x84,0xa5,0x85,0x10,0x86,0x45,0x87,0x41,0x88,0xf0,0x88,0x00, - 0x88,0xf0,0x90,0x00,0x91,0x08,0x92,0x00,0x93,0x80,0x94,0x08,0x95,0x00,0x96,0xc0, - 0x97,0x02,0x98,0x13,0x99,0x00,0x9a,0x38,0x9b,0x01,0x9c,0x80,0x9d,0x02,0x9e,0x06, - 0x9f,0x01,0xa0,0x01,0xa1,0x00,0xa2,0x00,0xa4,0x80,0xa5,0x36,0xa6,0x36,0xa8,0x67, - 0xa9,0x04,0xaa,0x00,0xac,0x33,0xad,0x02,0xae,0x00,0xb0,0xcd,0xb1,0x04,0xb2,0xcd, - 0xb3,0x04,0xb4,0x01,0xb8,0x00,0xb9,0x00,0xba,0x00,0xbb,0x00,0xbc,0x00,0xbd,0x00, - 0xbe,0x00,0xbf,0x00 -}; - #define TVNORMS ARRAY_SIZE(tvnorms) /* supported controls */ @@ -144,65 +127,6 @@ static struct v4l2_queryctrl em28xx_qctrl[] = { } }; -/* FIXME: These are specific to saa711x - should be moved to its code */ -static struct v4l2_queryctrl saa711x_qctrl[] = { - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = -128, - .maximum = 127, - .step = 1, - .default_value = 0, - .flags = 0, - },{ - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contrast", - .minimum = 0x0, - .maximum = 0x1f, - .step = 0x1, - .default_value = 0x10, - .flags = 0, - },{ - .id = V4L2_CID_SATURATION, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Saturation", - .minimum = 0x0, - .maximum = 0x1f, - .step = 0x1, - .default_value = 0x10, - .flags = 0, - },{ - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Red chroma balance", - .minimum = -128, - .maximum = 127, - .step = 1, - .default_value = 0, - .flags = 0, - },{ - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Blue chroma balance", - .minimum = -128, - .maximum = 127, - .step = 1, - .default_value = 0, - .flags = 0, - },{ - .id = V4L2_CID_GAMMA, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Gamma", - .minimum = 0x0, - .maximum = 0x3f, - .step = 0x1, - .default_value = 0x20, - .flags = 0, - } -}; - static struct usb_driver em28xx_usb_driver; static DEFINE_MUTEX(em28xx_sysfs_lock); @@ -245,22 +169,9 @@ static int em28xx_config(struct em28xx *dev) static void em28xx_config_i2c(struct em28xx *dev) { struct v4l2_frequency f; - struct video_decoder_init em28xx_vdi = {.data = NULL }; - - - /* configure decoder */ - if(dev->model == EM2820_BOARD_MSI_VOX_USB_2){ - em28xx_vdi.data=saa7114_i2c_init; - em28xx_vdi.len=sizeof(saa7114_i2c_init); - } - - - em28xx_i2c_call_clients(dev, DECODER_INIT, &em28xx_vdi); - em28xx_i2c_call_clients(dev, DECODER_SET_INPUT, &dev->ctl_input); -/* em28xx_i2c_call_clients(dev,DECODER_SET_PICTURE, &dev->vpic); */ -/* em28xx_i2c_call_clients(dev,DECODER_SET_NORM,&dev->tvnorm->id); */ -/* em28xx_i2c_call_clients(dev,DECODER_ENABLE_OUTPUT,&output); */ -/* em28xx_i2c_call_clients(dev,DECODER_DUMP, NULL); */ + em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, NULL); + em28xx_i2c_call_clients(dev, VIDIOC_S_INPUT, &dev->ctl_input); + em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL); /* configure tuner */ f.tuner = 0; @@ -300,8 +211,7 @@ static void video_mux(struct em28xx *dev, int index) dev->ctl_input = index; dev->ctl_ainput = INPUT(index)->amux; - em28xx_i2c_call_clients(dev, DECODER_SET_INPUT, &input); - + em28xx_i2c_call_clients(dev, VIDIOC_S_INPUT, &input); em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,input,dev->ctl_ainput); @@ -747,43 +657,6 @@ static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) } } -/*FIXME: should be moved to saa711x */ -static int saa711x_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) -{ - s32 tmp; - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - if ((tmp = em28xx_brightness_get(dev)) < 0) - return -EIO; - ctrl->value = (s32) ((s8) tmp); /* FIXME: clenaer way to extend sign? */ - return 0; - case V4L2_CID_CONTRAST: - if ((ctrl->value = em28xx_contrast_get(dev)) < 0) - return -EIO; - return 0; - case V4L2_CID_SATURATION: - if ((ctrl->value = em28xx_saturation_get(dev)) < 0) - return -EIO; - return 0; - case V4L2_CID_RED_BALANCE: - if ((tmp = em28xx_v_balance_get(dev)) < 0) - return -EIO; - ctrl->value = (s32) ((s8) tmp); /* FIXME: clenaer way to extend sign? */ - return 0; - case V4L2_CID_BLUE_BALANCE: - if ((tmp = em28xx_u_balance_get(dev)) < 0) - return -EIO; - ctrl->value = (s32) ((s8) tmp); /* FIXME: clenaer way to extend sign? */ - return 0; - case V4L2_CID_GAMMA: - if ((ctrl->value = em28xx_gamma_get(dev)) < 0) - return -EIO; - return 0; - default: - return -EINVAL; - } -} - /* * em28xx_set_ctrl() * mute or set new saturation, brightness or contrast @@ -806,27 +679,6 @@ static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) } } -/*FIXME: should be moved to saa711x */ -static int saa711x_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - return em28xx_brightness_set(dev, ctrl->value); - case V4L2_CID_CONTRAST: - return em28xx_contrast_set(dev, ctrl->value); - case V4L2_CID_SATURATION: - return em28xx_saturation_set(dev, ctrl->value); - case V4L2_CID_RED_BALANCE: - return em28xx_v_balance_set(dev, ctrl->value); - case V4L2_CID_BLUE_BALANCE: - return em28xx_u_balance_set(dev, ctrl->value); - case V4L2_CID_GAMMA: - return em28xx_gamma_set(dev, ctrl->value); - default: - return -EINVAL; - } -} - /* * em28xx_stream_interrupt() * stops streaming @@ -1130,8 +982,6 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, em28xx_set_norm(dev, dev->width, dev->height); - em28xx_i2c_call_clients(dev, DECODER_SET_NORM, - &tvnorms[i].mode); em28xx_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id); @@ -1242,22 +1092,11 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, } } } - if (dev->decoder == EM28XX_TVP5150) { - em28xx_i2c_call_clients(dev,cmd,qc); - if (qc->type) - return 0; - else - return -EINVAL; - } - for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) { - if (qc->id && qc->id == saa711x_qctrl[i].id) { - memcpy(qc, &(saa711x_qctrl[i]), - sizeof(*qc)); - return 0; - } - } - - return -EINVAL; + em28xx_i2c_call_clients(dev,cmd,qc); + if (qc->type) + return 0; + else + return -EINVAL; } case VIDIOC_G_CTRL: { @@ -1267,12 +1106,8 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, if (!dev->has_msp34xx) retval=em28xx_get_ctrl(dev, ctrl); if (retval==-EINVAL) { - if (dev->decoder == EM28XX_TVP5150) { - em28xx_i2c_call_clients(dev,cmd,arg); - return 0; - } - - return saa711x_get_ctrl(dev, ctrl); + em28xx_i2c_call_clients(dev,cmd,arg); + return 0; } else return retval; } case VIDIOC_S_CTRL: @@ -1293,33 +1128,8 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, } } - if (dev->decoder == EM28XX_TVP5150) { - em28xx_i2c_call_clients(dev,cmd,arg); - return 0; - } else if (!dev->has_msp34xx) { - for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { - if (ctrl->id == em28xx_qctrl[i].id) { - if (ctrl->value < - em28xx_qctrl[i].minimum - || ctrl->value > - em28xx_qctrl[i].maximum) - return -ERANGE; - return em28xx_set_ctrl(dev, ctrl); - } - } - for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) { - if (ctrl->id == saa711x_qctrl[i].id) { - if (ctrl->value < - saa711x_qctrl[i].minimum - || ctrl->value > - saa711x_qctrl[i].maximum) - return -ERANGE; - return saa711x_set_ctrl(dev, ctrl); - } - } - } - - return -EINVAL; + em28xx_i2c_call_clients(dev,cmd,arg); + return 0; } /* --- tuner ioctls ------------------------------------------ */ case VIDIOC_G_TUNER: @@ -1772,7 +1582,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, #ifdef CONFIG_MODULES /* request some modules */ if (dev->decoder == EM28XX_SAA7113 || dev->decoder == EM28XX_SAA7114) - request_module("saa711x"); + request_module("saa7115"); if (dev->decoder == EM28XX_TVP5150) request_module("tvp5150"); if (dev->has_tuner) diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index f0eb9851bf53..7050d81c0242 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1,4 +1,4 @@ -/* saa7115 - Philips SAA7114/SAA7115 video decoder driver +/* saa7115 - Philips SAA7113/SAA7114/SAA7115 video decoder driver * * Based on saa7114 driver by Maxim Yevtyushkin, which is based on * the saa7111 driver by Dave Perks. @@ -16,6 +16,7 @@ * (2/17/2003) * * VBI support (2004) and cleanups (2005) by Hans Verkuil + * SAA7113 support by Mauro Carvalho Chehab * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -42,8 +43,9 @@ #include #include -MODULE_DESCRIPTION("Philips SAA7114/SAA7115 video decoder driver"); -MODULE_AUTHOR("Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, Hans Verkuil"); +MODULE_DESCRIPTION("Philips SAA7113/SAA7114/SAA7115 video decoder driver"); +MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, " + "Hans Verkuil, Mauro Carvalho Chehab"); MODULE_LICENSE("GPL"); static int debug = 0; @@ -51,7 +53,10 @@ module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { + 0x4a >>1, 0x48 >>1, /* SAA7113 */ + 0x42 >> 1, 0x40 >> 1, /* SAA7114 and SAA7115 */ + I2C_CLIENT_END }; I2C_CLIENT_INSMOD; @@ -101,10 +106,12 @@ static inline int saa7115_read(struct i2c_client *client, u8 reg) Hauppauge driver sets. */ static const unsigned char saa7115_init_auto_input[] = { + /* Front-End Part */ 0x01, 0x48, /* white peak control disabled */ 0x03, 0x20, /* was 0x30. 0x20: long vertical blanking */ 0x04, 0x90, /* analog gain set to 0 */ 0x05, 0x90, /* analog gain set to 0 */ + /* Decoder Part */ 0x06, 0xeb, /* horiz sync begin = -21 */ 0x07, 0xe0, /* horiz sync stop = -17 */ 0x0a, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */ @@ -123,6 +130,8 @@ static const unsigned char saa7115_init_auto_input[] = { 0x1b, 0x42, /* misc chroma control 0x42 = recommended */ 0x1c, 0xa9, /* combfilter control 0xA9 = recommended */ 0x1d, 0x01, /* combfilter control 0x01 = recommended */ + + /* Power Device Control */ 0x88, 0xd0, /* reset device */ 0x88, 0xf0, /* set device programmed, all in operational mode */ 0x00, 0x00 @@ -338,6 +347,33 @@ static const unsigned char saa7115_cfg_vbi_off[] = { 0x00, 0x00 }; +static const unsigned char saa7113_init_auto_input[] = { + 0x01, 0x08, /* PH7113_INCREMENT_DELAY - (1) (1) (1) (1) IDEL3 IDEL2 IDELL1 IDEL0 */ + 0x02, 0xc2, /* PH7113_ANALOG_INPUT_CONTR_1 - FUSE1 FUSE0 GUDL1 GUDL0 MODE3 MODE2 MODE1 MODE0 */ + 0x03, 0x30, /* PH7113_ANALOG_INPUT_CONTR_2 - (1) HLNRS VBSL WPOFF HOLDG GAFIX GAI28 GAI18 */ + 0x04, 0x00, /* PH7113_ANALOG_INPUT_CONTR_3 - GAI17 GAI16 GAI15 GAI14 GAI13 GAI12 GAI11 GAI10 */ + 0x05, 0x00, /* PH7113_ANALOG_INPUT_CONTR_4 - GAI27 GAI26 GAI25 GAI24 GAI23 GAI22 GAI21 GAI20 */ + 0x06, 0x89, /* PH7113_HORIZONTAL_SYNC_START - HSB7 HSB6 HSB5 HSB4 HSB3 HSB2 HSB1 HSB0 */ + 0x07, 0x0d, /* PH7113_HORIZONTAL_SYNC_STOP - HSS7 HSS6 HSS5 HSS4 HSS3 HSS2 HSS1 HSS0 */ + 0x08, 0x88, /* PH7113_SYNC_CONTROL - AUFD FSEL FOET HTC1 HTC0 HPLL VNOI1 VNOI0 */ + 0x09, 0x01, /* PH7113_LUMINANCE_CONTROL - BYPS PREF BPSS1 BPSS0 VBLB UPTCV APER1 APER0 */ + 0x0a, 0x80, /* PH7113_LUMINANCE_BRIGHTNESS - BRIG7 BRIG6 BRIG5 BRIG4 BRIG3 BRIG2 BRIG1 BRIG0 */ + 0x0b, 0x47, /* PH7113_LUMINANCE_CONTRAST - CONT7 CONT6 CONT5 CONT4 CONT3 CONT2 CONT1 CONT0 */ + 0x0c, 0x40, /* PH7113_CHROMA_SATURATION - SATN7 SATN6 SATN5 SATN4 SATN3 SATN2 SATN1 SATN0 */ + 0x0d, 0x00, /* PH7113_CHROMA_HUE_CONTROL - HUEC7 HUEC6 HUEC5 HUEC4 HUEC3 HUEC2 HUEC1 HUEC0 */ + 0x0e, 0x01, /* PH7113_CHROMA_CONTROL - CDTO CSTD2 CSTD1 CSTD0 DCCF FCTC CHBW1 CHBW0 */ + 0x0f, 0x2a, /* PH7113_CHROMA_GAIN_CONTROL - ACGC CGAIN6 CGAIN5 CGAIN4 CGAIN3 CGAIN2 CGAIN1 CGAIN0 */ + 0x10, 0x08, /* PH7113_FORMAT_DELAY_CONTROL - OFTS1 OFTS0 HDEL1 HDEL0 VRLN YDEL2 YDEL1 YDEL0 */ + 0x11, 0x0c, /* PH7113_OUTPUT_CONTROL_1 - GPSW1 CM99 GPSW0 HLSEL OEYC OERT VIPB COLO */ + 0x12, 0x07, /* PH7113_OUTPUT_CONTROL_2 - RTSE13 RTSE12 RTSE11 RTSE10 RTSE03 RTSE02 RTSE01 RTSE00 */ + 0x13, 0x00, /* PH7113_OUTPUT_CONTROL_3 - ADLSB (1) (1) OLDSB FIDP (1) AOSL1 AOSL0 */ + 0x14, 0x00, /* RESERVED 14 - (1) (1) (1) (1) (1) (1) (1) (1) */ + 0x15, 0x00, /* PH7113_V_GATE1_START - VSTA7 VSTA6 VSTA5 VSTA4 VSTA3 VSTA2 VSTA1 VSTA0 */ + 0x16, 0x00, /* PH7113_V_GATE1_STOP - VSTO7 VSTO6 VSTO5 VSTO4 VSTO3 VSTO2 VSTO1 VSTO0 */ + 0x17, 0x00, /* PH7113_V_GATE1_MSB - (1) (1) (1) (1) (1) (1) VSTO8 VSTA8 */ + 0x00, 0x00 +}; + static const unsigned char saa7115_init_misc[] = { 0x38, 0x03, /* audio stuff */ 0x39, 0x10, @@ -680,7 +716,7 @@ static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std) state->std = std; /* restart task B if needed */ - if (taskb && state->ident == V4L2_IDENT_SAA7114) { + if (taskb && state->ident != V4L2_IDENT_SAA7115) { saa7115_writeregs(client, saa7115_cfg_vbi_on); } @@ -703,7 +739,7 @@ static void saa7115_log_status(struct i2c_client *client) int vcr; v4l_info(client, "Audio frequency: %d Hz\n", state->audclk_freq); - if (client->name[6] == '4') { + if (state->ident != V4L2_IDENT_SAA7115) { /* status for the saa7114 */ reg1f = saa7115_read(client, 0x1f); signalOk = (reg1f & 0xc1) == 0x81; @@ -751,8 +787,8 @@ static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo u8 lcr[24]; int i, x; - /* saa7114 doesn't yet support VBI */ - if (state->ident == V4L2_IDENT_SAA7114) + /* saa7113/71144 doesn't yet support VBI */ + if (state->ident != V4L2_IDENT_SAA7115) return; for (i = 0; i <= 23; i++) @@ -1261,14 +1297,12 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) saa7115_write(client, 0, 5); chip_id = saa7115_read(client, 0) & 0x0f; - if (chip_id != 4 && chip_id != 5) { + if (chip_id <3 && chip_id > 5) { v4l_dbg(1, debug, client, "saa7115 not found\n"); kfree(client); return 0; } - if (chip_id == 4) { - snprintf(client->name, sizeof(client->name) - 1, "saa7114"); - } + snprintf(client->name, sizeof(client->name) - 1, "saa711%d",chip_id); v4l_info(client, "saa711%d found @ 0x%x (%s)\n", chip_id, address << 1, adapter->name); state = kzalloc(sizeof(struct saa7115_state), GFP_KERNEL); @@ -1285,13 +1319,27 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) state->contrast = 64; state->hue = 0; state->sat = 64; - state->ident = (chip_id == 4) ? V4L2_IDENT_SAA7114 : V4L2_IDENT_SAA7115; + switch (chip_id) { + case 3: + state->ident = V4L2_IDENT_SAA7113; + break; + case 4: + state->ident = V4L2_IDENT_SAA7114; + break; + default: + state->ident = V4L2_IDENT_SAA7115; + break; + } + state->audclk_freq = 48000; v4l_dbg(1, debug, client, "writing init values\n"); /* init to 60hz/48khz */ - saa7115_writeregs(client, saa7115_init_auto_input); + if (state->ident==V4L2_IDENT_SAA7113) + saa7115_writeregs(client, saa7113_init_auto_input); + else + saa7115_writeregs(client, saa7115_init_auto_input); saa7115_writeregs(client, saa7115_init_misc); saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index c44741e78f20..2360453e7496 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -103,6 +103,7 @@ enum v4l2_chip_ident { V4L2_IDENT_UNKNOWN = 0, /* module saa7115: reserved range 100-149 */ + V4L2_IDENT_SAA7113 = 103, V4L2_IDENT_SAA7114 = 104, V4L2_IDENT_SAA7115 = 105, -- cgit v1.2.3 From 30afc84cf7325e88fb9746340eba3c161080ff49 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 18 Mar 2006 18:40:14 +0900 Subject: [SCSI] libata: implement minimal transport template for ->eh_timed_out SCSI midlayer has moved hostt->eh_timed_out to transport template. As libata doesn't need full-blown transport support yet, implement minimal transport for libata. No transport class or whatsoever, just empty transport template with ->eh_timed_out hook. Signed-off-by: Tejun Heo Signed-off-by: James Bottomley --- drivers/scsi/ahci.c | 1 - drivers/scsi/ata_piix.c | 1 - drivers/scsi/libata-core.c | 3 ++- drivers/scsi/libata-scsi.c | 10 ++++++++++ drivers/scsi/libata.h | 2 ++ drivers/scsi/pdc_adma.c | 1 - drivers/scsi/sata_mv.c | 1 - drivers/scsi/sata_nv.c | 1 - drivers/scsi/sata_promise.c | 1 - drivers/scsi/sata_qstor.c | 1 - drivers/scsi/sata_sil.c | 1 - drivers/scsi/sata_sil24.c | 1 - drivers/scsi/sata_sis.c | 1 - drivers/scsi/sata_svw.c | 1 - drivers/scsi/sata_sx4.c | 1 - drivers/scsi/sata_uli.c | 1 - drivers/scsi/sata_via.c | 1 - drivers/scsi/sata_vsc.c | 1 - include/linux/libata.h | 1 - 19 files changed, 14 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index e97ab3e6de4d..a1ddbba2cbdf 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -207,7 +207,6 @@ static struct scsi_host_template ahci_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 9327b62f97de..a74e23d39ba9 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -209,7 +209,6 @@ static struct scsi_host_template piix_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 714b42bad935..64dce00e9c46 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4653,6 +4653,8 @@ static struct ata_port * ata_host_add(const struct ata_probe_ent *ent, if (!host) return NULL; + host->transportt = &ata_scsi_transport_template; + ap = (struct ata_port *) &host->hostdata[0]; ata_host_init(ap, host, host_set, ent, port_no); @@ -5084,7 +5086,6 @@ EXPORT_SYMBOL_GPL(ata_busy_sleep); EXPORT_SYMBOL_GPL(ata_port_queue_task); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); -EXPORT_SYMBOL_GPL(ata_scsi_timed_out); EXPORT_SYMBOL_GPL(ata_scsi_error); EXPORT_SYMBOL_GPL(ata_scsi_slave_config); EXPORT_SYMBOL_GPL(ata_scsi_release); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index ccedb4536977..bd9f2176f79a 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,7 @@ typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd); static struct ata_device * ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); +enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); #define RW_RECOVERY_MPAGE 0x1 #define RW_RECOVERY_MPAGE_LEN 12 @@ -92,6 +94,14 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = { 0, 30 /* extended self test time, see 05-359r1 */ }; +/* + * libata transport template. libata doesn't do real transport stuff. + * It just needs the eh_timed_out hook. + */ +struct scsi_transport_template ata_scsi_transport_template = { + .eh_timed_out = ata_scsi_timed_out, +}; + static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index f4c48c91b63d..65f52beea884 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -57,6 +57,8 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); /* libata-scsi.c */ +extern struct scsi_transport_template ata_scsi_transport_template; + extern void ata_scsi_scan_host(struct ata_port *ap); extern int ata_scsi_error(struct Scsi_Host *host); extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index 5f33cc932e70..b3dc5f85ae0b 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -143,7 +143,6 @@ static struct scsi_host_template adma_ata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index e561281967dd..874c5be0843c 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -378,7 +378,6 @@ static struct scsi_host_template mv_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = MV_USE_Q_DEPTH, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index caffadc2e0ae..e5b20c6afc18 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -229,7 +229,6 @@ static struct scsi_host_template nv_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 84cb3940ad88..cc928c68a479 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -111,7 +111,6 @@ static struct scsi_host_template pdc_ata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 9602f43a298e..9ffe1ef0d205 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -132,7 +132,6 @@ static struct scsi_host_template qs_ata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 4f2a67ed39d8..3e75d6733239 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -146,7 +146,6 @@ static struct scsi_host_template sil_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 9a53a5ed38c5..5d01e5ce5ac5 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -281,7 +281,6 @@ static struct scsi_host_template sil24_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index 7fd45f86de99..acc8439dea23 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -87,7 +87,6 @@ static struct scsi_host_template sis_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index 4aaccd53e736..051e47d975ca 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -288,7 +288,6 @@ static struct scsi_host_template k2_sata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index 9f8a76815402..ae70f60c7c0d 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -182,7 +182,6 @@ static struct scsi_host_template pdc_sata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index 37a487b7d655..8f5025733def 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -75,7 +75,6 @@ static struct scsi_host_template uli_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index ff65a0b0457f..791bf652ba63 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -94,7 +94,6 @@ static struct scsi_host_template svia_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index b574379a7a82..ee75b9b38ae8 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -251,7 +251,6 @@ static struct scsi_host_template vsc_sata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/include/linux/libata.h b/include/linux/libata.h index 239408ecfddf..204c37a55f06 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -508,7 +508,6 @@ extern void ata_host_set_remove(struct ata_host_set *host_set); extern int ata_scsi_detect(struct scsi_host_template *sht); extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); -extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); extern int ata_scsi_error(struct Scsi_Host *host); extern void ata_eh_qc_complete(struct ata_queued_cmd *qc); extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); -- cgit v1.2.3 From f80658137fc8b789a71953adeca194a5a4747427 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 2 Mar 2006 22:41:59 +0000 Subject: [ARM] Move HZ definition into Kconfig Move the HZ definition into Kconfig, and set appropriate defaults for platforms. Remove mostly empty asm/arch/param.h include file. Signed-off-by: Russell King --- arch/arm/Kconfig | 7 +++++++ include/asm-arm/arch-aaec2000/param.h | 15 --------------- include/asm-arm/arch-at91rm9200/param.h | 28 ---------------------------- include/asm-arm/arch-cl7500/param.h | 5 ----- include/asm-arm/arch-clps711x/param.h | 19 ------------------- include/asm-arm/arch-ebsa110/param.h | 4 ---- include/asm-arm/arch-ebsa285/param.h | 3 --- include/asm-arm/arch-h720x/param.h | 10 ---------- include/asm-arm/arch-imx/param.h | 19 ------------------- include/asm-arm/arch-integrator/param.h | 19 ------------------- include/asm-arm/arch-iop3xx/param.h | 3 --- include/asm-arm/arch-ixp2000/param.h | 3 --- include/asm-arm/arch-ixp4xx/param.h | 3 --- include/asm-arm/arch-l7200/param.h | 19 ------------------- include/asm-arm/arch-lh7a40x/param.h | 9 --------- include/asm-arm/arch-omap/param.h | 8 -------- include/asm-arm/arch-pxa/param.h | 3 --- include/asm-arm/arch-realview/param.h | 19 ------------------- include/asm-arm/arch-rpc/param.h | 3 --- include/asm-arm/arch-s3c2410/param.h | 27 --------------------------- include/asm-arm/arch-sa1100/param.h | 3 --- include/asm-arm/arch-shark/param.h | 5 ----- include/asm-arm/arch-versatile/param.h | 19 ------------------- include/asm-arm/param.h | 7 +------ 24 files changed, 8 insertions(+), 252 deletions(-) delete mode 100644 include/asm-arm/arch-aaec2000/param.h delete mode 100644 include/asm-arm/arch-at91rm9200/param.h delete mode 100644 include/asm-arm/arch-cl7500/param.h delete mode 100644 include/asm-arm/arch-clps711x/param.h delete mode 100644 include/asm-arm/arch-ebsa110/param.h delete mode 100644 include/asm-arm/arch-ebsa285/param.h delete mode 100644 include/asm-arm/arch-h720x/param.h delete mode 100644 include/asm-arm/arch-imx/param.h delete mode 100644 include/asm-arm/arch-integrator/param.h delete mode 100644 include/asm-arm/arch-iop3xx/param.h delete mode 100644 include/asm-arm/arch-ixp2000/param.h delete mode 100644 include/asm-arm/arch-ixp4xx/param.h delete mode 100644 include/asm-arm/arch-l7200/param.h delete mode 100644 include/asm-arm/arch-lh7a40x/param.h delete mode 100644 include/asm-arm/arch-omap/param.h delete mode 100644 include/asm-arm/arch-pxa/param.h delete mode 100644 include/asm-arm/arch-realview/param.h delete mode 100644 include/asm-arm/arch-rpc/param.h delete mode 100644 include/asm-arm/arch-s3c2410/param.h delete mode 100644 include/asm-arm/arch-sa1100/param.h delete mode 100644 include/asm-arm/arch-shark/param.h delete mode 100644 include/asm-arm/arch-versatile/param.h (limited to 'include') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 32ba00bd0a2f..2c63228b4ab6 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -434,6 +434,13 @@ config NO_IDLE_HZ Currently at least OMAP, PXA2xx and SA11x0 platforms are known to have accurate timekeeping with dynamic tick. +config HZ + int + default 128 if ARCH_L7200 + default 200 if ARCH_EBSA110 || ARCH_S3C2410 + default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER_HZ != 0 + default 100 + config AEABI bool "Use the ARM EABI to compile the kernel" help diff --git a/include/asm-arm/arch-aaec2000/param.h b/include/asm-arm/arch-aaec2000/param.h deleted file mode 100644 index 139936c2faf2..000000000000 --- a/include/asm-arm/arch-aaec2000/param.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * linux/include/asm-arm/arch-aaec2000/param.h - * - * Copyright (c) 2005 Nicolas Bellido Y Ortega - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __ASM_ARCH_PARAM_H -#define __ASM_ARCH_PARAM_H - -#endif /* __ASM_ARCH_PARAM_H */ - diff --git a/include/asm-arm/arch-at91rm9200/param.h b/include/asm-arm/arch-at91rm9200/param.h deleted file mode 100644 index 9480f8446852..000000000000 --- a/include/asm-arm/arch-at91rm9200/param.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * include/asm-arm/arch-at91rm9200/param.h - * - * Copyright (C) 2003 SAN People - * - * 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. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __ASM_ARCH_PARAM_H -#define __ASM_ARCH_PARAM_H - -/* - * We use default params - */ - -#endif diff --git a/include/asm-arm/arch-cl7500/param.h b/include/asm-arm/arch-cl7500/param.h deleted file mode 100644 index 974bf69fbb1a..000000000000 --- a/include/asm-arm/arch-cl7500/param.h +++ /dev/null @@ -1,5 +0,0 @@ -/* - * linux/include/asm-arm/arch-cl7500/param.h - * - * Copyright (C) 1999 Nexus Electronics Ltd - */ diff --git a/include/asm-arm/arch-clps711x/param.h b/include/asm-arm/arch-clps711x/param.h deleted file mode 100644 index 86f6bd29623d..000000000000 --- a/include/asm-arm/arch-clps711x/param.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * linux/include/asm-arm/arch-clps711x/param.h - * - * Copyright (C) 2000 Deep Blue Solutions Ltd. - * - * 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. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ diff --git a/include/asm-arm/arch-ebsa110/param.h b/include/asm-arm/arch-ebsa110/param.h deleted file mode 100644 index be19b08d1c75..000000000000 --- a/include/asm-arm/arch-ebsa110/param.h +++ /dev/null @@ -1,4 +0,0 @@ -/* - * linux/include/asm-arm/arch-ebsa110/param.h - */ -#define HZ 200 diff --git a/include/asm-arm/arch-ebsa285/param.h b/include/asm-arm/arch-ebsa285/param.h deleted file mode 100644 index 3827103b27a0..000000000000 --- a/include/asm-arm/arch-ebsa285/param.h +++ /dev/null @@ -1,3 +0,0 @@ -/* - * linux/include/asm-arm/arch-ebsa285/param.h - */ diff --git a/include/asm-arm/arch-h720x/param.h b/include/asm-arm/arch-h720x/param.h deleted file mode 100644 index 2b80235f9847..000000000000 --- a/include/asm-arm/arch-h720x/param.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * linux/include/asm-arm/arch-h720x/param.h - * - * Copyright (C) 2000 Jungjun Kim - */ - -#ifndef __ASM_ARCH_PARAM_H -#define __ASM_ARCH_PARAM_H - -#endif diff --git a/include/asm-arm/arch-imx/param.h b/include/asm-arm/arch-imx/param.h deleted file mode 100644 index 7c724f03333e..000000000000 --- a/include/asm-arm/arch-imx/param.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * linux/include/asm-arm/arch-imx/param.h - * - * Copyright (C) 1999 ARM Limited - * - * 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. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ diff --git a/include/asm-arm/arch-integrator/param.h b/include/asm-arm/arch-integrator/param.h deleted file mode 100644 index afa582ff3717..000000000000 --- a/include/asm-arm/arch-integrator/param.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * linux/include/asm-arm/arch-integrator/param.h - * - * Copyright (C) 1999 ARM Limited - * - * 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. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ diff --git a/include/asm-arm/arch-iop3xx/param.h b/include/asm-arm/arch-iop3xx/param.h deleted file mode 100644 index acf404e87358..000000000000 --- a/include/asm-arm/arch-iop3xx/param.h +++ /dev/null @@ -1,3 +0,0 @@ -/* - * linux/include/asm-arm/arch-iop3xx/param.h - */ diff --git a/include/asm-arm/arch-ixp2000/param.h b/include/asm-arm/arch-ixp2000/param.h deleted file mode 100644 index 2646d9e5919d..000000000000 --- a/include/asm-arm/arch-ixp2000/param.h +++ /dev/null @@ -1,3 +0,0 @@ -/* - * linux/include/asm-arm/arch-ixp2000/param.h - */ diff --git a/include/asm-arm/arch-ixp4xx/param.h b/include/asm-arm/arch-ixp4xx/param.h deleted file mode 100644 index 8a757125e5e7..000000000000 --- a/include/asm-arm/arch-ixp4xx/param.h +++ /dev/null @@ -1,3 +0,0 @@ -/* - * linux/include/asm-arm/arch-ixp4xx/param.h - */ diff --git a/include/asm-arm/arch-l7200/param.h b/include/asm-arm/arch-l7200/param.h deleted file mode 100644 index 9962a12ab158..000000000000 --- a/include/asm-arm/arch-l7200/param.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * linux/include/asm-arm/arch-l7200/param.h - * - * Copyright (C) 2000 Rob Scott (rscott@mtrob.fdns.net) - * Steve Hill (sjhill@cotw.com) - * - * This file contains the hardware definitions for the - * LinkUp Systems L7200 SOC development board. - * - * Changelog: - * 04-21-2000 RS Created L7200 version - * 04-25-2000 SJH Cleaned up file - * 05-03-2000 SJH Change comments and rate - */ - -/* - * See 'time.h' for how the RTC HZ rate is set - */ -#define HZ 128 diff --git a/include/asm-arm/arch-lh7a40x/param.h b/include/asm-arm/arch-lh7a40x/param.h deleted file mode 100644 index acad0bc5deba..000000000000 --- a/include/asm-arm/arch-lh7a40x/param.h +++ /dev/null @@ -1,9 +0,0 @@ -/* include/asm-arm/arch-lh7a40x/param.h - * - * Copyright (C) 2004 Coastal Environmental Systems - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - */ diff --git a/include/asm-arm/arch-omap/param.h b/include/asm-arm/arch-omap/param.h deleted file mode 100644 index face9ad41e97..000000000000 --- a/include/asm-arm/arch-omap/param.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * linux/include/asm-arm/arch-omap/param.h - * - */ - -#ifdef CONFIG_OMAP_32K_TIMER_HZ -#define HZ CONFIG_OMAP_32K_TIMER_HZ -#endif diff --git a/include/asm-arm/arch-pxa/param.h b/include/asm-arm/arch-pxa/param.h deleted file mode 100644 index 3197d82d7573..000000000000 --- a/include/asm-arm/arch-pxa/param.h +++ /dev/null @@ -1,3 +0,0 @@ -/* - * linux/include/asm-arm/arch-pxa/param.h - */ diff --git a/include/asm-arm/arch-realview/param.h b/include/asm-arm/arch-realview/param.h deleted file mode 100644 index 89b1235d32bd..000000000000 --- a/include/asm-arm/arch-realview/param.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * linux/include/asm-arm/arch-realview/param.h - * - * Copyright (C) 2002 ARM Limited - * - * 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. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ diff --git a/include/asm-arm/arch-rpc/param.h b/include/asm-arm/arch-rpc/param.h deleted file mode 100644 index 721dcd658858..000000000000 --- a/include/asm-arm/arch-rpc/param.h +++ /dev/null @@ -1,3 +0,0 @@ -/* - * linux/include/asm-arm/arch-rpc/param.h - */ diff --git a/include/asm-arm/arch-s3c2410/param.h b/include/asm-arm/arch-s3c2410/param.h deleted file mode 100644 index 483d3f149883..000000000000 --- a/include/asm-arm/arch-s3c2410/param.h +++ /dev/null @@ -1,27 +0,0 @@ -/* linux/include/asm-arm/arch-s3c2410/param.h - * - * (c) 2003 Simtec Electronics - * Ben Dooks - * - * S3C2410 - Machine parameters - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Changelog: - * 02-Sep-2003 BJD Created file - * 12-Mar-2004 BJD Added include protection -*/ - -#ifndef __ASM_ARCH_PARAM_H -#define __ASM_ARCH_PARAM_H - -/* we cannot get our timer down to 100Hz with the setup as is, but we can - * manage 200 clock ticks per second... if this is a problem, we can always - * add a software pre-scaler to the evil timer systems. -*/ - -#define HZ 200 - -#endif /* __ASM_ARCH_PARAM_H */ diff --git a/include/asm-arm/arch-sa1100/param.h b/include/asm-arm/arch-sa1100/param.h deleted file mode 100644 index 867488909ecd..000000000000 --- a/include/asm-arm/arch-sa1100/param.h +++ /dev/null @@ -1,3 +0,0 @@ -/* - * linux/include/asm-arm/arch-sa1100/param.h - */ diff --git a/include/asm-arm/arch-shark/param.h b/include/asm-arm/arch-shark/param.h deleted file mode 100644 index 997eeb71de00..000000000000 --- a/include/asm-arm/arch-shark/param.h +++ /dev/null @@ -1,5 +0,0 @@ -/* - * linux/include/asm-arm/arch-shark/param.h - * - * by Alexander Schulz - */ diff --git a/include/asm-arm/arch-versatile/param.h b/include/asm-arm/arch-versatile/param.h deleted file mode 100644 index 34b897335f87..000000000000 --- a/include/asm-arm/arch-versatile/param.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * linux/include/asm-arm/arch-versatile/param.h - * - * Copyright (C) 2002 ARM Limited - * - * 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. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ diff --git a/include/asm-arm/param.h b/include/asm-arm/param.h index 94223d4d7e88..15806468ba72 100644 --- a/include/asm-arm/param.h +++ b/include/asm-arm/param.h @@ -11,12 +11,7 @@ #define __ASM_PARAM_H #ifdef __KERNEL__ -# include /* for kernel version of HZ */ - -# ifndef HZ -# define HZ 100 /* Internal kernel timer frequency */ -# endif - +# define HZ CONFIG_HZ /* Internal kernel timer frequency */ # define USER_HZ 100 /* User interfaces are in "ticks" */ # define CLOCKS_PER_SEC (USER_HZ) /* like times() */ #else -- cgit v1.2.3 From 411ef7f4cf1684ca7977c7917fd841ea091c5b26 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 4 Mar 2006 10:37:07 +0000 Subject: [ARM] Remove asm/arch/irq.h asm/arch/irq.h used to be included from asm/irq.h, but was removed from the ARM kernel a long time ago. Consequently, the contents of asm/arch/irq.h (which mostly contain a definition for fixup_irq()) have not been used. Hence, remove asm/arch/irq.h. Some machine support files incorrectly included this file, making little or no use of the contents. Move the contents to a local include file, and remove those include statements as well. Signed-off-by: Russell King --- arch/arm/mach-lh7a40x/common.h | 1 + arch/arm/mach-lh7a40x/irq-kev7a400.c | 1 + arch/arm/mach-lh7a40x/irq-lh7a400.c | 2 +- arch/arm/mach-lh7a40x/irq-lh7a404.c | 3 ++- arch/arm/mach-lh7a40x/irq-lpd7a40x.c | 1 + arch/arm/mach-pxa/corgi.c | 1 - arch/arm/mach-pxa/poodle.c | 1 - arch/arm/mach-pxa/spitz.c | 1 - arch/arm/mach-pxa/tosa.c | 1 - include/asm-arm/arch-h720x/irq.h | 14 -------------- include/asm-arm/arch-imx/irq.h | 20 -------------------- include/asm-arm/arch-ixp2000/irq.h | 13 ------------- include/asm-arm/arch-ixp4xx/irq.h | 13 ------------- include/asm-arm/arch-lh7a40x/irq.h | 11 ----------- include/asm-arm/arch-pxa/irq.h | 14 -------------- 15 files changed, 6 insertions(+), 91 deletions(-) delete mode 100644 include/asm-arm/arch-h720x/irq.h delete mode 100644 include/asm-arm/arch-imx/irq.h delete mode 100644 include/asm-arm/arch-ixp2000/irq.h delete mode 100644 include/asm-arm/arch-ixp4xx/irq.h delete mode 100644 include/asm-arm/arch-lh7a40x/irq.h delete mode 100644 include/asm-arm/arch-pxa/irq.h (limited to 'include') diff --git a/arch/arm/mach-lh7a40x/common.h b/arch/arm/mach-lh7a40x/common.h index 578a52461fdb..ea8de7e3ab1b 100644 --- a/arch/arm/mach-lh7a40x/common.h +++ b/arch/arm/mach-lh7a40x/common.h @@ -12,5 +12,6 @@ extern struct sys_timer lh7a40x_timer; extern void lh7a400_init_irq (void); extern void lh7a404_init_irq (void); +extern void lh7a40x_init_board_irq (void); #define IRQ_DISPATCH(irq) desc_handle_irq((irq),(irq_desc + irq), regs) diff --git a/arch/arm/mach-lh7a40x/irq-kev7a400.c b/arch/arm/mach-lh7a40x/irq-kev7a400.c index 691bb09232a5..8535764d89ca 100644 --- a/arch/arm/mach-lh7a40x/irq-kev7a400.c +++ b/arch/arm/mach-lh7a40x/irq-kev7a400.c @@ -16,6 +16,7 @@ #include #include +#include "common.h" /* KEV7a400 CPLD IRQ handling */ diff --git a/arch/arm/mach-lh7a40x/irq-lh7a400.c b/arch/arm/mach-lh7a40x/irq-lh7a400.c index f334d81c2cd8..f9fdefef6d6f 100644 --- a/arch/arm/mach-lh7a40x/irq-lh7a400.c +++ b/arch/arm/mach-lh7a40x/irq-lh7a400.c @@ -16,9 +16,9 @@ #include #include #include -#include #include +#include "common.h" /* CPU IRQ handling */ diff --git a/arch/arm/mach-lh7a40x/irq-lh7a404.c b/arch/arm/mach-lh7a40x/irq-lh7a404.c index 122fadabc97d..e902e3d87da4 100644 --- a/arch/arm/mach-lh7a40x/irq-lh7a404.c +++ b/arch/arm/mach-lh7a40x/irq-lh7a404.c @@ -16,9 +16,10 @@ #include #include #include -#include #include +#include "common.h" + #define USE_PRIORITIES /* See Documentation/arm/Sharp-LH/VectoredInterruptController for more diff --git a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c index 6262d449120c..dcb4e17b9419 100644 --- a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c +++ b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c @@ -19,6 +19,7 @@ #include #include +#include "common.h" static void lh7a40x_ack_cpld_irq (u32 irq) { diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 7ffd2de8f2f3..68923b1d2b62 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -32,7 +32,6 @@ #include #include -#include #include #include #include diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 911e6ff5a9bd..b45560a8f6c4 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -29,7 +29,6 @@ #include #include -#include #include #include #include diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index c094d99ebf56..30ec317bbb97 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -33,7 +33,6 @@ #include #include -#include #include #include #include diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index d168286ed470..66ec71756d0f 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -34,7 +34,6 @@ #include #include -#include #include #include diff --git a/include/asm-arm/arch-h720x/irq.h b/include/asm-arm/arch-h720x/irq.h deleted file mode 100644 index b3821e957aa4..000000000000 --- a/include/asm-arm/arch-h720x/irq.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * include/asm-arm/arch-h720x/irq.h - * - * Copyright (C) 2000-2002 Jungjun Kim - * (C) 2003 Robert Schwebel - * (C) 2003 Thomas Gleixner - */ - -#ifndef __ASM_ARCH_IRQ_H -#define __ASM_ARCH_IRQ_H - -extern void __init h720x_init_irq (void); - -#endif /* __ASM_ARCH_IRQ_H */ diff --git a/include/asm-arm/arch-imx/irq.h b/include/asm-arm/arch-imx/irq.h deleted file mode 100644 index 545e065d2325..000000000000 --- a/include/asm-arm/arch-imx/irq.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * linux/include/asm-arm/arch-imxads/irq.h - * - * Copyright (C) 1999 ARM Limited - * - * 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. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#define fixup_irq(i) (i) diff --git a/include/asm-arm/arch-ixp2000/irq.h b/include/asm-arm/arch-ixp2000/irq.h deleted file mode 100644 index ba00b23f9828..000000000000 --- a/include/asm-arm/arch-ixp2000/irq.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * linux/include/asm-arm/arch-ixp2000/irq.h - * - * Copyright (C) 2002 Intel Corp. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#define fixup_irq(irq) (irq) - - diff --git a/include/asm-arm/arch-ixp4xx/irq.h b/include/asm-arm/arch-ixp4xx/irq.h deleted file mode 100644 index 87da70695f0a..000000000000 --- a/include/asm-arm/arch-ixp4xx/irq.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * irq.h - * - * Copyright (C) 2002 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#define fixup_irq(irq) (irq) - diff --git a/include/asm-arm/arch-lh7a40x/irq.h b/include/asm-arm/arch-lh7a40x/irq.h deleted file mode 100644 index 0f5f0b10f6ca..000000000000 --- a/include/asm-arm/arch-lh7a40x/irq.h +++ /dev/null @@ -1,11 +0,0 @@ -/* include/asm-arm/arch-lh7a40x/irq.h - * - * Copyright (C) 2004 Logic Product Development - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - */ - -void __init lh7a40x_init_board_irq (void); diff --git a/include/asm-arm/arch-pxa/irq.h b/include/asm-arm/arch-pxa/irq.h deleted file mode 100644 index 48c60f5eff6a..000000000000 --- a/include/asm-arm/arch-pxa/irq.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * linux/include/asm-arm/arch-pxa/irq.h - * - * Author: Nicolas Pitre - * Created: Jun 15, 2001 - * Copyright: MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#define fixup_irq(x) (x) - -- cgit v1.2.3 From 548153663bbf33ca7c244a6bbddd82c26a17c331 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Mar 2006 15:43:04 +0000 Subject: [ARM] Rename chipdata to 'base' and make it an iomem pointer In all current use cases, "chipdata" is used to store an iomem address. Mark it with __iomem, and rename it to 'base'. Leave the accessor macros alone. Signed-off-by: Russell King --- arch/arm/common/locomo.c | 42 ++++++++++++++++++++--------------------- arch/arm/mach-at91rm9200/gpio.c | 4 ++-- include/asm-arm/mach/irq.h | 6 +++--- 3 files changed, 26 insertions(+), 26 deletions(-) (limited to 'include') diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index 23609400a8e2..787e0d027f04 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c @@ -60,7 +60,7 @@ struct locomo { unsigned long phys; unsigned int irq; spinlock_t lock; - void *base; + void __iomem *base; }; struct locomo_dev_info { @@ -162,7 +162,7 @@ static void locomo_handler(unsigned int irq, struct irqdesc *desc, { int req, i; struct irqdesc *d; - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); /* Acknowledge the parent IRQ */ desc->chip->ack(irq); @@ -189,7 +189,7 @@ static void locomo_ack_irq(unsigned int irq) static void locomo_mask_irq(unsigned int irq) { - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_ICR); r &= ~(0x0010 << (irq - LOCOMO_IRQ_START)); @@ -198,7 +198,7 @@ static void locomo_mask_irq(unsigned int irq) static void locomo_unmask_irq(unsigned int irq) { - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_ICR); r |= (0x0010 << (irq - LOCOMO_IRQ_START)); @@ -215,7 +215,7 @@ static void locomo_key_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { struct irqdesc *d; - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) { d = irq_desc + LOCOMO_IRQ_KEY_START; @@ -225,7 +225,7 @@ static void locomo_key_handler(unsigned int irq, struct irqdesc *desc, static void locomo_key_ack_irq(unsigned int irq) { - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); r &= ~(0x0100 << (irq - LOCOMO_IRQ_KEY_START)); @@ -234,7 +234,7 @@ static void locomo_key_ack_irq(unsigned int irq) static void locomo_key_mask_irq(unsigned int irq) { - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); r &= ~(0x0010 << (irq - LOCOMO_IRQ_KEY_START)); @@ -243,7 +243,7 @@ static void locomo_key_mask_irq(unsigned int irq) static void locomo_key_unmask_irq(unsigned int irq) { - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); r |= (0x0010 << (irq - LOCOMO_IRQ_KEY_START)); @@ -261,7 +261,7 @@ static void locomo_gpio_handler(unsigned int irq, struct irqdesc *desc, { int req, i; struct irqdesc *d; - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); req = locomo_readl(mapbase + LOCOMO_GIR) & locomo_readl(mapbase + LOCOMO_GPD) & @@ -280,7 +280,7 @@ static void locomo_gpio_handler(unsigned int irq, struct irqdesc *desc, static void locomo_gpio_ack_irq(unsigned int irq) { - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_GWE); r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); @@ -297,7 +297,7 @@ static void locomo_gpio_ack_irq(unsigned int irq) static void locomo_gpio_mask_irq(unsigned int irq) { - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_GIE); r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); @@ -306,7 +306,7 @@ static void locomo_gpio_mask_irq(unsigned int irq) static void locomo_gpio_unmask_irq(unsigned int irq) { - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_GIE); r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); @@ -323,7 +323,7 @@ static void locomo_lt_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { struct irqdesc *d; - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) { d = irq_desc + LOCOMO_IRQ_LT_START; @@ -333,7 +333,7 @@ static void locomo_lt_handler(unsigned int irq, struct irqdesc *desc, static void locomo_lt_ack_irq(unsigned int irq) { - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_LTINT); r &= ~(0x0100 << (irq - LOCOMO_IRQ_LT_START)); @@ -342,7 +342,7 @@ static void locomo_lt_ack_irq(unsigned int irq) static void locomo_lt_mask_irq(unsigned int irq) { - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_LTINT); r &= ~(0x0010 << (irq - LOCOMO_IRQ_LT_START)); @@ -351,7 +351,7 @@ static void locomo_lt_mask_irq(unsigned int irq) static void locomo_lt_unmask_irq(unsigned int irq) { - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_LTINT); r |= (0x0010 << (irq - LOCOMO_IRQ_LT_START)); @@ -369,7 +369,7 @@ static void locomo_spi_handler(unsigned int irq, struct irqdesc *desc, { int req, i; struct irqdesc *d; - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); req = locomo_readl(mapbase + LOCOMO_SPIIR) & 0x000F; if (req) { @@ -386,7 +386,7 @@ static void locomo_spi_handler(unsigned int irq, struct irqdesc *desc, static void locomo_spi_ack_irq(unsigned int irq) { - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_SPIWE); r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START)); @@ -403,7 +403,7 @@ static void locomo_spi_ack_irq(unsigned int irq) static void locomo_spi_mask_irq(unsigned int irq) { - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_SPIIE); r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START)); @@ -412,7 +412,7 @@ static void locomo_spi_mask_irq(unsigned int irq) static void locomo_spi_unmask_irq(unsigned int irq) { - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_SPIIE); r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START)); @@ -428,7 +428,7 @@ static struct irqchip locomo_spi_chip = { static void locomo_setup_irq(struct locomo *lchip) { int irq; - void *irqbase = lchip->base; + void __iomem *irqbase = lchip->base; /* * Install handler for IRQ_LOCOMO_HW. diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c index 0e396feec468..5ab46274e1a3 100644 --- a/arch/arm/mach-at91rm9200/gpio.c +++ b/arch/arm/mach-at91rm9200/gpio.c @@ -261,7 +261,7 @@ static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs void __iomem *pio; u32 isr; - pio = (void __force __iomem *) desc->chipdata; + pio = desc->base; /* temporarily mask (level sensitive) parent IRQ */ desc->chip->ack(irq); @@ -312,7 +312,7 @@ void __init at91_gpio_irq_setup(unsigned banks) __raw_writel(~0, controller + PIO_IDR); set_irq_data(id, (void *) pin); - set_irq_chipdata(id, (void __force *) controller); + set_irq_chipdata(id, controller); for (i = 0; i < 32; i++, pin++) { set_irq_chip(pin, &gpio_irqchip); diff --git a/include/asm-arm/mach/irq.h b/include/asm-arm/mach/irq.h index 0ce6ca588d8c..76d05244c632 100644 --- a/include/asm-arm/mach/irq.h +++ b/include/asm-arm/mach/irq.h @@ -61,7 +61,7 @@ struct irqdesc { struct irqchip *chip; struct irqaction *action; struct list_head pend; - void *chipdata; + void __iomem *base; void *data; unsigned int disable_depth; @@ -113,8 +113,8 @@ void __set_irq_handler(unsigned int irq, irq_handler_t, int); #define set_irq_handler(irq,handler) __set_irq_handler(irq,handler,0) #define set_irq_chained_handler(irq,handler) __set_irq_handler(irq,handler,1) #define set_irq_data(irq,d) do { irq_desc[irq].data = d; } while (0) -#define set_irq_chipdata(irq,d) do { irq_desc[irq].chipdata = d; } while (0) -#define get_irq_chipdata(irq) (irq_desc[irq].chipdata) +#define set_irq_chipdata(irq,d) do { irq_desc[irq].base = d; } while (0) +#define get_irq_chipdata(irq) (irq_desc[irq].base) void set_irq_chip(unsigned int irq, struct irqchip *); void set_irq_flags(unsigned int irq, unsigned int flags); -- cgit v1.2.3 From 824b5b5e59472c89bc508afa5c453547c91ed53b Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Mar 2006 15:44:29 +0000 Subject: [ARM] Adapt vic.c to allow for multiple VICs in a system. Some SoCs have multiple VIC devices. Adapt the generic vic code to allow multiple implementations to be handled. Signed-off-by: Russell King --- arch/arm/common/vic.c | 49 +++++++++++++++++++++++------------------- arch/arm/mach-versatile/core.c | 2 +- include/asm-arm/hardware/vic.h | 2 +- 3 files changed, 29 insertions(+), 24 deletions(-) (limited to 'include') diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c index a45ed1687a59..a19bc4a6196d 100644 --- a/arch/arm/common/vic.c +++ b/arch/arm/common/vic.c @@ -22,22 +22,21 @@ #include #include -#include #include #include -static void __iomem *vic_base; - static void vic_mask_irq(unsigned int irq) { - irq -= IRQ_VIC_START; - writel(1 << irq, vic_base + VIC_INT_ENABLE_CLEAR); + void __iomem *base = get_irq_chipdata(irq); + irq &= 31; + writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); } static void vic_unmask_irq(unsigned int irq) { - irq -= IRQ_VIC_START; - writel(1 << irq, vic_base + VIC_INT_ENABLE); + void __iomem *base = get_irq_chipdata(irq); + irq &= 31; + writel(1 << irq, base + VIC_INT_ENABLE); } static struct irqchip vic_chip = { @@ -46,43 +45,49 @@ static struct irqchip vic_chip = { .unmask = vic_unmask_irq, }; -void __init vic_init(void __iomem *base, u32 vic_sources) +/** + * vic_init - initialise a vectored interrupt controller + * @base: iomem base address + * @irq_start: starting interrupt number, must be muliple of 32 + * @vic_sources: bitmask of interrupt sources to allow + */ +void __init vic_init(void __iomem *base, unsigned int irq_start, + u32 vic_sources) { unsigned int i; - vic_base = base; - /* Disable all interrupts initially. */ - writel(0, vic_base + VIC_INT_SELECT); - writel(0, vic_base + VIC_INT_ENABLE); - writel(~0, vic_base + VIC_INT_ENABLE_CLEAR); - writel(0, vic_base + VIC_IRQ_STATUS); - writel(0, vic_base + VIC_ITCR); - writel(~0, vic_base + VIC_INT_SOFT_CLEAR); + writel(0, base + VIC_INT_SELECT); + writel(0, base + VIC_INT_ENABLE); + writel(~0, base + VIC_INT_ENABLE_CLEAR); + writel(0, base + VIC_IRQ_STATUS); + writel(0, base + VIC_ITCR); + writel(~0, base + VIC_INT_SOFT_CLEAR); /* * Make sure we clear all existing interrupts */ - writel(0, vic_base + VIC_VECT_ADDR); + writel(0, base + VIC_VECT_ADDR); for (i = 0; i < 19; i++) { unsigned int value; - value = readl(vic_base + VIC_VECT_ADDR); - writel(value, vic_base + VIC_VECT_ADDR); + value = readl(base + VIC_VECT_ADDR); + writel(value, base + VIC_VECT_ADDR); } for (i = 0; i < 16; i++) { - void __iomem *reg = vic_base + VIC_VECT_CNTL0 + (i * 4); + void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4); writel(VIC_VECT_CNTL_ENABLE | i, reg); } - writel(32, vic_base + VIC_DEF_VECT_ADDR); + writel(32, base + VIC_DEF_VECT_ADDR); for (i = 0; i < 32; i++) { - unsigned int irq = IRQ_VIC_START + i; + unsigned int irq = irq_start + i; set_irq_chip(irq, &vic_chip); + set_irq_chipdata(irq, base); if (vic_sources & (1 << i)) { set_irq_handler(irq, do_level_IRQ); diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 9ebbe808b41d..799697d32dec 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -112,7 +112,7 @@ void __init versatile_init_irq(void) { unsigned int i; - vic_init(VA_VIC_BASE, ~(1 << 31)); + vic_init(VA_VIC_BASE, IRQ_VIC_START, ~(1 << 31)); set_irq_handler(IRQ_VICSOURCE31, sic_handle_irq); enable_irq(IRQ_VICSOURCE31); diff --git a/include/asm-arm/hardware/vic.h b/include/asm-arm/hardware/vic.h index 81825eb54c9e..ed9ca3736a0b 100644 --- a/include/asm-arm/hardware/vic.h +++ b/include/asm-arm/hardware/vic.h @@ -39,7 +39,7 @@ #define VIC_VECT_CNTL_ENABLE (1 << 5) #ifndef __ASSEMBLY__ -void vic_init(void __iomem *base, u32 vic_sources); +void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources); #endif #endif -- cgit v1.2.3 From 22398f57b6372f3150f9ebb4b6d0aa4bf98c5dfb Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Mar 2006 15:55:01 +0000 Subject: [ARM] Fix SA1100 debug-macros.S This needs asm/hardware.h - include it. Signed-off-by: Russell King --- include/asm-arm/arch-sa1100/debug-macro.S | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/asm-arm/arch-sa1100/debug-macro.S b/include/asm-arm/arch-sa1100/debug-macro.S index 755fa3453862..267c317a7408 100644 --- a/include/asm-arm/arch-sa1100/debug-macro.S +++ b/include/asm-arm/arch-sa1100/debug-macro.S @@ -10,6 +10,7 @@ * published by the Free Software Foundation. * */ +#include .macro addruart,rx mrc p15, 0, \rx, c1, c0 -- cgit v1.2.3 From 268099e3ccca5a988632ce18abd21d809d632ddc Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 16 Mar 2006 20:40:25 +0000 Subject: [ARM] Collect 8250-based debug implementations together Several ARM machine implementations used an 8250 compatible port for debugging purposes, and indepdently implemented the low level debug macros every time. Provide a common implementation and convert these implementations to use this version. Signed-off-by: Russell King --- include/asm-arm/arch-cl7500/debug-macro.S | 14 ++------------ include/asm-arm/arch-ebsa110/debug-macro.S | 19 +++---------------- include/asm-arm/arch-ebsa285/debug-macro.S | 18 +++--------------- include/asm-arm/arch-iop3xx/debug-macro.S | 19 +++---------------- include/asm-arm/arch-ixp4xx/debug-macro.S | 15 ++------------- include/asm-arm/arch-pxa/debug-macro.S | 17 ++--------------- include/asm-arm/arch-rpc/debug-macro.S | 19 +++---------------- include/asm-arm/hardware/debug-8250.S | 29 +++++++++++++++++++++++++++++ 8 files changed, 47 insertions(+), 103 deletions(-) create mode 100644 include/asm-arm/hardware/debug-8250.S (limited to 'include') diff --git a/include/asm-arm/arch-cl7500/debug-macro.S b/include/asm-arm/arch-cl7500/debug-macro.S index a5d489d7955a..9a2b67d24098 100644 --- a/include/asm-arm/arch-cl7500/debug-macro.S +++ b/include/asm-arm/arch-cl7500/debug-macro.S @@ -17,15 +17,5 @@ orr \rx, \rx, #0x00000be0 .endm - .macro senduart,rd,rx - strb \rd, [\rx] - .endm - - .macro busyuart,rd,rx - .endm - - .macro waituart,rd,rx -1001: ldrb \rd, [\rx, #0x14] - tst \rd, #0x20 - beq 1001b - .endm +#define UART_SHIFT 2 +#include diff --git a/include/asm-arm/arch-ebsa110/debug-macro.S b/include/asm-arm/arch-ebsa110/debug-macro.S index dcd03a40c502..f61cadabe0ec 100644 --- a/include/asm-arm/arch-ebsa110/debug-macro.S +++ b/include/asm-arm/arch-ebsa110/debug-macro.S @@ -16,19 +16,6 @@ orr \rx, \rx, #0x00000be0 .endm - .macro senduart,rd,rx - strb \rd, [\rx] - .endm - - .macro busyuart,rd,rx -1002: ldrb \rd, [\rx, #0x14] - and \rd, \rd, #0x60 - teq \rd, #0x60 - bne 1002b - .endm - - .macro waituart,rd,rx -1001: ldrb \rd, [\rx, #0x18] - tst \rd, #0x10 - beq 1001b - .endm +#define UART_SHIFT 2 +#define FLOW_CONTROL +#include diff --git a/include/asm-arm/arch-ebsa285/debug-macro.S b/include/asm-arm/arch-ebsa285/debug-macro.S index 97d15fc629af..b48cec4a0c45 100644 --- a/include/asm-arm/arch-ebsa285/debug-macro.S +++ b/include/asm-arm/arch-ebsa285/debug-macro.S @@ -23,22 +23,10 @@ orr \rx, \rx, #0x000003f8 .endm - .macro senduart,rd,rx - strb \rd, [\rx] - .endm +#define UART_SHIFT 0 +#define FLOW_CONTROL +#include - .macro busyuart,rd,rx -1002: ldrb \rd, [\rx, #0x5] - and \rd, \rd, #0x60 - teq \rd, #0x60 - bne 1002b - .endm - - .macro waituart,rd,rx -1001: ldrb \rd, [\rx, #0x6] - tst \rd, #0x10 - beq 1001b - .endm #else /* For EBSA285 debugging */ .equ dc21285_high, ARMCSR_BASE & 0xff000000 diff --git a/include/asm-arm/arch-iop3xx/debug-macro.S b/include/asm-arm/arch-iop3xx/debug-macro.S index cc15f80ebd9a..ce007e531994 100644 --- a/include/asm-arm/arch-iop3xx/debug-macro.S +++ b/include/asm-arm/arch-iop3xx/debug-macro.S @@ -28,21 +28,8 @@ #endif .endm - .macro senduart,rd,rx - strb \rd, [\rx] - .endm - - .macro busyuart,rd,rx -1002: ldrb \rd, [\rx, #0x5] - and \rd, \rd, #0x60 - teq \rd, #0x60 - bne 1002b - .endm - - .macro waituart,rd,rx #if !defined(CONFIG_ARCH_IQ80321) || !defined(CONFIG_ARCH_IQ31244) || !defined(CONFIG_ARCH_IQ80331) -1001: ldrb \rd, [\rx, #0x6] - tst \rd, #0x10 - beq 1001b +#define FLOW_CONTROL #endif - .endm +#define UART_SHIFT 0 +#include diff --git a/include/asm-arm/arch-ixp4xx/debug-macro.S b/include/asm-arm/arch-ixp4xx/debug-macro.S index 2e23651e217f..37bc8ef23e67 100644 --- a/include/asm-arm/arch-ixp4xx/debug-macro.S +++ b/include/asm-arm/arch-ixp4xx/debug-macro.S @@ -20,16 +20,5 @@ @ byte writes used - Big Endian. .endm - .macro senduart,rd,rx - strb \rd, [\rx] - .endm - - .macro waituart,rd,rx -1002: ldrb \rd, [\rx, #0x14] - and \rd, \rd, #0x60 @ check THRE and TEMT bits - teq \rd, #0x60 - bne 1002b - .endm - - .macro busyuart,rd,rx - .endm +#define UART_SHIFT 2 +#include diff --git a/include/asm-arm/arch-pxa/debug-macro.S b/include/asm-arm/arch-pxa/debug-macro.S index b6ec68879176..9012cbc0ad8b 100644 --- a/include/asm-arm/arch-pxa/debug-macro.S +++ b/include/asm-arm/arch-pxa/debug-macro.S @@ -21,18 +21,5 @@ orr \rx, \rx, #0x00100000 .endm - .macro senduart,rd,rx - str \rd, [\rx, #0] - .endm - - .macro busyuart,rd,rx -1002: ldr \rd, [\rx, #0x14] - tst \rd, #(1 << 6) - beq 1002b - .endm - - .macro waituart,rd,rx -1001: ldr \rd, [\rx, #0x14] - tst \rd, #(1 << 5) - beq 1001b - .endm +#define UART_SHIFT 2 +#include diff --git a/include/asm-arm/arch-rpc/debug-macro.S b/include/asm-arm/arch-rpc/debug-macro.S index 456d3d754c3d..c634c8d8f4a1 100644 --- a/include/asm-arm/arch-rpc/debug-macro.S +++ b/include/asm-arm/arch-rpc/debug-macro.S @@ -20,19 +20,6 @@ orr \rx, \rx, #0x00000fe0 .endm - .macro senduart,rd,rx - strb \rd, [\rx] - .endm - - .macro busyuart,rd,rx -1001: ldrb \rd, [\rx, #0x14] - and \rd, \rd, #0x60 - teq \rd, #0x60 - bne 1001b - .endm - - .macro waituart,rd,rx -1001: ldrb \rd, [\rx, #0x18] - tst \rd, #0x10 - beq 1001b - .endm +#define UART_SHIFT 2 +#define FLOW_CONTROL +#include diff --git a/include/asm-arm/hardware/debug-8250.S b/include/asm-arm/hardware/debug-8250.S new file mode 100644 index 000000000000..4594fea91ec1 --- /dev/null +++ b/include/asm-arm/hardware/debug-8250.S @@ -0,0 +1,29 @@ +/* + * linux/include/asm-arm/hardware/debug-8250.h + * + * Copyright (C) 1994-1999 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include + + .macro senduart,rd,rx + strb \rd, [\rx, #UART_TX << UART_SHIFT] + .endm + + .macro busyuart,rd,rx +1002: ldrb \rd, [\rx, #UART_LSR << UART_SHIFT] + and \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE + teq \rd, #UART_LSR_TEMT | UART_LSR_THRE + bne 1002b + .endm + + .macro waituart,rd,rx +#ifdef FLOW_CONTROL +1001: ldrb \rd, [\rx, #UART_MSR << UART_SHIFT] + tst \rd, #UART_MSR_CTS + beq 1001b +#endif + .endm -- cgit v1.2.3 From 71dccd0f158a8077c92d51f213b55991b7a0e47e Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 16 Mar 2006 20:50:34 +0000 Subject: [ARM] Collect Primecell PL01x-based debug implementations together Several ARM machine implementations used a PL01x primecell compatible serial port for debugging purposes, and indepdently implemented the low level debug macros every time. Provide a common implementation and convert these implementations to use this version. Signed-off-by: Russell King --- include/asm-arm/arch-integrator/debug-macro.S | 18 +---------------- include/asm-arm/arch-realview/debug-macro.S | 18 +---------------- include/asm-arm/arch-versatile/debug-macro.S | 18 +---------------- include/asm-arm/hardware/debug-pl01x.S | 29 +++++++++++++++++++++++++++ 4 files changed, 32 insertions(+), 51 deletions(-) create mode 100644 include/asm-arm/hardware/debug-pl01x.S (limited to 'include') diff --git a/include/asm-arm/arch-integrator/debug-macro.S b/include/asm-arm/arch-integrator/debug-macro.S index 031d30941791..85b327c352df 100644 --- a/include/asm-arm/arch-integrator/debug-macro.S +++ b/include/asm-arm/arch-integrator/debug-macro.S @@ -11,8 +11,6 @@ * */ -#include - .macro addruart,rx mrc p15, 0, \rx, c1, c0 tst \rx, #1 @ MMU enabled? @@ -21,18 +19,4 @@ addne \rx, \rx, #0x16000000 >> 4 .endm - .macro senduart,rd,rx - strb \rd, [\rx, #UART01x_DR] - .endm - - .macro waituart,rd,rx -1001: ldr \rd, [\rx, #0x18] @ UARTFLG - tst \rd, #1 << 5 @ UARTFLGUTXFF - 1 when full - bne 1001b - .endm - - .macro busyuart,rd,rx -1001: ldr \rd, [\rx, #0x18] @ UARTFLG - tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy - bne 1001b - .endm +#include diff --git a/include/asm-arm/arch-realview/debug-macro.S b/include/asm-arm/arch-realview/debug-macro.S index 017ad996848d..f17efc65518a 100644 --- a/include/asm-arm/arch-realview/debug-macro.S +++ b/include/asm-arm/arch-realview/debug-macro.S @@ -11,8 +11,6 @@ * */ -#include - .macro addruart,rx mrc p15, 0, \rx, c1, c0 tst \rx, #1 @ MMU enabled? @@ -21,18 +19,4 @@ orr \rx, \rx, #0x00009000 .endm - .macro senduart,rd,rx - strb \rd, [\rx, #UART01x_DR] - .endm - - .macro waituart,rd,rx -1001: ldr \rd, [\rx, #0x18] @ UARTFLG - tst \rd, #1 << 5 @ UARTFLGUTXFF - 1 when full - bne 1001b - .endm - - .macro busyuart,rd,rx -1001: ldr \rd, [\rx, #0x18] @ UARTFLG - tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy - bne 1001b - .endm +#include diff --git a/include/asm-arm/arch-versatile/debug-macro.S b/include/asm-arm/arch-versatile/debug-macro.S index ef6167116dbb..fe106d184e62 100644 --- a/include/asm-arm/arch-versatile/debug-macro.S +++ b/include/asm-arm/arch-versatile/debug-macro.S @@ -11,8 +11,6 @@ * */ -#include - .macro addruart,rx mrc p15, 0, \rx, c1, c0 tst \rx, #1 @ MMU enabled? @@ -22,18 +20,4 @@ orr \rx, \rx, #0x00001000 .endm - .macro senduart,rd,rx - strb \rd, [\rx, #UART01x_DR] - .endm - - .macro waituart,rd,rx -1001: ldr \rd, [\rx, #0x18] @ UARTFLG - tst \rd, #1 << 5 @ UARTFLGUTXFF - 1 when full - bne 1001b - .endm - - .macro busyuart,rd,rx -1001: ldr \rd, [\rx, #0x18] @ UARTFLG - tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy - bne 1001b - .endm +#include diff --git a/include/asm-arm/hardware/debug-pl01x.S b/include/asm-arm/hardware/debug-pl01x.S new file mode 100644 index 000000000000..db0d0f7de5e9 --- /dev/null +++ b/include/asm-arm/hardware/debug-pl01x.S @@ -0,0 +1,29 @@ +/* linux/include/asm-arm/arch-integrator/debug-macro.S + * + * Debugging macro include header + * + * Copyright (C) 1994-1999 Russell King + * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ +#include + + .macro senduart,rd,rx + strb \rd, [\rx, #UART01x_DR] + .endm + + .macro waituart,rd,rx +1001: ldr \rd, [\rx, #UART01x_FR] + tst \rd, #UART01x_FR_TXFF + bne 1001b + .endm + + .macro busyuart,rd,rx +1001: ldr \rd, [\rx, #UART01x_FR] + tst \rd, #UART01x_FR_BUSY + bne 1001b + .endm -- cgit v1.2.3 From a61ea9326d9ba94bcdc21f36bb74aa203657c58f Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 20 Mar 2006 17:10:01 +0000 Subject: [ARM] 3261/2: remove phys_ram from struct machine_desc (part 3) Patch from Nicolas Pitre This field is redundent since it must be equal to PHYS_OFFSET anyway. There is no reference to it anymore so remove it at last. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/kernel/head.S | 7 +++---- include/asm-arm/mach/arch.h | 5 +---- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 1aca1775b28f..84277fe818a1 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -28,10 +28,9 @@ #define PROCINFO_INITFUNC 12 #define MACHINFO_TYPE 0 -#define MACHINFO_PHYSRAM 4 -#define MACHINFO_PHYSIO 8 -#define MACHINFO_PGOFFIO 12 -#define MACHINFO_NAME 16 +#define MACHINFO_PHYSIO 4 +#define MACHINFO_PGOFFIO 8 +#define MACHINFO_NAME 12 #define KERNEL_RAM_ADDR (PAGE_OFFSET + TEXT_OFFSET) diff --git a/include/asm-arm/mach/arch.h b/include/asm-arm/mach/arch.h index 2cd57b4d64d9..fd2f9bf4dcc6 100644 --- a/include/asm-arm/mach/arch.h +++ b/include/asm-arm/mach/arch.h @@ -10,19 +10,16 @@ #ifndef __ASSEMBLY__ -#include - struct tag; struct meminfo; struct sys_timer; struct machine_desc { /* - * Note! The first five elements are used + * Note! The first four elements are used * by assembler code in head-armv.S */ unsigned int nr; /* architecture number */ - unsigned int __deprecated phys_ram; /* start of physical ram */ unsigned int phys_io; /* start of physical io */ unsigned int io_pg_offst; /* byte offset for io * page tabe entry */ -- cgit v1.2.3 From 110d322b29c08d8cf1dba599fd45ad2b9752a4bb Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 20 Mar 2006 17:10:02 +0000 Subject: [ARM] 3327/1: S3C2410 - add osiris machine support Patch from Ben Dooks Support for Simtec IM2440D20 CPU modules (Osiris) Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2410/Kconfig | 7 + arch/arm/mach-s3c2410/Makefile | 1 + arch/arm/mach-s3c2410/mach-osiris.c | 290 +++++++++++++++++++++++++++++ include/asm-arm/arch-s3c2410/osiris-cpld.h | 25 +++ include/asm-arm/arch-s3c2410/osiris-map.h | 41 ++++ 5 files changed, 364 insertions(+) create mode 100644 arch/arm/mach-s3c2410/mach-osiris.c create mode 100644 include/asm-arm/arch-s3c2410/osiris-cpld.h create mode 100644 include/asm-arm/arch-s3c2410/osiris-map.h (limited to 'include') diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index 0b9d7ca49ec1..ed07c4149d82 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig @@ -9,6 +9,13 @@ config MACH_ANUBIS Say Y gere if you are using the Simtec Electronics ANUBIS development system +config MACH_OSIRIS + bool "Simtec IM2440D20 (OSIRIS) module" + select CPU_S3C2440 + help + Say Y here if you are using the Simtec IM2440D20 module, also + known as the Osiris. + config ARCH_BAST bool "Simtec Electronics BAST (EB2410ITX)" select CPU_S3C2410 diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile index 1217bf00309c..1b3b476e5637 100644 --- a/arch/arm/mach-s3c2410/Makefile +++ b/arch/arm/mach-s3c2410/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_BAST_PC104_IRQ) += bast-irq.o # machine specific support obj-$(CONFIG_MACH_ANUBIS) += mach-anubis.o +obj-$(CONFIG_MACH_OSIRIS) += mach-osiris.o obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o obj-$(CONFIG_ARCH_H1940) += mach-h1940.o obj-$(CONFIG_MACH_N30) += mach-n30.o diff --git a/arch/arm/mach-s3c2410/mach-osiris.c b/arch/arm/mach-s3c2410/mach-osiris.c new file mode 100644 index 000000000000..72083e645e77 --- /dev/null +++ b/arch/arm/mach-s3c2410/mach-osiris.c @@ -0,0 +1,290 @@ +/* linux/arch/arm/mach-s3c2410/mach-osiris.c + * + * Copyright (c) 2005 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "clock.h" +#include "devs.h" +#include "cpu.h" + +/* onboard perihpheral map */ + +static struct map_desc osiris_iodesc[] __initdata = { + /* ISA IO areas (may be over-written later) */ + + { + .virtual = (u32)S3C24XX_VA_ISA_BYTE, + .pfn = __phys_to_pfn(S3C2410_CS5), + .length = SZ_16M, + .type = MT_DEVICE, + }, { + .virtual = (u32)S3C24XX_VA_ISA_WORD, + .pfn = __phys_to_pfn(S3C2410_CS5), + .length = SZ_16M, + .type = MT_DEVICE, + }, + + /* CPLD control registers */ + + { + .virtual = (u32)OSIRIS_VA_CTRL1, + .pfn = __phys_to_pfn(OSIRIS_PA_CTRL1), + .length = SZ_16K, + .type = MT_DEVICE + }, { + .virtual = (u32)OSIRIS_VA_CTRL2, + .pfn = __phys_to_pfn(OSIRIS_PA_CTRL2), + .length = SZ_16K, + .type = MT_DEVICE + }, +}; + +#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK +#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB +#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE + +static struct s3c24xx_uart_clksrc osiris_serial_clocks[] = { + [0] = { + .name = "uclk", + .divisor = 1, + .min_baud = 0, + .max_baud = 0, + }, + [1] = { + .name = "pclk", + .divisor = 1, + .min_baud = 0, + .max_baud = 0. + } +}; + + +static struct s3c2410_uartcfg osiris_uartcfgs[] = { + [0] = { + .hwport = 0, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, + .clocks = osiris_serial_clocks, + .clocks_size = ARRAY_SIZE(osiris_serial_clocks) + }, + [1] = { + .hwport = 2, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, + .clocks = osiris_serial_clocks, + .clocks_size = ARRAY_SIZE(osiris_serial_clocks) + }, +}; + +/* NAND Flash on Osiris board */ + +static int external_map[] = { 2 }; +static int chip0_map[] = { 0 }; +static int chip1_map[] = { 1 }; + +struct mtd_partition osiris_default_nand_part[] = { + [0] = { + .name = "Boot Agent", + .size = SZ_16K, + .offset = 0 + }, + [1] = { + .name = "/boot", + .size = SZ_4M - SZ_16K, + .offset = SZ_16K, + }, + [2] = { + .name = "user1", + .offset = SZ_4M, + .size = SZ_32M - SZ_4M, + }, + [3] = { + .name = "user2", + .offset = SZ_32M, + .size = MTDPART_SIZ_FULL, + } +}; + +/* the Osiris has 3 selectable slots for nand-flash, the two + * on-board chip areas, as well as the external slot. + * + * Note, there is no current hot-plug support for the External + * socket. +*/ + +static struct s3c2410_nand_set osiris_nand_sets[] = { + [1] = { + .name = "External", + .nr_chips = 1, + .nr_map = external_map, + .nr_partitions = ARRAY_SIZE(osiris_default_nand_part), + .partitions = osiris_default_nand_part + }, + [0] = { + .name = "chip0", + .nr_chips = 1, + .nr_map = chip0_map, + .nr_partitions = ARRAY_SIZE(osiris_default_nand_part), + .partitions = osiris_default_nand_part + }, + [2] = { + .name = "chip1", + .nr_chips = 1, + .nr_map = chip1_map, + .nr_partitions = ARRAY_SIZE(osiris_default_nand_part), + .partitions = osiris_default_nand_part + }, +}; + +static void osiris_nand_select(struct s3c2410_nand_set *set, int slot) +{ + unsigned int tmp; + + slot = set->nr_map[slot] & 3; + + pr_debug("osiris_nand: selecting slot %d (set %p,%p)\n", + slot, set, set->nr_map); + + tmp = __raw_readb(OSIRIS_VA_CTRL1); + tmp &= ~OSIRIS_CTRL1_NANDSEL; + tmp |= slot; + + pr_debug("osiris_nand: ctrl1 now %02x\n", tmp); + + __raw_writeb(tmp, OSIRIS_VA_CTRL1); +} + +static struct s3c2410_platform_nand osiris_nand_info = { + .tacls = 25, + .twrph0 = 60, + .twrph1 = 60, + .nr_sets = ARRAY_SIZE(osiris_nand_sets), + .sets = osiris_nand_sets, + .select_chip = osiris_nand_select, +}; + +/* PCMCIA control and configuration */ + +static struct resource osiris_pcmcia_resource[] = { + [0] = { + .start = 0x0f000000, + .end = 0x0f100000, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 0x0c000000, + .end = 0x0c100000, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device osiris_pcmcia = { + .name = "osiris-pcmcia", + .id = -1, + .num_resources = ARRAY_SIZE(osiris_pcmcia_resource), + .resource = osiris_pcmcia_resource, +}; + +/* Standard Osiris devices */ + +static struct platform_device *osiris_devices[] __initdata = { + &s3c_device_i2c, + &s3c_device_nand, + &osiris_pcmcia, +}; + +static struct clk *osiris_clocks[] = { + &s3c24xx_dclk0, + &s3c24xx_dclk1, + &s3c24xx_clkout0, + &s3c24xx_clkout1, + &s3c24xx_uclk, +}; + +static struct s3c24xx_board osiris_board __initdata = { + .devices = osiris_devices, + .devices_count = ARRAY_SIZE(osiris_devices), + .clocks = osiris_clocks, + .clocks_count = ARRAY_SIZE(osiris_clocks) +}; + +void __init osiris_map_io(void) +{ + /* initialise the clocks */ + + s3c24xx_dclk0.parent = NULL; + s3c24xx_dclk0.rate = 12*1000*1000; + + s3c24xx_dclk1.parent = NULL; + s3c24xx_dclk1.rate = 24*1000*1000; + + s3c24xx_clkout0.parent = &s3c24xx_dclk0; + s3c24xx_clkout1.parent = &s3c24xx_dclk1; + + s3c24xx_uclk.parent = &s3c24xx_clkout1; + + s3c_device_nand.dev.platform_data = &osiris_nand_info; + + s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc)); + s3c24xx_init_clocks(0); + s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs)); + s3c24xx_set_board(&osiris_board); + + /* fix bus configuration (nBE settings wrong on ABLE pre v2.20) */ + __raw_writel(__raw_readl(S3C2410_BWSCON) | S3C2410_BWSCON_ST1 | S3C2410_BWSCON_ST2 | S3C2410_BWSCON_ST3 | S3C2410_BWSCON_ST4 | S3C2410_BWSCON_ST5, S3C2410_BWSCON); + + /* write-protect line to the NAND */ + s3c2410_gpio_setpin(S3C2410_GPA0, 1); +} + +MACHINE_START(OSIRIS, "Simtec-OSIRIS") + /* Maintainer: Ben Dooks */ + .phys_ram = S3C2410_SDRAM_PA, + .phys_io = S3C2410_PA_UART, + .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, + .boot_params = S3C2410_SDRAM_PA + 0x100, + .map_io = osiris_map_io, + .init_irq = s3c24xx_init_irq, + .timer = &s3c24xx_timer, +MACHINE_END diff --git a/include/asm-arm/arch-s3c2410/osiris-cpld.h b/include/asm-arm/arch-s3c2410/osiris-cpld.h new file mode 100644 index 000000000000..e9d1ae1f354f --- /dev/null +++ b/include/asm-arm/arch-s3c2410/osiris-cpld.h @@ -0,0 +1,25 @@ +/* linux/include/asm-arm/arch-s3c2410/osiris-cpld.h + * + * (c) 2005 Simtec Electronics + * http://www.simtec.co.uk/products/ + * Ben Dooks + * + * OSIRIS - CPLD control constants + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_OSIRISCPLD_H +#define __ASM_ARCH_OSIRISCPLD_H + +/* CTRL1 - NAND WP control */ + +#define OSIRIS_CTRL1_NANDSEL (0x3) +#define OSIRIS_CTRL1_BOOT_INT (1<<3) +#define OSIRIS_CTRL1_PCMCIA (1<<4) +#define OSIRIS_CTRL1_PCMCIA_nWAIT (1<<6) +#define OSIRIS_CTRL1_PCMCIA_nIOIS16 (1<<7) + +#endif /* __ASM_ARCH_OSIRISCPLD_H */ diff --git a/include/asm-arm/arch-s3c2410/osiris-map.h b/include/asm-arm/arch-s3c2410/osiris-map.h new file mode 100644 index 000000000000..7c4b0cd2d14d --- /dev/null +++ b/include/asm-arm/arch-s3c2410/osiris-map.h @@ -0,0 +1,41 @@ +/* linux/include/asm-arm/arch-s3c2410/osiris-map.h + * + * (c) 2005 Simtec Electronics + * http://www.simtec.co.uk/products/ + * Ben Dooks + * + * OSIRIS - Memory map definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Changelog: +*/ + +/* needs arch/map.h including with this */ + +#ifndef __ASM_ARCH_OSIRISMAP_H +#define __ASM_ARCH_OSIRISMAP_H + +/* start peripherals off after the S3C2410 */ + +#define OSIRIS_IOADDR(x) (S3C2410_ADDR((x) + 0x05000000)) + +#define OSIRIS_PA_CPLD (S3C2410_CS1 | (3<<25)) + +/* we put the CPLD registers next, to get them out of the way */ + +#define OSIRIS_VA_CTRL1 OSIRIS_IOADDR(0x00000000) /* 0x01300000 */ +#define OSIRIS_PA_CTRL1 (OSIRIS_PA_CPLD) + +#define OSIRIS_VA_CTRL2 OSIRIS_IOADDR(0x00100000) /* 0x01400000 */ +#define OSIRIS_PA_CTRL2 (OSIRIS_PA_CPLD + (1<<24)) + +#define OSIRIS_VA_CTRL3 OSIRIS_IOADDR(0x00200000) /* 0x01500000 */ +#define OSIRIS_PA_CTRL3 (OSIRIS_PA_CPLD + (2<<24)) + +#define OSIRIS_VA_CTRL4 OSIRIS_IOADDR(0x00300000) /* 0x01600000 */ +#define OSIRIS_PA_CTRL4 (OSIRIS_PA_CPLD + (3<<24)) + +#endif /* __ASM_ARCH_OSIRISMAP_H */ -- cgit v1.2.3 From 3fc3e1c0640887f883c28330e9d35145d23b2696 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 20 Mar 2006 17:10:07 +0000 Subject: [ARM] 3333/1: S3C2XX - add dclk and clkout clock support Patch from Ben Dooks Add enable and set_parent calls for the dclk and clkout clocks. Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2410/clock.c | 94 +++++++++++++++++++++++++++++++- include/asm-arm/arch-s3c2410/regs-gpio.h | 2 + 2 files changed, 95 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c index 773b7aec3e99..e205a6316b08 100644 --- a/arch/arm/mach-s3c2410/clock.c +++ b/arch/arm/mach-s3c2410/clock.c @@ -45,6 +45,7 @@ #include #include +#include #include "clock.h" #include "cpu.h" @@ -285,24 +286,115 @@ static struct clk clk_p = { /* clocks that could be registered by external code */ +static int s3c24xx_dclk_enable(struct clk *clk, int enable) +{ + unsigned long dclkcon = __raw_readl(S3C2410_DCLKCON); + + if (enable) + dclkcon |= clk->ctrlbit; + else + dclkcon &= ~clk->ctrlbit; + + __raw_writel(dclkcon, S3C2410_DCLKCON); + + return 0; +} + +static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent) +{ + unsigned long dclkcon; + unsigned int uclk; + + if (parent == &clk_upll) + uclk = 1; + else if (parent == &clk_p) + uclk = 0; + else + return -EINVAL; + + clk->parent = parent; + + dclkcon = __raw_readl(S3C2410_DCLKCON); + + if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) { + if (uclk) + dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK; + else + dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK; + } else { + if (uclk) + dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK; + else + dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK; + } + + __raw_writel(dclkcon, S3C2410_DCLKCON); + + return 0; +} + + +static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent) +{ + unsigned long mask; + unsigned long source; + + /* calculate the MISCCR setting for the clock */ + + if (parent == &clk_xtal) + source = S3C2410_MISCCR_CLK0_MPLL; + else if (parent == &clk_upll) + source = S3C2410_MISCCR_CLK0_UPLL; + else if (parent == &clk_f) + source = S3C2410_MISCCR_CLK0_FCLK; + else if (parent == &clk_p) + source = S3C2410_MISCCR_CLK0_PCLK; + else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0) + source = S3C2410_MISCCR_CLK0_DCLK0; + else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1) + source = S3C2410_MISCCR_CLK0_DCLK0; + else + return -EINVAL; + + if (clk == &s3c24xx_dclk0) + mask = S3C2410_MISCCR_CLK0_MASK; + else { + source <<= 4; + mask = S3C2410_MISCCR_CLK1_MASK; + } + + s3c2410_modify_misccr(mask, source); + return 0; +} + +/* external clock definitions */ + struct clk s3c24xx_dclk0 = { .name = "dclk0", .id = -1, + .ctrlbit = S3C2410_DCLKCON_DCLK0EN, + .enable = s3c24xx_dclk_enable, + .set_parent = s3c24xx_dclk_setparent, }; struct clk s3c24xx_dclk1 = { .name = "dclk1", .id = -1, + .ctrlbit = S3C2410_DCLKCON_DCLK0EN, + .enable = s3c24xx_dclk_enable, + .set_parent = s3c24xx_dclk_setparent, }; struct clk s3c24xx_clkout0 = { .name = "clkout0", .id = -1, + .set_parent = s3c24xx_clkout_setparent, }; struct clk s3c24xx_clkout1 = { .name = "clkout1", .id = -1, + .set_parent = s3c24xx_clkout_setparent, }; struct clk s3c24xx_uclk = { @@ -423,7 +515,7 @@ int s3c24xx_register_clock(struct clk *clk) /* if this is a standard clock, set the usage state */ - if (clk->ctrlbit) { + if (clk->ctrlbit && clk->enable == s3c24xx_clkcon_enable) { unsigned long clkcon = __raw_readl(S3C2410_CLKCON); clk->usage = (clkcon & clk->ctrlbit) ? 1 : 0; diff --git a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h index 9697f93afe74..d2574084697f 100644 --- a/include/asm-arm/arch-s3c2410/regs-gpio.h +++ b/include/asm-arm/arch-s3c2410/regs-gpio.h @@ -979,6 +979,7 @@ #define S3C2410_MISCCR_CLK0_HCLK (3<<4) #define S3C2410_MISCCR_CLK0_PCLK (4<<4) #define S3C2410_MISCCR_CLK0_DCLK0 (5<<4) +#define S3C2410_MISCCR_CLK0_MASK (7<<4) #define S3C2410_MISCCR_CLK1_MPLL (0<<8) #define S3C2410_MISCCR_CLK1_UPLL (1<<8) @@ -986,6 +987,7 @@ #define S3C2410_MISCCR_CLK1_HCLK (3<<8) #define S3C2410_MISCCR_CLK1_PCLK (4<<8) #define S3C2410_MISCCR_CLK1_DCLK1 (5<<8) +#define S3C2410_MISCCR_CLK1_MASK (7<<8) #define S3C2410_MISCCR_USBSUSPND0 (1<<12) #define S3C2410_MISCCR_USBSUSPND1 (1<<13) -- cgit v1.2.3 From 0328ad23cfd8a0501f44a1b83e49d5b0e47e2b3c Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Mon, 20 Mar 2006 17:10:08 +0000 Subject: [ARM] 3334/1: Add support for IXDP28x5 platforms Patch from Deepak Saxena This patch adds support for Intel's IXDP28x5 platform. This is just and IXDP2801 with a new CPU rev but the bootloader has been updated to reflect a new machine ID so we just build support for it by default when we build IXDP2801. Signed-off-by: Deepak Saxena Signed-off-by: Russell King --- arch/arm/mach-ixp2000/Kconfig | 9 +++++++-- arch/arm/mach-ixp2000/ixdp2x01.c | 20 ++++++++++++++++++-- include/asm-arm/arch-ixp2000/system.h | 2 +- 3 files changed, 26 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/arch/arm/mach-ixp2000/Kconfig b/arch/arm/mach-ixp2000/Kconfig index ecb58d83478e..86f53f8ccbf5 100644 --- a/arch/arm/mach-ixp2000/Kconfig +++ b/arch/arm/mach-ixp2000/Kconfig @@ -43,12 +43,17 @@ config ARCH_IXDP2401 this platform, see . config ARCH_IXDP2801 - bool "Support Intel IXDP2801" + bool "Support Intel IXDP2801 and IXDP28x5" help Say 'Y' here if you want your kernel to support the Intel - IXDP2801 reference platform. For more information on + IXDP2801/2805/2855 reference platforms. For more information on this platform, see . +config MACH_IXDP28X5 + bool + depends on ARCH_IXDP2801 + default y + config ARCH_IXDP2X01 bool depends on ARCH_IXDP2401 || ARCH_IXDP2801 diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c index 150519fb38ec..f9d4968c1d66 100644 --- a/arch/arm/mach-ixp2000/ixdp2x01.c +++ b/arch/arm/mach-ixp2000/ixdp2x01.c @@ -284,7 +284,7 @@ static int ixdp2x01_pci_setup(int nr, struct pci_sys_data *sys) { sys->mem_offset = 0xe0000000; - if (machine_is_ixdp2801()) + if (machine_is_ixdp2801() || machine_is_ixdp28x5()) sys->mem_offset -= ((*IXP2000_PCI_ADDR_EXT & 0xE000) << 16); return ixp2000_pci_setup(nr, sys); @@ -300,7 +300,8 @@ struct hw_pci ixdp2x01_pci __initdata = { int __init ixdp2x01_pci_init(void) { - if (machine_is_ixdp2401() || machine_is_ixdp2801()) + if (machine_is_ixdp2401() || machine_is_ixdp2801() ||\ + machine_is_ixdp28x5()) pci_common_init(&ixdp2x01_pci); return 0; @@ -400,6 +401,21 @@ MACHINE_START(IXDP2801, "Intel IXDP2801 Development Platform") .timer = &ixdp2x01_timer, .init_machine = ixdp2x01_init_machine, MACHINE_END + +/* + * IXDP28x5 is basically an IXDP2801 with a different CPU but Intel + * changed the machine ID in the bootloader + */ +MACHINE_START(IXDP28X5, "Intel IXDP2805/2855 Development Platform") + /* Maintainer: MontaVista Software, Inc. */ + .phys_io = IXP2000_UART_PHYS_BASE, + .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = ixdp2x01_map_io, + .init_irq = ixdp2x01_init_irq, + .timer = &ixdp2x01_timer, + .init_machine = ixdp2x01_init_machine, +MACHINE_END #endif diff --git a/include/asm-arm/arch-ixp2000/system.h b/include/asm-arm/arch-ixp2000/system.h index ddbbb34b5f95..3cc9a04f68cb 100644 --- a/include/asm-arm/arch-ixp2000/system.h +++ b/include/asm-arm/arch-ixp2000/system.h @@ -37,7 +37,7 @@ static inline void arch_reset(char mode) * to cause a complete reset of the CPU and all external devices * and move the flash bank register back to 0. */ - if (machine_is_ixdp2801()) { + if (machine_is_ixdp2801() || machine_is_ixdp28x5()) { unsigned long reset_reg = *IXDP2X01_CPLD_RESET_REG; reset_reg = 0x55AA0000 | (reset_reg & 0x0000FFFF); -- cgit v1.2.3 From 6d4518d76f9612d580f9423cc0c3364a06b69588 Mon Sep 17 00:00:00 2001 From: Peter Teichmann Date: Mon, 20 Mar 2006 17:10:09 +0000 Subject: [ARM] 3346/1: Fix udelay() for HZ values different from 100 Patch from Peter Teichmann Currently, if the kernels HZ value is greater than 100, delays with the udelay function are too short. This can cause trouble for instance with the zd1201 usb wlan driver. This patch suggests a solution that keeps the overhead small and maintains (hopefully) sufficient resolution. Signed-off-by: Peter Teichmann Signed-off-by: Russell King --- arch/arm/lib/delay.S | 20 ++++++++++++-------- include/asm-arm/delay.h | 12 +++++++----- 2 files changed, 19 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/arch/arm/lib/delay.S b/arch/arm/lib/delay.S index b3fb475b4120..9183b06c0e2f 100644 --- a/arch/arm/lib/delay.S +++ b/arch/arm/lib/delay.S @@ -9,28 +9,32 @@ */ #include #include +#include .text .LC0: .word loops_per_jiffy +.LC1: .word (2199023*HZ)>>11 /* - * 0 <= r0 <= 2000 + * r0 <= 2000 + * lpj <= 0x01ffffff (max. 3355 bogomips) + * HZ <= 1000 */ + ENTRY(__udelay) - mov r2, #0x6800 - orr r2, r2, #0x00db + ldr r2, .LC1 mul r0, r2, r0 -ENTRY(__const_udelay) @ 0 <= r0 <= 0x01ffffff +ENTRY(__const_udelay) @ 0 <= r0 <= 0x7fffff06 ldr r2, .LC0 - ldr r2, [r2] @ max = 0x0fffffff - mov r0, r0, lsr #11 @ max = 0x00003fff - mov r2, r2, lsr #11 @ max = 0x0003ffff + ldr r2, [r2] @ max = 0x01ffffff + mov r0, r0, lsr #14 @ max = 0x0001ffff + mov r2, r2, lsr #10 @ max = 0x00007fff mul r0, r2, r0 @ max = 2^32-1 movs r0, r0, lsr #6 RETINSTR(moveq,pc,lr) /* - * loops = (r0 * 0x10c6 * 100 * loops_per_jiffy) / 2^32 + * loops = r0 * HZ * loops_per_jiffy / 1000000 * * Oh, if only we had a cycle counter... */ diff --git a/include/asm-arm/delay.h b/include/asm-arm/delay.h index 1704360e9699..b2deda181549 100644 --- a/include/asm-arm/delay.h +++ b/include/asm-arm/delay.h @@ -6,6 +6,8 @@ #ifndef __ASM_ARM_DELAY_H #define __ASM_ARM_DELAY_H +#include /* HZ */ + extern void __delay(int loops); /* @@ -13,7 +15,7 @@ extern void __delay(int loops); * it, it means that you're calling udelay() with an out of range value. * * With currently imposed limits, this means that we support a max delay - * of 2000us and 671 bogomips + * of 2000us. Further limits: HZ<=1000 and bogomips<=3355 */ extern void __bad_udelay(void); @@ -32,10 +34,10 @@ extern void __const_udelay(unsigned long); #define MAX_UDELAY_MS 2 -#define udelay(n) \ - (__builtin_constant_p(n) ? \ - ((n) > (MAX_UDELAY_MS * 1000) ? __bad_udelay() : \ - __const_udelay((n) * 0x68dbul)) : \ +#define udelay(n) \ + (__builtin_constant_p(n) ? \ + ((n) > (MAX_UDELAY_MS * 1000) ? __bad_udelay() : \ + __const_udelay((n) * ((2199023U*HZ)>>11))) : \ __udelay(n)) #endif /* defined(_ARM_DELAY_H) */ -- cgit v1.2.3 From 03bd14c4b7fa535c78f17751172dbe8937729f05 Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Mon, 20 Mar 2006 17:10:10 +0000 Subject: [ARM] 3349/1: ixp4xx exp bus defines Patch from Alessandro Zummo This patch adds a few defines that are useful to configure the CS regions on ixp4xx. Signed-off-by: Alessandro Zummo Signed-off-by: OEyvind Repvik Signed-off-by: Deepak Saxena Signed-off-by: Russell King --- include/asm-arm/arch-ixp4xx/platform.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'include') diff --git a/include/asm-arm/arch-ixp4xx/platform.h b/include/asm-arm/arch-ixp4xx/platform.h index daf9790645ca..13aee17b0475 100644 --- a/include/asm-arm/arch-ixp4xx/platform.h +++ b/include/asm-arm/arch-ixp4xx/platform.h @@ -38,6 +38,33 @@ extern unsigned long ixp4xx_exp_bus_size; #define IXP4XX_EXP_BUS_BASE(region)\ (IXP4XX_EXP_BUS_BASE_PHYS + ((region) * ixp4xx_exp_bus_size)) +#define IXP4XX_EXP_BUS_END(region)\ + (IXP4XX_EXP_BUS_BASE(region) + ixp4xx_exp_bus_size - 1) + +/* Those macros can be used to adjust timing and configure + * other features for each region. + */ + +#define IXP4XX_EXP_BUS_RECOVERY_T(x) (((x) & 0x0f) << 16) +#define IXP4XX_EXP_BUS_HOLD_T(x) (((x) & 0x03) << 20) +#define IXP4XX_EXP_BUS_STROBE_T(x) (((x) & 0x0f) << 22) +#define IXP4XX_EXP_BUS_SETUP_T(x) (((x) & 0x03) << 26) +#define IXP4XX_EXP_BUS_ADDR_T(x) (((x) & 0x03) << 28) +#define IXP4XX_EXP_BUS_SIZE(x) (((x) & 0x0f) << 10) +#define IXP4XX_EXP_BUS_CYCLES(x) (((x) & 0x03) << 14) + +#define IXP4XX_EXP_BUS_CS_EN (1L << 31) +#define IXP4XX_EXP_BUS_BYTE_RD16 (1L << 6) +#define IXP4XX_EXP_BUS_HRDY_POL (1L << 5) +#define IXP4XX_EXP_BUS_MUX_EN (1L << 4) +#define IXP4XX_EXP_BUS_SPLT_EN (1L << 3) +#define IXP4XX_EXP_BUS_WR_EN (1L << 1) +#define IXP4XX_EXP_BUS_BYTE_EN (1L << 0) + +#define IXP4XX_EXP_BUS_CYCLES_INTEL 0x00 +#define IXP4XX_EXP_BUS_CYCLES_MOTOROLA 0x01 +#define IXP4XX_EXP_BUS_CYCLES_HPI 0x02 + #define IXP4XX_FLASH_WRITABLE (0x2) #define IXP4XX_FLASH_DEFAULT (0xbcd23c40) #define IXP4XX_FLASH_WRITE (0xbcd23c42) -- cgit v1.2.3 From e7736d47a11a771ba87314be563b2cb6b8d11d14 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 20 Mar 2006 17:10:13 +0000 Subject: [ARM] 3369/1: ep93xx: add core cirrus ep93xx support Patch from Lennert Buytenhek This patch adds support for the Cirrus ep93xx series of CPUs. The ep93xx is an ARM920T based CPU with two VICs, PL010 based UARTs, IrDA, MaverickCrunch floating point coprocessor, between 24 and 64 GPIOs, ethernet, OHCI USB and, depending on the model, pcmcia, raster engine, graphics accelerator, IDE controller and a bunch of other stuff. This patch adds the core ep93xx support code, and support for the Glomation GESBC-9312-sx and the Technologic Systems TS-72xx SBCs. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/Kconfig | 9 ++ arch/arm/Makefile | 1 + arch/arm/mach-ep93xx/Kconfig | 21 ++++ arch/arm/mach-ep93xx/Makefile | 10 ++ arch/arm/mach-ep93xx/Makefile.boot | 2 + arch/arm/mach-ep93xx/core.c | 173 ++++++++++++++++++++++++++++++ arch/arm/mach-ep93xx/gesbc9312.c | 40 +++++++ arch/arm/mach-ep93xx/ts72xx.c | 118 ++++++++++++++++++++ arch/arm/mm/Kconfig | 2 +- include/asm-arm/arch-ep93xx/debug-macro.S | 22 ++++ include/asm-arm/arch-ep93xx/dma.h | 3 + include/asm-arm/arch-ep93xx/entry-macro.S | 53 +++++++++ include/asm-arm/arch-ep93xx/ep93xx-regs.h | 114 ++++++++++++++++++++ include/asm-arm/arch-ep93xx/gesbc9312.h | 3 + include/asm-arm/arch-ep93xx/hardware.h | 12 +++ include/asm-arm/arch-ep93xx/io.h | 8 ++ include/asm-arm/arch-ep93xx/irqs.h | 78 ++++++++++++++ include/asm-arm/arch-ep93xx/memory.h | 14 +++ include/asm-arm/arch-ep93xx/platform.h | 14 +++ include/asm-arm/arch-ep93xx/system.h | 26 +++++ include/asm-arm/arch-ep93xx/timex.h | 5 + include/asm-arm/arch-ep93xx/ts72xx.h | 90 ++++++++++++++++ include/asm-arm/arch-ep93xx/uncompress.h | 53 +++++++++ include/asm-arm/arch-ep93xx/vmalloc.h | 5 + 24 files changed, 875 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-ep93xx/Kconfig create mode 100644 arch/arm/mach-ep93xx/Makefile create mode 100644 arch/arm/mach-ep93xx/Makefile.boot create mode 100644 arch/arm/mach-ep93xx/core.c create mode 100644 arch/arm/mach-ep93xx/gesbc9312.c create mode 100644 arch/arm/mach-ep93xx/ts72xx.c create mode 100644 include/asm-arm/arch-ep93xx/debug-macro.S create mode 100644 include/asm-arm/arch-ep93xx/dma.h create mode 100644 include/asm-arm/arch-ep93xx/entry-macro.S create mode 100644 include/asm-arm/arch-ep93xx/ep93xx-regs.h create mode 100644 include/asm-arm/arch-ep93xx/gesbc9312.h create mode 100644 include/asm-arm/arch-ep93xx/hardware.h create mode 100644 include/asm-arm/arch-ep93xx/io.h create mode 100644 include/asm-arm/arch-ep93xx/irqs.h create mode 100644 include/asm-arm/arch-ep93xx/memory.h create mode 100644 include/asm-arm/arch-ep93xx/platform.h create mode 100644 include/asm-arm/arch-ep93xx/system.h create mode 100644 include/asm-arm/arch-ep93xx/timex.h create mode 100644 include/asm-arm/arch-ep93xx/ts72xx.h create mode 100644 include/asm-arm/arch-ep93xx/uncompress.h create mode 100644 include/asm-arm/arch-ep93xx/vmalloc.h (limited to 'include') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 6e9e8cedd723..0dd24ebdf6ac 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -108,6 +108,13 @@ config ARCH_EBSA110 Ethernet interface, two PCMCIA sockets, two serial ports and a parallel port. +config ARCH_EP93XX + bool "EP93xx-based" + select ARM_AMBA + select ARM_VIC + help + This enables support for the Cirrus EP93xx series of CPUs. + config ARCH_FOOTBRIDGE bool "FootBridge" select FOOTBRIDGE @@ -250,6 +257,8 @@ endchoice source "arch/arm/mach-clps711x/Kconfig" +source "arch/arm/mach-ep93xx/Kconfig" + source "arch/arm/mach-footbridge/Kconfig" source "arch/arm/mach-integrator/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index fbfc14a56b96..b5b1e4087516 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -105,6 +105,7 @@ endif machine-$(CONFIG_ARCH_AAEC2000) := aaec2000 machine-$(CONFIG_ARCH_REALVIEW) := realview machine-$(CONFIG_ARCH_AT91RM9200) := at91rm9200 + machine-$(CONFIG_ARCH_EP93XX) := ep93xx ifeq ($(CONFIG_ARCH_EBSA110),y) # This is what happens if you forget the IOCS16 line. diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig new file mode 100644 index 000000000000..cec5a21ca4e3 --- /dev/null +++ b/arch/arm/mach-ep93xx/Kconfig @@ -0,0 +1,21 @@ +if ARCH_EP93XX + +menu "Cirrus EP93xx Implementation Options" + +comment "EP93xx Platforms" + +config MACH_GESBC9312 + bool "Support Glomation GESBC-9312-sx" + help + Say 'Y' here if you want your kernel to support the Glomation + GESBC-9312-sx board. + +config MACH_TS72XX + bool "Support Technologic Systems TS-72xx SBC" + help + Say 'Y' here if you want your kernel to support the + Technologic Systems TS-72xx board. + +endmenu + +endif diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile new file mode 100644 index 000000000000..5393af989e94 --- /dev/null +++ b/arch/arm/mach-ep93xx/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for the linux kernel. +# +obj-y := core.o +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_MACH_GESBC9312) += gesbc9312.o +obj-$(CONFIG_MACH_TS72XX) += ts72xx.o diff --git a/arch/arm/mach-ep93xx/Makefile.boot b/arch/arm/mach-ep93xx/Makefile.boot new file mode 100644 index 000000000000..d5561ad15bad --- /dev/null +++ b/arch/arm/mach-ep93xx/Makefile.boot @@ -0,0 +1,2 @@ + zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c new file mode 100644 index 000000000000..f831f74dc8cc --- /dev/null +++ b/arch/arm/mach-ep93xx/core.c @@ -0,0 +1,173 @@ +/* + * arch/arm/mach-ep93xx/core.c + * Core routines for Cirrus EP93xx chips. + * + * Copyright (C) 2006 Lennert Buytenhek + * + * Thanks go to Michael Burian and Ray Lehtiniemi for their key + * role in the ep93xx linux community. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + + +/************************************************************************* + * Static I/O mappings that are needed for all EP93xx platforms + *************************************************************************/ +static struct map_desc ep93xx_io_desc[] __initdata = { + { + .virtual = EP93XX_AHB_VIRT_BASE, + .pfn = __phys_to_pfn(EP93XX_AHB_PHYS_BASE), + .length = EP93XX_AHB_SIZE, + .type = MT_DEVICE, + }, { + .virtual = EP93XX_APB_VIRT_BASE, + .pfn = __phys_to_pfn(EP93XX_APB_PHYS_BASE), + .length = EP93XX_APB_SIZE, + .type = MT_DEVICE, + }, +}; + +void __init ep93xx_map_io(void) +{ + iotable_init(ep93xx_io_desc, ARRAY_SIZE(ep93xx_io_desc)); +} + + +/************************************************************************* + * Timer handling for EP93xx + ************************************************************************* + * The ep93xx has four internal timers. Timers 1, 2 (both 16 bit) and + * 3 (32 bit) count down at 508 kHz, are self-reloading, and can generate + * an interrupt on underflow. Timer 4 (40 bit) counts down at 983.04 kHz, + * is free-running, and can't generate interrupts. + * + * The 508 kHz timers are ideal for use for the timer interrupt, as the + * most common values of HZ divide 508 kHz nicely. We pick one of the 16 + * bit timers (timer 1) since we don't need more than 16 bits of reload + * value as long as HZ >= 8. + * + * The higher clock rate of timer 4 makes it a better choice than the + * other timers for use in gettimeoffset(), while the fact that it can't + * generate interrupts means we don't have to worry about not being able + * to use this timer for something else. We also use timer 4 for keeping + * track of lost jiffies. + */ +static unsigned int last_jiffy_time; + +#define TIMER4_TICKS_PER_JIFFY ((CLOCK_TICK_RATE + (HZ/2)) / HZ) + +static int ep93xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + write_seqlock(&xtime_lock); + + __raw_writel(1, EP93XX_TIMER1_CLEAR); + while (__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time + >= TIMER4_TICKS_PER_JIFFY) { + last_jiffy_time += TIMER4_TICKS_PER_JIFFY; + timer_tick(regs); + } + + write_sequnlock(&xtime_lock); + + return IRQ_HANDLED; +} + +static struct irqaction ep93xx_timer_irq = { + .name = "ep93xx timer", + .flags = SA_INTERRUPT | SA_TIMER, + .handler = ep93xx_timer_interrupt, +}; + +static void __init ep93xx_timer_init(void) +{ + /* Enable periodic HZ timer. */ + __raw_writel(0x48, EP93XX_TIMER1_CONTROL); + __raw_writel((508000 / HZ) - 1, EP93XX_TIMER1_LOAD); + __raw_writel(0xc8, EP93XX_TIMER1_CONTROL); + + /* Enable lost jiffy timer. */ + __raw_writel(0x100, EP93XX_TIMER4_VALUE_HIGH); + + setup_irq(IRQ_EP93XX_TIMER1, &ep93xx_timer_irq); +} + +static unsigned long ep93xx_gettimeoffset(void) +{ + int offset; + + offset = __raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time; + + /* Calculate (1000000 / 983040) * offset. */ + return offset + (53 * offset / 3072); +} + +struct sys_timer ep93xx_timer = { + .init = ep93xx_timer_init, + .offset = ep93xx_gettimeoffset, +}; + + +/************************************************************************* + * EP93xx IRQ handling + *************************************************************************/ +void __init ep93xx_init_irq(void) +{ + vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK); + vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK); +} + + +/************************************************************************* + * EP93xx peripheral handling + *************************************************************************/ +void __init ep93xx_init_devices(void) +{ + unsigned int v; + + /* + * Disallow access to MaverickCrunch initially. + */ + v = __raw_readl(EP93XX_SYSCON_DEVICE_CONFIG); + v &= ~EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE; + __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); + __raw_writel(v, EP93XX_SYSCON_DEVICE_CONFIG); +} diff --git a/arch/arm/mach-ep93xx/gesbc9312.c b/arch/arm/mach-ep93xx/gesbc9312.c new file mode 100644 index 000000000000..d18fcb1a2f1b --- /dev/null +++ b/arch/arm/mach-ep93xx/gesbc9312.c @@ -0,0 +1,40 @@ +/* + * arch/arm/mach-ep93xx/gesbc9312.c + * Glomation GESBC-9312-sx support. + * + * Copyright (C) 2006 Lennert Buytenhek + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void __init gesbc9312_init_machine(void) +{ + ep93xx_init_devices(); + physmap_configure(0x60000000, 0x00800000, 4, NULL); +} + +MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx") + /* Maintainer: Lennert Buytenhek */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = gesbc9312_init_machine, +MACHINE_END diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c new file mode 100644 index 000000000000..777e75daa8a5 --- /dev/null +++ b/arch/arm/mach-ep93xx/ts72xx.c @@ -0,0 +1,118 @@ +/* + * arch/arm/mach-ep93xx/ts72xx.c + * Technologic Systems TS72xx SBC support. + * + * Copyright (C) 2006 Lennert Buytenhek + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct map_desc ts72xx_io_desc[] __initdata = { + { + .virtual = TS72XX_MODEL_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_MODEL_PHYS_BASE), + .length = TS72XX_MODEL_SIZE, + .type = MT_DEVICE, + }, { + .virtual = TS72XX_OPTIONS_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_OPTIONS_PHYS_BASE), + .length = TS72XX_OPTIONS_SIZE, + .type = MT_DEVICE, + }, { + .virtual = TS72XX_OPTIONS2_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE), + .length = TS72XX_OPTIONS2_SIZE, + .type = MT_DEVICE, + } +}; + +static struct map_desc ts72xx_nand_io_desc[] __initdata = { + { + .virtual = TS72XX_NAND_DATA_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_NAND1_DATA_PHYS_BASE), + .length = TS72XX_NAND_DATA_SIZE, + .type = MT_DEVICE, + }, { + .virtual = TS72XX_NAND_CONTROL_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_NAND1_CONTROL_PHYS_BASE), + .length = TS72XX_NAND_CONTROL_SIZE, + .type = MT_DEVICE, + }, { + .virtual = TS72XX_NAND_BUSY_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_NAND1_BUSY_PHYS_BASE), + .length = TS72XX_NAND_BUSY_SIZE, + .type = MT_DEVICE, + } +}; + +static struct map_desc ts72xx_alternate_nand_io_desc[] __initdata = { + { + .virtual = TS72XX_NAND_DATA_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_NAND2_DATA_PHYS_BASE), + .length = TS72XX_NAND_DATA_SIZE, + .type = MT_DEVICE, + }, { + .virtual = TS72XX_NAND_CONTROL_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_NAND2_CONTROL_PHYS_BASE), + .length = TS72XX_NAND_CONTROL_SIZE, + .type = MT_DEVICE, + }, { + .virtual = TS72XX_NAND_BUSY_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_NAND2_BUSY_PHYS_BASE), + .length = TS72XX_NAND_BUSY_SIZE, + .type = MT_DEVICE, + } +}; + +static void __init ts72xx_map_io(void) +{ + ep93xx_map_io(); + iotable_init(ts72xx_io_desc, ARRAY_SIZE(ts72xx_io_desc)); + + /* + * The TS-7200 has NOR flash, the other models have NAND flash. + */ + if (!board_is_ts7200()) { + if (is_ts9420_installed()) { + iotable_init(ts72xx_alternate_nand_io_desc, + ARRAY_SIZE(ts72xx_alternate_nand_io_desc)); + } else { + iotable_init(ts72xx_nand_io_desc, + ARRAY_SIZE(ts72xx_nand_io_desc)); + } + } +} + +static void __init ts72xx_init_machine(void) +{ + ep93xx_init_devices(); + if (board_is_ts7200()) + physmap_configure(TS72XX_NOR_PHYS_BASE, 0x01000000, 1, NULL); +} + +MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC") + /* Maintainer: Lennert Buytenhek */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = ts72xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = ts72xx_init_machine, +MACHINE_END diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 3b79d0e23455..eaaec90db972 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -62,7 +62,7 @@ config CPU_ARM720T # ARM920T config CPU_ARM920T bool "Support ARM920T processor" if !ARCH_S3C2410 - depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200 + depends on ARCH_EP93XX || ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200 default y if ARCH_S3C2410 || ARCH_AT91RM9200 select CPU_32v4 select CPU_ABRT_EV4T diff --git a/include/asm-arm/arch-ep93xx/debug-macro.S b/include/asm-arm/arch-ep93xx/debug-macro.S new file mode 100644 index 000000000000..397565a0c671 --- /dev/null +++ b/include/asm-arm/arch-ep93xx/debug-macro.S @@ -0,0 +1,22 @@ +/* + * linux/include/asm-arm/arch-ep93xx/debug-macro.S + * Debugging macro include header + * + * Copyright (C) 2006 Lennert Buytenhek + * + * 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. + */ +#include + + .macro addruart,rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + ldreq \rx, =EP93XX_APB_PHYS_BASE @ Physical base + ldrne \rx, =EP93XX_APB_VIRT_BASE @ virtual base + orr \rx, \rx, #0x000c0000 + .endm + +#include diff --git a/include/asm-arm/arch-ep93xx/dma.h b/include/asm-arm/arch-ep93xx/dma.h new file mode 100644 index 000000000000..898b3ab7fd46 --- /dev/null +++ b/include/asm-arm/arch-ep93xx/dma.h @@ -0,0 +1,3 @@ +/* + * linux/include/asm-arm/arch-ep93xx/dma.h + */ diff --git a/include/asm-arm/arch-ep93xx/entry-macro.S b/include/asm-arm/arch-ep93xx/entry-macro.S new file mode 100644 index 000000000000..84140a28dfcf --- /dev/null +++ b/include/asm-arm/arch-ep93xx/entry-macro.S @@ -0,0 +1,53 @@ +/* + * linux/include/asm-arm/arch-ep93xx/entry-macro.S + * IRQ demultiplexing for EP93xx + * + * Copyright (C) 2006 Lennert Buytenhek + * + * 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. + */ +#include + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \base, =(EP93XX_AHB_VIRT_BASE) + orr \base, \base, #0x000b0000 + mov \irqnr, #0 + ldr \irqstat, [\base] @ lower 32 interrupts + cmp \irqstat, #0 + bne 1001f + + eor \base, \base, #0x00070000 + ldr \irqstat, [\base] @ upper 32 interrupts + cmp \irqstat, #0 + beq 1002f + mov \irqnr, #0x20 + +1001: + movs \tmp, \irqstat, lsl #16 + movne \irqstat, \tmp + addeq \irqnr, \irqnr, #16 + + movs \tmp, \irqstat, lsl #8 + movne \irqstat, \tmp + addeq \irqnr, \irqnr, #8 + + movs \tmp, \irqstat, lsl #4 + movne \irqstat, \tmp + addeq \irqnr, \irqnr, #4 + + movs \tmp, \irqstat, lsl #2 + movne \irqstat, \tmp + addeq \irqnr, \irqnr, #2 + + movs \tmp, \irqstat, lsl #1 + addeq \irqnr, \irqnr, #1 + orrs \base, \base, #1 + +1002: + .endm diff --git a/include/asm-arm/arch-ep93xx/ep93xx-regs.h b/include/asm-arm/arch-ep93xx/ep93xx-regs.h new file mode 100644 index 000000000000..693f23886e85 --- /dev/null +++ b/include/asm-arm/arch-ep93xx/ep93xx-regs.h @@ -0,0 +1,114 @@ +/* + * linux/include/asm-arm/arch-ep93xx/ep93xx-regs.h + */ + +#ifndef __ASM_ARCH_EP93XX_REGS_H +#define __ASM_ARCH_EP93XX_REGS_H + +/* + * EP93xx linux memory map: + * + * virt phys size + * fe800000 5M per-platform mappings + * fed00000 80800000 2M APB + * fef00000 80000000 1M AHB + */ + +#define EP93XX_AHB_PHYS_BASE 0x80000000 +#define EP93XX_AHB_VIRT_BASE 0xfef00000 +#define EP93XX_AHB_SIZE 0x00100000 + +#define EP93XX_APB_PHYS_BASE 0x80800000 +#define EP93XX_APB_VIRT_BASE 0xfed00000 +#define EP93XX_APB_SIZE 0x00200000 + + +/* AHB peripherals */ +#define EP93XX_DMA_BASE (EP93XX_AHB_VIRT_BASE + 0x00000000) + +#define EP93XX_ETHERNET_BASE (EP93XX_AHB_VIRT_BASE + 0x00010000) + +#define EP93XX_USB_BASE (EP93XX_AHB_VIRT_BASE + 0x00020000) +#define EP93XX_USB_PHYS_BASE (EP93XX_AHB_PHYS_BASE + 0x00020000) + +#define EP93XX_RASTER_BASE (EP93XX_AHB_VIRT_BASE + 0x00030000) + +#define EP93XX_GRAPHICS_ACCEL_BASE (EP93XX_AHB_VIRT_BASE + 0x00040000) + +#define EP93XX_SDRAM_CONTROLLER_BASE (EP93XX_AHB_VIRT_BASE + 0x00060000) + +#define EP93XX_PCMCIA_CONTROLLER_BASE (EP93XX_AHB_VIRT_BASE + 0x00080000) + +#define EP93XX_BOOT_ROM_BASE (EP93XX_AHB_VIRT_BASE + 0x00090000) + +#define EP93XX_IDE_BASE (EP93XX_AHB_VIRT_BASE + 0x000a0000) + +#define EP93XX_VIC1_BASE (EP93XX_AHB_VIRT_BASE + 0x000b0000) + +#define EP93XX_VIC2_BASE (EP93XX_AHB_VIRT_BASE + 0x000c0000) + + +/* APB peripherals */ +#define EP93XX_TIMER_BASE (EP93XX_APB_VIRT_BASE + 0x00010000) +#define EP93XX_TIMER_REG(x) (EP93XX_TIMER_BASE + (x)) +#define EP93XX_TIMER1_LOAD EP93XX_TIMER_REG(0x00) +#define EP93XX_TIMER1_VALUE EP93XX_TIMER_REG(0x04) +#define EP93XX_TIMER1_CONTROL EP93XX_TIMER_REG(0x08) +#define EP93XX_TIMER1_CLEAR EP93XX_TIMER_REG(0x0c) +#define EP93XX_TIMER2_LOAD EP93XX_TIMER_REG(0x20) +#define EP93XX_TIMER2_VALUE EP93XX_TIMER_REG(0x24) +#define EP93XX_TIMER2_CONTROL EP93XX_TIMER_REG(0x28) +#define EP93XX_TIMER2_CLEAR EP93XX_TIMER_REG(0x2c) +#define EP93XX_TIMER4_VALUE_LOW EP93XX_TIMER_REG(0x60) +#define EP93XX_TIMER4_VALUE_HIGH EP93XX_TIMER_REG(0x64) +#define EP93XX_TIMER3_LOAD EP93XX_TIMER_REG(0x80) +#define EP93XX_TIMER3_VALUE EP93XX_TIMER_REG(0x84) +#define EP93XX_TIMER3_CONTROL EP93XX_TIMER_REG(0x88) +#define EP93XX_TIMER3_CLEAR EP93XX_TIMER_REG(0x8c) + +#define EP93XX_I2S_BASE (EP93XX_APB_VIRT_BASE + 0x00020000) + +#define EP93XX_SECURITY_BASE (EP93XX_APB_VIRT_BASE + 0x00030000) + +#define EP93XX_GPIO_BASE (EP93XX_APB_VIRT_BASE + 0x00040000) + +#define EP93XX_AAC_BASE (EP93XX_APB_VIRT_BASE + 0x00080000) + +#define EP93XX_SPI_BASE (EP93XX_APB_VIRT_BASE + 0x000a0000) + +#define EP93XX_IRDA_BASE (EP93XX_APB_VIRT_BASE + 0x000b0000) + +#define EP93XX_UART1_BASE (EP93XX_APB_VIRT_BASE + 0x000c0000) +#define EP93XX_UART1_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x000c0000) + +#define EP93XX_UART2_BASE (EP93XX_APB_VIRT_BASE + 0x000d0000) +#define EP93XX_UART2_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x000d0000) + +#define EP93XX_UART3_BASE (EP93XX_APB_VIRT_BASE + 0x000e0000) +#define EP93XX_UART3_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x000e0000) + +#define EP93XX_KEY_MATRIX_BASE (EP93XX_APB_VIRT_BASE + 0x000f0000) + +#define EP93XX_ADC_BASE (EP93XX_APB_VIRT_BASE + 0x00100000) +#define EP93XX_TOUCHSCREEN_BASE (EP93XX_APB_VIRT_BASE + 0x00100000) + +#define EP93XX_PWM_BASE (EP93XX_APB_VIRT_BASE + 0x00110000) + +#define EP93XX_RTC_BASE (EP93XX_APB_VIRT_BASE + 0x00120000) + +#define EP93XX_SYSCON_BASE (EP93XX_APB_VIRT_BASE + 0x00130000) +#define EP93XX_SYSCON_REG(x) (EP93XX_SYSCON_BASE + (x)) +#define EP93XX_SYSCON_POWER_STATE EP93XX_SYSCON_REG(0x00) +#define EP93XX_SYSCON_CLOCK_CONTROL EP93XX_SYSCON_REG(0x04) +#define EP93XX_SYSCON_CLOCK_UARTBAUD 0x20000000 +#define EP93XX_SYSCON_CLOCK_USH_EN 0x10000000 +#define EP93XX_SYSCON_HALT EP93XX_SYSCON_REG(0x08) +#define EP93XX_SYSCON_STANDBY EP93XX_SYSCON_REG(0x0c) +#define EP93XX_SYSCON_DEVICE_CONFIG EP93XX_SYSCON_REG(0x80) +#define EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE 0x00800000 +#define EP93XX_SYSCON_SWLOCK EP93XX_SYSCON_REG(0xc0) + +#define EP93XX_WATCHDOG_BASE (EP93XX_APB_VIRT_BASE + 0x00140000) + + +#endif diff --git a/include/asm-arm/arch-ep93xx/gesbc9312.h b/include/asm-arm/arch-ep93xx/gesbc9312.h new file mode 100644 index 000000000000..4d0b3023bff7 --- /dev/null +++ b/include/asm-arm/arch-ep93xx/gesbc9312.h @@ -0,0 +1,3 @@ +/* + * linux/include/asm-arm/arch-ep93xx/gesbc9312.h + */ diff --git a/include/asm-arm/arch-ep93xx/hardware.h b/include/asm-arm/arch-ep93xx/hardware.h new file mode 100644 index 000000000000..9b69f454065d --- /dev/null +++ b/include/asm-arm/arch-ep93xx/hardware.h @@ -0,0 +1,12 @@ +/* + * linux/include/asm-arm/arch-ep93xx/hardware.h + */ + +#include "ep93xx-regs.h" + +#define pcibios_assign_all_busses() 0 + +#include "platform.h" + +#include "gesbc9312.h" +#include "ts72xx.h" diff --git a/include/asm-arm/arch-ep93xx/io.h b/include/asm-arm/arch-ep93xx/io.h new file mode 100644 index 000000000000..7b4d25e29060 --- /dev/null +++ b/include/asm-arm/arch-ep93xx/io.h @@ -0,0 +1,8 @@ +/* + * linux/include/asm-arm/arch-ep93xx/io.h + */ + +#define IO_SPACE_LIMIT 0xffffffff + +#define __io(p) ((void __iomem *)(p)) +#define __mem_pci(p) (p) diff --git a/include/asm-arm/arch-ep93xx/irqs.h b/include/asm-arm/arch-ep93xx/irqs.h new file mode 100644 index 000000000000..8c10fb964faf --- /dev/null +++ b/include/asm-arm/arch-ep93xx/irqs.h @@ -0,0 +1,78 @@ +/* + * linux/include/asm-arm/arch-ep93xx/irqs.h + */ + +#ifndef __ASM_ARCH_IRQS_H +#define __ASM_ARCH_IRQS_H + +#define IRQ_EP93XX_COMMRX 2 +#define IRQ_EP93XX_COMMTX 3 +#define IRQ_EP93XX_TIMER1 4 +#define IRQ_EP93XX_TIMER2 5 +#define IRQ_EP93XX_AACINTR 6 +#define IRQ_EP93XX_DMAM2P0 7 +#define IRQ_EP93XX_DMAM2P1 8 +#define IRQ_EP93XX_DMAM2P2 9 +#define IRQ_EP93XX_DMAM2P3 10 +#define IRQ_EP93XX_DMAM2P4 11 +#define IRQ_EP93XX_DMAM2P5 12 +#define IRQ_EP93XX_DMAM2P6 13 +#define IRQ_EP93XX_DMAM2P7 14 +#define IRQ_EP93XX_DMAM2P8 15 +#define IRQ_EP93XX_DMAM2P9 16 +#define IRQ_EP93XX_DMAM2M0 17 +#define IRQ_EP93XX_DMAM2M1 18 +#define IRQ_EP93XX_GPIO0MUX 20 +#define IRQ_EP93XX_GPIO1MUX 21 +#define IRQ_EP93XX_GPIO2MUX 22 +#define IRQ_EP93XX_GPIO3MUX 22 +#define IRQ_EP93XX_UART1RX 23 +#define IRQ_EP93XX_UART1TX 24 +#define IRQ_EP93XX_UART2RX 25 +#define IRQ_EP93XX_UART2TX 26 +#define IRQ_EP93XX_UART3RX 27 +#define IRQ_EP93XX_UART3TX 28 +#define IRQ_EP93XX_KEY 29 +#define IRQ_EP93XX_TOUCH 30 +#define EP93XX_VIC1_VALID_IRQ_MASK 0x7ffffffc + +#define IRQ_EP93XX_EXT0 32 +#define IRQ_EP93XX_EXT1 33 +#define IRQ_EP93XX_EXT2 34 +#define IRQ_EP93XX_64HZ 35 +#define IRQ_EP93XX_WATCHDOG 36 +#define IRQ_EP93XX_RTC 37 +#define IRQ_EP93XX_IRDA 38 +#define IRQ_EP93XX_ETHERNET 39 +#define IRQ_EP93XX_EXT3 40 +#define IRQ_EP93XX_PROG 41 +#define IRQ_EP93XX_1HZ 42 +#define IRQ_EP93XX_VSYNC 43 +#define IRQ_EP93XX_VIDEO_FIFO 44 +#define IRQ_EP93XX_SSP1RX 45 +#define IRQ_EP93XX_SSP1TX 46 +#define IRQ_EP93XX_GPIO4MUX 47 +#define IRQ_EP93XX_GPIO5MUX 48 +#define IRQ_EP93XX_GPIO6MUX 49 +#define IRQ_EP93XX_GPIO7MUX 50 +#define IRQ_EP93XX_TIMER3 51 +#define IRQ_EP93XX_UART1 52 +#define IRQ_EP93XX_SSP 53 +#define IRQ_EP93XX_UART2 54 +#define IRQ_EP93XX_UART3 55 +#define IRQ_EP93XX_USB 56 +#define IRQ_EP93XX_ETHERNET_PME 57 +#define IRQ_EP93XX_DSP 58 +#define IRQ_EP93XX_GPIO_AB 59 +#define IRQ_EP93XX_SAI 60 +#define EP93XX_VIC2_VALID_IRQ_MASK 0x1fffffff + +#define NR_EP93XX_IRQS 64 + +#define EP93XX_BOARD_IRQ(x) (NR_EP93XX_IRQS + (x)) +#define EP93XX_BOARD_IRQS 32 + +#define NR_IRQS (NR_EP93XX_IRQS + EP93XX_BOARD_IRQS) + + +#endif diff --git a/include/asm-arm/arch-ep93xx/memory.h b/include/asm-arm/arch-ep93xx/memory.h new file mode 100644 index 000000000000..4b1a5c7c8363 --- /dev/null +++ b/include/asm-arm/arch-ep93xx/memory.h @@ -0,0 +1,14 @@ +/* + * linux/include/asm-arm/arch-ep93xx/memory.h + */ + +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +#define PHYS_OFFSET UL(0x00000000) + +#define __bus_to_virt(x) __phys_to_virt(x) +#define __virt_to_bus(x) __virt_to_phys(x) + + +#endif diff --git a/include/asm-arm/arch-ep93xx/platform.h b/include/asm-arm/arch-ep93xx/platform.h new file mode 100644 index 000000000000..df9cbb6ef660 --- /dev/null +++ b/include/asm-arm/arch-ep93xx/platform.h @@ -0,0 +1,14 @@ +/* + * linux/include/asm-arm/arch-ep93xx/platform.h + */ + +#ifndef __ASSEMBLY__ + +void ep93xx_map_io(void); +void ep93xx_init_irq(void); +void ep93xx_init_time(unsigned long); +void ep93xx_init_devices(void); +extern struct sys_timer ep93xx_timer; + + +#endif diff --git a/include/asm-arm/arch-ep93xx/system.h b/include/asm-arm/arch-ep93xx/system.h new file mode 100644 index 000000000000..79b718586746 --- /dev/null +++ b/include/asm-arm/arch-ep93xx/system.h @@ -0,0 +1,26 @@ +/* + * linux/include/asm-arm/arch-ep93xx/system.h + */ + +#include + +static inline void arch_idle(void) +{ + cpu_do_idle(); +} + +static inline void arch_reset(char mode) +{ + u32 devicecfg; + + local_irq_disable(); + + devicecfg = __raw_readl(EP93XX_SYSCON_DEVICE_CONFIG); + __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); + __raw_writel(devicecfg | 0x80000000, EP93XX_SYSCON_DEVICE_CONFIG); + __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); + __raw_writel(devicecfg & ~0x80000000, EP93XX_SYSCON_DEVICE_CONFIG); + + while (1) + ; +} diff --git a/include/asm-arm/arch-ep93xx/timex.h b/include/asm-arm/arch-ep93xx/timex.h new file mode 100644 index 000000000000..4140bddc97e2 --- /dev/null +++ b/include/asm-arm/arch-ep93xx/timex.h @@ -0,0 +1,5 @@ +/* + * linux/include/asm-arm/arch-ep93xx/timex.h + */ + +#define CLOCK_TICK_RATE 983040 diff --git a/include/asm-arm/arch-ep93xx/ts72xx.h b/include/asm-arm/arch-ep93xx/ts72xx.h new file mode 100644 index 000000000000..412215e77f44 --- /dev/null +++ b/include/asm-arm/arch-ep93xx/ts72xx.h @@ -0,0 +1,90 @@ +/* + * linux/include/asm-arm/arch-ep93xx/ts72xx.h + */ + +/* + * TS72xx memory map: + * + * virt phys size + * febff000 22000000 4K model number register + * febfe000 22400000 4K options register + * febfd000 22800000 4K options register #2 + * febfc000 [67]0000000 4K NAND data register + * febfb000 [67]0400000 4K NAND control register + * febfa000 [67]0800000 4K NAND busy register + */ + +#define TS72XX_MODEL_PHYS_BASE 0x22000000 +#define TS72XX_MODEL_VIRT_BASE 0xfebff000 +#define TS72XX_MODEL_SIZE 0x00001000 + +#define TS72XX_MODEL_TS7200 0x00 +#define TS72XX_MODEL_TS7250 0x01 +#define TS72XX_MODEL_TS7260 0x02 + + +#define TS72XX_OPTIONS_PHYS_BASE 0x22400000 +#define TS72XX_OPTIONS_VIRT_BASE 0xfebfe000 +#define TS72XX_OPTIONS_SIZE 0x00001000 + +#define TS72XX_OPTIONS_COM2_RS485 0x02 +#define TS72XX_OPTIONS_MAX197 0x01 + + +#define TS72XX_OPTIONS2_PHYS_BASE 0x22800000 +#define TS72XX_OPTIONS2_VIRT_BASE 0xfebfd000 +#define TS72XX_OPTIONS2_SIZE 0x00001000 + +#define TS72XX_OPTIONS2_TS9420 0x04 +#define TS72XX_OPTIONS2_TS9420_BOOT 0x02 + + +#define TS72XX_NOR_PHYS_BASE 0x60000000 +#define TS72XX_NOR2_PHYS_BASE 0x62000000 + +#define TS72XX_NAND1_DATA_PHYS_BASE 0x60000000 +#define TS72XX_NAND2_DATA_PHYS_BASE 0x70000000 +#define TS72XX_NAND_DATA_VIRT_BASE 0xfebfc000 +#define TS72XX_NAND_DATA_SIZE 0x00001000 + +#define TS72XX_NAND1_CONTROL_PHYS_BASE 0x60400000 +#define TS72XX_NAND2_CONTROL_PHYS_BASE 0x70400000 +#define TS72XX_NAND_CONTROL_VIRT_BASE 0xfebfb000 +#define TS72XX_NAND_CONTROL_SIZE 0x00001000 + +#define TS72XX_NAND1_BUSY_PHYS_BASE 0x60800000 +#define TS72XX_NAND2_BUSY_PHYS_BASE 0x70800000 +#define TS72XX_NAND_BUSY_VIRT_BASE 0xfebfa000 +#define TS72XX_NAND_BUSY_SIZE 0x00001000 + + +#ifndef __ASSEMBLY__ +#include + +static inline int board_is_ts7200(void) +{ + return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7200; +} + +static inline int board_is_ts7250(void) +{ + return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7250; +} + +static inline int board_is_ts7260(void) +{ + return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7260; +} + +static inline int is_max197_installed(void) +{ + return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) & + TS72XX_OPTIONS_MAX197); +} + +static inline int is_ts9420_installed(void) +{ + return !!(__raw_readb(TS72XX_OPTIONS2_VIRT_BASE) & + TS72XX_OPTIONS2_TS9420); +} +#endif diff --git a/include/asm-arm/arch-ep93xx/uncompress.h b/include/asm-arm/arch-ep93xx/uncompress.h new file mode 100644 index 000000000000..4410d217077e --- /dev/null +++ b/include/asm-arm/arch-ep93xx/uncompress.h @@ -0,0 +1,53 @@ +/* + * linux/include/asm-arm/arch-ep93xx/uncompress.h + * + * Copyright (C) 2006 Lennert Buytenhek + * + * 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. + */ + +#include + +static unsigned char __raw_readb(unsigned int ptr) +{ + return *((volatile unsigned char *)ptr); +} + +static void __raw_writeb(unsigned char value, unsigned int ptr) +{ + *((volatile unsigned char *)ptr) = value; +} + + +#define PHYS_UART1_DATA 0x808c0000 +#define PHYS_UART1_FLAG 0x808c0018 +#define UART1_FLAG_TXFF 0x20 + +static __inline__ void putc(char c) +{ + int i; + + for (i = 0; i < 1000; i++) { + /* Transmit fifo not full? */ + if (!(__raw_readb(PHYS_UART1_FLAG) & UART1_FLAG_TXFF)) + break; + } + + __raw_writeb(c, PHYS_UART1_DATA); +} + +static void putstr(const char *s) +{ + while (*s) { + putc(*s); + if (*s == '\n') + putc('\r'); + s++; + } +} + +#define arch_decomp_setup() +#define arch_decomp_wdog() diff --git a/include/asm-arm/arch-ep93xx/vmalloc.h b/include/asm-arm/arch-ep93xx/vmalloc.h new file mode 100644 index 000000000000..205ea6b1cf5e --- /dev/null +++ b/include/asm-arm/arch-ep93xx/vmalloc.h @@ -0,0 +1,5 @@ +/* + * linux/include/asm-arm/arch-ep93xx/vmalloc.h + */ + +#define VMALLOC_END 0xfe800000 -- cgit v1.2.3 From a8e19667a42d752f3eca6eaa17aa5d6f93066dfe Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 20 Mar 2006 17:10:14 +0000 Subject: [ARM] 3371/1: ep93xx: gpio support Patch from Lennert Buytenhek Add support for setting the direction of and getting/setting the value of the 64 GPIO lines. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/mach-ep93xx/core.c | 68 +++++++++++++++++++ include/asm-arm/arch-ep93xx/ep93xx-regs.h | 1 + include/asm-arm/arch-ep93xx/gpio.h | 107 ++++++++++++++++++++++++++++++ 3 files changed, 176 insertions(+) create mode 100644 include/asm-arm/arch-ep93xx/gpio.h (limited to 'include') diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index f831f74dc8cc..7d3e79990fad 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -45,6 +45,7 @@ #include #include #include +#include #include @@ -146,6 +147,73 @@ struct sys_timer ep93xx_timer = { }; +/************************************************************************* + * GPIO handling for EP93xx + *************************************************************************/ +static unsigned char data_register_offset[8] = { + 0x00, 0x04, 0x08, 0x0c, 0x20, 0x30, 0x38, 0x40, +}; + +static unsigned char data_direction_register_offset[8] = { + 0x10, 0x14, 0x18, 0x1c, 0x24, 0x34, 0x3c, 0x44, +}; + +void gpio_line_config(int line, int direction) +{ + unsigned int data_direction_register; + unsigned long flags; + unsigned char v; + + data_direction_register = + EP93XX_GPIO_REG(data_direction_register_offset[line >> 3]); + + local_irq_save(flags); + if (direction == GPIO_OUT) { + v = __raw_readb(data_direction_register); + v |= 1 << (line & 7); + __raw_writeb(v, data_direction_register); + } else if (direction == GPIO_IN) { + v = __raw_readb(data_direction_register); + v &= ~(1 << (line & 7)); + __raw_writeb(v, data_direction_register); + } + local_irq_restore(flags); +} +EXPORT_SYMBOL(gpio_line_config); + +int gpio_line_get(int line) +{ + unsigned int data_register; + + data_register = EP93XX_GPIO_REG(data_register_offset[line >> 3]); + + return !!(__raw_readb(data_register) & (1 << (line & 7))); +} +EXPORT_SYMBOL(gpio_line_get); + +void gpio_line_set(int line, int value) +{ + unsigned int data_register; + unsigned long flags; + unsigned char v; + + data_register = EP93XX_GPIO_REG(data_register_offset[line >> 3]); + + local_irq_save(flags); + if (value == EP93XX_GPIO_HIGH) { + v = __raw_readb(data_register); + v |= 1 << (line & 7); + __raw_writeb(v, data_register); + } else if (value == EP93XX_GPIO_LOW) { + v = __raw_readb(data_register); + v &= ~(1 << (line & 7)); + __raw_writeb(v, data_register); + } + local_irq_restore(flags); +} +EXPORT_SYMBOL(gpio_line_set); + + /************************************************************************* * EP93xx IRQ handling *************************************************************************/ diff --git a/include/asm-arm/arch-ep93xx/ep93xx-regs.h b/include/asm-arm/arch-ep93xx/ep93xx-regs.h index 693f23886e85..c1efacc83b75 100644 --- a/include/asm-arm/arch-ep93xx/ep93xx-regs.h +++ b/include/asm-arm/arch-ep93xx/ep93xx-regs.h @@ -71,6 +71,7 @@ #define EP93XX_SECURITY_BASE (EP93XX_APB_VIRT_BASE + 0x00030000) #define EP93XX_GPIO_BASE (EP93XX_APB_VIRT_BASE + 0x00040000) +#define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x)) #define EP93XX_AAC_BASE (EP93XX_APB_VIRT_BASE + 0x00080000) diff --git a/include/asm-arm/arch-ep93xx/gpio.h b/include/asm-arm/arch-ep93xx/gpio.h new file mode 100644 index 000000000000..1ee14a14cba0 --- /dev/null +++ b/include/asm-arm/arch-ep93xx/gpio.h @@ -0,0 +1,107 @@ +/* + * linux/include/asm-arm/arch-ep93xx/gpio.h + */ + +#ifndef __ASM_ARCH_GPIO_H +#define __ASM_ARCH_GPIO_H + +#define GPIO_IN 0 +#define GPIO_OUT 1 + +#define EP93XX_GPIO_LOW 0 +#define EP93XX_GPIO_HIGH 1 + +extern void gpio_line_config(int line, int direction); +extern int gpio_line_get(int line); +extern void gpio_line_set(int line, int value); + +/* GPIO port A. */ +#define EP93XX_GPIO_LINE_A(x) ((x) + 0) +#define EP93XX_GPIO_LINE_EGPIO0 EP93XX_GPIO_LINE_A(0) +#define EP93XX_GPIO_LINE_EGPIO1 EP93XX_GPIO_LINE_A(1) +#define EP93XX_GPIO_LINE_EGPIO2 EP93XX_GPIO_LINE_A(2) +#define EP93XX_GPIO_LINE_EGPIO3 EP93XX_GPIO_LINE_A(3) +#define EP93XX_GPIO_LINE_EGPIO4 EP93XX_GPIO_LINE_A(4) +#define EP93XX_GPIO_LINE_EGPIO5 EP93XX_GPIO_LINE_A(5) +#define EP93XX_GPIO_LINE_EGPIO6 EP93XX_GPIO_LINE_A(6) +#define EP93XX_GPIO_LINE_EGPIO7 EP93XX_GPIO_LINE_A(7) + +/* GPIO port B. */ +#define EP93XX_GPIO_LINE_B(x) ((x) + 8) +#define EP93XX_GPIO_LINE_EGPIO8 EP93XX_GPIO_LINE_B(0) +#define EP93XX_GPIO_LINE_EGPIO9 EP93XX_GPIO_LINE_B(1) +#define EP93XX_GPIO_LINE_EGPIO10 EP93XX_GPIO_LINE_B(2) +#define EP93XX_GPIO_LINE_EGPIO11 EP93XX_GPIO_LINE_B(3) +#define EP93XX_GPIO_LINE_EGPIO12 EP93XX_GPIO_LINE_B(4) +#define EP93XX_GPIO_LINE_EGPIO13 EP93XX_GPIO_LINE_B(5) +#define EP93XX_GPIO_LINE_EGPIO14 EP93XX_GPIO_LINE_B(6) +#define EP93XX_GPIO_LINE_EGPIO15 EP93XX_GPIO_LINE_B(7) + +/* GPIO port C. */ +#define EP93XX_GPIO_LINE_C(x) ((x) + 16) +#define EP93XX_GPIO_LINE_ROW0 EP93XX_GPIO_LINE_C(0) +#define EP93XX_GPIO_LINE_ROW1 EP93XX_GPIO_LINE_C(1) +#define EP93XX_GPIO_LINE_ROW2 EP93XX_GPIO_LINE_C(2) +#define EP93XX_GPIO_LINE_ROW3 EP93XX_GPIO_LINE_C(3) +#define EP93XX_GPIO_LINE_ROW4 EP93XX_GPIO_LINE_C(4) +#define EP93XX_GPIO_LINE_ROW5 EP93XX_GPIO_LINE_C(5) +#define EP93XX_GPIO_LINE_ROW6 EP93XX_GPIO_LINE_C(6) +#define EP93XX_GPIO_LINE_ROW7 EP93XX_GPIO_LINE_C(7) + +/* GPIO port D. */ +#define EP93XX_GPIO_LINE_D(x) ((x) + 24) +#define EP93XX_GPIO_LINE_COL0 EP93XX_GPIO_LINE_D(0) +#define EP93XX_GPIO_LINE_COL1 EP93XX_GPIO_LINE_D(1) +#define EP93XX_GPIO_LINE_COL2 EP93XX_GPIO_LINE_D(2) +#define EP93XX_GPIO_LINE_COL3 EP93XX_GPIO_LINE_D(3) +#define EP93XX_GPIO_LINE_COL4 EP93XX_GPIO_LINE_D(4) +#define EP93XX_GPIO_LINE_COL5 EP93XX_GPIO_LINE_D(5) +#define EP93XX_GPIO_LINE_COL6 EP93XX_GPIO_LINE_D(6) +#define EP93XX_GPIO_LINE_COL7 EP93XX_GPIO_LINE_D(7) + +/* GPIO port E. */ +#define EP93XX_GPIO_LINE_E(x) ((x) + 32) +#define EP93XX_GPIO_LINE_GRLED EP93XX_GPIO_LINE_E(0) +#define EP93XX_GPIO_LINE_RDLED EP93XX_GPIO_LINE_E(1) +#define EP93XX_GPIO_LINE_DIORn EP93XX_GPIO_LINE_E(2) +#define EP93XX_GPIO_LINE_IDECS1n EP93XX_GPIO_LINE_E(3) +#define EP93XX_GPIO_LINE_IDECS2n EP93XX_GPIO_LINE_E(4) +#define EP93XX_GPIO_LINE_IDEDA0 EP93XX_GPIO_LINE_E(5) +#define EP93XX_GPIO_LINE_IDEDA1 EP93XX_GPIO_LINE_E(6) +#define EP93XX_GPIO_LINE_IDEDA2 EP93XX_GPIO_LINE_E(7) + +/* GPIO port F. */ +#define EP93XX_GPIO_LINE_F(x) ((x) + 40) +#define EP93XX_GPIO_LINE_WP EP93XX_GPIO_LINE_F(0) +#define EP93XX_GPIO_LINE_MCCD1 EP93XX_GPIO_LINE_F(1) +#define EP93XX_GPIO_LINE_MCCD2 EP93XX_GPIO_LINE_F(2) +#define EP93XX_GPIO_LINE_MCBVD1 EP93XX_GPIO_LINE_F(3) +#define EP93XX_GPIO_LINE_MCBVD2 EP93XX_GPIO_LINE_F(4) +#define EP93XX_GPIO_LINE_VS1 EP93XX_GPIO_LINE_F(5) +#define EP93XX_GPIO_LINE_READY EP93XX_GPIO_LINE_F(6) +#define EP93XX_GPIO_LINE_VS2 EP93XX_GPIO_LINE_F(7) + +/* GPIO port G. */ +#define EP93XX_GPIO_LINE_G(x) ((x) + 48) +#define EP93XX_GPIO_LINE_EECLK EP93XX_GPIO_LINE_G(0) +#define EP93XX_GPIO_LINE_EEDAT EP93XX_GPIO_LINE_G(1) +#define EP93XX_GPIO_LINE_SLA0 EP93XX_GPIO_LINE_G(2) +#define EP93XX_GPIO_LINE_SLA1 EP93XX_GPIO_LINE_G(3) +#define EP93XX_GPIO_LINE_DD12 EP93XX_GPIO_LINE_G(4) +#define EP93XX_GPIO_LINE_DD13 EP93XX_GPIO_LINE_G(5) +#define EP93XX_GPIO_LINE_DD14 EP93XX_GPIO_LINE_G(6) +#define EP93XX_GPIO_LINE_DD15 EP93XX_GPIO_LINE_G(7) + +/* GPIO port H. */ +#define EP93XX_GPIO_LINE_H(x) ((x) + 56) +#define EP93XX_GPIO_LINE_DD0 EP93XX_GPIO_LINE_H(0) +#define EP93XX_GPIO_LINE_DD1 EP93XX_GPIO_LINE_H(1) +#define EP93XX_GPIO_LINE_DD2 EP93XX_GPIO_LINE_H(2) +#define EP93XX_GPIO_LINE_DD3 EP93XX_GPIO_LINE_H(3) +#define EP93XX_GPIO_LINE_DD4 EP93XX_GPIO_LINE_H(4) +#define EP93XX_GPIO_LINE_DD5 EP93XX_GPIO_LINE_H(5) +#define EP93XX_GPIO_LINE_DD6 EP93XX_GPIO_LINE_H(6) +#define EP93XX_GPIO_LINE_DD7 EP93XX_GPIO_LINE_H(7) + + +#endif -- cgit v1.2.3 From 18ec5c731271939acb414614e964c15c8ef52156 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 20 Mar 2006 17:10:17 +0000 Subject: [ARM] 3373/1: move uengine loader to arch/arm/common Patch from Lennert Buytenhek Move the uengine loader from arch/arm/mach-ixp2000 to arch/arm/common so that ixp23xx can use it too. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/common/Makefile | 1 + arch/arm/common/uengine.c | 473 +++++++++++++++++++++++++++++++++ arch/arm/mach-ixp2000/Makefile | 2 +- arch/arm/mach-ixp2000/uengine.c | 473 --------------------------------- drivers/net/ixp2000/enp2611.c | 2 +- drivers/net/ixp2000/ixpdev.c | 2 +- include/asm-arm/arch-ixp2000/uengine.h | 62 ----- include/asm-arm/hardware/uengine.h | 62 +++++ 8 files changed, 539 insertions(+), 538 deletions(-) create mode 100644 arch/arm/common/uengine.c delete mode 100644 arch/arm/mach-ixp2000/uengine.c delete mode 100644 include/asm-arm/arch-ixp2000/uengine.h create mode 100644 include/asm-arm/hardware/uengine.h (limited to 'include') diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index c81a2ff6b5be..847e3e6356c6 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -15,3 +15,4 @@ obj-$(CONFIG_SHARP_LOCOMO) += locomo.o obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o obj-$(CONFIG_SHARPSL_PM) += sharpsl_pm.o obj-$(CONFIG_SHARP_SCOOP) += scoop.o +obj-$(CONFIG_ARCH_IXP2000) += uengine.o diff --git a/arch/arm/common/uengine.c b/arch/arm/common/uengine.c new file mode 100644 index 000000000000..a1310b71004e --- /dev/null +++ b/arch/arm/common/uengine.c @@ -0,0 +1,473 @@ +/* + * Generic library functions for the microengines found on the Intel + * IXP2000 series of network processors. + * + * Copyright (C) 2004, 2005 Lennert Buytenhek + * Dedicated to Marija Kulikova. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of the + * License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USTORE_ADDRESS 0x000 +#define USTORE_DATA_LOWER 0x004 +#define USTORE_DATA_UPPER 0x008 +#define CTX_ENABLES 0x018 +#define CC_ENABLE 0x01c +#define CSR_CTX_POINTER 0x020 +#define INDIRECT_CTX_STS 0x040 +#define ACTIVE_CTX_STS 0x044 +#define INDIRECT_CTX_SIG_EVENTS 0x048 +#define INDIRECT_CTX_WAKEUP_EVENTS 0x050 +#define NN_PUT 0x080 +#define NN_GET 0x084 +#define TIMESTAMP_LOW 0x0c0 +#define TIMESTAMP_HIGH 0x0c4 +#define T_INDEX_BYTE_INDEX 0x0f4 +#define LOCAL_CSR_STATUS 0x180 + +u32 ixp2000_uengine_mask; + +static void *ixp2000_uengine_csr_area(int uengine) +{ + return ((void *)IXP2000_UENGINE_CSR_VIRT_BASE) + (uengine << 10); +} + +/* + * LOCAL_CSR_STATUS=1 after a read or write to a microengine's CSR + * space means that the microengine we tried to access was also trying + * to access its own CSR space on the same clock cycle as we did. When + * this happens, we lose the arbitration process by default, and the + * read or write we tried to do was not actually performed, so we try + * again until it succeeds. + */ +u32 ixp2000_uengine_csr_read(int uengine, int offset) +{ + void *uebase; + u32 *local_csr_status; + u32 *reg; + u32 value; + + uebase = ixp2000_uengine_csr_area(uengine); + + local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS); + reg = (u32 *)(uebase + offset); + do { + value = ixp2000_reg_read(reg); + } while (ixp2000_reg_read(local_csr_status) & 1); + + return value; +} +EXPORT_SYMBOL(ixp2000_uengine_csr_read); + +void ixp2000_uengine_csr_write(int uengine, int offset, u32 value) +{ + void *uebase; + u32 *local_csr_status; + u32 *reg; + + uebase = ixp2000_uengine_csr_area(uengine); + + local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS); + reg = (u32 *)(uebase + offset); + do { + ixp2000_reg_write(reg, value); + } while (ixp2000_reg_read(local_csr_status) & 1); +} +EXPORT_SYMBOL(ixp2000_uengine_csr_write); + +void ixp2000_uengine_reset(u32 uengine_mask) +{ + ixp2000_reg_wrb(IXP2000_RESET1, uengine_mask & ixp2000_uengine_mask); + ixp2000_reg_wrb(IXP2000_RESET1, 0); +} +EXPORT_SYMBOL(ixp2000_uengine_reset); + +void ixp2000_uengine_set_mode(int uengine, u32 mode) +{ + /* + * CTL_STR_PAR_EN: unconditionally enable parity checking on + * control store. + */ + mode |= 0x10000000; + ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mode); + + /* + * Enable updating of condition codes. + */ + ixp2000_uengine_csr_write(uengine, CC_ENABLE, 0x00002000); + + /* + * Initialise other per-microengine registers. + */ + ixp2000_uengine_csr_write(uengine, NN_PUT, 0x00); + ixp2000_uengine_csr_write(uengine, NN_GET, 0x00); + ixp2000_uengine_csr_write(uengine, T_INDEX_BYTE_INDEX, 0); +} +EXPORT_SYMBOL(ixp2000_uengine_set_mode); + +static int make_even_parity(u32 x) +{ + return hweight32(x) & 1; +} + +static void ustore_write(int uengine, u64 insn) +{ + /* + * Generate even parity for top and bottom 20 bits. + */ + insn |= (u64)make_even_parity((insn >> 20) & 0x000fffff) << 41; + insn |= (u64)make_even_parity(insn & 0x000fffff) << 40; + + /* + * Write to microstore. The second write auto-increments + * the USTORE_ADDRESS index register. + */ + ixp2000_uengine_csr_write(uengine, USTORE_DATA_LOWER, (u32)insn); + ixp2000_uengine_csr_write(uengine, USTORE_DATA_UPPER, (u32)(insn >> 32)); +} + +void ixp2000_uengine_load_microcode(int uengine, u8 *ucode, int insns) +{ + int i; + + /* + * Start writing to microstore at address 0. + */ + ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x80000000); + for (i = 0; i < insns; i++) { + u64 insn; + + insn = (((u64)ucode[0]) << 32) | + (((u64)ucode[1]) << 24) | + (((u64)ucode[2]) << 16) | + (((u64)ucode[3]) << 8) | + ((u64)ucode[4]); + ucode += 5; + + ustore_write(uengine, insn); + } + + /* + * Pad with a few NOPs at the end (to avoid the microengine + * aborting as it prefetches beyond the last instruction), unless + * we run off the end of the instruction store first, at which + * point the address register will wrap back to zero. + */ + for (i = 0; i < 4; i++) { + u32 addr; + + addr = ixp2000_uengine_csr_read(uengine, USTORE_ADDRESS); + if (addr == 0x80000000) + break; + ustore_write(uengine, 0xf0000c0300ULL); + } + + /* + * End programming. + */ + ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x00000000); +} +EXPORT_SYMBOL(ixp2000_uengine_load_microcode); + +void ixp2000_uengine_init_context(int uengine, int context, int pc) +{ + /* + * Select the right context for indirect access. + */ + ixp2000_uengine_csr_write(uengine, CSR_CTX_POINTER, context); + + /* + * Initialise signal masks to immediately go to Ready state. + */ + ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_SIG_EVENTS, 1); + ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_WAKEUP_EVENTS, 1); + + /* + * Set program counter. + */ + ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_STS, pc); +} +EXPORT_SYMBOL(ixp2000_uengine_init_context); + +void ixp2000_uengine_start_contexts(int uengine, u8 ctx_mask) +{ + u32 mask; + + /* + * Enable the specified context to go to Executing state. + */ + mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES); + mask |= ctx_mask << 8; + ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask); +} +EXPORT_SYMBOL(ixp2000_uengine_start_contexts); + +void ixp2000_uengine_stop_contexts(int uengine, u8 ctx_mask) +{ + u32 mask; + + /* + * Disable the Ready->Executing transition. Note that this + * does not stop the context until it voluntarily yields. + */ + mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES); + mask &= ~(ctx_mask << 8); + ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask); +} +EXPORT_SYMBOL(ixp2000_uengine_stop_contexts); + +static int check_ixp_type(struct ixp2000_uengine_code *c) +{ + u32 product_id; + u32 rev; + + product_id = ixp2000_reg_read(IXP2000_PRODUCT_ID); + if (((product_id >> 16) & 0x1f) != 0) + return 0; + + switch ((product_id >> 8) & 0xff) { + case 0: /* IXP2800 */ + if (!(c->cpu_model_bitmask & 4)) + return 0; + break; + + case 1: /* IXP2850 */ + if (!(c->cpu_model_bitmask & 8)) + return 0; + break; + + case 2: /* IXP2400 */ + if (!(c->cpu_model_bitmask & 2)) + return 0; + break; + + default: + return 0; + } + + rev = product_id & 0xff; + if (rev < c->cpu_min_revision || rev > c->cpu_max_revision) + return 0; + + return 1; +} + +static void generate_ucode(u8 *ucode, u32 *gpr_a, u32 *gpr_b) +{ + int offset; + int i; + + offset = 0; + + for (i = 0; i < 128; i++) { + u8 b3; + u8 b2; + u8 b1; + u8 b0; + + b3 = (gpr_a[i] >> 24) & 0xff; + b2 = (gpr_a[i] >> 16) & 0xff; + b1 = (gpr_a[i] >> 8) & 0xff; + b0 = gpr_a[i] & 0xff; + + // immed[@ai, (b1 << 8) | b0] + // 11110000 0000VVVV VVVV11VV VVVVVV00 1IIIIIII + ucode[offset++] = 0xf0; + ucode[offset++] = (b1 >> 4); + ucode[offset++] = (b1 << 4) | 0x0c | (b0 >> 6); + ucode[offset++] = (b0 << 2); + ucode[offset++] = 0x80 | i; + + // immed_w1[@ai, (b3 << 8) | b2] + // 11110100 0100VVVV VVVV11VV VVVVVV00 1IIIIIII + ucode[offset++] = 0xf4; + ucode[offset++] = 0x40 | (b3 >> 4); + ucode[offset++] = (b3 << 4) | 0x0c | (b2 >> 6); + ucode[offset++] = (b2 << 2); + ucode[offset++] = 0x80 | i; + } + + for (i = 0; i < 128; i++) { + u8 b3; + u8 b2; + u8 b1; + u8 b0; + + b3 = (gpr_b[i] >> 24) & 0xff; + b2 = (gpr_b[i] >> 16) & 0xff; + b1 = (gpr_b[i] >> 8) & 0xff; + b0 = gpr_b[i] & 0xff; + + // immed[@bi, (b1 << 8) | b0] + // 11110000 0000VVVV VVVV001I IIIIII11 VVVVVVVV + ucode[offset++] = 0xf0; + ucode[offset++] = (b1 >> 4); + ucode[offset++] = (b1 << 4) | 0x02 | (i >> 6); + ucode[offset++] = (i << 2) | 0x03; + ucode[offset++] = b0; + + // immed_w1[@bi, (b3 << 8) | b2] + // 11110100 0100VVVV VVVV001I IIIIII11 VVVVVVVV + ucode[offset++] = 0xf4; + ucode[offset++] = 0x40 | (b3 >> 4); + ucode[offset++] = (b3 << 4) | 0x02 | (i >> 6); + ucode[offset++] = (i << 2) | 0x03; + ucode[offset++] = b2; + } + + // ctx_arb[kill] + ucode[offset++] = 0xe0; + ucode[offset++] = 0x00; + ucode[offset++] = 0x01; + ucode[offset++] = 0x00; + ucode[offset++] = 0x00; +} + +static int set_initial_registers(int uengine, struct ixp2000_uengine_code *c) +{ + int per_ctx_regs; + u32 *gpr_a; + u32 *gpr_b; + u8 *ucode; + int i; + + gpr_a = kmalloc(128 * sizeof(u32), GFP_KERNEL); + gpr_b = kmalloc(128 * sizeof(u32), GFP_KERNEL); + ucode = kmalloc(513 * 5, GFP_KERNEL); + if (gpr_a == NULL || gpr_b == NULL || ucode == NULL) { + kfree(ucode); + kfree(gpr_b); + kfree(gpr_a); + return 1; + } + + per_ctx_regs = 16; + if (c->uengine_parameters & IXP2000_UENGINE_4_CONTEXTS) + per_ctx_regs = 32; + + memset(gpr_a, 0, sizeof(gpr_a)); + memset(gpr_b, 0, sizeof(gpr_b)); + for (i = 0; i < 256; i++) { + struct ixp2000_reg_value *r = c->initial_reg_values + i; + u32 *bank; + int inc; + int j; + + if (r->reg == -1) + break; + + bank = (r->reg & 0x400) ? gpr_b : gpr_a; + inc = (r->reg & 0x80) ? 128 : per_ctx_regs; + + j = r->reg & 0x7f; + while (j < 128) { + bank[j] = r->value; + j += inc; + } + } + + generate_ucode(ucode, gpr_a, gpr_b); + ixp2000_uengine_load_microcode(uengine, ucode, 513); + ixp2000_uengine_init_context(uengine, 0, 0); + ixp2000_uengine_start_contexts(uengine, 0x01); + for (i = 0; i < 100; i++) { + u32 status; + + status = ixp2000_uengine_csr_read(uengine, ACTIVE_CTX_STS); + if (!(status & 0x80000000)) + break; + } + ixp2000_uengine_stop_contexts(uengine, 0x01); + + kfree(ucode); + kfree(gpr_b); + kfree(gpr_a); + + return !!(i == 100); +} + +int ixp2000_uengine_load(int uengine, struct ixp2000_uengine_code *c) +{ + int ctx; + + if (!check_ixp_type(c)) + return 1; + + if (!(ixp2000_uengine_mask & (1 << uengine))) + return 1; + + ixp2000_uengine_reset(1 << uengine); + ixp2000_uengine_set_mode(uengine, c->uengine_parameters); + if (set_initial_registers(uengine, c)) + return 1; + ixp2000_uengine_load_microcode(uengine, c->insns, c->num_insns); + + for (ctx = 0; ctx < 8; ctx++) + ixp2000_uengine_init_context(uengine, ctx, 0); + + return 0; +} +EXPORT_SYMBOL(ixp2000_uengine_load); + + +static int __init ixp2000_uengine_init(void) +{ + int uengine; + u32 value; + + /* + * Determine number of microengines present. + */ + switch ((ixp2000_reg_read(IXP2000_PRODUCT_ID) >> 8) & 0x1fff) { + case 0: /* IXP2800 */ + case 1: /* IXP2850 */ + ixp2000_uengine_mask = 0x00ff00ff; + break; + + case 2: /* IXP2400 */ + ixp2000_uengine_mask = 0x000f000f; + break; + + default: + printk(KERN_INFO "Detected unknown IXP2000 model (%.8x)\n", + (unsigned int)ixp2000_reg_read(IXP2000_PRODUCT_ID)); + ixp2000_uengine_mask = 0x00000000; + break; + } + + /* + * Reset microengines. + */ + ixp2000_uengine_reset(ixp2000_uengine_mask); + + /* + * Synchronise timestamp counters across all microengines. + */ + value = ixp2000_reg_read(IXP2000_MISC_CONTROL); + ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value & ~0x80); + for (uengine = 0; uengine < 32; uengine++) { + if (ixp2000_uengine_mask & (1 << uengine)) { + ixp2000_uengine_csr_write(uengine, TIMESTAMP_LOW, 0); + ixp2000_uengine_csr_write(uengine, TIMESTAMP_HIGH, 0); + } + } + ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value | 0x80); + + return 0; +} + +subsys_initcall(ixp2000_uengine_init); diff --git a/arch/arm/mach-ixp2000/Makefile b/arch/arm/mach-ixp2000/Makefile index 9621aeb61f46..1e6139d42a92 100644 --- a/arch/arm/mach-ixp2000/Makefile +++ b/arch/arm/mach-ixp2000/Makefile @@ -1,7 +1,7 @@ # # Makefile for the linux kernel. # -obj-y := core.o pci.o uengine.o +obj-y := core.o pci.o obj-m := obj-n := obj- := diff --git a/arch/arm/mach-ixp2000/uengine.c b/arch/arm/mach-ixp2000/uengine.c deleted file mode 100644 index ec4e007a22ef..000000000000 --- a/arch/arm/mach-ixp2000/uengine.c +++ /dev/null @@ -1,473 +0,0 @@ -/* - * Generic library functions for the microengines found on the Intel - * IXP2000 series of network processors. - * - * Copyright (C) 2004, 2005 Lennert Buytenhek - * Dedicated to Marija Kulikova. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of the - * License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define USTORE_ADDRESS 0x000 -#define USTORE_DATA_LOWER 0x004 -#define USTORE_DATA_UPPER 0x008 -#define CTX_ENABLES 0x018 -#define CC_ENABLE 0x01c -#define CSR_CTX_POINTER 0x020 -#define INDIRECT_CTX_STS 0x040 -#define ACTIVE_CTX_STS 0x044 -#define INDIRECT_CTX_SIG_EVENTS 0x048 -#define INDIRECT_CTX_WAKEUP_EVENTS 0x050 -#define NN_PUT 0x080 -#define NN_GET 0x084 -#define TIMESTAMP_LOW 0x0c0 -#define TIMESTAMP_HIGH 0x0c4 -#define T_INDEX_BYTE_INDEX 0x0f4 -#define LOCAL_CSR_STATUS 0x180 - -u32 ixp2000_uengine_mask; - -static void *ixp2000_uengine_csr_area(int uengine) -{ - return ((void *)IXP2000_UENGINE_CSR_VIRT_BASE) + (uengine << 10); -} - -/* - * LOCAL_CSR_STATUS=1 after a read or write to a microengine's CSR - * space means that the microengine we tried to access was also trying - * to access its own CSR space on the same clock cycle as we did. When - * this happens, we lose the arbitration process by default, and the - * read or write we tried to do was not actually performed, so we try - * again until it succeeds. - */ -u32 ixp2000_uengine_csr_read(int uengine, int offset) -{ - void *uebase; - u32 *local_csr_status; - u32 *reg; - u32 value; - - uebase = ixp2000_uengine_csr_area(uengine); - - local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS); - reg = (u32 *)(uebase + offset); - do { - value = ixp2000_reg_read(reg); - } while (ixp2000_reg_read(local_csr_status) & 1); - - return value; -} -EXPORT_SYMBOL(ixp2000_uengine_csr_read); - -void ixp2000_uengine_csr_write(int uengine, int offset, u32 value) -{ - void *uebase; - u32 *local_csr_status; - u32 *reg; - - uebase = ixp2000_uengine_csr_area(uengine); - - local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS); - reg = (u32 *)(uebase + offset); - do { - ixp2000_reg_write(reg, value); - } while (ixp2000_reg_read(local_csr_status) & 1); -} -EXPORT_SYMBOL(ixp2000_uengine_csr_write); - -void ixp2000_uengine_reset(u32 uengine_mask) -{ - ixp2000_reg_wrb(IXP2000_RESET1, uengine_mask & ixp2000_uengine_mask); - ixp2000_reg_wrb(IXP2000_RESET1, 0); -} -EXPORT_SYMBOL(ixp2000_uengine_reset); - -void ixp2000_uengine_set_mode(int uengine, u32 mode) -{ - /* - * CTL_STR_PAR_EN: unconditionally enable parity checking on - * control store. - */ - mode |= 0x10000000; - ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mode); - - /* - * Enable updating of condition codes. - */ - ixp2000_uengine_csr_write(uengine, CC_ENABLE, 0x00002000); - - /* - * Initialise other per-microengine registers. - */ - ixp2000_uengine_csr_write(uengine, NN_PUT, 0x00); - ixp2000_uengine_csr_write(uengine, NN_GET, 0x00); - ixp2000_uengine_csr_write(uengine, T_INDEX_BYTE_INDEX, 0); -} -EXPORT_SYMBOL(ixp2000_uengine_set_mode); - -static int make_even_parity(u32 x) -{ - return hweight32(x) & 1; -} - -static void ustore_write(int uengine, u64 insn) -{ - /* - * Generate even parity for top and bottom 20 bits. - */ - insn |= (u64)make_even_parity((insn >> 20) & 0x000fffff) << 41; - insn |= (u64)make_even_parity(insn & 0x000fffff) << 40; - - /* - * Write to microstore. The second write auto-increments - * the USTORE_ADDRESS index register. - */ - ixp2000_uengine_csr_write(uengine, USTORE_DATA_LOWER, (u32)insn); - ixp2000_uengine_csr_write(uengine, USTORE_DATA_UPPER, (u32)(insn >> 32)); -} - -void ixp2000_uengine_load_microcode(int uengine, u8 *ucode, int insns) -{ - int i; - - /* - * Start writing to microstore at address 0. - */ - ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x80000000); - for (i = 0; i < insns; i++) { - u64 insn; - - insn = (((u64)ucode[0]) << 32) | - (((u64)ucode[1]) << 24) | - (((u64)ucode[2]) << 16) | - (((u64)ucode[3]) << 8) | - ((u64)ucode[4]); - ucode += 5; - - ustore_write(uengine, insn); - } - - /* - * Pad with a few NOPs at the end (to avoid the microengine - * aborting as it prefetches beyond the last instruction), unless - * we run off the end of the instruction store first, at which - * point the address register will wrap back to zero. - */ - for (i = 0; i < 4; i++) { - u32 addr; - - addr = ixp2000_uengine_csr_read(uengine, USTORE_ADDRESS); - if (addr == 0x80000000) - break; - ustore_write(uengine, 0xf0000c0300ULL); - } - - /* - * End programming. - */ - ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x00000000); -} -EXPORT_SYMBOL(ixp2000_uengine_load_microcode); - -void ixp2000_uengine_init_context(int uengine, int context, int pc) -{ - /* - * Select the right context for indirect access. - */ - ixp2000_uengine_csr_write(uengine, CSR_CTX_POINTER, context); - - /* - * Initialise signal masks to immediately go to Ready state. - */ - ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_SIG_EVENTS, 1); - ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_WAKEUP_EVENTS, 1); - - /* - * Set program counter. - */ - ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_STS, pc); -} -EXPORT_SYMBOL(ixp2000_uengine_init_context); - -void ixp2000_uengine_start_contexts(int uengine, u8 ctx_mask) -{ - u32 mask; - - /* - * Enable the specified context to go to Executing state. - */ - mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES); - mask |= ctx_mask << 8; - ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask); -} -EXPORT_SYMBOL(ixp2000_uengine_start_contexts); - -void ixp2000_uengine_stop_contexts(int uengine, u8 ctx_mask) -{ - u32 mask; - - /* - * Disable the Ready->Executing transition. Note that this - * does not stop the context until it voluntarily yields. - */ - mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES); - mask &= ~(ctx_mask << 8); - ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask); -} -EXPORT_SYMBOL(ixp2000_uengine_stop_contexts); - -static int check_ixp_type(struct ixp2000_uengine_code *c) -{ - u32 product_id; - u32 rev; - - product_id = ixp2000_reg_read(IXP2000_PRODUCT_ID); - if (((product_id >> 16) & 0x1f) != 0) - return 0; - - switch ((product_id >> 8) & 0xff) { - case 0: /* IXP2800 */ - if (!(c->cpu_model_bitmask & 4)) - return 0; - break; - - case 1: /* IXP2850 */ - if (!(c->cpu_model_bitmask & 8)) - return 0; - break; - - case 2: /* IXP2400 */ - if (!(c->cpu_model_bitmask & 2)) - return 0; - break; - - default: - return 0; - } - - rev = product_id & 0xff; - if (rev < c->cpu_min_revision || rev > c->cpu_max_revision) - return 0; - - return 1; -} - -static void generate_ucode(u8 *ucode, u32 *gpr_a, u32 *gpr_b) -{ - int offset; - int i; - - offset = 0; - - for (i = 0; i < 128; i++) { - u8 b3; - u8 b2; - u8 b1; - u8 b0; - - b3 = (gpr_a[i] >> 24) & 0xff; - b2 = (gpr_a[i] >> 16) & 0xff; - b1 = (gpr_a[i] >> 8) & 0xff; - b0 = gpr_a[i] & 0xff; - - // immed[@ai, (b1 << 8) | b0] - // 11110000 0000VVVV VVVV11VV VVVVVV00 1IIIIIII - ucode[offset++] = 0xf0; - ucode[offset++] = (b1 >> 4); - ucode[offset++] = (b1 << 4) | 0x0c | (b0 >> 6); - ucode[offset++] = (b0 << 2); - ucode[offset++] = 0x80 | i; - - // immed_w1[@ai, (b3 << 8) | b2] - // 11110100 0100VVVV VVVV11VV VVVVVV00 1IIIIIII - ucode[offset++] = 0xf4; - ucode[offset++] = 0x40 | (b3 >> 4); - ucode[offset++] = (b3 << 4) | 0x0c | (b2 >> 6); - ucode[offset++] = (b2 << 2); - ucode[offset++] = 0x80 | i; - } - - for (i = 0; i < 128; i++) { - u8 b3; - u8 b2; - u8 b1; - u8 b0; - - b3 = (gpr_b[i] >> 24) & 0xff; - b2 = (gpr_b[i] >> 16) & 0xff; - b1 = (gpr_b[i] >> 8) & 0xff; - b0 = gpr_b[i] & 0xff; - - // immed[@bi, (b1 << 8) | b0] - // 11110000 0000VVVV VVVV001I IIIIII11 VVVVVVVV - ucode[offset++] = 0xf0; - ucode[offset++] = (b1 >> 4); - ucode[offset++] = (b1 << 4) | 0x02 | (i >> 6); - ucode[offset++] = (i << 2) | 0x03; - ucode[offset++] = b0; - - // immed_w1[@bi, (b3 << 8) | b2] - // 11110100 0100VVVV VVVV001I IIIIII11 VVVVVVVV - ucode[offset++] = 0xf4; - ucode[offset++] = 0x40 | (b3 >> 4); - ucode[offset++] = (b3 << 4) | 0x02 | (i >> 6); - ucode[offset++] = (i << 2) | 0x03; - ucode[offset++] = b2; - } - - // ctx_arb[kill] - ucode[offset++] = 0xe0; - ucode[offset++] = 0x00; - ucode[offset++] = 0x01; - ucode[offset++] = 0x00; - ucode[offset++] = 0x00; -} - -static int set_initial_registers(int uengine, struct ixp2000_uengine_code *c) -{ - int per_ctx_regs; - u32 *gpr_a; - u32 *gpr_b; - u8 *ucode; - int i; - - gpr_a = kmalloc(128 * sizeof(u32), GFP_KERNEL); - gpr_b = kmalloc(128 * sizeof(u32), GFP_KERNEL); - ucode = kmalloc(513 * 5, GFP_KERNEL); - if (gpr_a == NULL || gpr_b == NULL || ucode == NULL) { - kfree(ucode); - kfree(gpr_b); - kfree(gpr_a); - return 1; - } - - per_ctx_regs = 16; - if (c->uengine_parameters & IXP2000_UENGINE_4_CONTEXTS) - per_ctx_regs = 32; - - memset(gpr_a, 0, sizeof(gpr_a)); - memset(gpr_b, 0, sizeof(gpr_b)); - for (i = 0; i < 256; i++) { - struct ixp2000_reg_value *r = c->initial_reg_values + i; - u32 *bank; - int inc; - int j; - - if (r->reg == -1) - break; - - bank = (r->reg & 0x400) ? gpr_b : gpr_a; - inc = (r->reg & 0x80) ? 128 : per_ctx_regs; - - j = r->reg & 0x7f; - while (j < 128) { - bank[j] = r->value; - j += inc; - } - } - - generate_ucode(ucode, gpr_a, gpr_b); - ixp2000_uengine_load_microcode(uengine, ucode, 513); - ixp2000_uengine_init_context(uengine, 0, 0); - ixp2000_uengine_start_contexts(uengine, 0x01); - for (i = 0; i < 100; i++) { - u32 status; - - status = ixp2000_uengine_csr_read(uengine, ACTIVE_CTX_STS); - if (!(status & 0x80000000)) - break; - } - ixp2000_uengine_stop_contexts(uengine, 0x01); - - kfree(ucode); - kfree(gpr_b); - kfree(gpr_a); - - return !!(i == 100); -} - -int ixp2000_uengine_load(int uengine, struct ixp2000_uengine_code *c) -{ - int ctx; - - if (!check_ixp_type(c)) - return 1; - - if (!(ixp2000_uengine_mask & (1 << uengine))) - return 1; - - ixp2000_uengine_reset(1 << uengine); - ixp2000_uengine_set_mode(uengine, c->uengine_parameters); - if (set_initial_registers(uengine, c)) - return 1; - ixp2000_uengine_load_microcode(uengine, c->insns, c->num_insns); - - for (ctx = 0; ctx < 8; ctx++) - ixp2000_uengine_init_context(uengine, ctx, 0); - - return 0; -} -EXPORT_SYMBOL(ixp2000_uengine_load); - - -static int __init ixp2000_uengine_init(void) -{ - int uengine; - u32 value; - - /* - * Determine number of microengines present. - */ - switch ((ixp2000_reg_read(IXP2000_PRODUCT_ID) >> 8) & 0x1fff) { - case 0: /* IXP2800 */ - case 1: /* IXP2850 */ - ixp2000_uengine_mask = 0x00ff00ff; - break; - - case 2: /* IXP2400 */ - ixp2000_uengine_mask = 0x000f000f; - break; - - default: - printk(KERN_INFO "Detected unknown IXP2000 model (%.8x)\n", - (unsigned int)ixp2000_reg_read(IXP2000_PRODUCT_ID)); - ixp2000_uengine_mask = 0x00000000; - break; - } - - /* - * Reset microengines. - */ - ixp2000_uengine_reset(ixp2000_uengine_mask); - - /* - * Synchronise timestamp counters across all microengines. - */ - value = ixp2000_reg_read(IXP2000_MISC_CONTROL); - ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value & ~0x80); - for (uengine = 0; uengine < 32; uengine++) { - if (ixp2000_uengine_mask & (1 << uengine)) { - ixp2000_uengine_csr_write(uengine, TIMESTAMP_LOW, 0); - ixp2000_uengine_csr_write(uengine, TIMESTAMP_HIGH, 0); - } - } - ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value | 0x80); - - return 0; -} - -subsys_initcall(ixp2000_uengine_init); diff --git a/drivers/net/ixp2000/enp2611.c b/drivers/net/ixp2000/enp2611.c index d82651a97bae..6f7dce8eba51 100644 --- a/drivers/net/ixp2000/enp2611.c +++ b/drivers/net/ixp2000/enp2611.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include "ixpdev.h" diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c index 09f03f493bea..77f104a005f3 100644 --- a/drivers/net/ixp2000/ixpdev.c +++ b/drivers/net/ixp2000/ixpdev.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include "ixp2400_rx.ucode" diff --git a/include/asm-arm/arch-ixp2000/uengine.h b/include/asm-arm/arch-ixp2000/uengine.h deleted file mode 100644 index b442d65c6593..000000000000 --- a/include/asm-arm/arch-ixp2000/uengine.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Generic library functions for the microengines found on the Intel - * IXP2000 series of network processors. - * - * Copyright (C) 2004, 2005 Lennert Buytenhek - * Dedicated to Marija Kulikova. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of the - * License, or (at your option) any later version. - */ - -#ifndef __IXP2000_UENGINE_H -#define __IXP2000_UENGINE_H - -extern u32 ixp2000_uengine_mask; - -struct ixp2000_uengine_code -{ - u32 cpu_model_bitmask; - u8 cpu_min_revision; - u8 cpu_max_revision; - - u32 uengine_parameters; - - struct ixp2000_reg_value { - int reg; - u32 value; - } *initial_reg_values; - - int num_insns; - u8 *insns; -}; - -u32 ixp2000_uengine_csr_read(int uengine, int offset); -void ixp2000_uengine_csr_write(int uengine, int offset, u32 value); -void ixp2000_uengine_reset(u32 uengine_mask); -void ixp2000_uengine_set_mode(int uengine, u32 mode); -void ixp2000_uengine_load_microcode(int uengine, u8 *ucode, int insns); -void ixp2000_uengine_init_context(int uengine, int context, int pc); -void ixp2000_uengine_start_contexts(int uengine, u8 ctx_mask); -void ixp2000_uengine_stop_contexts(int uengine, u8 ctx_mask); -int ixp2000_uengine_load(int uengine, struct ixp2000_uengine_code *c); - -#define IXP2000_UENGINE_8_CONTEXTS 0x00000000 -#define IXP2000_UENGINE_4_CONTEXTS 0x80000000 -#define IXP2000_UENGINE_PRN_UPDATE_EVERY 0x40000000 -#define IXP2000_UENGINE_PRN_UPDATE_ON_ACCESS 0x00000000 -#define IXP2000_UENGINE_NN_FROM_SELF 0x00100000 -#define IXP2000_UENGINE_NN_FROM_PREVIOUS 0x00000000 -#define IXP2000_UENGINE_ASSERT_EMPTY_AT_3 0x000c0000 -#define IXP2000_UENGINE_ASSERT_EMPTY_AT_2 0x00080000 -#define IXP2000_UENGINE_ASSERT_EMPTY_AT_1 0x00040000 -#define IXP2000_UENGINE_ASSERT_EMPTY_AT_0 0x00000000 -#define IXP2000_UENGINE_LM_ADDR1_GLOBAL 0x00020000 -#define IXP2000_UENGINE_LM_ADDR1_PER_CONTEXT 0x00000000 -#define IXP2000_UENGINE_LM_ADDR0_GLOBAL 0x00010000 -#define IXP2000_UENGINE_LM_ADDR0_PER_CONTEXT 0x00000000 - - -#endif diff --git a/include/asm-arm/hardware/uengine.h b/include/asm-arm/hardware/uengine.h new file mode 100644 index 000000000000..b442d65c6593 --- /dev/null +++ b/include/asm-arm/hardware/uengine.h @@ -0,0 +1,62 @@ +/* + * Generic library functions for the microengines found on the Intel + * IXP2000 series of network processors. + * + * Copyright (C) 2004, 2005 Lennert Buytenhek + * Dedicated to Marija Kulikova. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of the + * License, or (at your option) any later version. + */ + +#ifndef __IXP2000_UENGINE_H +#define __IXP2000_UENGINE_H + +extern u32 ixp2000_uengine_mask; + +struct ixp2000_uengine_code +{ + u32 cpu_model_bitmask; + u8 cpu_min_revision; + u8 cpu_max_revision; + + u32 uengine_parameters; + + struct ixp2000_reg_value { + int reg; + u32 value; + } *initial_reg_values; + + int num_insns; + u8 *insns; +}; + +u32 ixp2000_uengine_csr_read(int uengine, int offset); +void ixp2000_uengine_csr_write(int uengine, int offset, u32 value); +void ixp2000_uengine_reset(u32 uengine_mask); +void ixp2000_uengine_set_mode(int uengine, u32 mode); +void ixp2000_uengine_load_microcode(int uengine, u8 *ucode, int insns); +void ixp2000_uengine_init_context(int uengine, int context, int pc); +void ixp2000_uengine_start_contexts(int uengine, u8 ctx_mask); +void ixp2000_uengine_stop_contexts(int uengine, u8 ctx_mask); +int ixp2000_uengine_load(int uengine, struct ixp2000_uengine_code *c); + +#define IXP2000_UENGINE_8_CONTEXTS 0x00000000 +#define IXP2000_UENGINE_4_CONTEXTS 0x80000000 +#define IXP2000_UENGINE_PRN_UPDATE_EVERY 0x40000000 +#define IXP2000_UENGINE_PRN_UPDATE_ON_ACCESS 0x00000000 +#define IXP2000_UENGINE_NN_FROM_SELF 0x00100000 +#define IXP2000_UENGINE_NN_FROM_PREVIOUS 0x00000000 +#define IXP2000_UENGINE_ASSERT_EMPTY_AT_3 0x000c0000 +#define IXP2000_UENGINE_ASSERT_EMPTY_AT_2 0x00080000 +#define IXP2000_UENGINE_ASSERT_EMPTY_AT_1 0x00040000 +#define IXP2000_UENGINE_ASSERT_EMPTY_AT_0 0x00000000 +#define IXP2000_UENGINE_LM_ADDR1_GLOBAL 0x00020000 +#define IXP2000_UENGINE_LM_ADDR1_PER_CONTEXT 0x00000000 +#define IXP2000_UENGINE_LM_ADDR0_GLOBAL 0x00010000 +#define IXP2000_UENGINE_LM_ADDR0_PER_CONTEXT 0x00000000 + + +#endif -- cgit v1.2.3 From bd20ff5793b4ece4fa3e9e0fcf8e6bbd93526215 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 20 Mar 2006 21:02:37 +0000 Subject: [ARM] 3374/1: ep93xx: gpio interrupt support Patch from Lennert Buytenhek Add GPIO interrupt support for the first 16 GPIO lines (port A and B.) Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/mach-ep93xx/core.c | 133 ++++++++++++++++++++++++++++++ include/asm-arm/arch-ep93xx/ep93xx-regs.h | 10 +++ include/asm-arm/arch-ep93xx/irqs.h | 4 +- 3 files changed, 146 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 7d3e79990fad..865427bfad7e 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -150,6 +150,26 @@ struct sys_timer ep93xx_timer = { /************************************************************************* * GPIO handling for EP93xx *************************************************************************/ +static unsigned char gpio_int_enable[2]; +static unsigned char gpio_int_type1[2]; +static unsigned char gpio_int_type2[2]; + +static void update_gpio_ab_int_params(int port) +{ + if (port == 0) { + __raw_writeb(0, EP93XX_GPIO_A_INT_ENABLE); + __raw_writeb(gpio_int_type2[0], EP93XX_GPIO_A_INT_TYPE2); + __raw_writeb(gpio_int_type1[0], EP93XX_GPIO_A_INT_TYPE1); + __raw_writeb(gpio_int_enable[0], EP93XX_GPIO_A_INT_ENABLE); + } else if (port == 1) { + __raw_writeb(0, EP93XX_GPIO_B_INT_ENABLE); + __raw_writeb(gpio_int_type2[1], EP93XX_GPIO_B_INT_TYPE2); + __raw_writeb(gpio_int_type1[1], EP93XX_GPIO_B_INT_TYPE1); + __raw_writeb(gpio_int_enable[1], EP93XX_GPIO_B_INT_ENABLE); + } +} + + static unsigned char data_register_offset[8] = { 0x00, 0x04, 0x08, 0x0c, 0x20, 0x30, 0x38, 0x40, }; @@ -169,6 +189,11 @@ void gpio_line_config(int line, int direction) local_irq_save(flags); if (direction == GPIO_OUT) { + if (line >= 0 && line < 16) { + gpio_int_enable[line >> 3] &= ~(1 << (line & 7)); + update_gpio_ab_int_params(line >> 3); + } + v = __raw_readb(data_direction_register); v |= 1 << (line & 7); __raw_writeb(v, data_direction_register); @@ -217,10 +242,118 @@ EXPORT_SYMBOL(gpio_line_set); /************************************************************************* * EP93xx IRQ handling *************************************************************************/ +static void ep93xx_gpio_ab_irq_handler(unsigned int irq, + struct irqdesc *desc, struct pt_regs *regs) +{ + unsigned char status; + int i; + + status = __raw_readb(EP93XX_GPIO_A_INT_STATUS); + for (i = 0; i < 8; i++) { + if (status & (1 << i)) { + desc = irq_desc + IRQ_EP93XX_GPIO(0) + i; + desc_handle_irq(IRQ_EP93XX_GPIO(0) + i, desc, regs); + } + } + + status = __raw_readb(EP93XX_GPIO_B_INT_STATUS); + for (i = 0; i < 8; i++) { + if (status & (1 << i)) { + desc = irq_desc + IRQ_EP93XX_GPIO(8) + i; + desc_handle_irq(IRQ_EP93XX_GPIO(8) + i, desc, regs); + } + } +} + +static void ep93xx_gpio_ab_irq_mask_ack(unsigned int irq) +{ + int line = irq - IRQ_EP93XX_GPIO(0); + int port = line >> 3; + + gpio_int_enable[port] &= ~(1 << (line & 7)); + update_gpio_ab_int_params(port); + + if (line >> 3) { + __raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK); + } else { + __raw_writel(1 << (line & 7), EP93XX_GPIO_A_INT_ACK); + } +} + +static void ep93xx_gpio_ab_irq_mask(unsigned int irq) +{ + int line = irq - IRQ_EP93XX_GPIO(0); + int port = line >> 3; + + gpio_int_enable[port] &= ~(1 << (line & 7)); + update_gpio_ab_int_params(port); +} + +static void ep93xx_gpio_ab_irq_unmask(unsigned int irq) +{ + int line = irq - IRQ_EP93XX_GPIO(0); + int port = line >> 3; + + gpio_int_enable[port] |= 1 << (line & 7); + update_gpio_ab_int_params(port); +} + + +/* + * gpio_int_type1 controls whether the interrupt is level (0) or + * edge (1) triggered, while gpio_int_type2 controls whether it + * triggers on low/falling (0) or high/rising (1). + */ +static int ep93xx_gpio_ab_irq_type(unsigned int irq, unsigned int type) +{ + int port; + int line; + + line = irq - IRQ_EP93XX_GPIO(0); + gpio_line_config(line, GPIO_IN); + + port = line >> 3; + line &= 7; + + if (type & IRQT_RISING) { + gpio_int_type1[port] |= 1 << line; + gpio_int_type2[port] |= 1 << line; + } else if (type & IRQT_FALLING) { + gpio_int_type1[port] |= 1 << line; + gpio_int_type2[port] &= ~(1 << line); + } else if (type & IRQT_HIGH) { + gpio_int_type1[port] &= ~(1 << line); + gpio_int_type2[port] |= 1 << line; + } else if (type & IRQT_LOW) { + gpio_int_type1[port] &= ~(1 << line); + gpio_int_type2[port] &= ~(1 << line); + } + update_gpio_ab_int_params(port); + + return 0; +} + +static struct irqchip ep93xx_gpio_ab_irq_chip = { + .ack = ep93xx_gpio_ab_irq_mask_ack, + .mask = ep93xx_gpio_ab_irq_mask, + .unmask = ep93xx_gpio_ab_irq_unmask, + .set_type = ep93xx_gpio_ab_irq_type, +}; + + void __init ep93xx_init_irq(void) { + int irq; + vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK); vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK); + + for (irq = IRQ_EP93XX_GPIO(0) ; irq <= IRQ_EP93XX_GPIO(15); irq++) { + set_irq_chip(irq, &ep93xx_gpio_ab_irq_chip); + set_irq_handler(irq, do_level_IRQ); + set_irq_flags(irq, IRQF_VALID); + } + set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler); } diff --git a/include/asm-arm/arch-ep93xx/ep93xx-regs.h b/include/asm-arm/arch-ep93xx/ep93xx-regs.h index c1efacc83b75..71cea0b5841b 100644 --- a/include/asm-arm/arch-ep93xx/ep93xx-regs.h +++ b/include/asm-arm/arch-ep93xx/ep93xx-regs.h @@ -72,6 +72,16 @@ #define EP93XX_GPIO_BASE (EP93XX_APB_VIRT_BASE + 0x00040000) #define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x)) +#define EP93XX_GPIO_A_INT_TYPE1 EP93XX_GPIO_REG(0x90) +#define EP93XX_GPIO_A_INT_TYPE2 EP93XX_GPIO_REG(0x94) +#define EP93XX_GPIO_A_INT_ACK EP93XX_GPIO_REG(0x98) +#define EP93XX_GPIO_A_INT_ENABLE EP93XX_GPIO_REG(0x9c) +#define EP93XX_GPIO_A_INT_STATUS EP93XX_GPIO_REG(0xa0) +#define EP93XX_GPIO_B_INT_TYPE1 EP93XX_GPIO_REG(0xac) +#define EP93XX_GPIO_B_INT_TYPE2 EP93XX_GPIO_REG(0xb0) +#define EP93XX_GPIO_B_INT_ACK EP93XX_GPIO_REG(0xb4) +#define EP93XX_GPIO_B_INT_ENABLE EP93XX_GPIO_REG(0xb8) +#define EP93XX_GPIO_B_INT_STATUS EP93XX_GPIO_REG(0xbc) #define EP93XX_AAC_BASE (EP93XX_APB_VIRT_BASE + 0x00080000) diff --git a/include/asm-arm/arch-ep93xx/irqs.h b/include/asm-arm/arch-ep93xx/irqs.h index 8c10fb964faf..9a42f5de9e57 100644 --- a/include/asm-arm/arch-ep93xx/irqs.h +++ b/include/asm-arm/arch-ep93xx/irqs.h @@ -67,7 +67,9 @@ #define IRQ_EP93XX_SAI 60 #define EP93XX_VIC2_VALID_IRQ_MASK 0x1fffffff -#define NR_EP93XX_IRQS 64 +#define IRQ_EP93XX_GPIO(x) (64 + (x)) + +#define NR_EP93XX_IRQS IRQ_EP93XX_GPIO(16) #define EP93XX_BOARD_IRQ(x) (NR_EP93XX_IRQS + (x)) #define EP93XX_BOARD_IRQS 32 -- cgit v1.2.3 From 4de151d8cd2553e7e89044ab5d72fcad4eb04afb Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 22 Mar 2006 00:13:35 +0100 Subject: It's UTF-8 Fix some comments to "UTF-8". Signed-off-by: Alexey Dobriyan Signed-off-by: Adrian Bunk --- Documentation/filesystems/isofs.txt | 4 ++-- Documentation/filesystems/jfs.txt | 2 +- Documentation/filesystems/vfat.txt | 6 +++--- fs/befs/linuxvfs.c | 2 +- fs/cifs/CHANGES | 2 +- fs/fat/dir.c | 2 +- fs/fat/inode.c | 2 +- fs/isofs/joliet.c | 2 +- fs/nls/Kconfig | 2 +- include/asm-mips/termbits.h | 2 +- include/linux/msdos_fs.h | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/Documentation/filesystems/isofs.txt b/Documentation/filesystems/isofs.txt index 424585ff6ea1..758e50401c16 100644 --- a/Documentation/filesystems/isofs.txt +++ b/Documentation/filesystems/isofs.txt @@ -9,9 +9,9 @@ when using discs encoded using Microsoft's Joliet extensions. iocharset=name Character set to use for converting from Unicode to ASCII. Joliet filenames are stored in Unicode format, but Unix for the most part doesn't know how to deal with Unicode. - There is also an option of doing UTF8 translations with the + There is also an option of doing UTF-8 translations with the utf8 option. - utf8 Encode Unicode names in UTF8 format. Default is no. + utf8 Encode Unicode names in UTF-8 format. Default is no. Mount options unique to the isofs filesystem. block=512 Set the block size for the disk to 512 bytes diff --git a/Documentation/filesystems/jfs.txt b/Documentation/filesystems/jfs.txt index 3e992daf99ad..bae128663748 100644 --- a/Documentation/filesystems/jfs.txt +++ b/Documentation/filesystems/jfs.txt @@ -6,7 +6,7 @@ The following mount options are supported: iocharset=name Character set to use for converting from Unicode to ASCII. The default is to do no conversion. Use - iocharset=utf8 for UTF8 translations. This requires + iocharset=utf8 for UTF-8 translations. This requires CONFIG_NLS_UTF8 to be set in the kernel .config file. iocharset=none specifies the default behavior explicitly. diff --git a/Documentation/filesystems/vfat.txt b/Documentation/filesystems/vfat.txt index 5ead20c6c744..2001abbc60e6 100644 --- a/Documentation/filesystems/vfat.txt +++ b/Documentation/filesystems/vfat.txt @@ -28,16 +28,16 @@ iocharset=name -- Character set to use for converting between the know how to deal with Unicode. By default, FAT_DEFAULT_IOCHARSET setting is used. - There is also an option of doing UTF8 translations + There is also an option of doing UTF-8 translations with the utf8 option. NOTE: "iocharset=utf8" is not recommended. If unsure, you should consider the following option instead. -utf8= -- UTF8 is the filesystem safe version of Unicode that +utf8= -- UTF-8 is the filesystem safe version of Unicode that is used by the console. It can be be enabled for the filesystem with this option. If 'uni_xlate' gets set, - UTF8 gets disabled. + UTF-8 gets disabled. uni_xlate= -- Translate unhandled Unicode characters to special escaped sequences. This would let you backup and diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 2d365cb8eec6..dd6048ce0532 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -561,7 +561,7 @@ befs_utf2nls(struct super_block *sb, const char *in, * @sb: Superblock * @src: Input string buffer in NLS format * @srclen: Length of input string in bytes - * @dest: The output string in UTF8 format + * @dest: The output string in UTF-8 format * @destlen: Length of the output buffer * * Converts input string @src, which is in the format of the loaded NLS map, diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index d335015473a5..cb68efba35db 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -160,7 +160,7 @@ improperly zeroed buffer in CIFS Unix extensions set times call. Version 1.25 ------------ Fix internationalization problem in cifs readdir with filenames that map to -longer UTF8 strings than the string on the wire was in Unicode. Add workaround +longer UTF-8 strings than the string on the wire was in Unicode. Add workaround for readdir to netapp servers. Fix search rewind (seek into readdir to return non-consecutive entries). Do not do readdir when server negotiates buffer size to small to fit filename. Add support for reading POSIX ACLs from diff --git a/fs/fat/dir.c b/fs/fat/dir.c index db0de5c621c7..4095bc149eb1 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -114,7 +114,7 @@ static inline int fat_get_entry(struct inode *dir, loff_t *pos, } /* - * Convert Unicode 16 to UTF8, translated Unicode, or ASCII. + * Convert Unicode 16 to UTF-8, translated Unicode, or ASCII. * If uni_xlate is enabled and we can't get a 1:1 conversion, use a * colon as an escape character since it is normally invalid on the vfat * filesystem. The following four characters are the hexadecimal digits diff --git a/fs/fat/inode.c b/fs/fat/inode.c index e7f4aa7fc686..e78d7b4842cc 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -1101,7 +1101,7 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, return -EINVAL; } } - /* UTF8 doesn't provide FAT semantics */ + /* UTF-8 doesn't provide FAT semantics */ if (!strcmp(opts->iocharset, "utf8")) { printk(KERN_ERR "FAT: utf8 is not a recommended IO charset" " for FAT filesystems, filesystem will be case sensitive!\n"); diff --git a/fs/isofs/joliet.c b/fs/isofs/joliet.c index 2931de7f1a6a..81a90e170ac3 100644 --- a/fs/isofs/joliet.c +++ b/fs/isofs/joliet.c @@ -11,7 +11,7 @@ #include "isofs.h" /* - * Convert Unicode 16 to UTF8 or ASCII. + * Convert Unicode 16 to UTF-8 or ASCII. */ static int uni16_to_x8(unsigned char *ascii, u16 *uni, int len, struct nls_table *nls) diff --git a/fs/nls/Kconfig b/fs/nls/Kconfig index 0ab8f00bdbb2..976ecccd6f56 100644 --- a/fs/nls/Kconfig +++ b/fs/nls/Kconfig @@ -491,7 +491,7 @@ config NLS_KOI8_U (koi8-u) and Belarusian (koi8-ru) character sets. config NLS_UTF8 - tristate "NLS UTF8" + tristate "NLS UTF-8" depends on NLS help If you want to display filenames with native language characters diff --git a/include/asm-mips/termbits.h b/include/asm-mips/termbits.h index c29c65b7818e..fa6d04dac56b 100644 --- a/include/asm-mips/termbits.h +++ b/include/asm-mips/termbits.h @@ -77,7 +77,7 @@ struct termios { #define IXANY 0004000 /* Any character will restart after stop. */ #define IXOFF 0010000 /* Enable start/stop input control. */ #define IMAXBEL 0020000 /* Ring bell when input queue is full. */ -#define IUTF8 0040000 /* Input is UTF8 */ +#define IUTF8 0040000 /* Input is UTF-8 */ /* c_oflag bits */ #define OPOST 0000001 /* Perform output processing. */ diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h index e933e2a355ad..8bcd9450d926 100644 --- a/include/linux/msdos_fs.h +++ b/include/linux/msdos_fs.h @@ -199,7 +199,7 @@ struct fat_mount_options { sys_immutable:1, /* set = system files are immutable */ dotsOK:1, /* set = hidden and system files are named '.filename' */ isvfat:1, /* 0=no vfat long filename support, 1=vfat support */ - utf8:1, /* Use of UTF8 character set (Default) */ + utf8:1, /* Use of UTF-8 character set (Default) */ unicode_xlate:1, /* create escape sequences for unhandled Unicode */ numtail:1, /* Does first alias have a numeric '~1' type tail? */ atari:1, /* Use Atari GEMDOS variation of MS-DOS fs */ -- cgit v1.2.3 From 116f232b3794a8b6ebde21aef5004b18cc1cfa86 Mon Sep 17 00:00:00 2001 From: Rytchkov Alexey Date: Wed, 22 Mar 2006 00:58:53 +0100 Subject: fixed path to moved file in include/linux/device.h Signed-off-by: Adrian Bunk --- include/linux/device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index 5b595fdfb672..10c1693a2529 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -399,7 +399,7 @@ extern struct device * get_device(struct device * dev); extern void put_device(struct device * dev); -/* drivers/base/power.c */ +/* drivers/base/power/shutdown.c */ extern void device_shutdown(void); -- cgit v1.2.3 From f59b0cf8a3a39b75e580066c6a9aeabd97ec2743 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Thu, 16 Mar 2006 17:59:22 +0800 Subject: [PATCH] libata-dev: Remove ATA_PROT_PIO_MULT Remove the ATA_PROT_PIO_MULT protocol. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 1 - drivers/scsi/libata-scsi.c | 7 ++++--- include/linux/ata.h | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index a28569d0081d..7a5392c8ec6f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3909,7 +3909,6 @@ static inline int ata_should_dma_map(struct ata_queued_cmd *qc) case ATA_PROT_ATAPI: case ATA_PROT_PIO: - case ATA_PROT_PIO_MULT: if (ap->flags & ATA_FLAG_PIO_DMA) return 1; diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 3aaa74cbef1d..cebf9b31b516 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -2379,9 +2379,6 @@ ata_scsi_map_proto(u8 byte1) case 4: /* PIO Data-in */ case 5: /* PIO Data-out */ - if (byte1 & 0xe0) { - return ATA_PROT_PIO_MULT; - } return ATA_PROT_PIO; case 10: /* Device Reset */ @@ -2420,6 +2417,10 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd) if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN) goto invalid_fld; + if (scsicmd[1] & 0xe0) + /* PIO multi not supported yet */ + goto invalid_fld; + /* * 12 and 16 byte CDBs use different offsets to * provide the various register values. diff --git a/include/linux/ata.h b/include/linux/ata.h index b02a16c435e7..6b188b3b61dd 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -204,7 +204,6 @@ enum ata_tf_protocols { ATA_PROT_UNKNOWN, /* unknown/invalid */ ATA_PROT_NODATA, /* no data */ ATA_PROT_PIO, /* PIO single sector */ - ATA_PROT_PIO_MULT, /* PIO multiple sector */ ATA_PROT_DMA, /* DMA */ ATA_PROT_ATAPI, /* packet command, PIO data xfer*/ ATA_PROT_ATAPI_NODATA, /* packet command, no data */ -- cgit v1.2.3 From e46834cd2ddb1e2941806cb8fec60fb6bdd2ec29 Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 17 Mar 2006 17:04:03 -0600 Subject: [PATCH] libata: Add some dummy noop functions Add some dummy noop functions for use by libata clients that do not need to do anything. Future SAS patches will utilize these functions. Signed-off-by: Brian King Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 3 +++ include/linux/libata.h | 1 + 2 files changed, 4 insertions(+) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 7a5392c8ec6f..8c86ae8d79b5 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2865,6 +2865,8 @@ void ata_qc_prep(struct ata_queued_cmd *qc) ata_fill_sg(qc); } +void ata_noop_qc_prep(struct ata_queued_cmd *qc) { } + /** * ata_sg_init_one - Associate command with memory buffer * @qc: Command to be associated @@ -5063,6 +5065,7 @@ EXPORT_SYMBOL_GPL(ata_port_stop); EXPORT_SYMBOL_GPL(ata_host_stop); EXPORT_SYMBOL_GPL(ata_interrupt); EXPORT_SYMBOL_GPL(ata_qc_prep); +EXPORT_SYMBOL_GPL(ata_noop_qc_prep); EXPORT_SYMBOL_GPL(ata_bmdma_setup); EXPORT_SYMBOL_GPL(ata_bmdma_start); EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear); diff --git a/include/linux/libata.h b/include/linux/libata.h index 239408ecfddf..17e5a719c72b 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -543,6 +543,7 @@ extern void ata_port_stop (struct ata_port *ap); extern void ata_host_stop (struct ata_host_set *host_set); extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs); extern void ata_qc_prep(struct ata_queued_cmd *qc); +extern void ata_noop_qc_prep(struct ata_queued_cmd *qc); extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc); extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen); -- cgit v1.2.3 From b6782728d703fa3f0e5478a8b89e49ea10b1fdd0 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 21 Mar 2006 15:52:49 +0000 Subject: [PATCH] libata: Add the useful macros/constants needed for merging PATA stuff HPA presence/enabled HPA commands Also add ata_id_is_cfa() as that is needed to detect and handle CF cards which currently we reject. Signed-off-by: Jeff Garzik --- include/linux/ata.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include') diff --git a/include/linux/ata.h b/include/linux/ata.h index 6b188b3b61dd..312a2c0c64e6 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -146,6 +146,8 @@ enum { ATA_CMD_STANDBYNOW1 = 0xE0, ATA_CMD_IDLEIMMEDIATE = 0xE1, ATA_CMD_INIT_DEV_PARAMS = 0x91, + ATA_CMD_READ_NATIVE_MAX = 0xF8, + ATA_CMD_READ_NATIVE_MAX_EXT = 0x27, /* SETFEATURES stuff */ SETFEATURES_XFER = 0x03, @@ -246,18 +248,22 @@ struct ata_taskfile { }; #define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0) +#define ata_id_is_cfa(id) ((id)[0] == 0x848A) #define ata_id_is_sata(id) ((id)[93] == 0) #define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6)) #define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5)) +#define ata_id_hpa_enabled(id) ((id)[85] & (1 << 10)) #define ata_id_has_fua(id) ((id)[84] & (1 << 6)) #define ata_id_has_flush(id) ((id)[83] & (1 << 12)) #define ata_id_has_flush_ext(id) ((id)[83] & (1 << 13)) #define ata_id_has_lba48(id) ((id)[83] & (1 << 10)) +#define ata_id_has_hpa(id) ((id)[82] & (1 << 10)) #define ata_id_has_wcache(id) ((id)[82] & (1 << 5)) #define ata_id_has_pm(id) ((id)[82] & (1 << 3)) #define ata_id_has_lba(id) ((id)[49] & (1 << 9)) #define ata_id_has_dma(id) ((id)[49] & (1 << 8)) #define ata_id_removeable(id) ((id)[0] & (1 << 7)) +#define ata_id_has_dword_io(id) ((id)[50] & (1 << 0)) #define ata_id_u32(id,n) \ (((u32) (id)[(n) + 1] << 16) | ((u32) (id)[(n)])) #define ata_id_u64(id,n) \ -- cgit v1.2.3 From 17bb34a3c548c4fd2a7c859123a631f97c2af09f Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 21 Mar 2006 21:29:21 -0500 Subject: [libata] add prototypes for helpers Add prototypes for stuff recently added by Alan. --- include/linux/libata.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/libata.h b/include/linux/libata.h index 17e5a719c72b..d81cecdda4f3 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -502,6 +502,7 @@ extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_i extern void ata_pci_remove_one (struct pci_dev *pdev); extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state); extern int ata_pci_device_resume(struct pci_dev *pdev); +extern int ata_pci_clear_simplex(struct pci_dev *pdev); #endif /* CONFIG_PCI */ extern int ata_device_add(const struct ata_probe_ent *ent); extern void ata_host_set_remove(struct ata_host_set *host_set); @@ -610,7 +611,7 @@ extern void ata_pci_host_stop (struct ata_host_set *host_set); extern struct ata_probe_ent * ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int portmask); extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits); - +extern unsigned long ata_pci_default_filter(const struct ata_port *, struct ata_device *, unsigned long); #endif /* CONFIG_PCI */ -- cgit v1.2.3 From 3d15910bfbeb02286ce4b5009c53754e88066ccb Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 21 Mar 2006 20:45:58 +1100 Subject: [PATCH] powerpc: trivial: Cleanup whitespace in cputable.h Remove redundant whitespace in include/asm-powerpc/cputable.h Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- include/asm-powerpc/cputable.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index aaaeb452770f..fe45f6f3a4be 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -102,19 +102,19 @@ extern void do_cpu_ftr_fixups(unsigned long offset); #define CPU_FTR_NEED_COHERENT ASM_CONST(0x0000000000020000) #define CPU_FTR_NO_BTIC ASM_CONST(0x0000000000040000) #define CPU_FTR_BIG_PHYS ASM_CONST(0x0000000000080000) -#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000000000100000) +#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000000000100000) #ifdef __powerpc64__ /* Add the 64b processor unique features in the top half of the word */ -#define CPU_FTR_SLB ASM_CONST(0x0000000100000000) -#define CPU_FTR_16M_PAGE ASM_CONST(0x0000000200000000) -#define CPU_FTR_TLBIEL ASM_CONST(0x0000000400000000) -#define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000800000000) -#define CPU_FTR_IABR ASM_CONST(0x0000002000000000) -#define CPU_FTR_MMCRA ASM_CONST(0x0000004000000000) +#define CPU_FTR_SLB ASM_CONST(0x0000000100000000) +#define CPU_FTR_16M_PAGE ASM_CONST(0x0000000200000000) +#define CPU_FTR_TLBIEL ASM_CONST(0x0000000400000000) +#define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000800000000) +#define CPU_FTR_IABR ASM_CONST(0x0000002000000000) +#define CPU_FTR_MMCRA ASM_CONST(0x0000004000000000) #define CPU_FTR_CTRL ASM_CONST(0x0000008000000000) -#define CPU_FTR_SMT ASM_CONST(0x0000010000000000) -#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000) +#define CPU_FTR_SMT ASM_CONST(0x0000010000000000) +#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000) #define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0000040000000000) #define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000) #define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0000100000000000) @@ -123,15 +123,15 @@ extern void do_cpu_ftr_fixups(unsigned long offset); #else /* ensure on 32b processors the flags are available for compiling but * don't do anything */ -#define CPU_FTR_SLB ASM_CONST(0x0) -#define CPU_FTR_16M_PAGE ASM_CONST(0x0) -#define CPU_FTR_TLBIEL ASM_CONST(0x0) -#define CPU_FTR_NOEXECUTE ASM_CONST(0x0) -#define CPU_FTR_IABR ASM_CONST(0x0) -#define CPU_FTR_MMCRA ASM_CONST(0x0) +#define CPU_FTR_SLB ASM_CONST(0x0) +#define CPU_FTR_16M_PAGE ASM_CONST(0x0) +#define CPU_FTR_TLBIEL ASM_CONST(0x0) +#define CPU_FTR_NOEXECUTE ASM_CONST(0x0) +#define CPU_FTR_IABR ASM_CONST(0x0) +#define CPU_FTR_MMCRA ASM_CONST(0x0) #define CPU_FTR_CTRL ASM_CONST(0x0) -#define CPU_FTR_SMT ASM_CONST(0x0) -#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0) +#define CPU_FTR_SMT ASM_CONST(0x0) +#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0) #define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0) #define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0) #define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0) -- cgit v1.2.3 From 57cfb814f698d30894bc28e22125550193ebe549 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 21 Mar 2006 20:45:59 +1100 Subject: [PATCH] powerpc: Replace platform_is_lpar() with a firmware feature It has been decreed that platform numbers are evil, so as a step in that direction, replace platform_is_lpar() with a FW_FEATURE_LPAR bit. Currently FW_FEATURE_LPAR really means i/pSeries LPAR, in the future we might have to clean that up if we need to be more specific about what LPAR actually means. But that's another patch ... Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/mm/hash_utils_64.c | 4 ++-- arch/powerpc/oprofile/op_model_power4.c | 3 ++- arch/powerpc/platforms/iseries/setup.c | 10 +++++++--- arch/powerpc/platforms/pseries/iommu.c | 2 +- arch/powerpc/platforms/pseries/setup.c | 11 +++++++---- arch/powerpc/platforms/pseries/smp.c | 2 +- arch/powerpc/platforms/pseries/xics.c | 3 ++- include/asm-powerpc/firmware.h | 7 ++++--- include/asm-powerpc/processor.h | 1 - 9 files changed, 26 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 7b4eccffd002..89b35c181314 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -422,7 +422,7 @@ void __init htab_initialize(void) htab_hash_mask = pteg_count - 1; - if (platform_is_lpar()) { + if (firmware_has_feature(FW_FEATURE_LPAR)) { /* Using a hypervisor which owns the htab */ htab_address = NULL; _SDR1 = 0; @@ -517,7 +517,7 @@ void __init htab_initialize(void) void htab_initialize_secondary(void) { - if (!platform_is_lpar()) + if (!firmware_has_feature(FW_FEATURE_LPAR)) mtspr(SPRN_SDR1, _SDR1); } diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c index 659a021da0c7..4b06e53eb9b4 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -232,7 +233,7 @@ static unsigned long get_pc(struct pt_regs *regs) mmcra = mfspr(SPRN_MMCRA); /* Were we in the hypervisor? */ - if (platform_is_lpar() && (mmcra & MMCRA_SIHV)) + if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & MMCRA_SIHV)) /* function descriptor madness */ return *((unsigned long *)hypervisor_bucket); diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 3ecc4a652d82..b08c3686f903 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -303,8 +303,6 @@ static void __init iSeries_init_early(void) { DBG(" -> iSeries_init_early()\n"); - ppc64_firmware_features = FW_FEATURE_ISERIES; - ppc64_interrupt_controller = IC_ISERIES; #if defined(CONFIG_BLK_DEV_INITRD) @@ -711,7 +709,13 @@ void __init iSeries_init_IRQ(void) { } static int __init iseries_probe(int platform) { - return PLATFORM_ISERIES_LPAR == platform; + if (PLATFORM_ISERIES_LPAR != platform) + return 0; + + ppc64_firmware_features |= FW_FEATURE_ISERIES; + ppc64_firmware_features |= FW_FEATURE_LPAR; + + return 1; } struct machdep_calls __initdata iseries_md = { diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 57930e23cc74..2643078433f0 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -580,7 +580,7 @@ void iommu_init_early_pSeries(void) return; } - if (platform_is_lpar()) { + if (firmware_has_feature(FW_FEATURE_LPAR)) { if (firmware_has_feature(FW_FEATURE_MULTITCE)) { ppc_md.tce_build = tce_buildmulti_pSeriesLP; ppc_md.tce_free = tce_freemulti_pSeriesLP; diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 149751a3742a..44d5c7fdcd97 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -246,7 +246,7 @@ static void __init pSeries_setup_arch(void) ppc_md.idle_loop = default_idle; } - if (platform_is_lpar()) + if (firmware_has_feature(FW_FEATURE_LPAR)) ppc_md.enable_pmcs = pseries_lpar_enable_pmcs; else ppc_md.enable_pmcs = power4_enable_pmcs; @@ -324,12 +324,12 @@ static void __init pSeries_init_early(void) fw_feature_init(); - if (platform_is_lpar()) + if (firmware_has_feature(FW_FEATURE_LPAR)) hpte_init_lpar(); else hpte_init_native(); - if (platform_is_lpar()) + if (firmware_has_feature(FW_FEATURE_LPAR)) find_udbg_vterm(); if (firmware_has_feature(FW_FEATURE_DABR)) @@ -385,6 +385,9 @@ static int __init pSeries_probe(int platform) * it here ... */ + if (platform == PLATFORM_PSERIES_LPAR) + ppc64_firmware_features |= FW_FEATURE_LPAR; + return 1; } @@ -524,7 +527,7 @@ static void pseries_shared_idle(void) static int pSeries_pci_probe_mode(struct pci_bus *bus) { - if (platform_is_lpar()) + if (firmware_has_feature(FW_FEATURE_LPAR)) return PCI_PROBE_DEVTREE; return PCI_PROBE_NORMAL; } diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 8d710af50756..3cf78a6cd27c 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c @@ -443,7 +443,7 @@ void __init smp_init_pSeries(void) smp_ops->cpu_die = pSeries_cpu_die; /* Processors can be added/removed only on LPAR */ - if (platform_is_lpar()) + if (firmware_has_feature(FW_FEATURE_LPAR)) pSeries_reconfig_notifier_register(&pSeries_smp_nb); #endif diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index fd823c7c9ac8..eb86cdb9b802 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -536,7 +537,7 @@ nextnode: of_node_put(np); } - if (platform_is_lpar()) + if (firmware_has_feature(FW_FEATURE_LPAR)) ops = &pSeriesLP_ops; else { #ifdef CONFIG_SMP diff --git a/include/asm-powerpc/firmware.h b/include/asm-powerpc/firmware.h index b7791a1b05db..ce3788224ed0 100644 --- a/include/asm-powerpc/firmware.h +++ b/include/asm-powerpc/firmware.h @@ -41,6 +41,7 @@ #define FW_FEATURE_MULTITCE (1UL<<19) #define FW_FEATURE_SPLPAR (1UL<<20) #define FW_FEATURE_ISERIES (1UL<<21) +#define FW_FEATURE_LPAR (1UL<<22) enum { #ifdef CONFIG_PPC64 @@ -51,10 +52,10 @@ enum { FW_FEATURE_MIGRATE | FW_FEATURE_PERFMON | FW_FEATURE_CRQ | FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN | FW_FEATURE_BULK | FW_FEATURE_XDABR | FW_FEATURE_MULTITCE | - FW_FEATURE_SPLPAR, + FW_FEATURE_SPLPAR | FW_FEATURE_LPAR, FW_FEATURE_PSERIES_ALWAYS = 0, - FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES, - FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES, + FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, + FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, FW_FEATURE_POSSIBLE = #ifdef CONFIG_PPC_PSERIES FW_FEATURE_PSERIES_POSSIBLE | diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h index 415fa393b00c..1c64a211cf19 100644 --- a/include/asm-powerpc/processor.h +++ b/include/asm-powerpc/processor.h @@ -52,7 +52,6 @@ #ifdef __KERNEL__ #define platform_is_pseries() (_machine == PLATFORM_PSERIES || \ _machine == PLATFORM_PSERIES_LPAR) -#define platform_is_lpar() (!!(_machine & PLATFORM_LPAR)) #if defined(CONFIG_PPC_MULTIPLATFORM) extern int _machine; -- cgit v1.2.3 From 260de22faac4d336ca122ebd0f1e59279d0b1dfd Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 21 Mar 2006 20:46:02 +1100 Subject: [PATCH] powerpc: iseries: mf related cleanups Some cleanups in the iSeries code. - Make mf_display_progress() check mf_initialized rather than the caller. - Set mf_initialized in mf_init() rather than in setup.c - Then move mf_initialized into mf.c, the only place it's used. - Move the mf related logic from iSeries_progress() to mf_display_progress() - Use a #define to size the pending_event_prealloc array - Use that define in the initialsation loop rather than sizeof jiggery pokery - Remove stupid comment(s) - Mark stuff static and/or __init Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/mf.c | 32 +++++++++++++++++++++++--------- arch/powerpc/platforms/iseries/setup.c | 11 +---------- include/asm-powerpc/iseries/mf.h | 1 - 3 files changed, 24 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index a41d8b78c0cd..97a26137cf40 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -46,6 +46,7 @@ #include "setup.h" extern int piranha_simulator; +static int mf_initialized; /* * This is the structure layout for the Machine Facilites LPAR event @@ -143,7 +144,8 @@ static spinlock_t pending_event_spinlock; static struct pending_event *pending_event_head; static struct pending_event *pending_event_tail; static struct pending_event *pending_event_avail; -static struct pending_event pending_event_prealloc[16]; +#define PENDING_EVENT_PREALLOC_LEN 16 +static struct pending_event pending_event_prealloc[PENDING_EVENT_PREALLOC_LEN]; /* * Put a pending event onto the available queue, so it can get reused. @@ -625,7 +627,7 @@ void mf_display_src(u32 word) /* * Display a single word SRC of the form "PROGXXXX" on the VSP control panel. */ -void mf_display_progress(u16 value) +static __init void mf_display_progress_src(u16 value) { u8 ce[12]; u8 src[72]; @@ -649,30 +651,42 @@ void mf_display_progress(u16 value) * Clear the VSP control panel. Used to "erase" an SRC that was * previously displayed. */ -void mf_clear_src(void) +static void mf_clear_src(void) { signal_ce_msg_simple(0x4b, NULL); } +void __init mf_display_progress(u16 value) +{ + if (piranha_simulator || !mf_initialized) + return; + + if (0xFFFF == value) + mf_clear_src(); + else + mf_display_progress_src(value); +} + /* * Initialization code here. */ -void mf_init(void) +void __init mf_init(void) { int i; - /* initialize */ spin_lock_init(&pending_event_spinlock); - for (i = 0; - i < sizeof(pending_event_prealloc) / sizeof(*pending_event_prealloc); - ++i) + + for (i = 0; i < PENDING_EVENT_PREALLOC_LEN; i++) free_pending_event(&pending_event_prealloc[i]); + HvLpEvent_registerHandler(HvLpEvent_Type_MachineFac, &hv_handler); /* virtual continue ack */ signal_ce_msg_simple(0x57, NULL); - /* initialization complete */ + mf_initialized = 1; + mb(); + printk(KERN_NOTICE "mf.c: iSeries Linux LPAR Machine Facilities " "initialized\n"); } diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index b08c3686f903..190891ce9cb4 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -89,8 +89,6 @@ extern unsigned long embedded_sysmap_end; extern unsigned long iSeries_recal_tb; extern unsigned long iSeries_recal_titan; -static int mf_initialized; - static unsigned long cmd_mem_limit; struct MemoryBlock { @@ -347,8 +345,6 @@ static void __init iSeries_init_early(void) HvCallEvent_setLpEventQueueInterruptProc(0, 0); mf_init(); - mf_initialized = 1; - mb(); /* If we were passed an initrd, set the ROOT_DEV properly if the values * look sensible. If not, clear initrd reference. @@ -585,12 +581,7 @@ static void iSeries_halt(void) static void __init iSeries_progress(char * st, unsigned short code) { printk("Progress: [%04x] - %s\n", (unsigned)code, st); - if (!piranha_simulator && mf_initialized) { - if (code != 0xffff) - mf_display_progress(code); - else - mf_clear_src(); - } + mf_display_progress(code); } static void __init iSeries_fixup_klimit(void) diff --git a/include/asm-powerpc/iseries/mf.h b/include/asm-powerpc/iseries/mf.h index 857e5202fc78..335e163daaf3 100644 --- a/include/asm-powerpc/iseries/mf.h +++ b/include/asm-powerpc/iseries/mf.h @@ -45,7 +45,6 @@ extern void mf_reboot(void); extern void mf_display_src(u32 word); extern void mf_display_progress(u16 value); -extern void mf_clear_src(void); extern void mf_init(void); -- cgit v1.2.3 From a9ea2101aaa7fe73cb352cea4145853efdabaa0d Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 21 Mar 2006 20:46:04 +1100 Subject: [PATCH] powerpc: iseries: Remove pointless iSeries_(restart|power_off|halt) These routines just call through to the mf routines, so point ppc_md straight at the mf routines. We need to pass the cmd through to mf_reboot to make it work, but that seems reasonable. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/mf.c | 2 +- arch/powerpc/platforms/iseries/setup.c | 30 +++--------------------------- include/asm-powerpc/iseries/mf.h | 2 +- 3 files changed, 5 insertions(+), 29 deletions(-) (limited to 'include') diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index 97a26137cf40..18054e922bd1 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -599,7 +599,7 @@ void mf_power_off(void) * Global kernel interface to tell the VSP object in the primary * partition to reboot this partition. */ -void mf_reboot(void) +void mf_reboot(char *cmd) { printk(KERN_INFO "mf.c: Preparing to bounce...\n"); signal_ce_msg_simple(0x4e, NULL); diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 190891ce9cb4..127af3b0ba82 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -554,30 +554,6 @@ static void iSeries_show_cpuinfo(struct seq_file *m) seq_printf(m, "machine\t\t: 64-bit iSeries Logical Partition\n"); } -/* - * Document me. - */ -static void iSeries_restart(char *cmd) -{ - mf_reboot(); -} - -/* - * Document me. - */ -static void iSeries_power_off(void) -{ - mf_power_off(); -} - -/* - * Document me. - */ -static void iSeries_halt(void) -{ - mf_power_off(); -} - static void __init iSeries_progress(char * st, unsigned short code) { printk("Progress: [%04x] - %s\n", (unsigned)code, st); @@ -716,9 +692,9 @@ struct machdep_calls __initdata iseries_md = { .get_irq = iSeries_get_irq, .init_early = iSeries_init_early, .pcibios_fixup = iSeries_pci_final_fixup, - .restart = iSeries_restart, - .power_off = iSeries_power_off, - .halt = iSeries_halt, + .restart = mf_reboot, + .power_off = mf_power_off, + .halt = mf_power_off, .get_boot_time = iSeries_get_boot_time, .set_rtc_time = iSeries_set_rtc_time, .get_rtc_time = iSeries_get_rtc_time, diff --git a/include/asm-powerpc/iseries/mf.h b/include/asm-powerpc/iseries/mf.h index 335e163daaf3..89f3282df04d 100644 --- a/include/asm-powerpc/iseries/mf.h +++ b/include/asm-powerpc/iseries/mf.h @@ -41,7 +41,7 @@ extern void mf_deallocate_lp_events(HvLpIndex targetLp, HvLpEvent_Type type, unsigned count, MFCompleteHandler hdlr, void *userToken); extern void mf_power_off(void); -extern void mf_reboot(void); +extern void mf_reboot(char *cmd); extern void mf_display_src(u32 word); extern void mf_display_progress(u16 value); -- cgit v1.2.3 From 00611c5cfc8dea0914c65134f62948a484780a30 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 21 Mar 2006 20:46:05 +1100 Subject: [PATCH] powerpc: iseries: Make more stuff static in platforms/iseries/mf.c Make mf_get_rtc(), mf_get_boot_rtc() and mf_set_rtc() static, cause they can be. We need to move mf_set_rtc() to avoid a forward declaration. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/mf.c | 78 ++++++++++++++++++------------------- include/asm-powerpc/iseries/mf.h | 4 -- 2 files changed, 39 insertions(+), 43 deletions(-) (limited to 'include') diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index 18054e922bd1..d771b8ee857d 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -706,6 +706,43 @@ static void get_rtc_time_complete(void *token, struct ce_msg_data *ce_msg) complete(&rtc->com); } +static int mf_set_rtc(struct rtc_time *tm) +{ + char ce_time[12]; + u8 day, mon, hour, min, sec, y1, y2; + unsigned year; + + year = 1900 + tm->tm_year; + y1 = year / 100; + y2 = year % 100; + + sec = tm->tm_sec; + min = tm->tm_min; + hour = tm->tm_hour; + day = tm->tm_mday; + mon = tm->tm_mon + 1; + + BIN_TO_BCD(sec); + BIN_TO_BCD(min); + BIN_TO_BCD(hour); + BIN_TO_BCD(mon); + BIN_TO_BCD(day); + BIN_TO_BCD(y1); + BIN_TO_BCD(y2); + + memset(ce_time, 0, sizeof(ce_time)); + ce_time[3] = 0x41; + ce_time[4] = y1; + ce_time[5] = y2; + ce_time[6] = sec; + ce_time[7] = min; + ce_time[8] = hour; + ce_time[10] = day; + ce_time[11] = mon; + + return signal_ce_msg(ce_time, NULL); +} + static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm) { tm->tm_wday = 0; @@ -761,7 +798,7 @@ static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm) return 0; } -int mf_get_rtc(struct rtc_time *tm) +static int mf_get_rtc(struct rtc_time *tm) { struct ce_msg_comp_data ce_complete; struct rtc_time_data rtc_data; @@ -794,7 +831,7 @@ static void get_boot_rtc_time_complete(void *token, struct ce_msg_data *ce_msg) rtc->busy = 0; } -int mf_get_boot_rtc(struct rtc_time *tm) +static int mf_get_boot_rtc(struct rtc_time *tm) { struct ce_msg_comp_data ce_complete; struct boot_rtc_time_data rtc_data; @@ -816,43 +853,6 @@ int mf_get_boot_rtc(struct rtc_time *tm) return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm); } -int mf_set_rtc(struct rtc_time *tm) -{ - char ce_time[12]; - u8 day, mon, hour, min, sec, y1, y2; - unsigned year; - - year = 1900 + tm->tm_year; - y1 = year / 100; - y2 = year % 100; - - sec = tm->tm_sec; - min = tm->tm_min; - hour = tm->tm_hour; - day = tm->tm_mday; - mon = tm->tm_mon + 1; - - BIN_TO_BCD(sec); - BIN_TO_BCD(min); - BIN_TO_BCD(hour); - BIN_TO_BCD(mon); - BIN_TO_BCD(day); - BIN_TO_BCD(y1); - BIN_TO_BCD(y2); - - memset(ce_time, 0, sizeof(ce_time)); - ce_time[3] = 0x41; - ce_time[4] = y1; - ce_time[5] = y2; - ce_time[6] = sec; - ce_time[7] = min; - ce_time[8] = hour; - ce_time[10] = day; - ce_time[11] = mon; - - return signal_ce_msg(ce_time, NULL); -} - #ifdef CONFIG_PROC_FS static int proc_mf_dump_cmdline(char *page, char **start, off_t off, diff --git a/include/asm-powerpc/iseries/mf.h b/include/asm-powerpc/iseries/mf.h index 89f3282df04d..eb851a9c9e5c 100644 --- a/include/asm-powerpc/iseries/mf.h +++ b/include/asm-powerpc/iseries/mf.h @@ -48,8 +48,4 @@ extern void mf_display_progress(u16 value); extern void mf_init(void); -extern int mf_get_rtc(struct rtc_time *tm); -extern int mf_get_boot_rtc(struct rtc_time *tm); -extern int mf_set_rtc(struct rtc_time *tm); - #endif /* _ASM_POWERPC_ISERIES_MF_H */ -- cgit v1.2.3 From 584fc6d111c34a9a2512f6c7652dff29232bf70d Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 21 Mar 2006 20:46:08 +1100 Subject: [PATCH] powerpc: Add strne2a() to convert a string from EBCDIC to ASCII Add strne2a() which converts a string from EBCDIC to ASCII. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/lib/e2a.c | 10 ++++++++++ include/asm-powerpc/system.h | 2 ++ 2 files changed, 12 insertions(+) (limited to 'include') diff --git a/arch/powerpc/lib/e2a.c b/arch/powerpc/lib/e2a.c index 4f88f4cc21e8..4b72ed8fd50e 100644 --- a/arch/powerpc/lib/e2a.c +++ b/arch/powerpc/lib/e2a.c @@ -103,4 +103,14 @@ unsigned char e2a(unsigned char x) } EXPORT_SYMBOL(e2a); +unsigned char* strne2a(unsigned char *dest, const unsigned char *src, size_t n) +{ + int i; + + n = strnlen(src, n); + for (i = 0; i < n; i++) + dest[i] = e2a(src[i]); + + return dest; +} diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h index 41b7a5b3d701..65f5a7b2646b 100644 --- a/include/asm-powerpc/system.h +++ b/include/asm-powerpc/system.h @@ -171,6 +171,8 @@ extern u32 booke_wdt_period; /* EBCDIC -> ASCII conversion for [0-9A-Z] on iSeries */ extern unsigned char e2a(unsigned char); +extern unsigned char* strne2a(unsigned char *dest, + const unsigned char *src, size_t n); struct device_node; extern void note_scsi_host(struct device_node *, void *); -- cgit v1.2.3 From f8642ebee8e46d054d83828a4048fba4ebcd8f68 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 21 Mar 2006 20:46:11 +1100 Subject: [PATCH] powerpc: Remove calculation of io hole In mm_init_ppc64() we calculate the location of the "IO hole", but then no one ever looks at the value. So don't bother. That's actually all mm_init_ppc64() does, so get rid of it too. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/setup_64.c | 2 -- arch/powerpc/mm/init_64.c | 48 ------------------------------------------ include/asm-powerpc/lmb.h | 2 -- include/asm-powerpc/mmu.h | 1 - 4 files changed, 53 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index f96c49b03ba0..2f3fdad35594 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -497,8 +497,6 @@ void __init setup_system(void) #endif printk("-----------------------------------------------------\n"); - mm_init_ppc64(); - DBG(" <- setup_system()\n"); } diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 81cfb0c2ec58..5d4733d61805 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -84,54 +84,6 @@ /* max amount of RAM to use */ unsigned long __max_memory; -/* info on what we think the IO hole is */ -unsigned long io_hole_start; -unsigned long io_hole_size; - -/* - * Do very early mm setup. - */ -void __init mm_init_ppc64(void) -{ -#ifndef CONFIG_PPC_ISERIES - unsigned long i; -#endif - - ppc64_boot_msg(0x100, "MM Init"); - - /* This is the story of the IO hole... please, keep seated, - * unfortunately, we are out of oxygen masks at the moment. - * So we need some rough way to tell where your big IO hole - * is. On pmac, it's between 2G and 4G, on POWER3, it's around - * that area as well, on POWER4 we don't have one, etc... - * We need that as a "hint" when sizing the TCE table on POWER3 - * So far, the simplest way that seem work well enough for us it - * to just assume that the first discontinuity in our physical - * RAM layout is the IO hole. That may not be correct in the future - * (and isn't on iSeries but then we don't care ;) - */ - -#ifndef CONFIG_PPC_ISERIES - for (i = 1; i < lmb.memory.cnt; i++) { - unsigned long base, prevbase, prevsize; - - prevbase = lmb.memory.region[i-1].base; - prevsize = lmb.memory.region[i-1].size; - base = lmb.memory.region[i].base; - if (base > (prevbase + prevsize)) { - io_hole_start = prevbase + prevsize; - io_hole_size = base - (prevbase + prevsize); - break; - } - } -#endif /* CONFIG_PPC_ISERIES */ - if (io_hole_start) - printk("IO Hole assumed to be %lx -> %lx\n", - io_hole_start, io_hole_start + io_hole_size - 1); - - ppc64_boot_msg(0x100, "MM Init Done"); -} - void free_initmem(void) { unsigned long addr; diff --git a/include/asm-powerpc/lmb.h b/include/asm-powerpc/lmb.h index 377ac1b23aa3..0c5880f70225 100644 --- a/include/asm-powerpc/lmb.h +++ b/include/asm-powerpc/lmb.h @@ -54,8 +54,6 @@ extern void __init lmb_enforce_memory_limit(unsigned long memory_limit); extern void lmb_dump_all(void); -extern unsigned long io_hole_start; - static inline unsigned long lmb_size_bytes(struct lmb_region *type, unsigned long region_nr) { diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h index b0b9a3f8cdc2..31f721994bd8 100644 --- a/include/asm-powerpc/mmu.h +++ b/include/asm-powerpc/mmu.h @@ -236,7 +236,6 @@ extern void htab_initialize_secondary(void); extern void hpte_init_native(void); extern void hpte_init_lpar(void); extern void hpte_init_iSeries(void); -extern void mm_init_ppc64(void); extern long pSeries_lpar_hpte_insert(unsigned long hpte_group, unsigned long va, unsigned long prpn, -- cgit v1.2.3 From 89bbfc95d65839d6ae23ddab8a3cc5af4ae88383 Mon Sep 17 00:00:00 2001 From: Shaun Pereira Date: Tue, 21 Mar 2006 23:58:08 -0800 Subject: [NET]: allow 32 bit socket ioctl in 64 bit kernel Since the register_ioctl32_conversion() patch in the kernel is now obsolete, provide another method to allow 32 bit user space ioctls to reach the kernel. Signed-off-by: Shaun Pereira Acked-by: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- include/linux/net.h | 6 ++++++ net/socket.c | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+) (limited to 'include') diff --git a/include/linux/net.h b/include/linux/net.h index 152fa6551fd8..84a490e5f0a1 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -143,6 +143,8 @@ struct proto_ops { struct poll_table_struct *wait); int (*ioctl) (struct socket *sock, unsigned int cmd, unsigned long arg); + int (*compat_ioctl) (struct socket *sock, unsigned int cmd, + unsigned long arg); int (*listen) (struct socket *sock, int len); int (*shutdown) (struct socket *sock, int flags); int (*setsockopt)(struct socket *sock, int level, @@ -251,6 +253,8 @@ SOCKCALL_UWRAP(name, poll, (struct file *file, struct socket *sock, struct poll_ (file, sock, wait)) \ SOCKCALL_WRAP(name, ioctl, (struct socket *sock, unsigned int cmd, \ unsigned long arg), (sock, cmd, arg)) \ +SOCKCALL_WRAP(name, compat_ioctl, (struct socket *sock, unsigned int cmd, \ + unsigned long arg), (sock, cmd, arg)) \ SOCKCALL_WRAP(name, listen, (struct socket *sock, int len), (sock, len)) \ SOCKCALL_WRAP(name, shutdown, (struct socket *sock, int flags), (sock, flags)) \ SOCKCALL_WRAP(name, setsockopt, (struct socket *sock, int level, int optname, \ @@ -275,6 +279,7 @@ static const struct proto_ops name##_ops = { \ .getname = __lock_##name##_getname, \ .poll = __lock_##name##_poll, \ .ioctl = __lock_##name##_ioctl, \ + .compat_ioctl = __lock_##name##_compat_ioctl, \ .listen = __lock_##name##_listen, \ .shutdown = __lock_##name##_shutdown, \ .setsockopt = __lock_##name##_setsockopt, \ @@ -283,6 +288,7 @@ static const struct proto_ops name##_ops = { \ .recvmsg = __lock_##name##_recvmsg, \ .mmap = __lock_##name##_mmap, \ }; + #endif #define MODULE_ALIAS_NETPROTO(proto) \ diff --git a/net/socket.c b/net/socket.c index e3c21d5ec288..e2d5bae994de 100644 --- a/net/socket.c +++ b/net/socket.c @@ -107,6 +107,10 @@ static unsigned int sock_poll(struct file *file, struct poll_table_struct *wait); static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg); +#ifdef CONFIG_COMPAT +static long compat_sock_ioctl(struct file *file, + unsigned int cmd, unsigned long arg); +#endif static int sock_fasync(int fd, struct file *filp, int on); static ssize_t sock_readv(struct file *file, const struct iovec *vector, unsigned long count, loff_t *ppos); @@ -128,6 +132,9 @@ static struct file_operations socket_file_ops = { .aio_write = sock_aio_write, .poll = sock_poll, .unlocked_ioctl = sock_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = compat_sock_ioctl, +#endif .mmap = sock_mmap, .open = sock_no_open, /* special open code to disallow open via /proc */ .release = sock_close, @@ -2136,6 +2143,20 @@ void socket_seq_show(struct seq_file *seq) } #endif /* CONFIG_PROC_FS */ +#ifdef CONFIG_COMPAT +static long compat_sock_ioctl(struct file *file, unsigned cmd, + unsigned long arg) +{ + struct socket *sock = file->private_data; + int ret = -ENOIOCTLCMD; + + if (sock->ops->compat_ioctl) + ret = sock->ops->compat_ioctl(sock, cmd, arg); + + return ret; +} +#endif + /* ABI emulation layers need these two */ EXPORT_SYMBOL(move_addr_to_kernel); EXPORT_SYMBOL(move_addr_to_user); -- cgit v1.2.3 From f0ac2614412e2b597e2d5bfbd3960b4f73718b41 Mon Sep 17 00:00:00 2001 From: Shaun Pereira Date: Tue, 21 Mar 2006 23:59:39 -0800 Subject: [NET]: socket timestamp 32 bit handler for 64 bit kernel Get socket timestamp handler function that does not use the ioctl32_hash_table. Signed-off-by: Shaun Pereira Acked-by: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- include/net/compat.h | 4 +++- net/compat.c | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/compat.h b/include/net/compat.h index 290bab46d457..8662b8f43df5 100644 --- a/include/net/compat.h +++ b/include/net/compat.h @@ -23,6 +23,9 @@ struct compat_cmsghdr { compat_int_t cmsg_type; }; +struct sock; +extern int compat_sock_get_timestamp(struct sock *, struct timeval __user *); + #else /* defined(CONFIG_COMPAT) */ #define compat_msghdr msghdr /* to avoid compiler warnings */ #endif /* defined(CONFIG_COMPAT) */ @@ -34,7 +37,6 @@ extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsi extern asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *); extern int put_cmsg_compat(struct msghdr*, int, int, int, void *); -struct sock; extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *, unsigned char *, int); #endif /* NET_COMPAT_H */ diff --git a/net/compat.c b/net/compat.c index 13177a1a4b39..8fd37cd7b501 100644 --- a/net/compat.c +++ b/net/compat.c @@ -543,6 +543,25 @@ static int compat_sock_getsockopt(struct socket *sock, int level, int optname, return sock_getsockopt(sock, level, optname, optval, optlen); } +int compat_sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp) +{ + struct compat_timeval __user *ctv = + (struct compat_timeval __user*) userstamp; + int err = -ENOENT; + + if (!sock_flag(sk, SOCK_TIMESTAMP)) + sock_enable_timestamp(sk); + if (sk->sk_stamp.tv_sec == -1) + return err; + if (sk->sk_stamp.tv_sec == 0) + do_gettimeofday(&sk->sk_stamp); + if (put_user(sk->sk_stamp.tv_sec, &ctv->tv_sec) || + put_user(sk->sk_stamp.tv_usec, &ctv->tv_usec)) + err = -EFAULT; + return err; +} +EXPORT_SYMBOL(compat_sock_get_timestamp); + asmlinkage long compat_sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen) { -- cgit v1.2.3 From a64b7b936dcd926ace745c07c14f45ecfaddb034 Mon Sep 17 00:00:00 2001 From: Shaun Pereira Date: Wed, 22 Mar 2006 00:01:31 -0800 Subject: [X25]: allow ITU-T DTE facilities for x25 Allows use of the optional user facility to insert ITU-T (http://www.itu.int/ITU-T/) specified DTE facilities in call set-up x25 packets. This feature is optional; no facilities will be added if the ioctl is not used, and call setup packet remains the same as before. If the ioctls provided by the patch are used, then a facility marker will be added to the x25 packet header so that the called dte address extension facility can be differentiated from other types of facilities (as described in the ITU-T X.25 recommendation) that are also allowed in the x25 packet header. Facility markers are made up of two octets, and may be present in the x25 packet headers of call-request, incoming call, call accepted, clear request, and clear indication packets. The first of the two octets represents the facility code field and is set to zero by this patch. The second octet of the marker represents the facility parameter field and is set to 0x0F because the marker will be inserted before ITU-T type DTE facilities. Since according to ITU-T X.25 Recommendation X.25(10/96)- 7.1 "All networks will support the facility markers with a facility parameter field set to all ones or to 00001111", therefore this patch should work with all x.25 networks. While there are many ITU-T DTE facilities, this patch implements only the called and calling address extension, with placeholders in the x25_dte_facilities structure for the rest of the facilities. Testing: This patch was tested using a cisco xot router connected on its serial ports to an X.25 network, and on its lan ports to a host running an xotd daemon. It is also possible to test this patch using an xotd daemon and an x25tap patch, where the xotd daemons work back-to-back without actually using an x.25 network. See www.fyonne.net for details on how to do this. Signed-off-by: Shaun Pereira Acked-by: Andrew Hendry Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- include/linux/x25.h | 26 +++++++++++++++ include/net/x25.h | 21 ++++++++++--- net/x25/af_x25.c | 45 +++++++++++++++++++++++++- net/x25/x25_facilities.c | 82 +++++++++++++++++++++++++++++++++++++++++------- net/x25/x25_in.c | 3 +- net/x25/x25_subr.c | 6 ++-- 6 files changed, 163 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/include/linux/x25.h b/include/linux/x25.h index 16d44931afa0..d035e4e87d07 100644 --- a/include/linux/x25.h +++ b/include/linux/x25.h @@ -11,6 +11,8 @@ #ifndef X25_KERNEL_H #define X25_KERNEL_H +#include + #define SIOCX25GSUBSCRIP (SIOCPROTOPRIVATE + 0) #define SIOCX25SSUBSCRIP (SIOCPROTOPRIVATE + 1) #define SIOCX25GFACILITIES (SIOCPROTOPRIVATE + 2) @@ -21,6 +23,8 @@ #define SIOCX25SCUDMATCHLEN (SIOCPROTOPRIVATE + 7) #define SIOCX25CALLACCPTAPPRV (SIOCPROTOPRIVATE + 8) #define SIOCX25SENDCALLACCPT (SIOCPROTOPRIVATE + 9) +#define SIOCX25GDTEFACILITIES (SIOCPROTOPRIVATE + 10) +#define SIOCX25SDTEFACILITIES (SIOCPROTOPRIVATE + 11) /* * Values for {get,set}sockopt. @@ -77,6 +81,8 @@ struct x25_subscrip_struct { #define X25_MASK_PACKET_SIZE 0x04 #define X25_MASK_WINDOW_SIZE 0x08 +#define X25_MASK_CALLING_AE 0x10 +#define X25_MASK_CALLED_AE 0x20 /* @@ -98,6 +104,26 @@ struct x25_facilities { unsigned int reverse; }; +/* +* ITU DTE facilities +* Only the called and calling address +* extension are currently implemented. +* The rest are in place to avoid the struct +* changing size if someone needs them later +*/ + +struct x25_dte_facilities { + __u16 delay_cumul; + __u16 delay_target; + __u16 delay_max; + __u8 min_throughput; + __u8 expedited; + __u8 calling_len; + __u8 called_len; + __u8 calling_ae[20]; + __u8 called_ae[20]; +}; + /* * Call User Data structure. */ diff --git a/include/net/x25.h b/include/net/x25.h index fee62ff8c194..0ad90ebcf86e 100644 --- a/include/net/x25.h +++ b/include/net/x25.h @@ -101,9 +101,17 @@ enum { #define X25_FAC_PACKET_SIZE 0x42 #define X25_FAC_WINDOW_SIZE 0x43 -#define X25_MAX_FAC_LEN 20 /* Plenty to spare */ +#define X25_MAX_FAC_LEN 60 #define X25_MAX_CUD_LEN 128 +#define X25_FAC_CALLING_AE 0xCB +#define X25_FAC_CALLED_AE 0xC9 + +#define X25_MARKER 0x00 +#define X25_DTE_SERVICES 0x0F +#define X25_MAX_AE_LEN 40 /* Max num of semi-octets in AE - OSI Nw */ +#define X25_MAX_DTE_FACIL_LEN 21 /* Max length of DTE facility params */ + /** * struct x25_route - x25 routing entry * @node - entry in x25_list_lock @@ -148,6 +156,7 @@ struct x25_sock { struct timer_list timer; struct x25_causediag causediag; struct x25_facilities facilities; + struct x25_dte_facilities dte_facilities; struct x25_calluserdata calluserdata; unsigned long vc_facil_mask; /* inc_call facilities mask */ }; @@ -180,9 +189,13 @@ extern void x25_establish_link(struct x25_neigh *); extern void x25_terminate_link(struct x25_neigh *); /* x25_facilities.c */ -extern int x25_parse_facilities(struct sk_buff *, struct x25_facilities *, unsigned long *); -extern int x25_create_facilities(unsigned char *, struct x25_facilities *, unsigned long); -extern int x25_negotiate_facilities(struct sk_buff *, struct sock *, struct x25_facilities *); +extern int x25_parse_facilities(struct sk_buff *, struct x25_facilities *, + struct x25_dte_facilities *, unsigned long *); +extern int x25_create_facilities(unsigned char *, struct x25_facilities *, + struct x25_dte_facilities *, unsigned long); +extern int x25_negotiate_facilities(struct sk_buff *, struct sock *, + struct x25_facilities *, + struct x25_dte_facilities *); extern void x25_limit_facilities(struct x25_facilities *, struct x25_neigh *); /* x25_in.c */ diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 03725c051752..7bf93df7248b 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -525,6 +525,13 @@ static int x25_create(struct socket *sock, int protocol) x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; x25->facilities.throughput = X25_DEFAULT_THROUGHPUT; x25->facilities.reverse = X25_DEFAULT_REVERSE; + x25->dte_facilities.calling_len = 0; + x25->dte_facilities.called_len = 0; + memset(x25->dte_facilities.called_ae, '\0', + sizeof(x25->dte_facilities.called_ae)); + memset(x25->dte_facilities.calling_ae, '\0', + sizeof(x25->dte_facilities.calling_ae)); + rc = 0; out: return rc; @@ -561,6 +568,7 @@ static struct sock *x25_make_new(struct sock *osk) x25->t2 = ox25->t2; x25->facilities = ox25->facilities; x25->qbitincl = ox25->qbitincl; + x25->dte_facilities = ox25->dte_facilities; x25->cudmatchlength = ox25->cudmatchlength; x25->accptapprv = ox25->accptapprv; @@ -840,6 +848,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, struct x25_sock *makex25; struct x25_address source_addr, dest_addr; struct x25_facilities facilities; + struct x25_dte_facilities dte_facilities; int len, rc; /* @@ -876,7 +885,8 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, /* * Try to reach a compromise on the requested facilities. */ - if ((len = x25_negotiate_facilities(skb, sk, &facilities)) == -1) + len = x25_negotiate_facilities(skb, sk, &facilities, &dte_facilities); + if (len == -1) goto out_sock_put; /* @@ -907,9 +917,12 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, makex25->source_addr = source_addr; makex25->neighbour = nb; makex25->facilities = facilities; + makex25->dte_facilities= dte_facilities; makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask; /* ensure no reverse facil on accept */ makex25->vc_facil_mask &= ~X25_MASK_REVERSE; + /* ensure no calling address extension on accept */ + makex25->vc_facil_mask &= ~X25_MASK_CALLING_AE; makex25->cudmatchlength = x25_sk(sk)->cudmatchlength; /* Normally all calls are accepted immediatly */ @@ -1316,6 +1329,36 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) break; } + case SIOCX25GDTEFACILITIES: { + rc = copy_to_user(argp, &x25->dte_facilities, + sizeof(x25->dte_facilities)); + if (rc) + rc = -EFAULT; + break; + } + + case SIOCX25SDTEFACILITIES: { + struct x25_dte_facilities dtefacs; + rc = -EFAULT; + if (copy_from_user(&dtefacs, argp, sizeof(dtefacs))) + break; + rc = -EINVAL; + if (sk->sk_state != TCP_LISTEN && + sk->sk_state != TCP_CLOSE) + break; + if (dtefacs.calling_len > X25_MAX_AE_LEN) + break; + if (dtefacs.calling_ae == NULL) + break; + if (dtefacs.called_len > X25_MAX_AE_LEN) + break; + if (dtefacs.called_ae == NULL) + break; + x25->dte_facilities = dtefacs; + rc = 0; + break; + } + case SIOCX25GCALLUSERDATA: { struct x25_calluserdata cud = x25->calluserdata; rc = copy_to_user(argp, &cud, diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index 54278b962f4c..9f42b9c9de37 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c @@ -28,18 +28,28 @@ #include /* - * Parse a set of facilities into the facilities structure. Unrecognised + * Parse a set of facilities into the facilities structures. Unrecognised * facilities are written to the debug log file. */ -int x25_parse_facilities(struct sk_buff *skb, - struct x25_facilities *facilities, - unsigned long *vc_fac_mask) +int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, + struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask) { unsigned char *p = skb->data; unsigned int len = *p++; *vc_fac_mask = 0; + /* + * The kernel knows which facilities were set on an incoming call but + * currently this information is not available to userspace. Here we + * give userspace who read incoming call facilities 0 length to indicate + * it wasn't set. + */ + dte_facs->calling_len = 0; + dte_facs->called_len = 0; + memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae)); + memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae)); + while (len > 0) { switch (*p & X25_FAC_CLASS_MASK) { case X25_FAC_CLASS_A: @@ -74,6 +84,8 @@ int x25_parse_facilities(struct sk_buff *skb, facilities->throughput = p[1]; *vc_fac_mask |= X25_MASK_THROUGHPUT; break; + case X25_MARKER: + break; default: printk(KERN_DEBUG "X.25: unknown facility " "%02X, value %02X\n", @@ -112,11 +124,30 @@ int x25_parse_facilities(struct sk_buff *skb, len -= 4; break; case X25_FAC_CLASS_D: - printk(KERN_DEBUG "X.25: unknown facility %02X, " - "length %d, values %02X, %02X, %02X, %02X\n", - p[0], p[1], p[2], p[3], p[4], p[5]); + switch (*p) { + case X25_FAC_CALLING_AE: + if (p[1] > X25_MAX_DTE_FACIL_LEN) + break; + dte_facs->calling_len = p[2]; + memcpy(dte_facs->calling_ae, &p[3], p[1] - 1); + *vc_fac_mask |= X25_MASK_CALLING_AE; + break; + case X25_FAC_CALLED_AE: + if (p[1] > X25_MAX_DTE_FACIL_LEN) + break; + dte_facs->called_len = p[2]; + memcpy(dte_facs->called_ae, &p[3], p[1] - 1); + *vc_fac_mask |= X25_MASK_CALLED_AE; + break; + default: + printk(KERN_DEBUG "X.25: unknown facility %02X," + "length %d, values %02X, %02X, " + "%02X, %02X\n", + p[0], p[1], p[2], p[3], p[4], p[5]); + break; + } len -= p[1] + 2; - p += p[1] + 2; + p += p[1] + 2; break; } } @@ -128,8 +159,8 @@ int x25_parse_facilities(struct sk_buff *skb, * Create a set of facilities. */ int x25_create_facilities(unsigned char *buffer, - struct x25_facilities *facilities, - unsigned long facil_mask) + struct x25_facilities *facilities, + struct x25_dte_facilities *dte_facs, unsigned long facil_mask) { unsigned char *p = buffer + 1; int len; @@ -168,6 +199,33 @@ int x25_create_facilities(unsigned char *buffer, *p++ = facilities->winsize_out ? : facilities->winsize_in; } + if (facil_mask & (X25_MASK_CALLING_AE|X25_MASK_CALLED_AE)) { + *p++ = X25_MARKER; + *p++ = X25_DTE_SERVICES; + } + + if (dte_facs->calling_len && (facil_mask & X25_MASK_CALLING_AE)) { + unsigned bytecount = (dte_facs->calling_len % 2) ? + dte_facs->calling_len / 2 + 1 : + dte_facs->calling_len / 2; + *p++ = X25_FAC_CALLING_AE; + *p++ = 1 + bytecount; + *p++ = dte_facs->calling_len; + memcpy(p, dte_facs->calling_ae, bytecount); + p += bytecount; + } + + if (dte_facs->called_len && (facil_mask & X25_MASK_CALLED_AE)) { + unsigned bytecount = (dte_facs->called_len % 2) ? + dte_facs->called_len / 2 + 1 : + dte_facs->called_len / 2; + *p++ = X25_FAC_CALLED_AE; + *p++ = 1 + bytecount; + *p++ = dte_facs->called_len; + memcpy(p, dte_facs->called_ae, bytecount); + p+=bytecount; + } + len = p - buffer; buffer[0] = len - 1; @@ -180,7 +238,7 @@ int x25_create_facilities(unsigned char *buffer, * The only real problem is with reverse charging. */ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, - struct x25_facilities *new) + struct x25_facilities *new, struct x25_dte_facilities *dte) { struct x25_sock *x25 = x25_sk(sk); struct x25_facilities *ours = &x25->facilities; @@ -190,7 +248,7 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, memset(&theirs, 0, sizeof(theirs)); memcpy(new, ours, sizeof(*new)); - len = x25_parse_facilities(skb, &theirs, &x25->vc_facil_mask); + len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask); /* * They want reverse charging, we won't accept it. diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index 26146874b839..eed50e10f09b 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c @@ -106,7 +106,8 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr)); skb_pull(skb, x25_parse_facilities(skb, &x25->facilities, - &x25->vc_facil_mask)); + &x25->dte_facilities, + &x25->vc_facil_mask)); /* * Copy any Call User Data. */ diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c index 8be9b8fbc24d..8d6220aa5d0f 100644 --- a/net/x25/x25_subr.c +++ b/net/x25/x25_subr.c @@ -190,8 +190,9 @@ void x25_write_internal(struct sock *sk, int frametype) dptr = skb_put(skb, len); memcpy(dptr, addresses, len); len = x25_create_facilities(facilities, - &x25->facilities, - x25->neighbour->global_facil_mask); + &x25->facilities, + &x25->dte_facilities, + x25->neighbour->global_facil_mask); dptr = skb_put(skb, len); memcpy(dptr, facilities, len); dptr = skb_put(skb, x25->calluserdata.cudlength); @@ -206,6 +207,7 @@ void x25_write_internal(struct sock *sk, int frametype) *dptr++ = 0x00; /* Address lengths */ len = x25_create_facilities(facilities, &x25->facilities, + &x25->dte_facilities, x25->vc_facil_mask); dptr = skb_put(skb, len); memcpy(dptr, facilities, len); -- cgit v1.2.3 From 14778d9072e53d2171f66ffd9657daff41acfaed Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 21 Mar 2006 02:29:39 -0800 Subject: [SPARC]: Respect vm_page_prot in io_remap_page_range(). Make sure the callers do a pgprot_noncached() on vma->vm_page_prot. Pointed out by Hugh Dickens. Signed-off-by: David S. Miller --- arch/sparc/mm/generic.c | 1 - arch/sparc/mm/loadmmu.c | 2 -- arch/sparc/mm/srmmu.c | 9 ++++++++- arch/sparc/mm/sun4c.c | 15 ++++++++++++--- arch/sparc64/kernel/pci.c | 2 +- arch/sparc64/mm/generic.c | 1 - drivers/char/drm/drm_vm.c | 1 + drivers/sbus/char/flash.c | 3 +-- drivers/video/fbmem.c | 8 +------- drivers/video/sbuslib.c | 2 ++ include/asm-sparc/pgtable.h | 6 +++--- 11 files changed, 29 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/arch/sparc/mm/generic.c b/arch/sparc/mm/generic.c index 2cb0728cee05..1ef7fa03fefe 100644 --- a/arch/sparc/mm/generic.c +++ b/arch/sparc/mm/generic.c @@ -76,7 +76,6 @@ int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, vma->vm_pgoff = (offset >> PAGE_SHIFT) | ((unsigned long)space << 28UL); - prot = __pgprot(pg_iobits); offset -= from; dir = pgd_offset(mm, from); flush_cache_range(vma, beg, end); diff --git a/arch/sparc/mm/loadmmu.c b/arch/sparc/mm/loadmmu.c index e9f9571601ba..36b4d24988f8 100644 --- a/arch/sparc/mm/loadmmu.c +++ b/arch/sparc/mm/loadmmu.c @@ -22,8 +22,6 @@ struct ctx_list *ctx_list_pool; struct ctx_list ctx_free; struct ctx_list ctx_used; -unsigned int pg_iobits; - extern void ld_mmu_sun4c(void); extern void ld_mmu_srmmu(void); diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index c664b962987c..27b0e0ba8581 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -2130,6 +2130,13 @@ static unsigned long srmmu_pte_to_pgoff(pte_t pte) return pte_val(pte) >> SRMMU_PTE_FILE_SHIFT; } +static pgprot_t srmmu_pgprot_noncached(pgprot_t prot) +{ + prot &= ~__pgprot(SRMMU_CACHE); + + return prot; +} + /* Load up routines and constants for sun4m and sun4d mmu */ void __init ld_mmu_srmmu(void) { @@ -2150,9 +2157,9 @@ void __init ld_mmu_srmmu(void) BTFIXUPSET_INT(page_readonly, pgprot_val(SRMMU_PAGE_RDONLY)); BTFIXUPSET_INT(page_kernel, pgprot_val(SRMMU_PAGE_KERNEL)); page_kernel = pgprot_val(SRMMU_PAGE_KERNEL); - pg_iobits = SRMMU_VALID | SRMMU_WRITE | SRMMU_REF; /* Functions */ + BTFIXUPSET_CALL(pgprot_noncached, srmmu_pgprot_noncached, BTFIXUPCALL_NORM); #ifndef CONFIG_SMP BTFIXUPSET_CALL(___xchg32, ___xchg32_sun4md, BTFIXUPCALL_SWAPG1G2); #endif diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index 731f19603cad..49f28c1bdc6d 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -1589,7 +1589,10 @@ static void sun4c_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) static inline void sun4c_mapioaddr(unsigned long physaddr, unsigned long virt_addr) { - unsigned long page_entry; + unsigned long page_entry, pg_iobits; + + pg_iobits = _SUN4C_PAGE_PRESENT | _SUN4C_READABLE | _SUN4C_WRITEABLE | + _SUN4C_PAGE_IO | _SUN4C_PAGE_NOCACHE; page_entry = ((physaddr >> PAGE_SHIFT) & SUN4C_PFN_MASK); page_entry |= ((pg_iobits | _SUN4C_PAGE_PRIV) & ~(_SUN4C_PAGE_PRESENT)); @@ -2134,6 +2137,13 @@ void __init sun4c_paging_init(void) printk("SUN4C: %d mmu entries for the kernel\n", cnt); } +static pgprot_t sun4c_pgprot_noncached(pgprot_t prot) +{ + prot |= __pgprot(_SUN4C_PAGE_IO | _SUN4C_PAGE_NOCACHE); + + return prot; +} + /* Load up routines and constants for sun4c mmu */ void __init ld_mmu_sun4c(void) { @@ -2156,10 +2166,9 @@ void __init ld_mmu_sun4c(void) BTFIXUPSET_INT(page_readonly, pgprot_val(SUN4C_PAGE_READONLY)); BTFIXUPSET_INT(page_kernel, pgprot_val(SUN4C_PAGE_KERNEL)); page_kernel = pgprot_val(SUN4C_PAGE_KERNEL); - pg_iobits = _SUN4C_PAGE_PRESENT | _SUN4C_READABLE | _SUN4C_WRITEABLE | - _SUN4C_PAGE_IO | _SUN4C_PAGE_NOCACHE; /* Functions */ + BTFIXUPSET_CALL(pgprot_noncached, sun4c_pgprot_noncached, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(___xchg32, ___xchg32_sun4c, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(do_check_pgt_cache, sun4c_check_pgt_cache, BTFIXUPCALL_NORM); diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 95ffa9418620..dfccff29e182 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -656,6 +656,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, __pci_mmap_set_flags(dev, vma, mmap_state); __pci_mmap_set_pgprot(dev, vma, mmap_state); + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); ret = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start, @@ -663,7 +664,6 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, if (ret) return ret; - vma->vm_flags |= VM_IO; return 0; } diff --git a/arch/sparc64/mm/generic.c b/arch/sparc64/mm/generic.c index 5fc5c579e35e..8cb06205d265 100644 --- a/arch/sparc64/mm/generic.c +++ b/arch/sparc64/mm/generic.c @@ -140,7 +140,6 @@ int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP; vma->vm_pgoff = phys_base >> PAGE_SHIFT; - prot = __pgprot(pg_iobits); offset -= from; dir = pgd_offset(mm, from); flush_cache_range(vma, beg, end); diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c index 0291cd62c69f..ffd0800ed601 100644 --- a/drivers/char/drm/drm_vm.c +++ b/drivers/char/drm/drm_vm.c @@ -619,6 +619,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) #endif offset = dev->driver->get_reg_ofs(dev); #ifdef __sparc__ + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); if (io_remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start, (map->offset + offset) >> PAGE_SHIFT, vma->vm_end - vma->vm_start, diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index 6bdd768b731d..2beb3dded087 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c @@ -71,9 +71,8 @@ flash_mmap(struct file *file, struct vm_area_struct *vma) if (vma->vm_end - (vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT)) > size) size = vma->vm_end - (vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT)); - pgprot_val(vma->vm_page_prot) &= ~(_PAGE_CACHE); - pgprot_val(vma->vm_page_prot) |= _PAGE_E; vma->vm_flags |= (VM_SHM | VM_LOCKED); + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); if (io_remap_pfn_range(vma, vma->vm_start, addr, size, vma->vm_page_prot)) return -EAGAIN; diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 996c7b58564e..07d882b14396 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1169,11 +1169,6 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) vma->vm_pgoff = off >> PAGE_SHIFT; /* This is an IO map - tell maydump to skip this VMA */ vma->vm_flags |= VM_IO | VM_RESERVED; -#if defined(__sparc_v9__) - if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) - return -EAGAIN; -#else #if defined(__mc68000__) #if defined(CONFIG_SUN3) pgprot_val(vma->vm_page_prot) |= SUN3_PAGE_NOCACHE; @@ -1195,7 +1190,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) #elif defined(__i386__) || defined(__x86_64__) if (boot_cpu_data.x86 > 3) pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; -#elif defined(__mips__) +#elif defined(__mips__) || defined(__sparc_v9__) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); #elif defined(__hppa__) pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; @@ -1212,7 +1207,6 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; -#endif /* !__sparc_v9__ */ return 0; #endif /* !sparc32 */ } diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c index a4d7cc51ce0b..34ef859ee414 100644 --- a/drivers/video/sbuslib.c +++ b/drivers/video/sbuslib.c @@ -58,6 +58,8 @@ int sbusfb_mmap_helper(struct sbus_mmap_map *map, /* To stop the swapper from even considering these pages */ vma->vm_flags |= (VM_IO | VM_RESERVED); + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + /* Each page, see which map applies */ for (page = 0; page < size; ){ map_size = 0; diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h index b33c35411e82..9eea8f4d41f0 100644 --- a/include/asm-sparc/pgtable.h +++ b/include/asm-sparc/pgtable.h @@ -269,11 +269,14 @@ BTFIXUPDEF_CALL_CONST(pte_t, mk_pte, struct page *, pgprot_t) BTFIXUPDEF_CALL_CONST(pte_t, mk_pte_phys, unsigned long, pgprot_t) BTFIXUPDEF_CALL_CONST(pte_t, mk_pte_io, unsigned long, pgprot_t, int) +BTFIXUPDEF_CALL_CONST(pgprot_t, pgprot_noncached, pgprot_t) #define mk_pte(page,pgprot) BTFIXUP_CALL(mk_pte)(page,pgprot) #define mk_pte_phys(page,pgprot) BTFIXUP_CALL(mk_pte_phys)(page,pgprot) #define mk_pte_io(page,pgprot,space) BTFIXUP_CALL(mk_pte_io)(page,pgprot,space) +#define pgprot_noncached(pgprot) BTFIXUP_CALL(pgprot_noncached)(pgprot) + BTFIXUPDEF_INT(pte_modify_mask) static pte_t pte_modify(pte_t pte, pgprot_t newprot) __attribute_const__; @@ -309,9 +312,6 @@ BTFIXUPDEF_CALL(pte_t *, pte_offset_kernel, pmd_t *, unsigned long) #define pte_unmap(pte) do{}while(0) #define pte_unmap_nested(pte) do{}while(0) -/* The permissions for pgprot_val to make a page mapped on the obio space */ -extern unsigned int pg_iobits; - /* Certain architectures need to do special things when pte's * within a page table are directly modified. Thus, the following * hook is made available. -- cgit v1.2.3 From dcc1e8dd88d4bc55e32a26dad7633d20ffe606d2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 22 Mar 2006 00:49:59 -0800 Subject: [SPARC64]: Add a secondary TSB for hugepage mappings. Signed-off-by: David S. Miller --- arch/sparc64/Kconfig | 4 +- arch/sparc64/kernel/sun4v_tlb_miss.S | 39 +++--- arch/sparc64/kernel/traps.c | 21 +++- arch/sparc64/kernel/tsb.S | 210 +++++++++++++++++++++++-------- arch/sparc64/mm/fault.c | 15 ++- arch/sparc64/mm/hugetlbpage.c | 28 +++-- arch/sparc64/mm/init.c | 21 +++- arch/sparc64/mm/tsb.c | 234 ++++++++++++++++++++++------------- include/asm-sparc64/cpudata.h | 5 +- include/asm-sparc64/mmu.h | 29 ++++- include/asm-sparc64/mmu_context.h | 21 ++-- include/asm-sparc64/page.h | 34 ++--- include/asm-sparc64/pgtable.h | 2 + 13 files changed, 462 insertions(+), 201 deletions(-) (limited to 'include') diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index c3685b314d71..267afddf63cf 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -175,11 +175,11 @@ config HUGETLB_PAGE_SIZE_4MB bool "4MB" config HUGETLB_PAGE_SIZE_512K - depends on !SPARC64_PAGE_SIZE_4MB + depends on !SPARC64_PAGE_SIZE_4MB && !SPARC64_PAGE_SIZE_512KB bool "512K" config HUGETLB_PAGE_SIZE_64K - depends on !SPARC64_PAGE_SIZE_4MB && !SPARC64_PAGE_SIZE_512KB + depends on !SPARC64_PAGE_SIZE_4MB && !SPARC64_PAGE_SIZE_512KB && !SPARC64_PAGE_SIZE_64K bool "64K" endchoice diff --git a/arch/sparc64/kernel/sun4v_tlb_miss.S b/arch/sparc64/kernel/sun4v_tlb_miss.S index ab23ddb7116e..b731881224e8 100644 --- a/arch/sparc64/kernel/sun4v_tlb_miss.S +++ b/arch/sparc64/kernel/sun4v_tlb_miss.S @@ -29,15 +29,15 @@ * * index_mask = (512 << (tsb_reg & 0x7UL)) - 1UL; * tsb_base = tsb_reg & ~0x7UL; - * tsb_index = ((vaddr >> PAGE_SHIFT) & tsb_mask); + * tsb_index = ((vaddr >> HASH_SHIFT) & tsb_mask); * tsb_ptr = tsb_base + (tsb_index * 16); */ -#define COMPUTE_TSB_PTR(TSB_PTR, VADDR, TMP1, TMP2) \ +#define COMPUTE_TSB_PTR(TSB_PTR, VADDR, HASH_SHIFT, TMP1, TMP2) \ and TSB_PTR, 0x7, TMP1; \ mov 512, TMP2; \ andn TSB_PTR, 0x7, TSB_PTR; \ sllx TMP2, TMP1, TMP2; \ - srlx VADDR, PAGE_SHIFT, TMP1; \ + srlx VADDR, HASH_SHIFT, TMP1; \ sub TMP2, 1, TMP2; \ and TMP1, TMP2, TMP1; \ sllx TMP1, 4, TMP1; \ @@ -53,7 +53,7 @@ sun4v_itlb_miss: LOAD_ITLB_INFO(%g2, %g4, %g5) COMPUTE_TAG_TARGET(%g6, %g4, %g5, kvmap_itlb_4v) - COMPUTE_TSB_PTR(%g1, %g4, %g3, %g7) + COMPUTE_TSB_PTR(%g1, %g4, PAGE_SHIFT, %g3, %g7) /* Load TSB tag/pte into %g2/%g3 and compare the tag. */ ldda [%g1] ASI_QUAD_LDD_PHYS_4V, %g2 @@ -99,7 +99,7 @@ sun4v_dtlb_miss: LOAD_DTLB_INFO(%g2, %g4, %g5) COMPUTE_TAG_TARGET(%g6, %g4, %g5, kvmap_dtlb_4v) - COMPUTE_TSB_PTR(%g1, %g4, %g3, %g7) + COMPUTE_TSB_PTR(%g1, %g4, PAGE_SHIFT, %g3, %g7) /* Load TSB tag/pte into %g2/%g3 and compare the tag. */ ldda [%g1] ASI_QUAD_LDD_PHYS_4V, %g2 @@ -171,21 +171,26 @@ sun4v_dtsb_miss: /* fallthrough */ - /* Create TSB pointer into %g1. This is something like: - * - * index_mask = (512 << (tsb_reg & 0x7UL)) - 1UL; - * tsb_base = tsb_reg & ~0x7UL; - * tsb_index = ((vaddr >> PAGE_SHIFT) & tsb_mask); - * tsb_ptr = tsb_base + (tsb_index * 16); - */ sun4v_tsb_miss_common: - COMPUTE_TSB_PTR(%g1, %g4, %g5, %g7) + COMPUTE_TSB_PTR(%g1, %g4, PAGE_SHIFT, %g5, %g7) - /* Branch directly to page table lookup. We have SCRATCHPAD_MMU_MISS - * still in %g2, so it's quite trivial to get at the PGD PHYS value - * so we can preload it into %g7. - */ sub %g2, TRAP_PER_CPU_FAULT_INFO, %g2 + +#ifdef CONFIG_HUGETLB_PAGE + mov SCRATCHPAD_UTSBREG2, %g5 + ldxa [%g5] ASI_SCRATCHPAD, %g5 + cmp %g5, -1 + be,pt %xcc, 80f + nop + COMPUTE_TSB_PTR(%g5, %g4, HPAGE_SHIFT, %g2, %g7) + + /* That clobbered %g2, reload it. */ + ldxa [%g0] ASI_SCRATCHPAD, %g2 + sub %g2, TRAP_PER_CPU_FAULT_INFO, %g2 + +80: stx %g5, [%g2 + TRAP_PER_CPU_TSB_HUGE_TEMP] +#endif + ba,pt %xcc, tsb_miss_page_table_walk_sun4v_fastpath ldx [%g2 + TRAP_PER_CPU_PGD_PADDR], %g7 diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 7f7dba0ca96a..df612e4f75f9 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -2482,6 +2482,7 @@ void init_cur_cpu_trap(struct thread_info *t) extern void thread_info_offsets_are_bolixed_dave(void); extern void trap_per_cpu_offsets_are_bolixed_dave(void); +extern void tsb_config_offsets_are_bolixed_dave(void); /* Only invoked on boot processor. */ void __init trap_init(void) @@ -2535,9 +2536,27 @@ void __init trap_init(void) (TRAP_PER_CPU_CPU_MONDO_BLOCK_PA != offsetof(struct trap_per_cpu, cpu_mondo_block_pa)) || (TRAP_PER_CPU_CPU_LIST_PA != - offsetof(struct trap_per_cpu, cpu_list_pa))) + offsetof(struct trap_per_cpu, cpu_list_pa)) || + (TRAP_PER_CPU_TSB_HUGE != + offsetof(struct trap_per_cpu, tsb_huge)) || + (TRAP_PER_CPU_TSB_HUGE_TEMP != + offsetof(struct trap_per_cpu, tsb_huge_temp))) trap_per_cpu_offsets_are_bolixed_dave(); + if ((TSB_CONFIG_TSB != + offsetof(struct tsb_config, tsb)) || + (TSB_CONFIG_RSS_LIMIT != + offsetof(struct tsb_config, tsb_rss_limit)) || + (TSB_CONFIG_NENTRIES != + offsetof(struct tsb_config, tsb_nentries)) || + (TSB_CONFIG_REG_VAL != + offsetof(struct tsb_config, tsb_reg_val)) || + (TSB_CONFIG_MAP_VADDR != + offsetof(struct tsb_config, tsb_map_vaddr)) || + (TSB_CONFIG_MAP_PTE != + offsetof(struct tsb_config, tsb_map_pte))) + tsb_config_offsets_are_bolixed_dave(); + /* Attach to the address space of init_task. On SMP we * do this in smp.c:smp_callin for other cpus. */ diff --git a/arch/sparc64/kernel/tsb.S b/arch/sparc64/kernel/tsb.S index 118baea44f69..a0c8ba58920b 100644 --- a/arch/sparc64/kernel/tsb.S +++ b/arch/sparc64/kernel/tsb.S @@ -3,8 +3,13 @@ * Copyright (C) 2006 David S. Miller */ +#include + #include #include +#include +#include +#include .text .align 32 @@ -34,34 +39,124 @@ tsb_miss_itlb: ldxa [%g4] ASI_IMMU, %g4 /* At this point we have: - * %g1 -- TSB entry address + * %g1 -- PAGE_SIZE TSB entry address * %g3 -- FAULT_CODE_{D,I}TLB * %g4 -- missing virtual address * %g6 -- TAG TARGET (vaddr >> 22) */ tsb_miss_page_table_walk: - TRAP_LOAD_PGD_PHYS(%g7, %g5) + TRAP_LOAD_TRAP_BLOCK(%g7, %g5) - /* And now we have the PGD base physical address in %g7. */ -tsb_miss_page_table_walk_sun4v_fastpath: - USER_PGTABLE_WALK_TL1(%g4, %g7, %g5, %g2, tsb_do_fault) + /* Before committing to a full page table walk, + * check the huge page TSB. + */ +#ifdef CONFIG_HUGETLB_PAGE + +661: ldx [%g7 + TRAP_PER_CPU_TSB_HUGE], %g5 + nop + .section .sun4v_2insn_patch, "ax" + .word 661b + mov SCRATCHPAD_UTSBREG2, %g5 + ldxa [%g5] ASI_SCRATCHPAD, %g5 + .previous + + cmp %g5, -1 + be,pt %xcc, 80f + nop + + /* We need an aligned pair of registers containing 2 values + * which can be easily rematerialized. %g6 and %g7 foot the + * bill just nicely. We'll save %g6 away into %g2 for the + * huge page TSB TAG comparison. + * + * Perform a huge page TSB lookup. + */ + mov %g6, %g2 + and %g5, 0x7, %g6 + mov 512, %g7 + andn %g5, 0x7, %g5 + sllx %g7, %g6, %g7 + srlx %g4, HPAGE_SHIFT, %g6 + sub %g7, 1, %g7 + and %g6, %g7, %g6 + sllx %g6, 4, %g6 + add %g5, %g6, %g5 + + TSB_LOAD_QUAD(%g5, %g6) + cmp %g6, %g2 + be,a,pt %xcc, tsb_tlb_reload + mov %g7, %g5 + + /* No match, remember the huge page TSB entry address, + * and restore %g6 and %g7. + */ + TRAP_LOAD_TRAP_BLOCK(%g7, %g6) + srlx %g4, 22, %g6 +80: stx %g5, [%g7 + TRAP_PER_CPU_TSB_HUGE_TEMP] + +#endif + + ldx [%g7 + TRAP_PER_CPU_PGD_PADDR], %g7 /* At this point we have: * %g1 -- TSB entry address * %g3 -- FAULT_CODE_{D,I}TLB - * %g5 -- physical address of PTE in Linux page tables + * %g4 -- missing virtual address * %g6 -- TAG TARGET (vaddr >> 22) + * %g7 -- page table physical address + * + * We know that both the base PAGE_SIZE TSB and the HPAGE_SIZE + * TSB both lack a matching entry. */ -tsb_reload: - TSB_LOCK_TAG(%g1, %g2, %g7) +tsb_miss_page_table_walk_sun4v_fastpath: + USER_PGTABLE_WALK_TL1(%g4, %g7, %g5, %g2, tsb_do_fault) /* Load and check PTE. */ ldxa [%g5] ASI_PHYS_USE_EC, %g5 - mov 1, %g7 - sllx %g7, TSB_TAG_INVALID_BIT, %g7 - brgez,a,pn %g5, tsb_do_fault - TSB_STORE(%g1, %g7) + brgez,pn %g5, tsb_do_fault + nop + +#ifdef CONFIG_HUGETLB_PAGE +661: sethi %uhi(_PAGE_SZALL_4U), %g7 + sllx %g7, 32, %g7 + .section .sun4v_2insn_patch, "ax" + .word 661b + mov _PAGE_SZALL_4V, %g7 + nop + .previous + + and %g5, %g7, %g2 + +661: sethi %uhi(_PAGE_SZHUGE_4U), %g7 + sllx %g7, 32, %g7 + .section .sun4v_2insn_patch, "ax" + .word 661b + mov _PAGE_SZHUGE_4V, %g7 + nop + .previous + + cmp %g2, %g7 + bne,pt %xcc, 60f + nop + + /* It is a huge page, use huge page TSB entry address we + * calculated above. + */ + TRAP_LOAD_TRAP_BLOCK(%g7, %g2) + ldx [%g7 + TRAP_PER_CPU_TSB_HUGE_TEMP], %g2 + cmp %g2, -1 + movne %xcc, %g2, %g1 +60: +#endif + /* At this point we have: + * %g1 -- TSB entry address + * %g3 -- FAULT_CODE_{D,I}TLB + * %g5 -- valid PTE + * %g6 -- TAG TARGET (vaddr >> 22) + */ +tsb_reload: + TSB_LOCK_TAG(%g1, %g2, %g7) TSB_WRITE(%g1, %g5, %g6) /* Finally, load TLB and return from trap. */ @@ -240,10 +335,9 @@ tsb_flush: * schedule() time. * * %o0: page table physical address - * %o1: TSB register value - * %o2: TSB virtual address - * %o3: TSB mapping locked PTE - * %o4: Hypervisor TSB descriptor physical address + * %o1: TSB base config pointer + * %o2: TSB huge config pointer, or NULL if none + * %o3: Hypervisor TSB descriptor physical address * * We have to run this whole thing with interrupts * disabled so that the current cpu doesn't change @@ -253,63 +347,79 @@ tsb_flush: .globl __tsb_context_switch .type __tsb_context_switch,#function __tsb_context_switch: - rdpr %pstate, %o5 - wrpr %o5, PSTATE_IE, %pstate + rdpr %pstate, %g1 + wrpr %g1, PSTATE_IE, %pstate + + TRAP_LOAD_TRAP_BLOCK(%g2, %g3) - ldub [%g6 + TI_CPU], %g1 - sethi %hi(trap_block), %g2 - sllx %g1, TRAP_BLOCK_SZ_SHIFT, %g1 - or %g2, %lo(trap_block), %g2 - add %g2, %g1, %g2 stx %o0, [%g2 + TRAP_PER_CPU_PGD_PADDR] - sethi %hi(tlb_type), %g1 - lduw [%g1 + %lo(tlb_type)], %g1 - cmp %g1, 3 - bne,pt %icc, 1f + ldx [%o1 + TSB_CONFIG_REG_VAL], %o0 + brz,pt %o2, 1f + mov -1, %g3 + + ldx [%o2 + TSB_CONFIG_REG_VAL], %g3 + +1: stx %g3, [%g2 + TRAP_PER_CPU_TSB_HUGE] + + sethi %hi(tlb_type), %g2 + lduw [%g2 + %lo(tlb_type)], %g2 + cmp %g2, 3 + bne,pt %icc, 50f nop /* Hypervisor TSB switch. */ - mov SCRATCHPAD_UTSBREG1, %g1 - stxa %o1, [%g1] ASI_SCRATCHPAD - mov -1, %g2 - mov SCRATCHPAD_UTSBREG2, %g1 - stxa %g2, [%g1] ASI_SCRATCHPAD - - /* Save away %o5's %pstate, we have to use %o5 for - * the hypervisor call. - */ - mov %o5, %g1 + mov SCRATCHPAD_UTSBREG1, %o5 + stxa %o0, [%o5] ASI_SCRATCHPAD + mov SCRATCHPAD_UTSBREG2, %o5 + stxa %g3, [%o5] ASI_SCRATCHPAD + + mov 2, %o0 + cmp %g3, -1 + move %xcc, 1, %o0 mov HV_FAST_MMU_TSB_CTXNON0, %o5 - mov 1, %o0 - mov %o4, %o1 + mov %o3, %o1 ta HV_FAST_TRAP - /* Finish up and restore %o5. */ + /* Finish up. */ ba,pt %xcc, 9f - mov %g1, %o5 + nop /* SUN4U TSB switch. */ -1: mov TSB_REG, %g1 - stxa %o1, [%g1] ASI_DMMU +50: mov TSB_REG, %o5 + stxa %o0, [%o5] ASI_DMMU membar #Sync - stxa %o1, [%g1] ASI_IMMU + stxa %o0, [%o5] ASI_IMMU membar #Sync -2: brz %o2, 9f - nop +2: ldx [%o1 + TSB_CONFIG_MAP_VADDR], %o4 + brz %o4, 9f + ldx [%o1 + TSB_CONFIG_MAP_PTE], %o5 sethi %hi(sparc64_highest_unlocked_tlb_ent), %g2 - mov TLB_TAG_ACCESS, %g1 + mov TLB_TAG_ACCESS, %g3 lduw [%g2 + %lo(sparc64_highest_unlocked_tlb_ent)], %g2 - stxa %o2, [%g1] ASI_DMMU + stxa %o4, [%g3] ASI_DMMU membar #Sync sllx %g2, 3, %g2 - stxa %o3, [%g2] ASI_DTLB_DATA_ACCESS + stxa %o5, [%g2] ASI_DTLB_DATA_ACCESS + membar #Sync + + brz,pt %o2, 9f + nop + + ldx [%o2 + TSB_CONFIG_MAP_VADDR], %o4 + ldx [%o2 + TSB_CONFIG_MAP_PTE], %o5 + mov TLB_TAG_ACCESS, %g3 + stxa %o4, [%g3] ASI_DMMU + membar #Sync + sub %g2, (1 << 3), %g2 + stxa %o5, [%g2] ASI_DTLB_DATA_ACCESS membar #Sync + 9: - wrpr %o5, %pstate + wrpr %g1, %pstate retl nop diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index 63b6cc0cd5d5..d21ff3230c02 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -410,9 +410,18 @@ good_area: up_read(&mm->mmap_sem); mm_rss = get_mm_rss(mm); - if (unlikely(mm_rss >= mm->context.tsb_rss_limit)) - tsb_grow(mm, mm_rss); - +#ifdef CONFIG_HUGETLB_PAGE + mm_rss -= (mm->context.huge_pte_count * (HPAGE_SIZE / PAGE_SIZE)); +#endif + if (unlikely(mm_rss >= + mm->context.tsb_block[MM_TSB_BASE].tsb_rss_limit)) + tsb_grow(mm, MM_TSB_BASE, mm_rss); +#ifdef CONFIG_HUGETLB_PAGE + mm_rss = mm->context.huge_pte_count; + if (unlikely(mm_rss >= + mm->context.tsb_block[MM_TSB_HUGE].tsb_rss_limit)) + tsb_grow(mm, MM_TSB_HUGE, mm_rss); +#endif return; /* diff --git a/arch/sparc64/mm/hugetlbpage.c b/arch/sparc64/mm/hugetlbpage.c index a7a24869d045..0a1d4cd24cda 100644 --- a/arch/sparc64/mm/hugetlbpage.c +++ b/arch/sparc64/mm/hugetlbpage.c @@ -199,13 +199,11 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) pte_t *pte = NULL; pgd = pgd_offset(mm, addr); - if (pgd) { - pud = pud_offset(pgd, addr); - if (pud) { - pmd = pmd_alloc(mm, pud, addr); - if (pmd) - pte = pte_alloc_map(mm, pmd, addr); - } + pud = pud_alloc(mm, pgd, addr); + if (pud) { + pmd = pmd_alloc(mm, pud, addr); + if (pmd) + pte = pte_alloc_map(mm, pmd, addr); } return pte; } @@ -231,13 +229,14 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) return pte; } -#define mk_pte_huge(entry) do { pte_val(entry) |= _PAGE_SZHUGE; } while (0) - void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t entry) { int i; + if (!pte_present(*ptep) && pte_present(entry)) + mm->context.huge_pte_count++; + for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) { set_pte_at(mm, addr, ptep, entry); ptep++; @@ -253,6 +252,8 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, int i; entry = *ptep; + if (pte_present(entry)) + mm->context.huge_pte_count--; for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) { pte_clear(mm, addr, ptep); @@ -302,6 +303,15 @@ static void context_reload(void *__data) void hugetlb_prefault_arch_hook(struct mm_struct *mm) { + struct tsb_config *tp = &mm->context.tsb_block[MM_TSB_HUGE]; + + if (likely(tp->tsb != NULL)) + return; + + tsb_grow(mm, MM_TSB_HUGE, 0); + tsb_context_switch(mm); + smp_tsb_sync(mm); + /* On UltraSPARC-III+ and later, configure the second half of * the Data-TLB for huge pages. */ diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index c2b556106fc1..16d231703d6a 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -283,6 +283,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t p struct mm_struct *mm; struct tsb *tsb; unsigned long tag, flags; + unsigned long tsb_index, tsb_hash_shift; if (tlb_type != hypervisor) { unsigned long pfn = pte_pfn(pte); @@ -312,10 +313,26 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t p mm = vma->vm_mm; + tsb_index = MM_TSB_BASE; + tsb_hash_shift = PAGE_SHIFT; + spin_lock_irqsave(&mm->context.lock, flags); - tsb = &mm->context.tsb[(address >> PAGE_SHIFT) & - (mm->context.tsb_nentries - 1UL)]; +#ifdef CONFIG_HUGETLB_PAGE + if (mm->context.tsb_block[MM_TSB_HUGE].tsb != NULL) { + if ((tlb_type == hypervisor && + (pte_val(pte) & _PAGE_SZALL_4V) == _PAGE_SZHUGE_4V) || + (tlb_type != hypervisor && + (pte_val(pte) & _PAGE_SZALL_4U) == _PAGE_SZHUGE_4U)) { + tsb_index = MM_TSB_HUGE; + tsb_hash_shift = HPAGE_SHIFT; + } + } +#endif + + tsb = mm->context.tsb_block[tsb_index].tsb; + tsb += ((address >> tsb_hash_shift) & + (mm->context.tsb_block[tsb_index].tsb_nentries - 1UL)); tag = (address >> 22UL); tsb_insert(tsb, tag, pte_val(pte)); diff --git a/arch/sparc64/mm/tsb.c b/arch/sparc64/mm/tsb.c index b2064e2a44d6..beaa02810f0e 100644 --- a/arch/sparc64/mm/tsb.c +++ b/arch/sparc64/mm/tsb.c @@ -15,9 +15,9 @@ extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES]; -static inline unsigned long tsb_hash(unsigned long vaddr, unsigned long nentries) +static inline unsigned long tsb_hash(unsigned long vaddr, unsigned long hash_shift, unsigned long nentries) { - vaddr >>= PAGE_SHIFT; + vaddr >>= hash_shift; return vaddr & (nentries - 1); } @@ -36,7 +36,8 @@ void flush_tsb_kernel_range(unsigned long start, unsigned long end) unsigned long v; for (v = start; v < end; v += PAGE_SIZE) { - unsigned long hash = tsb_hash(v, KERNEL_TSB_NENTRIES); + unsigned long hash = tsb_hash(v, PAGE_SHIFT, + KERNEL_TSB_NENTRIES); struct tsb *ent = &swapper_tsb[hash]; if (tag_compare(ent->tag, v)) { @@ -46,49 +47,91 @@ void flush_tsb_kernel_range(unsigned long start, unsigned long end) } } -void flush_tsb_user(struct mmu_gather *mp) +static void __flush_tsb_one(struct mmu_gather *mp, unsigned long hash_shift, unsigned long tsb, unsigned long nentries) { - struct mm_struct *mm = mp->mm; - unsigned long nentries, base, flags; - struct tsb *tsb; - int i; - - spin_lock_irqsave(&mm->context.lock, flags); - - tsb = mm->context.tsb; - nentries = mm->context.tsb_nentries; + unsigned long i; - if (tlb_type == cheetah_plus || tlb_type == hypervisor) - base = __pa(tsb); - else - base = (unsigned long) tsb; - for (i = 0; i < mp->tlb_nr; i++) { unsigned long v = mp->vaddrs[i]; unsigned long tag, ent, hash; v &= ~0x1UL; - hash = tsb_hash(v, nentries); - ent = base + (hash * sizeof(struct tsb)); + hash = tsb_hash(v, hash_shift, nentries); + ent = tsb + (hash * sizeof(struct tsb)); tag = (v >> 22UL); tsb_flush(ent, tag); } +} + +void flush_tsb_user(struct mmu_gather *mp) +{ + struct mm_struct *mm = mp->mm; + unsigned long nentries, base, flags; + + spin_lock_irqsave(&mm->context.lock, flags); + base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb; + nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries; + if (tlb_type == cheetah_plus || tlb_type == hypervisor) + base = __pa(base); + __flush_tsb_one(mp, PAGE_SHIFT, base, nentries); + +#ifdef CONFIG_HUGETLB_PAGE + if (mm->context.tsb_block[MM_TSB_HUGE].tsb) { + base = (unsigned long) mm->context.tsb_block[MM_TSB_HUGE].tsb; + nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries; + if (tlb_type == cheetah_plus || tlb_type == hypervisor) + base = __pa(base); + __flush_tsb_one(mp, HPAGE_SHIFT, base, nentries); + } +#endif spin_unlock_irqrestore(&mm->context.lock, flags); } -static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_bytes) +#if defined(CONFIG_SPARC64_PAGE_SIZE_8KB) +#define HV_PGSZ_IDX_BASE HV_PGSZ_IDX_8K +#define HV_PGSZ_MASK_BASE HV_PGSZ_MASK_8K +#elif defined(CONFIG_SPARC64_PAGE_SIZE_64KB) +#define HV_PGSZ_IDX_BASE HV_PGSZ_IDX_64K +#define HV_PGSZ_MASK_BASE HV_PGSZ_MASK_64K +#elif defined(CONFIG_SPARC64_PAGE_SIZE_512KB) +#define HV_PGSZ_IDX_BASE HV_PGSZ_IDX_512K +#define HV_PGSZ_MASK_BASE HV_PGSZ_MASK_512K +#elif defined(CONFIG_SPARC64_PAGE_SIZE_4MB) +#define HV_PGSZ_IDX_BASE HV_PGSZ_IDX_4MB +#define HV_PGSZ_MASK_BASE HV_PGSZ_MASK_4MB +#else +#error Broken base page size setting... +#endif + +#ifdef CONFIG_HUGETLB_PAGE +#if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) +#define HV_PGSZ_IDX_HUGE HV_PGSZ_IDX_64K +#define HV_PGSZ_MASK_HUGE HV_PGSZ_MASK_64K +#elif defined(CONFIG_HUGETLB_PAGE_SIZE_512K) +#define HV_PGSZ_IDX_HUGE HV_PGSZ_IDX_512K +#define HV_PGSZ_MASK_HUGE HV_PGSZ_MASK_512K +#elif defined(CONFIG_HUGETLB_PAGE_SIZE_4MB) +#define HV_PGSZ_IDX_HUGE HV_PGSZ_IDX_4MB +#define HV_PGSZ_MASK_HUGE HV_PGSZ_MASK_4MB +#else +#error Broken huge page size setting... +#endif +#endif + +static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsigned long tsb_bytes) { unsigned long tsb_reg, base, tsb_paddr; unsigned long page_sz, tte; - mm->context.tsb_nentries = tsb_bytes / sizeof(struct tsb); + mm->context.tsb_block[tsb_idx].tsb_nentries = + tsb_bytes / sizeof(struct tsb); base = TSBMAP_BASE; tte = pgprot_val(PAGE_KERNEL_LOCKED); - tsb_paddr = __pa(mm->context.tsb); + tsb_paddr = __pa(mm->context.tsb_block[tsb_idx].tsb); BUG_ON(tsb_paddr & (tsb_bytes - 1UL)); /* Use the smallest page size that can map the whole TSB @@ -147,61 +190,49 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_bytes) /* Physical mapping, no locked TLB entry for TSB. */ tsb_reg |= tsb_paddr; - mm->context.tsb_reg_val = tsb_reg; - mm->context.tsb_map_vaddr = 0; - mm->context.tsb_map_pte = 0; + mm->context.tsb_block[tsb_idx].tsb_reg_val = tsb_reg; + mm->context.tsb_block[tsb_idx].tsb_map_vaddr = 0; + mm->context.tsb_block[tsb_idx].tsb_map_pte = 0; } else { tsb_reg |= base; tsb_reg |= (tsb_paddr & (page_sz - 1UL)); tte |= (tsb_paddr & ~(page_sz - 1UL)); - mm->context.tsb_reg_val = tsb_reg; - mm->context.tsb_map_vaddr = base; - mm->context.tsb_map_pte = tte; + mm->context.tsb_block[tsb_idx].tsb_reg_val = tsb_reg; + mm->context.tsb_block[tsb_idx].tsb_map_vaddr = base; + mm->context.tsb_block[tsb_idx].tsb_map_pte = tte; } /* Setup the Hypervisor TSB descriptor. */ if (tlb_type == hypervisor) { - struct hv_tsb_descr *hp = &mm->context.tsb_descr; + struct hv_tsb_descr *hp = &mm->context.tsb_descr[tsb_idx]; - switch (PAGE_SIZE) { - case 8192: - default: - hp->pgsz_idx = HV_PGSZ_IDX_8K; + switch (tsb_idx) { + case MM_TSB_BASE: + hp->pgsz_idx = HV_PGSZ_IDX_BASE; break; - - case 64 * 1024: - hp->pgsz_idx = HV_PGSZ_IDX_64K; - break; - - case 512 * 1024: - hp->pgsz_idx = HV_PGSZ_IDX_512K; - break; - - case 4 * 1024 * 1024: - hp->pgsz_idx = HV_PGSZ_IDX_4MB; +#ifdef CONFIG_HUGETLB_PAGE + case MM_TSB_HUGE: + hp->pgsz_idx = HV_PGSZ_IDX_HUGE; break; +#endif + default: + BUG(); }; hp->assoc = 1; hp->num_ttes = tsb_bytes / 16; hp->ctx_idx = 0; - switch (PAGE_SIZE) { - case 8192: - default: - hp->pgsz_mask = HV_PGSZ_MASK_8K; - break; - - case 64 * 1024: - hp->pgsz_mask = HV_PGSZ_MASK_64K; - break; - - case 512 * 1024: - hp->pgsz_mask = HV_PGSZ_MASK_512K; + switch (tsb_idx) { + case MM_TSB_BASE: + hp->pgsz_mask = HV_PGSZ_MASK_BASE; break; - - case 4 * 1024 * 1024: - hp->pgsz_mask = HV_PGSZ_MASK_4MB; +#ifdef CONFIG_HUGETLB_PAGE + case MM_TSB_HUGE: + hp->pgsz_mask = HV_PGSZ_MASK_HUGE; break; +#endif + default: + BUG(); }; hp->tsb_base = tsb_paddr; hp->resv = 0; @@ -241,11 +272,11 @@ void __init tsb_cache_init(void) } } -/* When the RSS of an address space exceeds mm->context.tsb_rss_limit, - * do_sparc64_fault() invokes this routine to try and grow the TSB. +/* When the RSS of an address space exceeds tsb_rss_limit for a TSB, + * do_sparc64_fault() invokes this routine to try and grow it. * * When we reach the maximum TSB size supported, we stick ~0UL into - * mm->context.tsb_rss_limit so the grow checks in update_mmu_cache() + * tsb_rss_limit for that TSB so the grow checks in do_sparc64_fault() * will not trigger any longer. * * The TSB can be anywhere from 8K to 1MB in size, in increasing powers @@ -257,7 +288,7 @@ void __init tsb_cache_init(void) * the number of entries that the current TSB can hold at once. Currently, * we trigger when the RSS hits 3/4 of the TSB capacity. */ -void tsb_grow(struct mm_struct *mm, unsigned long rss) +void tsb_grow(struct mm_struct *mm, unsigned long tsb_index, unsigned long rss) { unsigned long max_tsb_size = 1 * 1024 * 1024; unsigned long new_size, old_size, flags; @@ -297,7 +328,8 @@ retry_tsb_alloc: * down to a 0-order allocation and force no TSB * growing for this address space. */ - if (mm->context.tsb == NULL && new_cache_index > 0) { + if (mm->context.tsb_block[tsb_index].tsb == NULL && + new_cache_index > 0) { new_cache_index = 0; new_size = 8192; new_rss_limit = ~0UL; @@ -307,8 +339,8 @@ retry_tsb_alloc: /* If we failed on a TSB grow, we are under serious * memory pressure so don't try to grow any more. */ - if (mm->context.tsb != NULL) - mm->context.tsb_rss_limit = ~0UL; + if (mm->context.tsb_block[tsb_index].tsb != NULL) + mm->context.tsb_block[tsb_index].tsb_rss_limit = ~0UL; return; } @@ -339,23 +371,26 @@ retry_tsb_alloc: */ spin_lock_irqsave(&mm->context.lock, flags); - old_tsb = mm->context.tsb; - old_cache_index = (mm->context.tsb_reg_val & 0x7UL); - old_size = mm->context.tsb_nentries * sizeof(struct tsb); + old_tsb = mm->context.tsb_block[tsb_index].tsb; + old_cache_index = + (mm->context.tsb_block[tsb_index].tsb_reg_val & 0x7UL); + old_size = (mm->context.tsb_block[tsb_index].tsb_nentries * + sizeof(struct tsb)); /* Handle multiple threads trying to grow the TSB at the same time. * One will get in here first, and bump the size and the RSS limit. * The others will get in here next and hit this check. */ - if (unlikely(old_tsb && (rss < mm->context.tsb_rss_limit))) { + if (unlikely(old_tsb && + (rss < mm->context.tsb_block[tsb_index].tsb_rss_limit))) { spin_unlock_irqrestore(&mm->context.lock, flags); kmem_cache_free(tsb_caches[new_cache_index], new_tsb); return; } - mm->context.tsb_rss_limit = new_rss_limit; + mm->context.tsb_block[tsb_index].tsb_rss_limit = new_rss_limit; if (old_tsb) { extern void copy_tsb(unsigned long old_tsb_base, @@ -372,8 +407,8 @@ retry_tsb_alloc: copy_tsb(old_tsb_base, old_size, new_tsb_base, new_size); } - mm->context.tsb = new_tsb; - setup_tsb_params(mm, new_size); + mm->context.tsb_block[tsb_index].tsb = new_tsb; + setup_tsb_params(mm, tsb_index, new_size); spin_unlock_irqrestore(&mm->context.lock, flags); @@ -394,40 +429,65 @@ retry_tsb_alloc: int init_new_context(struct task_struct *tsk, struct mm_struct *mm) { +#ifdef CONFIG_HUGETLB_PAGE + unsigned long huge_pte_count; +#endif + unsigned int i; + spin_lock_init(&mm->context.lock); mm->context.sparc64_ctx_val = 0UL; +#ifdef CONFIG_HUGETLB_PAGE + /* We reset it to zero because the fork() page copying + * will re-increment the counters as the parent PTEs are + * copied into the child address space. + */ + huge_pte_count = mm->context.huge_pte_count; + mm->context.huge_pte_count = 0; +#endif + /* copy_mm() copies over the parent's mm_struct before calling * us, so we need to zero out the TSB pointer or else tsb_grow() * will be confused and think there is an older TSB to free up. */ - mm->context.tsb = NULL; + for (i = 0; i < MM_NUM_TSBS; i++) + mm->context.tsb_block[i].tsb = NULL; /* If this is fork, inherit the parent's TSB size. We would * grow it to that size on the first page fault anyways. */ - tsb_grow(mm, get_mm_rss(mm)); + tsb_grow(mm, MM_TSB_BASE, get_mm_rss(mm)); - if (unlikely(!mm->context.tsb)) +#ifdef CONFIG_HUGETLB_PAGE + if (unlikely(huge_pte_count)) + tsb_grow(mm, MM_TSB_HUGE, huge_pte_count); +#endif + + if (unlikely(!mm->context.tsb_block[MM_TSB_BASE].tsb)) return -ENOMEM; return 0; } -void destroy_context(struct mm_struct *mm) +static void tsb_destroy_one(struct tsb_config *tp) { - unsigned long flags, cache_index; + unsigned long cache_index; - cache_index = (mm->context.tsb_reg_val & 0x7UL); - kmem_cache_free(tsb_caches[cache_index], mm->context.tsb); + if (!tp->tsb) + return; + cache_index = tp->tsb_reg_val & 0x7UL; + kmem_cache_free(tsb_caches[cache_index], tp->tsb); + tp->tsb = NULL; + tp->tsb_reg_val = 0UL; +} - /* We can remove these later, but for now it's useful - * to catch any bogus post-destroy_context() references - * to the TSB. - */ - mm->context.tsb = NULL; - mm->context.tsb_reg_val = 0UL; +void destroy_context(struct mm_struct *mm) +{ + unsigned long flags, i; + + for (i = 0; i < MM_NUM_TSBS; i++) + tsb_destroy_one(&mm->context.tsb_block[i]); spin_lock_irqsave(&ctx_alloc_lock, flags); diff --git a/include/asm-sparc64/cpudata.h b/include/asm-sparc64/cpudata.h index c66a81bbc84d..9d6a6dbaf126 100644 --- a/include/asm-sparc64/cpudata.h +++ b/include/asm-sparc64/cpudata.h @@ -71,7 +71,8 @@ struct trap_per_cpu { /* Dcache line 7: Physical addresses of CPU send mondo block and CPU list. */ unsigned long cpu_mondo_block_pa; unsigned long cpu_list_pa; - unsigned long __pad1[2]; + unsigned long tsb_huge; + unsigned long tsb_huge_temp; /* Dcache line 8: Unused, needed to keep trap_block a power-of-2 in size. */ unsigned long __pad2[4]; @@ -116,6 +117,8 @@ extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch, #define TRAP_PER_CPU_FAULT_INFO 0x40 #define TRAP_PER_CPU_CPU_MONDO_BLOCK_PA 0xc0 #define TRAP_PER_CPU_CPU_LIST_PA 0xc8 +#define TRAP_PER_CPU_TSB_HUGE 0xd0 +#define TRAP_PER_CPU_TSB_HUGE_TEMP 0xd8 #define TRAP_BLOCK_SZ_SHIFT 8 diff --git a/include/asm-sparc64/mmu.h b/include/asm-sparc64/mmu.h index 230ba678d3b0..2d4f2ea9568a 100644 --- a/include/asm-sparc64/mmu.h +++ b/include/asm-sparc64/mmu.h @@ -90,18 +90,39 @@ extern void __tsb_insert(unsigned long ent, unsigned long tag, unsigned long pte extern void tsb_flush(unsigned long ent, unsigned long tag); extern void tsb_init(struct tsb *tsb, unsigned long size); -typedef struct { - spinlock_t lock; - unsigned long sparc64_ctx_val; +struct tsb_config { struct tsb *tsb; unsigned long tsb_rss_limit; unsigned long tsb_nentries; unsigned long tsb_reg_val; unsigned long tsb_map_vaddr; unsigned long tsb_map_pte; - struct hv_tsb_descr tsb_descr; +}; + +#define MM_TSB_BASE 0 + +#ifdef CONFIG_HUGETLB_PAGE +#define MM_TSB_HUGE 1 +#define MM_NUM_TSBS 2 +#else +#define MM_NUM_TSBS 1 +#endif + +typedef struct { + spinlock_t lock; + unsigned long sparc64_ctx_val; + unsigned long huge_pte_count; + struct tsb_config tsb_block[MM_NUM_TSBS]; + struct hv_tsb_descr tsb_descr[MM_NUM_TSBS]; } mm_context_t; #endif /* !__ASSEMBLY__ */ +#define TSB_CONFIG_TSB 0x00 +#define TSB_CONFIG_RSS_LIMIT 0x08 +#define TSB_CONFIG_NENTRIES 0x10 +#define TSB_CONFIG_REG_VAL 0x18 +#define TSB_CONFIG_MAP_VADDR 0x20 +#define TSB_CONFIG_MAP_PTE 0x28 + #endif /* __MMU_H */ diff --git a/include/asm-sparc64/mmu_context.h b/include/asm-sparc64/mmu_context.h index e7974321d052..2337eb487719 100644 --- a/include/asm-sparc64/mmu_context.h +++ b/include/asm-sparc64/mmu_context.h @@ -29,20 +29,25 @@ extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm); extern void destroy_context(struct mm_struct *mm); extern void __tsb_context_switch(unsigned long pgd_pa, - unsigned long tsb_reg, - unsigned long tsb_vaddr, - unsigned long tsb_pte, + struct tsb_config *tsb_base, + struct tsb_config *tsb_huge, unsigned long tsb_descr_pa); static inline void tsb_context_switch(struct mm_struct *mm) { - __tsb_context_switch(__pa(mm->pgd), mm->context.tsb_reg_val, - mm->context.tsb_map_vaddr, - mm->context.tsb_map_pte, - __pa(&mm->context.tsb_descr)); + __tsb_context_switch(__pa(mm->pgd), + &mm->context.tsb_block[0], +#ifdef CONFIG_HUGETLB_PAGE + (mm->context.tsb_block[1].tsb ? + &mm->context.tsb_block[1] : + NULL) +#else + NULL +#endif + , __pa(&mm->context.tsb_descr[0])); } -extern void tsb_grow(struct mm_struct *mm, unsigned long mm_rss); +extern void tsb_grow(struct mm_struct *mm, unsigned long tsb_index, unsigned long mm_rss); #ifdef CONFIG_SMP extern void smp_tsb_sync(struct mm_struct *mm); #else diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h index fcb2812265f4..66fe4ac59fd6 100644 --- a/include/asm-sparc64/page.h +++ b/include/asm-sparc64/page.h @@ -30,6 +30,23 @@ #ifdef __KERNEL__ +#if defined(CONFIG_HUGETLB_PAGE_SIZE_4MB) +#define HPAGE_SHIFT 22 +#elif defined(CONFIG_HUGETLB_PAGE_SIZE_512K) +#define HPAGE_SHIFT 19 +#elif defined(CONFIG_HUGETLB_PAGE_SIZE_64K) +#define HPAGE_SHIFT 16 +#endif + +#ifdef CONFIG_HUGETLB_PAGE +#define HPAGE_SIZE (_AC(1,UL) << HPAGE_SHIFT) +#define HPAGE_MASK (~(HPAGE_SIZE - 1UL)) +#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) +#define ARCH_HAS_SETCLEAR_HUGE_PTE +#define ARCH_HAS_HUGETLB_PREFAULT_HOOK +#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA +#endif + #ifndef __ASSEMBLY__ extern void _clear_page(void *page); @@ -90,23 +107,6 @@ typedef unsigned long pgprot_t; #endif /* (STRICT_MM_TYPECHECKS) */ -#if defined(CONFIG_HUGETLB_PAGE_SIZE_4MB) -#define HPAGE_SHIFT 22 -#elif defined(CONFIG_HUGETLB_PAGE_SIZE_512K) -#define HPAGE_SHIFT 19 -#elif defined(CONFIG_HUGETLB_PAGE_SIZE_64K) -#define HPAGE_SHIFT 16 -#endif - -#ifdef CONFIG_HUGETLB_PAGE -#define HPAGE_SIZE (_AC(1,UL) << HPAGE_SHIFT) -#define HPAGE_MASK (~(HPAGE_SIZE - 1UL)) -#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) -#define ARCH_HAS_SETCLEAR_HUGE_PTE -#define ARCH_HAS_HUGETLB_PREFAULT_HOOK -#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA -#endif - #define TASK_UNMAPPED_BASE (test_thread_flag(TIF_32BIT) ? \ (_AC(0x0000000070000000,UL)) : \ (_AC(0xfffff80000000000,UL) + (1UL << 32UL))) diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h index ed4124edf837..c44e7466534e 100644 --- a/include/asm-sparc64/pgtable.h +++ b/include/asm-sparc64/pgtable.h @@ -105,6 +105,7 @@ #define _PAGE_RES1_4U _AC(0x0002000000000000,UL) /* Reserved */ #define _PAGE_SZ32MB_4U _AC(0x0001000000000000,UL) /* (Panther) 32MB page */ #define _PAGE_SZ256MB_4U _AC(0x2001000000000000,UL) /* (Panther) 256MB page */ +#define _PAGE_SZALL_4U _AC(0x6001000000000000,UL) /* All pgsz bits */ #define _PAGE_SN_4U _AC(0x0000800000000000,UL) /* (Cheetah) Snoop */ #define _PAGE_RES2_4U _AC(0x0000780000000000,UL) /* Reserved */ #define _PAGE_PADDR_4U _AC(0x000007FFFFFFE000,UL) /* (Cheetah) pa[42:13] */ @@ -150,6 +151,7 @@ #define _PAGE_SZ512K_4V _AC(0x0000000000000002,UL) /* 512K Page */ #define _PAGE_SZ64K_4V _AC(0x0000000000000001,UL) /* 64K Page */ #define _PAGE_SZ8K_4V _AC(0x0000000000000000,UL) /* 8K Page */ +#define _PAGE_SZALL_4V _AC(0x0000000000000007,UL) /* All pgsz bits */ #if PAGE_SHIFT == 13 #define _PAGE_SZBITS_4U _PAGE_SZ8K_4U -- cgit v1.2.3 From 21a3479a0b606d36fe24093f70a1c27328cec286 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 13 Jan 2006 09:12:11 +0100 Subject: [ALSA] PCM midlevel & PCM OSS - make procfs & OSS plugin code optional Modules: ALSA Core,PCM Midlevel,ALSA<-OSS emulation,USB generic driver 1) The verbose procfs code for the PCM midlevel and usb audio can be removed now (more patches will follow). CONFIG_SND_VERBOSE_PROCFS 2) The PCM OSS plugin system can be also compiled optionaly. CONFIG_SND_PCM_OSS_PLUGINS Signed-off-by: Jaroslav Kysela --- include/sound/pcm_oss.h | 2 ++ sound/core/Kconfig | 18 ++++++++++++++++++ sound/core/oss/copy.c | 5 +++++ sound/core/oss/io.c | 5 +++++ sound/core/oss/linear.c | 5 +++++ sound/core/oss/mulaw.c | 5 +++++ sound/core/oss/pcm_oss.c | 20 ++++++++++++++++++-- sound/core/oss/pcm_plugin.c | 5 +++++ sound/core/oss/pcm_plugin.h | 10 ++++++++++ sound/core/oss/rate.c | 5 +++++ sound/core/oss/route.c | 5 +++++ sound/core/pcm.c | 4 +++- sound/usb/usbaudio.c | 13 +++++++++++-- 13 files changed, 97 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h index fddaddde47b4..d6ec886637db 100644 --- a/include/sound/pcm_oss.h +++ b/include/sound/pcm_oss.h @@ -56,8 +56,10 @@ struct snd_pcm_oss_runtime { size_t mmap_bytes; char *buffer; /* vmallocated period */ size_t buffer_used; /* used length from period buffer */ +#ifdef CONFIG_SND_PCM_OSS_PLUGINS struct snd_pcm_plugin *plugin_first; struct snd_pcm_plugin *plugin_last; +#endif unsigned int prev_hw_ptr_interrupt; }; diff --git a/sound/core/Kconfig b/sound/core/Kconfig index f79755f77a81..9dd121bb5638 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig @@ -73,6 +73,15 @@ config SND_PCM_OSS To compile this driver as a module, choose M here: the module will be called snd-pcm-oss. +config SND_PCM_OSS_PLUGINS + bool "OSS PCM (digital audio) API - Include plugin system" + depends on SND_PCM_OSS + default y + help + If you disable this option, the ALSA's OSS PCM API will not + support conversion of channels, formats and rates. It will + behave like most of new OSS/Free drivers in 2.4/2.6 kernels. + config SND_SEQUENCER_OSS bool "OSS Sequencer API" depends on SND && SND_SEQUENCER @@ -130,6 +139,15 @@ config SND_SUPPORT_OLD_API Say Y here to support the obsolete ALSA PCM API (ver.0.9.0 rc3 or older). +config SND_VERBOSE_PROCFS + bool "Verbose procfs contents" + depends on SND + default y + help + Say Y here to include code for verbose procfs contents (provides + usefull information to developers when a problem occurs). On the + other side, it makes the ALSA subsystem larger. + config SND_VERBOSE_PRINTK bool "Verbose printk" depends on SND diff --git a/sound/core/oss/copy.c b/sound/core/oss/copy.c index d6a04c2d5a75..7c008c4c0dd1 100644 --- a/sound/core/oss/copy.c +++ b/sound/core/oss/copy.c @@ -20,6 +20,9 @@ */ #include + +#ifdef SND_PCM_OSS_PLUGINS + #include #include #include @@ -85,3 +88,5 @@ int snd_pcm_plugin_build_copy(struct snd_pcm_substream *plug, *r_plugin = plugin; return 0; } + +#endif diff --git a/sound/core/oss/io.c b/sound/core/oss/io.c index 322702e05f3e..b6e7ce30e5a3 100644 --- a/sound/core/oss/io.c +++ b/sound/core/oss/io.c @@ -20,6 +20,9 @@ */ #include + +#ifdef CONFIG_SND_PCM_OSS_PLUGINS + #include #include #include @@ -132,3 +135,5 @@ int snd_pcm_plugin_build_io(struct snd_pcm_substream *plug, *r_plugin = plugin; return 0; } + +#endif diff --git a/sound/core/oss/linear.c b/sound/core/oss/linear.c index 8cbfa415ce40..ef331230b3a6 100644 --- a/sound/core/oss/linear.c +++ b/sound/core/oss/linear.c @@ -21,6 +21,9 @@ */ #include + +#ifdef CONFIG_SND_PCM_OSS_PLUGINS + #include #include #include @@ -156,3 +159,5 @@ int snd_pcm_plugin_build_linear(struct snd_pcm_substream *plug, *r_plugin = plugin; return 0; } + +#endif diff --git a/sound/core/oss/mulaw.c b/sound/core/oss/mulaw.c index 14f5578ec7a7..ed12c81fcf1b 100644 --- a/sound/core/oss/mulaw.c +++ b/sound/core/oss/mulaw.c @@ -22,6 +22,9 @@ */ #include + +#ifdef CONFIG_SND_PCM_OSS_PLUGINS + #include #include #include @@ -306,3 +309,5 @@ int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug, *r_plugin = plugin; return 0; } + +#endif diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 7fd072392c7e..bc24d028f518 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -78,6 +78,7 @@ static inline void snd_leave_user(mm_segment_t fs) set_fs(fs); } +#ifdef CONFIG_SND_PCM_OSS_PLUGINS static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -122,6 +123,7 @@ int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin) } return 0; } +#endif /* CONFIG_SND_PCM_OSS_PLUGINS */ static long snd_pcm_oss_bytes(struct snd_pcm_substream *substream, long frames) { @@ -412,6 +414,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) oss_frame_size = snd_pcm_format_physical_width(params_format(params)) * params_channels(params) / 8; +#ifdef CONFIG_SND_PCM_OSS_PLUGINS snd_pcm_oss_plugin_clear(substream); if (!direct) { /* add necessary plugins */ @@ -441,6 +444,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) } } } +#endif err = snd_pcm_oss_period_size(substream, params, sparams); if (err < 0) @@ -498,11 +502,13 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) runtime->oss.periods = params_periods(sparams); oss_period_size = snd_pcm_plug_client_size(substream, params_period_size(sparams)); snd_assert(oss_period_size >= 0, err = -EINVAL; goto failure); +#ifdef CONFIG_SND_PCM_OSS_PLUGINS if (runtime->oss.plugin_first) { err = snd_pcm_plug_alloc(substream, oss_period_size); if (err < 0) goto failure; } +#endif oss_period_size *= oss_frame_size; oss_buffer_size = oss_period_size * runtime->oss.periods; @@ -784,6 +790,7 @@ static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const cha { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_sframes_t frames, frames1; +#ifdef CONFIG_SND_PCM_OSS_PLUGINS if (runtime->oss.plugin_first) { struct snd_pcm_plugin_channel *channels; size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8; @@ -800,7 +807,9 @@ static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const cha if (frames1 <= 0) return frames1; bytes = frames1 * oss_frame_bytes; - } else { + } else +#endif + { frames = bytes_to_frames(runtime, bytes); frames1 = snd_pcm_oss_write3(substream, buf, frames, in_kernel); if (frames1 <= 0) @@ -871,6 +880,7 @@ static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf, { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_sframes_t frames, frames1; +#ifdef CONFIG_SND_PCM_OSS_PLUGINS char __user *final_dst = (char __user *)buf; if (runtime->oss.plugin_first) { struct snd_pcm_plugin_channel *channels; @@ -887,7 +897,9 @@ static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf, bytes = frames1 * oss_frame_bytes; if (!in_kernel && copy_to_user(final_dst, buf, bytes)) return -EFAULT; - } else { + } else +#endif + { frames = bytes_to_frames(runtime, bytes); frames1 = snd_pcm_oss_read3(substream, buf, frames, in_kernel); if (frames1 <= 0) @@ -1692,7 +1704,9 @@ static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime; runtime = substream->runtime; vfree(runtime->oss.buffer); +#ifdef CONFIG_SND_PCM_OSS_PLUGINS snd_pcm_oss_plugin_clear(substream); +#endif substream->oss.file = NULL; substream->oss.oss = 0; } @@ -2246,8 +2260,10 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) if ((err = snd_pcm_oss_change_params(substream)) < 0) return err; } +#ifdef CONFIG_SND_PCM_OSS_PLUGINS if (runtime->oss.plugin_first != NULL) return -EIO; +#endif if (area->vm_pgoff != 0) return -EINVAL; diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index 7e8676880dde..89bc8f965043 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c @@ -25,6 +25,9 @@ #endif #include + +#ifdef CONFIG_SND_PCM_OSS_PLUGINS + #include #include #include @@ -916,3 +919,5 @@ int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_area, size_t src_of } return 0; } + +#endif diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h index 29198da615cd..a8a4f9580435 100644 --- a/sound/core/oss/pcm_plugin.h +++ b/sound/core/oss/pcm_plugin.h @@ -22,6 +22,8 @@ * */ +#ifdef CONFIG_SND_PCM_OSS_PLUGINS + #include static inline unsigned long *bitmap_alloc(unsigned int nbits) @@ -191,6 +193,14 @@ void zero_channel(struct snd_pcm_plugin *plugin, const struct snd_pcm_plugin_channel *dst_channel, size_t samples); +#else + +static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; } +static inline snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size) { return clt_size; } +static inline int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask) { return format; } + +#endif + #ifdef PLUGIN_DEBUG #define pdprintf( fmt, args... ) printk( "plugin: " fmt, ##args) #else diff --git a/sound/core/oss/rate.c b/sound/core/oss/rate.c index 4854cef6fb4f..c4b75bff0ee5 100644 --- a/sound/core/oss/rate.c +++ b/sound/core/oss/rate.c @@ -20,6 +20,9 @@ */ #include + +#ifdef CONFIG_SND_PCM_OSS_PLUGINS + #include #include #include @@ -377,3 +380,5 @@ int snd_pcm_plugin_build_rate(struct snd_pcm_substream *plug, *r_plugin = plugin; return 0; } + +#endif diff --git a/sound/core/oss/route.c b/sound/core/oss/route.c index 726c5caa3fdb..f99a54e6551a 100644 --- a/sound/core/oss/route.c +++ b/sound/core/oss/route.c @@ -20,6 +20,9 @@ */ #include + +#ifdef CONFIG_SND_PCM_OSS_PLUGINS + #include #include #include @@ -519,3 +522,5 @@ int snd_pcm_plugin_build_route(struct snd_pcm_substream *plug, *r_plugin = plugin; return 0; } + +#endif diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 28ca61eb0b0d..d92c3ce4a4c9 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -140,6 +140,9 @@ static int snd_pcm_control_ioctl(struct snd_card *card, } return -ENOIOCTLCMD; } + +#if defined(CONFIG_PROC_FS) && defined(CONFIG_SND_VERBOSE_PROCFS) + #define STATE(v) [SNDRV_PCM_STATE_##v] = #v #define STREAM(v) [SNDRV_PCM_STREAM_##v] = #v #define READY(v) [SNDRV_PCM_READY_##v] = #v @@ -197,7 +200,6 @@ const char *snd_pcm_format_name(snd_pcm_format_t format) return snd_pcm_format_names[format]; } -#ifdef CONFIG_PROC_FS static char *snd_pcm_stream_names[] = { STREAM(PLAYBACK), STREAM(CAPTURE), diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index f5aadb001986..c9476c237c42 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -1384,8 +1384,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, channels = params_channels(hw_params); fmt = find_format(subs, format, rate, channels); if (! fmt) { - snd_printd(KERN_DEBUG "cannot set format: format = %s, rate = %d, channels = %d\n", - snd_pcm_format_name(format), rate, channels); + snd_printd(KERN_DEBUG "cannot set format: format = 0x%x, rate = %d, channels = %d\n", + format, rate, channels); return -EINVAL; } @@ -2011,6 +2011,8 @@ static struct usb_driver usb_audio_driver = { }; +#if defined(CONFIG_PROCFS) && defined(CONFIG_SND_VERBOSE_PROCFS) + /* * proc interface for list the supported pcm formats */ @@ -2101,6 +2103,13 @@ static void proc_pcm_format_add(struct snd_usb_stream *stream) snd_info_set_text_ops(entry, stream, 1024, proc_pcm_format_read); } +#else + +static inline void proc_pcm_format_add(struct snd_usb_stream *stream) +{ +} + +#endif /* * initialize the substream instance. -- cgit v1.2.3 From f7cbb7fcd3bae5264a079e06411b35366da9bd4d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 13 Jan 2006 18:48:06 +0100 Subject: [ALSA] Fix snd_xxx_t typedefs Modules: PXA Mainstone driver,CX88 driver,SAA7134 driver Replace snd_xxx_t typedefs with explicit structs. Signed-off-by: Takashi Iwai --- arch/arm/mach-pxa/mainstone.c | 4 +- drivers/media/video/cx88/cx88-alsa.c | 54 +++++++++++++------------ drivers/media/video/saa7134/saa7134-alsa.c | 65 +++++++++++++++++------------- drivers/media/video/saa7134/saa7134.h | 2 +- include/asm-arm/arch-pxa/audio.h | 4 +- 5 files changed, 70 insertions(+), 59 deletions(-) (limited to 'include') diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index d5bda60209ec..98356f810007 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -157,14 +157,14 @@ static struct platform_device smc91x_device = { .resource = smc91x_resources, }; -static int mst_audio_startup(snd_pcm_substream_t *substream, void *priv) +static int mst_audio_startup(struct snd_pcm_substream *substream, void *priv) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) MST_MSCWR2 &= ~MST_MSCWR2_AC97_SPKROFF; return 0; } -static void mst_audio_shutdown(snd_pcm_substream_t *substream, void *priv) +static void mst_audio_shutdown(struct snd_pcm_substream *substream, void *priv) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) MST_MSCWR2 |= MST_MSCWR2_AC97_SPKROFF; diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 2acccd6d49bc..c841914c0244 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -63,7 +63,7 @@ struct cx88_audio_dev { /* audio controls */ int irq; - snd_card_t *card; + struct snd_card *card; spinlock_t reg_lock; @@ -82,7 +82,7 @@ struct cx88_audio_dev { struct cx88_buffer *buf; long opened; - snd_pcm_substream_t *substream; + struct snd_pcm_substream *substream; }; typedef struct cx88_audio_dev snd_cx88_card_t; @@ -96,7 +96,7 @@ typedef struct cx88_audio_dev snd_cx88_card_t; static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; -static snd_card_t *snd_cx88_cards[SNDRV_CARDS]; +static struct snd_card *snd_cx88_cards[SNDRV_CARDS]; module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled."); @@ -320,7 +320,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip) /* * Digital hardware definition */ -static snd_pcm_hardware_t snd_cx88_digital_hw = { +static struct snd_pcm_hardware snd_cx88_digital_hw = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | @@ -342,16 +342,16 @@ static snd_pcm_hardware_t snd_cx88_digital_hw = { /* * audio pcm capture runtime free */ -static void snd_card_cx88_runtime_free(snd_pcm_runtime_t *runtime) +static void snd_card_cx88_runtime_free(struct snd_pcm_runtime *runtime) { } /* * audio pcm capture open callback */ -static int snd_cx88_pcm_open(snd_pcm_substream_t *substream) +static int snd_cx88_pcm_open(struct snd_pcm_substream *substream) { snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; int err; if (test_and_set_bit(0, &chip->opened)) @@ -380,7 +380,7 @@ _error: /* * audio close callback */ -static int snd_cx88_close(snd_pcm_substream_t *substream) +static int snd_cx88_close(struct snd_pcm_substream *substream) { snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); @@ -393,8 +393,8 @@ static int snd_cx88_close(snd_pcm_substream_t *substream) /* * hw_params callback */ -static int snd_cx88_hw_params(snd_pcm_substream_t * substream, - snd_pcm_hw_params_t * hw_params) +static int snd_cx88_hw_params(struct snd_pcm_substream * substream, + struct snd_pcm_hw_params * hw_params) { snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); struct cx88_buffer *buf; @@ -453,7 +453,7 @@ static int snd_cx88_hw_params(snd_pcm_substream_t * substream, /* * hw free callback */ -static int snd_cx88_hw_free(snd_pcm_substream_t * substream) +static int snd_cx88_hw_free(struct snd_pcm_substream * substream) { snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); @@ -469,7 +469,7 @@ static int snd_cx88_hw_free(snd_pcm_substream_t * substream) /* * prepare callback */ -static int snd_cx88_prepare(snd_pcm_substream_t *substream) +static int snd_cx88_prepare(struct snd_pcm_substream *substream) { return 0; } @@ -478,7 +478,7 @@ static int snd_cx88_prepare(snd_pcm_substream_t *substream) /* * trigger callback */ -static int snd_cx88_card_trigger(snd_pcm_substream_t *substream, int cmd) +static int snd_cx88_card_trigger(struct snd_pcm_substream *substream, int cmd) { snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); int err; @@ -505,10 +505,10 @@ static int snd_cx88_card_trigger(snd_pcm_substream_t *substream, int cmd) /* * pointer callback */ -static snd_pcm_uframes_t snd_cx88_pointer(snd_pcm_substream_t *substream) +static snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream) { snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; if (chip->read_count) { chip->read_count -= snd_pcm_lib_period_bytes(substream); @@ -525,7 +525,7 @@ static snd_pcm_uframes_t snd_cx88_pointer(snd_pcm_substream_t *substream) /* * operators */ -static snd_pcm_ops_t snd_cx88_pcm_ops = { +static struct snd_pcm_ops snd_cx88_pcm_ops = { .open = snd_cx88_pcm_open, .close = snd_cx88_close, .ioctl = snd_pcm_lib_ioctl, @@ -542,7 +542,7 @@ static snd_pcm_ops_t snd_cx88_pcm_ops = { static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, char *name) { int err; - snd_pcm_t *pcm; + struct snd_pcm *pcm; err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); if (err < 0) @@ -557,7 +557,8 @@ static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, char *name) /**************************************************************************** CONTROL INTERFACE ****************************************************************************/ -static int snd_cx88_capture_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *info) +static int snd_cx88_capture_volume_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *info) { info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; info->count = 1; @@ -568,7 +569,8 @@ static int snd_cx88_capture_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_i } /* OK - TODO: test it */ -static int snd_cx88_capture_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value) +static int snd_cx88_capture_volume_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *value) { snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); struct cx88_core *core=chip->core; @@ -579,7 +581,8 @@ static int snd_cx88_capture_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_va } /* OK - TODO: test it */ -static int snd_cx88_capture_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value) +static int snd_cx88_capture_volume_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *value) { snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); struct cx88_core *core=chip->core; @@ -595,7 +598,7 @@ static int snd_cx88_capture_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_va return v != old_control; } -static snd_kcontrol_new_t snd_cx88_capture_volume = { +static struct snd_kcontrol_new snd_cx88_capture_volume = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Volume", .info = snd_cx88_capture_volume_info, @@ -641,7 +644,7 @@ static int snd_cx88_free(snd_cx88_card_t *chip) /* * Component Destructor */ -static void snd_cx88_dev_free(snd_card_t * card) +static void snd_cx88_dev_free(struct snd_card * card) { snd_cx88_card_t *chip = card->private_data; @@ -654,8 +657,9 @@ static void snd_cx88_dev_free(snd_card_t * card) */ static int devno; -static int __devinit snd_cx88_create(snd_card_t *card, struct pci_dev *pci, - snd_cx88_card_t **rchip) +static int __devinit snd_cx88_create(struct snd_card *card, + struct pci_dev *pci, + snd_cx88_card_t **rchip) { snd_cx88_card_t *chip; struct cx88_core *core; @@ -726,7 +730,7 @@ static int __devinit snd_cx88_create(snd_card_t *card, struct pci_dev *pci, static int __devinit cx88_audio_initdev(struct pci_dev *pci, const struct pci_device_id *pci_id) { - snd_card_t *card; + struct snd_card *card; snd_cx88_card_t *chip; int err; diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 7df5e0826e12..e02e6ee31b78 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -71,7 +71,7 @@ MODULE_PARM_DESC(enable, "Enable (or not) the SAA7134 capture interface(s)."); */ typedef struct snd_card_saa7134 { - snd_card_t *card; + struct snd_card *card; spinlock_t mixer_lock; int mixer_volume[MIXER_ADDR_LAST+1][2]; int capture_source[MIXER_ADDR_LAST+1][2]; @@ -95,10 +95,10 @@ typedef struct snd_card_saa7134_pcm { spinlock_t lock; - snd_pcm_substream_t *substream; + struct snd_pcm_substream *substream; } snd_card_saa7134_pcm_t; -static snd_card_t *snd_saa7134_cards[SNDRV_CARDS]; +static struct snd_card *snd_saa7134_cards[SNDRV_CARDS]; /* @@ -251,10 +251,10 @@ out: * */ -static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream, +static int snd_card_saa7134_capture_trigger(struct snd_pcm_substream * substream, int cmd) { - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; snd_card_saa7134_pcm_t *pcm = runtime->private_data; struct saa7134_dev *dev=pcm->dev; int err = 0; @@ -333,9 +333,9 @@ static int dsp_buffer_free(struct saa7134_dev *dev) * */ -static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) +static int snd_card_saa7134_capture_prepare(struct snd_pcm_substream * substream) { - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; int bswap, sign; u32 fmt, control; snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); @@ -422,9 +422,10 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) * */ -static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * substream) +static snd_pcm_uframes_t +snd_card_saa7134_capture_pointer(struct snd_pcm_substream * substream) { - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; snd_card_saa7134_pcm_t *pcm = runtime->private_data; struct saa7134_dev *dev=pcm->dev; @@ -442,7 +443,7 @@ static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * * ALSA hardware capabilities definition */ -static snd_pcm_hardware_t snd_card_saa7134_capture = +static struct snd_pcm_hardware snd_card_saa7134_capture = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | @@ -465,7 +466,7 @@ static snd_pcm_hardware_t snd_card_saa7134_capture = .periods_max = 1024, }; -static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime) +static void snd_card_saa7134_runtime_free(struct snd_pcm_runtime *runtime) { snd_card_saa7134_pcm_t *pcm = runtime->private_data; @@ -482,8 +483,8 @@ static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime) * */ -static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, - snd_pcm_hw_params_t * hw_params) +static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, + struct snd_pcm_hw_params * hw_params) { snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); struct saa7134_dev *dev; @@ -562,7 +563,7 @@ static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, * */ -static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) +static int snd_card_saa7134_hw_free(struct snd_pcm_substream * substream) { snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); struct saa7134_dev *dev; @@ -588,7 +589,7 @@ static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) * */ -static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) +static int snd_card_saa7134_capture_close(struct snd_pcm_substream * substream) { return 0; } @@ -603,9 +604,9 @@ static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) * */ -static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) +static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream) { - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; snd_card_saa7134_pcm_t *pcm; snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); struct saa7134_dev *dev = saa7134->dev; @@ -641,7 +642,7 @@ static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) * ALSA capture callbacks definition */ -static snd_pcm_ops_t snd_card_saa7134_capture_ops = { +static struct snd_pcm_ops snd_card_saa7134_capture_ops = { .open = snd_card_saa7134_capture_open, .close = snd_card_saa7134_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -662,7 +663,7 @@ static snd_pcm_ops_t snd_card_saa7134_capture_ops = { static int snd_card_saa7134_pcm(snd_card_saa7134_t *saa7134, int device) { - snd_pcm_t *pcm; + struct snd_pcm *pcm; int err; if ((err = snd_pcm_new(saa7134->card, "SAA7134 PCM", device, 0, 1, &pcm)) < 0) @@ -680,7 +681,8 @@ static int snd_card_saa7134_pcm(snd_card_saa7134_t *saa7134, int device) .get = snd_saa7134_volume_get, .put = snd_saa7134_volume_put, \ .private_value = addr } -static int snd_saa7134_volume_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo) +static int snd_saa7134_volume_info(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_info * uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 2; @@ -689,7 +691,8 @@ static int snd_saa7134_volume_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_ return 0; } -static int snd_saa7134_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_saa7134_volume_get(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_value * ucontrol) { snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); int addr = kcontrol->private_value; @@ -699,7 +702,8 @@ static int snd_saa7134_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ return 0; } -static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_saa7134_volume_put(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_value * ucontrol) { snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); int change, addr = kcontrol->private_value; @@ -730,7 +734,8 @@ static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ .get = snd_saa7134_capsrc_get, .put = snd_saa7134_capsrc_put, \ .private_value = addr } -static int snd_saa7134_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo) +static int snd_saa7134_capsrc_info(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_info * uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 2; @@ -739,7 +744,8 @@ static int snd_saa7134_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_ return 0; } -static int snd_saa7134_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_saa7134_capsrc_get(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_value * ucontrol) { snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); int addr = kcontrol->private_value; @@ -752,7 +758,8 @@ static int snd_saa7134_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ return 0; } -static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_saa7134_capsrc_put(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_value * ucontrol) { snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); int change, addr = kcontrol->private_value; @@ -829,7 +836,7 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ return change; } -static snd_kcontrol_new_t snd_saa7134_controls[] = { +static struct snd_kcontrol_new snd_saa7134_controls[] = { SAA713x_VOLUME("Video Volume", 0, MIXER_ADDR_TVTUNER), SAA713x_CAPSRC("Video Capture Switch", 0, MIXER_ADDR_TVTUNER), SAA713x_VOLUME("Line Volume", 1, MIXER_ADDR_LINE1), @@ -848,7 +855,7 @@ SAA713x_CAPSRC("Line Capture Switch", 2, MIXER_ADDR_LINE2), static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip) { - snd_card_t *card = chip->card; + struct snd_card *card = chip->card; unsigned int idx; int err; @@ -862,7 +869,7 @@ static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip) return 0; } -static void snd_saa7134_free(snd_card_t * card) +static void snd_saa7134_free(struct snd_card * card) { snd_card_saa7134_t *chip = card->private_data; @@ -889,7 +896,7 @@ static void snd_saa7134_free(snd_card_t * card) static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum) { - snd_card_t *card; + struct snd_card *card; snd_card_saa7134_t *chip; int err; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 3261d8bebdd1..6873d9a85ef1 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -386,7 +386,7 @@ struct saa7134_dmasound { unsigned int read_offset; unsigned int read_count; void * priv_data; - snd_pcm_substream_t *substream; + struct snd_pcm_substream *substream; }; /* IR input */ diff --git a/include/asm-arm/arch-pxa/audio.h b/include/asm-arm/arch-pxa/audio.h index 60976f830e3f..17eccd720136 100644 --- a/include/asm-arm/arch-pxa/audio.h +++ b/include/asm-arm/arch-pxa/audio.h @@ -6,8 +6,8 @@ #include typedef struct { - int (*startup)(snd_pcm_substream_t *, void *); - void (*shutdown)(snd_pcm_substream_t *, void *); + int (*startup)(struct snd_pcm_substream *, void *); + void (*shutdown)(struct snd_pcm_substream *, void *); void (*suspend)(void *); void (*resume)(void *); void *priv; -- cgit v1.2.3 From 1a60d4c5a0c4028559585a74e48593b16e1ca9b2 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 16 Jan 2006 16:29:08 +0100 Subject: [ALSA] semaphore -> mutex (core part) Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Takashi Iwai --- include/sound/core.h | 8 ++--- include/sound/hwdep.h | 2 +- include/sound/info.h | 2 +- include/sound/mixer_oss.h | 2 +- include/sound/pcm.h | 2 +- include/sound/pcm_oss.h | 2 +- include/sound/rawmidi.h | 4 +-- include/sound/seq_instr.h | 2 +- sound/core/hwdep.c | 43 +++++++++++------------ sound/core/info.c | 27 ++++++++------- sound/core/info_oss.c | 13 +++---- sound/core/init.c | 2 +- sound/core/memalloc.c | 22 ++++++------ sound/core/oss/mixer_oss.c | 14 ++++---- sound/core/oss/pcm_oss.c | 30 ++++++++-------- sound/core/pcm.c | 40 +++++++++++----------- sound/core/pcm_native.c | 12 +++---- sound/core/rawmidi.c | 57 ++++++++++++++++--------------- sound/core/seq/oss/seq_oss.c | 27 ++++++++------- sound/core/seq/seq_clientmgr.c | 40 +++++++++++----------- sound/core/seq/seq_clientmgr.h | 2 +- sound/core/seq/seq_device.c | 53 +++++++++++++++-------------- sound/core/seq/seq_instr.c | 6 ++-- sound/core/seq/seq_midi.c | 20 +++++------ sound/core/seq/seq_ports.c | 12 +++---- sound/core/seq/seq_queue.c | 6 ++-- sound/core/seq/seq_queue.h | 2 +- sound/core/sound.c | 23 +++++++------ sound/core/sound_oss.c | 23 +++++++------ sound/core/timer.c | 77 +++++++++++++++++++++--------------------- 30 files changed, 293 insertions(+), 282 deletions(-) (limited to 'include') diff --git a/include/sound/core.h b/include/sound/core.h index 3093e3ddcf36..144bdc2f217f 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -23,7 +23,7 @@ */ #include /* wake_up() */ -#include /* struct semaphore */ +#include /* struct mutex */ #include /* struct rw_semaphore */ #include /* struct workqueue_struct */ #include /* pm_message_t */ @@ -137,7 +137,7 @@ struct snd_card { #ifdef CONFIG_PM unsigned int power_state; /* power state */ - struct semaphore power_lock; /* power lock */ + struct mutex power_lock; /* power lock */ wait_queue_head_t power_sleep; #endif @@ -150,12 +150,12 @@ struct snd_card { #ifdef CONFIG_PM static inline void snd_power_lock(struct snd_card *card) { - down(&card->power_lock); + mutex_lock(&card->power_lock); } static inline void snd_power_unlock(struct snd_card *card) { - up(&card->power_lock); + mutex_unlock(&card->power_lock); } static inline unsigned int snd_power_get_state(struct snd_card *card) diff --git a/include/sound/hwdep.h b/include/sound/hwdep.h index c679e5b31111..94c387b5d724 100644 --- a/include/sound/hwdep.h +++ b/include/sound/hwdep.h @@ -60,7 +60,7 @@ struct snd_hwdep { void *private_data; void (*private_free) (struct snd_hwdep *hwdep); - struct semaphore open_mutex; + struct mutex open_mutex; int used; unsigned int dsp_loaded; unsigned int exclusive: 1; diff --git a/include/sound/info.h b/include/sound/info.h index 8ea5c7497c03..f23d8381c216 100644 --- a/include/sound/info.h +++ b/include/sound/info.h @@ -84,7 +84,7 @@ struct snd_info_entry { void *private_data; void (*private_free)(struct snd_info_entry *entry); struct proc_dir_entry *p; - struct semaphore access; + struct mutex access; }; #if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS) diff --git a/include/sound/mixer_oss.h b/include/sound/mixer_oss.h index ca5b4822b62c..197b9e3d612b 100644 --- a/include/sound/mixer_oss.h +++ b/include/sound/mixer_oss.h @@ -61,7 +61,7 @@ struct snd_mixer_oss { unsigned int active_index); void *private_data_recsrc; void (*private_free_recsrc)(struct snd_mixer_oss *mixer); - struct semaphore reg_mutex; + struct mutex reg_mutex; struct snd_info_entry *proc_entry; int oss_dev_alloc; /* --- */ diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 314268a11048..15b885660bf0 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -420,7 +420,7 @@ struct snd_pcm { char id[64]; char name[80]; struct snd_pcm_str streams[2]; - struct semaphore open_mutex; + struct mutex open_mutex; wait_queue_head_t open_wait; void *private_data; void (*private_free) (struct snd_pcm *pcm); diff --git a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h index d6ec886637db..bff0778e1969 100644 --- a/include/sound/pcm_oss.h +++ b/include/sound/pcm_oss.h @@ -75,7 +75,7 @@ struct snd_pcm_oss_substream { struct snd_pcm_oss_stream { struct snd_pcm_oss_setup *setup_list; /* setup list */ - struct semaphore setup_mutex; + struct mutex setup_mutex; struct snd_info_entry *proc_entry; }; diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h index d19bddfbf995..584e73dd4793 100644 --- a/include/sound/rawmidi.h +++ b/include/sound/rawmidi.h @@ -26,7 +26,7 @@ #include #include #include -#include +#include #if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) #include "seq_device.h" @@ -130,7 +130,7 @@ struct snd_rawmidi { void *private_data; void (*private_free) (struct snd_rawmidi *rmidi); - struct semaphore open_mutex; + struct mutex open_mutex; wait_queue_head_t open_wait; struct snd_info_entry *dev; diff --git a/include/sound/seq_instr.h b/include/sound/seq_instr.h index db764f09efb7..f2db03bfd74e 100644 --- a/include/sound/seq_instr.h +++ b/include/sound/seq_instr.h @@ -64,7 +64,7 @@ struct snd_seq_kinstr_list { spinlock_t lock; spinlock_t ops_lock; - struct semaphore ops_mutex; + struct mutex ops_mutex; unsigned long ops_flags; }; diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 618c43be0bc3..2524e66eccdd 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -36,7 +37,7 @@ MODULE_DESCRIPTION("Hardware dependent layer"); MODULE_LICENSE("GPL"); static LIST_HEAD(snd_hwdep_devices); -static DECLARE_MUTEX(register_mutex); +static DEFINE_MUTEX(register_mutex); static int snd_hwdep_free(struct snd_hwdep *hwdep); static int snd_hwdep_dev_free(struct snd_device *device); @@ -111,7 +112,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) init_waitqueue_entry(&wait, current); add_wait_queue(&hw->open_wait, &wait); - down(&hw->open_mutex); + mutex_lock(&hw->open_mutex); while (1) { if (hw->exclusive && hw->used > 0) { err = -EBUSY; @@ -128,9 +129,9 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) } else break; set_current_state(TASK_INTERRUPTIBLE); - up(&hw->open_mutex); + mutex_unlock(&hw->open_mutex); schedule(); - down(&hw->open_mutex); + mutex_lock(&hw->open_mutex); if (signal_pending(current)) { err = -ERESTARTSYS; break; @@ -147,7 +148,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) hw->ops.release(hw, file); } } - up(&hw->open_mutex); + mutex_unlock(&hw->open_mutex); if (err < 0) module_put(hw->card->module); return err; @@ -157,7 +158,7 @@ static int snd_hwdep_release(struct inode *inode, struct file * file) { int err = -ENXIO; struct snd_hwdep *hw = file->private_data; - down(&hw->open_mutex); + mutex_lock(&hw->open_mutex); if (hw->ops.release) { err = hw->ops.release(hw, file); wake_up(&hw->open_wait); @@ -165,7 +166,7 @@ static int snd_hwdep_release(struct inode *inode, struct file * file) if (hw->used > 0) hw->used--; snd_card_file_remove(hw->card, file); - up(&hw->open_mutex); + mutex_unlock(&hw->open_mutex); module_put(hw->card->module); return err; } @@ -272,7 +273,7 @@ static int snd_hwdep_control_ioctl(struct snd_card *card, if (get_user(device, (int __user *)arg)) return -EFAULT; - down(®ister_mutex); + mutex_lock(®ister_mutex); device = device < 0 ? 0 : device + 1; while (device < SNDRV_MINOR_HWDEPS) { if (snd_hwdep_search(card, device)) @@ -281,7 +282,7 @@ static int snd_hwdep_control_ioctl(struct snd_card *card, } if (device >= SNDRV_MINOR_HWDEPS) device = -1; - up(®ister_mutex); + mutex_unlock(®ister_mutex); if (put_user(device, (int __user *)arg)) return -EFAULT; return 0; @@ -294,13 +295,13 @@ static int snd_hwdep_control_ioctl(struct snd_card *card, if (get_user(device, &info->device)) return -EFAULT; - down(®ister_mutex); + mutex_lock(®ister_mutex); hwdep = snd_hwdep_search(card, device); if (hwdep) err = snd_hwdep_info(hwdep, info); else err = -ENXIO; - up(®ister_mutex); + mutex_unlock(®ister_mutex); return err; } } @@ -375,7 +376,7 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device, return err; } init_waitqueue_head(&hwdep->open_wait); - init_MUTEX(&hwdep->open_mutex); + mutex_init(&hwdep->open_mutex); *rhwdep = hwdep; return 0; } @@ -401,9 +402,9 @@ static int snd_hwdep_dev_register(struct snd_device *device) int err; char name[32]; - down(®ister_mutex); + mutex_lock(®ister_mutex); if (snd_hwdep_search(hwdep->card, hwdep->device)) { - up(®ister_mutex); + mutex_unlock(®ister_mutex); return -EBUSY; } list_add_tail(&hwdep->list, &snd_hwdep_devices); @@ -414,7 +415,7 @@ static int snd_hwdep_dev_register(struct snd_device *device) snd_printk(KERN_ERR "unable to register hardware dependent device %i:%i\n", hwdep->card->number, hwdep->device); list_del(&hwdep->list); - up(®ister_mutex); + mutex_unlock(®ister_mutex); return err; } #ifdef CONFIG_SND_OSSEMUL @@ -434,7 +435,7 @@ static int snd_hwdep_dev_register(struct snd_device *device) } } #endif - up(®ister_mutex); + mutex_unlock(®ister_mutex); return 0; } @@ -443,9 +444,9 @@ static int snd_hwdep_dev_unregister(struct snd_device *device) struct snd_hwdep *hwdep = device->device_data; snd_assert(hwdep != NULL, return -ENXIO); - down(®ister_mutex); + mutex_lock(®ister_mutex); if (snd_hwdep_search(hwdep->card, hwdep->device) != hwdep) { - up(®ister_mutex); + mutex_unlock(®ister_mutex); return -EINVAL; } #ifdef CONFIG_SND_OSSEMUL @@ -454,7 +455,7 @@ static int snd_hwdep_dev_unregister(struct snd_device *device) #endif snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); list_del(&hwdep->list); - up(®ister_mutex); + mutex_unlock(®ister_mutex); return snd_hwdep_free(hwdep); } @@ -469,13 +470,13 @@ static void snd_hwdep_proc_read(struct snd_info_entry *entry, struct list_head *p; struct snd_hwdep *hwdep; - down(®ister_mutex); + mutex_lock(®ister_mutex); list_for_each(p, &snd_hwdep_devices) { hwdep = list_entry(p, struct snd_hwdep, list); snd_iprintf(buffer, "%02i-%02i: %s\n", hwdep->card->number, hwdep->device, hwdep->name); } - up(®ister_mutex); + mutex_unlock(®ister_mutex); } static struct snd_info_entry *snd_hwdep_proc_entry; diff --git a/sound/core/info.c b/sound/core/info.c index af123e3bdb24..2582b74d3199 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -31,6 +31,7 @@ #include #include #include +#include #include /* @@ -68,7 +69,7 @@ int snd_info_check_reserved_words(const char *str) return 1; } -static DECLARE_MUTEX(info_mutex); +static DEFINE_MUTEX(info_mutex); struct snd_info_private_data { struct snd_info_buffer *rbuffer; @@ -265,11 +266,11 @@ static int snd_info_entry_open(struct inode *inode, struct file *file) struct proc_dir_entry *p; int mode, err; - down(&info_mutex); + mutex_lock(&info_mutex); p = PDE(inode); entry = p == NULL ? NULL : (struct snd_info_entry *)p->data; if (entry == NULL || entry->disconnected) { - up(&info_mutex); + mutex_unlock(&info_mutex); return -ENODEV; } if (!try_module_get(entry->module)) { @@ -361,13 +362,13 @@ static int snd_info_entry_open(struct inode *inode, struct file *file) break; } file->private_data = data; - up(&info_mutex); + mutex_unlock(&info_mutex); if (entry->content == SNDRV_INFO_CONTENT_TEXT && (mode == O_RDONLY || mode == O_RDWR)) { if (entry->c.text.read) { - down(&entry->access); + mutex_lock(&entry->access); entry->c.text.read(entry, data->rbuffer); - up(&entry->access); + mutex_unlock(&entry->access); } } return 0; @@ -375,7 +376,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file) __error: module_put(entry->module); __error1: - up(&info_mutex); + mutex_unlock(&info_mutex); return err; } @@ -747,7 +748,7 @@ static struct snd_info_entry *snd_info_create_entry(const char *name) } entry->mode = S_IFREG | S_IRUGO; entry->content = SNDRV_INFO_CONTENT_TEXT; - init_MUTEX(&entry->access); + mutex_init(&entry->access); return entry; } @@ -896,10 +897,10 @@ int snd_info_register(struct snd_info_entry * entry) snd_assert(entry != NULL, return -ENXIO); root = entry->parent == NULL ? snd_proc_root : entry->parent->p; - down(&info_mutex); + mutex_lock(&info_mutex); p = snd_create_proc_entry(entry->name, entry->mode, root); if (!p) { - up(&info_mutex); + mutex_unlock(&info_mutex); return -ENOMEM; } p->owner = entry->module; @@ -908,7 +909,7 @@ int snd_info_register(struct snd_info_entry * entry) p->size = entry->size; p->data = entry; entry->p = p; - up(&info_mutex); + mutex_unlock(&info_mutex); return 0; } @@ -929,9 +930,9 @@ int snd_info_unregister(struct snd_info_entry * entry) snd_assert(entry->p != NULL, return -ENXIO); root = entry->parent == NULL ? snd_proc_root : entry->parent->p; snd_assert(root, return -ENXIO); - down(&info_mutex); + mutex_lock(&info_mutex); snd_remove_proc_entry(root, entry->p); - up(&info_mutex); + mutex_unlock(&info_mutex); snd_info_free_entry(entry); return 0; } diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c index 820f4772e44a..f9ce854b3d11 100644 --- a/sound/core/info_oss.c +++ b/sound/core/info_oss.c @@ -28,6 +28,7 @@ #include #include #include +#include #if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS) @@ -35,7 +36,7 @@ * OSS compatible part */ -static DECLARE_MUTEX(strings); +static DEFINE_MUTEX(strings); static char *snd_sndstat_strings[SNDRV_CARDS][SNDRV_OSS_INFO_DEV_COUNT]; static struct snd_info_entry *snd_sndstat_proc_entry; @@ -45,7 +46,7 @@ int snd_oss_info_register(int dev, int num, char *string) snd_assert(dev >= 0 && dev < SNDRV_OSS_INFO_DEV_COUNT, return -ENXIO); snd_assert(num >= 0 && num < SNDRV_CARDS, return -ENXIO); - down(&strings); + mutex_lock(&strings); if (string == NULL) { if ((x = snd_sndstat_strings[num][dev]) != NULL) { kfree(x); @@ -54,12 +55,12 @@ int snd_oss_info_register(int dev, int num, char *string) } else { x = kstrdup(string, GFP_KERNEL); if (x == NULL) { - up(&strings); + mutex_unlock(&strings); return -ENOMEM; } } snd_sndstat_strings[num][dev] = x; - up(&strings); + mutex_unlock(&strings); return 0; } @@ -71,7 +72,7 @@ static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int d char *str; snd_iprintf(buf, "\n%s:", id); - down(&strings); + mutex_lock(&strings); for (idx = 0; idx < SNDRV_CARDS; idx++) { str = snd_sndstat_strings[idx][dev]; if (str) { @@ -82,7 +83,7 @@ static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int d snd_iprintf(buf, "%i: %s\n", idx, str); } } - up(&strings); + mutex_unlock(&strings); if (ok < 0) snd_iprintf(buf, " NOT ENABLED IN CONFIG\n"); return ok; diff --git a/sound/core/init.c b/sound/core/init.c index 75816688607c..17fbd6c14fb8 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -145,7 +145,7 @@ struct snd_card *snd_card_new(int idx, const char *xid, init_waitqueue_head(&card->shutdown_sleep); INIT_WORK(&card->free_workq, snd_card_free_thread, card); #ifdef CONFIG_PM - init_MUTEX(&card->power_lock); + mutex_init(&card->power_lock); init_waitqueue_head(&card->power_sleep); #endif /* the control interface cannot be accessed from the user space until */ diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index 19b3dcbb09c2..9f2b88cb5877 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #ifdef CONFIG_SBUS #include @@ -54,7 +54,7 @@ int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab); /* */ -static DECLARE_MUTEX(list_mutex); +static DEFINE_MUTEX(list_mutex); static LIST_HEAD(mem_list_head); /* buffer preservation list */ @@ -440,7 +440,7 @@ size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id) snd_assert(dmab, return 0); - down(&list_mutex); + mutex_lock(&list_mutex); list_for_each(p, &mem_list_head) { mem = list_entry(p, struct snd_mem_list, list); if (mem->id == id && @@ -452,11 +452,11 @@ size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id) if (dmab->dev.dev == NULL) dmab->dev.dev = dev; kfree(mem); - up(&list_mutex); + mutex_unlock(&list_mutex); return dmab->bytes; } } - up(&list_mutex); + mutex_unlock(&list_mutex); return 0; } @@ -477,11 +477,11 @@ int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id) mem = kmalloc(sizeof(*mem), GFP_KERNEL); if (! mem) return -ENOMEM; - down(&list_mutex); + mutex_lock(&list_mutex); mem->buffer = *dmab; mem->id = id; list_add_tail(&mem->list, &mem_list_head); - up(&list_mutex); + mutex_unlock(&list_mutex); return 0; } @@ -493,7 +493,7 @@ static void free_all_reserved_pages(void) struct list_head *p; struct snd_mem_list *mem; - down(&list_mutex); + mutex_lock(&list_mutex); while (! list_empty(&mem_list_head)) { p = mem_list_head.next; mem = list_entry(p, struct snd_mem_list, list); @@ -501,7 +501,7 @@ static void free_all_reserved_pages(void) snd_dma_free_pages(&mem->buffer); kfree(mem); } - up(&list_mutex); + mutex_unlock(&list_mutex); } @@ -522,7 +522,7 @@ static int snd_mem_proc_read(char *page, char **start, off_t off, int devno; static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG", "SBUS" }; - down(&list_mutex); + mutex_lock(&list_mutex); len += snprintf(page + len, count - len, "pages : %li bytes (%li pages per %likB)\n", pages * PAGE_SIZE, pages, PAGE_SIZE / 1024); @@ -537,7 +537,7 @@ static int snd_mem_proc_read(char *page, char **start, off_t off, " addr = 0x%lx, size = %d bytes\n", (unsigned long)mem->buffer.addr, (int)mem->buffer.bytes); } - up(&list_mutex); + mutex_unlock(&list_mutex); return len; } diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index f08e65a2bffe..9c68bc3f97aa 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -1095,7 +1095,7 @@ static void snd_mixer_oss_proc_read(struct snd_info_entry *entry, struct snd_mixer_oss *mixer = entry->private_data; int i; - down(&mixer->reg_mutex); + mutex_lock(&mixer->reg_mutex); for (i = 0; i < SNDRV_OSS_MAX_MIXERS; i++) { struct slot *p; @@ -1110,7 +1110,7 @@ static void snd_mixer_oss_proc_read(struct snd_info_entry *entry, else snd_iprintf(buffer, "\"\" 0\n"); } - up(&mixer->reg_mutex); + mutex_unlock(&mixer->reg_mutex); } static void snd_mixer_oss_proc_write(struct snd_info_entry *entry, @@ -1134,9 +1134,9 @@ static void snd_mixer_oss_proc_write(struct snd_info_entry *entry, cptr = snd_info_get_str(str, cptr, sizeof(str)); if (! *str) { /* remove the entry */ - down(&mixer->reg_mutex); + mutex_lock(&mixer->reg_mutex); mixer_slot_clear(&mixer->slots[ch]); - up(&mixer->reg_mutex); + mutex_unlock(&mixer->reg_mutex); continue; } snd_info_get_str(idxstr, cptr, sizeof(idxstr)); @@ -1145,7 +1145,7 @@ static void snd_mixer_oss_proc_write(struct snd_info_entry *entry, snd_printk(KERN_ERR "mixer_oss: invalid index %d\n", idx); continue; } - down(&mixer->reg_mutex); + mutex_lock(&mixer->reg_mutex); slot = (struct slot *)mixer->slots[ch].private_data; if (slot && slot->assigned && slot->assigned->index == idx && ! strcmp(slot->assigned->name, str)) @@ -1168,7 +1168,7 @@ static void snd_mixer_oss_proc_write(struct snd_info_entry *entry, kfree(tbl); } __unlock: - up(&mixer->reg_mutex); + mutex_unlock(&mixer->reg_mutex); } } @@ -1288,7 +1288,7 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd) mixer = kcalloc(2, sizeof(*mixer), GFP_KERNEL); if (mixer == NULL) return -ENOMEM; - init_MUTEX(&mixer->reg_mutex); + mutex_init(&mixer->reg_mutex); sprintf(name, "mixer%i%i", card->number, 0); if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, card, 0, diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index bc24d028f518..f8302b703a30 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1643,10 +1643,10 @@ static struct snd_pcm_oss_setup *snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, const char *ptr, *ptrl; struct snd_pcm_oss_setup *setup; - down(&pcm->streams[stream].oss.setup_mutex); + mutex_lock(&pcm->streams[stream].oss.setup_mutex); for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) { if (!strcmp(setup->task_name, task_name)) { - up(&pcm->streams[stream].oss.setup_mutex); + mutex_unlock(&pcm->streams[stream].oss.setup_mutex); return setup; } } @@ -1662,12 +1662,12 @@ static struct snd_pcm_oss_setup *snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, } for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) { if (!strcmp(setup->task_name, ptrl)) { - up(&pcm->streams[stream].oss.setup_mutex); + mutex_unlock(&pcm->streams[stream].oss.setup_mutex); return setup; } } __not_found: - up(&pcm->streams[stream].oss.setup_mutex); + mutex_unlock(&pcm->streams[stream].oss.setup_mutex); return NULL; } @@ -1895,7 +1895,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) init_waitqueue_entry(&wait, current); add_wait_queue(&pcm->open_wait, &wait); - down(&pcm->open_mutex); + mutex_lock(&pcm->open_mutex); while (1) { err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file, iminor(inode), psetup, csetup); @@ -1909,16 +1909,16 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) } else break; set_current_state(TASK_INTERRUPTIBLE); - up(&pcm->open_mutex); + mutex_unlock(&pcm->open_mutex); schedule(); - down(&pcm->open_mutex); + mutex_lock(&pcm->open_mutex); if (signal_pending(current)) { err = -ERESTARTSYS; break; } } remove_wait_queue(&pcm->open_wait, &wait); - up(&pcm->open_mutex); + mutex_unlock(&pcm->open_mutex); if (err < 0) goto __error; return err; @@ -1944,9 +1944,9 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file) snd_assert(substream != NULL, return -ENXIO); pcm = substream->pcm; snd_pcm_oss_sync(pcm_oss_file); - down(&pcm->open_mutex); + mutex_lock(&pcm->open_mutex); snd_pcm_oss_release_file(pcm_oss_file); - up(&pcm->open_mutex); + mutex_unlock(&pcm->open_mutex); wake_up(&pcm->open_wait); module_put(pcm->card->module); snd_card_file_remove(pcm->card, file); @@ -2293,7 +2293,7 @@ static void snd_pcm_oss_proc_read(struct snd_info_entry *entry, { struct snd_pcm_str *pstr = entry->private_data; struct snd_pcm_oss_setup *setup = pstr->oss.setup_list; - down(&pstr->oss.setup_mutex); + mutex_lock(&pstr->oss.setup_mutex); while (setup) { snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n", setup->task_name, @@ -2307,7 +2307,7 @@ static void snd_pcm_oss_proc_read(struct snd_info_entry *entry, setup->nosilence ? " no-silence" : ""); setup = setup->next; } - up(&pstr->oss.setup_mutex); + mutex_unlock(&pstr->oss.setup_mutex); } static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr) @@ -2337,12 +2337,12 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry, struct snd_pcm_oss_setup *setup, *setup1, template; while (!snd_info_get_line(buffer, line, sizeof(line))) { - down(&pstr->oss.setup_mutex); + mutex_lock(&pstr->oss.setup_mutex); memset(&template, 0, sizeof(template)); ptr = snd_info_get_str(task_name, line, sizeof(task_name)); if (!strcmp(task_name, "clear") || !strcmp(task_name, "erase")) { snd_pcm_oss_proc_free_setup_list(pstr); - up(&pstr->oss.setup_mutex); + mutex_unlock(&pstr->oss.setup_mutex); continue; } for (setup = pstr->oss.setup_list; setup; setup = setup->next) { @@ -2394,7 +2394,7 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry, } if (setup) *setup = template; - up(&pstr->oss.setup_mutex); + mutex_unlock(&pstr->oss.setup_mutex); } } diff --git a/sound/core/pcm.c b/sound/core/pcm.c index d92c3ce4a4c9..f903d1bd74d5 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -35,7 +36,7 @@ MODULE_LICENSE("GPL"); static LIST_HEAD(snd_pcm_devices); static LIST_HEAD(snd_pcm_notify_list); -static DECLARE_MUTEX(register_mutex); +static DEFINE_MUTEX(register_mutex); static int snd_pcm_free(struct snd_pcm *pcm); static int snd_pcm_dev_free(struct snd_device *device); @@ -67,7 +68,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, if (get_user(device, (int __user *)arg)) return -EFAULT; - down(®ister_mutex); + mutex_lock(®ister_mutex); device = device < 0 ? 0 : device + 1; while (device < SNDRV_PCM_DEVICES) { if (snd_pcm_search(card, device)) @@ -76,7 +77,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, } if (device == SNDRV_PCM_DEVICES) device = -1; - up(®ister_mutex); + mutex_unlock(®ister_mutex); if (put_user(device, (int __user *)arg)) return -EFAULT; return 0; @@ -100,7 +101,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, return -EINVAL; if (get_user(subdevice, &info->subdevice)) return -EFAULT; - down(®ister_mutex); + mutex_lock(®ister_mutex); pcm = snd_pcm_search(card, device); if (pcm == NULL) { err = -ENXIO; @@ -125,7 +126,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, } err = snd_pcm_info_user(substream, info); _error: - up(®ister_mutex); + mutex_unlock(®ister_mutex); return err; } case SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE: @@ -262,6 +263,7 @@ static const char *snd_pcm_state_name(snd_pcm_state_t state) #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) #include + static const char *snd_pcm_oss_format_name(int format) { switch (format) { @@ -624,7 +626,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) struct snd_pcm_substream *substream, *prev; #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) - init_MUTEX(&pstr->oss.setup_mutex); + mutex_init(&pstr->oss.setup_mutex); #endif pstr->stream = stream; pstr->pcm = pcm; @@ -718,7 +720,7 @@ int snd_pcm_new(struct snd_card *card, char *id, int device, snd_pcm_free(pcm); return err; } - init_MUTEX(&pcm->open_mutex); + mutex_init(&pcm->open_mutex); init_waitqueue_head(&pcm->open_wait); if ((err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)) < 0) { snd_pcm_free(pcm); @@ -904,9 +906,9 @@ static int snd_pcm_dev_register(struct snd_device *device) struct snd_pcm *pcm = device->device_data; snd_assert(pcm != NULL && device != NULL, return -ENXIO); - down(®ister_mutex); + mutex_lock(®ister_mutex); if (snd_pcm_search(pcm->card, pcm->device)) { - up(®ister_mutex); + mutex_unlock(®ister_mutex); return -EBUSY; } list_add_tail(&pcm->list, &snd_pcm_devices); @@ -930,7 +932,7 @@ static int snd_pcm_dev_register(struct snd_device *device) pcm, str)) < 0) { list_del(&pcm->list); - up(®ister_mutex); + mutex_unlock(®ister_mutex); return err; } for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) @@ -941,7 +943,7 @@ static int snd_pcm_dev_register(struct snd_device *device) notify = list_entry(list, struct snd_pcm_notify, list); notify->n_register(pcm); } - up(®ister_mutex); + mutex_unlock(®ister_mutex); return 0; } @@ -952,7 +954,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) struct snd_pcm_substream *substream; int cidx; - down(®ister_mutex); + mutex_lock(®ister_mutex); list_del_init(&pcm->list); for (cidx = 0; cidx < 2; cidx++) for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) @@ -963,7 +965,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) notify = list_entry(list, struct snd_pcm_notify, list); notify->n_disconnect(pcm); } - up(®ister_mutex); + mutex_unlock(®ister_mutex); return 0; } @@ -975,7 +977,7 @@ static int snd_pcm_dev_unregister(struct snd_device *device) struct snd_pcm *pcm = device->device_data; snd_assert(pcm != NULL, return -ENXIO); - down(®ister_mutex); + mutex_lock(®ister_mutex); list_del(&pcm->list); for (cidx = 0; cidx < 2; cidx++) { devtype = -1; @@ -996,7 +998,7 @@ static int snd_pcm_dev_unregister(struct snd_device *device) notify = list_entry(list, struct snd_pcm_notify, list); notify->n_unregister(pcm); } - up(®ister_mutex); + mutex_unlock(®ister_mutex); return snd_pcm_free(pcm); } @@ -1005,7 +1007,7 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) struct list_head *p; snd_assert(notify != NULL && notify->n_register != NULL && notify->n_unregister != NULL, return -EINVAL); - down(®ister_mutex); + mutex_lock(®ister_mutex); if (nfree) { list_del(¬ify->list); list_for_each(p, &snd_pcm_devices) @@ -1016,7 +1018,7 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) list_for_each(p, &snd_pcm_devices) notify->n_register(list_entry(p, struct snd_pcm, list)); } - up(®ister_mutex); + mutex_unlock(®ister_mutex); return 0; } @@ -1031,7 +1033,7 @@ static void snd_pcm_proc_read(struct snd_info_entry *entry, struct list_head *p; struct snd_pcm *pcm; - down(®ister_mutex); + mutex_lock(®ister_mutex); list_for_each(p, &snd_pcm_devices) { pcm = list_entry(p, struct snd_pcm, list); snd_iprintf(buffer, "%02i-%02i: %s : %s", @@ -1044,7 +1046,7 @@ static void snd_pcm_proc_read(struct snd_info_entry *entry, pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count); snd_iprintf(buffer, "\n"); } - up(®ister_mutex); + mutex_unlock(®ister_mutex); } static struct snd_info_entry *snd_pcm_proc_entry = NULL; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index f3d5de7b55ac..ce1956a5528d 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2112,7 +2112,7 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) } init_waitqueue_entry(&wait, current); add_wait_queue(&pcm->open_wait, &wait); - down(&pcm->open_mutex); + mutex_lock(&pcm->open_mutex); while (1) { err = snd_pcm_open_file(file, pcm, stream, &pcm_file); if (err >= 0) @@ -2125,16 +2125,16 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) } else break; set_current_state(TASK_INTERRUPTIBLE); - up(&pcm->open_mutex); + mutex_unlock(&pcm->open_mutex); schedule(); - down(&pcm->open_mutex); + mutex_lock(&pcm->open_mutex); if (signal_pending(current)) { err = -ERESTARTSYS; break; } } remove_wait_queue(&pcm->open_wait, &wait); - up(&pcm->open_mutex); + mutex_unlock(&pcm->open_mutex); if (err < 0) goto __error; return err; @@ -2160,9 +2160,9 @@ static int snd_pcm_release(struct inode *inode, struct file *file) pcm = substream->pcm; snd_pcm_drop(substream); fasync_helper(-1, file, 0, &substream->runtime->fasync); - down(&pcm->open_mutex); + mutex_lock(&pcm->open_mutex); snd_pcm_release_file(pcm_file); - up(&pcm->open_mutex); + mutex_unlock(&pcm->open_mutex); wake_up(&pcm->open_wait); module_put(pcm->card->module); snd_card_file_remove(pcm->card, file); diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index d4d124e21924..6b7a36774298 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -57,7 +58,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device); static int snd_rawmidi_dev_unregister(struct snd_device *device); static LIST_HEAD(snd_rawmidi_devices); -static DECLARE_MUTEX(register_mutex); +static DEFINE_MUTEX(register_mutex); static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device) { @@ -237,9 +238,9 @@ int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, if (rfile) rfile->input = rfile->output = NULL; - down(®ister_mutex); + mutex_lock(®ister_mutex); rmidi = snd_rawmidi_search(card, device); - up(®ister_mutex); + mutex_unlock(®ister_mutex); if (rmidi == NULL) { err = -ENODEV; goto __error1; @@ -249,7 +250,7 @@ int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, goto __error1; } if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK)) - down(&rmidi->open_mutex); + mutex_lock(&rmidi->open_mutex); if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { if (!(rmidi->info_flags & SNDRV_RAWMIDI_INFO_INPUT)) { err = -ENXIO; @@ -359,7 +360,7 @@ int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, soutput = NULL; } if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK)) - up(&rmidi->open_mutex); + mutex_unlock(&rmidi->open_mutex); if (rfile) { rfile->rmidi = rmidi; rfile->input = sinput; @@ -374,7 +375,7 @@ int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, snd_rawmidi_runtime_free(soutput); module_put(rmidi->card->module); if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK)) - up(&rmidi->open_mutex); + mutex_unlock(&rmidi->open_mutex); __error1: return err; } @@ -422,7 +423,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) } init_waitqueue_entry(&wait, current); add_wait_queue(&rmidi->open_wait, &wait); - down(&rmidi->open_mutex); + mutex_lock(&rmidi->open_mutex); while (1) { subdevice = -1; down_read(&card->controls_rwsem); @@ -446,9 +447,9 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) } else break; set_current_state(TASK_INTERRUPTIBLE); - up(&rmidi->open_mutex); + mutex_unlock(&rmidi->open_mutex); schedule(); - down(&rmidi->open_mutex); + mutex_lock(&rmidi->open_mutex); if (signal_pending(current)) { err = -ERESTARTSYS; break; @@ -467,7 +468,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) snd_card_file_remove(card, file); kfree(rawmidi_file); } - up(&rmidi->open_mutex); + mutex_unlock(&rmidi->open_mutex); return err; } @@ -480,7 +481,7 @@ int snd_rawmidi_kernel_release(struct snd_rawmidi_file * rfile) snd_assert(rfile != NULL, return -ENXIO); snd_assert(rfile->input != NULL || rfile->output != NULL, return -ENXIO); rmidi = rfile->rmidi; - down(&rmidi->open_mutex); + mutex_lock(&rmidi->open_mutex); if (rfile->input != NULL) { substream = rfile->input; rfile->input = NULL; @@ -514,7 +515,7 @@ int snd_rawmidi_kernel_release(struct snd_rawmidi_file * rfile) } rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened--; } - up(&rmidi->open_mutex); + mutex_unlock(&rmidi->open_mutex); module_put(rmidi->card->module); return 0; } @@ -576,9 +577,9 @@ int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info struct snd_rawmidi_substream *substream; struct list_head *list; - down(®ister_mutex); + mutex_lock(®ister_mutex); rmidi = snd_rawmidi_search(card, info->device); - up(®ister_mutex); + mutex_unlock(®ister_mutex); if (!rmidi) return -ENXIO; if (info->stream < 0 || info->stream > 1) @@ -818,7 +819,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card, if (get_user(device, (int __user *)argp)) return -EFAULT; - down(®ister_mutex); + mutex_lock(®ister_mutex); device = device < 0 ? 0 : device + 1; while (device < SNDRV_RAWMIDI_DEVICES) { if (snd_rawmidi_search(card, device)) @@ -827,7 +828,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card, } if (device == SNDRV_RAWMIDI_DEVICES) device = -1; - up(®ister_mutex); + mutex_unlock(®ister_mutex); if (put_user(device, (int __user *)argp)) return -EFAULT; return 0; @@ -1314,7 +1315,7 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry, rmidi = entry->private_data; snd_iprintf(buffer, "%s\n\n", rmidi->name); - down(&rmidi->open_mutex); + mutex_lock(&rmidi->open_mutex); if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT) { list_for_each(list, &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) { substream = list_entry(list, struct snd_rawmidi_substream, list); @@ -1355,7 +1356,7 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry, } } } - up(&rmidi->open_mutex); + mutex_unlock(&rmidi->open_mutex); } /* @@ -1436,7 +1437,7 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device, } rmidi->card = card; rmidi->device = device; - init_MUTEX(&rmidi->open_mutex); + mutex_init(&rmidi->open_mutex); init_waitqueue_head(&rmidi->open_wait); if (id != NULL) strlcpy(rmidi->id, id, sizeof(rmidi->id)); @@ -1507,9 +1508,9 @@ static int snd_rawmidi_dev_register(struct snd_device *device) if (rmidi->device >= SNDRV_RAWMIDI_DEVICES) return -ENOMEM; - down(®ister_mutex); + mutex_lock(®ister_mutex); if (snd_rawmidi_search(rmidi->card, rmidi->device)) { - up(®ister_mutex); + mutex_unlock(®ister_mutex); return -EBUSY; } list_add_tail(&rmidi->list, &snd_rawmidi_devices); @@ -1519,14 +1520,14 @@ static int snd_rawmidi_dev_register(struct snd_device *device) &snd_rawmidi_f_ops, rmidi, name)) < 0) { snd_printk(KERN_ERR "unable to register rawmidi device %i:%i\n", rmidi->card->number, rmidi->device); list_del(&rmidi->list); - up(®ister_mutex); + mutex_unlock(®ister_mutex); return err; } if (rmidi->ops && rmidi->ops->dev_register && (err = rmidi->ops->dev_register(rmidi)) < 0) { snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); list_del(&rmidi->list); - up(®ister_mutex); + mutex_unlock(®ister_mutex); return err; } #ifdef CONFIG_SND_OSSEMUL @@ -1553,7 +1554,7 @@ static int snd_rawmidi_dev_register(struct snd_device *device) } } #endif /* CONFIG_SND_OSSEMUL */ - up(®ister_mutex); + mutex_unlock(®ister_mutex); sprintf(name, "midi%d", rmidi->device); entry = snd_info_create_card_entry(rmidi->card, name, rmidi->card->proc_root); if (entry) { @@ -1583,9 +1584,9 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device) { struct snd_rawmidi *rmidi = device->device_data; - down(®ister_mutex); + mutex_lock(®ister_mutex); list_del_init(&rmidi->list); - up(®ister_mutex); + mutex_unlock(®ister_mutex); return 0; } @@ -1594,7 +1595,7 @@ static int snd_rawmidi_dev_unregister(struct snd_device *device) struct snd_rawmidi *rmidi = device->device_data; snd_assert(rmidi != NULL, return -ENXIO); - down(®ister_mutex); + mutex_lock(®ister_mutex); list_del(&rmidi->list); if (rmidi->proc_entry) { snd_info_unregister(rmidi->proc_entry); @@ -1616,7 +1617,7 @@ static int snd_rawmidi_dev_unregister(struct snd_device *device) if (rmidi->ops && rmidi->ops->dev_unregister) rmidi->ops->dev_unregister(rmidi); snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); - up(®ister_mutex); + mutex_unlock(®ister_mutex); #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) if (rmidi->seq_dev) { snd_device_free(rmidi->card, rmidi->seq_dev); diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c index c98f0ba13810..b9919785180b 100644 --- a/sound/core/seq/oss/seq_oss.c +++ b/sound/core/seq/oss/seq_oss.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -124,7 +125,7 @@ module_exit(alsa_seq_oss_exit) * ALSA minor device interface */ -static DECLARE_MUTEX(register_mutex); +static DEFINE_MUTEX(register_mutex); static int odev_open(struct inode *inode, struct file *file) @@ -136,9 +137,9 @@ odev_open(struct inode *inode, struct file *file) else level = SNDRV_SEQ_OSS_MODE_SYNTH; - down(®ister_mutex); + mutex_lock(®ister_mutex); rc = snd_seq_oss_open(file, level); - up(®ister_mutex); + mutex_unlock(®ister_mutex); return rc; } @@ -153,9 +154,9 @@ odev_release(struct inode *inode, struct file *file) snd_seq_oss_drain_write(dp); - down(®ister_mutex); + mutex_lock(®ister_mutex); snd_seq_oss_release(dp); - up(®ister_mutex); + mutex_unlock(®ister_mutex); return 0; } @@ -224,13 +225,13 @@ register_device(void) { int rc; - down(®ister_mutex); + mutex_lock(®ister_mutex); if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0, &seq_oss_f_ops, NULL, SNDRV_SEQ_OSS_DEVNAME)) < 0) { snd_printk(KERN_ERR "can't register device seq\n"); - up(®ister_mutex); + mutex_unlock(®ister_mutex); return rc; } if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, @@ -239,24 +240,24 @@ register_device(void) SNDRV_SEQ_OSS_DEVNAME)) < 0) { snd_printk(KERN_ERR "can't register device music\n"); snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0); - up(®ister_mutex); + mutex_unlock(®ister_mutex); return rc; } debug_printk(("device registered\n")); - up(®ister_mutex); + mutex_unlock(®ister_mutex); return 0; } static void unregister_device(void) { - down(®ister_mutex); + mutex_lock(®ister_mutex); debug_printk(("device unregistered\n")); if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, NULL, 0) < 0) snd_printk(KERN_ERR "error unregister device music\n"); if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0) < 0) snd_printk(KERN_ERR "error unregister device seq\n"); - up(®ister_mutex); + mutex_unlock(®ister_mutex); } /* @@ -270,12 +271,12 @@ static struct snd_info_entry *info_entry; static void info_read(struct snd_info_entry *entry, struct snd_info_buffer *buf) { - down(®ister_mutex); + mutex_lock(®ister_mutex); snd_iprintf(buf, "OSS sequencer emulation version %s\n", SNDRV_SEQ_OSS_VERSION_STR); snd_seq_oss_system_info_read(buf); snd_seq_oss_synth_info_read(buf); snd_seq_oss_midi_info_read(buf); - up(®ister_mutex); + mutex_unlock(®ister_mutex); } diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index fd2032eae214..aae6420f5948 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -67,7 +67,7 @@ #define SNDRV_SEQ_LFLG_OPEN (SNDRV_SEQ_LFLG_INPUT|SNDRV_SEQ_LFLG_OUTPUT) static DEFINE_SPINLOCK(clients_lock); -static DECLARE_MUTEX(register_mutex); +static DEFINE_MUTEX(register_mutex); /* * client table @@ -237,7 +237,7 @@ static struct snd_seq_client *seq_create_client1(int client_index, int poolsize) client->type = NO_CLIENT; snd_use_lock_init(&client->use_lock); rwlock_init(&client->ports_lock); - init_MUTEX(&client->ports_mutex); + mutex_init(&client->ports_mutex); INIT_LIST_HEAD(&client->ports_list_head); /* find free slot in the client table */ @@ -290,7 +290,7 @@ static int seq_free_client1(struct snd_seq_client *client) static void seq_free_client(struct snd_seq_client * client) { - down(®ister_mutex); + mutex_lock(®ister_mutex); switch (client->type) { case NO_CLIENT: snd_printk(KERN_WARNING "Seq: Trying to free unused client %d\n", @@ -306,7 +306,7 @@ static void seq_free_client(struct snd_seq_client * client) snd_printk(KERN_ERR "Seq: Trying to free client %d with undefined type = %d\n", client->number, client->type); } - up(®ister_mutex); + mutex_unlock(®ister_mutex); snd_seq_system_client_ev_client_exit(client->number); } @@ -322,11 +322,11 @@ static int snd_seq_open(struct inode *inode, struct file *file) struct snd_seq_client *client; struct snd_seq_user_client *user; - if (down_interruptible(®ister_mutex)) + if (mutex_lock_interruptible(®ister_mutex)) return -ERESTARTSYS; client = seq_create_client1(-1, SNDRV_SEQ_DEFAULT_EVENTS); if (client == NULL) { - up(®ister_mutex); + mutex_unlock(®ister_mutex); return -ENOMEM; /* failure code */ } @@ -346,14 +346,14 @@ static int snd_seq_open(struct inode *inode, struct file *file) if (user->fifo == NULL) { seq_free_client1(client); kfree(client); - up(®ister_mutex); + mutex_unlock(®ister_mutex); return -ENOMEM; } } usage_alloc(&client_usage, 1); client->type = USER_CLIENT; - up(®ister_mutex); + mutex_unlock(®ister_mutex); c = client->number; file->private_data = client; @@ -1743,7 +1743,7 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client, if (queue == NULL) return -EINVAL; - if (down_interruptible(&queue->timer_mutex)) { + if (mutex_lock_interruptible(&queue->timer_mutex)) { queuefree(queue); return -ERESTARTSYS; } @@ -1756,7 +1756,7 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client, timer.u.alsa.id = tmr->alsa_id; timer.u.alsa.resolution = tmr->preferred_resolution; } - up(&queue->timer_mutex); + mutex_unlock(&queue->timer_mutex); queuefree(queue); if (copy_to_user(arg, &timer, sizeof(timer))) @@ -1785,7 +1785,7 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, q = queueptr(timer.queue); if (q == NULL) return -ENXIO; - if (down_interruptible(&q->timer_mutex)) { + if (mutex_lock_interruptible(&q->timer_mutex)) { queuefree(q); return -ERESTARTSYS; } @@ -1797,7 +1797,7 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, tmr->preferred_resolution = timer.u.alsa.resolution; } result = snd_seq_queue_timer_open(timer.queue); - up(&q->timer_mutex); + mutex_unlock(&q->timer_mutex); queuefree(q); } else { return -EPERM; @@ -2230,7 +2230,7 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index, if (card == NULL && client_index >= SNDRV_SEQ_GLOBAL_CLIENTS) return -EINVAL; - if (down_interruptible(®ister_mutex)) + if (mutex_lock_interruptible(®ister_mutex)) return -ERESTARTSYS; if (card) { @@ -2243,7 +2243,7 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index, /* empty write queue as default */ client = seq_create_client1(client_index, 0); if (client == NULL) { - up(®ister_mutex); + mutex_unlock(®ister_mutex); return -EBUSY; /* failure code */ } usage_alloc(&client_usage, 1); @@ -2256,7 +2256,7 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index, va_end(args); client->type = KERNEL_CLIENT; - up(®ister_mutex); + mutex_unlock(®ister_mutex); /* make others aware this new client */ snd_seq_system_client_ev_client_start(client->number); @@ -2464,7 +2464,7 @@ static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer, { struct list_head *l; - down(&client->ports_mutex); + mutex_lock(&client->ports_mutex); list_for_each(l, &client->ports_list_head) { struct snd_seq_client_port *p = list_entry(l, struct snd_seq_client_port, list); snd_iprintf(buffer, " Port %3d : \"%s\" (%c%c%c%c)\n", @@ -2476,7 +2476,7 @@ static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer, snd_seq_info_dump_subscribers(buffer, &p->c_src, 1, " Connecting To: "); snd_seq_info_dump_subscribers(buffer, &p->c_dest, 0, " Connected From: "); } - up(&client->ports_mutex); + mutex_unlock(&client->ports_mutex); } @@ -2550,16 +2550,16 @@ int __init snd_sequencer_device_init(void) { int err; - if (down_interruptible(®ister_mutex)) + if (mutex_lock_interruptible(®ister_mutex)) return -ERESTARTSYS; if ((err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0, &snd_seq_f_ops, NULL, "seq")) < 0) { - up(®ister_mutex); + mutex_unlock(®ister_mutex); return err; } - up(®ister_mutex); + mutex_unlock(®ister_mutex); return 0; } diff --git a/sound/core/seq/seq_clientmgr.h b/sound/core/seq/seq_clientmgr.h index 450091ca153d..5e04e20e239f 100644 --- a/sound/core/seq/seq_clientmgr.h +++ b/sound/core/seq/seq_clientmgr.h @@ -58,7 +58,7 @@ struct snd_seq_client { int num_ports; /* number of ports */ struct list_head ports_list_head; rwlock_t ports_lock; - struct semaphore ports_mutex; + struct mutex ports_mutex; int convert32; /* convert 32->64bit */ /* output pool */ diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c index 9ece443fba55..d9a3e5a18d6a 100644 --- a/sound/core/seq/seq_device.c +++ b/sound/core/seq/seq_device.c @@ -45,6 +45,7 @@ #include #include #include +#include MODULE_AUTHOR("Takashi Iwai "); MODULE_DESCRIPTION("ALSA sequencer device management"); @@ -69,7 +70,7 @@ struct ops_list { struct list_head dev_list; /* list of devices */ int num_devices; /* number of associated devices */ int num_init_devices; /* number of initialized devices */ - struct semaphore reg_mutex; + struct mutex reg_mutex; struct list_head list; /* next driver */ }; @@ -77,7 +78,7 @@ struct ops_list { static LIST_HEAD(opslist); static int num_ops; -static DECLARE_MUTEX(ops_mutex); +static DEFINE_MUTEX(ops_mutex); #ifdef CONFIG_PROC_FS static struct snd_info_entry *info_entry = NULL; #endif @@ -108,7 +109,7 @@ static void snd_seq_device_info(struct snd_info_entry *entry, { struct list_head *head; - down(&ops_mutex); + mutex_lock(&ops_mutex); list_for_each(head, &opslist) { struct ops_list *ops = list_entry(head, struct ops_list, list); snd_iprintf(buffer, "snd-%s%s%s%s,%d\n", @@ -118,7 +119,7 @@ static void snd_seq_device_info(struct snd_info_entry *entry, ops->driver & DRIVER_LOCKED ? ",locked" : "", ops->num_devices); } - up(&ops_mutex); + mutex_unlock(&ops_mutex); } #endif @@ -154,20 +155,20 @@ void snd_seq_device_load_drivers(void) if (! current->fs->root) return; - down(&ops_mutex); + mutex_lock(&ops_mutex); list_for_each(head, &opslist) { struct ops_list *ops = list_entry(head, struct ops_list, list); if (! (ops->driver & DRIVER_LOADED) && ! (ops->driver & DRIVER_REQUESTED)) { ops->used++; - up(&ops_mutex); + mutex_unlock(&ops_mutex); ops->driver |= DRIVER_REQUESTED; request_module("snd-%s", ops->id); - down(&ops_mutex); + mutex_lock(&ops_mutex); ops->used--; } } - up(&ops_mutex); + mutex_unlock(&ops_mutex); #endif } @@ -214,10 +215,10 @@ int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize, dev->status = SNDRV_SEQ_DEVICE_FREE; /* add this device to the list */ - down(&ops->reg_mutex); + mutex_lock(&ops->reg_mutex); list_add_tail(&dev->list, &ops->dev_list); ops->num_devices++; - up(&ops->reg_mutex); + mutex_unlock(&ops->reg_mutex); unlock_driver(ops); @@ -246,10 +247,10 @@ static int snd_seq_device_free(struct snd_seq_device *dev) return -ENXIO; /* remove the device from the list */ - down(&ops->reg_mutex); + mutex_lock(&ops->reg_mutex); list_del(&dev->list); ops->num_devices--; - up(&ops->reg_mutex); + mutex_unlock(&ops->reg_mutex); free_device(dev, ops); if (dev->private_free) @@ -344,7 +345,7 @@ int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry, return -EBUSY; } - down(&ops->reg_mutex); + mutex_lock(&ops->reg_mutex); /* copy driver operators */ ops->ops = *entry; ops->driver |= DRIVER_LOADED; @@ -355,7 +356,7 @@ int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry, struct snd_seq_device *dev = list_entry(head, struct snd_seq_device, list); init_device(dev, ops); } - up(&ops->reg_mutex); + mutex_unlock(&ops->reg_mutex); unlock_driver(ops); snd_seq_autoload_unlock(); @@ -378,17 +379,17 @@ static struct ops_list * create_driver(char *id) /* set up driver entry */ strlcpy(ops->id, id, sizeof(ops->id)); - init_MUTEX(&ops->reg_mutex); + mutex_init(&ops->reg_mutex); ops->driver = DRIVER_EMPTY; INIT_LIST_HEAD(&ops->dev_list); /* lock this instance */ ops->used = 1; /* register driver entry */ - down(&ops_mutex); + mutex_lock(&ops_mutex); list_add_tail(&ops->list, &opslist); num_ops++; - up(&ops_mutex); + mutex_unlock(&ops_mutex); return ops; } @@ -414,7 +415,7 @@ int snd_seq_device_unregister_driver(char *id) } /* close and release all devices associated with this driver */ - down(&ops->reg_mutex); + mutex_lock(&ops->reg_mutex); ops->driver |= DRIVER_LOCKED; /* do not remove this driver recursively */ list_for_each(head, &ops->dev_list) { struct snd_seq_device *dev = list_entry(head, struct snd_seq_device, list); @@ -425,7 +426,7 @@ int snd_seq_device_unregister_driver(char *id) if (ops->num_init_devices > 0) snd_printk(KERN_ERR "free_driver: init_devices > 0!! (%d)\n", ops->num_init_devices); - up(&ops->reg_mutex); + mutex_unlock(&ops->reg_mutex); unlock_driver(ops); @@ -443,7 +444,7 @@ static void remove_drivers(void) { struct list_head *head; - down(&ops_mutex); + mutex_lock(&ops_mutex); head = opslist.next; while (head != &opslist) { struct ops_list *ops = list_entry(head, struct ops_list, list); @@ -456,7 +457,7 @@ static void remove_drivers(void) } else head = head->next; } - up(&ops_mutex); + mutex_unlock(&ops_mutex); } /* @@ -519,16 +520,16 @@ static struct ops_list * find_driver(char *id, int create_if_empty) { struct list_head *head; - down(&ops_mutex); + mutex_lock(&ops_mutex); list_for_each(head, &opslist) { struct ops_list *ops = list_entry(head, struct ops_list, list); if (strcmp(ops->id, id) == 0) { ops->used++; - up(&ops_mutex); + mutex_unlock(&ops_mutex); return ops; } } - up(&ops_mutex); + mutex_unlock(&ops_mutex); if (create_if_empty) return create_driver(id); return NULL; @@ -536,9 +537,9 @@ static struct ops_list * find_driver(char *id, int create_if_empty) static void unlock_driver(struct ops_list *ops) { - down(&ops_mutex); + mutex_lock(&ops_mutex); ops->used--; - up(&ops_mutex); + mutex_unlock(&ops_mutex); } diff --git a/sound/core/seq/seq_instr.c b/sound/core/seq/seq_instr.c index 487452063965..f30d171b6d96 100644 --- a/sound/core/seq/seq_instr.c +++ b/sound/core/seq/seq_instr.c @@ -36,7 +36,7 @@ static void snd_instr_lock_ops(struct snd_seq_kinstr_list *list) if (!(list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT)) { spin_lock_irqsave(&list->ops_lock, list->ops_flags); } else { - down(&list->ops_mutex); + mutex_lock(&list->ops_mutex); } } @@ -45,7 +45,7 @@ static void snd_instr_unlock_ops(struct snd_seq_kinstr_list *list) if (!(list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT)) { spin_unlock_irqrestore(&list->ops_lock, list->ops_flags); } else { - up(&list->ops_mutex); + mutex_unlock(&list->ops_mutex); } } @@ -82,7 +82,7 @@ struct snd_seq_kinstr_list *snd_seq_instr_list_new(void) return NULL; spin_lock_init(&list->lock); spin_lock_init(&list->ops_lock); - init_MUTEX(&list->ops_mutex); + mutex_init(&list->ops_mutex); list->owner = -1; return list; } diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index ce0df86157de..9caa1372bece 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c @@ -32,7 +32,7 @@ Possible options for midisynth module: #include #include #include -#include +#include #include #include #include @@ -70,7 +70,7 @@ struct seq_midisynth_client { }; static struct seq_midisynth_client *synths[SNDRV_CARDS]; -static DECLARE_MUTEX(register_mutex); +static DEFINE_MUTEX(register_mutex); /* handle rawmidi input event (MIDI v1.0 stream) */ static void snd_midi_input_event(struct snd_rawmidi_substream *substream) @@ -308,13 +308,13 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev) if (ports > (256 / SNDRV_RAWMIDI_DEVICES)) ports = 256 / SNDRV_RAWMIDI_DEVICES; - down(®ister_mutex); + mutex_lock(®ister_mutex); client = synths[card->number]; if (client == NULL) { newclient = 1; client = kzalloc(sizeof(*client), GFP_KERNEL); if (client == NULL) { - up(®ister_mutex); + mutex_unlock(®ister_mutex); kfree(info); return -ENOMEM; } @@ -324,7 +324,7 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev) (const char *)info->name : "External MIDI"); if (client->seq_client < 0) { kfree(client); - up(®ister_mutex); + mutex_unlock(®ister_mutex); kfree(info); return -ENOMEM; } @@ -397,7 +397,7 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev) client->num_ports++; if (newclient) synths[card->number] = client; - up(®ister_mutex); + mutex_unlock(®ister_mutex); kfree(info); kfree(port); return 0; /* success */ @@ -414,7 +414,7 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev) } kfree(info); kfree(port); - up(®ister_mutex); + mutex_unlock(®ister_mutex); return -ENOMEM; } @@ -427,10 +427,10 @@ snd_seq_midisynth_unregister_port(struct snd_seq_device *dev) struct snd_card *card = dev->card; int device = dev->device, p, ports; - down(®ister_mutex); + mutex_lock(®ister_mutex); client = synths[card->number]; if (client == NULL || client->ports[device] == NULL) { - up(®ister_mutex); + mutex_unlock(®ister_mutex); return -ENODEV; } ports = client->ports_per_device[device]; @@ -446,7 +446,7 @@ snd_seq_midisynth_unregister_port(struct snd_seq_device *dev) synths[card->number] = NULL; kfree(client); } - up(®ister_mutex); + mutex_unlock(®ister_mutex); return 0; } diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index 2b384fd7967f..41e078c938cd 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c @@ -159,7 +159,7 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, port_subs_info_init(&new_port->c_dest); num = port >= 0 ? port : 0; - down(&client->ports_mutex); + mutex_lock(&client->ports_mutex); write_lock_irqsave(&client->ports_lock, flags); list_for_each(l, &client->ports_list_head) { struct snd_seq_client_port *p = list_entry(l, struct snd_seq_client_port, list); @@ -173,7 +173,7 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, client->num_ports++; new_port->addr.port = num; /* store the port number in the port */ write_unlock_irqrestore(&client->ports_lock, flags); - up(&client->ports_mutex); + mutex_unlock(&client->ports_mutex); sprintf(new_port->name, "port-%d", num); return new_port; @@ -292,7 +292,7 @@ int snd_seq_delete_port(struct snd_seq_client *client, int port) struct list_head *l; struct snd_seq_client_port *found = NULL; - down(&client->ports_mutex); + mutex_lock(&client->ports_mutex); write_lock_irqsave(&client->ports_lock, flags); list_for_each(l, &client->ports_list_head) { struct snd_seq_client_port *p = list_entry(l, struct snd_seq_client_port, list); @@ -305,7 +305,7 @@ int snd_seq_delete_port(struct snd_seq_client *client, int port) } } write_unlock_irqrestore(&client->ports_lock, flags); - up(&client->ports_mutex); + mutex_unlock(&client->ports_mutex); if (found) return port_delete(client, found); else @@ -321,7 +321,7 @@ int snd_seq_delete_all_ports(struct snd_seq_client *client) /* move the port list to deleted_list, and * clear the port list in the client data. */ - down(&client->ports_mutex); + mutex_lock(&client->ports_mutex); write_lock_irqsave(&client->ports_lock, flags); if (! list_empty(&client->ports_list_head)) { __list_add(&deleted_list, @@ -341,7 +341,7 @@ int snd_seq_delete_all_ports(struct snd_seq_client *client) snd_seq_system_client_ev_port_exit(port->addr.client, port->addr.port); port_delete(client, port); } - up(&client->ports_mutex); + mutex_unlock(&client->ports_mutex); return 0; } diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c index 9cf20f045542..9b87bb0c7f33 100644 --- a/sound/core/seq/seq_queue.c +++ b/sound/core/seq/seq_queue.c @@ -119,7 +119,7 @@ static struct snd_seq_queue *queue_new(int owner, int locked) spin_lock_init(&q->owner_lock); spin_lock_init(&q->check_lock); - init_MUTEX(&q->timer_mutex); + mutex_init(&q->timer_mutex); snd_use_lock_init(&q->use_lock); q->queue = -1; @@ -516,7 +516,7 @@ int snd_seq_queue_use(int queueid, int client, int use) queue = queueptr(queueid); if (queue == NULL) return -EINVAL; - down(&queue->timer_mutex); + mutex_lock(&queue->timer_mutex); if (use) { if (!test_and_set_bit(client, queue->clients_bitmap)) queue->clients++; @@ -531,7 +531,7 @@ int snd_seq_queue_use(int queueid, int client, int use) } else { snd_seq_timer_close(queue); } - up(&queue->timer_mutex); + mutex_unlock(&queue->timer_mutex); queuefree(queue); return 0; } diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h index 888438599387..30c8111477f6 100644 --- a/sound/core/seq/seq_queue.h +++ b/sound/core/seq/seq_queue.h @@ -54,7 +54,7 @@ struct snd_seq_queue { /* clients which uses this queue (bitmap) */ DECLARE_BITMAP(clients_bitmap, SNDRV_SEQ_MAX_CLIENTS); unsigned int clients; /* users of this queue */ - struct semaphore timer_mutex; + struct mutex timer_mutex; snd_use_lock_t use_lock; }; diff --git a/sound/core/sound.c b/sound/core/sound.c index a8eda02bcf1c..df4ab94d006e 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -33,6 +33,7 @@ #include #include #include +#include #define SNDRV_OS_MINORS 256 @@ -61,7 +62,7 @@ MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR); int snd_ecards_limit; static struct snd_minor *snd_minors[SNDRV_OS_MINORS]; -static DECLARE_MUTEX(sound_mutex); +static DEFINE_MUTEX(sound_mutex); extern struct class *sound_class; @@ -122,13 +123,13 @@ void *snd_lookup_minor_data(unsigned int minor, int type) if (minor > ARRAY_SIZE(snd_minors)) return NULL; - down(&sound_mutex); + mutex_lock(&sound_mutex); mreg = snd_minors[minor]; if (mreg && mreg->type == type) private_data = mreg->private_data; else private_data = NULL; - up(&sound_mutex); + mutex_unlock(&sound_mutex); return private_data; } @@ -256,7 +257,7 @@ int snd_register_device(int type, struct snd_card *card, int dev, preg->f_ops = f_ops; preg->private_data = private_data; strcpy(preg->name, name); - down(&sound_mutex); + mutex_lock(&sound_mutex); #ifdef CONFIG_SND_DYNAMIC_MINORS minor = snd_find_free_minor(); #else @@ -265,7 +266,7 @@ int snd_register_device(int type, struct snd_card *card, int dev, minor = -EBUSY; #endif if (minor < 0) { - up(&sound_mutex); + mutex_unlock(&sound_mutex); kfree(preg); return minor; } @@ -276,7 +277,7 @@ int snd_register_device(int type, struct snd_card *card, int dev, device = card->dev; class_device_create(sound_class, NULL, MKDEV(major, minor), device, "%s", name); - up(&sound_mutex); + mutex_unlock(&sound_mutex); return 0; } @@ -297,7 +298,7 @@ int snd_unregister_device(int type, struct snd_card *card, int dev) struct snd_minor *mptr; cardnum = card ? card->number : -1; - down(&sound_mutex); + mutex_lock(&sound_mutex); for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) if ((mptr = snd_minors[minor]) != NULL && mptr->type == type && @@ -305,7 +306,7 @@ int snd_unregister_device(int type, struct snd_card *card, int dev) mptr->device == dev) break; if (minor == ARRAY_SIZE(snd_minors)) { - up(&sound_mutex); + mutex_unlock(&sound_mutex); return -EINVAL; } @@ -315,7 +316,7 @@ int snd_unregister_device(int type, struct snd_card *card, int dev) class_device_destroy(sound_class, MKDEV(major, minor)); snd_minors[minor] = NULL; - up(&sound_mutex); + mutex_unlock(&sound_mutex); kfree(mptr); return 0; } @@ -354,7 +355,7 @@ static void snd_minor_info_read(struct snd_info_entry *entry, struct snd_info_bu int minor; struct snd_minor *mptr; - down(&sound_mutex); + mutex_lock(&sound_mutex); for (minor = 0; minor < SNDRV_OS_MINORS; ++minor) { if (!(mptr = snd_minors[minor])) continue; @@ -371,7 +372,7 @@ static void snd_minor_info_read(struct snd_info_entry *entry, struct snd_info_bu snd_iprintf(buffer, "%3i: : %s\n", minor, snd_device_type_name(mptr->type)); } - up(&sound_mutex); + mutex_unlock(&sound_mutex); } int __init snd_minor_info_init(void) diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index d0be32b517c1..6b4a4bccd8fe 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -34,11 +34,12 @@ #include #include #include +#include #define SNDRV_OSS_MINORS 128 static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS]; -static DECLARE_MUTEX(sound_oss_mutex); +static DEFINE_MUTEX(sound_oss_mutex); void *snd_lookup_oss_minor_data(unsigned int minor, int type) { @@ -47,13 +48,13 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type) if (minor > ARRAY_SIZE(snd_oss_minors)) return NULL; - down(&sound_oss_mutex); + mutex_lock(&sound_oss_mutex); mreg = snd_oss_minors[minor]; if (mreg && mreg->type == type) private_data = mreg->private_data; else private_data = NULL; - up(&sound_oss_mutex); + mutex_unlock(&sound_oss_mutex); return private_data; } @@ -117,7 +118,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, preg->device = dev; preg->f_ops = f_ops; preg->private_data = private_data; - down(&sound_oss_mutex); + mutex_lock(&sound_oss_mutex); snd_oss_minors[minor] = preg; minor_unit = SNDRV_MINOR_OSS_DEVICE(minor); switch (minor_unit) { @@ -143,7 +144,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, goto __end; snd_oss_minors[track2] = preg; } - up(&sound_oss_mutex); + mutex_unlock(&sound_oss_mutex); return 0; __end: @@ -152,7 +153,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, if (register1 >= 0) unregister_sound_special(register1); snd_oss_minors[minor] = NULL; - up(&sound_oss_mutex); + mutex_unlock(&sound_oss_mutex); kfree(preg); return -EBUSY; } @@ -168,10 +169,10 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev) return 0; if (minor < 0) return minor; - down(&sound_oss_mutex); + mutex_lock(&sound_oss_mutex); mptr = snd_oss_minors[minor]; if (mptr == NULL) { - up(&sound_oss_mutex); + mutex_unlock(&sound_oss_mutex); return -ENOENT; } unregister_sound_special(minor); @@ -191,7 +192,7 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev) snd_oss_minors[track2] = NULL; } snd_oss_minors[minor] = NULL; - up(&sound_oss_mutex); + mutex_unlock(&sound_oss_mutex); kfree(mptr); return 0; } @@ -229,7 +230,7 @@ static void snd_minor_info_oss_read(struct snd_info_entry *entry, int minor; struct snd_minor *mptr; - down(&sound_oss_mutex); + mutex_lock(&sound_oss_mutex); for (minor = 0; minor < SNDRV_OSS_MINORS; ++minor) { if (!(mptr = snd_oss_minors[minor])) continue; @@ -241,7 +242,7 @@ static void snd_minor_info_oss_read(struct snd_info_entry *entry, snd_iprintf(buffer, "%3i: : %s\n", minor, snd_oss_device_type_name(mptr->type)); } - up(&sound_oss_mutex); + mutex_unlock(&sound_oss_mutex); } diff --git a/sound/core/timer.c b/sound/core/timer.c index 2425b971b240..cdeeb639b675 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -70,7 +71,7 @@ struct snd_timer_user { struct timespec tstamp; /* trigger tstamp */ wait_queue_head_t qchange_sleep; struct fasync_struct *fasync; - struct semaphore tread_sem; + struct mutex tread_sem; }; /* list of timers */ @@ -82,7 +83,7 @@ static LIST_HEAD(snd_timer_slave_list); /* lock for slave active lists */ static DEFINE_SPINLOCK(slave_active_lock); -static DECLARE_MUTEX(register_mutex); +static DEFINE_MUTEX(register_mutex); static int snd_timer_free(struct snd_timer *timer); static int snd_timer_dev_free(struct snd_device *device); @@ -252,10 +253,10 @@ int snd_timer_open(struct snd_timer_instance **ti, snd_printd("invalid slave class %i\n", tid->dev_sclass); return -EINVAL; } - down(®ister_mutex); + mutex_lock(®ister_mutex); timeri = snd_timer_instance_new(owner, NULL); if (!timeri) { - up(®ister_mutex); + mutex_unlock(®ister_mutex); return -ENOMEM; } timeri->slave_class = tid->dev_sclass; @@ -263,37 +264,37 @@ int snd_timer_open(struct snd_timer_instance **ti, timeri->flags |= SNDRV_TIMER_IFLG_SLAVE; list_add_tail(&timeri->open_list, &snd_timer_slave_list); snd_timer_check_slave(timeri); - up(®ister_mutex); + mutex_unlock(®ister_mutex); *ti = timeri; return 0; } /* open a master instance */ - down(®ister_mutex); + mutex_lock(®ister_mutex); timer = snd_timer_find(tid); #ifdef CONFIG_KMOD if (timer == NULL) { - up(®ister_mutex); + mutex_unlock(®ister_mutex); snd_timer_request(tid); - down(®ister_mutex); + mutex_lock(®ister_mutex); timer = snd_timer_find(tid); } #endif if (!timer) { - up(®ister_mutex); + mutex_unlock(®ister_mutex); return -ENODEV; } if (!list_empty(&timer->open_list_head)) { timeri = list_entry(timer->open_list_head.next, struct snd_timer_instance, open_list); if (timeri->flags & SNDRV_TIMER_IFLG_EXCLUSIVE) { - up(®ister_mutex); + mutex_unlock(®ister_mutex); return -EBUSY; } } timeri = snd_timer_instance_new(owner, timer); if (!timeri) { - up(®ister_mutex); + mutex_unlock(®ister_mutex); return -ENOMEM; } timeri->slave_class = tid->dev_sclass; @@ -302,7 +303,7 @@ int snd_timer_open(struct snd_timer_instance **ti, timer->hw.open(timer); list_add_tail(&timeri->open_list, &timer->open_list_head); snd_timer_check_master(timeri); - up(®ister_mutex); + mutex_unlock(®ister_mutex); *ti = timeri; return 0; } @@ -333,9 +334,9 @@ int snd_timer_close(struct snd_timer_instance *timeri) spin_lock_irq(&slave_active_lock); } spin_unlock_irq(&slave_active_lock); - down(®ister_mutex); + mutex_lock(®ister_mutex); list_del(&timeri->open_list); - up(®ister_mutex); + mutex_unlock(®ister_mutex); } else { timer = timeri->timer; /* wait, until the active callback is finished */ @@ -346,7 +347,7 @@ int snd_timer_close(struct snd_timer_instance *timeri) spin_lock_irq(&timer->lock); } spin_unlock_irq(&timer->lock); - down(®ister_mutex); + mutex_lock(®ister_mutex); list_del(&timeri->open_list); if (timer && list_empty(&timer->open_list_head) && timer->hw.close) @@ -362,7 +363,7 @@ int snd_timer_close(struct snd_timer_instance *timeri) slave->timer = NULL; spin_unlock_irq(&slave_active_lock); } - up(®ister_mutex); + mutex_unlock(®ister_mutex); } if (timeri->private_free) timeri->private_free(timeri); @@ -835,7 +836,7 @@ static int snd_timer_dev_register(struct snd_device *dev) !timer->hw.resolution && timer->hw.c_resolution == NULL) return -EINVAL; - down(®ister_mutex); + mutex_lock(®ister_mutex); list_for_each(p, &snd_timer_list) { timer1 = list_entry(p, struct snd_timer, device_list); if (timer1->tmr_class > timer->tmr_class) @@ -857,11 +858,11 @@ static int snd_timer_dev_register(struct snd_device *dev) if (timer1->tmr_subdevice < timer->tmr_subdevice) continue; /* conflicts.. */ - up(®ister_mutex); + mutex_unlock(®ister_mutex); return -EBUSY; } list_add_tail(&timer->device_list, p); - up(®ister_mutex); + mutex_unlock(®ister_mutex); return 0; } @@ -871,7 +872,7 @@ static int snd_timer_unregister(struct snd_timer *timer) struct snd_timer_instance *ti; snd_assert(timer != NULL, return -ENXIO); - down(®ister_mutex); + mutex_lock(®ister_mutex); if (! list_empty(&timer->open_list_head)) { snd_printk(KERN_WARNING "timer 0x%lx is busy?\n", (long)timer); list_for_each_safe(p, n, &timer->open_list_head) { @@ -881,7 +882,7 @@ static int snd_timer_unregister(struct snd_timer *timer) } } list_del(&timer->device_list); - up(®ister_mutex); + mutex_unlock(®ister_mutex); return snd_timer_free(timer); } @@ -1065,7 +1066,7 @@ static void snd_timer_proc_read(struct snd_info_entry *entry, struct snd_timer_instance *ti; struct list_head *p, *q; - down(®ister_mutex); + mutex_lock(®ister_mutex); list_for_each(p, &snd_timer_list) { timer = list_entry(p, struct snd_timer, device_list); switch (timer->tmr_class) { @@ -1105,7 +1106,7 @@ static void snd_timer_proc_read(struct snd_info_entry *entry, } spin_unlock_irqrestore(&timer->lock, flags); } - up(®ister_mutex); + mutex_unlock(®ister_mutex); } static struct snd_info_entry *snd_timer_proc_entry = NULL; @@ -1269,7 +1270,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file) return -ENOMEM; spin_lock_init(&tu->qlock); init_waitqueue_head(&tu->qchange_sleep); - init_MUTEX(&tu->tread_sem); + mutex_init(&tu->tread_sem); tu->ticks = 1; tu->queue_size = 128; tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read), @@ -1325,7 +1326,7 @@ static int snd_timer_user_next_device(struct snd_timer_id __user *_tid) if (copy_from_user(&id, _tid, sizeof(id))) return -EFAULT; - down(®ister_mutex); + mutex_lock(®ister_mutex); if (id.dev_class < 0) { /* first item */ if (list_empty(&snd_timer_list)) snd_timer_user_zero_id(&id); @@ -1407,7 +1408,7 @@ static int snd_timer_user_next_device(struct snd_timer_id __user *_tid) snd_timer_user_zero_id(&id); } } - up(®ister_mutex); + mutex_unlock(®ister_mutex); if (copy_to_user(_tid, &id, sizeof(*_tid))) return -EFAULT; return 0; @@ -1432,7 +1433,7 @@ static int snd_timer_user_ginfo(struct file *file, tid = ginfo->tid; memset(ginfo, 0, sizeof(*ginfo)); ginfo->tid = tid; - down(®ister_mutex); + mutex_lock(®ister_mutex); t = snd_timer_find(&tid); if (t != NULL) { ginfo->card = t->card ? t->card->number : -1; @@ -1451,7 +1452,7 @@ static int snd_timer_user_ginfo(struct file *file, } else { err = -ENODEV; } - up(®ister_mutex); + mutex_unlock(®ister_mutex); if (err >= 0 && copy_to_user(_ginfo, ginfo, sizeof(*ginfo))) err = -EFAULT; kfree(ginfo); @@ -1467,7 +1468,7 @@ static int snd_timer_user_gparams(struct file *file, if (copy_from_user(&gparams, _gparams, sizeof(gparams))) return -EFAULT; - down(®ister_mutex); + mutex_lock(®ister_mutex); t = snd_timer_find(&gparams.tid); if (!t) { err = -ENODEV; @@ -1483,7 +1484,7 @@ static int snd_timer_user_gparams(struct file *file, } err = t->hw.set_period(t, gparams.period_num, gparams.period_den); _error: - up(®ister_mutex); + mutex_unlock(®ister_mutex); return err; } @@ -1500,7 +1501,7 @@ static int snd_timer_user_gstatus(struct file *file, tid = gstatus.tid; memset(&gstatus, 0, sizeof(gstatus)); gstatus.tid = tid; - down(®ister_mutex); + mutex_lock(®ister_mutex); t = snd_timer_find(&tid); if (t != NULL) { if (t->hw.c_resolution) @@ -1517,7 +1518,7 @@ static int snd_timer_user_gstatus(struct file *file, } else { err = -ENODEV; } - up(®ister_mutex); + mutex_unlock(®ister_mutex); if (err >= 0 && copy_to_user(_gstatus, &gstatus, sizeof(gstatus))) err = -EFAULT; return err; @@ -1532,7 +1533,7 @@ static int snd_timer_user_tselect(struct file *file, int err = 0; tu = file->private_data; - down(&tu->tread_sem); + mutex_lock(&tu->tread_sem); if (tu->timeri) { snd_timer_close(tu->timeri); tu->timeri = NULL; @@ -1576,7 +1577,7 @@ static int snd_timer_user_tselect(struct file *file, } __err: - up(&tu->tread_sem); + mutex_unlock(&tu->tread_sem); return err; } @@ -1797,17 +1798,17 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, { int xarg; - down(&tu->tread_sem); + mutex_lock(&tu->tread_sem); if (tu->timeri) { /* too late */ - up(&tu->tread_sem); + mutex_unlock(&tu->tread_sem); return -EBUSY; } if (get_user(xarg, p)) { - up(&tu->tread_sem); + mutex_unlock(&tu->tread_sem); return -EFAULT; } tu->tread = xarg ? 1 : 0; - up(&tu->tread_sem); + mutex_unlock(&tu->tread_sem); return 0; } case SNDRV_TIMER_IOCTL_GINFO: -- cgit v1.2.3 From ef9f0a42db987e7e2df72289fb4522d24027786b Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 16 Jan 2006 16:31:42 +0100 Subject: [ALSA] semaphore -> mutex (driver part) Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Takashi Iwai --- include/sound/emux_synth.h | 2 +- include/sound/i2c.h | 10 +++--- include/sound/opl3.h | 3 +- include/sound/soundfont.h | 2 +- include/sound/util_mem.h | 4 ++- include/sound/vx_core.h | 2 +- sound/drivers/opl3/opl3_lib.c | 2 +- sound/drivers/opl3/opl3_seq.c | 10 +++--- sound/drivers/opl3/opl3_synth.c | 10 +++--- sound/drivers/opl4/opl4_lib.c | 2 +- sound/drivers/opl4/opl4_local.h | 2 +- sound/drivers/opl4/opl4_proc.c | 10 +++--- sound/drivers/opl4/opl4_seq.c | 12 +++---- sound/drivers/vx/vx_core.c | 2 +- sound/drivers/vx/vx_mixer.c | 72 ++++++++++++++++++++--------------------- sound/i2c/i2c.c | 2 +- sound/synth/emux/emux.c | 2 +- sound/synth/emux/emux_oss.c | 12 +++---- sound/synth/emux/emux_proc.c | 8 ++--- sound/synth/emux/emux_seq.c | 12 +++---- sound/synth/emux/soundfont.c | 6 ++-- sound/synth/util_mem.c | 15 +++++---- 22 files changed, 103 insertions(+), 99 deletions(-) (limited to 'include') diff --git a/include/sound/emux_synth.h b/include/sound/emux_synth.h index b2d6b2acc7c7..d8cb51b86c20 100644 --- a/include/sound/emux_synth.h +++ b/include/sound/emux_synth.h @@ -113,7 +113,7 @@ struct snd_emux { struct snd_emux_voice *voices; /* Voices (EMU 'channel') */ int use_time; /* allocation counter */ spinlock_t voice_lock; /* Lock for voice access */ - struct semaphore register_mutex; + struct mutex register_mutex; int client; /* For the sequencer client */ int ports[SNDRV_EMUX_MAX_PORTS]; /* The ports for this device */ struct snd_emux_port *portptrs[SNDRV_EMUX_MAX_PORTS]; diff --git a/include/sound/i2c.h b/include/sound/i2c.h index 81eb23ed761f..d125ff8c85e8 100644 --- a/include/sound/i2c.h +++ b/include/sound/i2c.h @@ -55,7 +55,7 @@ struct snd_i2c_bus { struct snd_card *card; /* card which I2C belongs to */ char name[32]; /* some useful label */ - struct semaphore lock_mutex; + struct mutex lock_mutex; struct snd_i2c_bus *master; /* master bus when SCK/SCL is shared */ struct list_head buses; /* master: slave buses sharing SCK/SCL, slave: link list */ @@ -84,17 +84,17 @@ int snd_i2c_device_free(struct snd_i2c_device *device); static inline void snd_i2c_lock(struct snd_i2c_bus *bus) { if (bus->master) - down(&bus->master->lock_mutex); + mutex_lock(&bus->master->lock_mutex); else - down(&bus->lock_mutex); + mutex_lock(&bus->lock_mutex); } static inline void snd_i2c_unlock(struct snd_i2c_bus *bus) { if (bus->master) - up(&bus->master->lock_mutex); + mutex_unlock(&bus->master->lock_mutex); else - up(&bus->lock_mutex); + mutex_unlock(&bus->lock_mutex); } int snd_i2c_sendbytes(struct snd_i2c_device *device, unsigned char *bytes, int count); diff --git a/include/sound/opl3.h b/include/sound/opl3.h index 83392641cb47..444907166f97 100644 --- a/include/sound/opl3.h +++ b/include/sound/opl3.h @@ -53,6 +53,7 @@ #include "driver.h" #include +#include #include "core.h" #include "hwdep.h" #include "timer.h" @@ -312,7 +313,7 @@ struct snd_opl3 { int sys_timer_status; /* system timer run status */ spinlock_t sys_timer_lock; /* Lock for system timer access */ #endif - struct semaphore access_mutex; /* locking */ + struct mutex access_mutex; /* locking */ }; /* opl3.c */ diff --git a/include/sound/soundfont.h b/include/sound/soundfont.h index 61a010c65d02..f95d99ba7f74 100644 --- a/include/sound/soundfont.h +++ b/include/sound/soundfont.h @@ -93,7 +93,7 @@ struct snd_sf_list { int sample_locked; /* locked time for sample */ struct snd_sf_callback callback; /* callback functions */ int presets_locked; - struct semaphore presets_mutex; + struct mutex presets_mutex; spinlock_t lock; struct snd_util_memhdr *memhdr; }; diff --git a/include/sound/util_mem.h b/include/sound/util_mem.h index 69944bbb5445..a1fb706b59a6 100644 --- a/include/sound/util_mem.h +++ b/include/sound/util_mem.h @@ -1,5 +1,7 @@ #ifndef __SOUND_UTIL_MEM_H #define __SOUND_UTIL_MEM_H + +#include /* * Copyright (C) 2000 Takashi Iwai * @@ -40,7 +42,7 @@ struct snd_util_memhdr { int nblocks; /* # of allocated blocks */ unsigned int used; /* used memory size */ int block_extra_size; /* extra data size of chunk */ - struct semaphore block_mutex; /* lock */ + struct mutex block_mutex; /* lock */ }; /* diff --git a/include/sound/vx_core.h b/include/sound/vx_core.h index 5fd6f3305e0d..9821a6194caa 100644 --- a/include/sound/vx_core.h +++ b/include/sound/vx_core.h @@ -206,7 +206,7 @@ struct vx_core { int audio_monitor[4]; /* playback hw-monitor level */ unsigned char audio_monitor_active[4]; /* playback hw-monitor mute/unmute */ - struct semaphore mixer_mutex; + struct mutex mixer_mutex; const struct firmware *firmware[4]; /* loaded firmware data */ }; diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index 1e0c76b9acfc..4f8556976774 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c @@ -358,7 +358,7 @@ int snd_opl3_new(struct snd_card *card, opl3->hardware = hardware; spin_lock_init(&opl3->reg_lock); spin_lock_init(&opl3->timer_lock); - init_MUTEX(&opl3->access_mutex); + mutex_init(&opl3->access_mutex); if ((err = snd_device_new(card, SNDRV_DEV_CODEC, opl3, &ops)) < 0) { snd_opl3_free(opl3); diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c index c4ead790008a..e26556d500e5 100644 --- a/sound/drivers/opl3/opl3_seq.c +++ b/sound/drivers/opl3/opl3_seq.c @@ -52,13 +52,13 @@ int snd_opl3_synth_setup(struct snd_opl3 * opl3) { int idx; - down(&opl3->access_mutex); + mutex_lock(&opl3->access_mutex); if (opl3->used) { - up(&opl3->access_mutex); + mutex_unlock(&opl3->access_mutex); return -EBUSY; } opl3->used++; - up(&opl3->access_mutex); + mutex_unlock(&opl3->access_mutex); snd_opl3_reset(opl3); @@ -91,9 +91,9 @@ void snd_opl3_synth_cleanup(struct snd_opl3 * opl3) spin_unlock_irqrestore(&opl3->sys_timer_lock, flags); snd_opl3_reset(opl3); - down(&opl3->access_mutex); + mutex_lock(&opl3->access_mutex); opl3->used--; - up(&opl3->access_mutex); + mutex_unlock(&opl3->access_mutex); } static int snd_opl3_synth_use(void *private_data, struct snd_seq_port_subscribe * info) diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c index 3534a0e3342a..6db503f025b3 100644 --- a/sound/drivers/opl3/opl3_synth.c +++ b/sound/drivers/opl3/opl3_synth.c @@ -76,13 +76,13 @@ int snd_opl3_open(struct snd_hwdep * hw, struct file *file) { struct snd_opl3 *opl3 = hw->private_data; - down(&opl3->access_mutex); + mutex_lock(&opl3->access_mutex); if (opl3->used) { - up(&opl3->access_mutex); + mutex_unlock(&opl3->access_mutex); return -EAGAIN; } opl3->used++; - up(&opl3->access_mutex); + mutex_unlock(&opl3->access_mutex); return 0; } @@ -179,9 +179,9 @@ int snd_opl3_release(struct snd_hwdep * hw, struct file *file) struct snd_opl3 *opl3 = hw->private_data; snd_opl3_reset(opl3); - down(&opl3->access_mutex); + mutex_lock(&opl3->access_mutex); opl3->used--; - up(&opl3->access_mutex); + mutex_unlock(&opl3->access_mutex); return 0; } diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c index ddfc10d04be2..4bc860ae02de 100644 --- a/sound/drivers/opl4/opl4_lib.c +++ b/sound/drivers/opl4/opl4_lib.c @@ -214,7 +214,7 @@ int snd_opl4_create(struct snd_card *card, opl4->fm_port = fm_port; opl4->pcm_port = pcm_port; spin_lock_init(&opl4->reg_lock); - init_MUTEX(&opl4->access_mutex); + mutex_init(&opl4->access_mutex); err = snd_opl4_detect(opl4); if (err < 0) { diff --git a/sound/drivers/opl4/opl4_local.h b/sound/drivers/opl4/opl4_local.h index 7e088a4a2f4c..470e5a758a02 100644 --- a/sound/drivers/opl4/opl4_local.h +++ b/sound/drivers/opl4/opl4_local.h @@ -182,7 +182,7 @@ struct snd_opl4 { struct snd_info_entry *proc_entry; int memory_access; #endif - struct semaphore access_mutex; + struct mutex access_mutex; #if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) int used; diff --git a/sound/drivers/opl4/opl4_proc.c b/sound/drivers/opl4/opl4_proc.c index f4b4e74fcc18..e552ec34166f 100644 --- a/sound/drivers/opl4/opl4_proc.c +++ b/sound/drivers/opl4/opl4_proc.c @@ -28,13 +28,13 @@ static int snd_opl4_mem_proc_open(struct snd_info_entry *entry, { struct snd_opl4 *opl4 = entry->private_data; - down(&opl4->access_mutex); + mutex_lock(&opl4->access_mutex); if (opl4->memory_access) { - up(&opl4->access_mutex); + mutex_unlock(&opl4->access_mutex); return -EBUSY; } opl4->memory_access++; - up(&opl4->access_mutex); + mutex_unlock(&opl4->access_mutex); return 0; } @@ -43,9 +43,9 @@ static int snd_opl4_mem_proc_release(struct snd_info_entry *entry, { struct snd_opl4 *opl4 = entry->private_data; - down(&opl4->access_mutex); + mutex_lock(&opl4->access_mutex); opl4->memory_access--; - up(&opl4->access_mutex); + mutex_unlock(&opl4->access_mutex); return 0; } diff --git a/sound/drivers/opl4/opl4_seq.c b/sound/drivers/opl4/opl4_seq.c index e3480326e735..dc0dcdc6c313 100644 --- a/sound/drivers/opl4/opl4_seq.c +++ b/sound/drivers/opl4/opl4_seq.c @@ -62,10 +62,10 @@ static int snd_opl4_seq_use(void *private_data, struct snd_seq_port_subscribe *i struct snd_opl4 *opl4 = private_data; int err; - down(&opl4->access_mutex); + mutex_lock(&opl4->access_mutex); if (opl4->used) { - up(&opl4->access_mutex); + mutex_unlock(&opl4->access_mutex); return -EBUSY; } opl4->used++; @@ -73,12 +73,12 @@ static int snd_opl4_seq_use(void *private_data, struct snd_seq_port_subscribe *i if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) { err = snd_opl4_seq_use_inc(opl4); if (err < 0) { - up(&opl4->access_mutex); + mutex_unlock(&opl4->access_mutex); return err; } } - up(&opl4->access_mutex); + mutex_unlock(&opl4->access_mutex); snd_opl4_synth_reset(opl4); return 0; @@ -90,9 +90,9 @@ static int snd_opl4_seq_unuse(void *private_data, struct snd_seq_port_subscribe snd_opl4_synth_shutdown(opl4); - down(&opl4->access_mutex); + mutex_lock(&opl4->access_mutex); opl4->used--; - up(&opl4->access_mutex); + mutex_unlock(&opl4->access_mutex); if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) snd_opl4_seq_use_dec(opl4); diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c index 43f615d7a545..fa4a2b5c2d8d 100644 --- a/sound/drivers/vx/vx_core.c +++ b/sound/drivers/vx/vx_core.c @@ -778,7 +778,7 @@ struct vx_core *snd_vx_create(struct snd_card *card, struct snd_vx_hardware *hw, chip->type = hw->type; chip->ops = ops; tasklet_init(&chip->tq, vx_interrupt, (unsigned long)chip); - init_MUTEX(&chip->mixer_mutex); + mutex_init(&chip->mixer_mutex); chip->card = card; card->private_data = chip; diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c index 8ec2c605d2f0..c1d7fcdd1973 100644 --- a/sound/drivers/vx/vx_mixer.c +++ b/sound/drivers/vx/vx_mixer.c @@ -427,10 +427,10 @@ static int vx_output_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ele { struct vx_core *chip = snd_kcontrol_chip(kcontrol); int codec = kcontrol->id.index; - down(&chip->mixer_mutex); + mutex_lock(&chip->mixer_mutex); ucontrol->value.integer.value[0] = chip->output_level[codec][0]; ucontrol->value.integer.value[1] = chip->output_level[codec][1]; - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 0; } @@ -438,7 +438,7 @@ static int vx_output_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele { struct vx_core *chip = snd_kcontrol_chip(kcontrol); int codec = kcontrol->id.index; - down(&chip->mixer_mutex); + mutex_lock(&chip->mixer_mutex); if (ucontrol->value.integer.value[0] != chip->output_level[codec][0] || ucontrol->value.integer.value[1] != chip->output_level[codec][1]) { vx_set_analog_output_level(chip, codec, @@ -446,10 +446,10 @@ static int vx_output_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele ucontrol->value.integer.value[1]); chip->output_level[codec][0] = ucontrol->value.integer.value[0]; chip->output_level[codec][1] = ucontrol->value.integer.value[1]; - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 1; } - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 0; } @@ -502,14 +502,14 @@ static int vx_audio_src_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v static int vx_audio_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct vx_core *chip = snd_kcontrol_chip(kcontrol); - down(&chip->mixer_mutex); + mutex_lock(&chip->mixer_mutex); if (chip->audio_source_target != ucontrol->value.enumerated.item[0]) { chip->audio_source_target = ucontrol->value.enumerated.item[0]; vx_sync_audio_source(chip); - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 1; } - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 0; } @@ -550,14 +550,14 @@ static int vx_clock_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ static int vx_clock_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct vx_core *chip = snd_kcontrol_chip(kcontrol); - down(&chip->mixer_mutex); + mutex_lock(&chip->mixer_mutex); if (chip->clock_mode != ucontrol->value.enumerated.item[0]) { chip->clock_mode = ucontrol->value.enumerated.item[0]; vx_set_clock(chip, chip->freq); - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 1; } - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 0; } @@ -587,10 +587,10 @@ static int vx_audio_gain_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ int audio = kcontrol->private_value & 0xff; int capture = (kcontrol->private_value >> 8) & 1; - down(&chip->mixer_mutex); + mutex_lock(&chip->mixer_mutex); ucontrol->value.integer.value[0] = chip->audio_gain[capture][audio]; ucontrol->value.integer.value[1] = chip->audio_gain[capture][audio+1]; - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 0; } @@ -600,15 +600,15 @@ static int vx_audio_gain_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ int audio = kcontrol->private_value & 0xff; int capture = (kcontrol->private_value >> 8) & 1; - down(&chip->mixer_mutex); + mutex_lock(&chip->mixer_mutex); if (ucontrol->value.integer.value[0] != chip->audio_gain[capture][audio] || ucontrol->value.integer.value[1] != chip->audio_gain[capture][audio+1]) { vx_set_audio_gain(chip, audio, capture, ucontrol->value.integer.value[0]); vx_set_audio_gain(chip, audio+1, capture, ucontrol->value.integer.value[1]); - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 1; } - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 0; } @@ -617,10 +617,10 @@ static int vx_audio_monitor_get(struct snd_kcontrol *kcontrol, struct snd_ctl_el struct vx_core *chip = snd_kcontrol_chip(kcontrol); int audio = kcontrol->private_value & 0xff; - down(&chip->mixer_mutex); + mutex_lock(&chip->mixer_mutex); ucontrol->value.integer.value[0] = chip->audio_monitor[audio]; ucontrol->value.integer.value[1] = chip->audio_monitor[audio+1]; - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 0; } @@ -629,17 +629,17 @@ static int vx_audio_monitor_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el struct vx_core *chip = snd_kcontrol_chip(kcontrol); int audio = kcontrol->private_value & 0xff; - down(&chip->mixer_mutex); + mutex_lock(&chip->mixer_mutex); if (ucontrol->value.integer.value[0] != chip->audio_monitor[audio] || ucontrol->value.integer.value[1] != chip->audio_monitor[audio+1]) { vx_set_monitor_level(chip, audio, ucontrol->value.integer.value[0], chip->audio_monitor_active[audio]); vx_set_monitor_level(chip, audio+1, ucontrol->value.integer.value[1], chip->audio_monitor_active[audio+1]); - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 1; } - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 0; } @@ -657,10 +657,10 @@ static int vx_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va struct vx_core *chip = snd_kcontrol_chip(kcontrol); int audio = kcontrol->private_value & 0xff; - down(&chip->mixer_mutex); + mutex_lock(&chip->mixer_mutex); ucontrol->value.integer.value[0] = chip->audio_active[audio]; ucontrol->value.integer.value[1] = chip->audio_active[audio+1]; - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 0; } @@ -669,15 +669,15 @@ static int vx_audio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va struct vx_core *chip = snd_kcontrol_chip(kcontrol); int audio = kcontrol->private_value & 0xff; - down(&chip->mixer_mutex); + mutex_lock(&chip->mixer_mutex); if (ucontrol->value.integer.value[0] != chip->audio_active[audio] || ucontrol->value.integer.value[1] != chip->audio_active[audio+1]) { vx_set_audio_switch(chip, audio, ucontrol->value.integer.value[0]); vx_set_audio_switch(chip, audio+1, ucontrol->value.integer.value[1]); - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 1; } - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 0; } @@ -686,10 +686,10 @@ static int vx_monitor_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ struct vx_core *chip = snd_kcontrol_chip(kcontrol); int audio = kcontrol->private_value & 0xff; - down(&chip->mixer_mutex); + mutex_lock(&chip->mixer_mutex); ucontrol->value.integer.value[0] = chip->audio_monitor_active[audio]; ucontrol->value.integer.value[1] = chip->audio_monitor_active[audio+1]; - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 0; } @@ -698,17 +698,17 @@ static int vx_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ struct vx_core *chip = snd_kcontrol_chip(kcontrol); int audio = kcontrol->private_value & 0xff; - down(&chip->mixer_mutex); + mutex_lock(&chip->mixer_mutex); if (ucontrol->value.integer.value[0] != chip->audio_monitor_active[audio] || ucontrol->value.integer.value[1] != chip->audio_monitor_active[audio+1]) { vx_set_monitor_level(chip, audio, chip->audio_monitor[audio], ucontrol->value.integer.value[0]); vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1], ucontrol->value.integer.value[1]); - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 1; } - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 0; } @@ -756,12 +756,12 @@ static int vx_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu { struct vx_core *chip = snd_kcontrol_chip(kcontrol); - down(&chip->mixer_mutex); + mutex_lock(&chip->mixer_mutex); ucontrol->value.iec958.status[0] = (chip->uer_bits >> 0) & 0xff; ucontrol->value.iec958.status[1] = (chip->uer_bits >> 8) & 0xff; ucontrol->value.iec958.status[2] = (chip->uer_bits >> 16) & 0xff; ucontrol->value.iec958.status[3] = (chip->uer_bits >> 24) & 0xff; - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 0; } @@ -783,14 +783,14 @@ static int vx_iec958_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu (ucontrol->value.iec958.status[1] << 8) | (ucontrol->value.iec958.status[2] << 16) | (ucontrol->value.iec958.status[3] << 24); - down(&chip->mixer_mutex); + mutex_lock(&chip->mixer_mutex); if (chip->uer_bits != val) { chip->uer_bits = val; vx_set_iec958_status(chip, val); - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 1; } - up(&chip->mixer_mutex); + mutex_unlock(&chip->mixer_mutex); return 0; } diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c index c4e1f2c23ced..edfe76fb0074 100644 --- a/sound/i2c/i2c.c +++ b/sound/i2c/i2c.c @@ -88,7 +88,7 @@ int snd_i2c_bus_create(struct snd_card *card, const char *name, bus = kzalloc(sizeof(*bus), GFP_KERNEL); if (bus == NULL) return -ENOMEM; - init_MUTEX(&bus->lock_mutex); + mutex_init(&bus->lock_mutex); INIT_LIST_HEAD(&bus->devices); INIT_LIST_HEAD(&bus->buses); bus->card = card; diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c index 7c8e328fae62..fc733bbf4487 100644 --- a/sound/synth/emux/emux.c +++ b/sound/synth/emux/emux.c @@ -45,7 +45,7 @@ int snd_emux_new(struct snd_emux **remu) return -ENOMEM; spin_lock_init(&emu->voice_lock); - init_MUTEX(&emu->register_mutex); + mutex_init(&emu->register_mutex); emu->client = -1; #ifdef CONFIG_SND_SEQUENCER_OSS diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c index dfbfcfbe5dd2..3436816727c8 100644 --- a/sound/synth/emux/emux_oss.c +++ b/sound/synth/emux/emux_oss.c @@ -117,10 +117,10 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) emu = closure; snd_assert(arg != NULL && emu != NULL, return -ENXIO); - down(&emu->register_mutex); + mutex_lock(&emu->register_mutex); if (!snd_emux_inc_count(emu)) { - up(&emu->register_mutex); + mutex_unlock(&emu->register_mutex); return -EFAULT; } @@ -134,7 +134,7 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) if (p == NULL) { snd_printk("can't create port\n"); snd_emux_dec_count(emu); - up(&emu->register_mutex); + mutex_unlock(&emu->register_mutex); return -ENOMEM; } @@ -148,7 +148,7 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) snd_emux_reset_port(p); - up(&emu->register_mutex); + mutex_unlock(&emu->register_mutex); return 0; } @@ -191,13 +191,13 @@ snd_emux_close_seq_oss(struct snd_seq_oss_arg *arg) emu = p->emu; snd_assert(emu != NULL, return -ENXIO); - down(&emu->register_mutex); + mutex_lock(&emu->register_mutex); snd_emux_sounds_off_all(p); snd_soundfont_close_check(emu->sflist, SF_CLIENT_NO(p->chset.port)); snd_seq_event_port_detach(p->chset.client, p->chset.port); snd_emux_dec_count(emu); - up(&emu->register_mutex); + mutex_unlock(&emu->register_mutex); return 0; } diff --git a/sound/synth/emux/emux_proc.c b/sound/synth/emux/emux_proc.c index a70a179f6947..1ba68ce30279 100644 --- a/sound/synth/emux/emux_proc.c +++ b/sound/synth/emux/emux_proc.c @@ -37,7 +37,7 @@ snd_emux_proc_info_read(struct snd_info_entry *entry, int i; emu = entry->private_data; - down(&emu->register_mutex); + mutex_lock(&emu->register_mutex); if (emu->name) snd_iprintf(buf, "Device: %s\n", emu->name); snd_iprintf(buf, "Ports: %d\n", emu->num_ports); @@ -56,13 +56,13 @@ snd_emux_proc_info_read(struct snd_info_entry *entry, snd_iprintf(buf, "Memory Size: 0\n"); } if (emu->sflist) { - down(&emu->sflist->presets_mutex); + mutex_lock(&emu->sflist->presets_mutex); snd_iprintf(buf, "SoundFonts: %d\n", emu->sflist->fonts_size); snd_iprintf(buf, "Instruments: %d\n", emu->sflist->zone_counter); snd_iprintf(buf, "Samples: %d\n", emu->sflist->sample_counter); snd_iprintf(buf, "Locked Instruments: %d\n", emu->sflist->zone_locked); snd_iprintf(buf, "Locked Samples: %d\n", emu->sflist->sample_locked); - up(&emu->sflist->presets_mutex); + mutex_unlock(&emu->sflist->presets_mutex); } #if 0 /* debug */ if (emu->voices[0].state != SNDRV_EMUX_ST_OFF && emu->voices[0].ch >= 0) { @@ -103,7 +103,7 @@ snd_emux_proc_info_read(struct snd_info_entry *entry, snd_iprintf(buf, "sample_mode=%x, rate=%x\n", vp->reg.sample_mode, vp->reg.rate_offset); } #endif - up(&emu->register_mutex); + mutex_unlock(&emu->register_mutex); } diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c index 1a973d7a90f8..8f00f07701c4 100644 --- a/sound/synth/emux/emux_seq.c +++ b/sound/synth/emux/emux_seq.c @@ -123,12 +123,12 @@ snd_emux_detach_seq(struct snd_emux *emu) if (emu->voices) snd_emux_terminate_all(emu); - down(&emu->register_mutex); + mutex_lock(&emu->register_mutex); if (emu->client >= 0) { snd_seq_delete_kernel_client(emu->client); emu->client = -1; } - up(&emu->register_mutex); + mutex_unlock(&emu->register_mutex); } @@ -311,10 +311,10 @@ snd_emux_use(void *private_data, struct snd_seq_port_subscribe *info) emu = p->emu; snd_assert(emu != NULL, return -EINVAL); - down(&emu->register_mutex); + mutex_lock(&emu->register_mutex); snd_emux_init_port(p); snd_emux_inc_count(emu); - up(&emu->register_mutex); + mutex_unlock(&emu->register_mutex); return 0; } @@ -332,10 +332,10 @@ snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *info) emu = p->emu; snd_assert(emu != NULL, return -EINVAL); - down(&emu->register_mutex); + mutex_lock(&emu->register_mutex); snd_emux_sounds_off_all(p); snd_emux_dec_count(emu); - up(&emu->register_mutex); + mutex_unlock(&emu->register_mutex); return 0; } diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c index 4c5754d4a2e8..32c27162dfb6 100644 --- a/sound/synth/emux/soundfont.c +++ b/sound/synth/emux/soundfont.c @@ -79,7 +79,7 @@ static void lock_preset(struct snd_sf_list *sflist) { unsigned long flags; - down(&sflist->presets_mutex); + mutex_lock(&sflist->presets_mutex); spin_lock_irqsave(&sflist->lock, flags); sflist->presets_locked = 1; spin_unlock_irqrestore(&sflist->lock, flags); @@ -96,7 +96,7 @@ unlock_preset(struct snd_sf_list *sflist) spin_lock_irqsave(&sflist->lock, flags); sflist->presets_locked = 0; spin_unlock_irqrestore(&sflist->lock, flags); - up(&sflist->presets_mutex); + mutex_unlock(&sflist->presets_mutex); } @@ -1390,7 +1390,7 @@ snd_sf_new(struct snd_sf_callback *callback, struct snd_util_memhdr *hdr) if ((sflist = kzalloc(sizeof(*sflist), GFP_KERNEL)) == NULL) return NULL; - init_MUTEX(&sflist->presets_mutex); + mutex_init(&sflist->presets_mutex); spin_lock_init(&sflist->lock); sflist->memhdr = hdr; diff --git a/sound/synth/util_mem.c b/sound/synth/util_mem.c index 217e8e552a42..1d9b11f345f8 100644 --- a/sound/synth/util_mem.c +++ b/sound/synth/util_mem.c @@ -18,6 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include #include @@ -42,7 +43,7 @@ snd_util_memhdr_new(int memsize) if (hdr == NULL) return NULL; hdr->size = memsize; - init_MUTEX(&hdr->block_mutex); + mutex_init(&hdr->block_mutex); INIT_LIST_HEAD(&hdr->block); return hdr; @@ -136,9 +137,9 @@ struct snd_util_memblk * snd_util_mem_alloc(struct snd_util_memhdr *hdr, int size) { struct snd_util_memblk *blk; - down(&hdr->block_mutex); + mutex_lock(&hdr->block_mutex); blk = __snd_util_mem_alloc(hdr, size); - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return blk; } @@ -163,9 +164,9 @@ int snd_util_mem_free(struct snd_util_memhdr *hdr, struct snd_util_memblk *blk) { snd_assert(hdr && blk, return -EINVAL); - down(&hdr->block_mutex); + mutex_lock(&hdr->block_mutex); __snd_util_mem_free(hdr, blk); - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return 0; } @@ -175,9 +176,9 @@ int snd_util_mem_free(struct snd_util_memhdr *hdr, struct snd_util_memblk *blk) int snd_util_mem_avail(struct snd_util_memhdr *hdr) { unsigned int size; - down(&hdr->block_mutex); + mutex_lock(&hdr->block_mutex); size = hdr->size - hdr->used; - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return size; } -- cgit v1.2.3 From 8b7547f95cbe8a5940df62ed730646fdfcba5fda Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 16 Jan 2006 16:33:08 +0100 Subject: [ALSA] semaphore -> mutex (ISA part) Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Takashi Iwai --- include/sound/ad1848.h | 2 +- include/sound/cs4231.h | 4 ++-- include/sound/gus.h | 6 +++--- include/sound/sb16_csp.h | 2 +- sound/isa/ad1848/ad1848_lib.c | 14 +++++++------- sound/isa/cs423x/cs4231_lib.c | 30 +++++++++++++++--------------- sound/isa/cs423x/cs4236_lib.c | 4 ++-- sound/isa/gus/gus_dma.c | 10 +++++----- sound/isa/gus/gus_main.c | 2 +- sound/isa/gus/gus_mem.c | 14 +++++++------- sound/isa/gus/gus_synth.c | 14 +++++++------- sound/isa/sb/sb16_csp.c | 12 ++++++------ 12 files changed, 57 insertions(+), 57 deletions(-) (limited to 'include') diff --git a/include/sound/ad1848.h b/include/sound/ad1848.h index 1a2759f3a292..57af1fe7b309 100644 --- a/include/sound/ad1848.h +++ b/include/sound/ad1848.h @@ -154,7 +154,7 @@ struct snd_ad1848 { #endif spinlock_t reg_lock; - struct semaphore open_mutex; + struct mutex open_mutex; }; /* exported functions */ diff --git a/include/sound/cs4231.h b/include/sound/cs4231.h index ac6a5d882088..60b5b92a1319 100644 --- a/include/sound/cs4231.h +++ b/include/sound/cs4231.h @@ -248,8 +248,8 @@ struct snd_cs4231 { unsigned int c_dma_size; spinlock_t reg_lock; - struct semaphore mce_mutex; - struct semaphore open_mutex; + struct mutex mce_mutex; + struct mutex open_mutex; int (*rate_constraint) (struct snd_pcm_runtime *runtime); void (*set_playback_format) (struct snd_cs4231 *chip, struct snd_pcm_hw_params *hw_params, unsigned char pdfr); diff --git a/include/sound/gus.h b/include/sound/gus.h index 63da50fae773..68a664ab97f3 100644 --- a/include/sound/gus.h +++ b/include/sound/gus.h @@ -209,7 +209,7 @@ struct snd_gf1_mem { struct snd_gf1_bank_info banks_16[4]; struct snd_gf1_mem_block *first; struct snd_gf1_mem_block *last; - struct semaphore memory_mutex; + struct mutex memory_mutex; }; struct snd_gf1_dma_block { @@ -467,8 +467,8 @@ struct snd_gus_card { spinlock_t dma_lock; spinlock_t pcm_volume_level_lock; spinlock_t uart_cmd_lock; - struct semaphore dma_mutex; - struct semaphore register_mutex; + struct mutex dma_mutex; + struct mutex register_mutex; }; /* I/O functions for GF1/InterWave chip - gus_io.c */ diff --git a/include/sound/sb16_csp.h b/include/sound/sb16_csp.h index 3b44d4b370f5..caf6fe21514d 100644 --- a/include/sound/sb16_csp.h +++ b/include/sound/sb16_csp.h @@ -158,7 +158,7 @@ struct snd_sb_csp { struct snd_kcontrol *qsound_switch; struct snd_kcontrol *qsound_space; - struct semaphore access_mutex; /* locking */ + struct mutex access_mutex; /* locking */ }; int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep); diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c index b78530d7ea90..d4b0e580557e 100644 --- a/sound/isa/ad1848/ad1848_lib.c +++ b/sound/isa/ad1848/ad1848_lib.c @@ -387,9 +387,9 @@ static int snd_ad1848_open(struct snd_ad1848 *chip, unsigned int mode) { unsigned long flags; - down(&chip->open_mutex); + mutex_lock(&chip->open_mutex); if (chip->mode & AD1848_MODE_OPEN) { - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); return -EAGAIN; } snd_ad1848_mce_down(chip); @@ -432,7 +432,7 @@ static int snd_ad1848_open(struct snd_ad1848 *chip, unsigned int mode) spin_unlock_irqrestore(&chip->reg_lock, flags); chip->mode = mode; - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); return 0; } @@ -441,9 +441,9 @@ static void snd_ad1848_close(struct snd_ad1848 *chip) { unsigned long flags; - down(&chip->open_mutex); + mutex_lock(&chip->open_mutex); if (!chip->mode) { - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); return; } /* disable IRQ */ @@ -471,7 +471,7 @@ static void snd_ad1848_close(struct snd_ad1848 *chip) spin_unlock_irqrestore(&chip->reg_lock, flags); chip->mode = 0; - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); } /* @@ -889,7 +889,7 @@ int snd_ad1848_create(struct snd_card *card, if (chip == NULL) return -ENOMEM; spin_lock_init(&chip->reg_lock); - init_MUTEX(&chip->open_mutex); + mutex_init(&chip->open_mutex); chip->card = card; chip->port = port; chip->irq = -1; diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c index eab7eb59b5f7..823db8246701 100644 --- a/sound/isa/cs423x/cs4231_lib.c +++ b/sound/isa/cs423x/cs4231_lib.c @@ -531,7 +531,7 @@ static void snd_cs4231_playback_format(struct snd_cs4231 *chip, unsigned long flags; int full_calib = 1; - down(&chip->mce_mutex); + mutex_lock(&chip->mce_mutex); snd_cs4231_calibrate_mute(chip, 1); if (chip->hardware == CS4231_HW_CS4231A || (chip->hardware & CS4231_HW_CS4232_MASK)) { @@ -560,7 +560,7 @@ static void snd_cs4231_playback_format(struct snd_cs4231 *chip, snd_cs4231_mce_down(chip); } snd_cs4231_calibrate_mute(chip, 0); - up(&chip->mce_mutex); + mutex_unlock(&chip->mce_mutex); } static void snd_cs4231_capture_format(struct snd_cs4231 *chip, @@ -570,7 +570,7 @@ static void snd_cs4231_capture_format(struct snd_cs4231 *chip, unsigned long flags; int full_calib = 1; - down(&chip->mce_mutex); + mutex_lock(&chip->mce_mutex); snd_cs4231_calibrate_mute(chip, 1); if (chip->hardware == CS4231_HW_CS4231A || (chip->hardware & CS4231_HW_CS4232_MASK)) { @@ -603,7 +603,7 @@ static void snd_cs4231_capture_format(struct snd_cs4231 *chip, snd_cs4231_mce_down(chip); } snd_cs4231_calibrate_mute(chip, 0); - up(&chip->mce_mutex); + mutex_unlock(&chip->mce_mutex); } /* @@ -709,15 +709,15 @@ static int snd_cs4231_open(struct snd_cs4231 *chip, unsigned int mode) { unsigned long flags; - down(&chip->open_mutex); + mutex_lock(&chip->open_mutex); if ((chip->mode & mode) || ((chip->mode & CS4231_MODE_OPEN) && chip->single_dma)) { - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); return -EAGAIN; } if (chip->mode & CS4231_MODE_OPEN) { chip->mode |= mode; - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); return 0; } /* ok. now enable and ack CODEC IRQ */ @@ -737,7 +737,7 @@ static int snd_cs4231_open(struct snd_cs4231 *chip, unsigned int mode) spin_unlock_irqrestore(&chip->reg_lock, flags); chip->mode = mode; - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); return 0; } @@ -745,10 +745,10 @@ static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode) { unsigned long flags; - down(&chip->open_mutex); + mutex_lock(&chip->open_mutex); chip->mode &= ~mode; if (chip->mode & CS4231_MODE_OPEN) { - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); return; } snd_cs4231_calibrate_mute(chip, 1); @@ -785,7 +785,7 @@ static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode) snd_cs4231_calibrate_mute(chip, 0); chip->mode = 0; - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); } /* @@ -1408,8 +1408,8 @@ static int snd_cs4231_new(struct snd_card *card, chip->hwshare = hwshare; spin_lock_init(&chip->reg_lock); - init_MUTEX(&chip->mce_mutex); - init_MUTEX(&chip->open_mutex); + mutex_init(&chip->mce_mutex); + mutex_init(&chip->open_mutex); chip->card = card; chip->rate_constraint = snd_cs4231_xrate; chip->set_playback_format = snd_cs4231_playback_format; @@ -1538,8 +1538,8 @@ int snd_cs4231_pcm(struct snd_cs4231 *chip, int device, struct snd_pcm **rpcm) return err; spin_lock_init(&chip->reg_lock); - init_MUTEX(&chip->mce_mutex); - init_MUTEX(&chip->open_mutex); + mutex_init(&chip->mce_mutex); + mutex_init(&chip->open_mutex); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs4231_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs4231_capture_ops); diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c index e36981d64ec5..1125ddb2b1aa 100644 --- a/sound/isa/cs423x/cs4236_lib.c +++ b/sound/isa/cs423x/cs4236_lib.c @@ -841,7 +841,7 @@ static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct sn enable = ucontrol->value.integer.value[0] & 1; - down(&chip->mce_mutex); + mutex_lock(&chip->mce_mutex); snd_cs4231_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); val = (chip->image[CS4231_ALT_FEATURE_1] & ~0x0e) | (0<<2) | (enable << 1); @@ -854,7 +854,7 @@ static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct sn snd_cs4236_ctrl_out(chip, 4, val); spin_unlock_irqrestore(&chip->reg_lock, flags); snd_cs4231_mce_down(chip); - up(&chip->mce_mutex); + mutex_unlock(&chip->mce_mutex); #if 0 printk("set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", diff --git a/sound/isa/gus/gus_dma.c b/sound/isa/gus/gus_dma.c index 930f4bc56f34..44ee5d3674a1 100644 --- a/sound/isa/gus/gus_dma.c +++ b/sound/isa/gus/gus_dma.c @@ -149,10 +149,10 @@ static void snd_gf1_dma_interrupt(struct snd_gus_card * gus) int snd_gf1_dma_init(struct snd_gus_card * gus) { - down(&gus->dma_mutex); + mutex_lock(&gus->dma_mutex); gus->gf1.dma_shared++; if (gus->gf1.dma_shared > 1) { - up(&gus->dma_mutex); + mutex_unlock(&gus->dma_mutex); return 0; } gus->gf1.interrupt_handler_dma_write = snd_gf1_dma_interrupt; @@ -160,7 +160,7 @@ int snd_gf1_dma_init(struct snd_gus_card * gus) gus->gf1.dma_data_pcm_last = gus->gf1.dma_data_synth = gus->gf1.dma_data_synth_last = NULL; - up(&gus->dma_mutex); + mutex_unlock(&gus->dma_mutex); return 0; } @@ -168,7 +168,7 @@ int snd_gf1_dma_done(struct snd_gus_card * gus) { struct snd_gf1_dma_block *block; - down(&gus->dma_mutex); + mutex_lock(&gus->dma_mutex); gus->gf1.dma_shared--; if (!gus->gf1.dma_shared) { snd_dma_disable(gus->gf1.dma1); @@ -185,7 +185,7 @@ int snd_gf1_dma_done(struct snd_gus_card * gus) gus->gf1.dma_data_pcm_last = gus->gf1.dma_data_synth_last = NULL; } - up(&gus->dma_mutex); + mutex_unlock(&gus->dma_mutex); return 0; } diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c index 6d15b3d18a87..53eeaf37007d 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c @@ -225,7 +225,7 @@ int snd_gus_create(struct snd_card *card, spin_lock_init(&gus->dma_lock); spin_lock_init(&gus->pcm_volume_level_lock); spin_lock_init(&gus->uart_cmd_lock); - init_MUTEX(&gus->dma_mutex); + mutex_init(&gus->dma_mutex); if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, gus, &ops)) < 0) { snd_gus_free(gus); return err; diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c index e8bdb860a19f..3c0d27aa08b3 100644 --- a/sound/isa/gus/gus_mem.c +++ b/sound/isa/gus/gus_mem.c @@ -34,9 +34,9 @@ static void snd_gf1_mem_info_read(struct snd_info_entry *entry, void snd_gf1_mem_lock(struct snd_gf1_mem * alloc, int xup) { if (!xup) { - down(&alloc->memory_mutex); + mutex_lock(&alloc->memory_mutex); } else { - up(&alloc->memory_mutex); + mutex_unlock(&alloc->memory_mutex); } } @@ -59,7 +59,7 @@ static struct snd_gf1_mem_block *snd_gf1_mem_xalloc(struct snd_gf1_mem * alloc, alloc->first = nblock; else nblock->prev->next = nblock; - up(&alloc->memory_mutex); + mutex_unlock(&alloc->memory_mutex); return NULL; } pblock = pblock->next; @@ -80,7 +80,7 @@ int snd_gf1_mem_xfree(struct snd_gf1_mem * alloc, struct snd_gf1_mem_block * blo { if (block->share) { /* ok.. shared block */ block->share--; - up(&alloc->memory_mutex); + mutex_unlock(&alloc->memory_mutex); return 0; } if (alloc->first == block) { @@ -244,7 +244,7 @@ int snd_gf1_mem_init(struct snd_gus_card * gus) #endif alloc = &gus->gf1.mem_alloc; - init_MUTEX(&alloc->memory_mutex); + mutex_init(&alloc->memory_mutex); alloc->first = alloc->last = NULL; if (!gus->gf1.memory) return 0; @@ -299,7 +299,7 @@ static void snd_gf1_mem_info_read(struct snd_info_entry *entry, gus = entry->private_data; alloc = &gus->gf1.mem_alloc; - down(&alloc->memory_mutex); + mutex_lock(&alloc->memory_mutex); snd_iprintf(buffer, "8-bit banks : \n "); for (i = 0; i < 4; i++) snd_iprintf(buffer, "0x%06x (%04ik)%s", alloc->banks_8[i].address, alloc->banks_8[i].size >> 10, i + 1 < 4 ? "," : ""); @@ -343,7 +343,7 @@ static void snd_gf1_mem_info_read(struct snd_info_entry *entry, } snd_iprintf(buffer, " Total: memory = %i, used = %i, free = %i\n", total, used, total - used); - up(&alloc->memory_mutex); + mutex_unlock(&alloc->memory_mutex); #if 0 ultra_iprintf(buffer, " Verify: free = %i, max 8-bit block = %i, max 16-bit block = %i\n", ultra_memory_free_size(card, &card->gf1.mem_alloc), diff --git a/sound/isa/gus/gus_synth.c b/sound/isa/gus/gus_synth.c index 85a1b051f09a..2767cc187ae3 100644 --- a/sound/isa/gus/gus_synth.c +++ b/sound/isa/gus/gus_synth.c @@ -55,9 +55,9 @@ static int snd_gus_synth_use(void *private_data, struct snd_seq_port_subscribe * if (info->voices > 32) return -EINVAL; - down(&gus->register_mutex); + mutex_lock(&gus->register_mutex); if (!snd_gus_use_inc(gus)) { - up(&gus->register_mutex); + mutex_unlock(&gus->register_mutex); return -EFAULT; } for (idx = 0; idx < info->voices; idx++) { @@ -65,12 +65,12 @@ static int snd_gus_synth_use(void *private_data, struct snd_seq_port_subscribe * if (voice == NULL) { snd_gus_synth_free_voices(gus, info->sender.client, info->sender.port); snd_gus_use_dec(gus); - up(&gus->register_mutex); + mutex_unlock(&gus->register_mutex); return -EBUSY; } voice->index = idx; } - up(&gus->register_mutex); + mutex_unlock(&gus->register_mutex); return 0; } @@ -79,10 +79,10 @@ static int snd_gus_synth_unuse(void *private_data, struct snd_seq_port_subscribe struct snd_gus_port * port = private_data; struct snd_gus_card * gus = port->gus; - down(&gus->register_mutex); + mutex_lock(&gus->register_mutex); snd_gus_synth_free_voices(gus, info->sender.client, info->sender.port); snd_gus_use_dec(gus); - up(&gus->register_mutex); + mutex_unlock(&gus->register_mutex); return 0; } @@ -223,7 +223,7 @@ static int snd_gus_synth_new_device(struct snd_seq_device *dev) if (gus == NULL) return -EINVAL; - init_MUTEX(&gus->register_mutex); + mutex_init(&gus->register_mutex); gus->gf1.seq_client = -1; /* allocate new client */ diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index 9c2b5efbacbf..9703c68e4e08 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c @@ -138,7 +138,7 @@ int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep) p->ops.csp_stop = snd_sb_csp_stop; p->ops.csp_qsound_transfer = snd_sb_csp_qsound_transfer; - init_MUTEX(&p->access_mutex); + mutex_init(&p->access_mutex); sprintf(hw->name, "CSP v%d.%d", (version >> 4), (version & 0x0f)); hw->iface = SNDRV_HWDEP_IFACE_SB16CSP; hw->private_data = p; @@ -265,13 +265,13 @@ static int snd_sb_csp_release(struct snd_hwdep * hw, struct file *file) */ static int snd_sb_csp_use(struct snd_sb_csp * p) { - down(&p->access_mutex); + mutex_lock(&p->access_mutex); if (p->used) { - up(&p->access_mutex); + mutex_unlock(&p->access_mutex); return -EAGAIN; } p->used++; - up(&p->access_mutex); + mutex_unlock(&p->access_mutex); return 0; @@ -282,9 +282,9 @@ static int snd_sb_csp_use(struct snd_sb_csp * p) */ static int snd_sb_csp_unuse(struct snd_sb_csp * p) { - down(&p->access_mutex); + mutex_lock(&p->access_mutex); p->used--; - up(&p->access_mutex); + mutex_unlock(&p->access_mutex); return 0; } -- cgit v1.2.3 From 62932df8fb20ba2fb53a95fa52445eba22e821fe Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 16 Jan 2006 16:34:20 +0100 Subject: [ALSA] semaphore -> mutex (PCI part) Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Takashi Iwai --- include/sound/ac97_codec.h | 4 +- include/sound/ak4531_codec.h | 2 +- include/sound/cs46xx.h | 2 +- include/sound/emu10k1.h | 4 +- sound/pci/ac97/ac97_codec.c | 45 +++++++++---------- sound/pci/ac97/ac97_patch.c | 10 +++-- sound/pci/ac97/ac97_pcm.c | 6 ++- sound/pci/ac97/ac97_proc.c | 14 +++--- sound/pci/ac97/ak4531_codec.c | 28 ++++++------ sound/pci/atiixp.c | 21 ++++----- sound/pci/atiixp_modem.c | 13 +++--- sound/pci/cmipci.c | 25 +++++------ sound/pci/cs46xx/cs46xx_lib.c | 52 +++++++++++----------- sound/pci/cs46xx/dsp_spos.c | 58 +++++++++++++------------ sound/pci/cs46xx/dsp_spos_scb_lib.c | 6 ++- sound/pci/emu10k1/emu10k1_main.c | 5 ++- sound/pci/emu10k1/emufx.c | 22 +++++----- sound/pci/emu10k1/memory.c | 26 +++++------ sound/pci/ens1370.c | 32 +++++++------- sound/pci/es1968.c | 22 +++++----- sound/pci/hda/hda_codec.c | 51 +++++++++++----------- sound/pci/hda/hda_codec.h | 4 +- sound/pci/hda/hda_intel.c | 17 ++++---- sound/pci/hda/patch_analog.c | 28 ++++++------ sound/pci/ice1712/aureon.c | 38 ++++++++-------- sound/pci/ice1712/delta.c | 26 +++++------ sound/pci/ice1712/hoontech.c | 26 +++++------ sound/pci/ice1712/ice1712.c | 7 +-- sound/pci/ice1712/ice1712.h | 10 ++--- sound/pci/ice1712/ice1724.c | 37 ++++++++-------- sound/pci/ice1712/phase.c | 10 +++-- sound/pci/ice1712/pontis.c | 86 +++++++++++++++++++------------------ sound/pci/korg1212/korg1212.c | 17 ++++---- sound/pci/mixart/mixart.c | 21 ++++----- sound/pci/mixart/mixart.h | 7 +-- sound/pci/mixart/mixart_core.c | 18 ++++---- sound/pci/mixart/mixart_mixer.c | 52 +++++++++++----------- sound/pci/nm256/nm256.c | 16 ++++--- sound/pci/pcxhr/pcxhr.c | 36 ++++++++-------- sound/pci/pcxhr/pcxhr.h | 5 ++- sound/pci/pcxhr/pcxhr_mixer.c | 75 ++++++++++++++++---------------- sound/pci/trident/trident_memory.c | 36 ++++++++-------- sound/pci/vx222/vx222_ops.c | 18 ++++---- 43 files changed, 549 insertions(+), 489 deletions(-) (limited to 'include') diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index b0b3ea7b365e..ad3fe046f6cf 100644 --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h @@ -456,8 +456,8 @@ struct snd_ac97 { struct snd_info_entry *proc_regs; unsigned short subsystem_vendor; unsigned short subsystem_device; - struct semaphore reg_mutex; - struct semaphore page_mutex; /* mutex for AD18xx multi-codecs and paging (2.3) */ + struct mutex reg_mutex; + struct mutex page_mutex; /* mutex for AD18xx multi-codecs and paging (2.3) */ unsigned short num; /* number of codec: 0 = primary, 1 = secondary */ unsigned short addr; /* physical address of codec [0-3] */ unsigned int id; /* identification of codec */ diff --git a/include/sound/ak4531_codec.h b/include/sound/ak4531_codec.h index edf04070ce7c..fb30faab43a8 100644 --- a/include/sound/ak4531_codec.h +++ b/include/sound/ak4531_codec.h @@ -71,7 +71,7 @@ struct snd_ak4531 { void (*private_free) (struct snd_ak4531 *ak4531); /* --- */ unsigned char regs[0x20]; - struct semaphore reg_mutex; + struct mutex reg_mutex; }; int snd_ak4531_mixer(struct snd_card *card, struct snd_ak4531 *_ak4531, diff --git a/include/sound/cs46xx.h b/include/sound/cs46xx.h index 199b5098ff7e..80b2979c0cba 100644 --- a/include/sound/cs46xx.h +++ b/include/sound/cs46xx.h @@ -1711,7 +1711,7 @@ struct snd_cs46xx { int current_gpio; #endif #ifdef CONFIG_SND_CS46XX_NEW_DSP - struct semaphore spos_mutex; + struct mutex spos_mutex; struct dsp_spos_instance * dsp_spos_instance; diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index 951e40d720d9..186e00ad9e79 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h @@ -33,6 +33,7 @@ #include #include #include +#include #include /* ------------------- DEFINES -------------------- */ @@ -1022,7 +1023,7 @@ struct snd_emu10k1_fx8010 { int gpr_size; /* size of allocated GPR controls */ int gpr_count; /* count of used kcontrols */ struct list_head gpr_ctl; /* GPR controls */ - struct semaphore lock; + struct mutex lock; struct snd_emu10k1_fx8010_pcm pcm[8]; spinlock_t irq_lock; struct snd_emu10k1_fx8010_irq *irq_handlers; @@ -1122,7 +1123,6 @@ struct snd_emu10k1 { spinlock_t reg_lock; spinlock_t emu_lock; spinlock_t voice_lock; - struct semaphore ptb_lock; struct snd_emu10k1_voice voices[NUM_G]; struct snd_emu10k1_voice p16v_voices[4]; diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 3020ca2b602b..6108cdc5efb6 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -296,11 +297,11 @@ void snd_ac97_write_cache(struct snd_ac97 *ac97, unsigned short reg, unsigned sh { if (!snd_ac97_valid_reg(ac97, reg)) return; - down(&ac97->reg_mutex); + mutex_lock(&ac97->reg_mutex); ac97->regs[reg] = value; ac97->bus->ops->write(ac97, reg, value); set_bit(reg, ac97->reg_accessed); - up(&ac97->reg_mutex); + mutex_unlock(&ac97->reg_mutex); } /** @@ -321,14 +322,14 @@ int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short va if (!snd_ac97_valid_reg(ac97, reg)) return -EINVAL; - down(&ac97->reg_mutex); + mutex_lock(&ac97->reg_mutex); change = ac97->regs[reg] != value; if (change) { ac97->regs[reg] = value; ac97->bus->ops->write(ac97, reg, value); } set_bit(reg, ac97->reg_accessed); - up(&ac97->reg_mutex); + mutex_unlock(&ac97->reg_mutex); return change; } @@ -351,9 +352,9 @@ int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned sho if (!snd_ac97_valid_reg(ac97, reg)) return -EINVAL; - down(&ac97->reg_mutex); + mutex_lock(&ac97->reg_mutex); change = snd_ac97_update_bits_nolock(ac97, reg, mask, value); - up(&ac97->reg_mutex); + mutex_unlock(&ac97->reg_mutex); return change; } @@ -380,12 +381,12 @@ static int snd_ac97_ad18xx_update_pcm_bits(struct snd_ac97 *ac97, int codec, uns int change; unsigned short old, new, cfg; - down(&ac97->page_mutex); + mutex_lock(&ac97->page_mutex); old = ac97->spec.ad18xx.pcmreg[codec]; new = (old & ~mask) | value; change = old != new; if (change) { - down(&ac97->reg_mutex); + mutex_lock(&ac97->reg_mutex); cfg = snd_ac97_read_cache(ac97, AC97_AD_SERIAL_CFG); ac97->spec.ad18xx.pcmreg[codec] = new; /* select single codec */ @@ -397,9 +398,9 @@ static int snd_ac97_ad18xx_update_pcm_bits(struct snd_ac97 *ac97, int codec, uns /* select all codecs */ ac97->bus->ops->write(ac97, AC97_AD_SERIAL_CFG, cfg | 0x7000); - up(&ac97->reg_mutex); + mutex_unlock(&ac97->reg_mutex); } - up(&ac97->page_mutex); + mutex_unlock(&ac97->page_mutex); return change; } @@ -467,7 +468,7 @@ static int snd_ac97_page_save(struct snd_ac97 *ac97, int reg, struct snd_kcontro (ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23 && (reg >= 0x60 && reg < 0x70)) { unsigned short page = (kcontrol->private_value >> 26) & 0x0f; - down(&ac97->page_mutex); /* lock paging */ + mutex_lock(&ac97->page_mutex); /* lock paging */ page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK; snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page); } @@ -478,7 +479,7 @@ static void snd_ac97_page_restore(struct snd_ac97 *ac97, int page_save) { if (page_save >= 0) { snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); - up(&ac97->page_mutex); /* unlock paging */ + mutex_unlock(&ac97->page_mutex); /* unlock paging */ } } @@ -674,12 +675,12 @@ static int snd_ac97_spdif_default_get(struct snd_kcontrol *kcontrol, struct snd_ { struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - down(&ac97->reg_mutex); + mutex_lock(&ac97->reg_mutex); ucontrol->value.iec958.status[0] = ac97->spdif_status & 0xff; ucontrol->value.iec958.status[1] = (ac97->spdif_status >> 8) & 0xff; ucontrol->value.iec958.status[2] = (ac97->spdif_status >> 16) & 0xff; ucontrol->value.iec958.status[3] = (ac97->spdif_status >> 24) & 0xff; - up(&ac97->reg_mutex); + mutex_unlock(&ac97->reg_mutex); return 0; } @@ -718,7 +719,7 @@ static int snd_ac97_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ } } - down(&ac97->reg_mutex); + mutex_lock(&ac97->reg_mutex); change = ac97->spdif_status != new; ac97->spdif_status = new; @@ -746,7 +747,7 @@ static int snd_ac97_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ } } - up(&ac97->reg_mutex); + mutex_unlock(&ac97->reg_mutex); return change; } @@ -763,7 +764,7 @@ static int snd_ac97_put_spsa(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ value = (ucontrol->value.integer.value[0] & mask); - down(&ac97->reg_mutex); + mutex_lock(&ac97->reg_mutex); mask <<= shift; value <<= shift; old = snd_ac97_read_cache(ac97, reg); @@ -777,7 +778,7 @@ static int snd_ac97_put_spsa(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ if (extst & AC97_EA_SPDIF) snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ } - up(&ac97->reg_mutex); + mutex_unlock(&ac97->reg_mutex); return change; } @@ -888,10 +889,10 @@ static int snd_ac97_ad18xx_pcm_get_volume(struct snd_kcontrol *kcontrol, struct struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); int codec = kcontrol->private_value & 3; - down(&ac97->page_mutex); + mutex_lock(&ac97->page_mutex); ucontrol->value.integer.value[0] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 0) & 31); ucontrol->value.integer.value[1] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 8) & 31); - up(&ac97->page_mutex); + mutex_unlock(&ac97->page_mutex); return 0; } @@ -1856,8 +1857,8 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, ac97->limited_regs = template->limited_regs; memcpy(ac97->reg_accessed, template->reg_accessed, sizeof(ac97->reg_accessed)); bus->codec[ac97->num] = ac97; - init_MUTEX(&ac97->reg_mutex); - init_MUTEX(&ac97->page_mutex); + mutex_init(&ac97->reg_mutex); + mutex_init(&ac97->page_mutex); #ifdef CONFIG_PCI if (ac97->pci) { diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index a444a78c7c94..8bc79cbe3215 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -27,6 +27,8 @@ #include #include #include +#include + #include #include #include @@ -55,12 +57,12 @@ static int ac97_update_bits_page(struct snd_ac97 *ac97, unsigned short reg, unsi unsigned short page_save; int ret; - down(&ac97->page_mutex); + mutex_lock(&ac97->page_mutex); page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK; snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page); ret = snd_ac97_update_bits(ac97, reg, mask, value); snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); - up(&ac97->page_mutex); /* unlock paging */ + mutex_unlock(&ac97->page_mutex); /* unlock paging */ return ret; } @@ -897,12 +899,12 @@ static int snd_ac97_stac9708_put_bias(struct snd_kcontrol *kcontrol, struct snd_ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); int err; - down(&ac97->page_mutex); + mutex_lock(&ac97->page_mutex); snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0xabba); err = snd_ac97_update_bits(ac97, AC97_SIGMATEL_BIAS2, 0x0010, (ucontrol->value.integer.value[0] & 1) << 4); snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0); - up(&ac97->page_mutex); + mutex_unlock(&ac97->page_mutex); return err; } diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c index c3e590bf7a02..512a3583b0ce 100644 --- a/sound/pci/ac97/ac97_pcm.c +++ b/sound/pci/ac97/ac97_pcm.c @@ -27,6 +27,8 @@ #include #include #include +#include + #include #include #include @@ -206,7 +208,7 @@ static int set_spdif_rate(struct snd_ac97 *ac97, unsigned short rate) mask = AC97_SC_SPSR_MASK; } - down(&ac97->reg_mutex); + mutex_lock(&ac97->reg_mutex); old = snd_ac97_read(ac97, reg) & mask; if (old != bits) { snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); @@ -231,7 +233,7 @@ static int set_spdif_rate(struct snd_ac97 *ac97, unsigned short rate) ac97->spdif_status = sbits; } snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); - up(&ac97->reg_mutex); + mutex_unlock(&ac97->reg_mutex); return 0; } diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c index 7134b3f55fb5..4d523df79cc7 100644 --- a/sound/pci/ac97/ac97_proc.c +++ b/sound/pci/ac97/ac97_proc.c @@ -24,6 +24,8 @@ #include #include +#include + #include #include #include @@ -338,7 +340,7 @@ static void snd_ac97_proc_read(struct snd_info_entry *entry, struct snd_info_buf { struct snd_ac97 *ac97 = entry->private_data; - down(&ac97->page_mutex); + mutex_lock(&ac97->page_mutex); if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86 int idx; for (idx = 0; idx < 3; idx++) @@ -364,7 +366,7 @@ static void snd_ac97_proc_read(struct snd_info_entry *entry, struct snd_info_buf } else { snd_ac97_proc_read_main(ac97, buffer, 0); } - up(&ac97->page_mutex); + mutex_unlock(&ac97->page_mutex); } #ifdef CONFIG_SND_DEBUG @@ -374,7 +376,7 @@ static void snd_ac97_proc_regs_write(struct snd_info_entry *entry, struct snd_in struct snd_ac97 *ac97 = entry->private_data; char line[64]; unsigned int reg, val; - down(&ac97->page_mutex); + mutex_lock(&ac97->page_mutex); while (!snd_info_get_line(buffer, line, sizeof(line))) { if (sscanf(line, "%x %x", ®, &val) != 2) continue; @@ -382,7 +384,7 @@ static void snd_ac97_proc_regs_write(struct snd_info_entry *entry, struct snd_in if (reg < 0x80 && (reg & 1) == 0 && val <= 0xffff) snd_ac97_write_cache(ac97, reg, val); } - up(&ac97->page_mutex); + mutex_unlock(&ac97->page_mutex); } #endif @@ -401,7 +403,7 @@ static void snd_ac97_proc_regs_read(struct snd_info_entry *entry, { struct snd_ac97 *ac97 = entry->private_data; - down(&ac97->page_mutex); + mutex_lock(&ac97->page_mutex); if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86 int idx; @@ -417,7 +419,7 @@ static void snd_ac97_proc_regs_read(struct snd_info_entry *entry, } else { snd_ac97_proc_regs_read_main(ac97, buffer, 0); } - up(&ac97->page_mutex); + mutex_unlock(&ac97->page_mutex); } void snd_ac97_proc_init(struct snd_ac97 * ac97) diff --git a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c index dcfb5036ff8b..0fb7b3407312 100644 --- a/sound/pci/ac97/ak4531_codec.c +++ b/sound/pci/ac97/ak4531_codec.c @@ -23,6 +23,8 @@ #include #include #include +#include + #include #include @@ -82,9 +84,9 @@ static int snd_ak4531_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e int invert = (kcontrol->private_value >> 22) & 1; int val; - down(&ak4531->reg_mutex); + mutex_lock(&ak4531->reg_mutex); val = (ak4531->regs[reg] >> shift) & mask; - up(&ak4531->reg_mutex); + mutex_unlock(&ak4531->reg_mutex); if (invert) { val = mask - val; } @@ -107,11 +109,11 @@ static int snd_ak4531_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e val = mask - val; } val <<= shift; - down(&ak4531->reg_mutex); + mutex_lock(&ak4531->reg_mutex); val = (ak4531->regs[reg] & ~(mask << shift)) | val; change = val != ak4531->regs[reg]; ak4531->write(ak4531, reg, ak4531->regs[reg] = val); - up(&ak4531->reg_mutex); + mutex_unlock(&ak4531->reg_mutex); return change; } @@ -143,10 +145,10 @@ static int snd_ak4531_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e int invert = (kcontrol->private_value >> 22) & 1; int left, right; - down(&ak4531->reg_mutex); + mutex_lock(&ak4531->reg_mutex); left = (ak4531->regs[left_reg] >> left_shift) & mask; right = (ak4531->regs[right_reg] >> right_shift) & mask; - up(&ak4531->reg_mutex); + mutex_unlock(&ak4531->reg_mutex); if (invert) { left = mask - left; right = mask - right; @@ -176,7 +178,7 @@ static int snd_ak4531_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e } left <<= left_shift; right <<= right_shift; - down(&ak4531->reg_mutex); + mutex_lock(&ak4531->reg_mutex); if (left_reg == right_reg) { left = (ak4531->regs[left_reg] & ~((mask << left_shift) | (mask << right_shift))) | left | right; change = left != ak4531->regs[left_reg]; @@ -188,7 +190,7 @@ static int snd_ak4531_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e ak4531->write(ak4531, left_reg, ak4531->regs[left_reg] = left); ak4531->write(ak4531, right_reg, ak4531->regs[right_reg] = right); } - up(&ak4531->reg_mutex); + mutex_unlock(&ak4531->reg_mutex); return change; } @@ -215,12 +217,12 @@ static int snd_ak4531_get_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl int left_shift = (kcontrol->private_value >> 16) & 0x0f; int right_shift = (kcontrol->private_value >> 24) & 0x0f; - down(&ak4531->reg_mutex); + mutex_lock(&ak4531->reg_mutex); ucontrol->value.integer.value[0] = (ak4531->regs[reg1] >> left_shift) & 1; ucontrol->value.integer.value[1] = (ak4531->regs[reg2] >> left_shift) & 1; ucontrol->value.integer.value[2] = (ak4531->regs[reg1] >> right_shift) & 1; ucontrol->value.integer.value[3] = (ak4531->regs[reg2] >> right_shift) & 1; - up(&ak4531->reg_mutex); + mutex_unlock(&ak4531->reg_mutex); return 0; } @@ -234,7 +236,7 @@ static int snd_ak4531_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl int change; int val1, val2; - down(&ak4531->reg_mutex); + mutex_lock(&ak4531->reg_mutex); val1 = ak4531->regs[reg1] & ~((1 << left_shift) | (1 << right_shift)); val2 = ak4531->regs[reg2] & ~((1 << left_shift) | (1 << right_shift)); val1 |= (ucontrol->value.integer.value[0] & 1) << left_shift; @@ -244,7 +246,7 @@ static int snd_ak4531_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl change = val1 != ak4531->regs[reg1] || val2 != ak4531->regs[reg2]; ak4531->write(ak4531, reg1, ak4531->regs[reg1] = val1); ak4531->write(ak4531, reg2, ak4531->regs[reg2] = val2); - up(&ak4531->reg_mutex); + mutex_unlock(&ak4531->reg_mutex); return change; } @@ -366,7 +368,7 @@ int snd_ak4531_mixer(struct snd_card *card, struct snd_ak4531 *_ak4531, if (ak4531 == NULL) return -ENOMEM; *ak4531 = *_ak4531; - init_MUTEX(&ak4531->reg_mutex); + mutex_init(&ak4531->reg_mutex); if ((err = snd_component_add(card, "AK4531")) < 0) { snd_ak4531_free(ak4531); return err; diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index b7217adaf1d7..12e618851262 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -277,7 +278,7 @@ struct atiixp { unsigned int codec_not_ready_bits; /* for codec detection */ int spdif_over_aclink; /* passed from the module option */ - struct semaphore open_mutex; /* playback open mutex */ + struct mutex open_mutex; /* playback open mutex */ }; @@ -1051,9 +1052,9 @@ static int snd_atiixp_playback_open(struct snd_pcm_substream *substream) struct atiixp *chip = snd_pcm_substream_chip(substream); int err; - down(&chip->open_mutex); + mutex_lock(&chip->open_mutex); err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 0); - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); if (err < 0) return err; substream->runtime->hw.channels_max = chip->max_channels; @@ -1068,9 +1069,9 @@ static int snd_atiixp_playback_close(struct snd_pcm_substream *substream) { struct atiixp *chip = snd_pcm_substream_chip(substream); int err; - down(&chip->open_mutex); + mutex_lock(&chip->open_mutex); err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); return err; } @@ -1090,12 +1091,12 @@ static int snd_atiixp_spdif_open(struct snd_pcm_substream *substream) { struct atiixp *chip = snd_pcm_substream_chip(substream); int err; - down(&chip->open_mutex); + mutex_lock(&chip->open_mutex); if (chip->spdif_over_aclink) /* share DMA_PLAYBACK */ err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 2); else err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_SPDIF], -1); - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); return err; } @@ -1103,12 +1104,12 @@ static int snd_atiixp_spdif_close(struct snd_pcm_substream *substream) { struct atiixp *chip = snd_pcm_substream_chip(substream); int err; - down(&chip->open_mutex); + mutex_lock(&chip->open_mutex); if (chip->spdif_over_aclink) err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); else err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_SPDIF]); - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); return err; } @@ -1560,7 +1561,7 @@ static int __devinit snd_atiixp_create(struct snd_card *card, } spin_lock_init(&chip->reg_lock); - init_MUTEX(&chip->open_mutex); + mutex_init(&chip->open_mutex); chip->card = card; chip->pci = pci; chip->irq = -1; diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 8d8fd5a4ed35..1d3766044643 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -255,7 +256,7 @@ struct atiixp_modem { unsigned int codec_not_ready_bits; /* for codec detection */ int spdif_over_aclink; /* passed from the module option */ - struct semaphore open_mutex; /* playback open mutex */ + struct mutex open_mutex; /* playback open mutex */ }; @@ -911,9 +912,9 @@ static int snd_atiixp_playback_open(struct snd_pcm_substream *substream) struct atiixp_modem *chip = snd_pcm_substream_chip(substream); int err; - down(&chip->open_mutex); + mutex_lock(&chip->open_mutex); err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 0); - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); if (err < 0) return err; return 0; @@ -923,9 +924,9 @@ static int snd_atiixp_playback_close(struct snd_pcm_substream *substream) { struct atiixp_modem *chip = snd_pcm_substream_chip(substream); int err; - down(&chip->open_mutex); + mutex_lock(&chip->open_mutex); err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); return err; } @@ -1233,7 +1234,7 @@ static int __devinit snd_atiixp_create(struct snd_card *card, } spin_lock_init(&chip->reg_lock); - init_MUTEX(&chip->open_mutex); + mutex_init(&chip->open_mutex); chip->card = card; chip->pci = pci; chip->irq = -1; diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index c03b0a0a3b27..2ecbddbbdcf0 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -439,7 +440,7 @@ struct cmipci { struct snd_pcm_hardware *hw_info[3]; /* for playbacks */ int opened[2]; /* open mode */ - struct semaphore open_mutex; + struct mutex open_mutex; unsigned int mixer_insensitive: 1; struct snd_kcontrol *mixer_res_ctl[CM_SAVED_MIXERS]; @@ -641,14 +642,14 @@ static int snd_cmipci_playback2_hw_params(struct snd_pcm_substream *substream, { struct cmipci *cm = snd_pcm_substream_chip(substream); if (params_channels(hw_params) > 2) { - down(&cm->open_mutex); + mutex_lock(&cm->open_mutex); if (cm->opened[CM_CH_PLAY]) { - up(&cm->open_mutex); + mutex_unlock(&cm->open_mutex); return -EBUSY; } /* reserve the channel A */ cm->opened[CM_CH_PLAY] = CM_OPEN_PLAYBACK_MULTI; - up(&cm->open_mutex); + mutex_unlock(&cm->open_mutex); } return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); } @@ -1461,9 +1462,9 @@ static int open_device_check(struct cmipci *cm, int mode, struct snd_pcm_substre * pcm framework doesn't pass file pointer before actually opened, * we can't know whether blocking mode or not in open callback.. */ - down(&cm->open_mutex); + mutex_lock(&cm->open_mutex); if (cm->opened[ch]) { - up(&cm->open_mutex); + mutex_unlock(&cm->open_mutex); return -EBUSY; } cm->opened[ch] = mode; @@ -1475,7 +1476,7 @@ static int open_device_check(struct cmipci *cm, int mode, struct snd_pcm_substre snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENDBDAC); spin_unlock_irq(&cm->reg_lock); } - up(&cm->open_mutex); + mutex_unlock(&cm->open_mutex); return 0; } @@ -1483,7 +1484,7 @@ static void close_device_check(struct cmipci *cm, int mode) { int ch = mode & CM_OPEN_CH_MASK; - down(&cm->open_mutex); + mutex_lock(&cm->open_mutex); if (cm->opened[ch] == mode) { if (cm->channel[ch].substream) { snd_cmipci_ch_reset(cm, ch); @@ -1499,7 +1500,7 @@ static void close_device_check(struct cmipci *cm, int mode) spin_unlock_irq(&cm->reg_lock); } } - up(&cm->open_mutex); + mutex_unlock(&cm->open_mutex); } /* @@ -1546,7 +1547,7 @@ static int snd_cmipci_playback2_open(struct snd_pcm_substream *substream) if ((err = open_device_check(cm, CM_OPEN_PLAYBACK2, substream)) < 0) /* use channel B */ return err; runtime->hw = snd_cmipci_playback2; - down(&cm->open_mutex); + mutex_lock(&cm->open_mutex); if (! cm->opened[CM_CH_PLAY]) { if (cm->can_multi_ch) { runtime->hw.channels_max = cm->max_channels; @@ -1559,7 +1560,7 @@ static int snd_cmipci_playback2_open(struct snd_pcm_substream *substream) } snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); } - up(&cm->open_mutex); + mutex_unlock(&cm->open_mutex); return 0; } @@ -2844,7 +2845,7 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc } spin_lock_init(&cm->reg_lock); - init_MUTEX(&cm->open_mutex); + mutex_init(&cm->open_mutex); cm->device = pci->device; cm->card = card; cm->pci = pci; diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 8fb275d6eb77..69dbf542a6de 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -53,6 +53,8 @@ #include #include #include +#include + #include #include @@ -909,22 +911,22 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream, #ifdef CONFIG_SND_CS46XX_NEW_DSP snd_assert (sample_rate != 0, return -ENXIO); - down (&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); if (_cs46xx_adjust_sample_rate (chip,cpcm,sample_rate)) { - up (&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); return -ENXIO; } snd_assert (cpcm->pcm_channel != NULL); if (!cpcm->pcm_channel) { - up (&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); return -ENXIO; } if (cs46xx_dsp_pcm_channel_set_period (chip,cpcm->pcm_channel,period_size)) { - up (&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); return -EINVAL; } @@ -965,7 +967,7 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream, } if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) { #ifdef CONFIG_SND_CS46XX_NEW_DSP - up (&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); #endif return err; } @@ -989,7 +991,7 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream, } #ifdef CONFIG_SND_CS46XX_NEW_DSP - up (&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); #endif return 0; @@ -1319,7 +1321,7 @@ static int _cs46xx_playback_open_channel (struct snd_pcm_substream *substream,in cpcm->substream = substream; #ifdef CONFIG_SND_CS46XX_NEW_DSP - down (&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); cpcm->pcm_channel = NULL; cpcm->pcm_channel_id = pcm_channel_id; @@ -1328,7 +1330,7 @@ static int _cs46xx_playback_open_channel (struct snd_pcm_substream *substream,in SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_sizes); - up (&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); #else chip->playback_pcm = cpcm; /* HACK */ #endif @@ -1367,9 +1369,9 @@ static int snd_cs46xx_playback_open_iec958(struct snd_pcm_substream *substream) snd_printdd("open raw iec958 channel\n"); - down (&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); cs46xx_iec958_pre_open (chip); - up (&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); return _cs46xx_playback_open_channel(substream,DSP_IEC958_CHANNEL); } @@ -1385,9 +1387,9 @@ static int snd_cs46xx_playback_close_iec958(struct snd_pcm_substream *substream) err = snd_cs46xx_playback_close(substream); - down (&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); cs46xx_iec958_post_close (chip); - up (&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); return err; } @@ -1428,12 +1430,12 @@ static int snd_cs46xx_playback_close(struct snd_pcm_substream *substream) if (!cpcm) return -ENXIO; #ifdef CONFIG_SND_CS46XX_NEW_DSP - down (&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); if (cpcm->pcm_channel) { cs46xx_dsp_destroy_pcm_channel(chip,cpcm->pcm_channel); cpcm->pcm_channel = NULL; } - up (&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); #else chip->playback_pcm = NULL; #endif @@ -1848,7 +1850,7 @@ static int snd_cs46xx_iec958_put(struct snd_kcontrol *kcontrol, switch (kcontrol->private_value) { case CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT: - down (&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); change = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED); if (ucontrol->value.integer.value[0] && !change) cs46xx_dsp_enable_spdif_out(chip); @@ -1856,7 +1858,7 @@ static int snd_cs46xx_iec958_put(struct snd_kcontrol *kcontrol, cs46xx_dsp_disable_spdif_out(chip); res = (change != (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED)); - up (&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); break; case CS46XX_MIXER_SPDIF_INPUT_ELEMENT: change = chip->dsp_spos_instance->spdif_status_in; @@ -1997,12 +1999,12 @@ static int snd_cs46xx_spdif_default_get(struct snd_kcontrol *kcontrol, struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); struct dsp_spos_instance * ins = chip->dsp_spos_instance; - down (&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_default >> 24) & 0xff); ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_default >> 16) & 0xff); ucontrol->value.iec958.status[2] = 0; ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_default) & 0xff); - up (&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); return 0; } @@ -2015,7 +2017,7 @@ static int snd_cs46xx_spdif_default_put(struct snd_kcontrol *kcontrol, unsigned int val; int change; - down (&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[2]) << 16) | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) | @@ -2029,7 +2031,7 @@ static int snd_cs46xx_spdif_default_put(struct snd_kcontrol *kcontrol, if ( !(ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) ) cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val); - up (&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); return change; } @@ -2050,12 +2052,12 @@ static int snd_cs46xx_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); struct dsp_spos_instance * ins = chip->dsp_spos_instance; - down (&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_stream >> 24) & 0xff); ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_stream >> 16) & 0xff); ucontrol->value.iec958.status[2] = 0; ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_stream) & 0xff); - up (&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); return 0; } @@ -2068,7 +2070,7 @@ static int snd_cs46xx_spdif_stream_put(struct snd_kcontrol *kcontrol, unsigned int val; int change; - down (&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[1]) << 16) | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) | @@ -2082,7 +2084,7 @@ static int snd_cs46xx_spdif_stream_put(struct snd_kcontrol *kcontrol, if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN ) cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val); - up (&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); return change; } @@ -3755,7 +3757,7 @@ int __devinit snd_cs46xx_create(struct snd_card *card, } spin_lock_init(&chip->reg_lock); #ifdef CONFIG_SND_CS46XX_NEW_DSP - init_MUTEX(&chip->spos_mutex); + mutex_init(&chip->spos_mutex); #endif chip->card = card; chip->pci = pci; diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index 445a448949e7..8726a68051e7 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c @@ -28,6 +28,8 @@ #include #include #include +#include + #include #include #include @@ -287,7 +289,7 @@ void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip) snd_assert(ins != NULL, return); - down(&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); for (i = 0; i < ins->nscb; ++i) { if (ins->scbs[i].deleted) continue; @@ -298,7 +300,7 @@ void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip) vfree(ins->symbol_table.symbols); kfree(ins->modules); kfree(ins); - up(&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); } int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module) @@ -497,7 +499,7 @@ static void cs46xx_dsp_proc_modules_read (struct snd_info_entry *entry, struct dsp_spos_instance * ins = chip->dsp_spos_instance; int i,j; - down(&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); snd_iprintf(buffer, "MODULES:\n"); for ( i = 0; i < ins->nmodules; ++i ) { snd_iprintf(buffer, "\n%s:\n", ins->modules[i].module_name); @@ -510,7 +512,7 @@ static void cs46xx_dsp_proc_modules_read (struct snd_info_entry *entry, desc->segment_type,desc->offset, desc->size); } } - up(&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); } static void cs46xx_dsp_proc_task_tree_read (struct snd_info_entry *entry, @@ -521,7 +523,7 @@ static void cs46xx_dsp_proc_task_tree_read (struct snd_info_entry *entry, int i, j, col; void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET; - down(&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); snd_iprintf(buffer, "TASK TREES:\n"); for ( i = 0; i < ins->ntask; ++i) { snd_iprintf(buffer,"\n%04x %s:\n",ins->tasks[i].address,ins->tasks[i].task_name); @@ -538,7 +540,7 @@ static void cs46xx_dsp_proc_task_tree_read (struct snd_info_entry *entry, } snd_iprintf(buffer,"\n"); - up(&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); } static void cs46xx_dsp_proc_scb_read (struct snd_info_entry *entry, @@ -548,7 +550,7 @@ static void cs46xx_dsp_proc_scb_read (struct snd_info_entry *entry, struct dsp_spos_instance * ins = chip->dsp_spos_instance; int i; - down(&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); snd_iprintf(buffer, "SCB's:\n"); for ( i = 0; i < ins->nscb; ++i) { if (ins->scbs[i].deleted) @@ -571,7 +573,7 @@ static void cs46xx_dsp_proc_scb_read (struct snd_info_entry *entry, } snd_iprintf(buffer,"\n"); - up(&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); } static void cs46xx_dsp_proc_parameter_dump_read (struct snd_info_entry *entry, @@ -852,14 +854,14 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip) } ins->proc_scb_info_entry = entry; - down(&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); /* register/update SCB's entries on proc */ for (i = 0; i < ins->nscb; ++i) { if (ins->scbs[i].deleted) continue; cs46xx_dsp_proc_register_scb_desc (chip, (ins->scbs + i)); } - up(&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); return 0; } @@ -899,12 +901,12 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip) ins->proc_task_info_entry = NULL; } - down(&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); for (i = 0; i < ins->nscb; ++i) { if (ins->scbs[i].deleted) continue; cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) ); } - up(&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); if (ins->proc_dsp_dir) { snd_info_unregister (ins->proc_dsp_dir); @@ -1694,7 +1696,7 @@ int cs46xx_dsp_enable_spdif_in (struct snd_cs46xx *chip) snd_assert (ins->asynch_rx_scb == NULL,return -EINVAL); snd_assert (ins->spdif_in_src != NULL,return -EINVAL); - down(&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); if ( ! (ins->spdif_status_out & DSP_SPDIF_STATUS_INPUT_CTRL_ENABLED) ) { /* time countdown enable */ @@ -1738,7 +1740,7 @@ int cs46xx_dsp_enable_spdif_in (struct snd_cs46xx *chip) /* monitor state */ ins->spdif_status_in = 1; - up(&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); return 0; } @@ -1750,7 +1752,7 @@ int cs46xx_dsp_disable_spdif_in (struct snd_cs46xx *chip) snd_assert (ins->asynch_rx_scb != NULL, return -EINVAL); snd_assert (ins->spdif_in_src != NULL,return -EINVAL); - down(&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); /* Remove the asynchronous receiver SCB */ cs46xx_dsp_remove_scb (chip,ins->asynch_rx_scb); @@ -1760,7 +1762,7 @@ int cs46xx_dsp_disable_spdif_in (struct snd_cs46xx *chip) /* monitor state */ ins->spdif_status_in = 0; - up(&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); /* restore amplifier */ chip->active_ctrl(chip, -1); @@ -1776,10 +1778,10 @@ int cs46xx_dsp_enable_pcm_capture (struct snd_cs46xx *chip) snd_assert (ins->pcm_input == NULL,return -EINVAL); snd_assert (ins->ref_snoop_scb != NULL,return -EINVAL); - down(&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); ins->pcm_input = cs46xx_add_record_source(chip,ins->ref_snoop_scb,PCMSERIALIN_PCM_SCB_ADDR, "PCMSerialInput_Wave"); - up(&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); return 0; } @@ -1790,10 +1792,10 @@ int cs46xx_dsp_disable_pcm_capture (struct snd_cs46xx *chip) snd_assert (ins->pcm_input != NULL,return -EINVAL); - down(&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); cs46xx_dsp_remove_scb (chip,ins->pcm_input); ins->pcm_input = NULL; - up(&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); return 0; } @@ -1805,10 +1807,10 @@ int cs46xx_dsp_enable_adc_capture (struct snd_cs46xx *chip) snd_assert (ins->adc_input == NULL,return -EINVAL); snd_assert (ins->codec_in_scb != NULL,return -EINVAL); - down(&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); ins->adc_input = cs46xx_add_record_source(chip,ins->codec_in_scb,PCMSERIALIN_SCB_ADDR, "PCMSerialInput_ADC"); - up(&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); return 0; } @@ -1819,10 +1821,10 @@ int cs46xx_dsp_disable_adc_capture (struct snd_cs46xx *chip) snd_assert (ins->adc_input != NULL,return -EINVAL); - down(&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); cs46xx_dsp_remove_scb (chip,ins->adc_input); ins->adc_input = NULL; - up(&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); return 0; } @@ -1869,7 +1871,7 @@ int cs46xx_dsp_set_dac_volume (struct snd_cs46xx * chip, u16 left, u16 right) struct dsp_spos_instance * ins = chip->dsp_spos_instance; struct dsp_scb_descriptor * scb; - down(&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); /* main output */ scb = ins->master_mix_scb->sub_list_ptr; @@ -1888,7 +1890,7 @@ int cs46xx_dsp_set_dac_volume (struct snd_cs46xx * chip, u16 left, u16 right) ins->dac_volume_left = left; ins->dac_volume_right = right; - up(&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); return 0; } @@ -1897,7 +1899,7 @@ int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right) { struct dsp_spos_instance * ins = chip->dsp_spos_instance; - down(&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); if (ins->asynch_rx_scb != NULL) cs46xx_dsp_scb_set_volume (chip,ins->asynch_rx_scb, @@ -1906,7 +1908,7 @@ int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right) ins->spdif_input_volume_left = left; ins->spdif_input_volume_right = right; - up(&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); return 0; } diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index d4e0fb39bd06..2c4ee45fe10c 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c @@ -28,6 +28,8 @@ #include #include #include +#include + #include #include #include @@ -77,7 +79,7 @@ static void cs46xx_dsp_proc_scb_info_read (struct snd_info_entry *entry, ins = chip->dsp_spos_instance; - down(&chip->spos_mutex); + mutex_lock(&chip->spos_mutex); snd_iprintf(buffer,"%04x %s:\n",scb->address,scb->scb_name); for (col = 0,j = 0;j < 0x10; j++,col++) { @@ -105,7 +107,7 @@ static void cs46xx_dsp_proc_scb_info_read (struct snd_info_entry *entry, scb->task_entry->address); snd_iprintf(buffer,"index [%d] ref_count [%d]\n",scb->index,scb->ref_count); - up(&chip->spos_mutex); + mutex_unlock(&chip->spos_mutex); } #endif diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 3c7043b7d4c9..103a3f7708b7 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -36,6 +36,8 @@ #include #include #include +#include + #include #include @@ -1097,8 +1099,7 @@ int __devinit snd_emu10k1_create(struct snd_card *card, spin_lock_init(&emu->voice_lock); spin_lock_init(&emu->synth_lock); spin_lock_init(&emu->memblk_lock); - init_MUTEX(&emu->ptb_lock); - init_MUTEX(&emu->fx8010.lock); + mutex_init(&emu->fx8010.lock); INIT_LIST_HEAD(&emu->mapped_link_head); INIT_LIST_HEAD(&emu->mapped_order_link_head); emu->pci = pci; diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 509837252735..dfba00230d4d 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -32,6 +32,8 @@ #include #include #include +#include + #include #include @@ -874,7 +876,7 @@ static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu, { int err = 0; - down(&emu->fx8010.lock); + mutex_lock(&emu->fx8010.lock); if ((err = snd_emu10k1_verify_controls(emu, icode)) < 0) goto __error; strlcpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name)); @@ -897,7 +899,7 @@ static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu, else snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg); __error: - up(&emu->fx8010.lock); + mutex_unlock(&emu->fx8010.lock); return err; } @@ -906,7 +908,7 @@ static int snd_emu10k1_icode_peek(struct snd_emu10k1 *emu, { int err; - down(&emu->fx8010.lock); + mutex_lock(&emu->fx8010.lock); strlcpy(icode->name, emu->fx8010.name, sizeof(icode->name)); /* ok, do the main job */ err = snd_emu10k1_gpr_peek(emu, icode); @@ -916,7 +918,7 @@ static int snd_emu10k1_icode_peek(struct snd_emu10k1 *emu, err = snd_emu10k1_code_peek(emu, icode); if (err >= 0) err = snd_emu10k1_list_controls(emu, icode); - up(&emu->fx8010.lock); + mutex_unlock(&emu->fx8010.lock); return err; } @@ -932,7 +934,7 @@ static int snd_emu10k1_ipcm_poke(struct snd_emu10k1 *emu, if (ipcm->channels > 32) return -EINVAL; pcm = &emu->fx8010.pcm[ipcm->substream]; - down(&emu->fx8010.lock); + mutex_lock(&emu->fx8010.lock); spin_lock_irq(&emu->reg_lock); if (pcm->opened) { err = -EBUSY; @@ -962,7 +964,7 @@ static int snd_emu10k1_ipcm_poke(struct snd_emu10k1 *emu, } __error: spin_unlock_irq(&emu->reg_lock); - up(&emu->fx8010.lock); + mutex_unlock(&emu->fx8010.lock); return err; } @@ -976,7 +978,7 @@ static int snd_emu10k1_ipcm_peek(struct snd_emu10k1 *emu, if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT) return -EINVAL; pcm = &emu->fx8010.pcm[ipcm->substream]; - down(&emu->fx8010.lock); + mutex_lock(&emu->fx8010.lock); spin_lock_irq(&emu->reg_lock); ipcm->channels = pcm->channels; ipcm->tram_start = pcm->tram_start; @@ -992,7 +994,7 @@ static int snd_emu10k1_ipcm_peek(struct snd_emu10k1 *emu, ipcm->res1 = ipcm->res2 = 0; ipcm->pad = 0; spin_unlock_irq(&emu->reg_lock); - up(&emu->fx8010.lock); + mutex_unlock(&emu->fx8010.lock); return err; } @@ -2308,9 +2310,9 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un return -EPERM; if (get_user(addr, (unsigned int __user *)argp)) return -EFAULT; - down(&emu->fx8010.lock); + mutex_lock(&emu->fx8010.lock); res = snd_emu10k1_fx8010_tram_setup(emu, addr); - up(&emu->fx8010.lock); + mutex_unlock(&emu->fx8010.lock); return res; case SNDRV_EMU10K1_IOCTL_STOP: if (!capable(CAP_SYS_ADMIN)) diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 68c795c03109..e7ec98649f04 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -24,6 +24,8 @@ #include #include #include +#include + #include #include @@ -302,10 +304,10 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst hdr = emu->memhdr; snd_assert(hdr, return NULL); - down(&hdr->block_mutex); + mutex_lock(&hdr->block_mutex); blk = search_empty(emu, runtime->dma_bytes); if (blk == NULL) { - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return NULL; } /* fill buffer addresses but pointers are not stored so that @@ -318,14 +320,14 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst if (idx >= sgbuf->pages) { printk(KERN_ERR "emu: pages overflow! (%d-%d) for %d\n", blk->first_page, blk->last_page, sgbuf->pages); - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return NULL; } #endif addr = sgbuf->table[idx].addr; if (! is_valid_page(emu, addr)) { printk(KERN_ERR "emu: failure page = %d\n", idx); - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return NULL; } emu->page_addr_table[page] = addr; @@ -337,10 +339,10 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst err = snd_emu10k1_memblk_map(emu, blk); if (err < 0) { __snd_util_mem_free(hdr, (struct snd_util_memblk *)blk); - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return NULL; } - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return (struct snd_util_memblk *)blk; } @@ -369,19 +371,19 @@ snd_emu10k1_synth_alloc(struct snd_emu10k1 *hw, unsigned int size) struct snd_emu10k1_memblk *blk; struct snd_util_memhdr *hdr = hw->memhdr; - down(&hdr->block_mutex); + mutex_lock(&hdr->block_mutex); blk = (struct snd_emu10k1_memblk *)__snd_util_mem_alloc(hdr, size); if (blk == NULL) { - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return NULL; } if (synth_alloc_pages(hw, blk)) { __snd_util_mem_free(hdr, (struct snd_util_memblk *)blk); - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return NULL; } snd_emu10k1_memblk_map(hw, blk); - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return (struct snd_util_memblk *)blk; } @@ -396,14 +398,14 @@ snd_emu10k1_synth_free(struct snd_emu10k1 *emu, struct snd_util_memblk *memblk) struct snd_emu10k1_memblk *blk = (struct snd_emu10k1_memblk *)memblk; unsigned long flags; - down(&hdr->block_mutex); + mutex_lock(&hdr->block_mutex); spin_lock_irqsave(&emu->memblk_lock, flags); if (blk->mapped_page >= 0) unmap_memblk(emu, blk); spin_unlock_irqrestore(&emu->memblk_lock, flags); synth_free_pages(emu, blk); __snd_util_mem_free(hdr, memblk); - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return 0; } diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index bee382995fe9..a5533c86b0b6 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -35,6 +35,8 @@ #include #include #include +#include + #include #include #include @@ -379,7 +381,7 @@ MODULE_PARM_DESC(lineio, "Line In to Rear Out (0 = auto, 1 = force)."); struct ensoniq { spinlock_t reg_lock; - struct semaphore src_mutex; + struct mutex src_mutex; int irq; @@ -609,7 +611,7 @@ static void snd_es1371_codec_write(struct snd_ac97 *ac97, struct ensoniq *ensoniq = ac97->private_data; unsigned int t, x; - down(&ensoniq->src_mutex); + mutex_lock(&ensoniq->src_mutex); for (t = 0; t < POLL_COUNT; t++) { if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) { /* save the current state for latter */ @@ -634,11 +636,11 @@ static void snd_es1371_codec_write(struct snd_ac97 *ac97, /* restore SRC reg */ snd_es1371_wait_src_ready(ensoniq); outl(x, ES_REG(ensoniq, 1371_SMPRATE)); - up(&ensoniq->src_mutex); + mutex_unlock(&ensoniq->src_mutex); return; } } - up(&ensoniq->src_mutex); + mutex_unlock(&ensoniq->src_mutex); snd_printk(KERN_ERR "codec write timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC))); } @@ -650,7 +652,7 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97, unsigned int t, x, fail = 0; __again: - down(&ensoniq->src_mutex); + mutex_lock(&ensoniq->src_mutex); for (t = 0; t < POLL_COUNT; t++) { if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) { /* save the current state for latter */ @@ -683,11 +685,11 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97, /* now wait for the stinkin' data (RDY) */ for (t = 0; t < POLL_COUNT; t++) { if ((x = inl(ES_REG(ensoniq, 1371_CODEC))) & ES_1371_CODEC_RDY) { - up(&ensoniq->src_mutex); + mutex_unlock(&ensoniq->src_mutex); return ES_1371_CODEC_READ(x); } } - up(&ensoniq->src_mutex); + mutex_unlock(&ensoniq->src_mutex); if (++fail > 10) { snd_printk(KERN_ERR "codec read timeout (final) " "at 0x%lx, reg = 0x%x [0x%x]\n", @@ -698,7 +700,7 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97, goto __again; } } - up(&ensoniq->src_mutex); + mutex_unlock(&ensoniq->src_mutex); snd_printk(KERN_ERR "es1371: codec read timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC))); return 0; @@ -717,7 +719,7 @@ static void snd_es1371_adc_rate(struct ensoniq * ensoniq, unsigned int rate) { unsigned int n, truncm, freq, result; - down(&ensoniq->src_mutex); + mutex_lock(&ensoniq->src_mutex); n = rate / 3000; if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9))) n--; @@ -742,14 +744,14 @@ static void snd_es1371_adc_rate(struct ensoniq * ensoniq, unsigned int rate) snd_es1371_src_write(ensoniq, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff); snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC, n << 8); snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC + 1, n << 8); - up(&ensoniq->src_mutex); + mutex_unlock(&ensoniq->src_mutex); } static void snd_es1371_dac1_rate(struct ensoniq * ensoniq, unsigned int rate) { unsigned int freq, r; - down(&ensoniq->src_mutex); + mutex_lock(&ensoniq->src_mutex); freq = ((rate << 15) + 1500) / 3000; r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P2 | ES_1371_DIS_R1)) | @@ -763,14 +765,14 @@ static void snd_es1371_dac1_rate(struct ensoniq * ensoniq, unsigned int rate) r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P2 | ES_1371_DIS_R1)); outl(r, ES_REG(ensoniq, 1371_SMPRATE)); - up(&ensoniq->src_mutex); + mutex_unlock(&ensoniq->src_mutex); } static void snd_es1371_dac2_rate(struct ensoniq * ensoniq, unsigned int rate) { unsigned int freq, r; - down(&ensoniq->src_mutex); + mutex_lock(&ensoniq->src_mutex); freq = ((rate << 15) + 1500) / 3000; r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 | ES_1371_DIS_R1)) | @@ -785,7 +787,7 @@ static void snd_es1371_dac2_rate(struct ensoniq * ensoniq, unsigned int rate) r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 | ES_1371_DIS_R1)); outl(r, ES_REG(ensoniq, 1371_SMPRATE)); - up(&ensoniq->src_mutex); + mutex_unlock(&ensoniq->src_mutex); } #endif /* CHIP1371 */ @@ -2123,7 +2125,7 @@ static int __devinit snd_ensoniq_create(struct snd_card *card, return -ENOMEM; } spin_lock_init(&ensoniq->reg_lock); - init_MUTEX(&ensoniq->src_mutex); + mutex_init(&ensoniq->src_mutex); ensoniq->card = card; ensoniq->pci = pci; ensoniq->irq = -1; diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 3747a436f0cd..6a265ab3894e 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -103,6 +103,8 @@ #include #include #include +#include + #include #include #include @@ -569,7 +571,7 @@ struct es1968 { u16 maestro_map[32]; int bobclient; /* active timer instancs */ int bob_freq; /* timer frequency */ - struct semaphore memory_mutex; /* memory lock */ + struct mutex memory_mutex; /* memory lock */ /* APU states */ unsigned char apu[NR_APUS]; @@ -1356,13 +1358,13 @@ static int calc_available_memory_size(struct es1968 *chip) struct list_head *p; int max_size = 0; - down(&chip->memory_mutex); + mutex_lock(&chip->memory_mutex); list_for_each(p, &chip->buf_list) { struct esm_memory *buf = list_entry(p, struct esm_memory, list); if (buf->empty && buf->buf.bytes > max_size) max_size = buf->buf.bytes; } - up(&chip->memory_mutex); + mutex_unlock(&chip->memory_mutex); if (max_size >= 128*1024) max_size = 127*1024; return max_size; @@ -1375,20 +1377,20 @@ static struct esm_memory *snd_es1968_new_memory(struct es1968 *chip, int size) struct list_head *p; size = ((size + ESM_MEM_ALIGN - 1) / ESM_MEM_ALIGN) * ESM_MEM_ALIGN; - down(&chip->memory_mutex); + mutex_lock(&chip->memory_mutex); list_for_each(p, &chip->buf_list) { buf = list_entry(p, struct esm_memory, list); if (buf->empty && buf->buf.bytes >= size) goto __found; } - up(&chip->memory_mutex); + mutex_unlock(&chip->memory_mutex); return NULL; __found: if (buf->buf.bytes > size) { struct esm_memory *chunk = kmalloc(sizeof(*chunk), GFP_KERNEL); if (chunk == NULL) { - up(&chip->memory_mutex); + mutex_unlock(&chip->memory_mutex); return NULL; } chunk->buf = buf->buf; @@ -1400,7 +1402,7 @@ __found: list_add(&chunk->list, &buf->list); } buf->empty = 0; - up(&chip->memory_mutex); + mutex_unlock(&chip->memory_mutex); return buf; } @@ -1409,7 +1411,7 @@ static void snd_es1968_free_memory(struct es1968 *chip, struct esm_memory *buf) { struct esm_memory *chunk; - down(&chip->memory_mutex); + mutex_lock(&chip->memory_mutex); buf->empty = 1; if (buf->list.prev != &chip->buf_list) { chunk = list_entry(buf->list.prev, struct esm_memory, list); @@ -1428,7 +1430,7 @@ static void snd_es1968_free_memory(struct es1968 *chip, struct esm_memory *buf) kfree(chunk); } } - up(&chip->memory_mutex); + mutex_unlock(&chip->memory_mutex); } static void snd_es1968_free_dmabuf(struct es1968 *chip) @@ -2579,7 +2581,7 @@ static int __devinit snd_es1968_create(struct snd_card *card, INIT_LIST_HEAD(&chip->buf_list); INIT_LIST_HEAD(&chip->substream_list); spin_lock_init(&chip->ac97_lock); - init_MUTEX(&chip->memory_mutex); + mutex_init(&chip->memory_mutex); tasklet_init(&chip->hwvol_tq, es1968_update_hw_volume, (unsigned long)chip); chip->card = card; chip->pci = pci; diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 4a6dd97deba6..208a3341ec20 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "hda_codec.h" #include @@ -76,12 +77,12 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int dire unsigned int verb, unsigned int parm) { unsigned int res; - down(&codec->bus->cmd_mutex); + mutex_lock(&codec->bus->cmd_mutex); if (! codec->bus->ops.command(codec, nid, direct, verb, parm)) res = codec->bus->ops.get_response(codec); else res = (unsigned int)-1; - up(&codec->bus->cmd_mutex); + mutex_unlock(&codec->bus->cmd_mutex); return res; } @@ -101,9 +102,9 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, unsigned int verb, unsigned int parm) { int err; - down(&codec->bus->cmd_mutex); + mutex_lock(&codec->bus->cmd_mutex); err = codec->bus->ops.command(codec, nid, direct, verb, parm); - up(&codec->bus->cmd_mutex); + mutex_unlock(&codec->bus->cmd_mutex); return err; } @@ -371,7 +372,7 @@ int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp, bus->modelname = temp->modelname; bus->ops = temp->ops; - init_MUTEX(&bus->cmd_mutex); + mutex_init(&bus->cmd_mutex); INIT_LIST_HEAD(&bus->codec_list); if ((err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops)) < 0) { @@ -523,7 +524,7 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, codec->bus = bus; codec->addr = codec_addr; - init_MUTEX(&codec->spdif_mutex); + mutex_init(&codec->spdif_mutex); init_amp_hash(codec); list_add_tail(&codec->list, &bus->codec_list); @@ -881,12 +882,12 @@ int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ unsigned long pval; int err; - down(&codec->spdif_mutex); /* reuse spdif_mutex */ + mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ pval = kcontrol->private_value; kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); kcontrol->private_value = pval; - up(&codec->spdif_mutex); + mutex_unlock(&codec->spdif_mutex); return err; } @@ -896,7 +897,7 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ unsigned long pval; int i, indices, err = 0, change = 0; - down(&codec->spdif_mutex); /* reuse spdif_mutex */ + mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ pval = kcontrol->private_value; indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; for (i = 0; i < indices; i++) { @@ -907,7 +908,7 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ change |= err; } kcontrol->private_value = pval; - up(&codec->spdif_mutex); + mutex_unlock(&codec->spdif_mutex); return err < 0 ? err : change; } @@ -1011,7 +1012,7 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_c unsigned short val; int change; - down(&codec->spdif_mutex); + mutex_lock(&codec->spdif_mutex); codec->spdif_status = ucontrol->value.iec958.status[0] | ((unsigned int)ucontrol->value.iec958.status[1] << 8) | ((unsigned int)ucontrol->value.iec958.status[2] << 16) | @@ -1026,7 +1027,7 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_c snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_2, val >> 8); } - up(&codec->spdif_mutex); + mutex_unlock(&codec->spdif_mutex); return change; } @@ -1054,7 +1055,7 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, struct sn unsigned short val; int change; - down(&codec->spdif_mutex); + mutex_lock(&codec->spdif_mutex); val = codec->spdif_ctls & ~1; if (ucontrol->value.integer.value[0]) val |= 1; @@ -1066,7 +1067,7 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, struct sn AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | ((val & 1) ? 0 : 0x80)); } - up(&codec->spdif_mutex); + mutex_unlock(&codec->spdif_mutex); return change; } @@ -1150,13 +1151,13 @@ static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol, struct snd unsigned int val = !!ucontrol->value.integer.value[0]; int change; - down(&codec->spdif_mutex); + mutex_lock(&codec->spdif_mutex); change = codec->spdif_in_enable != val; if (change || codec->in_resume) { codec->spdif_in_enable = val; snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val); } - up(&codec->spdif_mutex); + mutex_unlock(&codec->spdif_mutex); return change; } @@ -1824,13 +1825,13 @@ int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *i */ int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout) { - down(&codec->spdif_mutex); + mutex_lock(&codec->spdif_mutex); if (mout->dig_out_used) { - up(&codec->spdif_mutex); + mutex_unlock(&codec->spdif_mutex); return -EBUSY; /* already being used */ } mout->dig_out_used = HDA_DIG_EXCLUSIVE; - up(&codec->spdif_mutex); + mutex_unlock(&codec->spdif_mutex); return 0; } @@ -1839,9 +1840,9 @@ int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mo */ int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout) { - down(&codec->spdif_mutex); + mutex_lock(&codec->spdif_mutex); mout->dig_out_used = 0; - up(&codec->spdif_mutex); + mutex_unlock(&codec->spdif_mutex); return 0; } @@ -1869,7 +1870,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o int chs = substream->runtime->channels; int i; - down(&codec->spdif_mutex); + mutex_lock(&codec->spdif_mutex); if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) { if (chs == 2 && snd_hda_is_supported_format(codec, mout->dig_out_nid, format) && @@ -1883,7 +1884,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0); } } - up(&codec->spdif_mutex); + mutex_unlock(&codec->spdif_mutex); /* front */ snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); @@ -1914,12 +1915,12 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_o snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0); if (mout->hp_nid) snd_hda_codec_setup_stream(codec, mout->hp_nid, 0, 0, 0); - down(&codec->spdif_mutex); + mutex_lock(&codec->spdif_mutex); if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) { snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0); mout->dig_out_used = 0; } - up(&codec->spdif_mutex); + mutex_unlock(&codec->spdif_mutex); return 0; } diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 63e26c7a2b7a..40520e9d5a4b 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -438,7 +438,7 @@ struct hda_bus { struct list_head codec_list; struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; /* caddr -> codec */ - struct semaphore cmd_mutex; + struct mutex cmd_mutex; /* unsolicited event queue */ struct hda_bus_unsolicited *unsol; @@ -559,7 +559,7 @@ struct hda_codec { int amp_info_size; struct hda_amp_info *amp_info; - struct semaphore spdif_mutex; + struct mutex spdif_mutex; unsigned int spdif_status; /* IEC958 status bits */ unsigned short spdif_ctls; /* SPDIF control bits */ unsigned int spdif_in_enable; /* SPDIF input enable? */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index b3f37e7b33c0..dbed2644a192 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include "hda_codec.h" @@ -297,7 +298,7 @@ struct azx { /* locks */ spinlock_t reg_lock; - struct semaphore open_mutex; + struct mutex open_mutex; /* streams (x num_streams) */ struct azx_dev *azx_dev; @@ -993,10 +994,10 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) unsigned long flags; int err; - down(&chip->open_mutex); + mutex_lock(&chip->open_mutex); azx_dev = azx_assign_device(chip, substream->stream); if (azx_dev == NULL) { - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); return -EBUSY; } runtime->hw = azx_pcm_hw; @@ -1008,7 +1009,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if ((err = hinfo->ops.open(hinfo, apcm->codec, substream)) < 0) { azx_release_device(azx_dev); - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); return err; } spin_lock_irqsave(&chip->reg_lock, flags); @@ -1017,7 +1018,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) spin_unlock_irqrestore(&chip->reg_lock, flags); runtime->private_data = azx_dev; - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); return 0; } @@ -1029,14 +1030,14 @@ static int azx_pcm_close(struct snd_pcm_substream *substream) struct azx_dev *azx_dev = get_azx_dev(substream); unsigned long flags; - down(&chip->open_mutex); + mutex_lock(&chip->open_mutex); spin_lock_irqsave(&chip->reg_lock, flags); azx_dev->substream = NULL; azx_dev->running = 0; spin_unlock_irqrestore(&chip->reg_lock, flags); azx_release_device(azx_dev); hinfo->ops.close(hinfo, apcm->codec, substream); - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); return 0; } @@ -1408,7 +1409,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, } spin_lock_init(&chip->reg_lock); - init_MUTEX(&chip->open_mutex); + mutex_init(&chip->open_mutex); chip->card = card; chip->pci = pci; chip->irq = -1; diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 1ada1b075c9a..5a3821ae93a8 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -23,6 +23,8 @@ #include #include #include +#include + #include #include "hda_codec.h" #include "hda_local.h" @@ -60,7 +62,7 @@ struct ad198x_spec { /* PCM information */ struct hda_pcm pcm_rec[2]; /* used in alc_build_pcms() */ - struct semaphore amp_mutex; /* PCM volume/mute control mutex */ + struct mutex amp_mutex; /* PCM volume/mute control mutex */ unsigned int spdif_route; /* dynamic controls, init_verbs and input_mux */ @@ -371,9 +373,9 @@ static int ad1986a_pcm_amp_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct ad198x_spec *ad = codec->spec; - down(&ad->amp_mutex); + mutex_lock(&ad->amp_mutex); snd_hda_mixer_amp_volume_get(kcontrol, ucontrol); - up(&ad->amp_mutex); + mutex_unlock(&ad->amp_mutex); return 0; } @@ -383,13 +385,13 @@ static int ad1986a_pcm_amp_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl struct ad198x_spec *ad = codec->spec; int i, change = 0; - down(&ad->amp_mutex); + mutex_lock(&ad->amp_mutex); for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) { kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT); change |= snd_hda_mixer_amp_volume_put(kcontrol, ucontrol); } kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT); - up(&ad->amp_mutex); + mutex_unlock(&ad->amp_mutex); return change; } @@ -400,9 +402,9 @@ static int ad1986a_pcm_amp_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct ad198x_spec *ad = codec->spec; - down(&ad->amp_mutex); + mutex_lock(&ad->amp_mutex); snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); - up(&ad->amp_mutex); + mutex_unlock(&ad->amp_mutex); return 0; } @@ -412,13 +414,13 @@ static int ad1986a_pcm_amp_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ struct ad198x_spec *ad = codec->spec; int i, change = 0; - down(&ad->amp_mutex); + mutex_lock(&ad->amp_mutex); for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) { kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT); change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); } kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT); - up(&ad->amp_mutex); + mutex_unlock(&ad->amp_mutex); return change; } @@ -544,7 +546,7 @@ static int patch_ad1986a(struct hda_codec *codec) if (spec == NULL) return -ENOMEM; - init_MUTEX(&spec->amp_mutex); + mutex_init(&spec->amp_mutex); codec->spec = spec; spec->multiout.max_channels = 6; @@ -708,7 +710,7 @@ static int patch_ad1983(struct hda_codec *codec) if (spec == NULL) return -ENOMEM; - init_MUTEX(&spec->amp_mutex); + mutex_init(&spec->amp_mutex); codec->spec = spec; spec->multiout.max_channels = 2; @@ -854,7 +856,7 @@ static int patch_ad1981(struct hda_codec *codec) if (spec == NULL) return -ENOMEM; - init_MUTEX(&spec->amp_mutex); + mutex_init(&spec->amp_mutex); codec->spec = spec; spec->multiout.max_channels = 2; @@ -2032,7 +2034,7 @@ static int patch_ad1988(struct hda_codec *codec) if (spec == NULL) return -ENOMEM; - init_MUTEX(&spec->amp_mutex); + mutex_init(&spec->amp_mutex); codec->spec = spec; if (codec->revision_id == AD1988A_REV2) diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 2175f6721347..0f7f4d8263c0 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c @@ -53,6 +53,8 @@ #include #include #include +#include + #include #include "ice1712.h" @@ -210,14 +212,14 @@ static int aureon_ac97_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ele struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned short vol; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F); ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F); if (kcontrol->private_value & AUREON_AC97_STEREO) ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F); - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -252,11 +254,11 @@ static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_el { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); ucontrol->value.integer.value[0] = aureon_ac97_read(ice, kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1; - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -288,11 +290,11 @@ static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ct { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1; - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -488,11 +490,11 @@ static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01; - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -557,9 +559,9 @@ static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1; - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -782,11 +784,11 @@ static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned short val; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; val = val > PCM_MIN ? (val - PCM_MIN) : 0; ucontrol->value.integer.value[0] = val; - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -827,12 +829,12 @@ static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va unsigned short val; int i; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); for (i = 0; i < 2; i++) { val = wm_get(ice, WM_ADC_GAIN + i); ucontrol->value.integer.value[i] = ~val>>5 & 0x1; } - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -874,13 +876,13 @@ static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val int i, idx; unsigned short vol; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); for (i = 0; i < 2; i++) { idx = WM_ADC_GAIN + i; vol = wm_get(ice, idx) & 0x1f; ucontrol->value.integer.value[i] = vol; } - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -951,11 +953,11 @@ static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned short val; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); val = wm_get(ice, WM_ADC_MUX); ucontrol->value.integer.value[0] = val & 7; ucontrol->value.integer.value[1] = (val >> 4) & 7; - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c index 9a51d34e6817..4bbf1e2ae653 100644 --- a/sound/pci/ice1712/delta.c +++ b/sound/pci/ice1712/delta.c @@ -28,6 +28,8 @@ #include #include #include +#include + #include #include #include @@ -130,13 +132,13 @@ static int ap_cs8427_sendbytes(struct snd_i2c_device *device, unsigned char *byt int res = count; unsigned char tmp; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); tmp = ap_cs8427_codec_select(ice); ap_cs8427_write_byte(ice, (device->addr << 1) | 0, tmp); /* address + write mode */ while (count-- > 0) ap_cs8427_write_byte(ice, *bytes++, tmp); ap_cs8427_codec_deassert(ice, tmp); - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return res; } @@ -147,13 +149,13 @@ static int ap_cs8427_readbytes(struct snd_i2c_device *device, unsigned char *byt int res = count; unsigned char tmp; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); tmp = ap_cs8427_codec_select(ice); ap_cs8427_write_byte(ice, (device->addr << 1) | 1, tmp); /* address + read mode */ while (count-- > 0) *bytes++ = ap_cs8427_read_byte(ice, tmp); ap_cs8427_codec_deassert(ice, tmp); - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return res; } @@ -180,7 +182,7 @@ static void snd_ice1712_delta_cs8403_spdif_write(struct snd_ice1712 *ice, unsign /* send byte to transmitter */ mask1 = ICE1712_DELTA_SPDIF_OUT_STAT_CLOCK; mask2 = ICE1712_DELTA_SPDIF_OUT_STAT_DATA; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); for (idx = 7; idx >= 0; idx--) { tmp &= ~(mask1 | mask2); @@ -194,7 +196,7 @@ static void snd_ice1712_delta_cs8403_spdif_write(struct snd_ice1712 *ice, unsign } tmp &= ~mask1; snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); } @@ -296,14 +298,14 @@ static void delta_1010_set_rate_val(struct snd_ice1712 *ice, unsigned int rate) if (rate == 0) /* no hint - S/PDIF input is master, simply return */ return; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); tmp2 = tmp & ~ICE1712_DELTA_DFS; if (rate > 48000) tmp2 |= ICE1712_DELTA_DFS; if (tmp != tmp2) snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp2); - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); } /* @@ -318,9 +320,9 @@ static void delta_ak4524_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) return; /* check before reset ak4524 to avoid unnecessary clicks */ - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); tmp2 = tmp & ~ICE1712_DELTA_DFS; if (rate > 48000) tmp2 |= ICE1712_DELTA_DFS; @@ -329,12 +331,12 @@ static void delta_ak4524_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) /* do it again */ snd_akm4xxx_reset(ak, 1); - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA) & ~ICE1712_DELTA_DFS; if (rate > 48000) tmp |= ICE1712_DELTA_DFS; snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); snd_akm4xxx_reset(ak, 0); } diff --git a/sound/pci/ice1712/hoontech.c b/sound/pci/ice1712/hoontech.c index 3f2f918536f5..3f27d04e7d3c 100644 --- a/sound/pci/ice1712/hoontech.c +++ b/sound/pci/ice1712/hoontech.c @@ -27,6 +27,8 @@ #include #include #include +#include + #include #include "ice1712.h" @@ -48,31 +50,31 @@ static void __devinit snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, un static void __devinit snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int activate) { - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); ICE1712_STDSP24_0_DAREAR(ice->spec.hoontech.boxbits, activate); snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[0]); - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); } static void __devinit snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int activate) { - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); ICE1712_STDSP24_3_MUTE(ice->spec.hoontech.boxbits, activate); snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[3]); - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); } static void __devinit snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int activate) { - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); ICE1712_STDSP24_3_INSEL(ice->spec.hoontech.boxbits, activate); snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[3]); - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); } static void __devinit snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, int chn, int activate) { - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); /* select box */ ICE1712_STDSP24_0_BOX(ice->spec.hoontech.boxbits, box); @@ -115,12 +117,12 @@ static void __devinit snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, i ICE1712_STDSP24_2_MIDI1(ice->spec.hoontech.boxbits, 0); snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]); - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); } static void __devinit snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int master) { - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); /* select box */ ICE1712_STDSP24_0_BOX(ice->spec.hoontech.boxbits, box); @@ -141,15 +143,15 @@ static void __devinit snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int ICE1712_STDSP24_2_MIDIIN(ice->spec.hoontech.boxbits, 1); snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]); - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); } static void __devinit snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int activate) { - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); ICE1712_STDSP24_3_MIDI2(ice->spec.hoontech.boxbits, activate); snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[3]); - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); } static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice) diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index ef6f18558c95..3156a3132990 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -2557,9 +2558,9 @@ static int __devinit snd_ice1712_create(struct snd_card *card, cs8427_timeout = 1000; ice->cs8427_timeout = cs8427_timeout; spin_lock_init(&ice->reg_lock); - init_MUTEX(&ice->gpio_mutex); - init_MUTEX(&ice->i2c_mutex); - init_MUTEX(&ice->open_mutex); + mutex_init(&ice->gpio_mutex); + mutex_init(&ice->i2c_mutex); + mutex_init(&ice->open_mutex); ice->gpio.set_mask = snd_ice1712_set_gpio_mask; ice->gpio.set_dir = snd_ice1712_set_gpio_dir; ice->gpio.set_data = snd_ice1712_set_gpio_data; diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index ce96b3bb6531..d7416a83fcac 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h @@ -334,7 +334,7 @@ struct snd_ice1712 { unsigned int num_total_adcs; /* total ADCs */ unsigned int cur_rate; /* current rate */ - struct semaphore open_mutex; + struct mutex open_mutex; struct snd_pcm_substream *pcm_reserved[4]; struct snd_pcm_hw_constraint_list *hw_rates; /* card-specific rate constraints */ @@ -342,7 +342,7 @@ struct snd_ice1712 { struct snd_akm4xxx *akm; struct snd_ice1712_spdif spdif; - struct semaphore i2c_mutex; /* I2C mutex for ICE1724 registers */ + struct mutex i2c_mutex; /* I2C mutex for ICE1724 registers */ struct snd_i2c_bus *i2c; /* I2C bus */ struct snd_i2c_device *cs8427; /* CS8427 I2C device */ unsigned int cs8427_timeout; /* CS8427 reset timeout in HZ/100 */ @@ -360,7 +360,7 @@ struct snd_ice1712 { void (*set_pro_rate)(struct snd_ice1712 *ice, unsigned int rate); void (*i2s_mclk_changed)(struct snd_ice1712 *ice); } gpio; - struct semaphore gpio_mutex; + struct mutex gpio_mutex; /* other board-specific data */ union { @@ -423,7 +423,7 @@ static inline unsigned int snd_ice1712_gpio_read(struct snd_ice1712 *ice) */ static inline void snd_ice1712_save_gpio_status(struct snd_ice1712 *ice) { - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); ice->gpio.saved[0] = ice->gpio.direction; ice->gpio.saved[1] = ice->gpio.write_mask; } @@ -434,7 +434,7 @@ static inline void snd_ice1712_restore_gpio_status(struct snd_ice1712 *ice) ice->gpio.set_mask(ice, ice->gpio.saved[1]); ice->gpio.direction = ice->gpio.saved[0]; ice->gpio.write_mask = ice->gpio.saved[1]; - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); } /* for bit controls */ diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 71f08c036019..fce616c2761f 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -487,7 +488,7 @@ static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream, int i, chs; chs = params_channels(hw_params); - down(&ice->open_mutex); + mutex_lock(&ice->open_mutex); /* mark surround channels */ if (substream == ice->playback_pro_substream) { /* PDMA0 can be multi-channel up to 8 */ @@ -495,7 +496,7 @@ static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream, for (i = 0; i < chs; i++) { if (ice->pcm_reserved[i] && ice->pcm_reserved[i] != substream) { - up(&ice->open_mutex); + mutex_unlock(&ice->open_mutex); return -EBUSY; } ice->pcm_reserved[i] = substream; @@ -510,7 +511,7 @@ static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream, if (ice->playback_con_substream_ds[i] == substream) { if (ice->pcm_reserved[i] && ice->pcm_reserved[i] != substream) { - up(&ice->open_mutex); + mutex_unlock(&ice->open_mutex); return -EBUSY; } ice->pcm_reserved[i] = substream; @@ -518,7 +519,7 @@ static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream, } } } - up(&ice->open_mutex); + mutex_unlock(&ice->open_mutex); snd_vt1724_set_pro_rate(ice, params_rate(hw_params), 0); return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); } @@ -528,12 +529,12 @@ static int snd_vt1724_pcm_hw_free(struct snd_pcm_substream *substream) struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); int i; - down(&ice->open_mutex); + mutex_lock(&ice->open_mutex); /* unmark surround channels */ for (i = 0; i < 3; i++) if (ice->pcm_reserved[i] == substream) ice->pcm_reserved[i] = NULL; - up(&ice->open_mutex); + mutex_unlock(&ice->open_mutex); return snd_pcm_lib_free_pages(substream); } @@ -778,7 +779,7 @@ static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream) snd_pcm_set_sync(substream); snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); set_rate_constraints(ice, substream); - down(&ice->open_mutex); + mutex_lock(&ice->open_mutex); /* calculate the currently available channels */ for (chs = 0; chs < 3; chs++) { if (ice->pcm_reserved[chs]) @@ -788,7 +789,7 @@ static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream) runtime->hw.channels_max = chs; if (chs > 2) /* channels must be even */ snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 2); - up(&ice->open_mutex); + mutex_unlock(&ice->open_mutex); snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, VT1724_BUFFER_ALIGN); snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, @@ -1128,13 +1129,13 @@ static int snd_vt1724_playback_indep_open(struct snd_pcm_substream *substream) struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - down(&ice->open_mutex); + mutex_lock(&ice->open_mutex); /* already used by PDMA0? */ if (ice->pcm_reserved[substream->number]) { - up(&ice->open_mutex); + mutex_unlock(&ice->open_mutex); return -EBUSY; /* FIXME: should handle blocking mode properly */ } - up(&ice->open_mutex); + mutex_unlock(&ice->open_mutex); runtime->private_data = &vt1724_playback_dma_regs[substream->number]; ice->playback_con_substream_ds[substream->number] = substream; runtime->hw = snd_vt1724_2ch_stereo; @@ -1978,12 +1979,12 @@ unsigned char snd_vt1724_read_i2c(struct snd_ice1712 *ice, { unsigned char val; - down(&ice->i2c_mutex); + mutex_lock(&ice->i2c_mutex); outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR)); outb(dev & ~VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR)); wait_i2c_busy(ice); val = inb(ICEREG1724(ice, I2C_DATA)); - up(&ice->i2c_mutex); + mutex_unlock(&ice->i2c_mutex); //printk("i2c_read: [0x%x,0x%x] = 0x%x\n", dev, addr, val); return val; } @@ -1991,14 +1992,14 @@ unsigned char snd_vt1724_read_i2c(struct snd_ice1712 *ice, void snd_vt1724_write_i2c(struct snd_ice1712 *ice, unsigned char dev, unsigned char addr, unsigned char data) { - down(&ice->i2c_mutex); + mutex_lock(&ice->i2c_mutex); wait_i2c_busy(ice); //printk("i2c_write: [0x%x,0x%x] = 0x%x\n", dev, addr, data); outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR)); outb(data, ICEREG1724(ice, I2C_DATA)); outb(dev | VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR)); wait_i2c_busy(ice); - up(&ice->i2c_mutex); + mutex_unlock(&ice->i2c_mutex); } static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice, @@ -2229,9 +2230,9 @@ static int __devinit snd_vt1724_create(struct snd_card *card, } ice->vt1724 = 1; spin_lock_init(&ice->reg_lock); - init_MUTEX(&ice->gpio_mutex); - init_MUTEX(&ice->open_mutex); - init_MUTEX(&ice->i2c_mutex); + mutex_init(&ice->gpio_mutex); + mutex_init(&ice->open_mutex); + mutex_init(&ice->i2c_mutex); ice->gpio.set_mask = snd_vt1724_set_gpio_mask; ice->gpio.set_dir = snd_vt1724_set_gpio_dir; ice->gpio.set_data = snd_vt1724_set_gpio_data; diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c index ec3757834b93..502da1c8b5f7 100644 --- a/sound/pci/ice1712/phase.c +++ b/sound/pci/ice1712/phase.c @@ -39,6 +39,8 @@ #include #include #include +#include + #include #include "ice1712.h" @@ -273,9 +275,9 @@ static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1; - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -584,11 +586,11 @@ static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned short val; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; val = val > PCM_MIN ? (val - PCM_MIN) : 0; ucontrol->value.integer.value[0] = val; - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c index 0dccd7707a4b..d23fb3fc2133 100644 --- a/sound/pci/ice1712/pontis.c +++ b/sound/pci/ice1712/pontis.c @@ -27,6 +27,8 @@ #include #include #include +#include + #include #include @@ -124,13 +126,13 @@ static int wm_dac_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val unsigned short val; int i; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); for (i = 0; i < 2; i++) { val = wm_get(ice, WM_DAC_ATTEN_L + i) & 0xff; val = val > DAC_MIN ? (val - DAC_MIN) : 0; ucontrol->value.integer.value[i] = val; } - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -140,7 +142,7 @@ static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val unsigned short oval, nval; int i, idx, change = 0; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); for (i = 0; i < 2; i++) { nval = ucontrol->value.integer.value[i]; nval = (nval ? (nval + DAC_MIN) : 0) & 0xff; @@ -152,7 +154,7 @@ static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val change = 1; } } - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return change; } @@ -179,13 +181,13 @@ static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val unsigned short val; int i; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); for (i = 0; i < 2; i++) { val = wm_get(ice, WM_ADC_ATTEN_L + i) & 0xff; val = val > ADC_MIN ? (val - ADC_MIN) : 0; ucontrol->value.integer.value[i] = val; } - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -195,7 +197,7 @@ static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val unsigned short ovol, nvol; int i, idx, change = 0; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); for (i = 0; i < 2; i++) { nvol = ucontrol->value.integer.value[i]; nvol = nvol ? (nvol + ADC_MIN) : 0; @@ -206,7 +208,7 @@ static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val change = 1; } } - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return change; } @@ -227,9 +229,9 @@ static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); int bit = kcontrol->private_value; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); ucontrol->value.integer.value[0] = (wm_get(ice, WM_ADC_MUX) & (1 << bit)) ? 1 : 0; - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -240,7 +242,7 @@ static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val unsigned short oval, nval; int change; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); nval = oval = wm_get(ice, WM_ADC_MUX); if (ucontrol->value.integer.value[0]) nval |= (1 << bit); @@ -250,7 +252,7 @@ static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val if (change) { wm_put(ice, WM_ADC_MUX, nval); } - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -270,9 +272,9 @@ static int wm_bypass_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX) & 0x04) ? 1 : 0; - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -282,7 +284,7 @@ static int wm_bypass_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu unsigned short val, oval; int change = 0; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); val = oval = wm_get(ice, WM_OUT_MUX); if (ucontrol->value.integer.value[0]) val |= 0x04; @@ -292,7 +294,7 @@ static int wm_bypass_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu wm_put(ice, WM_OUT_MUX, val); change = 1; } - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return change; } @@ -312,9 +314,9 @@ static int wm_chswap_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL1) & 0xf0) != 0x90; - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -324,7 +326,7 @@ static int wm_chswap_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu unsigned short val, oval; int change = 0; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); oval = wm_get(ice, WM_DAC_CTRL1); val = oval & 0x0f; if (ucontrol->value.integer.value[0]) @@ -336,7 +338,7 @@ static int wm_chswap_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu wm_put_nocache(ice, WM_DAC_CTRL1, val); change = 1; } - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return change; } @@ -449,9 +451,9 @@ static int cs_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); ucontrol->value.enumerated.item[0] = ice->gpio.saved[0]; - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -461,14 +463,14 @@ static int cs_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu unsigned char val; int change = 0; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); if (ucontrol->value.enumerated.item[0] != ice->gpio.saved[0]) { ice->gpio.saved[0] = ucontrol->value.enumerated.item[0] & 3; val = 0x80 | (ice->gpio.saved[0] << 3); spi_write(ice, CS_DEV, 0x04, val); change = 1; } - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -488,10 +490,10 @@ static int pontis_gpio_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_e static int pontis_gpio_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); /* 4-7 reserved */ ucontrol->value.integer.value[0] = (~ice->gpio.write_mask & 0xffff) | 0x00f0; - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -500,22 +502,22 @@ static int pontis_gpio_mask_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned int val; int changed; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); /* 4-7 reserved */ val = (~ucontrol->value.integer.value[0] & 0xffff) | 0x00f0; changed = val != ice->gpio.write_mask; ice->gpio.write_mask = val; - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return changed; } static int pontis_gpio_dir_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); /* 4-7 reserved */ ucontrol->value.integer.value[0] = ice->gpio.direction & 0xff0f; - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -524,23 +526,23 @@ static int pontis_gpio_dir_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned int val; int changed; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); /* 4-7 reserved */ val = ucontrol->value.integer.value[0] & 0xff0f; changed = (val != ice->gpio.direction); ice->gpio.direction = val; - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return changed; } static int pontis_gpio_data_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask); ucontrol->value.integer.value[0] = snd_ice1712_gpio_read(ice) & 0xffff; - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return 0; } @@ -549,7 +551,7 @@ static int pontis_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned int val, nval; int changed = 0; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask); val = snd_ice1712_gpio_read(ice) & 0xffff; @@ -558,7 +560,7 @@ static int pontis_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el snd_ice1712_gpio_write(ice, nval); changed = 1; } - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); return changed; } @@ -651,14 +653,14 @@ static void wm_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buf struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; char line[64]; unsigned int reg, val; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); while (!snd_info_get_line(buffer, line, sizeof(line))) { if (sscanf(line, "%x %x", ®, &val) != 2) continue; if (reg <= 0x17 && val <= 0xffff) wm_put(ice, reg, val); } - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); } static void wm_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) @@ -666,12 +668,12 @@ static void wm_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buff struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; int reg, val; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); for (reg = 0; reg <= 0x17; reg++) { val = wm_get(ice, reg); snd_iprintf(buffer, "%02x = %04x\n", reg, val); } - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); } static void wm_proc_init(struct snd_ice1712 *ice) @@ -690,14 +692,14 @@ static void cs_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buff struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; int reg, val; - down(&ice->gpio_mutex); + mutex_lock(&ice->gpio_mutex); for (reg = 0; reg <= 0x26; reg++) { val = spi_read(ice, CS_DEV, reg); snd_iprintf(buffer, "%02x = %02x\n", reg, val); } val = spi_read(ice, CS_DEV, 0x7f); snd_iprintf(buffer, "%02x = %02x\n", 0x7f, val); - up(&ice->gpio_mutex); + mutex_unlock(&ice->gpio_mutex); } static void cs_proc_init(struct snd_ice1712 *ice) diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 4eddb512c12f..4721c096335e 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -325,7 +326,7 @@ struct snd_korg1212 { int irq; spinlock_t lock; - struct semaphore open_mutex; + struct mutex open_mutex; struct timer_list timer; /* timer callback for checking ack of stop request */ int stop_pending_cnt; /* counter for stop pending check */ @@ -667,13 +668,13 @@ static int snd_korg1212_OpenCard(struct snd_korg1212 * korg1212) { K1212_DEBUG_PRINTK("K1212_DEBUG: OpenCard [%s] %d\n", stateName[korg1212->cardState], korg1212->opencnt); - down(&korg1212->open_mutex); + mutex_lock(&korg1212->open_mutex); if (korg1212->opencnt++ == 0) { snd_korg1212_TurnOffIdleMonitor(korg1212); snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN); } - up(&korg1212->open_mutex); + mutex_unlock(&korg1212->open_mutex); return 1; } @@ -682,9 +683,9 @@ static int snd_korg1212_CloseCard(struct snd_korg1212 * korg1212) K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard [%s] %d\n", stateName[korg1212->cardState], korg1212->opencnt); - down(&korg1212->open_mutex); + mutex_lock(&korg1212->open_mutex); if (--(korg1212->opencnt)) { - up(&korg1212->open_mutex); + mutex_unlock(&korg1212->open_mutex); return 0; } @@ -695,7 +696,7 @@ static int snd_korg1212_CloseCard(struct snd_korg1212 * korg1212) K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard - RC = %d [%s]\n", rc, stateName[korg1212->cardState]); if (rc != K1212_CMDRET_Success) { - up(&korg1212->open_mutex); + mutex_unlock(&korg1212->open_mutex); return 0; } } else if (korg1212->cardState > K1212_STATE_SETUP) { @@ -707,7 +708,7 @@ static int snd_korg1212_CloseCard(struct snd_korg1212 * korg1212) snd_korg1212_setCardState(korg1212, K1212_STATE_READY); } - up(&korg1212->open_mutex); + mutex_unlock(&korg1212->open_mutex); return 0; } @@ -2179,7 +2180,7 @@ static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev * init_waitqueue_head(&korg1212->wait); spin_lock_init(&korg1212->lock); - init_MUTEX(&korg1212->open_mutex); + mutex_init(&korg1212->open_mutex); init_timer(&korg1212->timer); korg1212->timer.function = snd_korg1212_timer_func; korg1212->timer.data = (unsigned long)korg1212; diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index b218e1d20c78..e79fb264532b 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -589,7 +590,7 @@ static int snd_mixart_hw_params(struct snd_pcm_substream *subs, /* set up format for the stream */ format = params_format(hw); - down(&mgr->setup_mutex); + mutex_lock(&mgr->setup_mutex); /* update the stream levels */ if( stream->pcm_number <= MIXART_PCM_DIGITAL ) { @@ -628,7 +629,7 @@ static int snd_mixart_hw_params(struct snd_pcm_substream *subs, bufferinfo[i].available_length, subs->number); } - up(&mgr->setup_mutex); + mutex_unlock(&mgr->setup_mutex); return err; } @@ -700,7 +701,7 @@ static int snd_mixart_playback_open(struct snd_pcm_substream *subs) int err = 0; int pcm_number; - down(&mgr->setup_mutex); + mutex_lock(&mgr->setup_mutex); if ( pcm == chip->pcm ) { pcm_number = MIXART_PCM_ANALOG; @@ -758,7 +759,7 @@ static int snd_mixart_playback_open(struct snd_pcm_substream *subs) } _exit_open: - up(&mgr->setup_mutex); + mutex_unlock(&mgr->setup_mutex); return err; } @@ -775,7 +776,7 @@ static int snd_mixart_capture_open(struct snd_pcm_substream *subs) int err = 0; int pcm_number; - down(&mgr->setup_mutex); + mutex_lock(&mgr->setup_mutex); if ( pcm == chip->pcm ) { pcm_number = MIXART_PCM_ANALOG; @@ -836,7 +837,7 @@ static int snd_mixart_capture_open(struct snd_pcm_substream *subs) } _exit_open: - up(&mgr->setup_mutex); + mutex_unlock(&mgr->setup_mutex); return err; } @@ -849,7 +850,7 @@ static int snd_mixart_close(struct snd_pcm_substream *subs) struct mixart_mgr *mgr = chip->mgr; struct mixart_stream *stream = subs->runtime->private_data; - down(&mgr->setup_mutex); + mutex_lock(&mgr->setup_mutex); snd_printdd("snd_mixart_close C%d/P%d/Sub%d\n", chip->chip_idx, stream->pcm_number, subs->number); @@ -868,7 +869,7 @@ static int snd_mixart_close(struct snd_pcm_substream *subs) stream->status = MIXART_STREAM_STATUS_FREE; stream->substream = NULL; - up(&mgr->setup_mutex); + mutex_unlock(&mgr->setup_mutex); return 0; } @@ -1335,12 +1336,12 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci, mgr->msg_fifo_writeptr = 0; spin_lock_init(&mgr->msg_lock); - init_MUTEX(&mgr->msg_mutex); + mutex_init(&mgr->msg_mutex); init_waitqueue_head(&mgr->msg_sleep); atomic_set(&mgr->msg_processed, 0); /* init setup mutex*/ - init_MUTEX(&mgr->setup_mutex); + mutex_init(&mgr->setup_mutex); /* init message taslket */ tasklet_init(&mgr->msg_taskq, snd_mixart_msg_tasklet, (unsigned long) mgr); diff --git a/sound/pci/mixart/mixart.h b/sound/pci/mixart/mixart.h index 3e84863ca02c..561634d5c007 100644 --- a/sound/pci/mixart/mixart.h +++ b/sound/pci/mixart/mixart.h @@ -24,6 +24,7 @@ #define __SOUND_MIXART_H #include +#include #include #define MIXART_DRIVER_VERSION 0x000100 /* 0.1.0 */ @@ -92,9 +93,9 @@ struct mixart_mgr { spinlock_t lock; /* interrupt spinlock */ spinlock_t msg_lock; /* mailbox spinlock */ - struct semaphore msg_mutex; /* mutex for blocking_requests */ + struct mutex msg_mutex; /* mutex for blocking_requests */ - struct semaphore setup_mutex; /* mutex used in hw_params, open and close */ + struct mutex setup_mutex; /* mutex used in hw_params, open and close */ /* hardware interface */ unsigned int dsp_loaded; /* bit flags of loaded dsp indices */ @@ -107,7 +108,7 @@ struct mixart_mgr { int sample_rate; int ref_count_rate; - struct semaphore mixer_mutex; /* mutex for mixer */ + struct mutex mixer_mutex; /* mutex for mixer */ }; diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c index 07c707d7ebbf..406ac3a9d42a 100644 --- a/sound/pci/mixart/mixart_core.c +++ b/sound/pci/mixart/mixart_core.c @@ -22,6 +22,8 @@ #include #include +#include + #include #include #include "mixart.h" @@ -239,7 +241,7 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int wait_queue_t wait; long timeout; - down(&mgr->msg_mutex); + mutex_lock(&mgr->msg_mutex); init_waitqueue_entry(&wait, current); @@ -248,7 +250,7 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int err = send_msg(mgr, request, max_resp_size, 1, &msg_frame); /* send and mark the answer pending */ if (err) { spin_unlock_irq(&mgr->msg_lock); - up(&mgr->msg_mutex); + mutex_unlock(&mgr->msg_mutex); return err; } @@ -260,7 +262,7 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int if (! timeout) { /* error - no ack */ - up(&mgr->msg_mutex); + mutex_unlock(&mgr->msg_mutex); snd_printk(KERN_ERR "error: no reponse on msg %x\n", msg_frame); return -EIO; } @@ -276,7 +278,7 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int if( request->message_id != resp.message_id ) snd_printk(KERN_ERR "REPONSE ERROR!\n"); - up(&mgr->msg_mutex); + mutex_unlock(&mgr->msg_mutex); return err; } @@ -292,7 +294,7 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, snd_assert((notif_event & MSG_TYPE_MASK) == MSG_TYPE_NOTIFY, return -EINVAL); snd_assert((notif_event & MSG_CANCEL_NOTIFY_MASK) == 0, return -EINVAL); - down(&mgr->msg_mutex); + mutex_lock(&mgr->msg_mutex); init_waitqueue_entry(&wait, current); @@ -301,7 +303,7 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 1, ¬if_event); /* send and mark the notification event pending */ if(err) { spin_unlock_irq(&mgr->msg_lock); - up(&mgr->msg_mutex); + mutex_unlock(&mgr->msg_mutex); return err; } @@ -313,12 +315,12 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, if (! timeout) { /* error - no ack */ - up(&mgr->msg_mutex); + mutex_unlock(&mgr->msg_mutex); snd_printk(KERN_ERR "error: notification %x not received\n", notif_event); return -EIO; } - up(&mgr->msg_mutex); + mutex_unlock(&mgr->msg_mutex); return 0; } diff --git a/sound/pci/mixart/mixart_mixer.c b/sound/pci/mixart/mixart_mixer.c index 36a7e9ddfb15..ed47b732c103 100644 --- a/sound/pci/mixart/mixart_mixer.c +++ b/sound/pci/mixart/mixart_mixer.c @@ -24,6 +24,8 @@ #include #include #include +#include + #include #include "mixart.h" #include "mixart_core.h" @@ -353,7 +355,7 @@ static int mixart_analog_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int mixart_analog_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); if(kcontrol->private_value == 0) { /* playback */ ucontrol->value.integer.value[0] = chip->analog_playback_volume[0]; ucontrol->value.integer.value[1] = chip->analog_playback_volume[1]; @@ -361,7 +363,7 @@ static int mixart_analog_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e ucontrol->value.integer.value[0] = chip->analog_capture_volume[0]; ucontrol->value.integer.value[1] = chip->analog_capture_volume[1]; } - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -371,7 +373,7 @@ static int mixart_analog_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e int changed = 0; int is_capture, i; - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); is_capture = (kcontrol->private_value != 0); for(i=0; i<2; i++) { int new_volume = ucontrol->value.integer.value[i]; @@ -382,7 +384,7 @@ static int mixart_analog_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e } } if(changed) mixart_update_analog_audio_level(chip, is_capture); - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -408,10 +410,10 @@ static int mixart_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ele { struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->analog_playback_active[0]; ucontrol->value.integer.value[1] = chip->analog_playback_active[1]; - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -419,7 +421,7 @@ static int mixart_audio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele { struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); int i, changed = 0; - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); for(i=0; i<2; i++) { if(chip->analog_playback_active[i] != ucontrol->value.integer.value[i]) { chip->analog_playback_active[i] = ucontrol->value.integer.value[i]; @@ -427,7 +429,7 @@ static int mixart_audio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele } } if(changed) mixart_update_analog_audio_level(chip, 0); /* update playback levels */ - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -817,7 +819,7 @@ static int mixart_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem int *stored_volume; int is_capture = kcontrol->private_value & MIXART_VOL_REC_MASK; int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK; - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); if(is_capture) { if(is_aes) stored_volume = chip->digital_capture_volume[1]; /* AES capture */ else stored_volume = chip->digital_capture_volume[0]; /* analog capture */ @@ -828,7 +830,7 @@ static int mixart_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem } ucontrol->value.integer.value[0] = stored_volume[0]; ucontrol->value.integer.value[1] = stored_volume[1]; - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -841,7 +843,7 @@ static int mixart_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK; int* stored_volume; int i; - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); if(is_capture) { if(is_aes) stored_volume = chip->digital_capture_volume[1]; /* AES capture */ else stored_volume = chip->digital_capture_volume[0]; /* analog capture */ @@ -860,7 +862,7 @@ static int mixart_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem if(is_capture) mixart_update_capture_stream_level(chip, is_aes); else mixart_update_playback_stream_level(chip, is_aes, idx); } - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -880,12 +882,12 @@ static int mixart_pcm_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ snd_assert ( idx < MIXART_PLAYBACK_STREAMS ); - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); if(kcontrol->private_value & MIXART_VOL_AES_MASK) /* AES playback */ idx += MIXART_PLAYBACK_STREAMS; ucontrol->value.integer.value[0] = chip->digital_playback_active[idx][0]; ucontrol->value.integer.value[1] = chip->digital_playback_active[idx][1]; - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -897,7 +899,7 @@ static int mixart_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ int i, j; snd_assert ( idx < MIXART_PLAYBACK_STREAMS ); - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); j = idx; if(is_aes) j += MIXART_PLAYBACK_STREAMS; for(i=0; i<2; i++) { @@ -907,7 +909,7 @@ static int mixart_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ } } if(changed) mixart_update_playback_stream_level(chip, is_aes, idx); - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -956,10 +958,10 @@ static int mixart_update_monitoring(struct snd_mixart* chip, int channel) static int mixart_monitor_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->monitoring_volume[0]; ucontrol->value.integer.value[1] = chip->monitoring_volume[1]; - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -968,7 +970,7 @@ static int mixart_monitor_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); int changed = 0; int i; - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); for(i=0; i<2; i++) { if(chip->monitoring_volume[i] != ucontrol->value.integer.value[i]) { chip->monitoring_volume[i] = ucontrol->value.integer.value[i]; @@ -976,7 +978,7 @@ static int mixart_monitor_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ changed = 1; } } - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -995,10 +997,10 @@ static struct snd_kcontrol_new mixart_control_monitor_vol = { static int mixart_monitor_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->monitoring_active[0]; ucontrol->value.integer.value[1] = chip->monitoring_active[1]; - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -1007,7 +1009,7 @@ static int mixart_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); int changed = 0; int i; - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); for(i=0; i<2; i++) { if(chip->monitoring_active[i] != ucontrol->value.integer.value[i]) { chip->monitoring_active[i] = ucontrol->value.integer.value[i]; @@ -1029,7 +1031,7 @@ static int mixart_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e } } - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return (changed != 0); } @@ -1059,7 +1061,7 @@ int snd_mixart_create_mixer(struct mixart_mgr *mgr) struct snd_mixart *chip; int err, i; - init_MUTEX(&mgr->mixer_mutex); /* can be in another place */ + mutex_init(&mgr->mixer_mutex); /* can be in another place */ for(i=0; inum_cards; i++) { struct snd_kcontrol_new temp; diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 0d0ff54f0fc6..3a3ba6f547bc 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -32,6 +32,8 @@ #include #include #include +#include + #include #include #include @@ -235,7 +237,7 @@ struct nm256 { int irq_acks; irqreturn_t (*interrupt)(int, void *, struct pt_regs *); int badintrcount; /* counter to check bogus interrupts */ - struct semaphore irq_mutex; + struct mutex irq_mutex; struct nm256_stream streams[2]; @@ -459,32 +461,32 @@ snd_nm256_set_format(struct nm256 *chip, struct nm256_stream *s, /* acquire interrupt */ static int snd_nm256_acquire_irq(struct nm256 *chip) { - down(&chip->irq_mutex); + mutex_lock(&chip->irq_mutex); if (chip->irq < 0) { if (request_irq(chip->pci->irq, chip->interrupt, SA_INTERRUPT|SA_SHIRQ, chip->card->driver, chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->pci->irq); - up(&chip->irq_mutex); + mutex_unlock(&chip->irq_mutex); return -EBUSY; } chip->irq = chip->pci->irq; } chip->irq_acks++; - up(&chip->irq_mutex); + mutex_unlock(&chip->irq_mutex); return 0; } /* release interrupt */ static void snd_nm256_release_irq(struct nm256 *chip) { - down(&chip->irq_mutex); + mutex_lock(&chip->irq_mutex); if (chip->irq_acks > 0) chip->irq_acks--; if (chip->irq_acks == 0 && chip->irq >= 0) { free_irq(chip->irq, chip); chip->irq = -1; } - up(&chip->irq_mutex); + mutex_unlock(&chip->irq_mutex); } /* @@ -1407,7 +1409,7 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci, chip->use_cache = use_cache; spin_lock_init(&chip->reg_lock); chip->irq = -1; - init_MUTEX(&chip->irq_mutex); + mutex_init(&chip->irq_mutex); /* store buffer sizes in bytes */ chip->streams[SNDRV_PCM_STREAM_PLAYBACK].bufsize = playback_bufsize * 1024; diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index b2cba75b6b16..31a3e8e1b234 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -28,6 +28,8 @@ #include #include #include +#include + #include #include #include @@ -518,7 +520,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg) struct timeval my_tv1, my_tv2; do_gettimeofday(&my_tv1); #endif - down(&mgr->setup_mutex); + mutex_lock(&mgr->setup_mutex); /* check the pipes concerned and build pipe_array */ for (i = 0; i < mgr->num_cards; i++) { @@ -537,7 +539,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg) } } if (capture_mask == 0 && playback_mask == 0) { - up(&mgr->setup_mutex); + mutex_unlock(&mgr->setup_mutex); snd_printk(KERN_ERR "pcxhr_trigger_tasklet : no pipes\n"); return; } @@ -548,7 +550,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg) /* synchronous stop of all the pipes concerned */ err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0); if (err) { - up(&mgr->setup_mutex); + mutex_unlock(&mgr->setup_mutex); snd_printk(KERN_ERR "pcxhr_trigger_tasklet : error stop pipes (P%x C%x)\n", playback_mask, capture_mask); return; @@ -592,7 +594,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg) /* synchronous start of all the pipes concerned */ err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1); if (err) { - up(&mgr->setup_mutex); + mutex_unlock(&mgr->setup_mutex); snd_printk(KERN_ERR "pcxhr_trigger_tasklet : error start pipes (P%x C%x)\n", playback_mask, capture_mask); return; @@ -619,7 +621,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg) } spin_unlock_irqrestore(&mgr->lock, flags); - up(&mgr->setup_mutex); + mutex_unlock(&mgr->setup_mutex); #ifdef CONFIG_SND_DEBUG_DETECT do_gettimeofday(&my_tv2); @@ -728,7 +730,7 @@ static int pcxhr_prepare(struct snd_pcm_substream *subs) } */ - down(&mgr->setup_mutex); + mutex_lock(&mgr->setup_mutex); do { /* if the stream was stopped before, format and buffer were reset */ @@ -755,7 +757,7 @@ static int pcxhr_prepare(struct snd_pcm_substream *subs) } } while(0); /* do only once (so we can use break instead of goto) */ - up(&mgr->setup_mutex); + mutex_unlock(&mgr->setup_mutex); return err; } @@ -780,7 +782,7 @@ static int pcxhr_hw_params(struct snd_pcm_substream *subs, /* set up format for the stream */ format = params_format(hw); - down(&mgr->setup_mutex); + mutex_lock(&mgr->setup_mutex); stream->channels = channels; stream->format = format; @@ -789,7 +791,7 @@ static int pcxhr_hw_params(struct snd_pcm_substream *subs, /* err = pcxhr_set_format(stream); if(err) { - up(&mgr->setup_mutex); + mutex_unlock(&mgr->setup_mutex); return err; } */ @@ -801,7 +803,7 @@ static int pcxhr_hw_params(struct snd_pcm_substream *subs, err = pcxhr_update_r_buffer(stream); } */ - up(&mgr->setup_mutex); + mutex_unlock(&mgr->setup_mutex); return err; } @@ -847,7 +849,7 @@ static int pcxhr_open(struct snd_pcm_substream *subs) struct pcxhr_stream *stream; int is_capture; - down(&mgr->setup_mutex); + mutex_lock(&mgr->setup_mutex); /* copy the struct snd_pcm_hardware struct */ runtime->hw = pcxhr_caps; @@ -871,7 +873,7 @@ static int pcxhr_open(struct snd_pcm_substream *subs) /* streams in use */ snd_printk(KERN_ERR "pcxhr_open chip%d subs%d in use\n", chip->chip_idx, subs->number); - up(&mgr->setup_mutex); + mutex_unlock(&mgr->setup_mutex); return -EBUSY; } @@ -887,7 +889,7 @@ static int pcxhr_open(struct snd_pcm_substream *subs) &external_rate) || external_rate == 0) { /* cannot detect the external clock rate */ - up(&mgr->setup_mutex); + mutex_unlock(&mgr->setup_mutex); return -EBUSY; } runtime->hw.rate_min = runtime->hw.rate_max = external_rate; @@ -905,7 +907,7 @@ static int pcxhr_open(struct snd_pcm_substream *subs) mgr->ref_count_rate++; - up(&mgr->setup_mutex); + mutex_unlock(&mgr->setup_mutex); return 0; } @@ -916,7 +918,7 @@ static int pcxhr_close(struct snd_pcm_substream *subs) struct pcxhr_mgr *mgr = chip->mgr; struct pcxhr_stream *stream = subs->runtime->private_data; - down(&mgr->setup_mutex); + mutex_lock(&mgr->setup_mutex); snd_printdd("pcxhr_close chip%d subs%d\n", chip->chip_idx, subs->number); @@ -929,7 +931,7 @@ static int pcxhr_close(struct snd_pcm_substream *subs) stream->status = PCXHR_STREAM_STATUS_FREE; stream->substream = NULL; - up(&mgr->setup_mutex); + mutex_unlock(&mgr->setup_mutex); return 0; } @@ -1264,7 +1266,7 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id spin_lock_init(&mgr->msg_lock); /* init setup mutex*/ - init_MUTEX(&mgr->setup_mutex); + mutex_init(&mgr->setup_mutex); /* init taslket */ tasklet_init(&mgr->msg_taskq, pcxhr_msg_tasklet, (unsigned long) mgr); diff --git a/sound/pci/pcxhr/pcxhr.h b/sound/pci/pcxhr/pcxhr.h index 049f2b3f2867..652064787a55 100644 --- a/sound/pci/pcxhr/pcxhr.h +++ b/sound/pci/pcxhr/pcxhr.h @@ -24,6 +24,7 @@ #define __SOUND_PCXHR_H #include +#include #include #define PCXHR_DRIVER_VERSION 0x000804 /* 0.8.4 */ @@ -76,8 +77,8 @@ struct pcxhr_mgr { spinlock_t lock; /* interrupt spinlock */ spinlock_t msg_lock; /* message spinlock */ - struct semaphore setup_mutex; /* mutex used in hw_params, open and close */ - struct semaphore mixer_mutex; /* mutex for mixer */ + struct mutex setup_mutex; /* mutex used in hw_params, open and close */ + struct mutex mixer_mutex; /* mutex for mixer */ /* hardware interface */ unsigned int dsp_loaded; /* bit flags of loaded dsp indices */ diff --git a/sound/pci/pcxhr/pcxhr_mixer.c b/sound/pci/pcxhr/pcxhr_mixer.c index 760e733ac25e..94e63a1e90d9 100644 --- a/sound/pci/pcxhr/pcxhr_mixer.c +++ b/sound/pci/pcxhr/pcxhr_mixer.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "pcxhr.h" #include "pcxhr_hwdep.h" @@ -92,7 +93,7 @@ static int pcxhr_analog_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); if (kcontrol->private_value == 0) { /* playback */ ucontrol->value.integer.value[0] = chip->analog_playback_volume[0]; ucontrol->value.integer.value[1] = chip->analog_playback_volume[1]; @@ -100,7 +101,7 @@ static int pcxhr_analog_vol_get(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[0] = chip->analog_capture_volume[0]; ucontrol->value.integer.value[1] = chip->analog_capture_volume[1]; } - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -111,7 +112,7 @@ static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol, int changed = 0; int is_capture, i; - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); is_capture = (kcontrol->private_value != 0); for (i = 0; i < 2; i++) { int new_volume = ucontrol->value.integer.value[i]; @@ -123,7 +124,7 @@ static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol, pcxhr_update_analog_audio_level(chip, is_capture, i); } } - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -150,10 +151,10 @@ static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol, { struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->analog_playback_active[0]; ucontrol->value.integer.value[1] = chip->analog_playback_active[1]; - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -162,7 +163,7 @@ static int pcxhr_audio_sw_put(struct snd_kcontrol *kcontrol, { struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); int i, changed = 0; - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); for(i = 0; i < 2; i++) { if (chip->analog_playback_active[i] != ucontrol->value.integer.value[i]) { chip->analog_playback_active[i] = ucontrol->value.integer.value[i]; @@ -170,7 +171,7 @@ static int pcxhr_audio_sw_put(struct snd_kcontrol *kcontrol, pcxhr_update_analog_audio_level(chip, 0, i); /* update playback levels */ } } - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -299,14 +300,14 @@ static int pcxhr_pcm_vol_get(struct snd_kcontrol *kcontrol, int *stored_volume; int is_capture = kcontrol->private_value; - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); if (is_capture) stored_volume = chip->digital_capture_volume; /* digital capture */ else stored_volume = chip->digital_playback_volume[idx]; /* digital playback */ ucontrol->value.integer.value[0] = stored_volume[0]; ucontrol->value.integer.value[1] = stored_volume[1]; - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -320,7 +321,7 @@ static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol, int *stored_volume; int i; - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); if (is_capture) stored_volume = chip->digital_capture_volume; /* digital capture */ else @@ -335,7 +336,7 @@ static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol, } if (! is_capture && changed) pcxhr_update_playback_stream_level(chip, idx); /* update playback volume */ - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -356,10 +357,10 @@ static int pcxhr_pcm_sw_get(struct snd_kcontrol *kcontrol, struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->digital_playback_active[idx][0]; ucontrol->value.integer.value[1] = chip->digital_playback_active[idx][1]; - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -370,7 +371,7 @@ static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ int i, j; - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); j = idx; for (i = 0; i < 2; i++) { if (chip->digital_playback_active[j][i] != ucontrol->value.integer.value[i]) { @@ -380,7 +381,7 @@ static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v } if (changed) pcxhr_update_playback_stream_level(chip, idx); - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -402,10 +403,10 @@ static int pcxhr_monitor_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->monitoring_volume[0]; ucontrol->value.integer.value[1] = chip->monitoring_volume[1]; - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -416,7 +417,7 @@ static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol, int changed = 0; int i; - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); for (i = 0; i < 2; i++) { if (chip->monitoring_volume[i] != ucontrol->value.integer.value[i]) { chip->monitoring_volume[i] = ucontrol->value.integer.value[i]; @@ -426,7 +427,7 @@ static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol, changed = 1; } } - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -446,10 +447,10 @@ static int pcxhr_monitor_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); ucontrol->value.integer.value[0] = chip->monitoring_active[0]; ucontrol->value.integer.value[1] = chip->monitoring_active[1]; - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -460,7 +461,7 @@ static int pcxhr_monitor_sw_put(struct snd_kcontrol *kcontrol, int changed = 0; int i; - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); for (i = 0; i < 2; i++) { if (chip->monitoring_active[i] != ucontrol->value.integer.value[i]) { chip->monitoring_active[i] = ucontrol->value.integer.value[i]; @@ -474,7 +475,7 @@ static int pcxhr_monitor_sw_put(struct snd_kcontrol *kcontrol, /* update right monitoring volume and mute */ pcxhr_update_audio_pipe_level(chip, 0, 1); - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return (changed != 0); } @@ -571,13 +572,13 @@ static int pcxhr_audio_src_put(struct snd_kcontrol *kcontrol, struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); int ret = 0; - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); if (chip->audio_capture_source != ucontrol->value.enumerated.item[0]) { chip->audio_capture_source = ucontrol->value.enumerated.item[0]; pcxhr_set_audio_source(chip); ret = 1; } - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return ret; } @@ -636,9 +637,9 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol, struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); int rate, ret = 0; - down(&mgr->mixer_mutex); + mutex_lock(&mgr->mixer_mutex); if (mgr->use_clock_type != ucontrol->value.enumerated.item[0]) { - down(&mgr->setup_mutex); + mutex_lock(&mgr->setup_mutex); mgr->use_clock_type = ucontrol->value.enumerated.item[0]; if (mgr->use_clock_type) pcxhr_get_external_clock(mgr, mgr->use_clock_type, &rate); @@ -649,10 +650,10 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol, if (mgr->sample_rate) mgr->sample_rate = rate; } - up(&mgr->setup_mutex); + mutex_unlock(&mgr->setup_mutex); ret = 1; /* return 1 even if the set was not done. ok ? */ } - up(&mgr->mixer_mutex); + mutex_unlock(&mgr->mixer_mutex); return ret; } @@ -685,7 +686,7 @@ static int pcxhr_clock_rate_get(struct snd_kcontrol *kcontrol, struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); int i, err, rate; - down(&mgr->mixer_mutex); + mutex_lock(&mgr->mixer_mutex); for(i = 0; i < 3 + mgr->capture_chips; i++) { if (i == PCXHR_CLOCK_TYPE_INTERNAL) rate = mgr->sample_rate_real; @@ -696,7 +697,7 @@ static int pcxhr_clock_rate_get(struct snd_kcontrol *kcontrol, } ucontrol->value.integer.value[i] = rate; } - up(&mgr->mixer_mutex); + mutex_unlock(&mgr->mixer_mutex); return 0; } @@ -765,7 +766,7 @@ static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v unsigned char aes_bits; int i, err; - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); for(i = 0; i < 5; i++) { if (kcontrol->private_value == 0) /* playback */ aes_bits = chip->aes_bits[i]; @@ -776,7 +777,7 @@ static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v } ucontrol->value.iec958.status[i] = aes_bits; } - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return 0; } @@ -828,14 +829,14 @@ static int pcxhr_iec958_put(struct snd_kcontrol *kcontrol, int i, changed = 0; /* playback */ - down(&chip->mgr->mixer_mutex); + mutex_lock(&chip->mgr->mixer_mutex); for (i = 0; i < 5; i++) { if (ucontrol->value.iec958.status[i] != chip->aes_bits[i]) { pcxhr_iec958_update_byte(chip, i, ucontrol->value.iec958.status[i]); changed = 1; } } - up(&chip->mgr->mixer_mutex); + mutex_unlock(&chip->mgr->mixer_mutex); return changed; } @@ -916,7 +917,7 @@ int pcxhr_create_mixer(struct pcxhr_mgr *mgr) struct snd_pcxhr *chip; int err, i; - init_MUTEX(&mgr->mixer_mutex); /* can be in another place */ + mutex_init(&mgr->mixer_mutex); /* can be in another place */ for (i = 0; i < mgr->num_cards; i++) { struct snd_kcontrol_new temp; diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c index cf09ea99755c..46c6982c9e88 100644 --- a/sound/pci/trident/trident_memory.c +++ b/sound/pci/trident/trident_memory.c @@ -27,6 +27,8 @@ #include #include #include +#include + #include #include @@ -201,16 +203,16 @@ snd_trident_alloc_sg_pages(struct snd_trident *trident, - down(&hdr->block_mutex); + mutex_lock(&hdr->block_mutex); blk = search_empty(hdr, runtime->dma_bytes); if (blk == NULL) { - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return NULL; } if (lastpg(blk) - firstpg(blk) >= sgbuf->pages) { snd_printk(KERN_ERR "page calculation doesn't match: allocated pages = %d, trident = %d/%d\n", sgbuf->pages, firstpg(blk), lastpg(blk)); __snd_util_mem_free(hdr, blk); - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return NULL; } @@ -221,12 +223,12 @@ snd_trident_alloc_sg_pages(struct snd_trident *trident, unsigned long ptr = (unsigned long)sgbuf->table[idx].buf; if (! is_valid_page(addr)) { __snd_util_mem_free(hdr, blk); - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return NULL; } set_tlb_bus(trident, page, ptr, addr); } - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return blk; } @@ -248,10 +250,10 @@ snd_trident_alloc_cont_pages(struct snd_trident *trident, hdr = trident->tlb.memhdr; snd_assert(hdr != NULL, return NULL); - down(&hdr->block_mutex); + mutex_lock(&hdr->block_mutex); blk = search_empty(hdr, runtime->dma_bytes); if (blk == NULL) { - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return NULL; } @@ -262,12 +264,12 @@ snd_trident_alloc_cont_pages(struct snd_trident *trident, ptr += SNDRV_TRIDENT_PAGE_SIZE, addr += SNDRV_TRIDENT_PAGE_SIZE) { if (! is_valid_page(addr)) { __snd_util_mem_free(hdr, blk); - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return NULL; } set_tlb_bus(trident, page, ptr, addr); } - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return blk; } @@ -300,13 +302,13 @@ int snd_trident_free_pages(struct snd_trident *trident, snd_assert(blk != NULL, return -EINVAL); hdr = trident->tlb.memhdr; - down(&hdr->block_mutex); + mutex_lock(&hdr->block_mutex); /* reset TLB entries */ for (page = firstpg(blk); page <= lastpg(blk); page++) set_silent_tlb(trident, page); /* free memory block */ __snd_util_mem_free(hdr, blk); - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return 0; } @@ -332,18 +334,18 @@ snd_trident_synth_alloc(struct snd_trident *hw, unsigned int size) struct snd_util_memblk *blk; struct snd_util_memhdr *hdr = hw->tlb.memhdr; - down(&hdr->block_mutex); + mutex_lock(&hdr->block_mutex); blk = __snd_util_mem_alloc(hdr, size); if (blk == NULL) { - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return NULL; } if (synth_alloc_pages(hw, blk)) { __snd_util_mem_free(hdr, blk); - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return NULL; } - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return blk; } @@ -356,10 +358,10 @@ snd_trident_synth_free(struct snd_trident *hw, struct snd_util_memblk *blk) { struct snd_util_memhdr *hdr = hw->tlb.memhdr; - down(&hdr->block_mutex); + mutex_lock(&hdr->block_mutex); synth_free_pages(hw, blk); __snd_util_mem_free(hdr, blk); - up(&hdr->block_mutex); + mutex_unlock(&hdr->block_mutex); return 0; } diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c index c705af409b0f..9b6d345b83a6 100644 --- a/sound/pci/vx222/vx222_ops.c +++ b/sound/pci/vx222/vx222_ops.c @@ -24,6 +24,8 @@ #include #include #include +#include + #include #include #include @@ -861,10 +863,10 @@ static int vx_input_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem { struct vx_core *_chip = snd_kcontrol_chip(kcontrol); struct snd_vx222 *chip = (struct snd_vx222 *)_chip; - down(&_chip->mixer_mutex); + mutex_lock(&_chip->mixer_mutex); ucontrol->value.integer.value[0] = chip->input_level[0]; ucontrol->value.integer.value[1] = chip->input_level[1]; - up(&_chip->mixer_mutex); + mutex_unlock(&_chip->mixer_mutex); return 0; } @@ -872,16 +874,16 @@ static int vx_input_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem { struct vx_core *_chip = snd_kcontrol_chip(kcontrol); struct snd_vx222 *chip = (struct snd_vx222 *)_chip; - down(&_chip->mixer_mutex); + mutex_lock(&_chip->mixer_mutex); if (chip->input_level[0] != ucontrol->value.integer.value[0] || chip->input_level[1] != ucontrol->value.integer.value[1]) { chip->input_level[0] = ucontrol->value.integer.value[0]; chip->input_level[1] = ucontrol->value.integer.value[1]; vx2_set_input_level(chip); - up(&_chip->mixer_mutex); + mutex_unlock(&_chip->mixer_mutex); return 1; } - up(&_chip->mixer_mutex); + mutex_unlock(&_chip->mixer_mutex); return 0; } @@ -907,14 +909,14 @@ static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v { struct vx_core *_chip = snd_kcontrol_chip(kcontrol); struct snd_vx222 *chip = (struct snd_vx222 *)_chip; - down(&_chip->mixer_mutex); + mutex_lock(&_chip->mixer_mutex); if (chip->mic_level != ucontrol->value.integer.value[0]) { chip->mic_level = ucontrol->value.integer.value[0]; vx2_set_input_level(chip); - up(&_chip->mixer_mutex); + mutex_unlock(&_chip->mixer_mutex); return 1; } - up(&_chip->mixer_mutex); + mutex_unlock(&_chip->mixer_mutex); return 0; } -- cgit v1.2.3 From 5a25c5cfd4f61f514decca3c4106210fb168ce19 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 18 Jan 2006 08:02:24 +0100 Subject: [ALSA] ymfpci - make rear channel swap optional Modules: YMFPCI driver Added rear_swap module option / kernel parameter to configure the rear channel swapping. Default value is enable to make the AC3 passthrough working, but analog only users might revert the previous behaviour. Signed-off-by: Jaroslav Kysela --- include/sound/ymfpci.h | 10 ++++++---- sound/pci/ymfpci/ymfpci.c | 5 ++++- sound/pci/ymfpci/ymfpci_main.c | 42 ++++++++++++++++++++++++++++-------------- 3 files changed, 38 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/include/sound/ymfpci.h b/include/sound/ymfpci.h index d567bfdbf513..d41cda97e952 100644 --- a/include/sound/ymfpci.h +++ b/include/sound/ymfpci.h @@ -269,9 +269,10 @@ struct snd_ymfpci_pcm { enum snd_ymfpci_pcm_type type; struct snd_pcm_substream *substream; struct snd_ymfpci_voice *voices[2]; /* playback only */ - unsigned int running: 1; - unsigned int output_front: 1; - unsigned int output_rear: 1; + unsigned int running: 1, + output_front: 1, + output_rear: 1, + swap_rear: 1; unsigned int update_pcm_vol; u32 period_size; /* cached from runtime->period_size */ u32 buffer_size; /* cached from runtime->buffer_size */ @@ -344,6 +345,7 @@ struct snd_ymfpci { struct snd_kcontrol *spdif_pcm_ctl; int mode_dup4ch; int rear_opened; + int rear_swap; int spdif_opened; struct { u16 left; @@ -376,7 +378,7 @@ int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm); int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm); int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm); int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm); -int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch); +int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch, int rear_swap); int snd_ymfpci_timer(struct snd_ymfpci *chip, int device); #endif /* __SOUND_YMFPCI_H */ diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index dab9b8310341..db57ce939fa8 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c @@ -49,6 +49,7 @@ static long mpu_port[SNDRV_CARDS]; static long joystick_port[SNDRV_CARDS]; #endif static int rear_switch[SNDRV_CARDS]; +static int rear_swap[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 1 }; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for the Yamaha DS-1 PCI soundcard."); @@ -66,6 +67,8 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address"); #endif module_param_array(rear_switch, bool, NULL, 0444); MODULE_PARM_DESC(rear_switch, "Enable shared rear/line-in switch"); +module_param_array(rear_swap, bool, NULL, 0444); +MODULE_PARM_DESC(rear_swap, "Swap rear channels (must be enabled for correct IEC958 (S/PDIF)) output"); static struct pci_device_id snd_ymfpci_ids[] = { { 0x1073, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* YMF724 */ @@ -295,7 +298,7 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, snd_card_free(card); return err; } - if ((err = snd_ymfpci_mixer(chip, rear_switch[dev])) < 0) { + if ((err = snd_ymfpci_mixer(chip, rear_switch[dev], rear_swap[dev])) < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 30ee53adb494..8ac5ab50b5c7 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -536,19 +536,30 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int } } if (ypcm->output_rear) { - /* The SPDIF out channels seem to be swapped, so we have - * to swap them here, too. The rear analog out channels - * will be wrong, but otherwise AC3 would not work. - */ - if (use_left) { - bank->eff3_gain = - bank->eff3_gain_end = vol_left; - } - if (use_right) { - bank->eff2_gain = - bank->eff2_gain_end = vol_right; - } - } + if (!ypcm->swap_rear) { + if (use_left) { + bank->eff2_gain = + bank->eff2_gain_end = vol_left; + } + if (use_right) { + bank->eff3_gain = + bank->eff3_gain_end = vol_right; + } + } else { + /* The SPDIF out channels seem to be swapped, so we have + * to swap them here, too. The rear analog out channels + * will be wrong, but otherwise AC3 would not work. + */ + if (use_left) { + bank->eff3_gain = + bank->eff3_gain_end = vol_left; + } + if (use_right) { + bank->eff2_gain = + bank->eff2_gain_end = vol_right; + } + } + } } } @@ -898,6 +909,7 @@ static int snd_ymfpci_playback_open(struct snd_pcm_substream *substream) ypcm = runtime->private_data; ypcm->output_front = 1; ypcm->output_rear = chip->mode_dup4ch ? 1 : 0; + ypcm->swap_rear = chip->rear_swap; spin_lock_irq(&chip->reg_lock); if (ypcm->output_rear) { ymfpci_open_extension(chip); @@ -1738,7 +1750,7 @@ static void snd_ymfpci_mixer_free_ac97(struct snd_ac97 *ac97) chip->ac97 = NULL; } -int __devinit snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch) +int __devinit snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch, int rear_swap) { struct snd_ac97_template ac97; struct snd_kcontrol *kctl; @@ -1750,6 +1762,7 @@ int __devinit snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch) .read = snd_ymfpci_codec_read, }; + chip->rear_swap = rear_swap; if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0) return err; chip->ac97_bus->private_free = snd_ymfpci_mixer_free_ac97_bus; @@ -2297,6 +2310,7 @@ int __devinit snd_ymfpci_create(struct snd_card *card, return -EIO; } + chip->rear_swap = 1; if ((err = snd_ymfpci_ac3_init(chip)) < 0) { snd_ymfpci_free(chip); return err; -- cgit v1.2.3 From 50dabc2d1139ba01362418874152aeeb591a4544 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 9 Feb 2006 11:45:20 +0100 Subject: [ALSA] ac97 - Add support of static resolution tables Modules: AC97 Codec Added the support of static resolution table support for codecs that the driver cannot probe the volume resolution properly. The table pointer should be set in each codec patch. Signed-off-by: Takashi Iwai --- include/sound/ac97_codec.h | 7 +++++++ sound/pci/ac97/ac97_codec.c | 12 ++++++++++++ 2 files changed, 19 insertions(+) (limited to 'include') diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index ad3fe046f6cf..9036d25e1bac 100644 --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h @@ -444,6 +444,12 @@ struct snd_ac97_template { DECLARE_BITMAP(reg_accessed, 0x80); /* bit flags */ }; +/* static resolution table */ +struct snd_ac97_res_table { + unsigned short reg; /* register */ + unsigned short bits; /* resolution bitmask */ +}; + struct snd_ac97 { /* -- lowlevel (hardware) driver specific -- */ struct snd_ac97_build_ops * build_ops; @@ -464,6 +470,7 @@ struct snd_ac97 { unsigned short caps; /* capabilities (register 0) */ unsigned short ext_id; /* extended feature identification (register 28) */ unsigned short ext_mid; /* extended modem ID (register 3C) */ + const struct snd_ac97_res_table *res_table; /* static resolution */ unsigned int scaps; /* driver capabilities */ unsigned int flags; /* specific code */ unsigned int rates[6]; /* see AC97_RATES_* defines */ diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 6108cdc5efb6..124c1bc4cb92 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1030,6 +1030,18 @@ static void check_volume_resolution(struct snd_ac97 *ac97, int reg, unsigned cha unsigned char max[3] = { 63, 31, 15 }; int i; + /* first look up the static resolution table */ + if (ac97->res_table) { + const struct snd_ac97_res_table *tbl; + for (tbl = ac97->res_table; tbl->reg; tbl++) { + if (tbl->reg == reg) { + *lo_max = tbl->bits & 0xff; + *hi_max = (tbl->bits >> 8) & 0xff; + return; + } + } + } + *lo_max = *hi_max = 0; for (i = 0 ; i < ARRAY_SIZE(cbit); i++) { unsigned short val; -- cgit v1.2.3 From 7c5706bb33687ce82f30d9ac06dd1bdf71b2262e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 15 Mar 2006 13:52:54 +0100 Subject: [ALSA] ac97 - Allow drivers to set static volume resolution table Modules: AC97 Codec Add the pointer to a static volume resolution table to ac97 template, so that the drivers can define the volume resolution, too. Signed-off-by: Takashi Iwai --- include/sound/ac97_codec.h | 13 +++++++------ sound/pci/ac97/ac97_codec.c | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index 9036d25e1bac..dee766c17e9c 100644 --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h @@ -433,6 +433,12 @@ struct snd_ac97_bus { struct snd_info_entry *proc; }; +/* static resolution table */ +struct snd_ac97_res_table { + unsigned short reg; /* register */ + unsigned short bits; /* resolution bitmask */ +}; + struct snd_ac97_template { void *private_data; void (*private_free) (struct snd_ac97 *ac97); @@ -442,12 +448,7 @@ struct snd_ac97_template { unsigned int scaps; /* driver capabilities */ unsigned int limited_regs; /* allow limited registers only */ DECLARE_BITMAP(reg_accessed, 0x80); /* bit flags */ -}; - -/* static resolution table */ -struct snd_ac97_res_table { - unsigned short reg; /* register */ - unsigned short bits; /* resolution bitmask */ + const struct snd_ac97_res_table *res_table; /* static resolution */ }; struct snd_ac97 { diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 38b6c65d40c3..c5bbdcbf5422 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1868,6 +1868,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, ac97->scaps = template->scaps; ac97->limited_regs = template->limited_regs; memcpy(ac97->reg_accessed, template->reg_accessed, sizeof(ac97->reg_accessed)); + ac97->res_table = template->res_table; bus->codec[ac97->num] = ac97; mutex_init(&ac97->reg_mutex); mutex_init(&ac97->page_mutex); -- cgit v1.2.3 From 0a589d80191471754e6f6cab3015a879bca2f7d2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 15 Mar 2006 14:08:20 +0100 Subject: [ALSA] ac97 - Clean up obsolete workarounds Modules: AC97 Codec Clean up obsolete workarounds provided only for nm256. Signed-off-by: Takashi Iwai --- include/sound/ac97_codec.h | 3 --- sound/pci/ac97/ac97_codec.c | 8 -------- 2 files changed, 11 deletions(-) (limited to 'include') diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index dee766c17e9c..b45a73712748 100644 --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h @@ -446,8 +446,6 @@ struct snd_ac97_template { unsigned short num; /* number of codec: 0 = primary, 1 = secondary */ unsigned short addr; /* physical address of codec [0-3] */ unsigned int scaps; /* driver capabilities */ - unsigned int limited_regs; /* allow limited registers only */ - DECLARE_BITMAP(reg_accessed, 0x80); /* bit flags */ const struct snd_ac97_res_table *res_table; /* static resolution */ }; @@ -477,7 +475,6 @@ struct snd_ac97 { unsigned int rates[6]; /* see AC97_RATES_* defines */ unsigned int spdif_status; unsigned short regs[0x80]; /* register cache */ - unsigned int limited_regs; /* allow limited registers only */ DECLARE_BITMAP(reg_accessed, 0x80); /* bit flags */ union { /* vendor specific code */ struct { diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index c5bbdcbf5422..278319bbdea1 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -192,9 +192,6 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { static int snd_ac97_valid_reg(struct snd_ac97 *ac97, unsigned short reg) { - if (ac97->limited_regs && ! test_bit(reg, ac97->reg_accessed)) - return 0; - /* filter some registers for buggy codecs */ switch (ac97->id) { case AC97_ID_AK4540: @@ -1008,9 +1005,6 @@ static int snd_ac97_try_volume_mix(struct snd_ac97 * ac97, int reg) break; } - if (ac97->limited_regs && test_bit(reg, ac97->reg_accessed)) - return 1; /* allow without check */ - val = snd_ac97_read(ac97, reg); if (!(val & mask)) { /* nothing seems to be here - mute flag is not set */ @@ -1866,8 +1860,6 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, ac97->num = template->num; ac97->addr = template->addr; ac97->scaps = template->scaps; - ac97->limited_regs = template->limited_regs; - memcpy(ac97->reg_accessed, template->reg_accessed, sizeof(ac97->reg_accessed)); ac97->res_table = template->res_table; bus->codec[ac97->num] = ac97; mutex_init(&ac97->reg_mutex); -- cgit v1.2.3 From 9d2f928ddf64ca0361562e30faf584cd33055c60 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 22 Mar 2006 10:53:19 +0100 Subject: [PATCH] Intruduce DMA_28BIT_MASK This patch introduces the DMA_28BIT_MASK constant in dma-mapping.h ALSA drivers using this mask are changed to use the new constant. Signed-off-by: Tobias Klauser Acked-by: Takashi Iwai Acked-by: Jaroslav Kysela --- include/linux/dma-mapping.h | 1 + sound/pci/ad1889.c | 7 ++++--- sound/pci/emu10k1/emu10k1x.c | 13 +++++++------ sound/pci/es1968.c | 5 +++-- sound/pci/ice1712/ice1712.c | 5 +++-- sound/pci/maestro3.c | 5 +++-- sound/pci/mixart/mixart.c | 3 ++- sound/pci/pcxhr/pcxhr.c | 3 ++- 8 files changed, 25 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index 2d80cc761a15..a8731062a74c 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -20,6 +20,7 @@ enum dma_data_direction { #define DMA_31BIT_MASK 0x000000007fffffffULL #define DMA_30BIT_MASK 0x000000003fffffffULL #define DMA_29BIT_MASK 0x000000001fffffffULL +#define DMA_28BIT_MASK 0x000000000fffffffULL #include diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index a208075cdc1e..2aa5a7fdb6e0 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -909,10 +910,10 @@ snd_ad1889_create(struct snd_card *card, if ((err = pci_enable_device(pci)) < 0) return err; - + /* check PCI availability (32bit DMA) */ - if (pci_set_dma_mask(pci, 0xffffffff) < 0 || - pci_set_consistent_dma_mask(pci, 0xffffffff) < 0) { + if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 || + pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) { printk(KERN_ERR PFX "error setting 32-bit DMA mask.\n"); pci_disable_device(pci); return -ENXIO; diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 1107c8ec7f78..2208dbd48be9 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -893,24 +894,24 @@ static int __devinit snd_emu10k1x_create(struct snd_card *card, static struct snd_device_ops ops = { .dev_free = snd_emu10k1x_dev_free, }; - + *rchip = NULL; - + if ((err = pci_enable_device(pci)) < 0) return err; - if (pci_set_dma_mask(pci, 0x0fffffff) < 0 || - pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) { + if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 || + pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) { snd_printk(KERN_ERR "error to set 28bit mask DMA\n"); pci_disable_device(pci); return -ENXIO; } - + chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (chip == NULL) { pci_disable_device(pci); return -ENOMEM; } - + chip->card = card; chip->pci = pci; chip->irq = -1; diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 6a265ab3894e..dd465a186e11 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -100,6 +100,7 @@ #include #include #include +#include #include #include #include @@ -2561,8 +2562,8 @@ static int __devinit snd_es1968_create(struct snd_card *card, if ((err = pci_enable_device(pci)) < 0) return err; /* check, if we can restrict PCI DMA transfers to 28 bits */ - if (pci_set_dma_mask(pci, 0x0fffffff) < 0 || - pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) { + if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 || + pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) { snd_printk(KERN_ERR "architecture does not support 28bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index b96b5d6efc5d..672e198317e1 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -2553,8 +2554,8 @@ static int __devinit snd_ice1712_create(struct snd_card *card, if ((err = pci_enable_device(pci)) < 0) return err; /* check, if we can restrict PCI DMA transfers to 28 bits */ - if (pci_set_dma_mask(pci, 0x0fffffff) < 0 || - pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) { + if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 || + pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) { snd_printk(KERN_ERR "architecture does not support 28bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index d3ef0cc6c4f9..8bc084956c28 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -2657,8 +2658,8 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, return -EIO; /* check, if we can restrict PCI DMA transfers to 28 bits */ - if (pci_set_dma_mask(pci, 0x0fffffff) < 0 || - pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) { + if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 || + pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) { snd_printk(KERN_ERR "architecture does not support 28bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index e79fb264532b..43ee3b2b948f 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -1289,7 +1290,7 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci, pci_set_master(pci); /* check if we can restrict PCI DMA transfers to 32 bits */ - if (pci_set_dma_mask(pci, 0xffffffff) < 0) { + if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0) { snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index 31a3e8e1b234..f679779d96e3 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1217,7 +1218,7 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id pci_set_master(pci); /* check if we can restrict PCI DMA transfers to 32 bits */ - if (pci_set_dma_mask(pci, 0xffffffff) < 0) { + if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0) { snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; -- cgit v1.2.3 From bec1b8193651ea4394cc4d6e18152cb83e735f93 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 22 Mar 2006 10:22:58 +0000 Subject: [ARM] Quieten spurious IRQ detection Only issue a "nobody cared" warning after 99900 spurious interrupts. This avoids the occasional spurious interrupt causing warnings, as per x86. Signed-off-by: Russell King --- arch/arm/kernel/irq.c | 11 ++++++++--- include/asm-arm/mach/irq.h | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 1d50d2b98f55..2d5896b36181 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -305,14 +305,19 @@ report_bad_irq(unsigned int irq, struct pt_regs *regs, struct irqdesc *desc, int static int count = 100; struct irqaction *action; - if (!count || noirqdebug) + if (noirqdebug) return; - count--; - if (ret != IRQ_HANDLED && ret != IRQ_NONE) { + if (!count) + return; + count--; printk("irq%u: bogus retval mask %x\n", irq, ret); } else { + desc->irqs_unhandled++; + if (desc->irqs_unhandled <= 99900) + return; + desc->irqs_unhandled = 0; printk("irq%u: nobody cared\n", irq); } show_regs(regs); diff --git a/include/asm-arm/mach/irq.h b/include/asm-arm/mach/irq.h index 76d05244c632..d4d420ecf3a8 100644 --- a/include/asm-arm/mach/irq.h +++ b/include/asm-arm/mach/irq.h @@ -74,6 +74,7 @@ struct irqdesc { unsigned int noautoenable : 1; /* don't automatically enable IRQ */ unsigned int unused :25; + unsigned int irqs_unhandled; struct proc_dir_entry *procdir; #ifdef CONFIG_SMP -- cgit v1.2.3 From a3c44854a59f7e983c867060aa906bbf5befb1ef Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 22 Mar 2006 14:37:15 +0100 Subject: [ALSA] version 1.0.11rc4 --- include/sound/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sound/version.h b/include/sound/version.h index 919da0dd001c..4f0e65808cf1 100644 --- a/include/sound/version.h +++ b/include/sound/version.h @@ -1,3 +1,3 @@ /* include/version.h. Generated by configure. */ -#define CONFIG_SND_VERSION "1.0.11rc2" -#define CONFIG_SND_DATE " (Wed Jan 04 08:57:20 2006 UTC)" +#define CONFIG_SND_VERSION "1.0.11rc4" +#define CONFIG_SND_DATE " (Wed Mar 22 10:27:24 2006 UTC)" -- cgit v1.2.3 From 152475cb0a65ed73301cfbd7d7afab65536643f7 Mon Sep 17 00:00:00 2001 From: Herbert Poetzl Date: Wed, 22 Mar 2006 00:07:34 -0800 Subject: [PATCH] don't call check_acpi_pci() on x86 with ACPI disabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit check_acpi_pci() is called from arch/i386/kernel/setup.c even if CONFIG_ACPI is not defined, but the code in include/asm/acpi.h doesn't provide it in this case. Signed-off-by: Herbert Pötzl Cc: "Brown, Len" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-i386/acpi.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/asm-i386/acpi.h b/include/asm-i386/acpi.h index 55059abf9c95..20f523954218 100644 --- a/include/asm-i386/acpi.h +++ b/include/asm-i386/acpi.h @@ -103,6 +103,12 @@ __acpi_release_global_lock (unsigned int *lock) :"=r"(n_hi), "=r"(n_lo) \ :"0"(n_hi), "1"(n_lo)) +#ifdef CONFIG_X86_IO_APIC +extern void check_acpi_pci(void); +#else +static inline void check_acpi_pci(void) { } +#endif + #ifdef CONFIG_ACPI extern int acpi_lapic; extern int acpi_ioapic; @@ -128,8 +134,6 @@ extern int acpi_gsi_to_irq(u32 gsi, unsigned int *irq); extern int skip_ioapic_setup; extern int acpi_skip_timer_override; -extern void check_acpi_pci(void); - static inline void disable_ioapic_setup(void) { skip_ioapic_setup = 1; @@ -142,8 +146,6 @@ static inline int ioapic_setup_disabled(void) #else static inline void disable_ioapic_setup(void) { } -static inline void check_acpi_pci(void) { } - #endif static inline void acpi_noirq_set(void) { acpi_noirq = 1; } -- cgit v1.2.3 From 4024ce5e0f396447cc1e07fd65c2a1d056b066bb Mon Sep 17 00:00:00 2001 From: Joe Korty Date: Wed, 22 Mar 2006 00:07:43 -0800 Subject: [PATCH] rtc.h broke strace(1) builds Git patch 52dfa9a64cfb3dd01fa1ee1150d589481e54e28e [PATCH] move rtc_interrupt() prototype to rtc.h broke strace(1) builds. The below moves the kernel-only additions lower, under the already provided #ifdef __KERNEL__ statement. Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/rtc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 0b2ba67ff13c..b739ac1f7ca0 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -11,8 +11,6 @@ #ifndef _LINUX_RTC_H_ #define _LINUX_RTC_H_ -#include - /* * The struct used to pass data via the following ioctl. Similar to the * struct tm in , but it needs to be here so that the kernel @@ -95,6 +93,8 @@ struct rtc_pll_info { #ifdef __KERNEL__ +#include + typedef struct rtc_task { void (*func)(void *private_data); void *private_data; -- cgit v1.2.3 From 2492ecc1a16b8ccf679d2999dca4f1b48aef07ee Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 22 Mar 2006 00:07:57 -0800 Subject: [PATCH] mm: remove set_pgdir leftovers set_pgdir isn't needed anymore for a very long time. Remove the leftover implementation on sh64 and the stub on s390. Signed-off-by: Christoph Hellwig Cc: Heiko Carstens Cc: Martin Schwidefsky Cc: Paul Mundt Cc: Richard Curnow Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-s390/pgalloc.h | 7 ------- include/asm-sh64/pgalloc.h | 16 ---------------- 2 files changed, 23 deletions(-) (limited to 'include') diff --git a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h index 3417dd71ab43..e28aaf28e4a8 100644 --- a/include/asm-s390/pgalloc.h +++ b/include/asm-s390/pgalloc.h @@ -158,11 +158,4 @@ static inline void pte_free(struct page *pte) #define __pte_free_tlb(tlb,pte) tlb_remove_page(tlb,pte) -/* - * This establishes kernel virtual mappings (e.g., as a result of a - * vmalloc call). Since s390-esame uses a separate kernel page table, - * there is nothing to do here... :) - */ -#define set_pgdir(addr,entry) do { } while(0) - #endif /* _S390_PGALLOC_H */ diff --git a/include/asm-sh64/pgalloc.h b/include/asm-sh64/pgalloc.h index 678251ac1db8..b29dd468817e 100644 --- a/include/asm-sh64/pgalloc.h +++ b/include/asm-sh64/pgalloc.h @@ -167,22 +167,6 @@ static __inline__ void pmd_free(pmd_t *pmd) extern int do_check_pgt_cache(int, int); -static inline void set_pgdir(unsigned long address, pgd_t entry) -{ - struct task_struct * p; - pgd_t *pgd; - - read_lock(&tasklist_lock); - for_each_process(p) { - if (!p->mm) - continue; - *pgd_offset(p->mm,address) = entry; - } - read_unlock(&tasklist_lock); - for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd) - pgd[address >> PGDIR_SHIFT] = entry; -} - #define pmd_populate_kernel(mm, pmd, pte) \ set_pmd(pmd, __pmd(_PAGE_TABLE + (unsigned long) (pte))) -- cgit v1.2.3 From 8d438f96d2b8eade6cbcd8adfc22dae6f5cbd6c0 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 22 Mar 2006 00:07:59 -0800 Subject: [PATCH] mm: PageLRU no testset PG_lru is protected by zone->lru_lock. It does not need TestSet/TestClear operations. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/page-flags.h | 5 ++--- mm/swap.c | 16 ++++++++-------- mm/vmscan.c | 20 +++++++++++--------- 3 files changed, 21 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index d52999c43336..58856c823f8b 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -239,10 +239,9 @@ extern void __mod_page_state_offset(unsigned long offset, unsigned long delta); #define __ClearPageDirty(page) __clear_bit(PG_dirty, &(page)->flags) #define TestClearPageDirty(page) test_and_clear_bit(PG_dirty, &(page)->flags) -#define SetPageLRU(page) set_bit(PG_lru, &(page)->flags) #define PageLRU(page) test_bit(PG_lru, &(page)->flags) -#define TestSetPageLRU(page) test_and_set_bit(PG_lru, &(page)->flags) -#define TestClearPageLRU(page) test_and_clear_bit(PG_lru, &(page)->flags) +#define SetPageLRU(page) set_bit(PG_lru, &(page)->flags) +#define ClearPageLRU(page) clear_bit(PG_lru, &(page)->flags) #define PageActive(page) test_bit(PG_active, &(page)->flags) #define SetPageActive(page) set_bit(PG_active, &(page)->flags) diff --git a/mm/swap.c b/mm/swap.c index 3045a0f4c451..985324ee9368 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -214,8 +214,8 @@ void fastcall __page_cache_release(struct page *page) struct zone *zone = page_zone(page); spin_lock_irqsave(&zone->lru_lock, flags); - if (!TestClearPageLRU(page)) - BUG(); + BUG_ON(!PageLRU(page)); + ClearPageLRU(page); del_page_from_lru(zone, page); spin_unlock_irqrestore(&zone->lru_lock, flags); } @@ -265,8 +265,8 @@ void release_pages(struct page **pages, int nr, int cold) zone = pagezone; spin_lock_irq(&zone->lru_lock); } - if (!TestClearPageLRU(page)) - BUG(); + BUG_ON(!PageLRU(page)); + ClearPageLRU(page); del_page_from_lru(zone, page); } @@ -345,8 +345,8 @@ void __pagevec_lru_add(struct pagevec *pvec) zone = pagezone; spin_lock_irq(&zone->lru_lock); } - if (TestSetPageLRU(page)) - BUG(); + BUG_ON(PageLRU(page)); + SetPageLRU(page); add_page_to_inactive_list(zone, page); } if (zone) @@ -372,8 +372,8 @@ void __pagevec_lru_add_active(struct pagevec *pvec) zone = pagezone; spin_lock_irq(&zone->lru_lock); } - if (TestSetPageLRU(page)) - BUG(); + BUG_ON(PageLRU(page)); + SetPageLRU(page); if (TestSetPageActive(page)) BUG(); add_page_to_active_list(zone, page); diff --git a/mm/vmscan.c b/mm/vmscan.c index acb7611cd525..40fb37828e8c 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1042,9 +1042,10 @@ int isolate_lru_page(struct page *page) if (PageLRU(page)) { struct zone *zone = page_zone(page); spin_lock_irq(&zone->lru_lock); - if (TestClearPageLRU(page)) { + if (PageLRU(page)) { ret = 1; get_page(page); + ClearPageLRU(page); if (PageActive(page)) del_page_from_active_list(zone, page); else @@ -1085,6 +1086,8 @@ static int isolate_lru_pages(int nr_to_scan, struct list_head *src, page = lru_to_page(src); prefetchw_prev_lru_page(page, src, flags); + BUG_ON(!PageLRU(page)); + list_del(&page->lru); if (unlikely(get_page_testone(page))) { /* @@ -1100,8 +1103,7 @@ static int isolate_lru_pages(int nr_to_scan, struct list_head *src, * the page is not being freed elsewhere -- the page release * code relies on it. */ - if (!TestClearPageLRU(page)) - BUG(); + ClearPageLRU(page); list_add(&page->lru, dst); nr_taken++; } @@ -1156,8 +1158,8 @@ static void shrink_cache(struct zone *zone, struct scan_control *sc) */ while (!list_empty(&page_list)) { page = lru_to_page(&page_list); - if (TestSetPageLRU(page)) - BUG(); + BUG_ON(PageLRU(page)); + SetPageLRU(page); list_del(&page->lru); if (PageActive(page)) add_page_to_active_list(zone, page); @@ -1276,8 +1278,8 @@ refill_inactive_zone(struct zone *zone, struct scan_control *sc) while (!list_empty(&l_inactive)) { page = lru_to_page(&l_inactive); prefetchw_prev_lru_page(page, &l_inactive, flags); - if (TestSetPageLRU(page)) - BUG(); + BUG_ON(PageLRU(page)); + SetPageLRU(page); if (!TestClearPageActive(page)) BUG(); list_move(&page->lru, &zone->inactive_list); @@ -1305,8 +1307,8 @@ refill_inactive_zone(struct zone *zone, struct scan_control *sc) while (!list_empty(&l_active)) { page = lru_to_page(&l_active); prefetchw_prev_lru_page(page, &l_active, flags); - if (TestSetPageLRU(page)) - BUG(); + BUG_ON(PageLRU(page)); + SetPageLRU(page); BUG_ON(!PageActive(page)); list_move(&page->lru, &zone->active_list); pgmoved++; -- cgit v1.2.3 From 4c84cacfa424264f7ad5287298d3ea4a3e935278 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 22 Mar 2006 00:08:00 -0800 Subject: [PATCH] mm: PageActive no testset PG_active is protected by zone->lru_lock, it does not need TestSet/TestClear operations. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/page-flags.h | 2 -- mm/swap.c | 4 ++-- mm/vmscan.c | 5 +++-- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 58856c823f8b..5d1e7bd85107 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -246,8 +246,6 @@ extern void __mod_page_state_offset(unsigned long offset, unsigned long delta); #define PageActive(page) test_bit(PG_active, &(page)->flags) #define SetPageActive(page) set_bit(PG_active, &(page)->flags) #define ClearPageActive(page) clear_bit(PG_active, &(page)->flags) -#define TestClearPageActive(page) test_and_clear_bit(PG_active, &(page)->flags) -#define TestSetPageActive(page) test_and_set_bit(PG_active, &(page)->flags) #define PageSlab(page) test_bit(PG_slab, &(page)->flags) #define SetPageSlab(page) set_bit(PG_slab, &(page)->flags) diff --git a/mm/swap.c b/mm/swap.c index 985324ee9368..cf88226cf96d 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -374,8 +374,8 @@ void __pagevec_lru_add_active(struct pagevec *pvec) } BUG_ON(PageLRU(page)); SetPageLRU(page); - if (TestSetPageActive(page)) - BUG(); + BUG_ON(PageActive(page)); + SetPageActive(page); add_page_to_active_list(zone, page); } if (zone) diff --git a/mm/vmscan.c b/mm/vmscan.c index 40fb37828e8c..8e477b1a4838 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1280,8 +1280,9 @@ refill_inactive_zone(struct zone *zone, struct scan_control *sc) prefetchw_prev_lru_page(page, &l_inactive, flags); BUG_ON(PageLRU(page)); SetPageLRU(page); - if (!TestClearPageActive(page)) - BUG(); + BUG_ON(!PageActive(page)); + ClearPageActive(page); + list_move(&page->lru, &zone->inactive_list); pgmoved++; if (!pagevec_add(&pvec, page)) { -- cgit v1.2.3 From 674539115cc88473f623581e1d53c0e2ecef2179 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 22 Mar 2006 00:08:00 -0800 Subject: [PATCH] mm: less atomic ops In the page release paths, we can be sure that nobody will mess with our page->flags because the refcount has dropped to 0. So no need for atomic operations here. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mm_inline.h | 2 +- include/linux/page-flags.h | 2 ++ mm/swap.c | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index 8ac854f7f190..3b6723dfaff3 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -32,7 +32,7 @@ del_page_from_lru(struct zone *zone, struct page *page) { list_del(&page->lru); if (PageActive(page)) { - ClearPageActive(page); + __ClearPageActive(page); zone->nr_active--; } else { zone->nr_inactive--; diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 5d1e7bd85107..da71d63df465 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -242,10 +242,12 @@ extern void __mod_page_state_offset(unsigned long offset, unsigned long delta); #define PageLRU(page) test_bit(PG_lru, &(page)->flags) #define SetPageLRU(page) set_bit(PG_lru, &(page)->flags) #define ClearPageLRU(page) clear_bit(PG_lru, &(page)->flags) +#define __ClearPageLRU(page) __clear_bit(PG_lru, &(page)->flags) #define PageActive(page) test_bit(PG_active, &(page)->flags) #define SetPageActive(page) set_bit(PG_active, &(page)->flags) #define ClearPageActive(page) clear_bit(PG_active, &(page)->flags) +#define __ClearPageActive(page) __clear_bit(PG_active, &(page)->flags) #define PageSlab(page) test_bit(PG_slab, &(page)->flags) #define SetPageSlab(page) set_bit(PG_slab, &(page)->flags) diff --git a/mm/swap.c b/mm/swap.c index cf88226cf96d..91b7e2026f69 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -215,7 +215,7 @@ void fastcall __page_cache_release(struct page *page) spin_lock_irqsave(&zone->lru_lock, flags); BUG_ON(!PageLRU(page)); - ClearPageLRU(page); + __ClearPageLRU(page); del_page_from_lru(zone, page); spin_unlock_irqrestore(&zone->lru_lock, flags); } @@ -266,7 +266,7 @@ void release_pages(struct page **pages, int nr, int cold) spin_lock_irq(&zone->lru_lock); } BUG_ON(!PageLRU(page)); - ClearPageLRU(page); + __ClearPageLRU(page); del_page_from_lru(zone, page); } -- cgit v1.2.3 From 5e9dace8d386def04219134d7160e8a778824764 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 22 Mar 2006 00:08:01 -0800 Subject: [PATCH] mm: page_alloc less atomics More atomic operation removal from page allocator Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/page-flags.h | 4 ++-- mm/page_alloc.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index da71d63df465..76c7ffdd0424 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -328,8 +328,8 @@ extern void __mod_page_state_offset(unsigned long offset, unsigned long delta); #define TestClearPageReclaim(page) test_and_clear_bit(PG_reclaim, &(page)->flags) #define PageCompound(page) test_bit(PG_compound, &(page)->flags) -#define SetPageCompound(page) set_bit(PG_compound, &(page)->flags) -#define ClearPageCompound(page) clear_bit(PG_compound, &(page)->flags) +#define __SetPageCompound(page) __set_bit(PG_compound, &(page)->flags) +#define __ClearPageCompound(page) __clear_bit(PG_compound, &(page)->flags) #ifdef CONFIG_SWAP #define PageSwapCache(page) test_bit(PG_swapcache, &(page)->flags) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 61775866ea18..102919851353 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -190,7 +190,7 @@ static void prep_compound_page(struct page *page, unsigned long order) for (i = 0; i < nr_pages; i++) { struct page *p = page + i; - SetPageCompound(p); + __SetPageCompound(p); set_page_private(p, (unsigned long)page); } } @@ -209,7 +209,7 @@ static void destroy_compound_page(struct page *page, unsigned long order) if (unlikely(!PageCompound(p) | (page_private(p) != (unsigned long)page))) bad_page(page); - ClearPageCompound(p); + __ClearPageCompound(p); } } -- cgit v1.2.3 From f205b2fe62d321403525065a4cb31b6bff1bbe53 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 22 Mar 2006 00:08:02 -0800 Subject: [PATCH] mm: slab less atomics Atomic operation removal from slab Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/page-flags.h | 6 ++---- mm/slab.c | 6 +++--- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 76c7ffdd0424..8cef69d462f2 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -250,10 +250,8 @@ extern void __mod_page_state_offset(unsigned long offset, unsigned long delta); #define __ClearPageActive(page) __clear_bit(PG_active, &(page)->flags) #define PageSlab(page) test_bit(PG_slab, &(page)->flags) -#define SetPageSlab(page) set_bit(PG_slab, &(page)->flags) -#define ClearPageSlab(page) clear_bit(PG_slab, &(page)->flags) -#define TestClearPageSlab(page) test_and_clear_bit(PG_slab, &(page)->flags) -#define TestSetPageSlab(page) test_and_set_bit(PG_slab, &(page)->flags) +#define __SetPageSlab(page) __set_bit(PG_slab, &(page)->flags) +#define __ClearPageSlab(page) __clear_bit(PG_slab, &(page)->flags) #ifdef CONFIG_HIGHMEM #define PageHighMem(page) is_highmem(page_zone(page)) diff --git a/mm/slab.c b/mm/slab.c index d0bd7f07ab04..5988adf010c5 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1402,7 +1402,7 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid) atomic_add(i, &slab_reclaim_pages); add_page_state(nr_slab, i); while (i--) { - SetPageSlab(page); + __SetPageSlab(page); page++; } return addr; @@ -1418,8 +1418,8 @@ static void kmem_freepages(struct kmem_cache *cachep, void *addr) const unsigned long nr_freed = i; while (i--) { - if (!TestClearPageSlab(page)) - BUG(); + BUG_ON(!PageSlab(page)); + __ClearPageSlab(page); page++; } sub_page_state(nr_slab, nr_freed); -- cgit v1.2.3 From 7c8ee9a86340db686cd4314e9944dc9b6111bda9 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 22 Mar 2006 00:08:03 -0800 Subject: [PATCH] mm: simplify vmscan vs release refcounting The VM has an interesting race where a page refcount can drop to zero, but it is still on the LRU lists for a short time. This was solved by testing a 0->1 refcount transition when picking up pages from the LRU, and dropping the refcount in that case. Instead, use atomic_add_unless to ensure we never pick up a 0 refcount page from the LRU, thus a 0 refcount page will never have its refcount elevated until it is allocated again. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mm.h | 19 +++++++++++-------- mm/vmscan.c | 25 +++++++++++-------------- 2 files changed, 22 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/include/linux/mm.h b/include/linux/mm.h index 498ff8778fb6..b12d5c76420d 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -301,17 +301,20 @@ struct page { * Drop a ref, return true if the logical refcount fell to zero (the page has * no users) */ -#define put_page_testzero(p) \ - ({ \ - BUG_ON(atomic_read(&(p)->_count) == -1);\ - atomic_add_negative(-1, &(p)->_count); \ - }) +static inline int put_page_testzero(struct page *page) +{ + BUG_ON(atomic_read(&page->_count) == -1); + return atomic_add_negative(-1, &page->_count); +} /* - * Grab a ref, return true if the page previously had a logical refcount of - * zero. ie: returns true if we just grabbed an already-deemed-to-be-free page + * Try to grab a ref unless the page has a refcount of zero, return false if + * that is the case. */ -#define get_page_testone(p) atomic_inc_and_test(&(p)->_count) +static inline int get_page_unless_zero(struct page *page) +{ + return atomic_add_unless(&page->_count, 1, -1); +} #define set_page_count(p,v) atomic_set(&(p)->_count, (v) - 1) #define __put_page(p) atomic_dec(&(p)->_count) diff --git a/mm/vmscan.c b/mm/vmscan.c index 8e477b1a4838..e21bab4deda6 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1083,29 +1083,26 @@ static int isolate_lru_pages(int nr_to_scan, struct list_head *src, int scan = 0; while (scan++ < nr_to_scan && !list_empty(src)) { + struct list_head *target; page = lru_to_page(src); prefetchw_prev_lru_page(page, src, flags); BUG_ON(!PageLRU(page)); list_del(&page->lru); - if (unlikely(get_page_testone(page))) { + target = src; + if (likely(get_page_unless_zero(page))) { /* - * It is being freed elsewhere + * Be careful not to clear PageLRU until after we're + * sure the page is not being freed elsewhere -- the + * page release code relies on it. */ - __put_page(page); - list_add(&page->lru, src); - continue; - } + ClearPageLRU(page); + target = dst; + nr_taken++; + } /* else it is being freed elsewhere */ - /* - * Be careful not to clear PageLRU until after we're sure - * the page is not being freed elsewhere -- the page release - * code relies on it. - */ - ClearPageLRU(page); - list_add(&page->lru, dst); - nr_taken++; + list_add(&page->lru, target); } *scanned = scan; -- cgit v1.2.3 From 8dc04efbfb3c08a08fb7a3b97348d5d561b26ae2 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 22 Mar 2006 00:08:03 -0800 Subject: [PATCH] mm: de-skew page refcounting atomic_add_unless (atomic_inc_not_zero) no longer requires an offset refcount to function correctly. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mm.h | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/include/linux/mm.h b/include/linux/mm.h index b12d5c76420d..9bbddf228cd9 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -286,15 +286,6 @@ struct page { * * Also, many kernel routines increase the page count before a critical * routine so they can be sure the page doesn't go away from under them. - * - * Since 2.6.6 (approx), a free page has ->_count = -1. This is so that we - * can use atomic_add_negative(-1, page->_count) to detect when the page - * becomes free and so that we can also use atomic_inc_and_test to atomically - * detect when we just tried to grab a ref on a page which some other CPU has - * already deemed to be freeable. - * - * NO code should make assumptions about this internal detail! Use the provided - * macros which retain the old rules: page_count(page) == 0 is a free page. */ /* @@ -303,8 +294,8 @@ struct page { */ static inline int put_page_testzero(struct page *page) { - BUG_ON(atomic_read(&page->_count) == -1); - return atomic_add_negative(-1, &page->_count); + BUG_ON(atomic_read(&page->_count) == 0); + return atomic_dec_and_test(&page->_count); } /* @@ -313,10 +304,10 @@ static inline int put_page_testzero(struct page *page) */ static inline int get_page_unless_zero(struct page *page) { - return atomic_add_unless(&page->_count, 1, -1); + return atomic_inc_not_zero(&page->_count); } -#define set_page_count(p,v) atomic_set(&(p)->_count, (v) - 1) +#define set_page_count(p,v) atomic_set(&(p)->_count, (v)) #define __put_page(p) atomic_dec(&(p)->_count) extern void FASTCALL(__page_cache_release(struct page *)); @@ -325,7 +316,7 @@ static inline int page_count(struct page *page) { if (PageCompound(page)) page = (struct page *)page_private(page); - return atomic_read(&page->_count) + 1; + return atomic_read(&page->_count); } static inline void get_page(struct page *page) -- cgit v1.2.3 From 8dfcc9ba27e2ed257e5de9539f7f03e57c2c0e33 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 22 Mar 2006 00:08:05 -0800 Subject: [PATCH] mm: split highorder pages Have an explicit mm call to split higher order pages into individual pages. Should help to avoid bugs and be more explicit about the code's intention. Signed-off-by: Nick Piggin Cc: Russell King Cc: David Howells Cc: Ralf Baechle Cc: Benjamin Herrenschmidt Cc: Paul Mundt Cc: "David S. Miller" Cc: Chris Zankel Signed-off-by: Yoichi Yuasa Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/mm/consistent.c | 4 ++-- arch/frv/mm/dma-alloc.c | 4 +--- arch/mips/mm/init.c | 5 +++-- arch/ppc/kernel/dma-mapping.c | 4 ++-- arch/sh/mm/consistent.c | 3 +-- arch/xtensa/mm/pgtable.c | 10 +++------- include/linux/mm.h | 6 ++++++ mm/memory.c | 4 +--- mm/page_alloc.c | 22 ++++++++++++++++++++++ 9 files changed, 41 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c index c2ee18d2075e..8a1bfcd50087 100644 --- a/arch/arm/mm/consistent.c +++ b/arch/arm/mm/consistent.c @@ -223,6 +223,8 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, pte = consistent_pte[idx] + off; c->vm_pages = page; + split_page(page, order); + /* * Set the "dma handle" */ @@ -231,7 +233,6 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, do { BUG_ON(!pte_none(*pte)); - set_page_count(page, 1); /* * x86 does not mark the pages reserved... */ @@ -250,7 +251,6 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, * Free the otherwise unused pages. */ while (page < end) { - set_page_count(page, 1); __free_page(page); page++; } diff --git a/arch/frv/mm/dma-alloc.c b/arch/frv/mm/dma-alloc.c index 342823aad758..636b2f8b5d98 100644 --- a/arch/frv/mm/dma-alloc.c +++ b/arch/frv/mm/dma-alloc.c @@ -115,9 +115,7 @@ void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *dma_handle) */ if (order > 0) { struct page *rpage = virt_to_page(page); - - for (i = 1; i < (1 << order); i++) - set_page_count(rpage + i, 1); + split_page(rpage, order); } err = 0; diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 0ff9a348b843..a140da9732db 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -54,7 +54,8 @@ unsigned long empty_zero_page, zero_page_mask; */ unsigned long setup_zero_pages(void) { - unsigned long order, size; + unsigned int order; + unsigned long size; struct page *page; if (cpu_has_vce) @@ -67,9 +68,9 @@ unsigned long setup_zero_pages(void) panic("Oh boy, that early out of memory?"); page = virt_to_page(empty_zero_page); + split_page(page, order); while (page < virt_to_page(empty_zero_page + (PAGE_SIZE << order))) { SetPageReserved(page); - set_page_count(page, 1); page++; } diff --git a/arch/ppc/kernel/dma-mapping.c b/arch/ppc/kernel/dma-mapping.c index 685fd0defe23..61465ec88bc7 100644 --- a/arch/ppc/kernel/dma-mapping.c +++ b/arch/ppc/kernel/dma-mapping.c @@ -223,6 +223,8 @@ __dma_alloc_coherent(size_t size, dma_addr_t *handle, gfp_t gfp) pte_t *pte = consistent_pte + CONSISTENT_OFFSET(vaddr); struct page *end = page + (1 << order); + split_page(page, order); + /* * Set the "dma handle" */ @@ -231,7 +233,6 @@ __dma_alloc_coherent(size_t size, dma_addr_t *handle, gfp_t gfp) do { BUG_ON(!pte_none(*pte)); - set_page_count(page, 1); SetPageReserved(page); set_pte_at(&init_mm, vaddr, pte, mk_pte(page, pgprot_noncached(PAGE_KERNEL))); @@ -244,7 +245,6 @@ __dma_alloc_coherent(size_t size, dma_addr_t *handle, gfp_t gfp) * Free the otherwise unused pages. */ while (page < end) { - set_page_count(page, 1); __free_page(page); page++; } diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c index df3a9e452cc5..ee73e30263af 100644 --- a/arch/sh/mm/consistent.c +++ b/arch/sh/mm/consistent.c @@ -23,6 +23,7 @@ void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle) page = alloc_pages(gfp, order); if (!page) return NULL; + split_page(page, order); ret = page_address(page); *handle = virt_to_phys(ret); @@ -37,8 +38,6 @@ void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle) end = page + (1 << order); while (++page < end) { - set_page_count(page, 1); - /* Free any unused pages */ if (page >= free) { __free_page(page); diff --git a/arch/xtensa/mm/pgtable.c b/arch/xtensa/mm/pgtable.c index cbc56aedf13e..7d28914d11cb 100644 --- a/arch/xtensa/mm/pgtable.c +++ b/arch/xtensa/mm/pgtable.c @@ -21,13 +21,9 @@ pte_t* pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) p = (pte_t*) __get_free_pages(GFP_KERNEL|__GFP_REPEAT, COLOR_ORDER); if (likely(p)) { - struct page *page; + split_page(virt_to_page(p), COLOR_ORDER); for (i = 0; i < COLOR_SIZE; i++) { - page = virt_to_page(p); - - set_page_count(page, 1); - if (ADDR_COLOR(p) == color) pte = p; else @@ -55,9 +51,9 @@ struct page* pte_alloc_one(struct mm_struct *mm, unsigned long address) p = alloc_pages(GFP_KERNEL | __GFP_REPEAT, PTE_ORDER); if (likely(p)) { - for (i = 0; i < PAGE_ORDER; i++) { - set_page_count(p, 1); + split_page(p, COLOR_ORDER); + for (i = 0; i < PAGE_ORDER; i++) { if (PADDR_COLOR(page_address(p)) == color) page = p; else diff --git a/include/linux/mm.h b/include/linux/mm.h index 9bbddf228cd9..e67980654c49 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -328,6 +328,12 @@ static inline void get_page(struct page *page) void put_page(struct page *page); +#ifdef CONFIG_MMU +void split_page(struct page *page, unsigned int order); +#else +static inline void split_page(struct page *page, unsigned int order) {} +#endif + /* * Multiple processes may "see" the same page. E.g. for untouched * mappings of /dev/null, all processes see the same page full of diff --git a/mm/memory.c b/mm/memory.c index 85e80a57db29..6af555c1c42a 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1221,9 +1221,7 @@ out: * The page has to be a nice clean _individual_ kernel allocation. * If you allocate a compound page, you need to have marked it as * such (__GFP_COMP), or manually just split the page up yourself - * (which is mainly an issue of doing "set_page_count(page, 1)" for - * each sub-page, and then freeing them one by one when you free - * them rather than freeing it as a compound page). + * (see split_page()). * * NOTE! Traditionally this was done with "remap_pfn_range()" which * took an arbitrary page protection parameter. This doesn't allow diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 102919851353..fc65e87368b3 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -752,6 +752,28 @@ static inline void prep_zero_page(struct page *page, int order, gfp_t gfp_flags) clear_highpage(page + i); } +#ifdef CONFIG_MMU +/* + * split_page takes a non-compound higher-order page, and splits it into + * n (1< 0 path. Saves a branch -- cgit v1.2.3 From 9d41415221214ca4820b9464dfa548e2f20e7dd5 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 22 Mar 2006 00:08:06 -0800 Subject: [PATCH] mm: page_state comment more Clarify that preemption needs to be guarded against with the __xxx_page_state functions. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/page-flags.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 8cef69d462f2..9ea629c02a4b 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -86,8 +86,9 @@ * - The __xxx_page_state variants can be used safely when interrupts are * disabled. * - The __xxx_page_state variants can be used if the field is only - * modified from process context, or only modified from interrupt context. - * In this case, the field should be commented here. + * modified from process context and protected from preemption, or only + * modified from interrupt context. In this case, the field should be + * commented here. */ struct page_state { unsigned long nr_dirty; /* Dirty writeable pages */ -- cgit v1.2.3 From b50ec7d8070ae7a39fe78e65a8812bbc3ca2f7ac Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 22 Mar 2006 00:08:09 -0800 Subject: [PATCH] kcalloc(): INT_MAX -> ULONG_MAX Since size_t has the same size as a long on all architectures, it's enough for overflow checks to check against ULONG_MAX. This change could allow a compiler better optimization (especially in the n=1 case). The practical effect seems to be positive, but quite small: text data bss dec hex filename 21762380 5859870 1848928 29471178 1c1b1ca vmlinux-old 21762211 5859870 1848928 29471009 1c1b121 vmlinux-patched Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/slab.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/slab.h b/include/linux/slab.h index 8cf52939d0ab..38bed95dda7a 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -118,7 +118,7 @@ extern void *kzalloc(size_t, gfp_t); */ static inline void *kcalloc(size_t n, size_t size, gfp_t flags) { - if (n != 0 && size > INT_MAX / n) + if (n != 0 && size > ULONG_MAX / n) return NULL; return kzalloc(n * size, flags); } -- cgit v1.2.3 From ac2b898ca6fb06196a26869c23b66afe7944e52e Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 22 Mar 2006 00:08:15 -0800 Subject: [PATCH] slab: Remove SLAB_NO_REAP option SLAB_NO_REAP is documented as an option that will cause this slab not to be reaped under memory pressure. However, that is not what happens. The only thing that SLAB_NO_REAP controls at the moment is the reclaim of the unused slab elements that were allocated in batch in cache_reap(). Cache_reap() is run every few seconds independently of memory pressure. Could we remove the whole thing? Its only used by three slabs anyways and I cannot find a reason for having this option. There is an additional problem with SLAB_NO_REAP. If set then the recovery of objects from alien caches is switched off. Objects not freed on the same node where they were initially allocated will only be reused if a certain amount of objects accumulates from one alien node (not very likely) or if the cache is explicitly shrunk. (Strangely __cache_shrink does not check for SLAB_NO_REAP) Getting rid of SLAB_NO_REAP fixes the problems with alien cache freeing. Signed-off-by: Christoph Lameter Cc: Pekka Enberg Cc: Manfred Spraul Cc: Mark Fasheh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/iscsi_tcp.c | 2 +- fs/ocfs2/super.c | 2 +- include/linux/slab.h | 1 - mm/slab.c | 13 ++----------- 4 files changed, 4 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index ff79e68b347c..7b82ff090d42 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -3639,7 +3639,7 @@ iscsi_tcp_init(void) taskcache = kmem_cache_create("iscsi_taskcache", sizeof(struct iscsi_data_task), 0, - SLAB_HWCACHE_ALIGN | SLAB_NO_REAP, NULL, NULL); + SLAB_HWCACHE_ALIGN, NULL, NULL); if (!taskcache) return -ENOMEM; diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 8dd3aafec499..09e1c57a86a0 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -959,7 +959,7 @@ static int ocfs2_initialize_mem_caches(void) ocfs2_lock_cache = kmem_cache_create("ocfs2_lock", sizeof(struct ocfs2_journal_lock), 0, - SLAB_NO_REAP|SLAB_HWCACHE_ALIGN, + SLAB_HWCACHE_ALIGN, NULL, NULL); if (!ocfs2_lock_cache) return -ENOMEM; diff --git a/include/linux/slab.h b/include/linux/slab.h index 38bed95dda7a..2b28c849d75a 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -38,7 +38,6 @@ typedef struct kmem_cache kmem_cache_t; #define SLAB_DEBUG_INITIAL 0x00000200UL /* Call constructor (as verifier) */ #define SLAB_RED_ZONE 0x00000400UL /* Red zone objs in a cache */ #define SLAB_POISON 0x00000800UL /* Poison objects */ -#define SLAB_NO_REAP 0x00001000UL /* never reap from the cache */ #define SLAB_HWCACHE_ALIGN 0x00002000UL /* align objs on a h/w cache lines */ #define SLAB_CACHE_DMA 0x00004000UL /* use GFP_DMA memory */ #define SLAB_MUST_HWCACHE_ALIGN 0x00008000UL /* force alignment */ diff --git a/mm/slab.c b/mm/slab.c index 5c2574989834..24235506b2a0 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -170,12 +170,12 @@ #if DEBUG # define CREATE_MASK (SLAB_DEBUG_INITIAL | SLAB_RED_ZONE | \ SLAB_POISON | SLAB_HWCACHE_ALIGN | \ - SLAB_NO_REAP | SLAB_CACHE_DMA | \ + SLAB_CACHE_DMA | \ SLAB_MUST_HWCACHE_ALIGN | SLAB_STORE_USER | \ SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \ SLAB_DESTROY_BY_RCU) #else -# define CREATE_MASK (SLAB_HWCACHE_ALIGN | SLAB_NO_REAP | \ +# define CREATE_MASK (SLAB_HWCACHE_ALIGN | \ SLAB_CACHE_DMA | SLAB_MUST_HWCACHE_ALIGN | \ SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \ SLAB_DESTROY_BY_RCU) @@ -662,7 +662,6 @@ static struct kmem_cache cache_cache = { .limit = BOOT_CPUCACHE_ENTRIES, .shared = 1, .buffer_size = sizeof(struct kmem_cache), - .flags = SLAB_NO_REAP, .name = "kmem_cache", #if DEBUG .obj_size = sizeof(struct kmem_cache), @@ -1848,9 +1847,6 @@ static void setup_cpu_cache(struct kmem_cache *cachep) * %SLAB_RED_ZONE - Insert `Red' zones around the allocated memory to check * for buffer overruns. * - * %SLAB_NO_REAP - Don't automatically reap this cache when we're under - * memory pressure. - * * %SLAB_HWCACHE_ALIGN - Align the objects in this cache to a hardware * cacheline. This can be beneficial if you're counting cycles as closely * as davem. @@ -3584,10 +3580,6 @@ static void cache_reap(void *unused) struct slab *slabp; searchp = list_entry(walk, struct kmem_cache, next); - - if (searchp->flags & SLAB_NO_REAP) - goto next; - check_irq_on(); l3 = searchp->nodelists[numa_node_id()]; @@ -3635,7 +3627,6 @@ static void cache_reap(void *unused) } while (--tofree > 0); next_unlock: spin_unlock_irq(&l3->list_lock); -next: cond_resched(); } check_irq_on(); -- cgit v1.2.3 From 78eef01b0fae087c5fadbd85dd4fe2918c3a015f Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 22 Mar 2006 00:08:16 -0800 Subject: [PATCH] on_each_cpu(): disable local interrupts When on_each_cpu() runs the callback on other CPUs, it runs with local interrupts disabled. So we should run the function with local interrupts disabled on this CPU, too. And do the same for UP, so the callback is run in the same environment on both UP and SMP. (strictly it should do preempt_disable() too, but I think local_irq_disable is sufficiently equivalent). Also uninlines on_each_cpu(). softirq.c was the most appropriate file I could find, but it doesn't seem to justify creating a new file. Oh, and fix up that comment over (under?) x86's smp_call_function(). It drives me nuts. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/smp.c | 28 ++++++++++++---------------- include/linux/smp.h | 23 +++++++++-------------- kernel/softirq.c | 20 ++++++++++++++++++++ 3 files changed, 41 insertions(+), 30 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index 218d725a5a1e..d134e9643a58 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -504,27 +504,23 @@ void unlock_ipi_call_lock(void) spin_unlock_irq(&call_lock); } -static struct call_data_struct * call_data; - -/* - * this function sends a 'generic call function' IPI to all other CPUs - * in the system. - */ - -int smp_call_function (void (*func) (void *info), void *info, int nonatomic, - int wait) -/* - * [SUMMARY] Run a function on all other CPUs. - * The function to run. This must be fast and non-blocking. - * An arbitrary pointer to pass to the function. - * currently unused. - * If true, wait (atomically) until function has completed on other CPUs. - * [RETURNS] 0 on success, else a negative status code. Does not return until +static struct call_data_struct *call_data; + +/** + * smp_call_function(): Run a function on all other CPUs. + * @func: The function to run. This must be fast and non-blocking. + * @info: An arbitrary pointer to pass to the function. + * @nonatomic: currently unused. + * @wait: If true, wait (atomically) until function has completed on other CPUs. + * + * Returns 0 on success, else a negative status code. Does not return until * remote CPUs are nearly ready to execute <> or are or have executed. * * You must not call this function with disabled interrupts or from a * hardware interrupt handler or from a bottom half handler. */ +int smp_call_function (void (*func) (void *info), void *info, int nonatomic, + int wait) { struct call_data_struct data; int cpus; diff --git a/include/linux/smp.h b/include/linux/smp.h index 44153fdf73fc..d699a16b0cb2 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -52,23 +52,12 @@ extern void smp_cpus_done(unsigned int max_cpus); /* * Call a function on all other processors */ -extern int smp_call_function (void (*func) (void *info), void *info, - int retry, int wait); +int smp_call_function(void(*func)(void *info), void *info, int retry, int wait); /* * Call a function on all processors */ -static inline int on_each_cpu(void (*func) (void *info), void *info, - int retry, int wait) -{ - int ret = 0; - - preempt_disable(); - ret = smp_call_function(func, info, retry, wait); - func(info); - preempt_enable(); - return ret; -} +int on_each_cpu(void (*func) (void *info), void *info, int retry, int wait); #define MSG_ALL_BUT_SELF 0x8000 /* Assume <32768 CPU's */ #define MSG_ALL 0x8001 @@ -94,7 +83,13 @@ void smp_prepare_boot_cpu(void); #define raw_smp_processor_id() 0 #define hard_smp_processor_id() 0 #define smp_call_function(func,info,retry,wait) ({ 0; }) -#define on_each_cpu(func,info,retry,wait) ({ func(info); 0; }) +#define on_each_cpu(func,info,retry,wait) \ + ({ \ + local_irq_disable(); \ + func(info); \ + local_irq_enable(); \ + 0; \ + }) static inline void smp_send_reschedule(int cpu) { } #define num_booting_cpus() 1 #define smp_prepare_boot_cpu() do {} while (0) diff --git a/kernel/softirq.c b/kernel/softirq.c index ad3295cdded5..ec8fed42a86f 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -16,6 +16,7 @@ #include #include #include +#include #include /* @@ -495,3 +496,22 @@ __init int spawn_ksoftirqd(void) register_cpu_notifier(&cpu_nfb); return 0; } + +#ifdef CONFIG_SMP +/* + * Call a function on all processors + */ +int on_each_cpu(void (*func) (void *info), void *info, int retry, int wait) +{ + int ret = 0; + + preempt_disable(); + ret = smp_call_function(func, info, retry, wait); + local_irq_disable(); + func(info); + local_irq_enable(); + preempt_enable(); + return ret; +} +EXPORT_SYMBOL(on_each_cpu); +#endif -- cgit v1.2.3 From 69e05944af39fc6c97b09380c8721e38433bd828 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 22 Mar 2006 00:08:19 -0800 Subject: [PATCH] vmscan: use unsigned longs Turn basically everything in vmscan.c into `unsigned long'. This is to avoid the possibility that some piece of code in there might decide to operate upon more than 4G (or even 2G) of pages in one hit. This might be silly, but we'll need it one day. Cc: Christoph Lameter Cc: Nick Piggin Signed-off-by: Rafael J. Wysocki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mm.h | 2 +- include/linux/swap.h | 8 ++-- mm/vmscan.c | 104 +++++++++++++++++++++++++++++---------------------- 3 files changed, 64 insertions(+), 50 deletions(-) (limited to 'include') diff --git a/include/linux/mm.h b/include/linux/mm.h index e67980654c49..1850cf8bad64 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1046,7 +1046,7 @@ int in_gate_area_no_task(unsigned long addr); int drop_caches_sysctl_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *); -int shrink_slab(unsigned long scanned, gfp_t gfp_mask, +unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask, unsigned long lru_pages); void drop_pagecache(void); void drop_slab(void); diff --git a/include/linux/swap.h b/include/linux/swap.h index d572b19afb7d..3dc6c89c49b8 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -172,8 +172,8 @@ extern int rotate_reclaimable_page(struct page *page); extern void swap_setup(void); /* linux/mm/vmscan.c */ -extern int try_to_free_pages(struct zone **, gfp_t); -extern int shrink_all_memory(int); +extern unsigned long try_to_free_pages(struct zone **, gfp_t); +extern unsigned long shrink_all_memory(unsigned long nr_pages); extern int vm_swappiness; #ifdef CONFIG_NUMA @@ -190,11 +190,11 @@ static inline int zone_reclaim(struct zone *z, gfp_t mask, unsigned int order) #ifdef CONFIG_MIGRATION extern int isolate_lru_page(struct page *p); -extern int putback_lru_pages(struct list_head *l); +extern unsigned long putback_lru_pages(struct list_head *l); extern int migrate_page(struct page *, struct page *); extern void migrate_page_copy(struct page *, struct page *); extern int migrate_page_remove_references(struct page *, struct page *, int); -extern int migrate_pages(struct list_head *l, struct list_head *t, +extern unsigned long migrate_pages(struct list_head *l, struct list_head *t, struct list_head *moved, struct list_head *failed); extern int fail_migrate_page(struct page *, struct page *); #else diff --git a/mm/vmscan.c b/mm/vmscan.c index 5feef4d4650e..62cd7cd257e3 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -177,10 +177,11 @@ EXPORT_SYMBOL(remove_shrinker); * * Returns the number of slab objects which we shrunk. */ -int shrink_slab(unsigned long scanned, gfp_t gfp_mask, unsigned long lru_pages) +unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask, + unsigned long lru_pages) { struct shrinker *shrinker; - int ret = 0; + unsigned long ret = 0; if (scanned == 0) scanned = SWAP_CLUSTER_MAX; @@ -410,12 +411,13 @@ cannot_free: /* * shrink_list adds the number of reclaimed pages to sc->nr_reclaimed */ -static int shrink_list(struct list_head *page_list, struct scan_control *sc) +static unsigned long shrink_list(struct list_head *page_list, + struct scan_control *sc) { LIST_HEAD(ret_pages); struct pagevec freed_pvec; int pgactivate = 0; - int reclaimed = 0; + unsigned long reclaimed = 0; cond_resched(); @@ -599,11 +601,11 @@ static inline void move_to_lru(struct page *page) * * returns the number of pages put back. */ -int putback_lru_pages(struct list_head *l) +unsigned long putback_lru_pages(struct list_head *l) { struct page *page; struct page *page2; - int count = 0; + unsigned long count = 0; list_for_each_entry_safe(page, page2, l, lru) { move_to_lru(page); @@ -848,11 +850,11 @@ EXPORT_SYMBOL(migrate_page); * * Return: Number of pages not migrated when "to" ran empty. */ -int migrate_pages(struct list_head *from, struct list_head *to, +unsigned long migrate_pages(struct list_head *from, struct list_head *to, struct list_head *moved, struct list_head *failed) { - int retry; - int nr_failed = 0; + unsigned long retry; + unsigned long nr_failed = 0; int pass = 0; struct page *page; struct page *page2; @@ -1069,12 +1071,13 @@ int isolate_lru_page(struct page *page) * * returns how many pages were moved onto *@dst. */ -static int isolate_lru_pages(int nr_to_scan, struct list_head *src, - struct list_head *dst, int *scanned) +static unsigned long isolate_lru_pages(unsigned long nr_to_scan, + struct list_head *src, struct list_head *dst, + unsigned long *scanned) { - int nr_taken = 0; + unsigned long nr_taken = 0; struct page *page; - int scan = 0; + unsigned long scan = 0; while (scan++ < nr_to_scan && !list_empty(src)) { struct list_head *target; @@ -1106,20 +1109,22 @@ static int isolate_lru_pages(int nr_to_scan, struct list_head *src, /* * shrink_cache() adds the number of pages reclaimed to sc->nr_reclaimed */ -static void shrink_cache(int max_scan, struct zone *zone, struct scan_control *sc) +static void shrink_cache(unsigned long max_scan, struct zone *zone, + struct scan_control *sc) { LIST_HEAD(page_list); struct pagevec pvec; + unsigned long nr_scanned = 0; pagevec_init(&pvec, 1); lru_add_drain(); spin_lock_irq(&zone->lru_lock); - while (max_scan > 0) { + do { struct page *page; - int nr_taken; - int nr_scan; - int nr_freed; + unsigned long nr_taken; + unsigned long nr_scan; + unsigned long nr_freed; nr_taken = isolate_lru_pages(sc->swap_cluster_max, &zone->inactive_list, @@ -1131,7 +1136,7 @@ static void shrink_cache(int max_scan, struct zone *zone, struct scan_control *s if (nr_taken == 0) goto done; - max_scan -= nr_scan; + nr_scanned += nr_scan; nr_freed = shrink_list(&page_list, sc); local_irq_disable(); @@ -1161,7 +1166,7 @@ static void shrink_cache(int max_scan, struct zone *zone, struct scan_control *s spin_lock_irq(&zone->lru_lock); } } - } + } while (nr_scanned < max_scan); spin_unlock_irq(&zone->lru_lock); done: pagevec_release(&pvec); @@ -1185,11 +1190,12 @@ done: * But we had to alter page->flags anyway. */ static void -refill_inactive_zone(int nr_pages, struct zone *zone, struct scan_control *sc) +refill_inactive_zone(unsigned long nr_pages, struct zone *zone, + struct scan_control *sc) { - int pgmoved; + unsigned long pgmoved; int pgdeactivate = 0; - int pgscanned; + unsigned long pgscanned; LIST_HEAD(l_hold); /* The pages which were snipped off */ LIST_HEAD(l_inactive); /* Pages to go onto the inactive_list */ LIST_HEAD(l_active); /* Pages to go onto the active_list */ @@ -1323,8 +1329,8 @@ refill_inactive_zone(int nr_pages, struct zone *zone, struct scan_control *sc) /* * This is a basic per-zone page freer. Used by both kswapd and direct reclaim. */ -static void -shrink_zone(int priority, struct zone *zone, struct scan_control *sc) +static void shrink_zone(int priority, struct zone *zone, + struct scan_control *sc) { unsigned long nr_active; unsigned long nr_inactive; @@ -1387,8 +1393,8 @@ shrink_zone(int priority, struct zone *zone, struct scan_control *sc) * If a zone is deemed to be full of pinned pages then just give it a light * scan then give up on it. */ -static void -shrink_caches(int priority, struct zone **zones, struct scan_control *sc) +static void shrink_caches(int priority, struct zone **zones, + struct scan_control *sc) { int i; @@ -1425,11 +1431,12 @@ shrink_caches(int priority, struct zone **zones, struct scan_control *sc) * holds filesystem locks which prevent writeout this might not work, and the * allocation attempt will fail. */ -int try_to_free_pages(struct zone **zones, gfp_t gfp_mask) +unsigned long try_to_free_pages(struct zone **zones, gfp_t gfp_mask) { int priority; int ret = 0; - int total_scanned = 0, total_reclaimed = 0; + unsigned long total_scanned = 0; + unsigned long total_reclaimed = 0; struct reclaim_state *reclaim_state = current->reclaim_state; unsigned long lru_pages = 0; int i; @@ -1525,13 +1532,15 @@ out: * the page allocator fallback scheme to ensure that aging of pages is balanced * across the zones. */ -static int balance_pgdat(pg_data_t *pgdat, int nr_pages, int order) +static unsigned long balance_pgdat(pg_data_t *pgdat, unsigned long nr_pages, + int order) { - int to_free = nr_pages; + unsigned long to_free = nr_pages; int all_zones_ok; int priority; int i; - int total_scanned, total_reclaimed; + unsigned long total_scanned; + unsigned long total_reclaimed; struct reclaim_state *reclaim_state = current->reclaim_state; struct scan_control sc = { .gfp_mask = GFP_KERNEL, @@ -1776,22 +1785,23 @@ void wakeup_kswapd(struct zone *zone, int order) * Try to free `nr_pages' of memory, system-wide. Returns the number of freed * pages. */ -int shrink_all_memory(int nr_pages) +unsigned long shrink_all_memory(unsigned long nr_pages) { pg_data_t *pgdat; - int nr_to_free = nr_pages; - int ret = 0; + unsigned long nr_to_free = nr_pages; + unsigned long ret = 0; struct reclaim_state reclaim_state = { .reclaimed_slab = 0, }; current->reclaim_state = &reclaim_state; for_each_pgdat(pgdat) { - int freed; + unsigned long freed; + freed = balance_pgdat(pgdat, nr_to_free, 0); ret += freed; nr_to_free -= freed; - if (nr_to_free <= 0) + if ((long)nr_to_free <= 0) break; } current->reclaim_state = NULL; @@ -1805,8 +1815,7 @@ int shrink_all_memory(int nr_pages) away, we get changed to run anywhere: as the first one comes back, restore their cpu bindings. */ static int __devinit cpu_callback(struct notifier_block *nfb, - unsigned long action, - void *hcpu) + unsigned long action, void *hcpu) { pg_data_t *pgdat; cpumask_t mask; @@ -1826,10 +1835,15 @@ static int __devinit cpu_callback(struct notifier_block *nfb, static int __init kswapd_init(void) { pg_data_t *pgdat; + swap_setup(); - for_each_pgdat(pgdat) - pgdat->kswapd - = find_task_by_pid(kernel_thread(kswapd, pgdat, CLONE_KERNEL)); + for_each_pgdat(pgdat) { + pid_t pid; + + pid = kernel_thread(kswapd, pgdat, CLONE_KERNEL); + BUG_ON(pid < 0); + pgdat->kswapd = find_task_by_pid(pid); + } total_memory = nr_free_pagecache_pages(); hotcpu_notifier(cpu_callback, 0); return 0; @@ -1873,7 +1887,7 @@ int zone_reclaim_interval __read_mostly = 30*HZ; */ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) { - const int nr_pages = 1 << order; + const unsigned long nr_pages = 1 << order; struct task_struct *p = current; struct reclaim_state reclaim_state; int priority; @@ -1881,7 +1895,8 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) .may_writepage = !!(zone_reclaim_mode & RECLAIM_WRITE), .may_swap = !!(zone_reclaim_mode & RECLAIM_SWAP), .nr_mapped = read_page_state(nr_mapped), - .swap_cluster_max = max(nr_pages, SWAP_CLUSTER_MAX), + .swap_cluster_max = max_t(unsigned long, nr_pages, + SWAP_CLUSTER_MAX), .gfp_mask = gfp_mask, }; @@ -1966,4 +1981,3 @@ int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) return __zone_reclaim(zone, gfp_mask, order); } #endif - -- cgit v1.2.3 From 0f8053a509ceba4a077a50ea7b77039b5559b428 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 22 Mar 2006 00:08:33 -0800 Subject: [PATCH] mm: make __put_page internal Remove __put_page from outside the core mm/. It is dangerous because it does not handle compound pages nicely, and misses 1->0 transitions. If a user later appears that really needs the extra speed we can reevaluate. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mm.h | 1 - mm/filemap.c | 2 ++ mm/internal.h | 11 +++++++++++ mm/vmscan.c | 2 ++ 4 files changed, 15 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/mm.h b/include/linux/mm.h index 1850cf8bad64..9b3cdfc8046d 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -308,7 +308,6 @@ static inline int get_page_unless_zero(struct page *page) } #define set_page_count(p,v) atomic_set(&(p)->_count, (v)) -#define __put_page(p) atomic_dec(&(p)->_count) extern void FASTCALL(__page_cache_release(struct page *)); diff --git a/mm/filemap.c b/mm/filemap.c index 44da3d476994..e8f58f7dd7a5 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -30,6 +30,8 @@ #include #include #include "filemap.h" +#include "internal.h" + /* * FIXME: remove all knowledge of the buffer layer from the core VM */ diff --git a/mm/internal.h b/mm/internal.h index 17256bb2f4ef..e3042db2a2d6 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -8,6 +8,10 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ +#ifndef __MM_INTERNAL_H +#define __MM_INTERNAL_H + +#include static inline void set_page_refs(struct page *page, int order) { @@ -26,5 +30,12 @@ static inline void set_page_refs(struct page *page, int order) #endif /* CONFIG_MMU */ } +static inline void __put_page(struct page *page) +{ + atomic_dec(&page->_count); +} + extern void fastcall __init __free_pages_bootmem(struct page *page, unsigned int order); + +#endif diff --git a/mm/vmscan.c b/mm/vmscan.c index 486184d2b50c..3914a94aa905 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -39,6 +39,8 @@ #include +#include "internal.h" + /* possible outcome of pageout() */ typedef enum { /* failed to write page out, page is locked */ -- cgit v1.2.3 From 84097518d1ecd2330f9488e4c2d09953a3340e74 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 22 Mar 2006 00:08:34 -0800 Subject: [PATCH] mm: nommu use compound pages Now that compound page handling is properly fixed in the VM, move nommu over to using compound pages rather than rolling their own refcounting. nommu vm page refcounting is broken anyway, but there is no need to have divergent code in the core VM now, nor when it gets fixed. Signed-off-by: Nick Piggin Cc: David Howells (Needs testing, please). Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ramfs/file-nommu.c | 3 +-- include/linux/mm.h | 4 ---- mm/internal.h | 12 ------------ mm/nommu.c | 4 ++-- mm/page_alloc.c | 7 ------- mm/slab.c | 9 ++++++++- 6 files changed, 11 insertions(+), 28 deletions(-) (limited to 'include') diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index 3f810acd0bfa..b1ca234068f6 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c @@ -87,8 +87,7 @@ static int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) xpages = 1UL << order; npages = (newsize + PAGE_SIZE - 1) >> PAGE_SHIFT; - for (loop = 0; loop < npages; loop++) - set_page_count(pages + loop, 1); + split_page(pages, order); /* trim off any pages we don't actually require */ for (loop = npages; loop < xpages; loop++) diff --git a/include/linux/mm.h b/include/linux/mm.h index 9b3cdfc8046d..3d84b7a35e0d 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -327,11 +327,7 @@ static inline void get_page(struct page *page) void put_page(struct page *page); -#ifdef CONFIG_MMU void split_page(struct page *page, unsigned int order); -#else -static inline void split_page(struct page *page, unsigned int order) {} -#endif /* * Multiple processes may "see" the same page. E.g. for untouched diff --git a/mm/internal.h b/mm/internal.h index e3042db2a2d6..7bb339779818 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -15,19 +15,7 @@ static inline void set_page_refs(struct page *page, int order) { -#ifdef CONFIG_MMU set_page_count(page, 1); -#else - int i; - - /* - * We need to reference all the pages for this order, otherwise if - * anyone accesses one of the pages with (get/put) it will be freed. - * - eg: access_process_vm() - */ - for (i = 0; i < (1 << order); i++) - set_page_count(page + i, 1); -#endif /* CONFIG_MMU */ } static inline void __put_page(struct page *page) diff --git a/mm/nommu.c b/mm/nommu.c index 4951f4786f28..db45efac17cc 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -159,7 +159,7 @@ void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot) /* * kmalloc doesn't like __GFP_HIGHMEM for some reason */ - return kmalloc(size, gfp_mask & ~__GFP_HIGHMEM); + return kmalloc(size, (gfp_mask | __GFP_COMP) & ~__GFP_HIGHMEM); } struct page * vmalloc_to_page(void *addr) @@ -623,7 +623,7 @@ static int do_mmap_private(struct vm_area_struct *vma, unsigned long len) * - note that this may not return a page-aligned address if the object * we're allocating is smaller than a page */ - base = kmalloc(len, GFP_KERNEL); + base = kmalloc(len, GFP_KERNEL|__GFP_COMP); if (!base) goto enomem; diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 7aa0181287e1..e197818a7cf6 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -422,11 +422,6 @@ static void __free_pages_ok(struct page *page, unsigned int order) mutex_debug_check_no_locks_freed(page_address(page), PAGE_SIZE<lru.next; } @@ -600,6 +602,8 @@ static inline void page_set_slab(struct page *page, struct slab *slab) static inline struct slab *page_get_slab(struct page *page) { + if (unlikely(PageCompound(page))) + page = (struct page *)page_private(page); return (struct slab *)page->lru.prev; } @@ -2412,8 +2416,11 @@ static void set_slab_attr(struct kmem_cache *cachep, struct slab *slabp, struct page *page; /* Nasty!!!!!! I hope this is OK. */ - i = 1 << cachep->gfporder; page = virt_to_page(objp); + + i = 1; + if (likely(!PageCompound(page))) + i <<= cachep->gfporder; do { page_set_cache(page, cachep); page_set_slab(page, slabp); -- cgit v1.2.3 From 7835e98b2e3c66dba79cb0ff8ebb90a2fe030c29 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 22 Mar 2006 00:08:40 -0800 Subject: [PATCH] remove set_page_count() outside mm/ set_page_count usage outside mm/ is limited to setting the refcount to 1. Remove set_page_count from outside mm/, and replace those users with init_page_count() and set_page_refcounted(). This allows more debug checking, and tighter control on how code is allowed to play around with page->_count. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/alpha/mm/init.c | 2 +- arch/arm/mm/init.c | 2 +- arch/arm26/mm/init.c | 2 +- arch/cris/mm/init.c | 2 +- arch/frv/mm/init.c | 6 +++--- arch/h8300/mm/init.c | 4 ++-- arch/i386/mm/init.c | 6 +++--- arch/ia64/mm/init.c | 6 +++--- arch/m32r/mm/init.c | 4 ++-- arch/m68k/mm/init.c | 2 +- arch/m68k/mm/memory.c | 2 +- arch/m68k/mm/motorola.c | 2 +- arch/m68knommu/mm/init.c | 4 ++-- arch/mips/arc/memory.c | 2 +- arch/mips/dec/prom/memory.c | 2 +- arch/mips/mips-boards/generic/memory.c | 2 +- arch/mips/mips-boards/sim/sim_mem.c | 2 +- arch/mips/mm/init.c | 6 +++--- arch/mips/sgi-ip27/ip27-memory.c | 2 +- arch/parisc/mm/init.c | 4 ++-- arch/powerpc/mm/init_32.c | 4 ++-- arch/powerpc/mm/init_64.c | 4 ++-- arch/powerpc/mm/mem.c | 4 ++-- arch/powerpc/platforms/cell/setup.c | 2 +- arch/ppc/mm/init.c | 6 +++--- arch/s390/mm/init.c | 4 ++-- arch/sh/mm/init.c | 4 ++-- arch/sh64/mm/init.c | 4 ++-- arch/sparc/kernel/sun4d_smp.c | 6 +++--- arch/sparc/kernel/sun4m_smp.c | 6 +++--- arch/sparc/mm/init.c | 6 +++--- arch/sparc64/mm/init.c | 4 ++-- arch/um/kernel/mem.c | 4 ++-- arch/x86_64/mm/init.c | 6 +++--- arch/xtensa/mm/init.c | 2 +- drivers/video/acornfb.c | 2 +- include/linux/mm.h | 11 +++++++++-- mm/hugetlb.c | 5 +++-- mm/internal.h | 13 ++++++++++++- mm/page_alloc.c | 14 ++++++-------- 40 files changed, 96 insertions(+), 79 deletions(-) (limited to 'include') diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c index 486d7945583d..544ac5dc09eb 100644 --- a/arch/alpha/mm/init.c +++ b/arch/alpha/mm/init.c @@ -357,7 +357,7 @@ free_reserved_mem(void *start, void *end) void *__start = start; for (; __start < end; __start += PAGE_SIZE) { ClearPageReserved(virt_to_page(__start)); - set_page_count(virt_to_page(__start), 1); + init_page_count(virt_to_page(__start)); free_page((long)__start); totalram_pages++; } diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 8b276ee38acf..b0321e943b76 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -531,7 +531,7 @@ static inline void free_area(unsigned long addr, unsigned long end, char *s) for (; addr < end; addr += PAGE_SIZE) { struct page *page = virt_to_page(addr); ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); free_page(addr); totalram_pages++; } diff --git a/arch/arm26/mm/init.c b/arch/arm26/mm/init.c index 1f09a9d0fb83..e3ecaa453747 100644 --- a/arch/arm26/mm/init.c +++ b/arch/arm26/mm/init.c @@ -324,7 +324,7 @@ static inline void free_area(unsigned long addr, unsigned long end, char *s) for (; addr < end; addr += PAGE_SIZE) { struct page *page = virt_to_page(addr); ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); free_page(addr); totalram_pages++; } diff --git a/arch/cris/mm/init.c b/arch/cris/mm/init.c index 31a0018b525a..b7842ff213a6 100644 --- a/arch/cris/mm/init.c +++ b/arch/cris/mm/init.c @@ -216,7 +216,7 @@ free_initmem(void) addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } diff --git a/arch/frv/mm/init.c b/arch/frv/mm/init.c index 765088ea8a50..8899aa1a4f06 100644 --- a/arch/frv/mm/init.c +++ b/arch/frv/mm/init.c @@ -169,7 +169,7 @@ void __init mem_init(void) struct page *page = &mem_map[pfn]; ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalram_pages++; } @@ -210,7 +210,7 @@ void __init free_initmem(void) /* next to check that the page we free is not a partial page */ for (addr = start; addr < end; addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } @@ -230,7 +230,7 @@ void __init free_initrd_mem(unsigned long start, unsigned long end) int pages = 0; for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; pages++; diff --git a/arch/h8300/mm/init.c b/arch/h8300/mm/init.c index 1e0929ddc8c4..09efc4b1f038 100644 --- a/arch/h8300/mm/init.c +++ b/arch/h8300/mm/init.c @@ -196,7 +196,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) int pages = 0; for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; pages++; @@ -219,7 +219,7 @@ free_initmem() /* next to check that the page we free is not a partial page */ for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 2700f01994ba..7ba55a6e2dbc 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -270,7 +270,7 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base) static void __meminit free_new_highpage(struct page *page) { - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalhigh_pages++; } @@ -727,7 +727,7 @@ void free_initmem(void) addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); memset((void *)addr, 0xcc, PAGE_SIZE); free_page(addr); totalram_pages++; @@ -766,7 +766,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) printk (KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; } diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index b38b6d213c15..08d94e6bfa18 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -197,7 +197,7 @@ free_initmem (void) eaddr = (unsigned long) ia64_imva(__init_end); while (addr < eaddr) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); ++totalram_pages; addr += PAGE_SIZE; @@ -252,7 +252,7 @@ free_initrd_mem (unsigned long start, unsigned long end) continue; page = virt_to_page(start); ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); free_page(start); ++totalram_pages; } @@ -640,7 +640,7 @@ mem_init (void) void online_page(struct page *page) { ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalram_pages++; num_physpages++; diff --git a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c index 6facf15b04f3..c9e7dad860b7 100644 --- a/arch/m32r/mm/init.c +++ b/arch/m32r/mm/init.c @@ -226,7 +226,7 @@ void free_initmem(void) addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } @@ -244,7 +244,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) unsigned long p; for (p = start; p < end; p += PAGE_SIZE) { ClearPageReserved(virt_to_page(p)); - set_page_count(virt_to_page(p), 1); + init_page_count(virt_to_page(p)); free_page(p); totalram_pages++; } diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c index c45beb955943..a190e39c907a 100644 --- a/arch/m68k/mm/init.c +++ b/arch/m68k/mm/init.c @@ -137,7 +137,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) int pages = 0; for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; pages++; diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c index 559942ce0e1e..d6d582a5abb0 100644 --- a/arch/m68k/mm/memory.c +++ b/arch/m68k/mm/memory.c @@ -54,7 +54,7 @@ void __init init_pointer_table(unsigned long ptable) /* unreserve the page so it's possible to free that page */ PD_PAGE(dp)->flags &= ~(1 << PG_reserved); - set_page_count(PD_PAGE(dp), 1); + init_page_count(PD_PAGE(dp)); return; } diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c index d855fec26317..afb57eeafdcb 100644 --- a/arch/m68k/mm/motorola.c +++ b/arch/m68k/mm/motorola.c @@ -276,7 +276,7 @@ void free_initmem(void) addr = (unsigned long)&__init_begin; for (; addr < (unsigned long)&__init_end; addr += PAGE_SIZE) { virt_to_page(addr)->flags &= ~(1 << PG_reserved); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } diff --git a/arch/m68knommu/mm/init.c b/arch/m68knommu/mm/init.c index 89f0b554ffb7..d79503fe6e42 100644 --- a/arch/m68knommu/mm/init.c +++ b/arch/m68knommu/mm/init.c @@ -195,7 +195,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) int pages = 0; for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; pages++; @@ -218,7 +218,7 @@ free_initmem() /* next to check that the page we free is not a partial page */ for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } diff --git a/arch/mips/arc/memory.c b/arch/mips/arc/memory.c index 958d2eb78862..8a9ef58cc399 100644 --- a/arch/mips/arc/memory.c +++ b/arch/mips/arc/memory.c @@ -158,7 +158,7 @@ unsigned long __init prom_free_prom_memory(void) while (addr < boot_mem_map.map[i].addr + boot_mem_map.map[i].size) { ClearPageReserved(virt_to_page(__va(addr))); - set_page_count(virt_to_page(__va(addr)), 1); + init_page_count(virt_to_page(__va(addr))); free_page((unsigned long)__va(addr)); addr += PAGE_SIZE; freed += PAGE_SIZE; diff --git a/arch/mips/dec/prom/memory.c b/arch/mips/dec/prom/memory.c index 81cb5a76cfb7..1edaf3074ee9 100644 --- a/arch/mips/dec/prom/memory.c +++ b/arch/mips/dec/prom/memory.c @@ -118,7 +118,7 @@ unsigned long __init prom_free_prom_memory(void) addr = PAGE_SIZE; while (addr < end) { ClearPageReserved(virt_to_page(__va(addr))); - set_page_count(virt_to_page(__va(addr)), 1); + init_page_count(virt_to_page(__va(addr))); free_page((unsigned long)__va(addr)); addr += PAGE_SIZE; } diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c index 2c8afd77a20b..ee5e70c95cf3 100644 --- a/arch/mips/mips-boards/generic/memory.c +++ b/arch/mips/mips-boards/generic/memory.c @@ -174,7 +174,7 @@ unsigned long __init prom_free_prom_memory(void) while (addr < boot_mem_map.map[i].addr + boot_mem_map.map[i].size) { ClearPageReserved(virt_to_page(__va(addr))); - set_page_count(virt_to_page(__va(addr)), 1); + init_page_count(virt_to_page(__va(addr))); free_page((unsigned long)__va(addr)); addr += PAGE_SIZE; freed += PAGE_SIZE; diff --git a/arch/mips/mips-boards/sim/sim_mem.c b/arch/mips/mips-boards/sim/sim_mem.c index 0dbd7435bb2a..1ec4e75656bd 100644 --- a/arch/mips/mips-boards/sim/sim_mem.c +++ b/arch/mips/mips-boards/sim/sim_mem.c @@ -117,7 +117,7 @@ unsigned long __init prom_free_prom_memory(void) while (addr < boot_mem_map.map[i].addr + boot_mem_map.map[i].size) { ClearPageReserved(virt_to_page(__va(addr))); - set_page_count(virt_to_page(__va(addr)), 1); + init_page_count(virt_to_page(__va(addr))); free_page((unsigned long)__va(addr)); addr += PAGE_SIZE; freed += PAGE_SIZE; diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index a140da9732db..52f7d59fe612 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -245,7 +245,7 @@ void __init mem_init(void) #ifdef CONFIG_LIMITED_DMA set_page_address(page, lowmem_page_address(page)); #endif - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalhigh_pages++; } @@ -292,7 +292,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; } @@ -315,7 +315,7 @@ void free_initmem(void) page = addr; #endif ClearPageReserved(virt_to_page(page)); - set_page_count(virt_to_page(page), 1); + init_page_count(virt_to_page(page)); free_page(page); totalram_pages++; freed += PAGE_SIZE; diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c index ed93a9792959..e0d095daa5ed 100644 --- a/arch/mips/sgi-ip27/ip27-memory.c +++ b/arch/mips/sgi-ip27/ip27-memory.c @@ -559,7 +559,7 @@ void __init mem_init(void) /* if (!page_is_ram(pgnr)) continue; */ /* commented out until page_is_ram works */ ClearPageReserved(p); - set_page_count(p, 1); + init_page_count(p); __free_page(p); totalram_pages++; } diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 7847ca13d6c2..852eda3953dc 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -398,7 +398,7 @@ void free_initmem(void) addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); num_physpages++; totalram_pages++; @@ -1018,7 +1018,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); num_physpages++; totalram_pages++; diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 7d0d75c11848..b57fb3a2b7bb 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c @@ -216,7 +216,7 @@ static void free_sec(unsigned long start, unsigned long end, const char *name) while (start < end) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); cnt++; start += PAGE_SIZE; @@ -248,7 +248,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; } diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 81cfb0c2ec58..bacb71c89811 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -140,7 +140,7 @@ void free_initmem(void) for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) { memset((void *)addr, 0xcc, PAGE_SIZE); ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } @@ -155,7 +155,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; } diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 6ae5c130d0db..454cac01d8cc 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -108,7 +108,7 @@ EXPORT_SYMBOL(phys_mem_access_prot); void online_page(struct page *page) { ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalram_pages++; num_physpages++; @@ -376,7 +376,7 @@ void __init mem_init(void) struct page *page = pfn_to_page(pfn); ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalhigh_pages++; } diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index b33a4443f5a9..fec8e65b36ea 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -115,7 +115,7 @@ static void __init cell_spuprop_present(struct device_node *spe, for (pfn = start_pfn; pfn < end_pfn; pfn++) { struct page *page = pfn_to_page(pfn); set_page_links(page, ZONE_DMA, node_id, pfn); - set_page_count(page, 1); + init_page_count(page); reset_page_mapcount(page); SetPageReserved(page); INIT_LIST_HEAD(&page->lru); diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index 134db5c04203..cb1c294fb932 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -140,7 +140,7 @@ static void free_sec(unsigned long start, unsigned long end, const char *name) while (start < end) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); cnt++; start += PAGE_SIZE; @@ -172,7 +172,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; } @@ -441,7 +441,7 @@ void __init mem_init(void) struct page *page = mem_map + pfn; ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalhigh_pages++; } diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index df953383724d..a055894f3bd8 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -292,7 +292,7 @@ void free_initmem(void) addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } @@ -307,7 +307,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; } diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index e342565f75fb..77b4a838fe10 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -273,7 +273,7 @@ void free_initmem(void) addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } @@ -286,7 +286,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) unsigned long p; for (p = start; p < end; p += PAGE_SIZE) { ClearPageReserved(virt_to_page(p)); - set_page_count(virt_to_page(p), 1); + init_page_count(virt_to_page(p)); free_page(p); totalram_pages++; } diff --git a/arch/sh64/mm/init.c b/arch/sh64/mm/init.c index a65e8bb2c3cc..1169757fb38b 100644 --- a/arch/sh64/mm/init.c +++ b/arch/sh64/mm/init.c @@ -173,7 +173,7 @@ void free_initmem(void) addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } @@ -186,7 +186,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) unsigned long p; for (p = start; p < end; p += PAGE_SIZE) { ClearPageReserved(virt_to_page(p)); - set_page_count(virt_to_page(p), 1); + init_page_count(virt_to_page(p)); free_page(p); totalram_pages++; } diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index 40d426cce824..4219dd2ce3a2 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -266,19 +266,19 @@ void __init smp4d_boot_cpus(void) /* Free unneeded trap tables */ ClearPageReserved(virt_to_page(trapbase_cpu1)); - set_page_count(virt_to_page(trapbase_cpu1), 1); + init_page_count(virt_to_page(trapbase_cpu1)); free_page((unsigned long)trapbase_cpu1); totalram_pages++; num_physpages++; ClearPageReserved(virt_to_page(trapbase_cpu2)); - set_page_count(virt_to_page(trapbase_cpu2), 1); + init_page_count(virt_to_page(trapbase_cpu2)); free_page((unsigned long)trapbase_cpu2); totalram_pages++; num_physpages++; ClearPageReserved(virt_to_page(trapbase_cpu3)); - set_page_count(virt_to_page(trapbase_cpu3), 1); + init_page_count(virt_to_page(trapbase_cpu3)); free_page((unsigned long)trapbase_cpu3); totalram_pages++; num_physpages++; diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index a21f27d10e55..fbbd8a474c4c 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -233,21 +233,21 @@ void __init smp4m_boot_cpus(void) /* Free unneeded trap tables */ if (!cpu_isset(i, cpu_present_map)) { ClearPageReserved(virt_to_page(trapbase_cpu1)); - set_page_count(virt_to_page(trapbase_cpu1), 1); + init_page_count(virt_to_page(trapbase_cpu1)); free_page((unsigned long)trapbase_cpu1); totalram_pages++; num_physpages++; } if (!cpu_isset(2, cpu_present_map)) { ClearPageReserved(virt_to_page(trapbase_cpu2)); - set_page_count(virt_to_page(trapbase_cpu2), 1); + init_page_count(virt_to_page(trapbase_cpu2)); free_page((unsigned long)trapbase_cpu2); totalram_pages++; num_physpages++; } if (!cpu_isset(3, cpu_present_map)) { ClearPageReserved(virt_to_page(trapbase_cpu3)); - set_page_count(virt_to_page(trapbase_cpu3), 1); + init_page_count(virt_to_page(trapbase_cpu3)); free_page((unsigned long)trapbase_cpu3); totalram_pages++; num_physpages++; diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c index c03babaa0498..898669732466 100644 --- a/arch/sparc/mm/init.c +++ b/arch/sparc/mm/init.c @@ -383,7 +383,7 @@ void map_high_region(unsigned long start_pfn, unsigned long end_pfn) struct page *page = pfn_to_page(tmp); ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalhigh_pages++; } @@ -480,7 +480,7 @@ void free_initmem (void) p = virt_to_page(addr); ClearPageReserved(p); - set_page_count(p, 1); + init_page_count(p); __free_page(p); totalram_pages++; num_physpages++; @@ -497,7 +497,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) struct page *p = virt_to_page(start); ClearPageReserved(p); - set_page_count(p, 1); + init_page_count(p); __free_page(p); num_physpages++; } diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index c2b556106fc1..2ae143ba50d8 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -1461,7 +1461,7 @@ void free_initmem(void) p = virt_to_page(page); ClearPageReserved(p); - set_page_count(p, 1); + init_page_count(p); __free_page(p); num_physpages++; totalram_pages++; @@ -1477,7 +1477,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) struct page *p = virt_to_page(start); ClearPageReserved(p); - set_page_count(p, 1); + init_page_count(p); __free_page(p); num_physpages++; totalram_pages++; diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index fa4f915be5c5..92cce96b5e24 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -57,7 +57,7 @@ static void setup_highmem(unsigned long highmem_start, for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){ page = &mem_map[highmem_pfn + i]; ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); __free_page(page); } } @@ -296,7 +296,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; } diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index 7af1742aa958..40ed13d263cd 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c @@ -486,7 +486,7 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size) void online_page(struct page *page) { ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalram_pages++; num_physpages++; @@ -592,7 +592,7 @@ void free_initmem(void) addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); memset((void *)(addr & ~(PAGE_SIZE-1)), 0xcc, PAGE_SIZE); free_page(addr); totalram_pages++; @@ -632,7 +632,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; } diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c index 5a91d6c9e66d..e1be4235f367 100644 --- a/arch/xtensa/mm/init.c +++ b/arch/xtensa/mm/init.c @@ -272,7 +272,7 @@ free_reserved_mem(void *start, void *end) { for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page((unsigned long)start); totalram_pages++; } diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index b058273527bb..76448d6ae896 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c @@ -1269,7 +1269,7 @@ free_unused_pages(unsigned int virtual_start, unsigned int virtual_end) */ page = virt_to_page(virtual_start); ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); free_page(virtual_start); virtual_start += PAGE_SIZE; diff --git a/include/linux/mm.h b/include/linux/mm.h index 3d84b7a35e0d..7d8c127daad7 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -307,8 +307,6 @@ static inline int get_page_unless_zero(struct page *page) return atomic_inc_not_zero(&page->_count); } -#define set_page_count(p,v) atomic_set(&(p)->_count, (v)) - extern void FASTCALL(__page_cache_release(struct page *)); static inline int page_count(struct page *page) @@ -325,6 +323,15 @@ static inline void get_page(struct page *page) atomic_inc(&page->_count); } +/* + * Setup the page count before being freed into the page allocator for + * the first time (boot or memory hotplug) + */ +static inline void init_page_count(struct page *page) +{ + atomic_set(&page->_count, 1); +} + void put_page(struct page *page); void split_page(struct page *page, unsigned int order); diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 39d49ecea8e8..20117a4b8ab6 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -18,6 +18,7 @@ #include #include +#include "internal.h" const unsigned long hugetlb_zero = 0, hugetlb_infinity = ~0UL; static unsigned long nr_huge_pages, free_huge_pages; @@ -106,7 +107,7 @@ struct page *alloc_huge_page(struct vm_area_struct *vma, unsigned long addr) return NULL; } spin_unlock(&hugetlb_lock); - set_page_count(page, 1); + set_page_refcounted(page); for (i = 0; i < (HPAGE_SIZE/PAGE_SIZE); ++i) clear_user_highpage(&page[i], addr); return page; @@ -152,7 +153,7 @@ static void update_and_free_page(struct page *page) 1 << PG_private | 1<< PG_writeback); } page[1].lru.next = NULL; - set_page_count(page, 1); + set_page_refcounted(page); __free_pages(page, HUGETLB_PAGE_ORDER); } diff --git a/mm/internal.h b/mm/internal.h index 7bb339779818..d20e3cc4aef0 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -13,8 +13,19 @@ #include -static inline void set_page_refs(struct page *page, int order) +static inline void set_page_count(struct page *page, int v) { + atomic_set(&page->_count, v); +} + +/* + * Turn a non-refcounted page (->_count == 0) into refcounted with + * a count of one. + */ +static inline void set_page_refcounted(struct page *page) +{ + BUG_ON(PageCompound(page) && page_private(page) != (unsigned long)page); + BUG_ON(atomic_read(&page->_count)); set_page_count(page, 1); } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index e197818a7cf6..7f65b5a63bb3 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -442,7 +442,7 @@ void fastcall __init __free_pages_bootmem(struct page *page, unsigned int order) if (order == 0) { __ClearPageReserved(page); set_page_count(page, 0); - set_page_refs(page, 0); + set_page_refcounted(page); __free_page(page); } else { int loop; @@ -457,7 +457,7 @@ void fastcall __init __free_pages_bootmem(struct page *page, unsigned int order) set_page_count(p, 0); } - set_page_refs(page, order); + set_page_refcounted(page); __free_pages(page, order); } } @@ -525,7 +525,7 @@ static int prep_new_page(struct page *page, int order) 1 << PG_referenced | 1 << PG_arch_1 | 1 << PG_checked | 1 << PG_mappedtodisk); set_page_private(page, 0); - set_page_refs(page, order); + set_page_refcounted(page); kernel_map_pages(page, 1 << order, 1); return 0; } @@ -755,10 +755,8 @@ void split_page(struct page *page, unsigned int order) BUG_ON(PageCompound(page)); BUG_ON(!page_count(page)); - for (i = 1; i < (1 << order); i++) { - BUG_ON(page_count(page + i)); - set_page_count(page + i, 1); - } + for (i = 1; i < (1 << order); i++) + set_page_refcounted(page + i); } /* @@ -1771,7 +1769,7 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, continue; page = pfn_to_page(pfn); set_page_links(page, zone, nid, pfn); - set_page_count(page, 1); + init_page_count(page); reset_page_mapcount(page); SetPageReserved(page); INIT_LIST_HEAD(&page->lru); -- cgit v1.2.3 From 617d2214ee06c209e5c375c280d50abace8058e1 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 22 Mar 2006 00:08:43 -0800 Subject: [PATCH] mm: optimise page_count Optimise page_count compound page test and make it consistent with similar functions. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/mm.h b/include/linux/mm.h index 7d8c127daad7..6aa016f1d3ae 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -311,7 +311,7 @@ extern void FASTCALL(__page_cache_release(struct page *)); static inline int page_count(struct page *page) { - if (PageCompound(page)) + if (unlikely(PageCompound(page))) page = (struct page *)page_private(page); return atomic_read(&page->_count); } -- cgit v1.2.3 From 8f860591ffb29738cf5539b6fbf27f50dcdeb380 Mon Sep 17 00:00:00 2001 From: "Zhang, Yanmin" Date: Wed, 22 Mar 2006 00:08:50 -0800 Subject: [PATCH] Enable mprotect on huge pages 2.6.16-rc3 uses hugetlb on-demand paging, but it doesn_t support hugetlb mprotect. From: David Gibson Remove a test from the mprotect() path which checks that the mprotect()ed range on a hugepage VMA is hugepage aligned (yes, really, the sense of is_aligned_hugepage_range() is the opposite of what you'd guess :-/). In fact, we don't need this test. If the given addresses match the beginning/end of a hugepage VMA they must already be suitably aligned. If they don't, then mprotect_fixup() will attempt to split the VMA. The very first test in split_vma() will check for a badly aligned address on a hugepage VMA and return -EINVAL if necessary. From: "Chen, Kenneth W" On i386 and x86-64, pte flag _PAGE_PSE collides with _PAGE_PROTNONE. The identify of hugetlb pte is lost when changing page protection via mprotect. A page fault occurs later will trigger a bug check in huge_pte_alloc(). The fix is to always make new pte a hugetlb pte and also to clean up legacy code where _PAGE_PRESENT is forced on in the pre-faulting day. Signed-off-by: Zhang Yanmin Cc: David Gibson Cc: "David S. Miller" Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: William Lee Irwin III Signed-off-by: Ken Chen Signed-off-by: Nishanth Aravamudan Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-i386/pgtable.h | 5 ++--- include/asm-ia64/pgtable.h | 2 +- include/asm-x86_64/pgtable.h | 4 ++-- include/linux/hugetlb.h | 4 ++++ mm/hugetlb.c | 29 +++++++++++++++++++++++++++++ mm/mprotect.c | 12 +++++------- 6 files changed, 43 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h index 088a945bf26b..ee056c41a9fb 100644 --- a/include/asm-i386/pgtable.h +++ b/include/asm-i386/pgtable.h @@ -219,13 +219,12 @@ extern unsigned long pg0[]; * The following only work if pte_present() is true. * Undefined behaviour if not.. */ -#define __LARGE_PTE (_PAGE_PSE | _PAGE_PRESENT) static inline int pte_user(pte_t pte) { return (pte).pte_low & _PAGE_USER; } static inline int pte_read(pte_t pte) { return (pte).pte_low & _PAGE_USER; } static inline int pte_dirty(pte_t pte) { return (pte).pte_low & _PAGE_DIRTY; } static inline int pte_young(pte_t pte) { return (pte).pte_low & _PAGE_ACCESSED; } static inline int pte_write(pte_t pte) { return (pte).pte_low & _PAGE_RW; } -static inline int pte_huge(pte_t pte) { return ((pte).pte_low & __LARGE_PTE) == __LARGE_PTE; } +static inline int pte_huge(pte_t pte) { return (pte).pte_low & _PAGE_PSE; } /* * The following only works if pte_present() is not true. @@ -242,7 +241,7 @@ static inline pte_t pte_mkexec(pte_t pte) { (pte).pte_low |= _PAGE_USER; return static inline pte_t pte_mkdirty(pte_t pte) { (pte).pte_low |= _PAGE_DIRTY; return pte; } static inline pte_t pte_mkyoung(pte_t pte) { (pte).pte_low |= _PAGE_ACCESSED; return pte; } static inline pte_t pte_mkwrite(pte_t pte) { (pte).pte_low |= _PAGE_RW; return pte; } -static inline pte_t pte_mkhuge(pte_t pte) { (pte).pte_low |= __LARGE_PTE; return pte; } +static inline pte_t pte_mkhuge(pte_t pte) { (pte).pte_low |= _PAGE_PSE; return pte; } #ifdef CONFIG_X86_PAE # include diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h index e2560c58384b..5890972a69bf 100644 --- a/include/asm-ia64/pgtable.h +++ b/include/asm-ia64/pgtable.h @@ -314,7 +314,7 @@ ia64_phys_addr_valid (unsigned long addr) #define pte_mkyoung(pte) (__pte(pte_val(pte) | _PAGE_A)) #define pte_mkclean(pte) (__pte(pte_val(pte) & ~_PAGE_D)) #define pte_mkdirty(pte) (__pte(pte_val(pte) | _PAGE_D)) -#define pte_mkhuge(pte) (__pte(pte_val(pte) | _PAGE_P)) +#define pte_mkhuge(pte) (__pte(pte_val(pte))) /* * Macro to a page protection value as "uncacheable". Note that "protection" is really a diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h index 715fd94cf577..a617d364d08d 100644 --- a/include/asm-x86_64/pgtable.h +++ b/include/asm-x86_64/pgtable.h @@ -273,7 +273,7 @@ static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; } static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; } -static inline int pte_huge(pte_t pte) { return (pte_val(pte) & __LARGE_PTE) == __LARGE_PTE; } +static inline int pte_huge(pte_t pte) { return pte_val(pte) & _PAGE_PSE; } static inline pte_t pte_rdprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; } static inline pte_t pte_exprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; } @@ -285,7 +285,7 @@ static inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _ static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; } static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; } static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; } -static inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | __LARGE_PTE)); return pte; } +static inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_PSE)); return pte; } struct vm_area_struct; diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 68d82ad6b17c..fa83836b63d2 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -41,6 +41,8 @@ struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address, pmd_t *pmd, int write); int is_aligned_hugepage_range(unsigned long addr, unsigned long len); int pmd_huge(pmd_t pmd); +void hugetlb_change_protection(struct vm_area_struct *vma, + unsigned long address, unsigned long end, pgprot_t newprot); #ifndef ARCH_HAS_HUGEPAGE_ONLY_RANGE #define is_hugepage_only_range(mm, addr, len) 0 @@ -101,6 +103,8 @@ static inline unsigned long hugetlb_total_pages(void) #define free_huge_page(p) ({ (void)(p); BUG(); }) #define hugetlb_fault(mm, vma, addr, write) ({ BUG(); 0; }) +#define hugetlb_change_protection(vma, address, end, newprot) + #ifndef HPAGE_MASK #define HPAGE_MASK PAGE_MASK /* Keep the compiler happy */ #define HPAGE_SIZE PAGE_SIZE diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 20117a4b8ab6..783098f6cf8e 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -565,3 +565,32 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, return i; } + +void hugetlb_change_protection(struct vm_area_struct *vma, + unsigned long address, unsigned long end, pgprot_t newprot) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned long start = address; + pte_t *ptep; + pte_t pte; + + BUG_ON(address >= end); + flush_cache_range(vma, address, end); + + spin_lock(&mm->page_table_lock); + for (; address < end; address += HPAGE_SIZE) { + ptep = huge_pte_offset(mm, address); + if (!ptep) + continue; + if (!pte_none(*ptep)) { + pte = huge_ptep_get_and_clear(mm, address, ptep); + pte = pte_mkhuge(pte_modify(pte, newprot)); + set_huge_pte_at(mm, address, ptep, pte); + lazy_mmu_prot_update(pte); + } + } + spin_unlock(&mm->page_table_lock); + + flush_tlb_range(vma, start, end); +} + diff --git a/mm/mprotect.c b/mm/mprotect.c index 653b8571c1ed..4c14d4289b61 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -124,7 +124,7 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, * a MAP_NORESERVE private mapping to writable will now reserve. */ if (newflags & VM_WRITE) { - if (!(oldflags & (VM_ACCOUNT|VM_WRITE|VM_SHARED|VM_HUGETLB))) { + if (!(oldflags & (VM_ACCOUNT|VM_WRITE|VM_SHARED))) { charged = nrpages; if (security_vm_enough_memory(charged)) return -ENOMEM; @@ -166,7 +166,10 @@ success: */ vma->vm_flags = newflags; vma->vm_page_prot = newprot; - change_protection(vma, start, end, newprot); + if (is_vm_hugetlb_page(vma)) + hugetlb_change_protection(vma, start, end, newprot); + else + change_protection(vma, start, end, newprot); vm_stat_account(mm, oldflags, vma->vm_file, -nrpages); vm_stat_account(mm, newflags, vma->vm_file, nrpages); return 0; @@ -240,11 +243,6 @@ sys_mprotect(unsigned long start, size_t len, unsigned long prot) /* Here we know that vma->vm_start <= nstart < vma->vm_end. */ - if (is_vm_hugetlb_page(vma)) { - error = -EACCES; - goto out; - } - newflags = vm_flags | (vma->vm_flags & ~(VM_READ | VM_WRITE | VM_EXEC)); /* newflags >> 4 shift VM_MAY% in place of VM_% */ -- cgit v1.2.3 From b45b5bd65f668a665db40d093e4e1fe563533608 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 22 Mar 2006 00:08:55 -0800 Subject: [PATCH] hugepage: Strict page reservation for hugepage inodes These days, hugepages are demand-allocated at first fault time. There's a somewhat dubious (and racy) heuristic when making a new mmap() to check if there are enough available hugepages to fully satisfy that mapping. A particularly obvious case where the heuristic breaks down is where a process maps its hugepages not as a single chunk, but as a bunch of individually mmap()ed (or shmat()ed) blocks without touching and instantiating the pages in between allocations. In this case the size of each block is compared against the total number of available hugepages. It's thus easy for the process to become overcommitted, because each block mapping will succeed, although the total number of hugepages required by all blocks exceeds the number available. In particular, this defeats such a program which will detect a mapping failure and adjust its hugepage usage downward accordingly. The patch below addresses this problem, by strictly reserving a number of physical hugepages for hugepage inodes which have been mapped, but not instatiated. MAP_SHARED mappings are thus "safe" - they will fail on mmap(), not later with an OOM SIGKILL. MAP_PRIVATE mappings can still trigger an OOM. (Actually SHARED mappings can technically still OOM, but only if the sysadmin explicitly reduces the hugepage pool between mapping and instantiation) This patch appears to address the problem at hand - it allows DB2 to start correctly, for instance, which previously suffered the failure described above. This patch causes no regressions on the libhugetblfs testsuite, and makes a test (designed to catch this problem) pass which previously failed (ppc64, POWER5). Signed-off-by: David Gibson Cc: William Lee Irwin III Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hugetlbfs/inode.c | 74 ++++++++------------------ include/linux/hugetlb.h | 8 ++- mm/hugetlb.c | 136 ++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 154 insertions(+), 64 deletions(-) (limited to 'include') diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index b35195289945..1a1c2fcb7823 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -56,48 +56,10 @@ static void huge_pagevec_release(struct pagevec *pvec) pagevec_reinit(pvec); } -/* - * huge_pages_needed tries to determine the number of new huge pages that - * will be required to fully populate this VMA. This will be equal to - * the size of the VMA in huge pages minus the number of huge pages - * (covered by this VMA) that are found in the page cache. - * - * Result is in bytes to be compatible with is_hugepage_mem_enough() - */ -static unsigned long -huge_pages_needed(struct address_space *mapping, struct vm_area_struct *vma) -{ - int i; - struct pagevec pvec; - unsigned long start = vma->vm_start; - unsigned long end = vma->vm_end; - unsigned long hugepages = (end - start) >> HPAGE_SHIFT; - pgoff_t next = vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT); - pgoff_t endpg = next + hugepages; - - pagevec_init(&pvec, 0); - while (next < endpg) { - if (!pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) - break; - for (i = 0; i < pagevec_count(&pvec); i++) { - struct page *page = pvec.pages[i]; - if (page->index > next) - next = page->index; - if (page->index >= endpg) - break; - next++; - hugepages--; - } - huge_pagevec_release(&pvec); - } - return hugepages << HPAGE_SHIFT; -} - static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) { struct inode *inode = file->f_dentry->d_inode; - struct address_space *mapping = inode->i_mapping; - unsigned long bytes; + struct hugetlbfs_inode_info *info = HUGETLBFS_I(inode); loff_t len, vma_len; int ret; @@ -113,10 +75,6 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) if (vma->vm_end - vma->vm_start < HPAGE_SIZE) return -EINVAL; - bytes = huge_pages_needed(mapping, vma); - if (!is_hugepage_mem_enough(bytes)) - return -ENOMEM; - vma_len = (loff_t)(vma->vm_end - vma->vm_start); mutex_lock(&inode->i_mutex); @@ -129,6 +87,10 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) if (!(vma->vm_flags & VM_WRITE) && len > inode->i_size) goto out; + if (vma->vm_flags & VM_MAYSHARE) + if (hugetlb_extend_reservation(info, len >> HPAGE_SHIFT) != 0) + goto out; + ret = 0; hugetlb_prefault_arch_hook(vma->vm_mm); if (inode->i_size < len) @@ -227,13 +189,18 @@ static void truncate_huge_page(struct page *page) put_page(page); } -static void truncate_hugepages(struct address_space *mapping, loff_t lstart) +static void truncate_hugepages(struct inode *inode, loff_t lstart) { + struct address_space *mapping = &inode->i_data; const pgoff_t start = lstart >> HPAGE_SHIFT; struct pagevec pvec; pgoff_t next; int i; + hugetlb_truncate_reservation(HUGETLBFS_I(inode), + lstart >> HPAGE_SHIFT); + if (!mapping->nrpages) + return; pagevec_init(&pvec, 0); next = start; while (1) { @@ -262,8 +229,7 @@ static void truncate_hugepages(struct address_space *mapping, loff_t lstart) static void hugetlbfs_delete_inode(struct inode *inode) { - if (inode->i_data.nrpages) - truncate_hugepages(&inode->i_data, 0); + truncate_hugepages(inode, 0); clear_inode(inode); } @@ -296,8 +262,7 @@ static void hugetlbfs_forget_inode(struct inode *inode) inode->i_state |= I_FREEING; inodes_stat.nr_inodes--; spin_unlock(&inode_lock); - if (inode->i_data.nrpages) - truncate_hugepages(&inode->i_data, 0); + truncate_hugepages(inode, 0); clear_inode(inode); destroy_inode(inode); } @@ -356,7 +321,7 @@ static int hugetlb_vmtruncate(struct inode *inode, loff_t offset) if (!prio_tree_empty(&mapping->i_mmap)) hugetlb_vmtruncate_list(&mapping->i_mmap, pgoff); spin_unlock(&mapping->i_mmap_lock); - truncate_hugepages(mapping, offset); + truncate_hugepages(inode, offset); return 0; } @@ -573,6 +538,7 @@ static struct inode *hugetlbfs_alloc_inode(struct super_block *sb) hugetlbfs_inc_free_inodes(sbinfo); return NULL; } + p->prereserved_hpages = 0; return &p->vfs_inode; } @@ -805,9 +771,6 @@ struct file *hugetlb_zero_setup(size_t size) if (!can_do_hugetlb_shm()) return ERR_PTR(-EPERM); - if (!is_hugepage_mem_enough(size)) - return ERR_PTR(-ENOMEM); - if (!user_shm_lock(size, current->user)) return ERR_PTR(-ENOMEM); @@ -831,6 +794,11 @@ struct file *hugetlb_zero_setup(size_t size) if (!inode) goto out_file; + error = -ENOMEM; + if (hugetlb_extend_reservation(HUGETLBFS_I(inode), + size >> HPAGE_SHIFT) != 0) + goto out_inode; + d_instantiate(dentry, inode); inode->i_size = size; inode->i_nlink = 0; @@ -841,6 +809,8 @@ struct file *hugetlb_zero_setup(size_t size) file->f_mode = FMODE_WRITE | FMODE_READ; return file; +out_inode: + iput(inode); out_file: put_filp(file); out_dentry: diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index fa83836b63d2..cafe73eecb05 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -20,7 +20,6 @@ void unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long) int hugetlb_prefault(struct address_space *, struct vm_area_struct *); int hugetlb_report_meminfo(char *); int hugetlb_report_node_meminfo(int, char *); -int is_hugepage_mem_enough(size_t); unsigned long hugetlb_total_pages(void); struct page *alloc_huge_page(struct vm_area_struct *, unsigned long); void free_huge_page(struct page *); @@ -89,7 +88,6 @@ static inline unsigned long hugetlb_total_pages(void) #define copy_hugetlb_page_range(src, dst, vma) ({ BUG(); 0; }) #define hugetlb_prefault(mapping, vma) ({ BUG(); 0; }) #define unmap_hugepage_range(vma, start, end) BUG() -#define is_hugepage_mem_enough(size) 0 #define hugetlb_report_meminfo(buf) 0 #define hugetlb_report_node_meminfo(n, buf) 0 #define follow_huge_pmd(mm, addr, pmd, write) NULL @@ -132,6 +130,8 @@ struct hugetlbfs_sb_info { struct hugetlbfs_inode_info { struct shared_policy policy; + /* Protected by the (global) hugetlb_lock */ + unsigned long prereserved_hpages; struct inode vfs_inode; }; @@ -148,6 +148,10 @@ static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb) extern struct file_operations hugetlbfs_file_operations; extern struct vm_operations_struct hugetlb_vm_ops; struct file *hugetlb_zero_setup(size_t); +int hugetlb_extend_reservation(struct hugetlbfs_inode_info *info, + unsigned long atleast_hpages); +void hugetlb_truncate_reservation(struct hugetlbfs_inode_info *info, + unsigned long atmost_hpages); int hugetlb_get_quota(struct address_space *mapping); void hugetlb_put_quota(struct address_space *mapping); diff --git a/mm/hugetlb.c b/mm/hugetlb.c index d5987a87bbe5..27fad5d9bcf6 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -22,7 +22,7 @@ #include "internal.h" const unsigned long hugetlb_zero = 0, hugetlb_infinity = ~0UL; -static unsigned long nr_huge_pages, free_huge_pages; +static unsigned long nr_huge_pages, free_huge_pages, reserved_huge_pages; unsigned long max_huge_pages; static struct list_head hugepage_freelists[MAX_NUMNODES]; static unsigned int nr_huge_pages_node[MAX_NUMNODES]; @@ -120,17 +120,136 @@ void free_huge_page(struct page *page) struct page *alloc_huge_page(struct vm_area_struct *vma, unsigned long addr) { + struct inode *inode = vma->vm_file->f_dentry->d_inode; struct page *page; + int use_reserve = 0; + unsigned long idx; spin_lock(&hugetlb_lock); - page = dequeue_huge_page(vma, addr); - if (!page) { - spin_unlock(&hugetlb_lock); - return NULL; + + if (vma->vm_flags & VM_MAYSHARE) { + + /* idx = radix tree index, i.e. offset into file in + * HPAGE_SIZE units */ + idx = ((addr - vma->vm_start) >> HPAGE_SHIFT) + + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT)); + + /* The hugetlbfs specific inode info stores the number + * of "guaranteed available" (huge) pages. That is, + * the first 'prereserved_hpages' pages of the inode + * are either already instantiated, or have been + * pre-reserved (by hugetlb_reserve_for_inode()). Here + * we're in the process of instantiating the page, so + * we use this to determine whether to draw from the + * pre-reserved pool or the truly free pool. */ + if (idx < HUGETLBFS_I(inode)->prereserved_hpages) + use_reserve = 1; + } + + if (!use_reserve) { + if (free_huge_pages <= reserved_huge_pages) + goto fail; + } else { + BUG_ON(reserved_huge_pages == 0); + reserved_huge_pages--; } + + page = dequeue_huge_page(vma, addr); + if (!page) + goto fail; + spin_unlock(&hugetlb_lock); set_page_refcounted(page); return page; + + fail: + WARN_ON(use_reserve); /* reserved allocations shouldn't fail */ + spin_unlock(&hugetlb_lock); + return NULL; +} + +/* hugetlb_extend_reservation() + * + * Ensure that at least 'atleast' hugepages are, and will remain, + * available to instantiate the first 'atleast' pages of the given + * inode. If the inode doesn't already have this many pages reserved + * or instantiated, set aside some hugepages in the reserved pool to + * satisfy later faults (or fail now if there aren't enough, rather + * than getting the SIGBUS later). + */ +int hugetlb_extend_reservation(struct hugetlbfs_inode_info *info, + unsigned long atleast) +{ + struct inode *inode = &info->vfs_inode; + unsigned long change_in_reserve = 0; + int ret = 0; + + spin_lock(&hugetlb_lock); + read_lock_irq(&inode->i_mapping->tree_lock); + + if (info->prereserved_hpages >= atleast) + goto out; + + /* Because we always call this on shared mappings, none of the + * pages beyond info->prereserved_hpages can have been + * instantiated, so we need to reserve all of them now. */ + change_in_reserve = atleast - info->prereserved_hpages; + + if ((reserved_huge_pages + change_in_reserve) > free_huge_pages) { + ret = -ENOMEM; + goto out; + } + + reserved_huge_pages += change_in_reserve; + info->prereserved_hpages = atleast; + + out: + read_unlock_irq(&inode->i_mapping->tree_lock); + spin_unlock(&hugetlb_lock); + + return ret; +} + +/* hugetlb_truncate_reservation() + * + * This returns pages reserved for the given inode to the general free + * hugepage pool. If the inode has any pages prereserved, but not + * instantiated, beyond offset (atmost << HPAGE_SIZE), then release + * them. + */ +void hugetlb_truncate_reservation(struct hugetlbfs_inode_info *info, + unsigned long atmost) +{ + struct inode *inode = &info->vfs_inode; + struct address_space *mapping = inode->i_mapping; + unsigned long idx; + unsigned long change_in_reserve = 0; + struct page *page; + + spin_lock(&hugetlb_lock); + read_lock_irq(&inode->i_mapping->tree_lock); + + if (info->prereserved_hpages <= atmost) + goto out; + + /* Count pages which were reserved, but not instantiated, and + * which we can now release. */ + for (idx = atmost; idx < info->prereserved_hpages; idx++) { + page = radix_tree_lookup(&mapping->page_tree, idx); + if (!page) + /* Pages which are already instantiated can't + * be unreserved (and in fact have already + * been removed from the reserved pool) */ + change_in_reserve++; + } + + BUG_ON(reserved_huge_pages < change_in_reserve); + reserved_huge_pages -= change_in_reserve; + info->prereserved_hpages = atmost; + + out: + read_unlock_irq(&inode->i_mapping->tree_lock); + spin_unlock(&hugetlb_lock); } static int __init hugetlb_init(void) @@ -238,9 +357,11 @@ int hugetlb_report_meminfo(char *buf) return sprintf(buf, "HugePages_Total: %5lu\n" "HugePages_Free: %5lu\n" + "HugePages_Rsvd: %5lu\n" "Hugepagesize: %5lu kB\n", nr_huge_pages, free_huge_pages, + reserved_huge_pages, HPAGE_SIZE/1024); } @@ -253,11 +374,6 @@ int hugetlb_report_node_meminfo(int nid, char *buf) nid, free_huge_pages_node[nid]); } -int is_hugepage_mem_enough(size_t size) -{ - return (size + ~HPAGE_MASK)/HPAGE_SIZE <= free_huge_pages; -} - /* Return the number pages of memory we physically have, in PAGE_SIZE units. */ unsigned long hugetlb_total_pages(void) { -- cgit v1.2.3 From 27a85ef1b81300cfff06b4c8037e9914dfb09acc Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 22 Mar 2006 00:08:56 -0800 Subject: [PATCH] hugepage: Make {alloc,free}_huge_page() local Originally, mm/hugetlb.c just handled the hugepage physical allocation path and its {alloc,free}_huge_page() functions were used from the arch specific hugepage code. These days those functions are only used with mm/hugetlb.c itself. Therefore, this patch makes them static and removes their prototypes from hugetlb.h. This requires a small rearrangement of code in mm/hugetlb.c to avoid a forward declaration. This patch causes no regressions on the libhugetlbfs testsuite (ppc64, POWER5). Signed-off-by: David Gibson Cc: William Lee Irwin III Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/hugetlb.h | 4 ---- mm/hugetlb.c | 25 +++++++++++++------------ 2 files changed, 13 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index cafe73eecb05..5d84c368ffe4 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -21,8 +21,6 @@ int hugetlb_prefault(struct address_space *, struct vm_area_struct *); int hugetlb_report_meminfo(char *); int hugetlb_report_node_meminfo(int, char *); unsigned long hugetlb_total_pages(void); -struct page *alloc_huge_page(struct vm_area_struct *, unsigned long); -void free_huge_page(struct page *); int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long address, int write_access); @@ -97,8 +95,6 @@ static inline unsigned long hugetlb_total_pages(void) #define is_hugepage_only_range(mm, addr, len) 0 #define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) \ do { } while (0) -#define alloc_huge_page(vma, addr) ({ NULL; }) -#define free_huge_page(p) ({ (void)(p); BUG(); }) #define hugetlb_fault(mm, vma, addr, write) ({ BUG(); 0; }) #define hugetlb_change_protection(vma, address, end, newprot) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 27fad5d9bcf6..075877b1cbc0 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -88,6 +88,17 @@ static struct page *dequeue_huge_page(struct vm_area_struct *vma, return page; } +static void free_huge_page(struct page *page) +{ + BUG_ON(page_count(page)); + + INIT_LIST_HEAD(&page->lru); + + spin_lock(&hugetlb_lock); + enqueue_huge_page(page); + spin_unlock(&hugetlb_lock); +} + static int alloc_fresh_huge_page(void) { static int nid = 0; @@ -107,18 +118,8 @@ static int alloc_fresh_huge_page(void) return 0; } -void free_huge_page(struct page *page) -{ - BUG_ON(page_count(page)); - - INIT_LIST_HEAD(&page->lru); - - spin_lock(&hugetlb_lock); - enqueue_huge_page(page); - spin_unlock(&hugetlb_lock); -} - -struct page *alloc_huge_page(struct vm_area_struct *vma, unsigned long addr) +static struct page *alloc_huge_page(struct vm_area_struct *vma, + unsigned long addr) { struct inode *inode = vma->vm_file->f_dentry->d_inode; struct page *page; -- cgit v1.2.3 From 9da61aef0fd5b17dd4bf4baf33db12c470def774 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 22 Mar 2006 00:08:57 -0800 Subject: [PATCH] hugepage: Fix hugepage logic in free_pgtables() free_pgtables() has special logic to call hugetlb_free_pgd_range() instead of the normal free_pgd_range() on hugepage VMAs. However, the test it uses to do so is incorrect: it calls is_hugepage_only_range on a hugepage sized range at the start of the vma. is_hugepage_only_range() will return true if the given range has any intersection with a hugepage address region, and in this case the given region need not be hugepage aligned. So, for example, this test can return true if called on, say, a 4k VMA immediately preceding a (nicely aligned) hugepage VMA. At present we get away with this because the powerpc version of hugetlb_free_pgd_range() is just a call to free_pgd_range(). On ia64 (the only other arch with a non-trivial is_hugepage_only_range()) we get away with it for a different reason; the hugepage area is not contiguous with the rest of the user address space, and VMAs are not permitted in between, so the test can't return a false positive there. Nonetheless this should be fixed. We do that in the patch below by replacing the is_hugepage_only_range() test with an explicit test of the VMA using is_vm_hugetlb_page(). This in turn changes behaviour for platforms where is_hugepage_only_range() returns false always (everything except powerpc and ia64). We address this by ensuring that hugetlb_free_pgd_range() is defined to be identical to free_pgd_range() (instead of a no-op) on everything except ia64. Even so, it will prevent some otherwise possible coalescing of calls down to free_pgd_range(). Since this only happens for hugepage VMAs, removing this small optimization seems unlikely to cause any trouble. This patch causes no regressions on the libhugetlbfs testsuite - ppc64 POWER5 (8-way), ppc64 G5 (2-way) and i386 Pentium M (UP). Signed-off-by: David Gibson Cc: William Lee Irwin III Acked-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-ia64/page.h | 1 + include/asm-powerpc/pgtable.h | 5 ----- include/linux/hugetlb.h | 9 +++++---- mm/memory.c | 5 ++--- 4 files changed, 8 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h index 5e6362a786b7..732cf3086741 100644 --- a/include/asm-ia64/page.h +++ b/include/asm-ia64/page.h @@ -57,6 +57,7 @@ # define HAVE_ARCH_HUGETLB_UNMAPPED_AREA # define ARCH_HAS_HUGEPAGE_ONLY_RANGE +# define ARCH_HAS_HUGETLB_FREE_PGD_RANGE #endif /* CONFIG_HUGETLB_PAGE */ #ifdef __ASSEMBLY__ diff --git a/include/asm-powerpc/pgtable.h b/include/asm-powerpc/pgtable.h index e38931379a72..185ee15963a1 100644 --- a/include/asm-powerpc/pgtable.h +++ b/include/asm-powerpc/pgtable.h @@ -468,11 +468,6 @@ extern pgd_t swapper_pg_dir[]; extern void paging_init(void); -#ifdef CONFIG_HUGETLB_PAGE -#define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) \ - free_pgd_range(tlb, addr, end, floor, ceiling) -#endif - /* * This gets called at the end of handling a page fault, when * the kernel has put a new PTE into the page table for the process. diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 5d84c368ffe4..e465fbf1ef5f 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -43,8 +43,10 @@ void hugetlb_change_protection(struct vm_area_struct *vma, #ifndef ARCH_HAS_HUGEPAGE_ONLY_RANGE #define is_hugepage_only_range(mm, addr, len) 0 -#define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) \ - do { } while (0) +#endif + +#ifndef ARCH_HAS_HUGETLB_FREE_PGD_RANGE +#define hugetlb_free_pgd_range free_pgd_range #endif #ifndef ARCH_HAS_PREPARE_HUGEPAGE_RANGE @@ -93,8 +95,7 @@ static inline unsigned long hugetlb_total_pages(void) #define prepare_hugepage_range(addr, len) (-EINVAL) #define pmd_huge(x) 0 #define is_hugepage_only_range(mm, addr, len) 0 -#define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) \ - do { } while (0) +#define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) ({BUG(); 0; }) #define hugetlb_fault(mm, vma, addr, write) ({ BUG(); 0; }) #define hugetlb_change_protection(vma, address, end, newprot) diff --git a/mm/memory.c b/mm/memory.c index 71bc664efed5..f6e3be9cbf5a 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -277,7 +277,7 @@ void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *vma, anon_vma_unlink(vma); unlink_file_vma(vma); - if (is_hugepage_only_range(vma->vm_mm, addr, HPAGE_SIZE)) { + if (is_vm_hugetlb_page(vma)) { hugetlb_free_pgd_range(tlb, addr, vma->vm_end, floor, next? next->vm_start: ceiling); } else { @@ -285,8 +285,7 @@ void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *vma, * Optimization: gather nearby vmas into one call down */ while (next && next->vm_start <= vma->vm_end + PMD_SIZE - && !is_hugepage_only_range(vma->vm_mm, next->vm_start, - HPAGE_SIZE)) { + && !is_vm_hugetlb_page(vma)) { vma = next; next = vma->vm_next; anon_vma_unlink(vma); -- cgit v1.2.3 From 3915bcf38fe0b6d130b4bbde97804f29a0becf32 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 22 Mar 2006 00:08:59 -0800 Subject: [PATCH] hugepage: Move hugetlb_free_pgd_range() prototype to hugetlb.h The optional hugepage callback, hugetlb_free_pgd_range() is presently implemented non-trivially only on ia64 (but I plan to add one for powerpc shortly). It has its own prototype for the function in asm-ia64/pgtable.h. However, since the function is called from generic code, it make sense for its prototype to be in the generic hugetlb.h header file, as the protypes other arch callbacks already are (prepare_hugepage_range(), set_huge_pte_at(), etc.). This patch makes it so. Signed-off-by: David Gibson Cc: William Lee Irwin III Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-ia64/pgtable.h | 3 --- include/linux/hugetlb.h | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h index 5890972a69bf..c0f8144f2349 100644 --- a/include/asm-ia64/pgtable.h +++ b/include/asm-ia64/pgtable.h @@ -505,9 +505,6 @@ extern struct page *zero_page_memmap_ptr; #define HUGETLB_PGDIR_SHIFT (HPAGE_SHIFT + 2*(PAGE_SHIFT-3)) #define HUGETLB_PGDIR_SIZE (__IA64_UL(1) << HUGETLB_PGDIR_SHIFT) #define HUGETLB_PGDIR_MASK (~(HUGETLB_PGDIR_SIZE-1)) -struct mmu_gather; -void hugetlb_free_pgd_range(struct mmu_gather **tlb, unsigned long addr, - unsigned long end, unsigned long floor, unsigned long ceiling); #endif /* diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index e465fbf1ef5f..5db25ffdb3eb 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -47,6 +47,10 @@ void hugetlb_change_protection(struct vm_area_struct *vma, #ifndef ARCH_HAS_HUGETLB_FREE_PGD_RANGE #define hugetlb_free_pgd_range free_pgd_range +#else +void hugetlb_free_pgd_range(struct mmu_gather **tlb, unsigned long addr, + unsigned long end, unsigned long floor, + unsigned long ceiling); #endif #ifndef ARCH_HAS_PREPARE_HUGEPAGE_RANGE -- cgit v1.2.3 From 42b88befd6e0dae1a5fe04c03925037fa890e1f3 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 22 Mar 2006 00:09:01 -0800 Subject: [PATCH] hugepage: is_aligned_hugepage_range() cleanup Quite a long time back, prepare_hugepage_range() replaced is_aligned_hugepage_range() as the callback from mm/mmap.c to arch code to verify if an address range is suitable for a hugepage mapping. is_aligned_hugepage_range() stuck around, but only to implement prepare_hugepage_range() on archs which didn't implement their own. Most archs (everything except ia64 and powerpc) used the same implementation of is_aligned_hugepage_range(). On powerpc, which implements its own prepare_hugepage_range(), the custom version was never used. In addition, "is_aligned_hugepage_range()" was a bad name, because it suggests it returns true iff the given range is a good hugepage range, whereas in fact it returns 0-or-error (so the sense is reversed). This patch cleans up by abolishing is_aligned_hugepage_range(). Instead prepare_hugepage_range() is defined directly. Most archs use the default version, which simply checks the given region is aligned to the size of a hugepage. ia64 and powerpc define custom versions. The ia64 one simply checks that the range is in the correct address space region in addition to being suitably aligned. The powerpc version (just as previously) checks for suitable addresses, and if necessary performs low-level MMU frobbing to set up new areas for use by hugepages. No libhugetlbfs testsuite regressions on ppc64 (POWER5 LPAR). Signed-off-by: David Gibson Signed-off-by: Zhang Yanmin Cc: "David S. Miller" Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: William Lee Irwin III Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/mm/hugetlbpage.c | 12 ------------ arch/ia64/mm/hugetlbpage.c | 5 +++-- arch/powerpc/mm/hugetlbpage.c | 15 --------------- arch/sh/mm/hugetlbpage.c | 12 ------------ arch/sh64/mm/hugetlbpage.c | 12 ------------ arch/sparc64/mm/hugetlbpage.c | 12 ------------ include/asm-ia64/page.h | 1 + include/linux/hugetlb.h | 16 ++++++++++++---- 8 files changed, 16 insertions(+), 69 deletions(-) (limited to 'include') diff --git a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c index d524127c9afc..a7d891585411 100644 --- a/arch/i386/mm/hugetlbpage.c +++ b/arch/i386/mm/hugetlbpage.c @@ -48,18 +48,6 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) return (pte_t *) pmd; } -/* - * This function checks for proper alignment of input addr and len parameters. - */ -int is_aligned_hugepage_range(unsigned long addr, unsigned long len) -{ - if (len & ~HPAGE_MASK) - return -EINVAL; - if (addr & ~HPAGE_MASK) - return -EINVAL; - return 0; -} - #if 0 /* This is just for testing */ struct page * follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c index 2d13889d0a99..9dbc7dadd165 100644 --- a/arch/ia64/mm/hugetlbpage.c +++ b/arch/ia64/mm/hugetlbpage.c @@ -68,9 +68,10 @@ huge_pte_offset (struct mm_struct *mm, unsigned long addr) #define mk_pte_huge(entry) { pte_val(entry) |= _PAGE_P; } /* - * This function checks for proper alignment of input addr and len parameters. + * Don't actually need to do any preparation, but need to make sure + * the address is in the right region. */ -int is_aligned_hugepage_range(unsigned long addr, unsigned long len) +int prepare_hugepage_range(unsigned long addr, unsigned long len) { if (len & ~HPAGE_MASK) return -EINVAL; diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index b51bb28c054b..7370f9f33e29 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -133,21 +133,6 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, return __pte(old); } -/* - * This function checks for proper alignment of input addr and len parameters. - */ -int is_aligned_hugepage_range(unsigned long addr, unsigned long len) -{ - if (len & ~HPAGE_MASK) - return -EINVAL; - if (addr & ~HPAGE_MASK) - return -EINVAL; - if (! (within_hugepage_low_range(addr, len) - || within_hugepage_high_range(addr, len)) ) - return -EINVAL; - return 0; -} - struct slb_flush_info { struct mm_struct *mm; u16 newareas; diff --git a/arch/sh/mm/hugetlbpage.c b/arch/sh/mm/hugetlbpage.c index 6b7a7688c98e..a3568fd51508 100644 --- a/arch/sh/mm/hugetlbpage.c +++ b/arch/sh/mm/hugetlbpage.c @@ -84,18 +84,6 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, return entry; } -/* - * This function checks for proper alignment of input addr and len parameters. - */ -int is_aligned_hugepage_range(unsigned long addr, unsigned long len) -{ - if (len & ~HPAGE_MASK) - return -EINVAL; - if (addr & ~HPAGE_MASK) - return -EINVAL; - return 0; -} - struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) { diff --git a/arch/sh64/mm/hugetlbpage.c b/arch/sh64/mm/hugetlbpage.c index ed6a505b3ee2..3d89f2a6c785 100644 --- a/arch/sh64/mm/hugetlbpage.c +++ b/arch/sh64/mm/hugetlbpage.c @@ -84,18 +84,6 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, return entry; } -/* - * This function checks for proper alignment of input addr and len parameters. - */ -int is_aligned_hugepage_range(unsigned long addr, unsigned long len) -{ - if (len & ~HPAGE_MASK) - return -EINVAL; - if (addr & ~HPAGE_MASK) - return -EINVAL; - return 0; -} - struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) { diff --git a/arch/sparc64/mm/hugetlbpage.c b/arch/sparc64/mm/hugetlbpage.c index a7a24869d045..280dc7958a13 100644 --- a/arch/sparc64/mm/hugetlbpage.c +++ b/arch/sparc64/mm/hugetlbpage.c @@ -263,18 +263,6 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, return entry; } -/* - * This function checks for proper alignment of input addr and len parameters. - */ -int is_aligned_hugepage_range(unsigned long addr, unsigned long len) -{ - if (len & ~HPAGE_MASK) - return -EINVAL; - if (addr & ~HPAGE_MASK) - return -EINVAL; - return 0; -} - struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) { diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h index 732cf3086741..3ab27333dae4 100644 --- a/include/asm-ia64/page.h +++ b/include/asm-ia64/page.h @@ -57,6 +57,7 @@ # define HAVE_ARCH_HUGETLB_UNMAPPED_AREA # define ARCH_HAS_HUGEPAGE_ONLY_RANGE +# define ARCH_HAS_PREPARE_HUGEPAGE_RANGE # define ARCH_HAS_HUGETLB_FREE_PGD_RANGE #endif /* CONFIG_HUGETLB_PAGE */ diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 5db25ffdb3eb..d6f1019625af 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -36,7 +36,6 @@ struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address, int write); struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address, pmd_t *pmd, int write); -int is_aligned_hugepage_range(unsigned long addr, unsigned long len); int pmd_huge(pmd_t pmd); void hugetlb_change_protection(struct vm_area_struct *vma, unsigned long address, unsigned long end, pgprot_t newprot); @@ -54,8 +53,18 @@ void hugetlb_free_pgd_range(struct mmu_gather **tlb, unsigned long addr, #endif #ifndef ARCH_HAS_PREPARE_HUGEPAGE_RANGE -#define prepare_hugepage_range(addr, len) \ - is_aligned_hugepage_range(addr, len) +/* + * If the arch doesn't supply something else, assume that hugepage + * size aligned regions are ok without further preparation. + */ +static inline int prepare_hugepage_range(unsigned long addr, unsigned long len) +{ + if (len & ~HPAGE_MASK) + return -EINVAL; + if (addr & ~HPAGE_MASK) + return -EINVAL; + return 0; +} #else int prepare_hugepage_range(unsigned long addr, unsigned long len); #endif @@ -95,7 +104,6 @@ static inline unsigned long hugetlb_total_pages(void) #define hugetlb_report_meminfo(buf) 0 #define hugetlb_report_node_meminfo(n, buf) 0 #define follow_huge_pmd(mm, addr, pmd, write) NULL -#define is_aligned_hugepage_range(addr, len) 0 #define prepare_hugepage_range(addr, len) (-EINVAL) #define pmd_huge(x) 0 #define is_hugepage_only_range(mm, addr, len) 0 -- cgit v1.2.3 From b20a35035f983f4ac7e29c4a68f30e43510007e0 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 22 Mar 2006 00:09:12 -0800 Subject: [PATCH] page migration reorg Centralize the page migration functions in anticipation of additional tinkering. Creates a new file mm/migrate.c 1. Extract buffer_migrate_page() from fs/buffer.c 2. Extract central migration code from vmscan.c 3. Extract some components from mempolicy.c 4. Export pageout() and remove_from_swap() from vmscan.c 5. Make it possible to configure NUMA systems without page migration and non-NUMA systems with page migration. I had to so some #ifdeffing in mempolicy.c that may need a cleanup. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/buffer.c | 62 ----- fs/xfs/linux-2.6/xfs_buf.c | 1 + include/linux/migrate.h | 36 +++ include/linux/swap.h | 34 ++- mm/Kconfig | 6 + mm/Makefile | 2 + mm/mempolicy.c | 113 ++------ mm/migrate.c | 655 +++++++++++++++++++++++++++++++++++++++++++++ mm/swap_state.c | 1 + mm/vmscan.c | 491 +-------------------------------- 10 files changed, 741 insertions(+), 660 deletions(-) create mode 100644 include/linux/migrate.h create mode 100644 mm/migrate.c (limited to 'include') diff --git a/fs/buffer.c b/fs/buffer.c index a9b399402007..1d3683d496f8 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -3050,68 +3050,6 @@ asmlinkage long sys_bdflush(int func, long data) return 0; } -/* - * Migration function for pages with buffers. This function can only be used - * if the underlying filesystem guarantees that no other references to "page" - * exist. - */ -#ifdef CONFIG_MIGRATION -int buffer_migrate_page(struct page *newpage, struct page *page) -{ - struct address_space *mapping = page->mapping; - struct buffer_head *bh, *head; - int rc; - - if (!mapping) - return -EAGAIN; - - if (!page_has_buffers(page)) - return migrate_page(newpage, page); - - head = page_buffers(page); - - rc = migrate_page_remove_references(newpage, page, 3); - if (rc) - return rc; - - bh = head; - do { - get_bh(bh); - lock_buffer(bh); - bh = bh->b_this_page; - - } while (bh != head); - - ClearPagePrivate(page); - set_page_private(newpage, page_private(page)); - set_page_private(page, 0); - put_page(page); - get_page(newpage); - - bh = head; - do { - set_bh_page(bh, newpage, bh_offset(bh)); - bh = bh->b_this_page; - - } while (bh != head); - - SetPagePrivate(newpage); - - migrate_page_copy(newpage, page); - - bh = head; - do { - unlock_buffer(bh); - put_bh(bh); - bh = bh->b_this_page; - - } while (bh != head); - - return 0; -} -EXPORT_SYMBOL(buffer_migrate_page); -#endif - /* * Buffer-head allocation */ diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index bfb4f2917bb6..8cdfa4151659 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "xfs_linux.h" STATIC kmem_zone_t *xfs_buf_zone; diff --git a/include/linux/migrate.h b/include/linux/migrate.h new file mode 100644 index 000000000000..7d09962c3c0b --- /dev/null +++ b/include/linux/migrate.h @@ -0,0 +1,36 @@ +#ifndef _LINUX_MIGRATE_H +#define _LINUX_MIGRATE_H + +#include +#include + +#ifdef CONFIG_MIGRATION +extern int isolate_lru_page(struct page *p, struct list_head *pagelist); +extern int putback_lru_pages(struct list_head *l); +extern int migrate_page(struct page *, struct page *); +extern void migrate_page_copy(struct page *, struct page *); +extern int migrate_page_remove_references(struct page *, struct page *, int); +extern int migrate_pages(struct list_head *l, struct list_head *t, + struct list_head *moved, struct list_head *failed); +int migrate_pages_to(struct list_head *pagelist, + struct vm_area_struct *vma, int dest); +extern int fail_migrate_page(struct page *, struct page *); + +extern int migrate_prep(void); + +#else + +static inline int isolate_lru_page(struct page *p, struct list_head *list) + { return -ENOSYS; } +static inline int putback_lru_pages(struct list_head *l) { return 0; } +static inline int migrate_pages(struct list_head *l, struct list_head *t, + struct list_head *moved, struct list_head *failed) { return -ENOSYS; } + +static inline int migrate_prep(void) { return -ENOSYS; } + +/* Possible settings for the migrate_page() method in address_operations */ +#define migrate_page NULL +#define fail_migrate_page NULL + +#endif /* CONFIG_MIGRATION */ +#endif /* _LINUX_MIGRATE_H */ diff --git a/include/linux/swap.h b/include/linux/swap.h index 3dc6c89c49b8..12415dd94451 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -175,6 +175,21 @@ extern void swap_setup(void); extern unsigned long try_to_free_pages(struct zone **, gfp_t); extern unsigned long shrink_all_memory(unsigned long nr_pages); extern int vm_swappiness; +extern int remove_mapping(struct address_space *mapping, struct page *page); + +/* possible outcome of pageout() */ +typedef enum { + /* failed to write page out, page is locked */ + PAGE_KEEP, + /* move page to the active list, page is locked */ + PAGE_ACTIVATE, + /* page has been sent to the disk successfully, page is unlocked */ + PAGE_SUCCESS, + /* page is clean and locked */ + PAGE_CLEAN, +} pageout_t; + +extern pageout_t pageout(struct page *page, struct address_space *mapping); #ifdef CONFIG_NUMA extern int zone_reclaim_mode; @@ -188,25 +203,6 @@ static inline int zone_reclaim(struct zone *z, gfp_t mask, unsigned int order) } #endif -#ifdef CONFIG_MIGRATION -extern int isolate_lru_page(struct page *p); -extern unsigned long putback_lru_pages(struct list_head *l); -extern int migrate_page(struct page *, struct page *); -extern void migrate_page_copy(struct page *, struct page *); -extern int migrate_page_remove_references(struct page *, struct page *, int); -extern unsigned long migrate_pages(struct list_head *l, struct list_head *t, - struct list_head *moved, struct list_head *failed); -extern int fail_migrate_page(struct page *, struct page *); -#else -static inline int isolate_lru_page(struct page *p) { return -ENOSYS; } -static inline int putback_lru_pages(struct list_head *l) { return 0; } -static inline int migrate_pages(struct list_head *l, struct list_head *t, - struct list_head *moved, struct list_head *failed) { return -ENOSYS; } -/* Possible settings for the migrate_page() method in address_operations */ -#define migrate_page NULL -#define fail_migrate_page NULL -#endif - #ifdef CONFIG_MMU /* linux/mm/shmem.c */ extern int shmem_unuse(swp_entry_t entry, struct page *page); diff --git a/mm/Kconfig b/mm/Kconfig index a9cb80ae6409..bd80460360db 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -137,5 +137,11 @@ config SPLIT_PTLOCK_CPUS # support for page migration # config MIGRATION + bool "Page migration" def_bool y if NUMA || SPARSEMEM || DISCONTIGMEM depends on SWAP + help + Allows the migration of the physical location of pages of processes + while the virtual addresses are not changed. This is useful for + example on NUMA systems to put pages nearer to the processors accessing + the page. diff --git a/mm/Makefile b/mm/Makefile index 9aa03fa1dcc3..f10c753dce6d 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -22,3 +22,5 @@ obj-$(CONFIG_SLOB) += slob.o obj-$(CONFIG_SLAB) += slab.o obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o obj-$(CONFIG_FS_XIP) += filemap_xip.o +obj-$(CONFIG_MIGRATION) += migrate.o + diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 96195dcb62e1..e93cc740c22b 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -86,6 +86,7 @@ #include #include #include +#include #include #include @@ -95,9 +96,6 @@ #define MPOL_MF_INVERT (MPOL_MF_INTERNAL << 1) /* Invert check for nodemask */ #define MPOL_MF_STATS (MPOL_MF_INTERNAL << 2) /* Gather statistics */ -/* The number of pages to migrate per call to migrate_pages() */ -#define MIGRATE_CHUNK_SIZE 256 - static struct kmem_cache *policy_cache; static struct kmem_cache *sn_cache; @@ -331,17 +329,10 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end, struct vm_area_struct *first, *vma, *prev; if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) { - /* Must have swap device for migration */ - if (nr_swap_pages <= 0) - return ERR_PTR(-ENODEV); - /* - * Clear the LRU lists so pages can be isolated. - * Note that pages may be moved off the LRU after we have - * drained them. Those pages will fail to migrate like other - * pages that may be busy. - */ - lru_add_drain_all(); + err = migrate_prep(); + if (err) + return ERR_PTR(err); } first = find_vma(mm, start); @@ -550,92 +541,18 @@ long do_get_mempolicy(int *policy, nodemask_t *nmask, return err; } +#ifdef CONFIG_MIGRATION /* * page migration */ - static void migrate_page_add(struct page *page, struct list_head *pagelist, unsigned long flags) { /* * Avoid migrating a page that is shared with others. */ - if ((flags & MPOL_MF_MOVE_ALL) || page_mapcount(page) == 1) { - if (isolate_lru_page(page)) - list_add_tail(&page->lru, pagelist); - } -} - -/* - * Migrate the list 'pagelist' of pages to a certain destination. - * - * Specify destination with either non-NULL vma or dest_node >= 0 - * Return the number of pages not migrated or error code - */ -static int migrate_pages_to(struct list_head *pagelist, - struct vm_area_struct *vma, int dest) -{ - LIST_HEAD(newlist); - LIST_HEAD(moved); - LIST_HEAD(failed); - int err = 0; - unsigned long offset = 0; - int nr_pages; - struct page *page; - struct list_head *p; - -redo: - nr_pages = 0; - list_for_each(p, pagelist) { - if (vma) { - /* - * The address passed to alloc_page_vma is used to - * generate the proper interleave behavior. We fake - * the address here by an increasing offset in order - * to get the proper distribution of pages. - * - * No decision has been made as to which page - * a certain old page is moved to so we cannot - * specify the correct address. - */ - page = alloc_page_vma(GFP_HIGHUSER, vma, - offset + vma->vm_start); - offset += PAGE_SIZE; - } - else - page = alloc_pages_node(dest, GFP_HIGHUSER, 0); - - if (!page) { - err = -ENOMEM; - goto out; - } - list_add_tail(&page->lru, &newlist); - nr_pages++; - if (nr_pages > MIGRATE_CHUNK_SIZE) - break; - } - err = migrate_pages(pagelist, &newlist, &moved, &failed); - - putback_lru_pages(&moved); /* Call release pages instead ?? */ - - if (err >= 0 && list_empty(&newlist) && !list_empty(pagelist)) - goto redo; -out: - /* Return leftover allocated pages */ - while (!list_empty(&newlist)) { - page = list_entry(newlist.next, struct page, lru); - list_del(&page->lru); - __free_page(page); - } - list_splice(&failed, pagelist); - if (err < 0) - return err; - - /* Calculate number of leftover pages */ - nr_pages = 0; - list_for_each(p, pagelist) - nr_pages++; - return nr_pages; + if ((flags & MPOL_MF_MOVE_ALL) || page_mapcount(page) == 1) + isolate_lru_page(page, pagelist); } /* @@ -742,8 +659,23 @@ int do_migrate_pages(struct mm_struct *mm, if (err < 0) return err; return busy; + } +#else + +static void migrate_page_add(struct page *page, struct list_head *pagelist, + unsigned long flags) +{ +} + +int do_migrate_pages(struct mm_struct *mm, + const nodemask_t *from_nodes, const nodemask_t *to_nodes, int flags) +{ + return -ENOSYS; +} +#endif + long do_mbind(unsigned long start, unsigned long len, unsigned long mode, nodemask_t *nmask, unsigned long flags) { @@ -808,6 +740,7 @@ long do_mbind(unsigned long start, unsigned long len, if (!err && nr_failed && (flags & MPOL_MF_STRICT)) err = -EIO; } + if (!list_empty(&pagelist)) putback_lru_pages(&pagelist); diff --git a/mm/migrate.c b/mm/migrate.c new file mode 100644 index 000000000000..09f6e4aa87fc --- /dev/null +++ b/mm/migrate.c @@ -0,0 +1,655 @@ +/* + * Memory Migration functionality - linux/mm/migration.c + * + * Copyright (C) 2006 Silicon Graphics, Inc., Christoph Lameter + * + * Page migration was first developed in the context of the memory hotplug + * project. The main authors of the migration code are: + * + * IWAMOTO Toshihiro + * Hirokazu Takahashi + * Dave Hansen + * Christoph Lameter + */ + +#include +#include +#include +#include +#include /* for try_to_release_page(), + buffer_heads_over_limit */ +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + +#include "internal.h" + +/* The maximum number of pages to take off the LRU for migration */ +#define MIGRATE_CHUNK_SIZE 256 + +#define lru_to_page(_head) (list_entry((_head)->prev, struct page, lru)) + +/* + * Isolate one page from the LRU lists. If successful put it onto + * the indicated list with elevated page count. + * + * Result: + * -EBUSY: page not on LRU list + * 0: page removed from LRU list and added to the specified list. + */ +int isolate_lru_page(struct page *page, struct list_head *pagelist) +{ + int ret = -EBUSY; + + if (PageLRU(page)) { + struct zone *zone = page_zone(page); + + spin_lock_irq(&zone->lru_lock); + if (PageLRU(page)) { + ret = 0; + get_page(page); + ClearPageLRU(page); + if (PageActive(page)) + del_page_from_active_list(zone, page); + else + del_page_from_inactive_list(zone, page); + list_add_tail(&page->lru, pagelist); + } + spin_unlock_irq(&zone->lru_lock); + } + return ret; +} + +/* + * migrate_prep() needs to be called after we have compiled the list of pages + * to be migrated using isolate_lru_page() but before we begin a series of calls + * to migrate_pages(). + */ +int migrate_prep(void) +{ + /* Must have swap device for migration */ + if (nr_swap_pages <= 0) + return -ENODEV; + + /* + * Clear the LRU lists so pages can be isolated. + * Note that pages may be moved off the LRU after we have + * drained them. Those pages will fail to migrate like other + * pages that may be busy. + */ + lru_add_drain_all(); + + return 0; +} + +static inline void move_to_lru(struct page *page) +{ + list_del(&page->lru); + if (PageActive(page)) { + /* + * lru_cache_add_active checks that + * the PG_active bit is off. + */ + ClearPageActive(page); + lru_cache_add_active(page); + } else { + lru_cache_add(page); + } + put_page(page); +} + +/* + * Add isolated pages on the list back to the LRU. + * + * returns the number of pages put back. + */ +int putback_lru_pages(struct list_head *l) +{ + struct page *page; + struct page *page2; + int count = 0; + + list_for_each_entry_safe(page, page2, l, lru) { + move_to_lru(page); + count++; + } + return count; +} + +/* + * Non migratable page + */ +int fail_migrate_page(struct page *newpage, struct page *page) +{ + return -EIO; +} +EXPORT_SYMBOL(fail_migrate_page); + +/* + * swapout a single page + * page is locked upon entry, unlocked on exit + */ +static int swap_page(struct page *page) +{ + struct address_space *mapping = page_mapping(page); + + if (page_mapped(page) && mapping) + if (try_to_unmap(page, 1) != SWAP_SUCCESS) + goto unlock_retry; + + if (PageDirty(page)) { + /* Page is dirty, try to write it out here */ + switch(pageout(page, mapping)) { + case PAGE_KEEP: + case PAGE_ACTIVATE: + goto unlock_retry; + + case PAGE_SUCCESS: + goto retry; + + case PAGE_CLEAN: + ; /* try to free the page below */ + } + } + + if (PagePrivate(page)) { + if (!try_to_release_page(page, GFP_KERNEL) || + (!mapping && page_count(page) == 1)) + goto unlock_retry; + } + + if (remove_mapping(mapping, page)) { + /* Success */ + unlock_page(page); + return 0; + } + +unlock_retry: + unlock_page(page); + +retry: + return -EAGAIN; +} +EXPORT_SYMBOL(swap_page); + +/* + * Remove references for a page and establish the new page with the correct + * basic settings to be able to stop accesses to the page. + */ +int migrate_page_remove_references(struct page *newpage, + struct page *page, int nr_refs) +{ + struct address_space *mapping = page_mapping(page); + struct page **radix_pointer; + + /* + * Avoid doing any of the following work if the page count + * indicates that the page is in use or truncate has removed + * the page. + */ + if (!mapping || page_mapcount(page) + nr_refs != page_count(page)) + return -EAGAIN; + + /* + * Establish swap ptes for anonymous pages or destroy pte + * maps for files. + * + * In order to reestablish file backed mappings the fault handlers + * will take the radix tree_lock which may then be used to stop + * processses from accessing this page until the new page is ready. + * + * A process accessing via a swap pte (an anonymous page) will take a + * page_lock on the old page which will block the process until the + * migration attempt is complete. At that time the PageSwapCache bit + * will be examined. If the page was migrated then the PageSwapCache + * bit will be clear and the operation to retrieve the page will be + * retried which will find the new page in the radix tree. Then a new + * direct mapping may be generated based on the radix tree contents. + * + * If the page was not migrated then the PageSwapCache bit + * is still set and the operation may continue. + */ + if (try_to_unmap(page, 1) == SWAP_FAIL) + /* A vma has VM_LOCKED set -> permanent failure */ + return -EPERM; + + /* + * Give up if we were unable to remove all mappings. + */ + if (page_mapcount(page)) + return -EAGAIN; + + write_lock_irq(&mapping->tree_lock); + + radix_pointer = (struct page **)radix_tree_lookup_slot( + &mapping->page_tree, + page_index(page)); + + if (!page_mapping(page) || page_count(page) != nr_refs || + *radix_pointer != page) { + write_unlock_irq(&mapping->tree_lock); + return 1; + } + + /* + * Now we know that no one else is looking at the page. + * + * Certain minimal information about a page must be available + * in order for other subsystems to properly handle the page if they + * find it through the radix tree update before we are finished + * copying the page. + */ + get_page(newpage); + newpage->index = page->index; + newpage->mapping = page->mapping; + if (PageSwapCache(page)) { + SetPageSwapCache(newpage); + set_page_private(newpage, page_private(page)); + } + + *radix_pointer = newpage; + __put_page(page); + write_unlock_irq(&mapping->tree_lock); + + return 0; +} +EXPORT_SYMBOL(migrate_page_remove_references); + +/* + * Copy the page to its new location + */ +void migrate_page_copy(struct page *newpage, struct page *page) +{ + copy_highpage(newpage, page); + + if (PageError(page)) + SetPageError(newpage); + if (PageReferenced(page)) + SetPageReferenced(newpage); + if (PageUptodate(page)) + SetPageUptodate(newpage); + if (PageActive(page)) + SetPageActive(newpage); + if (PageChecked(page)) + SetPageChecked(newpage); + if (PageMappedToDisk(page)) + SetPageMappedToDisk(newpage); + + if (PageDirty(page)) { + clear_page_dirty_for_io(page); + set_page_dirty(newpage); + } + + ClearPageSwapCache(page); + ClearPageActive(page); + ClearPagePrivate(page); + set_page_private(page, 0); + page->mapping = NULL; + + /* + * If any waiters have accumulated on the new page then + * wake them up. + */ + if (PageWriteback(newpage)) + end_page_writeback(newpage); +} +EXPORT_SYMBOL(migrate_page_copy); + +/* + * Common logic to directly migrate a single page suitable for + * pages that do not use PagePrivate. + * + * Pages are locked upon entry and exit. + */ +int migrate_page(struct page *newpage, struct page *page) +{ + int rc; + + BUG_ON(PageWriteback(page)); /* Writeback must be complete */ + + rc = migrate_page_remove_references(newpage, page, 2); + + if (rc) + return rc; + + migrate_page_copy(newpage, page); + + /* + * Remove auxiliary swap entries and replace + * them with real ptes. + * + * Note that a real pte entry will allow processes that are not + * waiting on the page lock to use the new page via the page tables + * before the new page is unlocked. + */ + remove_from_swap(newpage); + return 0; +} +EXPORT_SYMBOL(migrate_page); + +/* + * migrate_pages + * + * Two lists are passed to this function. The first list + * contains the pages isolated from the LRU to be migrated. + * The second list contains new pages that the pages isolated + * can be moved to. If the second list is NULL then all + * pages are swapped out. + * + * The function returns after 10 attempts or if no pages + * are movable anymore because to has become empty + * or no retryable pages exist anymore. + * + * Return: Number of pages not migrated when "to" ran empty. + */ +int migrate_pages(struct list_head *from, struct list_head *to, + struct list_head *moved, struct list_head *failed) +{ + int retry; + int nr_failed = 0; + int pass = 0; + struct page *page; + struct page *page2; + int swapwrite = current->flags & PF_SWAPWRITE; + int rc; + + if (!swapwrite) + current->flags |= PF_SWAPWRITE; + +redo: + retry = 0; + + list_for_each_entry_safe(page, page2, from, lru) { + struct page *newpage = NULL; + struct address_space *mapping; + + cond_resched(); + + rc = 0; + if (page_count(page) == 1) + /* page was freed from under us. So we are done. */ + goto next; + + if (to && list_empty(to)) + break; + + /* + * Skip locked pages during the first two passes to give the + * functions holding the lock time to release the page. Later we + * use lock_page() to have a higher chance of acquiring the + * lock. + */ + rc = -EAGAIN; + if (pass > 2) + lock_page(page); + else + if (TestSetPageLocked(page)) + goto next; + + /* + * Only wait on writeback if we have already done a pass where + * we we may have triggered writeouts for lots of pages. + */ + if (pass > 0) { + wait_on_page_writeback(page); + } else { + if (PageWriteback(page)) + goto unlock_page; + } + + /* + * Anonymous pages must have swap cache references otherwise + * the information contained in the page maps cannot be + * preserved. + */ + if (PageAnon(page) && !PageSwapCache(page)) { + if (!add_to_swap(page, GFP_KERNEL)) { + rc = -ENOMEM; + goto unlock_page; + } + } + + if (!to) { + rc = swap_page(page); + goto next; + } + + newpage = lru_to_page(to); + lock_page(newpage); + + /* + * Pages are properly locked and writeback is complete. + * Try to migrate the page. + */ + mapping = page_mapping(page); + if (!mapping) + goto unlock_both; + + if (mapping->a_ops->migratepage) { + /* + * Most pages have a mapping and most filesystems + * should provide a migration function. Anonymous + * pages are part of swap space which also has its + * own migration function. This is the most common + * path for page migration. + */ + rc = mapping->a_ops->migratepage(newpage, page); + goto unlock_both; + } + + /* + * Default handling if a filesystem does not provide + * a migration function. We can only migrate clean + * pages so try to write out any dirty pages first. + */ + if (PageDirty(page)) { + switch (pageout(page, mapping)) { + case PAGE_KEEP: + case PAGE_ACTIVATE: + goto unlock_both; + + case PAGE_SUCCESS: + unlock_page(newpage); + goto next; + + case PAGE_CLEAN: + ; /* try to migrate the page below */ + } + } + + /* + * Buffers are managed in a filesystem specific way. + * We must have no buffers or drop them. + */ + if (!page_has_buffers(page) || + try_to_release_page(page, GFP_KERNEL)) { + rc = migrate_page(newpage, page); + goto unlock_both; + } + + /* + * On early passes with mapped pages simply + * retry. There may be a lock held for some + * buffers that may go away. Later + * swap them out. + */ + if (pass > 4) { + /* + * Persistently unable to drop buffers..... As a + * measure of last resort we fall back to + * swap_page(). + */ + unlock_page(newpage); + newpage = NULL; + rc = swap_page(page); + goto next; + } + +unlock_both: + unlock_page(newpage); + +unlock_page: + unlock_page(page); + +next: + if (rc == -EAGAIN) { + retry++; + } else if (rc) { + /* Permanent failure */ + list_move(&page->lru, failed); + nr_failed++; + } else { + if (newpage) { + /* Successful migration. Return page to LRU */ + move_to_lru(newpage); + } + list_move(&page->lru, moved); + } + } + if (retry && pass++ < 10) + goto redo; + + if (!swapwrite) + current->flags &= ~PF_SWAPWRITE; + + return nr_failed + retry; +} + +/* + * Migration function for pages with buffers. This function can only be used + * if the underlying filesystem guarantees that no other references to "page" + * exist. + */ +int buffer_migrate_page(struct page *newpage, struct page *page) +{ + struct address_space *mapping = page->mapping; + struct buffer_head *bh, *head; + int rc; + + if (!mapping) + return -EAGAIN; + + if (!page_has_buffers(page)) + return migrate_page(newpage, page); + + head = page_buffers(page); + + rc = migrate_page_remove_references(newpage, page, 3); + + if (rc) + return rc; + + bh = head; + do { + get_bh(bh); + lock_buffer(bh); + bh = bh->b_this_page; + + } while (bh != head); + + ClearPagePrivate(page); + set_page_private(newpage, page_private(page)); + set_page_private(page, 0); + put_page(page); + get_page(newpage); + + bh = head; + do { + set_bh_page(bh, newpage, bh_offset(bh)); + bh = bh->b_this_page; + + } while (bh != head); + + SetPagePrivate(newpage); + + migrate_page_copy(newpage, page); + + bh = head; + do { + unlock_buffer(bh); + put_bh(bh); + bh = bh->b_this_page; + + } while (bh != head); + + return 0; +} +EXPORT_SYMBOL(buffer_migrate_page); + +/* + * Migrate the list 'pagelist' of pages to a certain destination. + * + * Specify destination with either non-NULL vma or dest_node >= 0 + * Return the number of pages not migrated or error code + */ +int migrate_pages_to(struct list_head *pagelist, + struct vm_area_struct *vma, int dest) +{ + LIST_HEAD(newlist); + LIST_HEAD(moved); + LIST_HEAD(failed); + int err = 0; + unsigned long offset = 0; + int nr_pages; + struct page *page; + struct list_head *p; + +redo: + nr_pages = 0; + list_for_each(p, pagelist) { + if (vma) { + /* + * The address passed to alloc_page_vma is used to + * generate the proper interleave behavior. We fake + * the address here by an increasing offset in order + * to get the proper distribution of pages. + * + * No decision has been made as to which page + * a certain old page is moved to so we cannot + * specify the correct address. + */ + page = alloc_page_vma(GFP_HIGHUSER, vma, + offset + vma->vm_start); + offset += PAGE_SIZE; + } + else + page = alloc_pages_node(dest, GFP_HIGHUSER, 0); + + if (!page) { + err = -ENOMEM; + goto out; + } + list_add_tail(&page->lru, &newlist); + nr_pages++; + if (nr_pages > MIGRATE_CHUNK_SIZE) + break; + } + err = migrate_pages(pagelist, &newlist, &moved, &failed); + + putback_lru_pages(&moved); /* Call release pages instead ?? */ + + if (err >= 0 && list_empty(&newlist) && !list_empty(pagelist)) + goto redo; +out: + /* Return leftover allocated pages */ + while (!list_empty(&newlist)) { + page = list_entry(newlist.next, struct page, lru); + list_del(&page->lru); + __free_page(page); + } + list_splice(&failed, pagelist); + if (err < 0) + return err; + + /* Calculate number of leftover pages */ + nr_pages = 0; + list_for_each(p, pagelist) + nr_pages++; + return nr_pages; +} diff --git a/mm/swap_state.c b/mm/swap_state.c index db8a3d3e1636..d7af296833fc 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -15,6 +15,7 @@ #include #include #include +#include #include diff --git a/mm/vmscan.c b/mm/vmscan.c index 548e023c193b..fd572bbdc9f5 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -42,18 +42,6 @@ #include "internal.h" -/* possible outcome of pageout() */ -typedef enum { - /* failed to write page out, page is locked */ - PAGE_KEEP, - /* move page to the active list, page is locked */ - PAGE_ACTIVATE, - /* page has been sent to the disk successfully, page is unlocked */ - PAGE_SUCCESS, - /* page is clean and locked */ - PAGE_CLEAN, -} pageout_t; - struct scan_control { /* Incremented by the number of inactive pages that were scanned */ unsigned long nr_scanned; @@ -304,7 +292,7 @@ static void handle_write_error(struct address_space *mapping, * pageout is called by shrink_page_list() for each dirty page. * Calls ->writepage(). */ -static pageout_t pageout(struct page *page, struct address_space *mapping) +pageout_t pageout(struct page *page, struct address_space *mapping) { /* * If the page is dirty, only perform writeback if that write @@ -372,7 +360,7 @@ static pageout_t pageout(struct page *page, struct address_space *mapping) return PAGE_CLEAN; } -static int remove_mapping(struct address_space *mapping, struct page *page) +int remove_mapping(struct address_space *mapping, struct page *page) { if (!mapping) return 0; /* truncate got there first */ @@ -570,481 +558,6 @@ keep: return nr_reclaimed; } -#ifdef CONFIG_MIGRATION -static inline void move_to_lru(struct page *page) -{ - list_del(&page->lru); - if (PageActive(page)) { - /* - * lru_cache_add_active checks that - * the PG_active bit is off. - */ - ClearPageActive(page); - lru_cache_add_active(page); - } else { - lru_cache_add(page); - } - put_page(page); -} - -/* - * Add isolated pages on the list back to the LRU. - * - * returns the number of pages put back. - */ -unsigned long putback_lru_pages(struct list_head *l) -{ - struct page *page; - struct page *page2; - unsigned long count = 0; - - list_for_each_entry_safe(page, page2, l, lru) { - move_to_lru(page); - count++; - } - return count; -} - -/* - * Non migratable page - */ -int fail_migrate_page(struct page *newpage, struct page *page) -{ - return -EIO; -} -EXPORT_SYMBOL(fail_migrate_page); - -/* - * swapout a single page - * page is locked upon entry, unlocked on exit - */ -static int swap_page(struct page *page) -{ - struct address_space *mapping = page_mapping(page); - - if (page_mapped(page) && mapping) - if (try_to_unmap(page, 1) != SWAP_SUCCESS) - goto unlock_retry; - - if (PageDirty(page)) { - /* Page is dirty, try to write it out here */ - switch(pageout(page, mapping)) { - case PAGE_KEEP: - case PAGE_ACTIVATE: - goto unlock_retry; - - case PAGE_SUCCESS: - goto retry; - - case PAGE_CLEAN: - ; /* try to free the page below */ - } - } - - if (PagePrivate(page)) { - if (!try_to_release_page(page, GFP_KERNEL) || - (!mapping && page_count(page) == 1)) - goto unlock_retry; - } - - if (remove_mapping(mapping, page)) { - /* Success */ - unlock_page(page); - return 0; - } - -unlock_retry: - unlock_page(page); - -retry: - return -EAGAIN; -} -EXPORT_SYMBOL(swap_page); - -/* - * Page migration was first developed in the context of the memory hotplug - * project. The main authors of the migration code are: - * - * IWAMOTO Toshihiro - * Hirokazu Takahashi - * Dave Hansen - * Christoph Lameter - */ - -/* - * Remove references for a page and establish the new page with the correct - * basic settings to be able to stop accesses to the page. - */ -int migrate_page_remove_references(struct page *newpage, - struct page *page, int nr_refs) -{ - struct address_space *mapping = page_mapping(page); - struct page **radix_pointer; - - /* - * Avoid doing any of the following work if the page count - * indicates that the page is in use or truncate has removed - * the page. - */ - if (!mapping || page_mapcount(page) + nr_refs != page_count(page)) - return -EAGAIN; - - /* - * Establish swap ptes for anonymous pages or destroy pte - * maps for files. - * - * In order to reestablish file backed mappings the fault handlers - * will take the radix tree_lock which may then be used to stop - * processses from accessing this page until the new page is ready. - * - * A process accessing via a swap pte (an anonymous page) will take a - * page_lock on the old page which will block the process until the - * migration attempt is complete. At that time the PageSwapCache bit - * will be examined. If the page was migrated then the PageSwapCache - * bit will be clear and the operation to retrieve the page will be - * retried which will find the new page in the radix tree. Then a new - * direct mapping may be generated based on the radix tree contents. - * - * If the page was not migrated then the PageSwapCache bit - * is still set and the operation may continue. - */ - if (try_to_unmap(page, 1) == SWAP_FAIL) - /* A vma has VM_LOCKED set -> Permanent failure */ - return -EPERM; - - /* - * Give up if we were unable to remove all mappings. - */ - if (page_mapcount(page)) - return -EAGAIN; - - write_lock_irq(&mapping->tree_lock); - - radix_pointer = (struct page **)radix_tree_lookup_slot( - &mapping->page_tree, - page_index(page)); - - if (!page_mapping(page) || page_count(page) != nr_refs || - *radix_pointer != page) { - write_unlock_irq(&mapping->tree_lock); - return -EAGAIN; - } - - /* - * Now we know that no one else is looking at the page. - * - * Certain minimal information about a page must be available - * in order for other subsystems to properly handle the page if they - * find it through the radix tree update before we are finished - * copying the page. - */ - get_page(newpage); - newpage->index = page->index; - newpage->mapping = page->mapping; - if (PageSwapCache(page)) { - SetPageSwapCache(newpage); - set_page_private(newpage, page_private(page)); - } - - *radix_pointer = newpage; - __put_page(page); - write_unlock_irq(&mapping->tree_lock); - - return 0; -} -EXPORT_SYMBOL(migrate_page_remove_references); - -/* - * Copy the page to its new location - */ -void migrate_page_copy(struct page *newpage, struct page *page) -{ - copy_highpage(newpage, page); - - if (PageError(page)) - SetPageError(newpage); - if (PageReferenced(page)) - SetPageReferenced(newpage); - if (PageUptodate(page)) - SetPageUptodate(newpage); - if (PageActive(page)) - SetPageActive(newpage); - if (PageChecked(page)) - SetPageChecked(newpage); - if (PageMappedToDisk(page)) - SetPageMappedToDisk(newpage); - - if (PageDirty(page)) { - clear_page_dirty_for_io(page); - set_page_dirty(newpage); - } - - ClearPageSwapCache(page); - ClearPageActive(page); - ClearPagePrivate(page); - set_page_private(page, 0); - page->mapping = NULL; - - /* - * If any waiters have accumulated on the new page then - * wake them up. - */ - if (PageWriteback(newpage)) - end_page_writeback(newpage); -} -EXPORT_SYMBOL(migrate_page_copy); - -/* - * Common logic to directly migrate a single page suitable for - * pages that do not use PagePrivate. - * - * Pages are locked upon entry and exit. - */ -int migrate_page(struct page *newpage, struct page *page) -{ - int rc; - - BUG_ON(PageWriteback(page)); /* Writeback must be complete */ - - rc = migrate_page_remove_references(newpage, page, 2); - - if (rc) - return rc; - - migrate_page_copy(newpage, page); - - /* - * Remove auxiliary swap entries and replace - * them with real ptes. - * - * Note that a real pte entry will allow processes that are not - * waiting on the page lock to use the new page via the page tables - * before the new page is unlocked. - */ - remove_from_swap(newpage); - return 0; -} -EXPORT_SYMBOL(migrate_page); - -/* - * migrate_pages - * - * Two lists are passed to this function. The first list - * contains the pages isolated from the LRU to be migrated. - * The second list contains new pages that the pages isolated - * can be moved to. If the second list is NULL then all - * pages are swapped out. - * - * The function returns after 10 attempts or if no pages - * are movable anymore because to has become empty - * or no retryable pages exist anymore. - * - * Return: Number of pages not migrated when "to" ran empty. - */ -unsigned long migrate_pages(struct list_head *from, struct list_head *to, - struct list_head *moved, struct list_head *failed) -{ - unsigned long retry; - unsigned long nr_failed = 0; - int pass = 0; - struct page *page; - struct page *page2; - int swapwrite = current->flags & PF_SWAPWRITE; - int rc; - - if (!swapwrite) - current->flags |= PF_SWAPWRITE; - -redo: - retry = 0; - - list_for_each_entry_safe(page, page2, from, lru) { - struct page *newpage = NULL; - struct address_space *mapping; - - cond_resched(); - - rc = 0; - if (page_count(page) == 1) - /* page was freed from under us. So we are done. */ - goto next; - - if (to && list_empty(to)) - break; - - /* - * Skip locked pages during the first two passes to give the - * functions holding the lock time to release the page. Later we - * use lock_page() to have a higher chance of acquiring the - * lock. - */ - rc = -EAGAIN; - if (pass > 2) - lock_page(page); - else - if (TestSetPageLocked(page)) - goto next; - - /* - * Only wait on writeback if we have already done a pass where - * we we may have triggered writeouts for lots of pages. - */ - if (pass > 0) { - wait_on_page_writeback(page); - } else { - if (PageWriteback(page)) - goto unlock_page; - } - - /* - * Anonymous pages must have swap cache references otherwise - * the information contained in the page maps cannot be - * preserved. - */ - if (PageAnon(page) && !PageSwapCache(page)) { - if (!add_to_swap(page, GFP_KERNEL)) { - rc = -ENOMEM; - goto unlock_page; - } - } - - if (!to) { - rc = swap_page(page); - goto next; - } - - newpage = lru_to_page(to); - lock_page(newpage); - - /* - * Pages are properly locked and writeback is complete. - * Try to migrate the page. - */ - mapping = page_mapping(page); - if (!mapping) - goto unlock_both; - - if (mapping->a_ops->migratepage) { - /* - * Most pages have a mapping and most filesystems - * should provide a migration function. Anonymous - * pages are part of swap space which also has its - * own migration function. This is the most common - * path for page migration. - */ - rc = mapping->a_ops->migratepage(newpage, page); - goto unlock_both; - } - - /* - * Default handling if a filesystem does not provide - * a migration function. We can only migrate clean - * pages so try to write out any dirty pages first. - */ - if (PageDirty(page)) { - switch (pageout(page, mapping)) { - case PAGE_KEEP: - case PAGE_ACTIVATE: - goto unlock_both; - - case PAGE_SUCCESS: - unlock_page(newpage); - goto next; - - case PAGE_CLEAN: - ; /* try to migrate the page below */ - } - } - - /* - * Buffers are managed in a filesystem specific way. - * We must have no buffers or drop them. - */ - if (!page_has_buffers(page) || - try_to_release_page(page, GFP_KERNEL)) { - rc = migrate_page(newpage, page); - goto unlock_both; - } - - /* - * On early passes with mapped pages simply - * retry. There may be a lock held for some - * buffers that may go away. Later - * swap them out. - */ - if (pass > 4) { - /* - * Persistently unable to drop buffers..... As a - * measure of last resort we fall back to - * swap_page(). - */ - unlock_page(newpage); - newpage = NULL; - rc = swap_page(page); - goto next; - } - -unlock_both: - unlock_page(newpage); - -unlock_page: - unlock_page(page); - -next: - if (rc == -EAGAIN) { - retry++; - } else if (rc) { - /* Permanent failure */ - list_move(&page->lru, failed); - nr_failed++; - } else { - if (newpage) { - /* Successful migration. Return page to LRU */ - move_to_lru(newpage); - } - list_move(&page->lru, moved); - } - } - if (retry && pass++ < 10) - goto redo; - - if (!swapwrite) - current->flags &= ~PF_SWAPWRITE; - - return nr_failed + retry; -} - -/* - * Isolate one page from the LRU lists and put it on the - * indicated list with elevated refcount. - * - * Result: - * 0 = page not on LRU list - * 1 = page removed from LRU list and added to the specified list. - */ -int isolate_lru_page(struct page *page) -{ - int ret = 0; - - if (PageLRU(page)) { - struct zone *zone = page_zone(page); - spin_lock_irq(&zone->lru_lock); - if (PageLRU(page)) { - ret = 1; - get_page(page); - ClearPageLRU(page); - if (PageActive(page)) - del_page_from_active_list(zone, page); - else - del_page_from_inactive_list(zone, page); - } - spin_unlock_irq(&zone->lru_lock); - } - - return ret; -} -#endif - /* * zone->lru_lock is heavily contended. Some of the functions that * shrink the lists perform better by taking out a batch of pages -- cgit v1.2.3 From e99053e07514e514611167ad648c65c87982c4d9 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Wed, 22 Mar 2006 20:14:09 +0000 Subject: [ARM] 3379/1: ixp2000: use generic 8250 debug macros Patch from Lennert Buytenhek The xscale UART in the ixp2000 is basically just an 8250 UART (with some extra bits and pieces), so we can use the generic 8250 debug macros on the ixp2000. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- include/asm-arm/arch-ixp2000/debug-macro.S | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/include/asm-arm/arch-ixp2000/debug-macro.S b/include/asm-arm/arch-ixp2000/debug-macro.S index 5631e0889861..bc8b39654793 100644 --- a/include/asm-arm/arch-ixp2000/debug-macro.S +++ b/include/asm-arm/arch-ixp2000/debug-macro.S @@ -23,18 +23,5 @@ #endif .endm - .macro senduart,rd,rx - strb \rd, [\rx] - .endm - - .macro busyuart,rd,rx -1002: ldrb \rd, [\rx, #0x14] - tst \rd, #0x20 - beq 1002b - .endm - - .macro waituart,rd,rx - nop - nop - nop - .endm +#define UART_SHIFT 2 +#include -- cgit v1.2.3 From 709eb502ebcfcca8a3a36bab3bca3bd78caa53b1 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Wed, 22 Mar 2006 20:14:11 +0000 Subject: [ARM] 3380/1: ixp2000: simplify ixdp2x00_master_npu() check Patch from Lennert Buytenhek On the IXDP2x00s, the NPU that is PCI master is always the egress (i.e. 'master') NPU. At least on the IXDP2800, both NPUs have flash, so the ixp2000_has_flash() check in ixdp2x00_master_npu() is useless. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- include/asm-arm/arch-ixp2000/ixdp2x00.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/asm-arm/arch-ixp2000/ixdp2x00.h b/include/asm-arm/arch-ixp2000/ixdp2x00.h index 229381c64283..546e2e8e27b8 100644 --- a/include/asm-arm/arch-ixp2000/ixdp2x00.h +++ b/include/asm-arm/arch-ixp2000/ixdp2x00.h @@ -72,12 +72,11 @@ #ifndef __ASSEMBLY__ /* - * Master NPU will always have flash and be PCI master. - * Slave NPU may or may not have flash but will never be PCI master. + * The master NPU is always PCI master. */ static inline unsigned int ixdp2x00_master_npu(void) { - return ((ixp2000_has_flash()) && (ixp2000_is_pcimaster())); + return !!ixp2000_is_pcimaster(); } /* -- cgit v1.2.3 From a04f2d9d3a08002a7712f18fcec43e2c4151d953 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Wed, 22 Mar 2006 20:14:11 +0000 Subject: [ARM] 3381/1: ixp2000: fix slowport write timing control register fields Patch from Lennert Buytenhek The original version of the chip docs had the PW and SU fields in the slowport write timing control register accidentally reversed. This is mentioned in the errata (documentation change #4) and fixed in newer docs. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- include/asm-arm/arch-ixp2000/ixp2000-regs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-arm/arch-ixp2000/ixp2000-regs.h b/include/asm-arm/arch-ixp2000/ixp2000-regs.h index 2b57f91b4ebd..ccae4bec92c5 100644 --- a/include/asm-arm/arch-ixp2000/ixp2000-regs.h +++ b/include/asm-arm/arch-ixp2000/ixp2000-regs.h @@ -353,8 +353,8 @@ * Masks and shifts for various fields in the WTC and RTC registers. */ #define SLOWPORT_WRTC_MASK_HD 0x0003 -#define SLOWPORT_WRTC_MASK_SU 0x003c -#define SLOWPORT_WRTC_MASK_PW 0x03c0 +#define SLOWPORT_WRTC_MASK_PW 0x003c +#define SLOWPORT_WRTC_MASK_SU 0x03c0 #define SLOWPORT_WRTC_SHIFT_HD 0x00 #define SLOWPORT_WRTC_SHIFT_SU 0x02 -- cgit v1.2.3 From a45049c51ce6a3fecf2a909b591b28164c927112 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 22 Mar 2006 13:55:40 -0800 Subject: [NETFILTER]: x_tables: set the protocol family in x_tables targets/matches Set the family field in xt_[matches|targets] registered. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter/x_tables.h | 8 ++++---- include/linux/netfilter_arp/arp_tables.h | 6 ++++-- include/linux/netfilter_ipv4/ip_tables.h | 14 +++++++++----- include/linux/netfilter_ipv6/ip6_tables.h | 14 +++++++++----- net/ipv4/netfilter/arp_tables.c | 6 ++++-- net/ipv4/netfilter/ip_tables.c | 15 +++++++++------ net/ipv6/netfilter/ip6_tables.c | 15 +++++++++------ net/netfilter/x_tables.c | 16 ++++++++++------ net/netfilter/xt_CLASSIFY.c | 12 +++++++----- net/netfilter/xt_CONNMARK.c | 12 +++++++----- net/netfilter/xt_MARK.c | 21 ++++++++++++--------- net/netfilter/xt_NFQUEUE.c | 19 +++++++++++-------- net/netfilter/xt_NOTRACK.c | 12 +++++++----- net/netfilter/xt_comment.c | 12 +++++++----- net/netfilter/xt_connbytes.c | 12 +++++++----- net/netfilter/xt_connmark.c | 12 +++++++----- net/netfilter/xt_conntrack.c | 5 +++-- net/netfilter/xt_dccp.c | 12 +++++++----- net/netfilter/xt_helper.c | 12 +++++++----- net/netfilter/xt_length.c | 12 +++++++----- net/netfilter/xt_limit.c | 12 +++++++----- net/netfilter/xt_mac.c | 12 +++++++----- net/netfilter/xt_mark.c | 12 +++++++----- net/netfilter/xt_physdev.c | 12 +++++++----- net/netfilter/xt_pkttype.c | 12 +++++++----- net/netfilter/xt_policy.c | 12 +++++++----- net/netfilter/xt_realm.c | 5 +++-- net/netfilter/xt_sctp.c | 12 +++++++----- net/netfilter/xt_state.c | 12 +++++++----- net/netfilter/xt_string.c | 12 +++++++----- net/netfilter/xt_tcpmss.c | 12 +++++++----- net/netfilter/xt_tcpudp.c | 26 +++++++++++++++----------- 32 files changed, 235 insertions(+), 163 deletions(-) (limited to 'include') diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 46a0f974f87c..bf71efb63007 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -220,10 +220,10 @@ struct xt_table_info char *entries[NR_CPUS]; }; -extern int xt_register_target(int af, struct xt_target *target); -extern void xt_unregister_target(int af, struct xt_target *target); -extern int xt_register_match(int af, struct xt_match *target); -extern void xt_unregister_match(int af, struct xt_match *target); +extern int xt_register_target(struct xt_target *target); +extern void xt_unregister_target(struct xt_target *target); +extern int xt_register_match(struct xt_match *target); +extern void xt_unregister_match(struct xt_match *target); extern int xt_check_match(const struct xt_match *match, unsigned short family, unsigned int size, const char *table, unsigned int hook, diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h index fd21796e5131..a27be05f67f0 100644 --- a/include/linux/netfilter_arp/arp_tables.h +++ b/include/linux/netfilter_arp/arp_tables.h @@ -263,8 +263,10 @@ static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e */ #ifdef __KERNEL__ -#define arpt_register_target(tgt) xt_register_target(NF_ARP, tgt) -#define arpt_unregister_target(tgt) xt_unregister_target(NF_ARP, tgt) +#define arpt_register_target(tgt) \ +({ (tgt)->family = NF_ARP; \ + xt_register_target(tgt); }) +#define arpt_unregister_target(tgt) xt_unregister_target(tgt) extern int arpt_register_table(struct arpt_table *table, const struct arpt_replace *repl); diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index 76ba24b68515..ee262b5344e1 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h @@ -321,11 +321,15 @@ ipt_get_target(struct ipt_entry *e) #include extern void ipt_init(void) __init; -#define ipt_register_target(tgt) xt_register_target(AF_INET, tgt) -#define ipt_unregister_target(tgt) xt_unregister_target(AF_INET, tgt) - -#define ipt_register_match(mtch) xt_register_match(AF_INET, mtch) -#define ipt_unregister_match(mtch) xt_unregister_match(AF_INET, mtch) +#define ipt_register_target(tgt) \ +({ (tgt)->family = AF_INET; \ + xt_register_target(tgt); }) +#define ipt_unregister_target(tgt) xt_unregister_target(tgt) + +#define ipt_register_match(mtch) \ +({ (mtch)->family = AF_INET; \ + xt_register_match(mtch); }) +#define ipt_unregister_match(mtch) xt_unregister_match(mtch) //#define ipt_register_table(tbl, repl) xt_register_table(AF_INET, tbl, repl) //#define ipt_unregister_table(tbl) xt_unregister_table(AF_INET, tbl) diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index f249b574f0fa..7107f942eb05 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h @@ -334,11 +334,15 @@ ip6t_get_target(struct ip6t_entry *e) #include extern void ip6t_init(void) __init; -#define ip6t_register_target(tgt) xt_register_target(AF_INET6, tgt) -#define ip6t_unregister_target(tgt) xt_unregister_target(AF_INET6, tgt) - -#define ip6t_register_match(match) xt_register_match(AF_INET6, match) -#define ip6t_unregister_match(match) xt_unregister_match(AF_INET6, match) +#define ip6t_register_target(tgt) \ +({ (tgt)->family = AF_INET6; \ + xt_register_target(tgt); }) +#define ip6t_unregister_target(tgt) xt_unregister_target(tgt) + +#define ip6t_register_match(match) \ +({ (match)->family = AF_INET6; \ + xt_register_match(match); }) +#define ip6t_unregister_match(match) xt_unregister_match(match) extern int ip6t_register_table(struct ip6t_table *table, const struct ip6t_replace *repl); diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index f7efb3f27bf5..ff0c594a4198 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -1146,12 +1146,14 @@ void arpt_unregister_table(struct arpt_table *table) static struct arpt_target arpt_standard_target = { .name = ARPT_STANDARD_TARGET, .targetsize = sizeof(int), + .family = NF_ARP, }; static struct arpt_target arpt_error_target = { .name = ARPT_ERROR_TARGET, .target = arpt_error, .targetsize = ARPT_FUNCTION_MAXNAMELEN, + .family = NF_ARP, }; static struct nf_sockopt_ops arpt_sockopts = { @@ -1171,8 +1173,8 @@ static int __init init(void) xt_proto_init(NF_ARP); /* Noone else will be downing sem now, so we won't sleep */ - xt_register_target(NF_ARP, &arpt_standard_target); - xt_register_target(NF_ARP, &arpt_error_target); + xt_register_target(&arpt_standard_target); + xt_register_target(&arpt_error_target); /* Register setsockopt */ ret = nf_register_sockopt(&arpt_sockopts); diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 39705f9bc154..a7b194c4d79d 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1335,12 +1335,14 @@ icmp_checkentry(const char *tablename, static struct ipt_target ipt_standard_target = { .name = IPT_STANDARD_TARGET, .targetsize = sizeof(int), + .family = AF_INET, }; static struct ipt_target ipt_error_target = { .name = IPT_ERROR_TARGET, .target = ipt_error, .targetsize = IPT_FUNCTION_MAXNAMELEN, + .family = AF_INET, }; static struct nf_sockopt_ops ipt_sockopts = { @@ -1358,6 +1360,7 @@ static struct ipt_match icmp_matchstruct = { .match = icmp_match, .matchsize = sizeof(struct ipt_icmp), .proto = IPPROTO_ICMP, + .family = AF_INET, .checkentry = icmp_checkentry, }; @@ -1368,9 +1371,9 @@ static int __init init(void) xt_proto_init(AF_INET); /* Noone else will be downing sem now, so we won't sleep */ - xt_register_target(AF_INET, &ipt_standard_target); - xt_register_target(AF_INET, &ipt_error_target); - xt_register_match(AF_INET, &icmp_matchstruct); + xt_register_target(&ipt_standard_target); + xt_register_target(&ipt_error_target); + xt_register_match(&icmp_matchstruct); /* Register setsockopt */ ret = nf_register_sockopt(&ipt_sockopts); @@ -1387,9 +1390,9 @@ static void __exit fini(void) { nf_unregister_sockopt(&ipt_sockopts); - xt_unregister_match(AF_INET, &icmp_matchstruct); - xt_unregister_target(AF_INET, &ipt_error_target); - xt_unregister_target(AF_INET, &ipt_standard_target); + xt_unregister_match(&icmp_matchstruct); + xt_unregister_target(&ipt_error_target); + xt_unregister_target(&ipt_standard_target); xt_proto_fini(AF_INET); } diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 5a2063bda676..db3c9ae98e95 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1377,12 +1377,14 @@ icmp6_checkentry(const char *tablename, static struct ip6t_target ip6t_standard_target = { .name = IP6T_STANDARD_TARGET, .targetsize = sizeof(int), + .family = AF_INET6, }; static struct ip6t_target ip6t_error_target = { .name = IP6T_ERROR_TARGET, .target = ip6t_error, .targetsize = IP6T_FUNCTION_MAXNAMELEN, + .family = AF_INET6, }; static struct nf_sockopt_ops ip6t_sockopts = { @@ -1401,6 +1403,7 @@ static struct ip6t_match icmp6_matchstruct = { .matchsize = sizeof(struct ip6t_icmp), .checkentry = icmp6_checkentry, .proto = IPPROTO_ICMPV6, + .family = AF_INET6, }; static int __init init(void) @@ -1410,9 +1413,9 @@ static int __init init(void) xt_proto_init(AF_INET6); /* Noone else will be downing sem now, so we won't sleep */ - xt_register_target(AF_INET6, &ip6t_standard_target); - xt_register_target(AF_INET6, &ip6t_error_target); - xt_register_match(AF_INET6, &icmp6_matchstruct); + xt_register_target(&ip6t_standard_target); + xt_register_target(&ip6t_error_target); + xt_register_match(&icmp6_matchstruct); /* Register setsockopt */ ret = nf_register_sockopt(&ip6t_sockopts); @@ -1429,9 +1432,9 @@ static int __init init(void) static void __exit fini(void) { nf_unregister_sockopt(&ip6t_sockopts); - xt_unregister_match(AF_INET6, &icmp6_matchstruct); - xt_unregister_target(AF_INET6, &ip6t_error_target); - xt_unregister_target(AF_INET6, &ip6t_standard_target); + xt_unregister_match(&icmp6_matchstruct); + xt_unregister_target(&ip6t_error_target); + xt_unregister_target(&ip6t_standard_target); xt_proto_fini(AF_INET6); } diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 750b92829766..0a29a24d9a72 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -60,9 +60,9 @@ static const char *xt_prefix[NPROTO] = { /* Registration hooks for targets. */ int -xt_register_target(int af, struct xt_target *target) +xt_register_target(struct xt_target *target) { - int ret; + int ret, af = target->family; ret = down_interruptible(&xt[af].mutex); if (ret != 0) @@ -74,8 +74,10 @@ xt_register_target(int af, struct xt_target *target) EXPORT_SYMBOL(xt_register_target); void -xt_unregister_target(int af, struct xt_target *target) +xt_unregister_target(struct xt_target *target) { + int af = target->family; + down(&xt[af].mutex); LIST_DELETE(&xt[af].target, target); up(&xt[af].mutex); @@ -83,9 +85,9 @@ xt_unregister_target(int af, struct xt_target *target) EXPORT_SYMBOL(xt_unregister_target); int -xt_register_match(int af, struct xt_match *match) +xt_register_match(struct xt_match *match) { - int ret; + int ret, af = match->family; ret = down_interruptible(&xt[af].mutex); if (ret != 0) @@ -99,8 +101,10 @@ xt_register_match(int af, struct xt_match *match) EXPORT_SYMBOL(xt_register_match); void -xt_unregister_match(int af, struct xt_match *match) +xt_unregister_match(struct xt_match *match) { + int af = match->family; + down(&xt[af].mutex); LIST_DELETE(&xt[af].match, match); up(&xt[af].mutex); diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c index 3224ed87d4c7..3cd2ac90a25b 100644 --- a/net/netfilter/xt_CLASSIFY.c +++ b/net/netfilter/xt_CLASSIFY.c @@ -47,6 +47,7 @@ static struct xt_target classify_reg = { .table = "mangle", .hooks = (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) | (1 << NF_IP_POST_ROUTING), + .family = AF_INET, .me = THIS_MODULE, }; static struct xt_target classify6_reg = { @@ -56,6 +57,7 @@ static struct xt_target classify6_reg = { .table = "mangle", .hooks = (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) | (1 << NF_IP_POST_ROUTING), + .family = AF_INET6, .me = THIS_MODULE, }; @@ -64,21 +66,21 @@ static int __init init(void) { int ret; - ret = xt_register_target(AF_INET, &classify_reg); + ret = xt_register_target(&classify_reg); if (ret) return ret; - ret = xt_register_target(AF_INET6, &classify6_reg); + ret = xt_register_target(&classify6_reg); if (ret) - xt_unregister_target(AF_INET, &classify_reg); + xt_unregister_target(&classify_reg); return ret; } static void __exit fini(void) { - xt_unregister_target(AF_INET, &classify_reg); - xt_unregister_target(AF_INET6, &classify6_reg); + xt_unregister_target(&classify_reg); + xt_unregister_target(&classify6_reg); } module_init(init); diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c index df2486a3efd5..35448b8e6883 100644 --- a/net/netfilter/xt_CONNMARK.c +++ b/net/netfilter/xt_CONNMARK.c @@ -102,6 +102,7 @@ static struct xt_target connmark_reg = { .target = target, .targetsize = sizeof(struct xt_connmark_target_info), .checkentry = checkentry, + .family = AF_INET, .me = THIS_MODULE }; @@ -110,6 +111,7 @@ static struct xt_target connmark6_reg = { .target = target, .targetsize = sizeof(struct xt_connmark_target_info), .checkentry = checkentry, + .family = AF_INET6, .me = THIS_MODULE }; @@ -119,21 +121,21 @@ static int __init init(void) need_conntrack(); - ret = xt_register_target(AF_INET, &connmark_reg); + ret = xt_register_target(&connmark_reg); if (ret) return ret; - ret = xt_register_target(AF_INET6, &connmark6_reg); + ret = xt_register_target(&connmark6_reg); if (ret) - xt_unregister_target(AF_INET, &connmark_reg); + xt_unregister_target(&connmark_reg); return ret; } static void __exit fini(void) { - xt_unregister_target(AF_INET, &connmark_reg); - xt_unregister_target(AF_INET6, &connmark6_reg); + xt_unregister_target(&connmark_reg); + xt_unregister_target(&connmark6_reg); } module_init(init); diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c index dcb5266efae0..73bdd5c80e17 100644 --- a/net/netfilter/xt_MARK.c +++ b/net/netfilter/xt_MARK.c @@ -119,6 +119,7 @@ static struct xt_target ipt_mark_reg_v0 = { .table = "mangle", .checkentry = checkentry_v0, .me = THIS_MODULE, + .family = AF_INET, .revision = 0, }; @@ -129,6 +130,7 @@ static struct xt_target ipt_mark_reg_v1 = { .table = "mangle", .checkentry = checkentry_v1, .me = THIS_MODULE, + .family = AF_INET, .revision = 1, }; @@ -139,6 +141,7 @@ static struct xt_target ip6t_mark_reg_v0 = { .table = "mangle", .checkentry = checkentry_v0, .me = THIS_MODULE, + .family = AF_INET6, .revision = 0, }; @@ -146,18 +149,18 @@ static int __init init(void) { int err; - err = xt_register_target(AF_INET, &ipt_mark_reg_v0); + err = xt_register_target(&ipt_mark_reg_v0); if (err) return err; - err = xt_register_target(AF_INET, &ipt_mark_reg_v1); + err = xt_register_target(&ipt_mark_reg_v1); if (err) - xt_unregister_target(AF_INET, &ipt_mark_reg_v0); + xt_unregister_target(&ipt_mark_reg_v0); - err = xt_register_target(AF_INET6, &ip6t_mark_reg_v0); + err = xt_register_target(&ip6t_mark_reg_v0); if (err) { - xt_unregister_target(AF_INET, &ipt_mark_reg_v0); - xt_unregister_target(AF_INET, &ipt_mark_reg_v1); + xt_unregister_target(&ipt_mark_reg_v0); + xt_unregister_target(&ipt_mark_reg_v1); } return err; @@ -165,9 +168,9 @@ static int __init init(void) static void __exit fini(void) { - xt_unregister_target(AF_INET, &ipt_mark_reg_v0); - xt_unregister_target(AF_INET, &ipt_mark_reg_v1); - xt_unregister_target(AF_INET6, &ip6t_mark_reg_v0); + xt_unregister_target(&ipt_mark_reg_v0); + xt_unregister_target(&ipt_mark_reg_v1); + xt_unregister_target(&ip6t_mark_reg_v0); } module_init(init); diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c index 39a963edf16b..2873e1c60f68 100644 --- a/net/netfilter/xt_NFQUEUE.c +++ b/net/netfilter/xt_NFQUEUE.c @@ -41,6 +41,7 @@ static struct xt_target ipt_NFQ_reg = { .name = "NFQUEUE", .target = target, .targetsize = sizeof(struct xt_NFQ_info), + .family = AF_INET, .me = THIS_MODULE, }; @@ -48,6 +49,7 @@ static struct xt_target ip6t_NFQ_reg = { .name = "NFQUEUE", .target = target, .targetsize = sizeof(struct xt_NFQ_info), + .family = AF_INET6, .me = THIS_MODULE, }; @@ -55,36 +57,37 @@ static struct xt_target arpt_NFQ_reg = { .name = "NFQUEUE", .target = target, .targetsize = sizeof(struct xt_NFQ_info), + .family = NF_ARP, .me = THIS_MODULE, }; static int __init init(void) { int ret; - ret = xt_register_target(AF_INET, &ipt_NFQ_reg); + ret = xt_register_target(&ipt_NFQ_reg); if (ret) return ret; - ret = xt_register_target(AF_INET6, &ip6t_NFQ_reg); + ret = xt_register_target(&ip6t_NFQ_reg); if (ret) goto out_ip; - ret = xt_register_target(NF_ARP, &arpt_NFQ_reg); + ret = xt_register_target(&arpt_NFQ_reg); if (ret) goto out_ip6; return ret; out_ip6: - xt_unregister_target(AF_INET6, &ip6t_NFQ_reg); + xt_unregister_target(&ip6t_NFQ_reg); out_ip: - xt_unregister_target(AF_INET, &ipt_NFQ_reg); + xt_unregister_target(&ipt_NFQ_reg); return ret; } static void __exit fini(void) { - xt_unregister_target(NF_ARP, &arpt_NFQ_reg); - xt_unregister_target(AF_INET6, &ip6t_NFQ_reg); - xt_unregister_target(AF_INET, &ipt_NFQ_reg); + xt_unregister_target(&arpt_NFQ_reg); + xt_unregister_target(&ip6t_NFQ_reg); + xt_unregister_target(&ipt_NFQ_reg); } module_init(init); diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c index b8634e3f6169..cf2ebd76fd6f 100644 --- a/net/netfilter/xt_NOTRACK.c +++ b/net/netfilter/xt_NOTRACK.c @@ -39,6 +39,7 @@ static struct xt_target notrack_reg = { .target = target, .targetsize = 0, .table = "raw", + .family = AF_INET, .me = THIS_MODULE, }; @@ -47,6 +48,7 @@ static struct xt_target notrack6_reg = { .target = target, .targetsize = 0, .table = "raw", + .family = AF_INET6, .me = THIS_MODULE, }; @@ -54,21 +56,21 @@ static int __init init(void) { int ret; - ret = xt_register_target(AF_INET, ¬rack_reg); + ret = xt_register_target(¬rack_reg); if (ret) return ret; - ret = xt_register_target(AF_INET6, ¬rack6_reg); + ret = xt_register_target(¬rack6_reg); if (ret) - xt_unregister_target(AF_INET, ¬rack_reg); + xt_unregister_target(¬rack_reg); return ret; } static void __exit fini(void) { - xt_unregister_target(AF_INET6, ¬rack6_reg); - xt_unregister_target(AF_INET, ¬rack_reg); + xt_unregister_target(¬rack6_reg); + xt_unregister_target(¬rack_reg); } module_init(init); diff --git a/net/netfilter/xt_comment.c b/net/netfilter/xt_comment.c index 03d9d741231c..2637724b498d 100644 --- a/net/netfilter/xt_comment.c +++ b/net/netfilter/xt_comment.c @@ -33,6 +33,7 @@ static struct xt_match comment_match = { .name = "comment", .match = match, .matchsize = sizeof(struct xt_comment_info), + .family = AF_INET, .me = THIS_MODULE }; @@ -40,6 +41,7 @@ static struct xt_match comment6_match = { .name = "comment", .match = match, .matchsize = sizeof(struct xt_comment_info), + .family = AF_INET6, .me = THIS_MODULE }; @@ -47,21 +49,21 @@ static int __init init(void) { int ret; - ret = xt_register_match(AF_INET, &comment_match); + ret = xt_register_match(&comment_match); if (ret) return ret; - ret = xt_register_match(AF_INET6, &comment6_match); + ret = xt_register_match(&comment6_match); if (ret) - xt_unregister_match(AF_INET, &comment_match); + xt_unregister_match(&comment_match); return ret; } static void __exit fini(void) { - xt_unregister_match(AF_INET, &comment_match); - xt_unregister_match(AF_INET6, &comment6_match); + xt_unregister_match(&comment_match); + xt_unregister_match(&comment6_match); } module_init(init); diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c index f34ecb9485c7..4985f5ec58ca 100644 --- a/net/netfilter/xt_connbytes.c +++ b/net/netfilter/xt_connbytes.c @@ -148,6 +148,7 @@ static struct xt_match connbytes_match = { .match = match, .checkentry = check, .matchsize = sizeof(struct xt_connbytes_info), + .family = AF_INET, .me = THIS_MODULE }; static struct xt_match connbytes6_match = { @@ -155,26 +156,27 @@ static struct xt_match connbytes6_match = { .match = match, .checkentry = check, .matchsize = sizeof(struct xt_connbytes_info), + .family = AF_INET6, .me = THIS_MODULE }; static int __init init(void) { int ret; - ret = xt_register_match(AF_INET, &connbytes_match); + ret = xt_register_match(&connbytes_match); if (ret) return ret; - ret = xt_register_match(AF_INET6, &connbytes6_match); + ret = xt_register_match(&connbytes6_match); if (ret) - xt_unregister_match(AF_INET, &connbytes_match); + xt_unregister_match(&connbytes_match); return ret; } static void __exit fini(void) { - xt_unregister_match(AF_INET, &connbytes_match); - xt_unregister_match(AF_INET6, &connbytes6_match); + xt_unregister_match(&connbytes_match); + xt_unregister_match(&connbytes6_match); } module_init(init); diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c index 51822471e919..e810600345e3 100644 --- a/net/netfilter/xt_connmark.c +++ b/net/netfilter/xt_connmark.c @@ -72,6 +72,7 @@ static struct xt_match connmark_match = { .match = match, .matchsize = sizeof(struct xt_connmark_info), .checkentry = checkentry, + .family = AF_INET, .me = THIS_MODULE }; @@ -80,6 +81,7 @@ static struct xt_match connmark6_match = { .match = match, .matchsize = sizeof(struct xt_connmark_info), .checkentry = checkentry, + .family = AF_INET6, .me = THIS_MODULE }; @@ -89,20 +91,20 @@ static int __init init(void) need_conntrack(); - ret = xt_register_match(AF_INET, &connmark_match); + ret = xt_register_match(&connmark_match); if (ret) return ret; - ret = xt_register_match(AF_INET6, &connmark6_match); + ret = xt_register_match(&connmark6_match); if (ret) - xt_unregister_match(AF_INET, &connmark_match); + xt_unregister_match(&connmark_match); return ret; } static void __exit fini(void) { - xt_unregister_match(AF_INET6, &connmark6_match); - xt_unregister_match(AF_INET, &connmark_match); + xt_unregister_match(&connmark6_match); + xt_unregister_match(&connmark_match); } module_init(init); diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c index 39fc29496e00..7d20caa0d605 100644 --- a/net/netfilter/xt_conntrack.c +++ b/net/netfilter/xt_conntrack.c @@ -207,6 +207,7 @@ static struct xt_match conntrack_match = { .name = "conntrack", .match = match, .matchsize = sizeof(struct xt_conntrack_info), + .family = AF_INET, .me = THIS_MODULE, }; @@ -214,14 +215,14 @@ static int __init init(void) { int ret; need_conntrack(); - ret = xt_register_match(AF_INET, &conntrack_match); + ret = xt_register_match(&conntrack_match); return ret; } static void __exit fini(void) { - xt_unregister_match(AF_INET, &conntrack_match); + xt_unregister_match(&conntrack_match); } module_init(init); diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c index db6b70cdc770..2f331decd151 100644 --- a/net/netfilter/xt_dccp.c +++ b/net/netfilter/xt_dccp.c @@ -149,6 +149,7 @@ static struct xt_match dccp_match = .matchsize = sizeof(struct xt_dccp_info), .proto = IPPROTO_DCCP, .checkentry = checkentry, + .family = AF_INET, .me = THIS_MODULE, }; static struct xt_match dccp6_match = @@ -158,6 +159,7 @@ static struct xt_match dccp6_match = .matchsize = sizeof(struct xt_dccp_info), .proto = IPPROTO_DCCP, .checkentry = checkentry, + .family = AF_INET6, .me = THIS_MODULE, }; @@ -172,17 +174,17 @@ static int __init init(void) dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL); if (!dccp_optbuf) return -ENOMEM; - ret = xt_register_match(AF_INET, &dccp_match); + ret = xt_register_match(&dccp_match); if (ret) goto out_kfree; - ret = xt_register_match(AF_INET6, &dccp6_match); + ret = xt_register_match(&dccp6_match); if (ret) goto out_unreg; return ret; out_unreg: - xt_unregister_match(AF_INET, &dccp_match); + xt_unregister_match(&dccp_match); out_kfree: kfree(dccp_optbuf); @@ -191,8 +193,8 @@ out_kfree: static void __exit fini(void) { - xt_unregister_match(AF_INET6, &dccp6_match); - xt_unregister_match(AF_INET, &dccp_match); + xt_unregister_match(&dccp6_match); + xt_unregister_match(&dccp_match); kfree(dccp_optbuf); } diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c index ef8e54d40c92..7d2d68b9155f 100644 --- a/net/netfilter/xt_helper.c +++ b/net/netfilter/xt_helper.c @@ -153,6 +153,7 @@ static struct xt_match helper_match = { .match = match, .matchsize = sizeof(struct xt_helper_info), .checkentry = check, + .family = AF_INET, .me = THIS_MODULE, }; static struct xt_match helper6_match = { @@ -160,6 +161,7 @@ static struct xt_match helper6_match = { .match = match, .matchsize = sizeof(struct xt_helper_info), .checkentry = check, + .family = AF_INET6, .me = THIS_MODULE, }; @@ -168,21 +170,21 @@ static int __init init(void) int ret; need_conntrack(); - ret = xt_register_match(AF_INET, &helper_match); + ret = xt_register_match(&helper_match); if (ret < 0) return ret; - ret = xt_register_match(AF_INET6, &helper6_match); + ret = xt_register_match(&helper6_match); if (ret < 0) - xt_unregister_match(AF_INET, &helper_match); + xt_unregister_match(&helper_match); return ret; } static void __exit fini(void) { - xt_unregister_match(AF_INET, &helper_match); - xt_unregister_match(AF_INET6, &helper6_match); + xt_unregister_match(&helper_match); + xt_unregister_match(&helper6_match); } module_init(init); diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c index b9e60f041a64..38560caef757 100644 --- a/net/netfilter/xt_length.c +++ b/net/netfilter/xt_length.c @@ -56,6 +56,7 @@ static struct xt_match length_match = { .name = "length", .match = match, .matchsize = sizeof(struct xt_length_info), + .family = AF_INET, .me = THIS_MODULE, }; @@ -63,26 +64,27 @@ static struct xt_match length6_match = { .name = "length", .match = match6, .matchsize = sizeof(struct xt_length_info), + .family = AF_INET6, .me = THIS_MODULE, }; static int __init init(void) { int ret; - ret = xt_register_match(AF_INET, &length_match); + ret = xt_register_match(&length_match); if (ret) return ret; - ret = xt_register_match(AF_INET6, &length6_match); + ret = xt_register_match(&length6_match); if (ret) - xt_unregister_match(AF_INET, &length_match); + xt_unregister_match(&length_match); return ret; } static void __exit fini(void) { - xt_unregister_match(AF_INET, &length_match); - xt_unregister_match(AF_INET6, &length6_match); + xt_unregister_match(&length_match); + xt_unregister_match(&length6_match); } module_init(init); diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c index 3049e6f8889e..e91c1a444e77 100644 --- a/net/netfilter/xt_limit.c +++ b/net/netfilter/xt_limit.c @@ -141,6 +141,7 @@ static struct xt_match ipt_limit_reg = { .match = ipt_limit_match, .matchsize = sizeof(struct xt_rateinfo), .checkentry = ipt_limit_checkentry, + .family = AF_INET, .me = THIS_MODULE, }; static struct xt_match limit6_reg = { @@ -148,6 +149,7 @@ static struct xt_match limit6_reg = { .match = ipt_limit_match, .matchsize = sizeof(struct xt_rateinfo), .checkentry = ipt_limit_checkentry, + .family = AF_INET6, .me = THIS_MODULE, }; @@ -155,21 +157,21 @@ static int __init init(void) { int ret; - ret = xt_register_match(AF_INET, &ipt_limit_reg); + ret = xt_register_match(&ipt_limit_reg); if (ret) return ret; - ret = xt_register_match(AF_INET6, &limit6_reg); + ret = xt_register_match(&limit6_reg); if (ret) - xt_unregister_match(AF_INET, &ipt_limit_reg); + xt_unregister_match(&ipt_limit_reg); return ret; } static void __exit fini(void) { - xt_unregister_match(AF_INET, &ipt_limit_reg); - xt_unregister_match(AF_INET6, &limit6_reg); + xt_unregister_match(&ipt_limit_reg); + xt_unregister_match(&limit6_reg); } module_init(init); diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c index b4559a46dce8..f4defa28a6ec 100644 --- a/net/netfilter/xt_mac.c +++ b/net/netfilter/xt_mac.c @@ -49,6 +49,7 @@ static struct xt_match mac_match = { .matchsize = sizeof(struct xt_mac_info), .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD), + .family = AF_INET, .me = THIS_MODULE, }; static struct xt_match mac6_match = { @@ -57,27 +58,28 @@ static struct xt_match mac6_match = { .matchsize = sizeof(struct xt_mac_info), .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD), + .family = AF_INET6, .me = THIS_MODULE, }; static int __init init(void) { int ret; - ret = xt_register_match(AF_INET, &mac_match); + ret = xt_register_match(&mac_match); if (ret) return ret; - ret = xt_register_match(AF_INET6, &mac6_match); + ret = xt_register_match(&mac6_match); if (ret) - xt_unregister_match(AF_INET, &mac_match); + xt_unregister_match(&mac_match); return ret; } static void __exit fini(void) { - xt_unregister_match(AF_INET, &mac_match); - xt_unregister_match(AF_INET6, &mac6_match); + xt_unregister_match(&mac_match); + xt_unregister_match(&mac6_match); } module_init(init); diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c index c1a8f0f587f0..ce0badfeef9a 100644 --- a/net/netfilter/xt_mark.c +++ b/net/netfilter/xt_mark.c @@ -56,6 +56,7 @@ static struct xt_match mark_match = { .match = match, .matchsize = sizeof(struct xt_mark_info), .checkentry = checkentry, + .family = AF_INET, .me = THIS_MODULE, }; @@ -64,27 +65,28 @@ static struct xt_match mark6_match = { .match = match, .matchsize = sizeof(struct xt_mark_info), .checkentry = checkentry, + .family = AF_INET6, .me = THIS_MODULE, }; static int __init init(void) { int ret; - ret = xt_register_match(AF_INET, &mark_match); + ret = xt_register_match(&mark_match); if (ret) return ret; - ret = xt_register_match(AF_INET6, &mark6_match); + ret = xt_register_match(&mark6_match); if (ret) - xt_unregister_match(AF_INET, &mark_match); + xt_unregister_match(&mark_match); return ret; } static void __exit fini(void) { - xt_unregister_match(AF_INET, &mark_match); - xt_unregister_match(AF_INET6, &mark6_match); + xt_unregister_match(&mark_match); + xt_unregister_match(&mark6_match); } module_init(init); diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c index f788e8e76254..089f4f7e8636 100644 --- a/net/netfilter/xt_physdev.c +++ b/net/netfilter/xt_physdev.c @@ -121,6 +121,7 @@ static struct xt_match physdev_match = { .match = match, .matchsize = sizeof(struct xt_physdev_info), .checkentry = checkentry, + .family = AF_INET, .me = THIS_MODULE, }; @@ -129,6 +130,7 @@ static struct xt_match physdev6_match = { .match = match, .matchsize = sizeof(struct xt_physdev_info), .checkentry = checkentry, + .family = AF_INET6, .me = THIS_MODULE, }; @@ -136,21 +138,21 @@ static int __init init(void) { int ret; - ret = xt_register_match(AF_INET, &physdev_match); + ret = xt_register_match(&physdev_match); if (ret < 0) return ret; - ret = xt_register_match(AF_INET6, &physdev6_match); + ret = xt_register_match(&physdev6_match); if (ret < 0) - xt_unregister_match(AF_INET, &physdev_match); + xt_unregister_match(&physdev_match); return ret; } static void __exit fini(void) { - xt_unregister_match(AF_INET, &physdev_match); - xt_unregister_match(AF_INET6, &physdev6_match); + xt_unregister_match(&physdev_match); + xt_unregister_match(&physdev6_match); } module_init(init); diff --git a/net/netfilter/xt_pkttype.c b/net/netfilter/xt_pkttype.c index f38638dfd139..8b8bca988ac6 100644 --- a/net/netfilter/xt_pkttype.c +++ b/net/netfilter/xt_pkttype.c @@ -37,6 +37,7 @@ static struct xt_match pkttype_match = { .name = "pkttype", .match = match, .matchsize = sizeof(struct xt_pkttype_info), + .family = AF_INET, .me = THIS_MODULE, }; @@ -44,27 +45,28 @@ static struct xt_match pkttype6_match = { .name = "pkttype", .match = match, .matchsize = sizeof(struct xt_pkttype_info), + .family = AF_INET6, .me = THIS_MODULE, }; static int __init init(void) { int ret; - ret = xt_register_match(AF_INET, &pkttype_match); + ret = xt_register_match(&pkttype_match); if (ret) return ret; - ret = xt_register_match(AF_INET6, &pkttype6_match); + ret = xt_register_match(&pkttype6_match); if (ret) - xt_unregister_match(AF_INET, &pkttype_match); + xt_unregister_match(&pkttype_match); return ret; } static void __exit fini(void) { - xt_unregister_match(AF_INET, &pkttype_match); - xt_unregister_match(AF_INET6, &pkttype6_match); + xt_unregister_match(&pkttype_match); + xt_unregister_match(&pkttype6_match); } module_init(init); diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c index 1ec22082f04d..d57a611ae0d3 100644 --- a/net/netfilter/xt_policy.c +++ b/net/netfilter/xt_policy.c @@ -172,6 +172,7 @@ static struct xt_match policy_match = { .match = match, .matchsize = sizeof(struct xt_policy_info), .checkentry = checkentry, + .family = AF_INET, .me = THIS_MODULE, }; @@ -181,6 +182,7 @@ static struct xt_match policy6_match = { .match = match, .matchsize = sizeof(struct xt_policy_info), .checkentry = checkentry, + .family = AF_INET6, .me = THIS_MODULE, }; @@ -188,19 +190,19 @@ static int __init init(void) { int ret; - ret = xt_register_match(AF_INET, &policy_match); + ret = xt_register_match(&policy_match); if (ret) return ret; - ret = xt_register_match(AF_INET6, &policy6_match); + ret = xt_register_match(&policy6_match); if (ret) - xt_unregister_match(AF_INET, &policy_match); + xt_unregister_match(&policy_match); return ret; } static void __exit fini(void) { - xt_unregister_match(AF_INET6, &policy6_match); - xt_unregister_match(AF_INET, &policy_match); + xt_unregister_match(&policy6_match); + xt_unregister_match(&policy_match); } module_init(init); diff --git a/net/netfilter/xt_realm.c b/net/netfilter/xt_realm.c index 57815a07db67..5e31a4a835bf 100644 --- a/net/netfilter/xt_realm.c +++ b/net/netfilter/xt_realm.c @@ -45,17 +45,18 @@ static struct xt_match realm_match = { .matchsize = sizeof(struct xt_realm_info), .hooks = (1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN), + .family = AF_INET, .me = THIS_MODULE }; static int __init init(void) { - return xt_register_match(AF_INET, &realm_match); + return xt_register_match(&realm_match); } static void __exit fini(void) { - xt_unregister_match(AF_INET, &realm_match); + xt_unregister_match(&realm_match); } module_init(init); diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c index f5d698ba03ca..c6eb24a2fe13 100644 --- a/net/netfilter/xt_sctp.c +++ b/net/netfilter/xt_sctp.c @@ -186,6 +186,7 @@ static struct xt_match sctp_match = { .matchsize = sizeof(struct xt_sctp_info), .proto = IPPROTO_SCTP, .checkentry = checkentry, + .family = AF_INET, .me = THIS_MODULE }; @@ -195,27 +196,28 @@ static struct xt_match sctp6_match = { .matchsize = sizeof(struct xt_sctp_info), .proto = IPPROTO_SCTP, .checkentry = checkentry, + .family = AF_INET6, .me = THIS_MODULE }; static int __init init(void) { int ret; - ret = xt_register_match(AF_INET, &sctp_match); + ret = xt_register_match(&sctp_match); if (ret) return ret; - ret = xt_register_match(AF_INET6, &sctp6_match); + ret = xt_register_match(&sctp6_match); if (ret) - xt_unregister_match(AF_INET, &sctp_match); + xt_unregister_match(&sctp_match); return ret; } static void __exit fini(void) { - xt_unregister_match(AF_INET6, &sctp6_match); - xt_unregister_match(AF_INET, &sctp_match); + xt_unregister_match(&sctp6_match); + xt_unregister_match(&sctp_match); } module_init(init); diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c index b8ec00cd51fc..7cd557c932ba 100644 --- a/net/netfilter/xt_state.c +++ b/net/netfilter/xt_state.c @@ -48,6 +48,7 @@ static struct xt_match state_match = { .name = "state", .match = match, .matchsize = sizeof(struct xt_state_info), + .family = AF_INET, .me = THIS_MODULE, }; @@ -55,6 +56,7 @@ static struct xt_match state6_match = { .name = "state", .match = match, .matchsize = sizeof(struct xt_state_info), + .family = AF_INET6, .me = THIS_MODULE, }; @@ -64,21 +66,21 @@ static int __init init(void) need_conntrack(); - ret = xt_register_match(AF_INET, &state_match); + ret = xt_register_match(&state_match); if (ret < 0) return ret; - ret = xt_register_match(AF_INET6, &state6_match); + ret = xt_register_match(&state6_match); if (ret < 0) - xt_unregister_match(AF_INET,&state_match); + xt_unregister_match(&state_match); return ret; } static void __exit fini(void) { - xt_unregister_match(AF_INET, &state_match); - xt_unregister_match(AF_INET6, &state6_match); + xt_unregister_match(&state_match); + xt_unregister_match(&state6_match); } module_init(init); diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c index fccbad6a7f40..703d80fccacf 100644 --- a/net/netfilter/xt_string.c +++ b/net/netfilter/xt_string.c @@ -78,6 +78,7 @@ static struct xt_match string_match = { .matchsize = sizeof(struct xt_string_info), .checkentry = checkentry, .destroy = destroy, + .family = AF_INET, .me = THIS_MODULE }; static struct xt_match string6_match = { @@ -86,6 +87,7 @@ static struct xt_match string6_match = { .matchsize = sizeof(struct xt_string_info), .checkentry = checkentry, .destroy = destroy, + .family = AF_INET6, .me = THIS_MODULE }; @@ -93,20 +95,20 @@ static int __init init(void) { int ret; - ret = xt_register_match(AF_INET, &string_match); + ret = xt_register_match(&string_match); if (ret) return ret; - ret = xt_register_match(AF_INET6, &string6_match); + ret = xt_register_match(&string6_match); if (ret) - xt_unregister_match(AF_INET, &string_match); + xt_unregister_match(&string_match); return ret; } static void __exit fini(void) { - xt_unregister_match(AF_INET, &string_match); - xt_unregister_match(AF_INET6, &string6_match); + xt_unregister_match(&string_match); + xt_unregister_match(&string6_match); } module_init(init); diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c index 4925fc98f4ae..70a8858ae3f1 100644 --- a/net/netfilter/xt_tcpmss.c +++ b/net/netfilter/xt_tcpmss.c @@ -98,6 +98,7 @@ static struct xt_match tcpmss_match = { .match = match, .matchsize = sizeof(struct xt_tcpmss_match_info), .proto = IPPROTO_TCP, + .family = AF_INET, .me = THIS_MODULE, }; @@ -106,6 +107,7 @@ static struct xt_match tcpmss6_match = { .match = match, .matchsize = sizeof(struct xt_tcpmss_match_info), .proto = IPPROTO_TCP, + .family = AF_INET6, .me = THIS_MODULE, }; @@ -113,21 +115,21 @@ static struct xt_match tcpmss6_match = { static int __init init(void) { int ret; - ret = xt_register_match(AF_INET, &tcpmss_match); + ret = xt_register_match(&tcpmss_match); if (ret) return ret; - ret = xt_register_match(AF_INET6, &tcpmss6_match); + ret = xt_register_match(&tcpmss6_match); if (ret) - xt_unregister_match(AF_INET, &tcpmss_match); + xt_unregister_match(&tcpmss_match); return ret; } static void __exit fini(void) { - xt_unregister_match(AF_INET6, &tcpmss6_match); - xt_unregister_match(AF_INET, &tcpmss_match); + xt_unregister_match(&tcpmss6_match); + xt_unregister_match(&tcpmss_match); } module_init(init); diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c index b5cd0dd4e41f..14a990eb666a 100644 --- a/net/netfilter/xt_tcpudp.c +++ b/net/netfilter/xt_tcpudp.c @@ -204,6 +204,7 @@ static struct xt_match tcp_matchstruct = { .match = tcp_match, .matchsize = sizeof(struct xt_tcp), .proto = IPPROTO_TCP, + .family = AF_INET, .checkentry = tcp_checkentry, .me = THIS_MODULE, }; @@ -213,6 +214,7 @@ static struct xt_match tcp6_matchstruct = { .match = tcp_match, .matchsize = sizeof(struct xt_tcp), .proto = IPPROTO_TCP, + .family = AF_INET6, .checkentry = tcp_checkentry, .me = THIS_MODULE, }; @@ -222,6 +224,7 @@ static struct xt_match udp_matchstruct = { .match = udp_match, .matchsize = sizeof(struct xt_udp), .proto = IPPROTO_UDP, + .family = AF_INET, .checkentry = udp_checkentry, .me = THIS_MODULE, }; @@ -230,6 +233,7 @@ static struct xt_match udp6_matchstruct = { .match = udp_match, .matchsize = sizeof(struct xt_udp), .proto = IPPROTO_UDP, + .family = AF_INET6, .checkentry = udp_checkentry, .me = THIS_MODULE, }; @@ -237,39 +241,39 @@ static struct xt_match udp6_matchstruct = { static int __init init(void) { int ret; - ret = xt_register_match(AF_INET, &tcp_matchstruct); + ret = xt_register_match(&tcp_matchstruct); if (ret) return ret; - ret = xt_register_match(AF_INET6, &tcp6_matchstruct); + ret = xt_register_match(&tcp6_matchstruct); if (ret) goto out_unreg_tcp; - ret = xt_register_match(AF_INET, &udp_matchstruct); + ret = xt_register_match(&udp_matchstruct); if (ret) goto out_unreg_tcp6; - ret = xt_register_match(AF_INET6, &udp6_matchstruct); + ret = xt_register_match(&udp6_matchstruct); if (ret) goto out_unreg_udp; return ret; out_unreg_udp: - xt_unregister_match(AF_INET, &tcp_matchstruct); + xt_unregister_match(&tcp_matchstruct); out_unreg_tcp6: - xt_unregister_match(AF_INET6, &tcp6_matchstruct); + xt_unregister_match(&tcp6_matchstruct); out_unreg_tcp: - xt_unregister_match(AF_INET, &tcp_matchstruct); + xt_unregister_match(&tcp_matchstruct); return ret; } static void __exit fini(void) { - xt_unregister_match(AF_INET6, &udp6_matchstruct); - xt_unregister_match(AF_INET, &udp_matchstruct); - xt_unregister_match(AF_INET6, &tcp6_matchstruct); - xt_unregister_match(AF_INET, &tcp_matchstruct); + xt_unregister_match(&udp6_matchstruct); + xt_unregister_match(&udp_matchstruct); + xt_unregister_match(&tcp6_matchstruct); + xt_unregister_match(&tcp_matchstruct); } module_init(init); -- cgit v1.2.3 From b9f78f9fca626875af8adc0f7366a38b8e625a0e Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 22 Mar 2006 13:56:08 -0800 Subject: [NETFILTER]: nf_conntrack: support for layer 3 protocol load on demand x_tables matches and targets that require nf_conntrack_ipv[4|6] to work don't have enough information to load on demand these modules. This patch introduces the following changes to solve this issue: o nf_ct_l3proto_try_module_get: try to load the layer 3 connection tracker module and increases the refcount. o nf_ct_l3proto_module put: drop the refcount of the module. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/netfilter/nf_conntrack.h | 4 ++++ net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 1 + net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 1 + net/netfilter/nf_conntrack_core.c | 31 ++++++++++++++++++++++++++ net/netfilter/nf_conntrack_standalone.c | 2 ++ net/netfilter/xt_connmark.c | 17 ++++++++++++++ net/netfilter/xt_conntrack.c | 28 +++++++++++++++++++++++ net/netfilter/xt_helper.c | 17 ++++++++++++++ net/netfilter/xt_state.c | 29 ++++++++++++++++++++++++ 9 files changed, 130 insertions(+) (limited to 'include') diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 2743c156caa0..b6f0905a4ee2 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -195,6 +195,10 @@ static inline void nf_ct_put(struct nf_conn *ct) nf_conntrack_put(&ct->ct_general); } +/* Protocol module loading */ +extern int nf_ct_l3proto_try_module_get(unsigned short l3proto); +extern void nf_ct_l3proto_module_put(unsigned short l3proto); + extern struct nf_conntrack_tuple_hash * __nf_conntrack_find(const struct nf_conntrack_tuple *tuple, const struct nf_conn *ignored_conntrack); diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index cb9c661f3f33..c8abc9d859b9 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -568,6 +568,7 @@ static int init_or_cleanup(int init) return ret; } +MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET)); MODULE_LICENSE("GPL"); static int __init init(void) diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index ac35f9526368..c16f62934bd9 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -584,6 +584,7 @@ static int init_or_cleanup(int init) return ret; } +MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6)); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI "); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index c28840656451..0ae281d9bfc3 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -23,6 +23,8 @@ * 26 Jan 2006: Harald Welte * - restructure nf_conn (introduce nf_conn_help) * - redesign 'features' how they were originally intended + * 26 Feb 2006: Pablo Neira Ayuso + * - add support for L3 protocol module load on demand. * * Derived from net/ipv4/netfilter/ip_conntrack_core.c */ @@ -241,6 +243,35 @@ void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p) module_put(p->me); } +int +nf_ct_l3proto_try_module_get(unsigned short l3proto) +{ + int ret; + struct nf_conntrack_l3proto *p; + +retry: p = nf_ct_l3proto_find_get(l3proto); + if (p == &nf_conntrack_generic_l3proto) { + ret = request_module("nf_conntrack-%d", l3proto); + if (!ret) + goto retry; + + return -EPROTOTYPE; + } + + return 0; +} + +void nf_ct_l3proto_module_put(unsigned short l3proto) +{ + struct nf_conntrack_l3proto *p; + + preempt_disable(); + p = __nf_ct_l3proto_find(l3proto); + preempt_enable(); + + module_put(p->me); +} + static int nf_conntrack_hash_rnd_initted; static unsigned int nf_conntrack_hash_rnd; diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 290d5a0c559b..75577e175b35 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -834,6 +834,8 @@ EXPORT_SYMBOL_GPL(__nf_ct_event_cache_init); EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache); EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events); #endif +EXPORT_SYMBOL(nf_ct_l3proto_try_module_get); +EXPORT_SYMBOL(nf_ct_l3proto_module_put); EXPORT_SYMBOL(nf_conntrack_l3proto_register); EXPORT_SYMBOL(nf_conntrack_l3proto_unregister); EXPORT_SYMBOL(nf_conntrack_protocol_register); diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c index e810600345e3..7b16f1ee16b4 100644 --- a/net/netfilter/xt_connmark.c +++ b/net/netfilter/xt_connmark.c @@ -64,14 +64,30 @@ checkentry(const char *tablename, printk(KERN_WARNING "connmark: only support 32bit mark\n"); return 0; } +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + if (nf_ct_l3proto_try_module_get(match->family) < 0) { + printk(KERN_WARNING "can't load nf_conntrack support for " + "proto=%d\n", match->family); + return 0; + } +#endif return 1; } +static void +destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize) +{ +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + nf_ct_l3proto_module_put(match->family); +#endif +} + static struct xt_match connmark_match = { .name = "connmark", .match = match, .matchsize = sizeof(struct xt_connmark_info), .checkentry = checkentry, + .destroy = destroy, .family = AF_INET, .me = THIS_MODULE }; @@ -81,6 +97,7 @@ static struct xt_match connmark6_match = { .match = match, .matchsize = sizeof(struct xt_connmark_info), .checkentry = checkentry, + .destroy = destroy, .family = AF_INET6, .me = THIS_MODULE }; diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c index 7d20caa0d605..65a84809fd30 100644 --- a/net/netfilter/xt_conntrack.c +++ b/net/netfilter/xt_conntrack.c @@ -203,9 +203,37 @@ match(const struct sk_buff *skb, #endif /* CONFIG_NF_IP_CONNTRACK */ +static int +checkentry(const char *tablename, + const void *ip, + const struct xt_match *match, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + if (nf_ct_l3proto_try_module_get(match->family) < 0) { + printk(KERN_WARNING "can't load nf_conntrack support for " + "proto=%d\n", match->family); + return 0; + } +#endif + return 1; +} + +static void +destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize) +{ +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + nf_ct_l3proto_module_put(match->family); +#endif +} + static struct xt_match conntrack_match = { .name = "conntrack", .match = match, + .checkentry = checkentry, + .destroy = destroy, .matchsize = sizeof(struct xt_conntrack_info), .family = AF_INET, .me = THIS_MODULE, diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c index 7d2d68b9155f..101f0005e987 100644 --- a/net/netfilter/xt_helper.c +++ b/net/netfilter/xt_helper.c @@ -144,15 +144,31 @@ static int check(const char *tablename, { struct xt_helper_info *info = matchinfo; +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + if (nf_ct_l3proto_try_module_get(match->family) < 0) { + printk(KERN_WARNING "can't load nf_conntrack support for " + "proto=%d\n", match->family); + return 0; + } +#endif info->name[29] = '\0'; return 1; } +static void +destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize) +{ +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + nf_ct_l3proto_module_put(match->family); +#endif +} + static struct xt_match helper_match = { .name = "helper", .match = match, .matchsize = sizeof(struct xt_helper_info), .checkentry = check, + .destroy = destroy, .family = AF_INET, .me = THIS_MODULE, }; @@ -161,6 +177,7 @@ static struct xt_match helper6_match = { .match = match, .matchsize = sizeof(struct xt_helper_info), .checkentry = check, + .destroy = destroy, .family = AF_INET6, .me = THIS_MODULE, }; diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c index 7cd557c932ba..e6c0be9d94d2 100644 --- a/net/netfilter/xt_state.c +++ b/net/netfilter/xt_state.c @@ -44,9 +44,36 @@ match(const struct sk_buff *skb, return (sinfo->statemask & statebit); } +static int check(const char *tablename, + const void *inf, + const struct xt_match *match, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + if (nf_ct_l3proto_try_module_get(match->family) < 0) { + printk(KERN_WARNING "can't load nf_conntrack support for " + "proto=%d\n", match->family); + return 0; + } +#endif + return 1; +} + +static void +destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize) +{ +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + nf_ct_l3proto_module_put(match->family); +#endif +} + static struct xt_match state_match = { .name = "state", .match = match, + .checkentry = check, + .destroy = destroy, .matchsize = sizeof(struct xt_state_info), .family = AF_INET, .me = THIS_MODULE, @@ -55,6 +82,8 @@ static struct xt_match state_match = { static struct xt_match state6_match = { .name = "state", .match = match, + .checkentry = check, + .destroy = destroy, .matchsize = sizeof(struct xt_state_info), .family = AF_INET6, .me = THIS_MODULE, -- cgit v1.2.3 From 1e30a014e311e627b91489ff5ec1b54496d308af Mon Sep 17 00:00:00 2001 From: Dmitry Mishin Date: Wed, 22 Mar 2006 13:56:56 -0800 Subject: [NETFILTER]: futher {ip,ip6,arp}_tables unification This patch moves {ip,ip6,arp}t_entry_{match,target} definitions to x_tables.h. This move simplifies code and future compatibility fixes. Signed-off-by: Dmitry Mishin Acked-off-by: Kirill Korotaev Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter/x_tables.h | 56 +++++++++++++++++++++++++++++ include/linux/netfilter_arp/arp_tables.h | 31 ++--------------- include/linux/netfilter_ipv4/ip_tables.h | 58 ++----------------------------- include/linux/netfilter_ipv6/ip6_tables.h | 57 ++---------------------------- include/net/tc_act/tc_ipt.h | 4 +-- 5 files changed, 66 insertions(+), 140 deletions(-) (limited to 'include') diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index bf71efb63007..1350e47b0234 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -4,6 +4,62 @@ #define XT_FUNCTION_MAXNAMELEN 30 #define XT_TABLE_MAXNAMELEN 32 +struct xt_entry_match +{ + union { + struct { + u_int16_t match_size; + + /* Used by userspace */ + char name[XT_FUNCTION_MAXNAMELEN-1]; + + u_int8_t revision; + } user; + struct { + u_int16_t match_size; + + /* Used inside the kernel */ + struct xt_match *match; + } kernel; + + /* Total length */ + u_int16_t match_size; + } u; + + unsigned char data[0]; +}; + +struct xt_entry_target +{ + union { + struct { + u_int16_t target_size; + + /* Used by userspace */ + char name[XT_FUNCTION_MAXNAMELEN-1]; + + u_int8_t revision; + } user; + struct { + u_int16_t target_size; + + /* Used inside the kernel */ + struct xt_target *target; + } kernel; + + /* Total length */ + u_int16_t target_size; + } u; + + unsigned char data[0]; +}; + +struct xt_standard_target +{ + struct xt_entry_target target; + int verdict; +}; + /* The argument to IPT_SO_GET_REVISION_*. Returns highest revision * kernel supports, if >= revision. */ struct xt_get_revision diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h index a27be05f67f0..62cc27daca4e 100644 --- a/include/linux/netfilter_arp/arp_tables.h +++ b/include/linux/netfilter_arp/arp_tables.h @@ -65,35 +65,8 @@ struct arpt_arp { u_int16_t invflags; }; -struct arpt_entry_target -{ - union { - struct { - u_int16_t target_size; - - /* Used by userspace */ - char name[ARPT_FUNCTION_MAXNAMELEN-1]; - u_int8_t revision; - } user; - struct { - u_int16_t target_size; - - /* Used inside the kernel */ - struct arpt_target *target; - } kernel; - - /* Total length */ - u_int16_t target_size; - } u; - - unsigned char data[0]; -}; - -struct arpt_standard_target -{ - struct arpt_entry_target target; - int verdict; -}; +#define arpt_entry_target xt_entry_target +#define arpt_standard_target xt_standard_target /* Values for "flag" field in struct arpt_ip (general arp structure). * No flags defined yet. diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index ee262b5344e1..d5b8c0d6a12b 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h @@ -52,61 +52,9 @@ struct ipt_ip { u_int8_t invflags; }; -struct ipt_entry_match -{ - union { - struct { - u_int16_t match_size; - - /* Used by userspace */ - char name[IPT_FUNCTION_MAXNAMELEN-1]; - - u_int8_t revision; - } user; - struct { - u_int16_t match_size; - - /* Used inside the kernel */ - struct ipt_match *match; - } kernel; - - /* Total length */ - u_int16_t match_size; - } u; - - unsigned char data[0]; -}; - -struct ipt_entry_target -{ - union { - struct { - u_int16_t target_size; - - /* Used by userspace */ - char name[IPT_FUNCTION_MAXNAMELEN-1]; - - u_int8_t revision; - } user; - struct { - u_int16_t target_size; - - /* Used inside the kernel */ - struct ipt_target *target; - } kernel; - - /* Total length */ - u_int16_t target_size; - } u; - - unsigned char data[0]; -}; - -struct ipt_standard_target -{ - struct ipt_entry_target target; - int verdict; -}; +#define ipt_entry_match xt_entry_match +#define ipt_entry_target xt_entry_target +#define ipt_standard_target xt_standard_target #define ipt_counters xt_counters diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index 7107f942eb05..d0d5d1ee4be3 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h @@ -56,60 +56,9 @@ struct ip6t_ip6 { u_int8_t invflags; }; -/* FIXME: If alignment in kernel different from userspace? --RR */ -struct ip6t_entry_match -{ - union { - struct { - u_int16_t match_size; - - /* Used by userspace */ - char name[IP6T_FUNCTION_MAXNAMELEN-1]; - u_int8_t revision; - } user; - struct { - u_int16_t match_size; - - /* Used inside the kernel */ - struct ip6t_match *match; - } kernel; - - /* Total length */ - u_int16_t match_size; - } u; - - unsigned char data[0]; -}; - -struct ip6t_entry_target -{ - union { - struct { - u_int16_t target_size; - - /* Used by userspace */ - char name[IP6T_FUNCTION_MAXNAMELEN-1]; - u_int8_t revision; - } user; - struct { - u_int16_t target_size; - - /* Used inside the kernel */ - struct ip6t_target *target; - } kernel; - - /* Total length */ - u_int16_t target_size; - } u; - - unsigned char data[0]; -}; - -struct ip6t_standard_target -{ - struct ip6t_entry_target target; - int verdict; -}; +#define ip6t_entry_match xt_entry_match +#define ip6t_entry_target xt_entry_target +#define ip6t_standard_target xt_standard_target #define ip6t_counters xt_counters diff --git a/include/net/tc_act/tc_ipt.h b/include/net/tc_act/tc_ipt.h index 02eccebd55ae..cb37ad08427f 100644 --- a/include/net/tc_act/tc_ipt.h +++ b/include/net/tc_act/tc_ipt.h @@ -3,14 +3,14 @@ #include -struct ipt_entry_target; +struct xt_entry_target; struct tcf_ipt { tca_gen(ipt); u32 hook; char *tname; - struct ipt_entry_target *t; + struct xt_entry_target *t; }; #endif -- cgit v1.2.3 From 370121e5190a86a2d8a717ecd6f33028c7dc6fd4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 4 Jan 2006 16:32:16 +0100 Subject: [PATCH] wireless: Add softmac layer to the kernel Signed-off-by: John W. Linville --- include/net/ieee80211softmac.h | 269 ++++++++++++++ include/net/ieee80211softmac_wx.h | 66 ++++ net/ieee80211/Kconfig | 1 + net/ieee80211/softmac/Kconfig | 9 + net/ieee80211/softmac/Makefile | 9 + net/ieee80211/softmac/ieee80211softmac_assoc.c | 356 ++++++++++++++++++ net/ieee80211/softmac/ieee80211softmac_auth.c | 348 +++++++++++++++++ net/ieee80211/softmac/ieee80211softmac_event.c | 135 +++++++ net/ieee80211/softmac/ieee80211softmac_io.c | 474 ++++++++++++++++++++++++ net/ieee80211/softmac/ieee80211softmac_module.c | 441 ++++++++++++++++++++++ net/ieee80211/softmac/ieee80211softmac_priv.h | 206 ++++++++++ net/ieee80211/softmac/ieee80211softmac_scan.c | 216 +++++++++++ net/ieee80211/softmac/ieee80211softmac_wx.c | 390 +++++++++++++++++++ 13 files changed, 2920 insertions(+) create mode 100644 include/net/ieee80211softmac.h create mode 100644 include/net/ieee80211softmac_wx.h create mode 100644 net/ieee80211/softmac/Kconfig create mode 100644 net/ieee80211/softmac/Makefile create mode 100644 net/ieee80211/softmac/ieee80211softmac_assoc.c create mode 100644 net/ieee80211/softmac/ieee80211softmac_auth.c create mode 100644 net/ieee80211/softmac/ieee80211softmac_event.c create mode 100644 net/ieee80211/softmac/ieee80211softmac_io.c create mode 100644 net/ieee80211/softmac/ieee80211softmac_module.c create mode 100644 net/ieee80211/softmac/ieee80211softmac_priv.h create mode 100644 net/ieee80211/softmac/ieee80211softmac_scan.c create mode 100644 net/ieee80211/softmac/ieee80211softmac_wx.c (limited to 'include') diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h new file mode 100644 index 000000000000..0b5f2df29f02 --- /dev/null +++ b/include/net/ieee80211softmac.h @@ -0,0 +1,269 @@ +#ifndef IEEE80211SOFTMAC_H_ +#define IEEE80211SOFTMAC_H_ + +#include +#include +#include +#include +#include + +/* Once the API is considered more or less stable, + * this should be incremented on API incompatible changes. + */ +#define IEEE80211SOFTMAC_API 0 + +#define IEEE80211SOFTMAC_MAX_RATES_LEN 8 +#define IEEE80211SOFTMAC_MAX_EX_RATES_LEN 255 + +struct ieee80211softmac_ratesinfo { + u8 count; + u8 rates[IEEE80211SOFTMAC_MAX_RATES_LEN + IEEE80211SOFTMAC_MAX_EX_RATES_LEN]; +}; + +/* internal structures */ +struct ieee80211softmac_network; +struct ieee80211softmac_scaninfo; + +struct ieee80211softmac_essid { + u8 len; + char data[IW_ESSID_MAX_SIZE+1]; +}; + +struct ieee80211softmac_wpa { + char *IE; + int IElen; + int IEbuflen; +}; + +/* + * Information about association + * + * Do we need a lock for this? + * We only ever use this structure inlined + * into our global struct. I've used its lock, + * but maybe we need a local one here? + */ +struct ieee80211softmac_assoc_info { + /* + * This is the requested ESSID. It is written + * only by the WX handlers. + * + */ + struct ieee80211softmac_essid req_essid; + /* + * the ESSID of the network we're currently + * associated (or trying) to. This is + * updated to the network's actual ESSID + * even if the requested ESSID was 'ANY' + */ + struct ieee80211softmac_essid associate_essid; + + /* BSSID we're trying to associate to */ + char bssid[ETH_ALEN]; + + /* some flags. + * static_essid is valid if the essid is constant, + * this is for use by the wx handlers only. + * + * associating is true, if the network has been + * auth'ed on and we are in the process of associating. + * + * bssvalid is true if we found a matching network + * and saved it's BSSID into the bssid above. + */ + u8 static_essid:1, + associating:1, + bssvalid:1; + + /* Scan retries remaining */ + int scan_retry; + + struct work_struct work; + struct work_struct timeout; +}; + +enum { + IEEE80211SOFTMAC_AUTH_OPEN_REQUEST = 1, + IEEE80211SOFTMAC_AUTH_OPEN_RESPONSE = 2, +}; + +enum { + IEEE80211SOFTMAC_AUTH_SHARED_REQUEST = 1, + IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE = 2, + IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE = 3, + IEEE80211SOFTMAC_AUTH_SHARED_PASS = 4, +}; + +/* We should make these tunable + * AUTH_TIMEOUT seems really long, but that's what it is in BSD */ +#define IEEE80211SOFTMAC_AUTH_TIMEOUT (12 * HZ) +#define IEEE80211SOFTMAC_AUTH_RETRY_LIMIT 5 +#define IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT 3 + +struct ieee80211softmac_txrates { + /* The Bit-Rate to be used for multicast frames. */ + u8 mcast_rate; + /* The Bit-Rate to be used for multicast fallback + * (If the device supports fallback and hardware-retry) + */ + u8 mcast_fallback; + /* The Bit-Rate to be used for any other (normal) data packet. */ + u8 default_rate; + /* The Bit-Rate to be used for default fallback + * (If the device supports fallback and hardware-retry) + */ + u8 default_fallback; +}; + +/* Bits for txrates_change callback. */ +#define IEEE80211SOFTMAC_TXRATECHG_DEFAULT (1 << 0) /* default_rate */ +#define IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK (1 << 1) /* default_fallback */ +#define IEEE80211SOFTMAC_TXRATECHG_MCAST (1 << 2) /* mcast_rate */ +#define IEEE80211SOFTMAC_TXRATECHG_MCAST_FBACK (1 << 3) /* mcast_fallback */ + +struct ieee80211softmac_device { + /* 802.11 structure for data stuff */ + struct ieee80211_device *ieee; + struct net_device *dev; + + /* only valid if associated, then holds the Association ID */ + u16 association_id; + + /* the following methods are callbacks that the driver + * using this framework has to assign + */ + + /* always assign these */ + void (*set_bssid_filter)(struct net_device *dev, const u8 *bssid); + void (*set_channel)(struct net_device *dev, u8 channel); + + /* assign if you need it, informational only */ + void (*link_change)(struct net_device *dev); + + /* If the hardware can do scanning, assign _all_ three of these callbacks. + * When the scan finishes, call ieee80211softmac_scan_finished(). + */ + + /* when called, start_scan is guaranteed to not be called again + * until you call ieee80211softmac_scan_finished. + * Return 0 if scanning could start, error otherwise. + * SOFTMAC AUTHORS: don't call this, use ieee80211softmac_start_scan */ + int (*start_scan)(struct net_device *dev); + /* this should block until after ieee80211softmac_scan_finished was called + * SOFTMAC AUTHORS: don't call this, use ieee80211softmac_wait_for_scan */ + void (*wait_for_scan)(struct net_device *dev); + /* stop_scan aborts a scan, but is asynchronous. + * if you want to wait for it too, use wait_for_scan + * SOFTMAC AUTHORS: don't call this, use ieee80211softmac_stop_scan */ + void (*stop_scan)(struct net_device *dev); + + /* we'll need something about beacons here too, for AP or ad-hoc modes */ + + /* Transmission rates to be used by the driver. + * The SoftMAC figures out the best possible rates. + * The driver just needs to read them. + */ + struct ieee80211softmac_txrates txrates; + /* If the driver needs to do stuff on TX rate changes, assign this callback. */ + void (*txrates_change)(struct net_device *dev, + u32 changes, /* see IEEE80211SOFTMAC_TXRATECHG flags */ + const struct ieee80211softmac_txrates *rates_before_change); + + /* private stuff follows */ + /* this lock protects this structure */ + spinlock_t lock; + + /* couple of flags */ + u8 scanning:1, /* protects scanning from being done multiple times at once */ + associated:1; + + /* workquere for scannning, ... */ + struct workqueue_struct *workqueue; + + struct ieee80211softmac_scaninfo *scaninfo; + struct ieee80211softmac_assoc_info associnfo; + + struct list_head auth_queue; + struct list_head events; + + struct ieee80211softmac_ratesinfo ratesinfo; + int txrate_badness; + + /* WPA stuff */ + struct ieee80211softmac_wpa wpa; + + /* we need to keep a list of network structs we copied */ + struct list_head network_list; + + /* This must be the last item so that it points to the data + * allocated beyond this structure by alloc_ieee80211 */ + u8 priv[0]; +}; + +extern void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm); + +static inline void * ieee80211softmac_priv(struct net_device *dev) +{ + return ((struct ieee80211softmac_device *)ieee80211_priv(dev))->priv; +} + +extern struct net_device * alloc_ieee80211softmac(int sizeof_priv); +extern void free_ieee80211softmac(struct net_device *dev); + +/* Call this function if you detect a lost TX fragment. + * (If the device indicates failure of ACK RX, for example.) + * It is wise to call this function if you are able to detect lost packets, + * because it contributes to the TX Rates auto adjustment. + */ +extern void ieee80211softmac_fragment_lost(struct net_device *dev, + u16 wireless_sequence_number); +/* Call this function before _start to tell the softmac what rates + * the hw supports. The rates parameter is copied, so you can + * free it right after calling this function. + * Note that the rates need to be sorted. */ +extern void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates); + +/* Start the SoftMAC. Call this after you initialized the device + * and it is ready to run. + */ +extern void ieee80211softmac_start(struct net_device *dev); +/* Stop the SoftMAC. Call this before you shutdown the device. */ +extern void ieee80211softmac_stop(struct net_device *dev); + +/* + * Event system + */ + +/* valid event types */ +#define IEEE80211SOFTMAC_EVENT_ANY -1 /*private use only*/ +#define IEEE80211SOFTMAC_EVENT_SCAN_FINISHED 0 +#define IEEE80211SOFTMAC_EVENT_ASSOCIATED 1 +#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED 2 +#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT 3 +#define IEEE80211SOFTMAC_EVENT_AUTHENTICATED 4 +#define IEEE80211SOFTMAC_EVENT_AUTH_FAILED 5 +#define IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT 6 +#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND 7 +/* keep this updated! */ +#define IEEE80211SOFTMAC_EVENT_LAST 7 +/* + * If you want to be notified of certain events, you can call + * ieee80211softmac_notify[_atomic] with + * - event set to one of the constants below + * - fun set to a function pointer of the appropriate type + * - context set to the context data you want passed + * The return value is 0, or an error. + */ +typedef void (*notify_function_ptr)(struct net_device *dev, void *context); + +#define ieee80211softmac_notify(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_KERNEL); +#define ieee80211softmac_notify_atomic(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_ATOMIC); + +extern int ieee80211softmac_notify_gfp(struct net_device *dev, + int event, notify_function_ptr fun, void *context, gfp_t gfp_mask); + +/* To clear pending work (for ifconfig down, etc.) */ +extern void +ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm); + +#endif /* IEEE80211SOFTMAC_H_ */ diff --git a/include/net/ieee80211softmac_wx.h b/include/net/ieee80211softmac_wx.h new file mode 100644 index 000000000000..165ea4c78ee0 --- /dev/null +++ b/include/net/ieee80211softmac_wx.h @@ -0,0 +1,66 @@ +#ifndef _IEEE80211SOFTMAC_WX_H +#define _IEEE80211SOFTMAC_WX_H + +#include +#include + +extern int +ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra); + +extern int +ieee80211softmac_wx_get_scan_results(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra); + +extern int +ieee80211softmac_wx_set_essid(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra); + +extern int +ieee80211softmac_wx_get_essid(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra); + +extern int +ieee80211softmac_wx_set_rate(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra); + +extern int +ieee80211softmac_wx_get_rate(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra); + +extern int +ieee80211softmac_wx_get_wap(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra); + +extern int +ieee80211softmac_wx_set_wap(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra); + +extern int +ieee80211softmac_wx_set_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra); + +extern int +ieee80211softmac_wx_get_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra); +#endif /* _IEEE80211SOFTMAC_WX */ diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig index d18ccba3ea9e..dbb08528ddf5 100644 --- a/net/ieee80211/Kconfig +++ b/net/ieee80211/Kconfig @@ -66,3 +66,4 @@ config IEEE80211_CRYPT_TKIP This can be compiled as a modules and it will be called "ieee80211_crypt_tkip". +source "net/ieee80211/softmac/Kconfig" diff --git a/net/ieee80211/softmac/Kconfig b/net/ieee80211/softmac/Kconfig new file mode 100644 index 000000000000..8d4250425911 --- /dev/null +++ b/net/ieee80211/softmac/Kconfig @@ -0,0 +1,9 @@ +config IEEE80211_SOFTMAC + tristate "Software MAC add-on to the IEEE 802.11 networking stack" + ---help--- + This option enables the hardware independent software MAC addon + for the IEEE 802.11 networking stack. + +config IEEE80211_SOFTMAC_DEBUG + bool "Enable full debugging output" + depends on IEEE80211_SOFTMAC diff --git a/net/ieee80211/softmac/Makefile b/net/ieee80211/softmac/Makefile new file mode 100644 index 000000000000..d8c416bdddd7 --- /dev/null +++ b/net/ieee80211/softmac/Makefile @@ -0,0 +1,9 @@ +obj-$(CONFIG_IEEE80211_SOFTMAC) := ieee80211softmac.o +ieee80211softmac-objs := \ + ieee80211softmac_io.o \ + ieee80211softmac_auth.o \ + ieee80211softmac_module.o \ + ieee80211softmac_scan.o \ + ieee80211softmac_wx.o \ + ieee80211softmac_assoc.o \ + ieee80211softmac_event.o diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c new file mode 100644 index 000000000000..d491005d6cfd --- /dev/null +++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c @@ -0,0 +1,356 @@ +#include "ieee80211softmac_priv.h" + +/* + * Overview + * + * Before you can associate, you have to authenticate. + * + */ + +/* Sends out an association request to the desired AP */ +static void +ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net) +{ + unsigned long flags; + function_enter(); + /* Switch to correct channel for this network */ + mac->set_channel(mac->dev, net->channel); + + /* Send association request */ + ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_ASSOC_REQ, 0); + + dprintk(KERN_INFO PFX "sent association request!\n"); + + /* Change the state to associating */ + spin_lock_irqsave(&mac->lock, flags); + mac->associnfo.associating = 1; + mac->associated = 0; /* just to make sure */ + spin_unlock_irqrestore(&mac->lock, flags); + + /* Set a timer for timeout */ + /* FIXME: make timeout configurable */ + queue_delayed_work(mac->workqueue, &mac->associnfo.timeout, 5 * HZ); +} + +void +ieee80211softmac_assoc_timeout(void *d) +{ + struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d; + unsigned long flags; + + function_enter(); + + spin_lock_irqsave(&mac->lock, flags); + /* we might race against ieee80211softmac_handle_assoc_response, + * so make sure only one of us does something */ + if (!mac->associnfo.associating) { + spin_unlock_irqrestore(&mac->lock, flags); + return; + } + mac->associnfo.associating = 0; + mac->associnfo.bssvalid = 0; + mac->associated = 0; + spin_unlock_irqrestore(&mac->lock, flags); + + dprintk(KERN_INFO PFX "assoc request timed out!\n"); + /* FIXME: we need to know the network here. that requires a bit of restructuring */ + ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, NULL); +} + +static void +ieee80211softmac_reassoc(struct ieee80211softmac_device *mac) +{ + function_enter(); +} + + +/* Sends out a disassociation request to the desired AP */ +static void +ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason) +{ + unsigned long flags; + struct ieee80211softmac_network *found; + function_enter(); + + if (mac->associnfo.bssvalid && mac->associated) { + found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); + if (found) + ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason); + } else if (mac->associnfo.associating) { + cancel_delayed_work(&mac->associnfo.timeout); + } + + /* Change our state */ + spin_lock_irqsave(&mac->lock, flags); + /* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */ + mac->associated = 0; + mac->associnfo.associating = 0; + spin_unlock_irqrestore(&mac->lock, flags); +} + +static inline int +we_support_all_basic_rates(struct ieee80211softmac_device *mac, u8 *from, u8 from_len) +{ + int idx, search, found; + u8 rate, search_rate; + + for (idx = 0; idx < (from_len); idx++) { + rate = (from)[idx]; + if (!(rate & IEEE80211_BASIC_RATE_MASK)) + continue; + found = 0; + rate &= ~IEEE80211_BASIC_RATE_MASK; + for (search = 0; search < mac->ratesinfo.count; search++) { + search_rate = mac->ratesinfo.rates[search]; + search_rate &= ~IEEE80211_BASIC_RATE_MASK; + if (rate == search_rate) { + found = 1; + break; + } + } + if (!found) + return 0; + } + return 1; +} + +static int +network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_network *net) +{ + /* we cannot associate to networks whose name we don't know */ + if (ieee80211_is_empty_essid(net->ssid, net->ssid_len)) + return 0; + /* do not associate to a network whose BSSBasicRateSet we cannot support */ + if (!we_support_all_basic_rates(mac, net->rates, net->rates_len)) + return 0; + /* do we really need to check the ex rates? */ + if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len)) + return 0; + + /* if 'ANY' network requested, take any that doesn't have privacy enabled */ + if (mac->associnfo.req_essid.len == 0 + && !(net->capability & WLAN_CAPABILITY_PRIVACY)) + return 1; + if (net->ssid_len != mac->associnfo.req_essid.len) + return 0; + if (!memcmp(net->ssid, mac->associnfo.req_essid.data, mac->associnfo.req_essid.len)) + return 1; + return 0; +} + +static void +ieee80211softmac_assoc_notify(struct net_device *dev, void *context) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + ieee80211softmac_assoc_work((void*)mac); +} + +/* This function is called to handle userspace requests (asynchronously) */ +void +ieee80211softmac_assoc_work(void *d) +{ + struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d; + struct ieee80211softmac_network *found = NULL; + struct ieee80211_network *net = NULL, *best = NULL; + unsigned long flags; + + function_enter(); + + /* meh */ + if (mac->associated) + ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); + + /* try to find the requested network in our list, if we found one already */ + if (mac->associnfo.bssvalid) + found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); + + /* Search the ieee80211 networks for this network if we didn't find it */ + if (!found) + { + spin_lock_irqsave(&mac->ieee->lock, flags); + list_for_each_entry(net, &mac->ieee->network_list, list) { + /* we're supposed to find the network with + * the best signal here, as we're asked to join + * any network with a specific ESSID, and many + * different ones could have that. + * + * I'll for now implement just finding one at all + * + * We also should take into account the rateset + * here to find the best BSSID to try. + */ + if (network_matches_request(mac, net)) { + if (!best) { + best = net; + continue; + } + /* we already had a matching network, so + * compare their properties to get the + * better of the two ... (see above) + */ + /* TODO */ + /* for now, just */ + break; + } + } + /* if we unlock here, we might get interrupted and the `best' + * pointer could go stale */ + if (best) { + found = ieee80211softmac_create_network(mac, best); + /* if found is still NULL, then we got -ENOMEM somewhere */ + if (found) + ieee80211softmac_add_network(mac, found); + } + spin_unlock_irqrestore(&mac->ieee->lock, flags); + } + + if (!found) { + if (mac->associnfo.scan_retry > 0) { + spin_lock_irqsave(&mac->lock, flags); + mac->associnfo.scan_retry--; + spin_unlock_irqrestore(&mac->lock, flags); + + /* We know of no such network. Let's scan. + * NB: this also happens if we had no memory to copy the network info... + * Maybe we can hope to have more memory after scanning finishes ;) + */ + dprintk(KERN_INFO PFX "Associate: Network not known, trying to initiate scan: "); + ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify, NULL); + if (ieee80211softmac_start_scan(mac)) + dprintk("failed.\n"); + else + dprintk("ok.\n"); + return; + } + else { + spin_lock_irqsave(&mac->lock, flags); + mac->associnfo.associating = 0; + mac->associated = 0; + spin_unlock_irqrestore(&mac->lock, flags); + + dprintk(KERN_INFO PFX "Unable to find network after scan!\n"); + ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL); + return; + } + } + + mac->associnfo.bssvalid = 1; + memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN); + /* copy the ESSID for displaying it */ + mac->associnfo.associate_essid.len = found->essid.len; + memcpy(mac->associnfo.associate_essid.data, found->essid.data, IW_ESSID_MAX_SIZE + 1); + + /* we found a network! authenticate (if necessary) and associate to it. */ + if (!found->authenticated) { + /* This relies on the fact that _auth_req only queues the work, + * otherwise adding the notification would be racy. */ + if (!ieee80211softmac_auth_req(mac, found)) { + dprintk(KERN_INFO PFX "cannot associate without being authenticated, requested authentication\n"); + ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify, NULL, GFP_KERNEL); + } else { + printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n"); + ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found); + } + return; + } + /* finally! now we can start associating */ + ieee80211softmac_assoc(mac, found); +} + +/* call this to do whatever is necessary when we're associated */ +static void +ieee80211softmac_associated(struct ieee80211softmac_device *mac, + struct ieee80211_assoc_response * resp, + struct ieee80211softmac_network *net) +{ + mac->associnfo.associating = 0; + mac->associated = 1; + if (mac->set_bssid_filter) + mac->set_bssid_filter(mac->dev, net->bssid); + memcpy(mac->ieee->bssid, net->bssid, ETH_ALEN); + mac->dev->flags |= IFF_RUNNING; + + mac->association_id = le16_to_cpup(&resp->aid); +} + +/* received frame handling functions */ +int +ieee80211softmac_handle_assoc_response(struct net_device * dev, + struct ieee80211_assoc_response * resp, + struct ieee80211_network * _ieee80211_network_do_not_use) +{ + /* NOTE: the network parameter has to be ignored by + * this code because it is the ieee80211's pointer + * to the struct, not ours (we made a copy) + */ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + u16 status = le16_to_cpup(&resp->status); + struct ieee80211softmac_network *network = NULL; + unsigned long flags; + + spin_lock_irqsave(&mac->lock, flags); + + if (!mac->associnfo.associating) { + /* we race against the timeout function, so make sure + * only one of us can do work */ + spin_unlock_irqrestore(&mac->lock, flags); + return 0; + } + network = ieee80211softmac_get_network_by_bssid_locked(mac, resp->header.addr3); + + /* someone sending us things without us knowing him? Ignore. */ + if (!network) { + dprintk(KERN_INFO PFX "Received unrequested assocation response from " MAC_FMT "\n", MAC_ARG(resp->header.addr3)); + spin_unlock_irqrestore(&mac->lock, flags); + return 0; + } + + /* now that we know it was for us, we can cancel the timeout */ + cancel_delayed_work(&mac->associnfo.timeout); + + switch (status) { + case 0: + dprintk(KERN_INFO PFX "associated!\n"); + ieee80211softmac_associated(mac, resp, network); + ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATED, network); + break; + case WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH: + if (!network->auth_desynced_once) { + /* there seem to be a few rare cases where our view of + * the world is obscured, or buggy APs that don't DEAUTH + * us properly. So we handle that, but allow it only once. + */ + printkl(KERN_INFO PFX "We were not authenticated during association, retrying...\n"); + network->authenticated = 0; + /* we don't want to do this more than once ... */ + network->auth_desynced_once = 1; + queue_work(mac->workqueue, &mac->associnfo.work); + break; + } + default: + dprintk(KERN_INFO PFX "associating failed (reason: 0x%x)!\n", status); + mac->associnfo.associating = 0; + mac->associnfo.bssvalid = 0; + mac->associated = 0; + ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, network); + } + + spin_unlock_irqrestore(&mac->lock, flags); + return 0; +} + +int +ieee80211softmac_handle_disassoc(struct net_device * dev, + struct ieee80211_disassoc *disassoc) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + unsigned long flags; + dprintk(KERN_INFO PFX "got disassoc frame\n"); + + spin_lock_irqsave(&mac->lock, flags); + mac->associnfo.bssvalid = 0; + mac->associated = 0; + spin_unlock_irqrestore(&mac->lock, flags); + + return 0; +} diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c new file mode 100644 index 000000000000..94cac14bc1d4 --- /dev/null +++ b/net/ieee80211/softmac/ieee80211softmac_auth.c @@ -0,0 +1,348 @@ +#include "ieee80211softmac_priv.h" + +static void ieee80211softmac_auth_queue(void *data); + +/* Queues an auth request to the desired AP */ +int +ieee80211softmac_auth_req(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *net) +{ + struct ieee80211softmac_auth_queue_item *auth; + unsigned long flags; + + function_enter(); + + if (net->authenticating) + return 0; + + /* Add the network if it's not already added */ + ieee80211softmac_add_network(mac, net); + + dprintk(KERN_NOTICE PFX "Queueing Authentication Request to "MAC_FMT"\n", MAC_ARG(net->bssid)); + /* Queue the auth request */ + auth = (struct ieee80211softmac_auth_queue_item *) + kmalloc(sizeof(struct ieee80211softmac_auth_queue_item), GFP_KERNEL); + if(auth == NULL) + return -ENOMEM; + + auth->net = net; + auth->mac = mac; + auth->retry = IEEE80211SOFTMAC_AUTH_RETRY_LIMIT; + auth->state = IEEE80211SOFTMAC_AUTH_OPEN_REQUEST; + INIT_WORK(&auth->work, &ieee80211softmac_auth_queue, (void *)auth); + + /* Lock (for list) */ + spin_lock_irqsave(&mac->lock, flags); + + /* add to list */ + list_add_tail(&auth->list, &mac->auth_queue); + queue_work(mac->workqueue, &auth->work); + spin_unlock_irqrestore(&mac->lock, flags); + + return 0; +} + + +/* Sends an auth request to the desired AP and handles timeouts */ +static void +ieee80211softmac_auth_queue(void *data) +{ + struct ieee80211softmac_device *mac; + struct ieee80211softmac_auth_queue_item *auth; + struct ieee80211softmac_network *net; + unsigned long flags; + + function_enter(); + + auth = (struct ieee80211softmac_auth_queue_item *)data; + net = auth->net; + mac = auth->mac; + + if(auth->retry > 0) { + /* Switch to correct channel for this network */ + mac->set_channel(mac->dev, net->channel); + + /* Lock and set flags */ + spin_lock_irqsave(&mac->lock, flags); + net->authenticated = 0; + net->authenticating = 1; + /* add a timeout call so we eventually give up waiting for an auth reply */ + queue_delayed_work(mac->workqueue, &auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT); + auth->retry--; + spin_unlock_irqrestore(&mac->lock, flags); + if (ieee80211softmac_send_mgt_frame(mac, auth->net, IEEE80211_STYPE_AUTH, auth->state)) + dprintk(KERN_NOTICE PFX "Sending Authentication Request to "MAC_FMT" failed (this shouldn't happen, wait for the timeout).\n", MAC_ARG(net->bssid)); + else + dprintk(KERN_NOTICE PFX "Sent Authentication Request to "MAC_FMT".\n", MAC_ARG(net->bssid)); + return; + } + + printkl(KERN_WARNING PFX "Authentication timed out with "MAC_FMT"\n", MAC_ARG(net->bssid)); + /* Remove this item from the queue */ + spin_lock_irqsave(&mac->lock, flags); + ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net); + cancel_delayed_work(&auth->work); /* just to make sure... */ + list_del(&auth->list); + spin_unlock_irqrestore(&mac->lock, flags); + /* Free it */ + kfree(auth); +} + +/* Handle the auth response from the AP + * This should be registered with ieee80211 as handle_auth + */ +int +ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) +{ + + struct list_head *list_ptr; + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + struct ieee80211softmac_auth_queue_item *aq = NULL; + struct ieee80211softmac_network *net = NULL; + unsigned long flags; + u8 * data; + + function_enter(); + + /* Find correct auth queue item */ + spin_lock_irqsave(&mac->lock, flags); + list_for_each(list_ptr, &mac->auth_queue) { + aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list); + net = aq->net; + if (!memcmp(net->bssid, auth->header.addr2, ETH_ALEN)) + break; + else + aq = NULL; + } + spin_unlock_irqrestore(&mac->lock, flags); + + /* Make sure that we've got an auth queue item for this request */ + if(aq == NULL) + { + printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but no queue item exists.\n", MAC_ARG(auth->header.addr2)); + /* Error #? */ + return -1; + } + + /* Check for out of order authentication */ + if(!net->authenticating) + { + printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but did not request authentication.\n",MAC_ARG(auth->header.addr2)); + return -1; + } + + /* Parse the auth packet */ + switch(auth->algorithm) { + case WLAN_AUTH_OPEN: + /* Check the status code of the response */ + + switch(auth->status) { + case WLAN_STATUS_SUCCESS: + /* Update the status to Authenticated */ + spin_lock_irqsave(&mac->lock, flags); + net->authenticating = 0; + net->authenticated = 1; + spin_unlock_irqrestore(&mac->lock, flags); + + /* Send event */ + printkl(KERN_NOTICE PFX "Open Authentication completed with "MAC_FMT"\n", MAC_ARG(net->bssid)); + ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net); + break; + default: + /* Lock and reset flags */ + spin_lock_irqsave(&mac->lock, flags); + net->authenticated = 0; + net->authenticating = 0; + spin_unlock_irqrestore(&mac->lock, flags); + + printkl(KERN_NOTICE PFX "Open Authentication with "MAC_FMT" failed, error code: %i\n", + MAC_ARG(net->bssid), le16_to_cpup(&auth->status)); + /* Count the error? */ + break; + } + goto free_aq; + break; + case WLAN_AUTH_SHARED_KEY: + /* Figure out where we are in the process */ + switch(auth->transaction) { + case IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE: + /* Check to make sure we have a challenge IE */ + data = (u8 *)auth->info_element; + if(*data++ != MFIE_TYPE_CHALLENGE){ + printkl(KERN_NOTICE PFX "Shared Key Authentication failed due to a missing challenge.\n"); + break; + } + /* Save the challenge */ + spin_lock_irqsave(&mac->lock, flags); + net->challenge_len = *data++; + if(net->challenge_len > WLAN_AUTH_CHALLENGE_LEN) + net->challenge_len = WLAN_AUTH_CHALLENGE_LEN; + if(net->challenge != NULL) + kfree(net->challenge); + net->challenge = kmalloc(net->challenge_len, GFP_ATOMIC); + memcpy(net->challenge, data, net->challenge_len); + aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE; + spin_unlock_irqrestore(&mac->lock, flags); + + /* Switch to correct channel for this network */ + mac->set_channel(mac->dev, net->channel); + + /* Send our response (How to encrypt?) */ + ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state); + break; + case IEEE80211SOFTMAC_AUTH_SHARED_PASS: + /* Check the status code of the response */ + switch(auth->status) { + case WLAN_STATUS_SUCCESS: + /* Update the status to Authenticated */ + spin_lock_irqsave(&mac->lock, flags); + net->authenticating = 0; + net->authenticated = 1; + spin_unlock_irqrestore(&mac->lock, flags); + printkl(KERN_NOTICE PFX "Shared Key Authentication completed with "MAC_FMT"\n", + MAC_ARG(net->bssid)); + break; + default: + printkl(KERN_NOTICE PFX "Shared Key Authentication with "MAC_FMT" failed, error code: %i\n", + MAC_ARG(net->bssid), le16_to_cpup(&auth->status)); + /* Lock and reset flags */ + spin_lock_irqsave(&mac->lock, flags); + net->authenticating = 0; + net->authenticated = 0; + spin_unlock_irqrestore(&mac->lock, flags); + /* Count the error? */ + break; + } + goto free_aq; + break; + default: + printkl(KERN_WARNING PFX "Unhandled Authentication Step: %i\n", auth->transaction); + break; + } + goto free_aq; + break; + default: + /* ERROR */ + goto free_aq; + break; + } + return 0; +free_aq: + /* Cancel the timeout */ + spin_lock_irqsave(&mac->lock, flags); + cancel_delayed_work(&aq->work); + /* Remove this item from the queue */ + list_del(&aq->list); + spin_unlock_irqrestore(&mac->lock, flags); + + /* Free it */ + kfree(aq); + return 0; +} + +/* + * Handle deauthorization + */ +void +ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *net) +{ + struct ieee80211softmac_auth_queue_item *aq = NULL; + struct list_head *list_ptr; + unsigned long flags; + + function_enter(); + + /* Lock and reset status flags */ + spin_lock_irqsave(&mac->lock, flags); + net->authenticating = 0; + net->authenticated = 0; + + /* Find correct auth queue item, if it exists */ + list_for_each(list_ptr, &mac->auth_queue) { + aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list); + if (!memcmp(net->bssid, aq->net->bssid, ETH_ALEN)) + break; + else + aq = NULL; + } + + /* Cancel pending work */ + if(aq != NULL) + /* Not entirely safe? What about running work? */ + cancel_delayed_work(&aq->work); + + /* Free our network ref */ + ieee80211softmac_del_network_locked(mac, net); + if(net->challenge != NULL) + kfree(net->challenge); + kfree(net); + + /* let's try to re-associate */ + queue_work(mac->workqueue, &mac->associnfo.work); + spin_unlock_irqrestore(&mac->lock, flags); +} + +/* + * Sends a deauth request to the desired AP + */ +int +ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *net, int reason) +{ + int ret; + + function_enter(); + + /* Make sure the network is authenticated */ + if (!net->authenticated) + { + printkl(KERN_DEBUG PFX "Can't send deauthentication packet, network is not authenticated.\n"); + /* Error okay? */ + return -EPERM; + } + + /* Send the de-auth packet */ + if((ret = ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_DEAUTH, reason))) + return ret; + + ieee80211softmac_deauth_from_net(mac, net); + return 0; +} + +/* + * This should be registered with ieee80211 as handle_deauth + */ +int +ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_auth *auth) +{ + + struct ieee80211softmac_network *net = NULL; + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + + function_enter(); + + if (!auth) { + dprintk("deauth without deauth packet. eek!\n"); + return 0; + } + + net = ieee80211softmac_get_network_by_bssid(mac, auth->header.addr2); + + if (net == NULL) { + printkl(KERN_DEBUG PFX "Recieved deauthentication packet from "MAC_FMT", but that network is unknown.\n", + MAC_ARG(auth->header.addr2)); + return 0; + } + + /* Make sure the network is authenticated */ + if(!net->authenticated) + { + printkl(KERN_DEBUG PFX "Can't perform deauthentication, network is not authenticated.\n"); + /* Error okay? */ + return -EPERM; + } + + ieee80211softmac_deauth_from_net(mac, net); + return 0; +} diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c new file mode 100644 index 000000000000..0d0a8327252f --- /dev/null +++ b/net/ieee80211/softmac/ieee80211softmac_event.c @@ -0,0 +1,135 @@ +#include "ieee80211softmac_priv.h" + +/* + * Event system + * Also see comments in public header file + * + * Each event has associated to it + * - an event type (see constants in public header) + * - an event context (see below) + * - the function to be called + * - a context (extra parameter to call the function with) + * - and the softmac struct + * + * The event context is private and can only be used from + * within this module. Its meaning varies with the event + * type: + * SCAN_FINISHED: no special meaning + * ASSOCIATED, + * ASSOCIATE_FAILED, + * ASSOCIATE_TIMEOUT, + * AUTHENTICATED, + * AUTH_FAILED, + * AUTH_TIMEOUT: a pointer to the network struct + * ... + * Code within this module can use the event context to be only + * called when the event is true for that specific context + * as per above table. + * If the event context is NULL, then the notification is always called, + * regardless of the event context. The event context is not passed to + * the callback, it is assumed that the context suffices. + * + * You can also use the event context only by setting the event type + * to -1 (private use only), in which case you'll be notified + * whenever the event context matches. + */ + +static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = { + "scan finished", + "associated", + "associating failed", + "associating timed out", + "authenticated", + "authenticating failed", + "authenticating timed out", + "associating failed because no suitable network was found", +}; + + +static void +ieee80211softmac_notify_callback(void *d) +{ + struct ieee80211softmac_event event = *(struct ieee80211softmac_event*) d; + kfree(d); + + event.fun(event.mac->dev, event.context); +} + +int +ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac, + int event, void *event_context, notify_function_ptr fun, void *context, gfp_t gfp_mask) +{ + struct ieee80211softmac_event *eventptr; + unsigned long flags; + + if (event < -1 || event > IEEE80211SOFTMAC_EVENT_LAST) + return -ENOSYS; + + if (!fun) + return -EINVAL; + + eventptr = kmalloc(sizeof(struct ieee80211softmac_event), gfp_mask); + if (!eventptr) + return -ENOMEM; + + eventptr->event_type = event; + INIT_WORK(&eventptr->work, ieee80211softmac_notify_callback, eventptr); + eventptr->fun = fun; + eventptr->context = context; + eventptr->mac = mac; + eventptr->event_context = event_context; + + spin_lock_irqsave(&mac->lock, flags); + list_add(&eventptr->list, &mac->events); + spin_unlock_irqrestore(&mac->lock, flags); + + return 0; +} + +int +ieee80211softmac_notify_gfp(struct net_device *dev, + int event, notify_function_ptr fun, void *context, gfp_t gfp_mask) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + + if (event < 0 || event > IEEE80211SOFTMAC_EVENT_LAST) + return -ENOSYS; + + return ieee80211softmac_notify_internal(mac, event, NULL, fun, context, gfp_mask); +} +EXPORT_SYMBOL_GPL(ieee80211softmac_notify_gfp); + +/* private -- calling all callbacks that were specified */ +void +ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx) +{ + struct ieee80211softmac_event *eventptr, *tmp; + union iwreq_data wrqu; + char *msg; + + if (event >= 0) { + msg = event_descriptions[event]; + wrqu.data.length = strlen(msg); + wireless_send_event(mac->dev, IWEVCUSTOM, &wrqu, msg); + } + + if (!list_empty(&mac->events)) + list_for_each_entry_safe(eventptr, tmp, &mac->events, list) { + if ((eventptr->event_type == event || eventptr->event_type == -1) + && (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) { + list_del(&eventptr->list); + queue_work(mac->workqueue, &eventptr->work); + } + } +} + +void +ieee80211softmac_call_events(struct ieee80211softmac_device *mac, int event, void *event_ctx) +{ + unsigned long flags; + + spin_lock_irqsave(&mac->lock, flags); + ieee80211softmac_call_events_locked(mac, event, event_ctx); + + spin_unlock_irqrestore(&mac->lock, flags); +} diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c new file mode 100644 index 000000000000..2cb3087197d8 --- /dev/null +++ b/net/ieee80211/softmac/ieee80211softmac_io.c @@ -0,0 +1,474 @@ +/* + * Some parts based on code from net80211 + * Copyright (c) 2001 Atsushi Onoe + * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "ieee80211softmac_priv.h" + +/* Helper functions for inserting data into the frames */ + +/* + * Adds an ESSID element to the frame + * + */ +static u8 * +ieee80211softmac_add_essid(u8 *dst, struct ieee80211softmac_essid *essid) +{ + if (essid) { + *dst++ = MFIE_TYPE_SSID; + *dst++ = essid->len; + memcpy(dst, essid->data, essid->len); + return dst+essid->len; + } else { + *dst++ = MFIE_TYPE_SSID; + *dst++ = 0; + return dst; + } +} + +/* Adds Supported Rates and if required Extended Rates Information Element + * to the frame, ASSUMES WE HAVE A SORTED LIST OF RATES */ +static u8 * +ieee80211softmac_frame_add_rates(u8 *dst, const struct ieee80211softmac_ratesinfo *r) +{ + int cck_len, ofdm_len; + *dst++ = MFIE_TYPE_RATES; + + for(cck_len=0; ieee80211_is_cck_rate(r->rates[cck_len]) && (cck_len < r->count);cck_len++); + + if(cck_len > IEEE80211SOFTMAC_MAX_RATES_LEN) + cck_len = IEEE80211SOFTMAC_MAX_RATES_LEN; + *dst++ = cck_len; + memcpy(dst, r->rates, cck_len); + dst += cck_len; + + if(cck_len < r->count){ + for (ofdm_len=0; ieee80211_is_ofdm_rate(r->rates[ofdm_len + cck_len]) && (ofdm_len + cck_len < r->count); ofdm_len++); + if (ofdm_len > 0) { + if (ofdm_len > IEEE80211SOFTMAC_MAX_EX_RATES_LEN) + ofdm_len = IEEE80211SOFTMAC_MAX_EX_RATES_LEN; + *dst++ = MFIE_TYPE_RATES_EX; + *dst++ = ofdm_len; + memcpy(dst, r->rates + cck_len, ofdm_len); + dst += ofdm_len; + } + } + return dst; +} + +/* Allocate a management frame */ +static u8 * +ieee80211softmac_alloc_mgt(u32 size) +{ + u8 * data; + + /* Add the header and FCS to the size */ + size = size + IEEE80211_3ADDR_LEN; + if(size > IEEE80211_DATA_LEN) + return NULL; + /* Allocate the frame */ + data = kmalloc(size, GFP_ATOMIC); + memset(data, 0, size); + return data; +} + +/* + * Add a 2 Address Header + */ +static void +ieee80211softmac_hdr_2addr(struct ieee80211softmac_device *mac, + struct ieee80211_hdr_2addr *header, u32 type, u8 *dest) +{ + /* Fill in the frame control flags */ + header->frame_ctl = cpu_to_le16(type); + /* Control packets always have WEP turned off */ + if(type > IEEE80211_STYPE_CFENDACK && type < IEEE80211_STYPE_PSPOLL) + header->frame_ctl |= mac->ieee->sec.level ? cpu_to_le16(IEEE80211_FCTL_PROTECTED) : 0; + + /* Fill in the duration */ + header->duration_id = 0; + /* FIXME: How do I find this? + * calculate. But most drivers just fill in 0 (except if it's a station id of course) */ + + /* Fill in the Destination Address */ + if(dest == NULL) + memset(header->addr1, 0xFF, ETH_ALEN); + else + memcpy(header->addr1, dest, ETH_ALEN); + /* Fill in the Source Address */ + memcpy(header->addr2, mac->ieee->dev->dev_addr, ETH_ALEN); + +} + + +/* Add a 3 Address Header */ +static void +ieee80211softmac_hdr_3addr(struct ieee80211softmac_device *mac, + struct ieee80211_hdr_3addr *header, u32 type, u8 *dest, u8 *bssid) +{ + /* This is common with 2addr, so use that instead */ + ieee80211softmac_hdr_2addr(mac, (struct ieee80211_hdr_2addr *)header, type, dest); + + /* Fill in the BSS ID */ + if(bssid == NULL) + memset(header->addr3, 0xFF, ETH_ALEN); + else + memcpy(header->addr3, bssid, ETH_ALEN); + + /* Fill in the sequence # */ + /* FIXME: I need to add this to the softmac struct + * shouldn't the sequence number be in ieee80211? */ +} + + +/***************************************************************************** + * Create Management packets + *****************************************************************************/ + +/* Creates an association request packet */ +u32 +ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt, + struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net) +{ + u8 *data; + (*pkt) = (struct ieee80211_assoc_request *)ieee80211softmac_alloc_mgt( + 2 + /* Capability Info */ + 2 + /* Listen Interval */ + /* SSID IE */ + 1 + 1 + IW_ESSID_MAX_SIZE + + /* Rates IE */ + 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN + + /* Extended Rates IE */ + 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN + + /* WPA IE if present */ + mac->wpa.IElen + /* Other IE's? Optional? + * Yeah, probably need an extra IE parameter -- lots of vendors like to + * fill in their own IEs */ + ); + if (unlikely((*pkt) == NULL)) + return 0; + ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid); + + /* Fill in capability Info */ + (*pkt)->capability = (mac->ieee->iw_mode == IW_MODE_MASTER) || (mac->ieee->iw_mode == IW_MODE_INFRA) ? + cpu_to_le16(WLAN_CAPABILITY_ESS) : + cpu_to_le16(WLAN_CAPABILITY_IBSS); + /* Need to add this + (*pkt)->capability |= mac->ieee->short_slot ? + cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0; + */ + (*pkt)->capability |= mac->ieee->sec.level ? cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0; + /* Fill in Listen Interval (?) */ + (*pkt)->listen_interval = cpu_to_le16(10); + + data = (u8 *)(*pkt)->info_element; + /* Add SSID */ + data = ieee80211softmac_add_essid(data, &net->essid); + /* Add Rates */ + data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo); + /* Add WPA IE */ + if (mac->wpa.IElen && mac->wpa.IE) { + memcpy(data, mac->wpa.IE, mac->wpa.IElen); + data += mac->wpa.IElen; + } + /* Return the number of used bytes */ + return (data - (u8*)(*pkt)); +} + +/* Create a reassociation request packet */ +u32 +ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt, + struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net) +{ + u8 *data; + (*pkt) = (struct ieee80211_reassoc_request *)ieee80211softmac_alloc_mgt( + 2 + /* Capability Info */ + 2 + /* Listen Interval */ + ETH_ALEN + /* AP MAC */ + /* SSID IE */ + 1 + 1 + IW_ESSID_MAX_SIZE + + /* Rates IE */ + 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN + + /* Extended Rates IE */ + 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN + /* Other IE's? */ + ); + if (unlikely((*pkt) == NULL)) + return 0; + ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_REASSOC_REQ, net->bssid, net->bssid); + + /* Fill in capability Info */ + (*pkt)->capability = mac->ieee->iw_mode == IW_MODE_MASTER ? + cpu_to_le16(WLAN_CAPABILITY_ESS) : + cpu_to_le16(WLAN_CAPABILITY_IBSS); + /* + (*pkt)->capability |= mac->ieee->short_slot ? + cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0; + */ + (*pkt)->capability |= mac->ieee->sec.level ? + cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0; + + /* Fill in Listen Interval (?) */ + (*pkt)->listen_interval = cpu_to_le16(10); + /* Fill in the current AP MAC */ + memcpy((*pkt)->current_ap, mac->ieee->bssid, ETH_ALEN); + + data = (u8 *)(*pkt)->info_element; + /* Add SSID */ + data = ieee80211softmac_add_essid(data, &net->essid); + /* Add Rates */ + data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo); + /* Return packet size */ + return (data - (u8 *)(*pkt)); +} + +/* Create an authentication packet */ +u32 +ieee80211softmac_auth(struct ieee80211_auth **pkt, + struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, + u16 transaction, u16 status) +{ + u8 *data; + /* Allocate Packet */ + (*pkt) = (struct ieee80211_auth *)ieee80211softmac_alloc_mgt( + 2 + /* Auth Algorithm */ + 2 + /* Auth Transaction Seq */ + 2 + /* Status Code */ + /* Challenge Text IE */ + mac->ieee->open_wep ? 0 : + 1 + 1 + WLAN_AUTH_CHALLENGE_LEN + ); + if (unlikely((*pkt) == NULL)) + return 0; + ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_AUTH, net->bssid, net->bssid); + + /* Algorithm */ + (*pkt)->algorithm = mac->ieee->open_wep ? + cpu_to_le16(WLAN_AUTH_OPEN) : + cpu_to_le16(WLAN_AUTH_SHARED_KEY); + /* Transaction */ + (*pkt)->transaction = cpu_to_le16(transaction); + /* Status */ + (*pkt)->status = cpu_to_le16(status); + + data = (u8 *)(*pkt)->info_element; + /* Challenge Text */ + if(!mac->ieee->open_wep){ + *data = MFIE_TYPE_CHALLENGE; + data++; + + /* Copy the challenge in */ + // *data = challenge length + // data += sizeof(u16); + // memcpy(data, challenge, challenge length); + // data += challenge length; + + /* Add the full size to the packet length */ + } + + /* Return the packet size */ + return (data - (u8 *)(*pkt)); +} + +/* Create a disassocation or deauthentication packet */ +u32 +ieee80211softmac_disassoc_deauth(struct ieee80211_disassoc **pkt, + struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, + u16 type, u16 reason) +{ + /* Allocate Packet */ + (*pkt) = (struct ieee80211_disassoc *)ieee80211softmac_alloc_mgt(2); + if (unlikely(pkt == NULL)) + return 0; + ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), type, net->bssid, net->bssid); + /* Reason */ + (*pkt)->reason = cpu_to_le16(reason); + /* Return the packet size */ + return (2 + IEEE80211_3ADDR_LEN); +} + +/* Create a probe request packet */ +u32 +ieee80211softmac_probe_req(struct ieee80211_probe_request **pkt, + struct ieee80211softmac_device *mac, struct ieee80211softmac_essid *essid) +{ + u8 *data; + /* Allocate Packet */ + (*pkt) = (struct ieee80211_probe_request *)ieee80211softmac_alloc_mgt( + /* SSID of requested network */ + 1 + 1 + IW_ESSID_MAX_SIZE + + /* Rates IE */ + 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN + + /* Extended Rates IE */ + 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN + ); + if (unlikely((*pkt) == NULL)) + return 0; + ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_PROBE_REQ, NULL, NULL); + + data = (u8 *)(*pkt)->info_element; + /* Add ESSID (can be NULL) */ + data = ieee80211softmac_add_essid(data, essid); + /* Add Rates */ + data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo); + /* Return packet size */ + return (data - (u8 *)(*pkt)); +} + +/* Create a probe response packet */ +/* FIXME: Not complete */ +u32 +ieee80211softmac_probe_resp(struct ieee80211_probe_response **pkt, + struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net) +{ + u8 *data; + /* Allocate Packet */ + (*pkt) = (struct ieee80211_probe_response *)ieee80211softmac_alloc_mgt( + 8 + /* Timestamp */ + 2 + /* Beacon Interval */ + 2 + /* Capability Info */ + /* SSID IE */ + 1 + 1 + IW_ESSID_MAX_SIZE + + 7 + /* FH Parameter Set */ + 2 + /* DS Parameter Set */ + 8 + /* CF Parameter Set */ + 4 /* IBSS Parameter Set */ + ); + if (unlikely((*pkt) == NULL)) + return 0; + ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_PROBE_RESP, net->bssid, net->bssid); + data = (u8 *)(*pkt)->info_element; + + /* Return the packet size */ + return (data - (u8 *)(*pkt)); +} + + +/* Sends a manangement packet + * FIXME: document the use of the arg parameter + * for _AUTH: (transaction #) | (status << 16) + */ +int +ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac, + void *ptrarg, u32 type, u32 arg) +{ + void *pkt = NULL; + u32 pkt_size = 0; + + switch(type) { + case IEEE80211_STYPE_ASSOC_REQ: + pkt_size = ieee80211softmac_assoc_req((struct ieee80211_assoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg); + break; + case IEEE80211_STYPE_REASSOC_REQ: + pkt_size = ieee80211softmac_reassoc_req((struct ieee80211_reassoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg); + break; + case IEEE80211_STYPE_AUTH: + pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16)); + break; + case IEEE80211_STYPE_DISASSOC: + case IEEE80211_STYPE_DEAUTH: + pkt_size = ieee80211softmac_disassoc_deauth((struct ieee80211_disassoc **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, type, (u16)(arg & 0xFFFF)); + break; + case IEEE80211_STYPE_PROBE_REQ: + pkt_size = ieee80211softmac_probe_req((struct ieee80211_probe_request **)(&pkt), mac, (struct ieee80211softmac_essid *)ptrarg); + break; + case IEEE80211_STYPE_PROBE_RESP: + pkt_size = ieee80211softmac_probe_resp((struct ieee80211_probe_response **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg); + break; + default: + printkl(KERN_DEBUG PFX "Unsupported Management Frame type: %i\n", type); + return -EINVAL; + }; + + if(pkt_size == 0 || pkt == NULL) { + printkl(KERN_DEBUG PFX "Error, packet is nonexistant or 0 length\n"); + return -ENOMEM; + } + + /* Send the packet to the ieee80211 layer for tx */ + /* we defined softmac->mgmt_xmit for this. Should we keep it + * as it is (that means we'd need to wrap this into a txb), + * modify the prototype (so it matches this function), + * or get rid of it alltogether? + * Does this work for you now? + */ + ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt, pkt_size); + + kfree(pkt); + return 0; +} + + +/* Create an rts/cts frame */ +u32 +ieee80211softmac_rts_cts(struct ieee80211_hdr_2addr **pkt, + struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, + u32 type) +{ + /* Allocate Packet */ + (*pkt) = kmalloc(IEEE80211_2ADDR_LEN, GFP_ATOMIC); + memset(*pkt, 0, IEEE80211_2ADDR_LEN); + if((*pkt) == NULL) + return 0; + ieee80211softmac_hdr_2addr(mac, (*pkt), type, net->bssid); + return IEEE80211_2ADDR_LEN; +} + + +/* Sends a control packet */ +static int +ieee80211softmac_send_ctl_frame(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *net, u32 type, u32 arg) +{ + void *pkt = NULL; + u32 pkt_size = 0; + + switch(type) { + case IEEE80211_STYPE_RTS: + case IEEE80211_STYPE_CTS: + pkt_size = ieee80211softmac_rts_cts((struct ieee80211_hdr_2addr **)(&pkt), mac, net, type); + break; + default: + printkl(KERN_DEBUG PFX "Unsupported Control Frame type: %i\n", type); + return -EINVAL; + } + + if(pkt_size == 0) + return -ENOMEM; + + /* Send the packet to the ieee80211 layer for tx */ + ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *) pkt, pkt_size); + + kfree(pkt); + return 0; +} diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c new file mode 100644 index 000000000000..1244a659cd83 --- /dev/null +++ b/net/ieee80211/softmac/ieee80211softmac_module.c @@ -0,0 +1,441 @@ +#include "ieee80211softmac_priv.h" +#include + +struct net_device *alloc_ieee80211softmac(int sizeof_priv) +{ + struct ieee80211softmac_device *softmac; + struct net_device *dev; + + dev = alloc_ieee80211(sizeof(struct ieee80211softmac_device) + sizeof_priv); + softmac = ieee80211_priv(dev); + softmac->dev = dev; + softmac->ieee = netdev_priv(dev); + spin_lock_init(&softmac->lock); + + softmac->ieee->handle_auth = ieee80211softmac_auth_resp; + softmac->ieee->handle_deauth = ieee80211softmac_deauth_resp; + softmac->ieee->handle_assoc_response = ieee80211softmac_handle_assoc_response; + softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc; + softmac->scaninfo = NULL; + + /* TODO: initialise all the other callbacks in the ieee struct + * (once they're written) + */ + + softmac->workqueue = create_workqueue("80211softmac"); + if (!softmac->workqueue) + goto err_free_ieee80211; + + INIT_LIST_HEAD(&softmac->auth_queue); + INIT_LIST_HEAD(&softmac->network_list); + INIT_LIST_HEAD(&softmac->events); + + INIT_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work, softmac); + INIT_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout, softmac); + softmac->start_scan = ieee80211softmac_start_scan_implementation; + softmac->wait_for_scan = ieee80211softmac_wait_for_scan_implementation; + softmac->stop_scan = ieee80211softmac_stop_scan_implementation; + + //TODO: The mcast rate has to be assigned dynamically somewhere (in scanning, association. Not sure...) + // It has to be set to the highest rate all stations in the current network can handle. + softmac->txrates.mcast_rate = IEEE80211_CCK_RATE_1MB; + softmac->txrates.mcast_fallback = IEEE80211_CCK_RATE_1MB; + /* This is reassigned in ieee80211softmac_start to sane values. */ + softmac->txrates.default_rate = IEEE80211_CCK_RATE_1MB; + softmac->txrates.default_fallback = IEEE80211_CCK_RATE_1MB; + + /* should we also assign softmac->mgmt_xmit here so + * that it is always valid? If so, we probably want + * to define a new function for that which just + * wraps ieee80211_tx_frame + */ + + /* until associated, we're not ready */ + dev->flags &= ~IFF_RUNNING; + + return dev; + +err_free_ieee80211: + free_ieee80211(dev); + + return NULL; +} + +/* Clears the pending work queue items, stops all scans, etc. */ +void +ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm) +{ + unsigned long flags; + struct ieee80211softmac_event *eventptr, *eventtmp; + struct ieee80211softmac_auth_queue_item *authptr, *authtmp; + struct ieee80211softmac_network *netptr, *nettmp; + + ieee80211softmac_stop_scan(sm); + ieee80211softmac_wait_for_scan(sm); + + spin_lock_irqsave(&sm->lock, flags); + /* Free all pending assoc work items */ + cancel_delayed_work(&sm->associnfo.work); + + /* Free all pending scan work items */ + if(sm->scaninfo != NULL) + cancel_delayed_work(&sm->scaninfo->softmac_scan); + + /* Free all pending auth work items */ + list_for_each_entry(authptr, &sm->auth_queue, list) + cancel_delayed_work(&authptr->work); + + /* delete all pending event calls and work items */ + list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list) + cancel_delayed_work(&eventptr->work); + + spin_unlock_irqrestore(&sm->lock, flags); + flush_workqueue(sm->workqueue); + + // now we should be save and no longer need locking... + spin_lock_irqsave(&sm->lock, flags); + /* Free all pending auth work items */ + list_for_each_entry_safe(authptr, authtmp, &sm->auth_queue, list) { + list_del(&authptr->list); + kfree(authptr); + } + + /* delete all pending event calls and work items */ + list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list) { + list_del(&eventptr->list); + kfree(eventptr); + } + + /* Free all networks */ + list_for_each_entry_safe(netptr, nettmp, &sm->network_list, list) { + ieee80211softmac_del_network_locked(sm, netptr); + if(netptr->challenge != NULL) + kfree(netptr->challenge); + kfree(netptr); + } + + spin_unlock_irqrestore(&sm->lock, flags); +} + +void free_ieee80211softmac(struct net_device *dev) +{ + struct ieee80211softmac_device *sm = ieee80211_priv(dev); + ieee80211softmac_clear_pending_work(sm); + destroy_workqueue(sm->workqueue); + kfree(sm->scaninfo); + kfree(sm->wpa.IE); + free_ieee80211(dev); +} + +static void ieee80211softmac_start_check_rates(struct ieee80211softmac_device *mac) +{ + struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo; + /* I took out the sorting check, we're seperating by modulation now. */ + if (ri->count) + return; + /* otherwise assume we hav'em all! */ + if (mac->ieee->modulation & IEEE80211_CCK_MODULATION) { + ri->rates[ri->count++] = IEEE80211_CCK_RATE_1MB; + ri->rates[ri->count++] = IEEE80211_CCK_RATE_2MB; + ri->rates[ri->count++] = IEEE80211_CCK_RATE_5MB; + ri->rates[ri->count++] = IEEE80211_CCK_RATE_11MB; + } + if (mac->ieee->modulation & IEEE80211_OFDM_MODULATION) { + ri->rates[ri->count++] = IEEE80211_OFDM_RATE_6MB; + ri->rates[ri->count++] = IEEE80211_OFDM_RATE_9MB; + ri->rates[ri->count++] = IEEE80211_OFDM_RATE_12MB; + ri->rates[ri->count++] = IEEE80211_OFDM_RATE_18MB; + ri->rates[ri->count++] = IEEE80211_OFDM_RATE_24MB; + ri->rates[ri->count++] = IEEE80211_OFDM_RATE_36MB; + ri->rates[ri->count++] = IEEE80211_OFDM_RATE_48MB; + ri->rates[ri->count++] = IEEE80211_OFDM_RATE_54MB; + } +} + +void ieee80211softmac_start(struct net_device *dev) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + struct ieee80211_device *ieee = mac->ieee; + u32 change = 0; + struct ieee80211softmac_txrates oldrates; + + ieee80211softmac_start_check_rates(mac); + + /* TODO: We need some kind of state machine to lower the default rates + * if we loose too many packets. + */ + /* Change the default txrate to the highest possible value. + * The txrate machine will lower it, if it is too high. + */ + if (mac->txrates_change) + oldrates = mac->txrates; + if (ieee->modulation & IEEE80211_OFDM_MODULATION) { + mac->txrates.default_rate = IEEE80211_OFDM_RATE_54MB; + change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; + mac->txrates.default_fallback = IEEE80211_OFDM_RATE_24MB; + change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK; + } else if (ieee->modulation & IEEE80211_CCK_MODULATION) { + mac->txrates.default_rate = IEEE80211_CCK_RATE_11MB; + change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; + mac->txrates.default_fallback = IEEE80211_CCK_RATE_5MB; + change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK; + } else + assert(0); + if (mac->txrates_change) + mac->txrates_change(dev, change, &oldrates); +} + +void ieee80211softmac_stop(struct net_device *dev) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + + ieee80211softmac_clear_pending_work(mac); +} + +void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + unsigned long flags; + + spin_lock_irqsave(&mac->lock, flags); + memcpy(mac->ratesinfo.rates, rates, count); + mac->ratesinfo.count = count; + spin_unlock_irqrestore(&mac->lock, flags); +} + +static u8 raise_rate(struct ieee80211softmac_device *mac, u8 rate) +{ + int i; + struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo; + + for (i=0; icount-1; i++) { + if (ri->rates[i] == rate) + return ri->rates[i+1]; + } + /* I guess we can't go any higher... */ + return ri->rates[ri->count]; +} + +u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta) +{ + int i; + struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo; + + for (i=delta; icount; i++) { + if (ri->rates[i] == rate) + return ri->rates[i-delta]; + } + /* I guess we can't go any lower... */ + return ri->rates[0]; +} + +static void ieee80211softmac_add_txrates_badness(struct ieee80211softmac_device *mac, + int amount) +{ + struct ieee80211softmac_txrates oldrates; + u8 default_rate = mac->txrates.default_rate; + u8 default_fallback = mac->txrates.default_fallback; + u32 changes = 0; + + //TODO: This is highly experimental code. + // Maybe the dynamic rate selection does not work + // and it has to be removed again. + +printk("badness %d\n", mac->txrate_badness); + mac->txrate_badness += amount; + if (mac->txrate_badness <= -1000) { + /* Very small badness. Try a faster bitrate. */ + if (mac->txrates_change) + memcpy(&oldrates, &mac->txrates, sizeof(oldrates)); + default_rate = raise_rate(mac, default_rate); + changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; + default_fallback = get_fallback_rate(mac, default_rate); + changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK; + mac->txrate_badness = 0; +printk("Bitrate raised to %u\n", default_rate); + } else if (mac->txrate_badness >= 10000) { + /* Very high badness. Try a slower bitrate. */ + if (mac->txrates_change) + memcpy(&oldrates, &mac->txrates, sizeof(oldrates)); + default_rate = lower_rate(mac, default_rate); + changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; + default_fallback = get_fallback_rate(mac, default_rate); + changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK; + mac->txrate_badness = 0; +printk("Bitrate lowered to %u\n", default_rate); + } + + mac->txrates.default_rate = default_rate; + mac->txrates.default_fallback = default_fallback; + + if (changes && mac->txrates_change) + mac->txrates_change(mac->dev, changes, &oldrates); +} + +void ieee80211softmac_fragment_lost(struct net_device *dev, + u16 wl_seq) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + unsigned long flags; + + spin_lock_irqsave(&mac->lock, flags); + ieee80211softmac_add_txrates_badness(mac, 1000); + //TODO + + spin_unlock_irqrestore(&mac->lock, flags); +} + +static int rate_cmp(const void *a_, const void *b_) { + u8 *a, *b; + a = (u8*)a_; + b = (u8*)b_; + return ((*a & ~IEEE80211_BASIC_RATE_MASK) - (*b & ~IEEE80211_BASIC_RATE_MASK)); +} + +/* Allocate a softmac network struct and fill it from a network */ +struct ieee80211softmac_network * +ieee80211softmac_create_network(struct ieee80211softmac_device *mac, + struct ieee80211_network *net) +{ + struct ieee80211softmac_network *softnet; + softnet = kzalloc(sizeof(struct ieee80211softmac_network), GFP_ATOMIC); + if(softnet == NULL) + return NULL; + memcpy(softnet->bssid, net->bssid, ETH_ALEN); + softnet->channel = net->channel; + softnet->essid.len = net->ssid_len; + memcpy(softnet->essid.data, net->ssid, softnet->essid.len); + + /* copy rates over */ + softnet->supported_rates.count = net->rates_len; + memcpy(&softnet->supported_rates.rates[0], net->rates, net->rates_len); + memcpy(&softnet->supported_rates.rates[softnet->supported_rates.count], net->rates_ex, net->rates_ex_len); + softnet->supported_rates.count += net->rates_ex_len; + sort(softnet->supported_rates.rates, softnet->supported_rates.count, sizeof(softnet->supported_rates.rates[0]), rate_cmp, NULL); + + softnet->capabilities = net->capability; + return softnet; +} + + +/* Add a network to the list, while locked */ +void +ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *add_net) +{ + struct list_head *list_ptr; + struct ieee80211softmac_network *softmac_net = NULL; + + list_for_each(list_ptr, &mac->network_list) { + softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list); + if(!memcmp(softmac_net->bssid, add_net->bssid, ETH_ALEN)) + break; + else + softmac_net = NULL; + } + if(softmac_net == NULL) + list_add(&(add_net->list), &mac->network_list); +} + +/* Add a network to the list, with locking */ +void +ieee80211softmac_add_network(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *add_net) +{ + unsigned long flags; + spin_lock_irqsave(&mac->lock, flags); + ieee80211softmac_add_network_locked(mac, add_net); + spin_unlock_irqrestore(&mac->lock, flags); +} + + +/* Delete a network from the list, while locked*/ +void +ieee80211softmac_del_network_locked(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *del_net) +{ + list_del(&(del_net->list)); +} + +/* Delete a network from the list with locking */ +void +ieee80211softmac_del_network(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *del_net) +{ + unsigned long flags; + spin_lock_irqsave(&mac->lock, flags); + ieee80211softmac_del_network_locked(mac, del_net); + spin_unlock_irqrestore(&mac->lock, flags); +} + +/* Get a network from the list by MAC while locked */ +struct ieee80211softmac_network * +ieee80211softmac_get_network_by_bssid_locked(struct ieee80211softmac_device *mac, + u8 *bssid) +{ + struct list_head *list_ptr; + struct ieee80211softmac_network *softmac_net = NULL; + list_for_each(list_ptr, &mac->network_list) { + softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list); + if(!memcmp(softmac_net->bssid, bssid, ETH_ALEN)) + break; + else + softmac_net = NULL; + } + return softmac_net; +} + +/* Get a network from the list by BSSID with locking */ +struct ieee80211softmac_network * +ieee80211softmac_get_network_by_bssid(struct ieee80211softmac_device *mac, + u8 *bssid) +{ + unsigned long flags; + struct ieee80211softmac_network *softmac_net; + + spin_lock_irqsave(&mac->lock, flags); + softmac_net = ieee80211softmac_get_network_by_bssid_locked(mac, bssid); + spin_unlock_irqrestore(&mac->lock, flags); + return softmac_net; +} + +/* Get a network from the list by ESSID while locked */ +struct ieee80211softmac_network * +ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac, + struct ieee80211softmac_essid *essid) +{ + struct list_head *list_ptr; + struct ieee80211softmac_network *softmac_net = NULL; + + list_for_each(list_ptr, &mac->network_list) { + softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list); + if (softmac_net->essid.len == essid->len && + !memcmp(softmac_net->essid.data, essid->data, essid->len)) + return softmac_net; + } + return NULL; +} + +/* Get a network from the list by ESSID with locking */ +struct ieee80211softmac_network * +ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac, + struct ieee80211softmac_essid *essid) +{ + unsigned long flags; + struct ieee80211softmac_network *softmac_net = NULL; + + spin_lock_irqsave(&mac->lock, flags); + softmac_net = ieee80211softmac_get_network_by_essid_locked(mac, essid); + spin_unlock_irqrestore(&mac->lock, flags); + return softmac_net; +} + +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL_GPL(alloc_ieee80211softmac); +EXPORT_SYMBOL_GPL(free_ieee80211softmac); +EXPORT_SYMBOL_GPL(ieee80211softmac_set_rates); +EXPORT_SYMBOL_GPL(ieee80211softmac_start); +EXPORT_SYMBOL_GPL(ieee80211softmac_stop); +EXPORT_SYMBOL_GPL(ieee80211softmac_fragment_lost); +EXPORT_SYMBOL_GPL(ieee80211softmac_clear_pending_work); diff --git a/net/ieee80211/softmac/ieee80211softmac_priv.h b/net/ieee80211/softmac/ieee80211softmac_priv.h new file mode 100644 index 000000000000..591d3bdf37ee --- /dev/null +++ b/net/ieee80211/softmac/ieee80211softmac_priv.h @@ -0,0 +1,206 @@ +#ifndef IEEE80211SOFTMAC_PRIV_H_ +#define IEEE80211SOFTMAC_PRIV_H_ + +#include +#include +#include +#include + + +#define PFX "SoftMAC: " + +#ifdef assert +# undef assert +#endif +#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG +#define assert(expr) \ + do { \ + if (unlikely(!(expr))) { \ + printkl(KERN_ERR PFX "ASSERTION FAILED (%s) at: %s:%d:%s()\n", #expr, \ + __FILE__, __LINE__, __FUNCTION__); \ + } \ + } while (0) +#else +#define assert(expr) do {} while (0) +#endif + +/* rate limited printk(). */ +#ifdef printkl +# undef printkl +#endif +#define printkl(f, x...) do { if (printk_ratelimit()) printk(f ,##x); } while (0) +/* rate limited printk() for debugging */ +#ifdef dprintkl +# undef dprintkl +#endif +#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG +# define dprintkl printkl +#else +# define dprintkl(f, x...) do { /* nothing */ } while (0) +#endif + +/* debugging printk() */ +#ifdef dprintk +# undef dprintk +#endif +#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG +# define dprintk(f, x...) do { printk(f ,##x); } while (0) +#else +# define dprintk(f, x...) do { /* nothing */ } while (0) +#endif + +#ifdef function_enter +# undef function_enter +#endif +#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG +# define function_enter() do { printk(KERN_DEBUG PFX "%s:%d:%s()\n", __FILE__, __LINE__, __FUNCTION__); } while (0) +#else +# define function_enter() do { /* nothing */ } while (0) +#endif + +/* private definitions and prototypes */ + +/*** prototypes from _scan.c */ +void ieee80211softmac_scan(void *sm); +/* for internal use if scanning is needed */ +int ieee80211softmac_start_scan(struct ieee80211softmac_device *mac); +void ieee80211softmac_stop_scan(struct ieee80211softmac_device *mac); +void ieee80211softmac_wait_for_scan(struct ieee80211softmac_device *mac); + +/* for use by _module.c to assign to the callbacks */ +int ieee80211softmac_start_scan_implementation(struct net_device *dev); +void ieee80211softmac_stop_scan_implementation(struct net_device *dev); +void ieee80211softmac_wait_for_scan_implementation(struct net_device *dev); + +/*** Network prototypes from _module.c */ +struct ieee80211softmac_network * ieee80211softmac_create_network( + struct ieee80211softmac_device *mac, struct ieee80211_network *net); +void ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *net); +void ieee80211softmac_add_network(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *net); +void ieee80211softmac_del_network_locked(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *net); +void ieee80211softmac_del_network(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *net); +struct ieee80211softmac_network * ieee80211softmac_get_network_by_bssid_locked( + struct ieee80211softmac_device *mac, u8 *ea); +struct ieee80211softmac_network * ieee80211softmac_get_network_by_bssid( + struct ieee80211softmac_device *mac, u8 *ea); +struct ieee80211softmac_network * ieee80211softmac_get_network_by_ssid_locked( + struct ieee80211softmac_device *mac, u8 *ssid, u8 ssid_len); +struct ieee80211softmac_network * ieee80211softmac_get_network_by_ssid( + struct ieee80211softmac_device *mac, u8 *ssid, u8 ssid_len); + + +/* Rates related */ +u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta); +static inline u8 lower_rate(struct ieee80211softmac_device *mac, u8 rate) { + return ieee80211softmac_lower_rate_delta(mac, rate, 1); +} + +static inline u8 get_fallback_rate(struct ieee80211softmac_device *mac, u8 rate) +{ + return ieee80211softmac_lower_rate_delta(mac, rate, 2); +} + + +/*** prototypes from _io.c */ +int ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac, + void* ptrarg, u32 type, u32 arg); + +/*** prototypes from _auth.c */ +/* do these have to go into the public header? */ +int ieee80211softmac_auth_req(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net); +int ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, int reason); + +/* for use by _module.c to assign to the callbacks */ +int ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth); +int ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_auth *auth); + +/*** prototypes from _assoc.c */ +void ieee80211softmac_assoc_work(void *d); +int ieee80211softmac_handle_assoc_response(struct net_device * dev, + struct ieee80211_assoc_response * resp, + struct ieee80211_network * network); +int ieee80211softmac_handle_disassoc(struct net_device * dev, + struct ieee80211_disassoc * disassoc); +void ieee80211softmac_assoc_timeout(void *d); + +/* some helper functions */ +static inline int ieee80211softmac_scan_handlers_check_self(struct ieee80211softmac_device *sm) +{ + return (sm->start_scan == ieee80211softmac_start_scan_implementation) && + (sm->stop_scan == ieee80211softmac_stop_scan_implementation) && + (sm->wait_for_scan == ieee80211softmac_wait_for_scan_implementation); +} + +static inline int ieee80211softmac_scan_sanity_check(struct ieee80211softmac_device *sm) +{ + return ((sm->start_scan != ieee80211softmac_start_scan_implementation) && + (sm->stop_scan != ieee80211softmac_stop_scan_implementation) && + (sm->wait_for_scan != ieee80211softmac_wait_for_scan_implementation) + ) || ieee80211softmac_scan_handlers_check_self(sm); +} + +#define IEEE80211SOFTMAC_PROBE_DELAY HZ/2 +#define IEEE80211SOFTMAC_WORKQUEUE_NAME_LEN (17 + IFNAMSIZ) + +struct ieee80211softmac_network { + struct list_head list; /* List */ + /* Network information copied from ieee80211_network */ + u8 bssid[ETH_ALEN]; + u8 channel; + struct ieee80211softmac_essid essid; + + struct ieee80211softmac_ratesinfo supported_rates; + + /* SoftMAC specific */ + u16 authenticating:1, /* Status Flags */ + authenticated:1, + auth_desynced_once:1; + + u16 capabilities; /* Capabilities bitfield */ + u8 challenge_len; /* Auth Challenge length */ + char *challenge; /* Challenge Text */ +}; + +/* structure used to keep track of networks we're auth'ing to */ +struct ieee80211softmac_auth_queue_item { + struct list_head list; /* List head */ + struct ieee80211softmac_network *net; /* Network to auth */ + struct ieee80211softmac_device *mac; /* SoftMAC device */ + u8 retry; /* Retry limit */ + u8 state; /* Auth State */ + struct work_struct work; /* Work queue */ +}; + +/* scanning information */ +struct ieee80211softmac_scaninfo { + u8 current_channel_idx, + number_channels; + struct ieee80211_channel *channels; + u8 started:1, + stop:1; + u8 skip_flags; + struct completion finished; + struct work_struct softmac_scan; +}; + +/* private event struct */ +struct ieee80211softmac_event { + struct list_head list; + int event_type; + void *event_context; + struct work_struct work; + notify_function_ptr fun; + void *context; + struct ieee80211softmac_device *mac; +}; + +void ieee80211softmac_call_events(struct ieee80211softmac_device *mac, int event, void *event_context); +void ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_context); +int ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac, + int event, void *event_context, notify_function_ptr fun, void *context, gfp_t gfp_mask); + +#endif /* IEEE80211SOFTMAC_PRIV_H_ */ diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c new file mode 100644 index 000000000000..b4b44fa8727d --- /dev/null +++ b/net/ieee80211/softmac/ieee80211softmac_scan.c @@ -0,0 +1,216 @@ +/* + * Scanning routines. + * + * These are not exported because they're assigned to the function pointers. + */ + +#include +#include "ieee80211softmac_priv.h" + +/* internal, use to trigger scanning if needed. + * Returns -EBUSY if already scanning, + * result of start_scan otherwise */ +int +ieee80211softmac_start_scan(struct ieee80211softmac_device *sm) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&sm->lock, flags); + if (sm->scanning) + { + spin_unlock_irqrestore(&sm->lock, flags); + return -EINPROGRESS; + } + sm->scanning = 1; + spin_unlock_irqrestore(&sm->lock, flags); + + ret = sm->start_scan(sm->dev); + if (ret) { + spin_lock_irqsave(&sm->lock, flags); + sm->scanning = 0; + spin_unlock_irqrestore(&sm->lock, flags); + } + return ret; +} + +void +ieee80211softmac_stop_scan(struct ieee80211softmac_device *sm) +{ + unsigned long flags; + + spin_lock_irqsave(&sm->lock, flags); + + if (!sm->scanning) { + spin_unlock_irqrestore(&sm->lock, flags); + return; + } + + spin_unlock_irqrestore(&sm->lock, flags); + sm->stop_scan(sm->dev); +} + +void +ieee80211softmac_wait_for_scan(struct ieee80211softmac_device *sm) +{ + unsigned long flags; + + spin_lock_irqsave(&sm->lock, flags); + + if (!sm->scanning) { + spin_unlock_irqrestore(&sm->lock, flags); + return; + } + + spin_unlock_irqrestore(&sm->lock, flags); + sm->wait_for_scan(sm->dev); +} + + +/* internal scanning implementation follows */ +void ieee80211softmac_scan(void *d) +{ + int invalid_channel; + u8 current_channel_idx; + struct ieee80211softmac_device *sm = (struct ieee80211softmac_device *)d; + struct ieee80211softmac_scaninfo *si = sm->scaninfo; + unsigned long flags; + + while (!(si->stop) && (si->current_channel_idx < si->number_channels)) { + current_channel_idx = si->current_channel_idx; + si->current_channel_idx++; /* go to the next channel */ + + invalid_channel = (si->skip_flags & si->channels[current_channel_idx].flags); + + if (!invalid_channel) { + sm->set_channel(sm->dev, si->channels[current_channel_idx].channel); + //TODO: Probe the channel + // FIXME make this user configurable (active/passive) + if(ieee80211softmac_send_mgt_frame(sm, NULL, IEEE80211_STYPE_PROBE_REQ, 0)) + printkl(KERN_DEBUG PFX "Sending Probe Request Failed\n"); + + /* also send directed management frame for the network we're looking for */ + // TODO: is this if correct, or should we do this only if scanning from assoc request? + if (sm->associnfo.req_essid.len) + ieee80211softmac_send_mgt_frame(sm, &sm->associnfo.req_essid, IEEE80211_STYPE_PROBE_REQ, 0); + queue_delayed_work(sm->workqueue, &si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY); + return; + } else { + dprintk(PFX "Not probing Channel %d (not allowed here)\n", si->channels[current_channel_idx].channel); + } + } + + spin_lock_irqsave(&sm->lock, flags); + cancel_delayed_work(&si->softmac_scan); + si->started = 0; + spin_unlock_irqrestore(&sm->lock, flags); + + dprintk(PFX "Scanning finished\n"); + ieee80211softmac_scan_finished(sm); + complete_all(&sm->scaninfo->finished); +} + +static inline struct ieee80211softmac_scaninfo *allocate_scaninfo(struct ieee80211softmac_device *mac) +{ + /* ugh. can we call this without having the spinlock held? */ + struct ieee80211softmac_scaninfo *info = kmalloc(sizeof(struct ieee80211softmac_scaninfo), GFP_ATOMIC); + if (unlikely(!info)) + return NULL; + INIT_WORK(&info->softmac_scan, ieee80211softmac_scan, mac); + init_completion(&info->finished); + return info; +} + +int ieee80211softmac_start_scan_implementation(struct net_device *dev) +{ + struct ieee80211softmac_device *sm = ieee80211_priv(dev); + unsigned long flags; + + if (!(dev->flags & IFF_UP)) + return -ENODEV; + + assert(ieee80211softmac_scan_handlers_check_self(sm)); + if (!ieee80211softmac_scan_handlers_check_self(sm)) + return -EINVAL; + + spin_lock_irqsave(&sm->lock, flags); + /* it looks like we need to hold the lock here + * to make sure we don't allocate two of these... */ + if (unlikely(!sm->scaninfo)) + sm->scaninfo = allocate_scaninfo(sm); + if (unlikely(!sm->scaninfo)) { + spin_unlock_irqrestore(&sm->lock, flags); + return -ENOMEM; + } + + sm->scaninfo->skip_flags = IEEE80211_CH_INVALID; + if (0 /* not scanning in IEEE802.11b */)//TODO + sm->scaninfo->skip_flags |= IEEE80211_CH_B_ONLY; + if (0 /* IEEE802.11a */) {//TODO + sm->scaninfo->channels = sm->ieee->geo.a; + sm->scaninfo->number_channels = sm->ieee->geo.a_channels; + } else { + sm->scaninfo->channels = sm->ieee->geo.bg; + sm->scaninfo->number_channels = sm->ieee->geo.bg_channels; + } + dprintk(PFX "Start scanning with channel: %d\n", sm->scaninfo->channels[0].channel); + dprintk(PFX "Scanning %d channels\n", sm->scaninfo->number_channels); + sm->scaninfo->current_channel_idx = 0; + sm->scaninfo->started = 1; + INIT_COMPLETION(sm->scaninfo->finished); + queue_work(sm->workqueue, &sm->scaninfo->softmac_scan); + spin_unlock_irqrestore(&sm->lock, flags); + return 0; +} + +void ieee80211softmac_stop_scan_implementation(struct net_device *dev) +{ + struct ieee80211softmac_device *sm = ieee80211_priv(dev); + unsigned long flags; + + assert(ieee80211softmac_scan_handlers_check_self(sm)); + if (!ieee80211softmac_scan_handlers_check_self(sm)) + return; + + spin_lock_irqsave(&sm->lock, flags); + assert(sm->scaninfo != NULL); + if (sm->scaninfo) { + if (sm->scaninfo->started) + sm->scaninfo->stop = 1; + else + complete_all(&sm->scaninfo->finished); + } + spin_unlock_irqrestore(&sm->lock, flags); +} + +void ieee80211softmac_wait_for_scan_implementation(struct net_device *dev) +{ + struct ieee80211softmac_device *sm = ieee80211_priv(dev); + unsigned long flags; + + assert(ieee80211softmac_scan_handlers_check_self(sm)); + if (!ieee80211softmac_scan_handlers_check_self(sm)) + return; + + spin_lock_irqsave(&sm->lock, flags); + if (!sm->scaninfo->started) { + spin_unlock_irqrestore(&sm->lock, flags); + return; + } + spin_unlock_irqrestore(&sm->lock, flags); + wait_for_completion(&sm->scaninfo->finished); +} + +/* this is what drivers (that do scanning) call when they're done */ +void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm) +{ + unsigned long flags; + + spin_lock_irqsave(&sm->lock, flags); + sm->scanning = 0; + spin_unlock_irqrestore(&sm->lock, flags); + + ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL); +} + +EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished); diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c new file mode 100644 index 000000000000..bae5fcc11967 --- /dev/null +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c @@ -0,0 +1,390 @@ +/* + * This file contains our _wx handlers. Make sure you EXPORT_SYMBOL_GPL them + */ + +#include "ieee80211softmac_priv.h" + +#include + + +int +ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); + return ieee80211softmac_start_scan(sm); +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan); + + +int +ieee80211softmac_wx_get_scan_results(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); + return ieee80211_wx_get_scan(sm->ieee, info, data, extra); +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results); + +int +ieee80211softmac_wx_set_essid(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); + int length = 0; + unsigned long flags; + + spin_lock_irqsave(&sm->lock, flags); + + sm->associnfo.static_essid = 0; + + if (data->essid.flags && data->essid.length && extra /*required?*/) { + length = min(data->essid.length - 1, IW_ESSID_MAX_SIZE); + if (length) { + memcpy(sm->associnfo.req_essid.data, extra, length); + sm->associnfo.static_essid = 1; + } + } + sm->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; + + /* set our requested ESSID length. + * If applicable, we have already copied the data in */ + sm->associnfo.req_essid.len = length; + + /* queue lower level code to do work (if necessary) */ + queue_work(sm->workqueue, &sm->associnfo.work); + + spin_unlock_irqrestore(&sm->lock, flags); + return 0; +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid); + +int +ieee80211softmac_wx_get_essid(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); + unsigned long flags; + + /* avoid getting inconsistent information */ + spin_lock_irqsave(&sm->lock, flags); + /* If all fails, return ANY (empty) */ + data->essid.length = 0; + data->essid.flags = 0; /* active */ + + /* If we have a statically configured ESSID then return it */ + if (sm->associnfo.static_essid) { + data->essid.length = sm->associnfo.req_essid.len; + data->essid.flags = 1; /* active */ + memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len); + } + + /* If we're associating/associated, return that */ + if (sm->associated || sm->associnfo.associating) { + data->essid.length = sm->associnfo.associate_essid.len; + data->essid.flags = 1; /* active */ + memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len); + } + spin_unlock_irqrestore(&sm->lock, flags); + return 0; +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid); + +int +ieee80211softmac_wx_set_rate(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); + struct ieee80211_device *ieee = mac->ieee; + unsigned long flags; + s32 in_rate = data->bitrate.value; + u8 rate; + int is_ofdm = 0; + int err = -EINVAL; + + if (in_rate == -1) { + /* automatic detect */ + if (ieee->modulation & IEEE80211_OFDM_MODULATION) + in_rate = 54000000; + else + in_rate = 11000000; + } + + switch (in_rate) { + case 1000000: + rate = IEEE80211_CCK_RATE_1MB; + break; + case 2000000: + rate = IEEE80211_CCK_RATE_2MB; + break; + case 5500000: + rate = IEEE80211_CCK_RATE_5MB; + break; + case 11000000: + rate = IEEE80211_CCK_RATE_11MB; + break; + case 6000000: + rate = IEEE80211_OFDM_RATE_6MB; + is_ofdm = 1; + break; + case 9000000: + rate = IEEE80211_OFDM_RATE_9MB; + is_ofdm = 1; + break; + case 12000000: + rate = IEEE80211_OFDM_RATE_12MB; + is_ofdm = 1; + break; + case 18000000: + rate = IEEE80211_OFDM_RATE_18MB; + is_ofdm = 1; + break; + case 24000000: + rate = IEEE80211_OFDM_RATE_24MB; + is_ofdm = 1; + break; + case 36000000: + rate = IEEE80211_OFDM_RATE_36MB; + is_ofdm = 1; + break; + case 48000000: + rate = IEEE80211_OFDM_RATE_48MB; + is_ofdm = 1; + break; + case 54000000: + rate = IEEE80211_OFDM_RATE_54MB; + is_ofdm = 1; + break; + default: + goto out; + } + + spin_lock_irqsave(&mac->lock, flags); + + /* Check if correct modulation for this PHY. */ + if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION)) + goto out_unlock; + + mac->txrates.default_rate = rate; + mac->txrates.default_fallback = lower_rate(mac, rate); + err = 0; + +out_unlock: + spin_unlock_irqrestore(&mac->lock, flags); +out: + return err; +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_rate); + +int +ieee80211softmac_wx_get_rate(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); + unsigned long flags; + int err = -EINVAL; + + spin_lock_irqsave(&mac->lock, flags); + switch (mac->txrates.default_rate) { + case IEEE80211_CCK_RATE_1MB: + data->bitrate.value = 1000000; + break; + case IEEE80211_CCK_RATE_2MB: + data->bitrate.value = 2000000; + break; + case IEEE80211_CCK_RATE_5MB: + data->bitrate.value = 5500000; + break; + case IEEE80211_CCK_RATE_11MB: + data->bitrate.value = 11000000; + break; + case IEEE80211_OFDM_RATE_6MB: + data->bitrate.value = 6000000; + break; + case IEEE80211_OFDM_RATE_9MB: + data->bitrate.value = 9000000; + break; + case IEEE80211_OFDM_RATE_12MB: + data->bitrate.value = 12000000; + break; + case IEEE80211_OFDM_RATE_18MB: + data->bitrate.value = 18000000; + break; + case IEEE80211_OFDM_RATE_24MB: + data->bitrate.value = 24000000; + break; + case IEEE80211_OFDM_RATE_36MB: + data->bitrate.value = 36000000; + break; + case IEEE80211_OFDM_RATE_48MB: + data->bitrate.value = 48000000; + break; + case IEEE80211_OFDM_RATE_54MB: + data->bitrate.value = 54000000; + break; + default: + assert(0); + goto out_unlock; + } + err = 0; +out_unlock: + spin_unlock_irqrestore(&mac->lock, flags); + + return err; +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_rate); + +int +ieee80211softmac_wx_get_wap(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); + int err = 0; + unsigned long flags; + + spin_lock_irqsave(&mac->lock, flags); + if (mac->associnfo.bssvalid) + memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN); + else + memset(data->ap_addr.sa_data, 0xff, ETH_ALEN); + data->ap_addr.sa_family = ARPHRD_ETHER; + spin_unlock_irqrestore(&mac->lock, flags); + return err; +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap); + +int +ieee80211softmac_wx_set_wap(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); + static const unsigned char any[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + static const unsigned char off[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + unsigned long flags; + + /* sanity check */ + if (data->ap_addr.sa_family != ARPHRD_ETHER) { + return -EINVAL; + } + + spin_lock_irqsave(&mac->lock, flags); + if (!memcmp(any, data->ap_addr.sa_data, ETH_ALEN) || + !memcmp(off, data->ap_addr.sa_data, ETH_ALEN)) { + queue_work(mac->workqueue, &mac->associnfo.work); + goto out; + } else { + if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) { + if (mac->associnfo.associating || mac->associated) { + /* bssid unchanged and associated or associating - just return */ + goto out; + } + } else { + /* copy new value in data->ap_addr.sa_data to bssid */ + memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN); + } + /* queue associate if new bssid or (old one again and not associated) */ + queue_work(mac->workqueue,&mac->associnfo.work); + } + +out: + spin_unlock_irqrestore(&mac->lock, flags); + return 0; +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap); + +int +ieee80211softmac_wx_set_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + unsigned long flags; + int err = 0; + char *buf; + int i; + + spin_lock_irqsave(&mac->lock, flags); + /* bleh. shouldn't be locked for that kmalloc... */ + + if (wrqu->data.length) { + if ((wrqu->data.length < 2) || (extra[1]+2 != wrqu->data.length)) { + /* this is an IE, so the length must be + * correct. Is it possible though that + * more than one IE is passed in? + */ + err = -EINVAL; + goto out; + } + if (mac->wpa.IEbuflen <= wrqu->data.length) { + buf = kmalloc(wrqu->data.length, GFP_ATOMIC); + if (!buf) { + err = -ENOMEM; + goto out; + } + kfree(mac->wpa.IE); + mac->wpa.IE = buf; + mac->wpa.IEbuflen = wrqu->data.length; + } + memcpy(mac->wpa.IE, extra, wrqu->data.length); + dprintk(KERN_INFO PFX "generic IE set to "); + for (i=0;idata.length;i++) + dprintk("%.2x", mac->wpa.IE[i]); + dprintk("\n"); + mac->wpa.IElen = wrqu->data.length; + } else { + kfree(mac->wpa.IE); + mac->wpa.IE = NULL; + mac->wpa.IElen = 0; + mac->wpa.IEbuflen = 0; + } + + out: + spin_unlock_irqrestore(&mac->lock, flags); + return err; +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie); + +int +ieee80211softmac_wx_get_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + unsigned long flags; + int err = 0; + int space = wrqu->data.length; + + spin_lock_irqsave(&mac->lock, flags); + + wrqu->data.length = 0; + + if (mac->wpa.IE && mac->wpa.IElen) { + wrqu->data.length = mac->wpa.IElen; + if (mac->wpa.IElen <= space) + memcpy(extra, mac->wpa.IE, mac->wpa.IElen); + else + err = -E2BIG; + } + spin_unlock_irqrestore(&mac->lock, flags); + return err; +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie); + -- cgit v1.2.3 From 5c4df6da580b9317dc0856e235232b95cbc8251c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 6 Jan 2006 01:43:45 +0100 Subject: [PATCH] softmac: convert to use global workqueue Convert softmac to use global workqueue instead of private one... Signed-off-by: John W. Linville --- include/net/ieee80211softmac.h | 3 --- net/ieee80211/softmac/ieee80211softmac_assoc.c | 4 ++-- net/ieee80211/softmac/ieee80211softmac_auth.c | 6 +++--- net/ieee80211/softmac/ieee80211softmac_event.c | 2 +- net/ieee80211/softmac/ieee80211softmac_module.c | 7 +------ net/ieee80211/softmac/ieee80211softmac_scan.c | 4 ++-- net/ieee80211/softmac/ieee80211softmac_wx.c | 6 +++--- 7 files changed, 12 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h index 0b5f2df29f02..7264bd87c7d7 100644 --- a/include/net/ieee80211softmac.h +++ b/include/net/ieee80211softmac.h @@ -177,9 +177,6 @@ struct ieee80211softmac_device { u8 scanning:1, /* protects scanning from being done multiple times at once */ associated:1; - /* workquere for scannning, ... */ - struct workqueue_struct *workqueue; - struct ieee80211softmac_scaninfo *scaninfo; struct ieee80211softmac_assoc_info associnfo; diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c index d491005d6cfd..98487448f2d3 100644 --- a/net/ieee80211/softmac/ieee80211softmac_assoc.c +++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c @@ -29,7 +29,7 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft /* Set a timer for timeout */ /* FIXME: make timeout configurable */ - queue_delayed_work(mac->workqueue, &mac->associnfo.timeout, 5 * HZ); + schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ); } void @@ -324,7 +324,7 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev, network->authenticated = 0; /* we don't want to do this more than once ... */ network->auth_desynced_once = 1; - queue_work(mac->workqueue, &mac->associnfo.work); + schedule_work(&mac->associnfo.work); break; } default: diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c index 286f0718eb7e..5a773528110f 100644 --- a/net/ieee80211/softmac/ieee80211softmac_auth.c +++ b/net/ieee80211/softmac/ieee80211softmac_auth.c @@ -36,7 +36,7 @@ ieee80211softmac_auth_req(struct ieee80211softmac_device *mac, /* add to list */ list_add_tail(&auth->list, &mac->auth_queue); - queue_work(mac->workqueue, &auth->work); + schedule_work(&auth->work); spin_unlock_irqrestore(&mac->lock, flags); return 0; @@ -67,7 +67,7 @@ ieee80211softmac_auth_queue(void *data) net->authenticated = 0; net->authenticating = 1; /* add a timeout call so we eventually give up waiting for an auth reply */ - queue_delayed_work(mac->workqueue, &auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT); + schedule_delayed_work(&auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT); auth->retry--; spin_unlock_irqrestore(&mac->lock, flags); if (ieee80211softmac_send_mgt_frame(mac, auth->net, IEEE80211_STYPE_AUTH, auth->state)) @@ -279,7 +279,7 @@ ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac, kfree(net); /* let's try to re-associate */ - queue_work(mac->workqueue, &mac->associnfo.work); + schedule_work(&mac->associnfo.work); spin_unlock_irqrestore(&mac->lock, flags); } diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c index 0d0a8327252f..b640a58a2687 100644 --- a/net/ieee80211/softmac/ieee80211softmac_event.c +++ b/net/ieee80211/softmac/ieee80211softmac_event.c @@ -118,7 +118,7 @@ ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int eve if ((eventptr->event_type == event || eventptr->event_type == -1) && (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) { list_del(&eventptr->list); - queue_work(mac->workqueue, &eventptr->work); + schedule_work(&eventptr->work); } } } diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c index 1244a659cd83..79ef959a2c11 100644 --- a/net/ieee80211/softmac/ieee80211softmac_module.c +++ b/net/ieee80211/softmac/ieee80211softmac_module.c @@ -22,10 +22,6 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv) * (once they're written) */ - softmac->workqueue = create_workqueue("80211softmac"); - if (!softmac->workqueue) - goto err_free_ieee80211; - INIT_LIST_HEAD(&softmac->auth_queue); INIT_LIST_HEAD(&softmac->network_list); INIT_LIST_HEAD(&softmac->events); @@ -90,7 +86,7 @@ ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm) cancel_delayed_work(&eventptr->work); spin_unlock_irqrestore(&sm->lock, flags); - flush_workqueue(sm->workqueue); + flush_scheduled_work(); // now we should be save and no longer need locking... spin_lock_irqsave(&sm->lock, flags); @@ -121,7 +117,6 @@ void free_ieee80211softmac(struct net_device *dev) { struct ieee80211softmac_device *sm = ieee80211_priv(dev); ieee80211softmac_clear_pending_work(sm); - destroy_workqueue(sm->workqueue); kfree(sm->scaninfo); kfree(sm->wpa.IE); free_ieee80211(dev); diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c index b4b44fa8727d..1a1eda434cfd 100644 --- a/net/ieee80211/softmac/ieee80211softmac_scan.c +++ b/net/ieee80211/softmac/ieee80211softmac_scan.c @@ -93,7 +93,7 @@ void ieee80211softmac_scan(void *d) // TODO: is this if correct, or should we do this only if scanning from assoc request? if (sm->associnfo.req_essid.len) ieee80211softmac_send_mgt_frame(sm, &sm->associnfo.req_essid, IEEE80211_STYPE_PROBE_REQ, 0); - queue_delayed_work(sm->workqueue, &si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY); + schedule_delayed_work(&si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY); return; } else { dprintk(PFX "Not probing Channel %d (not allowed here)\n", si->channels[current_channel_idx].channel); @@ -158,7 +158,7 @@ int ieee80211softmac_start_scan_implementation(struct net_device *dev) sm->scaninfo->current_channel_idx = 0; sm->scaninfo->started = 1; INIT_COMPLETION(sm->scaninfo->finished); - queue_work(sm->workqueue, &sm->scaninfo->softmac_scan); + schedule_work(&sm->scaninfo->softmac_scan); spin_unlock_irqrestore(&sm->lock, flags); return 0; } diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c index bae5fcc11967..ca11737de6f5 100644 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c @@ -58,7 +58,7 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, sm->associnfo.req_essid.len = length; /* queue lower level code to do work (if necessary) */ - queue_work(sm->workqueue, &sm->associnfo.work); + schedule_work(&sm->associnfo.work); spin_unlock_irqrestore(&sm->lock, flags); return 0; @@ -286,7 +286,7 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, spin_lock_irqsave(&mac->lock, flags); if (!memcmp(any, data->ap_addr.sa_data, ETH_ALEN) || !memcmp(off, data->ap_addr.sa_data, ETH_ALEN)) { - queue_work(mac->workqueue, &mac->associnfo.work); + schedule_work(&mac->associnfo.work); goto out; } else { if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) { @@ -299,7 +299,7 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN); } /* queue associate if new bssid or (old one again and not associated) */ - queue_work(mac->workqueue,&mac->associnfo.work); + schedule_work(&mac->associnfo.work); } out: -- cgit v1.2.3 From 4855d25b1ef9d74aeb29c2e46f0d6a289922eab6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 12 Jan 2006 21:12:59 +0100 Subject: [PATCH] softmac: add copyright and license headers add copyright and license headers to all softmac files Signed-off-by: John W. Linville --- include/net/ieee80211softmac.h | 26 +++++++++++++++++++++ include/net/ieee80211softmac_wx.h | 28 +++++++++++++++++++++++ net/ieee80211/softmac/ieee80211softmac_assoc.c | 26 +++++++++++++++++++++ net/ieee80211/softmac/ieee80211softmac_auth.c | 26 +++++++++++++++++++++ net/ieee80211/softmac/ieee80211softmac_event.c | 30 ++++++++++++++++++++++--- net/ieee80211/softmac/ieee80211softmac_module.c | 26 +++++++++++++++++++++ net/ieee80211/softmac/ieee80211softmac_priv.h | 26 +++++++++++++++++++++ net/ieee80211/softmac/ieee80211softmac_scan.c | 22 ++++++++++++++++++ net/ieee80211/softmac/ieee80211softmac_wx.c | 22 ++++++++++++++++++ 9 files changed, 229 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h index 7264bd87c7d7..b971d8c82bdd 100644 --- a/include/net/ieee80211softmac.h +++ b/include/net/ieee80211softmac.h @@ -1,3 +1,29 @@ +/* + * ieee80211softmac.h - public interface to the softmac + * + * Copyright (c) 2005 Johannes Berg + * Joseph Jezak + * Larry Finger + * Danny van Dyk + * Michael Buesch + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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. 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + #ifndef IEEE80211SOFTMAC_H_ #define IEEE80211SOFTMAC_H_ diff --git a/include/net/ieee80211softmac_wx.h b/include/net/ieee80211softmac_wx.h index 165ea4c78ee0..3e0be453ecea 100644 --- a/include/net/ieee80211softmac_wx.h +++ b/include/net/ieee80211softmac_wx.h @@ -1,3 +1,31 @@ +/* + * This file contains the prototypes for the wireless extension + * handlers that the softmac API provides. Include this file to + * use the wx handlers, you can assign these directly. + * + * Copyright (c) 2005 Johannes Berg + * Joseph Jezak + * Larry Finger + * Danny van Dyk + * Michael Buesch + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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. 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + #ifndef _IEEE80211SOFTMAC_WX_H #define _IEEE80211SOFTMAC_WX_H diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c index aef018f8000e..b29fb1cc72c6 100644 --- a/net/ieee80211/softmac/ieee80211softmac_assoc.c +++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c @@ -1,3 +1,29 @@ +/* + * This file contains the softmac's association logic. + * + * Copyright (c) 2005 Johannes Berg + * Joseph Jezak + * Larry Finger + * Danny van Dyk + * Michael Buesch + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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. 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + #include "ieee80211softmac_priv.h" /* diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c index 6eab2be91870..84ad029031ba 100644 --- a/net/ieee80211/softmac/ieee80211softmac_auth.c +++ b/net/ieee80211/softmac/ieee80211softmac_auth.c @@ -1,3 +1,29 @@ +/* + * This file contains the softmac's authentication logic. + * + * Copyright (c) 2005 Johannes Berg + * Joseph Jezak + * Larry Finger + * Danny van Dyk + * Michael Buesch + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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. 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + #include "ieee80211softmac_priv.h" static void ieee80211softmac_auth_queue(void *data); diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c index b640a58a2687..0ed8e304ecf3 100644 --- a/net/ieee80211/softmac/ieee80211softmac_event.c +++ b/net/ieee80211/softmac/ieee80211softmac_event.c @@ -1,9 +1,33 @@ -#include "ieee80211softmac_priv.h" - /* * Event system - * Also see comments in public header file + * Also see comments in public header file and longer explanation below. + * + * Copyright (c) 2005 Johannes Berg + * Joseph Jezak + * Larry Finger + * Danny van Dyk + * Michael Buesch + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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. 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + +#include "ieee80211softmac_priv.h" + +/* * Each event has associated to it * - an event type (see constants in public header) * - an event context (see below) diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c index a5699966fbc5..ebb9dbe4178f 100644 --- a/net/ieee80211/softmac/ieee80211softmac_module.c +++ b/net/ieee80211/softmac/ieee80211softmac_module.c @@ -1,3 +1,29 @@ +/* + * Contains some basic softmac functions along with module registration code etc. + * + * Copyright (c) 2005 Johannes Berg + * Joseph Jezak + * Larry Finger + * Danny van Dyk + * Michael Buesch + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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. 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + #include "ieee80211softmac_priv.h" #include diff --git a/net/ieee80211/softmac/ieee80211softmac_priv.h b/net/ieee80211/softmac/ieee80211softmac_priv.h index 44a8ba45355c..5b98c3e28900 100644 --- a/net/ieee80211/softmac/ieee80211softmac_priv.h +++ b/net/ieee80211/softmac/ieee80211softmac_priv.h @@ -1,3 +1,29 @@ +/* + * Internal softmac API definitions. + * + * Copyright (c) 2005 Johannes Berg + * Joseph Jezak + * Larry Finger + * Danny van Dyk + * Michael Buesch + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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. 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + #ifndef IEEE80211SOFTMAC_PRIV_H_ #define IEEE80211SOFTMAC_PRIV_H_ diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c index 30e79d45af6b..d90d31f22dd5 100644 --- a/net/ieee80211/softmac/ieee80211softmac_scan.c +++ b/net/ieee80211/softmac/ieee80211softmac_scan.c @@ -2,6 +2,28 @@ * Scanning routines. * * These are not exported because they're assigned to the function pointers. + * + * Copyright (c) 2005 Johannes Berg + * Joseph Jezak + * Larry Finger + * Danny van Dyk + * Michael Buesch + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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. 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. */ #include diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c index ca11737de6f5..17d30f4e7fe7 100644 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c @@ -1,5 +1,27 @@ /* * This file contains our _wx handlers. Make sure you EXPORT_SYMBOL_GPL them + * + * Copyright (c) 2005 Johannes Berg + * Joseph Jezak + * Larry Finger + * Danny van Dyk + * Michael Buesch + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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. 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. */ #include "ieee80211softmac_priv.h" -- cgit v1.2.3 From a5cdc030030ef5a16e48aebeb65067bdc3120899 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 23 Mar 2006 01:16:06 -0800 Subject: [IPV4]: Add fib rule netlink notifications To really make sense of route notifications in the presence of multiple tables, userspace also needs to be notified about routing rule updates. Notifications are sent to the so far unused RTNLGRP_NOP1 (now RTNLGRP_RULE) group. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/rtnetlink.h | 4 +++- net/ipv4/fib_rules.c | 27 ++++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index d572d5376319..df0cdd41085c 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -839,6 +839,7 @@ enum #define RTMGRP_IPV4_IFADDR 0x10 #define RTMGRP_IPV4_MROUTE 0x20 #define RTMGRP_IPV4_ROUTE 0x40 +#define RTMGRP_IPV4_RULE 0x80 #define RTMGRP_IPV6_IFADDR 0x100 #define RTMGRP_IPV6_MROUTE 0x200 @@ -869,7 +870,8 @@ enum rtnetlink_groups { #define RTNLGRP_IPV4_MROUTE RTNLGRP_IPV4_MROUTE RTNLGRP_IPV4_ROUTE, #define RTNLGRP_IPV4_ROUTE RTNLGRP_IPV4_ROUTE - RTNLGRP_NOP1, + RTNLGRP_IPV4_RULE, +#define RTNLGRP_IPV4_RULE RTNLGRP_IPV4_RULE RTNLGRP_IPV6_IFADDR, #define RTNLGRP_IPV6_IFADDR RTNLGRP_IPV6_IFADDR RTNLGRP_IPV6_MROUTE, diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index 768e8f5d7daa..ec566f3e66c7 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -104,6 +104,8 @@ static struct hlist_head fib_rules; /* writer func called from netlink -- rtnl_sem hold*/ +static void rtmsg_rule(int, struct fib_rule *); + int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) { struct rtattr **rta = arg; @@ -131,6 +133,7 @@ int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) hlist_del_rcu(&r->hlist); r->r_dead = 1; + rtmsg_rule(RTM_DELRULE, r); fib_rule_put(r); err = 0; break; @@ -253,6 +256,7 @@ int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) else hlist_add_before_rcu(&new_r->hlist, &r->hlist); + rtmsg_rule(RTM_NEWRULE, new_r); return 0; } @@ -382,14 +386,14 @@ static struct notifier_block fib_rules_notifier = { static __inline__ int inet_fill_rule(struct sk_buff *skb, struct fib_rule *r, - struct netlink_callback *cb, + u32 pid, u32 seq, int event, unsigned int flags) { struct rtmsg *rtm; struct nlmsghdr *nlh; unsigned char *b = skb->tail; - nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWRULE, sizeof(*rtm), flags); + nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags); rtm = NLMSG_DATA(nlh); rtm->rtm_family = AF_INET; rtm->rtm_dst_len = r->r_dst_len; @@ -430,6 +434,21 @@ rtattr_failure: /* callers should hold rtnl semaphore */ +static void rtmsg_rule(int event, struct fib_rule *r) +{ + int size = NLMSG_SPACE(sizeof(struct rtmsg) + 128); + struct sk_buff *skb = alloc_skb(size, GFP_KERNEL); + + if (!skb) + netlink_set_err(rtnl, 0, RTNLGRP_IPV4_RULE, ENOBUFS); + else if (inet_fill_rule(skb, r, 0, 0, event, 0) < 0) { + kfree_skb(skb); + netlink_set_err(rtnl, 0, RTNLGRP_IPV4_RULE, EINVAL); + } else { + netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV4_RULE, GFP_KERNEL); + } +} + int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) { int idx = 0; @@ -442,7 +461,9 @@ int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) if (idx < s_idx) continue; - if (inet_fill_rule(skb, r, cb, NLM_F_MULTI) < 0) + if (inet_fill_rule(skb, r, NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, + RTM_NEWRULE, NLM_F_MULTI) < 0) break; idx++; } -- cgit v1.2.3 From af36e6b6d7f4ad7a5ccfd14dfa71ec941255f93d Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 23 Mar 2006 01:28:06 -0800 Subject: [TG3]: Add 5755 support Add support for new chip 5755 which is very similar to 5787. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 37 +++++++++++++++++++++++++++++++------ drivers/net/tg3.h | 6 +++++- include/linux/pci_ids.h | 2 ++ 3 files changed, 38 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 88829eb9568e..c69c8df088d0 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -225,6 +225,10 @@ static struct pci_device_id tg3_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M, @@ -4557,6 +4561,7 @@ static int tg3_chip_reset(struct tg3 *tp) } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) tw32(GRC_FASTBOOT_PC, 0); @@ -6152,6 +6157,9 @@ static int tg3_reset_hw(struct tg3 *tp) gpio_mask |= GRC_LCLCTRL_GPIO_OE3 | GRC_LCLCTRL_GPIO_OUTPUT3; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + gpio_mask |= GRC_LCLCTRL_GPIO_UART_SEL; + tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask; /* GPIO1 must be driven high for eeprom write protect */ @@ -6191,7 +6199,8 @@ static int tg3_reset_hw(struct tg3 *tp) } /* Enable host coalescing bug fix */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)) val |= (1 << 29); tw32_f(WDMAC_MODE, val); @@ -6249,6 +6258,9 @@ static int tg3_reset_hw(struct tg3 *tp) udelay(100); tp->rx_mode = RX_MODE_ENABLE; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE; + tw32_f(MAC_RX_MODE, tp->rx_mode); udelay(10); @@ -7907,7 +7919,8 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data) return 0; } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) ethtool_op_set_tx_hw_csum(dev, data); else ethtool_op_set_tx_csum(dev, data); @@ -8332,7 +8345,8 @@ static int tg3_test_memory(struct tg3 *tp) int i; if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) mem_tbl = mem_tbl_5755; else mem_tbl = mem_tbl_5705; @@ -9310,6 +9324,7 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, nvram_cmd |= NVRAM_CMD_LAST; if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755) && (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) && (tp->nvram_jedecnum == JEDEC_ST) && (nvram_cmd & NVRAM_CMD_FIRST)) { @@ -10044,6 +10059,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) tp->tg3_flags2 |= TG3_FLG2_5750_PLUS; @@ -10053,7 +10069,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_5705_PLUS; if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) { tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2; tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI; } else @@ -10063,6 +10080,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE; @@ -10219,6 +10237,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL; + /* Force the chip into D0. */ err = tg3_set_power_state(tp, PCI_D0); if (err) { @@ -10274,6 +10295,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG; if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755) && (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787)) tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG; @@ -10413,7 +10435,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* All chips before 5787 can get confused if TX buffers * straddle the 4GB address boundary in some cases. */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) tp->dev->hard_start_xmit = tg3_start_xmit; else tp->dev->hard_start_xmit = tg3_start_xmit_dma_bug; @@ -11002,6 +11025,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) case PHY_ID_BCM5752: return "5752"; case PHY_ID_BCM5714: return "5714"; case PHY_ID_BCM5780: return "5780"; + case PHY_ID_BCM5755: return "5755"; case PHY_ID_BCM5787: return "5787"; case PHY_ID_BCM8002: return "8002/serdes"; case 0: return "serdes"; @@ -11350,7 +11374,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, * checksumming. */ if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) dev->features |= NETIF_F_HW_CSUM; else dev->features |= NETIF_F_IP_CSUM; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index baa34c4721db..672f375ef711 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -138,6 +138,7 @@ #define ASIC_REV_5752 0x06 #define ASIC_REV_5780 0x08 #define ASIC_REV_5714 0x09 +#define ASIC_REV_5755 0x0a #define ASIC_REV_5787 0x0b #define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8) #define CHIPREV_5700_AX 0x70 @@ -456,6 +457,7 @@ #define RX_MODE_PROMISC 0x00000100 #define RX_MODE_NO_CRC_CHECK 0x00000200 #define RX_MODE_KEEP_VLAN_TAG 0x00000400 +#define RX_MODE_IPV6_CSUM_ENABLE 0x01000000 #define MAC_RX_STATUS 0x0000046c #define RX_STATUS_REMOTE_TX_XOFFED 0x00000001 #define RX_STATUS_XOFF_RCVD 0x00000002 @@ -1340,6 +1342,7 @@ #define GRC_LCLCTRL_CLEARINT 0x00000002 #define GRC_LCLCTRL_SETINT 0x00000004 #define GRC_LCLCTRL_INT_ON_ATTN 0x00000008 +#define GRC_LCLCTRL_GPIO_UART_SEL 0x00000010 /* 5755 only */ #define GRC_LCLCTRL_USE_SIG_DETECT 0x00000010 /* 5714/5780 only */ #define GRC_LCLCTRL_USE_EXT_SIG_DETECT 0x00000020 /* 5714/5780 only */ #define GRC_LCLCTRL_GPIO_INPUT3 0x00000020 @@ -2259,6 +2262,7 @@ struct tg3 { #define PHY_ID_BCM5752 0x60008100 #define PHY_ID_BCM5714 0x60008340 #define PHY_ID_BCM5780 0x60008350 +#define PHY_ID_BCM5755 0xbc050cc0 #define PHY_ID_BCM5787 0xbc050ce0 #define PHY_ID_BCM8002 0x60010140 #define PHY_ID_INVALID 0xffffffff @@ -2286,7 +2290,7 @@ struct tg3 { (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \ (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5714 || \ (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM5787 || \ - (X) == PHY_ID_BCM8002) + (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM8002) struct tg3_hw_stats *hw_stats; dma_addr_t stats_mapping; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index ec3c32932620..989a9d00dec1 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1864,11 +1864,13 @@ #define PCI_DEVICE_ID_TIGON3_5780S 0x166b #define PCI_DEVICE_ID_TIGON3_5705F 0x166e #define PCI_DEVICE_ID_TIGON3_5754M 0x1672 +#define PCI_DEVICE_ID_TIGON3_5755M 0x1673 #define PCI_DEVICE_ID_TIGON3_5750 0x1676 #define PCI_DEVICE_ID_TIGON3_5751 0x1677 #define PCI_DEVICE_ID_TIGON3_5715 0x1678 #define PCI_DEVICE_ID_TIGON3_5715S 0x1679 #define PCI_DEVICE_ID_TIGON3_5754 0x167a +#define PCI_DEVICE_ID_TIGON3_5755 0x167b #define PCI_DEVICE_ID_TIGON3_5750M 0x167c #define PCI_DEVICE_ID_TIGON3_5751M 0x167d #define PCI_DEVICE_ID_TIGON3_5751F 0x167e -- cgit v1.2.3 From 711e2c33ac9221a419a9e28d05dd78a6a9c5fd4d Mon Sep 17 00:00:00 2001 From: Jean Tourrilhes Date: Wed, 22 Feb 2006 15:10:56 -0800 Subject: [PATCH] WE-20 for kernel 2.6.16 This is version 20 of the Wireless Extensions. This is the completion of the RtNetlink work I started early 2004, it enables the full Wireless Extension API over RtNetlink. Few comments on the patch : o totally driver transparent, no change in drivers needed. o iwevent were already RtNetlink based since they were created (around 2.5.7). This adds all the regular SET and GET requests over RtNetlink, using the exact same mechanism and data format as iwevents. o This is a Kconfig option, as currently most people have no need for it. Surprisingly, patch is actually small and well encapsulated. o Tested on SMP, attention as been paid to make it 64 bits clean. o Code do probably too many checks and could be further optimised, but better safe than sorry. o RtNetlink based version of the Wireless Tools available on my web page for people inclined to try out this stuff. I would also like to thank Alexey Kuznetsov for his helpful suggestions to make this patch better. Signed-off-by: Jean Tourrilhes Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 9 + include/linux/wireless.h | 10 +- include/net/iw_handler.h | 12 +- net/core/rtnetlink.c | 98 ++++- net/core/wireless.c | 911 ++++++++++++++++++++++++++++++++++++++----- 5 files changed, 947 insertions(+), 93 deletions(-) (limited to 'include') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 5b0a19a5058d..6a1033ec06cf 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -25,6 +25,15 @@ config NET_RADIO the tools from . +config NET_WIRELESS_RTNETLINK + bool "Wireless Extension API over RtNetlink" + ---help--- + Support the Wireless Extension API over the RtNetlink socket + in addition to the traditional ioctl interface (selected above). + + For now, few tools use this facility, but it might grow in the + future. The only downside is that it adds 4.5 kB to your kernel. + # Note : the cards are obsolete (can't buy them anymore), but the drivers # are not, as people are still using them... comment "Obsolete Wireless cards support (pre-802.11)" diff --git a/include/linux/wireless.h b/include/linux/wireless.h index a555a0f7a7b4..13588564b42b 100644 --- a/include/linux/wireless.h +++ b/include/linux/wireless.h @@ -1,10 +1,10 @@ /* * This file define a set of standard wireless extensions * - * Version : 19 18.3.05 + * Version : 20 17.2.06 * * Authors : Jean Tourrilhes - HPL - - * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved. + * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved. */ #ifndef _LINUX_WIRELESS_H @@ -80,7 +80,7 @@ * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ -#define WIRELESS_EXT 19 +#define WIRELESS_EXT 20 /* * Changes : @@ -204,6 +204,10 @@ * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros + * + * V19 to V20 + * ---------- + * - RtNetlink requests support (SET/GET) */ /**************************** CONSTANTS ****************************/ diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h index a2c5e0b88422..10559e937d27 100644 --- a/include/net/iw_handler.h +++ b/include/net/iw_handler.h @@ -4,7 +4,7 @@ * Version : 7 18.3.05 * * Authors : Jean Tourrilhes - HPL - - * Copyright (c) 2001-2005 Jean Tourrilhes, All Rights Reserved. + * Copyright (c) 2001-2006 Jean Tourrilhes, All Rights Reserved. */ #ifndef _IW_HANDLER_H @@ -436,6 +436,16 @@ extern int dev_get_wireless_info(char * buffer, char **start, off_t offset, /* Handle IOCTLs, called in net/core/dev.c */ extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd); +/* Handle RtNetlink requests, called in net/core/rtnetlink.c */ +extern int wireless_rtnetlink_set(struct net_device * dev, + char * data, + int len); +extern int wireless_rtnetlink_get(struct net_device * dev, + char * data, + int len, + char ** p_buf, + int * p_len); + /* Second : functions that may be called by driver modules */ /* Send a single event to user space */ diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index ae10d3740faa..3fcfa9c59e1f 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -51,6 +51,10 @@ #include #include #include +#ifdef CONFIG_NET_WIRELESS_RTNETLINK +#include +#include +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ static DEFINE_MUTEX(rtnl_mutex); @@ -467,6 +471,17 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) goto out; } +#ifdef CONFIG_NET_WIRELESS_RTNETLINK + if (ida[IFLA_WIRELESS - 1]) { + + /* Call Wireless Extensions. + * Various stuff checked in there... */ + err = wireless_rtnetlink_set(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len); + if (err) + goto out; + } +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ + err = 0; out: @@ -477,6 +492,83 @@ out: return err; } +#ifdef CONFIG_NET_WIRELESS_RTNETLINK +static int do_getlink(struct sk_buff *in_skb, struct nlmsghdr* in_nlh, void *arg) +{ + struct ifinfomsg *ifm = NLMSG_DATA(in_nlh); + struct rtattr **ida = arg; + struct net_device *dev; + struct ifinfomsg *r; + struct nlmsghdr *nlh; + int err = -ENOBUFS; + struct sk_buff *skb; + unsigned char *b; + char *iw_buf = NULL; + int iw_buf_len = 0; + + if (ifm->ifi_index >= 0) + dev = dev_get_by_index(ifm->ifi_index); + else + return -EINVAL; + if (!dev) + return -ENODEV; + +#ifdef CONFIG_NET_WIRELESS_RTNETLINK + if (ida[IFLA_WIRELESS - 1]) { + + /* Call Wireless Extensions. We need to know the size before + * we can alloc. Various stuff checked in there... */ + err = wireless_rtnetlink_get(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len, &iw_buf, &iw_buf_len); + if (err) + goto out; + } +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ + + /* Create a skb big enough to include all the data. + * Some requests are way bigger than 4k... Jean II */ + skb = alloc_skb((NLMSG_LENGTH(sizeof(*r))) + (RTA_SPACE(iw_buf_len)), + GFP_KERNEL); + if (!skb) + goto out; + b = skb->tail; + + /* Put in the message the usual good stuff */ + nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid, in_nlh->nlmsg_seq, + RTM_NEWLINK, sizeof(*r)); + r = NLMSG_DATA(nlh); + r->ifi_family = AF_UNSPEC; + r->__ifi_pad = 0; + r->ifi_type = dev->type; + r->ifi_index = dev->ifindex; + r->ifi_flags = dev->flags; + r->ifi_change = 0; + + /* Put the wireless payload if it exist */ + if(iw_buf != NULL) + RTA_PUT(skb, IFLA_WIRELESS, iw_buf_len, + iw_buf + IW_EV_POINT_OFF); + + nlh->nlmsg_len = skb->tail - b; + + /* Needed ? */ + NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid; + + err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); + if (err > 0) + err = 0; +out: + if(iw_buf != NULL) + kfree(iw_buf); + dev_put(dev); + return err; + +rtattr_failure: +nlmsg_failure: + kfree_skb(skb); + goto out; +} +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ + static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb) { int idx; @@ -642,7 +734,11 @@ static void rtnetlink_rcv(struct sock *sk, int len) static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] = { - [RTM_GETLINK - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo }, + [RTM_GETLINK - RTM_BASE] = { +#ifdef CONFIG_NET_WIRELESS_RTNETLINK + .doit = do_getlink, +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ + .dumpit = rtnetlink_dump_ifinfo }, [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink }, [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, diff --git a/net/core/wireless.c b/net/core/wireless.c index 2add7ed609e9..81d6995fcfdb 100644 --- a/net/core/wireless.c +++ b/net/core/wireless.c @@ -2,7 +2,7 @@ * This file implement the Wireless Extensions APIs. * * Authors : Jean Tourrilhes - HPL - - * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved. + * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved. * * (As all part of the Linux kernel, this file is GPL) */ @@ -65,6 +65,9 @@ * o Start deprecating dev->get_wireless_stats, output a warning * o If IW_QUAL_DBM is set, show dBm values in /proc/net/wireless * o Don't loose INVALID/DBM flags when clearing UPDATED flags (iwstats) + * + * v8 - 17.02.06 - Jean II + * o RtNetlink requests support (SET/GET) */ /***************************** INCLUDES *****************************/ @@ -89,11 +92,13 @@ /* Debugging stuff */ #undef WE_IOCTL_DEBUG /* Debug IOCTL API */ +#undef WE_RTNETLINK_DEBUG /* Debug RtNetlink API */ #undef WE_EVENT_DEBUG /* Debug Event dispatcher */ #undef WE_SPY_DEBUG /* Debug enhanced spy support */ /* Options */ -#define WE_EVENT_NETLINK /* Propagate events using rtnetlink */ +//CONFIG_NET_WIRELESS_RTNETLINK /* Wireless requests over RtNetlink */ +#define WE_EVENT_RTNETLINK /* Propagate events using RtNetlink */ #define WE_SET_EVENT /* Generate an event on some set commands */ /************************* GLOBAL VARIABLES *************************/ @@ -156,13 +161,18 @@ static const struct iw_ioctl_description standard_ioctl[] = { .header_type = IW_HEADER_TYPE_NULL, }, [SIOCGIWPRIV - SIOCIWFIRST] = { /* (handled directly by us) */ - .header_type = IW_HEADER_TYPE_NULL, + .header_type = IW_HEADER_TYPE_POINT, + .token_size = sizeof(struct iw_priv_args), + .max_tokens = 16, + .flags = IW_DESCR_FLAG_NOMAX, }, [SIOCSIWSTATS - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_NULL, }, [SIOCGIWSTATS - SIOCIWFIRST] = { /* (handled directly by us) */ - .header_type = IW_HEADER_TYPE_NULL, + .header_type = IW_HEADER_TYPE_POINT, + .token_size = 1, + .max_tokens = sizeof(struct iw_statistics), .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWSPY - SIOCIWFIRST] = { @@ -529,6 +539,70 @@ static inline int adjust_priv_size(__u16 args, return num * iw_priv_type_size[type]; } +/* ---------------------------------------------------------------- */ +/* + * Standard Wireless Handler : get wireless stats + * Allow programatic access to /proc/net/wireless even if /proc + * doesn't exist... Also more efficient... + */ +static int iw_handler_get_iwstats(struct net_device * dev, + struct iw_request_info * info, + union iwreq_data * wrqu, + char * extra) +{ + /* Get stats from the driver */ + struct iw_statistics *stats; + + stats = get_wireless_stats(dev); + if (stats != (struct iw_statistics *) NULL) { + + /* Copy statistics to extra */ + memcpy(extra, stats, sizeof(struct iw_statistics)); + wrqu->data.length = sizeof(struct iw_statistics); + + /* Check if we need to clear the updated flag */ + if(wrqu->data.flags != 0) + stats->qual.updated &= ~IW_QUAL_ALL_UPDATED; + return 0; + } else + return -EOPNOTSUPP; +} + +/* ---------------------------------------------------------------- */ +/* + * Standard Wireless Handler : get iwpriv definitions + * Export the driver private handler definition + * They will be picked up by tools like iwpriv... + */ +static int iw_handler_get_private(struct net_device * dev, + struct iw_request_info * info, + union iwreq_data * wrqu, + char * extra) +{ + /* Check if the driver has something to export */ + if((dev->wireless_handlers->num_private_args == 0) || + (dev->wireless_handlers->private_args == NULL)) + return -EOPNOTSUPP; + + /* Check if there is enough buffer up there */ + if(wrqu->data.length < dev->wireless_handlers->num_private_args) { + /* User space can't know in advance how large the buffer + * needs to be. Give it a hint, so that we can support + * any size buffer we want somewhat efficiently... */ + wrqu->data.length = dev->wireless_handlers->num_private_args; + return -E2BIG; + } + + /* Set the number of available ioctls. */ + wrqu->data.length = dev->wireless_handlers->num_private_args; + + /* Copy structure to the user buffer. */ + memcpy(extra, dev->wireless_handlers->private_args, + sizeof(struct iw_priv_args) * wrqu->data.length); + + return 0; +} + /******************** /proc/net/wireless SUPPORT ********************/ /* @@ -628,83 +702,16 @@ int __init wireless_proc_init(void) * or just call the driver ioctl handler. */ -/* ---------------------------------------------------------------- */ -/* - * Allow programatic access to /proc/net/wireless even if /proc - * doesn't exist... Also more efficient... - */ -static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr) -{ - /* Get stats from the driver */ - struct iw_statistics *stats; - - stats = get_wireless_stats(dev); - if (stats != (struct iw_statistics *) NULL) { - struct iwreq * wrq = (struct iwreq *)ifr; - - /* Copy statistics to the user buffer */ - if(copy_to_user(wrq->u.data.pointer, stats, - sizeof(struct iw_statistics))) - return -EFAULT; - - /* Check if we need to clear the updated flag */ - if(wrq->u.data.flags != 0) - stats->qual.updated &= ~IW_QUAL_ALL_UPDATED; - return 0; - } else - return -EOPNOTSUPP; -} - -/* ---------------------------------------------------------------- */ -/* - * Export the driver private handler definition - * They will be picked up by tools like iwpriv... - */ -static inline int ioctl_export_private(struct net_device * dev, - struct ifreq * ifr) -{ - struct iwreq * iwr = (struct iwreq *) ifr; - - /* Check if the driver has something to export */ - if((dev->wireless_handlers->num_private_args == 0) || - (dev->wireless_handlers->private_args == NULL)) - return -EOPNOTSUPP; - - /* Check NULL pointer */ - if(iwr->u.data.pointer == NULL) - return -EFAULT; - - /* Check if there is enough buffer up there */ - if(iwr->u.data.length < dev->wireless_handlers->num_private_args) { - /* User space can't know in advance how large the buffer - * needs to be. Give it a hint, so that we can support - * any size buffer we want somewhat efficiently... */ - iwr->u.data.length = dev->wireless_handlers->num_private_args; - return -E2BIG; - } - - /* Set the number of available ioctls. */ - iwr->u.data.length = dev->wireless_handlers->num_private_args; - - /* Copy structure to the user buffer. */ - if (copy_to_user(iwr->u.data.pointer, - dev->wireless_handlers->private_args, - sizeof(struct iw_priv_args) * iwr->u.data.length)) - return -EFAULT; - - return 0; -} - /* ---------------------------------------------------------------- */ /* * Wrapper to call a standard Wireless Extension handler. * We do various checks and also take care of moving data between * user space and kernel space. */ -static inline int ioctl_standard_call(struct net_device * dev, - struct ifreq * ifr, - unsigned int cmd, - iw_handler handler) +static int ioctl_standard_call(struct net_device * dev, + struct ifreq * ifr, + unsigned int cmd, + iw_handler handler) { struct iwreq * iwr = (struct iwreq *) ifr; const struct iw_ioctl_description * descr; @@ -1048,14 +1055,20 @@ int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd) { case SIOCGIWSTATS: /* Get Wireless Stats */ - return dev_iwstats(dev, ifr); + return ioctl_standard_call(dev, + ifr, + cmd, + &iw_handler_get_iwstats); case SIOCGIWPRIV: /* Check if we have some wireless handlers defined */ if(dev->wireless_handlers != NULL) { /* We export to user space the definition of * the private handler ourselves */ - return ioctl_export_private(dev, ifr); + return ioctl_standard_call(dev, + ifr, + cmd, + &iw_handler_get_private); } // ## Fall-through for old API ## default: @@ -1088,16 +1101,739 @@ int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd) return -EINVAL; } +/********************** RTNETLINK REQUEST API **********************/ +/* + * The alternate user space API to configure all those Wireless Extensions + * is through RtNetlink. + * This API support only the new driver API (iw_handler). + * + * This RtNetlink API use the same query/reply model as the ioctl API. + * Maximum effort has been done to fit in the RtNetlink model, and + * we support both RtNetlink Set and RtNelink Get operations. + * On the other hand, we don't offer Dump operations because of the + * following reasons : + * o Large number of parameters, most optional + * o Large size of some parameters (> 100 bytes) + * o Each parameters need to be extracted from hardware + * o Scan requests can take seconds and disable network activity. + * Because of this high cost/overhead, we want to return only the + * parameters the user application is really interested in. + * We could offer partial Dump using the IW_DESCR_FLAG_DUMP flag. + * + * The API uses the standard RtNetlink socket. When the RtNetlink code + * find a IFLA_WIRELESS field in a RtNetlink SET_LINK request, + * it calls here. + */ + +#ifdef CONFIG_NET_WIRELESS_RTNETLINK +/* ---------------------------------------------------------------- */ +/* + * Wrapper to call a standard Wireless Extension GET handler. + * We do various checks and call the handler with the proper args. + */ +static int rtnetlink_standard_get(struct net_device * dev, + struct iw_event * request, + int request_len, + iw_handler handler, + char ** p_buf, + int * p_len) +{ + const struct iw_ioctl_description * descr = NULL; + unsigned int cmd; + union iwreq_data * wrqu; + int hdr_len; + struct iw_request_info info; + char * buffer = NULL; + int buffer_size = 0; + int ret = -EINVAL; + + /* Get the description of the Request */ + cmd = request->cmd; + if((cmd - SIOCIWFIRST) >= standard_ioctl_num) + return -EOPNOTSUPP; + descr = &(standard_ioctl[cmd - SIOCIWFIRST]); + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Found standard handler for 0x%04X\n", + dev->name, cmd); + printk(KERN_DEBUG "%s (WE.r) : Header type : %d, Token type : %d, size : %d, token : %d\n", dev->name, descr->header_type, descr->token_type, descr->token_size, descr->max_tokens); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Check if wrqu is complete */ + hdr_len = event_type_size[descr->header_type]; + if(request_len < hdr_len) { +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG + "%s (WE.r) : Wireless request too short (%d)\n", + dev->name, request_len); +#endif /* WE_RTNETLINK_DEBUG */ + return -EINVAL; + } + + /* Prepare the call */ + info.cmd = cmd; + info.flags = 0; + + /* Check if we have extra data in the reply or not */ + if(descr->header_type != IW_HEADER_TYPE_POINT) { + + /* Create the kernel buffer that we will return. + * It's at an offset to match the TYPE_POINT case... */ + buffer_size = request_len + IW_EV_POINT_OFF; + buffer = kmalloc(buffer_size, GFP_KERNEL); + if (buffer == NULL) { + return -ENOMEM; + } + /* Copy event data */ + memcpy(buffer + IW_EV_POINT_OFF, request, request_len); + /* Use our own copy of wrqu */ + wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF + + IW_EV_LCP_LEN); + + /* No extra arguments. Trivial to handle */ + ret = handler(dev, &info, wrqu, NULL); + + } else { + union iwreq_data wrqu_point; + char * extra = NULL; + int extra_size = 0; + + /* Get a temp copy of wrqu (skip pointer) */ + memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, + ((char *) request) + IW_EV_LCP_LEN, + IW_EV_POINT_LEN - IW_EV_LCP_LEN); + + /* Calculate space needed by arguments. Always allocate + * for max space. Easier, and won't last long... */ + extra_size = descr->max_tokens * descr->token_size; + /* Support for very large requests */ + if((descr->flags & IW_DESCR_FLAG_NOMAX) && + (wrqu_point.data.length > descr->max_tokens)) + extra_size = (wrqu_point.data.length + * descr->token_size); + buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF; +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n", + dev->name, extra_size, buffer_size); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Create the kernel buffer that we will return */ + buffer = kmalloc(buffer_size, GFP_KERNEL); + if (buffer == NULL) { + return -ENOMEM; + } + + /* Put wrqu in the right place (just before extra). + * Leave space for IWE header and dummy pointer... + * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned... + */ + memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF, + ((char *) &wrqu_point) + IW_EV_POINT_OFF, + IW_EV_POINT_LEN - IW_EV_LCP_LEN); + wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN); + + /* Extra comes logically after that. Offset +12 bytes. */ + extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN; + + /* Call the handler */ + ret = handler(dev, &info, wrqu, extra); + + /* Calculate real returned length */ + extra_size = (wrqu->data.length * descr->token_size); + /* Re-adjust reply size */ + request->len = extra_size + IW_EV_POINT_LEN; + + /* Put the iwe header where it should, i.e. scrap the + * dummy pointer. */ + memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN); + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Check if there is enough buffer up there */ + if(wrqu_point.data.length < wrqu->data.length) + ret = -E2BIG; + } + + /* Return the buffer to the caller */ + if (!ret) { + *p_buf = buffer; + *p_len = request->len; + } else { + /* Cleanup */ + if(buffer) + kfree(buffer); + } + + return ret; +} + +/* ---------------------------------------------------------------- */ +/* + * Wrapper to call a standard Wireless Extension SET handler. + * We do various checks and call the handler with the proper args. + */ +static inline int rtnetlink_standard_set(struct net_device * dev, + struct iw_event * request, + int request_len, + iw_handler handler) +{ + const struct iw_ioctl_description * descr = NULL; + unsigned int cmd; + union iwreq_data * wrqu; + union iwreq_data wrqu_point; + int hdr_len; + char * extra = NULL; + int extra_size = 0; + struct iw_request_info info; + int ret = -EINVAL; + + /* Get the description of the Request */ + cmd = request->cmd; + if((cmd - SIOCIWFIRST) >= standard_ioctl_num) + return -EOPNOTSUPP; + descr = &(standard_ioctl[cmd - SIOCIWFIRST]); + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Found standard SET handler for 0x%04X\n", + dev->name, cmd); + printk(KERN_DEBUG "%s (WE.r) : Header type : %d, Token type : %d, size : %d, token : %d\n", dev->name, descr->header_type, descr->token_type, descr->token_size, descr->max_tokens); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Extract fixed header from request. This is properly aligned. */ + wrqu = &request->u; + + /* Check if wrqu is complete */ + hdr_len = event_type_size[descr->header_type]; + if(request_len < hdr_len) { +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG + "%s (WE.r) : Wireless request too short (%d)\n", + dev->name, request_len); +#endif /* WE_RTNETLINK_DEBUG */ + return -EINVAL; + } + + /* Prepare the call */ + info.cmd = cmd; + info.flags = 0; + + /* Check if we have extra data in the request or not */ + if(descr->header_type != IW_HEADER_TYPE_POINT) { + + /* No extra arguments. Trivial to handle */ + ret = handler(dev, &info, wrqu, NULL); + + } else { + int extra_len; + + /* Put wrqu in the right place (skip pointer) */ + memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, + wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN); + /* Don't forget about the event code... */ + wrqu = &wrqu_point; + + /* Check if number of token fits within bounds */ + if(wrqu_point.data.length > descr->max_tokens) + return -E2BIG; + if(wrqu_point.data.length < descr->min_tokens) + return -EINVAL; + + /* Real length of payload */ + extra_len = wrqu_point.data.length * descr->token_size; + + /* Check if request is self consistent */ + if((request_len - hdr_len) < extra_len) { +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Wireless request data too short (%d)\n", + dev->name, extra_size); +#endif /* WE_RTNETLINK_DEBUG */ + return -EINVAL; + } + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes\n", + dev->name, extra_size); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Always allocate for max space. Easier, and won't last + * long... */ + extra_size = descr->max_tokens * descr->token_size; + extra = kmalloc(extra_size, GFP_KERNEL); + if (extra == NULL) + return -ENOMEM; + + /* Copy extra in aligned buffer */ + memcpy(extra, ((char *) request) + hdr_len, extra_len); + + /* Call the handler */ + ret = handler(dev, &info, &wrqu_point, extra); + } + +#ifdef WE_SET_EVENT + /* Generate an event to notify listeners of the change */ + if((descr->flags & IW_DESCR_FLAG_EVENT) && + ((ret == 0) || (ret == -EIWCOMMIT))) { + if(descr->flags & IW_DESCR_FLAG_RESTRICT) + /* If the event is restricted, don't + * export the payload */ + wireless_send_event(dev, cmd, wrqu, NULL); + else + wireless_send_event(dev, cmd, wrqu, extra); + } +#endif /* WE_SET_EVENT */ + + /* Cleanup - I told you it wasn't that long ;-) */ + if(extra) + kfree(extra); + + /* Call commit handler if needed and defined */ + if(ret == -EIWCOMMIT) + ret = call_commit_handler(dev); + + return ret; +} + +/* ---------------------------------------------------------------- */ +/* + * Wrapper to call a private Wireless Extension GET handler. + * Same as above... + * It's not as nice and slimline as the standard wrapper. The cause + * is struct iw_priv_args, which was not really designed for the + * job we are going here. + * + * IMPORTANT : This function prevent to set and get data on the same + * IOCTL and enforce the SET/GET convention. Not doing it would be + * far too hairy... + * If you need to set and get data at the same time, please don't use + * a iw_handler but process it in your ioctl handler (i.e. use the + * old driver API). + */ +static inline int rtnetlink_private_get(struct net_device * dev, + struct iw_event * request, + int request_len, + iw_handler handler, + char ** p_buf, + int * p_len) +{ + const struct iw_priv_args * descr = NULL; + unsigned int cmd; + union iwreq_data * wrqu; + int hdr_len; + struct iw_request_info info; + int extra_size = 0; + int i; + char * buffer = NULL; + int buffer_size = 0; + int ret = -EINVAL; + + /* Get the description of the Request */ + cmd = request->cmd; + for(i = 0; i < dev->wireless_handlers->num_private_args; i++) + if(cmd == dev->wireless_handlers->private_args[i].cmd) { + descr = &(dev->wireless_handlers->private_args[i]); + break; + } + if(descr == NULL) + return -EOPNOTSUPP; + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Found private handler for 0x%04X\n", + dev->name, cmd); + printk(KERN_DEBUG "%s (WE.r) : Name %s, set %X, get %X\n", + dev->name, descr->name, descr->set_args, descr->get_args); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Compute the max size of the get arguments */ + extra_size = get_priv_size(descr->get_args); + + /* Does it fits in wrqu ? */ + if((descr->get_args & IW_PRIV_SIZE_FIXED) && + (extra_size <= IFNAMSIZ)) { + hdr_len = extra_size; + extra_size = 0; + } else { + hdr_len = IW_EV_POINT_LEN; + } + + /* Check if wrqu is complete */ + if(request_len < hdr_len) { +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG + "%s (WE.r) : Wireless request too short (%d)\n", + dev->name, request_len); +#endif /* WE_RTNETLINK_DEBUG */ + return -EINVAL; + } + + /* Prepare the call */ + info.cmd = cmd; + info.flags = 0; + + /* Check if we have a pointer to user space data or not. */ + if(extra_size == 0) { + + /* Create the kernel buffer that we will return. + * It's at an offset to match the TYPE_POINT case... */ + buffer_size = request_len + IW_EV_POINT_OFF; + buffer = kmalloc(buffer_size, GFP_KERNEL); + if (buffer == NULL) { + return -ENOMEM; + } + /* Copy event data */ + memcpy(buffer + IW_EV_POINT_OFF, request, request_len); + /* Use our own copy of wrqu */ + wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF + + IW_EV_LCP_LEN); + + /* No extra arguments. Trivial to handle */ + ret = handler(dev, &info, wrqu, (char *) wrqu); + + } else { + char * extra; + + /* Buffer for full reply */ + buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF; + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n", + dev->name, extra_size, buffer_size); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Create the kernel buffer that we will return */ + buffer = kmalloc(buffer_size, GFP_KERNEL); + if (buffer == NULL) { + return -ENOMEM; + } + + /* Put wrqu in the right place (just before extra). + * Leave space for IWE header and dummy pointer... + * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned... + */ + memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF, + ((char *) request) + IW_EV_LCP_LEN, + IW_EV_POINT_LEN - IW_EV_LCP_LEN); + wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN); + + /* Extra comes logically after that. Offset +12 bytes. */ + extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN; + + /* Call the handler */ + ret = handler(dev, &info, wrqu, extra); + + /* Adjust for the actual length if it's variable, + * avoid leaking kernel bits outside. */ + if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) + extra_size = adjust_priv_size(descr->get_args, wrqu); + /* Re-adjust reply size */ + request->len = extra_size + IW_EV_POINT_LEN; + + /* Put the iwe header where it should, i.e. scrap the + * dummy pointer. */ + memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN); + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size); +#endif /* WE_RTNETLINK_DEBUG */ + } + + /* Return the buffer to the caller */ + if (!ret) { + *p_buf = buffer; + *p_len = request->len; + } else { + /* Cleanup */ + if(buffer) + kfree(buffer); + } + + return ret; +} + +/* ---------------------------------------------------------------- */ +/* + * Wrapper to call a private Wireless Extension SET handler. + * Same as above... + * It's not as nice and slimline as the standard wrapper. The cause + * is struct iw_priv_args, which was not really designed for the + * job we are going here. + * + * IMPORTANT : This function prevent to set and get data on the same + * IOCTL and enforce the SET/GET convention. Not doing it would be + * far too hairy... + * If you need to set and get data at the same time, please don't use + * a iw_handler but process it in your ioctl handler (i.e. use the + * old driver API). + */ +static inline int rtnetlink_private_set(struct net_device * dev, + struct iw_event * request, + int request_len, + iw_handler handler) +{ + const struct iw_priv_args * descr = NULL; + unsigned int cmd; + union iwreq_data * wrqu; + union iwreq_data wrqu_point; + int hdr_len; + char * extra = NULL; + int extra_size = 0; + int offset = 0; /* For sub-ioctls */ + struct iw_request_info info; + int i; + int ret = -EINVAL; + + /* Get the description of the Request */ + cmd = request->cmd; + for(i = 0; i < dev->wireless_handlers->num_private_args; i++) + if(cmd == dev->wireless_handlers->private_args[i].cmd) { + descr = &(dev->wireless_handlers->private_args[i]); + break; + } + if(descr == NULL) + return -EOPNOTSUPP; + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Found private handler for 0x%04X\n", + ifr->ifr_name, cmd); + printk(KERN_DEBUG "%s (WE.r) : Name %s, set %X, get %X\n", + dev->name, descr->name, descr->set_args, descr->get_args); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Compute the size of the set arguments */ + /* Check for sub-ioctl handler */ + if(descr->name[0] == '\0') + /* Reserve one int for sub-ioctl index */ + offset = sizeof(__u32); + + /* Size of set arguments */ + extra_size = get_priv_size(descr->set_args); + + /* Does it fits in wrqu ? */ + if((descr->set_args & IW_PRIV_SIZE_FIXED) && + (extra_size <= IFNAMSIZ)) { + hdr_len = IW_EV_LCP_LEN + extra_size; + extra_size = 0; + } else { + hdr_len = IW_EV_POINT_LEN; + } + + /* Extract fixed header from request. This is properly aligned. */ + wrqu = &request->u; + + /* Check if wrqu is complete */ + if(request_len < hdr_len) { +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG + "%s (WE.r) : Wireless request too short (%d)\n", + dev->name, request_len); +#endif /* WE_RTNETLINK_DEBUG */ + return -EINVAL; + } + + /* Prepare the call */ + info.cmd = cmd; + info.flags = 0; + + /* Check if we have a pointer to user space data or not. */ + if(extra_size == 0) { + + /* No extra arguments. Trivial to handle */ + ret = handler(dev, &info, wrqu, (char *) wrqu); + + } else { + int extra_len; + + /* Put wrqu in the right place (skip pointer) */ + memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, + wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN); + + /* Does it fits within bounds ? */ + if(wrqu_point.data.length > (descr->set_args & + IW_PRIV_SIZE_MASK)) + return -E2BIG; + + /* Real length of payload */ + extra_len = adjust_priv_size(descr->set_args, &wrqu_point); + + /* Check if request is self consistent */ + if((request_len - hdr_len) < extra_len) { +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Wireless request data too short (%d)\n", + dev->name, extra_size); +#endif /* WE_RTNETLINK_DEBUG */ + return -EINVAL; + } + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes\n", + dev->name, extra_size); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Always allocate for max space. Easier, and won't last + * long... */ + extra = kmalloc(extra_size, GFP_KERNEL); + if (extra == NULL) + return -ENOMEM; + + /* Copy extra in aligned buffer */ + memcpy(extra, ((char *) request) + hdr_len, extra_len); + + /* Call the handler */ + ret = handler(dev, &info, &wrqu_point, extra); + + /* Cleanup - I told you it wasn't that long ;-) */ + kfree(extra); + } + + /* Call commit handler if needed and defined */ + if(ret == -EIWCOMMIT) + ret = call_commit_handler(dev); + + return ret; +} + +/* ---------------------------------------------------------------- */ +/* + * Main RtNetlink dispatcher. Called from the main networking code + * (do_getlink() in net/core/rtnetlink.c). + * Check the type of Request and call the appropriate wrapper... + */ +int wireless_rtnetlink_get(struct net_device * dev, + char * data, + int len, + char ** p_buf, + int * p_len) +{ + struct iw_event * request = (struct iw_event *) data; + iw_handler handler; + + /* Check length */ + if(len < IW_EV_LCP_LEN) { + printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n", + dev->name, len); + return -EINVAL; + } + + /* ReCheck length (len may have padding) */ + if(request->len > len) { + printk(KERN_DEBUG "%s (WE.r) : RtNetlink request len invalid (%d-%d)\n", + dev->name, request->len, len); + return -EINVAL; + } + + /* Only accept GET requests in here */ + if(!IW_IS_GET(request->cmd)) + return -EOPNOTSUPP; + + /* Special cases */ + if(request->cmd == SIOCGIWSTATS) + /* Get Wireless Stats */ + return rtnetlink_standard_get(dev, + request, + request->len, + &iw_handler_get_iwstats, + p_buf, p_len); + if(request->cmd == SIOCGIWPRIV) { + /* Check if we have some wireless handlers defined */ + if(dev->wireless_handlers == NULL) + return -EOPNOTSUPP; + /* Get Wireless Stats */ + return rtnetlink_standard_get(dev, + request, + request->len, + &iw_handler_get_private, + p_buf, p_len); + } + + /* Basic check */ + if (!netif_device_present(dev)) + return -ENODEV; + + /* Try to find the handler */ + handler = get_handler(dev, request->cmd); + if(handler != NULL) { + /* Standard and private are not the same */ + if(request->cmd < SIOCIWFIRSTPRIV) + return rtnetlink_standard_get(dev, + request, + request->len, + handler, + p_buf, p_len); + else + return rtnetlink_private_get(dev, + request, + request->len, + handler, + p_buf, p_len); + } + + return -EOPNOTSUPP; +} + +/* ---------------------------------------------------------------- */ +/* + * Main RtNetlink dispatcher. Called from the main networking code + * (do_setlink() in net/core/rtnetlink.c). + * Check the type of Request and call the appropriate wrapper... + */ +int wireless_rtnetlink_set(struct net_device * dev, + char * data, + int len) +{ + struct iw_event * request = (struct iw_event *) data; + iw_handler handler; + + /* Check length */ + if(len < IW_EV_LCP_LEN) { + printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n", + dev->name, len); + return -EINVAL; + } + + /* ReCheck length (len may have padding) */ + if(request->len > len) { + printk(KERN_DEBUG "%s (WE.r) : RtNetlink request len invalid (%d-%d)\n", + dev->name, request->len, len); + return -EINVAL; + } + + /* Only accept SET requests in here */ + if(!IW_IS_SET(request->cmd)) + return -EOPNOTSUPP; + + /* Basic check */ + if (!netif_device_present(dev)) + return -ENODEV; + + /* New driver API : try to find the handler */ + handler = get_handler(dev, request->cmd); + if(handler != NULL) { + /* Standard and private are not the same */ + if(request->cmd < SIOCIWFIRSTPRIV) + return rtnetlink_standard_set(dev, + request, + request->len, + handler); + else + return rtnetlink_private_set(dev, + request, + request->len, + handler); + } + + return -EOPNOTSUPP; +} +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ + + /************************* EVENT PROCESSING *************************/ /* * Process events generated by the wireless layer or the driver. * Most often, the event will be propagated through rtnetlink */ -#ifdef WE_EVENT_NETLINK -/* "rtnl" is defined in net/core/rtnetlink.c, but we need it here. - * It is declared in */ - +#ifdef WE_EVENT_RTNETLINK /* ---------------------------------------------------------------- */ /* * Fill a rtnetlink message with our event data. @@ -1121,12 +1857,11 @@ static inline int rtnetlink_fill_iwinfo(struct sk_buff * skb, r->__ifi_pad = 0; r->ifi_type = dev->type; r->ifi_index = dev->ifindex; - r->ifi_flags = dev->flags; + r->ifi_flags = dev_get_flags(dev); r->ifi_change = 0; /* Wireless changes don't affect those flags */ /* Add the wireless events in the netlink packet */ - RTA_PUT(skb, IFLA_WIRELESS, - event_len, event); + RTA_PUT(skb, IFLA_WIRELESS, event_len, event); nlh->nlmsg_len = skb->tail - b; return skb->len; @@ -1163,7 +1898,7 @@ static inline void rtmsg_iwinfo(struct net_device * dev, NETLINK_CB(skb).dst_group = RTNLGRP_LINK; netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC); } -#endif /* WE_EVENT_NETLINK */ +#endif /* WE_EVENT_RTNETLINK */ /* ---------------------------------------------------------------- */ /* @@ -1255,10 +1990,10 @@ void wireless_send_event(struct net_device * dev, if(extra != NULL) memcpy(((char *) event) + hdr_len, extra, extra_len); -#ifdef WE_EVENT_NETLINK - /* rtnetlink event channel */ +#ifdef WE_EVENT_RTNETLINK + /* Send via the RtNetlink event channel */ rtmsg_iwinfo(dev, (char *) event, event_len); -#endif /* WE_EVENT_NETLINK */ +#endif /* WE_EVENT_RTNETLINK */ /* Cleanup */ kfree(event); -- cgit v1.2.3 From 9e71f9c848e669f003b1319da52f03cb8e7d7403 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 23 Mar 2006 02:59:22 -0800 Subject: [PATCH] DM: Fix bug: BIO_RW_BARRIER requests to md/raid1 hang. Both R1BIO_Barrier and R1BIO_Returned are 4 !!!! This means that barrier requests don't get returned (i.e. b_endio called) because it looks like they already have been. Signed-off-by: Neil Brown Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/raid/raid1.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/raid/raid1.h b/include/linux/raid/raid1.h index 9d5494aaac0f..3009c813d83d 100644 --- a/include/linux/raid/raid1.h +++ b/include/linux/raid/raid1.h @@ -130,6 +130,6 @@ struct r1bio_s { * with failure when last write completes (and all failed). * Record that bi_end_io was called with this flag... */ -#define R1BIO_Returned 4 +#define R1BIO_Returned 6 #endif -- cgit v1.2.3 From 9a0b5817ad97bb718ab85322759d19a238712b47 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 23 Mar 2006 02:59:32 -0800 Subject: [PATCH] x86: SMP alternatives Implement SMP alternatives, i.e. switching at runtime between different code versions for UP and SMP. The code can patch both SMP->UP and UP->SMP. The UP->SMP case is useful for CPU hotplug. With CONFIG_CPU_HOTPLUG enabled the code switches to UP at boot time and when the number of CPUs goes down to 1, and switches to SMP when the number of CPUs goes up to 2. Without CONFIG_CPU_HOTPLUG or on non-SMP-capable systems the code is patched once at boot time (if needed) and the tables are released afterwards. The changes in detail: * The current alternatives bits are moved to a separate file, the SMP alternatives code is added there. * The patch adds some new elf sections to the kernel: .smp_altinstructions like .altinstructions, also contains a list of alt_instr structs. .smp_altinstr_replacement like .altinstr_replacement, but also has some space to save original instruction before replaving it. .smp_locks list of pointers to lock prefixes which can be nop'ed out on UP. The first two are used to replace more complex instruction sequences such as spinlocks and semaphores. It would be possible to deal with the lock prefixes with that as well, but by handling them as special case the table sizes become much smaller. * The sections are page-aligned and padded up to page size, so they can be free if they are not needed. * Splitted the code to release init pages to a separate function and use it to release the elf sections if they are unused. Signed-off-by: Gerd Hoffmann Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/Makefile | 2 +- arch/i386/kernel/alternative.c | 321 +++++++++++++++++++++++++++++++++++++++++ arch/i386/kernel/cpu/proc.c | 2 +- arch/i386/kernel/module.c | 32 ++-- arch/i386/kernel/semaphore.c | 8 +- arch/i386/kernel/setup.c | 95 ------------ arch/i386/kernel/smpboot.c | 3 + arch/i386/kernel/vmlinux.lds.S | 20 +++ arch/i386/mm/init.c | 45 +++--- arch/um/kernel/um_arch.c | 12 +- include/asm-i386/alternative.h | 129 +++++++++++++++++ include/asm-i386/atomic.h | 28 ++-- include/asm-i386/bitops.h | 7 +- include/asm-i386/cpufeature.h | 1 + include/asm-i386/mutex.h | 6 +- include/asm-i386/rwlock.h | 56 +++---- include/asm-i386/semaphore.h | 8 +- include/asm-i386/spinlock.h | 21 ++- include/asm-i386/system.h | 62 +------- include/asm-um/alternative.h | 6 + 20 files changed, 605 insertions(+), 259 deletions(-) create mode 100644 arch/i386/kernel/alternative.c create mode 100644 include/asm-i386/alternative.h create mode 100644 include/asm-um/alternative.h (limited to 'include') diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index 65656c033d70..5b9ed21216cf 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -7,7 +7,7 @@ extra-y := head.o init_task.o vmlinux.lds obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \ pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o \ - quirks.o i8237.o topology.o + quirks.o i8237.o topology.o alternative.o obj-y += cpu/ obj-y += timers/ diff --git a/arch/i386/kernel/alternative.c b/arch/i386/kernel/alternative.c new file mode 100644 index 000000000000..5cbd6f99fb2a --- /dev/null +++ b/arch/i386/kernel/alternative.c @@ -0,0 +1,321 @@ +#include +#include +#include +#include +#include + +#define DEBUG 0 +#if DEBUG +# define DPRINTK(fmt, args...) printk(fmt, args) +#else +# define DPRINTK(fmt, args...) +#endif + +/* Use inline assembly to define this because the nops are defined + as inline assembly strings in the include files and we cannot + get them easily into strings. */ +asm("\t.data\nintelnops: " + GENERIC_NOP1 GENERIC_NOP2 GENERIC_NOP3 GENERIC_NOP4 GENERIC_NOP5 GENERIC_NOP6 + GENERIC_NOP7 GENERIC_NOP8); +asm("\t.data\nk8nops: " + K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6 + K8_NOP7 K8_NOP8); +asm("\t.data\nk7nops: " + K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6 + K7_NOP7 K7_NOP8); + +extern unsigned char intelnops[], k8nops[], k7nops[]; +static unsigned char *intel_nops[ASM_NOP_MAX+1] = { + NULL, + intelnops, + intelnops + 1, + intelnops + 1 + 2, + intelnops + 1 + 2 + 3, + intelnops + 1 + 2 + 3 + 4, + intelnops + 1 + 2 + 3 + 4 + 5, + intelnops + 1 + 2 + 3 + 4 + 5 + 6, + intelnops + 1 + 2 + 3 + 4 + 5 + 6 + 7, +}; +static unsigned char *k8_nops[ASM_NOP_MAX+1] = { + NULL, + k8nops, + k8nops + 1, + k8nops + 1 + 2, + k8nops + 1 + 2 + 3, + k8nops + 1 + 2 + 3 + 4, + k8nops + 1 + 2 + 3 + 4 + 5, + k8nops + 1 + 2 + 3 + 4 + 5 + 6, + k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7, +}; +static unsigned char *k7_nops[ASM_NOP_MAX+1] = { + NULL, + k7nops, + k7nops + 1, + k7nops + 1 + 2, + k7nops + 1 + 2 + 3, + k7nops + 1 + 2 + 3 + 4, + k7nops + 1 + 2 + 3 + 4 + 5, + k7nops + 1 + 2 + 3 + 4 + 5 + 6, + k7nops + 1 + 2 + 3 + 4 + 5 + 6 + 7, +}; +static struct nop { + int cpuid; + unsigned char **noptable; +} noptypes[] = { + { X86_FEATURE_K8, k8_nops }, + { X86_FEATURE_K7, k7_nops }, + { -1, NULL } +}; + + +extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; +extern struct alt_instr __smp_alt_instructions[], __smp_alt_instructions_end[]; +extern u8 *__smp_locks[], *__smp_locks_end[]; + +extern u8 __smp_alt_begin[], __smp_alt_end[]; + + +static unsigned char** find_nop_table(void) +{ + unsigned char **noptable = intel_nops; + int i; + + for (i = 0; noptypes[i].cpuid >= 0; i++) { + if (boot_cpu_has(noptypes[i].cpuid)) { + noptable = noptypes[i].noptable; + break; + } + } + return noptable; +} + +/* Replace instructions with better alternatives for this CPU type. + This runs before SMP is initialized to avoid SMP problems with + self modifying code. This implies that assymetric systems where + APs have less capabilities than the boot processor are not handled. + Tough. Make sure you disable such features by hand. */ + +void apply_alternatives(struct alt_instr *start, struct alt_instr *end) +{ + unsigned char **noptable = find_nop_table(); + struct alt_instr *a; + int diff, i, k; + + DPRINTK("%s: alt table %p -> %p\n", __FUNCTION__, start, end); + for (a = start; a < end; a++) { + BUG_ON(a->replacementlen > a->instrlen); + if (!boot_cpu_has(a->cpuid)) + continue; + memcpy(a->instr, a->replacement, a->replacementlen); + diff = a->instrlen - a->replacementlen; + /* Pad the rest with nops */ + for (i = a->replacementlen; diff > 0; diff -= k, i += k) { + k = diff; + if (k > ASM_NOP_MAX) + k = ASM_NOP_MAX; + memcpy(a->instr + i, noptable[k], k); + } + } +} + +static void alternatives_smp_save(struct alt_instr *start, struct alt_instr *end) +{ + struct alt_instr *a; + + DPRINTK("%s: alt table %p-%p\n", __FUNCTION__, start, end); + for (a = start; a < end; a++) { + memcpy(a->replacement + a->replacementlen, + a->instr, + a->instrlen); + } +} + +static void alternatives_smp_apply(struct alt_instr *start, struct alt_instr *end) +{ + struct alt_instr *a; + + for (a = start; a < end; a++) { + memcpy(a->instr, + a->replacement + a->replacementlen, + a->instrlen); + } +} + +static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end) +{ + u8 **ptr; + + for (ptr = start; ptr < end; ptr++) { + if (*ptr < text) + continue; + if (*ptr > text_end) + continue; + **ptr = 0xf0; /* lock prefix */ + }; +} + +static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end) +{ + unsigned char **noptable = find_nop_table(); + u8 **ptr; + + for (ptr = start; ptr < end; ptr++) { + if (*ptr < text) + continue; + if (*ptr > text_end) + continue; + **ptr = noptable[1][0]; + }; +} + +struct smp_alt_module { + /* what is this ??? */ + struct module *mod; + char *name; + + /* ptrs to lock prefixes */ + u8 **locks; + u8 **locks_end; + + /* .text segment, needed to avoid patching init code ;) */ + u8 *text; + u8 *text_end; + + struct list_head next; +}; +static LIST_HEAD(smp_alt_modules); +static DEFINE_SPINLOCK(smp_alt); + +static int smp_alt_once = 0; +static int __init bootonly(char *str) +{ + smp_alt_once = 1; + return 1; +} +__setup("smp-alt-boot", bootonly); + +void alternatives_smp_module_add(struct module *mod, char *name, + void *locks, void *locks_end, + void *text, void *text_end) +{ + struct smp_alt_module *smp; + unsigned long flags; + + if (smp_alt_once) { + if (boot_cpu_has(X86_FEATURE_UP)) + alternatives_smp_unlock(locks, locks_end, + text, text_end); + return; + } + + smp = kzalloc(sizeof(*smp), GFP_KERNEL); + if (NULL == smp) + return; /* we'll run the (safe but slow) SMP code then ... */ + + smp->mod = mod; + smp->name = name; + smp->locks = locks; + smp->locks_end = locks_end; + smp->text = text; + smp->text_end = text_end; + DPRINTK("%s: locks %p -> %p, text %p -> %p, name %s\n", + __FUNCTION__, smp->locks, smp->locks_end, + smp->text, smp->text_end, smp->name); + + spin_lock_irqsave(&smp_alt, flags); + list_add_tail(&smp->next, &smp_alt_modules); + if (boot_cpu_has(X86_FEATURE_UP)) + alternatives_smp_unlock(smp->locks, smp->locks_end, + smp->text, smp->text_end); + spin_unlock_irqrestore(&smp_alt, flags); +} + +void alternatives_smp_module_del(struct module *mod) +{ + struct smp_alt_module *item; + unsigned long flags; + + if (smp_alt_once) + return; + + spin_lock_irqsave(&smp_alt, flags); + list_for_each_entry(item, &smp_alt_modules, next) { + if (mod != item->mod) + continue; + list_del(&item->next); + spin_unlock_irqrestore(&smp_alt, flags); + DPRINTK("%s: %s\n", __FUNCTION__, item->name); + kfree(item); + return; + } + spin_unlock_irqrestore(&smp_alt, flags); +} + +void alternatives_smp_switch(int smp) +{ + struct smp_alt_module *mod; + unsigned long flags; + + if (smp_alt_once) + return; + BUG_ON(!smp && (num_online_cpus() > 1)); + + spin_lock_irqsave(&smp_alt, flags); + if (smp) { + printk(KERN_INFO "SMP alternatives: switching to SMP code\n"); + clear_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability); + clear_bit(X86_FEATURE_UP, cpu_data[0].x86_capability); + alternatives_smp_apply(__smp_alt_instructions, + __smp_alt_instructions_end); + list_for_each_entry(mod, &smp_alt_modules, next) + alternatives_smp_lock(mod->locks, mod->locks_end, + mod->text, mod->text_end); + } else { + printk(KERN_INFO "SMP alternatives: switching to UP code\n"); + set_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability); + set_bit(X86_FEATURE_UP, cpu_data[0].x86_capability); + apply_alternatives(__smp_alt_instructions, + __smp_alt_instructions_end); + list_for_each_entry(mod, &smp_alt_modules, next) + alternatives_smp_unlock(mod->locks, mod->locks_end, + mod->text, mod->text_end); + } + spin_unlock_irqrestore(&smp_alt, flags); +} + +void __init alternative_instructions(void) +{ + apply_alternatives(__alt_instructions, __alt_instructions_end); + + /* switch to patch-once-at-boottime-only mode and free the + * tables in case we know the number of CPUs will never ever + * change */ +#ifdef CONFIG_HOTPLUG_CPU + if (num_possible_cpus() < 2) + smp_alt_once = 1; +#else + smp_alt_once = 1; +#endif + + if (smp_alt_once) { + if (1 == num_possible_cpus()) { + printk(KERN_INFO "SMP alternatives: switching to UP code\n"); + set_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability); + set_bit(X86_FEATURE_UP, cpu_data[0].x86_capability); + apply_alternatives(__smp_alt_instructions, + __smp_alt_instructions_end); + alternatives_smp_unlock(__smp_locks, __smp_locks_end, + _text, _etext); + } + free_init_pages("SMP alternatives", + (unsigned long)__smp_alt_begin, + (unsigned long)__smp_alt_end); + } else { + alternatives_smp_save(__smp_alt_instructions, + __smp_alt_instructions_end); + alternatives_smp_module_add(NULL, "core kernel", + __smp_locks, __smp_locks_end, + _text, _etext); + alternatives_smp_switch(0); + } +} diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c index 89a85af33d28..5cfbd8011698 100644 --- a/arch/i386/kernel/cpu/proc.c +++ b/arch/i386/kernel/cpu/proc.c @@ -40,7 +40,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) /* Other (Linux-defined) */ "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", NULL, NULL, NULL, NULL, - "constant_tsc", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "constant_tsc", "up", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/arch/i386/kernel/module.c b/arch/i386/kernel/module.c index 5149c8a621f0..470cf97e7cd3 100644 --- a/arch/i386/kernel/module.c +++ b/arch/i386/kernel/module.c @@ -104,26 +104,38 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, return -ENOEXEC; } -extern void apply_alternatives(void *start, void *end); - int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *me) { - const Elf_Shdr *s; + const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL; char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; - /* look for .altinstructions to patch */ for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { - void *seg; - if (strcmp(".altinstructions", secstrings + s->sh_name)) - continue; - seg = (void *)s->sh_addr; - apply_alternatives(seg, seg + s->sh_size); - } + if (!strcmp(".text", secstrings + s->sh_name)) + text = s; + if (!strcmp(".altinstructions", secstrings + s->sh_name)) + alt = s; + if (!strcmp(".smp_locks", secstrings + s->sh_name)) + locks= s; + } + + if (alt) { + /* patch .altinstructions */ + void *aseg = (void *)alt->sh_addr; + apply_alternatives(aseg, aseg + alt->sh_size); + } + if (locks && text) { + void *lseg = (void *)locks->sh_addr; + void *tseg = (void *)text->sh_addr; + alternatives_smp_module_add(me, me->name, + lseg, lseg + locks->sh_size, + tseg, tseg + text->sh_size); + } return 0; } void module_arch_cleanup(struct module *mod) { + alternatives_smp_module_del(mod); } diff --git a/arch/i386/kernel/semaphore.c b/arch/i386/kernel/semaphore.c index 7455ab643943..967dc74df9ee 100644 --- a/arch/i386/kernel/semaphore.c +++ b/arch/i386/kernel/semaphore.c @@ -110,11 +110,11 @@ asm( ".align 4\n" ".globl __write_lock_failed\n" "__write_lock_failed:\n\t" - LOCK "addl $" RW_LOCK_BIAS_STR ",(%eax)\n" + LOCK_PREFIX "addl $" RW_LOCK_BIAS_STR ",(%eax)\n" "1: rep; nop\n\t" "cmpl $" RW_LOCK_BIAS_STR ",(%eax)\n\t" "jne 1b\n\t" - LOCK "subl $" RW_LOCK_BIAS_STR ",(%eax)\n\t" + LOCK_PREFIX "subl $" RW_LOCK_BIAS_STR ",(%eax)\n\t" "jnz __write_lock_failed\n\t" "ret" ); @@ -124,11 +124,11 @@ asm( ".align 4\n" ".globl __read_lock_failed\n" "__read_lock_failed:\n\t" - LOCK "incl (%eax)\n" + LOCK_PREFIX "incl (%eax)\n" "1: rep; nop\n\t" "cmpl $1,(%eax)\n\t" "js 1b\n\t" - LOCK "decl (%eax)\n\t" + LOCK_PREFIX "decl (%eax)\n\t" "js __read_lock_failed\n\t" "ret" ); diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index ab62a9f4701e..5f58f8cb9836 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -1377,101 +1377,6 @@ static void __init register_memory(void) pci_mem_start, gapstart, gapsize); } -/* Use inline assembly to define this because the nops are defined - as inline assembly strings in the include files and we cannot - get them easily into strings. */ -asm("\t.data\nintelnops: " - GENERIC_NOP1 GENERIC_NOP2 GENERIC_NOP3 GENERIC_NOP4 GENERIC_NOP5 GENERIC_NOP6 - GENERIC_NOP7 GENERIC_NOP8); -asm("\t.data\nk8nops: " - K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6 - K8_NOP7 K8_NOP8); -asm("\t.data\nk7nops: " - K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6 - K7_NOP7 K7_NOP8); - -extern unsigned char intelnops[], k8nops[], k7nops[]; -static unsigned char *intel_nops[ASM_NOP_MAX+1] = { - NULL, - intelnops, - intelnops + 1, - intelnops + 1 + 2, - intelnops + 1 + 2 + 3, - intelnops + 1 + 2 + 3 + 4, - intelnops + 1 + 2 + 3 + 4 + 5, - intelnops + 1 + 2 + 3 + 4 + 5 + 6, - intelnops + 1 + 2 + 3 + 4 + 5 + 6 + 7, -}; -static unsigned char *k8_nops[ASM_NOP_MAX+1] = { - NULL, - k8nops, - k8nops + 1, - k8nops + 1 + 2, - k8nops + 1 + 2 + 3, - k8nops + 1 + 2 + 3 + 4, - k8nops + 1 + 2 + 3 + 4 + 5, - k8nops + 1 + 2 + 3 + 4 + 5 + 6, - k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7, -}; -static unsigned char *k7_nops[ASM_NOP_MAX+1] = { - NULL, - k7nops, - k7nops + 1, - k7nops + 1 + 2, - k7nops + 1 + 2 + 3, - k7nops + 1 + 2 + 3 + 4, - k7nops + 1 + 2 + 3 + 4 + 5, - k7nops + 1 + 2 + 3 + 4 + 5 + 6, - k7nops + 1 + 2 + 3 + 4 + 5 + 6 + 7, -}; -static struct nop { - int cpuid; - unsigned char **noptable; -} noptypes[] = { - { X86_FEATURE_K8, k8_nops }, - { X86_FEATURE_K7, k7_nops }, - { -1, NULL } -}; - -/* Replace instructions with better alternatives for this CPU type. - - This runs before SMP is initialized to avoid SMP problems with - self modifying code. This implies that assymetric systems where - APs have less capabilities than the boot processor are not handled. - Tough. Make sure you disable such features by hand. */ -void apply_alternatives(void *start, void *end) -{ - struct alt_instr *a; - int diff, i, k; - unsigned char **noptable = intel_nops; - for (i = 0; noptypes[i].cpuid >= 0; i++) { - if (boot_cpu_has(noptypes[i].cpuid)) { - noptable = noptypes[i].noptable; - break; - } - } - for (a = start; (void *)a < end; a++) { - if (!boot_cpu_has(a->cpuid)) - continue; - BUG_ON(a->replacementlen > a->instrlen); - memcpy(a->instr, a->replacement, a->replacementlen); - diff = a->instrlen - a->replacementlen; - /* Pad the rest with nops */ - for (i = a->replacementlen; diff > 0; diff -= k, i += k) { - k = diff; - if (k > ASM_NOP_MAX) - k = ASM_NOP_MAX; - memcpy(a->instr + i, noptable[k], k); - } - } -} - -void __init alternative_instructions(void) -{ - extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; - apply_alternatives(__alt_instructions, __alt_instructions_end); -} - static char * __init machine_specific_memory_setup(void); #ifdef CONFIG_MCA diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 7007e1783797..4c470e99a742 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -899,6 +899,7 @@ static int __devinit do_boot_cpu(int apicid, int cpu) unsigned short nmi_high = 0, nmi_low = 0; ++cpucount; + alternatives_smp_switch(1); /* * We can't use kernel_thread since we must avoid to @@ -1368,6 +1369,8 @@ void __cpu_die(unsigned int cpu) /* They ack this in play_dead by setting CPU_DEAD */ if (per_cpu(cpu_state, cpu) == CPU_DEAD) { printk ("CPU %d is now offline\n", cpu); + if (1 == num_online_cpus()) + alternatives_smp_switch(0); return; } msleep(100); diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S index 4710195b6b74..3f21c6f6466d 100644 --- a/arch/i386/kernel/vmlinux.lds.S +++ b/arch/i386/kernel/vmlinux.lds.S @@ -68,6 +68,26 @@ SECTIONS *(.data.init_task) } + /* might get freed after init */ + . = ALIGN(4096); + __smp_alt_begin = .; + __smp_alt_instructions = .; + .smp_altinstructions : AT(ADDR(.smp_altinstructions) - LOAD_OFFSET) { + *(.smp_altinstructions) + } + __smp_alt_instructions_end = .; + . = ALIGN(4); + __smp_locks = .; + .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) { + *(.smp_locks) + } + __smp_locks_end = .; + .smp_altinstr_replacement : AT(ADDR(.smp_altinstr_replacement) - LOAD_OFFSET) { + *(.smp_altinstr_replacement) + } + . = ALIGN(4096); + __smp_alt_end = .; + /* will be freed after init */ . = ALIGN(4096); /* Init code and data */ __init_begin = .; diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 7ba55a6e2dbc..9f66ac582a8b 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -720,21 +720,6 @@ static int noinline do_test_wp_bit(void) return flag; } -void free_initmem(void) -{ - unsigned long addr; - - addr = (unsigned long)(&__init_begin); - for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { - ClearPageReserved(virt_to_page(addr)); - init_page_count(virt_to_page(addr)); - memset((void *)addr, 0xcc, PAGE_SIZE); - free_page(addr); - totalram_pages++; - } - printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (__init_end - __init_begin) >> 10); -} - #ifdef CONFIG_DEBUG_RODATA extern char __start_rodata, __end_rodata; @@ -758,17 +743,31 @@ void mark_rodata_ro(void) } #endif +void free_init_pages(char *what, unsigned long begin, unsigned long end) +{ + unsigned long addr; + + for (addr = begin; addr < end; addr += PAGE_SIZE) { + ClearPageReserved(virt_to_page(addr)); + init_page_count(virt_to_page(addr)); + memset((void *)addr, 0xcc, PAGE_SIZE); + free_page(addr); + totalram_pages++; + } + printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10); +} + +void free_initmem(void) +{ + free_init_pages("unused kernel memory", + (unsigned long)(&__init_begin), + (unsigned long)(&__init_end)); +} #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { - if (start < end) - printk (KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10); - for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(virt_to_page(start)); - init_page_count(virt_to_page(start)); - free_page(start); - totalram_pages++; - } + free_init_pages("initrd memory", start, end); } #endif + diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 27cdf9164422..80c9c18aae94 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -491,6 +491,16 @@ void __init check_bugs(void) check_devanon(); } -void apply_alternatives(void *start, void *end) +void apply_alternatives(struct alt_instr *start, struct alt_instr *end) +{ +} + +void alternatives_smp_module_add(struct module *mod, char *name, + void *locks, void *locks_end, + void *text, void *text_end) +{ +} + +void alternatives_smp_module_del(struct module *mod) { } diff --git a/include/asm-i386/alternative.h b/include/asm-i386/alternative.h new file mode 100644 index 000000000000..e201decea0c9 --- /dev/null +++ b/include/asm-i386/alternative.h @@ -0,0 +1,129 @@ +#ifndef _I386_ALTERNATIVE_H +#define _I386_ALTERNATIVE_H + +#ifdef __KERNEL__ + +struct alt_instr { + u8 *instr; /* original instruction */ + u8 *replacement; + u8 cpuid; /* cpuid bit set for replacement */ + u8 instrlen; /* length of original instruction */ + u8 replacementlen; /* length of new instruction, <= instrlen */ + u8 pad; +}; + +extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end); + +struct module; +extern void alternatives_smp_module_add(struct module *mod, char *name, + void *locks, void *locks_end, + void *text, void *text_end); +extern void alternatives_smp_module_del(struct module *mod); +extern void alternatives_smp_switch(int smp); + +#endif + +/* + * Alternative instructions for different CPU types or capabilities. + * + * This allows to use optimized instructions even on generic binary + * kernels. + * + * length of oldinstr must be longer or equal the length of newinstr + * It can be padded with nops as needed. + * + * For non barrier like inlines please define new variants + * without volatile and memory clobber. + */ +#define alternative(oldinstr, newinstr, feature) \ + asm volatile ("661:\n\t" oldinstr "\n662:\n" \ + ".section .altinstructions,\"a\"\n" \ + " .align 4\n" \ + " .long 661b\n" /* label */ \ + " .long 663f\n" /* new instruction */ \ + " .byte %c0\n" /* feature bit */ \ + " .byte 662b-661b\n" /* sourcelen */ \ + " .byte 664f-663f\n" /* replacementlen */ \ + ".previous\n" \ + ".section .altinstr_replacement,\"ax\"\n" \ + "663:\n\t" newinstr "\n664:\n" /* replacement */\ + ".previous" :: "i" (feature) : "memory") + +/* + * Alternative inline assembly with input. + * + * Pecularities: + * No memory clobber here. + * Argument numbers start with 1. + * Best is to use constraints that are fixed size (like (%1) ... "r") + * If you use variable sized constraints like "m" or "g" in the + * replacement maake sure to pad to the worst case length. + */ +#define alternative_input(oldinstr, newinstr, feature, input...) \ + asm volatile ("661:\n\t" oldinstr "\n662:\n" \ + ".section .altinstructions,\"a\"\n" \ + " .align 4\n" \ + " .long 661b\n" /* label */ \ + " .long 663f\n" /* new instruction */ \ + " .byte %c0\n" /* feature bit */ \ + " .byte 662b-661b\n" /* sourcelen */ \ + " .byte 664f-663f\n" /* replacementlen */ \ + ".previous\n" \ + ".section .altinstr_replacement,\"ax\"\n" \ + "663:\n\t" newinstr "\n664:\n" /* replacement */\ + ".previous" :: "i" (feature), ##input) + +/* + * Alternative inline assembly for SMP. + * + * alternative_smp() takes two versions (SMP first, UP second) and is + * for more complex stuff such as spinlocks. + * + * The LOCK_PREFIX macro defined here replaces the LOCK and + * LOCK_PREFIX macros used everywhere in the source tree. + * + * SMP alternatives use the same data structures as the other + * alternatives and the X86_FEATURE_UP flag to indicate the case of a + * UP system running a SMP kernel. The existing apply_alternatives() + * works fine for patching a SMP kernel for UP. + * + * The SMP alternative tables can be kept after boot and contain both + * UP and SMP versions of the instructions to allow switching back to + * SMP at runtime, when hotplugging in a new CPU, which is especially + * useful in virtualized environments. + * + * The very common lock prefix is handled as special case in a + * separate table which is a pure address list without replacement ptr + * and size information. That keeps the table sizes small. + */ + +#ifdef CONFIG_SMP +#define alternative_smp(smpinstr, upinstr, args...) \ + asm volatile ("661:\n\t" smpinstr "\n662:\n" \ + ".section .smp_altinstructions,\"a\"\n" \ + " .align 4\n" \ + " .long 661b\n" /* label */ \ + " .long 663f\n" /* new instruction */ \ + " .byte 0x68\n" /* X86_FEATURE_UP */ \ + " .byte 662b-661b\n" /* sourcelen */ \ + " .byte 664f-663f\n" /* replacementlen */ \ + ".previous\n" \ + ".section .smp_altinstr_replacement,\"awx\"\n" \ + "663:\n\t" upinstr "\n" /* replacement */ \ + "664:\n\t.fill 662b-661b,1,0x42\n" /* space for original */ \ + ".previous" : args) + +#define LOCK_PREFIX \ + ".section .smp_locks,\"a\"\n" \ + " .align 4\n" \ + " .long 661f\n" /* address */ \ + ".previous\n" \ + "661:\n\tlock; " + +#else /* ! CONFIG_SMP */ +#define alternative_smp(smpinstr, upinstr, args...) \ + asm volatile (upinstr : args) +#define LOCK_PREFIX "" +#endif + +#endif /* _I386_ALTERNATIVE_H */ diff --git a/include/asm-i386/atomic.h b/include/asm-i386/atomic.h index de649d3aa2d4..78b0032d1f29 100644 --- a/include/asm-i386/atomic.h +++ b/include/asm-i386/atomic.h @@ -10,12 +10,6 @@ * resource counting etc.. */ -#ifdef CONFIG_SMP -#define LOCK "lock ; " -#else -#define LOCK "" -#endif - /* * Make sure gcc doesn't try to be clever and move things around * on us. We need to use _exactly_ the address the user gave us, @@ -52,7 +46,7 @@ typedef struct { volatile int counter; } atomic_t; static __inline__ void atomic_add(int i, atomic_t *v) { __asm__ __volatile__( - LOCK "addl %1,%0" + LOCK_PREFIX "addl %1,%0" :"=m" (v->counter) :"ir" (i), "m" (v->counter)); } @@ -67,7 +61,7 @@ static __inline__ void atomic_add(int i, atomic_t *v) static __inline__ void atomic_sub(int i, atomic_t *v) { __asm__ __volatile__( - LOCK "subl %1,%0" + LOCK_PREFIX "subl %1,%0" :"=m" (v->counter) :"ir" (i), "m" (v->counter)); } @@ -86,7 +80,7 @@ static __inline__ int atomic_sub_and_test(int i, atomic_t *v) unsigned char c; __asm__ __volatile__( - LOCK "subl %2,%0; sete %1" + LOCK_PREFIX "subl %2,%0; sete %1" :"=m" (v->counter), "=qm" (c) :"ir" (i), "m" (v->counter) : "memory"); return c; @@ -101,7 +95,7 @@ static __inline__ int atomic_sub_and_test(int i, atomic_t *v) static __inline__ void atomic_inc(atomic_t *v) { __asm__ __volatile__( - LOCK "incl %0" + LOCK_PREFIX "incl %0" :"=m" (v->counter) :"m" (v->counter)); } @@ -115,7 +109,7 @@ static __inline__ void atomic_inc(atomic_t *v) static __inline__ void atomic_dec(atomic_t *v) { __asm__ __volatile__( - LOCK "decl %0" + LOCK_PREFIX "decl %0" :"=m" (v->counter) :"m" (v->counter)); } @@ -133,7 +127,7 @@ static __inline__ int atomic_dec_and_test(atomic_t *v) unsigned char c; __asm__ __volatile__( - LOCK "decl %0; sete %1" + LOCK_PREFIX "decl %0; sete %1" :"=m" (v->counter), "=qm" (c) :"m" (v->counter) : "memory"); return c != 0; @@ -152,7 +146,7 @@ static __inline__ int atomic_inc_and_test(atomic_t *v) unsigned char c; __asm__ __volatile__( - LOCK "incl %0; sete %1" + LOCK_PREFIX "incl %0; sete %1" :"=m" (v->counter), "=qm" (c) :"m" (v->counter) : "memory"); return c != 0; @@ -172,7 +166,7 @@ static __inline__ int atomic_add_negative(int i, atomic_t *v) unsigned char c; __asm__ __volatile__( - LOCK "addl %2,%0; sets %1" + LOCK_PREFIX "addl %2,%0; sets %1" :"=m" (v->counter), "=qm" (c) :"ir" (i), "m" (v->counter) : "memory"); return c; @@ -195,7 +189,7 @@ static __inline__ int atomic_add_return(int i, atomic_t *v) /* Modern 486+ processor */ __i = i; __asm__ __volatile__( - LOCK "xaddl %0, %1;" + LOCK_PREFIX "xaddl %0, %1;" :"=r"(i) :"m"(v->counter), "0"(i)); return i + __i; @@ -242,11 +236,11 @@ static __inline__ int atomic_sub_return(int i, atomic_t *v) /* These are x86-specific, used by some header files */ #define atomic_clear_mask(mask, addr) \ -__asm__ __volatile__(LOCK "andl %0,%1" \ +__asm__ __volatile__(LOCK_PREFIX "andl %0,%1" \ : : "r" (~(mask)),"m" (*addr) : "memory") #define atomic_set_mask(mask, addr) \ -__asm__ __volatile__(LOCK "orl %0,%1" \ +__asm__ __volatile__(LOCK_PREFIX "orl %0,%1" \ : : "r" (mask),"m" (*(addr)) : "memory") /* Atomic operations are already serializing on x86 */ diff --git a/include/asm-i386/bitops.h b/include/asm-i386/bitops.h index 88e6ca248cd7..7d20b95edb3b 100644 --- a/include/asm-i386/bitops.h +++ b/include/asm-i386/bitops.h @@ -7,6 +7,7 @@ #include #include +#include /* * These have to be done with inline assembly: that way the bit-setting @@ -16,12 +17,6 @@ * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). */ -#ifdef CONFIG_SMP -#define LOCK_PREFIX "lock ; " -#else -#define LOCK_PREFIX "" -#endif - #define ADDR (*(volatile long *) addr) /** diff --git a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h index c4ec2a4d8fdf..5c0b5876b931 100644 --- a/include/asm-i386/cpufeature.h +++ b/include/asm-i386/cpufeature.h @@ -70,6 +70,7 @@ #define X86_FEATURE_P3 (3*32+ 6) /* P3 */ #define X86_FEATURE_P4 (3*32+ 7) /* P4 */ #define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */ +#define X86_FEATURE_UP (3*32+ 9) /* smp kernel running on up */ /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ #define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ diff --git a/include/asm-i386/mutex.h b/include/asm-i386/mutex.h index 9b2199e829f3..05a538531229 100644 --- a/include/asm-i386/mutex.h +++ b/include/asm-i386/mutex.h @@ -9,6 +9,8 @@ #ifndef _ASM_MUTEX_H #define _ASM_MUTEX_H +#include "asm/alternative.h" + /** * __mutex_fastpath_lock - try to take the lock by moving the count * from 1 to a 0 value @@ -27,7 +29,7 @@ do { \ typecheck_fn(fastcall void (*)(atomic_t *), fail_fn); \ \ __asm__ __volatile__( \ - LOCK " decl (%%eax) \n" \ + LOCK_PREFIX " decl (%%eax) \n" \ " js 2f \n" \ "1: \n" \ \ @@ -83,7 +85,7 @@ do { \ typecheck_fn(fastcall void (*)(atomic_t *), fail_fn); \ \ __asm__ __volatile__( \ - LOCK " incl (%%eax) \n" \ + LOCK_PREFIX " incl (%%eax) \n" \ " jle 2f \n" \ "1: \n" \ \ diff --git a/include/asm-i386/rwlock.h b/include/asm-i386/rwlock.h index b57cc7afdf7e..94f00195d543 100644 --- a/include/asm-i386/rwlock.h +++ b/include/asm-i386/rwlock.h @@ -21,21 +21,23 @@ #define RW_LOCK_BIAS_STR "0x01000000" #define __build_read_lock_ptr(rw, helper) \ - asm volatile(LOCK "subl $1,(%0)\n\t" \ - "jns 1f\n" \ - "call " helper "\n\t" \ - "1:\n" \ - ::"a" (rw) : "memory") + alternative_smp("lock; subl $1,(%0)\n\t" \ + "jns 1f\n" \ + "call " helper "\n\t" \ + "1:\n", \ + "subl $1,(%0)\n\t", \ + :"a" (rw) : "memory") #define __build_read_lock_const(rw, helper) \ - asm volatile(LOCK "subl $1,%0\n\t" \ - "jns 1f\n" \ - "pushl %%eax\n\t" \ - "leal %0,%%eax\n\t" \ - "call " helper "\n\t" \ - "popl %%eax\n\t" \ - "1:\n" \ - :"=m" (*(volatile int *)rw) : : "memory") + alternative_smp("lock; subl $1,%0\n\t" \ + "jns 1f\n" \ + "pushl %%eax\n\t" \ + "leal %0,%%eax\n\t" \ + "call " helper "\n\t" \ + "popl %%eax\n\t" \ + "1:\n", \ + "subl $1,%0\n\t", \ + "=m" (*(volatile int *)rw) : : "memory") #define __build_read_lock(rw, helper) do { \ if (__builtin_constant_p(rw)) \ @@ -45,21 +47,23 @@ } while (0) #define __build_write_lock_ptr(rw, helper) \ - asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ - "jz 1f\n" \ - "call " helper "\n\t" \ - "1:\n" \ - ::"a" (rw) : "memory") + alternative_smp("lock; subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ + "jz 1f\n" \ + "call " helper "\n\t" \ + "1:\n", \ + "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t", \ + :"a" (rw) : "memory") #define __build_write_lock_const(rw, helper) \ - asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",%0\n\t" \ - "jz 1f\n" \ - "pushl %%eax\n\t" \ - "leal %0,%%eax\n\t" \ - "call " helper "\n\t" \ - "popl %%eax\n\t" \ - "1:\n" \ - :"=m" (*(volatile int *)rw) : : "memory") + alternative_smp("lock; subl $" RW_LOCK_BIAS_STR ",%0\n\t" \ + "jz 1f\n" \ + "pushl %%eax\n\t" \ + "leal %0,%%eax\n\t" \ + "call " helper "\n\t" \ + "popl %%eax\n\t" \ + "1:\n", \ + "subl $" RW_LOCK_BIAS_STR ",%0\n\t", \ + "=m" (*(volatile int *)rw) : : "memory") #define __build_write_lock(rw, helper) do { \ if (__builtin_constant_p(rw)) \ diff --git a/include/asm-i386/semaphore.h b/include/asm-i386/semaphore.h index 6a42b2142fd6..f7a0f310c524 100644 --- a/include/asm-i386/semaphore.h +++ b/include/asm-i386/semaphore.h @@ -99,7 +99,7 @@ static inline void down(struct semaphore * sem) might_sleep(); __asm__ __volatile__( "# atomic down operation\n\t" - LOCK "decl %0\n\t" /* --sem->count */ + LOCK_PREFIX "decl %0\n\t" /* --sem->count */ "js 2f\n" "1:\n" LOCK_SECTION_START("") @@ -123,7 +123,7 @@ static inline int down_interruptible(struct semaphore * sem) might_sleep(); __asm__ __volatile__( "# atomic interruptible down operation\n\t" - LOCK "decl %1\n\t" /* --sem->count */ + LOCK_PREFIX "decl %1\n\t" /* --sem->count */ "js 2f\n\t" "xorl %0,%0\n" "1:\n" @@ -148,7 +148,7 @@ static inline int down_trylock(struct semaphore * sem) __asm__ __volatile__( "# atomic interruptible down operation\n\t" - LOCK "decl %1\n\t" /* --sem->count */ + LOCK_PREFIX "decl %1\n\t" /* --sem->count */ "js 2f\n\t" "xorl %0,%0\n" "1:\n" @@ -173,7 +173,7 @@ static inline void up(struct semaphore * sem) { __asm__ __volatile__( "# atomic up operation\n\t" - LOCK "incl %0\n\t" /* ++sem->count */ + LOCK_PREFIX "incl %0\n\t" /* ++sem->count */ "jle 2f\n" "1:\n" LOCK_SECTION_START("") diff --git a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h index 23604350cdf4..a1b8a8a30e21 100644 --- a/include/asm-i386/spinlock.h +++ b/include/asm-i386/spinlock.h @@ -48,18 +48,23 @@ "jmp 1b\n" \ "4:\n\t" +#define __raw_spin_lock_string_up \ + "\n\tdecb %0" + static inline void __raw_spin_lock(raw_spinlock_t *lock) { - __asm__ __volatile__( - __raw_spin_lock_string - :"=m" (lock->slock) : : "memory"); + alternative_smp( + __raw_spin_lock_string, + __raw_spin_lock_string_up, + "=m" (lock->slock) : : "memory"); } static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags) { - __asm__ __volatile__( - __raw_spin_lock_string_flags - :"=m" (lock->slock) : "r" (flags) : "memory"); + alternative_smp( + __raw_spin_lock_string_flags, + __raw_spin_lock_string_up, + "=m" (lock->slock) : "r" (flags) : "memory"); } static inline int __raw_spin_trylock(raw_spinlock_t *lock) @@ -178,12 +183,12 @@ static inline int __raw_write_trylock(raw_rwlock_t *lock) static inline void __raw_read_unlock(raw_rwlock_t *rw) { - asm volatile("lock ; incl %0" :"=m" (rw->lock) : : "memory"); + asm volatile(LOCK_PREFIX "incl %0" :"=m" (rw->lock) : : "memory"); } static inline void __raw_write_unlock(raw_rwlock_t *rw) { - asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ", %0" + asm volatile(LOCK_PREFIX "addl $" RW_LOCK_BIAS_STR ", %0" : "=m" (rw->lock) : : "memory"); } diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h index 399145a247f2..d0d8d7448d88 100644 --- a/include/asm-i386/system.h +++ b/include/asm-i386/system.h @@ -352,67 +352,6 @@ static inline unsigned long long __cmpxchg64(volatile void *ptr, unsigned long l #endif -#ifdef __KERNEL__ -struct alt_instr { - __u8 *instr; /* original instruction */ - __u8 *replacement; - __u8 cpuid; /* cpuid bit set for replacement */ - __u8 instrlen; /* length of original instruction */ - __u8 replacementlen; /* length of new instruction, <= instrlen */ - __u8 pad; -}; -#endif - -/* - * Alternative instructions for different CPU types or capabilities. - * - * This allows to use optimized instructions even on generic binary - * kernels. - * - * length of oldinstr must be longer or equal the length of newinstr - * It can be padded with nops as needed. - * - * For non barrier like inlines please define new variants - * without volatile and memory clobber. - */ -#define alternative(oldinstr, newinstr, feature) \ - asm volatile ("661:\n\t" oldinstr "\n662:\n" \ - ".section .altinstructions,\"a\"\n" \ - " .align 4\n" \ - " .long 661b\n" /* label */ \ - " .long 663f\n" /* new instruction */ \ - " .byte %c0\n" /* feature bit */ \ - " .byte 662b-661b\n" /* sourcelen */ \ - " .byte 664f-663f\n" /* replacementlen */ \ - ".previous\n" \ - ".section .altinstr_replacement,\"ax\"\n" \ - "663:\n\t" newinstr "\n664:\n" /* replacement */ \ - ".previous" :: "i" (feature) : "memory") - -/* - * Alternative inline assembly with input. - * - * Pecularities: - * No memory clobber here. - * Argument numbers start with 1. - * Best is to use constraints that are fixed size (like (%1) ... "r") - * If you use variable sized constraints like "m" or "g" in the - * replacement maake sure to pad to the worst case length. - */ -#define alternative_input(oldinstr, newinstr, feature, input...) \ - asm volatile ("661:\n\t" oldinstr "\n662:\n" \ - ".section .altinstructions,\"a\"\n" \ - " .align 4\n" \ - " .long 661b\n" /* label */ \ - " .long 663f\n" /* new instruction */ \ - " .byte %c0\n" /* feature bit */ \ - " .byte 662b-661b\n" /* sourcelen */ \ - " .byte 664f-663f\n" /* replacementlen */ \ - ".previous\n" \ - ".section .altinstr_replacement,\"ax\"\n" \ - "663:\n\t" newinstr "\n664:\n" /* replacement */ \ - ".previous" :: "i" (feature), ##input) - /* * Force strict CPU ordering. * And yes, this is required on UP too when we're talking @@ -558,5 +497,6 @@ static inline void sched_cacheflush(void) } extern unsigned long arch_align_stack(unsigned long sp); +extern void free_init_pages(char *what, unsigned long begin, unsigned long end); #endif diff --git a/include/asm-um/alternative.h b/include/asm-um/alternative.h new file mode 100644 index 000000000000..b6434396bd42 --- /dev/null +++ b/include/asm-um/alternative.h @@ -0,0 +1,6 @@ +#ifndef __UM_ALTERNATIVE_H +#define __UM_ALTERNATIVE_H + +#include "asm/arch/alternative.h" + +#endif -- cgit v1.2.3 From 30e931d4092713cecd6b8c2fd70f268efaa6e428 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 23 Mar 2006 02:59:35 -0800 Subject: [PATCH] i386: Add a temporary to make put_user more type safe In some code I am developing I had occasion to change the type of a variable. This made the value put_user was putting to user space wrong. But the code continued to build cleanly without errors. Introducing a temporary fixes this problem and at least with gcc-3.3.5 does not cause gcc any problems with optimizing out the temporary. gcc-4.x using SSA internally ought to be even better at optimizing out temporaries, so I don't expect a temporary to become a problem. Especially because in all correct cases the types on both sides of the assignment to the temporary are the same. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-i386/uaccess.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h index 3f1337c34208..371457b1ceb6 100644 --- a/include/asm-i386/uaccess.h +++ b/include/asm-i386/uaccess.h @@ -197,13 +197,15 @@ extern void __put_user_8(void); #define put_user(x,ptr) \ ({ int __ret_pu; \ + __typeof__(*(ptr)) __pu_val; \ __chk_user_ptr(ptr); \ + __pu_val = x; \ switch(sizeof(*(ptr))) { \ - case 1: __put_user_1(x, ptr); break; \ - case 2: __put_user_2(x, ptr); break; \ - case 4: __put_user_4(x, ptr); break; \ - case 8: __put_user_8(x, ptr); break; \ - default:__put_user_X(x, ptr); break; \ + case 1: __put_user_1(__pu_val, ptr); break; \ + case 2: __put_user_2(__pu_val, ptr); break; \ + case 4: __put_user_4(__pu_val, ptr); break; \ + case 8: __put_user_8(__pu_val, ptr); break; \ + default:__put_user_X(__pu_val, ptr); break; \ } \ __ret_pu; \ }) -- cgit v1.2.3 From e5428ede94179ddccaa56308e0f194fa299edbb4 Mon Sep 17 00:00:00 2001 From: "Natalie.Protasevich@unisys.com" Date: Thu, 23 Mar 2006 02:59:36 -0800 Subject: [PATCH] Compilation fix for ES7000 when no ACPI is specified in config (i386) ES7000 platform code clean up for compilation errors and a warning. Ifdef'd the ACPI related parts in the ES7000 platform code. They were causing compile errors in certain configuration (without ACPI defined). I think this approach would be best (as opposed to Kconfig changes) since it only touches the subarch... Signed-off-by: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/mpparse.c | 4 ++-- arch/i386/mach-es7000/es7000.h | 5 ++++- arch/i386/mach-es7000/es7000plat.c | 6 ++---- include/asm-i386/mach-es7000/mach_mpparse.h | 10 ++++++++-- 4 files changed, 16 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c index e6e2f43db85e..e85e463af7ce 100644 --- a/arch/i386/kernel/mpparse.c +++ b/arch/i386/kernel/mpparse.c @@ -828,6 +828,8 @@ void __init find_smp_config (void) smp_scan_config(address, 0x400); } +int es7000_plat; + /* -------------------------------------------------------------------------- ACPI-based MP Configuration -------------------------------------------------------------------------- */ @@ -1011,8 +1013,6 @@ void __init mp_override_legacy_irq ( return; } -int es7000_plat; - void __init mp_config_acpi_legacy_irqs (void) { struct mpc_config_intsrc intsrc; diff --git a/arch/i386/mach-es7000/es7000.h b/arch/i386/mach-es7000/es7000.h index f1e3204f5dec..80566ca4a80a 100644 --- a/arch/i386/mach-es7000/es7000.h +++ b/arch/i386/mach-es7000/es7000.h @@ -83,6 +83,7 @@ struct es7000_oem_table { struct psai psai; }; +#ifdef CONFIG_ACPI struct acpi_table_sdt { unsigned long pa; unsigned long count; @@ -99,6 +100,9 @@ struct oem_table { u32 OEMTableSize; }; +extern int find_unisys_acpi_oem_table(unsigned long *oem_addr); +#endif + struct mip_reg { unsigned long long off_0; unsigned long long off_8; @@ -114,7 +118,6 @@ struct mip_reg { #define MIP_FUNC(VALUE) (VALUE & 0xff) extern int parse_unisys_oem (char *oemptr); -extern int find_unisys_acpi_oem_table(unsigned long *oem_addr); extern void setup_unisys(void); extern int es7000_start_cpu(int cpu, unsigned long eip); extern void es7000_sw_apic(void); diff --git a/arch/i386/mach-es7000/es7000plat.c b/arch/i386/mach-es7000/es7000plat.c index a9ab0644f403..3d0fc853516d 100644 --- a/arch/i386/mach-es7000/es7000plat.c +++ b/arch/i386/mach-es7000/es7000plat.c @@ -51,8 +51,6 @@ struct mip_reg *host_reg; int mip_port; unsigned long mip_addr, host_addr; -#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI) - /* * GSI override for ES7000 platforms. */ @@ -76,8 +74,6 @@ es7000_rename_gsi(int ioapic, int gsi) return gsi; } -#endif /* (CONFIG_X86_IO_APIC) && (CONFIG_ACPI) */ - void __init setup_unisys(void) { @@ -160,6 +156,7 @@ parse_unisys_oem (char *oemptr) return es7000_plat; } +#ifdef CONFIG_ACPI int __init find_unisys_acpi_oem_table(unsigned long *oem_addr) { @@ -212,6 +209,7 @@ find_unisys_acpi_oem_table(unsigned long *oem_addr) } return -1; } +#endif static void es7000_spin(int n) diff --git a/include/asm-i386/mach-es7000/mach_mpparse.h b/include/asm-i386/mach-es7000/mach_mpparse.h index 4a0637a3e208..99f66be240be 100644 --- a/include/asm-i386/mach-es7000/mach_mpparse.h +++ b/include/asm-i386/mach-es7000/mach_mpparse.h @@ -30,7 +30,8 @@ static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, return 0; } -static inline int es7000_check_dsdt() +#ifdef CONFIG_ACPI +static inline int es7000_check_dsdt(void) { struct acpi_table_header *header = NULL; if(!acpi_get_table_header_early(ACPI_DSDT, &header)) @@ -54,6 +55,11 @@ static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) } return 0; } - +#else +static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + return 0; +} +#endif #endif /* __ASM_MACH_MPPARSE_H */ -- cgit v1.2.3 From 7c63ee5cf7d210b51c2a8243e29988edec2646ed Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Thu, 23 Mar 2006 02:59:37 -0800 Subject: [PATCH] i386: remove duplicate declaration of mp_bus_id_to_pci_bus mp_bus_id_to_pci_bus is declared identically twice. Signed-off-by: Chris Wright Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-i386/mpspec.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/asm-i386/mpspec.h b/include/asm-i386/mpspec.h index 64a0b8e6afeb..62113d3bfdc2 100644 --- a/include/asm-i386/mpspec.h +++ b/include/asm-i386/mpspec.h @@ -22,7 +22,6 @@ extern int mp_bus_id_to_type [MAX_MP_BUSSES]; extern int mp_irq_entries; extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES]; extern int mpc_default_type; -extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES]; extern unsigned long mp_lapic_addr; extern int pic_mode; extern int using_apic_timer; -- cgit v1.2.3 From 99b7de33477882b86d54ce8ecbf90147f9d106d7 Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Thu, 23 Mar 2006 02:59:41 -0800 Subject: [PATCH] x86: early printk handling fixes The history is that -mm kernels do not work for me for a few months already. The things started from crashing somewhere after starting init, and for the last month - no boot at all, just "Uncompressing... OK, booting kernel", and silence. Early console didn't work too. With the latest releases this degraded into an infinite stream of the "Unknown interrupt or fault" messages. So today my patience ran out and I started to think how can I collect at least some info for the bug-report. Attached is the patch that allows to gather some valueable debug info on the problem by making an early console more useable. I can't properly test the patch, as the kernel still doesn't boot, so I'll explain it in details in a hope someone else can justify the intrusive changes. arch_hooks.h: added prototypes for setup_early_printk() and early_printk(). setup.c: killed wrong setup_early_printk() prototype. Moved setup_early_printk() a bit earlier, as it was not "early enough" to cover the bug I was fighting with. early_printk.c: made it to start printing from the bottom of the screen, otherwise the messages interfere with the ones of the boot-loader, so you can't read them. Signed-off-by: Stas Sergeev Cc: Andi Kleen Cc: Zwane Mwaikambo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/setup.c | 23 ++++++++++------------- arch/x86_64/kernel/early_printk.c | 3 ++- include/asm-i386/arch_hooks.h | 3 +++ 3 files changed, 15 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 5f58f8cb9836..2d8782960f41 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -1459,6 +1459,16 @@ void __init setup_arch(char **cmdline_p) parse_cmdline_early(cmdline_p); +#ifdef CONFIG_EARLY_PRINTK + { + char *s = strstr(*cmdline_p, "earlyprintk="); + if (s) { + setup_early_printk(strchr(s, '=') + 1); + printk("early console enabled\n"); + } + } +#endif + max_low_pfn = setup_memory(); /* @@ -1483,19 +1493,6 @@ void __init setup_arch(char **cmdline_p) * NOTE: at this point the bootmem allocator is fully available. */ -#ifdef CONFIG_EARLY_PRINTK - { - char *s = strstr(*cmdline_p, "earlyprintk="); - if (s) { - extern void setup_early_printk(char *); - - setup_early_printk(strchr(s, '=') + 1); - printk("early console enabled\n"); - } - } -#endif - - dmi_scan_machine(); #ifdef CONFIG_X86_GENERICARCH diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c index 6dffb498ccd7..6fcdcb80b07a 100644 --- a/arch/x86_64/kernel/early_printk.c +++ b/arch/x86_64/kernel/early_printk.c @@ -21,7 +21,7 @@ #define MAX_XPOS max_xpos static int max_ypos = 25, max_xpos = 80; -static int current_ypos = 1, current_xpos = 0; +static int current_ypos = 25, current_xpos = 0; static void early_vga_write(struct console *con, const char *str, unsigned n) { @@ -244,6 +244,7 @@ int __init setup_early_printk(char *opt) && SCREEN_INFO.orig_video_isVGA == 1) { max_xpos = SCREEN_INFO.orig_video_cols; max_ypos = SCREEN_INFO.orig_video_lines; + current_ypos = max_ypos; early_console = &early_vga_console; } else if (!strncmp(buf, "simnow", 6)) { simnow_init(buf + 6); diff --git a/include/asm-i386/arch_hooks.h b/include/asm-i386/arch_hooks.h index 28b96a6fb9fa..238cf4275b96 100644 --- a/include/asm-i386/arch_hooks.h +++ b/include/asm-i386/arch_hooks.h @@ -24,4 +24,7 @@ extern void trap_init_hook(void); extern void time_init_hook(void); extern void mca_nmi_hook(void); +extern int setup_early_printk(char *); +extern void early_printk(const char *fmt, ...) __attribute__((format(printf,1,2))); + #endif -- cgit v1.2.3 From 101f12af16fb12f8da8100899a13ee1b1b576a0a Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Thu, 23 Mar 2006 02:59:45 -0800 Subject: [PATCH] i386: actively synchronize vmalloc area when registering certain callbacks Registering a callback handler through register_die_notifier() is obviously primarily intended for use by modules. However, the way these currently get called it is basically impossible for them to actually be used by modules, as there is, on non-PAE configurationes, a good chance (the larger the module, the better) for the system to crash as a result. This is because the callback gets invoked (a) in the page fault path before the top level page table propagation gets carried out (hence a fault to propagate the top level page table entry/entries mapping to module's code/data would nest infinitly) and (b) in the NMI path, where nested faults must absolutely not happen, since otherwise the IRET from the nested fault re-enables NMIs, potentially resulting in nested NMI occurences. Besides the modular aspect, similar problems would even arise for in- kernel consumers of the API if they touched ioremap()ed or vmalloc()ed memory inside their handlers. Signed-off-by: Jan Beulich Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/traps.c | 3 + arch/i386/mm/fault.c | 173 +++++++++++++++++++++++++------------- include/asm-i386/pgtable-2level.h | 2 + include/asm-i386/pgtable-3level.h | 2 + 4 files changed, 123 insertions(+), 57 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index f20797b8da1d..d510de7e4f2a 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -99,6 +99,8 @@ int register_die_notifier(struct notifier_block *nb) { int err = 0; unsigned long flags; + + vmalloc_sync_all(); spin_lock_irqsave(&die_notifier_lock, flags); err = notifier_chain_register(&i386die_chain, nb); spin_unlock_irqrestore(&die_notifier_lock, flags); @@ -713,6 +715,7 @@ fastcall void do_nmi(struct pt_regs * regs, long error_code) void set_nmi_callback(nmi_callback_t callback) { + vmalloc_sync_all(); rcu_assign_pointer(nmi_callback, callback); } EXPORT_SYMBOL_GPL(set_nmi_callback); diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index cf572d9a3b6e..bbb24af5d860 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c @@ -214,6 +214,68 @@ static noinline void force_sig_info_fault(int si_signo, int si_code, fastcall void do_invalid_op(struct pt_regs *, unsigned long); +static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) +{ + unsigned index = pgd_index(address); + pgd_t *pgd_k; + pud_t *pud, *pud_k; + pmd_t *pmd, *pmd_k; + + pgd += index; + pgd_k = init_mm.pgd + index; + + if (!pgd_present(*pgd_k)) + return NULL; + + /* + * set_pgd(pgd, *pgd_k); here would be useless on PAE + * and redundant with the set_pmd() on non-PAE. As would + * set_pud. + */ + + pud = pud_offset(pgd, address); + pud_k = pud_offset(pgd_k, address); + if (!pud_present(*pud_k)) + return NULL; + + pmd = pmd_offset(pud, address); + pmd_k = pmd_offset(pud_k, address); + if (!pmd_present(*pmd_k)) + return NULL; + if (!pmd_present(*pmd)) + set_pmd(pmd, *pmd_k); + else + BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k)); + return pmd_k; +} + +/* + * Handle a fault on the vmalloc or module mapping area + * + * This assumes no large pages in there. + */ +static inline int vmalloc_fault(unsigned long address) +{ + unsigned long pgd_paddr; + pmd_t *pmd_k; + pte_t *pte_k; + /* + * Synchronize this task's top level page-table + * with the 'reference' page table. + * + * Do _not_ use "current" here. We might be inside + * an interrupt in the middle of a task switch.. + */ + pgd_paddr = read_cr3(); + pmd_k = vmalloc_sync_one(__va(pgd_paddr), address); + if (!pmd_k) + return -1; + pte_k = pte_offset_kernel(pmd_k, address); + if (!pte_present(*pte_k)) + return -1; + return 0; +} + /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate @@ -223,6 +285,8 @@ fastcall void do_invalid_op(struct pt_regs *, unsigned long); * bit 0 == 0 means no page found, 1 means protection fault * bit 1 == 0 means read, 1 means write * bit 2 == 0 means kernel, 1 means user-mode + * bit 3 == 1 means use of reserved bit detected + * bit 4 == 1 means fault was an instruction fetch */ fastcall void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) @@ -237,13 +301,6 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs, /* get the address */ address = read_cr2(); - if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, - SIGSEGV) == NOTIFY_STOP) - return; - /* It's safe to allow irq's after cr2 has been saved */ - if (regs->eflags & (X86_EFLAGS_IF|VM_MASK)) - local_irq_enable(); - tsk = current; si_code = SEGV_MAPERR; @@ -259,17 +316,29 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs, * * This verifies that the fault happens in kernel space * (error_code & 4) == 0, and that the fault was not a - * protection error (error_code & 1) == 0. + * protection error (error_code & 9) == 0. */ - if (unlikely(address >= TASK_SIZE)) { - if (!(error_code & 5)) - goto vmalloc_fault; - /* + if (unlikely(address >= TASK_SIZE)) { + if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0) + return; + if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, + SIGSEGV) == NOTIFY_STOP) + return; + /* * Don't take the mm semaphore here. If we fixup a prefetch * fault we could otherwise deadlock. */ goto bad_area_nosemaphore; - } + } + + if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, + SIGSEGV) == NOTIFY_STOP) + return; + + /* It's safe to allow irq's after cr2 has been saved and the vmalloc + fault has been handled. */ + if (regs->eflags & (X86_EFLAGS_IF|VM_MASK)) + local_irq_enable(); mm = tsk->mm; @@ -510,51 +579,41 @@ do_sigbus: tsk->thread.error_code = error_code; tsk->thread.trap_no = 14; force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk); - return; - -vmalloc_fault: - { - /* - * Synchronize this task's top level page-table - * with the 'reference' page table. - * - * Do _not_ use "tsk" here. We might be inside - * an interrupt in the middle of a task switch.. - */ - int index = pgd_index(address); - unsigned long pgd_paddr; - pgd_t *pgd, *pgd_k; - pud_t *pud, *pud_k; - pmd_t *pmd, *pmd_k; - pte_t *pte_k; - - pgd_paddr = read_cr3(); - pgd = index + (pgd_t *)__va(pgd_paddr); - pgd_k = init_mm.pgd + index; - - if (!pgd_present(*pgd_k)) - goto no_context; - - /* - * set_pgd(pgd, *pgd_k); here would be useless on PAE - * and redundant with the set_pmd() on non-PAE. As would - * set_pud. - */ +} - pud = pud_offset(pgd, address); - pud_k = pud_offset(pgd_k, address); - if (!pud_present(*pud_k)) - goto no_context; - - pmd = pmd_offset(pud, address); - pmd_k = pmd_offset(pud_k, address); - if (!pmd_present(*pmd_k)) - goto no_context; - set_pmd(pmd, *pmd_k); +#ifndef CONFIG_X86_PAE +void vmalloc_sync_all(void) +{ + /* + * Note that races in the updates of insync and start aren't + * problematic: insync can only get set bits added, and updates to + * start are only improving performance (without affecting correctness + * if undone). + */ + static DECLARE_BITMAP(insync, PTRS_PER_PGD); + static unsigned long start = TASK_SIZE; + unsigned long address; - pte_k = pte_offset_kernel(pmd_k, address); - if (!pte_present(*pte_k)) - goto no_context; - return; + BUILD_BUG_ON(TASK_SIZE & ~PGDIR_MASK); + for (address = start; address >= TASK_SIZE; address += PGDIR_SIZE) { + if (!test_bit(pgd_index(address), insync)) { + unsigned long flags; + struct page *page; + + spin_lock_irqsave(&pgd_lock, flags); + for (page = pgd_list; page; page = + (struct page *)page->index) + if (!vmalloc_sync_one(page_address(page), + address)) { + BUG_ON(page != pgd_list); + break; + } + spin_unlock_irqrestore(&pgd_lock, flags); + if (!page) + set_bit(pgd_index(address), insync); + } + if (address == start && test_bit(pgd_index(address), insync)) + start = address + PGDIR_SIZE; } } +#endif diff --git a/include/asm-i386/pgtable-2level.h b/include/asm-i386/pgtable-2level.h index 74ef721b534d..27bde973abc7 100644 --- a/include/asm-i386/pgtable-2level.h +++ b/include/asm-i386/pgtable-2level.h @@ -61,4 +61,6 @@ static inline int pte_exec_kernel(pte_t pte) #define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_low }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) +void vmalloc_sync_all(void); + #endif /* _I386_PGTABLE_2LEVEL_H */ diff --git a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h index f1a8b454920a..36a5aa63cbbf 100644 --- a/include/asm-i386/pgtable-3level.h +++ b/include/asm-i386/pgtable-3level.h @@ -152,4 +152,6 @@ static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot) #define __pmd_free_tlb(tlb, x) do { } while (0) +#define vmalloc_sync_all() ((void)0) + #endif /* _I386_PGTABLE_3LEVEL_H */ -- cgit v1.2.3 From db753bdfc24c31228996799d508ce3bf7cbe3b99 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Thu, 23 Mar 2006 02:59:46 -0800 Subject: [PATCH] i386: fix uses of user_mode() vs. user_mode_vm() >commit 76381fee7e8feb4c22be636aa5d4765dbe4fbf9e >Author: Vincent Hanquez >Date: Thu Jun 23 00:08:46 2005 -0700 > > [PATCH] xen: x86_64: use more usermode macro > > Make use of the user_mode macro where it's possible. This is useful for Xen > because it will need only to redefine only the macro to a hypervisor call. I am of the opinion that the above changeset is incomplete, i.e. it missed converting some previous uses of user_mode to user_mode_vm. While most of them could be considered just cosmetical, at least the one in die_nmi doesn't appear to be. Signed-off-by: Jan Beulich Cc: Vincent Hanquez Cc: Zachary Amsden Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/crash.c | 2 +- arch/i386/kernel/process.c | 2 +- arch/i386/kernel/traps.c | 4 ++-- include/asm-i386/mach-default/do_timer.h | 2 +- include/asm-i386/mach-visws/do_timer.h | 2 +- include/asm-i386/mach-voyager/do_timer.h | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c index d49dbe8dc96b..e3c5fca0aa8a 100644 --- a/arch/i386/kernel/crash.c +++ b/arch/i386/kernel/crash.c @@ -105,7 +105,7 @@ static int crash_nmi_callback(struct pt_regs *regs, int cpu) return 1; local_irq_disable(); - if (!user_mode(regs)) { + if (!user_mode_vm(regs)) { crash_fixup_ss_esp(&fixed_regs, regs); regs = &fixed_regs; } diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 0480454ebffa..299e61674084 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -295,7 +295,7 @@ void show_regs(struct pt_regs * regs) printk("EIP: %04x:[<%08lx>] CPU: %d\n",0xffff & regs->xcs,regs->eip, smp_processor_id()); print_symbol("EIP is at %s\n", regs->eip); - if (user_mode(regs)) + if (user_mode_vm(regs)) printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp); printk(" EFLAGS: %08lx %s (%s %.*s)\n", regs->eflags, print_tainted(), system_utsname.release, diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index d510de7e4f2a..a807a2da581d 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -254,7 +254,7 @@ void show_registers(struct pt_regs *regs) esp = (unsigned long) (®s->esp); savesegment(ss, ss); - if (user_mode(regs)) { + if (user_mode_vm(regs)) { in_kernel = 0; esp = regs->esp; ss = regs->xss & 0xffff; @@ -644,7 +644,7 @@ void die_nmi (struct pt_regs *regs, const char *msg) /* If we are in kernel we are probably nested up pretty bad * and might aswell get out now while we still can. */ - if (!user_mode(regs)) { + if (!user_mode_vm(regs)) { current->thread.trap_no = 2; crash_kexec(regs); } diff --git a/include/asm-i386/mach-default/do_timer.h b/include/asm-i386/mach-default/do_timer.h index 56211414fc95..6312c3e79814 100644 --- a/include/asm-i386/mach-default/do_timer.h +++ b/include/asm-i386/mach-default/do_timer.h @@ -18,7 +18,7 @@ static inline void do_timer_interrupt_hook(struct pt_regs *regs) { do_timer(regs); #ifndef CONFIG_SMP - update_process_times(user_mode(regs)); + update_process_times(user_mode_vm(regs)); #endif /* * In the SMP case we use the local APIC timer interrupt to do the diff --git a/include/asm-i386/mach-visws/do_timer.h b/include/asm-i386/mach-visws/do_timer.h index 92d638fc8b11..95568e6ca91c 100644 --- a/include/asm-i386/mach-visws/do_timer.h +++ b/include/asm-i386/mach-visws/do_timer.h @@ -11,7 +11,7 @@ static inline void do_timer_interrupt_hook(struct pt_regs *regs) do_timer(regs); #ifndef CONFIG_SMP - update_process_times(user_mode(regs)); + update_process_times(user_mode_vm(regs)); #endif /* * In the SMP case we use the local APIC timer interrupt to do the diff --git a/include/asm-i386/mach-voyager/do_timer.h b/include/asm-i386/mach-voyager/do_timer.h index ae510e5d0d78..eaf518098981 100644 --- a/include/asm-i386/mach-voyager/do_timer.h +++ b/include/asm-i386/mach-voyager/do_timer.h @@ -5,7 +5,7 @@ static inline void do_timer_interrupt_hook(struct pt_regs *regs) { do_timer(regs); #ifndef CONFIG_SMP - update_process_times(user_mode(regs)); + update_process_times(user_mode_vm(regs)); #endif voyager_timer_interrupt(regs); -- cgit v1.2.3 From 52f4a91afd9316fb4f0f3a77c5ff56b9c98632ea Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Thu, 23 Mar 2006 02:59:50 -0800 Subject: [PATCH] Fix the imlicit declaration of mtrr_centaur_report_mcr in arch/i386/kernel/cpu/centaur.c arch/i386/kernel/cpu/centaur.c: In function `centaur_mcr_insert': arch/i386/kernel/cpu/centaur.c:33: warning: implicit declaration of function `mtrr_centaur_report_mcr' Signed-off-by: Jesper Juhl Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/centaur.c | 1 + include/asm-i386/mtrr.h | 1 + 2 files changed, 2 insertions(+) (limited to 'include') diff --git a/arch/i386/kernel/cpu/centaur.c b/arch/i386/kernel/cpu/centaur.c index f52669ecb93f..bd75629dd262 100644 --- a/arch/i386/kernel/cpu/centaur.c +++ b/arch/i386/kernel/cpu/centaur.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "cpu.h" #ifdef CONFIG_X86_OOSTORE diff --git a/include/asm-i386/mtrr.h b/include/asm-i386/mtrr.h index 5b6ceda68c5f..64cf937c7e33 100644 --- a/include/asm-i386/mtrr.h +++ b/include/asm-i386/mtrr.h @@ -25,6 +25,7 @@ #include #include +#include #define MTRR_IOCTL_BASE 'M' -- cgit v1.2.3 From 42c059e04d507802006911e316d86aa8ef75eb73 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert <76306.1226@compuserve.com> Date: Thu, 23 Mar 2006 02:59:55 -0800 Subject: [PATCH] i386 spinlocks: disable interrupts only if we enabled them _raw_spin_lock_flags() is entered with interrupts disabled. If it cannot obtain a spinlock, it checks the flags that were passed and re-enables interrupts before spinning if that's how the flags are set. When the spinlock might be available, it disables interrupts (even if they are already disabled) before trying to get the lock. Change that so interrupts are only disabled if they have been enabled. This costs nine bytes of duplicated spinloop code. Fastpath before patch: jle not-taken conditional jump cli disable interrupts jmp unconditional jump Fastpath after patch, if interrupts were not enabled: jg taken conditional branch Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Acked-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-i386/spinlock.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h index a1b8a8a30e21..d76b7693cf1d 100644 --- a/include/asm-i386/spinlock.h +++ b/include/asm-i386/spinlock.h @@ -35,18 +35,23 @@ #define __raw_spin_lock_string_flags \ "\n1:\t" \ "lock ; decb %0\n\t" \ - "jns 4f\n\t" \ + "jns 5f\n" \ "2:\t" \ "testl $0x200, %1\n\t" \ - "jz 3f\n\t" \ - "sti\n\t" \ + "jz 4f\n\t" \ + "sti\n" \ "3:\t" \ "rep;nop\n\t" \ "cmpb $0, %0\n\t" \ "jle 3b\n\t" \ "cli\n\t" \ "jmp 1b\n" \ - "4:\n\t" + "4:\t" \ + "rep;nop\n\t" \ + "cmpb $0, %0\n\t" \ + "jg 1b\n\t" \ + "jmp 4b\n" \ + "5:\n\t" #define __raw_spin_lock_string_up \ "\n\tdecb %0" -- cgit v1.2.3 From aeefc956d5d8f8402216a5447bd72ade9eb37eff Mon Sep 17 00:00:00 2001 From: Markus Gutschke Date: Thu, 23 Mar 2006 02:59:56 -0800 Subject: [PATCH] x86: Make _syscallX() macros compile in PIC mode Gcc reserves %ebx when compiling position-independent-code on i386. This means, the _syscallX() macros in include/asm-i386/unistd.h will not compile. This patch is changes the existing macros to take special care to preserve %ebx. The bug can be tracked at http://bugzilla.kernel.org/show_bug.cgi?id=6204 Signed-off-by: Markus Gutschke Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-i386/unistd.h | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h index dc81a55dd94d..d8afd0e3b81a 100644 --- a/include/asm-i386/unistd.h +++ b/include/asm-i386/unistd.h @@ -347,9 +347,9 @@ __syscall_return(type,__res); \ type name(type1 arg1) \ { \ long __res; \ -__asm__ volatile ("int $0x80" \ +__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \ : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(arg1)) : "memory"); \ + : "0" (__NR_##name),"ri" ((long)(arg1)) : "memory"); \ __syscall_return(type,__res); \ } @@ -357,9 +357,10 @@ __syscall_return(type,__res); \ type name(type1 arg1,type2 arg2) \ { \ long __res; \ -__asm__ volatile ("int $0x80" \ +__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \ : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)) : "memory"); \ + : "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)) \ + : "memory"); \ __syscall_return(type,__res); \ } @@ -367,9 +368,9 @@ __syscall_return(type,__res); \ type name(type1 arg1,type2 arg2,type3 arg3) \ { \ long __res; \ -__asm__ volatile ("int $0x80" \ +__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \ : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + : "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), \ "d" ((long)(arg3)) : "memory"); \ __syscall_return(type,__res); \ } @@ -378,9 +379,9 @@ __syscall_return(type,__res); \ type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ { \ long __res; \ -__asm__ volatile ("int $0x80" \ +__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \ : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + : "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), \ "d" ((long)(arg3)),"S" ((long)(arg4)) : "memory"); \ __syscall_return(type,__res); \ } @@ -390,10 +391,12 @@ __syscall_return(type,__res); \ type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ { \ long __res; \ -__asm__ volatile ("int $0x80" \ +__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; movl %1,%%eax ; " \ + "int $0x80 ; pop %%ebx" \ : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ - "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)) : "memory"); \ + : "i" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)) \ + : "memory"); \ __syscall_return(type,__res); \ } @@ -402,11 +405,14 @@ __syscall_return(type,__res); \ type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \ { \ long __res; \ -__asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; int $0x80 ; pop %%ebp" \ + struct { long __a1; long __a6; } __s = { (long)arg1, (long)arg6 }; \ +__asm__ volatile ("push %%ebp ; push %%ebx ; movl 4(%2),%%ebp ; " \ + "movl 0(%2),%%ebx ; movl %1,%%eax ; int $0x80 ; " \ + "pop %%ebx ; pop %%ebp" \ : "=a" (__res) \ - : "i" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ - "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)), \ - "0" ((long)(arg6)) : "memory"); \ + : "i" (__NR_##name),"0" ((long)(&__s)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)) \ + : "memory"); \ __syscall_return(type,__res); \ } -- cgit v1.2.3 From f577eb30afdc68233f25d4d82b04102129262365 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 23 Mar 2006 02:59:59 -0800 Subject: [PATCH] swsusp: low level interface Introduce the low level interface that can be used for handling the snapshot of the system memory by the in-kernel swap-writing/reading code of swsusp and the userland interface code (to be introduced shortly). Also change the way in which swsusp records the allocated swap pages and, consequently, simplifies the in-kernel swap-writing/reading code (this is necessary for the userland interface too). To this end, it introduces two helper functions in mm/swapfile.c, so that the swsusp code does not refer directly to the swap internals. Signed-off-by: Rafael J. Wysocki Acked-by: Pavel Machek Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/swap.h | 5 +- kernel/power/disk.c | 12 +- kernel/power/power.h | 26 +- kernel/power/snapshot.c | 326 +++++++++++++++++++++- kernel/power/swsusp.c | 723 +++++++++++++++++------------------------------- mm/swapfile.c | 55 +++- 6 files changed, 656 insertions(+), 491 deletions(-) (limited to 'include') diff --git a/include/linux/swap.h b/include/linux/swap.h index 12415dd94451..54eac8a39a4c 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -234,14 +234,15 @@ extern struct page * read_swap_cache_async(swp_entry_t, struct vm_area_struct *v /* linux/mm/swapfile.c */ extern long total_swap_pages; extern unsigned int nr_swapfiles; -extern struct swap_info_struct swap_info[]; extern void si_swapinfo(struct sysinfo *); extern swp_entry_t get_swap_page(void); -extern swp_entry_t get_swap_page_of_type(int type); +extern swp_entry_t get_swap_page_of_type(int); extern int swap_duplicate(swp_entry_t); extern int valid_swaphandles(swp_entry_t, unsigned long *); extern void swap_free(swp_entry_t); extern void free_swap_and_cache(swp_entry_t); +extern int swap_type_of(dev_t); +extern unsigned int count_swap_pages(int, int); extern sector_t map_swap_page(struct swap_info_struct *, pgoff_t); extern struct swap_info_struct *get_swap_info_struct(unsigned); extern int can_share_swap_page(struct page *); diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 0b43847dc980..4eb464b71347 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c @@ -26,9 +26,9 @@ extern suspend_disk_method_t pm_disk_mode; extern int swsusp_shrink_memory(void); extern int swsusp_suspend(void); -extern int swsusp_write(struct pbe *pblist, unsigned int nr_pages); +extern int swsusp_write(void); extern int swsusp_check(void); -extern int swsusp_read(struct pbe **pblist_ptr); +extern int swsusp_read(void); extern void swsusp_close(void); extern int swsusp_resume(void); @@ -70,10 +70,6 @@ static void power_down(suspend_disk_method_t mode) while(1); } - -static int in_suspend __nosavedata = 0; - - static inline void platform_finish(void) { if (pm_disk_mode == PM_DISK_PLATFORM) { @@ -145,7 +141,7 @@ int pm_suspend_disk(void) if (in_suspend) { device_resume(); pr_debug("PM: writing image.\n"); - error = swsusp_write(pagedir_nosave, nr_copy_pages); + error = swsusp_write(); if (!error) power_down(pm_disk_mode); else { @@ -216,7 +212,7 @@ static int software_resume(void) pr_debug("PM: Reading swsusp image.\n"); - if ((error = swsusp_read(&pagedir_nosave))) { + if ((error = swsusp_read())) { swsusp_free(); goto Thaw; } diff --git a/kernel/power/power.h b/kernel/power/power.h index 388dba680841..ea7132ed029b 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -37,21 +37,31 @@ extern struct subsystem power_subsys; /* References to section boundaries */ extern const void __nosave_begin, __nosave_end; -extern unsigned int nr_copy_pages; extern struct pbe *pagedir_nosave; /* Preferred image size in bytes (default 500 MB) */ extern unsigned long image_size; +extern int in_suspend; + extern asmlinkage int swsusp_arch_suspend(void); extern asmlinkage int swsusp_arch_resume(void); extern unsigned int count_data_pages(void); -extern void free_pagedir(struct pbe *pblist); -extern void release_eaten_pages(void); -extern struct pbe *alloc_pagedir(unsigned nr_pages, gfp_t gfp_mask, int safe_needed); extern void swsusp_free(void); -extern int alloc_data_pages(struct pbe *pblist, gfp_t gfp_mask, int safe_needed); -extern unsigned int snapshot_nr_pages(void); -extern struct pbe *snapshot_pblist(void); -extern void snapshot_pblist_set(struct pbe *pblist); + +struct snapshot_handle { + loff_t offset; + unsigned int page; + unsigned int page_offset; + unsigned int prev; + struct pbe *pbe; + void *buffer; + unsigned int buf_offset; +}; + +#define data_of(handle) ((handle).buffer + (handle).buf_offset) + +extern int snapshot_read_next(struct snapshot_handle *handle, size_t count); +extern int snapshot_write_next(struct snapshot_handle *handle, size_t count); +int snapshot_image_loaded(struct snapshot_handle *handle); diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 8d5a5986d621..cc349437fb72 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -10,6 +10,7 @@ */ +#include #include #include #include @@ -34,7 +35,8 @@ #include "power.h" struct pbe *pagedir_nosave; -unsigned int nr_copy_pages; +static unsigned int nr_copy_pages; +static unsigned int nr_meta_pages; #ifdef CONFIG_HIGHMEM unsigned int count_highmem_pages(void) @@ -235,7 +237,7 @@ static void copy_data_pages(struct pbe *pblist) * free_pagedir - free pages allocated with alloc_pagedir() */ -void free_pagedir(struct pbe *pblist) +static void free_pagedir(struct pbe *pblist) { struct pbe *pbe; @@ -301,7 +303,7 @@ struct eaten_page { static struct eaten_page *eaten_pages = NULL; -void release_eaten_pages(void) +static void release_eaten_pages(void) { struct eaten_page *p, *q; @@ -376,7 +378,6 @@ struct pbe *alloc_pagedir(unsigned int nr_pages, gfp_t gfp_mask, int safe_needed if (!nr_pages) return NULL; - pr_debug("alloc_pagedir(): nr_pages = %d\n", nr_pages); pblist = alloc_image_page(gfp_mask, safe_needed); /* FIXME: rewrite this ugly loop */ for (pbe = pblist, num = PBES_PER_PAGE; pbe && num < nr_pages; @@ -414,6 +415,9 @@ void swsusp_free(void) } } } + nr_copy_pages = 0; + nr_meta_pages = 0; + pagedir_nosave = NULL; } @@ -437,7 +441,7 @@ static int enough_free_mem(unsigned int nr_pages) (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE); } -int alloc_data_pages(struct pbe *pblist, gfp_t gfp_mask, int safe_needed) +static int alloc_data_pages(struct pbe *pblist, gfp_t gfp_mask, int safe_needed) { struct pbe *p; @@ -504,7 +508,319 @@ asmlinkage int swsusp_save(void) */ nr_copy_pages = nr_pages; + nr_meta_pages = (nr_pages * sizeof(long) + PAGE_SIZE - 1) >> PAGE_SHIFT; printk("swsusp: critical section/: done (%d pages copied)\n", nr_pages); return 0; } + +static void init_header(struct swsusp_info *info) +{ + memset(info, 0, sizeof(struct swsusp_info)); + info->version_code = LINUX_VERSION_CODE; + info->num_physpages = num_physpages; + memcpy(&info->uts, &system_utsname, sizeof(system_utsname)); + info->cpus = num_online_cpus(); + info->image_pages = nr_copy_pages; + info->pages = nr_copy_pages + nr_meta_pages + 1; +} + +/** + * pack_orig_addresses - the .orig_address fields of the PBEs from the + * list starting at @pbe are stored in the array @buf[] (1 page) + */ + +static inline struct pbe *pack_orig_addresses(unsigned long *buf, struct pbe *pbe) +{ + int j; + + for (j = 0; j < PAGE_SIZE / sizeof(long) && pbe; j++) { + buf[j] = pbe->orig_address; + pbe = pbe->next; + } + if (!pbe) + for (; j < PAGE_SIZE / sizeof(long); j++) + buf[j] = 0; + return pbe; +} + +/** + * snapshot_read_next - used for reading the system memory snapshot. + * + * On the first call to it @handle should point to a zeroed + * snapshot_handle structure. The structure gets updated and a pointer + * to it should be passed to this function every next time. + * + * The @count parameter should contain the number of bytes the caller + * wants to read from the snapshot. It must not be zero. + * + * On success the function returns a positive number. Then, the caller + * is allowed to read up to the returned number of bytes from the memory + * location computed by the data_of() macro. The number returned + * may be smaller than @count, but this only happens if the read would + * cross a page boundary otherwise. + * + * The function returns 0 to indicate the end of data stream condition, + * and a negative number is returned on error. In such cases the + * structure pointed to by @handle is not updated and should not be used + * any more. + */ + +int snapshot_read_next(struct snapshot_handle *handle, size_t count) +{ + static unsigned long *buffer; + + if (handle->page > nr_meta_pages + nr_copy_pages) + return 0; + if (!buffer) { + /* This makes the buffer be freed by swsusp_free() */ + buffer = alloc_image_page(GFP_ATOMIC, 0); + if (!buffer) + return -ENOMEM; + } + if (!handle->offset) { + init_header((struct swsusp_info *)buffer); + handle->buffer = buffer; + handle->pbe = pagedir_nosave; + } + if (handle->prev < handle->page) { + if (handle->page <= nr_meta_pages) { + handle->pbe = pack_orig_addresses(buffer, handle->pbe); + if (!handle->pbe) + handle->pbe = pagedir_nosave; + } else { + handle->buffer = (void *)handle->pbe->address; + handle->pbe = handle->pbe->next; + } + handle->prev = handle->page; + } + handle->buf_offset = handle->page_offset; + if (handle->page_offset + count >= PAGE_SIZE) { + count = PAGE_SIZE - handle->page_offset; + handle->page_offset = 0; + handle->page++; + } else { + handle->page_offset += count; + } + handle->offset += count; + return count; +} + +/** + * mark_unsafe_pages - mark the pages that cannot be used for storing + * the image during resume, because they conflict with the pages that + * had been used before suspend + */ + +static int mark_unsafe_pages(struct pbe *pblist) +{ + struct zone *zone; + unsigned long zone_pfn; + struct pbe *p; + + if (!pblist) /* a sanity check */ + return -EINVAL; + + /* Clear page flags */ + for_each_zone (zone) { + for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) + if (pfn_valid(zone_pfn + zone->zone_start_pfn)) + ClearPageNosaveFree(pfn_to_page(zone_pfn + + zone->zone_start_pfn)); + } + + /* Mark orig addresses */ + for_each_pbe (p, pblist) { + if (virt_addr_valid(p->orig_address)) + SetPageNosaveFree(virt_to_page(p->orig_address)); + else + return -EFAULT; + } + + return 0; +} + +static void copy_page_backup_list(struct pbe *dst, struct pbe *src) +{ + /* We assume both lists contain the same number of elements */ + while (src) { + dst->orig_address = src->orig_address; + dst = dst->next; + src = src->next; + } +} + +static int check_header(struct swsusp_info *info) +{ + char *reason = NULL; + + if (info->version_code != LINUX_VERSION_CODE) + reason = "kernel version"; + if (info->num_physpages != num_physpages) + reason = "memory size"; + if (strcmp(info->uts.sysname,system_utsname.sysname)) + reason = "system type"; + if (strcmp(info->uts.release,system_utsname.release)) + reason = "kernel release"; + if (strcmp(info->uts.version,system_utsname.version)) + reason = "version"; + if (strcmp(info->uts.machine,system_utsname.machine)) + reason = "machine"; + if (reason) { + printk(KERN_ERR "swsusp: Resume mismatch: %s\n", reason); + return -EPERM; + } + return 0; +} + +/** + * load header - check the image header and copy data from it + */ + +static int load_header(struct snapshot_handle *handle, + struct swsusp_info *info) +{ + int error; + struct pbe *pblist; + + error = check_header(info); + if (!error) { + pblist = alloc_pagedir(info->image_pages, GFP_ATOMIC, 0); + if (!pblist) + return -ENOMEM; + pagedir_nosave = pblist; + handle->pbe = pblist; + nr_copy_pages = info->image_pages; + nr_meta_pages = info->pages - info->image_pages - 1; + } + return error; +} + +/** + * unpack_orig_addresses - copy the elements of @buf[] (1 page) to + * the PBEs in the list starting at @pbe + */ + +static inline struct pbe *unpack_orig_addresses(unsigned long *buf, + struct pbe *pbe) +{ + int j; + + for (j = 0; j < PAGE_SIZE / sizeof(long) && pbe; j++) { + pbe->orig_address = buf[j]; + pbe = pbe->next; + } + return pbe; +} + +/** + * create_image - use metadata contained in the PBE list + * pointed to by pagedir_nosave to mark the pages that will + * be overwritten in the process of restoring the system + * memory state from the image and allocate memory for + * the image avoiding these pages + */ + +static int create_image(struct snapshot_handle *handle) +{ + int error = 0; + struct pbe *p, *pblist; + + p = pagedir_nosave; + error = mark_unsafe_pages(p); + if (!error) { + pblist = alloc_pagedir(nr_copy_pages, GFP_ATOMIC, 1); + if (pblist) + copy_page_backup_list(pblist, p); + free_pagedir(p); + if (!pblist) + error = -ENOMEM; + } + if (!error) + error = alloc_data_pages(pblist, GFP_ATOMIC, 1); + if (!error) { + release_eaten_pages(); + pagedir_nosave = pblist; + } else { + pagedir_nosave = NULL; + handle->pbe = NULL; + nr_copy_pages = 0; + nr_meta_pages = 0; + } + return error; +} + +/** + * snapshot_write_next - used for writing the system memory snapshot. + * + * On the first call to it @handle should point to a zeroed + * snapshot_handle structure. The structure gets updated and a pointer + * to it should be passed to this function every next time. + * + * The @count parameter should contain the number of bytes the caller + * wants to write to the image. It must not be zero. + * + * On success the function returns a positive number. Then, the caller + * is allowed to write up to the returned number of bytes to the memory + * location computed by the data_of() macro. The number returned + * may be smaller than @count, but this only happens if the write would + * cross a page boundary otherwise. + * + * The function returns 0 to indicate the "end of file" condition, + * and a negative number is returned on error. In such cases the + * structure pointed to by @handle is not updated and should not be used + * any more. + */ + +int snapshot_write_next(struct snapshot_handle *handle, size_t count) +{ + static unsigned long *buffer; + int error = 0; + + if (handle->prev && handle->page > nr_meta_pages + nr_copy_pages) + return 0; + if (!buffer) { + /* This makes the buffer be freed by swsusp_free() */ + buffer = alloc_image_page(GFP_ATOMIC, 0); + if (!buffer) + return -ENOMEM; + } + if (!handle->offset) + handle->buffer = buffer; + if (handle->prev < handle->page) { + if (!handle->prev) { + error = load_header(handle, (struct swsusp_info *)buffer); + if (error) + return error; + } else if (handle->prev <= nr_meta_pages) { + handle->pbe = unpack_orig_addresses(buffer, handle->pbe); + if (!handle->pbe) { + error = create_image(handle); + if (error) + return error; + handle->pbe = pagedir_nosave; + handle->buffer = (void *)handle->pbe->address; + } + } else { + handle->pbe = handle->pbe->next; + handle->buffer = (void *)handle->pbe->address; + } + handle->prev = handle->page; + } + handle->buf_offset = handle->page_offset; + if (handle->page_offset + count >= PAGE_SIZE) { + count = PAGE_SIZE - handle->page_offset; + handle->page_offset = 0; + handle->page++; + } else { + handle->page_offset += count; + } + handle->offset += count; + return count; +} + +int snapshot_image_loaded(struct snapshot_handle *handle) +{ + return !(!handle->pbe || handle->pbe->next || !nr_copy_pages || + handle->page <= nr_meta_pages + nr_copy_pages); +} diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 4e90905f0e87..457084f50010 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -77,6 +77,8 @@ */ unsigned long image_size = 500 * 1024 * 1024; +int in_suspend __nosavedata = 0; + #ifdef CONFIG_HIGHMEM unsigned int count_highmem_pages(void); int save_highmem(void); @@ -98,8 +100,6 @@ static struct swsusp_header { char sig[10]; } __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header; -static struct swsusp_info swsusp_info; - /* * Saving part... */ @@ -129,255 +129,261 @@ static int mark_swapfiles(swp_entry_t start) return error; } -/* - * Check whether the swap device is the specified resume - * device, irrespective of whether they are specified by - * identical names. - * - * (Thus, device inode aliasing is allowed. You can say /dev/hda4 - * instead of /dev/ide/host0/bus0/target0/lun0/part4 [if using devfs] - * and they'll be considered the same device. This is *necessary* for - * devfs, since the resume code can only recognize the form /dev/hda4, - * but the suspend code would see the long name.) +/** + * swsusp_swap_check - check if the resume device is a swap device + * and get its index (if so) */ -static inline int is_resume_device(const struct swap_info_struct *swap_info) -{ - struct file *file = swap_info->swap_file; - struct inode *inode = file->f_dentry->d_inode; - - return S_ISBLK(inode->i_mode) && - swsusp_resume_device == MKDEV(imajor(inode), iminor(inode)); -} static int swsusp_swap_check(void) /* This is called before saving image */ { - int i; - - if (!swsusp_resume_device) - return -ENODEV; - spin_lock(&swap_lock); - for (i = 0; i < MAX_SWAPFILES; i++) { - if (!(swap_info[i].flags & SWP_WRITEOK)) - continue; - if (is_resume_device(swap_info + i)) { - spin_unlock(&swap_lock); - root_swap = i; - return 0; - } + int res = swap_type_of(swsusp_resume_device); + + if (res >= 0) { + root_swap = res; + return 0; } - spin_unlock(&swap_lock); - return -ENODEV; + return res; } /** - * write_page - Write one page to a fresh swap location. - * @addr: Address we're writing. - * @loc: Place to store the entry we used. + * The bitmap is used for tracing allocated swap pages * - * Allocate a new swap entry and 'sync' it. Note we discard -EIO - * errors. That is an artifact left over from swsusp. It did not - * check the return of rw_swap_page_sync() at all, since most pages - * written back to swap would return -EIO. - * This is a partial improvement, since we will at least return other - * errors, though we need to eventually fix the damn code. + * The entire bitmap consists of a number of bitmap_page + * structures linked with the help of the .next member. + * Thus each page can be allocated individually, so we only + * need to make 0-order memory allocations to create + * the bitmap. */ -static int write_page(unsigned long addr, swp_entry_t *loc) -{ - swp_entry_t entry; - int error = -ENOSPC; - entry = get_swap_page_of_type(root_swap); - if (swp_offset(entry)) { - error = rw_swap_page_sync(WRITE, entry, virt_to_page(addr)); - if (!error || error == -EIO) - *loc = entry; - } - return error; -} +#define BITMAP_PAGE_SIZE (PAGE_SIZE - sizeof(void *)) +#define BITMAP_PAGE_CHUNKS (BITMAP_PAGE_SIZE / sizeof(long)) +#define BITS_PER_CHUNK (sizeof(long) * 8) +#define BITMAP_PAGE_BITS (BITMAP_PAGE_CHUNKS * BITS_PER_CHUNK) + +struct bitmap_page { + unsigned long chunks[BITMAP_PAGE_CHUNKS]; + struct bitmap_page *next; +}; /** - * Swap map-handling functions + * The following functions are used for tracing the allocated + * swap pages, so that they can be freed in case of an error. * - * The swap map is a data structure used for keeping track of each page - * written to the swap. It consists of many swap_map_page structures - * that contain each an array of MAP_PAGE_SIZE swap entries. - * These structures are linked together with the help of either the - * .next (in memory) or the .next_swap (in swap) member. - * - * The swap map is created during suspend. At that time we need to keep - * it in memory, because we have to free all of the allocated swap - * entries if an error occurs. The memory needed is preallocated - * so that we know in advance if there's enough of it. - * - * The first swap_map_page structure is filled with the swap entries that - * correspond to the first MAP_PAGE_SIZE data pages written to swap and - * so on. After the all of the data pages have been written, the order - * of the swap_map_page structures in the map is reversed so that they - * can be read from swap in the original order. This causes the data - * pages to be loaded in exactly the same order in which they have been - * saved. - * - * During resume we only need to use one swap_map_page structure - * at a time, which means that we only need to use two memory pages for - * reading the image - one for reading the swap_map_page structures - * and the second for reading the data pages from swap. + * The functions operate on a linked bitmap structure defined + * above */ -#define MAP_PAGE_SIZE ((PAGE_SIZE - sizeof(swp_entry_t) - sizeof(void *)) \ - / sizeof(swp_entry_t)) - -struct swap_map_page { - swp_entry_t entries[MAP_PAGE_SIZE]; - swp_entry_t next_swap; - struct swap_map_page *next; -}; - -static inline void free_swap_map(struct swap_map_page *swap_map) +static void free_bitmap(struct bitmap_page *bitmap) { - struct swap_map_page *swp; + struct bitmap_page *bp; - while (swap_map) { - swp = swap_map->next; - free_page((unsigned long)swap_map); - swap_map = swp; + while (bitmap) { + bp = bitmap->next; + free_page((unsigned long)bitmap); + bitmap = bp; } } -static struct swap_map_page *alloc_swap_map(unsigned int nr_pages) +static struct bitmap_page *alloc_bitmap(unsigned int nr_bits) { - struct swap_map_page *swap_map, *swp; - unsigned n = 0; + struct bitmap_page *bitmap, *bp; + unsigned int n; - if (!nr_pages) + if (!nr_bits) return NULL; - pr_debug("alloc_swap_map(): nr_pages = %d\n", nr_pages); - swap_map = (struct swap_map_page *)get_zeroed_page(GFP_ATOMIC); - swp = swap_map; - for (n = MAP_PAGE_SIZE; n < nr_pages; n += MAP_PAGE_SIZE) { - swp->next = (struct swap_map_page *)get_zeroed_page(GFP_ATOMIC); - swp = swp->next; - if (!swp) { - free_swap_map(swap_map); + bitmap = (struct bitmap_page *)get_zeroed_page(GFP_KERNEL); + bp = bitmap; + for (n = BITMAP_PAGE_BITS; n < nr_bits; n += BITMAP_PAGE_BITS) { + bp->next = (struct bitmap_page *)get_zeroed_page(GFP_KERNEL); + bp = bp->next; + if (!bp) { + free_bitmap(bitmap); return NULL; } } - return swap_map; + return bitmap; } -/** - * reverse_swap_map - reverse the order of pages in the swap map - * @swap_map - */ - -static inline struct swap_map_page *reverse_swap_map(struct swap_map_page *swap_map) +static int bitmap_set(struct bitmap_page *bitmap, unsigned long bit) { - struct swap_map_page *prev, *next; - - prev = NULL; - while (swap_map) { - next = swap_map->next; - swap_map->next = prev; - prev = swap_map; - swap_map = next; + unsigned int n; + + n = BITMAP_PAGE_BITS; + while (bitmap && n <= bit) { + n += BITMAP_PAGE_BITS; + bitmap = bitmap->next; } - return prev; + if (!bitmap) + return -EINVAL; + n -= BITMAP_PAGE_BITS; + bit -= n; + n = 0; + while (bit >= BITS_PER_CHUNK) { + bit -= BITS_PER_CHUNK; + n++; + } + bitmap->chunks[n] |= (1UL << bit); + return 0; } -/** - * free_swap_map_entries - free the swap entries allocated to store - * the swap map @swap_map (this is only called in case of an error) - */ -static inline void free_swap_map_entries(struct swap_map_page *swap_map) +static unsigned long alloc_swap_page(int swap, struct bitmap_page *bitmap) { - while (swap_map) { - if (swap_map->next_swap.val) - swap_free(swap_map->next_swap); - swap_map = swap_map->next; + unsigned long offset; + + offset = swp_offset(get_swap_page_of_type(swap)); + if (offset) { + if (bitmap_set(bitmap, offset)) { + swap_free(swp_entry(swap, offset)); + offset = 0; + } } + return offset; } -/** - * save_swap_map - save the swap map used for tracing the data pages - * stored in the swap - */ - -static int save_swap_map(struct swap_map_page *swap_map, swp_entry_t *start) +static void free_all_swap_pages(int swap, struct bitmap_page *bitmap) { - swp_entry_t entry = (swp_entry_t){0}; - int error; + unsigned int bit, n; + unsigned long test; - while (swap_map) { - swap_map->next_swap = entry; - if ((error = write_page((unsigned long)swap_map, &entry))) - return error; - swap_map = swap_map->next; + bit = 0; + while (bitmap) { + for (n = 0; n < BITMAP_PAGE_CHUNKS; n++) + for (test = 1UL; test; test <<= 1) { + if (bitmap->chunks[n] & test) + swap_free(swp_entry(swap, bit)); + bit++; + } + bitmap = bitmap->next; } - *start = entry; - return 0; } /** - * free_image_entries - free the swap entries allocated to store - * the image data pages (this is only called in case of an error) + * write_page - Write one page to given swap location. + * @buf: Address we're writing. + * @offset: Offset of the swap page we're writing to. */ -static inline void free_image_entries(struct swap_map_page *swp) +static int write_page(void *buf, unsigned long offset) { - unsigned k; + swp_entry_t entry; + int error = -ENOSPC; - while (swp) { - for (k = 0; k < MAP_PAGE_SIZE; k++) - if (swp->entries[k].val) - swap_free(swp->entries[k]); - swp = swp->next; + if (offset) { + entry = swp_entry(root_swap, offset); + error = rw_swap_page_sync(WRITE, entry, virt_to_page(buf)); } + return error; } +/* + * The swap map is a data structure used for keeping track of each page + * written to a swap partition. It consists of many swap_map_page + * structures that contain each an array of MAP_PAGE_SIZE swap entries. + * These structures are stored on the swap and linked together with the + * help of the .next_swap member. + * + * The swap map is created during suspend. The swap map pages are + * allocated and populated one at a time, so we only need one memory + * page to set up the entire structure. + * + * During resume we also only need to use one swap_map_page structure + * at a time. + */ + +#define MAP_PAGE_ENTRIES (PAGE_SIZE / sizeof(long) - 1) + +struct swap_map_page { + unsigned long entries[MAP_PAGE_ENTRIES]; + unsigned long next_swap; +}; + /** - * The swap_map_handle structure is used for handling the swap map in + * The swap_map_handle structure is used for handling swap in * a file-alike way */ struct swap_map_handle { struct swap_map_page *cur; + unsigned long cur_swap; + struct bitmap_page *bitmap; unsigned int k; }; -static inline void init_swap_map_handle(struct swap_map_handle *handle, - struct swap_map_page *map) +static void release_swap_writer(struct swap_map_handle *handle) { - handle->cur = map; + if (handle->cur) + free_page((unsigned long)handle->cur); + handle->cur = NULL; + if (handle->bitmap) + free_bitmap(handle->bitmap); + handle->bitmap = NULL; +} + +static int get_swap_writer(struct swap_map_handle *handle) +{ + handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL); + if (!handle->cur) + return -ENOMEM; + handle->bitmap = alloc_bitmap(count_swap_pages(root_swap, 0)); + if (!handle->bitmap) { + release_swap_writer(handle); + return -ENOMEM; + } + handle->cur_swap = alloc_swap_page(root_swap, handle->bitmap); + if (!handle->cur_swap) { + release_swap_writer(handle); + return -ENOSPC; + } handle->k = 0; + return 0; } -static inline int swap_map_write_page(struct swap_map_handle *handle, - unsigned long addr) +static int swap_write_page(struct swap_map_handle *handle, void *buf) { int error; + unsigned long offset; - error = write_page(addr, handle->cur->entries + handle->k); + if (!handle->cur) + return -EINVAL; + offset = alloc_swap_page(root_swap, handle->bitmap); + error = write_page(buf, offset); if (error) return error; - if (++handle->k >= MAP_PAGE_SIZE) { - handle->cur = handle->cur->next; + handle->cur->entries[handle->k++] = offset; + if (handle->k >= MAP_PAGE_ENTRIES) { + offset = alloc_swap_page(root_swap, handle->bitmap); + if (!offset) + return -ENOSPC; + handle->cur->next_swap = offset; + error = write_page(handle->cur, handle->cur_swap); + if (error) + return error; + memset(handle->cur, 0, PAGE_SIZE); + handle->cur_swap = offset; handle->k = 0; } return 0; } +static int flush_swap_writer(struct swap_map_handle *handle) +{ + if (handle->cur && handle->cur_swap) + return write_page(handle->cur, handle->cur_swap); + else + return -EINVAL; +} + /** - * save_image_data - save the data pages pointed to by the PBEs - * from the list @pblist using the swap map handle @handle - * (assume there are @nr_pages data pages to save) + * save_image - save the suspend image data */ -static int save_image_data(struct pbe *pblist, - struct swap_map_handle *handle, - unsigned int nr_pages) +static int save_image(struct swap_map_handle *handle, + struct snapshot_handle *snapshot, + unsigned int nr_pages) { unsigned int m; - struct pbe *p; + int ret; int error = 0; printk("Saving image data pages (%u pages) ... ", nr_pages); @@ -385,98 +391,22 @@ static int save_image_data(struct pbe *pblist, if (!m) m = 1; nr_pages = 0; - for_each_pbe (p, pblist) { - error = swap_map_write_page(handle, p->address); - if (error) - break; - if (!(nr_pages % m)) - printk("\b\b\b\b%3d%%", nr_pages / m); - nr_pages++; - } + do { + ret = snapshot_read_next(snapshot, PAGE_SIZE); + if (ret > 0) { + error = swap_write_page(handle, data_of(*snapshot)); + if (error) + break; + if (!(nr_pages % m)) + printk("\b\b\b\b%3d%%", nr_pages / m); + nr_pages++; + } + } while (ret > 0); if (!error) printk("\b\b\b\bdone\n"); return error; } -static void dump_info(void) -{ - pr_debug(" swsusp: Version: %u\n",swsusp_info.version_code); - pr_debug(" swsusp: Num Pages: %ld\n",swsusp_info.num_physpages); - pr_debug(" swsusp: UTS Sys: %s\n",swsusp_info.uts.sysname); - pr_debug(" swsusp: UTS Node: %s\n",swsusp_info.uts.nodename); - pr_debug(" swsusp: UTS Release: %s\n",swsusp_info.uts.release); - pr_debug(" swsusp: UTS Version: %s\n",swsusp_info.uts.version); - pr_debug(" swsusp: UTS Machine: %s\n",swsusp_info.uts.machine); - pr_debug(" swsusp: UTS Domain: %s\n",swsusp_info.uts.domainname); - pr_debug(" swsusp: CPUs: %d\n",swsusp_info.cpus); - pr_debug(" swsusp: Image: %ld Pages\n",swsusp_info.image_pages); - pr_debug(" swsusp: Total: %ld Pages\n", swsusp_info.pages); -} - -static void init_header(unsigned int nr_pages) -{ - memset(&swsusp_info, 0, sizeof(swsusp_info)); - swsusp_info.version_code = LINUX_VERSION_CODE; - swsusp_info.num_physpages = num_physpages; - memcpy(&swsusp_info.uts, &system_utsname, sizeof(system_utsname)); - - swsusp_info.cpus = num_online_cpus(); - swsusp_info.image_pages = nr_pages; - swsusp_info.pages = nr_pages + - ((nr_pages * sizeof(long) + PAGE_SIZE - 1) >> PAGE_SHIFT) + 1; -} - -/** - * pack_orig_addresses - the .orig_address fields of the PBEs from the - * list starting at @pbe are stored in the array @buf[] (1 page) - */ - -static inline struct pbe *pack_orig_addresses(unsigned long *buf, - struct pbe *pbe) -{ - int j; - - for (j = 0; j < PAGE_SIZE / sizeof(long) && pbe; j++) { - buf[j] = pbe->orig_address; - pbe = pbe->next; - } - if (!pbe) - for (; j < PAGE_SIZE / sizeof(long); j++) - buf[j] = 0; - return pbe; -} - -/** - * save_image_metadata - save the .orig_address fields of the PBEs - * from the list @pblist using the swap map handle @handle - */ - -static int save_image_metadata(struct pbe *pblist, - struct swap_map_handle *handle) -{ - unsigned long *buf; - unsigned int n = 0; - struct pbe *p; - int error = 0; - - printk("Saving image metadata ... "); - buf = (unsigned long *)get_zeroed_page(GFP_ATOMIC); - if (!buf) - return -ENOMEM; - p = pblist; - while (p) { - p = pack_orig_addresses(buf, p); - error = swap_map_write_page(handle, (unsigned long)buf); - if (error) - break; - n++; - } - free_page((unsigned long)buf); - if (!error) - printk("done (%u pages saved)\n", n); - return error; -} - /** * enough_swap - Make sure we have enough swap to save the image. * @@ -486,8 +416,7 @@ static int save_image_metadata(struct pbe *pblist, static int enough_swap(unsigned int nr_pages) { - unsigned int free_swap = swap_info[root_swap].pages - - swap_info[root_swap].inuse_pages; + unsigned int free_swap = count_swap_pages(root_swap, 1); pr_debug("swsusp: free swap pages: %u\n", free_swap); return free_swap > (nr_pages + PAGES_FOR_IO + @@ -503,57 +432,44 @@ static int enough_swap(unsigned int nr_pages) * correctly, we'll mark system clean, anyway.) */ -int swsusp_write(struct pbe *pblist, unsigned int nr_pages) +int swsusp_write(void) { - struct swap_map_page *swap_map; struct swap_map_handle handle; - swp_entry_t start; + struct snapshot_handle snapshot; + struct swsusp_info *header; + unsigned long start; int error; if ((error = swsusp_swap_check())) { printk(KERN_ERR "swsusp: Cannot find swap device, try swapon -a.\n"); return error; } - if (!enough_swap(nr_pages)) { + memset(&snapshot, 0, sizeof(struct snapshot_handle)); + error = snapshot_read_next(&snapshot, PAGE_SIZE); + if (error < PAGE_SIZE) + return error < 0 ? error : -EFAULT; + header = (struct swsusp_info *)data_of(snapshot); + if (!enough_swap(header->pages)) { printk(KERN_ERR "swsusp: Not enough free swap\n"); return -ENOSPC; } - - init_header(nr_pages); - swap_map = alloc_swap_map(swsusp_info.pages); - if (!swap_map) - return -ENOMEM; - init_swap_map_handle(&handle, swap_map); - - error = swap_map_write_page(&handle, (unsigned long)&swsusp_info); - if (!error) - error = save_image_metadata(pblist, &handle); + error = get_swap_writer(&handle); + if (!error) { + start = handle.cur_swap; + error = swap_write_page(&handle, header); + } if (!error) - error = save_image_data(pblist, &handle, nr_pages); - if (error) - goto Free_image_entries; - - swap_map = reverse_swap_map(swap_map); - error = save_swap_map(swap_map, &start); - if (error) - goto Free_map_entries; - - dump_info(); - printk( "S" ); - error = mark_swapfiles(start); - printk( "|\n" ); + error = save_image(&handle, &snapshot, header->pages - 1); + if (!error) { + flush_swap_writer(&handle); + printk("S"); + error = mark_swapfiles(swp_entry(root_swap, start)); + printk("|\n"); + } if (error) - goto Free_map_entries; - -Free_swap_map: - free_swap_map(swap_map); + free_all_swap_pages(root_swap, handle.bitmap); + release_swap_writer(&handle); return error; - -Free_map_entries: - free_swap_map_entries(swap_map); -Free_image_entries: - free_image_entries(swap_map); - goto Free_swap_map; } /** @@ -663,45 +579,6 @@ int swsusp_resume(void) return error; } -/** - * mark_unsafe_pages - mark the pages that cannot be used for storing - * the image during resume, because they conflict with the pages that - * had been used before suspend - */ - -static void mark_unsafe_pages(struct pbe *pblist) -{ - struct zone *zone; - unsigned long zone_pfn; - struct pbe *p; - - if (!pblist) /* a sanity check */ - return; - - /* Clear page flags */ - for_each_zone (zone) { - for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) - if (pfn_valid(zone_pfn + zone->zone_start_pfn)) - ClearPageNosaveFree(pfn_to_page(zone_pfn + - zone->zone_start_pfn)); - } - - /* Mark orig addresses */ - for_each_pbe (p, pblist) - SetPageNosaveFree(virt_to_page(p->orig_address)); - -} - -static void copy_page_backup_list(struct pbe *dst, struct pbe *src) -{ - /* We assume both lists contain the same number of elements */ - while (src) { - dst->orig_address = src->orig_address; - dst = dst->next; - src = src->next; - } -} - /* * Using bio to read from swap. * This code requires a bit more work than just using buffer heads @@ -779,14 +656,14 @@ static int bio_write_page(pgoff_t page_off, void *page) * in a file-alike way */ -static inline void release_swap_map_reader(struct swap_map_handle *handle) +static void release_swap_reader(struct swap_map_handle *handle) { if (handle->cur) free_page((unsigned long)handle->cur); handle->cur = NULL; } -static inline int get_swap_map_reader(struct swap_map_handle *handle, +static int get_swap_reader(struct swap_map_handle *handle, swp_entry_t start) { int error; @@ -798,149 +675,80 @@ static inline int get_swap_map_reader(struct swap_map_handle *handle, return -ENOMEM; error = bio_read_page(swp_offset(start), handle->cur); if (error) { - release_swap_map_reader(handle); + release_swap_reader(handle); return error; } handle->k = 0; return 0; } -static inline int swap_map_read_page(struct swap_map_handle *handle, void *buf) +static int swap_read_page(struct swap_map_handle *handle, void *buf) { unsigned long offset; int error; if (!handle->cur) return -EINVAL; - offset = swp_offset(handle->cur->entries[handle->k]); + offset = handle->cur->entries[handle->k]; if (!offset) - return -EINVAL; + return -EFAULT; error = bio_read_page(offset, buf); if (error) return error; - if (++handle->k >= MAP_PAGE_SIZE) { + if (++handle->k >= MAP_PAGE_ENTRIES) { handle->k = 0; - offset = swp_offset(handle->cur->next_swap); + offset = handle->cur->next_swap; if (!offset) - release_swap_map_reader(handle); + release_swap_reader(handle); else error = bio_read_page(offset, handle->cur); } return error; } -static int check_header(void) -{ - char *reason = NULL; - - dump_info(); - if (swsusp_info.version_code != LINUX_VERSION_CODE) - reason = "kernel version"; - if (swsusp_info.num_physpages != num_physpages) - reason = "memory size"; - if (strcmp(swsusp_info.uts.sysname,system_utsname.sysname)) - reason = "system type"; - if (strcmp(swsusp_info.uts.release,system_utsname.release)) - reason = "kernel release"; - if (strcmp(swsusp_info.uts.version,system_utsname.version)) - reason = "version"; - if (strcmp(swsusp_info.uts.machine,system_utsname.machine)) - reason = "machine"; - if (reason) { - printk(KERN_ERR "swsusp: Resume mismatch: %s\n", reason); - return -EPERM; - } - return 0; -} - /** - * load_image_data - load the image data using the swap map handle - * @handle and store them using the page backup list @pblist + * load_image - load the image using the swap map handle + * @handle and the snapshot handle @snapshot * (assume there are @nr_pages pages to load) */ -static int load_image_data(struct pbe *pblist, - struct swap_map_handle *handle, - unsigned int nr_pages) +static int load_image(struct swap_map_handle *handle, + struct snapshot_handle *snapshot, + unsigned int nr_pages) { - int error; unsigned int m; - struct pbe *p; + int ret; + int error = 0; - if (!pblist) - return -EINVAL; printk("Loading image data pages (%u pages) ... ", nr_pages); m = nr_pages / 100; if (!m) m = 1; nr_pages = 0; - p = pblist; - while (p) { - error = swap_map_read_page(handle, (void *)p->address); - if (error) - break; - p = p->next; - if (!(nr_pages % m)) - printk("\b\b\b\b%3d%%", nr_pages / m); - nr_pages++; - } + do { + ret = snapshot_write_next(snapshot, PAGE_SIZE); + if (ret > 0) { + error = swap_read_page(handle, data_of(*snapshot)); + if (error) + break; + if (!(nr_pages % m)) + printk("\b\b\b\b%3d%%", nr_pages / m); + nr_pages++; + } + } while (ret > 0); if (!error) printk("\b\b\b\bdone\n"); + if (!snapshot_image_loaded(snapshot)) + error = -ENODATA; return error; } -/** - * unpack_orig_addresses - copy the elements of @buf[] (1 page) to - * the PBEs in the list starting at @pbe - */ - -static inline struct pbe *unpack_orig_addresses(unsigned long *buf, - struct pbe *pbe) -{ - int j; - - for (j = 0; j < PAGE_SIZE / sizeof(long) && pbe; j++) { - pbe->orig_address = buf[j]; - pbe = pbe->next; - } - return pbe; -} - -/** - * load_image_metadata - load the image metadata using the swap map - * handle @handle and put them into the PBEs in the list @pblist - */ - -static int load_image_metadata(struct pbe *pblist, struct swap_map_handle *handle) -{ - struct pbe *p; - unsigned long *buf; - unsigned int n = 0; - int error = 0; - - printk("Loading image metadata ... "); - buf = (unsigned long *)get_zeroed_page(GFP_ATOMIC); - if (!buf) - return -ENOMEM; - p = pblist; - while (p) { - error = swap_map_read_page(handle, buf); - if (error) - break; - p = unpack_orig_addresses(buf, p); - n++; - } - free_page((unsigned long)buf); - if (!error) - printk("done (%u pages loaded)\n", n); - return error; -} - -int swsusp_read(struct pbe **pblist_ptr) +int swsusp_read(void) { int error; - struct pbe *p, *pblist; struct swap_map_handle handle; + struct snapshot_handle snapshot; + struct swsusp_info *header; unsigned int nr_pages; if (IS_ERR(resume_bdev)) { @@ -948,38 +756,19 @@ int swsusp_read(struct pbe **pblist_ptr) return PTR_ERR(resume_bdev); } - error = get_swap_map_reader(&handle, swsusp_header.image); + memset(&snapshot, 0, sizeof(struct snapshot_handle)); + error = snapshot_write_next(&snapshot, PAGE_SIZE); + if (error < PAGE_SIZE) + return error < 0 ? error : -EFAULT; + header = (struct swsusp_info *)data_of(snapshot); + error = get_swap_reader(&handle, swsusp_header.image); if (!error) - error = swap_map_read_page(&handle, &swsusp_info); - if (!error) - error = check_header(); - if (error) - return error; - nr_pages = swsusp_info.image_pages; - p = alloc_pagedir(nr_pages, GFP_ATOMIC, 0); - if (!p) - return -ENOMEM; - error = load_image_metadata(p, &handle); + error = swap_read_page(&handle, header); if (!error) { - mark_unsafe_pages(p); - pblist = alloc_pagedir(nr_pages, GFP_ATOMIC, 1); - if (pblist) - copy_page_backup_list(pblist, p); - free_pagedir(p); - if (!pblist) - error = -ENOMEM; - - /* Allocate memory for the image and read the data from swap */ - if (!error) - error = alloc_data_pages(pblist, GFP_ATOMIC, 1); - if (!error) { - release_eaten_pages(); - error = load_image_data(pblist, &handle, nr_pages); - } - if (!error) - *pblist_ptr = pblist; + nr_pages = header->image_pages; + error = load_image(&handle, &snapshot, nr_pages); } - release_swap_map_reader(&handle); + release_swap_reader(&handle); blkdev_put(resume_bdev); diff --git a/mm/swapfile.c b/mm/swapfile.c index 365ed6ff182d..4d11f9d84666 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -45,7 +45,7 @@ static const char Unused_offset[] = "Unused swap offset entry "; struct swap_list_t swap_list = {-1, -1}; -struct swap_info_struct swap_info[MAX_SWAPFILES]; +static struct swap_info_struct swap_info[MAX_SWAPFILES]; static DEFINE_MUTEX(swapon_mutex); @@ -417,6 +417,59 @@ void free_swap_and_cache(swp_entry_t entry) } } +#ifdef CONFIG_SOFTWARE_SUSPEND +/* + * Find the swap type that corresponds to given device (if any) + * + * This is needed for software suspend and is done in such a way that inode + * aliasing is allowed. + */ +int swap_type_of(dev_t device) +{ + int i; + + if (!device) + return -EINVAL; + spin_lock(&swap_lock); + for (i = 0; i < nr_swapfiles; i++) { + struct inode *inode; + + if (!(swap_info[i].flags & SWP_WRITEOK)) + continue; + inode = swap_info->swap_file->f_dentry->d_inode; + if (S_ISBLK(inode->i_mode) && + device == MKDEV(imajor(inode), iminor(inode))) { + spin_unlock(&swap_lock); + return i; + } + } + spin_unlock(&swap_lock); + return -ENODEV; +} + +/* + * Return either the total number of swap pages of given type, or the number + * of free pages of that type (depending on @free) + * + * This is needed for software suspend + */ +unsigned int count_swap_pages(int type, int free) +{ + unsigned int n = 0; + + if (type < nr_swapfiles) { + spin_lock(&swap_lock); + if (swap_info[type].flags & SWP_WRITEOK) { + n = swap_info[type].pages; + if (free) + n -= swap_info[type].inuse_pages; + } + spin_unlock(&swap_lock); + } + return n; +} +#endif + /* * No need to decide whether this PTE shares the swap entry with others, * just let do_wp_page work it out if a write is requested later - to -- cgit v1.2.3 From 74c7e2efbe37378026f00ad9e7253796d7b2fc99 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 23 Mar 2006 03:00:01 -0800 Subject: [PATCH] kernel/power: move externs to header files Move externs from C source files to header files. Signed-off-by: Randy Dunlap Cc: "Rafael J. Wysocki" Cc: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/pm.h | 3 ++- kernel/power/disk.c | 11 ----------- kernel/power/power.h | 6 +++++- 3 files changed, 7 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/linux/pm.h b/include/linux/pm.h index 5be87ba3b7ac..6df2585c0169 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -188,6 +188,8 @@ extern void device_power_up(void); extern void device_resume(void); #ifdef CONFIG_PM +extern suspend_disk_method_t pm_disk_mode; + extern int device_suspend(pm_message_t state); #define device_set_wakeup_enable(dev,val) \ @@ -215,7 +217,6 @@ static inline int dpm_runtime_suspend(struct device * dev, pm_message_t state) static inline void dpm_runtime_resume(struct device * dev) { - } #endif diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 4eb464b71347..4bd68f482f2b 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c @@ -22,17 +22,6 @@ #include "power.h" -extern suspend_disk_method_t pm_disk_mode; - -extern int swsusp_shrink_memory(void); -extern int swsusp_suspend(void); -extern int swsusp_write(void); -extern int swsusp_check(void); -extern int swsusp_read(void); -extern void swsusp_close(void); -extern int swsusp_resume(void); - - static int noresume = 0; char resume_file[256] = CONFIG_PM_STD_PARTITION; dev_t swsusp_resume_device; diff --git a/kernel/power/power.h b/kernel/power/power.h index 089c84bed895..5d1abffbb9ce 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -48,7 +48,6 @@ extern asmlinkage int swsusp_arch_suspend(void); extern asmlinkage int swsusp_arch_resume(void); extern unsigned int count_data_pages(void); -extern void swsusp_free(void); struct snapshot_handle { loff_t offset; @@ -91,6 +90,11 @@ extern struct bitmap_page *alloc_bitmap(unsigned int nr_bits); extern unsigned long alloc_swap_page(int swap, struct bitmap_page *bitmap); extern void free_all_swap_pages(int swap, struct bitmap_page *bitmap); +extern int swsusp_check(void); extern int swsusp_shrink_memory(void); +extern void swsusp_free(void); extern int swsusp_suspend(void); extern int swsusp_resume(void); +extern int swsusp_read(void); +extern int swsusp_write(void); +extern void swsusp_close(void); -- cgit v1.2.3 From ff4da2e262d2509fe1bacff70dd00934be569c66 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 23 Mar 2006 03:00:07 -0800 Subject: [PATCH] swsusp: add check for suspension of X-controlled devices It is unsafe to suspend devices if the hardware is controlled by X. Add an extra check to prevent this from happening. Signed-off-by: Rafael J. Wysocki Cc: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/power/suspend.c | 5 ++++- drivers/char/vt.c | 8 ++++++++ include/linux/vt_kern.h | 5 +++++ 3 files changed, 17 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c index 8660779fb288..bdb60663f2ef 100644 --- a/drivers/base/power/suspend.c +++ b/drivers/base/power/suspend.c @@ -8,6 +8,7 @@ * */ +#include #include #include "../base.h" #include "power.h" @@ -62,7 +63,6 @@ int suspend_device(struct device * dev, pm_message_t state) return error; } - /** * device_suspend - Save state and stop all devices in system. * @state: Power state to put each device in. @@ -82,6 +82,9 @@ int device_suspend(pm_message_t state) { int error = 0; + if (!is_console_suspend_safe()) + return -EINVAL; + down(&dpm_sem); down(&dpm_list_sem); while (!list_empty(&dpm_active) && error == 0) { diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 0900d1dbee59..86b31b87eb85 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -3234,6 +3234,14 @@ void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org) } } +int is_console_suspend_safe(void) +{ + /* It is unsafe to suspend devices while X has control of the + * hardware. Make sure we are running on a kernel-controlled console. + */ + return vc_cons[fg_console].d->vc_mode == KD_TEXT; +} + /* * Visible symbols for modules */ diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index fab5aed8ca31..530ae3f4248c 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h @@ -73,6 +73,11 @@ int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc); int vt_waitactive(int vt); void change_console(struct vc_data *new_vc); void reset_vc(struct vc_data *vc); +#ifdef CONFIG_VT +int is_console_suspend_safe(void); +#else +static inline int is_console_suspend_safe(void) { return 1; } +#endif /* * vc_screen.c shares this temporary buffer with the console write code so that -- cgit v1.2.3 From d8733c2956968a01394a4d2a9e97a8b431a78776 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 23 Mar 2006 03:00:11 -0800 Subject: [PATCH] ext3_readdir: use generic readahead Linus points out that ext3_readdir's readahead only cuts in when ext3_readdir() is operating at the very start of the directory. So for large directories we end up performing no readahead at all and we suck. So take it all out and use the core VM's page_cache_readahead(). This means that ext3 directory reads will use all of readahead's dynamic sizing goop. Note that we're using the directory's filp->f_ra to hold the readahead state, but readahead is actually being performed against the underlying blockdev's address_space. Fortunately the readahead code is all set up to handle this. Tested with printk. It works. I was struggling to find a real workload which actually cared. (The patch also exports page_cache_readahead() to GPL modules) Cc: "Stephen C. Tweedie" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/dir.c | 52 +++++++++++++++++++++++-------------------------- fs/ext3/inode.c | 2 +- include/linux/ext3_fs.h | 9 ++++++--- mm/readahead.c | 1 + 4 files changed, 32 insertions(+), 32 deletions(-) (limited to 'include') diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index 832867aef3dc..773459164bb2 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c @@ -95,11 +95,10 @@ static int ext3_readdir(struct file * filp, void * dirent, filldir_t filldir) { int error = 0; - unsigned long offset, blk; - int i, num, stored; - struct buffer_head * bh, * tmp, * bha[16]; - struct ext3_dir_entry_2 * de; - struct super_block * sb; + unsigned long offset; + int i, stored; + struct ext3_dir_entry_2 *de; + struct super_block *sb; int err; struct inode *inode = filp->f_dentry->d_inode; int ret = 0; @@ -124,12 +123,29 @@ static int ext3_readdir(struct file * filp, } #endif stored = 0; - bh = NULL; offset = filp->f_pos & (sb->s_blocksize - 1); while (!error && !stored && filp->f_pos < inode->i_size) { - blk = (filp->f_pos) >> EXT3_BLOCK_SIZE_BITS(sb); - bh = ext3_bread(NULL, inode, blk, 0, &err); + unsigned long blk = filp->f_pos >> EXT3_BLOCK_SIZE_BITS(sb); + struct buffer_head map_bh; + struct buffer_head *bh = NULL; + + map_bh.b_state = 0; + err = ext3_get_block_handle(NULL, inode, blk, &map_bh, 0, 0); + if (!err) { + page_cache_readahead(sb->s_bdev->bd_inode->i_mapping, + &filp->f_ra, + filp, + map_bh.b_blocknr >> + (PAGE_CACHE_SHIFT - inode->i_blkbits), + 1); + bh = ext3_bread(NULL, inode, blk, 0, &err); + } + + /* + * We ignore I/O errors on directories so users have a chance + * of recovering data when there's a bad sector + */ if (!bh) { ext3_error (sb, "ext3_readdir", "directory #%lu contains a hole at offset %lu", @@ -138,26 +154,6 @@ static int ext3_readdir(struct file * filp, continue; } - /* - * Do the readahead - */ - if (!offset) { - for (i = 16 >> (EXT3_BLOCK_SIZE_BITS(sb) - 9), num = 0; - i > 0; i--) { - tmp = ext3_getblk (NULL, inode, ++blk, 0, &err); - if (tmp && !buffer_uptodate(tmp) && - !buffer_locked(tmp)) - bha[num++] = tmp; - else - brelse (tmp); - } - if (num) { - ll_rw_block (READA, num, bha); - for (i = 0; i < num; i++) - brelse (bha[i]); - } - } - revalidate: /* If the dir block has changed since the last call to * readdir(2), then we might be pointing to an invalid diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 0384e539b88f..d59d5a667b0b 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -671,7 +671,7 @@ err_out: * The BKL may not be held on entry here. Be sure to take it early. */ -static int +int ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create, int extend_disksize) { diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index c0272d73ab20..e7239f2f97a1 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h @@ -772,9 +772,12 @@ extern unsigned long ext3_count_free (struct buffer_head *, unsigned); /* inode.c */ -extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int); -extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *); -extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *); +int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int); +struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *); +struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *); +int ext3_get_block_handle(handle_t *handle, struct inode *inode, + sector_t iblock, struct buffer_head *bh_result, int create, + int extend_disksize); extern void ext3_read_inode (struct inode *); extern int ext3_write_inode (struct inode *, int); diff --git a/mm/readahead.c b/mm/readahead.c index 301b36c4a0ce..0f142a40984b 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -555,6 +555,7 @@ recheck: out: return ra->prev_page + 1; } +EXPORT_SYMBOL_GPL(page_cache_readahead); /* * handle_ra_miss() is called when it is known that a page which should have -- cgit v1.2.3 From 0c9e63fd38a2fb2181668a0cdd622a3c23cfd567 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 23 Mar 2006 03:00:12 -0800 Subject: [PATCH] Shrinks sizeof(files_struct) and better layout 1) Reduce the size of (struct fdtable) to exactly 64 bytes on 32bits platforms, lowering kmalloc() allocated space by 50%. 2) Reduce the size of (files_struct), using a special 32 bits (or 64bits) embedded_fd_set, instead of a 1024 bits fd_set for the close_on_exec_init and open_fds_init fields. This save some ram (248 bytes per task) as most tasks dont open more than 32 files. D-Cache footprint for such tasks is also reduced to the minimum. 3) Reduce size of allocated fdset. Currently two full pages are allocated, that is 32768 bits on x86 for example, and way too much. The minimum is now L1_CACHE_BYTES. UP and SMP should benefit from this patch, because most tasks will touch only one cache line when open()/close() stdin/stdout/stderr (0/1/2), (next_fd, close_on_exec_init, open_fds_init, fd_array[0 .. 2] being in the same cache line) Signed-off-by: Eric Dumazet Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fcntl.c | 9 ++++----- fs/file.c | 34 ++++++++++++++-------------------- fs/open.c | 8 ++++---- include/linux/file.h | 28 ++++++++++++++++++++++++---- include/linux/init_task.h | 10 +++++----- kernel/fork.c | 8 ++++---- 6 files changed, 55 insertions(+), 42 deletions(-) (limited to 'include') diff --git a/fs/fcntl.c b/fs/fcntl.c index dc4a7007f4e7..03c789560fb8 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -73,8 +73,8 @@ repeat: * orig_start..fdt->next_fd */ start = orig_start; - if (start < fdt->next_fd) - start = fdt->next_fd; + if (start < files->next_fd) + start = files->next_fd; newfd = start; if (start < fdt->max_fdset) { @@ -102,9 +102,8 @@ repeat: * we reacquire the fdtable pointer and use it while holding * the lock, no one can free it during that time. */ - fdt = files_fdtable(files); - if (start <= fdt->next_fd) - fdt->next_fd = newfd + 1; + if (start <= files->next_fd) + files->next_fd = newfd + 1; error = newfd; diff --git a/fs/file.c b/fs/file.c index cea7cbea11d0..bbc743314730 100644 --- a/fs/file.c +++ b/fs/file.c @@ -125,7 +125,8 @@ static void free_fdtable_rcu(struct rcu_head *rcu) kmem_cache_free(files_cachep, fdt->free_files); return; } - if (fdt->max_fdset <= __FD_SETSIZE && fdt->max_fds <= NR_OPEN_DEFAULT) { + if (fdt->max_fdset <= EMBEDDED_FD_SET_SIZE && + fdt->max_fds <= NR_OPEN_DEFAULT) { /* * The fdtable was embedded */ @@ -155,8 +156,9 @@ static void free_fdtable_rcu(struct rcu_head *rcu) void free_fdtable(struct fdtable *fdt) { - if (fdt->free_files || fdt->max_fdset > __FD_SETSIZE || - fdt->max_fds > NR_OPEN_DEFAULT) + if (fdt->free_files || + fdt->max_fdset > EMBEDDED_FD_SET_SIZE || + fdt->max_fds > NR_OPEN_DEFAULT) call_rcu(&fdt->rcu, free_fdtable_rcu); } @@ -199,7 +201,6 @@ static void copy_fdtable(struct fdtable *nfdt, struct fdtable *fdt) (nfdt->max_fds - fdt->max_fds) * sizeof(struct file *)); } - nfdt->next_fd = fdt->next_fd; } /* @@ -220,11 +221,9 @@ fd_set * alloc_fdset(int num) void free_fdset(fd_set *array, int num) { - int size = num / 8; - - if (num <= __FD_SETSIZE) /* Don't free an embedded fdset */ + if (num <= EMBEDDED_FD_SET_SIZE) /* Don't free an embedded fdset */ return; - else if (size <= PAGE_SIZE) + else if (num <= 8 * PAGE_SIZE) kfree(array); else vfree(array); @@ -237,22 +236,17 @@ static struct fdtable *alloc_fdtable(int nr) fd_set *new_openset = NULL, *new_execset = NULL; struct file **new_fds; - fdt = kmalloc(sizeof(*fdt), GFP_KERNEL); + fdt = kzalloc(sizeof(*fdt), GFP_KERNEL); if (!fdt) goto out; - memset(fdt, 0, sizeof(*fdt)); - nfds = __FD_SETSIZE; + nfds = 8 * L1_CACHE_BYTES; /* Expand to the max in easy steps */ - do { - if (nfds < (PAGE_SIZE * 8)) - nfds = PAGE_SIZE * 8; - else { - nfds = nfds * 2; - if (nfds > NR_OPEN) - nfds = NR_OPEN; - } - } while (nfds <= nr); + while (nfds <= nr) { + nfds = nfds * 2; + if (nfds > NR_OPEN) + nfds = NR_OPEN; + } new_openset = alloc_fdset(nfds); new_execset = alloc_fdset(nfds); diff --git a/fs/open.c b/fs/open.c index 70e0230d8e77..1091dadd6c38 100644 --- a/fs/open.c +++ b/fs/open.c @@ -973,7 +973,7 @@ repeat: fdt = files_fdtable(files); fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fdset, - fdt->next_fd); + files->next_fd); /* * N.B. For clone tasks sharing a files structure, this test @@ -998,7 +998,7 @@ repeat: FD_SET(fd, fdt->open_fds); FD_CLR(fd, fdt->close_on_exec); - fdt->next_fd = fd + 1; + files->next_fd = fd + 1; #if 1 /* Sanity check */ if (fdt->fd[fd] != NULL) { @@ -1019,8 +1019,8 @@ static void __put_unused_fd(struct files_struct *files, unsigned int fd) { struct fdtable *fdt = files_fdtable(files); __FD_CLR(fd, fdt->open_fds); - if (fd < fdt->next_fd) - fdt->next_fd = fd; + if (fd < files->next_fd) + files->next_fd = fd; } void fastcall put_unused_fd(unsigned int fd) diff --git a/include/linux/file.h b/include/linux/file.h index 9901b850f2e4..9f7c2513866f 100644 --- a/include/linux/file.h +++ b/include/linux/file.h @@ -10,6 +10,7 @@ #include #include #include +#include /* * The default fd array needs to be at least BITS_PER_LONG, @@ -17,10 +18,22 @@ */ #define NR_OPEN_DEFAULT BITS_PER_LONG +/* + * The embedded_fd_set is a small fd_set, + * suitable for most tasks (which open <= BITS_PER_LONG files) + */ +struct embedded_fd_set { + unsigned long fds_bits[1]; +}; + +/* + * More than this number of fds: we use a separately allocated fd_set + */ +#define EMBEDDED_FD_SET_SIZE (BITS_PER_BYTE * sizeof(struct embedded_fd_set)) + struct fdtable { unsigned int max_fds; int max_fdset; - int next_fd; struct file ** fd; /* current fd array */ fd_set *close_on_exec; fd_set *open_fds; @@ -33,13 +46,20 @@ struct fdtable { * Open file table structure */ struct files_struct { + /* + * read mostly part + */ atomic_t count; struct fdtable *fdt; struct fdtable fdtab; - fd_set close_on_exec_init; - fd_set open_fds_init; + /* + * written part on a separate cache line in SMP + */ + spinlock_t file_lock ____cacheline_aligned_in_smp; + int next_fd; + struct embedded_fd_set close_on_exec_init; + struct embedded_fd_set open_fds_init; struct file * fd_array[NR_OPEN_DEFAULT]; - spinlock_t file_lock; /* Protects concurrent writers. Nests inside tsk->alloc_lock */ }; #define files_fdtable(files) (rcu_dereference((files)->fdt)) diff --git a/include/linux/init_task.h b/include/linux/init_task.h index dcfd2ecccb5d..92146f3b7423 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -7,11 +7,10 @@ #define INIT_FDTABLE \ { \ .max_fds = NR_OPEN_DEFAULT, \ - .max_fdset = __FD_SETSIZE, \ - .next_fd = 0, \ + .max_fdset = EMBEDDED_FD_SET_SIZE, \ .fd = &init_files.fd_array[0], \ - .close_on_exec = &init_files.close_on_exec_init, \ - .open_fds = &init_files.open_fds_init, \ + .close_on_exec = (fd_set *)&init_files.close_on_exec_init, \ + .open_fds = (fd_set *)&init_files.open_fds_init, \ .rcu = RCU_HEAD_INIT, \ .free_files = NULL, \ .next = NULL, \ @@ -20,9 +19,10 @@ #define INIT_FILES \ { \ .count = ATOMIC_INIT(1), \ - .file_lock = SPIN_LOCK_UNLOCKED, \ .fdt = &init_files.fdtab, \ .fdtab = INIT_FDTABLE, \ + .file_lock = SPIN_LOCK_UNLOCKED, \ + .next_fd = 0, \ .close_on_exec_init = { { 0, } }, \ .open_fds_init = { { 0, } }, \ .fd_array = { NULL, } \ diff --git a/kernel/fork.c b/kernel/fork.c index 9bd7b65ee418..c79ae0b19a49 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -607,12 +607,12 @@ static struct files_struct *alloc_files(void) atomic_set(&newf->count, 1); spin_lock_init(&newf->file_lock); + newf->next_fd = 0; fdt = &newf->fdtab; - fdt->next_fd = 0; fdt->max_fds = NR_OPEN_DEFAULT; - fdt->max_fdset = __FD_SETSIZE; - fdt->close_on_exec = &newf->close_on_exec_init; - fdt->open_fds = &newf->open_fds_init; + fdt->max_fdset = EMBEDDED_FD_SET_SIZE; + fdt->close_on_exec = (fd_set *)&newf->close_on_exec_init; + fdt->open_fds = (fd_set *)&newf->open_fds_init; fdt->fd = &newf->fd_array[0]; INIT_RCU_HEAD(&fdt->rcu); fdt->free_files = NULL; -- cgit v1.2.3 From 6a2900b67652421b51fe25e4b86ecfec742b1f30 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 23 Mar 2006 03:00:15 -0800 Subject: [PATCH] kill cdrom ->dev_ioctl method Since early 2.4.x all cdrom drivers implement the block_device methods themselves, so they can handle additional ioctls directly instead of going through the cdrom layer. Signed-off-by: Christoph Hellwig Acked-by: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/cdrom/cdrom.c | 7 - drivers/cdrom/cdu31a.c | 8 +- drivers/cdrom/cm206.c | 44 +- drivers/cdrom/sbpcd.c | 1890 +++++++++++++++++++++++------------------------ drivers/cdrom/viocd.c | 2 +- drivers/ide/ide-cd.c | 99 +-- drivers/scsi/sr.c | 37 +- drivers/scsi/sr.h | 1 - drivers/scsi/sr_ioctl.c | 19 - include/linux/cdrom.h | 5 +- 10 files changed, 1040 insertions(+), 1072 deletions(-) (limited to 'include') diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index d6653fc03b92..a59876a0bfa1 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -407,7 +407,6 @@ int register_cdrom(struct cdrom_device_info *cdi) ENSURE(get_mcn, CDC_MCN); ENSURE(reset, CDC_RESET); ENSURE(audio_ioctl, CDC_PLAY_AUDIO); - ENSURE(dev_ioctl, CDC_IOCTLS); ENSURE(generic_packet, CDC_GENERIC_PACKET); cdi->mc_flags = 0; cdo->n_minors = 0; @@ -2776,12 +2775,6 @@ int cdrom_ioctl(struct file * file, struct cdrom_device_info *cdi, return cdrom_ioctl_audioctl(cdi, cmd); } - /* - * Finally, do the device specific ioctls - */ - if (CDROM_CAN(CDC_IOCTLS)) - return cdi->ops->dev_ioctl(cdi, cmd, arg); - return -ENOSYS; } diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c index 378e88d20757..72ffd64e8b1e 100644 --- a/drivers/cdrom/cdu31a.c +++ b/drivers/cdrom/cdu31a.c @@ -2668,7 +2668,7 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi, return retval; } -static int scd_dev_ioctl(struct cdrom_device_info *cdi, +static int scd_read_audio(struct cdrom_device_info *cdi, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; @@ -2894,11 +2894,10 @@ static struct cdrom_device_ops scd_dops = { .get_mcn = scd_get_mcn, .reset = scd_reset, .audio_ioctl = scd_audio_ioctl, - .dev_ioctl = scd_dev_ioctl, .capability = CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | - CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS, + CDC_RESET | CDC_DRIVE_STATUS, .n_minors = 1, }; @@ -2936,6 +2935,9 @@ static int scd_block_ioctl(struct inode *inode, struct file *file, case CDROMCLOSETRAY: retval = scd_tray_move(&scd_info, 0); break; + case CDROMREADAUDIO: + retval = scd_read_audio(&scd_info, CDROMREADAUDIO, arg); + break; default: retval = cdrom_ioctl(file, &scd_info, inode, cmd, arg); } diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c index ce127f7ec0f6..fad27a87ce35 100644 --- a/drivers/cdrom/cm206.c +++ b/drivers/cdrom/cm206.c @@ -1157,32 +1157,6 @@ static int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, } } -/* Ioctl. These ioctls are specific to the cm206 driver. I have made - some driver statistics accessible through ioctl calls. - */ - -static int cm206_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, - unsigned long arg) -{ - switch (cmd) { -#ifdef STATISTICS - case CM206CTL_GET_STAT: - if (arg >= NR_STATS) - return -EINVAL; - else - return cd->stats[arg]; - case CM206CTL_GET_LAST_STAT: - if (arg >= NR_STATS) - return -EINVAL; - else - return cd->last_stat[arg]; -#endif - default: - debug(("Unknown ioctl call 0x%x\n", cmd)); - return -EINVAL; - } -} - static int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr) { if (cd != NULL) { @@ -1321,11 +1295,10 @@ static struct cdrom_device_ops cm206_dops = { .get_mcn = cm206_get_upc, .reset = cm206_reset, .audio_ioctl = cm206_audio_ioctl, - .dev_ioctl = cm206_ioctl, .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED | - CDC_IOCTLS | CDC_DRIVE_STATUS, + CDC_DRIVE_STATUS, .n_minors = 1, }; @@ -1350,6 +1323,21 @@ static int cm206_block_release(struct inode *inode, struct file *file) static int cm206_block_ioctl(struct inode *inode, struct file *file, unsigned cmd, unsigned long arg) { + switch (cmd) { +#ifdef STATISTICS + case CM206CTL_GET_STAT: + if (arg >= NR_STATS) + return -EINVAL; + return cd->stats[arg]; + case CM206CTL_GET_LAST_STAT: + if (arg >= NR_STATS) + return -EINVAL; + return cd->last_stat[arg]; +#endif + default: + break; + } + return cdrom_ioctl(file, &cm206_info, inode, cmd, arg); } diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c index 466e9c2974bd..4760f515f591 100644 --- a/drivers/cdrom/sbpcd.c +++ b/drivers/cdrom/sbpcd.c @@ -4160,18 +4160,13 @@ static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_mu return 0; } -/*==========================================================================*/ -/*==========================================================================*/ -/* - * ioctl support - */ -static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, - u_long arg) +static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, + void * arg) { struct sbpcd_drive *p = cdi->handle; - int i; + int i, st, j; - msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08lX)\n", cdi->name, cmd, arg); + msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08p)\n", cdi->name, cmd, arg); if (p->drv_id==-1) { msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name); return (-ENXIO); /* no such drive */ @@ -4183,484 +4178,163 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd); switch (cmd) /* Sun-compatible */ { - case DDIOCSDBG: /* DDI Debug */ - if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM); - i=sbpcd_dbg_ioctl(arg,1); - RETURN_UP(i); - case CDROMRESET: /* hard reset the drive */ - msg(DBG_IOC,"ioctl: CDROMRESET entered.\n"); - i=DriveReset(); - current_drive->audio_state=0; - RETURN_UP(i); - case CDROMREADMODE1: - msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n"); + case CDROMPAUSE: /* Pause the drive */ + msg(DBG_IOC,"ioctl: CDROMPAUSE entered.\n"); + /* pause the drive unit when it is currently in PLAY mode, */ + /* or reset the starting and ending locations when in PAUSED mode. */ + /* If applicable, at the next stopping point it reaches */ + /* the drive will discontinue playing. */ + switch (current_drive->audio_state) + { + case audio_playing: + if (famL_drive) i=cc_ReadSubQ(); + else i=cc_Pause_Resume(1); + if (i<0) RETURN_UP(-EIO); + if (famL_drive) i=cc_Pause_Resume(1); + else i=cc_ReadSubQ(); + if (i<0) RETURN_UP(-EIO); + current_drive->pos_audio_start=current_drive->SubQ_run_tot; + current_drive->audio_state=audio_pausing; + RETURN_UP(0); + case audio_pausing: + i=cc_Seek(current_drive->pos_audio_start,1); + if (i<0) RETURN_UP(-EIO); + RETURN_UP(0); + default: + RETURN_UP(-EINVAL); + } + + case CDROMRESUME: /* resume paused audio play */ + msg(DBG_IOC,"ioctl: CDROMRESUME entered.\n"); + /* resume playing audio tracks when a previous PLAY AUDIO call has */ + /* been paused with a PAUSE command. */ + /* It will resume playing from the location saved in SubQ_run_tot. */ + if (current_drive->audio_state!=audio_pausing) RETURN_UP(-EINVAL); + if (famL_drive) + i=cc_PlayAudio(current_drive->pos_audio_start, + current_drive->pos_audio_end); + else i=cc_Pause_Resume(3); + if (i<0) RETURN_UP(-EIO); + current_drive->audio_state=audio_playing; + RETURN_UP(0); + + case CDROMPLAYMSF: + msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n"); #ifdef SAFE_MIXED if (current_drive->has_data>1) RETURN_UP(-EBUSY); #endif /* SAFE_MIXED */ - cc_ModeSelect(CD_FRAMESIZE); - cc_ModeSense(); - current_drive->mode=READ_M1; + if (current_drive->audio_state==audio_playing) + { + i=cc_Pause_Resume(1); + if (i<0) RETURN_UP(-EIO); + i=cc_ReadSubQ(); + if (i<0) RETURN_UP(-EIO); + current_drive->pos_audio_start=current_drive->SubQ_run_tot; + i=cc_Seek(current_drive->pos_audio_start,1); + } + memcpy(&msf, (void *) arg, sizeof(struct cdrom_msf)); + /* values come as msf-bin */ + current_drive->pos_audio_start = (msf.cdmsf_min0<<16) | + (msf.cdmsf_sec0<<8) | + msf.cdmsf_frame0; + current_drive->pos_audio_end = (msf.cdmsf_min1<<16) | + (msf.cdmsf_sec1<<8) | + msf.cdmsf_frame1; + msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n", + current_drive->pos_audio_start,current_drive->pos_audio_end); + i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end); + if (i<0) + { + msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i); + DriveReset(); + current_drive->audio_state=0; + RETURN_UP(-EIO); + } + current_drive->audio_state=audio_playing; RETURN_UP(0); - case CDROMREADMODE2: /* not usable at the moment */ - msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n"); + case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ + msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n"); #ifdef SAFE_MIXED if (current_drive->has_data>1) RETURN_UP(-EBUSY); #endif /* SAFE_MIXED */ - cc_ModeSelect(CD_FRAMESIZE_RAW1); - cc_ModeSense(); - current_drive->mode=READ_M2; + if (current_drive->audio_state==audio_playing) + { + msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n"); +#if 1 + RETURN_UP(0); /* just let us play on */ +#else + RETURN_UP(-EINVAL); /* play on, but say "error" */ +#endif + } + memcpy(&ti,(void *) arg,sizeof(struct cdrom_ti)); + msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n", + ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1); + if (ti.cdti_trk0n_first_track) RETURN_UP(-EINVAL); + if (ti.cdti_trk0>current_drive->n_last_track) RETURN_UP(-EINVAL); + if (ti.cdti_trk1current_drive->n_last_track) ti.cdti_trk1=current_drive->n_last_track; + current_drive->pos_audio_start=current_drive->TocBuffer[ti.cdti_trk0].address; + current_drive->pos_audio_end=current_drive->TocBuffer[ti.cdti_trk1+1].address; + i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end); + if (i<0) + { + msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i); + DriveReset(); + current_drive->audio_state=0; + RETURN_UP(-EIO); + } + current_drive->audio_state=audio_playing; RETURN_UP(0); - case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */ - msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n"); - if (current_drive->sbp_audsiz>0) - vfree(current_drive->aud_buf); - current_drive->aud_buf=NULL; - current_drive->sbp_audsiz=arg; + case CDROMREADTOCHDR: /* Read the table of contents header */ + msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n"); + tochdr.cdth_trk0=current_drive->n_first_track; + tochdr.cdth_trk1=current_drive->n_last_track; + memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr)); + RETURN_UP(0); - if (current_drive->sbp_audsiz>16) - { - current_drive->sbp_audsiz = 0; - RETURN_UP(current_drive->sbp_audsiz); - } - - if (current_drive->sbp_audsiz>0) + case CDROMREADTOCENTRY: /* Read an entry in the table of contents */ + msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n"); + memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry)); + i=tocentry.cdte_track; + if (i==CDROM_LEADOUT) i=current_drive->n_last_track+1; + else if (in_first_track||i>current_drive->n_last_track) + RETURN_UP(-EINVAL); + tocentry.cdte_adr=current_drive->TocBuffer[i].ctl_adr&0x0F; + tocentry.cdte_ctrl=(current_drive->TocBuffer[i].ctl_adr>>4)&0x0F; + tocentry.cdte_datamode=current_drive->TocBuffer[i].format; + if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */ { - current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW); - if (current_drive->aud_buf==NULL) - { - msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz); - current_drive->sbp_audsiz=0; - } - else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz); + tocentry.cdte_addr.msf.minute=(current_drive->TocBuffer[i].address>>16)&0x00FF; + tocentry.cdte_addr.msf.second=(current_drive->TocBuffer[i].address>>8)&0x00FF; + tocentry.cdte_addr.msf.frame=current_drive->TocBuffer[i].address&0x00FF; } - RETURN_UP(current_drive->sbp_audsiz); - - case CDROMREADAUDIO: - { /* start of CDROMREADAUDIO */ - int i=0, j=0, frame, block=0; - u_int try=0; - u_long timeout; - u_char *p; - u_int data_tries = 0; - u_int data_waits = 0; - u_int data_retrying = 0; - int status_tries; - int error_flag; + else if (tocentry.cdte_format==CDROM_LBA) /* blk required */ + tocentry.cdte_addr.lba=msf2blk(current_drive->TocBuffer[i].address); + else RETURN_UP(-EINVAL); + memcpy((void *) arg, &tocentry, sizeof(struct cdrom_tocentry)); + RETURN_UP(0); - msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.\n"); - if (fam0_drive) RETURN_UP(-EINVAL); - if (famL_drive) RETURN_UP(-EINVAL); - if (famV_drive) RETURN_UP(-EINVAL); - if (famT_drive) RETURN_UP(-EINVAL); + case CDROMSTOP: /* Spin down the drive */ + msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n"); #ifdef SAFE_MIXED if (current_drive->has_data>1) RETURN_UP(-EBUSY); #endif /* SAFE_MIXED */ - if (current_drive->aud_buf==NULL) RETURN_UP(-EINVAL); - if (copy_from_user(&read_audio, (void __user *)arg, - sizeof(struct cdrom_read_audio))) - RETURN_UP(-EFAULT); - if (read_audio.nframes < 0 || read_audio.nframes>current_drive->sbp_audsiz) RETURN_UP(-EINVAL); - if (!access_ok(VERIFY_WRITE, read_audio.buf, - read_audio.nframes*CD_FRAMESIZE_RAW)) - RETURN_UP(-EFAULT); - - if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */ - block=msf2lba(&read_audio.addr.msf.minute); - else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */ - block=read_audio.addr.lba; - else RETURN_UP(-EINVAL); -#if 000 - i=cc_SetSpeed(speed_150,0,0); - if (i) msg(DBG_AUD,"read_audio: SetSpeed error %d\n", i); -#endif - msg(DBG_AUD,"read_audio: lba: %d, msf: %06X\n", - block, blk2msf(block)); - msg(DBG_AUD,"read_audio: before cc_ReadStatus.\n"); -#if OLD_BUSY - while (busy_data) sbp_sleep(HZ/10); /* wait a bit */ - busy_audio=1; -#endif /* OLD_BUSY */ - error_flag=0; - for (data_tries=5; data_tries>0; data_tries--) - { - msg(DBG_AUD,"data_tries=%d ...\n", data_tries); - current_drive->mode=READ_AU; - cc_ModeSelect(CD_FRAMESIZE_RAW); - cc_ModeSense(); - for (status_tries=3; status_tries > 0; status_tries--) - { - flags_cmd_out |= f_respo3; - cc_ReadStatus(); - if (sbp_status() != 0) break; - if (st_check) cc_ReadError(); - sbp_sleep(1); /* wait a bit, try again */ - } - if (status_tries == 0) - { - msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__); - continue; - } - msg(DBG_AUD,"read_audio: sbp_status: ok.\n"); - - flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; - if (fam0L_drive) - { - flags_cmd_out |= f_lopsta | f_getsta | f_bit1; - cmd_type=READ_M2; - drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ - drvcmd[1]=(block>>16)&0x000000ff; - drvcmd[2]=(block>>8)&0x000000ff; - drvcmd[3]=block&0x000000ff; - drvcmd[4]=0; - drvcmd[5]=read_audio.nframes; /* # of frames */ - drvcmd[6]=0; - } - else if (fam1_drive) - { - drvcmd[0]=CMD1_READ; /* "read frames", new drives */ - lba2msf(block,&drvcmd[1]); /* msf-bin format required */ - drvcmd[4]=0; - drvcmd[5]=0; - drvcmd[6]=read_audio.nframes; /* # of frames */ - } - else if (fam2_drive) - { - drvcmd[0]=CMD2_READ_XA2; - lba2msf(block,&drvcmd[1]); /* msf-bin format required */ - drvcmd[4]=0; - drvcmd[5]=read_audio.nframes; /* # of frames */ - drvcmd[6]=0x11; /* raw mode */ - } - else if (famT_drive) /* CD-55A: not tested yet */ - { - } - msg(DBG_AUD,"read_audio: before giving \"read\" command.\n"); - flags_cmd_out=f_putcmd; - response_count=0; - i=cmd_out(); - if (i<0) msg(DBG_INF,"error giving READ AUDIO command: %0d\n", i); - sbp_sleep(0); - msg(DBG_AUD,"read_audio: after giving \"read\" command.\n"); - for (frame=1;frame<2 && !error_flag; frame++) - { - try=maxtim_data; - for (timeout=jiffies+9*HZ; ; ) - { - for ( ; try!=0;try--) - { - j=inb(CDi_status); - if (!(j&s_not_data_ready)) break; - if (!(j&s_not_result_ready)) break; - if (fam0L_drive) if (j&s_attention) break; - } - if (try != 0 || time_after_eq(jiffies, timeout)) break; - if (data_retrying == 0) data_waits++; - data_retrying = 1; - sbp_sleep(1); - try = 1; - } - if (try==0) - { - msg(DBG_INF,"read_audio: sbp_data: CDi_status timeout.\n"); - error_flag++; - break; - } - msg(DBG_AUD,"read_audio: sbp_data: CDi_status ok.\n"); - if (j&s_not_data_ready) - { - msg(DBG_INF, "read_audio: sbp_data: DATA_READY timeout.\n"); - error_flag++; - break; - } - msg(DBG_AUD,"read_audio: before reading data.\n"); - error_flag=0; - p = current_drive->aud_buf; - if (sbpro_type==1) OUT(CDo_sel_i_d,1); - if (do_16bit) - { - u_short *p2 = (u_short *) p; - - for (; (u_char *) p2 < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) - { - if ((inb_p(CDi_status)&s_not_data_ready)) continue; - - /* get one sample */ - *p2++ = inw_p(CDi_data); - *p2++ = inw_p(CDi_data); - } - } else { - for (; p < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) - { - if ((inb_p(CDi_status)&s_not_data_ready)) continue; - - /* get one sample */ - *p++ = inb_p(CDi_data); - *p++ = inb_p(CDi_data); - *p++ = inb_p(CDi_data); - *p++ = inb_p(CDi_data); - } - } - if (sbpro_type==1) OUT(CDo_sel_i_d,0); - data_retrying = 0; - } - msg(DBG_AUD,"read_audio: after reading data.\n"); - if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */ - { - msg(DBG_AUD,"read_audio: read aborted by drive\n"); -#if 0000 - i=cc_DriveReset(); /* ugly fix to prevent a hang */ -#else - i=cc_ReadError(); -#endif - continue; - } - if (fam0L_drive) - { - i=maxtim_data; - for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--) - { - for ( ;i!=0;i--) - { - j=inb(CDi_status); - if (!(j&s_not_data_ready)) break; - if (!(j&s_not_result_ready)) break; - if (j&s_attention) break; - } - if (i != 0 || time_after_eq(jiffies, timeout)) break; - sbp_sleep(0); - i = 1; - } - if (i==0) msg(DBG_AUD,"read_audio: STATUS TIMEOUT AFTER READ"); - if (!(j&s_attention)) - { - msg(DBG_AUD,"read_audio: sbp_data: timeout waiting DRV_ATTN - retrying\n"); - i=cc_DriveReset(); /* ugly fix to prevent a hang */ - continue; - } - } - do - { - if (fam0L_drive) cc_ReadStatus(); - i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */ - if (i<0) { msg(DBG_AUD, - "read_audio: cc_ReadStatus error after read: %02X\n", - current_drive->status_bits); - continue; /* FIXME */ - } - } - while ((fam0L_drive)&&(!st_check)&&(!(i&p_success))); - if (st_check) - { - i=cc_ReadError(); - msg(DBG_AUD,"read_audio: cc_ReadError was necessary after read: %02X\n",i); - continue; - } - if (copy_to_user(read_audio.buf, - current_drive->aud_buf, - read_audio.nframes * CD_FRAMESIZE_RAW)) - RETURN_UP(-EFAULT); - msg(DBG_AUD,"read_audio: copy_to_user done.\n"); - break; - } - cc_ModeSelect(CD_FRAMESIZE); - cc_ModeSense(); - current_drive->mode=READ_M1; -#if OLD_BUSY - busy_audio=0; -#endif /* OLD_BUSY */ - if (data_tries == 0) - { - msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__); - RETURN_UP(-EIO); - } - msg(DBG_AUD,"read_audio: successful return.\n"); - RETURN_UP(0); - } /* end of CDROMREADAUDIO */ - - default: - msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd); - RETURN_UP(-EINVAL); - } /* end switch(cmd) */ -} - -static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, - void * arg) -{ - struct sbpcd_drive *p = cdi->handle; - int i, st, j; - - msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08p)\n", cdi->name, cmd, arg); - if (p->drv_id==-1) { - msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name); - return (-ENXIO); /* no such drive */ - } - down(&ioctl_read_sem); - if (p != current_drive) - switch_drive(p); - - msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd); - switch (cmd) /* Sun-compatible */ - { - - case CDROMPAUSE: /* Pause the drive */ - msg(DBG_IOC,"ioctl: CDROMPAUSE entered.\n"); - /* pause the drive unit when it is currently in PLAY mode, */ - /* or reset the starting and ending locations when in PAUSED mode. */ - /* If applicable, at the next stopping point it reaches */ - /* the drive will discontinue playing. */ - switch (current_drive->audio_state) - { - case audio_playing: - if (famL_drive) i=cc_ReadSubQ(); - else i=cc_Pause_Resume(1); - if (i<0) RETURN_UP(-EIO); - if (famL_drive) i=cc_Pause_Resume(1); - else i=cc_ReadSubQ(); - if (i<0) RETURN_UP(-EIO); - current_drive->pos_audio_start=current_drive->SubQ_run_tot; - current_drive->audio_state=audio_pausing; - RETURN_UP(0); - case audio_pausing: - i=cc_Seek(current_drive->pos_audio_start,1); - if (i<0) RETURN_UP(-EIO); - RETURN_UP(0); - default: - RETURN_UP(-EINVAL); - } - - case CDROMRESUME: /* resume paused audio play */ - msg(DBG_IOC,"ioctl: CDROMRESUME entered.\n"); - /* resume playing audio tracks when a previous PLAY AUDIO call has */ - /* been paused with a PAUSE command. */ - /* It will resume playing from the location saved in SubQ_run_tot. */ - if (current_drive->audio_state!=audio_pausing) RETURN_UP(-EINVAL); - if (famL_drive) - i=cc_PlayAudio(current_drive->pos_audio_start, - current_drive->pos_audio_end); - else i=cc_Pause_Resume(3); - if (i<0) RETURN_UP(-EIO); - current_drive->audio_state=audio_playing; - RETURN_UP(0); - - case CDROMPLAYMSF: - msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n"); -#ifdef SAFE_MIXED - if (current_drive->has_data>1) RETURN_UP(-EBUSY); -#endif /* SAFE_MIXED */ - if (current_drive->audio_state==audio_playing) - { - i=cc_Pause_Resume(1); - if (i<0) RETURN_UP(-EIO); - i=cc_ReadSubQ(); - if (i<0) RETURN_UP(-EIO); - current_drive->pos_audio_start=current_drive->SubQ_run_tot; - i=cc_Seek(current_drive->pos_audio_start,1); - } - memcpy(&msf, (void *) arg, sizeof(struct cdrom_msf)); - /* values come as msf-bin */ - current_drive->pos_audio_start = (msf.cdmsf_min0<<16) | - (msf.cdmsf_sec0<<8) | - msf.cdmsf_frame0; - current_drive->pos_audio_end = (msf.cdmsf_min1<<16) | - (msf.cdmsf_sec1<<8) | - msf.cdmsf_frame1; - msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n", - current_drive->pos_audio_start,current_drive->pos_audio_end); - i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end); - if (i<0) - { - msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i); - DriveReset(); - current_drive->audio_state=0; - RETURN_UP(-EIO); - } - current_drive->audio_state=audio_playing; - RETURN_UP(0); - - case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ - msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n"); -#ifdef SAFE_MIXED - if (current_drive->has_data>1) RETURN_UP(-EBUSY); -#endif /* SAFE_MIXED */ - if (current_drive->audio_state==audio_playing) - { - msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n"); -#if 1 - RETURN_UP(0); /* just let us play on */ -#else - RETURN_UP(-EINVAL); /* play on, but say "error" */ -#endif - } - memcpy(&ti,(void *) arg,sizeof(struct cdrom_ti)); - msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n", - ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1); - if (ti.cdti_trk0n_first_track) RETURN_UP(-EINVAL); - if (ti.cdti_trk0>current_drive->n_last_track) RETURN_UP(-EINVAL); - if (ti.cdti_trk1current_drive->n_last_track) ti.cdti_trk1=current_drive->n_last_track; - current_drive->pos_audio_start=current_drive->TocBuffer[ti.cdti_trk0].address; - current_drive->pos_audio_end=current_drive->TocBuffer[ti.cdti_trk1+1].address; - i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end); - if (i<0) - { - msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i); - DriveReset(); - current_drive->audio_state=0; - RETURN_UP(-EIO); - } - current_drive->audio_state=audio_playing; - RETURN_UP(0); - - case CDROMREADTOCHDR: /* Read the table of contents header */ - msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n"); - tochdr.cdth_trk0=current_drive->n_first_track; - tochdr.cdth_trk1=current_drive->n_last_track; - memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr)); - RETURN_UP(0); - - case CDROMREADTOCENTRY: /* Read an entry in the table of contents */ - msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n"); - memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry)); - i=tocentry.cdte_track; - if (i==CDROM_LEADOUT) i=current_drive->n_last_track+1; - else if (in_first_track||i>current_drive->n_last_track) - RETURN_UP(-EINVAL); - tocentry.cdte_adr=current_drive->TocBuffer[i].ctl_adr&0x0F; - tocentry.cdte_ctrl=(current_drive->TocBuffer[i].ctl_adr>>4)&0x0F; - tocentry.cdte_datamode=current_drive->TocBuffer[i].format; - if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */ - { - tocentry.cdte_addr.msf.minute=(current_drive->TocBuffer[i].address>>16)&0x00FF; - tocentry.cdte_addr.msf.second=(current_drive->TocBuffer[i].address>>8)&0x00FF; - tocentry.cdte_addr.msf.frame=current_drive->TocBuffer[i].address&0x00FF; - } - else if (tocentry.cdte_format==CDROM_LBA) /* blk required */ - tocentry.cdte_addr.lba=msf2blk(current_drive->TocBuffer[i].address); - else RETURN_UP(-EINVAL); - memcpy((void *) arg, &tocentry, sizeof(struct cdrom_tocentry)); - RETURN_UP(0); - - case CDROMSTOP: /* Spin down the drive */ - msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n"); -#ifdef SAFE_MIXED - if (current_drive->has_data>1) RETURN_UP(-EBUSY); -#endif /* SAFE_MIXED */ - i=cc_Pause_Resume(1); - current_drive->audio_state=0; -#if 0 - cc_DriveReset(); + i=cc_Pause_Resume(1); + current_drive->audio_state=0; +#if 0 + cc_DriveReset(); #endif RETURN_UP(i); - + case CDROMSTART: /* Spin up the drive */ msg(DBG_IOC,"ioctl: CDROMSTART entered.\n"); cc_SpinUp(); current_drive->audio_state=0; RETURN_UP(0); - + case CDROMVOLCTRL: /* Volume control */ msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n"); memcpy(&volctrl,(char *) arg,sizeof(volctrl)); @@ -4670,7 +4344,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, current_drive->vol_ctrl1=volctrl.channel1; i=cc_SetVolume(); RETURN_UP(0); - + case CDROMVOLREAD: /* read Volume settings from drive */ msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n"); st=cc_GetVolume(); @@ -4694,7 +4368,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, if (i<0) { j=cc_ReadError(); /* clear out error status from drive */ current_drive->audio_state=CDROM_AUDIO_NO_STATUS; - /* get and set the disk state here, + /* get and set the disk state here, probably not the right place, but who cares! It makes it work properly! --AJK */ if (current_drive->CD_changed==0xFF) { @@ -4715,8 +4389,8 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, } } memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl)); - /* - This virtual crap is very bogus! + /* + This virtual crap is very bogus! It doesn't detect when the cd is done playing audio! Lets do this right with proper hardware register reading! */ @@ -4775,7 +4449,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, SC.cdsc_trk,SC.cdsc_ind, SC.cdsc_absaddr,SC.cdsc_reladdr); RETURN_UP(0); - + default: msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd); RETURN_UP(-EINVAL); @@ -4788,7 +4462,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, static void sbp_transfer(struct request *req) { long offs; - + while ( (req->nr_sectors > 0) && (req->sector/4 >= current_drive->sbp_first_frame) && (req->sector/4 <= current_drive->sbp_last_frame) ) @@ -4807,11 +4481,11 @@ static void sbp_transfer(struct request *req) * * This is a kludge so we don't need to modify end_request. * We put the req we take out after INIT_REQUEST in the requests list, - * so that end_request will discard it. + * so that end_request will discard it. * * The bug could be present in other block devices, perhaps we * should modify INIT_REQUEST and end_request instead, and - * change every block device.. + * change every block device.. * * Could be a race here?? Could e.g. a timer interrupt schedule() us? * If so, we should copy end_request here, and do it right.. (or @@ -4831,546 +4505,865 @@ static void sbp_transfer(struct request *req) /*==========================================================================*/ /* - * I/O request routine, called from Linux kernel. + * I/O request routine, called from Linux kernel. + */ +static void do_sbpcd_request(request_queue_t * q) +{ + u_int block; + u_int nsect; + int status_tries, data_tries; + struct request *req; + struct sbpcd_drive *p; +#ifdef DEBUG_GTL + static int xx_nr=0; + int xnr; +#endif + + request_loop: +#ifdef DEBUG_GTL + xnr=++xx_nr; + + req = elv_next_request(q); + + if (!req) + { + printk( "do_sbpcd_request[%di](NULL), Pid:%d, Time:%li\n", + xnr, current->pid, jiffies); + printk( "do_sbpcd_request[%do](NULL) end 0 (null), Time:%li\n", + xnr, jiffies); + return; + } + + printk(" do_sbpcd_request[%di](%p:%ld+%ld), Pid:%d, Time:%li\n", + xnr, req, req->sector, req->nr_sectors, current->pid, jiffies); +#endif + + req = elv_next_request(q); /* take out our request so no other */ + if (!req) + return; + + if (req -> sector == -1) + end_request(req, 0); + spin_unlock_irq(q->queue_lock); + + down(&ioctl_read_sem); + if (rq_data_dir(elv_next_request(q)) != READ) + { + msg(DBG_INF, "bad cmd %d\n", req->cmd[0]); + goto err_done; + } + p = req->rq_disk->private_data; +#if OLD_BUSY + while (busy_audio) sbp_sleep(HZ); /* wait a bit */ + busy_data=1; +#endif /* OLD_BUSY */ + + if (p->audio_state==audio_playing) goto err_done; + if (p != current_drive) + switch_drive(p); + + block = req->sector; /* always numbered as 512-byte-pieces */ + nsect = req->nr_sectors; /* always counted as 512-byte-pieces */ + + msg(DBG_BSZ,"read sector %d (%d sectors)\n", block, nsect); +#if 0 + msg(DBG_MUL,"read LBA %d\n", block/4); +#endif + + sbp_transfer(req); + /* if we satisfied the request from the buffer, we're done. */ + if (req->nr_sectors == 0) + { +#ifdef DEBUG_GTL + printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 2, Time:%li\n", + xnr, req, req->sector, req->nr_sectors, jiffies); +#endif + up(&ioctl_read_sem); + spin_lock_irq(q->queue_lock); + end_request(req, 1); + goto request_loop; + } + +#ifdef FUTURE + i=prepare(0,0); /* at moment not really a hassle check, but ... */ + if (i!=0) + msg(DBG_INF,"\"prepare\" tells error %d -- ignored\n", i); +#endif /* FUTURE */ + + if (!st_spinning) cc_SpinUp(); + + for (data_tries=n_retries; data_tries > 0; data_tries--) + { + for (status_tries=3; status_tries > 0; status_tries--) + { + flags_cmd_out |= f_respo3; + cc_ReadStatus(); + if (sbp_status() != 0) break; + if (st_check) cc_ReadError(); + sbp_sleep(1); /* wait a bit, try again */ + } + if (status_tries == 0) + { + msg(DBG_INF,"sbp_status: failed after 3 tries in line %d\n", __LINE__); + break; + } + + sbp_read_cmd(req); + sbp_sleep(0); + if (sbp_data(req) != 0) + { +#ifdef SAFE_MIXED + current_drive->has_data=2; /* is really a data disk */ +#endif /* SAFE_MIXED */ +#ifdef DEBUG_GTL + printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%li\n", + xnr, req, req->sector, req->nr_sectors, jiffies); +#endif + up(&ioctl_read_sem); + spin_lock_irq(q->queue_lock); + end_request(req, 1); + goto request_loop; + } + } + + err_done: +#if OLD_BUSY + busy_data=0; +#endif /* OLD_BUSY */ +#ifdef DEBUG_GTL + printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 4 (error), Time:%li\n", + xnr, req, req->sector, req->nr_sectors, jiffies); +#endif + up(&ioctl_read_sem); + sbp_sleep(0); /* wait a bit, try again */ + spin_lock_irq(q->queue_lock); + end_request(req, 0); + goto request_loop; +} +/*==========================================================================*/ +/* + * build and send the READ command. + */ +static void sbp_read_cmd(struct request *req) +{ +#undef OLD + + int i; + int block; + + current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */ + current_drive->sbp_current = 0; + block=req->sector/4; + if (block+current_drive->sbp_bufsiz <= current_drive->CDsize_frm) + current_drive->sbp_read_frames = current_drive->sbp_bufsiz; + else + { + current_drive->sbp_read_frames=current_drive->CDsize_frm-block; + /* avoid reading past end of data */ + if (current_drive->sbp_read_frames < 1) + { + msg(DBG_INF,"requested frame %d, CD size %d ???\n", + block, current_drive->CDsize_frm); + current_drive->sbp_read_frames=1; + } + } + + flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; + clr_cmdbuf(); + if (famV_drive) + { + drvcmd[0]=CMDV_READ; + lba2msf(block,&drvcmd[1]); /* msf-bcd format required */ + bin2bcdx(&drvcmd[1]); + bin2bcdx(&drvcmd[2]); + bin2bcdx(&drvcmd[3]); + drvcmd[4]=current_drive->sbp_read_frames>>8; + drvcmd[5]=current_drive->sbp_read_frames&0xff; + drvcmd[6]=0x02; /* flag "msf-bcd" */ + } + else if (fam0L_drive) + { + flags_cmd_out |= f_lopsta | f_getsta | f_bit1; + if (current_drive->xa_byte==0x20) + { + cmd_type=READ_M2; + drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ + drvcmd[1]=(block>>16)&0x0ff; + drvcmd[2]=(block>>8)&0x0ff; + drvcmd[3]=block&0x0ff; + drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; + drvcmd[5]=current_drive->sbp_read_frames&0x0ff; + } + else + { + drvcmd[0]=CMD0_READ; /* "read frames", old drives */ + if (current_drive->drv_type>=drv_201) + { + lba2msf(block,&drvcmd[1]); /* msf-bcd format required */ + bin2bcdx(&drvcmd[1]); + bin2bcdx(&drvcmd[2]); + bin2bcdx(&drvcmd[3]); + } + else + { + drvcmd[1]=(block>>16)&0x0ff; + drvcmd[2]=(block>>8)&0x0ff; + drvcmd[3]=block&0x0ff; + } + drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; + drvcmd[5]=current_drive->sbp_read_frames&0x0ff; + drvcmd[6]=(current_drive->drv_typesbp_read_frames>>8)&0x0ff; + drvcmd[6]=current_drive->sbp_read_frames&0x0ff; + } + else if (fam2_drive) + { + drvcmd[0]=CMD2_READ; + lba2msf(block,&drvcmd[1]); /* msf-bin format required */ + drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; + drvcmd[5]=current_drive->sbp_read_frames&0x0ff; + drvcmd[6]=0x02; + } + else if (famT_drive) + { + drvcmd[0]=CMDT_READ; + drvcmd[2]=(block>>24)&0x0ff; + drvcmd[3]=(block>>16)&0x0ff; + drvcmd[4]=(block>>8)&0x0ff; + drvcmd[5]=block&0x0ff; + drvcmd[7]=(current_drive->sbp_read_frames>>8)&0x0ff; + drvcmd[8]=current_drive->sbp_read_frames&0x0ff; + } + flags_cmd_out=f_putcmd; + response_count=0; + i=cmd_out(); + if (i<0) msg(DBG_INF,"error giving READ command: %0d\n", i); + return; +} +/*==========================================================================*/ +/* + * Check the completion of the read-data command. On success, read + * the current_drive->sbp_bufsiz * 2048 bytes of data from the disk into buffer. */ -static void do_sbpcd_request(request_queue_t * q) +static int sbp_data(struct request *req) { - u_int block; - u_int nsect; - int status_tries, data_tries; - struct request *req; - struct sbpcd_drive *p; -#ifdef DEBUG_GTL - static int xx_nr=0; - int xnr; -#endif - - request_loop: -#ifdef DEBUG_GTL - xnr=++xx_nr; - - req = elv_next_request(q); - - if (!req) - { - printk( "do_sbpcd_request[%di](NULL), Pid:%d, Time:%li\n", - xnr, current->pid, jiffies); - printk( "do_sbpcd_request[%do](NULL) end 0 (null), Time:%li\n", - xnr, jiffies); - return; - } + int i=0, j=0, l, frame; + u_int try=0; + u_long timeout; + u_char *p; + u_int data_tries = 0; + u_int data_waits = 0; + u_int data_retrying = 0; + int error_flag; + int xa_count; + int max_latency; + int success; + int wait; + int duration; - printk(" do_sbpcd_request[%di](%p:%ld+%ld), Pid:%d, Time:%li\n", - xnr, req, req->sector, req->nr_sectors, current->pid, jiffies); + error_flag=0; + success=0; +#if LONG_TIMING + max_latency=9*HZ; +#else + if (current_drive->f_multisession) max_latency=15*HZ; + else max_latency=5*HZ; #endif + duration=jiffies; + for (frame=0;framesbp_read_frames&&!error_flag; frame++) + { + SBPCD_CLI; - req = elv_next_request(q); /* take out our request so no other */ - if (!req) - return; + del_timer(&data_timer); + data_timer.expires=jiffies+max_latency; + timed_out_data=0; + add_timer(&data_timer); + while (!timed_out_data) + { + if (current_drive->f_multisession) try=maxtim_data*4; + else try=maxtim_data; + msg(DBG_000,"sbp_data: CDi_status loop: try=%d.\n",try); + for ( ; try!=0;try--) + { + j=inb(CDi_status); + if (!(j&s_not_data_ready)) break; + if (!(j&s_not_result_ready)) break; + if (fam0LV_drive) if (j&s_attention) break; + } + if (!(j&s_not_data_ready)) goto data_ready; + if (try==0) + { + if (data_retrying == 0) data_waits++; + data_retrying = 1; + msg(DBG_000,"sbp_data: CDi_status loop: sleeping.\n"); + sbp_sleep(1); + try = 1; + } + } + msg(DBG_INF,"sbp_data: CDi_status loop expired.\n"); + data_ready: + del_timer(&data_timer); - if (req -> sector == -1) - end_request(req, 0); - spin_unlock_irq(q->queue_lock); + if (timed_out_data) + { + msg(DBG_INF,"sbp_data: CDi_status timeout (timed_out_data) (%02X).\n", j); + error_flag++; + } + if (try==0) + { + msg(DBG_INF,"sbp_data: CDi_status timeout (try=0) (%02X).\n", j); + error_flag++; + } + if (!(j&s_not_result_ready)) + { + msg(DBG_INF, "sbp_data: RESULT_READY where DATA_READY awaited (%02X).\n", j); + response_count=20; + j=ResponseInfo(); + j=inb(CDi_status); + } + if (j&s_not_data_ready) + { + if ((current_drive->ored_ctl_adr&0x40)==0) + msg(DBG_INF, "CD contains no data tracks.\n"); + else msg(DBG_INF, "sbp_data: DATA_READY timeout (%02X).\n", j); + error_flag++; + } + SBPCD_STI; + if (error_flag) break; - down(&ioctl_read_sem); - if (rq_data_dir(elv_next_request(q)) != READ) - { - msg(DBG_INF, "bad cmd %d\n", req->cmd[0]); - goto err_done; + msg(DBG_000, "sbp_data: beginning to read.\n"); + p = current_drive->sbp_buf + frame * CD_FRAMESIZE; + if (sbpro_type==1) OUT(CDo_sel_i_d,1); + if (cmd_type==READ_M2) { + if (do_16bit) insw(CDi_data, xa_head_buf, CD_XA_HEAD>>1); + else insb(CDi_data, xa_head_buf, CD_XA_HEAD); + } + if (do_16bit) insw(CDi_data, p, CD_FRAMESIZE>>1); + else insb(CDi_data, p, CD_FRAMESIZE); + if (cmd_type==READ_M2) { + if (do_16bit) insw(CDi_data, xa_tail_buf, CD_XA_TAIL>>1); + else insb(CDi_data, xa_tail_buf, CD_XA_TAIL); + } + current_drive->sbp_current++; + if (sbpro_type==1) OUT(CDo_sel_i_d,0); + if (cmd_type==READ_M2) + { + for (xa_count=0;xa_count= 1000) + { + msg(DBG_INF,"sbp_data() statistics: %d waits in %d frames.\n", data_waits, data_tries); + data_waits = data_tries = 0; + } } - p = req->rq_disk->private_data; -#if OLD_BUSY - while (busy_audio) sbp_sleep(HZ); /* wait a bit */ - busy_data=1; -#endif /* OLD_BUSY */ - - if (p->audio_state==audio_playing) goto err_done; - if (p != current_drive) - switch_drive(p); - - block = req->sector; /* always numbered as 512-byte-pieces */ - nsect = req->nr_sectors; /* always counted as 512-byte-pieces */ - - msg(DBG_BSZ,"read sector %d (%d sectors)\n", block, nsect); + duration=jiffies-duration; + msg(DBG_TEA,"time to read %d frames: %d jiffies .\n",frame,duration); + if (famT_drive) + { + wait=8; + do + { + if (teac==2) + { + if ((i=CDi_stat_loop_T()) == -1) break; + } + else + { + sbp_sleep(1); + OUT(CDo_sel_i_d,0); + i=inb(CDi_status); + } + if (!(i&s_not_data_ready)) + { + OUT(CDo_sel_i_d,1); + j=0; + do + { + if (do_16bit) i=inw(CDi_data); + else i=inb(CDi_data); + j++; + i=inb(CDi_status); + } + while (!(i&s_not_data_ready)); + msg(DBG_TEA, "==========too much data (%d bytes/words)==============.\n", j); + } + if (!(i&s_not_result_ready)) + { + OUT(CDo_sel_i_d,0); + l=0; + do + { + infobuf[l++]=inb(CDi_info); + i=inb(CDi_status); + } + while (!(i&s_not_result_ready)); + if (infobuf[0]==0x00) success=1; +#if 1 + for (j=0;j1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (sbp_data): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",recursion); + else msg(DBG_TEA,"sbp_data: CMDT_READ_ERR necessary.\n"); + clr_cmdbuf(); + drvcmd[0]=CMDT_READ_ERR; + j=cmd_out_T(); /* !!! recursive here !!! */ + --recursion; + sbp_sleep(1); + } + while (j<0); + current_drive->error_state=infobuf[2]; + current_drive->b3=infobuf[3]; + current_drive->b4=infobuf[4]; + } + break; + } + else + { #if 0 - msg(DBG_MUL,"read LBA %d\n", block/4); + msg(DBG_TEA, "============= waiting for result=================.\n"); + sbp_sleep(1); #endif - - sbp_transfer(req); - /* if we satisfied the request from the buffer, we're done. */ - if (req->nr_sectors == 0) + } + } + while (wait--); + } + + if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */ { -#ifdef DEBUG_GTL - printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 2, Time:%li\n", - xnr, req, req->sector, req->nr_sectors, jiffies); + msg(DBG_TEA, "================error flag: %d=================.\n", error_flag); + msg(DBG_INF,"sbp_data: read aborted by drive.\n"); +#if 1 + i=cc_DriveReset(); /* ugly fix to prevent a hang */ +#else + i=cc_ReadError(); #endif - up(&ioctl_read_sem); - spin_lock_irq(q->queue_lock); - end_request(req, 1); - goto request_loop; + return (0); } - -#ifdef FUTURE - i=prepare(0,0); /* at moment not really a hassle check, but ... */ - if (i!=0) - msg(DBG_INF,"\"prepare\" tells error %d -- ignored\n", i); -#endif /* FUTURE */ - - if (!st_spinning) cc_SpinUp(); - for (data_tries=n_retries; data_tries > 0; data_tries--) + if (fam0LV_drive) { - for (status_tries=3; status_tries > 0; status_tries--) + SBPCD_CLI; + i=maxtim_data; + for (timeout=jiffies+HZ; time_before(jiffies, timeout); timeout--) { - flags_cmd_out |= f_respo3; - cc_ReadStatus(); - if (sbp_status() != 0) break; - if (st_check) cc_ReadError(); - sbp_sleep(1); /* wait a bit, try again */ + for ( ;i!=0;i--) + { + j=inb(CDi_status); + if (!(j&s_not_data_ready)) break; + if (!(j&s_not_result_ready)) break; + if (j&s_attention) break; + } + if (i != 0 || time_after_eq(jiffies, timeout)) break; + sbp_sleep(0); + i = 1; } - if (status_tries == 0) + if (i==0) msg(DBG_INF,"status timeout after READ.\n"); + if (!(j&s_attention)) { - msg(DBG_INF,"sbp_status: failed after 3 tries in line %d\n", __LINE__); - break; + msg(DBG_INF,"sbp_data: timeout waiting DRV_ATTN - retrying.\n"); + i=cc_DriveReset(); /* ugly fix to prevent a hang */ + SBPCD_STI; + return (0); } - - sbp_read_cmd(req); - sbp_sleep(0); - if (sbp_data(req) != 0) + SBPCD_STI; + } + +#if 0 + if (!success) +#endif + do { -#ifdef SAFE_MIXED - current_drive->has_data=2; /* is really a data disk */ -#endif /* SAFE_MIXED */ -#ifdef DEBUG_GTL - printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%li\n", - xnr, req, req->sector, req->nr_sectors, jiffies); + if (fam0LV_drive) cc_ReadStatus(); +#if 1 + if (famT_drive) msg(DBG_TEA, "================before ResponseStatus=================.\n", i); #endif - up(&ioctl_read_sem); - spin_lock_irq(q->queue_lock); - end_request(req, 1); - goto request_loop; + i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */ +#if 1 + if (famT_drive) msg(DBG_TEA, "================ResponseStatus: %d=================.\n", i); +#endif + if (i<0) + { + msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", current_drive->status_bits); + return (0); + } } + while ((fam0LV_drive)&&(!st_check)&&(!(i&p_success))); + if (st_check) + { + i=cc_ReadError(); + msg(DBG_INF,"cc_ReadError was necessary after read: %d\n",i); + return (0); + } + if (fatal_err) + { + fatal_err=0; + current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */ + current_drive->sbp_current = 0; + msg(DBG_INF,"sbp_data: fatal_err - retrying.\n"); + return (0); } - err_done: -#if OLD_BUSY - busy_data=0; -#endif /* OLD_BUSY */ -#ifdef DEBUG_GTL - printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 4 (error), Time:%li\n", - xnr, req, req->sector, req->nr_sectors, jiffies); -#endif - up(&ioctl_read_sem); - sbp_sleep(0); /* wait a bit, try again */ - spin_lock_irq(q->queue_lock); - end_request(req, 0); - goto request_loop; + current_drive->sbp_first_frame = req -> sector / 4; + current_drive->sbp_last_frame = current_drive->sbp_first_frame + current_drive->sbp_read_frames - 1; + sbp_transfer(req); + return (1); } /*==========================================================================*/ -/* - * build and send the READ command. - */ -static void sbp_read_cmd(struct request *req) + +static int sbpcd_block_open(struct inode *inode, struct file *file) { -#undef OLD + struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; + return cdrom_open(p->sbpcd_infop, inode, file); +} - int i; - int block; +static int sbpcd_block_release(struct inode *inode, struct file *file) +{ + struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; + return cdrom_release(p->sbpcd_infop, file); +} + +static int sbpcd_block_ioctl(struct inode *inode, struct file *file, + unsigned cmd, unsigned long arg) +{ + struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; + struct cdrom_device_info *cdi = p->sbpcd_infop; + int ret, i; + + ret = cdrom_ioctl(file, p->sbpcd_infop, inode, cmd, arg); + if (ret != -ENOSYS) + return ret; + + msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08lX)\n", cdi->name, cmd, arg); + if (p->drv_id==-1) { + msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name); + return (-ENXIO); /* no such drive */ + } + down(&ioctl_read_sem); + if (p != current_drive) + switch_drive(p); - current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */ - current_drive->sbp_current = 0; - block=req->sector/4; - if (block+current_drive->sbp_bufsiz <= current_drive->CDsize_frm) - current_drive->sbp_read_frames = current_drive->sbp_bufsiz; - else + msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd); + switch (cmd) /* Sun-compatible */ { - current_drive->sbp_read_frames=current_drive->CDsize_frm-block; - /* avoid reading past end of data */ - if (current_drive->sbp_read_frames < 1) + case DDIOCSDBG: /* DDI Debug */ + if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM); + i=sbpcd_dbg_ioctl(arg,1); + RETURN_UP(i); + case CDROMRESET: /* hard reset the drive */ + msg(DBG_IOC,"ioctl: CDROMRESET entered.\n"); + i=DriveReset(); + current_drive->audio_state=0; + RETURN_UP(i); + + case CDROMREADMODE1: + msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n"); +#ifdef SAFE_MIXED + if (current_drive->has_data>1) RETURN_UP(-EBUSY); +#endif /* SAFE_MIXED */ + cc_ModeSelect(CD_FRAMESIZE); + cc_ModeSense(); + current_drive->mode=READ_M1; + RETURN_UP(0); + + case CDROMREADMODE2: /* not usable at the moment */ + msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n"); +#ifdef SAFE_MIXED + if (current_drive->has_data>1) RETURN_UP(-EBUSY); +#endif /* SAFE_MIXED */ + cc_ModeSelect(CD_FRAMESIZE_RAW1); + cc_ModeSense(); + current_drive->mode=READ_M2; + RETURN_UP(0); + + case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */ + msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n"); + if (current_drive->sbp_audsiz>0) + vfree(current_drive->aud_buf); + current_drive->aud_buf=NULL; + current_drive->sbp_audsiz=arg; + + if (current_drive->sbp_audsiz>16) { - msg(DBG_INF,"requested frame %d, CD size %d ???\n", - block, current_drive->CDsize_frm); - current_drive->sbp_read_frames=1; + current_drive->sbp_audsiz = 0; + RETURN_UP(current_drive->sbp_audsiz); } - } - flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; - clr_cmdbuf(); - if (famV_drive) - { - drvcmd[0]=CMDV_READ; - lba2msf(block,&drvcmd[1]); /* msf-bcd format required */ - bin2bcdx(&drvcmd[1]); - bin2bcdx(&drvcmd[2]); - bin2bcdx(&drvcmd[3]); - drvcmd[4]=current_drive->sbp_read_frames>>8; - drvcmd[5]=current_drive->sbp_read_frames&0xff; - drvcmd[6]=0x02; /* flag "msf-bcd" */ - } - else if (fam0L_drive) - { - flags_cmd_out |= f_lopsta | f_getsta | f_bit1; - if (current_drive->xa_byte==0x20) + if (current_drive->sbp_audsiz>0) { - cmd_type=READ_M2; - drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ - drvcmd[1]=(block>>16)&0x0ff; - drvcmd[2]=(block>>8)&0x0ff; - drvcmd[3]=block&0x0ff; - drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; - drvcmd[5]=current_drive->sbp_read_frames&0x0ff; + current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW); + if (current_drive->aud_buf==NULL) + { + msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz); + current_drive->sbp_audsiz=0; + } + else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz); } - else + RETURN_UP(current_drive->sbp_audsiz); + + case CDROMREADAUDIO: + { /* start of CDROMREADAUDIO */ + int i=0, j=0, frame, block=0; + u_int try=0; + u_long timeout; + u_char *p; + u_int data_tries = 0; + u_int data_waits = 0; + u_int data_retrying = 0; + int status_tries; + int error_flag; + + msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.\n"); + if (fam0_drive) RETURN_UP(-EINVAL); + if (famL_drive) RETURN_UP(-EINVAL); + if (famV_drive) RETURN_UP(-EINVAL); + if (famT_drive) RETURN_UP(-EINVAL); +#ifdef SAFE_MIXED + if (current_drive->has_data>1) RETURN_UP(-EBUSY); +#endif /* SAFE_MIXED */ + if (current_drive->aud_buf==NULL) RETURN_UP(-EINVAL); + if (copy_from_user(&read_audio, (void __user *)arg, + sizeof(struct cdrom_read_audio))) + RETURN_UP(-EFAULT); + if (read_audio.nframes < 0 || read_audio.nframes>current_drive->sbp_audsiz) RETURN_UP(-EINVAL); + if (!access_ok(VERIFY_WRITE, read_audio.buf, + read_audio.nframes*CD_FRAMESIZE_RAW)) + RETURN_UP(-EFAULT); + + if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */ + block=msf2lba(&read_audio.addr.msf.minute); + else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */ + block=read_audio.addr.lba; + else RETURN_UP(-EINVAL); +#if 000 + i=cc_SetSpeed(speed_150,0,0); + if (i) msg(DBG_AUD,"read_audio: SetSpeed error %d\n", i); +#endif + msg(DBG_AUD,"read_audio: lba: %d, msf: %06X\n", + block, blk2msf(block)); + msg(DBG_AUD,"read_audio: before cc_ReadStatus.\n"); +#if OLD_BUSY + while (busy_data) sbp_sleep(HZ/10); /* wait a bit */ + busy_audio=1; +#endif /* OLD_BUSY */ + error_flag=0; + for (data_tries=5; data_tries>0; data_tries--) { - drvcmd[0]=CMD0_READ; /* "read frames", old drives */ - if (current_drive->drv_type>=drv_201) + msg(DBG_AUD,"data_tries=%d ...\n", data_tries); + current_drive->mode=READ_AU; + cc_ModeSelect(CD_FRAMESIZE_RAW); + cc_ModeSense(); + for (status_tries=3; status_tries > 0; status_tries--) { - lba2msf(block,&drvcmd[1]); /* msf-bcd format required */ - bin2bcdx(&drvcmd[1]); - bin2bcdx(&drvcmd[2]); - bin2bcdx(&drvcmd[3]); + flags_cmd_out |= f_respo3; + cc_ReadStatus(); + if (sbp_status() != 0) break; + if (st_check) cc_ReadError(); + sbp_sleep(1); /* wait a bit, try again */ } - else + if (status_tries == 0) { - drvcmd[1]=(block>>16)&0x0ff; - drvcmd[2]=(block>>8)&0x0ff; - drvcmd[3]=block&0x0ff; + msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__); + continue; } - drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; - drvcmd[5]=current_drive->sbp_read_frames&0x0ff; - drvcmd[6]=(current_drive->drv_typesbp_read_frames>>8)&0x0ff; - drvcmd[6]=current_drive->sbp_read_frames&0x0ff; - } - else if (fam2_drive) - { - drvcmd[0]=CMD2_READ; - lba2msf(block,&drvcmd[1]); /* msf-bin format required */ - drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; - drvcmd[5]=current_drive->sbp_read_frames&0x0ff; - drvcmd[6]=0x02; - } - else if (famT_drive) - { - drvcmd[0]=CMDT_READ; - drvcmd[2]=(block>>24)&0x0ff; - drvcmd[3]=(block>>16)&0x0ff; - drvcmd[4]=(block>>8)&0x0ff; - drvcmd[5]=block&0x0ff; - drvcmd[7]=(current_drive->sbp_read_frames>>8)&0x0ff; - drvcmd[8]=current_drive->sbp_read_frames&0x0ff; - } - flags_cmd_out=f_putcmd; - response_count=0; - i=cmd_out(); - if (i<0) msg(DBG_INF,"error giving READ command: %0d\n", i); - return; -} -/*==========================================================================*/ -/* - * Check the completion of the read-data command. On success, read - * the current_drive->sbp_bufsiz * 2048 bytes of data from the disk into buffer. - */ -static int sbp_data(struct request *req) -{ - int i=0, j=0, l, frame; - u_int try=0; - u_long timeout; - u_char *p; - u_int data_tries = 0; - u_int data_waits = 0; - u_int data_retrying = 0; - int error_flag; - int xa_count; - int max_latency; - int success; - int wait; - int duration; - - error_flag=0; - success=0; -#if LONG_TIMING - max_latency=9*HZ; -#else - if (current_drive->f_multisession) max_latency=15*HZ; - else max_latency=5*HZ; -#endif - duration=jiffies; - for (frame=0;framesbp_read_frames&&!error_flag; frame++) - { - SBPCD_CLI; - - del_timer(&data_timer); - data_timer.expires=jiffies+max_latency; - timed_out_data=0; - add_timer(&data_timer); - while (!timed_out_data) - { - if (current_drive->f_multisession) try=maxtim_data*4; - else try=maxtim_data; - msg(DBG_000,"sbp_data: CDi_status loop: try=%d.\n",try); - for ( ; try!=0;try--) + msg(DBG_AUD,"read_audio: sbp_status: ok.\n"); + + flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; + if (fam0L_drive) { - j=inb(CDi_status); - if (!(j&s_not_data_ready)) break; - if (!(j&s_not_result_ready)) break; - if (fam0LV_drive) if (j&s_attention) break; + flags_cmd_out |= f_lopsta | f_getsta | f_bit1; + cmd_type=READ_M2; + drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ + drvcmd[1]=(block>>16)&0x000000ff; + drvcmd[2]=(block>>8)&0x000000ff; + drvcmd[3]=block&0x000000ff; + drvcmd[4]=0; + drvcmd[5]=read_audio.nframes; /* # of frames */ + drvcmd[6]=0; } - if (!(j&s_not_data_ready)) goto data_ready; - if (try==0) + else if (fam1_drive) { - if (data_retrying == 0) data_waits++; - data_retrying = 1; - msg(DBG_000,"sbp_data: CDi_status loop: sleeping.\n"); - sbp_sleep(1); - try = 1; + drvcmd[0]=CMD1_READ; /* "read frames", new drives */ + lba2msf(block,&drvcmd[1]); /* msf-bin format required */ + drvcmd[4]=0; + drvcmd[5]=0; + drvcmd[6]=read_audio.nframes; /* # of frames */ } - } - msg(DBG_INF,"sbp_data: CDi_status loop expired.\n"); - data_ready: - del_timer(&data_timer); - - if (timed_out_data) - { - msg(DBG_INF,"sbp_data: CDi_status timeout (timed_out_data) (%02X).\n", j); - error_flag++; - } - if (try==0) - { - msg(DBG_INF,"sbp_data: CDi_status timeout (try=0) (%02X).\n", j); - error_flag++; - } - if (!(j&s_not_result_ready)) - { - msg(DBG_INF, "sbp_data: RESULT_READY where DATA_READY awaited (%02X).\n", j); - response_count=20; - j=ResponseInfo(); - j=inb(CDi_status); - } - if (j&s_not_data_ready) - { - if ((current_drive->ored_ctl_adr&0x40)==0) - msg(DBG_INF, "CD contains no data tracks.\n"); - else msg(DBG_INF, "sbp_data: DATA_READY timeout (%02X).\n", j); - error_flag++; - } - SBPCD_STI; - if (error_flag) break; - - msg(DBG_000, "sbp_data: beginning to read.\n"); - p = current_drive->sbp_buf + frame * CD_FRAMESIZE; - if (sbpro_type==1) OUT(CDo_sel_i_d,1); - if (cmd_type==READ_M2) { - if (do_16bit) insw(CDi_data, xa_head_buf, CD_XA_HEAD>>1); - else insb(CDi_data, xa_head_buf, CD_XA_HEAD); - } - if (do_16bit) insw(CDi_data, p, CD_FRAMESIZE>>1); - else insb(CDi_data, p, CD_FRAMESIZE); - if (cmd_type==READ_M2) { - if (do_16bit) insw(CDi_data, xa_tail_buf, CD_XA_TAIL>>1); - else insb(CDi_data, xa_tail_buf, CD_XA_TAIL); - } - current_drive->sbp_current++; - if (sbpro_type==1) OUT(CDo_sel_i_d,0); - if (cmd_type==READ_M2) - { - for (xa_count=0;xa_count= 1000) - { - msg(DBG_INF,"sbp_data() statistics: %d waits in %d frames.\n", data_waits, data_tries); - data_waits = data_tries = 0; - } - } - duration=jiffies-duration; - msg(DBG_TEA,"time to read %d frames: %d jiffies .\n",frame,duration); - if (famT_drive) - { - wait=8; - do - { - if (teac==2) - { - if ((i=CDi_stat_loop_T()) == -1) break; - } - else - { - sbp_sleep(1); - OUT(CDo_sel_i_d,0); - i=inb(CDi_status); - } - if (!(i&s_not_data_ready)) + else if (fam2_drive) { - OUT(CDo_sel_i_d,1); - j=0; - do + drvcmd[0]=CMD2_READ_XA2; + lba2msf(block,&drvcmd[1]); /* msf-bin format required */ + drvcmd[4]=0; + drvcmd[5]=read_audio.nframes; /* # of frames */ + drvcmd[6]=0x11; /* raw mode */ + } + else if (famT_drive) /* CD-55A: not tested yet */ + { + } + msg(DBG_AUD,"read_audio: before giving \"read\" command.\n"); + flags_cmd_out=f_putcmd; + response_count=0; + i=cmd_out(); + if (i<0) msg(DBG_INF,"error giving READ AUDIO command: %0d\n", i); + sbp_sleep(0); + msg(DBG_AUD,"read_audio: after giving \"read\" command.\n"); + for (frame=1;frame<2 && !error_flag; frame++) + { + try=maxtim_data; + for (timeout=jiffies+9*HZ; ; ) { - if (do_16bit) i=inw(CDi_data); - else i=inb(CDi_data); - j++; - i=inb(CDi_status); + for ( ; try!=0;try--) + { + j=inb(CDi_status); + if (!(j&s_not_data_ready)) break; + if (!(j&s_not_result_ready)) break; + if (fam0L_drive) if (j&s_attention) break; + } + if (try != 0 || time_after_eq(jiffies, timeout)) break; + if (data_retrying == 0) data_waits++; + data_retrying = 1; + sbp_sleep(1); + try = 1; } - while (!(i&s_not_data_ready)); - msg(DBG_TEA, "==========too much data (%d bytes/words)==============.\n", j); - } - if (!(i&s_not_result_ready)) - { - OUT(CDo_sel_i_d,0); - l=0; - do + if (try==0) { - infobuf[l++]=inb(CDi_info); - i=inb(CDi_status); + msg(DBG_INF,"read_audio: sbp_data: CDi_status timeout.\n"); + error_flag++; + break; } - while (!(i&s_not_result_ready)); - if (infobuf[0]==0x00) success=1; -#if 1 - for (j=0;j1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (sbp_data): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",recursion); - else msg(DBG_TEA,"sbp_data: CMDT_READ_ERR necessary.\n"); - clr_cmdbuf(); - drvcmd[0]=CMDT_READ_ERR; - j=cmd_out_T(); /* !!! recursive here !!! */ - --recursion; - sbp_sleep(1); + break; + } + msg(DBG_AUD,"read_audio: before reading data.\n"); + error_flag=0; + p = current_drive->aud_buf; + if (sbpro_type==1) OUT(CDo_sel_i_d,1); + if (do_16bit) + { + u_short *p2 = (u_short *) p; + + for (; (u_char *) p2 < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) + { + if ((inb_p(CDi_status)&s_not_data_ready)) continue; + + /* get one sample */ + *p2++ = inw_p(CDi_data); + *p2++ = inw_p(CDi_data); + } + } else { + for (; p < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) + { + if ((inb_p(CDi_status)&s_not_data_ready)) continue; + + /* get one sample */ + *p++ = inb_p(CDi_data); + *p++ = inb_p(CDi_data); + *p++ = inb_p(CDi_data); + *p++ = inb_p(CDi_data); } - while (j<0); - current_drive->error_state=infobuf[2]; - current_drive->b3=infobuf[3]; - current_drive->b4=infobuf[4]; } - break; + if (sbpro_type==1) OUT(CDo_sel_i_d,0); + data_retrying = 0; } - else + msg(DBG_AUD,"read_audio: after reading data.\n"); + if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */ { -#if 0 - msg(DBG_TEA, "============= waiting for result=================.\n"); - sbp_sleep(1); -#endif - } - } - while (wait--); - } - - if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */ - { - msg(DBG_TEA, "================error flag: %d=================.\n", error_flag); - msg(DBG_INF,"sbp_data: read aborted by drive.\n"); -#if 1 - i=cc_DriveReset(); /* ugly fix to prevent a hang */ + msg(DBG_AUD,"read_audio: read aborted by drive\n"); +#if 0000 + i=cc_DriveReset(); /* ugly fix to prevent a hang */ #else - i=cc_ReadError(); + i=cc_ReadError(); #endif - return (0); - } - - if (fam0LV_drive) - { - SBPCD_CLI; - i=maxtim_data; - for (timeout=jiffies+HZ; time_before(jiffies, timeout); timeout--) - { - for ( ;i!=0;i--) + continue; + } + if (fam0L_drive) { - j=inb(CDi_status); - if (!(j&s_not_data_ready)) break; - if (!(j&s_not_result_ready)) break; - if (j&s_attention) break; + i=maxtim_data; + for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--) + { + for ( ;i!=0;i--) + { + j=inb(CDi_status); + if (!(j&s_not_data_ready)) break; + if (!(j&s_not_result_ready)) break; + if (j&s_attention) break; + } + if (i != 0 || time_after_eq(jiffies, timeout)) break; + sbp_sleep(0); + i = 1; + } + if (i==0) msg(DBG_AUD,"read_audio: STATUS TIMEOUT AFTER READ"); + if (!(j&s_attention)) + { + msg(DBG_AUD,"read_audio: sbp_data: timeout waiting DRV_ATTN - retrying\n"); + i=cc_DriveReset(); /* ugly fix to prevent a hang */ + continue; + } } - if (i != 0 || time_after_eq(jiffies, timeout)) break; - sbp_sleep(0); - i = 1; - } - if (i==0) msg(DBG_INF,"status timeout after READ.\n"); - if (!(j&s_attention)) - { - msg(DBG_INF,"sbp_data: timeout waiting DRV_ATTN - retrying.\n"); - i=cc_DriveReset(); /* ugly fix to prevent a hang */ - SBPCD_STI; - return (0); - } - SBPCD_STI; - } - -#if 0 - if (!success) -#endif - do - { - if (fam0LV_drive) cc_ReadStatus(); -#if 1 - if (famT_drive) msg(DBG_TEA, "================before ResponseStatus=================.\n", i); -#endif - i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */ -#if 1 - if (famT_drive) msg(DBG_TEA, "================ResponseStatus: %d=================.\n", i); -#endif - if (i<0) + do { - msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", current_drive->status_bits); - return (0); + if (fam0L_drive) cc_ReadStatus(); + i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */ + if (i<0) { msg(DBG_AUD, + "read_audio: cc_ReadStatus error after read: %02X\n", + current_drive->status_bits); + continue; /* FIXME */ + } + } + while ((fam0L_drive)&&(!st_check)&&(!(i&p_success))); + if (st_check) + { + i=cc_ReadError(); + msg(DBG_AUD,"read_audio: cc_ReadError was necessary after read: %02X\n",i); + continue; } + if (copy_to_user(read_audio.buf, + current_drive->aud_buf, + read_audio.nframes * CD_FRAMESIZE_RAW)) + RETURN_UP(-EFAULT); + msg(DBG_AUD,"read_audio: copy_to_user done.\n"); + break; } - while ((fam0LV_drive)&&(!st_check)&&(!(i&p_success))); - if (st_check) - { - i=cc_ReadError(); - msg(DBG_INF,"cc_ReadError was necessary after read: %d\n",i); - return (0); - } - if (fatal_err) - { - fatal_err=0; - current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */ - current_drive->sbp_current = 0; - msg(DBG_INF,"sbp_data: fatal_err - retrying.\n"); - return (0); - } - - current_drive->sbp_first_frame = req -> sector / 4; - current_drive->sbp_last_frame = current_drive->sbp_first_frame + current_drive->sbp_read_frames - 1; - sbp_transfer(req); - return (1); -} -/*==========================================================================*/ - -static int sbpcd_block_open(struct inode *inode, struct file *file) -{ - struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; - return cdrom_open(p->sbpcd_infop, inode, file); -} - -static int sbpcd_block_release(struct inode *inode, struct file *file) -{ - struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; - return cdrom_release(p->sbpcd_infop, file); -} + cc_ModeSelect(CD_FRAMESIZE); + cc_ModeSense(); + current_drive->mode=READ_M1; +#if OLD_BUSY + busy_audio=0; +#endif /* OLD_BUSY */ + if (data_tries == 0) + { + msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__); + RETURN_UP(-EIO); + } + msg(DBG_AUD,"read_audio: successful return.\n"); + RETURN_UP(0); + } /* end of CDROMREADAUDIO */ -static int sbpcd_block_ioctl(struct inode *inode, struct file *file, - unsigned cmd, unsigned long arg) -{ - struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; - return cdrom_ioctl(file, p->sbpcd_infop, inode, cmd, arg); + default: + msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd); + RETURN_UP(-EINVAL); + } /* end switch(cmd) */ } static int sbpcd_block_media_changed(struct gendisk *disk) @@ -5478,10 +5471,9 @@ static struct cdrom_device_ops sbpcd_dops = { .get_mcn = sbpcd_get_mcn, .reset = sbpcd_reset, .audio_ioctl = sbpcd_audio_ioctl, - .dev_ioctl = sbpcd_dev_ioctl, .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | - CDC_MCN | CDC_PLAY_AUDIO | CDC_IOCTLS, + CDC_MCN | CDC_PLAY_AUDIO, .n_minors = 1, }; diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index e27617259552..c0f817ba7adb 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -627,7 +627,7 @@ static struct cdrom_device_ops viocd_dops = { .media_changed = viocd_media_changed, .lock_door = viocd_lock_door, .generic_packet = viocd_packet, - .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_RAM + .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_RAM }; static int __init find_capability(const char *type) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 3325660f7248..430d8af35cb1 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -2470,52 +2470,6 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi, return cgc->stat; } -static -int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi, - unsigned int cmd, unsigned long arg) -{ - struct packet_command cgc; - char buffer[16]; - int stat; - - init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN); - - /* These will be moved into the Uniform layer shortly... */ - switch (cmd) { - case CDROMSETSPINDOWN: { - char spindown; - - if (copy_from_user(&spindown, (void __user *) arg, sizeof(char))) - return -EFAULT; - - if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0))) - return stat; - - buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f); - - return cdrom_mode_select(cdi, &cgc); - } - - case CDROMGETSPINDOWN: { - char spindown; - - if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0))) - return stat; - - spindown = buffer[11] & 0x0f; - - if (copy_to_user((void __user *) arg, &spindown, sizeof (char))) - return -EFAULT; - - return 0; - } - - default: - return -EINVAL; - } - -} - static int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi, unsigned int cmd, void *arg) @@ -2852,12 +2806,11 @@ static struct cdrom_device_ops ide_cdrom_dops = { .get_mcn = ide_cdrom_get_mcn, .reset = ide_cdrom_reset, .audio_ioctl = ide_cdrom_audio_ioctl, - .dev_ioctl = ide_cdrom_dev_ioctl, .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | - CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_CD_R | + CDC_DRIVE_STATUS | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R| CDC_DVD_RAM | CDC_GENERIC_PACKET | CDC_MO_DRIVE | CDC_MRW | CDC_MRW_W | CDC_RAM, @@ -3367,6 +3320,45 @@ static int idecd_release(struct inode * inode, struct file * file) return 0; } +static int idecd_set_spindown(struct cdrom_device_info *cdi, unsigned long arg) +{ + struct packet_command cgc; + char buffer[16]; + int stat; + char spindown; + + if (copy_from_user(&spindown, (void __user *)arg, sizeof(char))) + return -EFAULT; + + init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN); + + stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0); + if (stat) + return stat; + + buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f); + return cdrom_mode_select(cdi, &cgc); +} + +static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg) +{ + struct packet_command cgc; + char buffer[16]; + int stat; + char spindown; + + init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN); + + stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0); + if (stat) + return stat; + + spindown = buffer[11] & 0x0f; + if (copy_to_user((void __user *)arg, &spindown, sizeof (char))) + return -EFAULT; + return 0; +} + static int idecd_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -3374,7 +3366,16 @@ static int idecd_ioctl (struct inode *inode, struct file *file, struct cdrom_info *info = ide_cd_g(bdev->bd_disk); int err; - err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg); + switch (cmd) { + case CDROMSETSPINDOWN: + return idecd_set_spindown(&info->devinfo, arg); + case CDROMGETSPINDOWN: + return idecd_get_spindown(&info->devinfo, arg); + default: + break; + } + + err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg); if (err == -EINVAL) err = cdrom_ioctl(file, &info->devinfo, inode, cmd, arg); diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index f9c1192dc15e..7c80711e18ed 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -71,7 +71,7 @@ MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_CDROM_MAJOR); #define SR_CAPABILITIES \ (CDC_CLOSE_TRAY|CDC_OPEN_TRAY|CDC_LOCK|CDC_SELECT_SPEED| \ CDC_SELECT_DISC|CDC_MULTI_SESSION|CDC_MCN|CDC_MEDIA_CHANGED| \ - CDC_PLAY_AUDIO|CDC_RESET|CDC_IOCTLS|CDC_DRIVE_STATUS| \ + CDC_PLAY_AUDIO|CDC_RESET|CDC_DRIVE_STATUS| \ CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_DVD_RAM|CDC_GENERIC_PACKET| \ CDC_MRW|CDC_MRW_W|CDC_RAM) @@ -118,7 +118,6 @@ static struct cdrom_device_ops sr_dops = { .get_mcn = sr_get_mcn, .reset = sr_reset, .audio_ioctl = sr_audio_ioctl, - .dev_ioctl = sr_dev_ioctl, .capability = SR_CAPABILITIES, .generic_packet = sr_packet, }; @@ -456,17 +455,33 @@ static int sr_block_ioctl(struct inode *inode, struct file *file, unsigned cmd, { struct scsi_cd *cd = scsi_cd(inode->i_bdev->bd_disk); struct scsi_device *sdev = cd->device; + void __user *argp = (void __user *)arg; + int ret; - /* - * Send SCSI addressing ioctls directly to mid level, send other - * ioctls to cdrom/block level. - */ - switch (cmd) { - case SCSI_IOCTL_GET_IDLUN: - case SCSI_IOCTL_GET_BUS_NUMBER: - return scsi_ioctl(sdev, cmd, (void __user *)arg); + /* + * Send SCSI addressing ioctls directly to mid level, send other + * ioctls to cdrom/block level. + */ + switch (cmd) { + case SCSI_IOCTL_GET_IDLUN: + case SCSI_IOCTL_GET_BUS_NUMBER: + return scsi_ioctl(sdev, cmd, argp); } - return cdrom_ioctl(file, &cd->cdi, inode, cmd, arg); + + ret = cdrom_ioctl(file, &cd->cdi, inode, cmd, arg); + if (ret != ENOSYS) + return ret; + + /* + * ENODEV means that we didn't recognise the ioctl, or that we + * cannot execute it in the current device state. In either + * case fall through to scsi_ioctl, which will return ENDOEV again + * if it doesn't recognise the ioctl + */ + ret = scsi_nonblockable_ioctl(sdev, cmd, argp, NULL); + if (ret != -ENODEV) + return ret; + return scsi_ioctl(sdev, cmd, argp); } static int sr_block_media_changed(struct gendisk *disk) diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h index d2bcd99c272f..d65de9621b27 100644 --- a/drivers/scsi/sr.h +++ b/drivers/scsi/sr.h @@ -55,7 +55,6 @@ int sr_get_mcn(struct cdrom_device_info *, struct cdrom_mcn *); int sr_reset(struct cdrom_device_info *); int sr_select_speed(struct cdrom_device_info *cdi, int speed); int sr_audio_ioctl(struct cdrom_device_info *, unsigned int, void *); -int sr_dev_ioctl(struct cdrom_device_info *, unsigned int, unsigned long); int sr_is_xa(Scsi_CD *); diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c index b65462f76484..d1268cb46837 100644 --- a/drivers/scsi/sr_ioctl.c +++ b/drivers/scsi/sr_ioctl.c @@ -562,22 +562,3 @@ int sr_is_xa(Scsi_CD *cd) #endif return is_xa; } - -int sr_dev_ioctl(struct cdrom_device_info *cdi, - unsigned int cmd, unsigned long arg) -{ - Scsi_CD *cd = cdi->handle; - int ret; - - ret = scsi_nonblockable_ioctl(cd->device, cmd, - (void __user *)arg, NULL); - /* - * ENODEV means that we didn't recognise the ioctl, or that we - * cannot execute it in the current device state. In either - * case fall through to scsi_ioctl, which will return ENDOEV again - * if it doesn't recognise the ioctl - */ - if (ret != -ENODEV) - return ret; - return scsi_ioctl(cd->device, cmd, (void __user *)arg); -} diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h index b68fdf1f3156..3c9b0bc05123 100644 --- a/include/linux/cdrom.h +++ b/include/linux/cdrom.h @@ -378,7 +378,6 @@ struct cdrom_generic_command #define CDC_MEDIA_CHANGED 0x80 /* media changed */ #define CDC_PLAY_AUDIO 0x100 /* audio functions */ #define CDC_RESET 0x200 /* hard reset device */ -#define CDC_IOCTLS 0x400 /* driver has non-standard ioctls */ #define CDC_DRIVE_STATUS 0x800 /* driver implements drive status */ #define CDC_GENERIC_PACKET 0x1000 /* driver implements generic packets */ #define CDC_CD_R 0x2000 /* drive is a CD-R */ @@ -974,9 +973,7 @@ struct cdrom_device_ops { int (*reset) (struct cdrom_device_info *); /* play stuff */ int (*audio_ioctl) (struct cdrom_device_info *,unsigned int, void *); - /* dev-specific */ - int (*dev_ioctl) (struct cdrom_device_info *, - unsigned int, unsigned long); + /* driver specifications */ const int capability; /* capability flags */ int n_minors; /* number of active minor devices */ -- cgit v1.2.3 From 804f1594cc3deb161e531a43d90c501f0db2635a Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Thu, 23 Mar 2006 03:00:16 -0800 Subject: [PATCH] Move read_mostly definition to asm/cache.h Seems like needless clutter having a bunch of #if defined(CONFIG_$ARCH) in include/linux/cache.h. Move the per architecture section definition to asm/cache.h, and keep the if-not-defined dummy case in linux/cache.h to catch architectures which don't implement the section. Verified that symbols still go in .data.read_mostly on parisc, and the compile doesn't break. Signed-off-by: Kyle McMartin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-i386/cache.h | 2 ++ include/asm-ia64/cache.h | 2 ++ include/asm-parisc/cache.h | 2 ++ include/asm-sparc64/cache.h | 2 ++ include/asm-x86_64/cache.h | 2 ++ include/linux/cache.h | 4 +--- 6 files changed, 11 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/asm-i386/cache.h b/include/asm-i386/cache.h index 615911e5bd24..ca15c9c665cf 100644 --- a/include/asm-i386/cache.h +++ b/include/asm-i386/cache.h @@ -10,4 +10,6 @@ #define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT) #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) +#define __read_mostly __attribute__((__section__(".data.read_mostly"))) + #endif diff --git a/include/asm-ia64/cache.h b/include/asm-ia64/cache.h index 40dd25195d65..f0a104db8f20 100644 --- a/include/asm-ia64/cache.h +++ b/include/asm-ia64/cache.h @@ -25,4 +25,6 @@ # define SMP_CACHE_BYTES (1 << 3) #endif +#define __read_mostly __attribute__((__section__(".data.read_mostly"))) + #endif /* _ASM_IA64_CACHE_H */ diff --git a/include/asm-parisc/cache.h b/include/asm-parisc/cache.h index 93f179f13ce8..ae50f8e12eed 100644 --- a/include/asm-parisc/cache.h +++ b/include/asm-parisc/cache.h @@ -29,6 +29,8 @@ #define SMP_CACHE_BYTES L1_CACHE_BYTES +#define __read_mostly __attribute__((__section__(".data.read_mostly"))) + extern void flush_data_cache_local(void *); /* flushes local data-cache only */ extern void flush_instruction_cache_local(void *); /* flushes local code-cache only */ #ifdef CONFIG_SMP diff --git a/include/asm-sparc64/cache.h b/include/asm-sparc64/cache.h index f7d35a2ae9b8..e9df17acedde 100644 --- a/include/asm-sparc64/cache.h +++ b/include/asm-sparc64/cache.h @@ -13,4 +13,6 @@ #define SMP_CACHE_BYTES_SHIFT 6 #define SMP_CACHE_BYTES (1 << SMP_CACHE_BYTES_SHIFT) /* L2 cache line size. */ +#define __read_mostly __attribute__((__section__(".data.read_mostly"))) + #endif diff --git a/include/asm-x86_64/cache.h b/include/asm-x86_64/cache.h index 263f0a211ed7..c8043a16152e 100644 --- a/include/asm-x86_64/cache.h +++ b/include/asm-x86_64/cache.h @@ -20,6 +20,8 @@ __attribute__((__section__(".data.page_aligned"))) #endif +#define __read_mostly __attribute__((__section__(".data.read_mostly"))) + #endif #endif diff --git a/include/linux/cache.h b/include/linux/cache.h index d22e632f41fb..cc4b3aafad9a 100644 --- a/include/linux/cache.h +++ b/include/linux/cache.h @@ -13,9 +13,7 @@ #define SMP_CACHE_BYTES L1_CACHE_BYTES #endif -#if defined(CONFIG_X86) || defined(CONFIG_SPARC64) || defined(CONFIG_IA64) || defined(CONFIG_PARISC) -#define __read_mostly __attribute__((__section__(".data.read_mostly"))) -#else +#ifndef __read_mostly #define __read_mostly #endif -- cgit v1.2.3 From c039e3134ae62863bbc8e8429b29e3c43cf21b2a Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Thu, 23 Mar 2006 03:00:28 -0800 Subject: [PATCH] sem2mutex: blockdev #2 Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Acked-by: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- block/ioctl.c | 22 +++++++++++----------- drivers/block/rd.c | 4 ++-- drivers/s390/block/dasd_ioctl.c | 8 ++++---- fs/block_dev.c | 28 ++++++++++++++-------------- fs/buffer.c | 6 +++--- fs/super.c | 4 ++-- include/linux/fs.h | 4 ++-- 7 files changed, 38 insertions(+), 38 deletions(-) (limited to 'include') diff --git a/block/ioctl.c b/block/ioctl.c index e1109491c234..35fdb7dc6512 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -42,9 +42,9 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user return -EINVAL; } /* partition number in use? */ - down(&bdev->bd_sem); + mutex_lock(&bdev->bd_mutex); if (disk->part[part - 1]) { - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); return -EBUSY; } /* overlap? */ @@ -55,13 +55,13 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user continue; if (!(start+length <= s->start_sect || start >= s->start_sect + s->nr_sects)) { - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); return -EBUSY; } } /* all seems OK */ add_partition(disk, part, start, length); - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); return 0; case BLKPG_DEL_PARTITION: if (!disk->part[part-1]) @@ -71,9 +71,9 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user bdevp = bdget_disk(disk, part); if (!bdevp) return -ENOMEM; - down(&bdevp->bd_sem); + mutex_lock(&bdevp->bd_mutex); if (bdevp->bd_openers) { - up(&bdevp->bd_sem); + mutex_unlock(&bdevp->bd_mutex); bdput(bdevp); return -EBUSY; } @@ -81,10 +81,10 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user fsync_bdev(bdevp); invalidate_bdev(bdevp, 0); - down(&bdev->bd_sem); + mutex_lock(&bdev->bd_mutex); delete_partition(disk, part); - up(&bdev->bd_sem); - up(&bdevp->bd_sem); + mutex_unlock(&bdev->bd_mutex); + mutex_unlock(&bdevp->bd_mutex); bdput(bdevp); return 0; @@ -102,10 +102,10 @@ static int blkdev_reread_part(struct block_device *bdev) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (down_trylock(&bdev->bd_sem)) + if (!mutex_trylock(&bdev->bd_mutex)) return -EBUSY; res = rescan_partitions(disk, bdev); - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); return res; } diff --git a/drivers/block/rd.c b/drivers/block/rd.c index ffd6abd6d5a0..1c54f46d3f70 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -310,12 +310,12 @@ static int rd_ioctl(struct inode *inode, struct file *file, * cache */ error = -EBUSY; - down(&bdev->bd_sem); + mutex_lock(&bdev->bd_mutex); if (bdev->bd_openers <= 2) { truncate_inode_pages(bdev->bd_inode->i_mapping, 0); error = 0; } - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); return error; } diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index fafeeae52675..f9930552ab54 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -151,9 +151,9 @@ dasd_ioctl_enable(struct block_device *bdev, int no, long args) return -ENODEV; dasd_enable_device(device); /* Formatting the dasd device can change the capacity. */ - down(&bdev->bd_sem); + mutex_lock(&bdev->bd_mutex); i_size_write(bdev->bd_inode, (loff_t)get_capacity(device->gdp) << 9); - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); return 0; } @@ -184,9 +184,9 @@ dasd_ioctl_disable(struct block_device *bdev, int no, long args) * Set i_size to zero, since read, write, etc. check against this * value. */ - down(&bdev->bd_sem); + mutex_lock(&bdev->bd_mutex); i_size_write(bdev->bd_inode, 0); - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); return 0; } diff --git a/fs/block_dev.c b/fs/block_dev.c index 6e50346fb1ee..44d05e6e34db 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -265,8 +265,8 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) SLAB_CTOR_CONSTRUCTOR) { memset(bdev, 0, sizeof(*bdev)); - sema_init(&bdev->bd_sem, 1); - sema_init(&bdev->bd_mount_sem, 1); + mutex_init(&bdev->bd_mutex); + mutex_init(&bdev->bd_mount_mutex); INIT_LIST_HEAD(&bdev->bd_inodes); INIT_LIST_HEAD(&bdev->bd_list); inode_init_once(&ei->vfs_inode); @@ -574,7 +574,7 @@ static int do_open(struct block_device *bdev, struct file *file) } owner = disk->fops->owner; - down(&bdev->bd_sem); + mutex_lock(&bdev->bd_mutex); if (!bdev->bd_openers) { bdev->bd_disk = disk; bdev->bd_contains = bdev; @@ -605,21 +605,21 @@ static int do_open(struct block_device *bdev, struct file *file) if (ret) goto out_first; bdev->bd_contains = whole; - down(&whole->bd_sem); + mutex_lock(&whole->bd_mutex); whole->bd_part_count++; p = disk->part[part - 1]; bdev->bd_inode->i_data.backing_dev_info = whole->bd_inode->i_data.backing_dev_info; if (!(disk->flags & GENHD_FL_UP) || !p || !p->nr_sects) { whole->bd_part_count--; - up(&whole->bd_sem); + mutex_unlock(&whole->bd_mutex); ret = -ENXIO; goto out_first; } kobject_get(&p->kobj); bdev->bd_part = p; bd_set_size(bdev, (loff_t) p->nr_sects << 9); - up(&whole->bd_sem); + mutex_unlock(&whole->bd_mutex); } } else { put_disk(disk); @@ -633,13 +633,13 @@ static int do_open(struct block_device *bdev, struct file *file) if (bdev->bd_invalidated) rescan_partitions(bdev->bd_disk, bdev); } else { - down(&bdev->bd_contains->bd_sem); + mutex_lock(&bdev->bd_contains->bd_mutex); bdev->bd_contains->bd_part_count++; - up(&bdev->bd_contains->bd_sem); + mutex_unlock(&bdev->bd_contains->bd_mutex); } } bdev->bd_openers++; - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); unlock_kernel(); return 0; @@ -652,7 +652,7 @@ out_first: put_disk(disk); module_put(owner); out: - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); unlock_kernel(); if (ret) bdput(bdev); @@ -714,7 +714,7 @@ int blkdev_put(struct block_device *bdev) struct inode *bd_inode = bdev->bd_inode; struct gendisk *disk = bdev->bd_disk; - down(&bdev->bd_sem); + mutex_lock(&bdev->bd_mutex); lock_kernel(); if (!--bdev->bd_openers) { sync_blockdev(bdev); @@ -724,9 +724,9 @@ int blkdev_put(struct block_device *bdev) if (disk->fops->release) ret = disk->fops->release(bd_inode, NULL); } else { - down(&bdev->bd_contains->bd_sem); + mutex_lock(&bdev->bd_contains->bd_mutex); bdev->bd_contains->bd_part_count--; - up(&bdev->bd_contains->bd_sem); + mutex_unlock(&bdev->bd_contains->bd_mutex); } if (!bdev->bd_openers) { struct module *owner = disk->fops->owner; @@ -746,7 +746,7 @@ int blkdev_put(struct block_device *bdev) bdev->bd_contains = NULL; } unlock_kernel(); - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); bdput(bdev); return ret; } diff --git a/fs/buffer.c b/fs/buffer.c index 1d3683d496f8..0d6ca7bac6c8 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -201,7 +201,7 @@ int fsync_bdev(struct block_device *bdev) * freeze_bdev -- lock a filesystem and force it into a consistent state * @bdev: blockdevice to lock * - * This takes the block device bd_mount_sem to make sure no new mounts + * This takes the block device bd_mount_mutex to make sure no new mounts * happen on bdev until thaw_bdev() is called. * If a superblock is found on this device, we take the s_umount semaphore * on it to make sure nobody unmounts until the snapshot creation is done. @@ -210,7 +210,7 @@ struct super_block *freeze_bdev(struct block_device *bdev) { struct super_block *sb; - down(&bdev->bd_mount_sem); + mutex_lock(&bdev->bd_mount_mutex); sb = get_super(bdev); if (sb && !(sb->s_flags & MS_RDONLY)) { sb->s_frozen = SB_FREEZE_WRITE; @@ -264,7 +264,7 @@ void thaw_bdev(struct block_device *bdev, struct super_block *sb) drop_super(sb); } - up(&bdev->bd_mount_sem); + mutex_unlock(&bdev->bd_mount_mutex); } EXPORT_SYMBOL(thaw_bdev); diff --git a/fs/super.c b/fs/super.c index e20b5580afd5..8f9c9b3af70c 100644 --- a/fs/super.c +++ b/fs/super.c @@ -693,9 +693,9 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type, * will protect the lockfs code from trying to start a snapshot * while we are mounting */ - down(&bdev->bd_mount_sem); + mutex_lock(&bdev->bd_mount_mutex); s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); - up(&bdev->bd_mount_sem); + mutex_unlock(&bdev->bd_mount_mutex); if (IS_ERR(s)) goto out; diff --git a/include/linux/fs.h b/include/linux/fs.h index 128d0082522c..009ac96053fe 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -397,8 +397,8 @@ struct block_device { dev_t bd_dev; /* not a kdev_t - it's a search key */ struct inode * bd_inode; /* will die */ int bd_openers; - struct semaphore bd_sem; /* open/close mutex */ - struct semaphore bd_mount_sem; /* mount mutex */ + struct mutex bd_mutex; /* open/close mutex */ + struct mutex bd_mount_mutex; /* mount mutex */ struct list_head bd_inodes; void * bd_holder; int bd_holders; -- cgit v1.2.3 From d3be915fc5e7d19a2283ad9b0fe0782a74675d0a Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 23 Mar 2006 03:00:29 -0800 Subject: [PATCH] sem2mutex: quota Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Cc: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/dquot.c | 117 +++++++++++++++++++++++++------------------------- fs/ext3/super.c | 4 +- fs/quota.c | 6 +-- fs/quota_v2.c | 2 +- fs/super.c | 4 +- include/linux/quota.h | 7 +-- 6 files changed, 71 insertions(+), 69 deletions(-) (limited to 'include') diff --git a/fs/dquot.c b/fs/dquot.c index 9376a4378988..acf07e581f8c 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -103,12 +103,12 @@ * (these locking rules also apply for S_NOQUOTA flag in the inode - note that * for altering the flag i_mutex is also needed). If operation is holding * reference to dquot in other way (e.g. quotactl ops) it must be guarded by - * dqonoff_sem. + * dqonoff_mutex. * This locking assures that: * a) update/access to dquot pointers in inode is serialized * b) everyone is guarded against invalidate_dquots() * - * Each dquot has its dq_lock semaphore. Locked dquots might not be referenced + * Each dquot has its dq_lock mutex. Locked dquots might not be referenced * from inodes (dquot_alloc_space() and such don't check the dq_lock). * Currently dquot is locked only when it is being read to memory (or space for * it is being allocated) on the first dqget() and when it is being released on @@ -118,8 +118,9 @@ * spinlock to internal buffers before writing. * * Lock ordering (including related VFS locks) is the following: - * i_mutex > dqonoff_sem > journal_lock > dqptr_sem > dquot->dq_lock > dqio_sem - * i_mutex on quota files is special (it's below dqio_sem) + * i_mutex > dqonoff_sem > journal_lock > dqptr_sem > dquot->dq_lock > + * dqio_mutex + * i_mutex on quota files is special (it's below dqio_mutex) */ static DEFINE_SPINLOCK(dq_list_lock); @@ -280,8 +281,8 @@ static inline void remove_inuse(struct dquot *dquot) static void wait_on_dquot(struct dquot *dquot) { - down(&dquot->dq_lock); - up(&dquot->dq_lock); + mutex_lock(&dquot->dq_lock); + mutex_unlock(&dquot->dq_lock); } #define mark_dquot_dirty(dquot) ((dquot)->dq_sb->dq_op->mark_dirty(dquot)) @@ -320,8 +321,8 @@ int dquot_acquire(struct dquot *dquot) int ret = 0, ret2 = 0; struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); - down(&dquot->dq_lock); - down(&dqopt->dqio_sem); + mutex_lock(&dquot->dq_lock); + mutex_lock(&dqopt->dqio_mutex); if (!test_bit(DQ_READ_B, &dquot->dq_flags)) ret = dqopt->ops[dquot->dq_type]->read_dqblk(dquot); if (ret < 0) @@ -342,8 +343,8 @@ int dquot_acquire(struct dquot *dquot) } set_bit(DQ_ACTIVE_B, &dquot->dq_flags); out_iolock: - up(&dqopt->dqio_sem); - up(&dquot->dq_lock); + mutex_unlock(&dqopt->dqio_mutex); + mutex_unlock(&dquot->dq_lock); return ret; } @@ -355,7 +356,7 @@ int dquot_commit(struct dquot *dquot) int ret = 0, ret2 = 0; struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); - down(&dqopt->dqio_sem); + mutex_lock(&dqopt->dqio_mutex); spin_lock(&dq_list_lock); if (!clear_dquot_dirty(dquot)) { spin_unlock(&dq_list_lock); @@ -372,7 +373,7 @@ int dquot_commit(struct dquot *dquot) ret = ret2; } out_sem: - up(&dqopt->dqio_sem); + mutex_unlock(&dqopt->dqio_mutex); return ret; } @@ -384,11 +385,11 @@ int dquot_release(struct dquot *dquot) int ret = 0, ret2 = 0; struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); - down(&dquot->dq_lock); + mutex_lock(&dquot->dq_lock); /* Check whether we are not racing with some other dqget() */ if (atomic_read(&dquot->dq_count) > 1) goto out_dqlock; - down(&dqopt->dqio_sem); + mutex_lock(&dqopt->dqio_mutex); if (dqopt->ops[dquot->dq_type]->release_dqblk) { ret = dqopt->ops[dquot->dq_type]->release_dqblk(dquot); /* Write the info */ @@ -398,9 +399,9 @@ int dquot_release(struct dquot *dquot) ret = ret2; } clear_bit(DQ_ACTIVE_B, &dquot->dq_flags); - up(&dqopt->dqio_sem); + mutex_unlock(&dqopt->dqio_mutex); out_dqlock: - up(&dquot->dq_lock); + mutex_unlock(&dquot->dq_lock); return ret; } @@ -464,7 +465,7 @@ int vfs_quota_sync(struct super_block *sb, int type) struct quota_info *dqopt = sb_dqopt(sb); int cnt; - down(&dqopt->dqonoff_sem); + mutex_lock(&dqopt->dqonoff_mutex); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (type != -1 && cnt != type) continue; @@ -499,7 +500,7 @@ int vfs_quota_sync(struct super_block *sb, int type) spin_lock(&dq_list_lock); dqstats.syncs++; spin_unlock(&dq_list_lock); - up(&dqopt->dqonoff_sem); + mutex_unlock(&dqopt->dqonoff_mutex); return 0; } @@ -540,7 +541,7 @@ static int shrink_dqcache_memory(int nr, gfp_t gfp_mask) /* * Put reference to dquot * NOTE: If you change this function please check whether dqput_blocks() works right... - * MUST be called with either dqptr_sem or dqonoff_sem held + * MUST be called with either dqptr_sem or dqonoff_mutex held */ static void dqput(struct dquot *dquot) { @@ -605,7 +606,7 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type) return NODQUOT; memset((caddr_t)dquot, 0, sizeof(struct dquot)); - sema_init(&dquot->dq_lock, 1); + mutex_init(&dquot->dq_lock); INIT_LIST_HEAD(&dquot->dq_free); INIT_LIST_HEAD(&dquot->dq_inuse); INIT_HLIST_NODE(&dquot->dq_hash); @@ -620,7 +621,7 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type) /* * Get reference to dquot - * MUST be called with either dqptr_sem or dqonoff_sem held + * MUST be called with either dqptr_sem or dqonoff_mutex held */ static struct dquot *dqget(struct super_block *sb, unsigned int id, int type) { @@ -686,7 +687,7 @@ static int dqinit_needed(struct inode *inode, int type) return 0; } -/* This routine is guarded by dqonoff_sem semaphore */ +/* This routine is guarded by dqonoff_mutex mutex */ static void add_dquot_ref(struct super_block *sb, int type) { struct list_head *p; @@ -964,8 +965,8 @@ int dquot_initialize(struct inode *inode, int type) unsigned int id = 0; int cnt, ret = 0; - /* First test before acquiring semaphore - solves deadlocks when we - * re-enter the quota code and are already holding the semaphore */ + /* First test before acquiring mutex - solves deadlocks when we + * re-enter the quota code and are already holding the mutex */ if (IS_NOQUOTA(inode)) return 0; down_write(&sb_dqopt(inode->i_sb)->dqptr_sem); @@ -1028,8 +1029,8 @@ int dquot_alloc_space(struct inode *inode, qsize_t number, int warn) int cnt, ret = NO_QUOTA; char warntype[MAXQUOTAS]; - /* First test before acquiring semaphore - solves deadlocks when we - * re-enter the quota code and are already holding the semaphore */ + /* First test before acquiring mutex - solves deadlocks when we + * re-enter the quota code and are already holding the mutex */ if (IS_NOQUOTA(inode)) { out_add: inode_add_bytes(inode, number); @@ -1077,8 +1078,8 @@ int dquot_alloc_inode(const struct inode *inode, unsigned long number) int cnt, ret = NO_QUOTA; char warntype[MAXQUOTAS]; - /* First test before acquiring semaphore - solves deadlocks when we - * re-enter the quota code and are already holding the semaphore */ + /* First test before acquiring mutex - solves deadlocks when we + * re-enter the quota code and are already holding the mutex */ if (IS_NOQUOTA(inode)) return QUOTA_OK; for (cnt = 0; cnt < MAXQUOTAS; cnt++) @@ -1121,8 +1122,8 @@ int dquot_free_space(struct inode *inode, qsize_t number) { unsigned int cnt; - /* First test before acquiring semaphore - solves deadlocks when we - * re-enter the quota code and are already holding the semaphore */ + /* First test before acquiring mutex - solves deadlocks when we + * re-enter the quota code and are already holding the mutex */ if (IS_NOQUOTA(inode)) { out_sub: inode_sub_bytes(inode, number); @@ -1157,8 +1158,8 @@ int dquot_free_inode(const struct inode *inode, unsigned long number) { unsigned int cnt; - /* First test before acquiring semaphore - solves deadlocks when we - * re-enter the quota code and are already holding the semaphore */ + /* First test before acquiring mutex - solves deadlocks when we + * re-enter the quota code and are already holding the mutex */ if (IS_NOQUOTA(inode)) return QUOTA_OK; down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); @@ -1197,8 +1198,8 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr) chgid = (iattr->ia_valid & ATTR_GID) && inode->i_gid != iattr->ia_gid; char warntype[MAXQUOTAS]; - /* First test before acquiring semaphore - solves deadlocks when we - * re-enter the quota code and are already holding the semaphore */ + /* First test before acquiring mutex - solves deadlocks when we + * re-enter the quota code and are already holding the mutex */ if (IS_NOQUOTA(inode)) return QUOTA_OK; /* Clear the arrays */ @@ -1292,9 +1293,9 @@ int dquot_commit_info(struct super_block *sb, int type) int ret; struct quota_info *dqopt = sb_dqopt(sb); - down(&dqopt->dqio_sem); + mutex_lock(&dqopt->dqio_mutex); ret = dqopt->ops[type]->write_file_info(sb, type); - up(&dqopt->dqio_sem); + mutex_unlock(&dqopt->dqio_mutex); return ret; } @@ -1350,7 +1351,7 @@ int vfs_quota_off(struct super_block *sb, int type) struct inode *toputinode[MAXQUOTAS]; /* We need to serialize quota_off() for device */ - down(&dqopt->dqonoff_sem); + mutex_lock(&dqopt->dqonoff_mutex); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { toputinode[cnt] = NULL; if (type != -1 && cnt != type) @@ -1379,7 +1380,7 @@ int vfs_quota_off(struct super_block *sb, int type) dqopt->info[cnt].dqi_bgrace = 0; dqopt->ops[cnt] = NULL; } - up(&dqopt->dqonoff_sem); + mutex_unlock(&dqopt->dqonoff_mutex); /* Sync the superblock so that buffers with quota data are written to * disk (and so userspace sees correct data afterwards). */ if (sb->s_op->sync_fs) @@ -1392,7 +1393,7 @@ int vfs_quota_off(struct super_block *sb, int type) * changes done by userspace on the next quotaon() */ for (cnt = 0; cnt < MAXQUOTAS; cnt++) if (toputinode[cnt]) { - down(&dqopt->dqonoff_sem); + mutex_lock(&dqopt->dqonoff_mutex); /* If quota was reenabled in the meantime, we have * nothing to do */ if (!sb_has_quota_enabled(sb, cnt)) { @@ -1404,7 +1405,7 @@ int vfs_quota_off(struct super_block *sb, int type) mark_inode_dirty(toputinode[cnt]); iput(toputinode[cnt]); } - up(&dqopt->dqonoff_sem); + mutex_unlock(&dqopt->dqonoff_mutex); } if (sb->s_bdev) invalidate_bdev(sb->s_bdev, 0); @@ -1445,7 +1446,7 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id) /* And now flush the block cache so that kernel sees the changes */ invalidate_bdev(sb->s_bdev, 0); mutex_lock(&inode->i_mutex); - down(&dqopt->dqonoff_sem); + mutex_lock(&dqopt->dqonoff_mutex); if (sb_has_quota_enabled(sb, type)) { error = -EBUSY; goto out_lock; @@ -1470,17 +1471,17 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id) dqopt->ops[type] = fmt->qf_ops; dqopt->info[type].dqi_format = fmt; INIT_LIST_HEAD(&dqopt->info[type].dqi_dirty_list); - down(&dqopt->dqio_sem); + mutex_lock(&dqopt->dqio_mutex); if ((error = dqopt->ops[type]->read_file_info(sb, type)) < 0) { - up(&dqopt->dqio_sem); + mutex_unlock(&dqopt->dqio_mutex); goto out_file_init; } - up(&dqopt->dqio_sem); + mutex_unlock(&dqopt->dqio_mutex); mutex_unlock(&inode->i_mutex); set_enable_flags(dqopt, type); add_dquot_ref(sb, type); - up(&dqopt->dqonoff_sem); + mutex_unlock(&dqopt->dqonoff_mutex); return 0; @@ -1488,7 +1489,7 @@ out_file_init: dqopt->files[type] = NULL; iput(inode); out_lock: - up(&dqopt->dqonoff_sem); + mutex_unlock(&dqopt->dqonoff_mutex); if (oldflags != -1) { down_write(&dqopt->dqptr_sem); /* Set the flags back (in the case of accidental quotaon() @@ -1576,14 +1577,14 @@ int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d { struct dquot *dquot; - down(&sb_dqopt(sb)->dqonoff_sem); + mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); if (!(dquot = dqget(sb, id, type))) { - up(&sb_dqopt(sb)->dqonoff_sem); + mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); return -ESRCH; } do_get_dqblk(dquot, di); dqput(dquot); - up(&sb_dqopt(sb)->dqonoff_sem); + mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); return 0; } @@ -1645,14 +1646,14 @@ int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d { struct dquot *dquot; - down(&sb_dqopt(sb)->dqonoff_sem); + mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); if (!(dquot = dqget(sb, id, type))) { - up(&sb_dqopt(sb)->dqonoff_sem); + mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); return -ESRCH; } do_set_dqblk(dquot, di); dqput(dquot); - up(&sb_dqopt(sb)->dqonoff_sem); + mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); return 0; } @@ -1661,9 +1662,9 @@ int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii) { struct mem_dqinfo *mi; - down(&sb_dqopt(sb)->dqonoff_sem); + mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); if (!sb_has_quota_enabled(sb, type)) { - up(&sb_dqopt(sb)->dqonoff_sem); + mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); return -ESRCH; } mi = sb_dqopt(sb)->info + type; @@ -1673,7 +1674,7 @@ int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii) ii->dqi_flags = mi->dqi_flags & DQF_MASK; ii->dqi_valid = IIF_ALL; spin_unlock(&dq_data_lock); - up(&sb_dqopt(sb)->dqonoff_sem); + mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); return 0; } @@ -1682,9 +1683,9 @@ int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii) { struct mem_dqinfo *mi; - down(&sb_dqopt(sb)->dqonoff_sem); + mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); if (!sb_has_quota_enabled(sb, type)) { - up(&sb_dqopt(sb)->dqonoff_sem); + mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); return -ESRCH; } mi = sb_dqopt(sb)->info + type; @@ -1699,7 +1700,7 @@ int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii) mark_info_dirty(sb, type); /* Force write to disk */ sb->dq_op->write_info(sb, type); - up(&sb_dqopt(sb)->dqonoff_sem); + mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); return 0; } diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 56bf76586019..efa832059143 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -2382,8 +2382,8 @@ static int ext3_statfs (struct super_block * sb, struct kstatfs * buf) * Process 1 Process 2 * ext3_create() quota_sync() * journal_start() write_dquot() - * DQUOT_INIT() down(dqio_sem) - * down(dqio_sem) journal_start() + * DQUOT_INIT() down(dqio_mutex) + * down(dqio_mutex) journal_start() * */ diff --git a/fs/quota.c b/fs/quota.c index ba9e0bf32f67..d6a2be826e29 100644 --- a/fs/quota.c +++ b/fs/quota.c @@ -170,10 +170,10 @@ static void quota_sync_sb(struct super_block *sb, int type) /* Now when everything is written we can discard the pagecache so * that userspace sees the changes. We need i_mutex and so we could - * not do it inside dqonoff_sem. Moreover we need to be carefull + * not do it inside dqonoff_mutex. Moreover we need to be carefull * about races with quotaoff() (that is the reason why we have own * reference to inode). */ - down(&sb_dqopt(sb)->dqonoff_sem); + mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { discard[cnt] = NULL; if (type != -1 && cnt != type) @@ -182,7 +182,7 @@ static void quota_sync_sb(struct super_block *sb, int type) continue; discard[cnt] = igrab(sb_dqopt(sb)->files[cnt]); } - up(&sb_dqopt(sb)->dqonoff_sem); + mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (discard[cnt]) { mutex_lock(&discard[cnt]->i_mutex); diff --git a/fs/quota_v2.c b/fs/quota_v2.c index b4199ec3ece4..c519a583e681 100644 --- a/fs/quota_v2.c +++ b/fs/quota_v2.c @@ -394,7 +394,7 @@ static int v2_write_dquot(struct dquot *dquot) ssize_t ret; struct v2_disk_dqblk ddquot, empty; - /* dq_off is guarded by dqio_sem */ + /* dq_off is guarded by dqio_mutex */ if (!dquot->dq_off) if ((ret = dq_insert_tree(dquot)) < 0) { printk(KERN_ERR "VFS: Error %zd occurred while creating quota.\n", ret); diff --git a/fs/super.c b/fs/super.c index 8f9c9b3af70c..9cc6545dfa4c 100644 --- a/fs/super.c +++ b/fs/super.c @@ -77,8 +77,8 @@ static struct super_block *alloc_super(void) s->s_count = S_BIAS; atomic_set(&s->s_active, 1); sema_init(&s->s_vfs_rename_sem,1); - sema_init(&s->s_dquot.dqio_sem, 1); - sema_init(&s->s_dquot.dqonoff_sem, 1); + mutex_init(&s->s_dquot.dqio_mutex); + mutex_init(&s->s_dquot.dqonoff_mutex); init_rwsem(&s->s_dquot.dqptr_sem); init_waitqueue_head(&s->s_wait_unfrozen); s->s_maxbytes = MAX_NON_LFS; diff --git a/include/linux/quota.h b/include/linux/quota.h index f33aeb22c26a..8dc2d04a103f 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -38,6 +38,7 @@ #include #include #include +#include #define __DQUOT_VERSION__ "dquot_6.5.1" #define __DQUOT_NUM_VERSION__ 6*10000+5*100+1 @@ -215,7 +216,7 @@ struct dquot { struct list_head dq_inuse; /* List of all quotas */ struct list_head dq_free; /* Free list element */ struct list_head dq_dirty; /* List of dirty dquots */ - struct semaphore dq_lock; /* dquot IO lock */ + struct mutex dq_lock; /* dquot IO lock */ atomic_t dq_count; /* Use count */ wait_queue_head_t dq_wait_unused; /* Wait queue for dquot to become unused */ struct super_block *dq_sb; /* superblock this applies to */ @@ -285,8 +286,8 @@ struct quota_format_type { struct quota_info { unsigned int flags; /* Flags for diskquotas on this device */ - struct semaphore dqio_sem; /* lock device while I/O in progress */ - struct semaphore dqonoff_sem; /* Serialize quotaon & quotaoff */ + struct mutex dqio_mutex; /* lock device while I/O in progress */ + struct mutex dqonoff_mutex; /* Serialize quotaon & quotaoff */ struct rw_semaphore dqptr_sem; /* serialize ops using quota_info struct, pointers from inode to dquots */ struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */ struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */ -- cgit v1.2.3 From d4f9af9dac4ecb75818f909168f87b441cc95653 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 23 Mar 2006 03:00:30 -0800 Subject: [PATCH] sem2mutex: inotify Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Cc: John McCutchan Signed-off-by: Andrew Morton Acked-by: Robert Love Signed-off-by: Linus Torvalds --- fs/inode.c | 2 +- fs/inotify.c | 110 ++++++++++++++++++++++++++--------------------------- include/linux/fs.h | 2 +- 3 files changed, 57 insertions(+), 57 deletions(-) (limited to 'include') diff --git a/fs/inode.c b/fs/inode.c index d0be6159eb7f..603e93ef0c6f 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -206,7 +206,7 @@ void inode_init_once(struct inode *inode) i_size_ordered_init(inode); #ifdef CONFIG_INOTIFY INIT_LIST_HEAD(&inode->inotify_watches); - sema_init(&inode->inotify_sem, 1); + mutex_init(&inode->inotify_mutex); #endif } diff --git a/fs/inotify.c b/fs/inotify.c index 3041503bde02..60d9653d55b7 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -56,8 +56,8 @@ int inotify_max_queued_events; * dentry->d_lock (used to keep d_move() away from dentry->d_parent) * iprune_sem (synchronize shrink_icache_memory()) * inode_lock (protects the super_block->s_inodes list) - * inode->inotify_sem (protects inode->inotify_watches and watches->i_list) - * inotify_dev->sem (protects inotify_device and watches->d_list) + * inode->inotify_mutex (protects inode->inotify_watches and watches->i_list) + * inotify_dev->mutex (protects inotify_device and watches->d_list) */ /* @@ -79,12 +79,12 @@ int inotify_max_queued_events; /* * struct inotify_device - represents an inotify instance * - * This structure is protected by the semaphore 'sem'. + * This structure is protected by the mutex 'mutex'. */ struct inotify_device { wait_queue_head_t wq; /* wait queue for i/o */ struct idr idr; /* idr mapping wd -> watch */ - struct semaphore sem; /* protects this bad boy */ + struct mutex mutex; /* protects this bad boy */ struct list_head events; /* list of queued events */ struct list_head watches; /* list of watches */ atomic_t count; /* reference count */ @@ -101,7 +101,7 @@ struct inotify_device { * device. In read(), this list is walked and all events that can fit in the * buffer are returned. * - * Protected by dev->sem of the device in which we are queued. + * Protected by dev->mutex of the device in which we are queued. */ struct inotify_kernel_event { struct inotify_event event; /* the user-space event */ @@ -112,8 +112,8 @@ struct inotify_kernel_event { /* * struct inotify_watch - represents a watch request on a specific inode * - * d_list is protected by dev->sem of the associated watch->dev. - * i_list and mask are protected by inode->inotify_sem of the associated inode. + * d_list is protected by dev->mutex of the associated watch->dev. + * i_list and mask are protected by inode->inotify_mutex of the associated inode. * dev, inode, and wd are never written to once the watch is created. */ struct inotify_watch { @@ -261,7 +261,7 @@ static struct inotify_kernel_event * kernel_event(s32 wd, u32 mask, u32 cookie, /* * inotify_dev_get_event - return the next event in the given dev's queue * - * Caller must hold dev->sem. + * Caller must hold dev->mutex. */ static inline struct inotify_kernel_event * inotify_dev_get_event(struct inotify_device *dev) @@ -272,7 +272,7 @@ inotify_dev_get_event(struct inotify_device *dev) /* * inotify_dev_queue_event - add a new event to the given device * - * Caller must hold dev->sem. Can sleep (calls kernel_event()). + * Caller must hold dev->mutex. Can sleep (calls kernel_event()). */ static void inotify_dev_queue_event(struct inotify_device *dev, struct inotify_watch *watch, u32 mask, @@ -315,7 +315,7 @@ static void inotify_dev_queue_event(struct inotify_device *dev, /* * remove_kevent - cleans up and ultimately frees the given kevent * - * Caller must hold dev->sem. + * Caller must hold dev->mutex. */ static void remove_kevent(struct inotify_device *dev, struct inotify_kernel_event *kevent) @@ -332,7 +332,7 @@ static void remove_kevent(struct inotify_device *dev, /* * inotify_dev_event_dequeue - destroy an event on the given device * - * Caller must hold dev->sem. + * Caller must hold dev->mutex. */ static void inotify_dev_event_dequeue(struct inotify_device *dev) { @@ -346,7 +346,7 @@ static void inotify_dev_event_dequeue(struct inotify_device *dev) /* * inotify_dev_get_wd - returns the next WD for use by the given dev * - * Callers must hold dev->sem. This function can sleep. + * Callers must hold dev->mutex. This function can sleep. */ static int inotify_dev_get_wd(struct inotify_device *dev, struct inotify_watch *watch) @@ -383,7 +383,7 @@ static int find_inode(const char __user *dirname, struct nameidata *nd, /* * create_watch - creates a watch on the given device. * - * Callers must hold dev->sem. Calls inotify_dev_get_wd() so may sleep. + * Callers must hold dev->mutex. Calls inotify_dev_get_wd() so may sleep. * Both 'dev' and 'inode' (by way of nameidata) need to be pinned. */ static struct inotify_watch *create_watch(struct inotify_device *dev, @@ -434,7 +434,7 @@ static struct inotify_watch *create_watch(struct inotify_device *dev, /* * inotify_find_dev - find the watch associated with the given inode and dev * - * Callers must hold inode->inotify_sem. + * Callers must hold inode->inotify_mutex. */ static struct inotify_watch *inode_find_dev(struct inode *inode, struct inotify_device *dev) @@ -469,7 +469,7 @@ static void remove_watch_no_event(struct inotify_watch *watch, * the IN_IGNORED event to the given device signifying that the inode is no * longer watched. * - * Callers must hold both inode->inotify_sem and dev->sem. We drop a + * Callers must hold both inode->inotify_mutex and dev->mutex. We drop a * reference to the inode before returning. * * The inode is not iput() so as to remain atomic. If the inode needs to be @@ -507,21 +507,21 @@ void inotify_inode_queue_event(struct inode *inode, u32 mask, u32 cookie, if (!inotify_inode_watched(inode)) return; - down(&inode->inotify_sem); + mutex_lock(&inode->inotify_mutex); list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) { u32 watch_mask = watch->mask; if (watch_mask & mask) { struct inotify_device *dev = watch->dev; get_inotify_watch(watch); - down(&dev->sem); + mutex_lock(&dev->mutex); inotify_dev_queue_event(dev, watch, mask, cookie, name); if (watch_mask & IN_ONESHOT) remove_watch_no_event(watch, dev); - up(&dev->sem); + mutex_unlock(&dev->mutex); put_inotify_watch(watch); } } - up(&inode->inotify_sem); + mutex_unlock(&inode->inotify_mutex); } EXPORT_SYMBOL_GPL(inotify_inode_queue_event); @@ -626,16 +626,16 @@ void inotify_unmount_inodes(struct list_head *list) iput(need_iput_tmp); /* for each watch, send IN_UNMOUNT and then remove it */ - down(&inode->inotify_sem); + mutex_lock(&inode->inotify_mutex); watches = &inode->inotify_watches; list_for_each_entry_safe(watch, next_w, watches, i_list) { struct inotify_device *dev = watch->dev; - down(&dev->sem); + mutex_lock(&dev->mutex); inotify_dev_queue_event(dev, watch, IN_UNMOUNT,0,NULL); remove_watch(watch, dev); - up(&dev->sem); + mutex_unlock(&dev->mutex); } - up(&inode->inotify_sem); + mutex_unlock(&inode->inotify_mutex); iput(inode); spin_lock(&inode_lock); @@ -651,14 +651,14 @@ void inotify_inode_is_dead(struct inode *inode) { struct inotify_watch *watch, *next; - down(&inode->inotify_sem); + mutex_lock(&inode->inotify_mutex); list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) { struct inotify_device *dev = watch->dev; - down(&dev->sem); + mutex_lock(&dev->mutex); remove_watch(watch, dev); - up(&dev->sem); + mutex_unlock(&dev->mutex); } - up(&inode->inotify_sem); + mutex_unlock(&inode->inotify_mutex); } EXPORT_SYMBOL_GPL(inotify_inode_is_dead); @@ -670,10 +670,10 @@ static unsigned int inotify_poll(struct file *file, poll_table *wait) int ret = 0; poll_wait(file, &dev->wq, wait); - down(&dev->sem); + mutex_lock(&dev->mutex); if (!list_empty(&dev->events)) ret = POLLIN | POLLRDNORM; - up(&dev->sem); + mutex_unlock(&dev->mutex); return ret; } @@ -695,9 +695,9 @@ static ssize_t inotify_read(struct file *file, char __user *buf, prepare_to_wait(&dev->wq, &wait, TASK_INTERRUPTIBLE); - down(&dev->sem); + mutex_lock(&dev->mutex); events = !list_empty(&dev->events); - up(&dev->sem); + mutex_unlock(&dev->mutex); if (events) { ret = 0; break; @@ -720,7 +720,7 @@ static ssize_t inotify_read(struct file *file, char __user *buf, if (ret) return ret; - down(&dev->sem); + mutex_lock(&dev->mutex); while (1) { struct inotify_kernel_event *kevent; @@ -750,7 +750,7 @@ static ssize_t inotify_read(struct file *file, char __user *buf, remove_kevent(dev, kevent); } - up(&dev->sem); + mutex_unlock(&dev->mutex); return ret; } @@ -763,37 +763,37 @@ static int inotify_release(struct inode *ignored, struct file *file) * Destroy all of the watches on this device. Unfortunately, not very * pretty. We cannot do a simple iteration over the list, because we * do not know the inode until we iterate to the watch. But we need to - * hold inode->inotify_sem before dev->sem. The following works. + * hold inode->inotify_mutex before dev->mutex. The following works. */ while (1) { struct inotify_watch *watch; struct list_head *watches; struct inode *inode; - down(&dev->sem); + mutex_lock(&dev->mutex); watches = &dev->watches; if (list_empty(watches)) { - up(&dev->sem); + mutex_unlock(&dev->mutex); break; } watch = list_entry(watches->next, struct inotify_watch, d_list); get_inotify_watch(watch); - up(&dev->sem); + mutex_unlock(&dev->mutex); inode = watch->inode; - down(&inode->inotify_sem); - down(&dev->sem); + mutex_lock(&inode->inotify_mutex); + mutex_lock(&dev->mutex); remove_watch_no_event(watch, dev); - up(&dev->sem); - up(&inode->inotify_sem); + mutex_unlock(&dev->mutex); + mutex_unlock(&inode->inotify_mutex); put_inotify_watch(watch); } /* destroy all of the events on this device */ - down(&dev->sem); + mutex_lock(&dev->mutex); while (!list_empty(&dev->events)) inotify_dev_event_dequeue(dev); - up(&dev->sem); + mutex_unlock(&dev->mutex); /* free this device: the put matching the get in inotify_init() */ put_inotify_dev(dev); @@ -811,26 +811,26 @@ static int inotify_ignore(struct inotify_device *dev, s32 wd) struct inotify_watch *watch; struct inode *inode; - down(&dev->sem); + mutex_lock(&dev->mutex); watch = idr_find(&dev->idr, wd); if (unlikely(!watch)) { - up(&dev->sem); + mutex_unlock(&dev->mutex); return -EINVAL; } get_inotify_watch(watch); inode = watch->inode; - up(&dev->sem); + mutex_unlock(&dev->mutex); - down(&inode->inotify_sem); - down(&dev->sem); + mutex_lock(&inode->inotify_mutex); + mutex_lock(&dev->mutex); /* make sure that we did not race */ watch = idr_find(&dev->idr, wd); if (likely(watch)) remove_watch(watch, dev); - up(&dev->sem); - up(&inode->inotify_sem); + mutex_unlock(&dev->mutex); + mutex_unlock(&inode->inotify_mutex); put_inotify_watch(watch); return 0; @@ -905,7 +905,7 @@ asmlinkage long sys_inotify_init(void) INIT_LIST_HEAD(&dev->events); INIT_LIST_HEAD(&dev->watches); init_waitqueue_head(&dev->wq); - sema_init(&dev->sem, 1); + mutex_init(&dev->mutex); dev->event_count = 0; dev->queue_size = 0; dev->max_events = inotify_max_queued_events; @@ -960,8 +960,8 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) inode = nd.dentry->d_inode; dev = filp->private_data; - down(&inode->inotify_sem); - down(&dev->sem); + mutex_lock(&inode->inotify_mutex); + mutex_lock(&dev->mutex); if (mask & IN_MASK_ADD) mask_add = 1; @@ -998,8 +998,8 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) list_add(&watch->i_list, &inode->inotify_watches); ret = watch->wd; out: - up(&dev->sem); - up(&inode->inotify_sem); + mutex_unlock(&dev->mutex); + mutex_unlock(&inode->inotify_mutex); path_release(&nd); fput_and_out: fput_light(filp, fput_needed); diff --git a/include/linux/fs.h b/include/linux/fs.h index 009ac96053fe..9ed1f36b6d54 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -509,7 +509,7 @@ struct inode { #ifdef CONFIG_INOTIFY struct list_head inotify_watches; /* watches on this inode */ - struct semaphore inotify_sem; /* protects the watches list */ + struct mutex inotify_mutex; /* protects the watches list */ #endif unsigned long i_state; -- cgit v1.2.3 From 70522e121a521aa09bd0f4e62e1aa68708b798e1 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 23 Mar 2006 03:00:31 -0800 Subject: [PATCH] sem2mutex: tty Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Cc: Alan Cox Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/n_tty.c | 10 +++++----- drivers/char/tty_io.c | 50 +++++++++++++++++++++++++------------------------- drivers/char/vt.c | 14 +++++++------- include/linux/tty.h | 8 ++++---- kernel/exit.c | 4 ++-- kernel/sys.c | 4 ++-- 6 files changed, 45 insertions(+), 45 deletions(-) (limited to 'include') diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index ccad7ae94541..ede365d05387 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -132,7 +132,7 @@ static void put_tty_queue(unsigned char c, struct tty_struct *tty) * We test the TTY_THROTTLED bit first so that it always * indicates the current state. The decision about whether * it is worth allowing more input has been taken by the caller. - * Can sleep, may be called under the atomic_read semaphore but + * Can sleep, may be called under the atomic_read_lock mutex but * this is not guaranteed. */ @@ -1132,7 +1132,7 @@ static inline int input_available_p(struct tty_struct *tty, int amt) * buffer, and once to drain the space from the (physical) beginning of * the buffer to head pointer. * - * Called under the tty->atomic_read sem and with TTY_DONT_FLIP set + * Called under the tty->atomic_read_lock sem and with TTY_DONT_FLIP set * */ @@ -1262,11 +1262,11 @@ do_it_again: * Internal serialization of reads. */ if (file->f_flags & O_NONBLOCK) { - if (down_trylock(&tty->atomic_read)) + if (!mutex_trylock(&tty->atomic_read_lock)) return -EAGAIN; } else { - if (down_interruptible(&tty->atomic_read)) + if (mutex_lock_interruptible(&tty->atomic_read_lock)) return -ERESTARTSYS; } @@ -1393,7 +1393,7 @@ do_it_again: timeout = time; } clear_bit(TTY_DONT_FLIP, &tty->flags); - up(&tty->atomic_read); + mutex_unlock(&tty->atomic_read_lock); remove_wait_queue(&tty->read_wait, &wait); if (!waitqueue_active(&tty->read_wait)) diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 53d3d066554e..76592ee1fb38 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -130,7 +130,7 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */ /* Semaphore to protect creating and releasing a tty. This is shared with vt.c for deeply disgusting hack reasons */ -DECLARE_MUTEX(tty_sem); +DEFINE_MUTEX(tty_mutex); #ifdef CONFIG_UNIX98_PTYS extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */ @@ -1188,11 +1188,11 @@ void disassociate_ctty(int on_exit) lock_kernel(); - down(&tty_sem); + mutex_lock(&tty_mutex); tty = current->signal->tty; if (tty) { tty_pgrp = tty->pgrp; - up(&tty_sem); + mutex_unlock(&tty_mutex); if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) tty_vhangup(tty); } else { @@ -1200,7 +1200,7 @@ void disassociate_ctty(int on_exit) kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit); kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit); } - up(&tty_sem); + mutex_unlock(&tty_mutex); unlock_kernel(); return; } @@ -1211,7 +1211,7 @@ void disassociate_ctty(int on_exit) } /* Must lock changes to tty_old_pgrp */ - down(&tty_sem); + mutex_lock(&tty_mutex); current->signal->tty_old_pgrp = 0; tty->session = 0; tty->pgrp = -1; @@ -1222,7 +1222,7 @@ void disassociate_ctty(int on_exit) p->signal->tty = NULL; } while_each_task_pid(current->signal->session, PIDTYPE_SID, p); read_unlock(&tasklist_lock); - up(&tty_sem); + mutex_unlock(&tty_mutex); unlock_kernel(); } @@ -1306,7 +1306,7 @@ static inline ssize_t do_tty_write( ssize_t ret = 0, written = 0; unsigned int chunk; - if (down_interruptible(&tty->atomic_write)) { + if (mutex_lock_interruptible(&tty->atomic_write_lock)) { return -ERESTARTSYS; } @@ -1329,7 +1329,7 @@ static inline ssize_t do_tty_write( if (count < chunk) chunk = count; - /* write_buf/write_cnt is protected by the atomic_write semaphore */ + /* write_buf/write_cnt is protected by the atomic_write_lock mutex */ if (tty->write_cnt < chunk) { unsigned char *buf; @@ -1338,7 +1338,7 @@ static inline ssize_t do_tty_write( buf = kmalloc(chunk, GFP_KERNEL); if (!buf) { - up(&tty->atomic_write); + mutex_unlock(&tty->atomic_write_lock); return -ENOMEM; } kfree(tty->write_buf); @@ -1374,7 +1374,7 @@ static inline ssize_t do_tty_write( inode->i_mtime = current_fs_time(inode->i_sb); ret = written; } - up(&tty->atomic_write); + mutex_unlock(&tty->atomic_write_lock); return ret; } @@ -1442,8 +1442,8 @@ static inline void tty_line_name(struct tty_driver *driver, int index, char *p) /* * WSH 06/09/97: Rewritten to remove races and properly clean up after a - * failed open. The new code protects the open with a semaphore, so it's - * really quite straightforward. The semaphore locking can probably be + * failed open. The new code protects the open with a mutex, so it's + * really quite straightforward. The mutex locking can probably be * relaxed for the (most common) case of reopening a tty. */ static int init_dev(struct tty_driver *driver, int idx, @@ -1640,7 +1640,7 @@ fast_track: success: *ret_tty = tty; - /* All paths come through here to release the semaphore */ + /* All paths come through here to release the mutex */ end_init: return retval; @@ -1837,7 +1837,7 @@ static void release_dev(struct file * filp) /* Guard against races with tty->count changes elsewhere and opens on /dev/tty */ - down(&tty_sem); + mutex_lock(&tty_mutex); tty_closing = tty->count <= 1; o_tty_closing = o_tty && (o_tty->count <= (pty_master ? 1 : 0)); @@ -1868,7 +1868,7 @@ static void release_dev(struct file * filp) printk(KERN_WARNING "release_dev: %s: read/write wait queue " "active!\n", tty_name(tty, buf)); - up(&tty_sem); + mutex_unlock(&tty_mutex); schedule(); } @@ -1934,7 +1934,7 @@ static void release_dev(struct file * filp) read_unlock(&tasklist_lock); } - up(&tty_sem); + mutex_unlock(&tty_mutex); /* check whether both sides are closing ... */ if (!tty_closing || (o_tty && !o_tty_closing)) @@ -2040,11 +2040,11 @@ retry_open: index = -1; retval = 0; - down(&tty_sem); + mutex_lock(&tty_mutex); if (device == MKDEV(TTYAUX_MAJOR,0)) { if (!current->signal->tty) { - up(&tty_sem); + mutex_unlock(&tty_mutex); return -ENXIO; } driver = current->signal->tty->driver; @@ -2070,18 +2070,18 @@ retry_open: noctty = 1; goto got_driver; } - up(&tty_sem); + mutex_unlock(&tty_mutex); return -ENODEV; } driver = get_tty_driver(device, &index); if (!driver) { - up(&tty_sem); + mutex_unlock(&tty_mutex); return -ENODEV; } got_driver: retval = init_dev(driver, index, &tty); - up(&tty_sem); + mutex_unlock(&tty_mutex); if (retval) return retval; @@ -2167,9 +2167,9 @@ static int ptmx_open(struct inode * inode, struct file * filp) } up(&allocated_ptys_lock); - down(&tty_sem); + mutex_lock(&tty_mutex); retval = init_dev(ptm_driver, index, &tty); - up(&tty_sem); + mutex_unlock(&tty_mutex); if (retval) goto out; @@ -2915,8 +2915,8 @@ static void initialize_tty_struct(struct tty_struct *tty) init_waitqueue_head(&tty->write_wait); init_waitqueue_head(&tty->read_wait); INIT_WORK(&tty->hangup_work, do_tty_hangup, tty); - sema_init(&tty->atomic_read, 1); - sema_init(&tty->atomic_write, 1); + mutex_init(&tty->atomic_read_lock); + mutex_init(&tty->atomic_write_lock); spin_lock_init(&tty->read_lock); INIT_LIST_HEAD(&tty->tty_files); INIT_WORK(&tty->SAK_work, NULL, NULL); diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 86b31b87eb85..ca4844c527da 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -2489,7 +2489,7 @@ static int con_open(struct tty_struct *tty, struct file *filp) } /* - * We take tty_sem in here to prevent another thread from coming in via init_dev + * We take tty_mutex in here to prevent another thread from coming in via init_dev * and taking a ref against the tty while we're in the process of forgetting * about it and cleaning things up. * @@ -2497,7 +2497,7 @@ static int con_open(struct tty_struct *tty, struct file *filp) */ static void con_close(struct tty_struct *tty, struct file *filp) { - down(&tty_sem); + mutex_lock(&tty_mutex); acquire_console_sem(); if (tty && tty->count == 1) { struct vc_data *vc = tty->driver_data; @@ -2507,15 +2507,15 @@ static void con_close(struct tty_struct *tty, struct file *filp) tty->driver_data = NULL; release_console_sem(); vcs_remove_devfs(tty); - up(&tty_sem); + mutex_unlock(&tty_mutex); /* - * tty_sem is released, but we still hold BKL, so there is + * tty_mutex is released, but we still hold BKL, so there is * still exclusion against init_dev() */ return; } release_console_sem(); - up(&tty_sem); + mutex_unlock(&tty_mutex); } static void vc_init(struct vc_data *vc, unsigned int rows, @@ -2869,9 +2869,9 @@ void unblank_screen(void) } /* - * We defer the timer blanking to work queue so it can take the console semaphore + * We defer the timer blanking to work queue so it can take the console mutex * (console operations can still happen at irq time, but only from printk which - * has the console semaphore. Not perfect yet, but better than no locking + * has the console mutex. Not perfect yet, but better than no locking */ static void blank_screen_t(unsigned long dummy) { diff --git a/include/linux/tty.h b/include/linux/tty.h index f45cd74e6f24..f13f49afe198 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -231,8 +232,8 @@ struct tty_struct { int canon_data; unsigned long canon_head; unsigned int canon_column; - struct semaphore atomic_read; - struct semaphore atomic_write; + struct mutex atomic_read_lock; + struct mutex atomic_write_lock; unsigned char *write_buf; int write_cnt; spinlock_t read_lock; @@ -319,8 +320,7 @@ extern void tty_ldisc_put(int); extern void tty_wakeup(struct tty_struct *tty); extern void tty_ldisc_flush(struct tty_struct *tty); -struct semaphore; -extern struct semaphore tty_sem; +extern struct mutex tty_mutex; /* n_tty.c */ extern struct tty_ldisc tty_ldisc_N_TTY; diff --git a/kernel/exit.c b/kernel/exit.c index d1e8d500a7e1..8037405e136e 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -345,9 +345,9 @@ void daemonize(const char *name, ...) exit_mm(current); set_special_pids(1, 1); - down(&tty_sem); + mutex_lock(&tty_mutex); current->signal->tty = NULL; - up(&tty_sem); + mutex_unlock(&tty_mutex); /* Block and flush all signals */ sigfillset(&blocked); diff --git a/kernel/sys.c b/kernel/sys.c index 4941b9b14b97..c0fcad9f826c 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1227,7 +1227,7 @@ asmlinkage long sys_setsid(void) struct pid *pid; int err = -EPERM; - down(&tty_sem); + mutex_lock(&tty_mutex); write_lock_irq(&tasklist_lock); pid = find_pid(PIDTYPE_PGID, group_leader->pid); @@ -1241,7 +1241,7 @@ asmlinkage long sys_setsid(void) err = process_group(group_leader); out: write_unlock_irq(&tasklist_lock); - up(&tty_sem); + mutex_unlock(&tty_mutex); return err; } -- cgit v1.2.3 From a11f3a0574a5734db3e5de38922430d005d35118 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Thu, 23 Mar 2006 03:00:33 -0800 Subject: [PATCH] sem2mutex: vfs_rename_mutex Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Cc: Al Viro Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/cifs/dir.c | 8 ++++---- fs/cifs/fcntl.c | 4 ++-- fs/cifs/file.c | 4 ++-- fs/cifs/inode.c | 16 ++++++++-------- fs/cifs/link.c | 16 ++++++++-------- fs/cifs/readdir.c | 4 ++-- fs/cifs/xattr.c | 16 ++++++++-------- fs/namei.c | 12 ++++++------ fs/super.c | 2 +- include/linux/fs.h | 2 +- 10 files changed, 42 insertions(+), 42 deletions(-) (limited to 'include') diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index fed55e3c53df..632561dd9c50 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -138,9 +138,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; - down(&direntry->d_sb->s_vfs_rename_sem); + mutex_lock(&direntry->d_sb->s_vfs_rename_mutex); full_path = build_path_from_dentry(direntry); - up(&direntry->d_sb->s_vfs_rename_sem); + mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex); if(full_path == NULL) { FreeXid(xid); return -ENOMEM; @@ -317,9 +317,9 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; - down(&direntry->d_sb->s_vfs_rename_sem); + mutex_lock(&direntry->d_sb->s_vfs_rename_mutex); full_path = build_path_from_dentry(direntry); - up(&direntry->d_sb->s_vfs_rename_sem); + mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex); if(full_path == NULL) rc = -ENOMEM; else if (pTcon->ses->capabilities & CAP_UNIX) { diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c index a7a47bb36bf3..ec4dfe9bf5ef 100644 --- a/fs/cifs/fcntl.c +++ b/fs/cifs/fcntl.c @@ -86,9 +86,9 @@ int cifs_dir_notify(struct file * file, unsigned long arg) cifs_sb = CIFS_SB(file->f_dentry->d_sb); pTcon = cifs_sb->tcon; - down(&file->f_dentry->d_sb->s_vfs_rename_sem); + mutex_lock(&file->f_dentry->d_sb->s_vfs_rename_mutex); full_path = build_path_from_dentry(file->f_dentry); - up(&file->f_dentry->d_sb->s_vfs_rename_sem); + mutex_unlock(&file->f_dentry->d_sb->s_vfs_rename_mutex); if(full_path == NULL) { rc = -ENOMEM; diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 675bd2568297..165d67426381 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -203,9 +203,9 @@ int cifs_open(struct inode *inode, struct file *file) } } - down(&inode->i_sb->s_vfs_rename_sem); + mutex_lock(&inode->i_sb->s_vfs_rename_mutex); full_path = build_path_from_dentry(file->f_dentry); - up(&inode->i_sb->s_vfs_rename_sem); + mutex_unlock(&inode->i_sb->s_vfs_rename_mutex); if (full_path == NULL) { FreeXid(xid); return -ENOMEM; diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 59359911f481..ff93a9f81d1c 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -574,9 +574,9 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) /* Unlink can be called from rename so we can not grab the sem here since we deadlock otherwise */ -/* down(&direntry->d_sb->s_vfs_rename_sem);*/ +/* mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);*/ full_path = build_path_from_dentry(direntry); -/* up(&direntry->d_sb->s_vfs_rename_sem);*/ +/* mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);*/ if (full_path == NULL) { FreeXid(xid); return -ENOMEM; @@ -718,9 +718,9 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; - down(&inode->i_sb->s_vfs_rename_sem); + mutex_lock(&inode->i_sb->s_vfs_rename_mutex); full_path = build_path_from_dentry(direntry); - up(&inode->i_sb->s_vfs_rename_sem); + mutex_unlock(&inode->i_sb->s_vfs_rename_mutex); if (full_path == NULL) { FreeXid(xid); return -ENOMEM; @@ -803,9 +803,9 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; - down(&inode->i_sb->s_vfs_rename_sem); + mutex_lock(&inode->i_sb->s_vfs_rename_mutex); full_path = build_path_from_dentry(direntry); - up(&inode->i_sb->s_vfs_rename_sem); + mutex_unlock(&inode->i_sb->s_vfs_rename_mutex); if (full_path == NULL) { FreeXid(xid); return -ENOMEM; @@ -1137,9 +1137,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) rc = 0; } - down(&direntry->d_sb->s_vfs_rename_sem); + mutex_lock(&direntry->d_sb->s_vfs_rename_mutex); full_path = build_path_from_dentry(direntry); - up(&direntry->d_sb->s_vfs_rename_sem); + mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex); if (full_path == NULL) { FreeXid(xid); return -ENOMEM; diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 0f99aae33162..8d0da7c87c7b 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -48,10 +48,10 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, /* No need to check for cross device links since server will do that BB note DFS case in future though (when we may have to check) */ - down(&inode->i_sb->s_vfs_rename_sem); + mutex_lock(&inode->i_sb->s_vfs_rename_mutex); fromName = build_path_from_dentry(old_file); toName = build_path_from_dentry(direntry); - up(&inode->i_sb->s_vfs_rename_sem); + mutex_unlock(&inode->i_sb->s_vfs_rename_mutex); if((fromName == NULL) || (toName == NULL)) { rc = -ENOMEM; goto cifs_hl_exit; @@ -103,9 +103,9 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) xid = GetXid(); - down(&direntry->d_sb->s_vfs_rename_sem); + mutex_lock(&direntry->d_sb->s_vfs_rename_mutex); full_path = build_path_from_dentry(direntry); - up(&direntry->d_sb->s_vfs_rename_sem); + mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex); if (!full_path) goto out_no_free; @@ -164,9 +164,9 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; - down(&inode->i_sb->s_vfs_rename_sem); + mutex_lock(&inode->i_sb->s_vfs_rename_mutex); full_path = build_path_from_dentry(direntry); - up(&inode->i_sb->s_vfs_rename_sem); + mutex_unlock(&inode->i_sb->s_vfs_rename_mutex); if(full_path == NULL) { FreeXid(xid); @@ -232,9 +232,9 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) /* BB would it be safe against deadlock to grab this sem even though rename itself grabs the sem and calls lookup? */ -/* down(&inode->i_sb->s_vfs_rename_sem);*/ +/* mutex_lock(&inode->i_sb->s_vfs_rename_mutex);*/ full_path = build_path_from_dentry(direntry); -/* up(&inode->i_sb->s_vfs_rename_sem);*/ +/* mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/ if(full_path == NULL) { FreeXid(xid); diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 288cc048d37f..edb3b6eb34bc 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -404,9 +404,9 @@ static int initiate_cifs_search(const int xid, struct file *file) if(pTcon == NULL) return -EINVAL; - down(&file->f_dentry->d_sb->s_vfs_rename_sem); + mutex_lock(&file->f_dentry->d_sb->s_vfs_rename_mutex); full_path = build_path_from_dentry(file->f_dentry); - up(&file->f_dentry->d_sb->s_vfs_rename_sem); + mutex_unlock(&file->f_dentry->d_sb->s_vfs_rename_mutex); if(full_path == NULL) { return -ENOMEM; diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 777e3363c2a4..3938444d87b2 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -62,9 +62,9 @@ int cifs_removexattr(struct dentry * direntry, const char * ea_name) cifs_sb = CIFS_SB(sb); pTcon = cifs_sb->tcon; - down(&sb->s_vfs_rename_sem); + mutex_lock(&sb->s_vfs_rename_mutex); full_path = build_path_from_dentry(direntry); - up(&sb->s_vfs_rename_sem); + mutex_unlock(&sb->s_vfs_rename_mutex); if(full_path == NULL) { FreeXid(xid); return -ENOMEM; @@ -116,9 +116,9 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name, cifs_sb = CIFS_SB(sb); pTcon = cifs_sb->tcon; - down(&sb->s_vfs_rename_sem); + mutex_lock(&sb->s_vfs_rename_mutex); full_path = build_path_from_dentry(direntry); - up(&sb->s_vfs_rename_sem); + mutex_unlock(&sb->s_vfs_rename_mutex); if(full_path == NULL) { FreeXid(xid); return -ENOMEM; @@ -223,9 +223,9 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, cifs_sb = CIFS_SB(sb); pTcon = cifs_sb->tcon; - down(&sb->s_vfs_rename_sem); + mutex_lock(&sb->s_vfs_rename_mutex); full_path = build_path_from_dentry(direntry); - up(&sb->s_vfs_rename_sem); + mutex_unlock(&sb->s_vfs_rename_mutex); if(full_path == NULL) { FreeXid(xid); return -ENOMEM; @@ -341,9 +341,9 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size) cifs_sb = CIFS_SB(sb); pTcon = cifs_sb->tcon; - down(&sb->s_vfs_rename_sem); + mutex_lock(&sb->s_vfs_rename_mutex); full_path = build_path_from_dentry(direntry); - up(&sb->s_vfs_rename_sem); + mutex_unlock(&sb->s_vfs_rename_mutex); if(full_path == NULL) { FreeXid(xid); return -ENOMEM; diff --git a/fs/namei.c b/fs/namei.c index 8dc2b038d5d9..c72b940797fc 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -104,7 +104,7 @@ */ /* * [Sep 2001 AV] Single-semaphore locking scheme (kudos to David Holland) - * implemented. Let's see if raised priority of ->s_vfs_rename_sem gives + * implemented. Let's see if raised priority of ->s_vfs_rename_mutex gives * any extra contention... */ @@ -1422,7 +1422,7 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2) return NULL; } - down(&p1->d_inode->i_sb->s_vfs_rename_sem); + mutex_lock(&p1->d_inode->i_sb->s_vfs_rename_mutex); for (p = p1; p->d_parent != p; p = p->d_parent) { if (p->d_parent == p2) { @@ -1450,7 +1450,7 @@ void unlock_rename(struct dentry *p1, struct dentry *p2) mutex_unlock(&p1->d_inode->i_mutex); if (p1 != p2) { mutex_unlock(&p2->d_inode->i_mutex); - up(&p1->d_inode->i_sb->s_vfs_rename_sem); + mutex_unlock(&p1->d_inode->i_sb->s_vfs_rename_mutex); } } @@ -2277,17 +2277,17 @@ asmlinkage long sys_link(const char __user *oldname, const char __user *newname) * a) we can get into loop creation. Check is done in is_subdir(). * b) race potential - two innocent renames can create a loop together. * That's where 4.4 screws up. Current fix: serialization on - * sb->s_vfs_rename_sem. We might be more accurate, but that's another + * sb->s_vfs_rename_mutex. We might be more accurate, but that's another * story. * c) we have to lock _three_ objects - parents and victim (if it exists). * And that - after we got ->i_mutex on parents (until then we don't know * whether the target exists). Solution: try to be smart with locking * order for inodes. We rely on the fact that tree topology may change - * only under ->s_vfs_rename_sem _and_ that parent of the object we + * only under ->s_vfs_rename_mutex _and_ that parent of the object we * move will be locked. Thus we can rank directories by the tree * (ancestors first) and rank all non-directories after them. * That works since everybody except rename does "lock parent, lookup, - * lock child" and rename is under ->s_vfs_rename_sem. + * lock child" and rename is under ->s_vfs_rename_mutex. * HOWEVER, it relies on the assumption that any object with ->lookup() * has no more than 1 dentry. If "hybrid" objects will ever appear, * we'd better make sure that there's no link(2) for them. diff --git a/fs/super.c b/fs/super.c index 9cc6545dfa4c..425861cb1caa 100644 --- a/fs/super.c +++ b/fs/super.c @@ -76,7 +76,7 @@ static struct super_block *alloc_super(void) down_write(&s->s_umount); s->s_count = S_BIAS; atomic_set(&s->s_active, 1); - sema_init(&s->s_vfs_rename_sem,1); + mutex_init(&s->s_vfs_rename_mutex); mutex_init(&s->s_dquot.dqio_mutex); mutex_init(&s->s_dquot.dqonoff_mutex); init_rwsem(&s->s_dquot.dqptr_sem); diff --git a/include/linux/fs.h b/include/linux/fs.h index 9ed1f36b6d54..0f71ee730127 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -847,7 +847,7 @@ struct super_block { * The next field is for VFS *only*. No filesystems have any business * even looking at it. You had been warned. */ - struct semaphore s_vfs_rename_sem; /* Kludge */ + struct mutex s_vfs_rename_mutex; /* Kludge */ /* Granuality of c/m/atime in ns. Cannot be worse than a second */ -- cgit v1.2.3 From f24075bd0c1cd1cc2cf86d394f960aa0401de573 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 23 Mar 2006 03:00:34 -0800 Subject: [PATCH] sem2mutex: iprune Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/inode.c | 16 ++++++++-------- fs/inotify.c | 6 +++--- include/linux/fs.h | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/fs/inode.c b/fs/inode.c index 603e93ef0c6f..25967b67903d 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -84,14 +84,14 @@ static struct hlist_head *inode_hashtable; DEFINE_SPINLOCK(inode_lock); /* - * iprune_sem provides exclusion between the kswapd or try_to_free_pages + * iprune_mutex provides exclusion between the kswapd or try_to_free_pages * icache shrinking path, and the umount path. Without this exclusion, * by the time prune_icache calls iput for the inode whose pages it has * been invalidating, or by the time it calls clear_inode & destroy_inode * from its final dispose_list, the struct super_block they refer to * (for inode->i_sb->s_op) may already have been freed and reused. */ -DECLARE_MUTEX(iprune_sem); +DEFINE_MUTEX(iprune_mutex); /* * Statistics gathering.. @@ -319,7 +319,7 @@ static int invalidate_list(struct list_head *head, struct list_head *dispose) /* * We can reschedule here without worrying about the list's * consistency because the per-sb list of inodes must not - * change during umount anymore, and because iprune_sem keeps + * change during umount anymore, and because iprune_mutex keeps * shrink_icache_memory() away. */ cond_resched_lock(&inode_lock); @@ -355,14 +355,14 @@ int invalidate_inodes(struct super_block * sb) int busy; LIST_HEAD(throw_away); - down(&iprune_sem); + mutex_lock(&iprune_mutex); spin_lock(&inode_lock); inotify_unmount_inodes(&sb->s_inodes); busy = invalidate_list(&sb->s_inodes, &throw_away); spin_unlock(&inode_lock); dispose_list(&throw_away); - up(&iprune_sem); + mutex_unlock(&iprune_mutex); return busy; } @@ -377,7 +377,7 @@ int __invalidate_device(struct block_device *bdev) if (sb) { /* * no need to lock the super, get_super holds the - * read semaphore so the filesystem cannot go away + * read mutex so the filesystem cannot go away * under us (->put_super runs with the write lock * hold). */ @@ -423,7 +423,7 @@ static void prune_icache(int nr_to_scan) int nr_scanned; unsigned long reap = 0; - down(&iprune_sem); + mutex_lock(&iprune_mutex); spin_lock(&inode_lock); for (nr_scanned = 0; nr_scanned < nr_to_scan; nr_scanned++) { struct inode *inode; @@ -459,7 +459,7 @@ static void prune_icache(int nr_to_scan) spin_unlock(&inode_lock); dispose_list(&freeable); - up(&iprune_sem); + mutex_unlock(&iprune_mutex); if (current_is_kswapd()) mod_page_state(kswapd_inodesteal, reap); diff --git a/fs/inotify.c b/fs/inotify.c index 60d9653d55b7..0ee39ef591c6 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -54,7 +54,7 @@ int inotify_max_queued_events; * Lock ordering: * * dentry->d_lock (used to keep d_move() away from dentry->d_parent) - * iprune_sem (synchronize shrink_icache_memory()) + * iprune_mutex (synchronize shrink_icache_memory()) * inode_lock (protects the super_block->s_inodes list) * inode->inotify_mutex (protects inode->inotify_watches and watches->i_list) * inotify_dev->mutex (protects inotify_device and watches->d_list) @@ -569,7 +569,7 @@ EXPORT_SYMBOL_GPL(inotify_get_cookie); * @list: list of inodes being unmounted (sb->s_inodes) * * Called with inode_lock held, protecting the unmounting super block's list - * of inodes, and with iprune_sem held, keeping shrink_icache_memory() at bay. + * of inodes, and with iprune_mutex held, keeping shrink_icache_memory() at bay. * We temporarily drop inode_lock, however, and CAN block. */ void inotify_unmount_inodes(struct list_head *list) @@ -618,7 +618,7 @@ void inotify_unmount_inodes(struct list_head *list) * We can safely drop inode_lock here because we hold * references on both inode and next_i. Also no new inodes * will be added since the umount has begun. Finally, - * iprune_sem keeps shrink_icache_memory() away. + * iprune_mutex keeps shrink_icache_memory() away. */ spin_unlock(&inode_lock); diff --git a/include/linux/fs.h b/include/linux/fs.h index 0f71ee730127..8fd8d9b90b00 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1534,7 +1534,7 @@ extern void destroy_inode(struct inode *); extern struct inode *new_inode(struct super_block *); extern int remove_suid(struct dentry *); extern void remove_dquot_ref(struct super_block *, int, struct list_head *); -extern struct semaphore iprune_sem; +extern struct mutex iprune_mutex; extern void __insert_inode_hash(struct inode *, unsigned long hashval); extern void remove_inode_hash(struct inode *); -- cgit v1.2.3 From 2c68ee754c40099c59828e59618a54726f76126a Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Thu, 23 Mar 2006 03:00:35 -0800 Subject: [PATCH] sem2mutex: jbd, j_checkpoint_mutex Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/jbd/checkpoint.c | 4 ++-- fs/jbd/journal.c | 4 ++-- fs/jbd/transaction.c | 4 ++-- include/linux/jbd.h | 7 ++++--- 4 files changed, 10 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c index 543ed543d1e5..3f5102b069db 100644 --- a/fs/jbd/checkpoint.c +++ b/fs/jbd/checkpoint.c @@ -85,7 +85,7 @@ void __log_wait_for_space(journal_t *journal) if (journal->j_flags & JFS_ABORT) return; spin_unlock(&journal->j_state_lock); - down(&journal->j_checkpoint_sem); + mutex_lock(&journal->j_checkpoint_mutex); /* * Test again, another process may have checkpointed while we @@ -98,7 +98,7 @@ void __log_wait_for_space(journal_t *journal) log_do_checkpoint(journal); spin_lock(&journal->j_state_lock); } - up(&journal->j_checkpoint_sem); + mutex_unlock(&journal->j_checkpoint_mutex); } } diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index e4b516ac4989..95a628d8cac8 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c @@ -659,8 +659,8 @@ static journal_t * journal_init_common (void) init_waitqueue_head(&journal->j_wait_checkpoint); init_waitqueue_head(&journal->j_wait_commit); init_waitqueue_head(&journal->j_wait_updates); - init_MUTEX(&journal->j_barrier); - init_MUTEX(&journal->j_checkpoint_sem); + mutex_init(&journal->j_barrier); + mutex_init(&journal->j_checkpoint_mutex); spin_lock_init(&journal->j_revoke_lock); spin_lock_init(&journal->j_list_lock); spin_lock_init(&journal->j_state_lock); diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index ca917973c2c0..5fc40888f4cf 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -455,7 +455,7 @@ void journal_lock_updates(journal_t *journal) * to make sure that we serialise special journal-locked operations * too. */ - down(&journal->j_barrier); + mutex_lock(&journal->j_barrier); } /** @@ -470,7 +470,7 @@ void journal_unlock_updates (journal_t *journal) { J_ASSERT(journal->j_barrier_count != 0); - up(&journal->j_barrier); + mutex_unlock(&journal->j_barrier); spin_lock(&journal->j_state_lock); --journal->j_barrier_count; spin_unlock(&journal->j_state_lock); diff --git a/include/linux/jbd.h b/include/linux/jbd.h index 41ee79962bb2..2ccbfb6340ba 100644 --- a/include/linux/jbd.h +++ b/include/linux/jbd.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #endif @@ -575,7 +576,7 @@ struct transaction_s * @j_wait_checkpoint: Wait queue to trigger checkpointing * @j_wait_commit: Wait queue to trigger commit * @j_wait_updates: Wait queue to wait for updates to complete - * @j_checkpoint_sem: Semaphore for locking against concurrent checkpoints + * @j_checkpoint_mutex: Mutex for locking against concurrent checkpoints * @j_head: Journal head - identifies the first unused block in the journal * @j_tail: Journal tail - identifies the oldest still-used block in the * journal. @@ -645,7 +646,7 @@ struct journal_s int j_barrier_count; /* The barrier lock itself */ - struct semaphore j_barrier; + struct mutex j_barrier; /* * Transactions: The current running transaction... @@ -687,7 +688,7 @@ struct journal_s wait_queue_head_t j_wait_updates; /* Semaphore for locking against concurrent checkpoints */ - struct semaphore j_checkpoint_sem; + struct mutex j_checkpoint_mutex; /* * Journal head: identifies the first unused block in the journal. -- cgit v1.2.3 From 7a7d1cf95408863a657035701606b13644c9f55e Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 23 Mar 2006 03:00:35 -0800 Subject: [PATCH] sem2mutex: kprobes Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Acked-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/kprobes.c | 4 ++-- arch/powerpc/kernel/kprobes.c | 4 ++-- arch/x86_64/kernel/kprobes.c | 4 ++-- include/linux/kprobes.h | 3 ++- kernel/kprobes.c | 14 +++++++------- 5 files changed, 15 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index 694a13997637..7a59050242a7 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c @@ -84,9 +84,9 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) void __kprobes arch_remove_kprobe(struct kprobe *p) { - down(&kprobe_mutex); + mutex_lock(&kprobe_mutex); free_insn_slot(p->ainsn.insn); - up(&kprobe_mutex); + mutex_unlock(&kprobe_mutex); } static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb) diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 258039fb3016..cb1fe5878e8b 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -81,9 +81,9 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) void __kprobes arch_remove_kprobe(struct kprobe *p) { - down(&kprobe_mutex); + mutex_lock(&kprobe_mutex); free_insn_slot(p->ainsn.insn); - up(&kprobe_mutex); + mutex_unlock(&kprobe_mutex); } static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c index 8b866a8572cf..14f0ced613b6 100644 --- a/arch/x86_64/kernel/kprobes.c +++ b/arch/x86_64/kernel/kprobes.c @@ -222,9 +222,9 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) void __kprobes arch_remove_kprobe(struct kprobe *p) { - down(&kprobe_mutex); + mutex_lock(&kprobe_mutex); free_insn_slot(p->ainsn.insn); - up(&kprobe_mutex); + mutex_unlock(&kprobe_mutex); } static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb) diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 669756bc20a2..778adc0fa640 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -36,6 +36,7 @@ #include #include #include +#include #ifdef CONFIG_KPROBES #include @@ -152,7 +153,7 @@ struct kretprobe_instance { }; extern spinlock_t kretprobe_lock; -extern struct semaphore kprobe_mutex; +extern struct mutex kprobe_mutex; extern int arch_prepare_kprobe(struct kprobe *p); extern void arch_arm_kprobe(struct kprobe *p); extern void arch_disarm_kprobe(struct kprobe *p); diff --git a/kernel/kprobes.c b/kernel/kprobes.c index fef1af8a73ce..1fb9f753ef60 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -48,7 +48,7 @@ static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE]; static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE]; -DECLARE_MUTEX(kprobe_mutex); /* Protects kprobe_table */ +DEFINE_MUTEX(kprobe_mutex); /* Protects kprobe_table */ DEFINE_SPINLOCK(kretprobe_lock); /* Protects kretprobe_inst_table */ static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; @@ -460,7 +460,7 @@ static int __kprobes __register_kprobe(struct kprobe *p, } p->nmissed = 0; - down(&kprobe_mutex); + mutex_lock(&kprobe_mutex); old_p = get_kprobe(p->addr); if (old_p) { ret = register_aggr_kprobe(old_p, p); @@ -477,7 +477,7 @@ static int __kprobes __register_kprobe(struct kprobe *p, arch_arm_kprobe(p); out: - up(&kprobe_mutex); + mutex_unlock(&kprobe_mutex); if (ret && probed_mod) module_put(probed_mod); @@ -496,10 +496,10 @@ void __kprobes unregister_kprobe(struct kprobe *p) struct kprobe *old_p, *list_p; int cleanup_p; - down(&kprobe_mutex); + mutex_lock(&kprobe_mutex); old_p = get_kprobe(p->addr); if (unlikely(!old_p)) { - up(&kprobe_mutex); + mutex_unlock(&kprobe_mutex); return; } if (p != old_p) { @@ -507,7 +507,7 @@ void __kprobes unregister_kprobe(struct kprobe *p) if (list_p == p) /* kprobe p is a valid probe */ goto valid_p; - up(&kprobe_mutex); + mutex_unlock(&kprobe_mutex); return; } valid_p: @@ -523,7 +523,7 @@ valid_p: cleanup_p = 0; } - up(&kprobe_mutex); + mutex_unlock(&kprobe_mutex); synchronize_sched(); if (p->mod_refcounted && -- cgit v1.2.3 From 0ac1759abc69fb62438c30a7e422f628a1120d67 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 23 Mar 2006 03:00:37 -0800 Subject: [PATCH] sem2mutex: fs/seq_file.c Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/seq_file.c | 10 +++++----- include/linux/seq_file.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/fs/seq_file.c b/fs/seq_file.c index 7c40570b71dc..555b9ac04c25 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -37,7 +37,7 @@ int seq_open(struct file *file, struct seq_operations *op) file->private_data = p; } memset(p, 0, sizeof(*p)); - sema_init(&p->sem, 1); + mutex_init(&p->lock); p->op = op; /* @@ -71,7 +71,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) void *p; int err = 0; - down(&m->sem); + mutex_lock(&m->lock); /* * seq_file->op->..m_start/m_stop/m_next may do special actions * or optimisations based on the file->f_version, so we want to @@ -164,7 +164,7 @@ Done: else *ppos += copied; file->f_version = m->version; - up(&m->sem); + mutex_unlock(&m->lock); return copied; Enomem: err = -ENOMEM; @@ -237,7 +237,7 @@ loff_t seq_lseek(struct file *file, loff_t offset, int origin) struct seq_file *m = (struct seq_file *)file->private_data; long long retval = -EINVAL; - down(&m->sem); + mutex_lock(&m->lock); m->version = file->f_version; switch (origin) { case 1: @@ -260,7 +260,7 @@ loff_t seq_lseek(struct file *file, loff_t offset, int origin) } } } - up(&m->sem); + mutex_unlock(&m->lock); file->f_version = m->version; return retval; } diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h index 850a974ee505..b95f6eb7254c 100644 --- a/include/linux/seq_file.h +++ b/include/linux/seq_file.h @@ -4,7 +4,7 @@ #include #include -#include +#include struct seq_operations; struct file; @@ -19,7 +19,7 @@ struct seq_file { size_t count; loff_t index; loff_t version; - struct semaphore sem; + struct mutex lock; struct seq_operations *op; void *private; }; -- cgit v1.2.3 From f85221dd74f2708b78a2aa54de59944e44206d0e Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 23 Mar 2006 03:00:38 -0800 Subject: [PATCH] sem2mutex: drivers/block/loop.c Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/loop.c | 18 +++++++++--------- include/linux/loop.h | 3 ++- 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 0010704739e3..74bf0255e98f 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1144,7 +1144,7 @@ static int lo_ioctl(struct inode * inode, struct file * file, struct loop_device *lo = inode->i_bdev->bd_disk->private_data; int err; - down(&lo->lo_ctl_mutex); + mutex_lock(&lo->lo_ctl_mutex); switch (cmd) { case LOOP_SET_FD: err = loop_set_fd(lo, file, inode->i_bdev, arg); @@ -1170,7 +1170,7 @@ static int lo_ioctl(struct inode * inode, struct file * file, default: err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; } - up(&lo->lo_ctl_mutex); + mutex_unlock(&lo->lo_ctl_mutex); return err; } @@ -1178,9 +1178,9 @@ static int lo_open(struct inode *inode, struct file *file) { struct loop_device *lo = inode->i_bdev->bd_disk->private_data; - down(&lo->lo_ctl_mutex); + mutex_lock(&lo->lo_ctl_mutex); lo->lo_refcnt++; - up(&lo->lo_ctl_mutex); + mutex_unlock(&lo->lo_ctl_mutex); return 0; } @@ -1189,9 +1189,9 @@ static int lo_release(struct inode *inode, struct file *file) { struct loop_device *lo = inode->i_bdev->bd_disk->private_data; - down(&lo->lo_ctl_mutex); + mutex_lock(&lo->lo_ctl_mutex); --lo->lo_refcnt; - up(&lo->lo_ctl_mutex); + mutex_unlock(&lo->lo_ctl_mutex); return 0; } @@ -1233,12 +1233,12 @@ int loop_unregister_transfer(int number) xfer_funcs[n] = NULL; for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++) { - down(&lo->lo_ctl_mutex); + mutex_lock(&lo->lo_ctl_mutex); if (lo->lo_encryption == xfer) loop_release_xfer(lo); - up(&lo->lo_ctl_mutex); + mutex_unlock(&lo->lo_ctl_mutex); } return 0; @@ -1285,7 +1285,7 @@ static int __init loop_init(void) lo->lo_queue = blk_alloc_queue(GFP_KERNEL); if (!lo->lo_queue) goto out_mem4; - init_MUTEX(&lo->lo_ctl_mutex); + mutex_init(&lo->lo_ctl_mutex); init_completion(&lo->lo_done); init_completion(&lo->lo_bh_done); lo->lo_number = i; diff --git a/include/linux/loop.h b/include/linux/loop.h index f96506782ebe..e76c7611d6cc 100644 --- a/include/linux/loop.h +++ b/include/linux/loop.h @@ -17,6 +17,7 @@ #include #include #include +#include /* Possible states of device */ enum { @@ -60,7 +61,7 @@ struct loop_device { int lo_state; struct completion lo_done; struct completion lo_bh_done; - struct semaphore lo_ctl_mutex; + struct mutex lo_ctl_mutex; int lo_pending; request_queue_t *lo_queue; -- cgit v1.2.3 From 82d4dc5adb0055393248ad4ab8de392fac708a12 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 23 Mar 2006 03:00:38 -0800 Subject: [PATCH] sem2mutex: drivers/block/nbd.c Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Cc: Paul Clements Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/nbd.c | 16 ++++++++-------- include/linux/nbd.h | 3 ++- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 6997d8e6bfb5..a9bde30dadad 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -459,9 +459,9 @@ static void do_nbd_request(request_queue_t * q) req->errors = 0; spin_unlock_irq(q->queue_lock); - down(&lo->tx_lock); + mutex_lock(&lo->tx_lock); if (unlikely(!lo->sock)) { - up(&lo->tx_lock); + mutex_unlock(&lo->tx_lock); printk(KERN_ERR "%s: Attempted send on closed socket\n", lo->disk->disk_name); req->errors++; @@ -484,7 +484,7 @@ static void do_nbd_request(request_queue_t * q) } lo->active_req = NULL; - up(&lo->tx_lock); + mutex_unlock(&lo->tx_lock); wake_up_all(&lo->active_wq); spin_lock_irq(q->queue_lock); @@ -534,9 +534,9 @@ static int nbd_ioctl(struct inode *inode, struct file *file, case NBD_CLEAR_SOCK: error = 0; - down(&lo->tx_lock); + mutex_lock(&lo->tx_lock); lo->sock = NULL; - up(&lo->tx_lock); + mutex_unlock(&lo->tx_lock); file = lo->file; lo->file = NULL; nbd_clear_que(lo); @@ -590,7 +590,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file, * FIXME: This code is duplicated from sys_shutdown, but * there should be a more generic interface rather than * calling socket ops directly here */ - down(&lo->tx_lock); + mutex_lock(&lo->tx_lock); if (lo->sock) { printk(KERN_WARNING "%s: shutting down socket\n", lo->disk->disk_name); @@ -598,7 +598,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file, SEND_SHUTDOWN|RCV_SHUTDOWN); lo->sock = NULL; } - up(&lo->tx_lock); + mutex_unlock(&lo->tx_lock); file = lo->file; lo->file = NULL; nbd_clear_que(lo); @@ -683,7 +683,7 @@ static int __init nbd_init(void) nbd_dev[i].flags = 0; spin_lock_init(&nbd_dev[i].queue_lock); INIT_LIST_HEAD(&nbd_dev[i].queue_head); - init_MUTEX(&nbd_dev[i].tx_lock); + mutex_init(&nbd_dev[i].tx_lock); init_waitqueue_head(&nbd_dev[i].active_wq); nbd_dev[i].blksize = 1024; nbd_dev[i].bytesize = 0x7ffffc00ULL << 10; /* 2TB */ diff --git a/include/linux/nbd.h b/include/linux/nbd.h index f95d51fae733..a6ce409ec6fc 100644 --- a/include/linux/nbd.h +++ b/include/linux/nbd.h @@ -38,6 +38,7 @@ enum { #ifdef __KERNEL__ #include +#include /* values for flags field */ #define NBD_READ_ONLY 0x0001 @@ -57,7 +58,7 @@ struct nbd_device { struct request *active_req; wait_queue_head_t active_wq; - struct semaphore tx_lock; + struct mutex tx_lock; struct gendisk *disk; int blksize; u64 bytesize; -- cgit v1.2.3 From 97461518610fb1679f67333bb699bb81136e49fe Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Thu, 23 Mar 2006 03:00:42 -0800 Subject: [PATCH] convert ext3's truncate_sem to a mutex ext3's truncate_sem is always released in the same function it's taken and it otherwise is a mutex as well.. Signed-off-by: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/file.c | 4 ++-- fs/ext3/inode.c | 14 +++++++------- fs/ext3/ioctl.c | 4 ++-- fs/ext3/super.c | 2 +- include/linux/ext3_fs_i.h | 7 ++++--- 5 files changed, 16 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/fs/ext3/file.c b/fs/ext3/file.c index 98e78345ead9..59098ea56711 100644 --- a/fs/ext3/file.c +++ b/fs/ext3/file.c @@ -37,9 +37,9 @@ static int ext3_release_file (struct inode * inode, struct file * filp) if ((filp->f_mode & FMODE_WRITE) && (atomic_read(&inode->i_writecount) == 1)) { - down(&EXT3_I(inode)->truncate_sem); + mutex_lock(&EXT3_I(inode)->truncate_mutex); ext3_discard_reservation(inode); - up(&EXT3_I(inode)->truncate_sem); + mutex_unlock(&EXT3_I(inode)->truncate_mutex); } if (is_dx(inode) && filp->private_data) ext3_htree_free_dir_info(filp->private_data); diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index d59d5a667b0b..2c361377e0a5 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -702,7 +702,7 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock, if (!create || err == -EIO) goto cleanup; - down(&ei->truncate_sem); + mutex_lock(&ei->truncate_mutex); /* * If the indirect block is missing while we are reading @@ -723,7 +723,7 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock, } partial = ext3_get_branch(inode, depth, offsets, chain, &err); if (!partial) { - up(&ei->truncate_sem); + mutex_unlock(&ei->truncate_mutex); if (err) goto cleanup; clear_buffer_new(bh_result); @@ -759,13 +759,13 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock, err = ext3_splice_branch(handle, inode, iblock, chain, partial, left); /* - * i_disksize growing is protected by truncate_sem. Don't forget to + * i_disksize growing is protected by truncate_mutex. Don't forget to * protect it if you're about to implement concurrent * ext3_get_block() -bzzz */ if (!err && extend_disksize && inode->i_size > ei->i_disksize) ei->i_disksize = inode->i_size; - up(&ei->truncate_sem); + mutex_unlock(&ei->truncate_mutex); if (err) goto cleanup; @@ -1227,7 +1227,7 @@ static int journal_dirty_data_fn(handle_t *handle, struct buffer_head *bh) * ext3_file_write() -> generic_file_write() -> __alloc_pages() -> ... * * Same applies to ext3_get_block(). We will deadlock on various things like - * lock_journal and i_truncate_sem. + * lock_journal and i_truncate_mutex. * * Setting PF_MEMALLOC here doesn't work - too many internal memory * allocations fail. @@ -2161,7 +2161,7 @@ void ext3_truncate(struct inode * inode) * From here we block out all ext3_get_block() callers who want to * modify the block allocation tree. */ - down(&ei->truncate_sem); + mutex_lock(&ei->truncate_mutex); if (n == 1) { /* direct blocks */ ext3_free_data(handle, inode, NULL, i_data+offsets[0], @@ -2228,7 +2228,7 @@ do_indirects: ext3_discard_reservation(inode); - up(&ei->truncate_sem); + mutex_unlock(&ei->truncate_mutex); inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; ext3_mark_inode_dirty(handle, inode); diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c index 556cd5510078..aaf1da17b6d4 100644 --- a/fs/ext3/ioctl.c +++ b/fs/ext3/ioctl.c @@ -182,7 +182,7 @@ flags_err: * need to allocate reservation structure for this inode * before set the window size */ - down(&ei->truncate_sem); + mutex_lock(&ei->truncate_mutex); if (!ei->i_block_alloc_info) ext3_init_block_alloc_info(inode); @@ -190,7 +190,7 @@ flags_err: struct ext3_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node; rsv->rsv_goal_size = rsv_window_size; } - up(&ei->truncate_sem); + mutex_unlock(&ei->truncate_mutex); return 0; } case EXT3_IOC_GROUP_EXTEND: { diff --git a/fs/ext3/super.c b/fs/ext3/super.c index efa832059143..efe5b20d7a5a 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -472,7 +472,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) #ifdef CONFIG_EXT3_FS_XATTR init_rwsem(&ei->xattr_sem); #endif - init_MUTEX(&ei->truncate_sem); + mutex_init(&ei->truncate_mutex); inode_init_once(&ei->vfs_inode); } } diff --git a/include/linux/ext3_fs_i.h b/include/linux/ext3_fs_i.h index e71dd98dbcae..7abf90147180 100644 --- a/include/linux/ext3_fs_i.h +++ b/include/linux/ext3_fs_i.h @@ -19,6 +19,7 @@ #include #include #include +#include struct ext3_reserve_window { __u32 _rsv_start; /* First byte reserved */ @@ -122,16 +123,16 @@ struct ext3_inode_info { __u16 i_extra_isize; /* - * truncate_sem is for serialising ext3_truncate() against + * truncate_mutex is for serialising ext3_truncate() against * ext3_getblock(). In the 2.4 ext2 design, great chunks of inode's * data tree are chopped off during truncate. We can't do that in * ext3 because whenever we perform intermediate commits during * truncate, the inode and all the metadata blocks *must* be in a * consistent state which allows truncation of the orphans to restart * during recovery. Hence we must fix the get_block-vs-truncate race - * by other means, so we have truncate_sem. + * by other means, so we have truncate_mutex. */ - struct semaphore truncate_sem; + struct mutex truncate_mutex; struct inode vfs_inode; }; -- cgit v1.2.3 From 8e3f90459b7052c31a9669417b837fb14aa6d313 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 23 Mar 2006 03:00:43 -0800 Subject: [PATCH] sem2mutex: NCPFS Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ncpfs/file.c | 4 ++-- fs/ncpfs/inode.c | 6 +++--- fs/ncpfs/ncplib_kernel.c | 4 ++-- fs/ncpfs/sock.c | 34 +++++++++++++++++----------------- include/linux/ncp_fs_i.h | 2 +- include/linux/ncp_fs_sb.h | 5 +++-- 6 files changed, 28 insertions(+), 27 deletions(-) (limited to 'include') diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index 973b444d6914..ebdad8f6398f 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c @@ -46,7 +46,7 @@ int ncp_make_open(struct inode *inode, int right) NCP_FINFO(inode)->volNumber, NCP_FINFO(inode)->dirEntNum); error = -EACCES; - down(&NCP_FINFO(inode)->open_sem); + mutex_lock(&NCP_FINFO(inode)->open_mutex); if (!atomic_read(&NCP_FINFO(inode)->opened)) { struct ncp_entry_info finfo; int result; @@ -93,7 +93,7 @@ int ncp_make_open(struct inode *inode, int right) } out_unlock: - up(&NCP_FINFO(inode)->open_sem); + mutex_unlock(&NCP_FINFO(inode)->open_mutex); out: return error; } diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index d277a58bd128..0b521d3d97ce 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -63,7 +63,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) { - init_MUTEX(&ei->open_sem); + mutex_init(&ei->open_mutex); inode_init_once(&ei->vfs_inode); } } @@ -520,7 +520,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) } /* server->lock = 0; */ - init_MUTEX(&server->sem); + mutex_init(&server->mutex); server->packet = NULL; /* server->buffer_size = 0; */ /* server->conn_status = 0; */ @@ -557,7 +557,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) server->dentry_ttl = 0; /* no caching */ INIT_LIST_HEAD(&server->tx.requests); - init_MUTEX(&server->rcv.creq_sem); + mutex_init(&server->rcv.creq_mutex); server->tx.creq = NULL; server->rcv.creq = NULL; server->data_ready = sock->sk->sk_data_ready; diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c index c755e1848a42..d9ebf6439f59 100644 --- a/fs/ncpfs/ncplib_kernel.c +++ b/fs/ncpfs/ncplib_kernel.c @@ -291,7 +291,7 @@ ncp_make_closed(struct inode *inode) int err; err = 0; - down(&NCP_FINFO(inode)->open_sem); + mutex_lock(&NCP_FINFO(inode)->open_mutex); if (atomic_read(&NCP_FINFO(inode)->opened) == 1) { atomic_set(&NCP_FINFO(inode)->opened, 0); err = ncp_close_file(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle); @@ -301,7 +301,7 @@ ncp_make_closed(struct inode *inode) NCP_FINFO(inode)->volNumber, NCP_FINFO(inode)->dirEntNum, err); } - up(&NCP_FINFO(inode)->open_sem); + mutex_unlock(&NCP_FINFO(inode)->open_mutex); return err; } diff --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c index 6593a5ca88ba..8783eb7ec641 100644 --- a/fs/ncpfs/sock.c +++ b/fs/ncpfs/sock.c @@ -171,9 +171,9 @@ static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_req static inline void ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err) { - down(&server->rcv.creq_sem); + mutex_lock(&server->rcv.creq_mutex); __ncp_abort_request(server, req, err); - up(&server->rcv.creq_sem); + mutex_unlock(&server->rcv.creq_mutex); } static inline void __ncptcp_abort(struct ncp_server *server) @@ -303,20 +303,20 @@ static inline void __ncp_start_request(struct ncp_server *server, struct ncp_req static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply *req) { - down(&server->rcv.creq_sem); + mutex_lock(&server->rcv.creq_mutex); if (!ncp_conn_valid(server)) { - up(&server->rcv.creq_sem); + mutex_unlock(&server->rcv.creq_mutex); printk(KERN_ERR "ncpfs: tcp: Server died\n"); return -EIO; } if (server->tx.creq || server->rcv.creq) { req->status = RQ_QUEUED; list_add_tail(&req->req, &server->tx.requests); - up(&server->rcv.creq_sem); + mutex_unlock(&server->rcv.creq_mutex); return 0; } __ncp_start_request(server, req); - up(&server->rcv.creq_sem); + mutex_unlock(&server->rcv.creq_mutex); return 0; } @@ -400,7 +400,7 @@ void ncpdgram_rcv_proc(void *s) info_server(server, 0, server->unexpected_packet.data, result); continue; } - down(&server->rcv.creq_sem); + mutex_lock(&server->rcv.creq_mutex); req = server->rcv.creq; if (req && (req->tx_type == NCP_ALLOC_SLOT_REQUEST || (server->sequence == reply.sequence && server->connection == get_conn_number(&reply)))) { @@ -430,11 +430,11 @@ void ncpdgram_rcv_proc(void *s) server->rcv.creq = NULL; ncp_finish_request(req, result); __ncp_next_request(server); - up(&server->rcv.creq_sem); + mutex_unlock(&server->rcv.creq_mutex); continue; } } - up(&server->rcv.creq_sem); + mutex_unlock(&server->rcv.creq_mutex); } drop:; _recv(sock, &reply, sizeof(reply), MSG_DONTWAIT); @@ -472,9 +472,9 @@ static void __ncpdgram_timeout_proc(struct ncp_server *server) void ncpdgram_timeout_proc(void *s) { struct ncp_server *server = s; - down(&server->rcv.creq_sem); + mutex_lock(&server->rcv.creq_mutex); __ncpdgram_timeout_proc(server); - up(&server->rcv.creq_sem); + mutex_unlock(&server->rcv.creq_mutex); } static inline void ncp_init_req(struct ncp_request_reply* req) @@ -657,18 +657,18 @@ void ncp_tcp_rcv_proc(void *s) { struct ncp_server *server = s; - down(&server->rcv.creq_sem); + mutex_lock(&server->rcv.creq_mutex); __ncptcp_rcv_proc(server); - up(&server->rcv.creq_sem); + mutex_unlock(&server->rcv.creq_mutex); } void ncp_tcp_tx_proc(void *s) { struct ncp_server *server = s; - down(&server->rcv.creq_sem); + mutex_lock(&server->rcv.creq_mutex); __ncptcp_try_send(server); - up(&server->rcv.creq_sem); + mutex_unlock(&server->rcv.creq_mutex); } static int do_ncp_rpc_call(struct ncp_server *server, int size, @@ -833,7 +833,7 @@ int ncp_disconnect(struct ncp_server *server) void ncp_lock_server(struct ncp_server *server) { - down(&server->sem); + mutex_lock(&server->mutex); if (server->lock) printk(KERN_WARNING "ncp_lock_server: was locked!\n"); server->lock = 1; @@ -846,5 +846,5 @@ void ncp_unlock_server(struct ncp_server *server) return; } server->lock = 0; - up(&server->sem); + mutex_unlock(&server->mutex); } diff --git a/include/linux/ncp_fs_i.h b/include/linux/ncp_fs_i.h index 415be1ec6f98..bdb4c8ae6924 100644 --- a/include/linux/ncp_fs_i.h +++ b/include/linux/ncp_fs_i.h @@ -19,7 +19,7 @@ struct ncp_inode_info { __le32 DosDirNum; __u8 volNumber; __le32 nwattr; - struct semaphore open_sem; + struct mutex open_mutex; atomic_t opened; int access; int flags; diff --git a/include/linux/ncp_fs_sb.h b/include/linux/ncp_fs_sb.h index cf858eb80f0b..b089d9506283 100644 --- a/include/linux/ncp_fs_sb.h +++ b/include/linux/ncp_fs_sb.h @@ -11,6 +11,7 @@ #include #include #include +#include #ifdef __KERNEL__ @@ -51,7 +52,7 @@ struct ncp_server { receive replies */ int lock; /* To prevent mismatch in protocols. */ - struct semaphore sem; + struct mutex mutex; int current_size; /* for packet preparation */ int has_subfunction; @@ -96,7 +97,7 @@ struct ncp_server { struct { struct work_struct tq; /* STREAM/DGRAM: data/error ready */ struct ncp_request_reply* creq; /* STREAM/DGRAM: awaiting reply from this request */ - struct semaphore creq_sem; /* DGRAM only: lock accesses to rcv.creq */ + struct mutex creq_mutex; /* DGRAM only: lock accesses to rcv.creq */ unsigned int state; /* STREAM only: receiver state */ struct { -- cgit v1.2.3 From 1e7933defd0fce79b2d8ecdbc7ca37fed0c188ed Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 23 Mar 2006 03:00:44 -0800 Subject: [PATCH] sem2mutex: UDF Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/udf/balloc.c | 36 ++++++++++++++++++------------------ fs/udf/ialloc.c | 8 ++++---- fs/udf/super.c | 2 +- include/linux/udf_fs_sb.h | 4 ++-- 4 files changed, 25 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c index 201049ac8a96..ea521f846d97 100644 --- a/fs/udf/balloc.c +++ b/fs/udf/balloc.c @@ -152,7 +152,7 @@ static void udf_bitmap_free_blocks(struct super_block * sb, int bitmap_nr; unsigned long overflow; - down(&sbi->s_alloc_sem); + mutex_lock(&sbi->s_alloc_mutex); if (bloc.logicalBlockNum < 0 || (bloc.logicalBlockNum + count) > UDF_SB_PARTLEN(sb, bloc.partitionReferenceNum)) { @@ -211,7 +211,7 @@ error_return: sb->s_dirt = 1; if (UDF_SB_LVIDBH(sb)) mark_buffer_dirty(UDF_SB_LVIDBH(sb)); - up(&sbi->s_alloc_sem); + mutex_unlock(&sbi->s_alloc_mutex); return; } @@ -226,7 +226,7 @@ static int udf_bitmap_prealloc_blocks(struct super_block * sb, int nr_groups, bitmap_nr; struct buffer_head *bh; - down(&sbi->s_alloc_sem); + mutex_lock(&sbi->s_alloc_mutex); if (first_block < 0 || first_block >= UDF_SB_PARTLEN(sb, partition)) goto out; @@ -275,7 +275,7 @@ out: mark_buffer_dirty(UDF_SB_LVIDBH(sb)); } sb->s_dirt = 1; - up(&sbi->s_alloc_sem); + mutex_unlock(&sbi->s_alloc_mutex); return alloc_count; } @@ -291,7 +291,7 @@ static int udf_bitmap_new_block(struct super_block * sb, int newblock = 0; *err = -ENOSPC; - down(&sbi->s_alloc_sem); + mutex_lock(&sbi->s_alloc_mutex); repeat: if (goal < 0 || goal >= UDF_SB_PARTLEN(sb, partition)) @@ -364,7 +364,7 @@ repeat: } if (i >= (nr_groups*2)) { - up(&sbi->s_alloc_sem); + mutex_unlock(&sbi->s_alloc_mutex); return newblock; } if (bit < sb->s_blocksize << 3) @@ -373,7 +373,7 @@ repeat: bit = udf_find_next_one_bit(bh->b_data, sb->s_blocksize << 3, group_start << 3); if (bit >= sb->s_blocksize << 3) { - up(&sbi->s_alloc_sem); + mutex_unlock(&sbi->s_alloc_mutex); return 0; } @@ -387,7 +387,7 @@ got_block: */ if (inode && DQUOT_ALLOC_BLOCK(inode, 1)) { - up(&sbi->s_alloc_sem); + mutex_unlock(&sbi->s_alloc_mutex); *err = -EDQUOT; return 0; } @@ -410,13 +410,13 @@ got_block: mark_buffer_dirty(UDF_SB_LVIDBH(sb)); } sb->s_dirt = 1; - up(&sbi->s_alloc_sem); + mutex_unlock(&sbi->s_alloc_mutex); *err = 0; return newblock; error_return: *err = -EIO; - up(&sbi->s_alloc_sem); + mutex_unlock(&sbi->s_alloc_mutex); return 0; } @@ -433,7 +433,7 @@ static void udf_table_free_blocks(struct super_block * sb, int8_t etype; int i; - down(&sbi->s_alloc_sem); + mutex_lock(&sbi->s_alloc_mutex); if (bloc.logicalBlockNum < 0 || (bloc.logicalBlockNum + count) > UDF_SB_PARTLEN(sb, bloc.partitionReferenceNum)) { @@ -666,7 +666,7 @@ static void udf_table_free_blocks(struct super_block * sb, error_return: sb->s_dirt = 1; - up(&sbi->s_alloc_sem); + mutex_unlock(&sbi->s_alloc_mutex); return; } @@ -692,7 +692,7 @@ static int udf_table_prealloc_blocks(struct super_block * sb, else return 0; - down(&sbi->s_alloc_sem); + mutex_lock(&sbi->s_alloc_mutex); extoffset = sizeof(struct unallocSpaceEntry); bloc = UDF_I_LOCATION(table); @@ -736,7 +736,7 @@ static int udf_table_prealloc_blocks(struct super_block * sb, mark_buffer_dirty(UDF_SB_LVIDBH(sb)); sb->s_dirt = 1; } - up(&sbi->s_alloc_sem); + mutex_unlock(&sbi->s_alloc_mutex); return alloc_count; } @@ -761,7 +761,7 @@ static int udf_table_new_block(struct super_block * sb, else return newblock; - down(&sbi->s_alloc_sem); + mutex_lock(&sbi->s_alloc_mutex); if (goal < 0 || goal >= UDF_SB_PARTLEN(sb, partition)) goal = 0; @@ -811,7 +811,7 @@ static int udf_table_new_block(struct super_block * sb, if (spread == 0xFFFFFFFF) { udf_release_data(goal_bh); - up(&sbi->s_alloc_sem); + mutex_unlock(&sbi->s_alloc_mutex); return 0; } @@ -827,7 +827,7 @@ static int udf_table_new_block(struct super_block * sb, if (inode && DQUOT_ALLOC_BLOCK(inode, 1)) { udf_release_data(goal_bh); - up(&sbi->s_alloc_sem); + mutex_unlock(&sbi->s_alloc_mutex); *err = -EDQUOT; return 0; } @@ -846,7 +846,7 @@ static int udf_table_new_block(struct super_block * sb, } sb->s_dirt = 1; - up(&sbi->s_alloc_sem); + mutex_unlock(&sbi->s_alloc_mutex); *err = 0; return newblock; } diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c index c9b707b470ca..3873c672cb4c 100644 --- a/fs/udf/ialloc.c +++ b/fs/udf/ialloc.c @@ -42,7 +42,7 @@ void udf_free_inode(struct inode * inode) clear_inode(inode); - down(&sbi->s_alloc_sem); + mutex_lock(&sbi->s_alloc_mutex); if (sbi->s_lvidbh) { if (S_ISDIR(inode->i_mode)) UDF_SB_LVIDIU(sb)->numDirs = @@ -53,7 +53,7 @@ void udf_free_inode(struct inode * inode) mark_buffer_dirty(sbi->s_lvidbh); } - up(&sbi->s_alloc_sem); + mutex_unlock(&sbi->s_alloc_mutex); udf_free_blocks(sb, NULL, UDF_I_LOCATION(inode), 0, 1); } @@ -83,7 +83,7 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err) return NULL; } - down(&sbi->s_alloc_sem); + mutex_lock(&sbi->s_alloc_mutex); UDF_I_UNIQUE(inode) = 0; UDF_I_LENEXTENTS(inode) = 0; UDF_I_NEXT_ALLOC_BLOCK(inode) = 0; @@ -148,7 +148,7 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err) UDF_I_CRTIME(inode) = current_fs_time(inode->i_sb); insert_inode_hash(inode); mark_inode_dirty(inode); - up(&sbi->s_alloc_sem); + mutex_unlock(&sbi->s_alloc_mutex); if (DQUOT_ALLOC_INODE(inode)) { diff --git a/fs/udf/super.c b/fs/udf/super.c index 368d8f81fe54..9303c50c5d55 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1515,7 +1515,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) sb->s_fs_info = sbi; memset(UDF_SB(sb), 0x00, sizeof(struct udf_sb_info)); - init_MUTEX(&sbi->s_alloc_sem); + mutex_init(&sbi->s_alloc_mutex); if (!udf_parse_options((char *)options, &uopt)) goto error_out; diff --git a/include/linux/udf_fs_sb.h b/include/linux/udf_fs_sb.h index b15ff2e99c91..80ae9ef940dc 100644 --- a/include/linux/udf_fs_sb.h +++ b/include/linux/udf_fs_sb.h @@ -13,7 +13,7 @@ #ifndef _UDF_FS_SB_H #define _UDF_FS_SB_H 1 -#include +#include #pragma pack(1) @@ -111,7 +111,7 @@ struct udf_sb_info /* VAT inode */ struct inode *s_vat; - struct semaphore s_alloc_sem; + struct mutex s_alloc_mutex; }; #endif /* _UDF_FS_SB_H */ -- cgit v1.2.3 From 81861d78c9edf9a9b03a9ba1f5b242d658f16832 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 23 Mar 2006 03:00:44 -0800 Subject: [PATCH] sem2mutex: serial ->port_write_mutex Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/generic_serial.c | 14 +++++++------- drivers/char/ser_a2232.c | 4 ++-- drivers/char/sx.c | 2 +- drivers/char/vme_scc.c | 2 +- include/linux/generic_serial.h | 4 +++- 5 files changed, 14 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index e38a5f0e07bb..5e59c0b42731 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c @@ -48,8 +48,8 @@ static int gs_debug; #define NEW_WRITE_LOCKING 1 #if NEW_WRITE_LOCKING #define DECL /* Nothing */ -#define LOCKIT down (& port->port_write_sem); -#define RELEASEIT up (&port->port_write_sem); +#define LOCKIT mutex_lock(& port->port_write_mutex); +#define RELEASEIT mutex_unlock(&port->port_write_mutex); #else #define DECL unsigned long flags; #define LOCKIT save_flags (flags);cli () @@ -124,14 +124,14 @@ int gs_write(struct tty_struct * tty, /* get exclusive "write" access to this port (problem 3) */ /* This is not a spinlock because we can have a disk access (page fault) in copy_from_user */ - down (& port->port_write_sem); + mutex_lock(& port->port_write_mutex); while (1) { c = count; /* This is safe because we "OWN" the "head". Noone else can - change the "head": we own the port_write_sem. */ + change the "head": we own the port_write_mutex. */ /* Don't overrun the end of the buffer */ t = SERIAL_XMIT_SIZE - port->xmit_head; if (t < c) c = t; @@ -153,7 +153,7 @@ int gs_write(struct tty_struct * tty, count -= c; total += c; } - up (& port->port_write_sem); + mutex_unlock(& port->port_write_mutex); gs_dprintk (GS_DEBUG_WRITE, "write: interrupts are %s\n", (port->flags & GS_TX_INTEN)?"enabled": "disabled"); @@ -214,7 +214,7 @@ int gs_write(struct tty_struct * tty, c = count; /* This is safe because we "OWN" the "head". Noone else can - change the "head": we own the port_write_sem. */ + change the "head": we own the port_write_mutex. */ /* Don't overrun the end of the buffer */ t = SERIAL_XMIT_SIZE - port->xmit_head; if (t < c) c = t; @@ -888,7 +888,7 @@ int gs_init_port(struct gs_port *port) spin_lock_irqsave (&port->driver_lock, flags); if (port->tty) clear_bit(TTY_IO_ERROR, &port->tty->flags); - init_MUTEX(&port->port_write_sem); + mutex_init(&port->port_write_mutex); port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; spin_unlock_irqrestore(&port->driver_lock, flags); gs_set_termios(port->tty, NULL); diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c index fee68cc895f8..510bd3e0e88b 100644 --- a/drivers/char/ser_a2232.c +++ b/drivers/char/ser_a2232.c @@ -97,7 +97,7 @@ #include #include #include -#include +#include #include @@ -654,7 +654,7 @@ static void a2232_init_portstructs(void) port->gs.closing_wait = 30 * HZ; port->gs.rd = &a2232_real_driver; #ifdef NEW_WRITE_LOCKING - init_MUTEX(&(port->gs.port_write_sem)); + init_MUTEX(&(port->gs.port_write_mutex)); #endif init_waitqueue_head(&port->gs.open_wait); init_waitqueue_head(&port->gs.close_wait); diff --git a/drivers/char/sx.c b/drivers/char/sx.c index a6b4f02bdceb..3b4747230270 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -2318,7 +2318,7 @@ static int sx_init_portstructs (int nboards, int nports) port->board = board; port->gs.rd = &sx_real_driver; #ifdef NEW_WRITE_LOCKING - port->gs.port_write_sem = MUTEX; + port->gs.port_write_mutex = MUTEX; #endif port->gs.driver_lock = SPIN_LOCK_UNLOCKED; /* diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c index d9325281e482..fd00822ac145 100644 --- a/drivers/char/vme_scc.c +++ b/drivers/char/vme_scc.c @@ -184,7 +184,7 @@ static void scc_init_portstructs(void) port->gs.closing_wait = 30 * HZ; port->gs.rd = &scc_real_driver; #ifdef NEW_WRITE_LOCKING - port->gs.port_write_sem = MUTEX; + port->gs.port_write_mutex = MUTEX; #endif init_waitqueue_head(&port->gs.open_wait); init_waitqueue_head(&port->gs.close_wait); diff --git a/include/linux/generic_serial.h b/include/linux/generic_serial.h index 0abe9d9a0069..652611a4bdcd 100644 --- a/include/linux/generic_serial.h +++ b/include/linux/generic_serial.h @@ -12,6 +12,8 @@ #ifndef GENERIC_SERIAL_H #define GENERIC_SERIAL_H +#include + struct real_driver { void (*disable_tx_interrupts) (void *); void (*enable_tx_interrupts) (void *); @@ -34,7 +36,7 @@ struct gs_port { int xmit_head; int xmit_tail; int xmit_cnt; - struct semaphore port_write_sem; + struct mutex port_write_mutex; int flags; wait_queue_head_t open_wait; wait_queue_head_t close_wait; -- cgit v1.2.3 From 6b9438e1323a2be10dcc039f6321e7ca18b9459e Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Thu, 23 Mar 2006 03:00:48 -0800 Subject: [PATCH] fat_lock is used as a mutex, convert it to using the new mutex primitive The fat code uses the fat_lock always in a mutex way (taking and releasing the lock in the same function), the patch below converts it into the new mutex primitive. Please consider this patch for the code. Signed-off-by: Arjan van de Ven Acked-by: OGAWA Hirofumi Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fat/fatent.c | 6 +++--- include/linux/msdos_fs.h | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c index a1a9e0451217..ab171ea8e869 100644 --- a/fs/fat/fatent.c +++ b/fs/fat/fatent.c @@ -267,19 +267,19 @@ static struct fatent_operations fat32_ops = { static inline void lock_fat(struct msdos_sb_info *sbi) { - down(&sbi->fat_lock); + mutex_lock(&sbi->fat_lock); } static inline void unlock_fat(struct msdos_sb_info *sbi) { - up(&sbi->fat_lock); + mutex_unlock(&sbi->fat_lock); } void fat_ent_access_init(struct super_block *sb) { struct msdos_sb_info *sbi = MSDOS_SB(sb); - init_MUTEX(&sbi->fat_lock); + mutex_init(&sbi->fat_lock); switch (sbi->fat_bits) { case 32: diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h index 8bcd9450d926..779e6a5744c7 100644 --- a/include/linux/msdos_fs.h +++ b/include/linux/msdos_fs.h @@ -184,6 +184,7 @@ struct fat_slot_info { #include #include #include +#include struct fat_mount_options { uid_t fs_uid; @@ -226,7 +227,7 @@ struct msdos_sb_info { unsigned long max_cluster; /* maximum cluster number */ unsigned long root_cluster; /* first cluster of the root directory */ unsigned long fsinfo_sector; /* sector number of FAT32 fsinfo */ - struct semaphore fat_lock; + struct mutex fat_lock; unsigned int prev_free; /* previously allocated cluster number */ unsigned int free_clusters; /* -1 if undefined */ struct fat_mount_options options; -- cgit v1.2.3 From 66d2173053f64121f8dc69a1cf85972e37e1ee75 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 23 Mar 2006 03:00:51 -0800 Subject: [PATCH] Extract inode_inc_link_count(), inode_dec_link_count() Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/fs.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'include') diff --git a/include/linux/fs.h b/include/linux/fs.h index 8fd8d9b90b00..f9c9dea636d0 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1115,6 +1115,18 @@ static inline void mark_inode_dirty_sync(struct inode *inode) __mark_inode_dirty(inode, I_DIRTY_SYNC); } +static inline void inode_inc_link_count(struct inode *inode) +{ + inode->i_nlink++; + mark_inode_dirty(inode); +} + +static inline void inode_dec_link_count(struct inode *inode) +{ + inode->i_nlink--; + mark_inode_dirty(inode); +} + extern void touch_atime(struct vfsmount *mnt, struct dentry *dentry); static inline void file_accessed(struct file *file) { -- cgit v1.2.3 From 91368d73e4b60d577ad171e5bd315b564265fcdb Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 23 Mar 2006 03:00:54 -0800 Subject: [PATCH] make bug messages more consistent Consolidate all kernel bug printouts to begin with the "BUG: " string. Makes it easier to find them in large bootup logs. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/nmi.c | 2 +- arch/i386/mm/fault.c | 4 ++-- include/asm-generic/bug.h | 4 ++-- kernel/sched.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index be87c5e2ee95..1db34effdd8d 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c @@ -543,7 +543,7 @@ void nmi_watchdog_tick (struct pt_regs * regs) /* * die_nmi will return ONLY if NOTIFY_STOP happens.. */ - die_nmi(regs, "NMI Watchdog detected LOCKUP"); + die_nmi(regs, "BUG: NMI Watchdog detected LOCKUP"); } else { last_irq_sums[cpu] = sum; alert_counter[cpu] = 0; diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index bbb24af5d860..47a3b72ec7b6 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c @@ -518,9 +518,9 @@ no_context: } #endif if (address < PAGE_SIZE) - printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); + printk(KERN_ALERT "BUG: unable to handle kernel NULL pointer dereference"); else - printk(KERN_ALERT "Unable to handle kernel paging request"); + printk(KERN_ALERT "BUG: unable to handle kernel paging request"); printk(" at virtual address %08lx\n",address); printk(KERN_ALERT " printing eip:\n"); printk("%08lx\n", regs->eip); diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 400c2b41896e..1a565a9d2fa7 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -7,7 +7,7 @@ #ifdef CONFIG_BUG #ifndef HAVE_ARCH_BUG #define BUG() do { \ - printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ + printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __FUNCTION__); \ panic("BUG!"); \ } while (0) #endif @@ -19,7 +19,7 @@ #ifndef HAVE_ARCH_WARN_ON #define WARN_ON(condition) do { \ if (unlikely((condition)!=0)) { \ - printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \ + printk("BUG: warning at %s:%d/%s()\n", __FILE__, __LINE__, __FUNCTION__); \ dump_stack(); \ } \ } while (0) diff --git a/kernel/sched.c b/kernel/sched.c index a5bd60453eae..7ffaabd64f89 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2873,7 +2873,7 @@ asmlinkage void __sched schedule(void) */ if (likely(!current->exit_state)) { if (unlikely(in_atomic())) { - printk(KERN_ERR "scheduling while atomic: " + printk(KERN_ERR "BUG: scheduling while atomic: " "%s/0x%08x/%d\n", current->comm, preempt_count(), current->pid); dump_stack(); @@ -6074,7 +6074,7 @@ void __might_sleep(char *file, int line) if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy) return; prev_jiffy = jiffies; - printk(KERN_ERR "Debug: sleeping function called from invalid" + printk(KERN_ERR "BUG: sleeping function called from invalid" " context at %s:%d\n", file, line); printk("in_atomic():%d, irqs_disabled():%d\n", in_atomic(), irqs_disabled()); -- cgit v1.2.3 From 772a0dc5d2103baff2f15c2668930bcd37add777 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 23 Mar 2006 03:00:55 -0800 Subject: [PATCH] notifier: profile.h forward decl fix Declarations use struct notifier_block on both legs of the ifdef, so move the notifier_block forward declaration outside the ifdef. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/profile.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/profile.h b/include/linux/profile.h index 026969a5595c..1f2fea6640a4 100644 --- a/include/linux/profile.h +++ b/include/linux/profile.h @@ -14,6 +14,7 @@ struct proc_dir_entry; struct pt_regs; +struct notifier_block; /* init basic kernel profiler */ void __init profile_init(void); @@ -32,7 +33,6 @@ enum profile_type { #ifdef CONFIG_PROFILING -struct notifier_block; struct task_struct; struct mm_struct; -- cgit v1.2.3 From 41c28ff1635e71af072c4711ff5fadd5855d48e7 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 23 Mar 2006 03:00:56 -0800 Subject: [PATCH] kill _INLINE_ This patch removes all occurances of _INLINE_ in the kernel. With the exception of tty_flip.h, I've simply removed the inline's since gcc should know best which functions to be inlined. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/hp/sim/simserial.c | 7 +--- arch/xtensa/platform-iss/console.c | 4 --- drivers/char/amiserial.c | 18 ++++------ drivers/isdn/hisax/config.c | 1 - drivers/isdn/hisax/elsa.c | 1 - drivers/serial/68328serial.c | 9 +++-- drivers/serial/au1x00_uart.c | 11 +++--- drivers/serial/crisv10.c | 68 ++++++++++++-------------------------- drivers/serial/m32r_sio.c | 15 ++++----- drivers/serial/sunsu.c | 13 +++----- drivers/tc/zs.c | 9 ++--- include/linux/tty_flip.h | 12 ++----- 12 files changed, 56 insertions(+), 112 deletions(-) (limited to 'include') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 626cdc83668b..0e5c6ae50228 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -46,11 +46,6 @@ #define KEYBOARD_INTR 3 /* must match with simulator! */ #define NR_PORTS 1 /* only one port for now */ -#define SERIAL_INLINE 1 - -#ifdef SERIAL_INLINE -#define _INLINE_ inline -#endif #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) @@ -237,7 +232,7 @@ static void rs_put_char(struct tty_struct *tty, unsigned char ch) local_irq_restore(flags); } -static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) +static void transmit_chars(struct async_struct *info, int *intr_done) { int count; unsigned long flags; diff --git a/arch/xtensa/platform-iss/console.c b/arch/xtensa/platform-iss/console.c index 94fdfe474ac1..2a580efb58ec 100644 --- a/arch/xtensa/platform-iss/console.c +++ b/arch/xtensa/platform-iss/console.c @@ -31,10 +31,6 @@ #include #include -#ifdef SERIAL_INLINE -#define _INLINE_ inline -#endif - #define SERIAL_MAX_NUM_LINES 1 #define SERIAL_TIMER_VALUE (20 * HZ) diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 7ac365b5d9ec..6602b3156df5 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -46,8 +46,6 @@ /* Sanity checks */ -#define SERIAL_INLINE - #if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT) #define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \ tty->name, (info->flags), serial_driver->refcount,info->count,tty->count,s) @@ -95,10 +93,6 @@ static char *serial_version = "4.30"; #include #include -#ifdef SERIAL_INLINE -#define _INLINE_ inline -#endif - #define custom amiga_custom static char *serial_name = "Amiga-builtin serial driver"; @@ -253,14 +247,14 @@ static void rs_start(struct tty_struct *tty) * This routine is used by the interrupt handler to schedule * processing in the software interrupt portion of the driver. */ -static _INLINE_ void rs_sched_event(struct async_struct *info, - int event) +static void rs_sched_event(struct async_struct *info, + int event) { info->event |= 1 << event; tasklet_schedule(&info->tlet); } -static _INLINE_ void receive_chars(struct async_struct *info) +static void receive_chars(struct async_struct *info) { int status; int serdatr; @@ -349,7 +343,7 @@ out: return; } -static _INLINE_ void transmit_chars(struct async_struct *info) +static void transmit_chars(struct async_struct *info) { custom.intreq = IF_TBE; mb(); @@ -389,7 +383,7 @@ static _INLINE_ void transmit_chars(struct async_struct *info) } } -static _INLINE_ void check_modem_status(struct async_struct *info) +static void check_modem_status(struct async_struct *info) { unsigned char status = ciab.pra & (SER_DCD | SER_CTS | SER_DSR); unsigned char dstatus; @@ -1959,7 +1953,7 @@ done: * number, and identifies which options were configured into this * driver. */ -static _INLINE_ void show_serial_version(void) +static void show_serial_version(void) { printk(KERN_INFO "%s version %s\n", serial_name, serial_version); } diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index df9d65201819..27332506f9f7 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -25,7 +25,6 @@ #include #include #define HISAX_STATUS_BUFSIZE 4096 -#define INCLUDE_INLINE_FUNCS /* * This structure array contains one entry per card. An entry looks diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c index 110e9fd669c5..f8ca4b323331 100644 --- a/drivers/isdn/hisax/elsa.c +++ b/drivers/isdn/hisax/elsa.c @@ -108,7 +108,6 @@ static const char *ITACVer[] = #define ELSA_ASSIGN 4 #define RS_ISR_PASS_LIMIT 256 -#define _INLINE_ inline #define FLG_MODEM_ACTIVE 1 /* IPAC AUX */ #define ELSA_IPAC_LINE_LED 0x40 /* Bit 6 Gelbe LED */ diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 7f0f35a05dca..b88a7c1158af 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c @@ -101,8 +101,6 @@ struct tty_driver *serial_driver; #define RS_ISR_PASS_LIMIT 256 -#define _INLINE_ inline - static void change_speed(struct m68k_serial *info); /* @@ -262,7 +260,7 @@ static void batten_down_hatches(void) /* Drop into the debugger */ } -static _INLINE_ void status_handle(struct m68k_serial *info, unsigned short status) +static void status_handle(struct m68k_serial *info, unsigned short status) { #if 0 if(status & DCD) { @@ -289,7 +287,8 @@ static _INLINE_ void status_handle(struct m68k_serial *info, unsigned short stat return; } -static _INLINE_ void receive_chars(struct m68k_serial *info, struct pt_regs *regs, unsigned short rx) +static void receive_chars(struct m68k_serial *info, struct pt_regs *regs, + unsigned short rx) { struct tty_struct *tty = info->tty; m68328_uart *uart = &uart_addr[info->line]; @@ -359,7 +358,7 @@ clear_and_exit: return; } -static _INLINE_ void transmit_chars(struct m68k_serial *info) +static void transmit_chars(struct m68k_serial *info) { m68328_uart *uart = &uart_addr[info->line]; diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c index 29f94bbb79be..948880ac5878 100644 --- a/drivers/serial/au1x00_uart.c +++ b/drivers/serial/au1x00_uart.c @@ -133,13 +133,12 @@ static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = { { "AU1X00_UART",16, UART_CLEAR_FIFO | UART_USE_FIFO }, }; -static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) +static unsigned int serial_in(struct uart_8250_port *up, int offset) { return au_readl((unsigned long)up->port.membase + offset); } -static _INLINE_ void -serial_out(struct uart_8250_port *up, int offset, int value) +static void serial_out(struct uart_8250_port *up, int offset, int value) { au_writel(value, (unsigned long)up->port.membase + offset); } @@ -237,7 +236,7 @@ static void serial8250_enable_ms(struct uart_port *port) serial_out(up, UART_IER, up->ier); } -static _INLINE_ void +static void receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) { struct tty_struct *tty = up->port.info->tty; @@ -312,7 +311,7 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) spin_lock(&up->port.lock); } -static _INLINE_ void transmit_chars(struct uart_8250_port *up) +static void transmit_chars(struct uart_8250_port *up) { struct circ_buf *xmit = &up->port.info->xmit; int count; @@ -346,7 +345,7 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up) serial8250_stop_tx(&up->port); } -static _INLINE_ void check_modem_status(struct uart_8250_port *up) +static void check_modem_status(struct uart_8250_port *up) { int status; diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index be12623d8544..89700141f87e 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -481,8 +481,6 @@ static char *serial_version = "$Revision: 1.25 $"; #include "serial_compat.h" #endif -#define _INLINE_ inline - struct tty_driver *serial_driver; /* serial subtype definitions */ @@ -591,8 +589,6 @@ static void rs_throttle(struct tty_struct * tty); static void rs_wait_until_sent(struct tty_struct *tty, int timeout); static int rs_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count); -extern _INLINE_ int rs_raw_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count); #ifdef CONFIG_ETRAX_RS485 static int e100_write_rs485(struct tty_struct * tty, int from_user, const unsigned char *buf, int count); @@ -1538,8 +1534,7 @@ e100_enable_rxdma_irq(struct e100_serial *info) /* the tx DMA uses only dma_descr interrupt */ -static _INLINE_ void -e100_disable_txdma_irq(struct e100_serial *info) +static void e100_disable_txdma_irq(struct e100_serial *info) { #ifdef SERIAL_DEBUG_INTR printk("txdma_irq(%d): 0\n",info->line); @@ -1548,8 +1543,7 @@ e100_disable_txdma_irq(struct e100_serial *info) *R_IRQ_MASK2_CLR = info->irq; } -static _INLINE_ void -e100_enable_txdma_irq(struct e100_serial *info) +static void e100_enable_txdma_irq(struct e100_serial *info) { #ifdef SERIAL_DEBUG_INTR printk("txdma_irq(%d): 1\n",info->line); @@ -1558,8 +1552,7 @@ e100_enable_txdma_irq(struct e100_serial *info) *R_IRQ_MASK2_SET = info->irq; } -static _INLINE_ void -e100_disable_txdma_channel(struct e100_serial *info) +static void e100_disable_txdma_channel(struct e100_serial *info) { unsigned long flags; @@ -1599,8 +1592,7 @@ e100_disable_txdma_channel(struct e100_serial *info) } -static _INLINE_ void -e100_enable_txdma_channel(struct e100_serial *info) +static void e100_enable_txdma_channel(struct e100_serial *info) { unsigned long flags; @@ -1625,8 +1617,7 @@ e100_enable_txdma_channel(struct e100_serial *info) restore_flags(flags); } -static _INLINE_ void -e100_disable_rxdma_channel(struct e100_serial *info) +static void e100_disable_rxdma_channel(struct e100_serial *info) { unsigned long flags; @@ -1665,8 +1656,7 @@ e100_disable_rxdma_channel(struct e100_serial *info) } -static _INLINE_ void -e100_enable_rxdma_channel(struct e100_serial *info) +static void e100_enable_rxdma_channel(struct e100_serial *info) { unsigned long flags; @@ -1913,9 +1903,7 @@ rs_start(struct tty_struct *tty) * This routine is used by the interrupt handler to schedule * processing in the software interrupt portion of the driver. */ -static _INLINE_ void -rs_sched_event(struct e100_serial *info, - int event) +static void rs_sched_event(struct e100_serial *info, int event) { if (info->event & (1 << event)) return; @@ -2155,8 +2143,9 @@ add_char_and_flag(struct e100_serial *info, unsigned char data, unsigned char fl return 1; } -extern _INLINE_ unsigned int -handle_descr_data(struct e100_serial *info, struct etrax_dma_descr *descr, unsigned int recvl) +static unsigned int handle_descr_data(struct e100_serial *info, + struct etrax_dma_descr *descr, + unsigned int recvl) { struct etrax_recv_buffer *buffer = phys_to_virt(descr->buf) - sizeof *buffer; @@ -2182,8 +2171,7 @@ handle_descr_data(struct e100_serial *info, struct etrax_dma_descr *descr, unsig return recvl; } -static _INLINE_ unsigned int -handle_all_descr_data(struct e100_serial *info) +static unsigned int handle_all_descr_data(struct e100_serial *info) { struct etrax_dma_descr *descr; unsigned int recvl; @@ -2230,8 +2218,7 @@ handle_all_descr_data(struct e100_serial *info) return ret; } -static _INLINE_ void -receive_chars_dma(struct e100_serial *info) +static void receive_chars_dma(struct e100_serial *info) { struct tty_struct *tty; unsigned char rstat; @@ -2292,8 +2279,7 @@ receive_chars_dma(struct e100_serial *info) *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart); } -static _INLINE_ int -start_recv_dma(struct e100_serial *info) +static int start_recv_dma(struct e100_serial *info) { struct etrax_dma_descr *descr = info->rec_descr; struct etrax_recv_buffer *buffer; @@ -2348,11 +2334,6 @@ start_receive(struct e100_serial *info) } -static _INLINE_ void -status_handle(struct e100_serial *info, unsigned short status) -{ -} - /* the bits in the MASK2 register are laid out like this: DMAI_EOP DMAI_DESCR DMAO_EOP DMAO_DESCR where I is the input channel and O is the output channel for the port. @@ -2454,8 +2435,7 @@ rec_interrupt(int irq, void *dev_id, struct pt_regs * regs) return IRQ_RETVAL(handled); } /* rec_interrupt */ -static _INLINE_ int -force_eop_if_needed(struct e100_serial *info) +static int force_eop_if_needed(struct e100_serial *info) { /* We check data_avail bit to determine if data has * arrived since last time @@ -2499,8 +2479,7 @@ force_eop_if_needed(struct e100_serial *info) return 1; } -extern _INLINE_ void -flush_to_flip_buffer(struct e100_serial *info) +static void flush_to_flip_buffer(struct e100_serial *info) { struct tty_struct *tty; struct etrax_recv_buffer *buffer; @@ -2611,8 +2590,7 @@ flush_to_flip_buffer(struct e100_serial *info) tty_flip_buffer_push(tty); } -static _INLINE_ void -check_flush_timeout(struct e100_serial *info) +static void check_flush_timeout(struct e100_serial *info) { /* Flip what we've got (if we can) */ flush_to_flip_buffer(info); @@ -2741,7 +2719,7 @@ TODO: The break will be delayed until an F or V character is received. */ -extern _INLINE_ +static struct e100_serial * handle_ser_rx_interrupt_no_dma(struct e100_serial *info) { unsigned long data_read; @@ -2875,8 +2853,7 @@ more_data: return info; } -extern _INLINE_ -struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info) +static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info) { unsigned char rstat; @@ -2995,7 +2972,7 @@ struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info) return info; } /* handle_ser_rx_interrupt */ -extern _INLINE_ void handle_ser_tx_interrupt(struct e100_serial *info) +static void handle_ser_tx_interrupt(struct e100_serial *info) { unsigned long flags; @@ -3621,9 +3598,8 @@ rs_flush_chars(struct tty_struct *tty) restore_flags(flags); } -extern _INLINE_ int -rs_raw_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count) +static int rs_raw_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) { int c, ret = 0; struct e100_serial *info = (struct e100_serial *)tty->driver_data; @@ -4710,7 +4686,7 @@ rs_open(struct tty_struct *tty, struct file * filp) * /proc fs routines.... */ -extern _INLINE_ int line_info(char *buf, struct e100_serial *info) +static int line_info(char *buf, struct e100_serial *info) { char stat_buf[30]; int ret; diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c index 876bc5e027bb..e9c10c0a30fc 100644 --- a/drivers/serial/m32r_sio.c +++ b/drivers/serial/m32r_sio.c @@ -248,17 +248,17 @@ static void sio_error(int *status) #endif /* CONFIG_SERIAL_M32R_PLDSIO */ -static _INLINE_ unsigned int sio_in(struct uart_sio_port *up, int offset) +static unsigned int sio_in(struct uart_sio_port *up, int offset) { return __sio_in(up->port.iobase + offset); } -static _INLINE_ void sio_out(struct uart_sio_port *up, int offset, int value) +static void sio_out(struct uart_sio_port *up, int offset, int value) { __sio_out(value, up->port.iobase + offset); } -static _INLINE_ unsigned int serial_in(struct uart_sio_port *up, int offset) +static unsigned int serial_in(struct uart_sio_port *up, int offset) { if (!offset) return 0; @@ -266,8 +266,7 @@ static _INLINE_ unsigned int serial_in(struct uart_sio_port *up, int offset) return __sio_in(offset); } -static _INLINE_ void -serial_out(struct uart_sio_port *up, int offset, int value) +static void serial_out(struct uart_sio_port *up, int offset, int value) { if (!offset) return; @@ -326,8 +325,8 @@ static void m32r_sio_enable_ms(struct uart_port *port) serial_out(up, UART_IER, up->ier); } -static _INLINE_ void receive_chars(struct uart_sio_port *up, int *status, - struct pt_regs *regs) +static void receive_chars(struct uart_sio_port *up, int *status, + struct pt_regs *regs) { struct tty_struct *tty = up->port.info->tty; unsigned char ch; @@ -400,7 +399,7 @@ static _INLINE_ void receive_chars(struct uart_sio_port *up, int *status, tty_flip_buffer_push(tty); } -static _INLINE_ void transmit_chars(struct uart_sio_port *up) +static void transmit_chars(struct uart_sio_port *up) { struct circ_buf *xmit = &up->port.info->xmit; int count; diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 7fc3d3b41d18..9fe2283d91e5 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -102,9 +102,7 @@ struct uart_sunsu_port { #endif }; -#define _INLINE_ - -static _INLINE_ unsigned int serial_in(struct uart_sunsu_port *up, int offset) +static unsigned int serial_in(struct uart_sunsu_port *up, int offset) { offset <<= up->port.regshift; @@ -121,8 +119,7 @@ static _INLINE_ unsigned int serial_in(struct uart_sunsu_port *up, int offset) } } -static _INLINE_ void -serial_out(struct uart_sunsu_port *up, int offset, int value) +static void serial_out(struct uart_sunsu_port *up, int offset, int value) { #ifndef CONFIG_SPARC64 /* @@ -316,7 +313,7 @@ static void sunsu_enable_ms(struct uart_port *port) spin_unlock_irqrestore(&up->port.lock, flags); } -static _INLINE_ struct tty_struct * +static struct tty_struct * receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs *regs) { struct tty_struct *tty = up->port.info->tty; @@ -395,7 +392,7 @@ receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs return tty; } -static _INLINE_ void transmit_chars(struct uart_sunsu_port *up) +static void transmit_chars(struct uart_sunsu_port *up) { struct circ_buf *xmit = &up->port.info->xmit; int count; @@ -431,7 +428,7 @@ static _INLINE_ void transmit_chars(struct uart_sunsu_port *up) __stop_tx(up); } -static _INLINE_ void check_modem_status(struct uart_sunsu_port *up) +static void check_modem_status(struct uart_sunsu_port *up) { int status; diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c index 6756d0fab6fe..2dffa8e303b2 100644 --- a/drivers/tc/zs.c +++ b/drivers/tc/zs.c @@ -186,8 +186,6 @@ static struct tty_driver *serial_driver; #define RS_STROBE_TIME 10 #define RS_ISR_PASS_LIMIT 256 -#define _INLINE_ inline - static void probe_sccs(void); static void change_speed(struct dec_serial *info); static void rs_wait_until_sent(struct tty_struct *tty, int timeout); @@ -344,14 +342,13 @@ static inline void rs_recv_clear(struct dec_zschannel *zsc) * This routine is used by the interrupt handler to schedule * processing in the software interrupt portion of the driver. */ -static _INLINE_ void rs_sched_event(struct dec_serial *info, int event) +static void rs_sched_event(struct dec_serial *info, int event) { info->event |= 1 << event; tasklet_schedule(&info->tlet); } -static _INLINE_ void receive_chars(struct dec_serial *info, - struct pt_regs *regs) +static void receive_chars(struct dec_serial *info, struct pt_regs *regs) { struct tty_struct *tty = info->tty; unsigned char ch, stat, flag; @@ -441,7 +438,7 @@ static void transmit_chars(struct dec_serial *info) rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); } -static _INLINE_ void status_handle(struct dec_serial *info) +static void status_handle(struct dec_serial *info) { unsigned char stat; diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h index 222faf97d5f9..0c6169fff366 100644 --- a/include/linux/tty_flip.h +++ b/include/linux/tty_flip.h @@ -7,14 +7,8 @@ extern int tty_insert_flip_string_flags(struct tty_struct *tty, unsigned char *c extern int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size); extern int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size); -#ifdef INCLUDE_INLINE_FUNCS -#define _INLINE_ extern -#else -#define _INLINE_ static __inline__ -#endif - -_INLINE_ int tty_insert_flip_char(struct tty_struct *tty, - unsigned char ch, char flag) +static inline int tty_insert_flip_char(struct tty_struct *tty, + unsigned char ch, char flag) { struct tty_buffer *tb = tty->buf.tail; if (tb && tb->active && tb->used < tb->size) { @@ -25,7 +19,7 @@ _INLINE_ int tty_insert_flip_char(struct tty_struct *tty, return tty_insert_flip_string_flags(tty, &ch, &flag, 1); } -_INLINE_ void tty_schedule_flip(struct tty_struct *tty) +static inline void tty_schedule_flip(struct tty_struct *tty) { unsigned long flags; spin_lock_irqsave(&tty->buf.lock, flags); -- cgit v1.2.3 From dd287796d608fcdc3fe5e8fdb5bf762a8f1bc32a Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 23 Mar 2006 03:00:57 -0800 Subject: [PATCH] pause_on_oops command line option Attempt to fix the problem wherein people's oops reports scroll off the screen due to repeated oopsing or to oopses on other CPUs. If this happens the user can reboot with the `pause_on_oops=' option. It will allow the first oopsing CPU to print an oops record just a single time. Second oopsing attempts, or oopses on other CPUs will cause those CPUs to enter a tight loop until the specified number of seconds have elapsed. The patch implements the infrastructure generically in the expectation that architectures other than x86 will find it useful. Cc: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/kernel-parameters.txt | 5 ++ arch/i386/kernel/traps.c | 3 ++ arch/i386/mm/fault.c | 39 +++++++++------ include/linux/kernel.h | 3 ++ kernel/panic.c | 97 ++++++++++++++++++++++++++++++++++++- 5 files changed, 130 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 880be3a30d8d..7b7382d0f758 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1126,6 +1126,11 @@ running once the system is up. pas16= [HW,SCSI] See header of drivers/scsi/pas16.c. + pause_on_oops= + Halt all CPUs after the first oops has been printed for + the specified number of seconds. This is to be used if + your oopses keep scrolling off the screen. + pcbit= [HW,ISDN] pcd. [PARIDE] diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 1b7ad4115d81..de5386b01d38 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -352,6 +352,8 @@ void die(const char * str, struct pt_regs * regs, long err) static int die_counter; unsigned long flags; + oops_enter(); + if (die.lock_owner != raw_smp_processor_id()) { console_verbose(); spin_lock_irqsave(&die.lock, flags); @@ -404,6 +406,7 @@ void die(const char * str, struct pt_regs * regs, long err) ssleep(5); panic("Fatal exception"); } + oops_exit(); do_exit(SIGSEGV); } diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index 47a3b72ec7b6..7f0fcf219a26 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c @@ -509,24 +509,31 @@ no_context: bust_spinlocks(1); -#ifdef CONFIG_X86_PAE - if (error_code & 16) { - pte_t *pte = lookup_address(address); - - if (pte && pte_present(*pte) && !pte_exec_kernel(*pte)) - printk(KERN_CRIT "kernel tried to execute NX-protected page - exploit attempt? (uid: %d)\n", current->uid); + if (oops_may_print()) { + #ifdef CONFIG_X86_PAE + if (error_code & 16) { + pte_t *pte = lookup_address(address); + + if (pte && pte_present(*pte) && !pte_exec_kernel(*pte)) + printk(KERN_CRIT "kernel tried to execute " + "NX-protected page - exploit attempt? " + "(uid: %d)\n", current->uid); + } + #endif + if (address < PAGE_SIZE) + printk(KERN_ALERT "BUG: unable to handle kernel NULL " + "pointer dereference"); + else + printk(KERN_ALERT "BUG: unable to handle kernel paging" + " request"); + printk(" at virtual address %08lx\n",address); + printk(KERN_ALERT " printing eip:\n"); + printk("%08lx\n", regs->eip); } -#endif - if (address < PAGE_SIZE) - printk(KERN_ALERT "BUG: unable to handle kernel NULL pointer dereference"); - else - printk(KERN_ALERT "BUG: unable to handle kernel paging request"); - printk(" at virtual address %08lx\n",address); - printk(KERN_ALERT " printing eip:\n"); - printk("%08lx\n", regs->eip); page = read_cr3(); page = ((unsigned long *) __va(page))[address >> 22]; - printk(KERN_ALERT "*pde = %08lx\n", page); + if (oops_may_print()) + printk(KERN_ALERT "*pde = %08lx\n", page); /* * We must not directly access the pte in the highpte * case, the page table might be allocated in highmem. @@ -534,7 +541,7 @@ no_context: * it's allocated already. */ #ifndef CONFIG_HIGHPTE - if (page & 1) { + if ((page & 1) && oops_may_print()) { page &= PAGE_MASK; address &= 0x003ff000; page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT]; diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 3b507bf05d09..bb6e7ddee2fd 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -91,6 +91,9 @@ extern struct notifier_block *panic_notifier_list; extern long (*panic_blink)(long time); NORET_TYPE void panic(const char * fmt, ...) __attribute__ ((NORET_AND format (printf, 1, 2))); +extern void oops_enter(void); +extern void oops_exit(void); +extern int oops_may_print(void); fastcall NORET_TYPE void do_exit(long error_code) ATTRIB_NORET; NORET_TYPE void complete_and_exit(struct completion *, long) diff --git a/kernel/panic.c b/kernel/panic.c index 126dc43f1c74..acd95adddb93 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -20,10 +20,13 @@ #include #include -int panic_timeout; int panic_on_oops; int tainted; +static int pause_on_oops; +static int pause_on_oops_flag; +static DEFINE_SPINLOCK(pause_on_oops_lock); +int panic_timeout; EXPORT_SYMBOL(panic_timeout); struct notifier_block *panic_notifier_list; @@ -174,3 +177,95 @@ void add_taint(unsigned flag) tainted |= flag; } EXPORT_SYMBOL(add_taint); + +static int __init pause_on_oops_setup(char *str) +{ + pause_on_oops = simple_strtoul(str, NULL, 0); + return 1; +} +__setup("pause_on_oops=", pause_on_oops_setup); + +static void spin_msec(int msecs) +{ + int i; + + for (i = 0; i < msecs; i++) { + touch_nmi_watchdog(); + mdelay(1); + } +} + +/* + * It just happens that oops_enter() and oops_exit() are identically + * implemented... + */ +static void do_oops_enter_exit(void) +{ + unsigned long flags; + static int spin_counter; + + if (!pause_on_oops) + return; + + spin_lock_irqsave(&pause_on_oops_lock, flags); + if (pause_on_oops_flag == 0) { + /* This CPU may now print the oops message */ + pause_on_oops_flag = 1; + } else { + /* We need to stall this CPU */ + if (!spin_counter) { + /* This CPU gets to do the counting */ + spin_counter = pause_on_oops; + do { + spin_unlock(&pause_on_oops_lock); + spin_msec(MSEC_PER_SEC); + spin_lock(&pause_on_oops_lock); + } while (--spin_counter); + pause_on_oops_flag = 0; + } else { + /* This CPU waits for a different one */ + while (spin_counter) { + spin_unlock(&pause_on_oops_lock); + spin_msec(1); + spin_lock(&pause_on_oops_lock); + } + } + } + spin_unlock_irqrestore(&pause_on_oops_lock, flags); +} + +/* + * Return true if the calling CPU is allowed to print oops-related info. This + * is a bit racy.. + */ +int oops_may_print(void) +{ + return pause_on_oops_flag == 0; +} + +/* + * Called when the architecture enters its oops handler, before it prints + * anything. If this is the first CPU to oops, and it's oopsing the first time + * then let it proceed. + * + * This is all enabled by the pause_on_oops kernel boot option. We do all this + * to ensure that oopses don't scroll off the screen. It has the side-effect + * of preventing later-oopsing CPUs from mucking up the display, too. + * + * It turns out that the CPU which is allowed to print ends up pausing for the + * right duration, whereas all the other CPUs pause for twice as long: once in + * oops_enter(), once in oops_exit(). + */ +void oops_enter(void) +{ + do_oops_enter_exit(); +} + +/* + * Called when the architecture exits its oops handler, after printing + * everything. + */ +void oops_exit(void) +{ + do_oops_enter_exit(); +} -- cgit v1.2.3 From 2178426d26661ed6e18a8d6ea0bc05c98d73600d Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 23 Mar 2006 03:01:00 -0800 Subject: [PATCH] kernel/rcupdate.c: make two structs static This patch makes two needlessly global structs static. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/rcupdate.h | 2 -- kernel/rcupdate.c | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index c2ec6c77874e..5673008b61e1 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -113,8 +113,6 @@ struct rcu_data { DECLARE_PER_CPU(struct rcu_data, rcu_data); DECLARE_PER_CPU(struct rcu_data, rcu_bh_data); -extern struct rcu_ctrlblk rcu_ctrlblk; -extern struct rcu_ctrlblk rcu_bh_ctrlblk; /* * Increment the quiescent state counter. diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index af8a2a57e17d..6df1559b1c02 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c @@ -50,13 +50,13 @@ #include /* Definition for rcupdate control block. */ -struct rcu_ctrlblk rcu_ctrlblk = { +static struct rcu_ctrlblk rcu_ctrlblk = { .cur = -300, .completed = -300, .lock = SPIN_LOCK_UNLOCKED, .cpumask = CPU_MASK_NONE, }; -struct rcu_ctrlblk rcu_bh_ctrlblk = { +static struct rcu_ctrlblk rcu_bh_ctrlblk = { .cur = -300, .completed = -300, .lock = SPIN_LOCK_UNLOCKED, -- cgit v1.2.3 From 0b2fcfdb8b4e7e379192f24ea2203163ddf5df1d Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Thu, 23 Mar 2006 03:01:02 -0800 Subject: [PATCH] atomic: add_unless cmpxchg optimise Without branch hints, the very unlikely chance of the loop repeating due to cmpxchg failure is unrolled with gcc-4 that I have tested. Improve this for architectures with a native cas/cmpxchg. llsc archs should try to implement this natively. Signed-off-by: Nick Piggin Cc: Andi Kleen Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: "David S. Miller" Cc: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-i386/atomic.h | 8 +++++++- include/asm-ia64/atomic.h | 8 +++++++- include/asm-m68k/atomic.h | 8 +++++++- include/asm-s390/atomic.h | 18 ++++++++++++++---- include/asm-sparc64/atomic.h | 10 ++++++++-- include/asm-x86_64/atomic.h | 8 +++++++- 6 files changed, 50 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/asm-i386/atomic.h b/include/asm-i386/atomic.h index 78b0032d1f29..22d80ece95cb 100644 --- a/include/asm-i386/atomic.h +++ b/include/asm-i386/atomic.h @@ -225,8 +225,14 @@ static __inline__ int atomic_sub_return(int i, atomic_t *v) ({ \ int c, old; \ c = atomic_read(v); \ - while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ + for (;;) { \ + if (unlikely(c == (u))) \ + break; \ + old = atomic_cmpxchg((v), c, c + (a)); \ + if (likely(old == c)) \ + break; \ c = old; \ + } \ c != (u); \ }) #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) diff --git a/include/asm-ia64/atomic.h b/include/asm-ia64/atomic.h index d3e0dfa99e1f..569ec7574baf 100644 --- a/include/asm-ia64/atomic.h +++ b/include/asm-ia64/atomic.h @@ -95,8 +95,14 @@ ia64_atomic64_sub (__s64 i, atomic64_t *v) ({ \ int c, old; \ c = atomic_read(v); \ - while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ + for (;;) { \ + if (unlikely(c == (u))) \ + break; \ + old = atomic_cmpxchg((v), c, c + (a)); \ + if (likely(old == c)) \ + break; \ c = old; \ + } \ c != (u); \ }) #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) diff --git a/include/asm-m68k/atomic.h b/include/asm-m68k/atomic.h index 862e497c2645..732d696d31a6 100644 --- a/include/asm-m68k/atomic.h +++ b/include/asm-m68k/atomic.h @@ -175,8 +175,14 @@ static inline void atomic_set_mask(unsigned long mask, unsigned long *v) ({ \ int c, old; \ c = atomic_read(v); \ - while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ + for (;;) { \ + if (unlikely(c == (u))) \ + break; \ + old = atomic_cmpxchg((v), c, c + (a)); \ + if (likely(old == c)) \ + break; \ c = old; \ + } \ c != (u); \ }) #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h index be6fefe223d6..de1d9926aa60 100644 --- a/include/asm-s390/atomic.h +++ b/include/asm-s390/atomic.h @@ -89,10 +89,15 @@ static __inline__ int atomic_cmpxchg(atomic_t *v, int old, int new) static __inline__ int atomic_add_unless(atomic_t *v, int a, int u) { int c, old; - c = atomic_read(v); - while (c != u && (old = atomic_cmpxchg(v, c, c + a)) != c) + for (;;) { + if (unlikely(c == u)) + break; + old = atomic_cmpxchg(v, c, c + a); + if (likely(old == c)) + break; c = old; + } return c != u; } @@ -167,10 +172,15 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long long a, long long u) { long long c, old; - c = atomic64_read(v); - while (c != u && (old = atomic64_cmpxchg(v, c, c + a)) != c) + for (;;) { + if (unlikely(c == u)) + break; + old = atomic64_cmpxchg(v, c, c + a); + if (likely(old == c)) + break; c = old; + } return c != u; } diff --git a/include/asm-sparc64/atomic.h b/include/asm-sparc64/atomic.h index 25256bdc8aae..468eb48d8142 100644 --- a/include/asm-sparc64/atomic.h +++ b/include/asm-sparc64/atomic.h @@ -78,9 +78,15 @@ extern int atomic64_sub_ret(int, atomic64_t *); ({ \ int c, old; \ c = atomic_read(v); \ - while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ + for (;;) { \ + if (unlikely(c == (u))) \ + break; \ + old = atomic_cmpxchg((v), c, c + (a)); \ + if (likely(old == c)) \ + break; \ c = old; \ - c != (u); \ + } \ + likely(c != (u)); \ }) #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) diff --git a/include/asm-x86_64/atomic.h b/include/asm-x86_64/atomic.h index 4b5cd553e772..cecbf7baa6aa 100644 --- a/include/asm-x86_64/atomic.h +++ b/include/asm-x86_64/atomic.h @@ -405,8 +405,14 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t *v) ({ \ int c, old; \ c = atomic_read(v); \ - while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ + for (;;) { \ + if (unlikely(c == (u))) \ + break; \ + old = atomic_cmpxchg((v), c, c + (a)); \ + if (likely(old == c)) \ + break; \ c = old; \ + } \ c != (u); \ }) #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) -- cgit v1.2.3 From 5a6b7951bfcca7f45f44269ea87417c74558daf8 Mon Sep 17 00:00:00 2001 From: Benjamin LaHaise Date: Thu, 23 Mar 2006 03:01:03 -0800 Subject: [PATCH] get_empty_filp tweaks, inline epoll_init_file() Eliminate a handful of cache references by keeping current in a register instead of reloading (helps x86) and avoiding the overhead of a function call. Inlining eventpoll_init_file() saves 24 bytes. Also reorder file initialization to make writes occur more sequentially. Signed-off-by: Benjamin LaHaise Cc: Davide Libenzi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/eventpoll.c | 9 --------- fs/file_table.c | 10 ++++++---- include/linux/eventpoll.h | 8 ++++++-- 3 files changed, 12 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/fs/eventpoll.c b/fs/eventpoll.c index f5d69f46ba9b..1c2b16fda13a 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -452,15 +452,6 @@ static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq) } -/* Used to initialize the epoll bits inside the "struct file" */ -void eventpoll_init_file(struct file *file) -{ - - INIT_LIST_HEAD(&file->f_ep_links); - spin_lock_init(&file->f_ep_lock); -} - - /* * This is called from eventpoll_release() to unlink files from the eventpoll * interface. We need to have this facility to cleanup correctly files that are diff --git a/fs/file_table.c b/fs/file_table.c index 44fabeaa9415..bcea1998b4de 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -88,6 +88,7 @@ int proc_nr_files(ctl_table *table, int write, struct file *filp, */ struct file *get_empty_filp(void) { + struct task_struct *tsk; static int old_max; struct file * f; @@ -112,13 +113,14 @@ struct file *get_empty_filp(void) if (security_file_alloc(f)) goto fail_sec; - eventpoll_init_file(f); + tsk = current; + INIT_LIST_HEAD(&f->f_u.fu_list); atomic_set(&f->f_count, 1); - f->f_uid = current->fsuid; - f->f_gid = current->fsgid; rwlock_init(&f->f_owner.lock); + f->f_uid = tsk->fsuid; + f->f_gid = tsk->fsgid; + eventpoll_init_file(f); /* f->f_version: 0 */ - INIT_LIST_HEAD(&f->f_u.fu_list); return f; over: diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h index 1289f0ec4c00..1e4bdfcf83a2 100644 --- a/include/linux/eventpoll.h +++ b/include/linux/eventpoll.h @@ -52,7 +52,12 @@ struct file; #ifdef CONFIG_EPOLL /* Used to initialize the epoll bits inside the "struct file" */ -void eventpoll_init_file(struct file *file); +static inline void eventpoll_init_file(struct file *file) +{ + INIT_LIST_HEAD(&file->f_ep_links); + spin_lock_init(&file->f_ep_lock); +} + /* Used to release the epoll bits inside the "struct file" */ void eventpoll_release_file(struct file *file); @@ -85,7 +90,6 @@ static inline void eventpoll_release(struct file *file) eventpoll_release_file(file); } - #else static inline void eventpoll_init_file(struct file *file) {} -- cgit v1.2.3 From 394e3902c55e667945f6f1c2bdbc59842cce70f7 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 23 Mar 2006 03:01:05 -0800 Subject: [PATCH] more for_each_cpu() conversions When we stop allocating percpu memory for not-possible CPUs we must not touch the percpu data for not-possible CPUs at all. The correct way of doing this is to test cpu_possible() or to use for_each_cpu(). This patch is a kernel-wide sweep of all instances of NR_CPUS. I found very few instances of this bug, if any. But the patch converts lots of open-coded test to use the preferred helper macros. Cc: Mikael Starvik Cc: David Howells Acked-by: Kyle McMartin Cc: Anton Blanchard Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: Paul Mundt Cc: "David S. Miller" Cc: William Lee Irwin III Cc: Andi Kleen Cc: Christian Zankel Cc: Philippe Elie Cc: Nathan Scott Cc: Jens Axboe Cc: Eric Dumazet Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/cris/kernel/irq.c | 10 ++++------ arch/frv/kernel/irq.c | 10 ++++------ arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 4 +--- arch/i386/kernel/io_apic.c | 22 +++++++++------------- arch/i386/kernel/nmi.c | 4 ++-- arch/i386/oprofile/nmi_int.c | 7 ++----- arch/m32r/kernel/irq.c | 10 ++++------ arch/mips/kernel/irq.c | 10 ++++------ arch/mips/kernel/smp.c | 4 ++-- arch/mips/sgi-ip27/ip27-irq.c | 5 +---- arch/parisc/kernel/smp.c | 25 ++++++++++--------------- arch/powerpc/kernel/irq.c | 5 ++--- arch/powerpc/kernel/setup-common.c | 5 ++--- arch/powerpc/kernel/setup_32.c | 5 ++--- arch/powerpc/platforms/powermac/smp.c | 4 +--- arch/ppc/kernel/setup.c | 10 ++++------ arch/s390/kernel/smp.c | 4 +--- arch/sh/kernel/irq.c | 5 ++--- arch/sh/kernel/setup.c | 5 ++--- arch/sh64/kernel/irq.c | 5 ++--- arch/sparc/kernel/irq.c | 5 ++--- arch/sparc/kernel/smp.c | 24 ++++++++++-------------- arch/sparc/kernel/sun4d_irq.c | 8 +++----- arch/sparc/kernel/sun4d_smp.c | 8 +++----- arch/sparc/kernel/sun4m_smp.c | 6 ++---- arch/sparc64/kernel/irq.c | 4 +--- arch/sparc64/kernel/smp.c | 30 ++++++++++++------------------ arch/x86_64/kernel/irq.c | 21 ++++++++------------- arch/x86_64/kernel/nmi.c | 4 +--- arch/xtensa/kernel/irq.c | 15 ++++++--------- drivers/net/loopback.c | 4 +--- drivers/oprofile/cpu_buffer.c | 3 +-- fs/xfs/linux-2.6/xfs_stats.c | 7 ++----- fs/xfs/linux-2.6/xfs_sysctl.c | 3 +-- include/asm-alpha/mmu_context.h | 5 ++--- include/asm-alpha/topology.h | 4 ++-- include/asm-generic/percpu.h | 7 +++---- include/asm-powerpc/percpu.h | 7 +++---- include/asm-s390/percpu.h | 7 +++---- include/asm-sparc64/percpu.h | 7 +++---- include/asm-x86_64/percpu.h | 7 +++---- include/linux/genhd.h | 14 ++++---------- 42 files changed, 137 insertions(+), 222 deletions(-) (limited to 'include') diff --git a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c index 30deaf1b728a..b504def3e346 100644 --- a/arch/cris/kernel/irq.c +++ b/arch/cris/kernel/irq.c @@ -52,9 +52,8 @@ int show_interrupts(struct seq_file *p, void *v) if (i == 0) { seq_printf(p, " "); - for (j=0; jtypename); seq_printf(p, " %s", action->name); diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c index 27ab4c30aac6..11fa326a8f62 100644 --- a/arch/frv/kernel/irq.c +++ b/arch/frv/kernel/irq.c @@ -75,9 +75,8 @@ int show_interrupts(struct seq_file *p, void *v) switch (i) { case 0: seq_printf(p, " "); - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "CPU%d ",j); + for_each_online_cpu(j) + seq_printf(p, "CPU%d ",j); seq_putc(p, '\n'); break; @@ -100,9 +99,8 @@ int show_interrupts(struct seq_file *p, void *v) #ifndef CONFIG_SMP seq_printf(p, "%10u ", kstat_irqs(i)); #else - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i - 1]); + for_each_online_cpu(j) + seq_printf(p, "%10u ", kstat_cpu(j).irqs[i - 1]); #endif level = group->sources[ix]->level - frv_irq_levels; diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index e11a09207ec8..3d5110b65cc3 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -1145,9 +1145,7 @@ static int __cpuinit powernowk8_init(void) { unsigned int i, supported_cpus = 0; - for (i=0; i CPU_IRQ(i)) { @@ -441,9 +439,7 @@ tryanothercpu: */ tmp_cpu_irq = 0; tmp_loaded = -1; - for (i = 0; i < NR_CPUS; i++) { - if (!cpu_online(i)) - continue; + for_each_online_cpu(i) { if (i != CPU_TO_PACKAGEINDEX(i)) continue; if (max_cpu_irq <= CPU_IRQ(i)) @@ -619,9 +615,7 @@ static int __init balanced_irq_init(void) if (smp_num_siblings > 1 && !cpus_empty(tmp)) physical_balance = 1; - for (i = 0; i < NR_CPUS; i++) { - if (!cpu_online(i)) - continue; + for_each_online_cpu(i) { irq_cpu_data[i].irq_delta = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL); irq_cpu_data[i].last_irq = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL); if (irq_cpu_data[i].irq_delta == NULL || irq_cpu_data[i].last_irq == NULL) { @@ -638,9 +632,11 @@ static int __init balanced_irq_init(void) else printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq"); failed: - for (i = 0; i < NR_CPUS; i++) { + for_each_cpu(i) { kfree(irq_cpu_data[i].irq_delta); + irq_cpu_data[i].irq_delta = NULL; kfree(irq_cpu_data[i].last_irq); + irq_cpu_data[i].last_irq = NULL; } return 0; } diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index 1db34effdd8d..9074818b9473 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c @@ -143,7 +143,7 @@ static int __init check_nmi_watchdog(void) local_irq_enable(); mdelay((10*1000)/nmi_hz); // wait 10 ticks - for (cpu = 0; cpu < NR_CPUS; cpu++) { + for_each_cpu(cpu) { #ifdef CONFIG_SMP /* Check cpu_callin_map here because that is set after the timer is started. */ @@ -510,7 +510,7 @@ void touch_nmi_watchdog (void) * Just reset the alert counters, (other CPUs might be * spinning on locks we hold): */ - for (i = 0; i < NR_CPUS; i++) + for_each_cpu(i) alert_counter[i] = 0; /* diff --git a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c index 0493e8b8ec49..1accce50c2c7 100644 --- a/arch/i386/oprofile/nmi_int.c +++ b/arch/i386/oprofile/nmi_int.c @@ -122,7 +122,7 @@ static void nmi_save_registers(void * dummy) static void free_msrs(void) { int i; - for (i = 0; i < NR_CPUS; ++i) { + for_each_cpu(i) { kfree(cpu_msrs[i].counters); cpu_msrs[i].counters = NULL; kfree(cpu_msrs[i].controls); @@ -138,10 +138,7 @@ static int allocate_msrs(void) size_t counters_size = sizeof(struct op_msr) * model->num_counters; int i; - for (i = 0; i < NR_CPUS; ++i) { - if (!cpu_online(i)) - continue; - + for_each_online_cpu(i) { cpu_msrs[i].counters = kmalloc(counters_size, GFP_KERNEL); if (!cpu_msrs[i].counters) { success = 0; diff --git a/arch/m32r/kernel/irq.c b/arch/m32r/kernel/irq.c index 1ce63926a3c0..a4634b06f675 100644 --- a/arch/m32r/kernel/irq.c +++ b/arch/m32r/kernel/irq.c @@ -37,9 +37,8 @@ int show_interrupts(struct seq_file *p, void *v) if (i == 0) { seq_printf(p, " "); - for (j=0; jtypename); seq_printf(p, " %s", action->name); diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index 7d93992e462c..3dd76b3d2967 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c @@ -68,9 +68,8 @@ int show_interrupts(struct seq_file *p, void *v) if (i == 0) { seq_printf(p, " "); - for (j=0; jtypename); seq_printf(p, " %s", action->name); diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 06ed90752424..78d171bfa331 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -167,8 +167,8 @@ int smp_call_function (void (*func) (void *info), void *info, int retry, mb(); /* Send a message to all other CPUs and wait for them to respond */ - for (i = 0; i < NR_CPUS; i++) - if (cpu_online(i) && i != cpu) + for_each_online_cpu(i) + if (i != cpu) core_send_ipi(i, SMP_CALL_FUNCTION); /* Wait for response */ diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index 73e5e52781d8..2854ac4c9be1 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -88,12 +88,9 @@ static inline int find_level(cpuid_t *cpunum, int irq) { int cpu, i; - for (cpu = 0; cpu <= NR_CPUS; cpu++) { + for_each_online_cpu(cpu) { struct slice_data *si = cpu_data[cpu].data; - if (!cpu_online(cpu)) - continue; - for (i = BASE_PCI_IRQ; i < LEVELS_PER_SLICE; i++) if (si->level_to_irq[i] == irq) { *cpunum = cpu; diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 25564b7ca6bb..d6ac1c60a471 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -298,8 +298,8 @@ send_IPI_allbutself(enum ipi_message_type op) { int i; - for (i = 0; i < NR_CPUS; i++) { - if (cpu_online(i) && i != smp_processor_id()) + for_each_online_cpu(i) { + if (i != smp_processor_id()) send_IPI_single(i, op); } } @@ -643,14 +643,13 @@ int sys_cpus(int argc, char **argv) if ( argc == 1 ){ #ifdef DUMP_MORE_STATE - for(i=0; iflags & SA_INTERRUPT) ? '+' : ' ', diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index 4219dd2ce3a2..41bb9596be48 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -249,11 +249,9 @@ void __init smp4d_boot_cpus(void) } else { unsigned long bogosum = 0; - for(i = 0; i < NR_CPUS; i++) { - if (cpu_isset(i, cpu_present_map)) { - bogosum += cpu_data(i).udelay_val; - smp_highest_cpu = i; - } + for_each_present_cpu(i) { + bogosum += cpu_data(i).udelay_val; + smp_highest_cpu = i; } SMP_PRINTK(("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n", cpucount + 1, bogosum/(500000/HZ), (bogosum/(5000/HZ))%100)); printk("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n", diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index fbbd8a474c4c..1dde312eebda 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -218,10 +218,8 @@ void __init smp4m_boot_cpus(void) cpu_present_map = cpumask_of_cpu(smp_processor_id()); } else { unsigned long bogosum = 0; - for(i = 0; i < NR_CPUS; i++) { - if (cpu_isset(i, cpu_present_map)) - bogosum += cpu_data(i).udelay_val; - } + for_each_present_cpu(i) + bogosum += cpu_data(i).udelay_val; printk("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n", cpucount + 1, bogosum/(500000/HZ), diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 8c93ba655b33..e505a4125e35 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -117,9 +117,7 @@ int show_interrupts(struct seq_file *p, void *v) #ifndef CONFIG_SMP seq_printf(p, "%10u ", kstat_irqs(i)); #else - for (j = 0; j < NR_CPUS; j++) { - if (!cpu_online(j)) - continue; + for_each_online_cpu(j) { seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); } diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 373a701c90a5..1b6e2ade1008 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -57,25 +57,21 @@ void smp_info(struct seq_file *m) int i; seq_printf(m, "State:\n"); - for (i = 0; i < NR_CPUS; i++) { - if (cpu_online(i)) - seq_printf(m, - "CPU%d:\t\tonline\n", i); - } + for_each_online_cpu(i) + seq_printf(m, "CPU%d:\t\tonline\n", i); } void smp_bogo(struct seq_file *m) { int i; - for (i = 0; i < NR_CPUS; i++) - if (cpu_online(i)) - seq_printf(m, - "Cpu%dBogo\t: %lu.%02lu\n" - "Cpu%dClkTck\t: %016lx\n", - i, cpu_data(i).udelay_val / (500000/HZ), - (cpu_data(i).udelay_val / (5000/HZ)) % 100, - i, cpu_data(i).clock_tick); + for_each_online_cpu(i) + seq_printf(m, + "Cpu%dBogo\t: %lu.%02lu\n" + "Cpu%dClkTck\t: %016lx\n", + i, cpu_data(i).udelay_val / (500000/HZ), + (cpu_data(i).udelay_val / (5000/HZ)) % 100, + i, cpu_data(i).clock_tick); } void __init smp_store_cpu_info(int id) @@ -1282,7 +1278,7 @@ int setup_profiling_timer(unsigned int multiplier) return -EINVAL; spin_lock_irqsave(&prof_setup_lock, flags); - for (i = 0; i < NR_CPUS; i++) + for_each_cpu(i) prof_multiplier(i) = multiplier; current_tick_offset = (timer_tick_offset / multiplier); spin_unlock_irqrestore(&prof_setup_lock, flags); @@ -1384,10 +1380,8 @@ void __init smp_cpus_done(unsigned int max_cpus) unsigned long bogosum = 0; int i; - for (i = 0; i < NR_CPUS; i++) { - if (cpu_online(i)) - bogosum += cpu_data(i).udelay_val; - } + for_each_online_cpu(i) + bogosum += cpu_data(i).udelay_val; printk("Total of %ld processors activated " "(%lu.%02lu BogoMIPS).\n", (long) num_online_cpus(), diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c index 30d2a1e545fe..d8bd0b345b1e 100644 --- a/arch/x86_64/kernel/irq.c +++ b/arch/x86_64/kernel/irq.c @@ -38,9 +38,8 @@ int show_interrupts(struct seq_file *p, void *v) if (i == 0) { seq_printf(p, " "); - for (j=0; jtypename); @@ -68,15 +65,13 @@ skip: spin_unlock_irqrestore(&irq_desc[i].lock, flags); } else if (i == NR_IRQS) { seq_printf(p, "NMI: "); - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "%10u ", cpu_pda(j)->__nmi_count); + for_each_online_cpu(j) + seq_printf(p, "%10u ", cpu_pda(j)->__nmi_count); seq_putc(p, '\n'); #ifdef CONFIG_X86_LOCAL_APIC seq_printf(p, "LOC: "); - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "%10u ", cpu_pda(j)->apic_timer_irqs); + for_each_online_cpu(j) + seq_printf(p, "%10u ", cpu_pda(j)->apic_timer_irqs); seq_putc(p, '\n'); #endif seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index 5bf17e41cd2d..66c009e10bac 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c @@ -162,9 +162,7 @@ int __init check_nmi_watchdog (void) local_irq_enable(); mdelay((10*1000)/nmi_hz); // wait 10 ticks - for (cpu = 0; cpu < NR_CPUS; cpu++) { - if (!cpu_online(cpu)) - continue; + for_each_online_cpu(cpu) { if (cpu_pda(cpu)->__nmi_count - counts[cpu] <= 5) { endflag = 1; printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n", diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c index 4cbf6d91571f..51f9bed455fa 100644 --- a/arch/xtensa/kernel/irq.c +++ b/arch/xtensa/kernel/irq.c @@ -83,9 +83,8 @@ int show_interrupts(struct seq_file *p, void *v) if (i == 0) { seq_printf(p, " "); - for (j=0; jtypename); seq_printf(p, " %s", action->name); @@ -113,9 +111,8 @@ skip: spin_unlock_irqrestore(&irq_desc[i].lock, flags); } else if (i == NR_IRQS) { seq_printf(p, "NMI: "); - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "%10u ", nmi_count(j)); + for_each_online_cpu(j) + seq_printf(p, "%10u ", nmi_count(j)); seq_putc(p, '\n'); seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); } diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 690a1aae0b34..0c13795dca38 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -172,11 +172,9 @@ static struct net_device_stats *get_stats(struct net_device *dev) memset(stats, 0, sizeof(struct net_device_stats)); - for (i=0; i < NR_CPUS; i++) { + for_each_cpu(i) { struct net_device_stats *lb_stats; - if (!cpu_possible(i)) - continue; lb_stats = &per_cpu(loopback_stats, i); stats->rx_bytes += lb_stats->rx_bytes; stats->tx_bytes += lb_stats->tx_bytes; diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 78193e4bbdb5..330d3869b41e 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -38,9 +38,8 @@ void free_cpu_buffers(void) { int i; - for_each_online_cpu(i) { + for_each_online_cpu(i) vfree(cpu_buffer[i].buffer); - } } int alloc_cpu_buffers(void) diff --git a/fs/xfs/linux-2.6/xfs_stats.c b/fs/xfs/linux-2.6/xfs_stats.c index 8955720a2c6b..713e6a7505d0 100644 --- a/fs/xfs/linux-2.6/xfs_stats.c +++ b/fs/xfs/linux-2.6/xfs_stats.c @@ -62,18 +62,15 @@ xfs_read_xfsstats( while (j < xstats[i].endpoint) { val = 0; /* sum over all cpus */ - for (c = 0; c < NR_CPUS; c++) { - if (!cpu_possible(c)) continue; + for_each_cpu(c) val += *(((__u32*)&per_cpu(xfsstats, c) + j)); - } len += sprintf(buffer + len, " %u", val); j++; } buffer[len++] = '\n'; } /* extra precision counters */ - for (i = 0; i < NR_CPUS; i++) { - if (!cpu_possible(i)) continue; + for_each_cpu(i) { xs_xstrat_bytes += per_cpu(xfsstats, i).xs_xstrat_bytes; xs_write_bytes += per_cpu(xfsstats, i).xs_write_bytes; xs_read_bytes += per_cpu(xfsstats, i).xs_read_bytes; diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c index a02564972420..7079cc837210 100644 --- a/fs/xfs/linux-2.6/xfs_sysctl.c +++ b/fs/xfs/linux-2.6/xfs_sysctl.c @@ -38,8 +38,7 @@ xfs_stats_clear_proc_handler( if (!ret && write && *valp) { printk("XFS Clearing xfsstats\n"); - for (c = 0; c < NR_CPUS; c++) { - if (!cpu_possible(c)) continue; + for_each_cpu(c) { preempt_disable(); /* save vn_active, it's a universal truth! */ vn_active = per_cpu(xfsstats, c).vn_active; diff --git a/include/asm-alpha/mmu_context.h b/include/asm-alpha/mmu_context.h index 6f92482cc96c..0c017fc181c1 100644 --- a/include/asm-alpha/mmu_context.h +++ b/include/asm-alpha/mmu_context.h @@ -231,9 +231,8 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm) { int i; - for (i = 0; i < NR_CPUS; i++) - if (cpu_online(i)) - mm->context[i] = 0; + for_each_online_cpu(i) + mm->context[i] = 0; if (tsk != current) task_thread_info(tsk)->pcb.ptbr = ((unsigned long)mm->pgd - IDENT_ADDR) >> PAGE_SHIFT; diff --git a/include/asm-alpha/topology.h b/include/asm-alpha/topology.h index eb740e280d9c..420ccde6b916 100644 --- a/include/asm-alpha/topology.h +++ b/include/asm-alpha/topology.h @@ -27,8 +27,8 @@ static inline cpumask_t node_to_cpumask(int node) cpumask_t node_cpu_mask = CPU_MASK_NONE; int cpu; - for(cpu = 0; cpu < NR_CPUS; cpu++) { - if (cpu_online(cpu) && (cpu_to_node(cpu) == node)) + for_each_online_cpu(cpu) { + if (cpu_to_node(cpu) == node) cpu_set(cpu, node_cpu_mask); } diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h index 9044aeb37828..78cf45547e31 100644 --- a/include/asm-generic/percpu.h +++ b/include/asm-generic/percpu.h @@ -19,10 +19,9 @@ extern unsigned long __per_cpu_offset[NR_CPUS]; #define percpu_modcopy(pcpudst, src, size) \ do { \ unsigned int __i; \ - for (__i = 0; __i < NR_CPUS; __i++) \ - if (cpu_possible(__i)) \ - memcpy((pcpudst)+__per_cpu_offset[__i], \ - (src), (size)); \ + for_each_cpu(__i) \ + memcpy((pcpudst)+__per_cpu_offset[__i], \ + (src), (size)); \ } while (0) #else /* ! SMP */ diff --git a/include/asm-powerpc/percpu.h b/include/asm-powerpc/percpu.h index e31922c50e53..464301cd0d03 100644 --- a/include/asm-powerpc/percpu.h +++ b/include/asm-powerpc/percpu.h @@ -27,10 +27,9 @@ #define percpu_modcopy(pcpudst, src, size) \ do { \ unsigned int __i; \ - for (__i = 0; __i < NR_CPUS; __i++) \ - if (cpu_possible(__i)) \ - memcpy((pcpudst)+__per_cpu_offset(__i), \ - (src), (size)); \ + for_each_cpu(__i) \ + memcpy((pcpudst)+__per_cpu_offset(__i), \ + (src), (size)); \ } while (0) extern void setup_per_cpu_areas(void); diff --git a/include/asm-s390/percpu.h b/include/asm-s390/percpu.h index 123fcaca295e..e10ed87094f0 100644 --- a/include/asm-s390/percpu.h +++ b/include/asm-s390/percpu.h @@ -46,10 +46,9 @@ extern unsigned long __per_cpu_offset[NR_CPUS]; #define percpu_modcopy(pcpudst, src, size) \ do { \ unsigned int __i; \ - for (__i = 0; __i < NR_CPUS; __i++) \ - if (cpu_possible(__i)) \ - memcpy((pcpudst)+__per_cpu_offset[__i], \ - (src), (size)); \ + for_each_cpu(__i) \ + memcpy((pcpudst)+__per_cpu_offset[__i], \ + (src), (size)); \ } while (0) #else /* ! SMP */ diff --git a/include/asm-sparc64/percpu.h b/include/asm-sparc64/percpu.h index aea4e51e7cd1..82032e159a76 100644 --- a/include/asm-sparc64/percpu.h +++ b/include/asm-sparc64/percpu.h @@ -26,10 +26,9 @@ register unsigned long __local_per_cpu_offset asm("g5"); #define percpu_modcopy(pcpudst, src, size) \ do { \ unsigned int __i; \ - for (__i = 0; __i < NR_CPUS; __i++) \ - if (cpu_possible(__i)) \ - memcpy((pcpudst)+__per_cpu_offset(__i), \ - (src), (size)); \ + for_each_cpu(__i) \ + memcpy((pcpudst)+__per_cpu_offset(__i), \ + (src), (size)); \ } while (0) #else /* ! SMP */ diff --git a/include/asm-x86_64/percpu.h b/include/asm-x86_64/percpu.h index 29a6b0408f75..4405b4adeaba 100644 --- a/include/asm-x86_64/percpu.h +++ b/include/asm-x86_64/percpu.h @@ -26,10 +26,9 @@ #define percpu_modcopy(pcpudst, src, size) \ do { \ unsigned int __i; \ - for (__i = 0; __i < NR_CPUS; __i++) \ - if (cpu_possible(__i)) \ - memcpy((pcpudst)+__per_cpu_offset(__i), \ - (src), (size)); \ + for_each_cpu(__i) \ + memcpy((pcpudst)+__per_cpu_offset(__i), \ + (src), (size)); \ } while (0) extern void setup_per_cpu_areas(void); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index eef5ccdcd731..fd647fde5ec1 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -149,22 +149,16 @@ struct disk_attribute { ({ \ typeof(gendiskp->dkstats->field) res = 0; \ int i; \ - for (i=0; i < NR_CPUS; i++) { \ - if (!cpu_possible(i)) \ - continue; \ + for_each_cpu(i) \ res += per_cpu_ptr(gendiskp->dkstats, i)->field; \ - } \ res; \ }) static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { int i; - for (i=0; i < NR_CPUS; i++) { - if (cpu_possible(i)) { - memset(per_cpu_ptr(gendiskp->dkstats, i), value, - sizeof (struct disk_stats)); - } - } + for_each_cpu(i) + memset(per_cpu_ptr(gendiskp->dkstats, i), value, + sizeof (struct disk_stats)); } #else -- cgit v1.2.3 From b86ff981a8252d83d6a7719ae09f3a05307e3592 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 23 Mar 2006 19:56:55 +0100 Subject: [PATCH] relay: migrate from relayfs to a generic relay API Original patch from Paul Mundt, sysfs parts removed by me since they were broken. Signed-off-by: Jens Axboe --- fs/Kconfig | 12 - fs/Makefile | 1 - fs/relayfs/Makefile | 4 - fs/relayfs/buffers.c | 190 ----------- fs/relayfs/buffers.h | 12 - fs/relayfs/inode.c | 581 ------------------------------- fs/relayfs/relay.c | 482 -------------------------- fs/relayfs/relay.h | 8 - include/linux/relay.h | 281 +++++++++++++++ init/Kconfig | 11 + kernel/Makefile | 1 + kernel/relay.c | 919 ++++++++++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 1212 insertions(+), 1290 deletions(-) delete mode 100644 fs/relayfs/Makefile delete mode 100644 fs/relayfs/buffers.c delete mode 100644 fs/relayfs/buffers.h delete mode 100644 fs/relayfs/inode.c delete mode 100644 fs/relayfs/relay.c delete mode 100644 fs/relayfs/relay.h create mode 100644 include/linux/relay.h create mode 100644 kernel/relay.c (limited to 'include') diff --git a/fs/Kconfig b/fs/Kconfig index e9749b0eecd8..c8d0a209120c 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -859,18 +859,6 @@ config RAMFS To compile this as a module, choose M here: the module will be called ramfs. -config RELAYFS_FS - tristate "Relayfs file system support" - ---help--- - Relayfs is a high-speed data relay filesystem designed to provide - an efficient mechanism for tools and facilities to relay large - amounts of data from kernel space to user space. - - To compile this code as a module, choose M here: the module will be - called relayfs. - - If unsure, say N. - config CONFIGFS_FS tristate "Userspace-driven configuration filesystem (EXPERIMENTAL)" depends on EXPERIMENTAL diff --git a/fs/Makefile b/fs/Makefile index 1db711319c80..080b3867be4d 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -91,7 +91,6 @@ obj-$(CONFIG_AUTOFS4_FS) += autofs4/ obj-$(CONFIG_ADFS_FS) += adfs/ obj-$(CONFIG_FUSE_FS) += fuse/ obj-$(CONFIG_UDF_FS) += udf/ -obj-$(CONFIG_RELAYFS_FS) += relayfs/ obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/ obj-$(CONFIG_JFS_FS) += jfs/ obj-$(CONFIG_XFS_FS) += xfs/ diff --git a/fs/relayfs/Makefile b/fs/relayfs/Makefile deleted file mode 100644 index e76e182cdb38..000000000000 --- a/fs/relayfs/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_RELAYFS_FS) += relayfs.o - -relayfs-y := relay.o inode.o buffers.o - diff --git a/fs/relayfs/buffers.c b/fs/relayfs/buffers.c deleted file mode 100644 index 10187812771e..000000000000 --- a/fs/relayfs/buffers.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * RelayFS buffer management code. - * - * Copyright (C) 2002-2005 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp - * Copyright (C) 1999-2005 - Karim Yaghmour (karim@opersys.com) - * - * This file is released under the GPL. - */ - -#include -#include -#include -#include -#include "relay.h" -#include "buffers.h" - -/* - * close() vm_op implementation for relayfs file mapping. - */ -static void relay_file_mmap_close(struct vm_area_struct *vma) -{ - struct rchan_buf *buf = vma->vm_private_data; - buf->chan->cb->buf_unmapped(buf, vma->vm_file); -} - -/* - * nopage() vm_op implementation for relayfs file mapping. - */ -static struct page *relay_buf_nopage(struct vm_area_struct *vma, - unsigned long address, - int *type) -{ - struct page *page; - struct rchan_buf *buf = vma->vm_private_data; - unsigned long offset = address - vma->vm_start; - - if (address > vma->vm_end) - return NOPAGE_SIGBUS; /* Disallow mremap */ - if (!buf) - return NOPAGE_OOM; - - page = vmalloc_to_page(buf->start + offset); - if (!page) - return NOPAGE_OOM; - get_page(page); - - if (type) - *type = VM_FAULT_MINOR; - - return page; -} - -/* - * vm_ops for relay file mappings. - */ -static struct vm_operations_struct relay_file_mmap_ops = { - .nopage = relay_buf_nopage, - .close = relay_file_mmap_close, -}; - -/** - * relay_mmap_buf: - mmap channel buffer to process address space - * @buf: relay channel buffer - * @vma: vm_area_struct describing memory to be mapped - * - * Returns 0 if ok, negative on error - * - * Caller should already have grabbed mmap_sem. - */ -int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma) -{ - unsigned long length = vma->vm_end - vma->vm_start; - struct file *filp = vma->vm_file; - - if (!buf) - return -EBADF; - - if (length != (unsigned long)buf->chan->alloc_size) - return -EINVAL; - - vma->vm_ops = &relay_file_mmap_ops; - vma->vm_private_data = buf; - buf->chan->cb->buf_mapped(buf, filp); - - return 0; -} - -/** - * relay_alloc_buf - allocate a channel buffer - * @buf: the buffer struct - * @size: total size of the buffer - * - * Returns a pointer to the resulting buffer, NULL if unsuccessful - */ -static void *relay_alloc_buf(struct rchan_buf *buf, unsigned long size) -{ - void *mem; - unsigned int i, j, n_pages; - - size = PAGE_ALIGN(size); - n_pages = size >> PAGE_SHIFT; - - buf->page_array = kcalloc(n_pages, sizeof(struct page *), GFP_KERNEL); - if (!buf->page_array) - return NULL; - - for (i = 0; i < n_pages; i++) { - buf->page_array[i] = alloc_page(GFP_KERNEL); - if (unlikely(!buf->page_array[i])) - goto depopulate; - } - mem = vmap(buf->page_array, n_pages, VM_MAP, PAGE_KERNEL); - if (!mem) - goto depopulate; - - memset(mem, 0, size); - buf->page_count = n_pages; - return mem; - -depopulate: - for (j = 0; j < i; j++) - __free_page(buf->page_array[j]); - kfree(buf->page_array); - return NULL; -} - -/** - * relay_create_buf - allocate and initialize a channel buffer - * @alloc_size: size of the buffer to allocate - * @n_subbufs: number of sub-buffers in the channel - * - * Returns channel buffer if successful, NULL otherwise - */ -struct rchan_buf *relay_create_buf(struct rchan *chan) -{ - struct rchan_buf *buf = kcalloc(1, sizeof(struct rchan_buf), GFP_KERNEL); - if (!buf) - return NULL; - - buf->padding = kmalloc(chan->n_subbufs * sizeof(size_t *), GFP_KERNEL); - if (!buf->padding) - goto free_buf; - - buf->start = relay_alloc_buf(buf, chan->alloc_size); - if (!buf->start) - goto free_buf; - - buf->chan = chan; - kref_get(&buf->chan->kref); - return buf; - -free_buf: - kfree(buf->padding); - kfree(buf); - return NULL; -} - -/** - * relay_destroy_buf - destroy an rchan_buf struct and associated buffer - * @buf: the buffer struct - */ -void relay_destroy_buf(struct rchan_buf *buf) -{ - struct rchan *chan = buf->chan; - unsigned int i; - - if (likely(buf->start)) { - vunmap(buf->start); - for (i = 0; i < buf->page_count; i++) - __free_page(buf->page_array[i]); - kfree(buf->page_array); - } - kfree(buf->padding); - kfree(buf); - kref_put(&chan->kref, relay_destroy_channel); -} - -/** - * relay_remove_buf - remove a channel buffer - * - * Removes the file from the relayfs fileystem, which also frees the - * rchan_buf_struct and the channel buffer. Should only be called from - * kref_put(). - */ -void relay_remove_buf(struct kref *kref) -{ - struct rchan_buf *buf = container_of(kref, struct rchan_buf, kref); - buf->chan->cb->remove_buf_file(buf->dentry); - relay_destroy_buf(buf); -} diff --git a/fs/relayfs/buffers.h b/fs/relayfs/buffers.h deleted file mode 100644 index 37a12493f641..000000000000 --- a/fs/relayfs/buffers.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _BUFFERS_H -#define _BUFFERS_H - -/* This inspired by rtai/shmem */ -#define FIX_SIZE(x) (((x) - 1) & PAGE_MASK) + PAGE_SIZE - -extern int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma); -extern struct rchan_buf *relay_create_buf(struct rchan *chan); -extern void relay_destroy_buf(struct rchan_buf *buf); -extern void relay_remove_buf(struct kref *kref); - -#endif/* _BUFFERS_H */ diff --git a/fs/relayfs/inode.c b/fs/relayfs/inode.c deleted file mode 100644 index 383523011aad..000000000000 --- a/fs/relayfs/inode.c +++ /dev/null @@ -1,581 +0,0 @@ -/* - * VFS-related code for RelayFS, a high-speed data relay filesystem. - * - * Copyright (C) 2003-2005 - Tom Zanussi , IBM Corp - * Copyright (C) 2003-2005 - Karim Yaghmour - * - * Based on ramfs, Copyright (C) 2002 - Linus Torvalds - * - * This file is released under the GPL. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "relay.h" -#include "buffers.h" - -#define RELAYFS_MAGIC 0xF0B4A981 - -static struct vfsmount * relayfs_mount; -static int relayfs_mount_count; - -static struct backing_dev_info relayfs_backing_dev_info = { - .ra_pages = 0, /* No readahead */ - .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, -}; - -static struct inode *relayfs_get_inode(struct super_block *sb, - int mode, - struct file_operations *fops, - void *data) -{ - struct inode *inode; - - inode = new_inode(sb); - if (!inode) - return NULL; - - inode->i_mode = mode; - inode->i_uid = 0; - inode->i_gid = 0; - inode->i_blksize = PAGE_CACHE_SIZE; - inode->i_blocks = 0; - inode->i_mapping->backing_dev_info = &relayfs_backing_dev_info; - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; - switch (mode & S_IFMT) { - case S_IFREG: - inode->i_fop = fops; - if (data) - inode->u.generic_ip = data; - break; - case S_IFDIR: - inode->i_op = &simple_dir_inode_operations; - inode->i_fop = &simple_dir_operations; - - /* directory inodes start off with i_nlink == 2 (for "." entry) */ - inode->i_nlink++; - break; - default: - break; - } - - return inode; -} - -/** - * relayfs_create_entry - create a relayfs directory or file - * @name: the name of the file to create - * @parent: parent directory - * @mode: mode - * @fops: file operations to use for the file - * @data: user-associated data for this file - * - * Returns the new dentry, NULL on failure - * - * Creates a file or directory with the specifed permissions. - */ -static struct dentry *relayfs_create_entry(const char *name, - struct dentry *parent, - int mode, - struct file_operations *fops, - void *data) -{ - struct dentry *d; - struct inode *inode; - int error = 0; - - BUG_ON(!name || !(S_ISREG(mode) || S_ISDIR(mode))); - - error = simple_pin_fs("relayfs", &relayfs_mount, &relayfs_mount_count); - if (error) { - printk(KERN_ERR "Couldn't mount relayfs: errcode %d\n", error); - return NULL; - } - - if (!parent && relayfs_mount && relayfs_mount->mnt_sb) - parent = relayfs_mount->mnt_sb->s_root; - - if (!parent) { - simple_release_fs(&relayfs_mount, &relayfs_mount_count); - return NULL; - } - - parent = dget(parent); - mutex_lock(&parent->d_inode->i_mutex); - d = lookup_one_len(name, parent, strlen(name)); - if (IS_ERR(d)) { - d = NULL; - goto release_mount; - } - - if (d->d_inode) { - d = NULL; - goto release_mount; - } - - inode = relayfs_get_inode(parent->d_inode->i_sb, mode, fops, data); - if (!inode) { - d = NULL; - goto release_mount; - } - - d_instantiate(d, inode); - dget(d); /* Extra count - pin the dentry in core */ - - if (S_ISDIR(mode)) - parent->d_inode->i_nlink++; - - goto exit; - -release_mount: - simple_release_fs(&relayfs_mount, &relayfs_mount_count); - -exit: - mutex_unlock(&parent->d_inode->i_mutex); - dput(parent); - return d; -} - -/** - * relayfs_create_file - create a file in the relay filesystem - * @name: the name of the file to create - * @parent: parent directory - * @mode: mode, if not specied the default perms are used - * @fops: file operations to use for the file - * @data: user-associated data for this file - * - * Returns file dentry if successful, NULL otherwise. - * - * The file will be created user r on behalf of current user. - */ -struct dentry *relayfs_create_file(const char *name, - struct dentry *parent, - int mode, - struct file_operations *fops, - void *data) -{ - BUG_ON(!fops); - - if (!mode) - mode = S_IRUSR; - mode = (mode & S_IALLUGO) | S_IFREG; - - return relayfs_create_entry(name, parent, mode, fops, data); -} - -/** - * relayfs_create_dir - create a directory in the relay filesystem - * @name: the name of the directory to create - * @parent: parent directory, NULL if parent should be fs root - * - * Returns directory dentry if successful, NULL otherwise. - * - * The directory will be created world rwx on behalf of current user. - */ -struct dentry *relayfs_create_dir(const char *name, struct dentry *parent) -{ - int mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; - return relayfs_create_entry(name, parent, mode, NULL, NULL); -} - -/** - * relayfs_remove - remove a file or directory in the relay filesystem - * @dentry: file or directory dentry - * - * Returns 0 if successful, negative otherwise. - */ -int relayfs_remove(struct dentry *dentry) -{ - struct dentry *parent; - int error = 0; - - if (!dentry) - return -EINVAL; - parent = dentry->d_parent; - if (!parent) - return -EINVAL; - - parent = dget(parent); - mutex_lock(&parent->d_inode->i_mutex); - if (dentry->d_inode) { - if (S_ISDIR(dentry->d_inode->i_mode)) - error = simple_rmdir(parent->d_inode, dentry); - else - error = simple_unlink(parent->d_inode, dentry); - if (!error) - d_delete(dentry); - } - if (!error) - dput(dentry); - mutex_unlock(&parent->d_inode->i_mutex); - dput(parent); - - if (!error) - simple_release_fs(&relayfs_mount, &relayfs_mount_count); - - return error; -} - -/** - * relayfs_remove_file - remove a file from relay filesystem - * @dentry: directory dentry - * - * Returns 0 if successful, negative otherwise. - */ -int relayfs_remove_file(struct dentry *dentry) -{ - return relayfs_remove(dentry); -} - -/** - * relayfs_remove_dir - remove a directory in the relay filesystem - * @dentry: directory dentry - * - * Returns 0 if successful, negative otherwise. - */ -int relayfs_remove_dir(struct dentry *dentry) -{ - return relayfs_remove(dentry); -} - -/** - * relay_file_open - open file op for relay files - * @inode: the inode - * @filp: the file - * - * Increments the channel buffer refcount. - */ -static int relay_file_open(struct inode *inode, struct file *filp) -{ - struct rchan_buf *buf = inode->u.generic_ip; - kref_get(&buf->kref); - filp->private_data = buf; - - return 0; -} - -/** - * relay_file_mmap - mmap file op for relay files - * @filp: the file - * @vma: the vma describing what to map - * - * Calls upon relay_mmap_buf to map the file into user space. - */ -static int relay_file_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct rchan_buf *buf = filp->private_data; - return relay_mmap_buf(buf, vma); -} - -/** - * relay_file_poll - poll file op for relay files - * @filp: the file - * @wait: poll table - * - * Poll implemention. - */ -static unsigned int relay_file_poll(struct file *filp, poll_table *wait) -{ - unsigned int mask = 0; - struct rchan_buf *buf = filp->private_data; - - if (buf->finalized) - return POLLERR; - - if (filp->f_mode & FMODE_READ) { - poll_wait(filp, &buf->read_wait, wait); - if (!relay_buf_empty(buf)) - mask |= POLLIN | POLLRDNORM; - } - - return mask; -} - -/** - * relay_file_release - release file op for relay files - * @inode: the inode - * @filp: the file - * - * Decrements the channel refcount, as the filesystem is - * no longer using it. - */ -static int relay_file_release(struct inode *inode, struct file *filp) -{ - struct rchan_buf *buf = filp->private_data; - kref_put(&buf->kref, relay_remove_buf); - - return 0; -} - -/** - * relay_file_read_consume - update the consumed count for the buffer - */ -static void relay_file_read_consume(struct rchan_buf *buf, - size_t read_pos, - size_t bytes_consumed) -{ - size_t subbuf_size = buf->chan->subbuf_size; - size_t n_subbufs = buf->chan->n_subbufs; - size_t read_subbuf; - - if (buf->bytes_consumed + bytes_consumed > subbuf_size) { - relay_subbufs_consumed(buf->chan, buf->cpu, 1); - buf->bytes_consumed = 0; - } - - buf->bytes_consumed += bytes_consumed; - read_subbuf = read_pos / buf->chan->subbuf_size; - if (buf->bytes_consumed + buf->padding[read_subbuf] == subbuf_size) { - if ((read_subbuf == buf->subbufs_produced % n_subbufs) && - (buf->offset == subbuf_size)) - return; - relay_subbufs_consumed(buf->chan, buf->cpu, 1); - buf->bytes_consumed = 0; - } -} - -/** - * relay_file_read_avail - boolean, are there unconsumed bytes available? - */ -static int relay_file_read_avail(struct rchan_buf *buf, size_t read_pos) -{ - size_t bytes_produced, bytes_consumed, write_offset; - size_t subbuf_size = buf->chan->subbuf_size; - size_t n_subbufs = buf->chan->n_subbufs; - size_t produced = buf->subbufs_produced % n_subbufs; - size_t consumed = buf->subbufs_consumed % n_subbufs; - - write_offset = buf->offset > subbuf_size ? subbuf_size : buf->offset; - - if (consumed > produced) { - if ((produced > n_subbufs) && - (produced + n_subbufs - consumed <= n_subbufs)) - produced += n_subbufs; - } else if (consumed == produced) { - if (buf->offset > subbuf_size) { - produced += n_subbufs; - if (buf->subbufs_produced == buf->subbufs_consumed) - consumed += n_subbufs; - } - } - - if (buf->offset > subbuf_size) - bytes_produced = (produced - 1) * subbuf_size + write_offset; - else - bytes_produced = produced * subbuf_size + write_offset; - bytes_consumed = consumed * subbuf_size + buf->bytes_consumed; - - if (bytes_produced == bytes_consumed) - return 0; - - relay_file_read_consume(buf, read_pos, 0); - - return 1; -} - -/** - * relay_file_read_subbuf_avail - return bytes available in sub-buffer - */ -static size_t relay_file_read_subbuf_avail(size_t read_pos, - struct rchan_buf *buf) -{ - size_t padding, avail = 0; - size_t read_subbuf, read_offset, write_subbuf, write_offset; - size_t subbuf_size = buf->chan->subbuf_size; - - write_subbuf = (buf->data - buf->start) / subbuf_size; - write_offset = buf->offset > subbuf_size ? subbuf_size : buf->offset; - read_subbuf = read_pos / subbuf_size; - read_offset = read_pos % subbuf_size; - padding = buf->padding[read_subbuf]; - - if (read_subbuf == write_subbuf) { - if (read_offset + padding < write_offset) - avail = write_offset - (read_offset + padding); - } else - avail = (subbuf_size - padding) - read_offset; - - return avail; -} - -/** - * relay_file_read_start_pos - find the first available byte to read - * - * If the read_pos is in the middle of padding, return the - * position of the first actually available byte, otherwise - * return the original value. - */ -static size_t relay_file_read_start_pos(size_t read_pos, - struct rchan_buf *buf) -{ - size_t read_subbuf, padding, padding_start, padding_end; - size_t subbuf_size = buf->chan->subbuf_size; - size_t n_subbufs = buf->chan->n_subbufs; - - read_subbuf = read_pos / subbuf_size; - padding = buf->padding[read_subbuf]; - padding_start = (read_subbuf + 1) * subbuf_size - padding; - padding_end = (read_subbuf + 1) * subbuf_size; - if (read_pos >= padding_start && read_pos < padding_end) { - read_subbuf = (read_subbuf + 1) % n_subbufs; - read_pos = read_subbuf * subbuf_size; - } - - return read_pos; -} - -/** - * relay_file_read_end_pos - return the new read position - */ -static size_t relay_file_read_end_pos(struct rchan_buf *buf, - size_t read_pos, - size_t count) -{ - size_t read_subbuf, padding, end_pos; - size_t subbuf_size = buf->chan->subbuf_size; - size_t n_subbufs = buf->chan->n_subbufs; - - read_subbuf = read_pos / subbuf_size; - padding = buf->padding[read_subbuf]; - if (read_pos % subbuf_size + count + padding == subbuf_size) - end_pos = (read_subbuf + 1) * subbuf_size; - else - end_pos = read_pos + count; - if (end_pos >= subbuf_size * n_subbufs) - end_pos = 0; - - return end_pos; -} - -/** - * relay_file_read - read file op for relay files - * @filp: the file - * @buffer: the userspace buffer - * @count: number of bytes to read - * @ppos: position to read from - * - * Reads count bytes or the number of bytes available in the - * current sub-buffer being read, whichever is smaller. - */ -static ssize_t relay_file_read(struct file *filp, - char __user *buffer, - size_t count, - loff_t *ppos) -{ - struct rchan_buf *buf = filp->private_data; - struct inode *inode = filp->f_dentry->d_inode; - size_t read_start, avail; - ssize_t ret = 0; - void *from; - - mutex_lock(&inode->i_mutex); - if(!relay_file_read_avail(buf, *ppos)) - goto out; - - read_start = relay_file_read_start_pos(*ppos, buf); - avail = relay_file_read_subbuf_avail(read_start, buf); - if (!avail) - goto out; - - from = buf->start + read_start; - ret = count = min(count, avail); - if (copy_to_user(buffer, from, count)) { - ret = -EFAULT; - goto out; - } - relay_file_read_consume(buf, read_start, count); - *ppos = relay_file_read_end_pos(buf, read_start, count); -out: - mutex_unlock(&inode->i_mutex); - return ret; -} - -struct file_operations relay_file_operations = { - .open = relay_file_open, - .poll = relay_file_poll, - .mmap = relay_file_mmap, - .read = relay_file_read, - .llseek = no_llseek, - .release = relay_file_release, -}; - -static struct super_operations relayfs_ops = { - .statfs = simple_statfs, - .drop_inode = generic_delete_inode, -}; - -static int relayfs_fill_super(struct super_block * sb, void * data, int silent) -{ - struct inode *inode; - struct dentry *root; - int mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; - - sb->s_blocksize = PAGE_CACHE_SIZE; - sb->s_blocksize_bits = PAGE_CACHE_SHIFT; - sb->s_magic = RELAYFS_MAGIC; - sb->s_op = &relayfs_ops; - inode = relayfs_get_inode(sb, mode, NULL, NULL); - - if (!inode) - return -ENOMEM; - - root = d_alloc_root(inode); - if (!root) { - iput(inode); - return -ENOMEM; - } - sb->s_root = root; - - return 0; -} - -static struct super_block * relayfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) -{ - return get_sb_single(fs_type, flags, data, relayfs_fill_super); -} - -static struct file_system_type relayfs_fs_type = { - .owner = THIS_MODULE, - .name = "relayfs", - .get_sb = relayfs_get_sb, - .kill_sb = kill_litter_super, -}; - -static int __init init_relayfs_fs(void) -{ - return register_filesystem(&relayfs_fs_type); -} - -static void __exit exit_relayfs_fs(void) -{ - - - - - - unregister_filesystem(&relayfs_fs_type); -} - -module_init(init_relayfs_fs) -module_exit(exit_relayfs_fs) - -EXPORT_SYMBOL_GPL(relay_file_operations); -EXPORT_SYMBOL_GPL(relayfs_create_dir); -EXPORT_SYMBOL_GPL(relayfs_remove_dir); -EXPORT_SYMBOL_GPL(relayfs_create_file); -EXPORT_SYMBOL_GPL(relayfs_remove_file); - -MODULE_AUTHOR("Tom Zanussi and Karim Yaghmour "); -MODULE_DESCRIPTION("Relay Filesystem"); -MODULE_LICENSE("GPL"); - diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c deleted file mode 100644 index abf3ceaace49..000000000000 --- a/fs/relayfs/relay.c +++ /dev/null @@ -1,482 +0,0 @@ -/* - * Public API and common code for RelayFS. - * - * See Documentation/filesystems/relayfs.txt for an overview of relayfs. - * - * Copyright (C) 2002-2005 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp - * Copyright (C) 1999-2005 - Karim Yaghmour (karim@opersys.com) - * - * This file is released under the GPL. - */ - -#include -#include -#include -#include -#include -#include -#include "relay.h" -#include "buffers.h" - -/** - * relay_buf_empty - boolean, is the channel buffer empty? - * @buf: channel buffer - * - * Returns 1 if the buffer is empty, 0 otherwise. - */ -int relay_buf_empty(struct rchan_buf *buf) -{ - return (buf->subbufs_produced - buf->subbufs_consumed) ? 0 : 1; -} - -/** - * relay_buf_full - boolean, is the channel buffer full? - * @buf: channel buffer - * - * Returns 1 if the buffer is full, 0 otherwise. - */ -int relay_buf_full(struct rchan_buf *buf) -{ - size_t ready = buf->subbufs_produced - buf->subbufs_consumed; - return (ready >= buf->chan->n_subbufs) ? 1 : 0; -} - -/* - * High-level relayfs kernel API and associated functions. - */ - -/* - * rchan_callback implementations defining default channel behavior. Used - * in place of corresponding NULL values in client callback struct. - */ - -/* - * subbuf_start() default callback. Does nothing. - */ -static int subbuf_start_default_callback (struct rchan_buf *buf, - void *subbuf, - void *prev_subbuf, - size_t prev_padding) -{ - if (relay_buf_full(buf)) - return 0; - - return 1; -} - -/* - * buf_mapped() default callback. Does nothing. - */ -static void buf_mapped_default_callback(struct rchan_buf *buf, - struct file *filp) -{ -} - -/* - * buf_unmapped() default callback. Does nothing. - */ -static void buf_unmapped_default_callback(struct rchan_buf *buf, - struct file *filp) -{ -} - -/* - * create_buf_file_create() default callback. Creates file to represent buf. - */ -static struct dentry *create_buf_file_default_callback(const char *filename, - struct dentry *parent, - int mode, - struct rchan_buf *buf, - int *is_global) -{ - return relayfs_create_file(filename, parent, mode, - &relay_file_operations, buf); -} - -/* - * remove_buf_file() default callback. Removes file representing relay buffer. - */ -static int remove_buf_file_default_callback(struct dentry *dentry) -{ - return relayfs_remove(dentry); -} - -/* relay channel default callbacks */ -static struct rchan_callbacks default_channel_callbacks = { - .subbuf_start = subbuf_start_default_callback, - .buf_mapped = buf_mapped_default_callback, - .buf_unmapped = buf_unmapped_default_callback, - .create_buf_file = create_buf_file_default_callback, - .remove_buf_file = remove_buf_file_default_callback, -}; - -/** - * wakeup_readers - wake up readers waiting on a channel - * @private: the channel buffer - * - * This is the work function used to defer reader waking. The - * reason waking is deferred is that calling directly from write - * causes problems if you're writing from say the scheduler. - */ -static void wakeup_readers(void *private) -{ - struct rchan_buf *buf = private; - wake_up_interruptible(&buf->read_wait); -} - -/** - * __relay_reset - reset a channel buffer - * @buf: the channel buffer - * @init: 1 if this is a first-time initialization - * - * See relay_reset for description of effect. - */ -static inline void __relay_reset(struct rchan_buf *buf, unsigned int init) -{ - size_t i; - - if (init) { - init_waitqueue_head(&buf->read_wait); - kref_init(&buf->kref); - INIT_WORK(&buf->wake_readers, NULL, NULL); - } else { - cancel_delayed_work(&buf->wake_readers); - flush_scheduled_work(); - } - - buf->subbufs_produced = 0; - buf->subbufs_consumed = 0; - buf->bytes_consumed = 0; - buf->finalized = 0; - buf->data = buf->start; - buf->offset = 0; - - for (i = 0; i < buf->chan->n_subbufs; i++) - buf->padding[i] = 0; - - buf->chan->cb->subbuf_start(buf, buf->data, NULL, 0); -} - -/** - * relay_reset - reset the channel - * @chan: the channel - * - * This has the effect of erasing all data from all channel buffers - * and restarting the channel in its initial state. The buffers - * are not freed, so any mappings are still in effect. - * - * NOTE: Care should be taken that the channel isn't actually - * being used by anything when this call is made. - */ -void relay_reset(struct rchan *chan) -{ - unsigned int i; - struct rchan_buf *prev = NULL; - - if (!chan) - return; - - for (i = 0; i < NR_CPUS; i++) { - if (!chan->buf[i] || chan->buf[i] == prev) - break; - __relay_reset(chan->buf[i], 0); - prev = chan->buf[i]; - } -} - -/** - * relay_open_buf - create a new channel buffer in relayfs - * - * Internal - used by relay_open(). - */ -static struct rchan_buf *relay_open_buf(struct rchan *chan, - const char *filename, - struct dentry *parent, - int *is_global) -{ - struct rchan_buf *buf; - struct dentry *dentry; - - if (*is_global) - return chan->buf[0]; - - buf = relay_create_buf(chan); - if (!buf) - return NULL; - - /* Create file in fs */ - dentry = chan->cb->create_buf_file(filename, parent, S_IRUSR, - buf, is_global); - if (!dentry) { - relay_destroy_buf(buf); - return NULL; - } - - buf->dentry = dentry; - __relay_reset(buf, 1); - - return buf; -} - -/** - * relay_close_buf - close a channel buffer - * @buf: channel buffer - * - * Marks the buffer finalized and restores the default callbacks. - * The channel buffer and channel buffer data structure are then freed - * automatically when the last reference is given up. - */ -static inline void relay_close_buf(struct rchan_buf *buf) -{ - buf->finalized = 1; - buf->chan->cb = &default_channel_callbacks; - cancel_delayed_work(&buf->wake_readers); - flush_scheduled_work(); - kref_put(&buf->kref, relay_remove_buf); -} - -static inline void setup_callbacks(struct rchan *chan, - struct rchan_callbacks *cb) -{ - if (!cb) { - chan->cb = &default_channel_callbacks; - return; - } - - if (!cb->subbuf_start) - cb->subbuf_start = subbuf_start_default_callback; - if (!cb->buf_mapped) - cb->buf_mapped = buf_mapped_default_callback; - if (!cb->buf_unmapped) - cb->buf_unmapped = buf_unmapped_default_callback; - if (!cb->create_buf_file) - cb->create_buf_file = create_buf_file_default_callback; - if (!cb->remove_buf_file) - cb->remove_buf_file = remove_buf_file_default_callback; - chan->cb = cb; -} - -/** - * relay_open - create a new relayfs channel - * @base_filename: base name of files to create - * @parent: dentry of parent directory, NULL for root directory - * @subbuf_size: size of sub-buffers - * @n_subbufs: number of sub-buffers - * @cb: client callback functions - * - * Returns channel pointer if successful, NULL otherwise. - * - * Creates a channel buffer for each cpu using the sizes and - * attributes specified. The created channel buffer files - * will be named base_filename0...base_filenameN-1. File - * permissions will be S_IRUSR. - */ -struct rchan *relay_open(const char *base_filename, - struct dentry *parent, - size_t subbuf_size, - size_t n_subbufs, - struct rchan_callbacks *cb) -{ - unsigned int i; - struct rchan *chan; - char *tmpname; - int is_global = 0; - - if (!base_filename) - return NULL; - - if (!(subbuf_size && n_subbufs)) - return NULL; - - chan = kcalloc(1, sizeof(struct rchan), GFP_KERNEL); - if (!chan) - return NULL; - - chan->version = RELAYFS_CHANNEL_VERSION; - chan->n_subbufs = n_subbufs; - chan->subbuf_size = subbuf_size; - chan->alloc_size = FIX_SIZE(subbuf_size * n_subbufs); - setup_callbacks(chan, cb); - kref_init(&chan->kref); - - tmpname = kmalloc(NAME_MAX + 1, GFP_KERNEL); - if (!tmpname) - goto free_chan; - - for_each_online_cpu(i) { - sprintf(tmpname, "%s%d", base_filename, i); - chan->buf[i] = relay_open_buf(chan, tmpname, parent, - &is_global); - chan->buf[i]->cpu = i; - if (!chan->buf[i]) - goto free_bufs; - } - - kfree(tmpname); - return chan; - -free_bufs: - for (i = 0; i < NR_CPUS; i++) { - if (!chan->buf[i]) - break; - relay_close_buf(chan->buf[i]); - if (is_global) - break; - } - kfree(tmpname); - -free_chan: - kref_put(&chan->kref, relay_destroy_channel); - return NULL; -} - -/** - * relay_switch_subbuf - switch to a new sub-buffer - * @buf: channel buffer - * @length: size of current event - * - * Returns either the length passed in or 0 if full. - - * Performs sub-buffer-switch tasks such as invoking callbacks, - * updating padding counts, waking up readers, etc. - */ -size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length) -{ - void *old, *new; - size_t old_subbuf, new_subbuf; - - if (unlikely(length > buf->chan->subbuf_size)) - goto toobig; - - if (buf->offset != buf->chan->subbuf_size + 1) { - buf->prev_padding = buf->chan->subbuf_size - buf->offset; - old_subbuf = buf->subbufs_produced % buf->chan->n_subbufs; - buf->padding[old_subbuf] = buf->prev_padding; - buf->subbufs_produced++; - if (waitqueue_active(&buf->read_wait)) { - PREPARE_WORK(&buf->wake_readers, wakeup_readers, buf); - schedule_delayed_work(&buf->wake_readers, 1); - } - } - - old = buf->data; - new_subbuf = buf->subbufs_produced % buf->chan->n_subbufs; - new = buf->start + new_subbuf * buf->chan->subbuf_size; - buf->offset = 0; - if (!buf->chan->cb->subbuf_start(buf, new, old, buf->prev_padding)) { - buf->offset = buf->chan->subbuf_size + 1; - return 0; - } - buf->data = new; - buf->padding[new_subbuf] = 0; - - if (unlikely(length + buf->offset > buf->chan->subbuf_size)) - goto toobig; - - return length; - -toobig: - buf->chan->last_toobig = length; - return 0; -} - -/** - * relay_subbufs_consumed - update the buffer's sub-buffers-consumed count - * @chan: the channel - * @cpu: the cpu associated with the channel buffer to update - * @subbufs_consumed: number of sub-buffers to add to current buf's count - * - * Adds to the channel buffer's consumed sub-buffer count. - * subbufs_consumed should be the number of sub-buffers newly consumed, - * not the total consumed. - * - * NOTE: kernel clients don't need to call this function if the channel - * mode is 'overwrite'. - */ -void relay_subbufs_consumed(struct rchan *chan, - unsigned int cpu, - size_t subbufs_consumed) -{ - struct rchan_buf *buf; - - if (!chan) - return; - - if (cpu >= NR_CPUS || !chan->buf[cpu]) - return; - - buf = chan->buf[cpu]; - buf->subbufs_consumed += subbufs_consumed; - if (buf->subbufs_consumed > buf->subbufs_produced) - buf->subbufs_consumed = buf->subbufs_produced; -} - -/** - * relay_destroy_channel - free the channel struct - * - * Should only be called from kref_put(). - */ -void relay_destroy_channel(struct kref *kref) -{ - struct rchan *chan = container_of(kref, struct rchan, kref); - kfree(chan); -} - -/** - * relay_close - close the channel - * @chan: the channel - * - * Closes all channel buffers and frees the channel. - */ -void relay_close(struct rchan *chan) -{ - unsigned int i; - struct rchan_buf *prev = NULL; - - if (!chan) - return; - - for (i = 0; i < NR_CPUS; i++) { - if (!chan->buf[i] || chan->buf[i] == prev) - break; - relay_close_buf(chan->buf[i]); - prev = chan->buf[i]; - } - - if (chan->last_toobig) - printk(KERN_WARNING "relayfs: one or more items not logged " - "[item size (%Zd) > sub-buffer size (%Zd)]\n", - chan->last_toobig, chan->subbuf_size); - - kref_put(&chan->kref, relay_destroy_channel); -} - -/** - * relay_flush - close the channel - * @chan: the channel - * - * Flushes all channel buffers i.e. forces buffer switch. - */ -void relay_flush(struct rchan *chan) -{ - unsigned int i; - struct rchan_buf *prev = NULL; - - if (!chan) - return; - - for (i = 0; i < NR_CPUS; i++) { - if (!chan->buf[i] || chan->buf[i] == prev) - break; - relay_switch_subbuf(chan->buf[i], 0); - prev = chan->buf[i]; - } -} - -EXPORT_SYMBOL_GPL(relay_open); -EXPORT_SYMBOL_GPL(relay_close); -EXPORT_SYMBOL_GPL(relay_flush); -EXPORT_SYMBOL_GPL(relay_reset); -EXPORT_SYMBOL_GPL(relay_subbufs_consumed); -EXPORT_SYMBOL_GPL(relay_switch_subbuf); -EXPORT_SYMBOL_GPL(relay_buf_full); diff --git a/fs/relayfs/relay.h b/fs/relayfs/relay.h deleted file mode 100644 index 0993d3e5753b..000000000000 --- a/fs/relayfs/relay.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _RELAY_H -#define _RELAY_H - -extern int relayfs_remove(struct dentry *dentry); -extern int relay_buf_empty(struct rchan_buf *buf); -extern void relay_destroy_channel(struct kref *kref); - -#endif /* _RELAY_H */ diff --git a/include/linux/relay.h b/include/linux/relay.h new file mode 100644 index 000000000000..4bcc1531d6a9 --- /dev/null +++ b/include/linux/relay.h @@ -0,0 +1,281 @@ +/* + * linux/include/linux/relay.h + * + * Copyright (C) 2002, 2003 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp + * Copyright (C) 1999, 2000, 2001, 2002 - Karim Yaghmour (karim@opersys.com) + * + * CONFIG_RELAY definitions and declarations + */ + +#ifndef _LINUX_RELAY_H +#define _LINUX_RELAY_H + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Needs a _much_ better name... */ +#define FIX_SIZE(x) ((((x) - 1) & PAGE_MASK) + PAGE_SIZE) + +/* + * Tracks changes to rchan/rchan_buf structs + */ +#define RELAYFS_CHANNEL_VERSION 6 + +/* + * Per-cpu relay channel buffer + */ +struct rchan_buf +{ + void *start; /* start of channel buffer */ + void *data; /* start of current sub-buffer */ + size_t offset; /* current offset into sub-buffer */ + size_t subbufs_produced; /* count of sub-buffers produced */ + size_t subbufs_consumed; /* count of sub-buffers consumed */ + struct rchan *chan; /* associated channel */ + wait_queue_head_t read_wait; /* reader wait queue */ + struct work_struct wake_readers; /* reader wake-up work struct */ + struct dentry *dentry; /* channel file dentry */ + struct kref kref; /* channel buffer refcount */ + struct page **page_array; /* array of current buffer pages */ + unsigned int page_count; /* number of current buffer pages */ + unsigned int finalized; /* buffer has been finalized */ + size_t *padding; /* padding counts per sub-buffer */ + size_t prev_padding; /* temporary variable */ + size_t bytes_consumed; /* bytes consumed in cur read subbuf */ + unsigned int cpu; /* this buf's cpu */ +} ____cacheline_aligned; + +/* + * Relay channel data structure + */ +struct rchan +{ + u32 version; /* the version of this struct */ + size_t subbuf_size; /* sub-buffer size */ + size_t n_subbufs; /* number of sub-buffers per buffer */ + size_t alloc_size; /* total buffer size allocated */ + struct rchan_callbacks *cb; /* client callbacks */ + struct kref kref; /* channel refcount */ + void *private_data; /* for user-defined data */ + size_t last_toobig; /* tried to log event > subbuf size */ + struct rchan_buf *buf[NR_CPUS]; /* per-cpu channel buffers */ +}; + +/* + * Relay channel client callbacks + */ +struct rchan_callbacks +{ + /* + * subbuf_start - called on buffer-switch to a new sub-buffer + * @buf: the channel buffer containing the new sub-buffer + * @subbuf: the start of the new sub-buffer + * @prev_subbuf: the start of the previous sub-buffer + * @prev_padding: unused space at the end of previous sub-buffer + * + * The client should return 1 to continue logging, 0 to stop + * logging. + * + * NOTE: subbuf_start will also be invoked when the buffer is + * created, so that the first sub-buffer can be initialized + * if necessary. In this case, prev_subbuf will be NULL. + * + * NOTE: the client can reserve bytes at the beginning of the new + * sub-buffer by calling subbuf_start_reserve() in this callback. + */ + int (*subbuf_start) (struct rchan_buf *buf, + void *subbuf, + void *prev_subbuf, + size_t prev_padding); + + /* + * buf_mapped - relay buffer mmap notification + * @buf: the channel buffer + * @filp: relay file pointer + * + * Called when a relay file is successfully mmapped + */ + void (*buf_mapped)(struct rchan_buf *buf, + struct file *filp); + + /* + * buf_unmapped - relay buffer unmap notification + * @buf: the channel buffer + * @filp: relay file pointer + * + * Called when a relay file is successfully unmapped + */ + void (*buf_unmapped)(struct rchan_buf *buf, + struct file *filp); + /* + * create_buf_file - create file to represent a relay channel buffer + * @filename: the name of the file to create + * @parent: the parent of the file to create + * @mode: the mode of the file to create + * @buf: the channel buffer + * @is_global: outparam - set non-zero if the buffer should be global + * + * Called during relay_open(), once for each per-cpu buffer, + * to allow the client to create a file to be used to + * represent the corresponding channel buffer. If the file is + * created outside of relay, the parent must also exist in + * that filesystem. + * + * The callback should return the dentry of the file created + * to represent the relay buffer. + * + * Setting the is_global outparam to a non-zero value will + * cause relay_open() to create a single global buffer rather + * than the default set of per-cpu buffers. + * + * See Documentation/filesystems/relayfs.txt for more info. + */ + struct dentry *(*create_buf_file)(const char *filename, + struct dentry *parent, + int mode, + struct rchan_buf *buf, + int *is_global); + + /* + * remove_buf_file - remove file representing a relay channel buffer + * @dentry: the dentry of the file to remove + * + * Called during relay_close(), once for each per-cpu buffer, + * to allow the client to remove a file used to represent a + * channel buffer. + * + * The callback should return 0 if successful, negative if not. + */ + int (*remove_buf_file)(struct dentry *dentry); +}; + +/* + * CONFIG_RELAY kernel API, kernel/relay.c + */ + +struct rchan *relay_open(const char *base_filename, + struct dentry *parent, + size_t subbuf_size, + size_t n_subbufs, + struct rchan_callbacks *cb); +extern void relay_close(struct rchan *chan); +extern void relay_flush(struct rchan *chan); +extern void relay_subbufs_consumed(struct rchan *chan, + unsigned int cpu, + size_t consumed); +extern void relay_reset(struct rchan *chan); +extern int relay_buf_full(struct rchan_buf *buf); + +extern size_t relay_switch_subbuf(struct rchan_buf *buf, + size_t length); + +/** + * relay_write - write data into the channel + * @chan: relay channel + * @data: data to be written + * @length: number of bytes to write + * + * Writes data into the current cpu's channel buffer. + * + * Protects the buffer by disabling interrupts. Use this + * if you might be logging from interrupt context. Try + * __relay_write() if you know you won't be logging from + * interrupt context. + */ +static inline void relay_write(struct rchan *chan, + const void *data, + size_t length) +{ + unsigned long flags; + struct rchan_buf *buf; + + local_irq_save(flags); + buf = chan->buf[smp_processor_id()]; + if (unlikely(buf->offset + length > chan->subbuf_size)) + length = relay_switch_subbuf(buf, length); + memcpy(buf->data + buf->offset, data, length); + buf->offset += length; + local_irq_restore(flags); +} + +/** + * __relay_write - write data into the channel + * @chan: relay channel + * @data: data to be written + * @length: number of bytes to write + * + * Writes data into the current cpu's channel buffer. + * + * Protects the buffer by disabling preemption. Use + * relay_write() if you might be logging from interrupt + * context. + */ +static inline void __relay_write(struct rchan *chan, + const void *data, + size_t length) +{ + struct rchan_buf *buf; + + buf = chan->buf[get_cpu()]; + if (unlikely(buf->offset + length > buf->chan->subbuf_size)) + length = relay_switch_subbuf(buf, length); + memcpy(buf->data + buf->offset, data, length); + buf->offset += length; + put_cpu(); +} + +/** + * relay_reserve - reserve slot in channel buffer + * @chan: relay channel + * @length: number of bytes to reserve + * + * Returns pointer to reserved slot, NULL if full. + * + * Reserves a slot in the current cpu's channel buffer. + * Does not protect the buffer at all - caller must provide + * appropriate synchronization. + */ +static inline void *relay_reserve(struct rchan *chan, size_t length) +{ + void *reserved; + struct rchan_buf *buf = chan->buf[smp_processor_id()]; + + if (unlikely(buf->offset + length > buf->chan->subbuf_size)) { + length = relay_switch_subbuf(buf, length); + if (!length) + return NULL; + } + reserved = buf->data + buf->offset; + buf->offset += length; + + return reserved; +} + +/** + * subbuf_start_reserve - reserve bytes at the start of a sub-buffer + * @buf: relay channel buffer + * @length: number of bytes to reserve + * + * Helper function used to reserve bytes at the beginning of + * a sub-buffer in the subbuf_start() callback. + */ +static inline void subbuf_start_reserve(struct rchan_buf *buf, + size_t length) +{ + BUG_ON(length >= buf->chan->subbuf_size - 1); + buf->offset = length; +} + +/* + * exported relay file operations, kernel/relay.c + */ +extern struct file_operations relay_file_operations; + +#endif /* _LINUX_RELAY_H */ + diff --git a/init/Kconfig b/init/Kconfig index 38416a199def..1d19fd25204b 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -214,6 +214,17 @@ config CPUSETS Say N if unsure. +config RELAY + bool "Kernel->user space relay support (formerly relayfs)" + help + This option enables support for relay interface support in + certain file systems (such as debugfs). + It is designed to provide an efficient mechanism for tools and + facilities to relay large amounts of data from kernel space to + user space. + + If unsure, say N. + source "usr/Kconfig" config UID16 diff --git a/kernel/Makefile b/kernel/Makefile index 4ae0fbde815d..aebd7a78984e 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o obj-$(CONFIG_GENERIC_HARDIRQS) += irq/ obj-$(CONFIG_SECCOMP) += seccomp.o obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o +obj-$(CONFIG_RELAY) += relay.o ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y) # According to Alan Modra , the -fno-omit-frame-pointer is diff --git a/kernel/relay.c b/kernel/relay.c new file mode 100644 index 000000000000..9358e8eb8476 --- /dev/null +++ b/kernel/relay.c @@ -0,0 +1,919 @@ +/* + * Public API and common code for kernel->userspace relay file support. + * + * See Documentation/filesystems/relayfs.txt for an overview of relayfs. + * + * Copyright (C) 2002-2005 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp + * Copyright (C) 1999-2005 - Karim Yaghmour (karim@opersys.com) + * + * Moved to kernel/relay.c by Paul Mundt, 2006. + * + * This file is released under the GPL. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * close() vm_op implementation for relay file mapping. + */ +static void relay_file_mmap_close(struct vm_area_struct *vma) +{ + struct rchan_buf *buf = vma->vm_private_data; + buf->chan->cb->buf_unmapped(buf, vma->vm_file); +} + +/* + * nopage() vm_op implementation for relay file mapping. + */ +static struct page *relay_buf_nopage(struct vm_area_struct *vma, + unsigned long address, + int *type) +{ + struct page *page; + struct rchan_buf *buf = vma->vm_private_data; + unsigned long offset = address - vma->vm_start; + + if (address > vma->vm_end) + return NOPAGE_SIGBUS; /* Disallow mremap */ + if (!buf) + return NOPAGE_OOM; + + page = vmalloc_to_page(buf->start + offset); + if (!page) + return NOPAGE_OOM; + get_page(page); + + if (type) + *type = VM_FAULT_MINOR; + + return page; +} + +/* + * vm_ops for relay file mappings. + */ +static struct vm_operations_struct relay_file_mmap_ops = { + .nopage = relay_buf_nopage, + .close = relay_file_mmap_close, +}; + +/** + * relay_mmap_buf: - mmap channel buffer to process address space + * @buf: relay channel buffer + * @vma: vm_area_struct describing memory to be mapped + * + * Returns 0 if ok, negative on error + * + * Caller should already have grabbed mmap_sem. + */ +int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma) +{ + unsigned long length = vma->vm_end - vma->vm_start; + struct file *filp = vma->vm_file; + + if (!buf) + return -EBADF; + + if (length != (unsigned long)buf->chan->alloc_size) + return -EINVAL; + + vma->vm_ops = &relay_file_mmap_ops; + vma->vm_private_data = buf; + buf->chan->cb->buf_mapped(buf, filp); + + return 0; +} + +/** + * relay_alloc_buf - allocate a channel buffer + * @buf: the buffer struct + * @size: total size of the buffer + * + * Returns a pointer to the resulting buffer, NULL if unsuccessful + */ +static void *relay_alloc_buf(struct rchan_buf *buf, unsigned long size) +{ + void *mem; + unsigned int i, j, n_pages; + + size = PAGE_ALIGN(size); + n_pages = size >> PAGE_SHIFT; + + buf->page_array = kcalloc(n_pages, sizeof(struct page *), GFP_KERNEL); + if (!buf->page_array) + return NULL; + + for (i = 0; i < n_pages; i++) { + buf->page_array[i] = alloc_page(GFP_KERNEL); + if (unlikely(!buf->page_array[i])) + goto depopulate; + } + mem = vmap(buf->page_array, n_pages, VM_MAP, PAGE_KERNEL); + if (!mem) + goto depopulate; + + memset(mem, 0, size); + buf->page_count = n_pages; + return mem; + +depopulate: + for (j = 0; j < i; j++) + __free_page(buf->page_array[j]); + kfree(buf->page_array); + return NULL; +} + +/** + * relay_create_buf - allocate and initialize a channel buffer + * @alloc_size: size of the buffer to allocate + * @n_subbufs: number of sub-buffers in the channel + * + * Returns channel buffer if successful, NULL otherwise + */ +struct rchan_buf *relay_create_buf(struct rchan *chan) +{ + struct rchan_buf *buf = kcalloc(1, sizeof(struct rchan_buf), GFP_KERNEL); + if (!buf) + return NULL; + + buf->padding = kmalloc(chan->n_subbufs * sizeof(size_t *), GFP_KERNEL); + if (!buf->padding) + goto free_buf; + + buf->start = relay_alloc_buf(buf, chan->alloc_size); + if (!buf->start) + goto free_buf; + + buf->chan = chan; + kref_get(&buf->chan->kref); + return buf; + +free_buf: + kfree(buf->padding); + kfree(buf); + return NULL; +} + +/** + * relay_destroy_channel - free the channel struct + * + * Should only be called from kref_put(). + */ +void relay_destroy_channel(struct kref *kref) +{ + struct rchan *chan = container_of(kref, struct rchan, kref); + kfree(chan); +} + +/** + * relay_destroy_buf - destroy an rchan_buf struct and associated buffer + * @buf: the buffer struct + */ +void relay_destroy_buf(struct rchan_buf *buf) +{ + struct rchan *chan = buf->chan; + unsigned int i; + + if (likely(buf->start)) { + vunmap(buf->start); + for (i = 0; i < buf->page_count; i++) + __free_page(buf->page_array[i]); + kfree(buf->page_array); + } + kfree(buf->padding); + kfree(buf); + kref_put(&chan->kref, relay_destroy_channel); +} + +/** + * relay_remove_buf - remove a channel buffer + * + * Removes the file from the fileystem, which also frees the + * rchan_buf_struct and the channel buffer. Should only be called from + * kref_put(). + */ +void relay_remove_buf(struct kref *kref) +{ + struct rchan_buf *buf = container_of(kref, struct rchan_buf, kref); + buf->chan->cb->remove_buf_file(buf->dentry); + relay_destroy_buf(buf); +} + +/** + * relay_buf_empty - boolean, is the channel buffer empty? + * @buf: channel buffer + * + * Returns 1 if the buffer is empty, 0 otherwise. + */ +int relay_buf_empty(struct rchan_buf *buf) +{ + return (buf->subbufs_produced - buf->subbufs_consumed) ? 0 : 1; +} +EXPORT_SYMBOL_GPL(relay_buf_empty); + +/** + * relay_buf_full - boolean, is the channel buffer full? + * @buf: channel buffer + * + * Returns 1 if the buffer is full, 0 otherwise. + */ +int relay_buf_full(struct rchan_buf *buf) +{ + size_t ready = buf->subbufs_produced - buf->subbufs_consumed; + return (ready >= buf->chan->n_subbufs) ? 1 : 0; +} +EXPORT_SYMBOL_GPL(relay_buf_full); + +/* + * High-level relay kernel API and associated functions. + */ + +/* + * rchan_callback implementations defining default channel behavior. Used + * in place of corresponding NULL values in client callback struct. + */ + +/* + * subbuf_start() default callback. Does nothing. + */ +static int subbuf_start_default_callback (struct rchan_buf *buf, + void *subbuf, + void *prev_subbuf, + size_t prev_padding) +{ + if (relay_buf_full(buf)) + return 0; + + return 1; +} + +/* + * buf_mapped() default callback. Does nothing. + */ +static void buf_mapped_default_callback(struct rchan_buf *buf, + struct file *filp) +{ +} + +/* + * buf_unmapped() default callback. Does nothing. + */ +static void buf_unmapped_default_callback(struct rchan_buf *buf, + struct file *filp) +{ +} + +/* + * create_buf_file_create() default callback. Does nothing. + */ +static struct dentry *create_buf_file_default_callback(const char *filename, + struct dentry *parent, + int mode, + struct rchan_buf *buf, + int *is_global) +{ + return NULL; +} + +/* + * remove_buf_file() default callback. Does nothing. + */ +static int remove_buf_file_default_callback(struct dentry *dentry) +{ + return -EINVAL; +} + +/* relay channel default callbacks */ +static struct rchan_callbacks default_channel_callbacks = { + .subbuf_start = subbuf_start_default_callback, + .buf_mapped = buf_mapped_default_callback, + .buf_unmapped = buf_unmapped_default_callback, + .create_buf_file = create_buf_file_default_callback, + .remove_buf_file = remove_buf_file_default_callback, +}; + +/** + * wakeup_readers - wake up readers waiting on a channel + * @private: the channel buffer + * + * This is the work function used to defer reader waking. The + * reason waking is deferred is that calling directly from write + * causes problems if you're writing from say the scheduler. + */ +static void wakeup_readers(void *private) +{ + struct rchan_buf *buf = private; + wake_up_interruptible(&buf->read_wait); +} + +/** + * __relay_reset - reset a channel buffer + * @buf: the channel buffer + * @init: 1 if this is a first-time initialization + * + * See relay_reset for description of effect. + */ +static inline void __relay_reset(struct rchan_buf *buf, unsigned int init) +{ + size_t i; + + if (init) { + init_waitqueue_head(&buf->read_wait); + kref_init(&buf->kref); + INIT_WORK(&buf->wake_readers, NULL, NULL); + } else { + cancel_delayed_work(&buf->wake_readers); + flush_scheduled_work(); + } + + buf->subbufs_produced = 0; + buf->subbufs_consumed = 0; + buf->bytes_consumed = 0; + buf->finalized = 0; + buf->data = buf->start; + buf->offset = 0; + + for (i = 0; i < buf->chan->n_subbufs; i++) + buf->padding[i] = 0; + + buf->chan->cb->subbuf_start(buf, buf->data, NULL, 0); +} + +/** + * relay_reset - reset the channel + * @chan: the channel + * + * This has the effect of erasing all data from all channel buffers + * and restarting the channel in its initial state. The buffers + * are not freed, so any mappings are still in effect. + * + * NOTE: Care should be taken that the channel isn't actually + * being used by anything when this call is made. + */ +void relay_reset(struct rchan *chan) +{ + unsigned int i; + struct rchan_buf *prev = NULL; + + if (!chan) + return; + + for (i = 0; i < NR_CPUS; i++) { + if (!chan->buf[i] || chan->buf[i] == prev) + break; + __relay_reset(chan->buf[i], 0); + prev = chan->buf[i]; + } +} +EXPORT_SYMBOL_GPL(relay_reset); + +/** + * relay_open_buf - create a new relay channel buffer + * + * Internal - used by relay_open(). + */ +static struct rchan_buf *relay_open_buf(struct rchan *chan, + const char *filename, + struct dentry *parent, + int *is_global) +{ + struct rchan_buf *buf; + struct dentry *dentry; + + if (*is_global) + return chan->buf[0]; + + buf = relay_create_buf(chan); + if (!buf) + return NULL; + + /* Create file in fs */ + dentry = chan->cb->create_buf_file(filename, parent, S_IRUSR, + buf, is_global); + if (!dentry) { + relay_destroy_buf(buf); + return NULL; + } + + buf->dentry = dentry; + __relay_reset(buf, 1); + + return buf; +} + +/** + * relay_close_buf - close a channel buffer + * @buf: channel buffer + * + * Marks the buffer finalized and restores the default callbacks. + * The channel buffer and channel buffer data structure are then freed + * automatically when the last reference is given up. + */ +static inline void relay_close_buf(struct rchan_buf *buf) +{ + buf->finalized = 1; + cancel_delayed_work(&buf->wake_readers); + flush_scheduled_work(); + kref_put(&buf->kref, relay_remove_buf); +} + +static inline void setup_callbacks(struct rchan *chan, + struct rchan_callbacks *cb) +{ + if (!cb) { + chan->cb = &default_channel_callbacks; + return; + } + + if (!cb->subbuf_start) + cb->subbuf_start = subbuf_start_default_callback; + if (!cb->buf_mapped) + cb->buf_mapped = buf_mapped_default_callback; + if (!cb->buf_unmapped) + cb->buf_unmapped = buf_unmapped_default_callback; + if (!cb->create_buf_file) + cb->create_buf_file = create_buf_file_default_callback; + if (!cb->remove_buf_file) + cb->remove_buf_file = remove_buf_file_default_callback; + chan->cb = cb; +} + +/** + * relay_open - create a new relay channel + * @base_filename: base name of files to create + * @parent: dentry of parent directory, NULL for root directory + * @subbuf_size: size of sub-buffers + * @n_subbufs: number of sub-buffers + * @cb: client callback functions + * + * Returns channel pointer if successful, NULL otherwise. + * + * Creates a channel buffer for each cpu using the sizes and + * attributes specified. The created channel buffer files + * will be named base_filename0...base_filenameN-1. File + * permissions will be S_IRUSR. + */ +struct rchan *relay_open(const char *base_filename, + struct dentry *parent, + size_t subbuf_size, + size_t n_subbufs, + struct rchan_callbacks *cb) +{ + unsigned int i; + struct rchan *chan; + char *tmpname; + int is_global = 0; + + if (!base_filename) + return NULL; + + if (!(subbuf_size && n_subbufs)) + return NULL; + + chan = kcalloc(1, sizeof(struct rchan), GFP_KERNEL); + if (!chan) + return NULL; + + chan->version = RELAYFS_CHANNEL_VERSION; + chan->n_subbufs = n_subbufs; + chan->subbuf_size = subbuf_size; + chan->alloc_size = FIX_SIZE(subbuf_size * n_subbufs); + setup_callbacks(chan, cb); + kref_init(&chan->kref); + + tmpname = kmalloc(NAME_MAX + 1, GFP_KERNEL); + if (!tmpname) + goto free_chan; + + for_each_online_cpu(i) { + sprintf(tmpname, "%s%d", base_filename, i); + chan->buf[i] = relay_open_buf(chan, tmpname, parent, + &is_global); + if (!chan->buf[i]) + goto free_bufs; + + chan->buf[i]->cpu = i; + } + + kfree(tmpname); + return chan; + +free_bufs: + for (i = 0; i < NR_CPUS; i++) { + if (!chan->buf[i]) + break; + relay_close_buf(chan->buf[i]); + if (is_global) + break; + } + kfree(tmpname); + +free_chan: + kref_put(&chan->kref, relay_destroy_channel); + return NULL; +} +EXPORT_SYMBOL_GPL(relay_open); + +/** + * relay_switch_subbuf - switch to a new sub-buffer + * @buf: channel buffer + * @length: size of current event + * + * Returns either the length passed in or 0 if full. + * + * Performs sub-buffer-switch tasks such as invoking callbacks, + * updating padding counts, waking up readers, etc. + */ +size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length) +{ + void *old, *new; + size_t old_subbuf, new_subbuf; + + if (unlikely(length > buf->chan->subbuf_size)) + goto toobig; + + if (buf->offset != buf->chan->subbuf_size + 1) { + buf->prev_padding = buf->chan->subbuf_size - buf->offset; + old_subbuf = buf->subbufs_produced % buf->chan->n_subbufs; + buf->padding[old_subbuf] = buf->prev_padding; + buf->subbufs_produced++; + if (waitqueue_active(&buf->read_wait)) { + PREPARE_WORK(&buf->wake_readers, wakeup_readers, buf); + schedule_delayed_work(&buf->wake_readers, 1); + } + } + + old = buf->data; + new_subbuf = buf->subbufs_produced % buf->chan->n_subbufs; + new = buf->start + new_subbuf * buf->chan->subbuf_size; + buf->offset = 0; + if (!buf->chan->cb->subbuf_start(buf, new, old, buf->prev_padding)) { + buf->offset = buf->chan->subbuf_size + 1; + return 0; + } + buf->data = new; + buf->padding[new_subbuf] = 0; + + if (unlikely(length + buf->offset > buf->chan->subbuf_size)) + goto toobig; + + return length; + +toobig: + buf->chan->last_toobig = length; + return 0; +} +EXPORT_SYMBOL_GPL(relay_switch_subbuf); + +/** + * relay_subbufs_consumed - update the buffer's sub-buffers-consumed count + * @chan: the channel + * @cpu: the cpu associated with the channel buffer to update + * @subbufs_consumed: number of sub-buffers to add to current buf's count + * + * Adds to the channel buffer's consumed sub-buffer count. + * subbufs_consumed should be the number of sub-buffers newly consumed, + * not the total consumed. + * + * NOTE: kernel clients don't need to call this function if the channel + * mode is 'overwrite'. + */ +void relay_subbufs_consumed(struct rchan *chan, + unsigned int cpu, + size_t subbufs_consumed) +{ + struct rchan_buf *buf; + + if (!chan) + return; + + if (cpu >= NR_CPUS || !chan->buf[cpu]) + return; + + buf = chan->buf[cpu]; + buf->subbufs_consumed += subbufs_consumed; + if (buf->subbufs_consumed > buf->subbufs_produced) + buf->subbufs_consumed = buf->subbufs_produced; +} +EXPORT_SYMBOL_GPL(relay_subbufs_consumed); + +/** + * relay_close - close the channel + * @chan: the channel + * + * Closes all channel buffers and frees the channel. + */ +void relay_close(struct rchan *chan) +{ + unsigned int i; + struct rchan_buf *prev = NULL; + + if (!chan) + return; + + for (i = 0; i < NR_CPUS; i++) { + if (!chan->buf[i] || chan->buf[i] == prev) + break; + relay_close_buf(chan->buf[i]); + prev = chan->buf[i]; + } + + if (chan->last_toobig) + printk(KERN_WARNING "relay: one or more items not logged " + "[item size (%Zd) > sub-buffer size (%Zd)]\n", + chan->last_toobig, chan->subbuf_size); + + kref_put(&chan->kref, relay_destroy_channel); +} +EXPORT_SYMBOL_GPL(relay_close); + +/** + * relay_flush - close the channel + * @chan: the channel + * + * Flushes all channel buffers i.e. forces buffer switch. + */ +void relay_flush(struct rchan *chan) +{ + unsigned int i; + struct rchan_buf *prev = NULL; + + if (!chan) + return; + + for (i = 0; i < NR_CPUS; i++) { + if (!chan->buf[i] || chan->buf[i] == prev) + break; + relay_switch_subbuf(chan->buf[i], 0); + prev = chan->buf[i]; + } +} +EXPORT_SYMBOL_GPL(relay_flush); + +/** + * relay_file_open - open file op for relay files + * @inode: the inode + * @filp: the file + * + * Increments the channel buffer refcount. + */ +static int relay_file_open(struct inode *inode, struct file *filp) +{ + struct rchan_buf *buf = inode->u.generic_ip; + kref_get(&buf->kref); + filp->private_data = buf; + + return 0; +} + +/** + * relay_file_mmap - mmap file op for relay files + * @filp: the file + * @vma: the vma describing what to map + * + * Calls upon relay_mmap_buf to map the file into user space. + */ +static int relay_file_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct rchan_buf *buf = filp->private_data; + return relay_mmap_buf(buf, vma); +} + +/** + * relay_file_poll - poll file op for relay files + * @filp: the file + * @wait: poll table + * + * Poll implemention. + */ +static unsigned int relay_file_poll(struct file *filp, poll_table *wait) +{ + unsigned int mask = 0; + struct rchan_buf *buf = filp->private_data; + + if (buf->finalized) + return POLLERR; + + if (filp->f_mode & FMODE_READ) { + poll_wait(filp, &buf->read_wait, wait); + if (!relay_buf_empty(buf)) + mask |= POLLIN | POLLRDNORM; + } + + return mask; +} + +/** + * relay_file_release - release file op for relay files + * @inode: the inode + * @filp: the file + * + * Decrements the channel refcount, as the filesystem is + * no longer using it. + */ +static int relay_file_release(struct inode *inode, struct file *filp) +{ + struct rchan_buf *buf = filp->private_data; + kref_put(&buf->kref, relay_remove_buf); + + return 0; +} + +/** + * relay_file_read_consume - update the consumed count for the buffer + */ +static void relay_file_read_consume(struct rchan_buf *buf, + size_t read_pos, + size_t bytes_consumed) +{ + size_t subbuf_size = buf->chan->subbuf_size; + size_t n_subbufs = buf->chan->n_subbufs; + size_t read_subbuf; + + if (buf->bytes_consumed + bytes_consumed > subbuf_size) { + relay_subbufs_consumed(buf->chan, buf->cpu, 1); + buf->bytes_consumed = 0; + } + + buf->bytes_consumed += bytes_consumed; + read_subbuf = read_pos / buf->chan->subbuf_size; + if (buf->bytes_consumed + buf->padding[read_subbuf] == subbuf_size) { + if ((read_subbuf == buf->subbufs_produced % n_subbufs) && + (buf->offset == subbuf_size)) + return; + relay_subbufs_consumed(buf->chan, buf->cpu, 1); + buf->bytes_consumed = 0; + } +} + +/** + * relay_file_read_avail - boolean, are there unconsumed bytes available? + */ +static int relay_file_read_avail(struct rchan_buf *buf, size_t read_pos) +{ + size_t bytes_produced, bytes_consumed, write_offset; + size_t subbuf_size = buf->chan->subbuf_size; + size_t n_subbufs = buf->chan->n_subbufs; + size_t produced = buf->subbufs_produced % n_subbufs; + size_t consumed = buf->subbufs_consumed % n_subbufs; + + write_offset = buf->offset > subbuf_size ? subbuf_size : buf->offset; + + if (consumed > produced) { + if ((produced > n_subbufs) && + (produced + n_subbufs - consumed <= n_subbufs)) + produced += n_subbufs; + } else if (consumed == produced) { + if (buf->offset > subbuf_size) { + produced += n_subbufs; + if (buf->subbufs_produced == buf->subbufs_consumed) + consumed += n_subbufs; + } + } + + if (buf->offset > subbuf_size) + bytes_produced = (produced - 1) * subbuf_size + write_offset; + else + bytes_produced = produced * subbuf_size + write_offset; + bytes_consumed = consumed * subbuf_size + buf->bytes_consumed; + + if (bytes_produced == bytes_consumed) + return 0; + + relay_file_read_consume(buf, read_pos, 0); + + return 1; +} + +/** + * relay_file_read_subbuf_avail - return bytes available in sub-buffer + */ +static size_t relay_file_read_subbuf_avail(size_t read_pos, + struct rchan_buf *buf) +{ + size_t padding, avail = 0; + size_t read_subbuf, read_offset, write_subbuf, write_offset; + size_t subbuf_size = buf->chan->subbuf_size; + + write_subbuf = (buf->data - buf->start) / subbuf_size; + write_offset = buf->offset > subbuf_size ? subbuf_size : buf->offset; + read_subbuf = read_pos / subbuf_size; + read_offset = read_pos % subbuf_size; + padding = buf->padding[read_subbuf]; + + if (read_subbuf == write_subbuf) { + if (read_offset + padding < write_offset) + avail = write_offset - (read_offset + padding); + } else + avail = (subbuf_size - padding) - read_offset; + + return avail; +} + +/** + * relay_file_read_start_pos - find the first available byte to read + * + * If the read_pos is in the middle of padding, return the + * position of the first actually available byte, otherwise + * return the original value. + */ +static size_t relay_file_read_start_pos(size_t read_pos, + struct rchan_buf *buf) +{ + size_t read_subbuf, padding, padding_start, padding_end; + size_t subbuf_size = buf->chan->subbuf_size; + size_t n_subbufs = buf->chan->n_subbufs; + + read_subbuf = read_pos / subbuf_size; + padding = buf->padding[read_subbuf]; + padding_start = (read_subbuf + 1) * subbuf_size - padding; + padding_end = (read_subbuf + 1) * subbuf_size; + if (read_pos >= padding_start && read_pos < padding_end) { + read_subbuf = (read_subbuf + 1) % n_subbufs; + read_pos = read_subbuf * subbuf_size; + } + + return read_pos; +} + +/** + * relay_file_read_end_pos - return the new read position + */ +static size_t relay_file_read_end_pos(struct rchan_buf *buf, + size_t read_pos, + size_t count) +{ + size_t read_subbuf, padding, end_pos; + size_t subbuf_size = buf->chan->subbuf_size; + size_t n_subbufs = buf->chan->n_subbufs; + + read_subbuf = read_pos / subbuf_size; + padding = buf->padding[read_subbuf]; + if (read_pos % subbuf_size + count + padding == subbuf_size) + end_pos = (read_subbuf + 1) * subbuf_size; + else + end_pos = read_pos + count; + if (end_pos >= subbuf_size * n_subbufs) + end_pos = 0; + + return end_pos; +} + +/** + * relay_file_read - read file op for relay files + * @filp: the file + * @buffer: the userspace buffer + * @count: number of bytes to read + * @ppos: position to read from + * + * Reads count bytes or the number of bytes available in the + * current sub-buffer being read, whichever is smaller. + */ +static ssize_t relay_file_read(struct file *filp, + char __user *buffer, + size_t count, + loff_t *ppos) +{ + struct rchan_buf *buf = filp->private_data; + struct inode *inode = filp->f_dentry->d_inode; + size_t read_start, avail; + ssize_t ret = 0; + void *from; + + mutex_lock(&inode->i_mutex); + if(!relay_file_read_avail(buf, *ppos)) + goto out; + + read_start = relay_file_read_start_pos(*ppos, buf); + avail = relay_file_read_subbuf_avail(read_start, buf); + if (!avail) + goto out; + + from = buf->start + read_start; + ret = count = min(count, avail); + if (copy_to_user(buffer, from, count)) { + ret = -EFAULT; + goto out; + } + relay_file_read_consume(buf, read_start, count); + *ppos = relay_file_read_end_pos(buf, read_start, count); +out: + mutex_unlock(&inode->i_mutex); + return ret; +} + +struct file_operations relay_file_operations = { + .open = relay_file_open, + .poll = relay_file_poll, + .mmap = relay_file_mmap, + .read = relay_file_read, + .llseek = no_llseek, + .release = relay_file_release, +}; +EXPORT_SYMBOL_GPL(relay_file_operations); -- cgit v1.2.3 From 2056a782f8e7e65fd4bfd027506b4ce1c5e9ccd4 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 23 Mar 2006 20:00:26 +0100 Subject: [PATCH] Block queue IO tracing support (blktrace) as of 2006-03-23 Signed-off-by: Jens Axboe --- block/Kconfig | 12 + block/Makefile | 2 + block/blktrace.c | 538 +++++++++++++++++++++++++++++++++++++++++++ block/elevator.c | 4 + block/ioctl.c | 6 + block/ll_rw_blk.c | 44 +++- drivers/block/cciss.c | 2 + drivers/md/dm.c | 13 +- fs/bio.c | 4 + fs/compat_ioctl.c | 1 + include/linux/blkdev.h | 3 + include/linux/blktrace_api.h | 277 ++++++++++++++++++++++ include/linux/compat_ioctl.h | 4 + include/linux/fs.h | 4 + include/linux/sched.h | 1 + kernel/fork.c | 1 + mm/highmem.c | 3 + 17 files changed, 916 insertions(+), 3 deletions(-) create mode 100644 block/blktrace.c create mode 100644 include/linux/blktrace_api.h (limited to 'include') diff --git a/block/Kconfig b/block/Kconfig index 377f6dd20e17..96783645092d 100644 --- a/block/Kconfig +++ b/block/Kconfig @@ -11,4 +11,16 @@ config LBD your machine, or if you want to have a raid or loopback device bigger than 2TB. Otherwise say N. +config BLK_DEV_IO_TRACE + bool "Support for tracing block io actions" + select RELAY + select DEBUG_FS + help + Say Y here, if you want to be able to trace the block layer actions + on a given queue. Tracing allows you to see any traffic happening + on a block device queue. For more information (and the user space + support tools needed), fetch the blktrace app from: + + git://brick.kernel.dk/data/git/blktrace.git + source block/Kconfig.iosched diff --git a/block/Makefile b/block/Makefile index 7e4f93e2b44e..c05de0e0037f 100644 --- a/block/Makefile +++ b/block/Makefile @@ -8,3 +8,5 @@ obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o obj-$(CONFIG_IOSCHED_AS) += as-iosched.o obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o + +obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o diff --git a/block/blktrace.c b/block/blktrace.c new file mode 100644 index 000000000000..36f3a172275f --- /dev/null +++ b/block/blktrace.c @@ -0,0 +1,538 @@ +/* + * Copyright (C) 2006 Jens Axboe + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_PER_CPU(unsigned long long, blk_trace_cpu_offset) = { 0, }; +static unsigned int blktrace_seq __read_mostly = 1; + +/* + * Send out a notify for this process, if we haven't done so since a trace + * started + */ +static void trace_note_tsk(struct blk_trace *bt, struct task_struct *tsk) +{ + struct blk_io_trace *t; + + t = relay_reserve(bt->rchan, sizeof(*t) + sizeof(tsk->comm)); + if (t) { + t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION; + t->device = bt->dev; + t->action = BLK_TC_ACT(BLK_TC_NOTIFY); + t->pid = tsk->pid; + t->cpu = smp_processor_id(); + t->pdu_len = sizeof(tsk->comm); + memcpy((void *) t + sizeof(*t), tsk->comm, t->pdu_len); + tsk->btrace_seq = blktrace_seq; + } +} + +static int act_log_check(struct blk_trace *bt, u32 what, sector_t sector, + pid_t pid) +{ + if (((bt->act_mask << BLK_TC_SHIFT) & what) == 0) + return 1; + if (sector < bt->start_lba || sector > bt->end_lba) + return 1; + if (bt->pid && pid != bt->pid) + return 1; + + return 0; +} + +/* + * Data direction bit lookup + */ +static u32 ddir_act[2] __read_mostly = { BLK_TC_ACT(BLK_TC_READ), BLK_TC_ACT(BLK_TC_WRITE) }; + +/* + * Bio action bits of interest + */ +static u32 bio_act[3] __read_mostly = { 0, BLK_TC_ACT(BLK_TC_BARRIER), BLK_TC_ACT(BLK_TC_SYNC) }; + +/* + * More could be added as needed, taking care to increment the decrementer + * to get correct indexing + */ +#define trace_barrier_bit(rw) \ + (((rw) & (1 << BIO_RW_BARRIER)) >> (BIO_RW_BARRIER - 0)) +#define trace_sync_bit(rw) \ + (((rw) & (1 << BIO_RW_SYNC)) >> (BIO_RW_SYNC - 1)) + +/* + * The worker for the various blk_add_trace*() types. Fills out a + * blk_io_trace structure and places it in a per-cpu subbuffer. + */ +void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, + int rw, u32 what, int error, int pdu_len, void *pdu_data) +{ + struct task_struct *tsk = current; + struct blk_io_trace *t; + unsigned long flags; + unsigned long *sequence; + pid_t pid; + int cpu; + + if (unlikely(bt->trace_state != Blktrace_running)) + return; + + what |= ddir_act[rw & WRITE]; + what |= bio_act[trace_barrier_bit(rw)]; + what |= bio_act[trace_sync_bit(rw)]; + + pid = tsk->pid; + if (unlikely(act_log_check(bt, what, sector, pid))) + return; + + /* + * A word about the locking here - we disable interrupts to reserve + * some space in the relay per-cpu buffer, to prevent an irq + * from coming in and stepping on our toes. Once reserved, it's + * enough to get preemption disabled to prevent read of this data + * before we are through filling it. get_cpu()/put_cpu() does this + * for us + */ + local_irq_save(flags); + + if (unlikely(tsk->btrace_seq != blktrace_seq)) + trace_note_tsk(bt, tsk); + + t = relay_reserve(bt->rchan, sizeof(*t) + pdu_len); + if (t) { + cpu = smp_processor_id(); + sequence = per_cpu_ptr(bt->sequence, cpu); + + t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION; + t->sequence = ++(*sequence); + t->time = sched_clock() - per_cpu(blk_trace_cpu_offset, cpu); + t->sector = sector; + t->bytes = bytes; + t->action = what; + t->pid = pid; + t->device = bt->dev; + t->cpu = cpu; + t->error = error; + t->pdu_len = pdu_len; + + if (pdu_len) + memcpy((void *) t + sizeof(*t), pdu_data, pdu_len); + } + + local_irq_restore(flags); +} + +EXPORT_SYMBOL_GPL(__blk_add_trace); + +static struct dentry *blk_tree_root; +static struct mutex blk_tree_mutex; +static unsigned int root_users; + +static inline void blk_remove_root(void) +{ + if (blk_tree_root) { + debugfs_remove(blk_tree_root); + blk_tree_root = NULL; + } +} + +static void blk_remove_tree(struct dentry *dir) +{ + mutex_lock(&blk_tree_mutex); + debugfs_remove(dir); + if (--root_users == 0) + blk_remove_root(); + mutex_unlock(&blk_tree_mutex); +} + +static struct dentry *blk_create_tree(const char *blk_name) +{ + struct dentry *dir = NULL; + + mutex_lock(&blk_tree_mutex); + + if (!blk_tree_root) { + blk_tree_root = debugfs_create_dir("block", NULL); + if (!blk_tree_root) + goto err; + } + + dir = debugfs_create_dir(blk_name, blk_tree_root); + if (dir) + root_users++; + else + blk_remove_root(); + +err: + mutex_unlock(&blk_tree_mutex); + return dir; +} + +static void blk_trace_cleanup(struct blk_trace *bt) +{ + relay_close(bt->rchan); + debugfs_remove(bt->dropped_file); + blk_remove_tree(bt->dir); + free_percpu(bt->sequence); + kfree(bt); +} + +static int blk_trace_remove(request_queue_t *q) +{ + struct blk_trace *bt; + + bt = xchg(&q->blk_trace, NULL); + if (!bt) + return -EINVAL; + + if (bt->trace_state == Blktrace_setup || + bt->trace_state == Blktrace_stopped) + blk_trace_cleanup(bt); + + return 0; +} + +static int blk_dropped_open(struct inode *inode, struct file *filp) +{ + filp->private_data = inode->u.generic_ip; + + return 0; +} + +static ssize_t blk_dropped_read(struct file *filp, char __user *buffer, + size_t count, loff_t *ppos) +{ + struct blk_trace *bt = filp->private_data; + char buf[16]; + + snprintf(buf, sizeof(buf), "%u\n", atomic_read(&bt->dropped)); + + return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf)); +} + +static struct file_operations blk_dropped_fops = { + .owner = THIS_MODULE, + .open = blk_dropped_open, + .read = blk_dropped_read, +}; + +/* + * Keep track of how many times we encountered a full subbuffer, to aid + * the user space app in telling how many lost events there were. + */ +static int blk_subbuf_start_callback(struct rchan_buf *buf, void *subbuf, + void *prev_subbuf, size_t prev_padding) +{ + struct blk_trace *bt; + + if (!relay_buf_full(buf)) + return 1; + + bt = buf->chan->private_data; + atomic_inc(&bt->dropped); + return 0; +} + +static int blk_remove_buf_file_callback(struct dentry *dentry) +{ + debugfs_remove(dentry); + return 0; +} + +static struct dentry *blk_create_buf_file_callback(const char *filename, + struct dentry *parent, + int mode, + struct rchan_buf *buf, + int *is_global) +{ + return debugfs_create_file(filename, mode, parent, buf, + &relay_file_operations); +} + +static struct rchan_callbacks blk_relay_callbacks = { + .subbuf_start = blk_subbuf_start_callback, + .create_buf_file = blk_create_buf_file_callback, + .remove_buf_file = blk_remove_buf_file_callback, +}; + +/* + * Setup everything required to start tracing + */ +static int blk_trace_setup(request_queue_t *q, struct block_device *bdev, + char __user *arg) +{ + struct blk_user_trace_setup buts; + struct blk_trace *old_bt, *bt = NULL; + struct dentry *dir = NULL; + char b[BDEVNAME_SIZE]; + int ret, i; + + if (copy_from_user(&buts, arg, sizeof(buts))) + return -EFAULT; + + if (!buts.buf_size || !buts.buf_nr) + return -EINVAL; + + strcpy(buts.name, bdevname(bdev, b)); + + /* + * some device names have larger paths - convert the slashes + * to underscores for this to work as expected + */ + for (i = 0; i < strlen(buts.name); i++) + if (buts.name[i] == '/') + buts.name[i] = '_'; + + if (copy_to_user(arg, &buts, sizeof(buts))) + return -EFAULT; + + ret = -ENOMEM; + bt = kzalloc(sizeof(*bt), GFP_KERNEL); + if (!bt) + goto err; + + bt->sequence = alloc_percpu(unsigned long); + if (!bt->sequence) + goto err; + + ret = -ENOENT; + dir = blk_create_tree(buts.name); + if (!dir) + goto err; + + bt->dir = dir; + bt->dev = bdev->bd_dev; + atomic_set(&bt->dropped, 0); + + ret = -EIO; + bt->dropped_file = debugfs_create_file("dropped", 0444, dir, bt, &blk_dropped_fops); + if (!bt->dropped_file) + goto err; + + bt->rchan = relay_open("trace", dir, buts.buf_size, buts.buf_nr, &blk_relay_callbacks); + if (!bt->rchan) + goto err; + bt->rchan->private_data = bt; + + bt->act_mask = buts.act_mask; + if (!bt->act_mask) + bt->act_mask = (u16) -1; + + bt->start_lba = buts.start_lba; + bt->end_lba = buts.end_lba; + if (!bt->end_lba) + bt->end_lba = -1ULL; + + bt->pid = buts.pid; + bt->trace_state = Blktrace_setup; + + ret = -EBUSY; + old_bt = xchg(&q->blk_trace, bt); + if (old_bt) { + (void) xchg(&q->blk_trace, old_bt); + goto err; + } + + return 0; +err: + if (dir) + blk_remove_tree(dir); + if (bt) { + if (bt->dropped_file) + debugfs_remove(bt->dropped_file); + if (bt->sequence) + free_percpu(bt->sequence); + if (bt->rchan) + relay_close(bt->rchan); + kfree(bt); + } + return ret; +} + +static int blk_trace_startstop(request_queue_t *q, int start) +{ + struct blk_trace *bt; + int ret; + + if ((bt = q->blk_trace) == NULL) + return -EINVAL; + + /* + * For starting a trace, we can transition from a setup or stopped + * trace. For stopping a trace, the state must be running + */ + ret = -EINVAL; + if (start) { + if (bt->trace_state == Blktrace_setup || + bt->trace_state == Blktrace_stopped) { + blktrace_seq++; + smp_mb(); + bt->trace_state = Blktrace_running; + ret = 0; + } + } else { + if (bt->trace_state == Blktrace_running) { + bt->trace_state = Blktrace_stopped; + relay_flush(bt->rchan); + ret = 0; + } + } + + return ret; +} + +/** + * blk_trace_ioctl: - handle the ioctls associated with tracing + * @bdev: the block device + * @cmd: the ioctl cmd + * @arg: the argument data, if any + * + **/ +int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg) +{ + request_queue_t *q; + int ret, start = 0; + + q = bdev_get_queue(bdev); + if (!q) + return -ENXIO; + + mutex_lock(&bdev->bd_mutex); + + switch (cmd) { + case BLKTRACESETUP: + ret = blk_trace_setup(q, bdev, arg); + break; + case BLKTRACESTART: + start = 1; + case BLKTRACESTOP: + ret = blk_trace_startstop(q, start); + break; + case BLKTRACETEARDOWN: + ret = blk_trace_remove(q); + break; + default: + ret = -ENOTTY; + break; + } + + mutex_unlock(&bdev->bd_mutex); + return ret; +} + +/** + * blk_trace_shutdown: - stop and cleanup trace structures + * @q: the request queue associated with the device + * + **/ +void blk_trace_shutdown(request_queue_t *q) +{ + blk_trace_startstop(q, 0); + blk_trace_remove(q); +} + +/* + * Average offset over two calls to sched_clock() with a gettimeofday() + * in the middle + */ +static void blk_check_time(unsigned long long *t) +{ + unsigned long long a, b; + struct timeval tv; + + a = sched_clock(); + do_gettimeofday(&tv); + b = sched_clock(); + + *t = tv.tv_sec * 1000000000 + tv.tv_usec * 1000; + *t -= (a + b) / 2; +} + +static void blk_trace_check_cpu_time(void *data) +{ + unsigned long long *t; + int cpu = get_cpu(); + + t = &per_cpu(blk_trace_cpu_offset, cpu); + + /* + * Just call it twice, hopefully the second call will be cache hot + * and a little more precise + */ + blk_check_time(t); + blk_check_time(t); + + put_cpu(); +} + +/* + * Call blk_trace_check_cpu_time() on each CPU to calibrate our inter-CPU + * timings + */ +static void blk_trace_calibrate_offsets(void) +{ + unsigned long flags; + + smp_call_function(blk_trace_check_cpu_time, NULL, 1, 1); + local_irq_save(flags); + blk_trace_check_cpu_time(NULL); + local_irq_restore(flags); +} + +static void blk_trace_set_ht_offsets(void) +{ +#if defined(CONFIG_SCHED_SMT) + int cpu, i; + + /* + * now make sure HT siblings have the same time offset + */ + preempt_disable(); + for_each_online_cpu(cpu) { + unsigned long long *cpu_off, *sibling_off; + + for_each_cpu_mask(i, cpu_sibling_map[cpu]) { + if (i == cpu) + continue; + + cpu_off = &per_cpu(blk_trace_cpu_offset, cpu); + sibling_off = &per_cpu(blk_trace_cpu_offset, i); + *sibling_off = *cpu_off; + } + } + preempt_enable(); +#endif +} + +static __init int blk_trace_init(void) +{ + mutex_init(&blk_tree_mutex); + blk_trace_calibrate_offsets(); + blk_trace_set_ht_offsets(); + + return 0; +} + +module_init(blk_trace_init); + diff --git a/block/elevator.c b/block/elevator.c index db3d0d8296a0..5e558c4689a4 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -333,6 +334,8 @@ void elv_insert(request_queue_t *q, struct request *rq, int where) struct list_head *pos; unsigned ordseq; + blk_add_trace_rq(q, rq, BLK_TA_INSERT); + rq->q = q; switch (where) { @@ -499,6 +502,7 @@ struct request *elv_next_request(request_queue_t *q) * not be passed by new incoming requests */ rq->flags |= REQ_STARTED; + blk_add_trace_rq(q, rq, BLK_TA_ISSUE); } if (!q->boundary_rq || q->boundary_rq == rq) { diff --git a/block/ioctl.c b/block/ioctl.c index 35fdb7dc6512..9cfa2e1ecb24 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -5,6 +5,7 @@ #include #include #include +#include #include static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user *arg) @@ -189,6 +190,11 @@ static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev, return put_ulong(arg, bdev->bd_inode->i_size >> 9); case BLKGETSIZE64: return put_u64(arg, bdev->bd_inode->i_size); + case BLKTRACESTART: + case BLKTRACESTOP: + case BLKTRACESETUP: + case BLKTRACETEARDOWN: + return blk_trace_ioctl(bdev, cmd, (char __user *) arg); } return -ENOIOCTLCMD; } diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 6c793b196aa9..062067fa7ead 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -28,6 +28,7 @@ #include #include #include +#include /* * for max sense size @@ -1556,8 +1557,10 @@ void blk_plug_device(request_queue_t *q) if (test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)) return; - if (!test_and_set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) + if (!test_and_set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) { mod_timer(&q->unplug_timer, jiffies + q->unplug_delay); + blk_add_trace_generic(q, NULL, 0, BLK_TA_PLUG); + } } EXPORT_SYMBOL(blk_plug_device); @@ -1621,14 +1624,21 @@ static void blk_backing_dev_unplug(struct backing_dev_info *bdi, /* * devices don't necessarily have an ->unplug_fn defined */ - if (q->unplug_fn) + if (q->unplug_fn) { + blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_IO, NULL, + q->rq.count[READ] + q->rq.count[WRITE]); + q->unplug_fn(q); + } } static void blk_unplug_work(void *data) { request_queue_t *q = data; + blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_IO, NULL, + q->rq.count[READ] + q->rq.count[WRITE]); + q->unplug_fn(q); } @@ -1636,6 +1646,9 @@ static void blk_unplug_timeout(unsigned long data) { request_queue_t *q = (request_queue_t *)data; + blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_TIMER, NULL, + q->rq.count[READ] + q->rq.count[WRITE]); + kblockd_schedule_work(&q->unplug_work); } @@ -1753,6 +1766,9 @@ static void blk_release_queue(struct kobject *kobj) if (q->queue_tags) __blk_queue_free_tags(q); + if (q->blk_trace) + blk_trace_shutdown(q); + kmem_cache_free(requestq_cachep, q); } @@ -2129,6 +2145,8 @@ rq_starved: rq_init(q, rq); rq->rl = rl; + + blk_add_trace_generic(q, bio, rw, BLK_TA_GETRQ); out: return rq; } @@ -2157,6 +2175,8 @@ static struct request *get_request_wait(request_queue_t *q, int rw, if (!rq) { struct io_context *ioc; + blk_add_trace_generic(q, bio, rw, BLK_TA_SLEEPRQ); + __generic_unplug_device(q); spin_unlock_irq(q->queue_lock); io_schedule(); @@ -2210,6 +2230,8 @@ EXPORT_SYMBOL(blk_get_request); */ void blk_requeue_request(request_queue_t *q, struct request *rq) { + blk_add_trace_rq(q, rq, BLK_TA_REQUEUE); + if (blk_rq_tagged(rq)) blk_queue_end_tag(q, rq); @@ -2844,6 +2866,8 @@ static int __make_request(request_queue_t *q, struct bio *bio) if (!q->back_merge_fn(q, req, bio)) break; + blk_add_trace_bio(q, bio, BLK_TA_BACKMERGE); + req->biotail->bi_next = bio; req->biotail = bio; req->nr_sectors = req->hard_nr_sectors += nr_sectors; @@ -2859,6 +2883,8 @@ static int __make_request(request_queue_t *q, struct bio *bio) if (!q->front_merge_fn(q, req, bio)) break; + blk_add_trace_bio(q, bio, BLK_TA_FRONTMERGE); + bio->bi_next = req->bio; req->bio = bio; @@ -2976,6 +3002,7 @@ void generic_make_request(struct bio *bio) request_queue_t *q; sector_t maxsector; int ret, nr_sectors = bio_sectors(bio); + dev_t old_dev; might_sleep(); /* Test device or partition size, when known. */ @@ -3002,6 +3029,8 @@ void generic_make_request(struct bio *bio) * NOTE: we don't repeat the blk_size check for each new device. * Stacking drivers are expected to know what they are doing. */ + maxsector = -1; + old_dev = 0; do { char b[BDEVNAME_SIZE]; @@ -3034,6 +3063,15 @@ end_io: */ blk_partition_remap(bio); + if (maxsector != -1) + blk_add_trace_remap(q, bio, old_dev, bio->bi_sector, + maxsector); + + blk_add_trace_bio(q, bio, BLK_TA_QUEUE); + + maxsector = bio->bi_sector; + old_dev = bio->bi_bdev->bd_dev; + ret = q->make_request_fn(q, bio); } while (ret); } @@ -3153,6 +3191,8 @@ static int __end_that_request_first(struct request *req, int uptodate, int total_bytes, bio_nbytes, error, next_idx = 0; struct bio *bio; + blk_add_trace_rq(req->q, req, BLK_TA_COMPLETE); + /* * extend uptodate bool to allow < 0 value to be direct io error */ diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index e29b8926f80e..1f2890989b56 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -2331,6 +2332,7 @@ static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd, cmd->rq->completion_data = cmd; cmd->rq->errors = status; + blk_add_trace_rq(cmd->rq->q, cmd->rq, BLK_TA_COMPLETE); blk_complete_request(cmd->rq); } diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 26b08ee425c7..8c82373f7ff3 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -17,6 +17,7 @@ #include #include #include +#include static const char *_name = DM_NAME; @@ -334,6 +335,8 @@ static void dec_pending(struct dm_io *io, int error) /* nudge anyone waiting on suspend queue */ wake_up(&io->md->wait); + blk_add_trace_bio(io->md->queue, io->bio, BLK_TA_COMPLETE); + bio_endio(io->bio, io->bio->bi_size, io->error); free_io(io->md, io); } @@ -392,6 +395,7 @@ static void __map_bio(struct dm_target *ti, struct bio *clone, struct target_io *tio) { int r; + sector_t sector; /* * Sanity checks. @@ -407,10 +411,17 @@ static void __map_bio(struct dm_target *ti, struct bio *clone, * this io. */ atomic_inc(&tio->io->io_count); + sector = clone->bi_sector; r = ti->type->map(ti, clone, &tio->info); - if (r > 0) + if (r > 0) { /* the bio has been remapped so dispatch it */ + + blk_add_trace_remap(bdev_get_queue(clone->bi_bdev), clone, + tio->io->bio->bi_bdev->bd_dev, sector, + clone->bi_sector); + generic_make_request(clone); + } else if (r < 0) { /* error the io and bail out */ diff --git a/fs/bio.c b/fs/bio.c index 8f1d2e815c96..0a8c59cb68f5 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -25,6 +25,7 @@ #include #include #include +#include #include /* for struct sg_iovec */ #define BIO_POOL_SIZE 256 @@ -1095,6 +1096,9 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors) if (!bp) return bp; + blk_add_trace_pdu_int(bdev_get_queue(bi->bi_bdev), BLK_TA_SPLIT, bi, + bi->bi_sector + first_sectors); + BUG_ON(bi->bi_vcnt != 1); BUG_ON(bi->bi_idx != 0); atomic_set(&bp->cnt, 3); diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index c666769a875d..7c031f00fd79 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -72,6 +72,7 @@ #include #include #include +#include #include /* siocdevprivate_ioctl */ #include diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 56bb6a4e15f3..c179966f1a2f 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -22,6 +22,7 @@ typedef struct request_queue request_queue_t; struct elevator_queue; typedef struct elevator_queue elevator_t; struct request_pm_state; +struct blk_trace; #define BLKDEV_MIN_RQ 4 #define BLKDEV_MAX_RQ 128 /* Default maximum */ @@ -416,6 +417,8 @@ struct request_queue unsigned int sg_reserved_size; int node; + struct blk_trace *blk_trace; + /* * reserved for flush operations */ diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h new file mode 100644 index 000000000000..b34d3e73d5ea --- /dev/null +++ b/include/linux/blktrace_api.h @@ -0,0 +1,277 @@ +#ifndef BLKTRACE_H +#define BLKTRACE_H + +#include +#include +#include + +/* + * Trace categories + */ +enum blktrace_cat { + BLK_TC_READ = 1 << 0, /* reads */ + BLK_TC_WRITE = 1 << 1, /* writes */ + BLK_TC_BARRIER = 1 << 2, /* barrier */ + BLK_TC_SYNC = 1 << 3, /* barrier */ + BLK_TC_QUEUE = 1 << 4, /* queueing/merging */ + BLK_TC_REQUEUE = 1 << 5, /* requeueing */ + BLK_TC_ISSUE = 1 << 6, /* issue */ + BLK_TC_COMPLETE = 1 << 7, /* completions */ + BLK_TC_FS = 1 << 8, /* fs requests */ + BLK_TC_PC = 1 << 9, /* pc requests */ + BLK_TC_NOTIFY = 1 << 10, /* special message */ + + BLK_TC_END = 1 << 15, /* only 16-bits, reminder */ +}; + +#define BLK_TC_SHIFT (16) +#define BLK_TC_ACT(act) ((act) << BLK_TC_SHIFT) + +/* + * Basic trace actions + */ +enum blktrace_act { + __BLK_TA_QUEUE = 1, /* queued */ + __BLK_TA_BACKMERGE, /* back merged to existing rq */ + __BLK_TA_FRONTMERGE, /* front merge to existing rq */ + __BLK_TA_GETRQ, /* allocated new request */ + __BLK_TA_SLEEPRQ, /* sleeping on rq allocation */ + __BLK_TA_REQUEUE, /* request requeued */ + __BLK_TA_ISSUE, /* sent to driver */ + __BLK_TA_COMPLETE, /* completed by driver */ + __BLK_TA_PLUG, /* queue was plugged */ + __BLK_TA_UNPLUG_IO, /* queue was unplugged by io */ + __BLK_TA_UNPLUG_TIMER, /* queue was unplugged by timer */ + __BLK_TA_INSERT, /* insert request */ + __BLK_TA_SPLIT, /* bio was split */ + __BLK_TA_BOUNCE, /* bio was bounced */ + __BLK_TA_REMAP, /* bio was remapped */ +}; + +/* + * Trace actions in full. Additionally, read or write is masked + */ +#define BLK_TA_QUEUE (__BLK_TA_QUEUE | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_BACKMERGE (__BLK_TA_BACKMERGE | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_FRONTMERGE (__BLK_TA_FRONTMERGE | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_GETRQ (__BLK_TA_GETRQ | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_SLEEPRQ (__BLK_TA_SLEEPRQ | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_REQUEUE (__BLK_TA_REQUEUE | BLK_TC_ACT(BLK_TC_REQUEUE)) +#define BLK_TA_ISSUE (__BLK_TA_ISSUE | BLK_TC_ACT(BLK_TC_ISSUE)) +#define BLK_TA_COMPLETE (__BLK_TA_COMPLETE| BLK_TC_ACT(BLK_TC_COMPLETE)) +#define BLK_TA_PLUG (__BLK_TA_PLUG | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_UNPLUG_IO (__BLK_TA_UNPLUG_IO | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_UNPLUG_TIMER (__BLK_TA_UNPLUG_TIMER | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_INSERT (__BLK_TA_INSERT | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_SPLIT (__BLK_TA_SPLIT) +#define BLK_TA_BOUNCE (__BLK_TA_BOUNCE) +#define BLK_TA_REMAP (__BLK_TA_REMAP | BLK_TC_ACT(BLK_TC_QUEUE)) + +#define BLK_IO_TRACE_MAGIC 0x65617400 +#define BLK_IO_TRACE_VERSION 0x07 + +/* + * The trace itself + */ +struct blk_io_trace { + u32 magic; /* MAGIC << 8 | version */ + u32 sequence; /* event number */ + u64 time; /* in microseconds */ + u64 sector; /* disk offset */ + u32 bytes; /* transfer length */ + u32 action; /* what happened */ + u32 pid; /* who did it */ + u32 device; /* device number */ + u32 cpu; /* on what cpu did it happen */ + u16 error; /* completion error */ + u16 pdu_len; /* length of data after this trace */ +}; + +/* + * The remap event + */ +struct blk_io_trace_remap { + u32 device; + u32 __pad; + u64 sector; +}; + +enum { + Blktrace_setup = 1, + Blktrace_running, + Blktrace_stopped, +}; + +struct blk_trace { + int trace_state; + struct rchan *rchan; + unsigned long *sequence; + u16 act_mask; + u64 start_lba; + u64 end_lba; + u32 pid; + u32 dev; + struct dentry *dir; + struct dentry *dropped_file; + atomic_t dropped; +}; + +/* + * User setup structure passed with BLKTRACESTART + */ +struct blk_user_trace_setup { + char name[BDEVNAME_SIZE]; /* output */ + u16 act_mask; /* input */ + u32 buf_size; /* input */ + u32 buf_nr; /* input */ + u64 start_lba; + u64 end_lba; + u32 pid; +}; + +#if defined(CONFIG_BLK_DEV_IO_TRACE) +extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *); +extern void blk_trace_shutdown(request_queue_t *); +extern void __blk_add_trace(struct blk_trace *, sector_t, int, int, u32, int, int, void *); + +/** + * blk_add_trace_rq - Add a trace for a request oriented action + * @q: queue the io is for + * @rq: the source request + * @what: the action + * + * Description: + * Records an action against a request. Will log the bio offset + size. + * + **/ +static inline void blk_add_trace_rq(struct request_queue *q, struct request *rq, + u32 what) +{ + struct blk_trace *bt = q->blk_trace; + int rw = rq->flags & 0x07; + + if (likely(!bt)) + return; + + if (blk_pc_request(rq)) { + what |= BLK_TC_ACT(BLK_TC_PC); + __blk_add_trace(bt, 0, rq->data_len, rw, what, rq->errors, sizeof(rq->cmd), rq->cmd); + } else { + what |= BLK_TC_ACT(BLK_TC_FS); + __blk_add_trace(bt, rq->hard_sector, rq->hard_nr_sectors << 9, rw, what, rq->errors, 0, NULL); + } +} + +/** + * blk_add_trace_bio - Add a trace for a bio oriented action + * @q: queue the io is for + * @bio: the source bio + * @what: the action + * + * Description: + * Records an action against a bio. Will log the bio offset + size. + * + **/ +static inline void blk_add_trace_bio(struct request_queue *q, struct bio *bio, + u32 what) +{ + struct blk_trace *bt = q->blk_trace; + + if (likely(!bt)) + return; + + __blk_add_trace(bt, bio->bi_sector, bio->bi_size, bio->bi_rw, what, !bio_flagged(bio, BIO_UPTODATE), 0, NULL); +} + +/** + * blk_add_trace_generic - Add a trace for a generic action + * @q: queue the io is for + * @bio: the source bio + * @rw: the data direction + * @what: the action + * + * Description: + * Records a simple trace + * + **/ +static inline void blk_add_trace_generic(struct request_queue *q, + struct bio *bio, int rw, u32 what) +{ + struct blk_trace *bt = q->blk_trace; + + if (likely(!bt)) + return; + + if (bio) + blk_add_trace_bio(q, bio, what); + else + __blk_add_trace(bt, 0, 0, rw, what, 0, 0, NULL); +} + +/** + * blk_add_trace_pdu_int - Add a trace for a bio with an integer payload + * @q: queue the io is for + * @what: the action + * @bio: the source bio + * @pdu: the integer payload + * + * Description: + * Adds a trace with some integer payload. This might be an unplug + * option given as the action, with the depth at unplug time given + * as the payload + * + **/ +static inline void blk_add_trace_pdu_int(struct request_queue *q, u32 what, + struct bio *bio, unsigned int pdu) +{ + struct blk_trace *bt = q->blk_trace; + u64 rpdu = cpu_to_be64(pdu); + + if (likely(!bt)) + return; + + if (bio) + __blk_add_trace(bt, bio->bi_sector, bio->bi_size, bio->bi_rw, what, !bio_flagged(bio, BIO_UPTODATE), sizeof(rpdu), &rpdu); + else + __blk_add_trace(bt, 0, 0, 0, what, 0, sizeof(rpdu), &rpdu); +} + +/** + * blk_add_trace_remap - Add a trace for a remap operation + * @q: queue the io is for + * @bio: the source bio + * @dev: target device + * @from: source sector + * @to: target sector + * + * Description: + * Device mapper or raid target sometimes need to split a bio because + * it spans a stripe (or similar). Add a trace for that action. + * + **/ +static inline void blk_add_trace_remap(struct request_queue *q, struct bio *bio, + dev_t dev, sector_t from, sector_t to) +{ + struct blk_trace *bt = q->blk_trace; + struct blk_io_trace_remap r; + + if (likely(!bt)) + return; + + r.device = cpu_to_be32(dev); + r.sector = cpu_to_be64(to); + + __blk_add_trace(bt, from, bio->bi_size, bio->bi_rw, BLK_TA_REMAP, !bio_flagged(bio, BIO_UPTODATE), sizeof(r), &r); +} + +#else /* !CONFIG_BLK_DEV_IO_TRACE */ +#define blk_trace_ioctl(bdev, cmd, arg) (-ENOTTY) +#define blk_trace_shutdown(q) do { } while (0) +#define blk_add_trace_rq(q, rq, what) do { } while (0) +#define blk_add_trace_bio(q, rq, what) do { } while (0) +#define blk_add_trace_generic(q, rq, rw, what) do { } while (0) +#define blk_add_trace_pdu_int(q, what, bio, pdu) do { } while (0) +#define blk_add_trace_remap(q, bio, dev, f, t) do {} while (0) +#endif /* CONFIG_BLK_DEV_IO_TRACE */ + +#endif diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h index ae7dfb790df3..efb518f16bb3 100644 --- a/include/linux/compat_ioctl.h +++ b/include/linux/compat_ioctl.h @@ -97,6 +97,10 @@ COMPATIBLE_IOCTL(BLKRRPART) COMPATIBLE_IOCTL(BLKFLSBUF) COMPATIBLE_IOCTL(BLKSECTSET) COMPATIBLE_IOCTL(BLKSSZGET) +COMPATIBLE_IOCTL(BLKTRACESTART) +COMPATIBLE_IOCTL(BLKTRACESTOP) +COMPATIBLE_IOCTL(BLKTRACESETUP) +COMPATIBLE_IOCTL(BLKTRACETEARDOWN) ULONG_IOCTL(BLKRASET) ULONG_IOCTL(BLKFRASET) /* RAID */ diff --git a/include/linux/fs.h b/include/linux/fs.h index f9c9dea636d0..9b34a1b03455 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -197,6 +197,10 @@ extern int dir_notify_enable; #define BLKBSZGET _IOR(0x12,112,size_t) #define BLKBSZSET _IOW(0x12,113,size_t) #define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */ +#define BLKTRACESETUP _IOWR(0x12,115,struct blk_user_trace_setup) +#define BLKTRACESTART _IO(0x12,116) +#define BLKTRACESTOP _IO(0x12,117) +#define BLKTRACETEARDOWN _IO(0x12,118) #define BMAP_IOCTL 1 /* obsolete - kept for compatibility */ #define FIBMAP _IO(0x00,1) /* bmap access */ diff --git a/include/linux/sched.h b/include/linux/sched.h index 62e6314382f0..e60a91d5b369 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -706,6 +706,7 @@ struct task_struct { prio_array_t *array; unsigned short ioprio; + unsigned int btrace_seq; unsigned long sleep_avg; unsigned long long timestamp, last_ran; diff --git a/kernel/fork.c b/kernel/fork.c index c79ae0b19a49..c21bae8c93b9 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -181,6 +181,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) /* One for us, one for whoever does the "release_task()" (usually parent) */ atomic_set(&tsk->usage,2); atomic_set(&tsk->fs_excl, 0); + tsk->btrace_seq = 0; return tsk; } diff --git a/mm/highmem.c b/mm/highmem.c index ce2e7e8bbfa7..d0ea1eec6a9a 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -26,6 +26,7 @@ #include #include #include +#include #include static mempool_t *page_pool, *isa_page_pool; @@ -483,6 +484,8 @@ void blk_queue_bounce(request_queue_t *q, struct bio **bio_orig) pool = isa_page_pool; } + blk_add_trace_bio(q, *bio_orig, BLK_TA_BOUNCE); + /* * slow path */ -- cgit v1.2.3 From 42d3b83fecb7b576d477244347982baa02fa4f44 Mon Sep 17 00:00:00 2001 From: Jim Cromie Date: Mon, 9 Jan 2006 23:22:24 +0100 Subject: [PATCH] hwmon: Allow sensor attributes arrays This patch refactors SENSOR_DEVICE_ATTR macro. First it creates a new macro SENSOR_ATTR() which expands to an initialization expression, then it uses that in SENSOR_DEVICE_ATTR, which declares and initializes a struct sensor_device_attribute. IOW, SENSOR_ATTR() imitates __ATTR() in include/linux/device.h. Signed-off-by: Jim Cromie Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- include/linux/hwmon-sysfs.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/linux/hwmon-sysfs.h b/include/linux/hwmon-sysfs.h index 7eb4004b3601..dedca6a516b4 100644 --- a/include/linux/hwmon-sysfs.h +++ b/include/linux/hwmon-sysfs.h @@ -27,11 +27,13 @@ struct sensor_device_attribute{ #define to_sensor_dev_attr(_dev_attr) \ container_of(_dev_attr, struct sensor_device_attribute, dev_attr) -#define SENSOR_DEVICE_ATTR(_name,_mode,_show,_store,_index) \ -struct sensor_device_attribute sensor_dev_attr_##_name = { \ - .dev_attr = __ATTR(_name,_mode,_show,_store), \ - .index = _index, \ -} +#define SENSOR_ATTR(_name, _mode, _show, _store, _index) \ + { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .index = _index } + +#define SENSOR_DEVICE_ATTR(_name, _mode, _show, _store, _index) \ +struct sensor_device_attribute sensor_dev_attr_##_name \ + = SENSOR_ATTR(_name, _mode, _show, _store, _index) struct sensor_device_attribute_2 { struct device_attribute dev_attr; -- cgit v1.2.3 From 70adca5a9f506942ec88fb2d9d6e71ef271888b7 Mon Sep 17 00:00:00 2001 From: Jim Cromie Date: Wed, 18 Jan 2006 23:10:49 +0100 Subject: [PATCH] hwmon: Refactor SENSOR_DEVICE_ATTR_2 This patch refactors SENSOR_DEVICE_ATTR_2 macro, following pattern set by SENSOR_ATTR. First it creates a new macro SENSOR_ATTR_2() which expands to an initialization expression, then it uses that in SENSOR_DEVICE_ATTR_2, which declares and initializes a struct sensor_device_attribute_2. Signed-off-by: Jim Cromie Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- include/linux/hwmon-sysfs.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/linux/hwmon-sysfs.h b/include/linux/hwmon-sysfs.h index dedca6a516b4..a90c09d331c1 100644 --- a/include/linux/hwmon-sysfs.h +++ b/include/linux/hwmon-sysfs.h @@ -43,11 +43,13 @@ struct sensor_device_attribute_2 { #define to_sensor_dev_attr_2(_dev_attr) \ container_of(_dev_attr, struct sensor_device_attribute_2, dev_attr) +#define SENSOR_ATTR_2(_name, _mode, _show, _store, _nr, _index) \ + { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .index = _index, \ + .nr = _nr } + #define SENSOR_DEVICE_ATTR_2(_name,_mode,_show,_store,_nr,_index) \ -struct sensor_device_attribute_2 sensor_dev_attr_##_name = { \ - .dev_attr = __ATTR(_name,_mode,_show,_store), \ - .index = _index, \ - .nr = _nr, \ -} +struct sensor_device_attribute_2 sensor_dev_attr_##_name \ + = SENSOR_ATTR_2(_name, _mode, _show, _store, _nr, _index) #endif /* _LINUX_HWMON_SYSFS_H */ -- cgit v1.2.3 From 5c085d369c2c4f18942ec8951466e186366d5c78 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 18 Jan 2006 23:16:04 +0100 Subject: [PATCH] i2c: Semaphore to mutex conversions, part 2 semaphore to mutex conversion. the conversion was generated via scripts, and the result was validated automatically via a script as well. build tested. Signed-off-by: Ingo Molnar Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-amd756-s4882.c | 13 +++++----- drivers/i2c/busses/i2c-isa.c | 2 +- drivers/i2c/chips/eeprom.c | 9 +++---- drivers/i2c/chips/max6875.c | 10 ++++---- drivers/i2c/chips/pcf8591.c | 13 +++++----- drivers/i2c/chips/tps65010.c | 45 ++++++++++++++++++----------------- drivers/i2c/i2c-core.c | 34 +++++++++++++------------- include/linux/i2c.h | 6 ++--- 8 files changed, 68 insertions(+), 64 deletions(-) (limited to 'include') diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c index 56c7d987590f..f7b4cb4e9c75 100644 --- a/drivers/i2c/busses/i2c-amd756-s4882.c +++ b/drivers/i2c/busses/i2c-amd756-s4882.c @@ -38,6 +38,7 @@ #include #include #include +#include extern struct i2c_adapter amd756_smbus; @@ -45,7 +46,7 @@ static struct i2c_adapter *s4882_adapter; static struct i2c_algorithm *s4882_algo; /* Wrapper access functions for multiplexed SMBus */ -static struct semaphore amd756_lock; +static struct mutex amd756_lock; static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr, unsigned short flags, char read_write, @@ -59,12 +60,12 @@ static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr, || addr == 0x18) return -1; - down(&amd756_lock); + mutex_lock(&amd756_lock); error = amd756_smbus.algo->smbus_xfer(adap, addr, flags, read_write, command, size, data); - up(&amd756_lock); + mutex_unlock(&amd756_lock); return error; } @@ -87,7 +88,7 @@ static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr, if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30) return -1; - down(&amd756_lock); + mutex_lock(&amd756_lock); if (last_channels != channels) { union i2c_smbus_data mplxdata; @@ -105,7 +106,7 @@ static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr, command, size, data); UNLOCK: - up(&amd756_lock); + mutex_unlock(&amd756_lock); return error; } @@ -166,7 +167,7 @@ static int __init amd756_s4882_init(void) } printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4882\n"); - init_MUTEX(&amd756_lock); + mutex_init(&amd756_lock); /* Define the 5 virtual adapters and algorithms structures */ if (!(s4882_adapter = kzalloc(5 * sizeof(struct i2c_adapter), diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c index 4344ae6b1fcb..c3e1d3e888d7 100644 --- a/drivers/i2c/busses/i2c-isa.c +++ b/drivers/i2c/busses/i2c-isa.c @@ -125,7 +125,7 @@ int i2c_isa_del_driver(struct i2c_driver *driver) static int __init i2c_isa_init(void) { - init_MUTEX(&isa_adapter.clist_lock); + mutex_init(&isa_adapter.clist_lock); INIT_LIST_HEAD(&isa_adapter.clients); isa_adapter.nr = ANY_I2C_ISA_BUS; diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index 41116b7947f6..13c108269a6d 100644 --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c @@ -33,6 +33,7 @@ #include #include #include +#include /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, @@ -54,7 +55,7 @@ enum eeprom_nature { /* Each client has this additional data */ struct eeprom_data { struct i2c_client client; - struct semaphore update_lock; + struct mutex update_lock; u8 valid; /* bitfield, bit!=0 if slice is valid */ unsigned long last_updated[8]; /* In jiffies, 8 slices */ u8 data[EEPROM_SIZE]; /* Register values */ @@ -81,7 +82,7 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice) struct eeprom_data *data = i2c_get_clientdata(client); int i, j; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (!(data->valid & (1 << slice)) || time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { @@ -107,7 +108,7 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice) data->valid |= (1 << slice); } exit: - up(&data->update_lock); + mutex_unlock(&data->update_lock); } static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count) @@ -187,7 +188,7 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) /* Fill in the remaining client fields */ strlcpy(new_client->name, "eeprom", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); data->nature = UNKNOWN; /* Tell the I2C layer a new client has arrived */ diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c index 6d3ff584155e..88d2ddee4490 100644 --- a/drivers/i2c/chips/max6875.c +++ b/drivers/i2c/chips/max6875.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include /* Do not scan - the MAX6875 access method will write to some EEPROM chips */ static unsigned short normal_i2c[] = {I2C_CLIENT_END}; @@ -54,7 +54,7 @@ I2C_CLIENT_INSMOD_1(max6875); /* Each client has this additional data */ struct max6875_data { struct i2c_client client; - struct semaphore update_lock; + struct mutex update_lock; u32 valid; u8 data[USER_EEPROM_SIZE]; @@ -83,7 +83,7 @@ static void max6875_update_slice(struct i2c_client *client, int slice) if (slice >= USER_EEPROM_SLICES) return; - down(&data->update_lock); + mutex_lock(&data->update_lock); buf = &data->data[slice << SLICE_BITS]; @@ -122,7 +122,7 @@ static void max6875_update_slice(struct i2c_client *client, int slice) data->valid |= (1 << slice); } exit_up: - up(&data->update_lock); + mutex_unlock(&data->update_lock); } static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off, @@ -196,7 +196,7 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind) real_client->driver = &max6875_driver; real_client->flags = 0; strlcpy(real_client->name, "max6875", I2C_NAME_SIZE); - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Init fake client data */ /* set the client data to the i2c_client so that it will get freed */ diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c index 36cff09c678d..925a6b371fd2 100644 --- a/drivers/i2c/chips/pcf8591.c +++ b/drivers/i2c/chips/pcf8591.c @@ -24,6 +24,7 @@ #include #include #include +#include /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, @@ -74,7 +75,7 @@ MODULE_PARM_DESC(input_mode, struct pcf8591_data { struct i2c_client client; - struct semaphore update_lock; + struct mutex update_lock; u8 control; u8 aout; @@ -144,13 +145,13 @@ static ssize_t set_out0_enable(struct device *dev, struct device_attribute *attr struct pcf8591_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (val) data->control |= PCF8591_CONTROL_AOEF; else data->control &= ~PCF8591_CONTROL_AOEF; i2c_smbus_write_byte(client, data->control); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -200,7 +201,7 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind) /* Fill in the remaining client fields and put it into the global list */ strlcpy(new_client->name, "pcf8591", I2C_NAME_SIZE); - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -265,7 +266,7 @@ static int pcf8591_read_channel(struct device *dev, int channel) struct i2c_client *client = to_i2c_client(dev); struct pcf8591_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if ((data->control & PCF8591_CONTROL_AICH_MASK) != channel) { data->control = (data->control & ~PCF8591_CONTROL_AICH_MASK) @@ -278,7 +279,7 @@ static int pcf8591_read_channel(struct device *dev, int channel) } value = i2c_smbus_read_byte(client); - up(&data->update_lock); + mutex_unlock(&data->update_lock); if ((channel == 2 && input_mode == 2) || (channel != 3 && (input_mode == 1 || input_mode == 3))) diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c index 1af3dfbb8086..179b1e022d80 100644 --- a/drivers/i2c/chips/tps65010.c +++ b/drivers/i2c/chips/tps65010.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -81,7 +82,7 @@ enum tps_model { struct tps65010 { struct i2c_client client; - struct semaphore lock; + struct mutex lock; int irq; struct work_struct work; struct dentry *file; @@ -218,7 +219,7 @@ static int dbg_show(struct seq_file *s, void *_) seq_printf(s, "driver %s\nversion %s\nchip %s\n\n", DRIVER_NAME, DRIVER_VERSION, chip); - down(&tps->lock); + mutex_lock(&tps->lock); /* FIXME how can we tell whether a battery is present? * likely involves a charge gauging chip (like BQ26501). @@ -300,7 +301,7 @@ static int dbg_show(struct seq_file *s, void *_) (v2 & (1 << (4 + i))) ? "rising" : "falling"); } - up(&tps->lock); + mutex_unlock(&tps->lock); return 0; } @@ -416,7 +417,7 @@ static void tps65010_work(void *_tps) { struct tps65010 *tps = _tps; - down(&tps->lock); + mutex_lock(&tps->lock); tps65010_interrupt(tps); @@ -444,7 +445,7 @@ static void tps65010_work(void *_tps) if (test_and_clear_bit(FLAG_IRQ_ENABLE, &tps->flags)) enable_irq(tps->irq); - up(&tps->lock); + mutex_unlock(&tps->lock); } static irqreturn_t tps65010_irq(int irq, void *_tps, struct pt_regs *regs) @@ -505,7 +506,7 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind) if (!tps) return 0; - init_MUTEX(&tps->lock); + mutex_init(&tps->lock); INIT_WORK(&tps->work, tps65010_work, tps); tps->irq = -1; tps->client.addr = address; @@ -695,7 +696,7 @@ int tps65010_set_gpio_out_value(unsigned gpio, unsigned value) if ((gpio < GPIO1) || (gpio > GPIO4)) return -EINVAL; - down(&the_tps->lock); + mutex_lock(&the_tps->lock); defgpio = i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO); @@ -720,7 +721,7 @@ int tps65010_set_gpio_out_value(unsigned gpio, unsigned value) gpio, value ? "high" : "low", i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO)); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } EXPORT_SYMBOL(tps65010_set_gpio_out_value); @@ -745,7 +746,7 @@ int tps65010_set_led(unsigned led, unsigned mode) led = LED2; } - down(&the_tps->lock); + mutex_lock(&the_tps->lock); pr_debug("%s: led%i_on 0x%02x\n", DRIVER_NAME, led, i2c_smbus_read_byte_data(&the_tps->client, @@ -771,7 +772,7 @@ int tps65010_set_led(unsigned led, unsigned mode) default: printk(KERN_ERR "%s: Wrong mode parameter for set_led()\n", DRIVER_NAME); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return -EINVAL; } @@ -781,7 +782,7 @@ int tps65010_set_led(unsigned led, unsigned mode) if (status != 0) { printk(KERN_ERR "%s: Failed to write led%i_on register\n", DRIVER_NAME, led); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } @@ -794,7 +795,7 @@ int tps65010_set_led(unsigned led, unsigned mode) if (status != 0) { printk(KERN_ERR "%s: Failed to write led%i_per register\n", DRIVER_NAME, led); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } @@ -802,7 +803,7 @@ int tps65010_set_led(unsigned led, unsigned mode) i2c_smbus_read_byte_data(&the_tps->client, TPS_LED1_PER + offs)); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } @@ -820,7 +821,7 @@ int tps65010_set_vib(unsigned value) if (!the_tps) return -ENODEV; - down(&the_tps->lock); + mutex_lock(&the_tps->lock); vdcdc2 = i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC2); vdcdc2 &= ~(1 << 1); @@ -831,7 +832,7 @@ int tps65010_set_vib(unsigned value) pr_debug("%s: vibrator %s\n", DRIVER_NAME, value ? "on" : "off"); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } EXPORT_SYMBOL(tps65010_set_vib); @@ -848,7 +849,7 @@ int tps65010_set_low_pwr(unsigned mode) if (!the_tps) return -ENODEV; - down(&the_tps->lock); + mutex_lock(&the_tps->lock); pr_debug("%s: %s low_pwr, vdcdc1 0x%02x\n", DRIVER_NAME, mode ? "enable" : "disable", @@ -876,7 +877,7 @@ int tps65010_set_low_pwr(unsigned mode) pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME, i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1)); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } @@ -894,7 +895,7 @@ int tps65010_config_vregs1(unsigned value) if (!the_tps) return -ENODEV; - down(&the_tps->lock); + mutex_lock(&the_tps->lock); pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME, i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1)); @@ -909,7 +910,7 @@ int tps65010_config_vregs1(unsigned value) pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME, i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1)); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } @@ -931,7 +932,7 @@ int tps65013_set_low_pwr(unsigned mode) if (!the_tps || the_tps->por) return -ENODEV; - down(&the_tps->lock); + mutex_lock(&the_tps->lock); pr_debug("%s: %s low_pwr, chgconfig 0x%02x vdcdc1 0x%02x\n", DRIVER_NAME, @@ -959,7 +960,7 @@ int tps65013_set_low_pwr(unsigned mode) if (status != 0) { printk(KERN_ERR "%s: Failed to write chconfig register\n", DRIVER_NAME); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } @@ -977,7 +978,7 @@ int tps65013_set_low_pwr(unsigned mode) pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME, i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1)); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 2b0c555aa011..975cb647da10 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -169,8 +169,8 @@ int i2c_add_adapter(struct i2c_adapter *adap) } adap->nr = id & MAX_ID_MASK; - init_MUTEX(&adap->bus_lock); - init_MUTEX(&adap->clist_lock); + mutex_init(&adap->bus_lock); + mutex_init(&adap->clist_lock); list_add_tail(&adap->list,&adapters); INIT_LIST_HEAD(&adap->clients); @@ -385,9 +385,9 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr) { int rval; - down(&adapter->clist_lock); + mutex_lock(&adapter->clist_lock); rval = __i2c_check_addr(adapter, addr); - up(&adapter->clist_lock); + mutex_unlock(&adapter->clist_lock); return rval; } @@ -396,13 +396,13 @@ int i2c_attach_client(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; - down(&adapter->clist_lock); + mutex_lock(&adapter->clist_lock); if (__i2c_check_addr(client->adapter, client->addr)) { - up(&adapter->clist_lock); + mutex_unlock(&adapter->clist_lock); return -EBUSY; } list_add_tail(&client->list,&adapter->clients); - up(&adapter->clist_lock); + mutex_unlock(&adapter->clist_lock); if (adapter->client_register) { if (adapter->client_register(client)) { @@ -451,12 +451,12 @@ int i2c_detach_client(struct i2c_client *client) } } - down(&adapter->clist_lock); + mutex_lock(&adapter->clist_lock); list_del(&client->list); init_completion(&client->released); device_remove_file(&client->dev, &dev_attr_client_name); device_unregister(&client->dev); - up(&adapter->clist_lock); + mutex_unlock(&adapter->clist_lock); wait_for_completion(&client->released); out: @@ -514,19 +514,19 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg) struct list_head *item; struct i2c_client *client; - down(&adap->clist_lock); + mutex_lock(&adap->clist_lock); list_for_each(item,&adap->clients) { client = list_entry(item, struct i2c_client, list); if (!try_module_get(client->driver->driver.owner)) continue; if (NULL != client->driver->command) { - up(&adap->clist_lock); + mutex_unlock(&adap->clist_lock); client->driver->command(client,cmd,arg); - down(&adap->clist_lock); + mutex_lock(&adap->clist_lock); } module_put(client->driver->driver.owner); } - up(&adap->clist_lock); + mutex_unlock(&adap->clist_lock); } static int __init i2c_init(void) @@ -570,9 +570,9 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) } #endif - down(&adap->bus_lock); + mutex_lock(&adap->bus_lock); ret = adap->algo->master_xfer(adap,msgs,num); - up(&adap->bus_lock); + mutex_unlock(&adap->bus_lock); return ret; } else { @@ -1116,10 +1116,10 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags, flags &= I2C_M_TEN | I2C_CLIENT_PEC; if (adapter->algo->smbus_xfer) { - down(&adapter->bus_lock); + mutex_lock(&adapter->bus_lock); res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, command,size,data); - up(&adapter->bus_lock); + mutex_unlock(&adapter->bus_lock); } else res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, command,size,data); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 63f1d63cc1d8..1635ee25918f 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -32,7 +32,7 @@ #include #include /* for struct device */ #include /* for completion */ -#include +#include /* --- For i2c-isa ---------------------------------------------------- */ @@ -225,8 +225,8 @@ struct i2c_adapter { int (*client_unregister)(struct i2c_client *); /* data fields that are valid for all devices */ - struct semaphore bus_lock; - struct semaphore clist_lock; + struct mutex bus_lock; + struct mutex clist_lock; int timeout; int retries; -- cgit v1.2.3 From 2f27f46c49c096d86e7e63acd43cad3bc42f2383 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 5 Feb 2006 23:29:18 +0100 Subject: [PATCH] i2c: Drop the i2c-frodo bus driver Drop the i2c-frodo bus driver. It isn't referenced by the build system, and depends on code which was never included in 2.6 kernels. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-frodo.c | 85 ------------------------------------------ include/linux/i2c-id.h | 1 - 2 files changed, 86 deletions(-) delete mode 100644 drivers/i2c/busses/i2c-frodo.c (limited to 'include') diff --git a/drivers/i2c/busses/i2c-frodo.c b/drivers/i2c/busses/i2c-frodo.c deleted file mode 100644 index b6f52f5a4138..000000000000 --- a/drivers/i2c/busses/i2c-frodo.c +++ /dev/null @@ -1,85 +0,0 @@ - -/* - * linux/drivers/i2c/i2c-frodo.c - * - * Author: Abraham van der Merwe - * - * An I2C adapter driver for the 2d3D, Inc. StrongARM SA-1110 - * Development board (Frodo). - * - * This source code is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include - - -static void frodo_setsda (void *data,int state) -{ - if (state) - FRODO_CPLD_I2C |= FRODO_I2C_SDA_OUT; - else - FRODO_CPLD_I2C &= ~FRODO_I2C_SDA_OUT; -} - -static void frodo_setscl (void *data,int state) -{ - if (state) - FRODO_CPLD_I2C |= FRODO_I2C_SCL_OUT; - else - FRODO_CPLD_I2C &= ~FRODO_I2C_SCL_OUT; -} - -static int frodo_getsda (void *data) -{ - return ((FRODO_CPLD_I2C & FRODO_I2C_SDA_IN) != 0); -} - -static int frodo_getscl (void *data) -{ - return ((FRODO_CPLD_I2C & FRODO_I2C_SCL_IN) != 0); -} - -static struct i2c_algo_bit_data bit_frodo_data = { - .setsda = frodo_setsda, - .setscl = frodo_setscl, - .getsda = frodo_getsda, - .getscl = frodo_getscl, - .udelay = 80, - .mdelay = 80, - .timeout = HZ -}; - -static struct i2c_adapter frodo_ops = { - .owner = THIS_MODULE, - .id = I2C_HW_B_FRODO, - .algo_data = &bit_frodo_data, - .dev = { - .name = "Frodo adapter driver", - }, -}; - -static int __init i2c_frodo_init (void) -{ - return i2c_bit_add_bus(&frodo_ops); -} - -static void __exit i2c_frodo_exit (void) -{ - i2c_bit_del_bus(&frodo_ops); -} - -MODULE_AUTHOR ("Abraham van der Merwe "); -MODULE_DESCRIPTION ("I2C-Bus adapter routines for Frodo"); -MODULE_LICENSE ("GPL"); - -module_init (i2c_frodo_init); -module_exit (i2c_frodo_exit); - diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 474c8f4f5d4f..ec311bc89439 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -172,7 +172,6 @@ #define I2C_HW_B_RIVA 0x010010 /* Riva based graphics cards */ #define I2C_HW_B_IOC 0x010011 /* IOC bit-wiggling */ #define I2C_HW_B_TSUNA 0x010012 /* DEC Tsunami chipset */ -#define I2C_HW_B_FRODO 0x010013 /* 2d3D SA-1110 Development Board */ #define I2C_HW_B_OMAHA 0x010014 /* Omaha I2C interface (ARM) */ #define I2C_HW_B_GUIDE 0x010015 /* Guide bit-basher */ #define I2C_HW_B_IXP2000 0x010016 /* GPIO on IXP2000 systems */ -- cgit v1.2.3 From 5f7ea3c58c9aa571617a9d77dd2fbd4bd81cc50a Mon Sep 17 00:00:00 2001 From: Martin Devera Date: Mon, 27 Feb 2006 23:11:45 +0100 Subject: [PATCH] I2C: i2c-piix4: Add Broadcom HT-1000 support Add Broadcom HT-1000 south bridge's PCI ID to i2c-piix driver. Note that at least on Supermicro H8SSL it uses non-standard SMBHSTCFG = 3 and standard values like 0 or 9 causes hangup. Signed-off-by: Martin Devera Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/i2c/busses/i2c-piix4 | 2 +- drivers/i2c/busses/Kconfig | 4 +++- drivers/i2c/busses/i2c-piix4.c | 4 +++- include/linux/pci_ids.h | 1 + 4 files changed, 8 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4 index 856b4b8b962c..a1c8f581afed 100644 --- a/Documentation/i2c/busses/i2c-piix4 +++ b/Documentation/i2c/busses/i2c-piix4 @@ -4,7 +4,7 @@ Supported adapters: * Intel 82371AB PIIX4 and PIIX4E * Intel 82443MX (440MX) Datasheet: Publicly available at the Intel website - * ServerWorks OSB4, CSB5 and CSB6 southbridges + * ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges Datasheet: Only available via NDA from ServerWorks * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge Datasheet: Publicly available at the SMSC website http://www.smsc.com diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 7d2705a68e09..089c6f5b24de 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -168,12 +168,14 @@ config I2C_PIIX4 help If you say yes to this option, support will be included for the Intel PIIX4 family of mainboard I2C interfaces. Specifically, the following - versions of the chipset are supported: + versions of the chipset are supported (note that Serverworks is part + of Broadcom): Intel PIIX4 Intel 440MX Serverworks OSB4 Serverworks CSB5 Serverworks CSB6 + Serverworks HT-1000 SMSC Victory66 This driver can also be built as a module. If so, the module diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 692f47345481..d9c7c00e71f9 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -22,7 +22,7 @@ /* Supports: Intel PIIX4, 440MX - Serverworks OSB4, CSB5, CSB6 + Serverworks OSB4, CSB5, CSB6, HT-1000 SMSC Victory66 Note: we assume there can only be one device, with one SMBus interface. @@ -419,6 +419,8 @@ static struct pci_device_id piix4_ids[] = { .driver_data = 0 }, { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6), .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000SB), + .driver_data = 0 }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3), .driver_data = 3 }, { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3), diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index ec3c32932620..f5a724fbf094 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1371,6 +1371,7 @@ #define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200 #define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201 #define PCI_DEVICE_ID_SERVERWORKS_CSB6 0x0203 +#define PCI_DEVICE_ID_SERVERWORKS_HT1000SB 0x0205 #define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211 #define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212 #define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE 0x0213 -- cgit v1.2.3 From b82db5cedf78bfeb4a1c8a28ae284dc671d26eb3 Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Tue, 17 Jan 2006 16:56:56 -0800 Subject: [PATCH] PCI: return max reserved busnr Change the semantics of this call to return the max reserved bus number instead of just the max assigned bus number. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 5 +++-- include/linux/pci.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e17cd49d6244..0bf6d254426b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -19,7 +19,6 @@ #include /* isa_dma_bridge_buggy */ #include "pci.h" -#if 0 /** * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children @@ -34,7 +33,7 @@ pci_bus_max_busnr(struct pci_bus* bus) struct list_head *tmp; unsigned char max, n; - max = bus->number; + max = bus->subordinate; list_for_each(tmp, &bus->children) { n = pci_bus_max_busnr(pci_bus_b(tmp)); if(n > max) @@ -42,7 +41,9 @@ pci_bus_max_busnr(struct pci_bus* bus) } return max; } +EXPORT_SYMBOL_GPL(pci_bus_max_busnr); +#if 0 /** * pci_max_busnr - returns maximum PCI bus number * diff --git a/include/linux/pci.h b/include/linux/pci.h index fe1a2b02fc55..2039da1f3672 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -516,6 +516,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *), void *userdata); int pci_cfg_space_size(struct pci_dev *dev); +unsigned char pci_bus_max_busnr(struct pci_bus* bus); /* kmem_cache style wrapper around pci_alloc_consistent() */ -- cgit v1.2.3 From 6e325a62a0a228cd0222783802b53cce04551776 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 14 Feb 2006 18:52:22 +0200 Subject: [PATCH] PCI: make MSI quirk inheritable from the pci bus It turns out AMD 8131 quirk only affects MSI for devices behind the 8131 bridge. Handle this by adding a flags field in pci_bus, inherited from parent to child. Signed-off-by: Michael S. Tsirkin Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 3 +++ drivers/pci/probe.c | 1 + drivers/pci/quirks.c | 7 +++++-- include/linux/pci.h | 7 ++++++- 4 files changed, 15 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index d5a67c1bcb98..4de1c17ee573 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -703,6 +703,9 @@ int pci_enable_msi(struct pci_dev* dev) if (dev->no_msi) return status; + if (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) + return -EINVAL; + temp = dev->irq; status = msi_init(); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 3bc0fcd71d03..542e7dfb371b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -347,6 +347,7 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr) child->parent = parent; child->ops = parent->ops; child->sysdata = parent->sysdata; + child->bus_flags = parent->bus_flags; child->bridge = get_device(&bridge->dev); child->class_dev.class = &pcibus_class; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index d71c31df7fdf..4970f47be72c 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -575,8 +575,11 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev) { unsigned char revid, tmp; - pci_msi_quirk = 1; - printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n"); + if (dev->subordinate) { + printk(KERN_WARNING "PCI: MSI quirk detected. " + "PCI_BUS_FLAGS_NO_MSI set for subordinate bus.\n"); + dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; + } if (nr_ioapics == 0) return; diff --git a/include/linux/pci.h b/include/linux/pci.h index 2039da1f3672..d4d533fa5d30 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -95,6 +95,11 @@ enum pci_channel_state { pci_channel_io_perm_failure = (__force pci_channel_state_t) 3, }; +typedef unsigned short __bitwise pci_bus_flags_t; +enum pci_bus_flags { + PCI_BUS_FLAGS_NO_MSI = (pci_bus_flags_t) 1, +}; + /* * The pci_dev structure is used to describe PCI devices. */ @@ -203,7 +208,7 @@ struct pci_bus { char name[48]; unsigned short bridge_ctl; /* manage NO_ISA/FBB/et al behaviors */ - unsigned short pad2; + pci_bus_flags_t bus_flags; /* Inherited by child busses */ struct device *bridge; struct class_device class_dev; struct bin_attribute *legacy_io; /* legacy I/O for this bus */ -- cgit v1.2.3 From ceaba663055e38226a070a9668eac5881d65a2cc Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Thu, 23 Feb 2006 17:56:01 -0800 Subject: [PATCH] acpi: export acpi_bus_trim Export the acpi_bus_trim function so that the pci hotplug driver can use it. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/scan.c | 5 +++-- include/acpi/acpi_bus.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 9271e5209ac1..a0ab828b2cc5 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -23,7 +23,6 @@ static LIST_HEAD(acpi_device_list); DEFINE_SPINLOCK(acpi_device_lock); LIST_HEAD(acpi_wakeup_device_list); -static int acpi_bus_trim(struct acpi_device *start, int rmdevice); static void acpi_device_release(struct kobject *kobj) { @@ -1284,7 +1283,7 @@ int acpi_bus_start(struct acpi_device *device) EXPORT_SYMBOL(acpi_bus_start); -static int acpi_bus_trim(struct acpi_device *start, int rmdevice) +int acpi_bus_trim(struct acpi_device *start, int rmdevice) { acpi_status status; struct acpi_device *parent, *child; @@ -1337,6 +1336,8 @@ static int acpi_bus_trim(struct acpi_device *start, int rmdevice) } return err; } +EXPORT_SYMBOL_GPL(acpi_bus_trim); + static int acpi_bus_scan_fixed(struct acpi_device *root) { diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 0b54e9a4a8a1..e496fac860ac 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -330,6 +330,7 @@ int acpi_bus_register_driver(struct acpi_driver *driver); int acpi_bus_unregister_driver(struct acpi_driver *driver); int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type); +int acpi_bus_trim(struct acpi_device *start, int rmdevice); int acpi_bus_start(struct acpi_device *device); int acpi_match_ids(struct acpi_device *device, char *ids); -- cgit v1.2.3 From 3c990e9219ea0b0aee588473ce6c8a66cdee3ff5 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 4 Mar 2006 21:52:42 -0500 Subject: [PATCH] PCI: fix pci_request_region[s] arg Add missing 'const' to pci_request_region[s] 'res_name' arg, since we pass it directly to __request_region(), whose 'name' arg is also const. Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 4 ++-- include/linux/pci.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 03af23238939..bea1ad1ad5ba 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -639,7 +639,7 @@ void pci_release_region(struct pci_dev *pdev, int bar) * Returns 0 on success, or %EBUSY on error. A warning * message is also printed on failure. */ -int pci_request_region(struct pci_dev *pdev, int bar, char *res_name) +int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name) { if (pci_resource_len(pdev, bar) == 0) return 0; @@ -697,7 +697,7 @@ void pci_release_regions(struct pci_dev *pdev) * Returns 0 on success, or %EBUSY on error. A warning * message is also printed on failure. */ -int pci_request_regions(struct pci_dev *pdev, char *res_name) +int pci_request_regions(struct pci_dev *pdev, const char *res_name) { int i; diff --git a/include/linux/pci.h b/include/linux/pci.h index d4d533fa5d30..0aad5a378e95 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -490,9 +490,9 @@ void pdev_sort_resources(struct pci_dev *, struct resource_list *); void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *), int (*)(struct pci_dev *, u8, u8)); #define HAVE_PCI_REQ_REGIONS 2 -int pci_request_regions(struct pci_dev *, char *); +int pci_request_regions(struct pci_dev *, const char *); void pci_release_regions(struct pci_dev *); -int pci_request_region(struct pci_dev *, int, char *); +int pci_request_region(struct pci_dev *, int, const char *); void pci_release_region(struct pci_dev *, int); /* drivers/pci/bus.c */ -- cgit v1.2.3