From cdcca89e1a90fa9112260bd6384f20fcc4280e21 Mon Sep 17 00:00:00 2001 From: Brett Russ Date: Mon, 28 Mar 2005 15:10:27 -0500 Subject: [PATCH] libata: flush COMRESET set and clear Updated patch to fix erroneous flush of COMRESET set and missing flush of COMRESET clear. Created a new routine scr_write_flush() to try to prevent this in the future. Also, this patch is based on libata-2.6 instead of the previous libata-dev-2.6 based patch. Signed-off-by: Brett Russ Index: libata-2.6/drivers/scsi/libata-core.c =================================================================== --- include/linux/libata.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include') diff --git a/include/linux/libata.h b/include/linux/libata.h index 505160ab472..1f7e2039a04 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -584,6 +584,13 @@ static inline void scr_write(struct ata_port *ap, unsigned int reg, u32 val) ap->ops->scr_write(ap, reg, val); } +static inline void scr_write_flush(struct ata_port *ap, unsigned int reg, + u32 val) +{ + ap->ops->scr_write(ap, reg, val); + (void) ap->ops->scr_read(ap, reg); +} + static inline unsigned int sata_dev_present(struct ata_port *ap) { return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0; -- cgit v1.2.3-70-g09d2 From 02048817a70ad04dda5b30ad876c42a232229c99 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Mon, 16 May 2005 21:53:14 -0700 Subject: [PATCH] uml: remove elf.h Actually remove elf.h in the tree. The previous patch, due to a quilt bug/misuse, left it in the tree as a 0-length file, preventing the build to see it as missing and to generate a symlink in its place. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-um/elf.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 include/asm-um/elf.h (limited to 'include') diff --git a/include/asm-um/elf.h b/include/asm-um/elf.h deleted file mode 100644 index e69de29bb2d..00000000000 -- cgit v1.2.3-70-g09d2 From 637716a3825e186555361574aa1fa3c0ebf8018b Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 16 May 2005 21:53:20 -0700 Subject: [PATCH] x86_64: Add a guard page at the end of the 47bit address space This works around a bug in the AMD K8 CPUs. Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-x86_64/processor.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h index f0581c35628..9f74a286ef1 100644 --- a/include/asm-x86_64/processor.h +++ b/include/asm-x86_64/processor.h @@ -159,9 +159,9 @@ static inline void clear_in_cr4 (unsigned long mask) /* - * User space process size. 47bits. + * User space process size. 47bits minus one guard page. */ -#define TASK_SIZE (0x800000000000UL) +#define TASK_SIZE (0x800000000000UL - 4096) /* This decides where the kernel will search for a free chunk of vm * space during mmap's. -- cgit v1.2.3-70-g09d2 From 1f5ee8da005f50d9f46ae5a7edba9a9c2d37b32e Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 16 May 2005 21:53:22 -0700 Subject: [PATCH] x86_64: Increase number of IO-APICs Needed by big systems and only costs a few K of memory. Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-x86_64/apicdef.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-x86_64/apicdef.h b/include/asm-x86_64/apicdef.h index 3d7627ffe67..bfebdb69065 100644 --- a/include/asm-x86_64/apicdef.h +++ b/include/asm-x86_64/apicdef.h @@ -112,7 +112,7 @@ #define APIC_BASE (fix_to_virt(FIX_APIC_BASE)) -#define MAX_IO_APICS 32 +#define MAX_IO_APICS 128 /* * All x86-64 systems are xAPIC compatible. -- cgit v1.2.3-70-g09d2 From 2942283e970b357c146ebdcbbcc0bdf5048615ff Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 16 May 2005 21:53:26 -0700 Subject: [PATCH] x86_64: Remove x86_apicid field Remove x86_apicid field Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/setup.c | 4 +--- include/asm-x86_64/processor.h | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'include') diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index aab249a5746..966dfc768cb 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -727,7 +727,7 @@ static void __init display_cacheinfo(struct cpuinfo_x86 *c) static void __init amd_detect_cmp(struct cpuinfo_x86 *c) { #ifdef CONFIG_SMP - int cpu = c->x86_apicid; + int cpu = smp_processor_id(); int node = 0; if (c->x86_num_cores == 1) return; @@ -929,7 +929,6 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c) c->x86_clflush_size = 64; c->x86_cache_alignment = c->x86_clflush_size; c->x86_num_cores = 1; - c->x86_apicid = c == &boot_cpu_data ? 0 : c - cpu_data; c->extended_cpuid_level = 0; memset(&c->x86_capability, 0, sizeof c->x86_capability); @@ -958,7 +957,6 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c) } if (c->x86_capability[0] & (1<<19)) c->x86_clflush_size = ((misc >> 8) & 0xff) * 8; - c->x86_apicid = misc >> 24; } else { /* Have CPUID level 0 only - unheard of */ c->x86 = 4; diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h index 9f74a286ef1..d641b19f6da 100644 --- a/include/asm-x86_64/processor.h +++ b/include/asm-x86_64/processor.h @@ -62,7 +62,6 @@ struct cpuinfo_x86 { int x86_tlbsize; /* number of 4K pages in DTLB/ITLB combined(in pages)*/ __u8 x86_virt_bits, x86_phys_bits; __u8 x86_num_cores; - __u8 x86_apicid; __u32 x86_power; __u32 extended_cpuid_level; /* Max extended CPUID function supported */ unsigned long loops_per_jiffy; -- cgit v1.2.3-70-g09d2 From 0af2be0b721997512191e981a051fcb070b87260 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 16 May 2005 21:53:27 -0700 Subject: [PATCH] x86_64: Remove unique APIC/IO-APIC ID check It is unnecessary on modern Intel or AMD systems, and that is all we support on x86-64 Also causes problems on various systems Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/io_apic.c | 70 -------------------------------------------- arch/x86_64/kernel/mpparse.c | 2 +- include/asm-x86_64/io_apic.h | 1 - 3 files changed, 1 insertion(+), 72 deletions(-) (limited to 'include') diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 60be58617eb..ac768432495 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -1804,76 +1804,6 @@ device_initcall(ioapic_init_sysfs); #define IO_APIC_MAX_ID 0xFE -int __init io_apic_get_unique_id (int ioapic, int apic_id) -{ - union IO_APIC_reg_00 reg_00; - static physid_mask_t apic_id_map; - unsigned long flags; - int i = 0; - - /* - * The P4 platform supports up to 256 APIC IDs on two separate APIC - * buses (one for LAPICs, one for IOAPICs), where predecessors only - * supports up to 16 on one shared APIC bus. - * - * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full - * advantage of new APIC bus architecture. - */ - - if (physids_empty(apic_id_map)) - apic_id_map = phys_cpu_present_map; - - spin_lock_irqsave(&ioapic_lock, flags); - reg_00.raw = io_apic_read(ioapic, 0); - spin_unlock_irqrestore(&ioapic_lock, flags); - - if (apic_id >= IO_APIC_MAX_ID) { - apic_printk(APIC_QUIET, KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying " - "%d\n", ioapic, apic_id, reg_00.bits.ID); - apic_id = reg_00.bits.ID; - } - - /* - * Every APIC in a system must have a unique ID or we get lots of nice - * 'stuck on smp_invalidate_needed IPI wait' messages. - */ - if (physid_isset(apic_id, apic_id_map)) { - - for (i = 0; i < IO_APIC_MAX_ID; i++) { - if (!physid_isset(i, apic_id_map)) - break; - } - - if (i == IO_APIC_MAX_ID) - panic("Max apic_id exceeded!\n"); - - apic_printk(APIC_VERBOSE, KERN_WARNING "IOAPIC[%d]: apic_id %d already used, " - "trying %d\n", ioapic, apic_id, i); - - apic_id = i; - } - - physid_set(apic_id, apic_id_map); - - if (reg_00.bits.ID != apic_id) { - reg_00.bits.ID = apic_id; - - spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(ioapic, 0, reg_00.raw); - reg_00.raw = io_apic_read(ioapic, 0); - spin_unlock_irqrestore(&ioapic_lock, flags); - - /* Sanity check */ - if (reg_00.bits.ID != apic_id) - panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic); - } - - apic_printk(APIC_VERBOSE,KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id); - - return apic_id; -} - - int __init io_apic_get_version (int ioapic) { union IO_APIC_reg_01 reg_01; diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c index 7ec031c6ca1..f221231cd0a 100644 --- a/arch/x86_64/kernel/mpparse.c +++ b/arch/x86_64/kernel/mpparse.c @@ -759,7 +759,7 @@ void __init mp_register_ioapic ( mp_ioapics[idx].mpc_apicaddr = address; set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); - mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id); + mp_ioapics[idx].mpc_apicid = id; mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx); /* diff --git a/include/asm-x86_64/io_apic.h b/include/asm-x86_64/io_apic.h index 7efc932e8f0..32573749004 100644 --- a/include/asm-x86_64/io_apic.h +++ b/include/asm-x86_64/io_apic.h @@ -202,7 +202,6 @@ extern int skip_ioapic_setup; #define io_apic_assign_pci_irqs (mp_irq_entries && !skip_ioapic_setup && io_apic_irqs) #ifdef CONFIG_ACPI_BOOT -extern int io_apic_get_unique_id (int ioapic, int apic_id); extern int io_apic_get_version (int ioapic); extern int io_apic_get_redir_entries (int ioapic); extern int io_apic_set_pci_routing (int ioapic, int pin, int irq, int, int); -- cgit v1.2.3-70-g09d2 From 312df5f1a1da780e084b328bcabb02a6dcd044c3 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 16 May 2005 21:53:28 -0700 Subject: [PATCH] x86_64: Add pmtimer support There are unfortunately more and more multi processor Opteron systems which don't have HPET timer support in the southbridge. This covers in particular Nvidia and VIA chipsets. They also don't guarantee that the TSCs are synchronized between CPUs; and especially with MP powernow the systems are nearly unusable because the time gets very inconsistent between CPUs. The timer code for x86-64 was originally written under the assumption that we could fall back to the HPET timer on such systems. But this doesn't work there. Another alternative is to use the ACPI PM timer as primary time source. This patch does that. The kernel only uses PM timer when there is no other choice because it has some disadvantages. Ported over from i386. It should be faster than the i386 version because I dropped the "read three times" workaround, but is still considerable slower than HPET and also does not work together with vsyscalls which have to be disabled. Cc: Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/Kconfig | 14 ++++++ arch/x86_64/kernel/Makefile | 1 + arch/x86_64/kernel/pmtimer.c | 101 ++++++++++++++++++++++++++++++++++++++++++ arch/x86_64/kernel/time.c | 62 +++++++++++++++++++------- arch/x86_64/kernel/vsyscall.c | 3 +- include/asm-x86_64/proto.h | 5 +++ include/asm-x86_64/vsyscall.h | 3 ++ 7 files changed, 170 insertions(+), 19 deletions(-) create mode 100644 arch/x86_64/kernel/pmtimer.c (limited to 'include') diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 44ee7f6acf7..82cb2a3f127 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -303,6 +303,20 @@ config HPET_TIMER as it is off-chip. You can find the HPET spec at . +config X86_PM_TIMER + bool "PM timer" + default y + help + Support the ACPI PM timer for time keeping. This is slow, + but is useful on some chipsets without HPET on systems with more + than one CPU. On a single processor or single socket multi core + system it is normally not required. + When the PM timer is active 64bit vsyscalls are disabled + and should not be enabled (/proc/sys/kernel/vsyscall64 should + not be changed). + The kernel selects the PM timer only as a last resort, so it is + useful to enable just in case. + config HPET_EMULATE_RTC bool "Provide RTC interrupt" depends on HPET_TIMER && RTC=y diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile index 0a3318e08ab..5ca4a4598fd 100644 --- a/arch/x86_64/kernel/Makefile +++ b/arch/x86_64/kernel/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o pci-dma.o obj-$(CONFIG_SWIOTLB) += swiotlb.o obj-$(CONFIG_KPROBES) += kprobes.o +obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o obj-$(CONFIG_MODULES) += module.o diff --git a/arch/x86_64/kernel/pmtimer.c b/arch/x86_64/kernel/pmtimer.c new file mode 100644 index 00000000000..feb5f108dd2 --- /dev/null +++ b/arch/x86_64/kernel/pmtimer.c @@ -0,0 +1,101 @@ +/* Ported over from i386 by AK, original copyright was: + * + * (C) Dominik Brodowski 2003 + * + * Driver to use the Power Management Timer (PMTMR) available in some + * southbridges as primary timing source for the Linux kernel. + * + * Based on parts of linux/drivers/acpi/hardware/hwtimer.c, timer_pit.c, + * timer_hpet.c, and on Arjan van de Ven's implementation for 2.4. + * + * This file is licensed under the GPL v2. + * + * Dropped all the hardware bug workarounds for now. Hopefully they + * are not needed on 64bit chipsets. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* The I/O port the PMTMR resides at. + * The location is detected during setup_arch(), + * in arch/i386/kernel/acpi/boot.c */ +u32 pmtmr_ioport; + +/* value of the Power timer at last timer interrupt */ +static u32 offset_delay; +static u32 last_pmtmr_tick; + +#define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */ + +static inline u32 cyc2us(u32 cycles) +{ + /* The Power Management Timer ticks at 3.579545 ticks per microsecond. + * 1 / PM_TIMER_FREQUENCY == 0.27936511 =~ 286/1024 [error: 0.024%] + * + * Even with HZ = 100, delta is at maximum 35796 ticks, so it can + * easily be multiplied with 286 (=0x11E) without having to fear + * u32 overflows. + */ + cycles *= 286; + return (cycles >> 10); +} + +int pmtimer_mark_offset(void) +{ + static int first_run = 1; + unsigned long tsc; + u32 lost; + + u32 tick = inl(pmtmr_ioport); + u32 delta; + + delta = cyc2us((tick - last_pmtmr_tick) & ACPI_PM_MASK); + + last_pmtmr_tick = tick; + monotonic_base += delta * NSEC_PER_USEC; + + delta += offset_delay; + + lost = delta / (USEC_PER_SEC / HZ); + offset_delay = delta % (USEC_PER_SEC / HZ); + + rdtscll(tsc); + vxtime.last_tsc = tsc - offset_delay * cpu_khz; + + /* don't calculate delay for first run, + or if we've got less then a tick */ + if (first_run || (lost < 1)) { + first_run = 0; + offset_delay = 0; + } + + return lost - 1; +} + +unsigned int do_gettimeoffset_pm(void) +{ + u32 now, offset, delta = 0; + + offset = last_pmtmr_tick; + now = inl(pmtmr_ioport); + delta = (now - offset) & ACPI_PM_MASK; + + return offset_delay + cyc2us(delta); +} + + +static int __init nopmtimer_setup(char *s) +{ + pmtmr_ioport = 0; + return 0; +} + +__setup("nopmtimer", nopmtimer_setup); diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index 0e3b60e1ac5..735b6767c8e 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include /* for PM timer frequency */ #include #include #include @@ -396,6 +398,10 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) (offset - vxtime.last)*(NSEC_PER_SEC/HZ) / hpet_tick; vxtime.last = offset; +#ifdef CONFIG_X86_PM_TIMER + } else if (vxtime.mode == VXTIME_PMTMR) { + lost = pmtimer_mark_offset(); +#endif } else { offset = (((tsc - vxtime.last_tsc) * vxtime.tsc_quot) >> 32) - (USEC_PER_SEC / HZ); @@ -898,6 +904,13 @@ void __init time_init(void) hpet_period; cpu_khz = hpet_calibrate_tsc(); timename = "HPET"; +#ifdef CONFIG_X86_PM_TIMER + } else if (pmtmr_ioport) { + vxtime_hz = PM_TIMER_FREQUENCY; + timename = "PM"; + pit_init(); + cpu_khz = pit_calibrate_tsc(); +#endif } else { pit_init(); cpu_khz = pit_calibrate_tsc(); @@ -922,6 +935,27 @@ void __init time_init(void) #endif } +/* + * Make an educated guess if the TSC is trustworthy and synchronized + * over all CPUs. + */ +static __init int unsynchronized_tsc(void) +{ +#ifdef CONFIG_SMP + if (oem_force_hpet_timer()) + return 1; + /* Intel systems are normally all synchronized. Exceptions + are handled in the OEM check above. */ + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) + return 0; + /* All in a single socket - should be synchronized */ + if (cpus_weight(cpu_core_map[0]) == num_online_cpus()) + return 0; +#endif + /* Assume multi socket systems are not synchronized */ + return num_online_cpus() > 1; +} + /* * Decide after all CPUs are booted what mode gettimeofday should use. */ @@ -929,29 +963,23 @@ void __init time_init_gtod(void) { char *timetype; - /* - * AMD systems with more than one CPU don't have fully synchronized - * TSCs. Always use HPET gettimeofday for these, although it is slower. - * Intel SMP systems usually have synchronized TSCs, so use always - * the TSC. - * - * Exceptions: - * IBM Summit2 checked by oem_force_hpet_timer(). - * AMD dual core may also not need HPET. Check me. - * - * Can be turned off with "notsc". - */ - if (num_online_cpus() > 1 && - boot_cpu_data.x86_vendor == X86_VENDOR_AMD) - notsc = 1; - /* Some systems will want to disable TSC and use HPET. */ - if (oem_force_hpet_timer()) + if (unsynchronized_tsc()) notsc = 1; if (vxtime.hpet_address && notsc) { timetype = "HPET"; vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick; vxtime.mode = VXTIME_HPET; do_gettimeoffset = do_gettimeoffset_hpet; +#ifdef CONFIG_X86_PM_TIMER + /* Using PM for gettimeofday is quite slow, but we have no other + choice because the TSC is too unreliable on some systems. */ + } else if (pmtmr_ioport && !vxtime.hpet_address && notsc) { + timetype = "PM"; + do_gettimeoffset = do_gettimeoffset_pm; + vxtime.mode = VXTIME_PMTMR; + sysctl_vsyscall = 0; + printk(KERN_INFO "Disabling vsyscall due to use of PM timer\n"); +#endif } else { timetype = vxtime.hpet_address ? "HPET/TSC" : "PIT/TSC"; vxtime.mode = VXTIME_TSC; diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c index b4b8dc59663..1a7541435ef 100644 --- a/arch/x86_64/kernel/vsyscall.c +++ b/arch/x86_64/kernel/vsyscall.c @@ -65,7 +65,7 @@ static force_inline void do_vgettimeofday(struct timeval * tv) usec = (__xtime.tv_nsec / 1000) + (__jiffies - __wall_jiffies) * (1000000 / HZ); - if (__vxtime.mode == VXTIME_TSC) { + if (__vxtime.mode != VXTIME_HPET) { sync_core(); rdtscll(t); if (t < __vxtime.last_tsc) @@ -217,7 +217,6 @@ static int __init vsyscall_init(void) BUG_ON((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime)); BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE))); map_vsyscall(); - sysctl_vsyscall = 1; register_sysctl_table(kernel_root_table2, 0); return 0; } diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h index d0f8f8b4c39..f2f073642d6 100644 --- a/include/asm-x86_64/proto.h +++ b/include/asm-x86_64/proto.h @@ -30,6 +30,11 @@ extern void ia32_syscall(void); extern void iommu_hole_init(void); extern void time_init_gtod(void); +extern int pmtimer_mark_offset(void); +extern unsigned int do_gettimeoffset_pm(void); +extern u32 pmtmr_ioport; +extern unsigned long long monotonic_base; +extern int sysctl_vsyscall; extern void do_softirq_thunk(void); diff --git a/include/asm-x86_64/vsyscall.h b/include/asm-x86_64/vsyscall.h index b0c8d433990..2872da23fc7 100644 --- a/include/asm-x86_64/vsyscall.h +++ b/include/asm-x86_64/vsyscall.h @@ -25,6 +25,7 @@ enum vsyscall_num { #define VXTIME_TSC 1 #define VXTIME_HPET 2 +#define VXTIME_PMTMR 3 struct vxtime_data { long hpet_address; /* HPET base address */ @@ -54,6 +55,8 @@ extern struct timezone sys_tz; extern int sysctl_vsyscall; extern seqlock_t xtime_lock; +extern int sysctl_vsyscall; + #define ARCH_HAVE_XTIME_LOCK 1 #endif /* __KERNEL__ */ -- cgit v1.2.3-70-g09d2 From 751521149a05e308d863d01ced61080ce1a2ec99 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 16 May 2005 21:53:34 -0700 Subject: [PATCH] x86_64: Collected NMI watchdog fixes. Collected NMI watchdog fixes. - Fix call of check_nmi_watchdog - Remove earlier move of check_nmi_watchdog to later. It does not fix the race it was supposed to fix fully. - Remove unused P6 definitions - Add support for performance counter based watchdog on P4 systems. This allows to run it only once per second, which saves some CPU time. Previously it would run at 1000Hz, which was too much. Code ported from i386 Make this the default on Intel systems. - Use check_nmi_watchdog with local APIC based nmi - Fix race in touch_nmi_watchdog - Fix bug that caused incorrect performance counters to be programmed in a few cases on K8. - Remove useless check for local APIC - Use local_t and per_cpu variables for per CPU data. - Keep other CPUs busy during check_nmi_watchdog to make sure they really tick when in lapic mode. - Only check CPUs that are actually online. - Various other fixes. - Fix fallback path when MSRs are unimplemented Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/apic.c | 3 +- arch/x86_64/kernel/nmi.c | 250 +++++++++++++++++++++++++++++-------------- arch/x86_64/kernel/smpboot.c | 3 + include/asm-x86_64/nmi.h | 2 + 4 files changed, 179 insertions(+), 79 deletions(-) (limited to 'include') diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index 7f0b44e4a6e..f8e6cc4fecd 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c @@ -33,6 +33,7 @@ #include #include #include +#include int apic_verbosity; @@ -1056,7 +1057,7 @@ int __init APIC_init_uniprocessor (void) nr_ioapics = 0; #endif setup_boot_APIC_clock(); - + check_nmi_watchdog(); return 0; } diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index ec13eb97e8e..31c0f2e6ac9 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c @@ -33,6 +33,7 @@ #include #include #include +#include /* * lapic_nmi_owner tracks the ownership of the lapic NMI hardware: @@ -59,7 +60,8 @@ int panic_on_timeout; unsigned int nmi_watchdog = NMI_DEFAULT; static unsigned int nmi_hz = HZ; -unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */ +static unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */ +static unsigned int nmi_p4_cccr_val; /* Note that these events don't tick when the CPU idles. This means the frequency varies with CPU load. */ @@ -71,67 +73,87 @@ unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */ #define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 0x76 #define K7_NMI_EVENT K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING -#define P6_EVNTSEL0_ENABLE (1 << 22) -#define P6_EVNTSEL_INT (1 << 20) -#define P6_EVNTSEL_OS (1 << 17) -#define P6_EVNTSEL_USR (1 << 16) -#define P6_EVENT_CPU_CLOCKS_NOT_HALTED 0x79 -#define P6_NMI_EVENT P6_EVENT_CPU_CLOCKS_NOT_HALTED +#define MSR_P4_MISC_ENABLE 0x1A0 +#define MSR_P4_MISC_ENABLE_PERF_AVAIL (1<<7) +#define MSR_P4_MISC_ENABLE_PEBS_UNAVAIL (1<<12) +#define MSR_P4_PERFCTR0 0x300 +#define MSR_P4_CCCR0 0x360 +#define P4_ESCR_EVENT_SELECT(N) ((N)<<25) +#define P4_ESCR_OS (1<<3) +#define P4_ESCR_USR (1<<2) +#define P4_CCCR_OVF_PMI0 (1<<26) +#define P4_CCCR_OVF_PMI1 (1<<27) +#define P4_CCCR_THRESHOLD(N) ((N)<<20) +#define P4_CCCR_COMPLEMENT (1<<19) +#define P4_CCCR_COMPARE (1<<18) +#define P4_CCCR_REQUIRED (3<<16) +#define P4_CCCR_ESCR_SELECT(N) ((N)<<13) +#define P4_CCCR_ENABLE (1<<12) +/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter + CRU_ESCR0 (with any non-null event selector) through a complemented + max threshold. [IA32-Vol3, Section 14.9.9] */ +#define MSR_P4_IQ_COUNTER0 0x30C +#define P4_NMI_CRU_ESCR0 (P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS|P4_ESCR_USR) +#define P4_NMI_IQ_CCCR0 \ + (P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \ + P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE) + +static __init inline int nmi_known_cpu(void) +{ + switch (boot_cpu_data.x86_vendor) { + case X86_VENDOR_AMD: + return boot_cpu_data.x86 == 15; + case X86_VENDOR_INTEL: + return boot_cpu_data.x86 == 15; + } + return 0; +} /* Run after command line and cpu_init init, but before all other checks */ void __init nmi_watchdog_default(void) { if (nmi_watchdog != NMI_DEFAULT) return; - - /* For some reason the IO APIC watchdog doesn't work on the AMD - 8111 chipset. For now switch to local APIC mode using - perfctr0 there. On Intel CPUs we don't have code to handle - the perfctr and the IO-APIC seems to work, so use that. */ - - if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { - nmi_watchdog = NMI_LOCAL_APIC; - printk(KERN_INFO - "Using local APIC NMI watchdog using perfctr0\n"); - } else { - printk(KERN_INFO "Using IO APIC NMI watchdog\n"); + if (nmi_known_cpu()) + nmi_watchdog = NMI_LOCAL_APIC; + else nmi_watchdog = NMI_IO_APIC; - } } -/* Why is there no CPUID flag for this? */ -static __init int cpu_has_lapic(void) +#ifdef CONFIG_SMP +/* The performance counters used by NMI_LOCAL_APIC don't trigger when + * the CPU is idle. To make sure the NMI watchdog really ticks on all + * CPUs during the test make them busy. + */ +static __init void nmi_cpu_busy(void *data) { - switch (boot_cpu_data.x86_vendor) { - case X86_VENDOR_INTEL: - case X86_VENDOR_AMD: - return boot_cpu_data.x86 >= 6; - /* .... add more cpus here or find a different way to figure this out. */ - default: - return 0; - } + volatile int *endflag = data; + local_irq_enable(); + /* Intentionally don't use cpu_relax here. This is + to make sure that the performance counter really ticks, + even if there is a simulator or similar that catches the + pause instruction. On a real HT machine this is fine because + all other CPUs are busy with "useless" delay loops and don't + care if they get somewhat less cycles. */ + while (*endflag == 0) + barrier(); } +#endif -static int __init check_nmi_watchdog (void) +int __init check_nmi_watchdog (void) { + volatile int endflag = 0; int *counts; int cpu; - if (nmi_watchdog == NMI_NONE) - return 0; + counts = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL); + if (!counts) + return -1; - if (nmi_watchdog == NMI_LOCAL_APIC && !cpu_has_lapic()) { - nmi_watchdog = NMI_NONE; - return -1; - } + printk(KERN_INFO "testing NMI watchdog ... "); - counts = kmalloc(NR_CPUS * sizeof(int),GFP_KERNEL); - if (!counts) { - nmi_watchdog = NMI_NONE; - return 0; - } - - printk(KERN_INFO "Testing NMI watchdog ... "); + if (nmi_watchdog == NMI_LOCAL_APIC) + smp_call_function(nmi_cpu_busy, (void *)&endflag, 0, 0); for (cpu = 0; cpu < NR_CPUS; cpu++) counts[cpu] = cpu_pda[cpu].__nmi_count; @@ -139,16 +161,22 @@ static int __init check_nmi_watchdog (void) mdelay((10*1000)/nmi_hz); // wait 10 ticks for (cpu = 0; cpu < NR_CPUS; cpu++) { + if (!cpu_online(cpu)) + continue; if (cpu_pda[cpu].__nmi_count - counts[cpu] <= 5) { - printk("CPU#%d: NMI appears to be stuck (%d)!\n", + endflag = 1; + printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n", cpu, + counts[cpu], cpu_pda[cpu].__nmi_count); nmi_active = 0; lapic_nmi_owner &= ~LAPIC_NMI_WATCHDOG; + nmi_perfctr_msr = 0; kfree(counts); return -1; } } + endflag = 1; printk("OK.\n"); /* now that we know it works we can reduce NMI frequency to @@ -159,8 +187,6 @@ static int __init check_nmi_watchdog (void) kfree(counts); return 0; } -/* Have this called later during boot so counters are updating */ -late_initcall(check_nmi_watchdog); int __init setup_nmi_watchdog(char *str) { @@ -178,7 +204,7 @@ int __init setup_nmi_watchdog(char *str) if (nmi >= NMI_INVALID) return 0; - nmi_watchdog = nmi; + nmi_watchdog = nmi; return 1; } @@ -193,7 +219,10 @@ static void disable_lapic_nmi_watchdog(void) wrmsr(MSR_K7_EVNTSEL0, 0, 0); break; case X86_VENDOR_INTEL: - wrmsr(MSR_IA32_EVNTSEL0, 0, 0); + if (boot_cpu_data.x86 == 15) { + wrmsr(MSR_P4_IQ_CCCR0, 0, 0); + wrmsr(MSR_P4_CRU_ESCR0, 0, 0); + } break; } nmi_active = -1; @@ -261,7 +290,7 @@ void enable_timer_nmi_watchdog(void) static int nmi_pm_active; /* nmi_active before suspend */ -static int lapic_nmi_suspend(struct sys_device *dev, pm_message_t state) +static int lapic_nmi_suspend(struct sys_device *dev, u32 state) { nmi_pm_active = nmi_active; disable_lapic_nmi_watchdog(); @@ -308,22 +337,27 @@ late_initcall(init_lapic_nmi_sysfs); * Original code written by Keith Owens. */ +static void clear_msr_range(unsigned int base, unsigned int n) +{ + unsigned int i; + + for(i = 0; i < n; ++i) + wrmsr(base+i, 0, 0); +} + static void setup_k7_watchdog(void) { int i; unsigned int evntsel; - /* No check, so can start with slow frequency */ - nmi_hz = 1; - - /* XXX should check these in EFER */ - nmi_perfctr_msr = MSR_K7_PERFCTR0; for(i = 0; i < 4; ++i) { /* Simulator may not support it */ - if (checking_wrmsrl(MSR_K7_EVNTSEL0+i, 0UL)) + if (checking_wrmsrl(MSR_K7_EVNTSEL0+i, 0UL)) { + nmi_perfctr_msr = 0; return; + } wrmsrl(MSR_K7_PERFCTR0+i, 0UL); } @@ -333,12 +367,54 @@ static void setup_k7_watchdog(void) | K7_NMI_EVENT; wrmsr(MSR_K7_EVNTSEL0, evntsel, 0); - wrmsrl(MSR_K7_PERFCTR0, -((u64)cpu_khz*1000) / nmi_hz); + wrmsr(MSR_K7_PERFCTR0, -(cpu_khz/nmi_hz*1000), -1); apic_write(APIC_LVTPC, APIC_DM_NMI); evntsel |= K7_EVNTSEL_ENABLE; wrmsr(MSR_K7_EVNTSEL0, evntsel, 0); } + +static int setup_p4_watchdog(void) +{ + unsigned int misc_enable, dummy; + + rdmsr(MSR_P4_MISC_ENABLE, misc_enable, dummy); + if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL)) + return 0; + + nmi_perfctr_msr = MSR_P4_IQ_COUNTER0; + nmi_p4_cccr_val = P4_NMI_IQ_CCCR0; +#ifdef CONFIG_SMP + if (smp_num_siblings == 2) + nmi_p4_cccr_val |= P4_CCCR_OVF_PMI1; +#endif + + if (!(misc_enable & MSR_P4_MISC_ENABLE_PEBS_UNAVAIL)) + clear_msr_range(0x3F1, 2); + /* MSR 0x3F0 seems to have a default value of 0xFC00, but current + docs doesn't fully define it, so leave it alone for now. */ + if (boot_cpu_data.x86_model >= 0x3) { + /* MSR_P4_IQ_ESCR0/1 (0x3ba/0x3bb) removed */ + clear_msr_range(0x3A0, 26); + clear_msr_range(0x3BC, 3); + } else { + clear_msr_range(0x3A0, 31); + } + clear_msr_range(0x3C0, 6); + clear_msr_range(0x3C8, 6); + clear_msr_range(0x3E0, 2); + clear_msr_range(MSR_P4_CCCR0, 18); + clear_msr_range(MSR_P4_PERFCTR0, 18); + + wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0); + wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0); + Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000)); + wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1); + apic_write(APIC_LVTPC, APIC_DM_NMI); + wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0); + return 1; +} + void setup_apic_nmi_watchdog(void) { switch (boot_cpu_data.x86_vendor) { @@ -349,6 +425,13 @@ void setup_apic_nmi_watchdog(void) return; setup_k7_watchdog(); break; + case X86_VENDOR_INTEL: + if (boot_cpu_data.x86 != 15) + return; + if (!setup_p4_watchdog()) + return; + break; + default: return; } @@ -363,56 +446,67 @@ void setup_apic_nmi_watchdog(void) * * as these watchdog NMI IRQs are generated on every CPU, we only * have to check the current processor. - * - * since NMIs don't listen to _any_ locks, we have to be extremely - * careful not to rely on unsafe variables. The printk might lock - * up though, so we have to break up any console locks first ... - * [when there will be more tty-related locks, break them up - * here too!] */ -static unsigned int - last_irq_sums [NR_CPUS], - alert_counter [NR_CPUS]; +static DEFINE_PER_CPU(unsigned, last_irq_sum); +static DEFINE_PER_CPU(local_t, alert_counter); +static DEFINE_PER_CPU(int, nmi_touch); void touch_nmi_watchdog (void) { int i; /* - * Just reset the alert counters, (other CPUs might be - * spinning on locks we hold): + * Tell other CPUs to reset their alert counters. We cannot + * do it ourselves because the alert count increase is not + * atomic. */ for (i = 0; i < NR_CPUS; i++) - alert_counter[i] = 0; + per_cpu(nmi_touch, i) = 1; } void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason) { - int sum, cpu; + int sum; + int touched = 0; - cpu = safe_smp_processor_id(); sum = read_pda(apic_timer_irqs); - if (last_irq_sums[cpu] == sum) { + if (__get_cpu_var(nmi_touch)) { + __get_cpu_var(nmi_touch) = 0; + touched = 1; + } + if (!touched && __get_cpu_var(last_irq_sum) == sum) { /* * Ayiee, looks like this CPU is stuck ... * wait a few IRQs (5 seconds) before doing the oops ... */ - alert_counter[cpu]++; - if (alert_counter[cpu] == 5*nmi_hz) { + local_inc(&__get_cpu_var(alert_counter)); + if (local_read(&__get_cpu_var(alert_counter)) == 5*nmi_hz) { if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP) { - alert_counter[cpu] = 0; + local_set(&__get_cpu_var(alert_counter), 0); return; } die_nmi("NMI Watchdog detected LOCKUP on CPU%d", regs); } } else { - last_irq_sums[cpu] = sum; - alert_counter[cpu] = 0; + __get_cpu_var(last_irq_sum) = sum; + local_set(&__get_cpu_var(alert_counter), 0); } - if (nmi_perfctr_msr) + if (nmi_perfctr_msr) { + if (nmi_perfctr_msr == MSR_P4_IQ_COUNTER0) { + /* + * P4 quirks: + * - An overflown perfctr will assert its interrupt + * until the OVF flag in its CCCR is cleared. + * - LVTPC is masked on interrupt and must be + * unmasked by the LVTPC handler. + */ + wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0); + apic_write(APIC_LVTPC, APIC_DM_NMI); + } wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1); + } } static int dummy_nmi_callback(struct pt_regs * regs, int cpu) diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index 17efc40baa3..d00e494c1a3 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -56,6 +56,7 @@ #include #include #include +#include /* Change for real CPU hotplug. Note other files need to be fixed first too. */ @@ -1030,4 +1031,6 @@ void __cpuinit smp_cpus_done(unsigned int max_cpus) detect_siblings(); time_init_gtod(); + + check_nmi_watchdog(); } diff --git a/include/asm-x86_64/nmi.h b/include/asm-x86_64/nmi.h index 21d56b086b9..d3abfc6a8fd 100644 --- a/include/asm-x86_64/nmi.h +++ b/include/asm-x86_64/nmi.h @@ -53,5 +53,7 @@ extern void die_nmi(char *str, struct pt_regs *regs); extern int panic_on_timeout; extern int unknown_nmi_panic; + +extern int check_nmi_watchdog(void); #endif /* ASM_NMI_H */ -- cgit v1.2.3-70-g09d2 From 5418b6925c353c8286651b67fdb8559dd9e54e46 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 16 May 2005 21:53:57 -0700 Subject: [PATCH] kill These days handles everything, no need for an asm header on just two architectures. Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/ia32/ia32_ioctl.c | 1 - include/asm-ia64/ioctl32.h | 1 - include/asm-x86_64/ioctl32.h | 1 - 3 files changed, 3 deletions(-) (limited to 'include') diff --git a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c index 9845dabe261..164b211f417 100644 --- a/arch/ia64/ia32/ia32_ioctl.c +++ b/arch/ia64/ia32/ia32_ioctl.c @@ -13,7 +13,6 @@ #define INCLUDES #include "compat_ioctl.c" -#include #define IOCTL_NR(a) ((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) diff --git a/include/asm-ia64/ioctl32.h b/include/asm-ia64/ioctl32.h index d0d227f45e0..e69de29bb2d 100644 --- a/include/asm-ia64/ioctl32.h +++ b/include/asm-ia64/ioctl32.h @@ -1 +0,0 @@ -#include diff --git a/include/asm-x86_64/ioctl32.h b/include/asm-x86_64/ioctl32.h index d0d227f45e0..e69de29bb2d 100644 --- a/include/asm-x86_64/ioctl32.h +++ b/include/asm-x86_64/ioctl32.h @@ -1 +0,0 @@ -#include -- cgit v1.2.3-70-g09d2 From fdc53a6dbfea18e621dd23ed5cfb160837d7ce52 Mon Sep 17 00:00:00 2001 From: Johannes Stezenbach Date: Mon, 16 May 2005 21:54:39 -0700 Subject: [PATCH] dvb: modified dvb_register_adapter() to avoid kmalloc/kfree Modified dvb_register_adapter() to avoid kmalloc/kfree. Drivers have to embed struct dvb_adapter into their private data struct from now on. (Andreas Oberritter) Signed-off-by: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/b2c2/skystar2.c | 20 ++++++++-------- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 20 ++++++++-------- drivers/media/dvb/bt8xx/dvb-bt8xx.h | 2 +- drivers/media/dvb/cinergyT2/cinergyT2.c | 12 +++++----- drivers/media/dvb/dibusb/dvb-dibusb-dvb.c | 10 ++++---- drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c | 4 ++-- drivers/media/dvb/dibusb/dvb-dibusb.h | 2 +- drivers/media/dvb/dvb-core/dvbdev.c | 9 +------- drivers/media/dvb/dvb-core/dvbdev.h | 2 +- drivers/media/dvb/ttpci/av7110.c | 28 +++++++++++------------ drivers/media/dvb/ttpci/av7110.h | 2 +- drivers/media/dvb/ttpci/av7110_av.c | 4 ++-- drivers/media/dvb/ttpci/av7110_ca.c | 2 +- drivers/media/dvb/ttpci/av7110_hw.c | 8 +++---- drivers/media/dvb/ttpci/av7110_v4l.c | 10 ++++---- drivers/media/dvb/ttpci/budget-av.c | 12 +++++----- drivers/media/dvb/ttpci/budget-ci.c | 6 ++--- drivers/media/dvb/ttpci/budget-core.c | 12 +++++----- drivers/media/dvb/ttpci/budget-patch.c | 4 ++-- drivers/media/dvb/ttpci/budget.c | 4 ++-- drivers/media/dvb/ttpci/budget.h | 2 +- drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 20 ++++++++-------- drivers/media/dvb/ttusb-dec/ttusb_dec.c | 20 ++++++++-------- drivers/media/video/video-buf-dvb.c | 12 +++++----- include/media/video-buf-dvb.h | 2 +- 25 files changed, 111 insertions(+), 118 deletions(-) (limited to 'include') diff --git a/drivers/media/dvb/b2c2/skystar2.c b/drivers/media/dvb/b2c2/skystar2.c index 336c178fcd5..acbc4c34f72 100644 --- a/drivers/media/dvb/b2c2/skystar2.c +++ b/drivers/media/dvb/b2c2/skystar2.c @@ -97,7 +97,7 @@ struct adapter { u8 mac_addr[8]; u32 dw_sram_type; - struct dvb_adapter *dvb_adapter; + struct dvb_adapter dvb_adapter; struct dvb_demux demux; struct dmxdev dmxdev; struct dmx_frontend hw_frontend; @@ -2461,7 +2461,7 @@ static void frontend_init(struct adapter *skystar2) skystar2->pdev->subsystem_vendor, skystar2->pdev->subsystem_device); } else { - if (dvb_register_frontend(skystar2->dvb_adapter, skystar2->fe)) { + if (dvb_register_frontend(&skystar2->dvb_adapter, skystar2->fe)) { printk("skystar2: Frontend registration failed!\n"); if (skystar2->fe->ops->release) skystar2->fe->ops->release(skystar2->fe); @@ -2486,17 +2486,17 @@ static int skystar2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret < 0) goto out; - ret = dvb_register_adapter(&dvb_adapter, skystar2_pci_driver.name, + adapter = pci_get_drvdata(pdev); + dvb_adapter = &adapter->dvb_adapter; + + ret = dvb_register_adapter(dvb_adapter, skystar2_pci_driver.name, THIS_MODULE); if (ret < 0) { printk("%s: Error registering DVB adapter\n", __FUNCTION__); goto err_halt; } - adapter = pci_get_drvdata(pdev); - dvb_adapter->priv = adapter; - adapter->dvb_adapter = dvb_adapter; init_MUTEX(&adapter->i2c_sem); @@ -2541,7 +2541,7 @@ static int skystar2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->dmxdev.demux = dmx; adapter->dmxdev.capabilities = 0; - ret = dvb_dmxdev_init(&adapter->dmxdev, adapter->dvb_adapter); + ret = dvb_dmxdev_init(&adapter->dmxdev, &adapter->dvb_adapter); if (ret < 0) goto err_dmx_release; @@ -2559,7 +2559,7 @@ static int skystar2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret < 0) goto err_remove_mem_frontend; - dvb_net_init(adapter->dvb_adapter, &adapter->dvbnet, &dvbdemux->dmx); + dvb_net_init(&adapter->dvb_adapter, &adapter->dvbnet, &dvbdemux->dmx); frontend_init(adapter); out: @@ -2576,7 +2576,7 @@ err_dmx_release: err_i2c_del: i2c_del_adapter(&adapter->i2c_adap); err_dvb_unregister: - dvb_unregister_adapter(adapter->dvb_adapter); + dvb_unregister_adapter(&adapter->dvb_adapter); err_halt: driver_halt(pdev); goto out; @@ -2605,7 +2605,7 @@ static void skystar2_remove(struct pci_dev *pdev) if (adapter->fe != NULL) dvb_unregister_frontend(adapter->fe); - dvb_unregister_adapter(adapter->dvb_adapter); + dvb_unregister_adapter(&adapter->dvb_adapter); i2c_del_adapter(&adapter->i2c_adap); diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index b735397f59a..f9572426a14 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -531,7 +531,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) card->bt->dev->subsystem_vendor, card->bt->dev->subsystem_device); } else { - if (dvb_register_frontend(card->dvb_adapter, card->fe)) { + if (dvb_register_frontend(&card->dvb_adapter, card->fe)) { printk("dvb-bt8xx: Frontend registration failed!\n"); if (card->fe->ops->release) card->fe->ops->release(card->fe); @@ -550,7 +550,7 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) return result; } - card->dvb_adapter->priv = card; + card->dvb_adapter.priv = card; card->bt->adapter = card->i2c_adapter; @@ -568,7 +568,7 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) if ((result = dvb_dmx_init(&card->demux)) < 0) { printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result); - dvb_unregister_adapter(card->dvb_adapter); + dvb_unregister_adapter(&card->dvb_adapter); return result; } @@ -576,11 +576,11 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) card->dmxdev.demux = &card->demux.dmx; card->dmxdev.capabilities = 0; - if ((result = dvb_dmxdev_init(&card->dmxdev, card->dvb_adapter)) < 0) { + if ((result = dvb_dmxdev_init(&card->dmxdev, &card->dvb_adapter)) < 0) { printk("dvb_bt8xx: dvb_dmxdev_init failed (errno = %d)\n", result); dvb_dmx_release(&card->demux); - dvb_unregister_adapter(card->dvb_adapter); + dvb_unregister_adapter(&card->dvb_adapter); return result; } @@ -591,7 +591,7 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) dvb_dmxdev_release(&card->dmxdev); dvb_dmx_release(&card->demux); - dvb_unregister_adapter(card->dvb_adapter); + dvb_unregister_adapter(&card->dvb_adapter); return result; } @@ -603,7 +603,7 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw); dvb_dmxdev_release(&card->dmxdev); dvb_dmx_release(&card->demux); - dvb_unregister_adapter(card->dvb_adapter); + dvb_unregister_adapter(&card->dvb_adapter); return result; } @@ -614,11 +614,11 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw); dvb_dmxdev_release(&card->dmxdev); dvb_dmx_release(&card->demux); - dvb_unregister_adapter(card->dvb_adapter); + dvb_unregister_adapter(&card->dvb_adapter); return result; } - dvb_net_init(card->dvb_adapter, &card->dvbnet, &card->demux.dmx); + dvb_net_init(&card->dvb_adapter, &card->dvbnet, &card->demux.dmx); tasklet_init(&card->bt->tasklet, dvb_bt8xx_task, (unsigned long) card); @@ -759,7 +759,7 @@ static int dvb_bt8xx_remove(struct device *dev) dvb_dmxdev_release(&card->dmxdev); dvb_dmx_release(&card->demux); if (card->fe) dvb_unregister_frontend(card->fe); - dvb_unregister_adapter(card->dvb_adapter); + dvb_unregister_adapter(&card->dvb_adapter); kfree(card); diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h index 80ef189f930..e9310e3a17a 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h @@ -40,7 +40,7 @@ struct dvb_bt8xx_card { struct semaphore lock; int nfeeds; char card_name[32]; - struct dvb_adapter *dvb_adapter; + struct dvb_adapter dvb_adapter; struct bt878 *bt; unsigned int bttv_nr; struct dvb_demux demux; diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index 28d4d926de3..96c57fde95a 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -119,7 +119,7 @@ struct cinergyt2 { struct dvb_demux demux; struct usb_device *udev; struct semaphore sem; - struct dvb_adapter *adapter; + struct dvb_adapter adapter; struct dvb_device *fedev; struct dmxdev dmxdev; struct dvb_net dvbnet; @@ -813,15 +813,15 @@ static int cinergyt2_probe (struct usb_interface *intf, cinergyt2->dmxdev.demux = &cinergyt2->demux.dmx; cinergyt2->dmxdev.capabilities = 0; - if ((err = dvb_dmxdev_init(&cinergyt2->dmxdev, cinergyt2->adapter)) < 0) { + if ((err = dvb_dmxdev_init(&cinergyt2->dmxdev, &cinergyt2->adapter)) < 0) { dprintk(1, "dvb_dmxdev_init() failed (err = %d)\n", err); goto bailout; } - if (dvb_net_init(cinergyt2->adapter, &cinergyt2->dvbnet, &cinergyt2->demux.dmx)) + if (dvb_net_init(&cinergyt2->adapter, &cinergyt2->dvbnet, &cinergyt2->demux.dmx)) dprintk(1, "dvb_net_init() failed!\n"); - dvb_register_device(cinergyt2->adapter, &cinergyt2->fedev, + dvb_register_device(&cinergyt2->adapter, &cinergyt2->fedev, &cinergyt2_fe_template, cinergyt2, DVB_DEVICE_FRONTEND); @@ -848,7 +848,7 @@ static int cinergyt2_probe (struct usb_interface *intf, bailout: dvb_dmxdev_release(&cinergyt2->dmxdev); dvb_dmx_release(&cinergyt2->demux); - dvb_unregister_adapter (cinergyt2->adapter); + dvb_unregister_adapter (&cinergyt2->adapter); cinergyt2_free_stream_urbs (cinergyt2); kfree(cinergyt2); return -ENOMEM; @@ -872,7 +872,7 @@ static void cinergyt2_disconnect (struct usb_interface *intf) dvb_dmxdev_release(&cinergyt2->dmxdev); dvb_dmx_release(&cinergyt2->demux); dvb_unregister_device(cinergyt2->fedev); - dvb_unregister_adapter(cinergyt2->adapter); + dvb_unregister_adapter(&cinergyt2->adapter); cinergyt2_free_stream_urbs(cinergyt2); up(&cinergyt2->sem); diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c b/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c index 04e54ec093f..400b439e804 100644 --- a/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c +++ b/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c @@ -131,7 +131,7 @@ int dibusb_dvb_init(struct usb_dibusb *dib) deb_info("dvb_register_adapter failed: error %d", ret); goto err; } - dib->adapter->priv = dib; + dib->adapter.priv = dib; /* i2c is done in dibusb_i2c_init */ @@ -151,18 +151,18 @@ int dibusb_dvb_init(struct usb_dibusb *dib) dib->dmxdev.filternum = dib->demux.filternum; dib->dmxdev.demux = &dib->demux.dmx; dib->dmxdev.capabilities = 0; - if ((ret = dvb_dmxdev_init(&dib->dmxdev, dib->adapter)) < 0) { + if ((ret = dvb_dmxdev_init(&dib->dmxdev, &dib->adapter)) < 0) { err("dvb_dmxdev_init failed: error %d",ret); goto err_dmx_dev; } - dvb_net_init(dib->adapter, &dib->dvb_net, &dib->demux.dmx); + dvb_net_init(&dib->adapter, &dib->dvb_net, &dib->demux.dmx); goto success; err_dmx_dev: dvb_dmx_release(&dib->demux); err_dmx: - dvb_unregister_adapter(dib->adapter); + dvb_unregister_adapter(&dib->adapter); err: return ret; success: @@ -179,7 +179,7 @@ int dibusb_dvb_exit(struct usb_dibusb *dib) dib->demux.dmx.close(&dib->demux.dmx); dvb_dmxdev_release(&dib->dmxdev); dvb_dmx_release(&dib->demux); - dvb_unregister_adapter(dib->adapter); + dvb_unregister_adapter(&dib->adapter); } return 0; } diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c b/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c index 2ed89488c7c..5a71b88797d 100644 --- a/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c +++ b/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c @@ -183,7 +183,7 @@ int dibusb_fe_init(struct usb_dibusb* dib) dib->dibdev->name); return -ENODEV; } else { - if (dvb_register_frontend(dib->adapter, dib->fe)) { + if (dvb_register_frontend(&dib->adapter, dib->fe)) { err("Frontend registration failed."); if (dib->fe->ops->release) dib->fe->ops->release(dib->fe); @@ -206,7 +206,7 @@ int dibusb_i2c_init(struct usb_dibusb *dib) { int ret = 0; - dib->adapter->priv = dib; + dib->adapter.priv = dib; strncpy(dib->i2c_adap.name,dib->dibdev->name,I2C_NAME_SIZE); #ifdef I2C_ADAP_CLASS_TV_DIGITAL diff --git a/drivers/media/dvb/dibusb/dvb-dibusb.h b/drivers/media/dvb/dibusb/dvb-dibusb.h index 52cd35dd9d8..c965b64fb1a 100644 --- a/drivers/media/dvb/dibusb/dvb-dibusb.h +++ b/drivers/media/dvb/dibusb/dvb-dibusb.h @@ -181,7 +181,7 @@ struct usb_dibusb { struct semaphore i2c_sem; /* dvb */ - struct dvb_adapter *adapter; + struct dvb_adapter adapter; struct dmxdev dmxdev; struct dvb_demux demux; struct dvb_net dvb_net; diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index cf4ffe38fda..9d9662f4b8e 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -286,9 +286,8 @@ skip: } -int dvb_register_adapter(struct dvb_adapter **padap, const char *name, struct module *module) +int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module) { - struct dvb_adapter *adap; int num; if (down_interruptible (&dvbdev_register_lock)) @@ -299,11 +298,6 @@ int dvb_register_adapter(struct dvb_adapter **padap, const char *name, struct mo return -ENFILE; } - if (!(*padap = adap = kmalloc(sizeof(struct dvb_adapter), GFP_KERNEL))) { - up(&dvbdev_register_lock); - return -ENOMEM; - } - memset (adap, 0, sizeof(struct dvb_adapter)); INIT_LIST_HEAD (&adap->device_list); @@ -331,7 +325,6 @@ int dvb_unregister_adapter(struct dvb_adapter *adap) return -ERESTARTSYS; list_del (&adap->list_head); up (&dvbdev_register_lock); - kfree (adap); return 0; } EXPORT_SYMBOL(dvb_unregister_adapter); diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h index 184edba3caa..a251867f30f 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.h +++ b/drivers/media/dvb/dvb-core/dvbdev.h @@ -76,7 +76,7 @@ struct dvb_device { }; -extern int dvb_register_adapter (struct dvb_adapter **padap, const char *name, struct module *module); +extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module); extern int dvb_unregister_adapter (struct dvb_adapter *adap); extern int dvb_register_device (struct dvb_adapter *adap, diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index e3f7bd68591..8e33a850e13 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -130,7 +130,7 @@ static void init_av7110_av(struct av7110 *av7110) av7110->current_input = 0; if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) { printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n", - av7110->dvb_adapter->num); + av7110->dvb_adapter.num); av7110->adac_type = DVB_ADAC_CRYSTAL; i2c_writereg(av7110, 0x20, 0x01, 0xd2); i2c_writereg(av7110, 0x20, 0x02, 0x49); @@ -145,13 +145,13 @@ static void init_av7110_av(struct av7110 *av7110) } else if (dev->pci->subsystem_vendor == 0x110a) { printk("dvb-ttpci: DVB-C w/o analog module @ card %d detected\n", - av7110->dvb_adapter->num); + av7110->dvb_adapter.num); av7110->adac_type = DVB_ADAC_NONE; } else { av7110->adac_type = adac; printk("dvb-ttpci: adac type set to %d @ card %d\n", - av7110->dvb_adapter->num, av7110->adac_type); + av7110->dvb_adapter.num, av7110->adac_type); } if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP) { @@ -231,7 +231,7 @@ static int arm_thread(void *data) if (newloops == av7110->arm_loops) { printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n", - av7110->dvb_adapter->num); + av7110->dvb_adapter.num); arm_error(av7110); av7710_set_video_mode(av7110, vidmode); @@ -1282,7 +1282,7 @@ static int av7110_register(struct av7110 *av7110) av7110->dmxdev.demux = &dvbdemux->dmx; av7110->dmxdev.capabilities = 0; - dvb_dmxdev_init(&av7110->dmxdev, av7110->dvb_adapter); + dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter); av7110->hw_frontend.source = DMX_FRONTEND_0; @@ -1307,11 +1307,11 @@ static int av7110_register(struct av7110 *av7110) av7110_ca_register(av7110); #ifdef CONFIG_DVB_AV7110_OSD - dvb_register_device(av7110->dvb_adapter, &av7110->osd_dev, + dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev, &dvbdev_osd, av7110, DVB_DEVICE_OSD); #endif - dvb_net_init(av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx); + dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx); if (budgetpatch) { /* initialize software demux1 without its own frontend @@ -1334,9 +1334,9 @@ static int av7110_register(struct av7110 *av7110) av7110->dmxdev1.demux = &dvbdemux1->dmx; av7110->dmxdev1.capabilities = 0; - dvb_dmxdev_init(&av7110->dmxdev1, av7110->dvb_adapter); + dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter); - dvb_net_init(av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx); + dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx); printk("dvb-ttpci: additional demux1 for budget-patch registered\n"); } return 0; @@ -2246,7 +2246,7 @@ static int frontend_init(struct av7110 *av7110) FE_FUNC_OVERRIDE(av7110->fe->ops->dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command); FE_FUNC_OVERRIDE(av7110->fe->ops->set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend); - ret = dvb_register_frontend(av7110->dvb_adapter, av7110->fe); + ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe); if (ret < 0) { printk("av7110: Frontend registration failed!\n"); if (av7110->fe->ops->release) @@ -2460,7 +2460,7 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d goto err_dvb_unregister_adapter_2; ttpci_eeprom_parse_mac(&av7110->i2c_adap, - av7110->dvb_adapter->proposed_mac); + av7110->dvb_adapter.proposed_mac); ret = -ENOMEM; if (budgetpatch) { @@ -2631,7 +2631,7 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d if (ret < 0) goto err_av7110_unregister_11; - av7110->dvb_adapter->priv = av7110; + av7110->dvb_adapter.priv = av7110; ret = frontend_init(av7110); if (ret < 0) goto err_av7110_exit_v4l_12; @@ -2666,7 +2666,7 @@ err_saa71466_vfree_4: err_i2c_del_3: i2c_del_adapter(&av7110->i2c_adap); err_dvb_unregister_adapter_2: - dvb_unregister_adapter(av7110->dvb_adapter); + dvb_unregister_adapter(&av7110->dvb_adapter); err_put_firmware_1: put_firmware(av7110); err_kfree_0: @@ -2712,7 +2712,7 @@ static int av7110_detach(struct saa7146_dev* saa) i2c_del_adapter(&av7110->i2c_adap); - dvb_unregister_adapter (av7110->dvb_adapter); + dvb_unregister_adapter (&av7110->dvb_adapter); av7110_num--; diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h index ee6237b926b..4f69b4d0147 100644 --- a/drivers/media/dvb/ttpci/av7110.h +++ b/drivers/media/dvb/ttpci/av7110.h @@ -220,7 +220,7 @@ struct av7110 { struct audio_mixer mixer; - struct dvb_adapter *dvb_adapter; + struct dvb_adapter dvb_adapter; struct dvb_device *video_dev; struct dvb_device *audio_dev; struct dvb_device *ca_dev; diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c index f90e1cf2419..ccf946125d0 100644 --- a/drivers/media/dvb/ttpci/av7110_av.c +++ b/drivers/media/dvb/ttpci/av7110_av.c @@ -1415,10 +1415,10 @@ int av7110_av_register(struct av7110 *av7110) av7110->video_events.overflow = 0; memset(&av7110->video_size, 0, sizeof (video_size_t)); - dvb_register_device(av7110->dvb_adapter, &av7110->video_dev, + dvb_register_device(&av7110->dvb_adapter, &av7110->video_dev, &dvbdev_video, av7110, DVB_DEVICE_VIDEO); - dvb_register_device(av7110->dvb_adapter, &av7110->audio_dev, + dvb_register_device(&av7110->dvb_adapter, &av7110->audio_dev, &dvbdev_audio, av7110, DVB_DEVICE_AUDIO); return 0; diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c index 75173a22f5c..c3801e328fe 100644 --- a/drivers/media/dvb/ttpci/av7110_ca.c +++ b/drivers/media/dvb/ttpci/av7110_ca.c @@ -370,7 +370,7 @@ static struct dvb_device dvbdev_ca = { int av7110_ca_register(struct av7110 *av7110) { - return dvb_register_device(av7110->dvb_adapter, &av7110->ca_dev, + return dvb_register_device(&av7110->dvb_adapter, &av7110->ca_dev, &dvbdev_ca, av7110, DVB_DEVICE_CA); } diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c index 7c95d63f724..7fa4a0ebe13 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.c +++ b/drivers/media/dvb/ttpci/av7110_hw.c @@ -619,7 +619,7 @@ int av7110_firmversion(struct av7110 *av7110) if (av7110_fw_query(av7110, tag, buf, 16)) { printk("dvb-ttpci: failed to boot firmware @ card %d\n", - av7110->dvb_adapter->num); + av7110->dvb_adapter.num); return -EIO; } @@ -630,16 +630,16 @@ int av7110_firmversion(struct av7110 *av7110) av7110->avtype = (buf[8] << 16) + buf[9]; printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n", - av7110->dvb_adapter->num, av7110->arm_fw, + av7110->dvb_adapter.num, av7110->arm_fw, av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app); /* print firmware capabilities */ if (FW_CI_LL_SUPPORT(av7110->arm_app)) printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n", - av7110->dvb_adapter->num); + av7110->dvb_adapter.num); else printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n", - av7110->dvb_adapter->num); + av7110->dvb_adapter.num); return 0; } diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c index 62c905a2d17..e65fc36e2ce 100644 --- a/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/drivers/media/dvb/ttpci/av7110_v4l.c @@ -46,7 +46,7 @@ int msp_writereg(struct av7110 *av7110, u8 dev, u16 reg, u16 val) if (i2c_transfer(&av7110->i2c_adap, &msgs, 1) != 1) { dprintk(1, "dvb-ttpci: failed @ card %d, %u = %u\n", - av7110->dvb_adapter->num, reg, val); + av7110->dvb_adapter.num, reg, val); return -EIO; } return 0; @@ -63,7 +63,7 @@ static int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val) if (i2c_transfer(&av7110->i2c_adap, &msgs[0], 2) != 2) { dprintk(1, "dvb-ttpci: failed @ card %d, %u\n", - av7110->dvb_adapter->num, reg); + av7110->dvb_adapter.num, reg); return -EIO; } *val = (msg2[0] << 8) | msg2[1]; @@ -552,13 +552,13 @@ int av7110_init_analog_module(struct av7110 *av7110) return -ENODEV; printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n", - av7110->dvb_adapter->num); + av7110->dvb_adapter.num); av7110->adac_type = DVB_ADAC_MSP; msleep(100); // the probing above resets the msp... msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1); msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2); dprintk(1, "dvb-ttpci: @ card %d MSP3400 version 0x%04x 0x%04x\n", - av7110->dvb_adapter->num, version1, version2); + av7110->dvb_adapter.num, version1, version2); msp_writereg(av7110, MSP_WR_DSP, 0x0013, 0x0c00); msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source @@ -596,7 +596,7 @@ int av7110_init_analog_module(struct av7110 *av7110) /* init the saa7113 */ while (*i != 0xff) { if (i2c_writereg(av7110, 0x48, i[0], i[1]) != 1) { - dprintk(1, "saa7113 initialization failed @ card %d", av7110->dvb_adapter->num); + dprintk(1, "saa7113 initialization failed @ card %d", av7110->dvb_adapter.num); break; } i += 2; diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 9860caf3249..7891f3f06f0 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -297,7 +297,7 @@ static int ciintf_init(struct budget_av *budget_av) budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable; budget_av->ca.poll_slot_status = ciintf_poll_slot_status; budget_av->ca.data = budget_av; - if ((result = dvb_ca_en50221_init(budget_av->budget.dvb_adapter, + if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter, &budget_av->ca, 0, 1)) != 0) { printk("budget_av: CI interface detected, but initialisation failed.\n"); goto error; @@ -767,7 +767,7 @@ static void frontend_init(struct budget_av *budget_av) budget_av->budget.dev->pci->subsystem_device); } else { if (dvb_register_frontend - (budget_av->budget.dvb_adapter, budget_av->budget.dvb_frontend)) { + (&budget_av->budget.dvb_adapter, budget_av->budget.dvb_frontend)) { printk("budget-av: Frontend registration failed!\n"); if (budget_av->budget.dvb_frontend->ops->release) budget_av->budget.dvb_frontend->ops->release(budget_av->budget.dvb_frontend); @@ -875,18 +875,18 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio /* fixme: find some sane values here... */ saa7146_write(dev, PCI_BT_V1, 0x1c00101f); - mac = budget_av->budget.dvb_adapter->proposed_mac; + mac = budget_av->budget.dvb_adapter.proposed_mac; if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) { printk("KNC1-%d: Could not read MAC from KNC1 card\n", - budget_av->budget.dvb_adapter->num); + budget_av->budget.dvb_adapter.num); memset(mac, 0, 6); } else { printk("KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", - budget_av->budget.dvb_adapter->num, + budget_av->budget.dvb_adapter.num, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } - budget_av->budget.dvb_adapter->priv = budget_av; + budget_av->budget.dvb_adapter.priv = budget_av; frontend_init(budget_av); if (enable_ci) diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 521111be355..dce11611137 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -395,7 +395,7 @@ static int ciintf_init(struct budget_ci *budget_ci) budget_ci->ca.slot_shutdown = ciintf_slot_shutdown; budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable; budget_ci->ca.data = budget_ci; - if ((result = dvb_ca_en50221_init(budget_ci->budget.dvb_adapter, + if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter, &budget_ci->ca, DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE | DVB_CA_EN50221_FLAG_IRQ_FR | @@ -881,7 +881,7 @@ static void frontend_init(struct budget_ci *budget_ci) budget_ci->budget.dev->pci->subsystem_device); } else { if (dvb_register_frontend - (budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) { + (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) { printk("budget-ci: Frontend registration failed!\n"); if (budget_ci->budget.dvb_frontend->ops->release) budget_ci->budget.dvb_frontend->ops->release(budget_ci->budget.dvb_frontend); @@ -916,7 +916,7 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio ciintf_init(budget_ci); - budget_ci->budget.dvb_adapter->priv = budget_ci; + budget_ci->budget.dvb_adapter.priv = budget_ci; frontend_init(budget_ci); return 0; diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c index 93a9b40917e..0498a055a4c 100644 --- a/drivers/media/dvb/ttpci/budget-core.c +++ b/drivers/media/dvb/ttpci/budget-core.c @@ -298,7 +298,7 @@ static int budget_register(struct budget *budget) budget->dmxdev.demux = &dvbdemux->dmx; budget->dmxdev.capabilities = 0; - dvb_dmxdev_init(&budget->dmxdev, budget->dvb_adapter); + dvb_dmxdev_init(&budget->dmxdev, &budget->dvb_adapter); budget->hw_frontend.source = DMX_FRONTEND_0; @@ -316,7 +316,7 @@ static int budget_register(struct budget *budget) if (ret < 0) return ret; - dvb_net_init(budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx); + dvb_net_init(&budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx); return 0; } @@ -385,11 +385,11 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, strcpy(budget->i2c_adap.name, budget->card->name); if (i2c_add_adapter(&budget->i2c_adap) < 0) { - dvb_unregister_adapter(budget->dvb_adapter); + dvb_unregister_adapter(&budget->dvb_adapter); return -ENOMEM; } - ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter->proposed_mac); + ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter.proposed_mac); if (NULL == (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, length, &budget->pt))) { @@ -417,7 +417,7 @@ err: vfree(budget->grabbing); - dvb_unregister_adapter(budget->dvb_adapter); + dvb_unregister_adapter(&budget->dvb_adapter); return ret; } @@ -432,7 +432,7 @@ int ttpci_budget_deinit(struct budget *budget) i2c_del_adapter(&budget->i2c_adap); - dvb_unregister_adapter(budget->dvb_adapter); + dvb_unregister_adapter(&budget->dvb_adapter); tasklet_kill(&budget->vpe_tasklet); diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c index 5d524a4f213..8142e26b47f 100644 --- a/drivers/media/dvb/ttpci/budget-patch.c +++ b/drivers/media/dvb/ttpci/budget-patch.c @@ -453,7 +453,7 @@ static void frontend_init(struct budget_patch* budget) budget->dev->pci->subsystem_vendor, budget->dev->pci->subsystem_device); } else { - if (dvb_register_frontend(budget->dvb_adapter, budget->dvb_frontend)) { + if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) { printk("budget-av: Frontend registration failed!\n"); if (budget->dvb_frontend->ops->release) budget->dvb_frontend->ops->release(budget->dvb_frontend); @@ -702,7 +702,7 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte dev->ext_priv = budget; - budget->dvb_adapter->priv = budget; + budget->dvb_adapter.priv = budget; frontend_init(budget); return 0; diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 5e6a10f4ad9..083fd44e5f9 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -468,7 +468,7 @@ static void frontend_init(struct budget *budget) budget->dev->pci->subsystem_vendor, budget->dev->pci->subsystem_device); } else { - if (dvb_register_frontend(budget->dvb_adapter, budget->dvb_frontend)) { + if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) { printk("budget: Frontend registration failed!\n"); if (budget->dvb_frontend->ops->release) budget->dvb_frontend->ops->release(budget->dvb_frontend); @@ -497,7 +497,7 @@ static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_ return err; } - budget->dvb_adapter->priv = budget; + budget->dvb_adapter.priv = budget; frontend_init(budget); return 0; diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h index 6d82a6f4e43..c6ef496ba70 100644 --- a/drivers/media/dvb/ttpci/budget.h +++ b/drivers/media/dvb/ttpci/budget.h @@ -64,7 +64,7 @@ struct budget { spinlock_t debilock; - struct dvb_adapter *dvb_adapter; + struct dvb_adapter dvb_adapter; struct dvb_frontend *dvb_frontend; void *priv; }; diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index dc7e81b8a2f..afa0e7a0e50 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -84,7 +84,7 @@ struct ttusb { struct semaphore semi2c; struct semaphore semusb; - struct dvb_adapter *adapter; + struct dvb_adapter adapter; struct usb_device *dev; struct i2c_adapter i2c_adap; @@ -1412,7 +1412,7 @@ static void frontend_init(struct ttusb* ttusb) le16_to_cpu(ttusb->dev->descriptor.idVendor), le16_to_cpu(ttusb->dev->descriptor.idProduct)); } else { - if (dvb_register_frontend(ttusb->adapter, ttusb->fe)) { + if (dvb_register_frontend(&ttusb->adapter, ttusb->fe)) { printk("dvb-ttusb-budget: Frontend registration failed!\n"); if (ttusb->fe->ops->release) ttusb->fe->ops->release(ttusb->fe); @@ -1462,7 +1462,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i up(&ttusb->semi2c); dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE); - ttusb->adapter->priv = ttusb; + ttusb->adapter.priv = ttusb; /* i2c */ memset(&ttusb->i2c_adap, 0, sizeof(struct i2c_adapter)); @@ -1481,7 +1481,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i result = i2c_add_adapter(&ttusb->i2c_adap); if (result) { - dvb_unregister_adapter (ttusb->adapter); + dvb_unregister_adapter (&ttusb->adapter); return result; } @@ -1503,7 +1503,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i if ((result = dvb_dmx_init(&ttusb->dvb_demux)) < 0) { printk("ttusb_dvb: dvb_dmx_init failed (errno = %d)\n", result); i2c_del_adapter(&ttusb->i2c_adap); - dvb_unregister_adapter (ttusb->adapter); + dvb_unregister_adapter (&ttusb->adapter); return -ENODEV; } //FIXME dmxdev (nur WAS?) @@ -1511,21 +1511,21 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i ttusb->dmxdev.demux = &ttusb->dvb_demux.dmx; ttusb->dmxdev.capabilities = 0; - if ((result = dvb_dmxdev_init(&ttusb->dmxdev, ttusb->adapter)) < 0) { + if ((result = dvb_dmxdev_init(&ttusb->dmxdev, &ttusb->adapter)) < 0) { printk("ttusb_dvb: dvb_dmxdev_init failed (errno = %d)\n", result); dvb_dmx_release(&ttusb->dvb_demux); i2c_del_adapter(&ttusb->i2c_adap); - dvb_unregister_adapter (ttusb->adapter); + dvb_unregister_adapter (&ttusb->adapter); return -ENODEV; } - if (dvb_net_init(ttusb->adapter, &ttusb->dvbnet, &ttusb->dvb_demux.dmx)) { + if (dvb_net_init(&ttusb->adapter, &ttusb->dvbnet, &ttusb->dvb_demux.dmx)) { printk("ttusb_dvb: dvb_net_init failed!\n"); dvb_dmxdev_release(&ttusb->dmxdev); dvb_dmx_release(&ttusb->dvb_demux); i2c_del_adapter(&ttusb->i2c_adap); - dvb_unregister_adapter (ttusb->adapter); + dvb_unregister_adapter (&ttusb->adapter); return -ENODEV; } @@ -1559,7 +1559,7 @@ static void ttusb_disconnect(struct usb_interface *intf) dvb_dmx_release(&ttusb->dvb_demux); if (ttusb->fe != NULL) dvb_unregister_frontend(ttusb->fe); i2c_del_adapter(&ttusb->i2c_adap); - dvb_unregister_adapter(ttusb->adapter); + dvb_unregister_adapter(&ttusb->adapter); ttusb_free_iso_urbs(ttusb); diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 7b880aca88d..505bdaff5a7 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -98,7 +98,7 @@ struct ttusb_dec { int can_playback; /* DVB bits */ - struct dvb_adapter *adapter; + struct dvb_adapter adapter; struct dmxdev dmxdev; struct dvb_demux demux; struct dmx_frontend frontend; @@ -1435,7 +1435,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec) printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__, result); - dvb_unregister_adapter(dec->adapter); + dvb_unregister_adapter(&dec->adapter); return result; } @@ -1444,12 +1444,12 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec) dec->dmxdev.demux = &dec->demux.dmx; dec->dmxdev.capabilities = 0; - if ((result = dvb_dmxdev_init(&dec->dmxdev, dec->adapter)) < 0) { + if ((result = dvb_dmxdev_init(&dec->dmxdev, &dec->adapter)) < 0) { printk("%s: dvb_dmxdev_init failed: error %d\n", __FUNCTION__, result); dvb_dmx_release(&dec->demux); - dvb_unregister_adapter(dec->adapter); + dvb_unregister_adapter(&dec->adapter); return result; } @@ -1463,7 +1463,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec) dvb_dmxdev_release(&dec->dmxdev); dvb_dmx_release(&dec->demux); - dvb_unregister_adapter(dec->adapter); + dvb_unregister_adapter(&dec->adapter); return result; } @@ -1476,12 +1476,12 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec) dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend); dvb_dmxdev_release(&dec->dmxdev); dvb_dmx_release(&dec->demux); - dvb_unregister_adapter(dec->adapter); + dvb_unregister_adapter(&dec->adapter); return result; } - dvb_net_init(dec->adapter, &dec->dvb_net, &dec->demux.dmx); + dvb_net_init(&dec->adapter, &dec->dvb_net, &dec->demux.dmx); return 0; } @@ -1496,7 +1496,7 @@ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec) dvb_dmxdev_release(&dec->dmxdev); dvb_dmx_release(&dec->demux); if (dec->fe) dvb_unregister_frontend(dec->fe); - dvb_unregister_adapter(dec->adapter); + dvb_unregister_adapter(&dec->adapter); } static void ttusb_dec_exit_rc(struct ttusb_dec *dec) @@ -1620,7 +1620,7 @@ static int ttusb_dec_probe(struct usb_interface *intf, } ttusb_dec_init_dvb(dec); - dec->adapter->priv = dec; + dec->adapter.priv = dec; switch (le16_to_cpu(id->idProduct)) { case 0x1006: dec->fe = ttusbdecfe_dvbs_attach(&fe_config); @@ -1637,7 +1637,7 @@ static int ttusb_dec_probe(struct usb_interface *intf, le16_to_cpu(dec->udev->descriptor.idVendor), le16_to_cpu(dec->udev->descriptor.idProduct)); } else { - if (dvb_register_frontend(dec->adapter, dec->fe)) { + if (dvb_register_frontend(&dec->adapter, dec->fe)) { printk("budget-ci: Frontend registration failed!\n"); if (dec->fe->ops->release) dec->fe->ops->release(dec->fe); diff --git a/drivers/media/video/video-buf-dvb.c b/drivers/media/video/video-buf-dvb.c index 31cc4ed9b74..5f870075b55 100644 --- a/drivers/media/video/video-buf-dvb.c +++ b/drivers/media/video/video-buf-dvb.c @@ -149,10 +149,10 @@ int videobuf_dvb_register(struct videobuf_dvb *dvb, dvb->name, result); goto fail_adapter; } - dvb->adapter->priv = adapter_priv; + dvb->adapter.priv = adapter_priv; /* register frontend */ - result = dvb_register_frontend(dvb->adapter, dvb->frontend); + result = dvb_register_frontend(&dvb->adapter, dvb->frontend); if (result < 0) { printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", dvb->name, result); @@ -178,7 +178,7 @@ int videobuf_dvb_register(struct videobuf_dvb *dvb, dvb->dmxdev.filternum = 256; dvb->dmxdev.demux = &dvb->demux.dmx; dvb->dmxdev.capabilities = 0; - result = dvb_dmxdev_init(&dvb->dmxdev, dvb->adapter); + result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); if (result < 0) { printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n", dvb->name, result); @@ -209,7 +209,7 @@ int videobuf_dvb_register(struct videobuf_dvb *dvb, } /* register network adapter */ - dvb_net_init(dvb->adapter, &dvb->net, &dvb->demux.dmx); + dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); return 0; fail_fe_conn: @@ -223,7 +223,7 @@ fail_dmxdev: fail_dmx: dvb_unregister_frontend(dvb->frontend); fail_frontend: - dvb_unregister_adapter(dvb->adapter); + dvb_unregister_adapter(&dvb->adapter); fail_adapter: return result; } @@ -236,7 +236,7 @@ void videobuf_dvb_unregister(struct videobuf_dvb *dvb) dvb_dmxdev_release(&dvb->dmxdev); dvb_dmx_release(&dvb->demux); dvb_unregister_frontend(dvb->frontend); - dvb_unregister_adapter(dvb->adapter); + dvb_unregister_adapter(&dvb->adapter); } EXPORT_SYMBOL(videobuf_dvb_register); diff --git a/include/media/video-buf-dvb.h b/include/media/video-buf-dvb.h index 94bd33619aa..ad0a07a3a89 100644 --- a/include/media/video-buf-dvb.h +++ b/include/media/video-buf-dvb.h @@ -16,7 +16,7 @@ struct videobuf_dvb { int nfeeds; /* videobuf_dvb_(un)register manges this */ - struct dvb_adapter *adapter; + struct dvb_adapter adapter; struct dvb_demux demux; struct dmxdev dmxdev; struct dmx_frontend fe_hw; -- cgit v1.2.3-70-g09d2 From 0b405a0f7e4d4d18fd1fe46ddf5ff465443036ab Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 12 May 2005 12:06:27 -0700 Subject: [PATCH] Driver Core: remove driver model detach_state The driver model has a "detach_state" mechanism that: - Has never been used by any in-kernel drive; - Is superfluous, since driver remove() methods can do the same thing; - Became buggy when the suspend() parameter changed semantics and type; - Could self-deadlock when called from certain suspend contexts; - Is effectively wasted documentation, object code, and headspace. This removes that "detach_state" mechanism; net code shrink, as well as a per-device saving in the driver model and sysfs. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- Documentation/filesystems/sysfs-pci.txt | 6 ++-- Documentation/power/devices.txt | 21 -------------- Documentation/powerpc/hvcs.txt | 4 +-- drivers/base/Makefile | 2 +- drivers/base/bus.c | 1 - drivers/base/core.c | 3 -- drivers/base/interface.c | 51 --------------------------------- drivers/base/power/power.h | 11 ------- drivers/base/power/shutdown.c | 16 ----------- include/linux/device.h | 3 -- 10 files changed, 5 insertions(+), 113 deletions(-) delete mode 100644 drivers/base/interface.c (limited to 'include') diff --git a/Documentation/filesystems/sysfs-pci.txt b/Documentation/filesystems/sysfs-pci.txt index e97d024eae7..988a62fae11 100644 --- a/Documentation/filesystems/sysfs-pci.txt +++ b/Documentation/filesystems/sysfs-pci.txt @@ -7,7 +7,6 @@ that support it. For example, a given bus might look like this: |-- 0000:17:00.0 | |-- class | |-- config - | |-- detach_state | |-- device | |-- irq | |-- local_cpus @@ -19,7 +18,7 @@ that support it. For example, a given bus might look like this: | |-- subsystem_device | |-- subsystem_vendor | `-- vendor - `-- detach_state + `-- ... The topmost element describes the PCI domain and bus number. In this case, the domain number is 0000 and the bus number is 17 (both values are in hex). @@ -31,7 +30,6 @@ files, each with their own function. ---- -------- class PCI class (ascii, ro) config PCI config space (binary, rw) - detach_state connection status (bool, rw) device PCI device (ascii, ro) irq IRQ number (ascii, ro) local_cpus nearby CPU mask (cpumask, ro) @@ -85,4 +83,4 @@ useful return codes should be provided. Legacy resources are protected by the HAVE_PCI_LEGACY define. Platforms wishing to support legacy functionality should define it and provide -pci_legacy_read, pci_legacy_write and pci_mmap_legacy_page_range functions. \ No newline at end of file +pci_legacy_read, pci_legacy_write and pci_mmap_legacy_page_range functions. diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt index 5d4ae9a39f1..f987afe43e2 100644 --- a/Documentation/power/devices.txt +++ b/Documentation/power/devices.txt @@ -207,27 +207,6 @@ SYSTEM_SHUTDOWN, I do not understand this one too much. probably event #READY_AFTER_RESUME # -Driver Detach Power Management - -The kernel now supports the ability to place a device in a low-power -state when it is detached from its driver, which happens when its -module is removed. - -Each device contains a 'detach_state' file in its sysfs directory -which can be used to control this state. Reading from this file -displays what the current detach state is set to. This is 0 (On) by -default. A user may write a positive integer value to this file in the -range of 1-4 inclusive. - -A value of 1-3 will indicate the device should be placed in that -low-power state, which will cause ->suspend() to be called for that -device. A value of 4 indicates that the device should be shutdown, so -->shutdown() will be called for that device. - -The driver is responsible for reinitializing the device when the -module is re-inserted during it's ->probe() (or equivalent) method. -The driver core will not call any extra functions when binding the -device to the driver. pm_message_t meaning diff --git a/Documentation/powerpc/hvcs.txt b/Documentation/powerpc/hvcs.txt index c0a62e116e6..dca75cbda6f 100644 --- a/Documentation/powerpc/hvcs.txt +++ b/Documentation/powerpc/hvcs.txt @@ -347,8 +347,8 @@ address that is created by firmware. An example vty-server sysfs entry looks like the following: Pow5:/sys/bus/vio/drivers/hvcs/30000004 # ls - . current_vty devspec name partner_vtys - .. detach_state index partner_clcs vterm_state + . current_vty devspec name partner_vtys + .. index partner_clcs vterm_state Each entry is provided, by default with a "name" attribute. Reading the "name" attribute will reveal the device type as shown in the following diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 6662b545e0a..a47928a2e57 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -1,6 +1,6 @@ # Makefile for the Linux device tree -obj-y := core.o sys.o interface.o bus.o \ +obj-y := core.o sys.o bus.o \ driver.o class.o class_simple.o platform.o \ cpu.o firmware.o init.o map.o dmapool.o \ attribute_container.o transport_class.o diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 2b3902c867d..3cb04bb04c2 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -390,7 +390,6 @@ void device_release_driver(struct device * dev) sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj)); sysfs_remove_link(&dev->kobj, "driver"); list_del_init(&dev->driver_list); - device_detach_shutdown(dev); if (drv->remove) drv->remove(dev); dev->driver = NULL; diff --git a/drivers/base/core.c b/drivers/base/core.c index 268a9c8d168..d21eb774449 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -31,8 +31,6 @@ int (*platform_notify_remove)(struct device * dev) = NULL; #define to_dev(obj) container_of(obj, struct device, kobj) #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) -extern struct attribute * dev_default_attrs[]; - static ssize_t dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) { @@ -89,7 +87,6 @@ static void device_release(struct kobject * kobj) static struct kobj_type ktype_device = { .release = device_release, .sysfs_ops = &dev_sysfs_ops, - .default_attrs = dev_default_attrs, }; diff --git a/drivers/base/interface.c b/drivers/base/interface.c deleted file mode 100644 index bd515843a0c..00000000000 --- a/drivers/base/interface.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * drivers/base/interface.c - common driverfs interface that's exported to - * the world for all devices. - * - * Copyright (c) 2002-3 Patrick Mochel - * Copyright (c) 2002-3 Open Source Development Labs - * - * This file is released under the GPLv2 - * - */ - -#include -#include -#include -#include - -/** - * detach_state - control the default power state for the device. - * - * This is the state the device enters when it's driver module is - * unloaded. The value is an unsigned integer, in the range of 0-4. - * '0' indicates 'On', so no action will be taken when the driver is - * unloaded. This is the default behavior. - * '4' indicates 'Off', meaning the driver core will call the driver's - * shutdown method to quiesce the device. - * 1-3 indicate a low-power state for the device to enter via the - * driver's suspend method. - */ - -static ssize_t detach_show(struct device * dev, char * buf) -{ - return sprintf(buf, "%u\n", dev->detach_state); -} - -static ssize_t detach_store(struct device * dev, const char * buf, size_t n) -{ - u32 state; - state = simple_strtoul(buf, NULL, 10); - if (state > 4) - return -EINVAL; - dev->detach_state = state; - return n; -} - -static DEVICE_ATTR(detach_state, 0644, detach_show, detach_store); - - -struct attribute * dev_default_attrs[] = { - &dev_attr_detach_state.attr, - NULL, -}; diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index e5eda746f2a..2e700d795cf 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -1,18 +1,7 @@ - - -enum { - DEVICE_PM_ON, - DEVICE_PM1, - DEVICE_PM2, - DEVICE_PM3, - DEVICE_PM_OFF, -}; - /* * shutdown.c */ -extern int device_detach_shutdown(struct device *); extern void device_shutdown(void); diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c index 97979901c14..f50a08be424 100644 --- a/drivers/base/power/shutdown.c +++ b/drivers/base/power/shutdown.c @@ -19,22 +19,6 @@ extern struct subsystem devices_subsys; -int device_detach_shutdown(struct device * dev) -{ - if (!dev->detach_state) - return 0; - - if (dev->detach_state == DEVICE_PM_OFF) { - if (dev->driver && dev->driver->shutdown) { - dev_dbg(dev, "shutdown\n"); - dev->driver->shutdown(dev); - } - return 0; - } - return dpm_runtime_suspend(dev, dev->detach_state); -} - - /** * We handle system devices differently - we suspend and shut them * down last and resume them first. That way, we don't do anything stupid like diff --git a/include/linux/device.h b/include/linux/device.h index cf470459fa6..df94c0de53f 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -273,9 +273,6 @@ struct device { BIOS data relevant to device) */ struct dev_pm_info power; - u32 detach_state; /* State to enter when device is - detached from its driver. */ - u64 *dma_mask; /* dma mask (if dma'able device) */ u64 coherent_dma_mask;/* Like dma_mask, but for alloc_coherent mappings as -- cgit v1.2.3-70-g09d2