Merge branch 'linus' into core/rcu
This commit is contained in:
commit
cdbb92b31d
|
@ -77,7 +77,8 @@ documentation files are also added which explain how to use the feature.
|
|||
When a kernel change causes the interface that the kernel exposes to
|
||||
userspace to change, it is recommended that you send the information or
|
||||
a patch to the manual pages explaining the change to the manual pages
|
||||
maintainer at mtk.manpages@gmail.com.
|
||||
maintainer at mtk.manpages@gmail.com, and CC the list
|
||||
linux-api@vger.kernel.org.
|
||||
|
||||
Here is a list of files that are in the kernel source tree that are
|
||||
required reading:
|
||||
|
|
|
@ -67,6 +67,8 @@ kernel patches.
|
|||
|
||||
19: All new userspace interfaces are documented in Documentation/ABI/.
|
||||
See Documentation/ABI/README for more information.
|
||||
Patches that change userspace interfaces should be CCed to
|
||||
linux-api@vger.kernel.org.
|
||||
|
||||
20: Check that it all passes `make headers_check'.
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
45 -> Pinnacle PCTV DVB-T (em2870)
|
||||
46 -> Compro, VideoMate U3 (em2870) [185b:2870]
|
||||
47 -> KWorld DVB-T 305U (em2880) [eb1a:e305]
|
||||
48 -> KWorld DVB-T 310U (em2880)
|
||||
48 -> KWorld DVB-T 310U (em2880) [eb1a:e310]
|
||||
49 -> MSI DigiVox A/D (em2880) [eb1a:e310]
|
||||
50 -> MSI DigiVox A/D II (em2880) [eb1a:e320]
|
||||
51 -> Terratec Hybrid XS Secam (em2880) [0ccd:004c]
|
||||
|
|
|
@ -190,6 +190,7 @@ pac7311 093a:260f SnakeCam
|
|||
pac7311 093a:2621 PAC731x
|
||||
pac7311 093a:2624 PAC7302
|
||||
pac7311 093a:2626 Labtec 2200
|
||||
pac7311 093a:262a Webcam 300k
|
||||
zc3xx 0ac8:0302 Z-star Vimicro zc0302
|
||||
vc032x 0ac8:0321 Vimicro generic vc0321
|
||||
vc032x 0ac8:0323 Vimicro Vc0323
|
||||
|
|
|
@ -1198,9 +1198,7 @@ M: hpa@zytor.com
|
|||
S: Maintained
|
||||
|
||||
CPUSETS
|
||||
P: Paul Jackson
|
||||
P: Paul Menage
|
||||
M: pj@sgi.com
|
||||
M: menage@google.com
|
||||
L: linux-kernel@vger.kernel.org
|
||||
W: http://www.bullopensource.org/cpuset/
|
||||
|
@ -2706,6 +2704,7 @@ MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
|
|||
P: Michael Kerrisk
|
||||
M: mtk.manpages@gmail.com
|
||||
W: http://www.kernel.org/doc/man-pages
|
||||
L: linux-man@vger.kernel.org
|
||||
S: Supported
|
||||
|
||||
MARVELL LIBERTAS WIRELESS DRIVER
|
||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
|||
VERSION = 2
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 27
|
||||
EXTRAVERSION = -rc8
|
||||
EXTRAVERSION = -rc9
|
||||
NAME = Rotary Wombat
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#include <asm-generic/sections.h>
|
||||
|
||||
extern char __per_cpu_start[], __per_cpu_end[], __phys_per_cpu_start[];
|
||||
#ifdef CONFIG_SMP
|
||||
extern char __cpu0_per_cpu[];
|
||||
#endif
|
||||
extern char __start___vtop_patchlist[], __end___vtop_patchlist[];
|
||||
extern char __start___rse_patchlist[], __end___rse_patchlist[];
|
||||
extern char __start___mckinley_e9_bundles[], __end___mckinley_e9_bundles[];
|
||||
|
|
|
@ -367,16 +367,17 @@ start_ap:
|
|||
;;
|
||||
#else
|
||||
(isAP) br.few 2f
|
||||
mov r20=r19
|
||||
sub r19=r19,r18
|
||||
movl r20=__cpu0_per_cpu
|
||||
;;
|
||||
shr.u r18=r18,3
|
||||
1:
|
||||
ld8 r21=[r20],8;;
|
||||
st8[r19]=r21,8
|
||||
ld8 r21=[r19],8;;
|
||||
st8[r20]=r21,8
|
||||
adds r18=-1,r18;;
|
||||
cmp4.lt p7,p6=0,r18
|
||||
(p7) br.cond.dptk.few 1b
|
||||
mov r19=r20
|
||||
;;
|
||||
2:
|
||||
#endif
|
||||
tpa r19=r19
|
||||
|
|
|
@ -215,9 +215,6 @@ SECTIONS
|
|||
/* Per-cpu data: */
|
||||
percpu : { } :percpu
|
||||
. = ALIGN(PERCPU_PAGE_SIZE);
|
||||
#ifdef CONFIG_SMP
|
||||
. = . + PERCPU_PAGE_SIZE; /* cpu0 per-cpu space */
|
||||
#endif
|
||||
__phys_per_cpu_start = .;
|
||||
.data.percpu PERCPU_ADDR : AT(__phys_per_cpu_start - LOAD_OFFSET)
|
||||
{
|
||||
|
@ -233,6 +230,11 @@ SECTIONS
|
|||
data : { } :data
|
||||
.data : AT(ADDR(.data) - LOAD_OFFSET)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
. = ALIGN(PERCPU_PAGE_SIZE);
|
||||
__cpu0_per_cpu = .;
|
||||
. = . + PERCPU_PAGE_SIZE; /* cpu0 per-cpu space */
|
||||
#endif
|
||||
DATA_DATA
|
||||
*(.data1)
|
||||
*(.gnu.linkonce.d*)
|
||||
|
|
|
@ -163,7 +163,7 @@ per_cpu_init (void)
|
|||
* get_zeroed_page().
|
||||
*/
|
||||
if (first_time) {
|
||||
void *cpu0_data = __phys_per_cpu_start - PERCPU_PAGE_SIZE;
|
||||
void *cpu0_data = __cpu0_per_cpu;
|
||||
|
||||
first_time=0;
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ static void *per_cpu_node_setup(void *cpu_data, int node)
|
|||
|
||||
for_each_possible_early_cpu(cpu) {
|
||||
if (cpu == 0) {
|
||||
void *cpu0_data = __phys_per_cpu_start - PERCPU_PAGE_SIZE;
|
||||
void *cpu0_data = __cpu0_per_cpu;
|
||||
__per_cpu_offset[cpu] = (char*)cpu0_data -
|
||||
__per_cpu_start;
|
||||
} else if (node == node_cpuid[cpu].nid) {
|
||||
|
|
|
@ -211,6 +211,7 @@ config MIPS_MALTA
|
|||
select SYS_SUPPORTS_64BIT_KERNEL
|
||||
select SYS_SUPPORTS_BIG_ENDIAN
|
||||
select SYS_SUPPORTS_LITTLE_ENDIAN
|
||||
select SYS_SUPPORTS_MIPS_CMP if BROKEN # because SYNC_R4K is broken
|
||||
select SYS_SUPPORTS_MULTITHREADING
|
||||
select SYS_SUPPORTS_SMARTMIPS
|
||||
help
|
||||
|
@ -1403,7 +1404,6 @@ config MIPS_MT_SMTC
|
|||
depends on CPU_MIPS32_R2
|
||||
#depends on CPU_MIPS64_R2 # once there is hardware ...
|
||||
depends on SYS_SUPPORTS_MULTITHREADING
|
||||
select GENERIC_CLOCKEVENTS_BROADCAST
|
||||
select CPU_MIPSR2_IRQ_VI
|
||||
select CPU_MIPSR2_IRQ_EI
|
||||
select MIPS_MT
|
||||
|
@ -1451,32 +1451,17 @@ config MIPS_VPE_LOADER
|
|||
Includes a loader for loading an elf relocatable object
|
||||
onto another VPE and running it.
|
||||
|
||||
config MIPS_MT_SMTC_INSTANT_REPLAY
|
||||
bool "Low-latency Dispatch of Deferred SMTC IPIs"
|
||||
depends on MIPS_MT_SMTC && !PREEMPT
|
||||
default y
|
||||
help
|
||||
SMTC pseudo-interrupts between TCs are deferred and queued
|
||||
if the target TC is interrupt-inhibited (IXMT). In the first
|
||||
SMTC prototypes, these queued IPIs were serviced on return
|
||||
to user mode, or on entry into the kernel idle loop. The
|
||||
INSTANT_REPLAY option dispatches them as part of local_irq_restore()
|
||||
processing, which adds runtime overhead (hence the option to turn
|
||||
it off), but ensures that IPIs are handled promptly even under
|
||||
heavy I/O interrupt load.
|
||||
|
||||
config MIPS_MT_SMTC_IM_BACKSTOP
|
||||
bool "Use per-TC register bits as backstop for inhibited IM bits"
|
||||
depends on MIPS_MT_SMTC
|
||||
default y
|
||||
default n
|
||||
help
|
||||
To support multiple TC microthreads acting as "CPUs" within
|
||||
a VPE, VPE-wide interrupt mask bits must be specially manipulated
|
||||
during interrupt handling. To support legacy drivers and interrupt
|
||||
controller management code, SMTC has a "backstop" to track and
|
||||
if necessary restore the interrupt mask. This has some performance
|
||||
impact on interrupt service overhead. Disable it only if you know
|
||||
what you are doing.
|
||||
impact on interrupt service overhead.
|
||||
|
||||
config MIPS_MT_SMTC_IRQAFF
|
||||
bool "Support IRQ affinity API"
|
||||
|
@ -1486,10 +1471,8 @@ config MIPS_MT_SMTC_IRQAFF
|
|||
Enables SMP IRQ affinity API (/proc/irq/*/smp_affinity, etc.)
|
||||
for SMTC Linux kernel. Requires platform support, of which
|
||||
an example can be found in the MIPS kernel i8259 and Malta
|
||||
platform code. It is recommended that MIPS_MT_SMTC_INSTANT_REPLAY
|
||||
be enabled if MIPS_MT_SMTC_IRQAFF is used. Adds overhead to
|
||||
interrupt dispatch, and should be used only if you know what
|
||||
you are doing.
|
||||
platform code. Adds some overhead to interrupt dispatch, and
|
||||
should be used only if you know what you are doing.
|
||||
|
||||
config MIPS_VPE_LOADER_TOM
|
||||
bool "Load VPE program into memory hidden from linux"
|
||||
|
@ -1517,6 +1500,18 @@ config MIPS_APSP_KSPD
|
|||
"exit" syscall notifying other kernel modules the SP program is
|
||||
exiting. You probably want to say yes here.
|
||||
|
||||
config MIPS_CMP
|
||||
bool "MIPS CMP framework support"
|
||||
depends on SYS_SUPPORTS_MIPS_CMP
|
||||
select SYNC_R4K if BROKEN
|
||||
select SYS_SUPPORTS_SMP
|
||||
select SYS_SUPPORTS_SCHED_SMT if SMP
|
||||
select WEAK_ORDERING
|
||||
default n
|
||||
help
|
||||
This is a placeholder option for the GCMP work. It will need to
|
||||
be handled differently...
|
||||
|
||||
config SB1_PASS_1_WORKAROUNDS
|
||||
bool
|
||||
depends on CPU_SB1_PASS_1
|
||||
|
@ -1693,6 +1688,9 @@ config SMP
|
|||
config SMP_UP
|
||||
bool
|
||||
|
||||
config SYS_SUPPORTS_MIPS_CMP
|
||||
bool
|
||||
|
||||
config SYS_SUPPORTS_SMP
|
||||
bool
|
||||
|
||||
|
@ -1740,17 +1738,6 @@ config NR_CPUS
|
|||
performance should round up your number of processors to the next
|
||||
power of two.
|
||||
|
||||
config MIPS_CMP
|
||||
bool "MIPS CMP framework support"
|
||||
depends on SMP
|
||||
select SYNC_R4K
|
||||
select SYS_SUPPORTS_SCHED_SMT
|
||||
select WEAK_ORDERING
|
||||
default n
|
||||
help
|
||||
This is a placeholder option for the GCMP work. It will need to
|
||||
be handled differently...
|
||||
|
||||
source "kernel/time/Kconfig"
|
||||
|
||||
#
|
||||
|
|
|
@ -10,6 +10,7 @@ obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
|
|||
|
||||
obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o
|
||||
obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o
|
||||
obj-$(CONFIG_MIPS_MT_SMTC) += cevt-smtc.o
|
||||
obj-$(CONFIG_CEVT_DS1287) += cevt-ds1287.o
|
||||
obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o
|
||||
obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o
|
||||
|
|
|
@ -12,6 +12,14 @@
|
|||
|
||||
#include <asm/smtc_ipi.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/cevt-r4k.h>
|
||||
|
||||
/*
|
||||
* The SMTC Kernel for the 34K, 1004K, et. al. replaces several
|
||||
* of these routines with SMTC-specific variants.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_MIPS_MT_SMTC
|
||||
|
||||
static int mips_next_event(unsigned long delta,
|
||||
struct clock_event_device *evt)
|
||||
|
@ -19,60 +27,27 @@ static int mips_next_event(unsigned long delta,
|
|||
unsigned int cnt;
|
||||
int res;
|
||||
|
||||
#ifdef CONFIG_MIPS_MT_SMTC
|
||||
{
|
||||
unsigned long flags, vpflags;
|
||||
local_irq_save(flags);
|
||||
vpflags = dvpe();
|
||||
#endif
|
||||
cnt = read_c0_count();
|
||||
cnt += delta;
|
||||
write_c0_compare(cnt);
|
||||
res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0;
|
||||
#ifdef CONFIG_MIPS_MT_SMTC
|
||||
evpe(vpflags);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
static void mips_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
#endif /* CONFIG_MIPS_MT_SMTC */
|
||||
|
||||
void mips_set_clock_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
/* Nothing to do ... */
|
||||
}
|
||||
|
||||
static DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device);
|
||||
static int cp0_timer_irq_installed;
|
||||
DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device);
|
||||
int cp0_timer_irq_installed;
|
||||
|
||||
/*
|
||||
* Timer ack for an R4k-compatible timer of a known frequency.
|
||||
*/
|
||||
static void c0_timer_ack(void)
|
||||
{
|
||||
write_c0_compare(read_c0_compare());
|
||||
}
|
||||
#ifndef CONFIG_MIPS_MT_SMTC
|
||||
|
||||
/*
|
||||
* Possibly handle a performance counter interrupt.
|
||||
* Return true if the timer interrupt should not be checked
|
||||
*/
|
||||
static inline int handle_perf_irq(int r2)
|
||||
{
|
||||
/*
|
||||
* The performance counter overflow interrupt may be shared with the
|
||||
* timer interrupt (cp0_perfcount_irq < 0). If it is and a
|
||||
* performance counter has overflowed (perf_irq() == IRQ_HANDLED)
|
||||
* and we can't reliably determine if a counter interrupt has also
|
||||
* happened (!r2) then don't check for a timer interrupt.
|
||||
*/
|
||||
return (cp0_perfcount_irq < 0) &&
|
||||
perf_irq() == IRQ_HANDLED &&
|
||||
!r2;
|
||||
}
|
||||
|
||||
static irqreturn_t c0_compare_interrupt(int irq, void *dev_id)
|
||||
irqreturn_t c0_compare_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
const int r2 = cpu_has_mips_r2;
|
||||
struct clock_event_device *cd;
|
||||
|
@ -93,12 +68,8 @@ static irqreturn_t c0_compare_interrupt(int irq, void *dev_id)
|
|||
* interrupt. Being the paranoiacs we are we check anyway.
|
||||
*/
|
||||
if (!r2 || (read_c0_cause() & (1 << 30))) {
|
||||
c0_timer_ack();
|
||||
#ifdef CONFIG_MIPS_MT_SMTC
|
||||
if (cpu_data[cpu].vpe_id)
|
||||
goto out;
|
||||
cpu = 0;
|
||||
#endif
|
||||
/* Clear Count/Compare Interrupt */
|
||||
write_c0_compare(read_c0_compare());
|
||||
cd = &per_cpu(mips_clockevent_device, cpu);
|
||||
cd->event_handler(cd);
|
||||
}
|
||||
|
@ -107,65 +78,16 @@ out:
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction c0_compare_irqaction = {
|
||||
#endif /* Not CONFIG_MIPS_MT_SMTC */
|
||||
|
||||
struct irqaction c0_compare_irqaction = {
|
||||
.handler = c0_compare_interrupt,
|
||||
#ifdef CONFIG_MIPS_MT_SMTC
|
||||
.flags = IRQF_DISABLED,
|
||||
#else
|
||||
.flags = IRQF_DISABLED | IRQF_PERCPU,
|
||||
#endif
|
||||
.name = "timer",
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MIPS_MT_SMTC
|
||||
DEFINE_PER_CPU(struct clock_event_device, smtc_dummy_clockevent_device);
|
||||
|
||||
static void smtc_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
}
|
||||
|
||||
static void mips_broadcast(cpumask_t mask)
|
||||
{
|
||||
unsigned int cpu;
|
||||
|
||||
for_each_cpu_mask(cpu, mask)
|
||||
smtc_send_ipi(cpu, SMTC_CLOCK_TICK, 0);
|
||||
}
|
||||
|
||||
static void setup_smtc_dummy_clockevent_device(void)
|
||||
{
|
||||
//uint64_t mips_freq = mips_hpt_^frequency;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
struct clock_event_device *cd;
|
||||
|
||||
cd = &per_cpu(smtc_dummy_clockevent_device, cpu);
|
||||
|
||||
cd->name = "SMTC";
|
||||
cd->features = CLOCK_EVT_FEAT_DUMMY;
|
||||
|
||||
/* Calculate the min / max delta */
|
||||
cd->mult = 0; //div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32);
|
||||
cd->shift = 0; //32;
|
||||
cd->max_delta_ns = 0; //clockevent_delta2ns(0x7fffffff, cd);
|
||||
cd->min_delta_ns = 0; //clockevent_delta2ns(0x30, cd);
|
||||
|
||||
cd->rating = 200;
|
||||
cd->irq = 17; //-1;
|
||||
// if (cpu)
|
||||
// cd->cpumask = CPU_MASK_ALL; // cpumask_of_cpu(cpu);
|
||||
// else
|
||||
cd->cpumask = cpumask_of_cpu(cpu);
|
||||
|
||||
cd->set_mode = smtc_set_mode;
|
||||
|
||||
cd->broadcast = mips_broadcast;
|
||||
|
||||
clockevents_register_device(cd);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void mips_event_handler(struct clock_event_device *dev)
|
||||
void mips_event_handler(struct clock_event_device *dev)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -177,7 +99,23 @@ static int c0_compare_int_pending(void)
|
|||
return (read_c0_cause() >> cp0_compare_irq) & 0x100;
|
||||
}
|
||||
|
||||
static int c0_compare_int_usable(void)
|
||||
/*
|
||||
* Compare interrupt can be routed and latched outside the core,
|
||||
* so a single execution hazard barrier may not be enough to give
|
||||
* it time to clear as seen in the Cause register. 4 time the
|
||||
* pipeline depth seems reasonably conservative, and empirically
|
||||
* works better in configurations with high CPU/bus clock ratios.
|
||||
*/
|
||||
|
||||
#define compare_change_hazard() \
|
||||
do { \
|
||||
irq_disable_hazard(); \
|
||||
irq_disable_hazard(); \
|
||||
irq_disable_hazard(); \
|
||||
irq_disable_hazard(); \
|
||||
} while (0)
|
||||
|
||||
int c0_compare_int_usable(void)
|
||||
{
|
||||
unsigned int delta;
|
||||
unsigned int cnt;
|
||||
|
@ -187,7 +125,7 @@ static int c0_compare_int_usable(void)
|
|||
*/
|
||||
if (c0_compare_int_pending()) {
|
||||
write_c0_compare(read_c0_count());
|
||||
irq_disable_hazard();
|
||||
compare_change_hazard();
|
||||
if (c0_compare_int_pending())
|
||||
return 0;
|
||||
}
|
||||
|
@ -196,7 +134,7 @@ static int c0_compare_int_usable(void)
|
|||
cnt = read_c0_count();
|
||||
cnt += delta;
|
||||
write_c0_compare(cnt);
|
||||
irq_disable_hazard();
|
||||
compare_change_hazard();
|
||||
if ((int)(read_c0_count() - cnt) < 0)
|
||||
break;
|
||||
/* increase delta if the timer was already expired */
|
||||
|
@ -205,11 +143,12 @@ static int c0_compare_int_usable(void)
|
|||
while ((int)(read_c0_count() - cnt) <= 0)
|
||||
; /* Wait for expiry */
|
||||
|
||||
compare_change_hazard();
|
||||
if (!c0_compare_int_pending())
|
||||
return 0;
|
||||
|
||||
write_c0_compare(read_c0_count());
|
||||
irq_disable_hazard();
|
||||
compare_change_hazard();
|
||||
if (c0_compare_int_pending())
|
||||
return 0;
|
||||
|
||||
|
@ -219,6 +158,8 @@ static int c0_compare_int_usable(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_MIPS_MT_SMTC
|
||||
|
||||
int __cpuinit mips_clockevent_init(void)
|
||||
{
|
||||
uint64_t mips_freq = mips_hpt_frequency;
|
||||
|
@ -229,17 +170,6 @@ int __cpuinit mips_clockevent_init(void)
|
|||
if (!cpu_has_counter || !mips_hpt_frequency)
|
||||
return -ENXIO;
|
||||
|
||||
#ifdef CONFIG_MIPS_MT_SMTC
|
||||
setup_smtc_dummy_clockevent_device();
|
||||
|
||||
/*
|
||||
* On SMTC we only register VPE0's compare interrupt as clockevent
|
||||
* device.
|
||||
*/
|
||||
if (cpu)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if (!c0_compare_int_usable())
|
||||
return -ENXIO;
|
||||
|
||||
|
@ -265,13 +195,9 @@ int __cpuinit mips_clockevent_init(void)
|
|||
|
||||
cd->rating = 300;
|
||||
cd->irq = irq;
|
||||
#ifdef CONFIG_MIPS_MT_SMTC
|
||||
cd->cpumask = CPU_MASK_ALL;
|
||||
#else
|
||||
cd->cpumask = cpumask_of_cpu(cpu);
|
||||
#endif
|
||||
cd->set_next_event = mips_next_event;
|
||||
cd->set_mode = mips_set_mode;
|
||||
cd->set_mode = mips_set_clock_mode;
|
||||
cd->event_handler = mips_event_handler;
|
||||
|
||||
clockevents_register_device(cd);
|
||||
|
@ -281,12 +207,9 @@ int __cpuinit mips_clockevent_init(void)
|
|||
|
||||
cp0_timer_irq_installed = 1;
|
||||
|
||||
#ifdef CONFIG_MIPS_MT_SMTC
|
||||
#define CPUCTR_IMASKBIT (0x100 << cp0_compare_irq)
|
||||
setup_irq_smtc(irq, &c0_compare_irqaction, CPUCTR_IMASKBIT);
|
||||
#else
|
||||
setup_irq(irq, &c0_compare_irqaction);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* Not CONFIG_MIPS_MT_SMTC */
|
||||
|
|
|
@ -0,0 +1,321 @@
|
|||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2007 MIPS Technologies, Inc.
|
||||
* Copyright (C) 2007 Ralf Baechle <ralf@linux-mips.org>
|
||||
* Copyright (C) 2008 Kevin D. Kissell, Paralogos sarl
|
||||
*/
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/percpu.h>
|
||||
|
||||
#include <asm/smtc_ipi.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/cevt-r4k.h>
|
||||
|
||||
/*
|
||||
* Variant clock event timer support for SMTC on MIPS 34K, 1004K
|
||||
* or other MIPS MT cores.
|
||||
*
|
||||
* Notes on SMTC Support:
|
||||
*
|
||||
* SMTC has multiple microthread TCs pretending to be Linux CPUs.
|
||||
* But there's only one Count/Compare pair per VPE, and Compare
|
||||
* interrupts are taken opportunisitically by available TCs
|
||||
* bound to the VPE with the Count register. The new timer
|
||||
* framework provides for global broadcasts, but we really
|
||||
* want VPE-level multicasts for best behavior. So instead
|
||||
* of invoking the high-level clock-event broadcast code,
|
||||
* this version of SMTC support uses the historical SMTC
|
||||
* multicast mechanisms "under the hood", appearing to the
|
||||
* generic clock layer as if the interrupts are per-CPU.
|
||||
*
|
||||
* The approach taken here is to maintain a set of NR_CPUS
|
||||
* virtual timers, and track which "CPU" needs to be alerted
|
||||
* at each event.
|
||||
*
|
||||
* It's unlikely that we'll see a MIPS MT core with more than
|
||||
* 2 VPEs, but we *know* that we won't need to handle more
|
||||
* VPEs than we have "CPUs". So NCPUs arrays of NCPUs elements
|
||||
* is always going to be overkill, but always going to be enough.
|
||||
*/
|
||||
|
||||
unsigned long smtc_nexttime[NR_CPUS][NR_CPUS];
|
||||
static int smtc_nextinvpe[NR_CPUS];
|
||||
|
||||
/*
|
||||
* Timestamps stored are absolute values to be programmed
|
||||
* into Count register. Valid timestamps will never be zero.
|
||||
* If a Zero Count value is actually calculated, it is converted
|
||||
* to be a 1, which will introduce 1 or two CPU cycles of error
|
||||
* roughly once every four billion events, which at 1000 HZ means
|
||||
* about once every 50 days. If that's actually a problem, one
|
||||
* could alternate squashing 0 to 1 and to -1.
|
||||
*/
|
||||
|
||||
#define MAKEVALID(x) (((x) == 0L) ? 1L : (x))
|
||||
#define ISVALID(x) ((x) != 0L)
|
||||
|
||||
/*
|
||||
* Time comparison is subtle, as it's really truncated
|
||||
* modular arithmetic.
|
||||
*/
|
||||
|
||||
#define IS_SOONER(a, b, reference) \
|
||||
(((a) - (unsigned long)(reference)) < ((b) - (unsigned long)(reference)))
|
||||
|
||||
/*
|
||||
* CATCHUP_INCREMENT, used when the function falls behind the counter.
|
||||
* Could be an increasing function instead of a constant;
|
||||
*/
|
||||
|
||||
#define CATCHUP_INCREMENT 64
|
||||
|
||||
static int mips_next_event(unsigned long delta,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int mtflags;
|
||||
unsigned long timestamp, reference, previous;
|
||||
unsigned long nextcomp = 0L;
|
||||
int vpe = current_cpu_data.vpe_id;
|
||||
int cpu = smp_processor_id();
|
||||
local_irq_save(flags);
|
||||
mtflags = dmt();
|
||||
|
||||
/*
|
||||
* Maintain the per-TC virtual timer
|
||||
* and program the per-VPE shared Count register
|
||||
* as appropriate here...
|
||||
*/
|
||||
reference = (unsigned long)read_c0_count();
|
||||
timestamp = MAKEVALID(reference + delta);
|
||||
/*
|
||||
* To really model the clock, we have to catch the case
|
||||
* where the current next-in-VPE timestamp is the old
|
||||
* timestamp for the calling CPE, but the new value is
|
||||
* in fact later. In that case, we have to do a full
|
||||
* scan and discover the new next-in-VPE CPU id and
|
||||
* timestamp.
|
||||
*/
|
||||
previous = smtc_nexttime[vpe][cpu];
|
||||
if (cpu == smtc_nextinvpe[vpe] && ISVALID(previous)
|
||||
&& IS_SOONER(previous, timestamp, reference)) {
|
||||
int i;
|
||||
int soonest = cpu;
|
||||
|
||||
/*
|
||||
* Update timestamp array here, so that new
|
||||
* value gets considered along with those of
|
||||
* other virtual CPUs on the VPE.
|
||||
*/
|
||||
smtc_nexttime[vpe][cpu] = timestamp;
|
||||
for_each_online_cpu(i) {
|
||||
if (ISVALID(smtc_nexttime[vpe][i])
|
||||
&& IS_SOONER(smtc_nexttime[vpe][i],
|
||||
smtc_nexttime[vpe][soonest], reference)) {
|
||||
soonest = i;
|
||||
}
|
||||
}
|
||||
smtc_nextinvpe[vpe] = soonest;
|
||||
nextcomp = smtc_nexttime[vpe][soonest];
|
||||
/*
|
||||
* Otherwise, we don't have to process the whole array rank,
|
||||
* we just have to see if the event horizon has gotten closer.
|
||||
*/
|
||||
} else {
|
||||
if (!ISVALID(smtc_nexttime[vpe][smtc_nextinvpe[vpe]]) ||
|
||||
IS_SOONER(timestamp,
|
||||
smtc_nexttime[vpe][smtc_nextinvpe[vpe]], reference)) {
|
||||
smtc_nextinvpe[vpe] = cpu;
|
||||
nextcomp = timestamp;
|
||||
}
|
||||
/*
|
||||
* Since next-in-VPE may me the same as the executing
|
||||
* virtual CPU, we update the array *after* checking
|
||||
* its value.
|
||||
*/
|
||||
smtc_nexttime[vpe][cpu] = timestamp;
|
||||
}
|
||||
|
||||
/*
|
||||
* It may be that, in fact, we don't need to update Compare,
|
||||
* but if we do, we want to make sure we didn't fall into
|
||||
* a crack just behind Count.
|
||||
*/
|
||||
if (ISVALID(nextcomp)) {
|
||||
write_c0_compare(nextcomp);
|
||||
ehb();
|
||||
/*
|
||||
* We never return an error, we just make sure
|
||||
* that we trigger the handlers as quickly as
|
||||
* we can if we fell behind.
|
||||
*/
|
||||
while ((nextcomp - (unsigned long)read_c0_count())
|
||||
> (unsigned long)LONG_MAX) {
|
||||
nextcomp += CATCHUP_INCREMENT;
|
||||
write_c0_compare(nextcomp);
|
||||
ehb();
|
||||
}
|
||||
}
|
||||
emt(mtflags);
|
||||
local_irq_restore(flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void smtc_distribute_timer(int vpe)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int mtflags;
|
||||
int cpu;
|
||||
struct clock_event_device *cd;
|
||||
unsigned long nextstamp = 0L;
|
||||
unsigned long reference;
|
||||
|
||||
|
||||
repeat:
|
||||
for_each_online_cpu(cpu) {
|
||||
/*
|
||||
* Find virtual CPUs within the current VPE who have
|
||||
* unserviced timer requests whose time is now past.
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
mtflags = dmt();
|
||||
if (cpu_data[cpu].vpe_id == vpe &&
|
||||
ISVALID(smtc_nexttime[vpe][cpu])) {
|
||||
reference = (unsigned long)read_c0_count();
|
||||
if ((smtc_nexttime[vpe][cpu] - reference)
|
||||
> (unsigned long)LONG_MAX) {
|
||||
smtc_nexttime[vpe][cpu] = 0L;
|
||||
emt(mtflags);
|
||||
local_irq_restore(flags);
|
||||
/*
|
||||
* We don't send IPIs to ourself.
|
||||
*/
|
||||
if (cpu != smp_processor_id()) {
|
||||
smtc_send_ipi(cpu, SMTC_CLOCK_TICK, 0);
|
||||
} else {
|
||||
cd = &per_cpu(mips_clockevent_device, cpu);
|
||||
cd->event_handler(cd);
|
||||
}
|
||||
} else {
|
||||
/* Local to VPE but Valid Time not yet reached. */
|
||||
if (!ISVALID(nextstamp) ||
|
||||
IS_SOONER(smtc_nexttime[vpe][cpu], nextstamp,
|
||||
reference)) {
|
||||
smtc_nextinvpe[vpe] = cpu;
|
||||
nextstamp = smtc_nexttime[vpe][cpu];
|
||||
}
|
||||
emt(mtflags);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
} else {
|
||||
emt(mtflags);
|
||||
local_irq_restore(flags);
|
||||
|
||||
}
|
||||
}
|
||||
/* Reprogram for interrupt at next soonest timestamp for VPE */
|
||||
if (ISVALID(nextstamp)) {
|
||||
write_c0_compare(nextstamp);
|
||||
ehb();
|
||||
if ((nextstamp - (unsigned long)read_c0_count())
|
||||
> (unsigned long)LONG_MAX)
|
||||
goto repeat;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
irqreturn_t c0_compare_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
/* If we're running SMTC, we've got MIPS MT and therefore MIPS32R2 */
|
||||
handle_perf_irq(1);
|
||||
|
||||
if (read_c0_cause() & (1 << 30)) {
|
||||
/* Clear Count/Compare Interrupt */
|
||||
write_c0_compare(read_c0_compare());
|
||||
smtc_distribute_timer(cpu_data[cpu].vpe_id);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
int __cpuinit mips_clockevent_init(void)
|
||||
{
|
||||
uint64_t mips_freq = mips_hpt_frequency;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
struct clock_event_device *cd;
|
||||
unsigned int irq;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
if (!cpu_has_counter || !mips_hpt_frequency)
|
||||
return -ENXIO;
|
||||
if (cpu == 0) {
|
||||
for (i = 0; i < num_possible_cpus(); i++) {
|
||||
smtc_nextinvpe[i] = 0;
|
||||
for (j = 0; j < num_possible_cpus(); j++)
|
||||
smtc_nexttime[i][j] = 0L;
|
||||
}
|
||||
/*
|
||||
* SMTC also can't have the usablility test
|
||||
* run by secondary TCs once Compare is in use.
|
||||
*/
|
||||
if (!c0_compare_int_usable())
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* With vectored interrupts things are getting platform specific.
|
||||
* get_c0_compare_int is a hook to allow a platform to return the
|
||||
* interrupt number of it's liking.
|
||||
*/
|
||||
irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
|
||||
if (get_c0_compare_int)
|
||||
irq = get_c0_compare_int();
|
||||
|
||||
cd = &per_cpu(mips_clockevent_device, cpu);
|
||||
|
||||
cd->name = "MIPS";
|
||||
cd->features = CLOCK_EVT_FEAT_ONESHOT;
|
||||
|
||||
/* Calculate the min / max delta */
|
||||
cd->mult = div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32);
|
||||
cd->shift = 32;
|
||||
cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
|
||||
cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
|
||||
|
||||
cd->rating = 300;
|
||||
cd->irq = irq;
|
||||
cd->cpumask = cpumask_of_cpu(cpu);
|
||||
cd->set_next_event = mips_next_event;
|
||||
cd->set_mode = mips_set_clock_mode;
|
||||
cd->event_handler = mips_event_handler;
|
||||
|
||||
clockevents_register_device(cd);
|
||||
|
||||
/*
|
||||
* On SMTC we only want to do the data structure
|
||||
* initialization and IRQ setup once.
|
||||
*/
|
||||
if (cpu)
|
||||
return 0;
|
||||
/*
|
||||
* And we need the hwmask associated with the c0_compare
|
||||
* vector to be initialized.
|
||||
*/
|
||||
irq_hwmask[irq] = (0x100 << cp0_compare_irq);
|
||||
if (cp0_timer_irq_installed)
|
||||
return 0;
|
||||
|
||||
cp0_timer_irq_installed = 1;
|
||||
|
||||
setup_irq(irq, &c0_compare_irqaction);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -54,14 +54,18 @@ extern void r4k_wait(void);
|
|||
* interrupt is requested" restriction in the MIPS32/MIPS64 architecture makes
|
||||
* using this version a gamble.
|
||||
*/
|
||||
static void r4k_wait_irqoff(void)
|
||||
void r4k_wait_irqoff(void)
|
||||
{
|
||||
local_irq_disable();
|
||||
if (!need_resched())
|
||||
__asm__(" .set mips3 \n"
|
||||
__asm__(" .set push \n"
|
||||
" .set mips3 \n"
|
||||
" wait \n"
|
||||
" .set mips0 \n");
|
||||
" .set pop \n");
|
||||
local_irq_enable();
|
||||
__asm__(" .globl __pastwait \n"
|
||||
"__pastwait: \n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -79,11 +79,6 @@ FEXPORT(syscall_exit)
|
|||
|
||||
FEXPORT(restore_all) # restore full frame
|
||||
#ifdef CONFIG_MIPS_MT_SMTC
|
||||
/* Detect and execute deferred IPI "interrupts" */
|
||||
LONG_L s0, TI_REGS($28)
|
||||
LONG_S sp, TI_REGS($28)
|
||||
jal deferred_smtc_ipi
|
||||
LONG_S s0, TI_REGS($28)
|
||||
#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
|
||||
/* Re-arm any temporarily masked interrupts not explicitly "acked" */
|
||||
mfc0 v0, CP0_TCSTATUS
|
||||
|
@ -112,6 +107,11 @@ FEXPORT(restore_all) # restore full frame
|
|||
xor t0, t0, t3
|
||||
mtc0 t0, CP0_TCCONTEXT
|
||||
#endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */
|
||||
/* Detect and execute deferred IPI "interrupts" */
|
||||
LONG_L s0, TI_REGS($28)
|
||||
LONG_S sp, TI_REGS($28)
|
||||
jal deferred_smtc_ipi
|
||||
LONG_S s0, TI_REGS($28)
|
||||
#endif /* CONFIG_MIPS_MT_SMTC */
|
||||
.set noat
|
||||
RESTORE_TEMP
|
||||
|
|
|
@ -282,8 +282,8 @@ NESTED(except_vec_vi_handler, 0, sp)
|
|||
and t0, a0, t1
|
||||
#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
|
||||
mfc0 t2, CP0_TCCONTEXT
|
||||
or t0, t0, t2
|
||||
mtc0 t0, CP0_TCCONTEXT
|
||||
or t2, t0, t2
|
||||
mtc0 t2, CP0_TCCONTEXT
|
||||
#endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */
|
||||
xor t1, t1, t0
|
||||
mtc0 t1, CP0_STATUS
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <asm/irqflags.h>
|
||||
#include <asm/regdef.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable-bits.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/stackframe.h>
|
||||
|
||||
|
|
|
@ -159,7 +159,7 @@ __setup("fpaff=", fpaff_thresh);
|
|||
/*
|
||||
* FPU Use Factor empirically derived from experiments on 34K
|
||||
*/
|
||||
#define FPUSEFACTOR 333
|
||||
#define FPUSEFACTOR 2000
|
||||
|
||||
static __init int mt_fp_affinity_init(void)
|
||||
{
|
||||
|
|
|
@ -55,7 +55,7 @@ void __noreturn cpu_idle(void)
|
|||
while (1) {
|
||||
tick_nohz_stop_sched_tick(1);
|
||||
while (!need_resched()) {
|
||||
#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
|
||||
#ifdef CONFIG_MIPS_MT_SMTC
|
||||
extern void smtc_idle_loop_hook(void);
|
||||
|
||||
smtc_idle_loop_hook();
|
||||
|
@ -145,19 +145,18 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
|
|||
*/
|
||||
p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1);
|
||||
childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
|
||||
|
||||
#ifdef CONFIG_MIPS_MT_SMTC
|
||||
/*
|
||||
* SMTC restores TCStatus after Status, and the CU bits
|
||||
* are aliased there.
|
||||
*/
|
||||
childregs->cp0_tcstatus &= ~(ST0_CU2|ST0_CU1);
|
||||
#endif
|
||||
clear_tsk_thread_flag(p, TIF_USEDFPU);
|
||||
|
||||
#ifdef CONFIG_MIPS_MT_FPAFF
|
||||
clear_tsk_thread_flag(p, TIF_FPUBOUND);
|
||||
|
||||
/*
|
||||
* FPU affinity support is cleaner if we track the
|
||||
* user-visible CPU affinity from the very beginning.
|
||||
* The generic cpus_allowed mask will already have
|
||||
* been copied from the parent before copy_thread
|
||||
* is invoked.
|
||||
*/
|
||||
p->thread.user_cpus_allowed = p->cpus_allowed;
|
||||
#endif /* CONFIG_MIPS_MT_FPAFF */
|
||||
|
||||
if (clone_flags & CLONE_SETTLS)
|
||||
|
|
|
@ -238,7 +238,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
|||
case FPC_EIR: { /* implementation / version register */
|
||||
unsigned int flags;
|
||||
#ifdef CONFIG_MIPS_MT_SMTC
|
||||
unsigned int irqflags;
|
||||
unsigned long irqflags;
|
||||
unsigned int mtflags;
|
||||
#endif /* CONFIG_MIPS_MT_SMTC */
|
||||
|
||||
|
|
|
@ -1,4 +1,21 @@
|
|||
/* Copyright (C) 2004 Mips Technologies, Inc */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright (C) 2004 Mips Technologies, Inc
|
||||
* Copyright (C) 2008 Kevin D. Kissell
|
||||
*/
|
||||
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/kernel.h>
|
||||
|
@ -21,7 +38,6 @@
|
|||
#include <asm/time.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/smtc.h>
|
||||
#include <asm/smtc_ipi.h>
|
||||
#include <asm/smtc_proc.h>
|
||||
|
||||
/*
|
||||
|
@ -58,11 +74,6 @@ unsigned long irq_hwmask[NR_IRQS];
|
|||
|
||||
asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
|
||||
|
||||
/*
|
||||
* Clock interrupt "latch" buffers, per "CPU"
|
||||
*/
|
||||
|
||||
static atomic_t ipi_timer_latch[NR_CPUS];
|
||||
|
||||
/*
|
||||
* Number of InterProcessor Interrupt (IPI) message buffers to allocate
|
||||
|
@ -70,7 +81,7 @@ static atomic_t ipi_timer_latch[NR_CPUS];
|
|||
|
||||
#define IPIBUF_PER_CPU 4
|
||||
|
||||
static struct smtc_ipi_q IPIQ[NR_CPUS];
|
||||
struct smtc_ipi_q IPIQ[NR_CPUS];
|
||||
static struct smtc_ipi_q freeIPIq;
|
||||
|
||||
|
||||
|
@ -282,7 +293,7 @@ static void smtc_configure_tlb(void)
|
|||
* phys_cpu_present_map and the logical/physical mappings.
|
||||
*/
|
||||
|
||||
int __init mipsmt_build_cpu_map(int start_cpu_slot)
|
||||
int __init smtc_build_cpu_map(int start_cpu_slot)
|
||||
{
|
||||
int i, ntcs;
|
||||
|
||||
|
@ -325,7 +336,12 @@ static void smtc_tc_setup(int vpe, int tc, int cpu)
|
|||
write_tc_c0_tcstatus((read_tc_c0_tcstatus()
|
||||
& ~(TCSTATUS_TKSU | TCSTATUS_DA | TCSTATUS_IXMT))
|
||||
| TCSTATUS_A);
|
||||
write_tc_c0_tccontext(0);
|
||||
/*
|
||||
* TCContext gets an offset from the base of the IPIQ array
|
||||
* to be used in low-level code to detect the presence of
|
||||
* an active IPI queue
|
||||
*/
|
||||
write_tc_c0_tccontext((sizeof(struct smtc_ipi_q) * cpu) << 16);
|
||||
/* Bind tc to vpe */
|
||||
write_tc_c0_tcbind(vpe);
|
||||
/* In general, all TCs should have the same cpu_data indications */
|
||||
|
@ -336,10 +352,18 @@ static void smtc_tc_setup(int vpe, int tc, int cpu)
|
|||
cpu_data[cpu].options &= ~MIPS_CPU_FPU;
|
||||
cpu_data[cpu].vpe_id = vpe;
|
||||
cpu_data[cpu].tc_id = tc;
|
||||
/* Multi-core SMTC hasn't been tested, but be prepared */
|
||||
cpu_data[cpu].core = (read_vpe_c0_ebase() >> 1) & 0xff;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tweak to get Count registes in as close a sync as possible.
|
||||
* Value seems good for 34K-class cores.
|
||||
*/
|
||||
|
||||
void mipsmt_prepare_cpus(void)
|
||||
#define CP0_SKEW 8
|
||||
|
||||
void smtc_prepare_cpus(int cpus)
|
||||
{
|
||||
int i, vpe, tc, ntc, nvpe, tcpervpe[NR_CPUS], slop, cpu;
|
||||
unsigned long flags;
|
||||
|
@ -363,13 +387,13 @@ void mipsmt_prepare_cpus(void)
|
|||
IPIQ[i].head = IPIQ[i].tail = NULL;
|
||||
spin_lock_init(&IPIQ[i].lock);
|
||||
IPIQ[i].depth = 0;
|
||||
atomic_set(&ipi_timer_latch[i], 0);
|
||||
}
|
||||
|
||||
/* cpu_data index starts at zero */
|
||||
cpu = 0;
|
||||
cpu_data[cpu].vpe_id = 0;
|
||||
cpu_data[cpu].tc_id = 0;
|
||||
cpu_data[cpu].core = (read_c0_ebase() >> 1) & 0xff;
|
||||
cpu++;
|
||||
|
||||
/* Report on boot-time options */
|
||||
|
@ -484,7 +508,8 @@ void mipsmt_prepare_cpus(void)
|
|||
write_vpe_c0_compare(0);
|
||||
/* Propagate Config7 */
|
||||
write_vpe_c0_config7(read_c0_config7());
|
||||
write_vpe_c0_count(read_c0_count());
|
||||
write_vpe_c0_count(read_c0_count() + CP0_SKEW);
|
||||
ehb();
|
||||
}
|
||||
/* enable multi-threading within VPE */
|
||||
write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() | VPECONTROL_TE);
|
||||
|
@ -556,7 +581,7 @@ void mipsmt_prepare_cpus(void)
|
|||
void __cpuinit smtc_boot_secondary(int cpu, struct task_struct *idle)
|
||||
{
|
||||
extern u32 kernelsp[NR_CPUS];
|
||||
long flags;
|
||||
unsigned long flags;
|
||||
int mtflags;
|
||||
|
||||
LOCK_MT_PRA();
|
||||
|
@ -585,24 +610,22 @@ void __cpuinit smtc_boot_secondary(int cpu, struct task_struct *idle)
|
|||
|
||||
void smtc_init_secondary(void)
|
||||
{
|
||||
/*
|
||||
* Start timer on secondary VPEs if necessary.
|
||||
* plat_timer_setup has already have been invoked by init/main
|
||||
* on "boot" TC. Like per_cpu_trap_init() hack, this assumes that
|
||||
* SMTC init code assigns TCs consdecutively and in ascending order
|
||||
* to across available VPEs.
|
||||
*/
|
||||
if (((read_c0_tcbind() & TCBIND_CURTC) != 0) &&
|
||||
((read_c0_tcbind() & TCBIND_CURVPE)
|
||||
!= cpu_data[smp_processor_id() - 1].vpe_id)){
|
||||
write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ);
|
||||
}
|
||||
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
void smtc_smp_finish(void)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
/*
|
||||
* Lowest-numbered CPU per VPE starts a clock tick.
|
||||
* Like per_cpu_trap_init() hack, this assumes that
|
||||
* SMTC init code assigns TCs consdecutively and
|
||||
* in ascending order across available VPEs.
|
||||
*/
|
||||
if (cpu > 0 && (cpu_data[cpu].vpe_id != cpu_data[cpu - 1].vpe_id))
|
||||
write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ);
|
||||
|
||||
printk("TC %d going on-line as CPU %d\n",
|
||||
cpu_data[smp_processor_id()].tc_id, smp_processor_id());
|
||||
}
|
||||
|
@ -753,8 +776,10 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
|
|||
{
|
||||
int tcstatus;
|
||||
struct smtc_ipi *pipi;
|
||||
long flags;
|
||||
unsigned long flags;
|
||||
int mtflags;
|
||||
unsigned long tcrestart;
|
||||
extern void r4k_wait_irqoff(void), __pastwait(void);
|
||||
|
||||
if (cpu == smp_processor_id()) {
|
||||
printk("Cannot Send IPI to self!\n");
|
||||
|
@ -771,8 +796,6 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
|
|||
pipi->arg = (void *)action;
|
||||
pipi->dest = cpu;
|
||||
if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
|
||||
if (type == SMTC_CLOCK_TICK)
|
||||
atomic_inc(&ipi_timer_latch[cpu]);
|
||||
/* If not on same VPE, enqueue and send cross-VPE interrupt */
|
||||
smtc_ipi_nq(&IPIQ[cpu], pipi);
|
||||
LOCK_CORE_PRA();
|
||||
|
@ -800,22 +823,29 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
|
|||
|
||||
if ((tcstatus & TCSTATUS_IXMT) != 0) {
|
||||
/*
|
||||
* Spin-waiting here can deadlock,
|
||||
* so we queue the message for the target TC.
|
||||
* If we're in the the irq-off version of the wait
|
||||
* loop, we need to force exit from the wait and
|
||||
* do a direct post of the IPI.
|
||||
*/
|
||||
if (cpu_wait == r4k_wait_irqoff) {
|
||||
tcrestart = read_tc_c0_tcrestart();
|
||||
if (tcrestart >= (unsigned long)r4k_wait_irqoff
|
||||
&& tcrestart < (unsigned long)__pastwait) {
|
||||
write_tc_c0_tcrestart(__pastwait);
|
||||
tcstatus &= ~TCSTATUS_IXMT;
|
||||
write_tc_c0_tcstatus(tcstatus);
|
||||
goto postdirect;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Otherwise we queue the message for the target TC
|
||||
* to pick up when he does a local_irq_restore()
|
||||
*/
|
||||
write_tc_c0_tchalt(0);
|
||||
UNLOCK_CORE_PRA();
|
||||
/* Try to reduce redundant timer interrupt messages */
|
||||
if (type == SMTC_CLOCK_TICK) {
|
||||
if (atomic_postincrement(&ipi_timer_latch[cpu])!=0){
|
||||
smtc_ipi_nq(&freeIPIq, pipi);
|
||||
return;
|
||||
}
|
||||
}
|
||||
smtc_ipi_nq(&IPIQ[cpu], pipi);
|
||||
} else {
|
||||
if (type == SMTC_CLOCK_TICK)
|
||||
atomic_inc(&ipi_timer_latch[cpu]);
|
||||
postdirect:
|
||||
post_direct_ipi(cpu, pipi);
|
||||
write_tc_c0_tchalt(0);
|
||||
UNLOCK_CORE_PRA();
|
||||
|
@ -883,7 +913,7 @@ static void ipi_call_interrupt(void)
|
|||
smp_call_function_interrupt();
|
||||
}
|
||||
|
||||
DECLARE_PER_CPU(struct clock_event_device, smtc_dummy_clockevent_device);
|
||||
DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device);
|
||||
|
||||
void ipi_decode(struct smtc_ipi *pipi)
|
||||
{
|
||||
|
@ -891,20 +921,13 @@ void ipi_decode(struct smtc_ipi *pipi)
|
|||
struct clock_event_device *cd;
|
||||
void *arg_copy = pipi->arg;
|
||||
int type_copy = pipi->type;
|
||||
int ticks;
|
||||
|
||||
smtc_ipi_nq(&freeIPIq, pipi);
|
||||
switch (type_copy) {
|
||||
case SMTC_CLOCK_TICK:
|
||||
irq_enter();
|
||||
kstat_this_cpu.irqs[MIPS_CPU_IRQ_BASE + 1]++;
|
||||
cd = &per_cpu(smtc_dummy_clockevent_device, cpu);
|
||||
ticks = atomic_read(&ipi_timer_latch[cpu]);
|
||||
atomic_sub(ticks, &ipi_timer_latch[cpu]);
|
||||
while (ticks) {
|
||||
cd->event_handler(cd);
|
||||
ticks--;
|
||||
}
|
||||
cd = &per_cpu(mips_clockevent_device, cpu);
|
||||
cd->event_handler(cd);
|
||||
irq_exit();
|
||||
break;
|
||||
|
||||
|
@ -937,24 +960,48 @@ void ipi_decode(struct smtc_ipi *pipi)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Similar to smtc_ipi_replay(), but invoked from context restore,
|
||||
* so it reuses the current exception frame rather than set up a
|
||||
* new one with self_ipi.
|
||||
*/
|
||||
|
||||
void deferred_smtc_ipi(void)
|
||||
{
|
||||
struct smtc_ipi *pipi;
|
||||
unsigned long flags;
|
||||
/* DEBUG */
|
||||
int q = smp_processor_id();
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
/*
|
||||
* Test is not atomic, but much faster than a dequeue,
|
||||
* and the vast majority of invocations will have a null queue.
|
||||
* If irq_disabled when this was called, then any IPIs queued
|
||||
* after we test last will be taken on the next irq_enable/restore.
|
||||
* If interrupts were enabled, then any IPIs added after the
|
||||
* last test will be taken directly.
|
||||
*/
|
||||
if (IPIQ[q].head != NULL) {
|
||||
while((pipi = smtc_ipi_dq(&IPIQ[q])) != NULL) {
|
||||
/* ipi_decode() should be called with interrupts off */
|
||||
local_irq_save(flags);
|
||||
|
||||
while (IPIQ[cpu].head != NULL) {
|
||||
struct smtc_ipi_q *q = &IPIQ[cpu];
|
||||
struct smtc_ipi *pipi;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* It may be possible we'll come in with interrupts
|
||||
* already enabled.
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
|
||||
spin_lock(&q->lock);
|
||||
pipi = __smtc_ipi_dq(q);
|
||||
spin_unlock(&q->lock);
|
||||
if (pipi != NULL)
|
||||
ipi_decode(pipi);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
/*
|
||||
* The use of the __raw_local restore isn't
|
||||
* as obviously necessary here as in smtc_ipi_replay(),
|
||||
* but it's more efficient, given that we're already
|
||||
* running down the IPI queue.
|
||||
*/
|
||||
__raw_local_irq_restore(flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -975,7 +1022,7 @@ static irqreturn_t ipi_interrupt(int irq, void *dev_idm)
|
|||
struct smtc_ipi *pipi;
|
||||
unsigned long tcstatus;
|
||||
int sent;
|
||||
long flags;
|
||||
unsigned long flags;
|
||||
unsigned int mtflags;
|
||||
unsigned int vpflags;
|
||||
|
||||
|
@ -1066,55 +1113,53 @@ static void setup_cross_vpe_interrupts(unsigned int nvpe)
|
|||
|
||||
/*
|
||||
* SMTC-specific hacks invoked from elsewhere in the kernel.
|
||||
*
|
||||
* smtc_ipi_replay is called from raw_local_irq_restore which is only ever
|
||||
* called with interrupts disabled. We do rely on interrupts being disabled
|
||||
* here because using spin_lock_irqsave()/spin_unlock_irqrestore() would
|
||||
* result in a recursive call to raw_local_irq_restore().
|
||||
*/
|
||||
|
||||
static void __smtc_ipi_replay(void)
|
||||
/*
|
||||
* smtc_ipi_replay is called from raw_local_irq_restore
|
||||
*/
|
||||
|
||||
void smtc_ipi_replay(void)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
/*
|
||||
* To the extent that we've ever turned interrupts off,
|
||||
* we may have accumulated deferred IPIs. This is subtle.
|
||||
* If we use the smtc_ipi_qdepth() macro, we'll get an
|
||||
* exact number - but we'll also disable interrupts
|
||||
* and create a window of failure where a new IPI gets
|
||||
* queued after we test the depth but before we re-enable
|
||||
* interrupts. So long as IXMT never gets set, however,
|
||||
* we should be OK: If we pick up something and dispatch
|
||||
* it here, that's great. If we see nothing, but concurrent
|
||||
* with this operation, another TC sends us an IPI, IXMT
|
||||
* is clear, and we'll handle it as a real pseudo-interrupt
|
||||
* and not a pseudo-pseudo interrupt.
|
||||
* and not a pseudo-pseudo interrupt. The important thing
|
||||
* is to do the last check for queued message *after* the
|
||||
* re-enabling of interrupts.
|
||||
*/
|
||||
if (IPIQ[cpu].depth > 0) {
|
||||
while (1) {
|
||||
struct smtc_ipi_q *q = &IPIQ[cpu];
|
||||
struct smtc_ipi *pipi;
|
||||
extern void self_ipi(struct smtc_ipi *);
|
||||
while (IPIQ[cpu].head != NULL) {
|
||||
struct smtc_ipi_q *q = &IPIQ[cpu];
|
||||
struct smtc_ipi *pipi;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&q->lock);
|
||||
pipi = __smtc_ipi_dq(q);
|
||||
spin_unlock(&q->lock);
|
||||
if (!pipi)
|
||||
break;
|
||||
/*
|
||||
* It's just possible we'll come in with interrupts
|
||||
* already enabled.
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
|
||||
spin_lock(&q->lock);
|
||||
pipi = __smtc_ipi_dq(q);
|
||||
spin_unlock(&q->lock);
|
||||
/*
|
||||
** But use a raw restore here to avoid recursion.
|
||||
*/
|
||||
__raw_local_irq_restore(flags);
|
||||
|
||||
if (pipi) {
|
||||
self_ipi(pipi);
|
||||
smtc_cpu_stats[cpu].selfipis++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void smtc_ipi_replay(void)
|
||||
{
|
||||
raw_local_irq_disable();
|
||||
__smtc_ipi_replay();
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(smtc_ipi_replay);
|
||||
|
||||
void smtc_idle_loop_hook(void)
|
||||
|
@ -1193,40 +1238,13 @@ void smtc_idle_loop_hook(void)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that we limit outstanding timer IPIs, check for hung TC
|
||||
*/
|
||||
for (tc = 0; tc < NR_CPUS; tc++) {
|
||||
/* Don't check ourself - we'll dequeue IPIs just below */
|
||||
if ((tc != smp_processor_id()) &&
|
||||
atomic_read(&ipi_timer_latch[tc]) > timerq_limit) {
|
||||
if (clock_hang_reported[tc] == 0) {
|
||||
pdb_msg += sprintf(pdb_msg,
|
||||
"TC %d looks hung with timer latch at %d\n",
|
||||
tc, atomic_read(&ipi_timer_latch[tc]));
|
||||
clock_hang_reported[tc]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
emt(mtflags);
|
||||
local_irq_restore(flags);
|
||||
if (pdb_msg != &id_ho_db_msg[0])
|
||||
printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg);
|
||||
#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */
|
||||
|
||||
/*
|
||||
* Replay any accumulated deferred IPIs. If "Instant Replay"
|
||||
* is in use, there should never be any.
|
||||
*/
|
||||
#ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
__smtc_ipi_replay();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
#endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */
|
||||
smtc_ipi_replay();
|
||||
}
|
||||
|
||||
void smtc_soft_dump(void)
|
||||
|
@ -1242,10 +1260,6 @@ void smtc_soft_dump(void)
|
|||
printk("%d: %ld\n", i, smtc_cpu_stats[i].selfipis);
|
||||
}
|
||||
smtc_ipi_qdump();
|
||||
printk("Timer IPI Backlogs:\n");
|
||||
for (i=0; i < NR_CPUS; i++) {
|
||||
printk("%d: %d\n", i, atomic_read(&ipi_timer_latch[i]));
|
||||
}
|
||||
printk("%d Recoveries of \"stolen\" FPU\n",
|
||||
atomic_read(&smtc_fpu_recoveries));
|
||||
}
|
||||
|
|
|
@ -825,8 +825,10 @@ static void mt_ase_fp_affinity(void)
|
|||
if (cpus_intersects(current->cpus_allowed, mt_fpu_cpumask)) {
|
||||
cpumask_t tmask;
|
||||
|
||||
cpus_and(tmask, current->thread.user_cpus_allowed,
|
||||
mt_fpu_cpumask);
|
||||
current->thread.user_cpus_allowed
|
||||
= current->cpus_allowed;
|
||||
cpus_and(tmask, current->cpus_allowed,
|
||||
mt_fpu_cpumask);
|
||||
set_cpus_allowed(current, tmask);
|
||||
set_thread_flag(TIF_FPUBOUND);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,6 @@ obj-$(CONFIG_EARLY_PRINTK) += malta-console.o
|
|||
obj-$(CONFIG_PCI) += malta-pci.o
|
||||
|
||||
# FIXME FIXME FIXME
|
||||
obj-$(CONFIG_MIPS_MT_SMTC) += malta_smtc.o
|
||||
obj-$(CONFIG_MIPS_MT_SMTC) += malta-smtc.o
|
||||
|
||||
EXTRA_CFLAGS += -Werror
|
||||
|
|
|
@ -84,12 +84,17 @@ static void msmtc_cpus_done(void)
|
|||
|
||||
static void __init msmtc_smp_setup(void)
|
||||
{
|
||||
mipsmt_build_cpu_map(0);
|
||||
/*
|
||||
* we won't get the definitive value until
|
||||
* we've run smtc_prepare_cpus later, but
|
||||
* we would appear to need an upper bound now.
|
||||
*/
|
||||
smp_num_siblings = smtc_build_cpu_map(0);
|
||||
}
|
||||
|
||||
static void __init msmtc_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
mipsmt_prepare_cpus();
|
||||
smtc_prepare_cpus(max_cpus);
|
||||
}
|
||||
|
||||
struct plat_smp_ops msmtc_smp_ops = {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
obj-y := setup.o rtc_xicor1241.o rtc_m41t81.o
|
||||
obj-y := platform.o setup.o rtc_xicor1241.o \
|
||||
rtc_m41t81.o
|
||||
|
||||
obj-$(CONFIG_I2C_BOARDINFO) += swarm-i2c.o
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/ata_platform.h>
|
||||
|
||||
#include <asm/sibyte/board.h>
|
||||
#include <asm/sibyte/sb1250_genbus.h>
|
||||
#include <asm/sibyte/sb1250_regs.h>
|
||||
|
||||
#if defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_LITTLESUR)
|
||||
|
||||
#define DRV_NAME "pata-swarm"
|
||||
|
||||
#define SWARM_IDE_SHIFT 5
|
||||
#define SWARM_IDE_BASE 0x1f0
|
||||
#define SWARM_IDE_CTRL 0x3f6
|
||||
|
||||
static struct resource swarm_pata_resource[] = {
|
||||
{
|
||||
.name = "Swarm GenBus IDE",
|
||||
.flags = IORESOURCE_MEM,
|
||||
}, {
|
||||
.name = "Swarm GenBus IDE",
|
||||
.flags = IORESOURCE_MEM,
|
||||
}, {
|
||||
.name = "Swarm GenBus IDE",
|
||||
.flags = IORESOURCE_IRQ,
|
||||
.start = K_INT_GB_IDE,
|
||||
.end = K_INT_GB_IDE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct pata_platform_info pata_platform_data = {
|
||||
.ioport_shift = SWARM_IDE_SHIFT,
|
||||
};
|
||||
|
||||
static struct platform_device swarm_pata_device = {
|
||||
.name = "pata_platform",
|
||||
.id = -1,
|
||||
.resource = swarm_pata_resource,
|
||||
.num_resources = ARRAY_SIZE(swarm_pata_resource),
|
||||
.dev = {
|
||||
.platform_data = &pata_platform_data,
|
||||
.coherent_dma_mask = ~0, /* grumble */
|
||||
},
|
||||
};
|
||||
|
||||
static int __init swarm_pata_init(void)
|
||||
{
|
||||
u8 __iomem *base;
|
||||
phys_t offset, size;
|
||||
struct resource *r;
|
||||
|
||||
if (!SIBYTE_HAVE_IDE)
|
||||
return -ENODEV;
|
||||
|
||||
base = ioremap(A_IO_EXT_BASE, 0x800);
|
||||
offset = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS));
|
||||
size = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, IDE_CS));
|
||||
iounmap(base);
|
||||
|
||||
offset = G_IO_START_ADDR(offset) << S_IO_ADDRBASE;
|
||||
size = (G_IO_MULT_SIZE(size) + 1) << S_IO_REGSIZE;
|
||||
if (offset < A_PHYS_GENBUS || offset >= A_PHYS_GENBUS_END) {
|
||||
pr_info(DRV_NAME ": PATA interface at GenBus disabled\n");
|
||||
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
pr_info(DRV_NAME ": PATA interface at GenBus slot %i\n", IDE_CS);
|
||||
|
||||
r = swarm_pata_resource;
|
||||
r[0].start = offset + (SWARM_IDE_BASE << SWARM_IDE_SHIFT);
|
||||
r[0].end = offset + ((SWARM_IDE_BASE + 8) << SWARM_IDE_SHIFT) - 1;
|
||||
r[1].start = offset + (SWARM_IDE_CTRL << SWARM_IDE_SHIFT);
|
||||
r[1].end = offset + ((SWARM_IDE_CTRL + 1) << SWARM_IDE_SHIFT) - 1;
|
||||
|
||||
return platform_device_register(&swarm_pata_device);
|
||||
}
|
||||
|
||||
device_initcall(swarm_pata_init);
|
||||
|
||||
#endif /* defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_LITTLESUR) */
|
|
@ -20,22 +20,8 @@ EXPORT_SYMBOL(__mn10300_irq_enabled_epsw);
|
|||
atomic_t irq_err_count;
|
||||
|
||||
/*
|
||||
* MN10300 INTC controller operations
|
||||
* MN10300 interrupt controller operations
|
||||
*/
|
||||
static void mn10300_cpupic_disable(unsigned int irq)
|
||||
{
|
||||
u16 tmp = GxICR(irq);
|
||||
GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT;
|
||||
tmp = GxICR(irq);
|
||||
}
|
||||
|
||||
static void mn10300_cpupic_enable(unsigned int irq)
|
||||
{
|
||||
u16 tmp = GxICR(irq);
|
||||
GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE;
|
||||
tmp = GxICR(irq);
|
||||
}
|
||||
|
||||
static void mn10300_cpupic_ack(unsigned int irq)
|
||||
{
|
||||
u16 tmp;
|
||||
|
@ -58,28 +44,56 @@ static void mn10300_cpupic_mask_ack(unsigned int irq)
|
|||
}
|
||||
|
||||
static void mn10300_cpupic_unmask(unsigned int irq)
|
||||
{
|
||||
u16 tmp = GxICR(irq);
|
||||
GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
|
||||
tmp = GxICR(irq);
|
||||
}
|
||||
|
||||
static void mn10300_cpupic_end(unsigned int irq)
|
||||
{
|
||||
u16 tmp = GxICR(irq);
|
||||
GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE;
|
||||
tmp = GxICR(irq);
|
||||
}
|
||||
|
||||
static struct irq_chip mn10300_cpu_pic = {
|
||||
.name = "cpu",
|
||||
.disable = mn10300_cpupic_disable,
|
||||
.enable = mn10300_cpupic_enable,
|
||||
static void mn10300_cpupic_unmask_clear(unsigned int irq)
|
||||
{
|
||||
/* the MN10300 PIC latches its interrupt request bit, even after the
|
||||
* device has ceased to assert its interrupt line and the interrupt
|
||||
* channel has been disabled in the PIC, so for level-triggered
|
||||
* interrupts we need to clear the request bit when we re-enable */
|
||||
u16 tmp = GxICR(irq);
|
||||
GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
|
||||
tmp = GxICR(irq);
|
||||
}
|
||||
|
||||
/*
|
||||
* MN10300 PIC level-triggered IRQ handling.
|
||||
*
|
||||
* The PIC has no 'ACK' function per se. It is possible to clear individual
|
||||
* channel latches, but each latch relatches whether or not the channel is
|
||||
* masked, so we need to clear the latch when we unmask the channel.
|
||||
*
|
||||
* Also for this reason, we don't supply an ack() op (it's unused anyway if
|
||||
* mask_ack() is provided), and mask_ack() just masks.
|
||||
*/
|
||||
static struct irq_chip mn10300_cpu_pic_level = {
|
||||
.name = "cpu_l",
|
||||
.disable = mn10300_cpupic_mask,
|
||||
.enable = mn10300_cpupic_unmask_clear,
|
||||
.ack = NULL,
|
||||
.mask = mn10300_cpupic_mask,
|
||||
.mask_ack = mn10300_cpupic_mask,
|
||||
.unmask = mn10300_cpupic_unmask_clear,
|
||||
};
|
||||
|
||||
/*
|
||||
* MN10300 PIC edge-triggered IRQ handling.
|
||||
*
|
||||
* We use the latch clearing function of the PIC as the 'ACK' function.
|
||||
*/
|
||||
static struct irq_chip mn10300_cpu_pic_edge = {
|
||||
.name = "cpu_e",
|
||||
.disable = mn10300_cpupic_mask,
|
||||
.enable = mn10300_cpupic_unmask,
|
||||
.ack = mn10300_cpupic_ack,
|
||||
.mask = mn10300_cpupic_mask,
|
||||
.mask_ack = mn10300_cpupic_mask_ack,
|
||||
.unmask = mn10300_cpupic_unmask,
|
||||
.end = mn10300_cpupic_end,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -114,7 +128,8 @@ void set_intr_level(int irq, u16 level)
|
|||
*/
|
||||
void set_intr_postackable(int irq)
|
||||
{
|
||||
set_irq_handler(irq, handle_level_irq);
|
||||
set_irq_chip_and_handler(irq, &mn10300_cpu_pic_level,
|
||||
handle_level_irq);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -126,8 +141,12 @@ void __init init_IRQ(void)
|
|||
|
||||
for (irq = 0; irq < NR_IRQS; irq++)
|
||||
if (irq_desc[irq].chip == &no_irq_type)
|
||||
set_irq_chip_and_handler(irq, &mn10300_cpu_pic,
|
||||
handle_edge_irq);
|
||||
/* due to the PIC latching interrupt requests, even
|
||||
* when the IRQ is disabled, IRQ_PENDING is superfluous
|
||||
* and we can use handle_level_irq() for edge-triggered
|
||||
* interrupts */
|
||||
set_irq_chip_and_handler(irq, &mn10300_cpu_pic_edge,
|
||||
handle_level_irq);
|
||||
unit_init_IRQ();
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ void __init unit_init_IRQ(void)
|
|||
switch (GET_XIRQ_TRIGGER(extnum)) {
|
||||
case XIRQ_TRIGGER_HILEVEL:
|
||||
case XIRQ_TRIGGER_LOWLEVEL:
|
||||
set_irq_handler(XIRQ2IRQ(extnum), handle_level_irq);
|
||||
set_intr_postackable(XIRQ2IRQ(extnum));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -52,7 +52,7 @@ void __init unit_init_IRQ(void)
|
|||
switch (GET_XIRQ_TRIGGER(extnum)) {
|
||||
case XIRQ_TRIGGER_HILEVEL:
|
||||
case XIRQ_TRIGGER_LOWLEVEL:
|
||||
set_irq_handler(XIRQ2IRQ(extnum), handle_level_irq);
|
||||
set_intr_postackable(XIRQ2IRQ(extnum));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -133,61 +133,61 @@
|
|||
reg = <0x00007400 0x00000400>;
|
||||
big-endian;
|
||||
};
|
||||
};
|
||||
|
||||
pci@1000 {
|
||||
device_type = "pci";
|
||||
compatible = "tsi109-pci", "tsi108-pci";
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <0x00001000 0x00001000>;
|
||||
bus-range = <0x0 0x0>;
|
||||
/*----------------------------------------------------+
|
||||
| PCI memory range.
|
||||
| 01 denotes I/O space
|
||||
| 02 denotes 32-bit memory space
|
||||
+----------------------------------------------------*/
|
||||
ranges = <0x02000000 0x00000000 0x40000000 0x40000000 0x00000000 0x10000000
|
||||
0x01000000 0x00000000 0x00000000 0x7e000000 0x00000000 0x00010000>;
|
||||
clock-frequency = <133333332>;
|
||||
interrupt-parent = <&MPIC>;
|
||||
pci@c0001000 {
|
||||
device_type = "pci";
|
||||
compatible = "tsi109-pci", "tsi108-pci";
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <0xc0001000 0x00001000>;
|
||||
bus-range = <0x0 0x0>;
|
||||
/*----------------------------------------------------+
|
||||
| PCI memory range.
|
||||
| 01 denotes I/O space
|
||||
| 02 denotes 32-bit memory space
|
||||
+----------------------------------------------------*/
|
||||
ranges = <0x02000000 0x00000000 0x40000000 0x40000000 0x00000000 0x10000000
|
||||
0x01000000 0x00000000 0x00000000 0x7e000000 0x00000000 0x00010000>;
|
||||
clock-frequency = <133333332>;
|
||||
interrupt-parent = <&MPIC>;
|
||||
interrupts = <0x17 0x2>;
|
||||
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
|
||||
/*----------------------------------------------------+
|
||||
| The INTA, INTB, INTC, INTD are shared.
|
||||
+----------------------------------------------------*/
|
||||
interrupt-map = <
|
||||
0x800 0x0 0x0 0x1 &RT0 0x24 0x0
|
||||
0x800 0x0 0x0 0x2 &RT0 0x25 0x0
|
||||
0x800 0x0 0x0 0x3 &RT0 0x26 0x0
|
||||
0x800 0x0 0x0 0x4 &RT0 0x27 0x0
|
||||
|
||||
0x1000 0x0 0x0 0x1 &RT0 0x25 0x0
|
||||
0x1000 0x0 0x0 0x2 &RT0 0x26 0x0
|
||||
0x1000 0x0 0x0 0x3 &RT0 0x27 0x0
|
||||
0x1000 0x0 0x0 0x4 &RT0 0x24 0x0
|
||||
|
||||
0x1800 0x0 0x0 0x1 &RT0 0x26 0x0
|
||||
0x1800 0x0 0x0 0x2 &RT0 0x27 0x0
|
||||
0x1800 0x0 0x0 0x3 &RT0 0x24 0x0
|
||||
0x1800 0x0 0x0 0x4 &RT0 0x25 0x0
|
||||
|
||||
0x2000 0x0 0x0 0x1 &RT0 0x27 0x0
|
||||
0x2000 0x0 0x0 0x2 &RT0 0x24 0x0
|
||||
0x2000 0x0 0x0 0x3 &RT0 0x25 0x0
|
||||
0x2000 0x0 0x0 0x4 &RT0 0x26 0x0
|
||||
>;
|
||||
|
||||
RT0: router@1180 {
|
||||
device_type = "pic-router";
|
||||
interrupt-controller;
|
||||
big-endian;
|
||||
clock-frequency = <0>;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <0x17 0x2>;
|
||||
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
|
||||
/*----------------------------------------------------+
|
||||
| The INTA, INTB, INTC, INTD are shared.
|
||||
+----------------------------------------------------*/
|
||||
interrupt-map = <
|
||||
0x800 0x0 0x0 0x1 &RT0 0x24 0x0
|
||||
0x800 0x0 0x0 0x2 &RT0 0x25 0x0
|
||||
0x800 0x0 0x0 0x3 &RT0 0x26 0x0
|
||||
0x800 0x0 0x0 0x4 &RT0 0x27 0x0
|
||||
|
||||
0x1000 0x0 0x0 0x1 &RT0 0x25 0x0
|
||||
0x1000 0x0 0x0 0x2 &RT0 0x26 0x0
|
||||
0x1000 0x0 0x0 0x3 &RT0 0x27 0x0
|
||||
0x1000 0x0 0x0 0x4 &RT0 0x24 0x0
|
||||
|
||||
0x1800 0x0 0x0 0x1 &RT0 0x26 0x0
|
||||
0x1800 0x0 0x0 0x2 &RT0 0x27 0x0
|
||||
0x1800 0x0 0x0 0x3 &RT0 0x24 0x0
|
||||
0x1800 0x0 0x0 0x4 &RT0 0x25 0x0
|
||||
|
||||
0x2000 0x0 0x0 0x1 &RT0 0x27 0x0
|
||||
0x2000 0x0 0x0 0x2 &RT0 0x24 0x0
|
||||
0x2000 0x0 0x0 0x3 &RT0 0x25 0x0
|
||||
0x2000 0x0 0x0 0x4 &RT0 0x26 0x0
|
||||
>;
|
||||
|
||||
RT0: router@1180 {
|
||||
device_type = "pic-router";
|
||||
interrupt-controller;
|
||||
big-endian;
|
||||
clock-frequency = <0>;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <0x17 0x2>;
|
||||
interrupt-parent = <&MPIC>;
|
||||
};
|
||||
interrupt-parent = <&MPIC>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -34,11 +34,7 @@
|
|||
#include <asm/smp.h>
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
/* this is used for software suspend, and that shuts down
|
||||
* CPUs even while the system is still booting... */
|
||||
#define cpu_should_die() (cpu_is_offline(smp_processor_id()) && \
|
||||
(system_state == SYSTEM_RUNNING \
|
||||
|| system_state == SYSTEM_BOOTING))
|
||||
#define cpu_should_die() cpu_is_offline(smp_processor_id())
|
||||
#else
|
||||
#define cpu_should_die() 0
|
||||
#endif
|
||||
|
|
|
@ -219,11 +219,21 @@ static void __devinit quirk_final_uli5249(struct pci_dev *dev)
|
|||
int i;
|
||||
u8 *dummy;
|
||||
struct pci_bus *bus = dev->bus;
|
||||
resource_size_t end = 0;
|
||||
|
||||
for (i = PCI_BRIDGE_RESOURCES; i < PCI_BRIDGE_RESOURCES+3; i++) {
|
||||
unsigned long flags = pci_resource_flags(dev, i);
|
||||
if ((flags & (IORESOURCE_MEM|IORESOURCE_PREFETCH)) == IORESOURCE_MEM)
|
||||
end = pci_resource_end(dev, i);
|
||||
}
|
||||
|
||||
for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
|
||||
if ((bus->resource[i]) &&
|
||||
(bus->resource[i]->flags & IORESOURCE_MEM)) {
|
||||
dummy = ioremap(bus->resource[i]->end - 3, 0x4);
|
||||
if (bus->resource[i]->end == end)
|
||||
dummy = ioremap(bus->resource[i]->start, 0x4);
|
||||
else
|
||||
dummy = ioremap(bus->resource[i]->end - 3, 0x4);
|
||||
if (dummy) {
|
||||
in_8(dummy);
|
||||
iounmap(dummy);
|
||||
|
|
|
@ -169,6 +169,8 @@ void init_cpu_timer(void)
|
|||
|
||||
static void clock_comparator_interrupt(__u16 code)
|
||||
{
|
||||
if (S390_lowcore.clock_comparator == -1ULL)
|
||||
set_clock_comparator(S390_lowcore.clock_comparator);
|
||||
}
|
||||
|
||||
static void etr_timing_alert(struct etr_irq_parm *);
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
/*
|
||||
* arch/s390/lib/delay.c
|
||||
* Precise Delay Loops for S390
|
||||
*
|
||||
* S390 version
|
||||
* Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
|
||||
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
|
||||
*
|
||||
* Derived from "arch/i386/lib/delay.c"
|
||||
* Copyright (C) 1993 Linus Torvalds
|
||||
* Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
|
||||
* Copyright IBM Corp. 1999,2008
|
||||
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
|
||||
* Heiko Carstens <heiko.carstens@de.ibm.com>,
|
||||
*/
|
||||
|
||||
#include <linux/sched.h>
|
||||
|
@ -29,30 +24,31 @@ void __delay(unsigned long loops)
|
|||
asm volatile("0: brct %0,0b" : : "d" ((loops/2) + 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Waits for 'usecs' microseconds using the TOD clock comparator.
|
||||
*/
|
||||
void __udelay(unsigned long usecs)
|
||||
static void __udelay_disabled(unsigned long usecs)
|
||||
{
|
||||
u64 end, time, old_cc = 0;
|
||||
unsigned long flags, cr0, mask, dummy;
|
||||
int irq_context;
|
||||
unsigned long mask, cr0, cr0_saved;
|
||||
u64 clock_saved;
|
||||
|
||||
irq_context = in_interrupt();
|
||||
if (!irq_context)
|
||||
local_bh_disable();
|
||||
local_irq_save(flags);
|
||||
if (raw_irqs_disabled_flags(flags)) {
|
||||
old_cc = local_tick_disable();
|
||||
S390_lowcore.clock_comparator = -1ULL;
|
||||
__ctl_store(cr0, 0, 0);
|
||||
dummy = (cr0 & 0xffff00e0) | 0x00000800;
|
||||
__ctl_load(dummy , 0, 0);
|
||||
mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
|
||||
} else
|
||||
mask = psw_kernel_bits | PSW_MASK_WAIT |
|
||||
PSW_MASK_EXT | PSW_MASK_IO;
|
||||
clock_saved = local_tick_disable();
|
||||
set_clock_comparator(get_clock() + ((u64) usecs << 12));
|
||||
__ctl_store(cr0_saved, 0, 0);
|
||||
cr0 = (cr0_saved & 0xffff00e0) | 0x00000800;
|
||||
__ctl_load(cr0 , 0, 0);
|
||||
mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
|
||||
trace_hardirqs_on();
|
||||
__load_psw_mask(mask);
|
||||
local_irq_disable();
|
||||
__ctl_load(cr0_saved, 0, 0);
|
||||
local_tick_enable(clock_saved);
|
||||
set_clock_comparator(S390_lowcore.clock_comparator);
|
||||
}
|
||||
|
||||
static void __udelay_enabled(unsigned long usecs)
|
||||
{
|
||||
unsigned long mask;
|
||||
u64 end, time;
|
||||
|
||||
mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT | PSW_MASK_IO;
|
||||
end = get_clock() + ((u64) usecs << 12);
|
||||
do {
|
||||
time = end < S390_lowcore.clock_comparator ?
|
||||
|
@ -62,13 +58,37 @@ void __udelay(unsigned long usecs)
|
|||
__load_psw_mask(mask);
|
||||
local_irq_disable();
|
||||
} while (get_clock() < end);
|
||||
|
||||
if (raw_irqs_disabled_flags(flags)) {
|
||||
__ctl_load(cr0, 0, 0);
|
||||
local_tick_enable(old_cc);
|
||||
}
|
||||
if (!irq_context)
|
||||
_local_bh_enable();
|
||||
set_clock_comparator(S390_lowcore.clock_comparator);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Waits for 'usecs' microseconds using the TOD clock comparator.
|
||||
*/
|
||||
void __udelay(unsigned long usecs)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
preempt_disable();
|
||||
local_irq_save(flags);
|
||||
if (in_irq()) {
|
||||
__udelay_disabled(usecs);
|
||||
goto out;
|
||||
}
|
||||
if (in_softirq()) {
|
||||
if (raw_irqs_disabled_flags(flags))
|
||||
__udelay_disabled(usecs);
|
||||
else
|
||||
__udelay_enabled(usecs);
|
||||
goto out;
|
||||
}
|
||||
if (raw_irqs_disabled_flags(flags)) {
|
||||
local_bh_disable();
|
||||
__udelay_disabled(usecs);
|
||||
_local_bh_enable();
|
||||
goto out;
|
||||
}
|
||||
__udelay_enabled(usecs);
|
||||
out:
|
||||
local_irq_restore(flags);
|
||||
preempt_enable();
|
||||
}
|
||||
|
|
|
@ -492,7 +492,7 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym))
|
|||
continue;
|
||||
}
|
||||
sh_symtab = sec_symtab->symtab;
|
||||
sym_strtab = sec->link->strtab;
|
||||
sym_strtab = sec_symtab->link->strtab;
|
||||
for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
|
||||
Elf32_Rel *rel;
|
||||
Elf32_Sym *sym;
|
||||
|
|
|
@ -1603,6 +1603,14 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {
|
|||
* is not connected at all. Force ignoring BIOS IRQ0 pin2
|
||||
* override in that cases.
|
||||
*/
|
||||
{
|
||||
.callback = dmi_ignore_irq0_timer_override,
|
||||
.ident = "HP nx6115 laptop",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6115"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = dmi_ignore_irq0_timer_override,
|
||||
.ident = "HP NX6125 laptop",
|
||||
|
@ -1619,6 +1627,14 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {
|
|||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = dmi_ignore_irq0_timer_override,
|
||||
.ident = "HP 6715b laptop",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6715b"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -834,7 +834,7 @@ static int __init enable_mtrr_cleanup_setup(char *str)
|
|||
enable_mtrr_cleanup = 1;
|
||||
return 0;
|
||||
}
|
||||
early_param("enble_mtrr_cleanup", enable_mtrr_cleanup_setup);
|
||||
early_param("enable_mtrr_cleanup", enable_mtrr_cleanup_setup);
|
||||
|
||||
struct var_mtrr_state {
|
||||
unsigned long range_startk;
|
||||
|
|
|
@ -455,12 +455,7 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
|
|||
return NOTIFY_DONE;
|
||||
|
||||
case DIE_NMI_IPI:
|
||||
if (atomic_read(&kgdb_active) != -1) {
|
||||
/* KGDB CPU roundup */
|
||||
kgdb_nmicallback(raw_smp_processor_id(), regs);
|
||||
was_in_debug_nmi[raw_smp_processor_id()] = 1;
|
||||
touch_nmi_watchdog();
|
||||
}
|
||||
/* Just ignore, we will handle the roundup on DIE_NMI. */
|
||||
return NOTIFY_DONE;
|
||||
|
||||
case DIE_NMIUNKNOWN:
|
||||
|
|
|
@ -626,7 +626,6 @@ static __init int init_k8_gatt(struct agp_kern_info *info)
|
|||
struct pci_dev *dev;
|
||||
void *gatt;
|
||||
int i, error;
|
||||
unsigned long start_pfn, end_pfn;
|
||||
|
||||
printk(KERN_INFO "PCI-DMA: Disabling AGP.\n");
|
||||
aper_size = aper_base = info->aper_size = 0;
|
||||
|
@ -672,12 +671,6 @@ static __init int init_k8_gatt(struct agp_kern_info *info)
|
|||
printk(KERN_INFO "PCI-DMA: aperture base @ %x size %u KB\n",
|
||||
aper_base, aper_size>>10);
|
||||
|
||||
/* need to map that range */
|
||||
end_pfn = (aper_base>>PAGE_SHIFT) + (aper_size>>PAGE_SHIFT);
|
||||
if (end_pfn > max_low_pfn_mapped) {
|
||||
start_pfn = (aper_base>>PAGE_SHIFT);
|
||||
init_memory_mapping(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
|
||||
}
|
||||
return 0;
|
||||
|
||||
nommu:
|
||||
|
@ -727,7 +720,8 @@ void __init gart_iommu_init(void)
|
|||
{
|
||||
struct agp_kern_info info;
|
||||
unsigned long iommu_start;
|
||||
unsigned long aper_size;
|
||||
unsigned long aper_base, aper_size;
|
||||
unsigned long start_pfn, end_pfn;
|
||||
unsigned long scratch;
|
||||
long i;
|
||||
|
||||
|
@ -765,8 +759,16 @@ void __init gart_iommu_init(void)
|
|||
return;
|
||||
}
|
||||
|
||||
/* need to map that range */
|
||||
aper_size = info.aper_size << 20;
|
||||
aper_base = info.aper_base;
|
||||
end_pfn = (aper_base>>PAGE_SHIFT) + (aper_size>>PAGE_SHIFT);
|
||||
if (end_pfn > max_low_pfn_mapped) {
|
||||
start_pfn = (aper_base>>PAGE_SHIFT);
|
||||
init_memory_mapping(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
|
||||
}
|
||||
|
||||
printk(KERN_INFO "PCI-DMA: using GART IOMMU.\n");
|
||||
aper_size = info.aper_size * 1024 * 1024;
|
||||
iommu_size = check_iommu_size(info.aper_base, aper_size);
|
||||
iommu_pages = iommu_size >> PAGE_SHIFT;
|
||||
|
||||
|
|
|
@ -235,7 +235,7 @@ static void vmi_write_ldt_entry(struct desc_struct *dt, int entry,
|
|||
const void *desc)
|
||||
{
|
||||
u32 *ldt_entry = (u32 *)desc;
|
||||
vmi_ops.write_idt_entry(dt, entry, ldt_entry[0], ldt_entry[1]);
|
||||
vmi_ops.write_ldt_entry(dt, entry, ldt_entry[0], ldt_entry[1]);
|
||||
}
|
||||
|
||||
static void vmi_load_sp0(struct tss_struct *tss,
|
||||
|
|
|
@ -376,6 +376,8 @@ int braille_register_console(struct console *console, int index,
|
|||
console->flags |= CON_ENABLED;
|
||||
console->index = index;
|
||||
braille_co = console;
|
||||
register_keyboard_notifier(&keyboard_notifier_block);
|
||||
register_vt_notifier(&vt_notifier_block);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -383,15 +385,8 @@ int braille_unregister_console(struct console *console)
|
|||
{
|
||||
if (braille_co != console)
|
||||
return -EINVAL;
|
||||
unregister_keyboard_notifier(&keyboard_notifier_block);
|
||||
unregister_vt_notifier(&vt_notifier_block);
|
||||
braille_co = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init braille_init(void)
|
||||
{
|
||||
register_keyboard_notifier(&keyboard_notifier_block);
|
||||
register_vt_notifier(&vt_notifier_block);
|
||||
return 0;
|
||||
}
|
||||
|
||||
console_initcall(braille_init);
|
||||
|
|
|
@ -165,8 +165,11 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
|
|||
"firmware_node");
|
||||
ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
|
||||
"physical_node");
|
||||
if (acpi_dev->wakeup.flags.valid)
|
||||
if (acpi_dev->wakeup.flags.valid) {
|
||||
device_set_wakeup_capable(dev, true);
|
||||
device_set_wakeup_enable(dev,
|
||||
acpi_dev->wakeup.state.enabled);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -377,6 +377,14 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void physical_device_enable_wakeup(struct acpi_device *adev)
|
||||
{
|
||||
struct device *dev = acpi_get_physical_device(adev->handle);
|
||||
|
||||
if (dev && device_can_wakeup(dev))
|
||||
device_set_wakeup_enable(dev, adev->wakeup.state.enabled);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
acpi_system_write_wakeup_device(struct file *file,
|
||||
const char __user * buffer,
|
||||
|
@ -411,6 +419,7 @@ acpi_system_write_wakeup_device(struct file *file,
|
|||
}
|
||||
}
|
||||
if (found_dev) {
|
||||
physical_device_enable_wakeup(found_dev);
|
||||
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
|
||||
struct acpi_device *dev = container_of(node,
|
||||
struct
|
||||
|
@ -428,6 +437,7 @@ acpi_system_write_wakeup_device(struct file *file,
|
|||
dev->pnp.bus_id, found_dev->pnp.bus_id);
|
||||
dev->wakeup.state.enabled =
|
||||
found_dev->wakeup.state.enabled;
|
||||
physical_device_enable_wakeup(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -256,7 +256,6 @@ static inline int bpa10x_submit_intr_urb(struct hci_dev *hdev)
|
|||
BT_ERR("%s urb %p submission failed (%d)",
|
||||
hdev->name, urb, -err);
|
||||
usb_unanchor_urb(urb);
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
usb_free_urb(urb);
|
||||
|
@ -298,7 +297,6 @@ static inline int bpa10x_submit_bulk_urb(struct hci_dev *hdev)
|
|||
BT_ERR("%s urb %p submission failed (%d)",
|
||||
hdev->name, urb, -err);
|
||||
usb_unanchor_urb(urb);
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
usb_free_urb(urb);
|
||||
|
|
|
@ -102,6 +102,7 @@ static struct usb_device_id blacklist_table[] = {
|
|||
{ USB_DEVICE(0x0a5c, 0x2101), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
|
||||
|
||||
/* Broadcom BCM2046 */
|
||||
{ USB_DEVICE(0x0a5c, 0x2146), .driver_info = BTUSB_RESET },
|
||||
{ USB_DEVICE(0x0a5c, 0x2151), .driver_info = BTUSB_RESET },
|
||||
|
||||
/* Apple MacBook Pro with Broadcom chip */
|
||||
|
@ -113,6 +114,7 @@ static struct usb_device_id blacklist_table[] = {
|
|||
|
||||
/* Targus ACB10US */
|
||||
{ USB_DEVICE(0x0a5c, 0x2100), .driver_info = BTUSB_RESET },
|
||||
{ USB_DEVICE(0x0a5c, 0x2154), .driver_info = BTUSB_RESET },
|
||||
|
||||
/* ANYCOM Bluetooth USB-200 and USB-250 */
|
||||
{ USB_DEVICE(0x0a5c, 0x2111), .driver_info = BTUSB_RESET },
|
||||
|
@ -150,6 +152,9 @@ static struct usb_device_id blacklist_table[] = {
|
|||
{ USB_DEVICE(0x050d, 0x0012), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
|
||||
{ USB_DEVICE(0x050d, 0x0013), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
|
||||
|
||||
/* Belkin F8T016 device */
|
||||
{ USB_DEVICE(0x050d, 0x016a), .driver_info = BTUSB_RESET },
|
||||
|
||||
/* Digianswer devices */
|
||||
{ USB_DEVICE(0x08fd, 0x0001), .driver_info = BTUSB_DIGIANSWER },
|
||||
{ USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE },
|
||||
|
@ -271,7 +276,6 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev)
|
|||
BT_ERR("%s urb %p submission failed (%d)",
|
||||
hdev->name, urb, -err);
|
||||
usb_unanchor_urb(urb);
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
usb_free_urb(urb);
|
||||
|
@ -354,7 +358,6 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev)
|
|||
BT_ERR("%s urb %p submission failed (%d)",
|
||||
hdev->name, urb, -err);
|
||||
usb_unanchor_urb(urb);
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
usb_free_urb(urb);
|
||||
|
@ -475,7 +478,6 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev)
|
|||
BT_ERR("%s urb %p submission failed (%d)",
|
||||
hdev->name, urb, -err);
|
||||
usb_unanchor_urb(urb);
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
usb_free_urb(urb);
|
||||
|
|
|
@ -364,7 +364,7 @@ static void dw_dma_tasklet(unsigned long data)
|
|||
int i;
|
||||
|
||||
status_block = dma_readl(dw, RAW.BLOCK);
|
||||
status_xfer = dma_readl(dw, RAW.BLOCK);
|
||||
status_xfer = dma_readl(dw, RAW.XFER);
|
||||
status_err = dma_readl(dw, RAW.ERROR);
|
||||
|
||||
dev_vdbg(dw->dma.dev, "tasklet: status_block=%x status_err=%x\n",
|
||||
|
|
|
@ -780,10 +780,6 @@ config BLK_DEV_IDEDMA_PMAC
|
|||
to transfer data to and from memory. Saying Y is safe and improves
|
||||
performance.
|
||||
|
||||
config BLK_DEV_IDE_SWARM
|
||||
tristate "IDE for Sibyte evaluation boards"
|
||||
depends on SIBYTE_SB1xxx_SOC
|
||||
|
||||
config BLK_DEV_IDE_AU1XXX
|
||||
bool "IDE for AMD Alchemy Au1200"
|
||||
depends on SOC_AU1200
|
||||
|
|
|
@ -1661,7 +1661,9 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
|
|||
cdi->mask &= ~CDC_PLAY_AUDIO;
|
||||
|
||||
mechtype = buf[8 + 6] >> 5;
|
||||
if (mechtype == mechtype_caddy || mechtype == mechtype_popup)
|
||||
if (mechtype == mechtype_caddy ||
|
||||
mechtype == mechtype_popup ||
|
||||
(drive->atapi_flags & IDE_AFLAG_NO_AUTOCLOSE))
|
||||
cdi->mask |= CDC_CLOSE_TRAY;
|
||||
|
||||
if (cdi->sanyo_slot > 0) {
|
||||
|
@ -1859,6 +1861,8 @@ static const struct cd_list_entry ide_cd_quirks_list[] = {
|
|||
{ "MATSHITADVD-ROM SR-8176", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
|
||||
{ "MATSHITADVD-ROM SR-8174", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
|
||||
{ "Optiarc DVD RW AD-5200A", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
|
||||
{ "Optiarc DVD RW AD-7200A", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
|
||||
{ "Optiarc DVD RW AD-7543A", NULL, IDE_AFLAG_NO_AUTOCLOSE },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -211,7 +211,7 @@ int ide_build_dmatable (ide_drive_t *drive, struct request *rq)
|
|||
xcount = bcount & 0xffff;
|
||||
if (is_trm290)
|
||||
xcount = ((xcount >> 2) - 1) << 16;
|
||||
if (xcount == 0x0000) {
|
||||
else if (xcount == 0x0000) {
|
||||
/*
|
||||
* Most chipsets correctly interpret a length of 0x0000 as 64KB,
|
||||
* but at least one (e.g. CS5530) misinterprets it as zero (!).
|
||||
|
|
|
@ -1492,7 +1492,7 @@ static struct device_attribute *ide_port_attrs[] = {
|
|||
|
||||
static int ide_sysfs_register_port(ide_hwif_t *hwif)
|
||||
{
|
||||
int i, rc;
|
||||
int i, uninitialized_var(rc);
|
||||
|
||||
for (i = 0; ide_port_attrs[i]; i++) {
|
||||
rc = device_create_file(hwif->portdev, ide_port_attrs[i]);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
obj-$(CONFIG_BLK_DEV_IDE_SWARM) += swarm.o
|
||||
obj-$(CONFIG_BLK_DEV_IDE_AU1XXX) += au1xxx-ide.o
|
||||
|
||||
EXTRA_CFLAGS := -Idrivers/ide
|
||||
|
|
|
@ -1,197 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2001, 2002, 2003 Broadcom Corporation
|
||||
* Copyright (C) 2004 MontaVista Software Inc.
|
||||
* Author: Manish Lachwani, mlachwani@mvista.com
|
||||
* Copyright (C) 2004 MIPS Technologies, Inc. All rights reserved.
|
||||
* Author: Maciej W. Rozycki <macro@mips.com>
|
||||
* Copyright (c) 2006, 2008 Maciej W. Rozycki
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Derived loosely from ide-pmac.c, so:
|
||||
* Copyright (C) 1998 Paul Mackerras.
|
||||
* Copyright (C) 1995-1998 Mark Lord
|
||||
*/
|
||||
|
||||
/*
|
||||
* Boards with SiByte processors so far have supported IDE devices via
|
||||
* the Generic Bus, PCI bus, and built-in PCMCIA interface. In all
|
||||
* cases, byte-swapping must be avoided for these devices (whereas
|
||||
* other PCI devices, for example, will require swapping). Any
|
||||
* SiByte-targetted kernel including IDE support will include this
|
||||
* file. Probing of a Generic Bus for an IDE device is controlled by
|
||||
* the definition of "SIBYTE_HAVE_IDE", which is provided by
|
||||
* <asm/sibyte/board.h> for Broadcom boards.
|
||||
*/
|
||||
|
||||
#include <linux/ide.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/sibyte/board.h>
|
||||
#include <asm/sibyte/sb1250_genbus.h>
|
||||
#include <asm/sibyte/sb1250_regs.h>
|
||||
|
||||
#define DRV_NAME "ide-swarm"
|
||||
|
||||
static char swarm_ide_string[] = DRV_NAME;
|
||||
|
||||
static struct resource swarm_ide_resource = {
|
||||
.name = "SWARM GenBus IDE",
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
static struct platform_device *swarm_ide_dev;
|
||||
|
||||
static const struct ide_port_info swarm_port_info = {
|
||||
.name = DRV_NAME,
|
||||
.host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
|
||||
};
|
||||
|
||||
/*
|
||||
* swarm_ide_probe - if the board header indicates the existence of
|
||||
* Generic Bus IDE, allocate a HWIF for it.
|
||||
*/
|
||||
static int __devinit swarm_ide_probe(struct device *dev)
|
||||
{
|
||||
u8 __iomem *base;
|
||||
struct ide_host *host;
|
||||
phys_t offset, size;
|
||||
int i, rc;
|
||||
hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
|
||||
|
||||
if (!SIBYTE_HAVE_IDE)
|
||||
return -ENODEV;
|
||||
|
||||
base = ioremap(A_IO_EXT_BASE, 0x800);
|
||||
offset = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS));
|
||||
size = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, IDE_CS));
|
||||
iounmap(base);
|
||||
|
||||
offset = G_IO_START_ADDR(offset) << S_IO_ADDRBASE;
|
||||
size = (G_IO_MULT_SIZE(size) + 1) << S_IO_REGSIZE;
|
||||
if (offset < A_PHYS_GENBUS || offset >= A_PHYS_GENBUS_END) {
|
||||
printk(KERN_INFO DRV_NAME
|
||||
": IDE interface at GenBus disabled\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
printk(KERN_INFO DRV_NAME ": IDE interface at GenBus slot %i\n",
|
||||
IDE_CS);
|
||||
|
||||
swarm_ide_resource.start = offset;
|
||||
swarm_ide_resource.end = offset + size - 1;
|
||||
if (request_resource(&iomem_resource, &swarm_ide_resource)) {
|
||||
printk(KERN_ERR DRV_NAME
|
||||
": can't request I/O memory resource\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
base = ioremap(offset, size);
|
||||
|
||||
memset(&hw, 0, sizeof(hw));
|
||||
for (i = 0; i <= 7; i++)
|
||||
hw.io_ports_array[i] =
|
||||
(unsigned long)(base + ((0x1f0 + i) << 5));
|
||||
hw.io_ports.ctl_addr =
|
||||
(unsigned long)(base + (0x3f6 << 5));
|
||||
hw.irq = K_INT_GB_IDE;
|
||||
hw.chipset = ide_generic;
|
||||
|
||||
rc = ide_host_add(&swarm_port_info, hws, &host);
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
dev_set_drvdata(dev, host);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
release_resource(&swarm_ide_resource);
|
||||
iounmap(base);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct device_driver swarm_ide_driver = {
|
||||
.name = swarm_ide_string,
|
||||
.bus = &platform_bus_type,
|
||||
.probe = swarm_ide_probe,
|
||||
};
|
||||
|
||||
static void swarm_ide_platform_release(struct device *device)
|
||||
{
|
||||
struct platform_device *pldev;
|
||||
|
||||
/* free device */
|
||||
pldev = to_platform_device(device);
|
||||
kfree(pldev);
|
||||
}
|
||||
|
||||
static int __devinit swarm_ide_init_module(void)
|
||||
{
|
||||
struct platform_device *pldev;
|
||||
int err;
|
||||
|
||||
printk(KERN_INFO "SWARM IDE driver\n");
|
||||
|
||||
if (driver_register(&swarm_ide_driver)) {
|
||||
printk(KERN_ERR "Driver registration failed\n");
|
||||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(pldev = kzalloc(sizeof (*pldev), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto out_unregister_driver;
|
||||
}
|
||||
|
||||
pldev->name = swarm_ide_string;
|
||||
pldev->id = 0;
|
||||
pldev->dev.release = swarm_ide_platform_release;
|
||||
|
||||
if (platform_device_register(pldev)) {
|
||||
err = -ENODEV;
|
||||
goto out_free_pldev;
|
||||
}
|
||||
|
||||
if (!pldev->dev.driver) {
|
||||
/*
|
||||
* The driver was not bound to this device, there was
|
||||
* no hardware at this address. Unregister it, as the
|
||||
* release fuction will take care of freeing the
|
||||
* allocated structure
|
||||
*/
|
||||
platform_device_unregister (pldev);
|
||||
}
|
||||
|
||||
swarm_ide_dev = pldev;
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_pldev:
|
||||
kfree(pldev);
|
||||
|
||||
out_unregister_driver:
|
||||
driver_unregister(&swarm_ide_driver);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
module_init(swarm_ide_init_module);
|
|
@ -161,6 +161,16 @@ static int fsg_led_probe(struct platform_device *pdev)
|
|||
{
|
||||
int ret;
|
||||
|
||||
/* Map the LED chip select address space */
|
||||
latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512);
|
||||
if (!latch_address) {
|
||||
ret = -ENOMEM;
|
||||
goto failremap;
|
||||
}
|
||||
|
||||
latch_value = 0xffff;
|
||||
*latch_address = latch_value;
|
||||
|
||||
ret = led_classdev_register(&pdev->dev, &fsg_wlan_led);
|
||||
if (ret < 0)
|
||||
goto failwlan;
|
||||
|
@ -185,20 +195,8 @@ static int fsg_led_probe(struct platform_device *pdev)
|
|||
if (ret < 0)
|
||||
goto failring;
|
||||
|
||||
/* Map the LED chip select address space */
|
||||
latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512);
|
||||
if (!latch_address) {
|
||||
ret = -ENOMEM;
|
||||
goto failremap;
|
||||
}
|
||||
|
||||
latch_value = 0xffff;
|
||||
*latch_address = latch_value;
|
||||
|
||||
return ret;
|
||||
|
||||
failremap:
|
||||
led_classdev_unregister(&fsg_ring_led);
|
||||
failring:
|
||||
led_classdev_unregister(&fsg_sync_led);
|
||||
failsync:
|
||||
|
@ -210,14 +208,14 @@ static int fsg_led_probe(struct platform_device *pdev)
|
|||
failwan:
|
||||
led_classdev_unregister(&fsg_wlan_led);
|
||||
failwlan:
|
||||
iounmap(latch_address);
|
||||
failremap:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fsg_led_remove(struct platform_device *pdev)
|
||||
{
|
||||
iounmap(latch_address);
|
||||
|
||||
led_classdev_unregister(&fsg_wlan_led);
|
||||
led_classdev_unregister(&fsg_wan_led);
|
||||
led_classdev_unregister(&fsg_sata_led);
|
||||
|
@ -225,6 +223,8 @@ static int fsg_led_remove(struct platform_device *pdev)
|
|||
led_classdev_unregister(&fsg_sync_led);
|
||||
led_classdev_unregister(&fsg_ring_led);
|
||||
|
||||
iounmap(latch_address);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -248,11 +248,10 @@ static int __devinit pca955x_probe(struct i2c_client *client,
|
|||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct pca955x_led *pca955x;
|
||||
int i;
|
||||
int err = -ENODEV;
|
||||
struct pca955x_chipdef *chip;
|
||||
struct i2c_adapter *adapter;
|
||||
struct led_platform_data *pdata;
|
||||
int i, err;
|
||||
|
||||
chip = &pca955x_chipdefs[id->driver_data];
|
||||
adapter = to_i2c_adapter(client->dev.parent);
|
||||
|
@ -282,43 +281,41 @@ static int __devinit pca955x_probe(struct i2c_client *client,
|
|||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < chip->bits; i++) {
|
||||
pca955x = kzalloc(sizeof(struct pca955x_led), GFP_KERNEL);
|
||||
if (!pca955x) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
pca955x = kzalloc(sizeof(*pca955x) * chip->bits, GFP_KERNEL);
|
||||
if (!pca955x)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, pca955x);
|
||||
|
||||
for (i = 0; i < chip->bits; i++) {
|
||||
pca955x[i].chipdef = chip;
|
||||
pca955x[i].client = client;
|
||||
pca955x[i].led_num = i;
|
||||
|
||||
pca955x->chipdef = chip;
|
||||
pca955x->client = client;
|
||||
pca955x->led_num = i;
|
||||
/* Platform data can specify LED names and default triggers */
|
||||
if (pdata) {
|
||||
if (pdata->leds[i].name)
|
||||
snprintf(pca955x->name, 32, "pca955x:%s",
|
||||
pdata->leds[i].name);
|
||||
snprintf(pca955x[i].name,
|
||||
sizeof(pca955x[i].name), "pca955x:%s",
|
||||
pdata->leds[i].name);
|
||||
if (pdata->leds[i].default_trigger)
|
||||
pca955x->led_cdev.default_trigger =
|
||||
pca955x[i].led_cdev.default_trigger =
|
||||
pdata->leds[i].default_trigger;
|
||||
} else {
|
||||
snprintf(pca955x->name, 32, "pca955x:%d", i);
|
||||
snprintf(pca955x[i].name, sizeof(pca955x[i].name),
|
||||
"pca955x:%d", i);
|
||||
}
|
||||
spin_lock_init(&pca955x->lock);
|
||||
|
||||
pca955x->led_cdev.name = pca955x->name;
|
||||
pca955x->led_cdev.brightness_set =
|
||||
pca955x_led_set;
|
||||
spin_lock_init(&pca955x[i].lock);
|
||||
|
||||
/*
|
||||
* Client data is a pointer to the _first_ pca955x_led
|
||||
* struct
|
||||
*/
|
||||
if (i == 0)
|
||||
i2c_set_clientdata(client, pca955x);
|
||||
pca955x[i].led_cdev.name = pca955x[i].name;
|
||||
pca955x[i].led_cdev.brightness_set = pca955x_led_set;
|
||||
|
||||
INIT_WORK(&(pca955x->work), pca955x_led_work);
|
||||
INIT_WORK(&pca955x[i].work, pca955x_led_work);
|
||||
|
||||
led_classdev_register(&client->dev, &(pca955x->led_cdev));
|
||||
err = led_classdev_register(&client->dev, &pca955x[i].led_cdev);
|
||||
if (err < 0)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Turn off LEDs */
|
||||
|
@ -336,23 +333,32 @@ static int __devinit pca955x_probe(struct i2c_client *client,
|
|||
pca955x_write_psc(client, 1, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
exit:
|
||||
while (i--) {
|
||||
led_classdev_unregister(&pca955x[i].led_cdev);
|
||||
cancel_work_sync(&pca955x[i].work);
|
||||
}
|
||||
|
||||
kfree(pca955x);
|
||||
i2c_set_clientdata(client, NULL);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit pca955x_remove(struct i2c_client *client)
|
||||
{
|
||||
struct pca955x_led *pca955x = i2c_get_clientdata(client);
|
||||
int leds = pca955x->chipdef->bits;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < leds; i++) {
|
||||
led_classdev_unregister(&(pca955x->led_cdev));
|
||||
cancel_work_sync(&(pca955x->work));
|
||||
kfree(pca955x);
|
||||
pca955x = pca955x + 1;
|
||||
for (i = 0; i < pca955x->chipdef->bits; i++) {
|
||||
led_classdev_unregister(&pca955x[i].led_cdev);
|
||||
cancel_work_sync(&pca955x[i].work);
|
||||
}
|
||||
|
||||
kfree(pca955x);
|
||||
i2c_set_clientdata(client, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ struct multipath {
|
|||
|
||||
const char *hw_handler_name;
|
||||
struct work_struct activate_path;
|
||||
struct pgpath *pgpath_to_activate;
|
||||
unsigned nr_priority_groups;
|
||||
struct list_head priority_groups;
|
||||
unsigned pg_init_required; /* pg_init needs calling? */
|
||||
|
@ -146,6 +147,7 @@ static struct priority_group *alloc_priority_group(void)
|
|||
|
||||
static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct pgpath *pgpath, *tmp;
|
||||
struct multipath *m = ti->private;
|
||||
|
||||
|
@ -154,6 +156,10 @@ static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
|
|||
if (m->hw_handler_name)
|
||||
scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev));
|
||||
dm_put_device(ti, pgpath->path.dev);
|
||||
spin_lock_irqsave(&m->lock, flags);
|
||||
if (m->pgpath_to_activate == pgpath)
|
||||
m->pgpath_to_activate = NULL;
|
||||
spin_unlock_irqrestore(&m->lock, flags);
|
||||
free_pgpath(pgpath);
|
||||
}
|
||||
}
|
||||
|
@ -421,6 +427,7 @@ static void process_queued_ios(struct work_struct *work)
|
|||
__choose_pgpath(m);
|
||||
|
||||
pgpath = m->current_pgpath;
|
||||
m->pgpath_to_activate = m->current_pgpath;
|
||||
|
||||
if ((pgpath && !m->queue_io) ||
|
||||
(!pgpath && !m->queue_if_no_path))
|
||||
|
@ -1093,8 +1100,15 @@ static void activate_path(struct work_struct *work)
|
|||
int ret;
|
||||
struct multipath *m =
|
||||
container_of(work, struct multipath, activate_path);
|
||||
struct dm_path *path = &m->current_pgpath->path;
|
||||
struct dm_path *path;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&m->lock, flags);
|
||||
path = &m->pgpath_to_activate->path;
|
||||
m->pgpath_to_activate = NULL;
|
||||
spin_unlock_irqrestore(&m->lock, flags);
|
||||
if (!path)
|
||||
return;
|
||||
ret = scsi_dh_activate(bdev_get_queue(path->dev->bdev));
|
||||
pg_init_done(path, ret);
|
||||
}
|
||||
|
|
|
@ -837,12 +837,14 @@ static int dm_merge_bvec(struct request_queue *q,
|
|||
struct dm_table *map = dm_get_table(md);
|
||||
struct dm_target *ti;
|
||||
sector_t max_sectors;
|
||||
int max_size;
|
||||
int max_size = 0;
|
||||
|
||||
if (unlikely(!map))
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
ti = dm_table_find_target(map, bvm->bi_sector);
|
||||
if (!dm_target_is_valid(ti))
|
||||
goto out_table;
|
||||
|
||||
/*
|
||||
* Find maximum amount of I/O that won't need splitting
|
||||
|
@ -861,14 +863,16 @@ static int dm_merge_bvec(struct request_queue *q,
|
|||
if (max_size && ti->type->merge)
|
||||
max_size = ti->type->merge(ti, bvm, biovec, max_size);
|
||||
|
||||
out_table:
|
||||
dm_table_put(map);
|
||||
|
||||
out:
|
||||
/*
|
||||
* Always allow an entire first page
|
||||
*/
|
||||
if (max_size <= biovec->bv_len && !(bvm->bi_size >> SECTOR_SHIFT))
|
||||
max_size = biovec->bv_len;
|
||||
|
||||
dm_table_put(map);
|
||||
|
||||
return max_size;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "dvb_frontend.h"
|
||||
|
||||
#define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw"
|
||||
#define XC3028L_DEFAULT_FIRMWARE "xc3028L-v36.fw"
|
||||
|
||||
/* Dmoduler IF (kHz) */
|
||||
#define XC3028_FE_DEFAULT 0 /* Don't load SCODE */
|
||||
|
|
|
@ -491,6 +491,7 @@ static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
|
|||
.demod_address = 0x53,
|
||||
.invert = 1,
|
||||
.repeated_start_workaround = 1,
|
||||
.serial_mpeg = 1,
|
||||
};
|
||||
|
||||
static struct itd1000_config skystar2_rev2_7_itd1000_config = {
|
||||
|
|
|
@ -364,15 +364,16 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
|
|||
enum dmx_success success)
|
||||
{
|
||||
struct dmxdev_filter *dmxdevfilter = filter->priv;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (dmxdevfilter->buffer.error) {
|
||||
wake_up(&dmxdevfilter->buffer.queue);
|
||||
return 0;
|
||||
}
|
||||
spin_lock(&dmxdevfilter->dev->lock);
|
||||
spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
|
||||
if (dmxdevfilter->state != DMXDEV_STATE_GO) {
|
||||
spin_unlock(&dmxdevfilter->dev->lock);
|
||||
spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
del_timer(&dmxdevfilter->timer);
|
||||
|
@ -391,7 +392,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
|
|||
}
|
||||
if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
|
||||
dmxdevfilter->state = DMXDEV_STATE_DONE;
|
||||
spin_unlock(&dmxdevfilter->dev->lock);
|
||||
spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
|
||||
wake_up(&dmxdevfilter->buffer.queue);
|
||||
return 0;
|
||||
}
|
||||
|
@ -403,11 +404,12 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
|
|||
{
|
||||
struct dmxdev_filter *dmxdevfilter = feed->priv;
|
||||
struct dvb_ringbuffer *buffer;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock(&dmxdevfilter->dev->lock);
|
||||
spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
|
||||
if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
|
||||
spin_unlock(&dmxdevfilter->dev->lock);
|
||||
spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -417,7 +419,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
|
|||
else
|
||||
buffer = &dmxdevfilter->dev->dvr_buffer;
|
||||
if (buffer->error) {
|
||||
spin_unlock(&dmxdevfilter->dev->lock);
|
||||
spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
|
||||
wake_up(&buffer->queue);
|
||||
return 0;
|
||||
}
|
||||
|
@ -428,7 +430,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
|
|||
dvb_ringbuffer_flush(buffer);
|
||||
buffer->error = ret;
|
||||
}
|
||||
spin_unlock(&dmxdevfilter->dev->lock);
|
||||
spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
|
||||
wake_up(&buffer->queue);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -399,7 +399,9 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
|
|||
void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
|
||||
size_t count)
|
||||
{
|
||||
spin_lock(&demux->lock);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&demux->lock, flags);
|
||||
|
||||
while (count--) {
|
||||
if (buf[0] == 0x47)
|
||||
|
@ -407,16 +409,17 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
|
|||
buf += 188;
|
||||
}
|
||||
|
||||
spin_unlock(&demux->lock);
|
||||
spin_unlock_irqrestore(&demux->lock, flags);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
|
||||
|
||||
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
|
||||
{
|
||||
unsigned long flags;
|
||||
int p = 0, i, j;
|
||||
|
||||
spin_lock(&demux->lock);
|
||||
spin_lock_irqsave(&demux->lock, flags);
|
||||
|
||||
if (demux->tsbufp) {
|
||||
i = demux->tsbufp;
|
||||
|
@ -449,17 +452,18 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
|
|||
}
|
||||
|
||||
bailout:
|
||||
spin_unlock(&demux->lock);
|
||||
spin_unlock_irqrestore(&demux->lock, flags);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dvb_dmx_swfilter);
|
||||
|
||||
void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
|
||||
{
|
||||
unsigned long flags;
|
||||
int p = 0, i, j;
|
||||
u8 tmppack[188];
|
||||
|
||||
spin_lock(&demux->lock);
|
||||
spin_lock_irqsave(&demux->lock, flags);
|
||||
|
||||
if (demux->tsbufp) {
|
||||
i = demux->tsbufp;
|
||||
|
@ -500,7 +504,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
|
|||
}
|
||||
|
||||
bailout:
|
||||
spin_unlock(&demux->lock);
|
||||
spin_unlock_irqrestore(&demux->lock, flags);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dvb_dmx_swfilter_204);
|
||||
|
|
|
@ -59,7 +59,7 @@ struct s5h1420_state {
|
|||
* it does not support repeated-start, workaround: write addr-1
|
||||
* and then read
|
||||
*/
|
||||
u8 shadow[255];
|
||||
u8 shadow[256];
|
||||
};
|
||||
|
||||
static u32 s5h1420_getsymbolrate(struct s5h1420_state* state);
|
||||
|
@ -94,8 +94,11 @@ static u8 s5h1420_readreg(struct s5h1420_state *state, u8 reg)
|
|||
if (ret != 3)
|
||||
return ret;
|
||||
} else {
|
||||
ret = i2c_transfer(state->i2c, &msg[1], 2);
|
||||
if (ret != 2)
|
||||
ret = i2c_transfer(state->i2c, &msg[1], 1);
|
||||
if (ret != 1)
|
||||
return ret;
|
||||
ret = i2c_transfer(state->i2c, &msg[2], 1);
|
||||
if (ret != 1)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -823,7 +826,7 @@ static int s5h1420_init (struct dvb_frontend* fe)
|
|||
struct s5h1420_state* state = fe->demodulator_priv;
|
||||
|
||||
/* disable power down and do reset */
|
||||
state->CON_1_val = 0x10;
|
||||
state->CON_1_val = state->config->serial_mpeg << 4;
|
||||
s5h1420_writereg(state, 0x02, state->CON_1_val);
|
||||
msleep(10);
|
||||
s5h1420_reset(state);
|
||||
|
|
|
@ -32,10 +32,12 @@ struct s5h1420_config
|
|||
u8 demod_address;
|
||||
|
||||
/* does the inversion require inversion? */
|
||||
u8 invert : 1;
|
||||
u8 invert:1;
|
||||
|
||||
u8 repeated_start_workaround : 1;
|
||||
u8 cdclk_polarity : 1; /* 1 == falling edge, 0 == raising edge */
|
||||
u8 repeated_start_workaround:1;
|
||||
u8 cdclk_polarity:1; /* 1 == falling edge, 0 == raising edge */
|
||||
|
||||
u8 serial_mpeg:1;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_S5H1420) || (defined(CONFIG_DVB_S5H1420_MODULE) && defined(MODULE))
|
||||
|
|
|
@ -40,6 +40,8 @@ struct usb_device_id smsusb_id_table[] = {
|
|||
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B },
|
||||
{ USB_DEVICE(0x2040, 0x5500),
|
||||
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
|
||||
{ USB_DEVICE(0x2040, 0x5510),
|
||||
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
|
||||
{ USB_DEVICE(0x2040, 0x5580),
|
||||
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
|
||||
{ USB_DEVICE(0x2040, 0x5590),
|
||||
|
@ -87,7 +89,7 @@ static struct sms_board sms_boards[] = {
|
|||
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw",
|
||||
},
|
||||
[SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = {
|
||||
.name = "Hauppauge WinTV-Nova-T-MiniStick",
|
||||
.name = "Hauppauge WinTV MiniStick",
|
||||
.type = SMS_NOVA_B0,
|
||||
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-01.fw",
|
||||
},
|
||||
|
|
|
@ -3431,7 +3431,7 @@ static int radio_open(struct inode *inode, struct file *file)
|
|||
dprintk("bttv: open minor=%d\n",minor);
|
||||
|
||||
for (i = 0; i < bttv_num; i++) {
|
||||
if (bttvs[i].radio_dev->minor == minor) {
|
||||
if (bttvs[i].radio_dev && bttvs[i].radio_dev->minor == minor) {
|
||||
btv = &bttvs[i];
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
|
|
@ -632,7 +632,7 @@ int cpia2_usb_transfer_cmd(struct camera_data *cam,
|
|||
static int submit_urbs(struct camera_data *cam)
|
||||
{
|
||||
struct urb *urb;
|
||||
int fx, err, i;
|
||||
int fx, err, i, j;
|
||||
|
||||
for(i=0; i<NUM_SBUF; ++i) {
|
||||
if (cam->sbuf[i].data)
|
||||
|
@ -657,6 +657,9 @@ static int submit_urbs(struct camera_data *cam)
|
|||
}
|
||||
urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
|
||||
if (!urb) {
|
||||
ERR("%s: usb_alloc_urb error!\n", __func__);
|
||||
for (j = 0; j < i; j++)
|
||||
usb_free_urb(cam->sbuf[j].urb);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
|
|
@ -163,7 +163,7 @@ static const struct cx18_card cx18_card_h900 = {
|
|||
},
|
||||
.audio_inputs = {
|
||||
{ CX18_CARD_INPUT_AUD_TUNER,
|
||||
CX18_AV_AUDIO8, 0 },
|
||||
CX18_AV_AUDIO5, 0 },
|
||||
{ CX18_CARD_INPUT_LINE_IN1,
|
||||
CX18_AV_AUDIO_SERIAL1, 0 },
|
||||
},
|
||||
|
|
|
@ -117,10 +117,10 @@ static void em28xx_audio_isocirq(struct urb *urb)
|
|||
|
||||
if (oldptr + length >= runtime->buffer_size) {
|
||||
unsigned int cnt =
|
||||
runtime->buffer_size - oldptr - 1;
|
||||
runtime->buffer_size - oldptr;
|
||||
memcpy(runtime->dma_area + oldptr * stride, cp,
|
||||
cnt * stride);
|
||||
memcpy(runtime->dma_area, cp + cnt,
|
||||
memcpy(runtime->dma_area, cp + cnt * stride,
|
||||
length * stride - cnt * stride);
|
||||
} else {
|
||||
memcpy(runtime->dma_area + oldptr * stride, cp,
|
||||
|
@ -161,8 +161,14 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)
|
|||
|
||||
memset(dev->adev->transfer_buffer[i], 0x80, sb_size);
|
||||
urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
|
||||
if (!urb)
|
||||
if (!urb) {
|
||||
em28xx_errdev("usb_alloc_urb failed!\n");
|
||||
for (j = 0; j < i; j++) {
|
||||
usb_free_urb(dev->adev->urb[j]);
|
||||
kfree(dev->adev->transfer_buffer[j]);
|
||||
}
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
urb->dev = dev->udev;
|
||||
urb->context = dev;
|
||||
|
|
|
@ -93,28 +93,6 @@ struct em28xx_board em28xx_boards[] = {
|
|||
.amux = 0,
|
||||
} },
|
||||
},
|
||||
[EM2800_BOARD_KWORLD_USB2800] = {
|
||||
.name = "Kworld USB2800",
|
||||
.valid = EM28XX_BOARD_NOT_VALIDATED,
|
||||
.is_em2800 = 1,
|
||||
.vchannels = 3,
|
||||
.tuner_type = TUNER_PHILIPS_FCV1236D,
|
||||
.tda9887_conf = TDA9887_PRESENT,
|
||||
.decoder = EM28XX_SAA7113,
|
||||
.input = { {
|
||||
.type = EM28XX_VMUX_TELEVISION,
|
||||
.vmux = SAA7115_COMPOSITE2,
|
||||
.amux = 0,
|
||||
}, {
|
||||
.type = EM28XX_VMUX_COMPOSITE1,
|
||||
.vmux = SAA7115_COMPOSITE0,
|
||||
.amux = 1,
|
||||
}, {
|
||||
.type = EM28XX_VMUX_SVIDEO,
|
||||
.vmux = SAA7115_SVIDEO3,
|
||||
.amux = 1,
|
||||
} },
|
||||
},
|
||||
[EM2820_BOARD_KWORLD_PVRTV2800RF] = {
|
||||
.name = "Kworld PVR TV 2800 RF",
|
||||
.is_em2800 = 0,
|
||||
|
@ -599,7 +577,7 @@ struct em28xx_board em28xx_boards[] = {
|
|||
}, {
|
||||
.type = EM28XX_VMUX_COMPOSITE1,
|
||||
.vmux = TVP5150_COMPOSITE1,
|
||||
.amux = 1,
|
||||
.amux = 3,
|
||||
}, {
|
||||
.type = EM28XX_VMUX_SVIDEO,
|
||||
.vmux = TVP5150_SVIDEO,
|
||||
|
@ -952,22 +930,23 @@ struct em28xx_board em28xx_boards[] = {
|
|||
},
|
||||
[EM2880_BOARD_KWORLD_DVB_310U] = {
|
||||
.name = "KWorld DVB-T 310U",
|
||||
.valid = EM28XX_BOARD_NOT_VALIDATED,
|
||||
.vchannels = 3,
|
||||
.tuner_type = TUNER_XC2028,
|
||||
.has_dvb = 1,
|
||||
.mts_firmware = 1,
|
||||
.decoder = EM28XX_TVP5150,
|
||||
.input = { {
|
||||
.type = EM28XX_VMUX_TELEVISION,
|
||||
.vmux = TVP5150_COMPOSITE0,
|
||||
.amux = 0,
|
||||
.amux = EM28XX_AMUX_VIDEO,
|
||||
}, {
|
||||
.type = EM28XX_VMUX_COMPOSITE1,
|
||||
.vmux = TVP5150_COMPOSITE1,
|
||||
.amux = 1,
|
||||
}, {
|
||||
.amux = EM28XX_AMUX_AC97_LINE_IN,
|
||||
}, { /* S-video has not been tested yet */
|
||||
.type = EM28XX_VMUX_SVIDEO,
|
||||
.vmux = TVP5150_SVIDEO,
|
||||
.amux = 1,
|
||||
.amux = EM28XX_AMUX_AC97_LINE_IN,
|
||||
} },
|
||||
},
|
||||
[EM2881_BOARD_DNT_DA2_HYBRID] = {
|
||||
|
@ -1282,6 +1261,7 @@ static struct em28xx_reg_seq em2882_terratec_hybrid_xs_digital[] = {
|
|||
static struct em28xx_hash_table em28xx_eeprom_hash [] = {
|
||||
/* P/N: SA 60002070465 Tuner: TVF7533-MF */
|
||||
{0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF},
|
||||
{0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028},
|
||||
};
|
||||
|
||||
/* I2C devicelist hash table for devices with generic USB IDs */
|
||||
|
@ -1552,9 +1532,12 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
|
|||
/* djh - Not sure which demod we need here */
|
||||
ctl->demod = XC3028_FE_DEFAULT;
|
||||
break;
|
||||
case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
|
||||
ctl->demod = XC3028_FE_DEFAULT;
|
||||
ctl->fname = XC3028L_DEFAULT_FIRMWARE;
|
||||
break;
|
||||
case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
|
||||
case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
|
||||
case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
|
||||
/* FIXME: Better to specify the needed IF */
|
||||
ctl->demod = XC3028_FE_DEFAULT;
|
||||
break;
|
||||
|
@ -1764,6 +1747,20 @@ void em28xx_card_setup(struct em28xx *dev)
|
|||
break;
|
||||
case EM2820_BOARD_UNKNOWN:
|
||||
case EM2800_BOARD_UNKNOWN:
|
||||
/*
|
||||
* The K-WORLD DVB-T 310U is detected as an MSI Digivox AD.
|
||||
*
|
||||
* This occurs because they share identical USB vendor and
|
||||
* product IDs.
|
||||
*
|
||||
* What we do here is look up the EEPROM hash of the K-WORLD
|
||||
* and if it is found then we decide that we do not have
|
||||
* a DIGIVOX and reset the device to the K-WORLD instead.
|
||||
*
|
||||
* This solution is only valid if they do not share eeprom
|
||||
* hash identities which has not been determined as yet.
|
||||
*/
|
||||
case EM2880_BOARD_MSI_DIGIVOX_AD:
|
||||
if (!em28xx_hint_board(dev))
|
||||
em28xx_set_model(dev);
|
||||
break;
|
||||
|
|
|
@ -452,6 +452,15 @@ static int dvb_init(struct em28xx *dev)
|
|||
goto out_free;
|
||||
}
|
||||
break;
|
||||
case EM2880_BOARD_KWORLD_DVB_310U:
|
||||
dvb->frontend = dvb_attach(zl10353_attach,
|
||||
&em28xx_zl10353_with_xc3028,
|
||||
&dev->i2c_adap);
|
||||
if (attach_xc3028(0x61, dev) < 0) {
|
||||
result = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
|
||||
" isn't supported yet\n",
|
||||
|
|
|
@ -459,6 +459,7 @@ static int create_urbs(struct gspca_dev *gspca_dev,
|
|||
urb = usb_alloc_urb(npkt, GFP_KERNEL);
|
||||
if (!urb) {
|
||||
err("usb_alloc_urb failed");
|
||||
destroy_urbs(gspca_dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev,
|
||||
|
@ -468,8 +469,8 @@ static int create_urbs(struct gspca_dev *gspca_dev,
|
|||
|
||||
if (urb->transfer_buffer == NULL) {
|
||||
usb_free_urb(urb);
|
||||
destroy_urbs(gspca_dev);
|
||||
err("usb_buffer_urb failed");
|
||||
destroy_urbs(gspca_dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
gspca_dev->urb[n] = urb;
|
||||
|
|
|
@ -1063,6 +1063,7 @@ static __devinitdata struct usb_device_id device_table[] = {
|
|||
{USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302},
|
||||
{USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302},
|
||||
{USB_DEVICE(0x093a, 0x2626), .driver_info = SENSOR_PAC7302},
|
||||
{USB_DEVICE(0x093a, 0x262a), .driver_info = SENSOR_PAC7302},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, device_table);
|
||||
|
|
|
@ -232,7 +232,7 @@ static struct ctrl sd_ctrls[] = {
|
|||
static struct v4l2_pix_format vga_mode[] = {
|
||||
{160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
|
||||
.bytesperline = 160,
|
||||
.sizeimage = 160 * 120 * 5 / 4,
|
||||
.sizeimage = 160 * 120,
|
||||
.colorspace = V4L2_COLORSPACE_SRGB,
|
||||
.priv = 2 | MODE_RAW},
|
||||
{160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
|
||||
|
@ -264,7 +264,7 @@ static struct v4l2_pix_format sif_mode[] = {
|
|||
.priv = 1 | MODE_REDUCED_SIF},
|
||||
{176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
|
||||
.bytesperline = 176,
|
||||
.sizeimage = 176 * 144 * 5 / 4,
|
||||
.sizeimage = 176 * 144,
|
||||
.colorspace = V4L2_COLORSPACE_SRGB,
|
||||
.priv = 1 | MODE_RAW},
|
||||
{176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
|
||||
|
|
|
@ -707,6 +707,7 @@ static void i2c_w8(struct gspca_dev *gspca_dev,
|
|||
0x08, 0, /* value, index */
|
||||
gspca_dev->usb_buf, 8,
|
||||
500);
|
||||
msleep(2);
|
||||
}
|
||||
|
||||
/* read 5 bytes in gspca_dev->usb_buf */
|
||||
|
@ -976,13 +977,13 @@ static int sd_init(struct gspca_dev *gspca_dev)
|
|||
case BRIDGE_SN9C105:
|
||||
if (regF1 != 0x11)
|
||||
return -ENODEV;
|
||||
reg_w(gspca_dev, 0x02, regGpio, 2);
|
||||
reg_w(gspca_dev, 0x01, regGpio, 2);
|
||||
break;
|
||||
case BRIDGE_SN9C120:
|
||||
if (regF1 != 0x12)
|
||||
return -ENODEV;
|
||||
regGpio[1] = 0x70;
|
||||
reg_w(gspca_dev, 0x02, regGpio, 2);
|
||||
reg_w(gspca_dev, 0x01, regGpio, 2);
|
||||
break;
|
||||
default:
|
||||
/* case BRIDGE_SN9C110: */
|
||||
|
@ -1183,7 +1184,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
|
|||
static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
|
||||
static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
|
||||
static const __u8 CE_ov76xx[] =
|
||||
{ 0x32, 0xdd, 0x32, 0xdd }; /* OV7630/48 */
|
||||
{ 0x32, 0xdd, 0x32, 0xdd };
|
||||
|
||||
sn9c1xx = sn_tb[(int) sd->sensor];
|
||||
configure_gpio(gspca_dev, sn9c1xx);
|
||||
|
@ -1223,8 +1224,15 @@ static void sd_start(struct gspca_dev *gspca_dev)
|
|||
reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def);
|
||||
for (i = 0; i < 8; i++)
|
||||
reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
|
||||
switch (sd->sensor) {
|
||||
case SENSOR_OV7660:
|
||||
reg_w1(gspca_dev, 0x9a, 0x05);
|
||||
break;
|
||||
default:
|
||||
reg_w1(gspca_dev, 0x9a, 0x08);
|
||||
reg_w1(gspca_dev, 0x99, 0x59);
|
||||
break;
|
||||
}
|
||||
|
||||
mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
|
||||
if (mode)
|
||||
|
@ -1275,8 +1283,8 @@ static void sd_start(struct gspca_dev *gspca_dev)
|
|||
/* reg1 = 0x44; */
|
||||
/* reg1 = 0x46; (done) */
|
||||
} else {
|
||||
reg17 = 0x22; /* 640 MCKSIZE */
|
||||
reg1 = 0x06;
|
||||
reg17 = 0xa2; /* 640 */
|
||||
reg1 = 0x44;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1285,6 +1293,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
|
|||
switch (sd->sensor) {
|
||||
case SENSOR_OV7630:
|
||||
case SENSOR_OV7648:
|
||||
case SENSOR_OV7660:
|
||||
reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -225,7 +225,7 @@ static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
|
|||
reg_w_val(gspca_dev->dev, 0x8802, (mode | 0x01));
|
||||
do {
|
||||
reg_r(gspca_dev, 0x8803, 1);
|
||||
if (!gspca_dev->usb_buf)
|
||||
if (!gspca_dev->usb_buf[0])
|
||||
break;
|
||||
} while (--retry);
|
||||
if (retry == 0)
|
||||
|
|
|
@ -6576,8 +6576,8 @@ static int setlightfreq(struct gspca_dev *gspca_dev)
|
|||
cs2102_60HZ, cs2102_60HZScale},
|
||||
/* SENSOR_CS2102K 1 */
|
||||
{cs2102_NoFliker, cs2102_NoFlikerScale,
|
||||
cs2102_50HZ, cs2102_50HZScale,
|
||||
cs2102_60HZ, cs2102_60HZScale},
|
||||
NULL, NULL, /* currently disabled */
|
||||
NULL, NULL},
|
||||
/* SENSOR_GC0305 2 */
|
||||
{gc0305_NoFliker, gc0305_NoFliker,
|
||||
gc0305_50HZ, gc0305_50HZ,
|
||||
|
|
|
@ -3591,7 +3591,7 @@ static int
|
|||
ov51x_init_isoc(struct usb_ov511 *ov)
|
||||
{
|
||||
struct urb *urb;
|
||||
int fx, err, n, size;
|
||||
int fx, err, n, i, size;
|
||||
|
||||
PDEBUG(3, "*** Initializing capture ***");
|
||||
|
||||
|
@ -3662,6 +3662,8 @@ ov51x_init_isoc(struct usb_ov511 *ov)
|
|||
urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
|
||||
if (!urb) {
|
||||
err("init isoc: usb_alloc_urb ret. NULL");
|
||||
for (i = 0; i < n; i++)
|
||||
usb_free_urb(ov->sbuf[i].urb);
|
||||
return -ENOMEM;
|
||||
}
|
||||
ov->sbuf[n].urb = urb;
|
||||
|
@ -5651,7 +5653,7 @@ static ssize_t show_exposure(struct device *cd,
|
|||
if (!ov->dev)
|
||||
return -ENODEV;
|
||||
sensor_get_exposure(ov, &exp);
|
||||
return sprintf(buf, "%d\n", exp >> 8);
|
||||
return sprintf(buf, "%d\n", exp);
|
||||
}
|
||||
static DEVICE_ATTR(exposure, S_IRUGO, show_exposure, NULL);
|
||||
|
||||
|
|
|
@ -489,6 +489,8 @@ static const struct pvr2_device_desc pvr2_device_751xx = {
|
|||
struct usb_device_id pvr2_device_table[] = {
|
||||
{ USB_DEVICE(0x2040, 0x2900),
|
||||
.driver_info = (kernel_ulong_t)&pvr2_device_29xxx},
|
||||
{ USB_DEVICE(0x2040, 0x2950), /* Logically identical to 2900 */
|
||||
.driver_info = (kernel_ulong_t)&pvr2_device_29xxx},
|
||||
{ USB_DEVICE(0x2040, 0x2400),
|
||||
.driver_info = (kernel_ulong_t)&pvr2_device_24xxx},
|
||||
{ USB_DEVICE(0x1164, 0x0622),
|
||||
|
|
|
@ -669,7 +669,7 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
|
|||
(unsigned long)vbuf, pos);
|
||||
/* tell v4l buffer was filled */
|
||||
|
||||
buf->vb.field_count++;
|
||||
buf->vb.field_count = dev->frame_count[chn] * 2;
|
||||
do_gettimeofday(&ts);
|
||||
buf->vb.ts = ts;
|
||||
buf->vb.state = VIDEOBUF_DONE;
|
||||
|
@ -1268,6 +1268,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
|
|||
dev->last_frame[chn] = -1;
|
||||
dev->bad_payload[chn] = 0;
|
||||
dev->cur_frame[chn] = 0;
|
||||
dev->frame_count[chn] = 0;
|
||||
for (j = 0; j < SYS_FRAMES; j++) {
|
||||
dev->buffer[chn].frame[j].ulState = 0;
|
||||
dev->buffer[chn].frame[j].cur_size = 0;
|
||||
|
|
|
@ -592,7 +592,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
|
|||
if (ctrl == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
data = kmalloc(8, GFP_KERNEL);
|
||||
data = kmalloc(ctrl->info->size, GFP_KERNEL);
|
||||
if (data == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -911,7 +911,6 @@ static int w9968cf_start_transfer(struct w9968cf_device* cam)
|
|||
|
||||
for (i = 0; i < W9968CF_URBS; i++) {
|
||||
urb = usb_alloc_urb(W9968CF_ISO_PACKETS, GFP_KERNEL);
|
||||
cam->urb[i] = urb;
|
||||
if (!urb) {
|
||||
for (j = 0; j < i; j++)
|
||||
usb_free_urb(cam->urb[j]);
|
||||
|
@ -919,6 +918,7 @@ static int w9968cf_start_transfer(struct w9968cf_device* cam)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cam->urb[i] = urb;
|
||||
urb->dev = udev;
|
||||
urb->context = (void*)cam;
|
||||
urb->pipe = usb_rcvisocpipe(udev, 1);
|
||||
|
|
|
@ -274,10 +274,8 @@ static int wm8739_probe(struct i2c_client *client,
|
|||
client->addr << 1, client->adapter->name);
|
||||
|
||||
state = kmalloc(sizeof(struct wm8739_state), GFP_KERNEL);
|
||||
if (state == NULL) {
|
||||
kfree(client);
|
||||
if (state == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
state->vol_l = 0x17; /* 0dB */
|
||||
state->vol_r = 0x17; /* 0dB */
|
||||
state->muted = 0;
|
||||
|
|
|
@ -988,7 +988,7 @@ zoran_open_init_params (struct zoran *zr)
|
|||
zr->v4l_grab_seq = 0;
|
||||
zr->v4l_settings.width = 192;
|
||||
zr->v4l_settings.height = 144;
|
||||
zr->v4l_settings.format = &zoran_formats[4]; /* YUY2 - YUV-4:2:2 packed */
|
||||
zr->v4l_settings.format = &zoran_formats[7]; /* YUY2 - YUV-4:2:2 packed */
|
||||
zr->v4l_settings.bytesperline =
|
||||
zr->v4l_settings.width *
|
||||
((zr->v4l_settings.format->depth + 7) / 8);
|
||||
|
|
|
@ -134,7 +134,7 @@ const struct zoran_format zoran_formats[] = {
|
|||
}, {
|
||||
.name = "16-bit RGB BE",
|
||||
ZFMT(-1,
|
||||
V4L2_PIX_FMT_RGB565, V4L2_COLORSPACE_SRGB),
|
||||
V4L2_PIX_FMT_RGB565X, V4L2_COLORSPACE_SRGB),
|
||||
.depth = 16,
|
||||
.flags = ZORAN_FORMAT_CAPTURE |
|
||||
ZORAN_FORMAT_OVERLAY,
|
||||
|
@ -2737,7 +2737,8 @@ zoran_do_ioctl (struct inode *inode,
|
|||
fh->v4l_settings.format->fourcc;
|
||||
fmt->fmt.pix.colorspace =
|
||||
fh->v4l_settings.format->colorspace;
|
||||
fmt->fmt.pix.bytesperline = 0;
|
||||
fmt->fmt.pix.bytesperline =
|
||||
fh->v4l_settings.bytesperline;
|
||||
if (BUZ_MAX_HEIGHT <
|
||||
(fh->v4l_settings.height * 2))
|
||||
fmt->fmt.pix.field =
|
||||
|
@ -2833,13 +2834,6 @@ zoran_do_ioctl (struct inode *inode,
|
|||
fmt->fmt.pix.pixelformat,
|
||||
(char *) &printformat);
|
||||
|
||||
if (fmt->fmt.pix.bytesperline > 0) {
|
||||
dprintk(5,
|
||||
KERN_ERR "%s: bpl not supported\n",
|
||||
ZR_DEVNAME(zr));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* we can be requested to do JPEG/raw playback/capture */
|
||||
if (!
|
||||
(fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
|
||||
|
@ -2923,6 +2917,7 @@ zoran_do_ioctl (struct inode *inode,
|
|||
fh->jpg_buffers.buffer_size =
|
||||
zoran_v4l2_calc_bufsize(&fh->
|
||||
jpg_settings);
|
||||
fmt->fmt.pix.bytesperline = 0;
|
||||
fmt->fmt.pix.sizeimage =
|
||||
fh->jpg_buffers.buffer_size;
|
||||
|
||||
|
@ -2979,6 +2974,8 @@ zoran_do_ioctl (struct inode *inode,
|
|||
|
||||
/* tell the user the
|
||||
* results/missing stuff */
|
||||
fmt->fmt.pix.bytesperline =
|
||||
fh->v4l_settings.bytesperline;
|
||||
fmt->fmt.pix.sizeimage =
|
||||
fh->v4l_settings.height *
|
||||
fh->v4l_settings.bytesperline;
|
||||
|
|
|
@ -21,7 +21,7 @@ config MFD_SM501
|
|||
|
||||
config MFD_SM501_GPIO
|
||||
bool "Export GPIO via GPIO layer"
|
||||
depends on MFD_SM501 && HAVE_GPIO_LIB
|
||||
depends on MFD_SM501 && GPIOLIB
|
||||
---help---
|
||||
This option uses the gpio library layer to export the 64 GPIO
|
||||
lines on the SM501. The platform data is used to supply the
|
||||
|
@ -29,7 +29,7 @@ config MFD_SM501_GPIO
|
|||
|
||||
config MFD_ASIC3
|
||||
bool "Support for Compaq ASIC3"
|
||||
depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB && ARM
|
||||
depends on GENERIC_HARDIRQS && GPIOLIB && ARM
|
||||
---help---
|
||||
This driver supports the ASIC3 multifunction chip found on many
|
||||
PDAs (mainly iPAQ and HTC based ones)
|
||||
|
|
|
@ -312,7 +312,6 @@ static int __init asic3_irq_probe(struct platform_device *pdev)
|
|||
struct asic3 *asic = platform_get_drvdata(pdev);
|
||||
unsigned long clksel = 0;
|
||||
unsigned int irq, irq_base;
|
||||
int map_size;
|
||||
int ret;
|
||||
|
||||
ret = platform_get_irq(pdev, 0);
|
||||
|
@ -534,6 +533,7 @@ static int __init asic3_probe(struct platform_device *pdev)
|
|||
struct asic3 *asic;
|
||||
struct resource *mem;
|
||||
unsigned long clksel;
|
||||
int map_size;
|
||||
int ret = 0;
|
||||
|
||||
asic = kzalloc(sizeof(struct asic3), GFP_KERNEL);
|
||||
|
|
|
@ -426,8 +426,6 @@ static u32 atmci_submit_data(struct mmc_host *mmc, struct mmc_data *data)
|
|||
host->sg = NULL;
|
||||
host->data = data;
|
||||
|
||||
mci_writel(host, BLKR, MCI_BCNT(data->blocks)
|
||||
| MCI_BLKLEN(data->blksz));
|
||||
dev_vdbg(&mmc->class_dev, "BLKR=0x%08x\n",
|
||||
MCI_BCNT(data->blocks) | MCI_BLKLEN(data->blksz));
|
||||
|
||||
|
@ -483,6 +481,10 @@ static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
|
|||
if (data->blocks > 1 && data->blksz & 3)
|
||||
goto fail;
|
||||
atmci_set_timeout(host, data);
|
||||
|
||||
/* Must set block count/size before sending command */
|
||||
mci_writel(host, BLKR, MCI_BCNT(data->blocks)
|
||||
| MCI_BLKLEN(data->blksz));
|
||||
}
|
||||
|
||||
iflags = MCI_CMDRDY;
|
||||
|
|
|
@ -257,7 +257,6 @@ struct e1000_adapter {
|
|||
struct net_device *netdev;
|
||||
struct pci_dev *pdev;
|
||||
struct net_device_stats net_stats;
|
||||
spinlock_t stats_lock; /* prevent concurrent stats updates */
|
||||
|
||||
/* structs defined in e1000_hw.h */
|
||||
struct e1000_hw hw;
|
||||
|
@ -284,6 +283,8 @@ struct e1000_adapter {
|
|||
unsigned long led_status;
|
||||
|
||||
unsigned int flags;
|
||||
struct work_struct downshift_task;
|
||||
struct work_struct update_phy_task;
|
||||
};
|
||||
|
||||
struct e1000_info {
|
||||
|
@ -305,6 +306,7 @@ struct e1000_info {
|
|||
#define FLAG_HAS_CTRLEXT_ON_LOAD (1 << 5)
|
||||
#define FLAG_HAS_SWSM_ON_LOAD (1 << 6)
|
||||
#define FLAG_HAS_JUMBO_FRAMES (1 << 7)
|
||||
#define FLAG_READ_ONLY_NVM (1 << 8)
|
||||
#define FLAG_IS_ICH (1 << 9)
|
||||
#define FLAG_HAS_SMART_POWER_DOWN (1 << 11)
|
||||
#define FLAG_IS_QUAD_PORT_A (1 << 12)
|
||||
|
@ -385,6 +387,7 @@ extern bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw);
|
|||
extern bool e1000e_get_laa_state_82571(struct e1000_hw *hw);
|
||||
extern void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state);
|
||||
|
||||
extern void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw);
|
||||
extern void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
|
||||
bool state);
|
||||
extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
|
||||
|
|
|
@ -432,6 +432,10 @@ static void e1000_get_regs(struct net_device *netdev,
|
|||
regs_buff[11] = er32(TIDV);
|
||||
|
||||
regs_buff[12] = adapter->hw.phy.type; /* PHY type (IGP=1, M88=0) */
|
||||
|
||||
/* ethtool doesn't use anything past this point, so all this
|
||||
* code is likely legacy junk for apps that may or may not
|
||||
* exist */
|
||||
if (hw->phy.type == e1000_phy_m88) {
|
||||
e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
|
||||
regs_buff[13] = (u32)phy_data; /* cable length */
|
||||
|
@ -447,7 +451,7 @@ static void e1000_get_regs(struct net_device *netdev,
|
|||
regs_buff[22] = adapter->phy_stats.receive_errors;
|
||||
regs_buff[23] = regs_buff[13]; /* mdix mode */
|
||||
}
|
||||
regs_buff[21] = adapter->phy_stats.idle_errors; /* phy idle errors */
|
||||
regs_buff[21] = 0; /* was idle_errors */
|
||||
e1e_rphy(hw, PHY_1000T_STATUS, &phy_data);
|
||||
regs_buff[24] = (u32)phy_data; /* phy local receiver status */
|
||||
regs_buff[25] = regs_buff[24]; /* phy remote receiver status */
|
||||
|
@ -529,6 +533,9 @@ static int e1000_set_eeprom(struct net_device *netdev,
|
|||
if (eeprom->magic != (adapter->pdev->vendor | (adapter->pdev->device << 16)))
|
||||
return -EFAULT;
|
||||
|
||||
if (adapter->flags & FLAG_READ_ONLY_NVM)
|
||||
return -EINVAL;
|
||||
|
||||
max_len = hw->nvm.word_size * 2;
|
||||
|
||||
first_word = eeprom->offset >> 1;
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#define ICH_FLASH_HSFCTL 0x0006
|
||||
#define ICH_FLASH_FADDR 0x0008
|
||||
#define ICH_FLASH_FDATA0 0x0010
|
||||
#define ICH_FLASH_PR0 0x0074
|
||||
|
||||
#define ICH_FLASH_READ_COMMAND_TIMEOUT 500
|
||||
#define ICH_FLASH_WRITE_COMMAND_TIMEOUT 500
|
||||
|
@ -150,6 +151,19 @@ union ich8_hws_flash_regacc {
|
|||
u16 regval;
|
||||
};
|
||||
|
||||
/* ICH Flash Protected Region */
|
||||
union ich8_flash_protected_range {
|
||||
struct ich8_pr {
|
||||
u32 base:13; /* 0:12 Protected Range Base */
|
||||
u32 reserved1:2; /* 13:14 Reserved */
|
||||
u32 rpe:1; /* 15 Read Protection Enable */
|
||||
u32 limit:13; /* 16:28 Protected Range Limit */
|
||||
u32 reserved2:2; /* 29:30 Reserved */
|
||||
u32 wpe:1; /* 31 Write Protection Enable */
|
||||
} range;
|
||||
u32 regval;
|
||||
};
|
||||
|
||||
static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw);
|
||||
static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw);
|
||||
static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw);
|
||||
|
@ -366,6 +380,9 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static DEFINE_MUTEX(nvm_mutex);
|
||||
static pid_t nvm_owner = -1;
|
||||
|
||||
/**
|
||||
* e1000_acquire_swflag_ich8lan - Acquire software control flag
|
||||
* @hw: pointer to the HW structure
|
||||
|
@ -379,6 +396,15 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
|
|||
u32 extcnf_ctrl;
|
||||
u32 timeout = PHY_CFG_TIMEOUT;
|
||||
|
||||
might_sleep();
|
||||
|
||||
if (!mutex_trylock(&nvm_mutex)) {
|
||||
WARN(1, KERN_ERR "e1000e mutex contention. Owned by pid %d\n",
|
||||
nvm_owner);
|
||||
mutex_lock(&nvm_mutex);
|
||||
}
|
||||
nvm_owner = current->pid;
|
||||
|
||||
while (timeout) {
|
||||
extcnf_ctrl = er32(EXTCNF_CTRL);
|
||||
extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
|
||||
|
@ -393,6 +419,8 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
|
|||
|
||||
if (!timeout) {
|
||||
hw_dbg(hw, "FW or HW has locked the resource for too long.\n");
|
||||
nvm_owner = -1;
|
||||
mutex_unlock(&nvm_mutex);
|
||||
return -E1000_ERR_CONFIG;
|
||||
}
|
||||
|
||||
|
@ -414,6 +442,9 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)
|
|||
extcnf_ctrl = er32(EXTCNF_CTRL);
|
||||
extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
|
||||
ew32(EXTCNF_CTRL, extcnf_ctrl);
|
||||
|
||||
nvm_owner = -1;
|
||||
mutex_unlock(&nvm_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1284,6 +1315,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
|
|||
* programming failed.
|
||||
*/
|
||||
if (ret_val) {
|
||||
/* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */
|
||||
hw_dbg(hw, "Flash commit failed.\n");
|
||||
e1000_release_swflag_ich8lan(hw);
|
||||
return ret_val;
|
||||
|
@ -1373,6 +1405,49 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
|
|||
return e1000e_validate_nvm_checksum_generic(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000e_write_protect_nvm_ich8lan - Make the NVM read-only
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* To prevent malicious write/erase of the NVM, set it to be read-only
|
||||
* so that the hardware ignores all write/erase cycles of the NVM via
|
||||
* the flash control registers. The shadow-ram copy of the NVM will
|
||||
* still be updated, however any updates to this copy will not stick
|
||||
* across driver reloads.
|
||||
**/
|
||||
void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw)
|
||||
{
|
||||
union ich8_flash_protected_range pr0;
|
||||
union ich8_hws_flash_status hsfsts;
|
||||
u32 gfpreg;
|
||||
s32 ret_val;
|
||||
|
||||
ret_val = e1000_acquire_swflag_ich8lan(hw);
|
||||
if (ret_val)
|
||||
return;
|
||||
|
||||
gfpreg = er32flash(ICH_FLASH_GFPREG);
|
||||
|
||||
/* Write-protect GbE Sector of NVM */
|
||||
pr0.regval = er32flash(ICH_FLASH_PR0);
|
||||
pr0.range.base = gfpreg & FLASH_GFPREG_BASE_MASK;
|
||||
pr0.range.limit = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK);
|
||||
pr0.range.wpe = true;
|
||||
ew32flash(ICH_FLASH_PR0, pr0.regval);
|
||||
|
||||
/*
|
||||
* Lock down a subset of GbE Flash Control Registers, e.g.
|
||||
* PR0 to prevent the write-protection from being lifted.
|
||||
* Once FLOCKDN is set, the registers protected by it cannot
|
||||
* be written until FLOCKDN is cleared by a hardware reset.
|
||||
*/
|
||||
hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
|
||||
hsfsts.hsf_status.flockdn = true;
|
||||
ew32flash(ICH_FLASH_HSFSTS, hsfsts.regval);
|
||||
|
||||
e1000_release_swflag_ich8lan(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_write_flash_data_ich8lan - Writes bytes to the NVM
|
||||
* @hw: pointer to the HW structure
|
||||
|
@ -1720,6 +1795,9 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
|
|||
ew32(CTRL, (ctrl | E1000_CTRL_RST));
|
||||
msleep(20);
|
||||
|
||||
/* release the swflag because it is not reset by hardware reset */
|
||||
e1000_release_swflag_ich8lan(hw);
|
||||
|
||||
ret_val = e1000e_get_auto_rd_done(hw);
|
||||
if (ret_val) {
|
||||
/*
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
#include "e1000.h"
|
||||
|
||||
#define DRV_VERSION "0.3.3.3-k2"
|
||||
#define DRV_VERSION "0.3.3.3-k6"
|
||||
char e1000e_driver_name[] = "e1000e";
|
||||
const char e1000e_driver_version[] = DRV_VERSION;
|
||||
|
||||
|
@ -1115,6 +1115,14 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter)
|
|||
writel(0, adapter->hw.hw_addr + rx_ring->tail);
|
||||
}
|
||||
|
||||
static void e1000e_downshift_workaround(struct work_struct *work)
|
||||
{
|
||||
struct e1000_adapter *adapter = container_of(work,
|
||||
struct e1000_adapter, downshift_task);
|
||||
|
||||
e1000e_gig_downshift_workaround_ich8lan(&adapter->hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_intr_msi - Interrupt Handler
|
||||
* @irq: interrupt number
|
||||
|
@ -1139,7 +1147,7 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)
|
|||
*/
|
||||
if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
|
||||
(!(er32(STATUS) & E1000_STATUS_LU)))
|
||||
e1000e_gig_downshift_workaround_ich8lan(hw);
|
||||
schedule_work(&adapter->downshift_task);
|
||||
|
||||
/*
|
||||
* 80003ES2LAN workaround-- For packet buffer work-around on
|
||||
|
@ -1205,7 +1213,7 @@ static irqreturn_t e1000_intr(int irq, void *data)
|
|||
*/
|
||||
if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
|
||||
(!(er32(STATUS) & E1000_STATUS_LU)))
|
||||
e1000e_gig_downshift_workaround_ich8lan(hw);
|
||||
schedule_work(&adapter->downshift_task);
|
||||
|
||||
/*
|
||||
* 80003ES2LAN workaround--
|
||||
|
@ -2592,8 +2600,6 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
|
|||
/* Explicitly disable IRQ since the NIC can be in any state. */
|
||||
e1000_irq_disable(adapter);
|
||||
|
||||
spin_lock_init(&adapter->stats_lock);
|
||||
|
||||
set_bit(__E1000_DOWN, &adapter->state);
|
||||
return 0;
|
||||
|
||||
|
@ -2912,6 +2918,21 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000e_update_phy_task - work thread to update phy
|
||||
* @work: pointer to our work struct
|
||||
*
|
||||
* this worker thread exists because we must acquire a
|
||||
* semaphore to read the phy, which we could msleep while
|
||||
* waiting for it, and we can't msleep in a timer.
|
||||
**/
|
||||
static void e1000e_update_phy_task(struct work_struct *work)
|
||||
{
|
||||
struct e1000_adapter *adapter = container_of(work,
|
||||
struct e1000_adapter, update_phy_task);
|
||||
e1000_get_phy_info(&adapter->hw);
|
||||
}
|
||||
|
||||
/*
|
||||
* Need to wait a few seconds after link up to get diagnostic information from
|
||||
* the phy
|
||||
|
@ -2919,7 +2940,7 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
|
|||
static void e1000_update_phy_info(unsigned long data)
|
||||
{
|
||||
struct e1000_adapter *adapter = (struct e1000_adapter *) data;
|
||||
e1000_get_phy_info(&adapter->hw);
|
||||
schedule_work(&adapter->update_phy_task);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2930,10 +2951,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
|
|||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
unsigned long irq_flags;
|
||||
u16 phy_tmp;
|
||||
|
||||
#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
|
||||
|
||||
/*
|
||||
* Prevent stats update while adapter is being reset, or if the pci
|
||||
|
@ -2944,14 +2961,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
|
|||
if (pci_channel_offline(pdev))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&adapter->stats_lock, irq_flags);
|
||||
|
||||
/*
|
||||
* these counters are modified from e1000_adjust_tbi_stats,
|
||||
* called from the interrupt context, so they must only
|
||||
* be written while holding adapter->stats_lock
|
||||
*/
|
||||
|
||||
adapter->stats.crcerrs += er32(CRCERRS);
|
||||
adapter->stats.gprc += er32(GPRC);
|
||||
adapter->stats.gorc += er32(GORCL);
|
||||
|
@ -3022,21 +3031,10 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
|
|||
|
||||
/* Tx Dropped needs to be maintained elsewhere */
|
||||
|
||||
/* Phy Stats */
|
||||
if (hw->phy.media_type == e1000_media_type_copper) {
|
||||
if ((adapter->link_speed == SPEED_1000) &&
|
||||
(!e1e_rphy(hw, PHY_1000T_STATUS, &phy_tmp))) {
|
||||
phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
|
||||
adapter->phy_stats.idle_errors += phy_tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Management Stats */
|
||||
adapter->stats.mgptc += er32(MGTPTC);
|
||||
adapter->stats.mgprc += er32(MGTPRC);
|
||||
adapter->stats.mgpdc += er32(MGTPDC);
|
||||
|
||||
spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3048,10 +3046,6 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)
|
|||
struct e1000_hw *hw = &adapter->hw;
|
||||
struct e1000_phy_regs *phy = &adapter->phy_regs;
|
||||
int ret_val;
|
||||
unsigned long irq_flags;
|
||||
|
||||
|
||||
spin_lock_irqsave(&adapter->stats_lock, irq_flags);
|
||||
|
||||
if ((er32(STATUS) & E1000_STATUS_LU) &&
|
||||
(adapter->hw.phy.media_type == e1000_media_type_copper)) {
|
||||
|
@ -3082,8 +3076,6 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)
|
|||
phy->stat1000 = 0;
|
||||
phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
|
||||
}
|
||||
|
||||
static void e1000_print_link_info(struct e1000_adapter *adapter)
|
||||
|
@ -4467,6 +4459,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
|
|||
|
||||
adapter->bd_number = cards_found++;
|
||||
|
||||
e1000e_check_options(adapter);
|
||||
|
||||
/* setup adapter struct */
|
||||
err = e1000_sw_init(adapter);
|
||||
if (err)
|
||||
|
@ -4482,6 +4476,10 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
|
|||
if (err)
|
||||
goto err_hw_init;
|
||||
|
||||
if ((adapter->flags & FLAG_IS_ICH) &&
|
||||
(adapter->flags & FLAG_READ_ONLY_NVM))
|
||||
e1000e_write_protect_nvm_ich8lan(&adapter->hw);
|
||||
|
||||
hw->mac.ops.get_bus_info(&adapter->hw);
|
||||
|
||||
adapter->hw.phy.autoneg_wait_to_complete = 0;
|
||||
|
@ -4572,8 +4570,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
|
|||
|
||||
INIT_WORK(&adapter->reset_task, e1000_reset_task);
|
||||
INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task);
|
||||
|
||||
e1000e_check_options(adapter);
|
||||
INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround);
|
||||
INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task);
|
||||
|
||||
/* Initialize link parameters. User can change them with ethtool */
|
||||
adapter->hw.mac.autoneg = 1;
|
||||
|
|
|
@ -133,6 +133,15 @@ E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
|
|||
*/
|
||||
E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround");
|
||||
|
||||
/*
|
||||
* Write Protect NVM
|
||||
*
|
||||
* Valid Range: 0, 1
|
||||
*
|
||||
* Default Value: 1 (enabled)
|
||||
*/
|
||||
E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]");
|
||||
|
||||
struct e1000_option {
|
||||
enum { enable_option, range_option, list_option } type;
|
||||
const char *name;
|
||||
|
@ -388,4 +397,25 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
|
|||
opt.def);
|
||||
}
|
||||
}
|
||||
{ /* Write-protect NVM */
|
||||
const struct e1000_option opt = {
|
||||
.type = enable_option,
|
||||
.name = "Write-protect NVM",
|
||||
.err = "defaulting to Enabled",
|
||||
.def = OPTION_ENABLED
|
||||
};
|
||||
|
||||
if (adapter->flags & FLAG_IS_ICH) {
|
||||
if (num_WriteProtectNVM > bd) {
|
||||
unsigned int write_protect_nvm = WriteProtectNVM[bd];
|
||||
e1000_validate_option(&write_protect_nvm, &opt,
|
||||
adapter);
|
||||
if (write_protect_nvm)
|
||||
adapter->flags |= FLAG_READ_ONLY_NVM;
|
||||
} else {
|
||||
if (opt.def)
|
||||
adapter->flags |= FLAG_READ_ONLY_NVM;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/topology.h>
|
||||
|
@ -484,6 +485,21 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
|
|||
#endif /* HAVE_PCI_LEGACY */
|
||||
|
||||
#ifdef HAVE_PCI_MMAP
|
||||
|
||||
static int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma)
|
||||
{
|
||||
unsigned long nr, start, size;
|
||||
|
||||
nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
|
||||
start = vma->vm_pgoff;
|
||||
size = pci_resource_len(pdev, resno) >> PAGE_SHIFT;
|
||||
if (start < size && size - start >= nr)
|
||||
return 1;
|
||||
WARN(1, "process \"%s\" tried to map 0x%08lx-0x%08lx on %s BAR %d (size 0x%08lx)\n",
|
||||
current->comm, start, start+nr, pci_name(pdev), resno, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_mmap_resource - map a PCI resource into user memory space
|
||||
* @kobj: kobject for mapping
|
||||
|
@ -510,6 +526,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
|
|||
if (i >= PCI_ROM_RESOURCE)
|
||||
return -ENODEV;
|
||||
|
||||
if (!pci_mmap_fits(pdev, i, vma))
|
||||
return -EINVAL;
|
||||
|
||||
/* pci_mmap_page_range() expects the same kind of entry as coming
|
||||
* from /proc/bus/pci/ which is a "user visible" value. If this is
|
||||
* different from the resource itself, arch will do necessary fixup.
|
||||
|
|
|
@ -422,6 +422,12 @@ done:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int rtc_dev_fasync(int fd, struct file *file, int on)
|
||||
{
|
||||
struct rtc_device *rtc = file->private_data;
|
||||
return fasync_helper(fd, file, on, &rtc->async_queue);
|
||||
}
|
||||
|
||||
static int rtc_dev_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct rtc_device *rtc = file->private_data;
|
||||
|
@ -434,16 +440,13 @@ static int rtc_dev_release(struct inode *inode, struct file *file)
|
|||
if (rtc->ops->release)
|
||||
rtc->ops->release(rtc->dev.parent);
|
||||
|
||||
if (file->f_flags & FASYNC)
|
||||
rtc_dev_fasync(-1, file, 0);
|
||||
|
||||
clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtc_dev_fasync(int fd, struct file *file, int on)
|
||||
{
|
||||
struct rtc_device *rtc = file->private_data;
|
||||
return fasync_helper(fd, file, on, &rtc->async_queue);
|
||||
}
|
||||
|
||||
static const struct file_operations rtc_dev_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
|
|
|
@ -447,51 +447,36 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr,
|
|||
{
|
||||
char s[80];
|
||||
|
||||
sprintf(s, "%s sc:%x ", cdev->dev.bus_id, irq_ptr->schid.sch_no);
|
||||
|
||||
sprintf(s, "qdio: %s ", dev_name(&cdev->dev));
|
||||
switch (irq_ptr->qib.qfmt) {
|
||||
case QDIO_QETH_QFMT:
|
||||
sprintf(s + strlen(s), "OSADE ");
|
||||
sprintf(s + strlen(s), "OSA ");
|
||||
break;
|
||||
case QDIO_ZFCP_QFMT:
|
||||
sprintf(s + strlen(s), "ZFCP ");
|
||||
break;
|
||||
case QDIO_IQDIO_QFMT:
|
||||
sprintf(s + strlen(s), "HiperSockets ");
|
||||
sprintf(s + strlen(s), "HS ");
|
||||
break;
|
||||
}
|
||||
sprintf(s + strlen(s), "using: ");
|
||||
|
||||
if (!is_thinint_irq(irq_ptr))
|
||||
sprintf(s + strlen(s), "no");
|
||||
sprintf(s + strlen(s), "AdapterInterrupts ");
|
||||
if (!(irq_ptr->sch_token != 0))
|
||||
sprintf(s + strlen(s), "no");
|
||||
sprintf(s + strlen(s), "QEBSM ");
|
||||
if (!(irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED))
|
||||
sprintf(s + strlen(s), "no");
|
||||
sprintf(s + strlen(s), "OutboundPCI ");
|
||||
if (!css_general_characteristics.aif_tdd)
|
||||
sprintf(s + strlen(s), "no");
|
||||
sprintf(s + strlen(s), "TDD\n");
|
||||
printk(KERN_INFO "qdio: %s", s);
|
||||
|
||||
memset(s, 0, sizeof(s));
|
||||
sprintf(s, "%s SIGA required: ", cdev->dev.bus_id);
|
||||
if (irq_ptr->siga_flag.input)
|
||||
sprintf(s + strlen(s), "Read ");
|
||||
if (irq_ptr->siga_flag.output)
|
||||
sprintf(s + strlen(s), "Write ");
|
||||
if (irq_ptr->siga_flag.sync)
|
||||
sprintf(s + strlen(s), "Sync ");
|
||||
if (!irq_ptr->siga_flag.no_sync_ti)
|
||||
sprintf(s + strlen(s), "SyncAI ");
|
||||
if (!irq_ptr->siga_flag.no_sync_out_ti)
|
||||
sprintf(s + strlen(s), "SyncOutAI ");
|
||||
if (!irq_ptr->siga_flag.no_sync_out_pci)
|
||||
sprintf(s + strlen(s), "SyncOutPCI");
|
||||
sprintf(s + strlen(s), "on SC %x using ", irq_ptr->schid.sch_no);
|
||||
sprintf(s + strlen(s), "AI:%d ", is_thinint_irq(irq_ptr));
|
||||
sprintf(s + strlen(s), "QEBSM:%d ", (irq_ptr->sch_token) ? 1 : 0);
|
||||
sprintf(s + strlen(s), "PCI:%d ",
|
||||
(irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED) ? 1 : 0);
|
||||
sprintf(s + strlen(s), "TDD:%d ", css_general_characteristics.aif_tdd);
|
||||
sprintf(s + strlen(s), "SIGA:");
|
||||
sprintf(s + strlen(s), "%s", (irq_ptr->siga_flag.input) ? "R" : " ");
|
||||
sprintf(s + strlen(s), "%s", (irq_ptr->siga_flag.output) ? "W" : " ");
|
||||
sprintf(s + strlen(s), "%s", (irq_ptr->siga_flag.sync) ? "S" : " ");
|
||||
sprintf(s + strlen(s), "%s",
|
||||
(!irq_ptr->siga_flag.no_sync_ti) ? "A" : " ");
|
||||
sprintf(s + strlen(s), "%s",
|
||||
(!irq_ptr->siga_flag.no_sync_out_ti) ? "O" : " ");
|
||||
sprintf(s + strlen(s), "%s",
|
||||
(!irq_ptr->siga_flag.no_sync_out_pci) ? "P" : " ");
|
||||
sprintf(s + strlen(s), "\n");
|
||||
printk(KERN_INFO "qdio: %s", s);
|
||||
printk(KERN_INFO "%s", s);
|
||||
}
|
||||
|
||||
int __init qdio_setup_init(void)
|
||||
|
|
|
@ -427,7 +427,7 @@ static int orion_spi_transfer(struct spi_device *spi, struct spi_message *m)
|
|||
goto msg_rejected;
|
||||
}
|
||||
|
||||
if (t->speed_hz < orion_spi->min_speed) {
|
||||
if (t->speed_hz && t->speed_hz < orion_spi->min_speed) {
|
||||
dev_err(&spi->dev,
|
||||
"message rejected : "
|
||||
"device min speed (%d Hz) exceeds "
|
||||
|
|
|
@ -49,7 +49,7 @@ MODULE_ALIAS("platform:pxa2xx-spi");
|
|||
|
||||
#define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
|
||||
#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)
|
||||
#define IS_DMA_ALIGNED(x) (((x) & 0x07) == 0)
|
||||
#define IS_DMA_ALIGNED(x) ((((u32)(x)) & 0x07) == 0)
|
||||
#define MAX_DMA_LEN 8191
|
||||
|
||||
/*
|
||||
|
@ -896,7 +896,7 @@ static void pump_transfers(unsigned long data)
|
|||
|| transfer->rx_dma || transfer->tx_dma) {
|
||||
dev_err(&drv_data->pdev->dev,
|
||||
"pump_transfers: mapped transfer length "
|
||||
"of %lu is greater than %d\n",
|
||||
"of %u is greater than %d\n",
|
||||
transfer->len, MAX_DMA_LEN);
|
||||
message->status = -EINVAL;
|
||||
giveback(drv_data);
|
||||
|
|
|
@ -2400,11 +2400,15 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
|
|||
|
||||
if (!fbcon_is_inactive(vc, info)) {
|
||||
if (ops->blank_state != blank) {
|
||||
int ret = 1;
|
||||
|
||||
ops->blank_state = blank;
|
||||
fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
|
||||
ops->cursor_flash = (!blank);
|
||||
|
||||
if (fb_blank(info, blank))
|
||||
if (info->fbops->fb_blank)
|
||||
ret = info->fbops->fb_blank(blank, info);
|
||||
if (ret)
|
||||
fbcon_generic_blank(vc, info, blank);
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue