提交 ecc25fbd 编写于 作者: I Ingo Molnar

Merge branches 'x86/apic', 'x86/defconfig', 'x86/memtest', 'x86/mm' and 'linus' into x86/core

...@@ -1308,8 +1308,13 @@ and is between 256 and 4096 characters. It is defined in the file ...@@ -1308,8 +1308,13 @@ and is between 256 and 4096 characters. It is defined in the file
memtest= [KNL,X86] Enable memtest memtest= [KNL,X86] Enable memtest
Format: <integer> Format: <integer>
range: 0,4 : pattern number
default : 0 <disable> default : 0 <disable>
Specifies the number of memtest passes to be
performed. Each pass selects another test
pattern from a given set of patterns. Memtest
fills the memory with this pattern, validates
memory contents and reserves bad memory
regions that are detected.
meye.*= [HW] Set MotionEye Camera parameters meye.*= [HW] Set MotionEye Camera parameters
See Documentation/video4linux/meye.txt. See Documentation/video4linux/meye.txt.
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/ata_platform.h> #include <linux/ata_platform.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/i2c.h>
#include <asm/elf.h> #include <asm/elf.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
...@@ -201,8 +202,13 @@ static struct platform_device *devs[] __initdata = { ...@@ -201,8 +202,13 @@ static struct platform_device *devs[] __initdata = {
&pata_device, &pata_device,
}; };
static struct i2c_board_info i2c_rtc = {
I2C_BOARD_INFO("pcf8583", 0x50)
};
static int __init rpc_init(void) static int __init rpc_init(void)
{ {
i2c_register_board_info(0, &i2c_rtc, 1);
return platform_add_devices(devs, ARRAY_SIZE(devs)); return platform_add_devices(devs, ARRAY_SIZE(devs));
} }
......
# #
# Automatically generated make config: don't edit # Automatically generated make config: don't edit
# Linux kernel version: 2.6.29-rc4 # Linux kernel version: 2.6.29-rc4
# Thu Feb 12 12:57:57 2009 # Tue Feb 24 15:50:58 2009
# #
# CONFIG_64BIT is not set # CONFIG_64BIT is not set
CONFIG_X86_32=y CONFIG_X86_32=y
...@@ -266,7 +266,9 @@ CONFIG_PREEMPT_VOLUNTARY=y ...@@ -266,7 +266,9 @@ CONFIG_PREEMPT_VOLUNTARY=y
CONFIG_X86_LOCAL_APIC=y CONFIG_X86_LOCAL_APIC=y
CONFIG_X86_IO_APIC=y CONFIG_X86_IO_APIC=y
CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
# CONFIG_X86_MCE is not set CONFIG_X86_MCE=y
CONFIG_X86_MCE_NONFATAL=y
CONFIG_X86_MCE_P4THERMAL=y
CONFIG_VM86=y CONFIG_VM86=y
# CONFIG_TOSHIBA is not set # CONFIG_TOSHIBA is not set
# CONFIG_I8K is not set # CONFIG_I8K is not set
......
# #
# Automatically generated make config: don't edit # Automatically generated make config: don't edit
# Linux kernel version: 2.6.29-rc4 # Linux kernel version: 2.6.29-rc4
# Thu Feb 12 12:57:29 2009 # Tue Feb 24 15:44:16 2009
# #
CONFIG_64BIT=y CONFIG_64BIT=y
# CONFIG_X86_32 is not set # CONFIG_X86_32 is not set
...@@ -266,7 +266,9 @@ CONFIG_PREEMPT_VOLUNTARY=y ...@@ -266,7 +266,9 @@ CONFIG_PREEMPT_VOLUNTARY=y
CONFIG_X86_LOCAL_APIC=y CONFIG_X86_LOCAL_APIC=y
CONFIG_X86_IO_APIC=y CONFIG_X86_IO_APIC=y
CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
# CONFIG_X86_MCE is not set CONFIG_X86_MCE=y
CONFIG_X86_MCE_INTEL=y
CONFIG_X86_MCE_AMD=y
# CONFIG_I8K is not set # CONFIG_I8K is not set
CONFIG_MICROCODE=y CONFIG_MICROCODE=y
CONFIG_MICROCODE_INTEL=y CONFIG_MICROCODE_INTEL=y
......
...@@ -157,7 +157,7 @@ __copy_from_user(void *to, const void __user *from, unsigned long n) ...@@ -157,7 +157,7 @@ __copy_from_user(void *to, const void __user *from, unsigned long n)
} }
static __always_inline unsigned long __copy_from_user_nocache(void *to, static __always_inline unsigned long __copy_from_user_nocache(void *to,
const void __user *from, unsigned long n) const void __user *from, unsigned long n, unsigned long total)
{ {
might_fault(); might_fault();
if (__builtin_constant_p(n)) { if (__builtin_constant_p(n)) {
...@@ -180,7 +180,7 @@ static __always_inline unsigned long __copy_from_user_nocache(void *to, ...@@ -180,7 +180,7 @@ static __always_inline unsigned long __copy_from_user_nocache(void *to,
static __always_inline unsigned long static __always_inline unsigned long
__copy_from_user_inatomic_nocache(void *to, const void __user *from, __copy_from_user_inatomic_nocache(void *to, const void __user *from,
unsigned long n) unsigned long n, unsigned long total)
{ {
return __copy_from_user_ll_nocache_nozero(to, from, n); return __copy_from_user_ll_nocache_nozero(to, from, n);
} }
......
...@@ -189,7 +189,7 @@ extern long __copy_user_nocache(void *dst, const void __user *src, ...@@ -189,7 +189,7 @@ extern long __copy_user_nocache(void *dst, const void __user *src,
unsigned size, int zerorest); unsigned size, int zerorest);
static inline int __copy_from_user_nocache(void *dst, const void __user *src, static inline int __copy_from_user_nocache(void *dst, const void __user *src,
unsigned size) unsigned size, unsigned long total)
{ {
might_sleep(); might_sleep();
/* /*
...@@ -198,17 +198,16 @@ static inline int __copy_from_user_nocache(void *dst, const void __user *src, ...@@ -198,17 +198,16 @@ static inline int __copy_from_user_nocache(void *dst, const void __user *src,
* non-temporal stores here. Smaller writes get handled * non-temporal stores here. Smaller writes get handled
* via regular __copy_from_user(): * via regular __copy_from_user():
*/ */
if (likely(size >= PAGE_SIZE)) if (likely(total >= PAGE_SIZE))
return __copy_user_nocache(dst, src, size, 1); return __copy_user_nocache(dst, src, size, 1);
else else
return __copy_from_user(dst, src, size); return __copy_from_user(dst, src, size);
} }
static inline int __copy_from_user_inatomic_nocache(void *dst, static inline int __copy_from_user_inatomic_nocache(void *dst,
const void __user *src, const void __user *src, unsigned size, unsigned total)
unsigned size)
{ {
if (likely(size >= PAGE_SIZE)) if (likely(total >= PAGE_SIZE))
return __copy_user_nocache(dst, src, size, 0); return __copy_user_nocache(dst, src, size, 0);
else else
return __copy_from_user_inatomic(dst, src, size); return __copy_from_user_inatomic(dst, src, size);
......
...@@ -498,12 +498,12 @@ void *text_poke_early(void *addr, const void *opcode, size_t len) ...@@ -498,12 +498,12 @@ void *text_poke_early(void *addr, const void *opcode, size_t len)
*/ */
void *__kprobes text_poke(void *addr, const void *opcode, size_t len) void *__kprobes text_poke(void *addr, const void *opcode, size_t len)
{ {
unsigned long flags;
char *vaddr; char *vaddr;
int nr_pages = 2; int nr_pages = 2;
struct page *pages[2]; struct page *pages[2];
int i; int i;
might_sleep();
if (!core_kernel_text((unsigned long)addr)) { if (!core_kernel_text((unsigned long)addr)) {
pages[0] = vmalloc_to_page(addr); pages[0] = vmalloc_to_page(addr);
pages[1] = vmalloc_to_page(addr + PAGE_SIZE); pages[1] = vmalloc_to_page(addr + PAGE_SIZE);
...@@ -517,9 +517,9 @@ void *__kprobes text_poke(void *addr, const void *opcode, size_t len) ...@@ -517,9 +517,9 @@ void *__kprobes text_poke(void *addr, const void *opcode, size_t len)
nr_pages = 1; nr_pages = 1;
vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL); vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL);
BUG_ON(!vaddr); BUG_ON(!vaddr);
local_irq_save(flags); local_irq_disable();
memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len); memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len);
local_irq_restore(flags); local_irq_enable();
vunmap(vaddr); vunmap(vaddr);
sync_core(); sync_core();
/* Could also do a CLFLUSH here to speed up CPU recovery; but /* Could also do a CLFLUSH here to speed up CPU recovery; but
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/smp.h> #include <linux/smp.h>
static inline unsigned summit_get_apic_id(unsigned long x) static unsigned summit_get_apic_id(unsigned long x)
{ {
return (x >> 24) & 0xFF; return (x >> 24) & 0xFF;
} }
...@@ -58,7 +58,7 @@ static inline void summit_send_IPI_mask(const cpumask_t *mask, int vector) ...@@ -58,7 +58,7 @@ static inline void summit_send_IPI_mask(const cpumask_t *mask, int vector)
default_send_IPI_mask_sequence_logical(mask, vector); default_send_IPI_mask_sequence_logical(mask, vector);
} }
static inline void summit_send_IPI_allbutself(int vector) static void summit_send_IPI_allbutself(int vector)
{ {
cpumask_t mask = cpu_online_map; cpumask_t mask = cpu_online_map;
cpu_clear(smp_processor_id(), mask); cpu_clear(smp_processor_id(), mask);
...@@ -67,7 +67,7 @@ static inline void summit_send_IPI_allbutself(int vector) ...@@ -67,7 +67,7 @@ static inline void summit_send_IPI_allbutself(int vector)
summit_send_IPI_mask(&mask, vector); summit_send_IPI_mask(&mask, vector);
} }
static inline void summit_send_IPI_all(int vector) static void summit_send_IPI_all(int vector)
{ {
summit_send_IPI_mask(&cpu_online_map, vector); summit_send_IPI_mask(&cpu_online_map, vector);
} }
...@@ -82,8 +82,8 @@ extern void setup_summit(void); ...@@ -82,8 +82,8 @@ extern void setup_summit(void);
#define setup_summit() {} #define setup_summit() {}
#endif #endif
static inline int static int summit_mps_oem_check(struct mpc_table *mpc, char *oem,
summit_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) char *productid)
{ {
if (!strncmp(oem, "IBM ENSW", 8) && if (!strncmp(oem, "IBM ENSW", 8) &&
(!strncmp(productid, "VIGIL SMP", 9) (!strncmp(productid, "VIGIL SMP", 9)
...@@ -98,7 +98,7 @@ summit_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) ...@@ -98,7 +98,7 @@ summit_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
} }
/* Hook from generic ACPI tables.c */ /* Hook from generic ACPI tables.c */
static inline int summit_acpi_madt_oem_check(char *oem_id, char *oem_table_id) static int summit_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{ {
if (!strncmp(oem_id, "IBM", 3) && if (!strncmp(oem_id, "IBM", 3) &&
(!strncmp(oem_table_id, "SERVIGIL", 8) (!strncmp(oem_table_id, "SERVIGIL", 8)
...@@ -186,7 +186,7 @@ static inline int is_WPEG(struct rio_detail *rio){ ...@@ -186,7 +186,7 @@ static inline int is_WPEG(struct rio_detail *rio){
#define SUMMIT_APIC_DFR_VALUE (APIC_DFR_CLUSTER) #define SUMMIT_APIC_DFR_VALUE (APIC_DFR_CLUSTER)
static inline const cpumask_t *summit_target_cpus(void) static const cpumask_t *summit_target_cpus(void)
{ {
/* CPU_MASK_ALL (0xff) has undefined behaviour with /* CPU_MASK_ALL (0xff) has undefined behaviour with
* dest_LowestPrio mode logical clustered apic interrupt routing * dest_LowestPrio mode logical clustered apic interrupt routing
...@@ -195,19 +195,18 @@ static inline const cpumask_t *summit_target_cpus(void) ...@@ -195,19 +195,18 @@ static inline const cpumask_t *summit_target_cpus(void)
return &cpumask_of_cpu(0); return &cpumask_of_cpu(0);
} }
static inline unsigned long static unsigned long summit_check_apicid_used(physid_mask_t bitmap, int apicid)
summit_check_apicid_used(physid_mask_t bitmap, int apicid)
{ {
return 0; return 0;
} }
/* we don't use the phys_cpu_present_map to indicate apicid presence */ /* we don't use the phys_cpu_present_map to indicate apicid presence */
static inline unsigned long summit_check_apicid_present(int bit) static unsigned long summit_check_apicid_present(int bit)
{ {
return 1; return 1;
} }
static inline void summit_init_apic_ldr(void) static void summit_init_apic_ldr(void)
{ {
unsigned long val, id; unsigned long val, id;
int count = 0; int count = 0;
...@@ -234,18 +233,18 @@ static inline void summit_init_apic_ldr(void) ...@@ -234,18 +233,18 @@ static inline void summit_init_apic_ldr(void)
apic_write(APIC_LDR, val); apic_write(APIC_LDR, val);
} }
static inline int summit_apic_id_registered(void) static int summit_apic_id_registered(void)
{ {
return 1; return 1;
} }
static inline void summit_setup_apic_routing(void) static void summit_setup_apic_routing(void)
{ {
printk("Enabling APIC mode: Summit. Using %d I/O APICs\n", printk("Enabling APIC mode: Summit. Using %d I/O APICs\n",
nr_ioapics); nr_ioapics);
} }
static inline int summit_apicid_to_node(int logical_apicid) static int summit_apicid_to_node(int logical_apicid)
{ {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
return apicid_2_node[hard_smp_processor_id()]; return apicid_2_node[hard_smp_processor_id()];
...@@ -266,7 +265,7 @@ static inline int summit_cpu_to_logical_apicid(int cpu) ...@@ -266,7 +265,7 @@ static inline int summit_cpu_to_logical_apicid(int cpu)
#endif #endif
} }
static inline int summit_cpu_present_to_apicid(int mps_cpu) static int summit_cpu_present_to_apicid(int mps_cpu)
{ {
if (mps_cpu < nr_cpu_ids) if (mps_cpu < nr_cpu_ids)
return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu); return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu);
...@@ -274,28 +273,23 @@ static inline int summit_cpu_present_to_apicid(int mps_cpu) ...@@ -274,28 +273,23 @@ static inline int summit_cpu_present_to_apicid(int mps_cpu)
return BAD_APICID; return BAD_APICID;
} }
static inline physid_mask_t static physid_mask_t summit_ioapic_phys_id_map(physid_mask_t phys_id_map)
summit_ioapic_phys_id_map(physid_mask_t phys_id_map)
{ {
/* For clustered we don't have a good way to do this yet - hack */ /* For clustered we don't have a good way to do this yet - hack */
return physids_promote(0x0F); return physids_promote(0x0F);
} }
static inline physid_mask_t summit_apicid_to_cpu_present(int apicid) static physid_mask_t summit_apicid_to_cpu_present(int apicid)
{ {
return physid_mask_of_physid(0); return physid_mask_of_physid(0);
} }
static inline void summit_setup_portio_remap(void) static int summit_check_phys_apicid_present(int boot_cpu_physical_apicid)
{
}
static inline int summit_check_phys_apicid_present(int boot_cpu_physical_apicid)
{ {
return 1; return 1;
} }
static inline unsigned int summit_cpu_mask_to_apicid(const cpumask_t *cpumask) static unsigned int summit_cpu_mask_to_apicid(const cpumask_t *cpumask)
{ {
int cpus_found = 0; int cpus_found = 0;
int num_bits_set; int num_bits_set;
...@@ -303,12 +297,10 @@ static inline unsigned int summit_cpu_mask_to_apicid(const cpumask_t *cpumask) ...@@ -303,12 +297,10 @@ static inline unsigned int summit_cpu_mask_to_apicid(const cpumask_t *cpumask)
int cpu; int cpu;
num_bits_set = cpus_weight(*cpumask); num_bits_set = cpus_weight(*cpumask);
/* Return id to all */
if (num_bits_set >= nr_cpu_ids) if (num_bits_set >= nr_cpu_ids)
return 0xFF; return BAD_APICID;
/* /*
* The cpus in the mask must all be on the apic cluster. If are not * The cpus in the mask must all be on the apic cluster.
* on the same apicid cluster return default value of target_cpus():
*/ */
cpu = first_cpu(*cpumask); cpu = first_cpu(*cpumask);
apicid = summit_cpu_to_logical_apicid(cpu); apicid = summit_cpu_to_logical_apicid(cpu);
...@@ -318,9 +310,9 @@ static inline unsigned int summit_cpu_mask_to_apicid(const cpumask_t *cpumask) ...@@ -318,9 +310,9 @@ static inline unsigned int summit_cpu_mask_to_apicid(const cpumask_t *cpumask)
int new_apicid = summit_cpu_to_logical_apicid(cpu); int new_apicid = summit_cpu_to_logical_apicid(cpu);
if (APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { if (APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
printk ("%s: Not a valid mask!\n", __func__); printk("%s: Not a valid mask!\n", __func__);
return 0xFF; return BAD_APICID;
} }
apicid = apicid | new_apicid; apicid = apicid | new_apicid;
cpus_found++; cpus_found++;
...@@ -330,8 +322,7 @@ static inline unsigned int summit_cpu_mask_to_apicid(const cpumask_t *cpumask) ...@@ -330,8 +322,7 @@ static inline unsigned int summit_cpu_mask_to_apicid(const cpumask_t *cpumask)
return apicid; return apicid;
} }
static inline unsigned int static unsigned int summit_cpu_mask_to_apicid_and(const struct cpumask *inmask,
summit_cpu_mask_to_apicid_and(const struct cpumask *inmask,
const struct cpumask *andmask) const struct cpumask *andmask)
{ {
int apicid = summit_cpu_to_logical_apicid(0); int apicid = summit_cpu_to_logical_apicid(0);
...@@ -356,7 +347,7 @@ summit_cpu_mask_to_apicid_and(const struct cpumask *inmask, ...@@ -356,7 +347,7 @@ summit_cpu_mask_to_apicid_and(const struct cpumask *inmask,
* *
* See Intel's IA-32 SW Dev's Manual Vol2 under CPUID. * See Intel's IA-32 SW Dev's Manual Vol2 under CPUID.
*/ */
static inline int summit_phys_pkg_id(int cpuid_apic, int index_msb) static int summit_phys_pkg_id(int cpuid_apic, int index_msb)
{ {
return hard_smp_processor_id() >> index_msb; return hard_smp_processor_id() >> index_msb;
} }
......
...@@ -858,6 +858,9 @@ void __init reserve_early_overlap_ok(u64 start, u64 end, char *name) ...@@ -858,6 +858,9 @@ void __init reserve_early_overlap_ok(u64 start, u64 end, char *name)
*/ */
void __init reserve_early(u64 start, u64 end, char *name) void __init reserve_early(u64 start, u64 end, char *name)
{ {
if (start >= end)
return;
drop_overlaps_that_are_ok(start, end); drop_overlaps_that_are_ok(start, end);
__reserve_early(start, end, name, 0); __reserve_early(start, end, name, 0);
} }
......
...@@ -9,44 +9,44 @@ ...@@ -9,44 +9,44 @@
#include <asm/e820.h> #include <asm/e820.h>
static void __init memtest(unsigned long start_phys, unsigned long size, static u64 patterns[] __initdata = {
unsigned pattern) 0,
0xffffffffffffffffULL,
0x5555555555555555ULL,
0xaaaaaaaaaaaaaaaaULL,
0x1111111111111111ULL,
0x2222222222222222ULL,
0x4444444444444444ULL,
0x8888888888888888ULL,
0x3333333333333333ULL,
0x6666666666666666ULL,
0x9999999999999999ULL,
0xccccccccccccccccULL,
0x7777777777777777ULL,
0xbbbbbbbbbbbbbbbbULL,
0xddddddddddddddddULL,
0xeeeeeeeeeeeeeeeeULL,
0x7a6c7258554e494cULL, /* yeah ;-) */
};
static void __init reserve_bad_mem(u64 pattern, u64 start_bad, u64 end_bad)
{ {
unsigned long i; printk(KERN_INFO " %016llx bad mem addr %010llx - %010llx reserved\n",
unsigned long *start; (unsigned long long) pattern,
unsigned long start_bad; (unsigned long long) start_bad,
unsigned long last_bad; (unsigned long long) end_bad);
unsigned long val; reserve_early(start_bad, end_bad, "BAD RAM");
unsigned long start_phys_aligned; }
unsigned long count;
unsigned long incr;
switch (pattern) {
case 0:
val = 0UL;
break;
case 1:
val = -1UL;
break;
case 2:
#ifdef CONFIG_X86_64
val = 0x5555555555555555UL;
#else
val = 0x55555555UL;
#endif
break;
case 3:
#ifdef CONFIG_X86_64
val = 0xaaaaaaaaaaaaaaaaUL;
#else
val = 0xaaaaaaaaUL;
#endif
break;
default:
return;
}
incr = sizeof(unsigned long); static void __init memtest(u64 pattern, u64 start_phys, u64 size)
{
u64 i, count;
u64 *start;
u64 start_bad, last_bad;
u64 start_phys_aligned;
size_t incr;
incr = sizeof(pattern);
start_phys_aligned = ALIGN(start_phys, incr); start_phys_aligned = ALIGN(start_phys, incr);
count = (size - (start_phys_aligned - start_phys))/incr; count = (size - (start_phys_aligned - start_phys))/incr;
start = __va(start_phys_aligned); start = __va(start_phys_aligned);
...@@ -54,25 +54,42 @@ static void __init memtest(unsigned long start_phys, unsigned long size, ...@@ -54,25 +54,42 @@ static void __init memtest(unsigned long start_phys, unsigned long size,
last_bad = 0; last_bad = 0;
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
start[i] = val; start[i] = pattern;
for (i = 0; i < count; i++, start++, start_phys_aligned += incr) { for (i = 0; i < count; i++, start++, start_phys_aligned += incr) {
if (*start != val) { if (*start == pattern)
if (start_phys_aligned == last_bad + incr) { continue;
last_bad += incr; if (start_phys_aligned == last_bad + incr) {
} else { last_bad += incr;
if (start_bad) { continue;
printk(KERN_CONT "\n %016lx bad mem addr %010lx - %010lx reserved",
val, start_bad, last_bad + incr);
reserve_early(start_bad, last_bad + incr, "BAD RAM");
}
start_bad = last_bad = start_phys_aligned;
}
} }
if (start_bad)
reserve_bad_mem(pattern, start_bad, last_bad + incr);
start_bad = last_bad = start_phys_aligned;
} }
if (start_bad) { if (start_bad)
printk(KERN_CONT "\n %016lx bad mem addr %010lx - %010lx reserved", reserve_bad_mem(pattern, start_bad, last_bad + incr);
val, start_bad, last_bad + incr); }
reserve_early(start_bad, last_bad + incr, "BAD RAM");
static void __init do_one_pass(u64 pattern, u64 start, u64 end)
{
u64 size = 0;
while (start < end) {
start = find_e820_area_size(start, &size, 1);
/* done ? */
if (start >= end)
break;
if (start + size > end)
size = end - start;
printk(KERN_INFO " %010llx - %010llx pattern %016llx\n",
(unsigned long long) start,
(unsigned long long) start + size,
(unsigned long long) cpu_to_be64(pattern));
memtest(pattern, start, size);
start += size;
} }
} }
...@@ -90,33 +107,22 @@ early_param("memtest", parse_memtest); ...@@ -90,33 +107,22 @@ early_param("memtest", parse_memtest);
void __init early_memtest(unsigned long start, unsigned long end) void __init early_memtest(unsigned long start, unsigned long end)
{ {
u64 t_start, t_size; unsigned int i;
unsigned pattern; unsigned int idx = 0;
if (!memtest_pattern) if (!memtest_pattern)
return; return;
printk(KERN_INFO "early_memtest: pattern num %d", memtest_pattern); printk(KERN_INFO "early_memtest: # of tests: %d\n", memtest_pattern);
for (pattern = 0; pattern < memtest_pattern; pattern++) { for (i = 0; i < memtest_pattern; i++) {
t_start = start; idx = i % ARRAY_SIZE(patterns);
t_size = 0; do_one_pass(patterns[idx], start, end);
while (t_start < end) { }
t_start = find_e820_area_size(t_start, &t_size, 1);
/* done ? */
if (t_start >= end)
break;
if (t_start + t_size > end)
t_size = end - t_start;
printk(KERN_CONT "\n %010llx - %010llx pattern %d",
(unsigned long long)t_start,
(unsigned long long)t_start + t_size, pattern);
memtest(t_start, t_size, pattern);
t_start += t_size; if (idx > 0) {
} printk(KERN_INFO "early_memtest: wipe out "
"test pattern from memory\n");
/* additional test with pattern 0 will do this */
do_one_pass(0, start, end);
} }
printk(KERN_CONT "\n");
} }
...@@ -214,7 +214,7 @@ static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg) ...@@ -214,7 +214,7 @@ static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
seq_printf(m, "async : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ? seq_printf(m, "async : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
"yes" : "no"); "yes" : "no");
seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
seq_printf(m, "digestsize : %u\n", alg->cra_hash.digestsize); seq_printf(m, "digestsize : %u\n", alg->cra_ahash.digestsize);
} }
const struct crypto_type crypto_ahash_type = { const struct crypto_type crypto_ahash_type = {
......
...@@ -901,7 +901,7 @@ static int __devinit eeprom_read(struct lanai_dev *lanai) ...@@ -901,7 +901,7 @@ static int __devinit eeprom_read(struct lanai_dev *lanai)
clock_l(); udelay(5); clock_l(); udelay(5);
for (i = 128; i != 0; i >>= 1) { /* write command out */ for (i = 128; i != 0; i >>= 1) { /* write command out */
tmp = (lanai->conf1 & ~CONFIG1_PROMDATA) | tmp = (lanai->conf1 & ~CONFIG1_PROMDATA) |
(data & i) ? CONFIG1_PROMDATA : 0; ((data & i) ? CONFIG1_PROMDATA : 0);
if (lanai->conf1 != tmp) { if (lanai->conf1 != tmp) {
set_config1(tmp); set_config1(tmp);
udelay(5); /* Let new data settle */ udelay(5); /* Let new data settle */
......
...@@ -68,9 +68,11 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) ...@@ -68,9 +68,11 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
i915_save_state(dev); i915_save_state(dev);
/* If KMS is active, we do the leavevt stuff here */ /* If KMS is active, we do the leavevt stuff here */
if (drm_core_check_feature(dev, DRIVER_MODESET) && i915_gem_idle(dev)) { if (drm_core_check_feature(dev, DRIVER_MODESET)) {
dev_err(&dev->pdev->dev, "GEM idle failed, aborting suspend\n"); if (i915_gem_idle(dev))
return -EBUSY; dev_err(&dev->pdev->dev,
"GEM idle failed, resume may fail\n");
drm_irq_uninstall(dev);
} }
intel_opregion_free(dev); intel_opregion_free(dev);
...@@ -108,6 +110,8 @@ static int i915_resume(struct drm_device *dev) ...@@ -108,6 +110,8 @@ static int i915_resume(struct drm_device *dev)
if (ret != 0) if (ret != 0)
ret = -1; ret = -1;
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
drm_irq_install(dev);
} }
return ret; return ret;
......
...@@ -211,7 +211,7 @@ fast_user_write(struct io_mapping *mapping, ...@@ -211,7 +211,7 @@ fast_user_write(struct io_mapping *mapping,
vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base); vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base);
unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset, unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset,
user_data, length); user_data, length, length);
io_mapping_unmap_atomic(vaddr_atomic); io_mapping_unmap_atomic(vaddr_atomic);
if (unwritten) if (unwritten)
return -EFAULT; return -EFAULT;
...@@ -1051,6 +1051,9 @@ i915_gem_retire_requests(struct drm_device *dev) ...@@ -1051,6 +1051,9 @@ i915_gem_retire_requests(struct drm_device *dev)
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
uint32_t seqno; uint32_t seqno;
if (!dev_priv->hw_status_page)
return;
seqno = i915_get_gem_seqno(dev); seqno = i915_get_gem_seqno(dev);
while (!list_empty(&dev_priv->mm.request_list)) { while (!list_empty(&dev_priv->mm.request_list)) {
......
...@@ -79,10 +79,11 @@ static struct i2c_algo_bit_data ioc_data = { ...@@ -79,10 +79,11 @@ static struct i2c_algo_bit_data ioc_data = {
.getsda = ioc_getsda, .getsda = ioc_getsda,
.getscl = ioc_getscl, .getscl = ioc_getscl,
.udelay = 80, .udelay = 80,
.timeout = 100 .timeout = HZ,
}; };
static struct i2c_adapter ioc_ops = { static struct i2c_adapter ioc_ops = {
.nr = 0,
.algo_data = &ioc_data, .algo_data = &ioc_data,
}; };
...@@ -90,7 +91,7 @@ static int __init i2c_ioc_init(void) ...@@ -90,7 +91,7 @@ static int __init i2c_ioc_init(void)
{ {
force_ones = FORCE_ONES | SCL | SDA; force_ones = FORCE_ONES | SCL | SDA;
return i2c_bit_add_bus(&ioc_ops); return i2c_bit_add_numbered_bus(&ioc_ops);
} }
module_init(i2c_ioc_init); module_init(i2c_ioc_init);
...@@ -72,7 +72,7 @@ static unsigned int amd_ec_wait_write(struct amd_smbus *smbus) ...@@ -72,7 +72,7 @@ static unsigned int amd_ec_wait_write(struct amd_smbus *smbus)
{ {
int timeout = 500; int timeout = 500;
while (timeout-- && (inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF)) while ((inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF) && --timeout)
udelay(1); udelay(1);
if (!timeout) { if (!timeout) {
...@@ -88,7 +88,7 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus) ...@@ -88,7 +88,7 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus)
{ {
int timeout = 500; int timeout = 500;
while (timeout-- && (~inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF)) while ((~inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF) && --timeout)
udelay(1); udelay(1);
if (!timeout) { if (!timeout) {
......
...@@ -114,7 +114,7 @@ static int ixp2000_i2c_probe(struct platform_device *plat_dev) ...@@ -114,7 +114,7 @@ static int ixp2000_i2c_probe(struct platform_device *plat_dev)
drv_data->algo_data.getsda = ixp2000_bit_getsda; drv_data->algo_data.getsda = ixp2000_bit_getsda;
drv_data->algo_data.getscl = ixp2000_bit_getscl; drv_data->algo_data.getscl = ixp2000_bit_getscl;
drv_data->algo_data.udelay = 6; drv_data->algo_data.udelay = 6;
drv_data->algo_data.timeout = 100; drv_data->algo_data.timeout = HZ;
strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
sizeof(drv_data->adapter.name)); sizeof(drv_data->adapter.name));
......
...@@ -644,7 +644,7 @@ static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c, ...@@ -644,7 +644,7 @@ static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c,
i2c_pxa_start_message(i2c); i2c_pxa_start_message(i2c);
while (timeout-- && i2c->msg_num > 0) { while (i2c->msg_num > 0 && --timeout) {
i2c_pxa_handler(0, i2c); i2c_pxa_handler(0, i2c);
udelay(10); udelay(10);
} }
......
...@@ -76,7 +76,7 @@ static struct i2c_algo_bit_data scx200_i2c_data = { ...@@ -76,7 +76,7 @@ static struct i2c_algo_bit_data scx200_i2c_data = {
.getsda = scx200_i2c_getsda, .getsda = scx200_i2c_getsda,
.getscl = scx200_i2c_getscl, .getscl = scx200_i2c_getscl,
.udelay = 10, .udelay = 10,
.timeout = 100, .timeout = HZ,
}; };
static struct i2c_adapter scx200_i2c_ops = { static struct i2c_adapter scx200_i2c_ops = {
......
...@@ -1831,7 +1831,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, ...@@ -1831,7 +1831,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
msg[0].len = 0; msg[0].len = 0;
/* Special case: The read/write field is used as data */ /* Special case: The read/write field is used as data */
msg[0].flags = flags | (read_write==I2C_SMBUS_READ)?I2C_M_RD:0; msg[0].flags = flags | (read_write == I2C_SMBUS_READ ?
I2C_M_RD : 0);
num = 1; num = 1;
break; break;
case I2C_SMBUS_BYTE: case I2C_SMBUS_BYTE:
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-dev.h> #include <linux/i2c-dev.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/jiffies.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
static struct i2c_driver i2cdev_driver; static struct i2c_driver i2cdev_driver;
...@@ -422,7 +423,10 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -422,7 +423,10 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
client->adapter->retries = arg; client->adapter->retries = arg;
break; break;
case I2C_TIMEOUT: case I2C_TIMEOUT:
client->adapter->timeout = arg; /* For historical reasons, user-space sets the timeout
* value in units of 10 ms.
*/
client->adapter->timeout = msecs_to_jiffies(arg * 10);
break; break;
default: default:
/* NOTE: returning a fault code here could cause trouble /* NOTE: returning a fault code here could cause trouble
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <asm/types.h> #include <asm/types.h>
struct file;
struct pci_dev; struct pci_dev;
struct scatterlist; struct scatterlist;
struct vm_area_struct; struct vm_area_struct;
......
...@@ -1314,6 +1314,7 @@ EXPORT_SYMBOL(hpsb_make_lock64packet); ...@@ -1314,6 +1314,7 @@ EXPORT_SYMBOL(hpsb_make_lock64packet);
EXPORT_SYMBOL(hpsb_make_phypacket); EXPORT_SYMBOL(hpsb_make_phypacket);
EXPORT_SYMBOL(hpsb_read); EXPORT_SYMBOL(hpsb_read);
EXPORT_SYMBOL(hpsb_write); EXPORT_SYMBOL(hpsb_write);
EXPORT_SYMBOL(hpsb_lock);
EXPORT_SYMBOL(hpsb_packet_success); EXPORT_SYMBOL(hpsb_packet_success);
/** highlevel.c **/ /** highlevel.c **/
......
...@@ -501,8 +501,6 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation, ...@@ -501,8 +501,6 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
if (length == 0) if (length == 0)
return -EINVAL; return -EINVAL;
BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
packet = hpsb_make_readpacket(host, node, addr, length); packet = hpsb_make_readpacket(host, node, addr, length);
if (!packet) { if (!packet) {
...@@ -550,8 +548,6 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation, ...@@ -550,8 +548,6 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
if (length == 0) if (length == 0)
return -EINVAL; return -EINVAL;
BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
packet = hpsb_make_writepacket(host, node, addr, buffer, length); packet = hpsb_make_writepacket(host, node, addr, buffer, length);
if (!packet) if (!packet)
...@@ -570,3 +566,30 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation, ...@@ -570,3 +566,30 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
return retval; return retval;
} }
int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, int extcode, quadlet_t *data, quadlet_t arg)
{
struct hpsb_packet *packet;
int retval = 0;
packet = hpsb_make_lockpacket(host, node, addr, extcode, data, arg);
if (!packet)
return -ENOMEM;
packet->generation = generation;
retval = hpsb_send_packet_and_wait(packet);
if (retval < 0)
goto hpsb_lock_fail;
retval = hpsb_packet_success(packet);
if (retval == 0)
*data = packet->data[0];
hpsb_lock_fail:
hpsb_free_tlabel(packet);
hpsb_free_packet(packet);
return retval;
}
...@@ -30,6 +30,8 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation, ...@@ -30,6 +30,8 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, quadlet_t *buffer, size_t length); u64 addr, quadlet_t *buffer, size_t length);
int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation, int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, quadlet_t *buffer, size_t length); u64 addr, quadlet_t *buffer, size_t length);
int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, int extcode, quadlet_t *data, quadlet_t arg);
#ifdef HPSB_DEBUG_TLABELS #ifdef HPSB_DEBUG_TLABELS
extern spinlock_t hpsb_tlabel_lock; extern spinlock_t hpsb_tlabel_lock;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#define IEEE1394_ISO_H #define IEEE1394_ISO_H
#include <linux/spinlock_types.h> #include <linux/spinlock_types.h>
#include <linux/wait.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/types.h> #include <asm/types.h>
......
...@@ -971,6 +971,9 @@ static struct unit_directory *nodemgr_process_unit_directory ...@@ -971,6 +971,9 @@ static struct unit_directory *nodemgr_process_unit_directory
ud->ud_kv = ud_kv; ud->ud_kv = ud_kv;
ud->id = (*id)++; ud->id = (*id)++;
/* inherit vendor_id from root directory if none exists in unit dir */
ud->vendor_id = ne->vendor_id;
csr1212_for_each_dir_entry(ne->csr, kv, ud_kv, dentry) { csr1212_for_each_dir_entry(ne->csr, kv, ud_kv, dentry) {
switch (kv->key.id) { switch (kv->key.id) {
case CSR1212_KV_ID_VENDOR: case CSR1212_KV_ID_VENDOR:
...@@ -1265,7 +1268,8 @@ static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr, ...@@ -1265,7 +1268,8 @@ static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr,
csr1212_destroy_csr(csr); csr1212_destroy_csr(csr);
} }
/* Mark the node current */ /* Finally, mark the node current */
smp_wmb();
ne->generation = generation; ne->generation = generation;
if (ne->in_limbo) { if (ne->in_limbo) {
...@@ -1798,7 +1802,7 @@ void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet) ...@@ -1798,7 +1802,7 @@ void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet)
{ {
packet->host = ne->host; packet->host = ne->host;
packet->generation = ne->generation; packet->generation = ne->generation;
barrier(); smp_rmb();
packet->node_id = ne->nodeid; packet->node_id = ne->nodeid;
} }
...@@ -1807,7 +1811,7 @@ int hpsb_node_write(struct node_entry *ne, u64 addr, ...@@ -1807,7 +1811,7 @@ int hpsb_node_write(struct node_entry *ne, u64 addr,
{ {
unsigned int generation = ne->generation; unsigned int generation = ne->generation;
barrier(); smp_rmb();
return hpsb_write(ne->host, ne->nodeid, generation, return hpsb_write(ne->host, ne->nodeid, generation,
addr, buffer, length); addr, buffer, length);
} }
......
...@@ -21,9 +21,11 @@ ...@@ -21,9 +21,11 @@
#define _IEEE1394_NODEMGR_H #define _IEEE1394_NODEMGR_H
#include <linux/device.h> #include <linux/device.h>
#include <asm/system.h>
#include <asm/types.h> #include <asm/types.h>
#include "ieee1394_core.h" #include "ieee1394_core.h"
#include "ieee1394_transactions.h"
#include "ieee1394_types.h" #include "ieee1394_types.h"
struct csr1212_csr; struct csr1212_csr;
...@@ -154,6 +156,22 @@ static inline int hpsb_node_entry_valid(struct node_entry *ne) ...@@ -154,6 +156,22 @@ static inline int hpsb_node_entry_valid(struct node_entry *ne)
void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet); void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet);
int hpsb_node_write(struct node_entry *ne, u64 addr, int hpsb_node_write(struct node_entry *ne, u64 addr,
quadlet_t *buffer, size_t length); quadlet_t *buffer, size_t length);
static inline int hpsb_node_read(struct node_entry *ne, u64 addr,
quadlet_t *buffer, size_t length)
{
unsigned int g = ne->generation;
smp_rmb();
return hpsb_read(ne->host, ne->nodeid, g, addr, buffer, length);
}
static inline int hpsb_node_lock(struct node_entry *ne, u64 addr, int extcode,
quadlet_t *buffer, quadlet_t arg)
{
unsigned int g = ne->generation;
smp_rmb();
return hpsb_lock(ne->host, ne->nodeid, g, addr, extcode, buffer, arg);
}
int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *)); int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *));
int init_ieee1394_nodemgr(void); int init_ieee1394_nodemgr(void);
......
...@@ -54,7 +54,7 @@ void memcpy_toshmem(int card, void *dest, const void *src, size_t n) ...@@ -54,7 +54,7 @@ void memcpy_toshmem(int card, void *dest, const void *src, size_t n)
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags); spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename, pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename,
((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); ((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80);
pr_debug("%s: copying %d bytes from %#lx to %#lx\n", pr_debug("%s: copying %zu bytes from %#lx to %#lx\n",
sc_adapter[card]->devicename, n, sc_adapter[card]->devicename, n,
(unsigned long) src, (unsigned long) src,
sc_adapter[card]->rambase + ((unsigned long) dest %0x4000)); sc_adapter[card]->rambase + ((unsigned long) dest %0x4000));
......
...@@ -51,6 +51,10 @@ comment "Supported SDMC DM1105 Adapters" ...@@ -51,6 +51,10 @@ comment "Supported SDMC DM1105 Adapters"
depends on DVB_CORE && PCI && I2C depends on DVB_CORE && PCI && I2C
source "drivers/media/dvb/dm1105/Kconfig" source "drivers/media/dvb/dm1105/Kconfig"
comment "Supported FireWire (IEEE 1394) Adapters"
depends on DVB_CORE && IEEE1394
source "drivers/media/dvb/firewire/Kconfig"
comment "Supported DVB Frontends" comment "Supported DVB Frontends"
depends on DVB_CORE depends on DVB_CORE
source "drivers/media/dvb/frontends/Kconfig" source "drivers/media/dvb/frontends/Kconfig"
......
...@@ -3,3 +3,5 @@ ...@@ -3,3 +3,5 @@
# #
obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/ obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/
obj-$(CONFIG_DVB_FIREDTV) += firewire/
config DVB_FIREDTV
tristate "FireDTV and FloppyDTV"
depends on DVB_CORE && IEEE1394
help
Support for DVB receivers from Digital Everywhere
which are connected via IEEE 1394 (FireWire).
These devices don't have an MPEG decoder built in,
so you need an external software decoder to watch TV.
To compile this driver as a module, say M here:
the module will be called firedtv.
if DVB_FIREDTV
config DVB_FIREDTV_IEEE1394
def_bool IEEE1394
config DVB_FIREDTV_INPUT
def_bool INPUT = y || (INPUT = m && DVB_FIREDTV = m)
endif # DVB_FIREDTV
obj-$(CONFIG_DVB_FIREDTV) += firedtv.o
firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o
firedtv-$(CONFIG_DVB_FIREDTV_IEEE1394) += firedtv-1394.o
firedtv-$(CONFIG_DVB_FIREDTV_INPUT) += firedtv-rc.o
ccflags-y += -Idrivers/media/dvb/dvb-core
ccflags-$(CONFIG_DVB_FIREDTV_IEEE1394) += -Idrivers/ieee1394
/*
* FireDTV driver (formerly known as FireSAT)
*
* Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
* Copyright (C) 2007-2008 Ben Backx <ben@bbackx.com>
* Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
*
* 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 <linux/device.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <dma.h>
#include <csr1212.h>
#include <highlevel.h>
#include <hosts.h>
#include <ieee1394.h>
#include <iso.h>
#include <nodemgr.h>
#include "firedtv.h"
static LIST_HEAD(node_list);
static DEFINE_SPINLOCK(node_list_lock);
#define FIREWIRE_HEADER_SIZE 4
#define CIP_HEADER_SIZE 8
static void rawiso_activity_cb(struct hpsb_iso *iso)
{
struct firedtv *f, *fdtv = NULL;
unsigned int i, num, packet;
unsigned char *buf;
unsigned long flags;
int count;
spin_lock_irqsave(&node_list_lock, flags);
list_for_each_entry(f, &node_list, list)
if (f->backend_data == iso) {
fdtv = f;
break;
}
spin_unlock_irqrestore(&node_list_lock, flags);
packet = iso->first_packet;
num = hpsb_iso_n_ready(iso);
if (!fdtv) {
dev_err(fdtv->device, "received at unknown iso channel\n");
goto out;
}
for (i = 0; i < num; i++, packet = (packet + 1) % iso->buf_packets) {
buf = dma_region_i(&iso->data_buf, unsigned char,
iso->infos[packet].offset + CIP_HEADER_SIZE);
count = (iso->infos[packet].len - CIP_HEADER_SIZE) /
(188 + FIREWIRE_HEADER_SIZE);
/* ignore empty packet */
if (iso->infos[packet].len <= CIP_HEADER_SIZE)
continue;
while (count--) {
if (buf[FIREWIRE_HEADER_SIZE] == 0x47)
dvb_dmx_swfilter_packets(&fdtv->demux,
&buf[FIREWIRE_HEADER_SIZE], 1);
else
dev_err(fdtv->device,
"skipping invalid packet\n");
buf += 188 + FIREWIRE_HEADER_SIZE;
}
}
out:
hpsb_iso_recv_release_packets(iso, num);
}
static inline struct node_entry *node_of(struct firedtv *fdtv)
{
return container_of(fdtv->device, struct unit_directory, device)->ne;
}
static int node_lock(struct firedtv *fdtv, u64 addr, void *data, __be32 arg)
{
return hpsb_node_lock(node_of(fdtv), addr, EXTCODE_COMPARE_SWAP, data,
(__force quadlet_t)arg);
}
static int node_read(struct firedtv *fdtv, u64 addr, void *data, size_t len)
{
return hpsb_node_read(node_of(fdtv), addr, data, len);
}
static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
{
return hpsb_node_write(node_of(fdtv), addr, data, len);
}
#define FDTV_ISO_BUFFER_PACKETS 256
#define FDTV_ISO_BUFFER_SIZE (FDTV_ISO_BUFFER_PACKETS * 200)
static int start_iso(struct firedtv *fdtv)
{
struct hpsb_iso *iso_handle;
int ret;
iso_handle = hpsb_iso_recv_init(node_of(fdtv)->host,
FDTV_ISO_BUFFER_SIZE, FDTV_ISO_BUFFER_PACKETS,
fdtv->isochannel, HPSB_ISO_DMA_DEFAULT,
-1, /* stat.config.irq_interval */
rawiso_activity_cb);
if (iso_handle == NULL) {
dev_err(fdtv->device, "cannot initialize iso receive\n");
return -ENOMEM;
}
fdtv->backend_data = iso_handle;
ret = hpsb_iso_recv_start(iso_handle, -1, -1, 0);
if (ret != 0) {
dev_err(fdtv->device, "cannot start iso receive\n");
hpsb_iso_shutdown(iso_handle);
fdtv->backend_data = NULL;
}
return ret;
}
static void stop_iso(struct firedtv *fdtv)
{
struct hpsb_iso *iso_handle = fdtv->backend_data;
if (iso_handle != NULL) {
hpsb_iso_stop(iso_handle);
hpsb_iso_shutdown(iso_handle);
}
fdtv->backend_data = NULL;
}
static const struct firedtv_backend fdtv_1394_backend = {
.lock = node_lock,
.read = node_read,
.write = node_write,
.start_iso = start_iso,
.stop_iso = stop_iso,
};
static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
int cts, u8 *data, size_t length)
{
struct firedtv *f, *fdtv = NULL;
unsigned long flags;
int su;
if (length == 0 || (data[0] & 0xf0) != 0)
return;
su = data[1] & 0x7;
spin_lock_irqsave(&node_list_lock, flags);
list_for_each_entry(f, &node_list, list)
if (node_of(f)->host == host &&
node_of(f)->nodeid == nodeid &&
(f->subunit == su || (f->subunit == 0 && su == 0x7))) {
fdtv = f;
break;
}
spin_unlock_irqrestore(&node_list_lock, flags);
if (fdtv)
avc_recv(fdtv, data, length);
}
static int node_probe(struct device *dev)
{
struct unit_directory *ud =
container_of(dev, struct unit_directory, device);
struct firedtv *fdtv;
int kv_len, err;
void *kv_str;
kv_len = (ud->model_name_kv->value.leaf.len - 2) * sizeof(quadlet_t);
kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv);
fdtv = fdtv_alloc(dev, &fdtv_1394_backend, kv_str, kv_len);
if (!fdtv)
return -ENOMEM;
/*
* Work around a bug in udev's path_id script: Use the fw-host's dev
* instead of the unit directory's dev as parent of the input device.
*/
err = fdtv_register_rc(fdtv, dev->parent->parent);
if (err)
goto fail_free;
spin_lock_irq(&node_list_lock);
list_add_tail(&fdtv->list, &node_list);
spin_unlock_irq(&node_list_lock);
err = avc_identify_subunit(fdtv);
if (err)
goto fail;
err = fdtv_dvb_register(fdtv);
if (err)
goto fail;
avc_register_remote_control(fdtv);
return 0;
fail:
spin_lock_irq(&node_list_lock);
list_del(&fdtv->list);
spin_unlock_irq(&node_list_lock);
fdtv_unregister_rc(fdtv);
fail_free:
kfree(fdtv);
return err;
}
static int node_remove(struct device *dev)
{
struct firedtv *fdtv = dev->driver_data;
fdtv_dvb_unregister(fdtv);
spin_lock_irq(&node_list_lock);
list_del(&fdtv->list);
spin_unlock_irq(&node_list_lock);
cancel_work_sync(&fdtv->remote_ctrl_work);
fdtv_unregister_rc(fdtv);
kfree(fdtv);
return 0;
}
static int node_update(struct unit_directory *ud)
{
struct firedtv *fdtv = ud->device.driver_data;
if (fdtv->isochannel >= 0)
cmp_establish_pp_connection(fdtv, fdtv->subunit,
fdtv->isochannel);
return 0;
}
static struct hpsb_protocol_driver fdtv_driver = {
.name = "firedtv",
.update = node_update,
.driver = {
.probe = node_probe,
.remove = node_remove,
},
};
static struct hpsb_highlevel fdtv_highlevel = {
.name = "firedtv",
.fcp_request = fcp_request,
};
int __init fdtv_1394_init(struct ieee1394_device_id id_table[])
{
int ret;
hpsb_register_highlevel(&fdtv_highlevel);
fdtv_driver.id_table = id_table;
ret = hpsb_register_protocol(&fdtv_driver);
if (ret) {
printk(KERN_ERR "firedtv: failed to register protocol\n");
hpsb_unregister_highlevel(&fdtv_highlevel);
}
return ret;
}
void __exit fdtv_1394_exit(void)
{
hpsb_unregister_protocol(&fdtv_driver);
hpsb_unregister_highlevel(&fdtv_highlevel);
}
此差异已折叠。
/*
* FireDTV driver (formerly known as FireSAT)
*
* Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
* Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
*
* 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 <linux/device.h>
#include <linux/dvb/ca.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <dvbdev.h>
#include "firedtv.h"
#define EN50221_TAG_APP_INFO_ENQUIRY 0x9f8020
#define EN50221_TAG_CA_INFO_ENQUIRY 0x9f8030
#define EN50221_TAG_CA_PMT 0x9f8032
#define EN50221_TAG_ENTER_MENU 0x9f8022
static int fdtv_ca_ready(struct firedtv_tuner_status *stat)
{
return stat->ca_initialization_status == 1 &&
stat->ca_error_flag == 0 &&
stat->ca_dvb_flag == 1 &&
stat->ca_module_present_status == 1;
}
static int fdtv_get_ca_flags(struct firedtv_tuner_status *stat)
{
int flags = 0;
if (stat->ca_module_present_status == 1)
flags |= CA_CI_MODULE_PRESENT;
if (stat->ca_initialization_status == 1 &&
stat->ca_error_flag == 0 &&
stat->ca_dvb_flag == 1)
flags |= CA_CI_MODULE_READY;
return flags;
}
static int fdtv_ca_reset(struct firedtv *fdtv)
{
return avc_ca_reset(fdtv) ? -EFAULT : 0;
}
static int fdtv_ca_get_caps(void *arg)
{
struct ca_caps *cap = arg;
cap->slot_num = 1;
cap->slot_type = CA_CI;
cap->descr_num = 1;
cap->descr_type = CA_ECD;
return 0;
}
static int fdtv_ca_get_slot_info(struct firedtv *fdtv, void *arg)
{
struct firedtv_tuner_status stat;
struct ca_slot_info *slot = arg;
if (avc_tuner_status(fdtv, &stat))
return -EFAULT;
if (slot->num != 0)
return -EFAULT;
slot->type = CA_CI;
slot->flags = fdtv_get_ca_flags(&stat);
return 0;
}
static int fdtv_ca_app_info(struct firedtv *fdtv, void *arg)
{
struct ca_msg *reply = arg;
return avc_ca_app_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
}
static int fdtv_ca_info(struct firedtv *fdtv, void *arg)
{
struct ca_msg *reply = arg;
return avc_ca_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
}
static int fdtv_ca_get_mmi(struct firedtv *fdtv, void *arg)
{
struct ca_msg *reply = arg;
return avc_ca_get_mmi(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
}
static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg)
{
struct firedtv_tuner_status stat;
int err;
switch (fdtv->ca_last_command) {
case EN50221_TAG_APP_INFO_ENQUIRY:
err = fdtv_ca_app_info(fdtv, arg);
break;
case EN50221_TAG_CA_INFO_ENQUIRY:
err = fdtv_ca_info(fdtv, arg);
break;
default:
if (avc_tuner_status(fdtv, &stat))
err = -EFAULT;
else if (stat.ca_mmi == 1)
err = fdtv_ca_get_mmi(fdtv, arg);
else {
dev_info(fdtv->device, "unhandled CA message 0x%08x\n",
fdtv->ca_last_command);
err = -EFAULT;
}
}
fdtv->ca_last_command = 0;
return err;
}
static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
{
struct ca_msg *msg = arg;
int data_pos;
int data_length;
int i;
data_pos = 4;
if (msg->msg[3] & 0x80) {
data_length = 0;
for (i = 0; i < (msg->msg[3] & 0x7f); i++)
data_length = (data_length << 8) + msg->msg[data_pos++];
} else {
data_length = msg->msg[3];
}
return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length) ? -EFAULT : 0;
}
static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
{
struct ca_msg *msg = arg;
int err;
/* Do we need a semaphore for this? */
fdtv->ca_last_command =
(msg->msg[0] << 16) + (msg->msg[1] << 8) + msg->msg[2];
switch (fdtv->ca_last_command) {
case EN50221_TAG_CA_PMT:
err = fdtv_ca_pmt(fdtv, arg);
break;
case EN50221_TAG_APP_INFO_ENQUIRY:
/* handled in ca_get_msg */
err = 0;
break;
case EN50221_TAG_CA_INFO_ENQUIRY:
/* handled in ca_get_msg */
err = 0;
break;
case EN50221_TAG_ENTER_MENU:
err = avc_ca_enter_menu(fdtv);
break;
default:
dev_err(fdtv->device, "unhandled CA message 0x%08x\n",
fdtv->ca_last_command);
err = -EFAULT;
}
return err;
}
static int fdtv_ca_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *arg)
{
struct dvb_device *dvbdev = file->private_data;
struct firedtv *fdtv = dvbdev->priv;
struct firedtv_tuner_status stat;
int err;
switch (cmd) {
case CA_RESET:
err = fdtv_ca_reset(fdtv);
break;
case CA_GET_CAP:
err = fdtv_ca_get_caps(arg);
break;
case CA_GET_SLOT_INFO:
err = fdtv_ca_get_slot_info(fdtv, arg);
break;
case CA_GET_MSG:
err = fdtv_ca_get_msg(fdtv, arg);
break;
case CA_SEND_MSG:
err = fdtv_ca_send_msg(fdtv, arg);
break;
default:
dev_info(fdtv->device, "unhandled CA ioctl %u\n", cmd);
err = -EOPNOTSUPP;
}
/* FIXME Is this necessary? */
avc_tuner_status(fdtv, &stat);
return err;
}
static unsigned int fdtv_ca_io_poll(struct file *file, poll_table *wait)
{
return POLLIN;
}
static struct file_operations fdtv_ca_fops = {
.owner = THIS_MODULE,
.ioctl = dvb_generic_ioctl,
.open = dvb_generic_open,
.release = dvb_generic_release,
.poll = fdtv_ca_io_poll,
};
static struct dvb_device fdtv_ca = {
.users = 1,
.readers = 1,
.writers = 1,
.fops = &fdtv_ca_fops,
.kernel_ioctl = fdtv_ca_ioctl,
};
int fdtv_ca_register(struct firedtv *fdtv)
{
struct firedtv_tuner_status stat;
int err;
if (avc_tuner_status(fdtv, &stat))
return -EINVAL;
if (!fdtv_ca_ready(&stat))
return -EFAULT;
err = dvb_register_device(&fdtv->adapter, &fdtv->cadev,
&fdtv_ca, fdtv, DVB_DEVICE_CA);
if (stat.ca_application_info == 0)
dev_err(fdtv->device, "CaApplicationInfo is not set\n");
if (stat.ca_date_time_request == 1)
avc_ca_get_time_date(fdtv, &fdtv->ca_time_interval);
return err;
}
void fdtv_ca_release(struct firedtv *fdtv)
{
if (fdtv->cadev)
dvb_unregister_device(fdtv->cadev);
}
/*
* FireDTV driver (formerly known as FireSAT)
*
* Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
* Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
*
* 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 <linux/bitops.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <dmxdev.h>
#include <dvb_demux.h>
#include <dvbdev.h>
#include <dvb_frontend.h>
#include "firedtv.h"
static int alloc_channel(struct firedtv *fdtv)
{
int i;
for (i = 0; i < 16; i++)
if (!__test_and_set_bit(i, &fdtv->channel_active))
break;
return i;
}
static void collect_channels(struct firedtv *fdtv, int *pidc, u16 pid[])
{
int i, n;
for (i = 0, n = 0; i < 16; i++)
if (test_bit(i, &fdtv->channel_active))
pid[n++] = fdtv->channel_pid[i];
*pidc = n;
}
static inline void dealloc_channel(struct firedtv *fdtv, int i)
{
__clear_bit(i, &fdtv->channel_active);
}
int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed)
{
struct firedtv *fdtv = dvbdmxfeed->demux->priv;
int pidc, c, ret;
u16 pids[16];
switch (dvbdmxfeed->type) {
case DMX_TYPE_TS:
case DMX_TYPE_SEC:
break;
default:
dev_err(fdtv->device, "can't start dmx feed: invalid type %u\n",
dvbdmxfeed->type);
return -EINVAL;
}
if (mutex_lock_interruptible(&fdtv->demux_mutex))
return -EINTR;
if (dvbdmxfeed->type == DMX_TYPE_TS) {
switch (dvbdmxfeed->pes_type) {
case DMX_TS_PES_VIDEO:
case DMX_TS_PES_AUDIO:
case DMX_TS_PES_TELETEXT:
case DMX_TS_PES_PCR:
case DMX_TS_PES_OTHER:
c = alloc_channel(fdtv);
break;
default:
dev_err(fdtv->device,
"can't start dmx feed: invalid pes type %u\n",
dvbdmxfeed->pes_type);
ret = -EINVAL;
goto out;
}
} else {
c = alloc_channel(fdtv);
}
if (c > 15) {
dev_err(fdtv->device, "can't start dmx feed: busy\n");
ret = -EBUSY;
goto out;
}
dvbdmxfeed->priv = (typeof(dvbdmxfeed->priv))(unsigned long)c;
fdtv->channel_pid[c] = dvbdmxfeed->pid;
collect_channels(fdtv, &pidc, pids);
if (dvbdmxfeed->pid == 8192) {
ret = avc_tuner_get_ts(fdtv);
if (ret) {
dealloc_channel(fdtv, c);
dev_err(fdtv->device, "can't get TS\n");
goto out;
}
} else {
ret = avc_tuner_set_pids(fdtv, pidc, pids);
if (ret) {
dealloc_channel(fdtv, c);
dev_err(fdtv->device, "can't set PIDs\n");
goto out;
}
}
out:
mutex_unlock(&fdtv->demux_mutex);
return ret;
}
int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
{
struct dvb_demux *demux = dvbdmxfeed->demux;
struct firedtv *fdtv = demux->priv;
int pidc, c, ret;
u16 pids[16];
if (dvbdmxfeed->type == DMX_TYPE_TS &&
!((dvbdmxfeed->ts_type & TS_PACKET) &&
(demux->dmx.frontend->source != DMX_MEMORY_FE))) {
if (dvbdmxfeed->ts_type & TS_DECODER) {
if (dvbdmxfeed->pes_type >= DMX_TS_PES_OTHER ||
!demux->pesfilter[dvbdmxfeed->pes_type])
return -EINVAL;
demux->pids[dvbdmxfeed->pes_type] |= 0x8000;
demux->pesfilter[dvbdmxfeed->pes_type] = NULL;
}
if (!(dvbdmxfeed->ts_type & TS_DECODER &&
dvbdmxfeed->pes_type < DMX_TS_PES_OTHER))
return 0;
}
if (mutex_lock_interruptible(&fdtv->demux_mutex))
return -EINTR;
c = (unsigned long)dvbdmxfeed->priv;
dealloc_channel(fdtv, c);
collect_channels(fdtv, &pidc, pids);
ret = avc_tuner_set_pids(fdtv, pidc, pids);
mutex_unlock(&fdtv->demux_mutex);
return ret;
}
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
int fdtv_dvb_register(struct firedtv *fdtv)
{
int err;
err = dvb_register_adapter(&fdtv->adapter, fdtv_model_names[fdtv->type],
THIS_MODULE, fdtv->device, adapter_nr);
if (err < 0)
goto fail_log;
/*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/
fdtv->demux.dmx.capabilities = 0;
fdtv->demux.priv = fdtv;
fdtv->demux.filternum = 16;
fdtv->demux.feednum = 16;
fdtv->demux.start_feed = fdtv_start_feed;
fdtv->demux.stop_feed = fdtv_stop_feed;
fdtv->demux.write_to_decoder = NULL;
err = dvb_dmx_init(&fdtv->demux);
if (err)
goto fail_unreg_adapter;
fdtv->dmxdev.filternum = 16;
fdtv->dmxdev.demux = &fdtv->demux.dmx;
fdtv->dmxdev.capabilities = 0;
err = dvb_dmxdev_init(&fdtv->dmxdev, &fdtv->adapter);
if (err)
goto fail_dmx_release;
fdtv->frontend.source = DMX_FRONTEND_0;
err = fdtv->demux.dmx.add_frontend(&fdtv->demux.dmx, &fdtv->frontend);
if (err)
goto fail_dmxdev_release;
err = fdtv->demux.dmx.connect_frontend(&fdtv->demux.dmx,
&fdtv->frontend);
if (err)
goto fail_rem_frontend;
dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx);
fdtv_frontend_init(fdtv);
err = dvb_register_frontend(&fdtv->adapter, &fdtv->fe);
if (err)
goto fail_net_release;
err = fdtv_ca_register(fdtv);
if (err)
dev_info(fdtv->device,
"Conditional Access Module not enabled\n");
return 0;
fail_net_release:
dvb_net_release(&fdtv->dvbnet);
fdtv->demux.dmx.close(&fdtv->demux.dmx);
fail_rem_frontend:
fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
fail_dmxdev_release:
dvb_dmxdev_release(&fdtv->dmxdev);
fail_dmx_release:
dvb_dmx_release(&fdtv->demux);
fail_unreg_adapter:
dvb_unregister_adapter(&fdtv->adapter);
fail_log:
dev_err(fdtv->device, "DVB initialization failed\n");
return err;
}
void fdtv_dvb_unregister(struct firedtv *fdtv)
{
fdtv_ca_release(fdtv);
dvb_unregister_frontend(&fdtv->fe);
dvb_net_release(&fdtv->dvbnet);
fdtv->demux.dmx.close(&fdtv->demux.dmx);
fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
dvb_dmxdev_release(&fdtv->dmxdev);
dvb_dmx_release(&fdtv->demux);
dvb_unregister_adapter(&fdtv->adapter);
}
const char *fdtv_model_names[] = {
[FIREDTV_UNKNOWN] = "unknown type",
[FIREDTV_DVB_S] = "FireDTV S/CI",
[FIREDTV_DVB_C] = "FireDTV C/CI",
[FIREDTV_DVB_T] = "FireDTV T/CI",
[FIREDTV_DVB_S2] = "FireDTV S2 ",
};
struct firedtv *fdtv_alloc(struct device *dev,
const struct firedtv_backend *backend,
const char *name, size_t name_len)
{
struct firedtv *fdtv;
int i;
fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL);
if (!fdtv)
return NULL;
dev->driver_data = fdtv;
fdtv->device = dev;
fdtv->isochannel = -1;
fdtv->voltage = 0xff;
fdtv->tone = 0xff;
fdtv->backend = backend;
mutex_init(&fdtv->avc_mutex);
init_waitqueue_head(&fdtv->avc_wait);
fdtv->avc_reply_received = true;
mutex_init(&fdtv->demux_mutex);
INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work);
for (i = ARRAY_SIZE(fdtv_model_names); --i; )
if (strlen(fdtv_model_names[i]) <= name_len &&
strncmp(name, fdtv_model_names[i], name_len) == 0)
break;
fdtv->type = i;
return fdtv;
}
#define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION)
#define DIGITAL_EVERYWHERE_OUI 0x001287
#define AVC_UNIT_SPEC_ID_ENTRY 0x00a02d
#define AVC_SW_VERSION_ENTRY 0x010001
static struct ieee1394_device_id fdtv_id_table[] = {
{
/* FloppyDTV S/CI and FloppyDTV S2 */
.match_flags = MATCH_FLAGS,
.vendor_id = DIGITAL_EVERYWHERE_OUI,
.model_id = 0x000024,
.specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
.version = AVC_SW_VERSION_ENTRY,
}, {
/* FloppyDTV T/CI */
.match_flags = MATCH_FLAGS,
.vendor_id = DIGITAL_EVERYWHERE_OUI,
.model_id = 0x000025,
.specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
.version = AVC_SW_VERSION_ENTRY,
}, {
/* FloppyDTV C/CI */
.match_flags = MATCH_FLAGS,
.vendor_id = DIGITAL_EVERYWHERE_OUI,
.model_id = 0x000026,
.specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
.version = AVC_SW_VERSION_ENTRY,
}, {
/* FireDTV S/CI and FloppyDTV S2 */
.match_flags = MATCH_FLAGS,
.vendor_id = DIGITAL_EVERYWHERE_OUI,
.model_id = 0x000034,
.specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
.version = AVC_SW_VERSION_ENTRY,
}, {
/* FireDTV T/CI */
.match_flags = MATCH_FLAGS,
.vendor_id = DIGITAL_EVERYWHERE_OUI,
.model_id = 0x000035,
.specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
.version = AVC_SW_VERSION_ENTRY,
}, {
/* FireDTV C/CI */
.match_flags = MATCH_FLAGS,
.vendor_id = DIGITAL_EVERYWHERE_OUI,
.model_id = 0x000036,
.specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
.version = AVC_SW_VERSION_ENTRY,
}, {}
};
MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table);
static int __init fdtv_init(void)
{
return fdtv_1394_init(fdtv_id_table);
}
static void __exit fdtv_exit(void)
{
fdtv_1394_exit();
}
module_init(fdtv_init);
module_exit(fdtv_exit);
MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
MODULE_DESCRIPTION("FireDTV DVB Driver");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("FireDTV DVB");
/*
* FireDTV driver (formerly known as FireSAT)
*
* Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
* Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
*
* 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 <linux/device.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/types.h>
#include <dvb_frontend.h>
#include "firedtv.h"
static int fdtv_dvb_init(struct dvb_frontend *fe)
{
struct firedtv *fdtv = fe->sec_priv;
int err;
/* FIXME - allocate free channel at IRM */
fdtv->isochannel = fdtv->adapter.num;
err = cmp_establish_pp_connection(fdtv, fdtv->subunit,
fdtv->isochannel);
if (err) {
dev_err(fdtv->device,
"could not establish point to point connection\n");
return err;
}
return fdtv->backend->start_iso(fdtv);
}
static int fdtv_sleep(struct dvb_frontend *fe)
{
struct firedtv *fdtv = fe->sec_priv;
fdtv->backend->stop_iso(fdtv);
cmp_break_pp_connection(fdtv, fdtv->subunit, fdtv->isochannel);
fdtv->isochannel = -1;
return 0;
}
#define LNBCONTROL_DONTCARE 0xff
static int fdtv_diseqc_send_master_cmd(struct dvb_frontend *fe,
struct dvb_diseqc_master_cmd *cmd)
{
struct firedtv *fdtv = fe->sec_priv;
return avc_lnb_control(fdtv, LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE,
LNBCONTROL_DONTCARE, 1, cmd);
}
static int fdtv_diseqc_send_burst(struct dvb_frontend *fe,
fe_sec_mini_cmd_t minicmd)
{
return 0;
}
static int fdtv_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
{
struct firedtv *fdtv = fe->sec_priv;
fdtv->tone = tone;
return 0;
}
static int fdtv_set_voltage(struct dvb_frontend *fe,
fe_sec_voltage_t voltage)
{
struct firedtv *fdtv = fe->sec_priv;
fdtv->voltage = voltage;
return 0;
}
static int fdtv_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
struct firedtv *fdtv = fe->sec_priv;
struct firedtv_tuner_status stat;
if (avc_tuner_status(fdtv, &stat))
return -EINVAL;
if (stat.no_rf)
*status = 0;
else
*status = FE_HAS_SIGNAL | FE_HAS_VITERBI | FE_HAS_SYNC |
FE_HAS_CARRIER | FE_HAS_LOCK;
return 0;
}
static int fdtv_read_ber(struct dvb_frontend *fe, u32 *ber)
{
struct firedtv *fdtv = fe->sec_priv;
struct firedtv_tuner_status stat;
if (avc_tuner_status(fdtv, &stat))
return -EINVAL;
*ber = stat.ber;
return 0;
}
static int fdtv_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{
struct firedtv *fdtv = fe->sec_priv;
struct firedtv_tuner_status stat;
if (avc_tuner_status(fdtv, &stat))
return -EINVAL;
*strength = stat.signal_strength << 8;
return 0;
}
static int fdtv_read_snr(struct dvb_frontend *fe, u16 *snr)
{
struct firedtv *fdtv = fe->sec_priv;
struct firedtv_tuner_status stat;
if (avc_tuner_status(fdtv, &stat))
return -EINVAL;
/* C/N[dB] = -10 * log10(snr / 65535) */
*snr = stat.carrier_noise_ratio * 257;
return 0;
}
static int fdtv_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks)
{
return -EOPNOTSUPP;
}
#define ACCEPTED 0x9
static int fdtv_set_frontend(struct dvb_frontend *fe,
struct dvb_frontend_parameters *params)
{
struct firedtv *fdtv = fe->sec_priv;
/* FIXME: avc_tuner_dsd never returns ACCEPTED. Check status? */
if (avc_tuner_dsd(fdtv, params) != ACCEPTED)
return -EINVAL;
else
return 0; /* not sure of this... */
}
static int fdtv_get_frontend(struct dvb_frontend *fe,
struct dvb_frontend_parameters *params)
{
return -EOPNOTSUPP;
}
void fdtv_frontend_init(struct firedtv *fdtv)
{
struct dvb_frontend_ops *ops = &fdtv->fe.ops;
struct dvb_frontend_info *fi = &ops->info;
ops->init = fdtv_dvb_init;
ops->sleep = fdtv_sleep;
ops->set_frontend = fdtv_set_frontend;
ops->get_frontend = fdtv_get_frontend;
ops->read_status = fdtv_read_status;
ops->read_ber = fdtv_read_ber;
ops->read_signal_strength = fdtv_read_signal_strength;
ops->read_snr = fdtv_read_snr;
ops->read_ucblocks = fdtv_read_uncorrected_blocks;
ops->diseqc_send_master_cmd = fdtv_diseqc_send_master_cmd;
ops->diseqc_send_burst = fdtv_diseqc_send_burst;
ops->set_tone = fdtv_set_tone;
ops->set_voltage = fdtv_set_voltage;
switch (fdtv->type) {
case FIREDTV_DVB_S:
case FIREDTV_DVB_S2:
fi->type = FE_QPSK;
fi->frequency_min = 950000;
fi->frequency_max = 2150000;
fi->frequency_stepsize = 125;
fi->symbol_rate_min = 1000000;
fi->symbol_rate_max = 40000000;
fi->caps = FE_CAN_INVERSION_AUTO |
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;
break;
case FIREDTV_DVB_C:
fi->type = FE_QAM;
fi->frequency_min = 47000000;
fi->frequency_max = 866000000;
fi->frequency_stepsize = 62500;
fi->symbol_rate_min = 870000;
fi->symbol_rate_max = 6900000;
fi->caps = FE_CAN_INVERSION_AUTO |
FE_CAN_QAM_16 |
FE_CAN_QAM_32 |
FE_CAN_QAM_64 |
FE_CAN_QAM_128 |
FE_CAN_QAM_256 |
FE_CAN_QAM_AUTO;
break;
case FIREDTV_DVB_T:
fi->type = FE_OFDM;
fi->frequency_min = 49000000;
fi->frequency_max = 861000000;
fi->frequency_stepsize = 62500;
fi->caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_2_3 |
FE_CAN_TRANSMISSION_MODE_AUTO |
FE_CAN_GUARD_INTERVAL_AUTO |
FE_CAN_HIERARCHY_AUTO;
break;
default:
dev_err(fdtv->device, "no frontend for model type %d\n",
fdtv->type);
}
strcpy(fi->name, fdtv_model_names[fdtv->type]);
fdtv->fe.dvb = &fdtv->adapter;
fdtv->fe.sec_priv = fdtv;
}
/*
* FireDTV driver (formerly known as FireSAT)
*
* Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
*
* 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 <linux/bitops.h>
#include <linux/input.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/types.h>
#include "firedtv.h"
/* fixed table with older keycodes, geared towards MythTV */
const static u16 oldtable[] = {
/* code from device: 0x4501...0x451f */
KEY_ESC,
KEY_F9,
KEY_1,
KEY_2,
KEY_3,
KEY_4,
KEY_5,
KEY_6,
KEY_7,
KEY_8,
KEY_9,
KEY_I,
KEY_0,
KEY_ENTER,
KEY_RED,
KEY_UP,
KEY_GREEN,
KEY_F10,
KEY_SPACE,
KEY_F11,
KEY_YELLOW,
KEY_DOWN,
KEY_BLUE,
KEY_Z,
KEY_P,
KEY_PAGEDOWN,
KEY_LEFT,
KEY_W,
KEY_RIGHT,
KEY_P,
KEY_M,
/* code from device: 0x4540...0x4542 */
KEY_R,
KEY_V,
KEY_C,
};
/* user-modifiable table for a remote as sold in 2008 */
const static u16 keytable[] = {
/* code from device: 0x0300...0x031f */
[0x00] = KEY_POWER,
[0x01] = KEY_SLEEP,
[0x02] = KEY_STOP,
[0x03] = KEY_OK,
[0x04] = KEY_RIGHT,
[0x05] = KEY_1,
[0x06] = KEY_2,
[0x07] = KEY_3,
[0x08] = KEY_LEFT,
[0x09] = KEY_4,
[0x0a] = KEY_5,
[0x0b] = KEY_6,
[0x0c] = KEY_UP,
[0x0d] = KEY_7,
[0x0e] = KEY_8,
[0x0f] = KEY_9,
[0x10] = KEY_DOWN,
[0x11] = KEY_TITLE, /* "OSD" - fixme */
[0x12] = KEY_0,
[0x13] = KEY_F20, /* "16:9" - fixme */
[0x14] = KEY_SCREEN, /* "FULL" - fixme */
[0x15] = KEY_MUTE,
[0x16] = KEY_SUBTITLE,
[0x17] = KEY_RECORD,
[0x18] = KEY_TEXT,
[0x19] = KEY_AUDIO,
[0x1a] = KEY_RED,
[0x1b] = KEY_PREVIOUS,
[0x1c] = KEY_REWIND,
[0x1d] = KEY_PLAYPAUSE,
[0x1e] = KEY_NEXT,
[0x1f] = KEY_VOLUMEUP,
/* code from device: 0x0340...0x0354 */
[0x20] = KEY_CHANNELUP,
[0x21] = KEY_F21, /* "4:3" - fixme */
[0x22] = KEY_TV,
[0x23] = KEY_DVD,
[0x24] = KEY_VCR,
[0x25] = KEY_AUX,
[0x26] = KEY_GREEN,
[0x27] = KEY_YELLOW,
[0x28] = KEY_BLUE,
[0x29] = KEY_CHANNEL, /* "CH.LIST" */
[0x2a] = KEY_VENDOR, /* "CI" - fixme */
[0x2b] = KEY_VOLUMEDOWN,
[0x2c] = KEY_CHANNELDOWN,
[0x2d] = KEY_LAST,
[0x2e] = KEY_INFO,
[0x2f] = KEY_FORWARD,
[0x30] = KEY_LIST,
[0x31] = KEY_FAVORITES,
[0x32] = KEY_MENU,
[0x33] = KEY_EPG,
[0x34] = KEY_EXIT,
};
int fdtv_register_rc(struct firedtv *fdtv, struct device *dev)
{
struct input_dev *idev;
int i, err;
idev = input_allocate_device();
if (!idev)
return -ENOMEM;
fdtv->remote_ctrl_dev = idev;
idev->name = "FireDTV remote control";
idev->dev.parent = dev;
idev->evbit[0] = BIT_MASK(EV_KEY);
idev->keycode = kmemdup(keytable, sizeof(keytable), GFP_KERNEL);
if (!idev->keycode) {
err = -ENOMEM;
goto fail;
}
idev->keycodesize = sizeof(keytable[0]);
idev->keycodemax = ARRAY_SIZE(keytable);
for (i = 0; i < ARRAY_SIZE(keytable); i++)
set_bit(keytable[i], idev->keybit);
err = input_register_device(idev);
if (err)
goto fail_free_keymap;
return 0;
fail_free_keymap:
kfree(idev->keycode);
fail:
input_free_device(idev);
return err;
}
void fdtv_unregister_rc(struct firedtv *fdtv)
{
kfree(fdtv->remote_ctrl_dev->keycode);
input_unregister_device(fdtv->remote_ctrl_dev);
}
void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code)
{
u16 *keycode = fdtv->remote_ctrl_dev->keycode;
if (code >= 0x0300 && code <= 0x031f)
code = keycode[code - 0x0300];
else if (code >= 0x0340 && code <= 0x0354)
code = keycode[code - 0x0320];
else if (code >= 0x4501 && code <= 0x451f)
code = oldtable[code - 0x4501];
else if (code >= 0x4540 && code <= 0x4542)
code = oldtable[code - 0x4521];
else {
printk(KERN_DEBUG "firedtv: invalid key code 0x%04x "
"from remote control\n", code);
return;
}
input_report_key(fdtv->remote_ctrl_dev, code, 1);
input_report_key(fdtv->remote_ctrl_dev, code, 0);
}
/*
* FireDTV driver (formerly known as FireSAT)
*
* Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
* Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
*
* 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 _FIREDTV_H
#define _FIREDTV_H
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/spinlock_types.h>
#include <linux/types.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <demux.h>
#include <dmxdev.h>
#include <dvb_demux.h>
#include <dvb_frontend.h>
#include <dvb_net.h>
#include <dvbdev.h>
struct firedtv_tuner_status {
unsigned active_system:8;
unsigned searching:1;
unsigned moving:1;
unsigned no_rf:1;
unsigned input:1;
unsigned selected_antenna:7;
unsigned ber:32;
unsigned signal_strength:8;
unsigned raster_frequency:2;
unsigned rf_frequency:22;
unsigned man_dep_info_length:8;
unsigned front_end_error:1;
unsigned antenna_error:1;
unsigned front_end_power_status:1;
unsigned power_supply:1;
unsigned carrier_noise_ratio:16;
unsigned power_supply_voltage:8;
unsigned antenna_voltage:8;
unsigned firewire_bus_voltage:8;
unsigned ca_mmi:1;
unsigned ca_pmt_reply:1;
unsigned ca_date_time_request:1;
unsigned ca_application_info:1;
unsigned ca_module_present_status:1;
unsigned ca_dvb_flag:1;
unsigned ca_error_flag:1;
unsigned ca_initialization_status:1;
};
enum model_type {
FIREDTV_UNKNOWN = 0,
FIREDTV_DVB_S = 1,
FIREDTV_DVB_C = 2,
FIREDTV_DVB_T = 3,
FIREDTV_DVB_S2 = 4,
};
struct device;
struct input_dev;
struct firedtv;
struct firedtv_backend {
int (*lock)(struct firedtv *fdtv, u64 addr, void *data, __be32 arg);
int (*read)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
int (*start_iso)(struct firedtv *fdtv);
void (*stop_iso)(struct firedtv *fdtv);
};
struct firedtv {
struct device *device;
struct list_head list;
struct dvb_adapter adapter;
struct dmxdev dmxdev;
struct dvb_demux demux;
struct dmx_frontend frontend;
struct dvb_net dvbnet;
struct dvb_frontend fe;
struct dvb_device *cadev;
int ca_last_command;
int ca_time_interval;
struct mutex avc_mutex;
wait_queue_head_t avc_wait;
bool avc_reply_received;
struct work_struct remote_ctrl_work;
struct input_dev *remote_ctrl_dev;
enum model_type type;
char subunit;
char isochannel;
fe_sec_voltage_t voltage;
fe_sec_tone_mode_t tone;
const struct firedtv_backend *backend;
void *backend_data;
struct mutex demux_mutex;
unsigned long channel_active;
u16 channel_pid[16];
size_t response_length;
u8 response[512];
};
/* firedtv-1394.c */
#ifdef CONFIG_DVB_FIREDTV_IEEE1394
int fdtv_1394_init(struct ieee1394_device_id id_table[]);
void fdtv_1394_exit(void);
#else
static inline int fdtv_1394_init(struct ieee1394_device_id it[]) { return 0; }
static inline void fdtv_1394_exit(void) {}
#endif
/* firedtv-avc.c */
int avc_recv(struct firedtv *fdtv, void *data, size_t length);
int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat);
struct dvb_frontend_parameters;
int avc_tuner_dsd(struct firedtv *fdtv, struct dvb_frontend_parameters *params);
int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]);
int avc_tuner_get_ts(struct firedtv *fdtv);
int avc_identify_subunit(struct firedtv *fdtv);
struct dvb_diseqc_master_cmd;
int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
char conttone, char nrdiseq,
struct dvb_diseqc_master_cmd *diseqcmd);
void avc_remote_ctrl_work(struct work_struct *work);
int avc_register_remote_control(struct firedtv *fdtv);
int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
int avc_ca_reset(struct firedtv *fdtv);
int avc_ca_pmt(struct firedtv *fdtv, char *app_info, int length);
int avc_ca_get_time_date(struct firedtv *fdtv, int *interval);
int avc_ca_enter_menu(struct firedtv *fdtv);
int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len);
int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel);
void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel);
/* firedtv-ci.c */
int fdtv_ca_register(struct firedtv *fdtv);
void fdtv_ca_release(struct firedtv *fdtv);
/* firedtv-dvb.c */
int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed);
int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed);
int fdtv_dvb_register(struct firedtv *fdtv);
void fdtv_dvb_unregister(struct firedtv *fdtv);
struct firedtv *fdtv_alloc(struct device *dev,
const struct firedtv_backend *backend,
const char *name, size_t name_len);
extern const char *fdtv_model_names[];
/* firedtv-fe.c */
void fdtv_frontend_init(struct firedtv *fdtv);
/* firedtv-rc.c */
#ifdef CONFIG_DVB_FIREDTV_INPUT
int fdtv_register_rc(struct firedtv *fdtv, struct device *dev);
void fdtv_unregister_rc(struct firedtv *fdtv);
void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code);
#else
static inline int fdtv_register_rc(struct firedtv *fdtv,
struct device *dev) { return 0; }
static inline void fdtv_unregister_rc(struct firedtv *fdtv) {}
static inline void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code) {}
#endif
#endif /* _FIREDTV_H */
...@@ -2342,6 +2342,17 @@ config ATL1E ...@@ -2342,6 +2342,17 @@ config ATL1E
To compile this driver as a module, choose M here. The module To compile this driver as a module, choose M here. The module
will be called atl1e. will be called atl1e.
config ATL1C
tristate "Atheros L1C Gigabit Ethernet support (EXPERIMENTAL)"
depends on PCI && EXPERIMENTAL
select CRC32
select MII
help
This driver supports the Atheros L1C gigabit ethernet adapter.
To compile this driver as a module, choose M here. The module
will be called atl1c.
config JME config JME
tristate "JMicron(R) PCI-Express Gigabit Ethernet support" tristate "JMicron(R) PCI-Express Gigabit Ethernet support"
depends on PCI depends on PCI
......
...@@ -17,6 +17,7 @@ obj-$(CONFIG_BONDING) += bonding/ ...@@ -17,6 +17,7 @@ obj-$(CONFIG_BONDING) += bonding/
obj-$(CONFIG_ATL1) += atlx/ obj-$(CONFIG_ATL1) += atlx/
obj-$(CONFIG_ATL2) += atlx/ obj-$(CONFIG_ATL2) += atlx/
obj-$(CONFIG_ATL1E) += atl1e/ obj-$(CONFIG_ATL1E) += atl1e/
obj-$(CONFIG_ATL1C) += atl1c/
obj-$(CONFIG_GIANFAR) += gianfar_driver.o obj-$(CONFIG_GIANFAR) += gianfar_driver.o
obj-$(CONFIG_TEHUTI) += tehuti.o obj-$(CONFIG_TEHUTI) += tehuti.o
obj-$(CONFIG_ENIC) += enic/ obj-$(CONFIG_ENIC) += enic/
......
obj-$(CONFIG_ATL1C) += atl1c.o
atl1c-objs := atl1c_main.o atl1c_hw.o atl1c_ethtool.o
此差异已折叠。
/*
* Copyright(c) 2009 - 2009 Atheros Corporation. All rights reserved.
*
* Derived from Intel e1000 driver
* Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. 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 <linux/netdevice.h>
#include <linux/ethtool.h>
#include "atl1c.h"
static int atl1c_get_settings(struct net_device *netdev,
struct ethtool_cmd *ecmd)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
struct atl1c_hw *hw = &adapter->hw;
ecmd->supported = (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_Autoneg |
SUPPORTED_TP);
if (hw->ctrl_flags & ATL1C_LINK_CAP_1000M)
ecmd->supported |= SUPPORTED_1000baseT_Full;
ecmd->advertising = ADVERTISED_TP;
ecmd->advertising |= hw->autoneg_advertised;
ecmd->port = PORT_TP;
ecmd->phy_address = 0;
ecmd->transceiver = XCVR_INTERNAL;
if (adapter->link_speed != SPEED_0) {
ecmd->speed = adapter->link_speed;
if (adapter->link_duplex == FULL_DUPLEX)
ecmd->duplex = DUPLEX_FULL;
else
ecmd->duplex = DUPLEX_HALF;
} else {
ecmd->speed = -1;
ecmd->duplex = -1;
}
ecmd->autoneg = AUTONEG_ENABLE;
return 0;
}
static int atl1c_set_settings(struct net_device *netdev,
struct ethtool_cmd *ecmd)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
struct atl1c_hw *hw = &adapter->hw;
u16 autoneg_advertised;
while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
msleep(1);
if (ecmd->autoneg == AUTONEG_ENABLE) {
autoneg_advertised = ADVERTISED_Autoneg;
} else {
if (ecmd->speed == SPEED_1000) {
if (ecmd->duplex != DUPLEX_FULL) {
if (netif_msg_link(adapter))
dev_warn(&adapter->pdev->dev,
"1000M half is invalid\n");
clear_bit(__AT_RESETTING, &adapter->flags);
return -EINVAL;
}
autoneg_advertised = ADVERTISED_1000baseT_Full;
} else if (ecmd->speed == SPEED_100) {
if (ecmd->duplex == DUPLEX_FULL)
autoneg_advertised = ADVERTISED_100baseT_Full;
else
autoneg_advertised = ADVERTISED_100baseT_Half;
} else {
if (ecmd->duplex == DUPLEX_FULL)
autoneg_advertised = ADVERTISED_10baseT_Full;
else
autoneg_advertised = ADVERTISED_10baseT_Half;
}
}
if (hw->autoneg_advertised != autoneg_advertised) {
hw->autoneg_advertised = autoneg_advertised;
if (atl1c_restart_autoneg(hw) != 0) {
if (netif_msg_link(adapter))
dev_warn(&adapter->pdev->dev,
"ethtool speed/duplex setting failed\n");
clear_bit(__AT_RESETTING, &adapter->flags);
return -EINVAL;
}
}
clear_bit(__AT_RESETTING, &adapter->flags);
return 0;
}
static u32 atl1c_get_tx_csum(struct net_device *netdev)
{
return (netdev->features & NETIF_F_HW_CSUM) != 0;
}
static u32 atl1c_get_msglevel(struct net_device *netdev)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
return adapter->msg_enable;
}
static void atl1c_set_msglevel(struct net_device *netdev, u32 data)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
adapter->msg_enable = data;
}
static int atl1c_get_regs_len(struct net_device *netdev)
{
return AT_REGS_LEN;
}
static void atl1c_get_regs(struct net_device *netdev,
struct ethtool_regs *regs, void *p)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
struct atl1c_hw *hw = &adapter->hw;
u32 *regs_buff = p;
u16 phy_data;
memset(p, 0, AT_REGS_LEN);
regs->version = 0;
AT_READ_REG(hw, REG_VPD_CAP, p++);
AT_READ_REG(hw, REG_PM_CTRL, p++);
AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL, p++);
AT_READ_REG(hw, REG_TWSI_CTRL, p++);
AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL, p++);
AT_READ_REG(hw, REG_MASTER_CTRL, p++);
AT_READ_REG(hw, REG_MANUAL_TIMER_INIT, p++);
AT_READ_REG(hw, REG_IRQ_MODRT_TIMER_INIT, p++);
AT_READ_REG(hw, REG_GPHY_CTRL, p++);
AT_READ_REG(hw, REG_LINK_CTRL, p++);
AT_READ_REG(hw, REG_IDLE_STATUS, p++);
AT_READ_REG(hw, REG_MDIO_CTRL, p++);
AT_READ_REG(hw, REG_SERDES_LOCK, p++);
AT_READ_REG(hw, REG_MAC_CTRL, p++);
AT_READ_REG(hw, REG_MAC_IPG_IFG, p++);
AT_READ_REG(hw, REG_MAC_STA_ADDR, p++);
AT_READ_REG(hw, REG_MAC_STA_ADDR+4, p++);
AT_READ_REG(hw, REG_RX_HASH_TABLE, p++);
AT_READ_REG(hw, REG_RX_HASH_TABLE+4, p++);
AT_READ_REG(hw, REG_RXQ_CTRL, p++);
AT_READ_REG(hw, REG_TXQ_CTRL, p++);
AT_READ_REG(hw, REG_MTU, p++);
AT_READ_REG(hw, REG_WOL_CTRL, p++);
atl1c_read_phy_reg(hw, MII_BMCR, &phy_data);
regs_buff[73] = (u32) phy_data;
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
regs_buff[74] = (u32) phy_data;
}
static int atl1c_get_eeprom_len(struct net_device *netdev)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
if (atl1c_check_eeprom_exist(&adapter->hw))
return AT_EEPROM_LEN;
else
return 0;
}
static int atl1c_get_eeprom(struct net_device *netdev,
struct ethtool_eeprom *eeprom, u8 *bytes)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
struct atl1c_hw *hw = &adapter->hw;
u32 *eeprom_buff;
int first_dword, last_dword;
int ret_val = 0;
int i;
if (eeprom->len == 0)
return -EINVAL;
if (!atl1c_check_eeprom_exist(hw)) /* not exist */
return -EINVAL;
eeprom->magic = adapter->pdev->vendor |
(adapter->pdev->device << 16);
first_dword = eeprom->offset >> 2;
last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
eeprom_buff = kmalloc(sizeof(u32) *
(last_dword - first_dword + 1), GFP_KERNEL);
if (eeprom_buff == NULL)
return -ENOMEM;
for (i = first_dword; i < last_dword; i++) {
if (!atl1c_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) {
kfree(eeprom_buff);
return -EIO;
}
}
memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3),
eeprom->len);
kfree(eeprom_buff);
return ret_val;
return 0;
}
static void atl1c_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
strncpy(drvinfo->driver, atl1c_driver_name, sizeof(drvinfo->driver));
strncpy(drvinfo->version, atl1c_driver_version,
sizeof(drvinfo->version));
strncpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
drvinfo->n_stats = 0;
drvinfo->testinfo_len = 0;
drvinfo->regdump_len = atl1c_get_regs_len(netdev);
drvinfo->eedump_len = atl1c_get_eeprom_len(netdev);
}
static void atl1c_get_wol(struct net_device *netdev,
struct ethtool_wolinfo *wol)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
wol->supported = WAKE_MAGIC | WAKE_PHY;
wol->wolopts = 0;
if (adapter->wol & AT_WUFC_EX)
wol->wolopts |= WAKE_UCAST;
if (adapter->wol & AT_WUFC_MC)
wol->wolopts |= WAKE_MCAST;
if (adapter->wol & AT_WUFC_BC)
wol->wolopts |= WAKE_BCAST;
if (adapter->wol & AT_WUFC_MAG)
wol->wolopts |= WAKE_MAGIC;
if (adapter->wol & AT_WUFC_LNKC)
wol->wolopts |= WAKE_PHY;
return;
}
static int atl1c_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE |
WAKE_MCAST | WAKE_BCAST | WAKE_MCAST))
return -EOPNOTSUPP;
/* these settings will always override what we currently have */
adapter->wol = 0;
if (wol->wolopts & WAKE_MAGIC)
adapter->wol |= AT_WUFC_MAG;
if (wol->wolopts & WAKE_PHY)
adapter->wol |= AT_WUFC_LNKC;
return 0;
}
static int atl1c_nway_reset(struct net_device *netdev)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
if (netif_running(netdev))
atl1c_reinit_locked(adapter);
return 0;
}
static struct ethtool_ops atl1c_ethtool_ops = {
.get_settings = atl1c_get_settings,
.set_settings = atl1c_set_settings,
.get_drvinfo = atl1c_get_drvinfo,
.get_regs_len = atl1c_get_regs_len,
.get_regs = atl1c_get_regs,
.get_wol = atl1c_get_wol,
.set_wol = atl1c_set_wol,
.get_msglevel = atl1c_get_msglevel,
.set_msglevel = atl1c_set_msglevel,
.nway_reset = atl1c_nway_reset,
.get_link = ethtool_op_get_link,
.get_eeprom_len = atl1c_get_eeprom_len,
.get_eeprom = atl1c_get_eeprom,
.get_tx_csum = atl1c_get_tx_csum,
.get_sg = ethtool_op_get_sg,
.set_sg = ethtool_op_set_sg,
};
void atl1c_set_ethtool_ops(struct net_device *netdev)
{
SET_ETHTOOL_OPS(netdev, &atl1c_ethtool_ops);
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -90,6 +90,7 @@ static const struct pci_device_id cxgb3_pci_tbl[] = { ...@@ -90,6 +90,7 @@ static const struct pci_device_id cxgb3_pci_tbl[] = {
CH_DEVICE(0x30, 2), /* T3B10 */ CH_DEVICE(0x30, 2), /* T3B10 */
CH_DEVICE(0x31, 3), /* T3B20 */ CH_DEVICE(0x31, 3), /* T3B20 */
CH_DEVICE(0x32, 1), /* T3B02 */ CH_DEVICE(0x32, 1), /* T3B02 */
CH_DEVICE(0x35, 6), /* T3C20-derived T3C10 */
{0,} {0,}
}; };
......
...@@ -512,6 +512,13 @@ static const struct adapter_info t3_adap_info[] = { ...@@ -512,6 +512,13 @@ static const struct adapter_info t3_adap_info[] = {
F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL,
{ S_GPIO9, S_GPIO3 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, { S_GPIO9, S_GPIO3 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
&mi1_mdio_ext_ops, "Chelsio T320"}, &mi1_mdio_ext_ops, "Chelsio T320"},
{},
{},
{1, 0,
F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO6_OEN | F_GPIO7_OEN |
F_GPIO10_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL,
{ S_GPIO9 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
&mi1_mdio_ext_ops, "Chelsio T310" },
}; };
/* /*
......
...@@ -6011,9 +6011,20 @@ static void nv_shutdown(struct pci_dev *pdev) ...@@ -6011,9 +6011,20 @@ static void nv_shutdown(struct pci_dev *pdev)
if (netif_running(dev)) if (netif_running(dev))
nv_close(dev); nv_close(dev);
nv_restore_mac_addr(pdev); /*
* Restore the MAC so a kernel started by kexec won't get confused.
* If we really go for poweroff, we must not restore the MAC,
* otherwise the MAC for WOL will be reversed at least on some boards.
*/
if (system_state != SYSTEM_POWER_OFF) {
nv_restore_mac_addr(pdev);
}
pci_disable_device(pdev); pci_disable_device(pdev);
/*
* Apparently it is not possible to reinitialise from D3 hot,
* only put the device into D3 if we really go for poweroff.
*/
if (system_state == SYSTEM_POWER_OFF) { if (system_state == SYSTEM_POWER_OFF) {
if (pci_enable_wake(pdev, PCI_D3cold, np->wolenabled)) if (pci_enable_wake(pdev, PCI_D3cold, np->wolenabled))
pci_enable_wake(pdev, PCI_D3hot, np->wolenabled); pci_enable_wake(pdev, PCI_D3hot, np->wolenabled);
......
...@@ -1175,7 +1175,7 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) ...@@ -1175,7 +1175,7 @@ static void mib_counters_update(struct mv643xx_eth_private *mp)
{ {
struct mib_counters *p = &mp->mib_counters; struct mib_counters *p = &mp->mib_counters;
spin_lock(&mp->mib_counters_lock); spin_lock_bh(&mp->mib_counters_lock);
p->good_octets_received += mib_read(mp, 0x00); p->good_octets_received += mib_read(mp, 0x00);
p->good_octets_received += (u64)mib_read(mp, 0x04) << 32; p->good_octets_received += (u64)mib_read(mp, 0x04) << 32;
p->bad_octets_received += mib_read(mp, 0x08); p->bad_octets_received += mib_read(mp, 0x08);
...@@ -1208,7 +1208,7 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) ...@@ -1208,7 +1208,7 @@ static void mib_counters_update(struct mv643xx_eth_private *mp)
p->bad_crc_event += mib_read(mp, 0x74); p->bad_crc_event += mib_read(mp, 0x74);
p->collision += mib_read(mp, 0x78); p->collision += mib_read(mp, 0x78);
p->late_collision += mib_read(mp, 0x7c); p->late_collision += mib_read(mp, 0x7c);
spin_unlock(&mp->mib_counters_lock); spin_unlock_bh(&mp->mib_counters_lock);
mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ); mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ);
} }
...@@ -1575,7 +1575,7 @@ static void mv643xx_eth_program_multicast_filter(struct net_device *dev) ...@@ -1575,7 +1575,7 @@ static void mv643xx_eth_program_multicast_filter(struct net_device *dev)
return; return;
} }
mc_spec = kmalloc(0x200, GFP_KERNEL); mc_spec = kmalloc(0x200, GFP_ATOMIC);
if (mc_spec == NULL) if (mc_spec == NULL)
goto oom; goto oom;
mc_other = mc_spec + (0x100 >> 2); mc_other = mc_spec + (0x100 >> 2);
...@@ -2216,8 +2216,6 @@ static int mv643xx_eth_stop(struct net_device *dev) ...@@ -2216,8 +2216,6 @@ static int mv643xx_eth_stop(struct net_device *dev)
wrlp(mp, INT_MASK, 0x00000000); wrlp(mp, INT_MASK, 0x00000000);
rdlp(mp, INT_MASK); rdlp(mp, INT_MASK);
del_timer_sync(&mp->mib_counters_timer);
napi_disable(&mp->napi); napi_disable(&mp->napi);
del_timer_sync(&mp->rx_oom); del_timer_sync(&mp->rx_oom);
...@@ -2229,6 +2227,7 @@ static int mv643xx_eth_stop(struct net_device *dev) ...@@ -2229,6 +2227,7 @@ static int mv643xx_eth_stop(struct net_device *dev)
port_reset(mp); port_reset(mp);
mv643xx_eth_get_stats(dev); mv643xx_eth_get_stats(dev);
mib_counters_update(mp); mib_counters_update(mp);
del_timer_sync(&mp->mib_counters_timer);
skb_queue_purge(&mp->rx_recycle); skb_queue_purge(&mp->rx_recycle);
......
...@@ -1624,7 +1624,7 @@ static int smsc911x_eeprom_send_cmd(struct smsc911x_data *pdata, u32 op) ...@@ -1624,7 +1624,7 @@ static int smsc911x_eeprom_send_cmd(struct smsc911x_data *pdata, u32 op)
do { do {
msleep(1); msleep(1);
e2cmd = smsc911x_reg_read(pdata, E2P_CMD); e2cmd = smsc911x_reg_read(pdata, E2P_CMD);
} while ((e2cmd & E2P_CMD_EPC_BUSY_) && (timeout--)); } while ((e2cmd & E2P_CMD_EPC_BUSY_) && (--timeout));
if (!timeout) { if (!timeout) {
SMSC_TRACE(DRV, "TIMED OUT"); SMSC_TRACE(DRV, "TIMED OUT");
......
...@@ -341,7 +341,7 @@ static int smsc9420_eeprom_send_cmd(struct smsc9420_pdata *pd, u32 op) ...@@ -341,7 +341,7 @@ static int smsc9420_eeprom_send_cmd(struct smsc9420_pdata *pd, u32 op)
do { do {
msleep(1); msleep(1);
e2cmd = smsc9420_reg_read(pd, E2P_CMD); e2cmd = smsc9420_reg_read(pd, E2P_CMD);
} while ((e2cmd & E2P_CMD_EPC_BUSY_) && (timeout--)); } while ((e2cmd & E2P_CMD_EPC_BUSY_) && (--timeout));
if (!timeout) { if (!timeout) {
smsc_info(HW, "TIMED OUT"); smsc_info(HW, "TIMED OUT");
...@@ -413,6 +413,7 @@ static int smsc9420_ethtool_get_eeprom(struct net_device *dev, ...@@ -413,6 +413,7 @@ static int smsc9420_ethtool_get_eeprom(struct net_device *dev,
} }
memcpy(data, &eeprom_data[eeprom->offset], len); memcpy(data, &eeprom_data[eeprom->offset], len);
eeprom->magic = SMSC9420_EEPROM_MAGIC;
eeprom->len = len; eeprom->len = len;
return 0; return 0;
} }
...@@ -423,6 +424,9 @@ static int smsc9420_ethtool_set_eeprom(struct net_device *dev, ...@@ -423,6 +424,9 @@ static int smsc9420_ethtool_set_eeprom(struct net_device *dev,
struct smsc9420_pdata *pd = netdev_priv(dev); struct smsc9420_pdata *pd = netdev_priv(dev);
int ret; int ret;
if (eeprom->magic != SMSC9420_EEPROM_MAGIC)
return -EINVAL;
smsc9420_eeprom_enable_access(pd); smsc9420_eeprom_enable_access(pd);
smsc9420_eeprom_send_cmd(pd, E2P_CMD_EPC_CMD_EWEN_); smsc9420_eeprom_send_cmd(pd, E2P_CMD_EPC_CMD_EWEN_);
ret = smsc9420_eeprom_write_location(pd, eeprom->offset, *data); ret = smsc9420_eeprom_write_location(pd, eeprom->offset, *data);
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#define LAN_REGISTER_EXTENT (0x400) #define LAN_REGISTER_EXTENT (0x400)
#define SMSC9420_EEPROM_SIZE ((u32)11) #define SMSC9420_EEPROM_SIZE ((u32)11)
#define SMSC9420_EEPROM_MAGIC (0x9420)
#define PKT_BUF_SZ (VLAN_ETH_FRAME_LEN + NET_IP_ALIGN + 4) #define PKT_BUF_SZ (VLAN_ETH_FRAME_LEN + NET_IP_ALIGN + 4)
......
...@@ -909,7 +909,7 @@ static void check_duplex(struct net_device *dev) ...@@ -909,7 +909,7 @@ static void check_duplex(struct net_device *dev)
printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d " printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d "
"negotiated capability %4.4x.\n", dev->name, "negotiated capability %4.4x.\n", dev->name,
duplex ? "full" : "half", np->phys[0], negotiated); duplex ? "full" : "half", np->phys[0], negotiated);
iowrite16(ioread16(ioaddr + MACCtrl0) | duplex ? 0x20 : 0, ioaddr + MACCtrl0); iowrite16(ioread16(ioaddr + MACCtrl0) | (duplex ? 0x20 : 0), ioaddr + MACCtrl0);
} }
} }
......
...@@ -1157,7 +1157,7 @@ static void gem_pcs_reset(struct gem *gp) ...@@ -1157,7 +1157,7 @@ static void gem_pcs_reset(struct gem *gp)
if (limit-- <= 0) if (limit-- <= 0)
break; break;
} }
if (limit <= 0) if (limit < 0)
printk(KERN_WARNING "%s: PCS reset bit would not clear.\n", printk(KERN_WARNING "%s: PCS reset bit would not clear.\n",
gp->dev->name); gp->dev->name);
} }
......
...@@ -343,7 +343,7 @@ static void lance_init_ring_dvma(struct net_device *dev) ...@@ -343,7 +343,7 @@ static void lance_init_ring_dvma(struct net_device *dev)
ib->phys_addr [5] = dev->dev_addr [4]; ib->phys_addr [5] = dev->dev_addr [4];
/* Setup the Tx ring entries */ /* Setup the Tx ring entries */
for (i = 0; i <= TX_RING_SIZE; i++) { for (i = 0; i < TX_RING_SIZE; i++) {
leptr = LANCE_ADDR(aib + libbuff_offset(tx_buf, i)); leptr = LANCE_ADDR(aib + libbuff_offset(tx_buf, i));
ib->btx_ring [i].tmd0 = leptr; ib->btx_ring [i].tmd0 = leptr;
ib->btx_ring [i].tmd1_hadr = leptr >> 16; ib->btx_ring [i].tmd1_hadr = leptr >> 16;
...@@ -399,7 +399,7 @@ static void lance_init_ring_pio(struct net_device *dev) ...@@ -399,7 +399,7 @@ static void lance_init_ring_pio(struct net_device *dev)
sbus_writeb(dev->dev_addr[4], &ib->phys_addr[5]); sbus_writeb(dev->dev_addr[4], &ib->phys_addr[5]);
/* Setup the Tx ring entries */ /* Setup the Tx ring entries */
for (i = 0; i <= TX_RING_SIZE; i++) { for (i = 0; i < TX_RING_SIZE; i++) {
leptr = libbuff_offset(tx_buf, i); leptr = libbuff_offset(tx_buf, i);
sbus_writew(leptr, &ib->btx_ring [i].tmd0); sbus_writew(leptr, &ib->btx_ring [i].tmd0);
sbus_writeb(leptr >> 16,&ib->btx_ring [i].tmd1_hadr); sbus_writeb(leptr >> 16,&ib->btx_ring [i].tmd1_hadr);
......
...@@ -2237,8 +2237,8 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) ...@@ -2237,8 +2237,8 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
phyid = phydev->drv->phy_id & phydev->drv->phy_id_mask; phyid = phydev->drv->phy_id & phydev->drv->phy_id_mask;
if (phyid != TG3_PHY_ID_BCMAC131) { if (phyid != TG3_PHY_ID_BCMAC131) {
phyid &= TG3_PHY_OUI_MASK; phyid &= TG3_PHY_OUI_MASK;
if (phyid == TG3_PHY_OUI_1 && if (phyid == TG3_PHY_OUI_1 ||
phyid == TG3_PHY_OUI_2 && phyid == TG3_PHY_OUI_2 ||
phyid == TG3_PHY_OUI_3) phyid == TG3_PHY_OUI_3)
do_low_power = true; do_low_power = true;
} }
......
...@@ -263,10 +263,11 @@ static void veth_dev_free(struct net_device *dev) ...@@ -263,10 +263,11 @@ static void veth_dev_free(struct net_device *dev)
} }
static const struct net_device_ops veth_netdev_ops = { static const struct net_device_ops veth_netdev_ops = {
.ndo_init = veth_dev_init, .ndo_init = veth_dev_init,
.ndo_open = veth_open, .ndo_open = veth_open,
.ndo_start_xmit = veth_xmit, .ndo_start_xmit = veth_xmit,
.ndo_get_stats = veth_get_stats, .ndo_get_stats = veth_get_stats,
.ndo_set_mac_address = eth_mac_addr,
}; };
static void veth_setup(struct net_device *dev) static void veth_setup(struct net_device *dev)
......
...@@ -157,7 +157,7 @@ enum { ...@@ -157,7 +157,7 @@ enum {
/* Firmware version we request when pulling the fw image file */ /* Firmware version we request when pulling the fw image file */
#define I2400M_FW_VERSION "1.3" #define I2400M_FW_VERSION "1.4"
/** /**
......
...@@ -715,6 +715,13 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode) ...@@ -715,6 +715,13 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
if (sbi->s_log_groups_per_flex) { if (sbi->s_log_groups_per_flex) {
ret2 = find_group_flex(sb, dir, &group); ret2 = find_group_flex(sb, dir, &group);
if (ret2 == -1) {
ret2 = find_group_other(sb, dir, &group);
if (ret2 == 0 && printk_ratelimit())
printk(KERN_NOTICE "ext4: find_group_flex "
"failed, fallback succeeded dir %lu\n",
dir->i_ino);
}
goto got_group; goto got_group;
} }
......
...@@ -1368,6 +1368,10 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping, ...@@ -1368,6 +1368,10 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
goto out; goto out;
} }
/* We cannot recurse into the filesystem as the transaction is already
* started */
flags |= AOP_FLAG_NOFS;
page = grab_cache_page_write_begin(mapping, index, flags); page = grab_cache_page_write_begin(mapping, index, flags);
if (!page) { if (!page) {
ext4_journal_stop(handle); ext4_journal_stop(handle);
...@@ -1377,7 +1381,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping, ...@@ -1377,7 +1381,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
*pagep = page; *pagep = page;
ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
ext4_get_block); ext4_get_block);
if (!ret && ext4_should_journal_data(inode)) { if (!ret && ext4_should_journal_data(inode)) {
ret = walk_page_buffers(handle, page_buffers(page), ret = walk_page_buffers(handle, page_buffers(page),
...@@ -2667,6 +2671,9 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, ...@@ -2667,6 +2671,9 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
ret = PTR_ERR(handle); ret = PTR_ERR(handle);
goto out; goto out;
} }
/* We cannot recurse into the filesystem as the transaction is already
* started */
flags |= AOP_FLAG_NOFS;
page = grab_cache_page_write_begin(mapping, index, flags); page = grab_cache_page_write_begin(mapping, index, flags);
if (!page) { if (!page) {
......
...@@ -485,8 +485,10 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino, ...@@ -485,8 +485,10 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
} }
} }
unlock_new_inode(inode); unlock_new_inode(inode);
} else } else {
module_put(de->owner); module_put(de->owner);
de_put(de);
}
return inode; return inode;
out_ino: out_ino:
......
...@@ -107,7 +107,7 @@ static ssize_t kpageflags_read(struct file *file, char __user *buf, ...@@ -107,7 +107,7 @@ static ssize_t kpageflags_read(struct file *file, char __user *buf,
else else
kflags = ppage->flags; kflags = ppage->flags;
uflags = kpf_copy_bit(KPF_LOCKED, PG_locked, kflags) | uflags = kpf_copy_bit(kflags, KPF_LOCKED, PG_locked) |
kpf_copy_bit(kflags, KPF_ERROR, PG_error) | kpf_copy_bit(kflags, KPF_ERROR, PG_error) |
kpf_copy_bit(kflags, KPF_REFERENCED, PG_referenced) | kpf_copy_bit(kflags, KPF_REFERENCED, PG_referenced) |
kpf_copy_bit(kflags, KPF_UPTODATE, PG_uptodate) | kpf_copy_bit(kflags, KPF_UPTODATE, PG_uptodate) |
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
*/ */
#define I2C_RETRIES 0x0701 /* number of times a device address should #define I2C_RETRIES 0x0701 /* number of times a device address should
be polled when not acknowledging */ be polled when not acknowledging */
#define I2C_TIMEOUT 0x0702 /* set timeout in jiffies - call with int */ #define I2C_TIMEOUT 0x0702 /* set timeout in units of 10 ms */
/* NOTE: Slave address is 7 or 10 bits, but 10-bit addresses /* NOTE: Slave address is 7 or 10 bits, but 10-bit addresses
* are NOT supported! (due to code brokenness) * are NOT supported! (due to code brokenness)
......
...@@ -361,7 +361,7 @@ struct i2c_adapter { ...@@ -361,7 +361,7 @@ struct i2c_adapter {
struct mutex bus_lock; struct mutex bus_lock;
struct mutex clist_lock; struct mutex clist_lock;
int timeout; int timeout; /* in jiffies */
int retries; int retries;
struct device dev; /* the adapter device */ struct device dev; /* the adapter device */
......
...@@ -210,6 +210,7 @@ static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, u16 vlan_tci) ...@@ -210,6 +210,7 @@ static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, u16 vlan_tci)
/* Move the mac addresses to the beginning of the new header. */ /* Move the mac addresses to the beginning of the new header. */
memmove(skb->data, skb->data + VLAN_HLEN, 2 * VLAN_ETH_ALEN); memmove(skb->data, skb->data + VLAN_HLEN, 2 * VLAN_ETH_ALEN);
skb->mac_header -= VLAN_HLEN;
/* first, the ethernet type */ /* first, the ethernet type */
veth->h_vlan_proto = htons(ETH_P_8021Q); veth->h_vlan_proto = htons(ETH_P_8021Q);
......
...@@ -416,15 +416,6 @@ extern void skb_over_panic(struct sk_buff *skb, int len, ...@@ -416,15 +416,6 @@ extern void skb_over_panic(struct sk_buff *skb, int len,
void *here); void *here);
extern void skb_under_panic(struct sk_buff *skb, int len, extern void skb_under_panic(struct sk_buff *skb, int len,
void *here); void *here);
extern void skb_truesize_bug(struct sk_buff *skb);
static inline void skb_truesize_check(struct sk_buff *skb)
{
int len = sizeof(struct sk_buff) + skb->len;
if (unlikely((int)skb->truesize < len))
skb_truesize_bug(skb);
}
extern int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, extern int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
int getfrag(void *from, char *to, int offset, int getfrag(void *from, char *to, int offset,
......
...@@ -41,13 +41,13 @@ static inline void pagefault_enable(void) ...@@ -41,13 +41,13 @@ static inline void pagefault_enable(void)
#ifndef ARCH_HAS_NOCACHE_UACCESS #ifndef ARCH_HAS_NOCACHE_UACCESS
static inline unsigned long __copy_from_user_inatomic_nocache(void *to, static inline unsigned long __copy_from_user_inatomic_nocache(void *to,
const void __user *from, unsigned long n) const void __user *from, unsigned long n, unsigned long total)
{ {
return __copy_from_user_inatomic(to, from, n); return __copy_from_user_inatomic(to, from, n);
} }
static inline unsigned long __copy_from_user_nocache(void *to, static inline unsigned long __copy_from_user_nocache(void *to,
const void __user *from, unsigned long n) const void __user *from, unsigned long n, unsigned long total)
{ {
return __copy_from_user(to, from, n); return __copy_from_user(to, from, n);
} }
......
...@@ -860,7 +860,6 @@ static inline void sk_mem_uncharge(struct sock *sk, int size) ...@@ -860,7 +860,6 @@ static inline void sk_mem_uncharge(struct sock *sk, int size)
static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb) static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb)
{ {
skb_truesize_check(skb);
sock_set_flag(sk, SOCK_QUEUE_SHRUNK); sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
sk->sk_wmem_queued -= skb->truesize; sk->sk_wmem_queued -= skb->truesize;
sk_mem_uncharge(sk, skb->truesize); sk_mem_uncharge(sk, skb->truesize);
......
...@@ -1816,14 +1816,14 @@ EXPORT_SYMBOL(file_remove_suid); ...@@ -1816,14 +1816,14 @@ EXPORT_SYMBOL(file_remove_suid);
static size_t __iovec_copy_from_user_inatomic(char *vaddr, static size_t __iovec_copy_from_user_inatomic(char *vaddr,
const struct iovec *iov, size_t base, size_t bytes) const struct iovec *iov, size_t base, size_t bytes)
{ {
size_t copied = 0, left = 0; size_t copied = 0, left = 0, total = bytes;
while (bytes) { while (bytes) {
char __user *buf = iov->iov_base + base; char __user *buf = iov->iov_base + base;
int copy = min(bytes, iov->iov_len - base); int copy = min(bytes, iov->iov_len - base);
base = 0; base = 0;
left = __copy_from_user_inatomic_nocache(vaddr, buf, copy); left = __copy_from_user_inatomic_nocache(vaddr, buf, copy, total);
copied += copy; copied += copy;
bytes -= copy; bytes -= copy;
vaddr += copy; vaddr += copy;
...@@ -1851,8 +1851,9 @@ size_t iov_iter_copy_from_user_atomic(struct page *page, ...@@ -1851,8 +1851,9 @@ size_t iov_iter_copy_from_user_atomic(struct page *page,
if (likely(i->nr_segs == 1)) { if (likely(i->nr_segs == 1)) {
int left; int left;
char __user *buf = i->iov->iov_base + i->iov_offset; char __user *buf = i->iov->iov_base + i->iov_offset;
left = __copy_from_user_inatomic_nocache(kaddr + offset, left = __copy_from_user_inatomic_nocache(kaddr + offset,
buf, bytes); buf, bytes, bytes);
copied = bytes - left; copied = bytes - left;
} else { } else {
copied = __iovec_copy_from_user_inatomic(kaddr + offset, copied = __iovec_copy_from_user_inatomic(kaddr + offset,
...@@ -1880,7 +1881,8 @@ size_t iov_iter_copy_from_user(struct page *page, ...@@ -1880,7 +1881,8 @@ size_t iov_iter_copy_from_user(struct page *page,
if (likely(i->nr_segs == 1)) { if (likely(i->nr_segs == 1)) {
int left; int left;
char __user *buf = i->iov->iov_base + i->iov_offset; char __user *buf = i->iov->iov_base + i->iov_offset;
left = __copy_from_user_nocache(kaddr + offset, buf, bytes);
left = __copy_from_user_nocache(kaddr + offset, buf, bytes, bytes);
copied = bytes - left; copied = bytes - left;
} else { } else {
copied = __iovec_copy_from_user_inatomic(kaddr + offset, copied = __iovec_copy_from_user_inatomic(kaddr + offset,
......
...@@ -354,7 +354,7 @@ __xip_file_write(struct file *filp, const char __user *buf, ...@@ -354,7 +354,7 @@ __xip_file_write(struct file *filp, const char __user *buf,
break; break;
copied = bytes - copied = bytes -
__copy_from_user_nocache(xip_mem + offset, buf, bytes); __copy_from_user_nocache(xip_mem + offset, buf, bytes, bytes);
if (likely(copied > 0)) { if (likely(copied > 0)) {
status = copied; status = copied;
......
...@@ -1259,6 +1259,7 @@ EXPORT_SYMBOL(vfree); ...@@ -1259,6 +1259,7 @@ EXPORT_SYMBOL(vfree);
void vunmap(const void *addr) void vunmap(const void *addr)
{ {
BUG_ON(in_interrupt()); BUG_ON(in_interrupt());
might_sleep();
__vunmap(addr, 0); __vunmap(addr, 0);
} }
EXPORT_SYMBOL(vunmap); EXPORT_SYMBOL(vunmap);
...@@ -1278,6 +1279,8 @@ void *vmap(struct page **pages, unsigned int count, ...@@ -1278,6 +1279,8 @@ void *vmap(struct page **pages, unsigned int count,
{ {
struct vm_struct *area; struct vm_struct *area;
might_sleep();
if (count > num_physpages) if (count > num_physpages)
return NULL; return NULL;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册