“9f05f6a921353f4293cda37f221b9bfa532d3c57”上不存在“arch/arm/mach-s3c24xx/mach-osiris.c”
提交 0ce49a39 编写于 作者: P Paul Mackerras

Merge branch 'linux-2.6'

......@@ -166,7 +166,7 @@ To solve this problem, you really only have two options:
The option of being unfailingly polite really doesn't exist. Nobody will
trust somebody who is so clearly hiding his true character.
(*) Paul Simon sang "Fifty Ways to Lose Your Lover", because quite
(*) Paul Simon sang "Fifty Ways to Leave Your Lover", because quite
frankly, "A Million Ways to Tell a Developer He Is a D*ckhead" doesn't
scan nearly as well. But I'm sure he thought about it.
......
......@@ -298,3 +298,11 @@ Why: All mthca hardware also supports MSI-X, which provides
Who: Roland Dreier <rolandd@cisco.com>
---------------------------
What: sk98lin network driver
When: Feburary 2008
Why: In kernel tree version of driver is unmaintained. Sk98lin driver
replaced by the skge driver.
Who: Stephen Hemminger <shemminger@linux-foundation.org>
---------------------------
......@@ -468,9 +468,6 @@ and is between 256 and 4096 characters. It is defined in the file
Format:
<first_slot>,<last_slot>,<port>,<enum_bit>[,<debug>]
cpia_pp= [HW,PPT]
Format: { parport<nr> | auto | none }
crashkernel=nn[KMG]@ss[KMG]
[KNL] Reserve a chunk of physical memory to
hold a kernel to switch to with kexec on panic.
......
......@@ -96,6 +96,9 @@ routing.txt
- the new routing mechanism
shaper.txt
- info on the module that can shape/limit transmitted traffic.
sk98lin.txt
- Marvell Yukon Chipset / SysKonnect SK-98xx compliant Gigabit
Ethernet Adapter family driver info
skfp.txt
- SysKonnect FDDI (SK-5xxx, Compaq Netelligent) driver info.
smc9.txt
......
此差异已折叠。
ThinkPad ACPI Extras Driver
Version 0.15
July 1st, 2007
Version 0.16
August 2nd, 2007
Borislav Deianov <borislav@users.sf.net>
Henrique de Moraes Holschuh <hmh@hmh.eng.br>
......@@ -161,20 +161,22 @@ system. Enabling the hotkey functionality of thinkpad-acpi signals the
firmware that such a driver is present, and modifies how the ThinkPad
firmware will behave in many situations.
The driver enables the hot key feature automatically when loaded. The
feature can later be disabled and enabled back at runtime. The driver
will also restore the hot key feature to its previous state and mask
when it is unloaded.
When the hotkey feature is enabled and the hot key mask is set (see
below), the various hot keys either generate ACPI events in the
following format:
below), the driver will report HKEY events in the following format:
ibm/hotkey HKEY 00000080 0000xxxx
or events over the input layer. The input layer support accepts the
standard IOCTLs to remap the keycodes assigned to each hotkey.
Some of these events refer to hot key presses, but not all.
When the input device is open, the driver will suppress any ACPI hot key
events that get translated into a meaningful input layer event, in order
to avoid sending duplicate events to userspace. Hot keys that are
mapped to KEY_RESERVED in the keymap are not translated, and will always
generate an ACPI ibm/hotkey HKEY event, and no input layer events.
The driver will generate events over the input layer for hot keys and
radio switches, and over the ACPI netlink layer for other events. The
input layer support accepts the standard IOCTLs to remap the keycodes
assigned to each hot key.
The hot key bit mask allows some control over which hot keys generate
events. If a key is "masked" (bit set to 0 in the mask), the firmware
......@@ -256,6 +258,20 @@ sysfs notes:
disabled" postition, and 1 if the switch is in the
"radios enabled" position.
hotkey_report_mode:
Returns the state of the procfs ACPI event report mode
filter for hot keys. If it is set to 1 (the default),
all hot key presses are reported both through the input
layer and also as ACPI events through procfs (but not
through netlink). If it is set to 2, hot key presses
are reported only through the input layer.
This attribute is read-only in kernels 2.6.23 or later,
and read-write on earlier kernels.
May return -EPERM (write access locked out by module
parameter) or -EACCES (read-only).
input layer notes:
A Hot key is mapped to a single input layer EV_KEY event, possibly
......@@ -393,21 +409,63 @@ unknown by the driver if the ThinkPad firmware triggered these events on
hot key press or release, but the firmware will do it for either one, not
both.
If a key is mapped to KEY_RESERVED, it generates no input events at all,
and it may generate a legacy thinkpad-acpi ACPI hotkey event.
If a key is mapped to KEY_RESERVED, it generates no input events at all.
If a key is mapped to KEY_UNKNOWN, it generates an input event that
includes an scan code, and it may also generate a legacy thinkpad-acpi
ACPI hotkey event.
If a key is mapped to anything else, it will only generate legacy
thinkpad-acpi ACPI hotkey events if nobody has opened the input device.
includes an scan code. If a key is mapped to anything else, it will
generate input device EV_KEY events.
Non hot-key ACPI HKEY event map:
0x5001 Lid closed
0x5002 Lid opened
0x7000 Radio Switch may have changed state
The above events are not propagated by the driver, except for legacy
compatibility purposes when hotkey_report_mode is set to 1.
Compatibility notes:
ibm-acpi and thinkpad-acpi 0.15 (mainline kernels before 2.6.23) never
supported the input layer, and sent events over the procfs ACPI event
interface.
To avoid sending duplicate events over the input layer and the ACPI
event interface, thinkpad-acpi 0.16 implements a module parameter
(hotkey_report_mode), and also a sysfs device attribute with the same
name.
Make no mistake here: userspace is expected to switch to using the input
layer interface of thinkpad-acpi, together with the ACPI netlink event
interface in kernels 2.6.23 and later, or with the ACPI procfs event
interface in kernels 2.6.22 and earlier.
If no hotkey_report_mode module parameter is specified (or it is set to
zero), the driver defaults to mode 1 (see below), and on kernels 2.6.22
and earlier, also allows one to change the hotkey_report_mode through
sysfs. In kernels 2.6.23 and later, where the netlink ACPI event
interface is available, hotkey_report_mode cannot be changed through
sysfs (it is read-only).
If the hotkey_report_mode module parameter is set to 1 or 2, it cannot
be changed later through sysfs (any writes will return -EPERM to signal
that hotkey_report_mode was locked. On 2.6.23 and later, where
hotkey_report_mode cannot be changed at all, writes will return -EACES).
hotkey_report_mode set to 1 makes the driver export through the procfs
ACPI event interface all hot key presses (which are *also* sent to the
input layer). This is a legacy compatibility behaviour, and it is also
the default mode of operation for the driver.
hotkey_report_mode set to 2 makes the driver filter out the hot key
presses from the procfs ACPI event interface, so these events will only
be sent through the input layer. Userspace that has been updated to use
the thinkpad-acpi input layer interface should set hotkey_report_mode to
2.
Hot key press events are never sent to the ACPI netlink event interface.
Really up-to-date userspace under kernel 2.6.23 and later is to use the
netlink interface and the input layer interface, and don't bother at all
with hotkey_report_mode.
Bluetooth
---------
......
......@@ -407,8 +407,10 @@ Description
u32 length; // Length of this frame
u32 offset_low; // Offset in the file of the
u32 offset_high; // start of this frame
u32 mask1; // Bits 0-1 are the type mask:
u32 mask1; // Bits 0-2 are the type mask:
// 1=I, 2=P, 4=B
// 0=End of Program Index, other fields
// are invalid.
u32 pts; // The PTS of the frame
u32 mask2; // Bit 0 is bit 32 of the pts.
};
......
......@@ -165,7 +165,7 @@ static void __init gic_init_irq(void)
#endif
gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29);
gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE));
#ifdef CONFIG_REALVIEW_MPCORE
#if defined(CONFIG_REALVIEW_MPCORE) && !defined(CONFIG_REALVIEW_MPCORE_REVB)
gic_dist_init(1, __io_address(REALVIEW_GIC1_DIST_BASE), 64);
gic_cpu_init(1, __io_address(REALVIEW_GIC1_CPU_BASE));
gic_cascade_irq(1, IRQ_EB_IRQ1);
......
......@@ -323,6 +323,7 @@ static int __init vfp_init(void)
* we just need to read the VFPSID register.
*/
vfp_vector = vfp_testing_entry;
barrier();
vfpsid = fmrx(FPSID);
barrier();
vfp_vector = vfp_null_entry;
......
......@@ -158,10 +158,16 @@ static int bfin_pm_finish(suspend_state_t state)
return 0;
}
static int bfin_pm_valid(suspend_state_t state)
{
return (state == PM_SUSPEND_STANDBY);
}
struct pm_ops bfin_pm_ops = {
.prepare = bfin_pm_prepare,
.enter = bfin_pm_enter,
.finish = bfin_pm_finish,
.valid = bfin_pm_valid,
};
static int __init bfin_pm_init(void)
......
......@@ -623,8 +623,8 @@ static unsigned long xen_read_cr2_direct(void)
static void xen_write_cr4(unsigned long cr4)
{
/* never allow TSC to be disabled */
native_write_cr4(cr4 & ~X86_CR4_TSD);
/* Just ignore cr4 changes; Xen doesn't allow us to do
anything anyway. */
}
static unsigned long xen_read_cr3(void)
......
......@@ -55,7 +55,7 @@ EXPORT_SYMBOL(dec_kn_slot_size);
int dec_tc_bus;
spinlock_t ioasic_ssr_lock;
DEFINE_SPINLOCK(ioasic_ssr_lock);
volatile u32 *ioasic_base;
......
/*
* Copyright (C) 2003, 2004 Maciej W. Rozycki
* Copyright (C) 2003, 2004, 2007 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
......@@ -29,7 +29,7 @@ static inline void align_mod(const int align, const int mod)
".endr\n\t"
".set pop"
:
: "rn" (align), "rn" (mod));
: GCC_IMM_ASM (align), GCC_IMM_ASM (mod));
}
static inline void mult_sh_align_mod(long *v1, long *v2, long *w,
......
......@@ -199,7 +199,14 @@ static inline void check_wait(void)
if ((c->processor_id & 0xff) <= 0x64)
break;
cpu_wait = r4k_wait;
/*
* Another rev is incremeting c0_count at a reduced clock
* rate while in WAIT mode. So we basically have the choice
* between using the cp0 timer as clocksource or avoiding
* the WAIT instruction. Until more details are known,
* disable the use of WAIT for 20Kc entirely.
cpu_wait = r4k_wait;
*/
break;
case CPU_RM9000:
if ((c->processor_id & 0x00ff) >= 0x40)
......
......@@ -56,8 +56,6 @@ static struct chan_waitqueues {
struct mutex mutex;
} channel_wqs[RTLX_CHANNELS];
static struct irqaction irq;
static int irq_num;
static struct vpe_notifications notify;
static int sp_stopping = 0;
......@@ -111,7 +109,7 @@ static void __used dump_rtlx(void)
static int rtlx_init(struct rtlx_info *rtlxi)
{
if (rtlxi->id != RTLX_ID) {
printk(KERN_ERR "no valid RTLX id at 0x%p 0x%x\n", rtlxi, rtlxi->id);
printk(KERN_ERR "no valid RTLX id at 0x%p 0x%lx\n", rtlxi, rtlxi->id);
return -ENOEXEC;
}
......
......@@ -375,7 +375,7 @@ EXPORT(sysn32_call_table)
PTR sys_mkdirat
PTR sys_mknodat
PTR sys_fchownat
PTR sys_futimesat /* 6255 */
PTR compat_sys_futimesat /* 6255 */
PTR sys_newfstatat
PTR sys_unlinkat
PTR sys_renameat
......
......@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/param.h>
#include <linux/profile.h>
#include <linux/time.h>
#include <linux/timex.h>
#include <linux/smp.h>
......
......@@ -256,7 +256,7 @@ asmlinkage void plat_irq_dispatch(void)
if (irq == MIPSCPU_INT_I8259A)
malta_hw0_irqdispatch();
else if (irq > 0)
else if (irq >= 0)
do_IRQ(MIPS_CPU_IRQ_BASE + irq);
else
spurious_interrupt();
......
......@@ -57,6 +57,21 @@ static __init int __maybe_unused r10000_llsc_war(void)
return R10000_LLSC_WAR;
}
/*
* Found by experiment: At least some revisions of the 4kc throw under
* some circumstances a machine check exception, triggered by invalid
* values in the index register. Delaying the tlbp instruction until
* after the next branch, plus adding an additional nop in front of
* tlbwi/tlbwr avoids the invalid index register values. Nobody knows
* why; it's not an issue caused by the core RTL.
*
*/
static __init int __attribute__((unused)) m4kc_tlbp_war(void)
{
return (current_cpu_data.processor_id & 0xffff00) ==
(PRID_COMP_MIPS | PRID_IMP_4KC);
}
/*
* A little micro-assembler, intended for TLB refill handler
* synthesizing. It is intentionally kept simple, does only support
......@@ -894,6 +909,8 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l,
case CPU_20KC:
case CPU_25KF:
case CPU_LOONGSON2:
if (m4kc_tlbp_war())
i_nop(p);
tlbw(p);
break;
......@@ -1705,7 +1722,8 @@ build_r4000_tlbchange_handler_head(u32 **p, struct label **l,
l_smp_pgtable_change(l, *p);
# endif
iPTE_LW(p, l, pte, ptr); /* get even pte */
build_tlb_probe_entry(p);
if (!m4kc_tlbp_war())
build_tlb_probe_entry(p);
}
static void __init
......@@ -1747,6 +1765,8 @@ static void __init build_r4000_tlb_load_handler(void)
build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl);
if (m4kc_tlbp_war())
build_tlb_probe_entry(&p);
build_make_valid(&p, &r, K0, K1);
build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
......@@ -1781,6 +1801,8 @@ static void __init build_r4000_tlb_store_handler(void)
build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
build_pte_writable(&p, &l, &r, K0, K1, label_nopage_tlbs);
if (m4kc_tlbp_war())
build_tlb_probe_entry(&p);
build_make_write(&p, &r, K0, K1);
build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
......@@ -1815,6 +1837,8 @@ static void __init build_r4000_tlb_modify_handler(void)
build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm);
if (m4kc_tlbp_war())
build_tlb_probe_entry(&p);
/* Present and writable bits set, set accessed and dirty bits. */
build_make_write(&p, &r, K0, K1);
build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
......
......@@ -238,7 +238,7 @@ static void snapshot_tb_and_purr(void *data)
struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data);
local_irq_save(flags);
p->tb = mftb();
p->tb = get_tb_or_rtc();
p->purr = mfspr(SPRN_PURR);
wmb();
p->initialized = 1;
......@@ -316,7 +316,7 @@ static void snapshot_purr(void)
*/
void snapshot_timebase(void)
{
__get_cpu_var(last_jiffy) = get_tb();
__get_cpu_var(last_jiffy) = get_tb_or_rtc();
snapshot_purr();
}
......@@ -683,6 +683,8 @@ void timer_interrupt(struct pt_regs * regs)
write_seqlock(&xtime_lock);
tb_next_jiffy = tb_last_jiffy + tb_ticks_per_jiffy;
if (__USE_RTC() && tb_next_jiffy >= 1000000000)
tb_next_jiffy -= 1000000000;
if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) {
tb_last_jiffy = tb_next_jiffy;
do_timer(1);
......@@ -976,7 +978,7 @@ void __init time_init(void)
tb_to_ns_scale = scale;
tb_to_ns_shift = shift;
/* Save the current timebase to pretty up CONFIG_PRINTK_TIME */
boot_tb = get_tb();
boot_tb = get_tb_or_rtc();
tm = get_boot_time();
......
......@@ -98,6 +98,18 @@ static struct vdso_patch_def vdso_patches[] = {
CPU_FTR_USE_TB, 0,
"__kernel_gettimeofday", NULL
},
{
CPU_FTR_USE_TB, 0,
"__kernel_clock_gettime", NULL
},
{
CPU_FTR_USE_TB, 0,
"__kernel_clock_getres", NULL
},
{
CPU_FTR_USE_TB, 0,
"__kernel_get_tbfreq", NULL
},
};
/*
......
......@@ -594,7 +594,7 @@ static struct spu *find_victim(struct spu_context *ctx)
list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) {
struct spu_context *tmp = spu->ctx;
if (tmp->prio > ctx->prio &&
if (tmp && tmp->prio > ctx->prio &&
(!victim || tmp->prio > victim->prio))
victim = spu->ctx;
}
......@@ -626,9 +626,9 @@ static struct spu *find_victim(struct spu_context *ctx)
mutex_lock(&cbe_spu_info[node].list_mutex);
cbe_spu_info[node].nr_active--;
spu_unbind_context(spu, victim);
mutex_unlock(&cbe_spu_info[node].list_mutex);
spu_unbind_context(spu, victim);
victim->stats.invol_ctx_switch++;
spu->stats.invol_ctx_switch++;
mutex_unlock(&victim->state_mutex);
......
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.23-rc1
# Sun Jul 22 19:24:37 2007
# Linux kernel version: 2.6.23-rc6
# Sun Sep 16 09:52:11 2007
#
CONFIG_SPARC=y
CONFIG_SPARC64=y
......@@ -32,15 +32,11 @@ CONFIG_HZ=100
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
# Code maturity level options
# General setup
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
#
CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SWAP=y
......@@ -555,6 +551,7 @@ CONFIG_E1000_NAPI=y
# CONFIG_SIS190 is not set
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=m
CONFIG_BNX2=m
......@@ -809,6 +806,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_THMC50 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_VT1211 is not set
# CONFIG_SENSORS_VT8231 is not set
......@@ -1162,10 +1160,6 @@ CONFIG_USB_STORAGE=m
# CONFIG_MMC is not set
# CONFIG_NEW_LEDS is not set
# CONFIG_INFINIBAND is not set
#
# Real Time Clock
#
# CONFIG_RTC_CLASS is not set
#
......
......@@ -98,7 +98,7 @@ sparc64_boot:
.globl prom_boot_mapped_pc, prom_boot_mapping_mode
.globl prom_boot_mapping_phys_high, prom_boot_mapping_phys_low
.globl prom_compatible_name, prom_cpu_path, prom_cpu_compatible
.globl is_sun4v, sun4v_chip_type
.globl is_sun4v, sun4v_chip_type, prom_set_trap_table_name
prom_peer_name:
.asciz "peer"
prom_compatible_name:
......@@ -121,6 +121,8 @@ prom_map_name:
.asciz "map"
prom_unmap_name:
.asciz "unmap"
prom_set_trap_table_name:
.asciz "SUNW,set-trap-table"
prom_sun4v_name:
.asciz "sun4v"
prom_niagara_prefix:
......@@ -691,15 +693,38 @@ setup_trap_table:
sethi %hi(kern_base), %g3
ldx [%g3 + %lo(kern_base)], %g3
add %g2, %g3, %o1
sethi %hi(sparc64_ttable_tl0), %o0
call prom_set_trap_table_sun4v
sethi %hi(sparc64_ttable_tl0), %o0
set prom_set_trap_table_name, %g2
stx %g2, [%sp + 2047 + 128 + 0x00]
mov 2, %g2
stx %g2, [%sp + 2047 + 128 + 0x08]
mov 0, %g2
stx %g2, [%sp + 2047 + 128 + 0x10]
stx %o0, [%sp + 2047 + 128 + 0x18]
stx %o1, [%sp + 2047 + 128 + 0x20]
sethi %hi(p1275buf), %g2
or %g2, %lo(p1275buf), %g2
ldx [%g2 + 0x08], %o1
call %o1
add %sp, (2047 + 128), %o0
ba,pt %xcc, 2f
nop
1: call prom_set_trap_table
sethi %hi(sparc64_ttable_tl0), %o0
1: sethi %hi(sparc64_ttable_tl0), %o0
set prom_set_trap_table_name, %g2
stx %g2, [%sp + 2047 + 128 + 0x00]
mov 1, %g2
stx %g2, [%sp + 2047 + 128 + 0x08]
mov 0, %g2
stx %g2, [%sp + 2047 + 128 + 0x10]
stx %o0, [%sp + 2047 + 128 + 0x18]
sethi %hi(p1275buf), %g2
or %g2, %lo(p1275buf), %g2
ldx [%g2 + 0x08], %o1
call %o1
add %sp, (2047 + 128), %o0
/* Start using proper page size encodings in ctx register. */
2: sethi %hi(sparc64_kern_pri_context), %g3
......
......@@ -777,8 +777,12 @@ void __devinit mdesc_fill_in_cpu_data(cpumask_t mask)
cpuid = *id;
#ifdef CONFIG_SMP
if (cpuid >= NR_CPUS)
if (cpuid >= NR_CPUS) {
printk(KERN_WARNING "Ignoring CPU %d which is "
">= NR_CPUS (%d)\n",
cpuid, NR_CPUS);
continue;
}
if (!cpu_isset(cpuid, mask))
continue;
#else
......
......@@ -1583,8 +1583,12 @@ static void __init of_fill_in_cpu_data(void)
ncpus_probed++;
#ifdef CONFIG_SMP
if (cpuid >= NR_CPUS)
if (cpuid >= NR_CPUS) {
printk(KERN_WARNING "Ignoring CPU %d which is "
">= NR_CPUS (%d)\n",
cpuid, NR_CPUS);
continue;
}
#else
/* On uniprocessor we only want the values for the
* real physical cpu the kernel booted onto, however
......
......@@ -345,7 +345,7 @@ after_lock_tlb:
sethi %hi(tramp_stack), %g1
or %g1, %lo(tramp_stack), %g1
add %g1, TRAMP_STACK_SIZE, %g1
sub %g1, STACKFRAME_SZ + STACK_BIAS, %sp
sub %g1, STACKFRAME_SZ + STACK_BIAS + 256, %sp
mov 0, %fp
/* Put garbage in these registers to trap any access to them. */
......@@ -411,15 +411,38 @@ after_lock_tlb:
sethi %hi(kern_base), %g3
ldx [%g3 + %lo(kern_base)], %g3
add %g2, %g3, %o1
sethi %hi(sparc64_ttable_tl0), %o0
call prom_set_trap_table_sun4v
sethi %hi(sparc64_ttable_tl0), %o0
set prom_set_trap_table_name, %g2
stx %g2, [%sp + 2047 + 128 + 0x00]
mov 2, %g2
stx %g2, [%sp + 2047 + 128 + 0x08]
mov 0, %g2
stx %g2, [%sp + 2047 + 128 + 0x10]
stx %o0, [%sp + 2047 + 128 + 0x18]
stx %o1, [%sp + 2047 + 128 + 0x20]
sethi %hi(p1275buf), %g2
or %g2, %lo(p1275buf), %g2
ldx [%g2 + 0x08], %o1
call %o1
add %sp, (2047 + 128), %o0
ba,pt %xcc, 2f
nop
1: call prom_set_trap_table
sethi %hi(sparc64_ttable_tl0), %o0
1: sethi %hi(sparc64_ttable_tl0), %o0
set prom_set_trap_table_name, %g2
stx %g2, [%sp + 2047 + 128 + 0x00]
mov 1, %g2
stx %g2, [%sp + 2047 + 128 + 0x08]
mov 0, %g2
stx %g2, [%sp + 2047 + 128 + 0x10]
stx %o0, [%sp + 2047 + 128 + 0x18]
sethi %hi(p1275buf), %g2
or %g2, %lo(p1275buf), %g2
ldx [%g2 + 0x08], %o1
call %o1
add %sp, (2047 + 128), %o0
2: ldx [%l0], %g6
ldx [%g6 + TI_TASK], %g4
......
......@@ -143,22 +143,6 @@ unsigned char prom_get_idprom(char *idbuf, int num_bytes)
return 0xff;
}
/* Install Linux trap table so PROM uses that instead of its own. */
void prom_set_trap_table(unsigned long tba)
{
p1275_cmd("SUNW,set-trap-table",
(P1275_ARG(0, P1275_ARG_IN_64B) |
P1275_INOUT(1, 0)), tba);
}
void prom_set_trap_table_sun4v(unsigned long tba, unsigned long mmfsa)
{
p1275_cmd("SUNW,set-trap-table",
(P1275_ARG(0, P1275_ARG_IN_64B) |
P1275_ARG(1, P1275_ARG_IN_64B) |
P1275_INOUT(2, 0)), tba, mmfsa);
}
int prom_get_mmu_ihandle(void)
{
int node, ret;
......
......@@ -117,7 +117,7 @@ extern void sigio_handler(int sig, union uml_pt_regs *regs);
extern void copy_sc(union uml_pt_regs *regs, void *from);
unsigned long to_irq_stack(int sig, unsigned long *mask_out);
extern unsigned long to_irq_stack(unsigned long *mask_out);
unsigned long from_irq_stack(int nested);
#endif
......@@ -518,13 +518,13 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler)
static unsigned long pending_mask;
unsigned long to_irq_stack(int sig, unsigned long *mask_out)
unsigned long to_irq_stack(unsigned long *mask_out)
{
struct thread_info *ti;
unsigned long mask, old;
int nested;
mask = xchg(&pending_mask, 1 << sig);
mask = xchg(&pending_mask, *mask_out);
if(mask != 0){
/* If any interrupts come in at this point, we want to
* make sure that their bits aren't lost by our
......@@ -534,7 +534,7 @@ unsigned long to_irq_stack(int sig, unsigned long *mask_out)
* and pending_mask contains a bit for each interrupt
* that came in.
*/
old = 1 << sig;
old = *mask_out;
do {
old |= mask;
mask = xchg(&pending_mask, old);
......@@ -550,6 +550,7 @@ unsigned long to_irq_stack(int sig, unsigned long *mask_out)
task = cpu_tasks[ti->cpu].task;
tti = task_thread_info(task);
*ti = *tti;
ti->real_thread = tti;
task->stack = ti;
......
......@@ -320,7 +320,8 @@ int os_file_size(char *file, unsigned long long *size_out)
}
if(S_ISBLK(buf.ust_mode)){
int fd, blocks;
int fd;
long blocks;
fd = os_open_file(file, of_read(OPENFLAGS()), 0);
if(fd < 0){
......
......@@ -119,7 +119,7 @@ void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
void handle_signal(int sig, struct sigcontext *sc)
{
unsigned long pending = 0;
unsigned long pending = 1UL << sig;
do {
int nested, bail;
......@@ -134,7 +134,7 @@ void handle_signal(int sig, struct sigcontext *sc)
* have to return, and the upper handler will deal
* with this interrupt.
*/
bail = to_irq_stack(sig, &pending);
bail = to_irq_stack(&pending);
if(bail)
return;
......
......@@ -374,6 +374,13 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
if (unlikely(in_atomic() || !mm))
goto bad_area_nosemaphore;
/*
* User-mode registers count as a user access even for any
* potential system fault or CPU buglet.
*/
if (user_mode_vm(regs))
error_code |= PF_USER;
again:
/* When running in the kernel we expect faults to occur only to
* addresses in user space. All other faults represent errors in the
......
......@@ -27,7 +27,12 @@ platform-$(CONFIG_XTENSA_PLATFORM_ISS) := iss
PLATFORM = $(platform-y)
export PLATFORM
CFLAGS += -pipe -mlongcalls
# temporarily until string.h is fixed
cflags-y += -ffreestanding
cflags-y += -pipe -mlongcalls
CFLAGS += $(cflags-y)
KBUILD_DEFCONFIG := iss_defconfig
......
......@@ -7,7 +7,7 @@ extra-y := head.o vmlinux.lds
obj-y := align.o entry.o irq.o coprocessor.o process.o ptrace.o semaphore.o \
setup.o signal.o syscall.o time.o traps.o vectors.o platform.o \
pci-dma.o
pci-dma.o init_task.o io.o
## windowspill.o
......
......@@ -18,12 +18,13 @@
#include <linux/stddef.h>
#include <linux/thread_info.h>
#include <linux/ptrace.h>
#include <linux/mm.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#define DEFINE(sym, val) asm volatile("\n->" #sym " %0 " #val : : "i" (val))
#define BLANK() asm volatile("\n->" : : )
int main(void)
{
......@@ -63,7 +64,6 @@ int main(void)
DEFINE(PT_SIZE, sizeof(struct pt_regs));
DEFINE(PT_AREG_END, offsetof (struct pt_regs, areg[XCHAL_NUM_AREGS]));
DEFINE(PT_USER_SIZE, offsetof(struct pt_regs, areg[XCHAL_NUM_AREGS]));
BLANK();
/* struct task_struct */
DEFINE(TASK_PTRACE, offsetof (struct task_struct, ptrace));
......@@ -73,27 +73,26 @@ int main(void)
DEFINE(TASK_THREAD, offsetof (struct task_struct, thread));
DEFINE(TASK_THREAD_INFO, offsetof (struct task_struct, stack));
DEFINE(TASK_STRUCT_SIZE, sizeof (struct task_struct));
BLANK();
/* struct thread_info (offset from start_struct) */
DEFINE(THREAD_RA, offsetof (struct task_struct, thread.ra));
DEFINE(THREAD_SP, offsetof (struct task_struct, thread.sp));
DEFINE(THREAD_CP_SAVE, offsetof (struct task_struct, thread.cp_save));
DEFINE(THREAD_CURRENT_DS, offsetof (struct task_struct, thread.current_ds));
BLANK();
/* struct mm_struct */
DEFINE(MM_USERS, offsetof(struct mm_struct, mm_users));
DEFINE(MM_PGD, offsetof (struct mm_struct, pgd));
DEFINE(MM_CONTEXT, offsetof (struct mm_struct, context));
BLANK();
DEFINE(PT_SINGLESTEP_BIT, PT_SINGLESTEP_BIT);
/* struct page */
DEFINE(PAGE_FLAGS, offsetof(struct page, flags));
/* constants */
DEFINE(_CLONE_VM, CLONE_VM);
DEFINE(_CLONE_UNTRACED, CLONE_UNTRACED);
DEFINE(PG_ARCH_1, PG_arch_1);
return 0;
}
......@@ -7,7 +7,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2004-2005 by Tensilica Inc.
* Copyright (C) 2004-2007 by Tensilica Inc.
*
* Chris Zankel <chris@zankel.net>
*
......@@ -169,7 +169,7 @@ _user_exception:
* We have to save all registers up to the first '1' from
* the right, except the current frame (bit 0).
* Assume a2 is: 001001000110001
* All regiser frames starting from the top fiel to the marked '1'
* All register frames starting from the top field to the marked '1'
* must be saved.
*/
......@@ -1572,10 +1572,12 @@ ENTRY(fast_second_level_miss)
l32i a0, a1, TASK_MM # tsk->mm
beqz a0, 9f
8: rsr a1, EXCVADDR # fault address
_PGD_OFFSET(a0, a1, a1)
/* We deliberately destroy a3 that holds the exception table. */
8: rsr a3, EXCVADDR # fault address
_PGD_OFFSET(a0, a3, a1)
l32i a0, a0, 0 # read pmdval
//beqi a0, _PAGE_USER, 2f
beqz a0, 2f
/* Read ptevaddr and convert to top of page-table page.
......@@ -1588,7 +1590,7 @@ ENTRY(fast_second_level_miss)
* The messy computation for 'pteval' above really simplifies
* into the following:
*
* pteval = ((pmdval - PAGE_OFFSET) & PAGE_MASK) | PAGE_KERNEL
* pteval = ((pmdval - PAGE_OFFSET) & PAGE_MASK) | PAGE_DIRECTORY
*/
movi a1, -PAGE_OFFSET
......@@ -1596,20 +1598,34 @@ ENTRY(fast_second_level_miss)
extui a1, a0, 0, PAGE_SHIFT # ... & PAGE_MASK
xor a0, a0, a1
movi a1, PAGE_DIRECTORY
movi a1, _PAGE_DIRECTORY
or a0, a0, a1 # ... | PAGE_DIRECTORY
/*
* We utilize all three wired-ways (7-9) to hold pmd translations.
* Memory regions are mapped to the DTLBs according to bits 28 and 29.
* This allows to map the three most common regions to three different
* DTLBs:
* 0,1 -> way 7 program (0040.0000) and virtual (c000.0000)
* 2 -> way 8 shared libaries (2000.0000)
* 3 -> way 0 stack (3000.0000)
*/
extui a3, a3, 28, 2 # addr. bit 28 and 29 0,1,2,3
rsr a1, PTEVADDR
addx2 a3, a3, a3 # -> 0,3,6,9
srli a1, a1, PAGE_SHIFT
extui a3, a3, 2, 2 # -> 0,0,1,2
slli a1, a1, PAGE_SHIFT # ptevaddr & PAGE_MASK
addi a1, a1, DTLB_WAY_PGD # ... + way_number
addi a3, a3, DTLB_WAY_PGD
add a1, a1, a3 # ... + way_number
wdtlb a0, a1
3: wdtlb a0, a1
dsync
/* Exit critical section. */
4: movi a3, exc_table # restore a3
movi a0, 0
s32i a0, a3, EXC_TABLE_FIXUP
......@@ -1636,8 +1652,76 @@ ENTRY(fast_second_level_miss)
9: l32i a0, a1, TASK_ACTIVE_MM # unlikely case mm == 0
j 8b
#if (DCACHE_WAY_SIZE > PAGE_SIZE)
2: /* Special case for cache aliasing.
* We (should) only get here if a clear_user_page, copy_user_page
* or the aliased cache flush functions got preemptively interrupted
* by another task. Re-establish temporary mapping to the
* TLBTEMP_BASE areas.
*/
/* We shouldn't be in a double exception */
l32i a0, a2, PT_DEPC
bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 2f
/* Make sure the exception originated in the special functions */
movi a0, __tlbtemp_mapping_start
rsr a3, EPC_1
bltu a3, a0, 2f
movi a0, __tlbtemp_mapping_end
bgeu a3, a0, 2f
/* Check if excvaddr was in one of the TLBTEMP_BASE areas. */
movi a3, TLBTEMP_BASE_1
rsr a0, EXCVADDR
bltu a0, a3, 2f
addi a1, a0, -(2 << (DCACHE_ALIAS_ORDER + PAGE_SHIFT))
bgeu a1, a3, 2f
/* Check if we have to restore an ITLB mapping. */
movi a1, __tlbtemp_mapping_itlb
rsr a3, EPC_1
sub a3, a3, a1
/* Calculate VPN */
movi a1, PAGE_MASK
and a1, a1, a0
/* Jump for ITLB entry */
bgez a3, 1f
/* We can use up to two TLBTEMP areas, one for src and one for dst. */
extui a3, a0, PAGE_SHIFT + DCACHE_ALIAS_ORDER, 1
add a1, a3, a1
/* PPN is in a6 for the first TLBTEMP area and in a7 for the second. */
mov a0, a6
movnez a0, a7, a3
j 3b
/* ITLB entry. We only use dst in a6. */
1: witlb a6, a1
isync
j 4b
#endif // DCACHE_WAY_SIZE > PAGE_SIZE
2: /* Invalid PGD, default exception handling */
movi a3, exc_table
rsr a1, DEPC
xsr a3, EXCSAVE_1
s32i a1, a2, PT_AREG2
......@@ -1682,15 +1766,15 @@ ENTRY(fast_store_prohibited)
8: rsr a1, EXCVADDR # fault address
_PGD_OFFSET(a0, a1, a4)
l32i a0, a0, 0
//beqi a0, _PAGE_USER, 2f # FIXME use _PAGE_INVALID
beqz a0, 2f
/* Note that we assume _PAGE_WRITABLE_BIT is only set if pte is valid.*/
_PTE_OFFSET(a0, a1, a4)
l32i a4, a0, 0 # read pteval
movi a1, _PAGE_VALID | _PAGE_RW
bnall a4, a1, 2f
bbci.l a4, _PAGE_WRITABLE_BIT, 2f
movi a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_WRENABLE
movi a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HW_WRITE
or a4, a4, a1
rsr a1, EXCVADDR
s32i a4, a0, 0
......@@ -1700,10 +1784,7 @@ ENTRY(fast_store_prohibited)
dhwb a0, 0
#endif
pdtlb a0, a1
beqz a0, 1f
idtlb a0 // FIXME do we need this?
wdtlb a4, a0
1:
/* Exit critical section. */
......
/*
* arch/xtensa/kernel/init_task.c
*
* Xtensa Processor version.
*
* 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 Tensilica Inc.
*
* Chris Zankel <chris@zankel.net>
*/
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/init_task.h>
#include <linux/module.h>
#include <linux/mqueue.h>
#include <asm/uaccess.h>
static struct fs_struct init_fs = INIT_FS;
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
EXPORT_SYMBOL(init_mm);
union thread_union init_thread_union
__attribute__((__section__(".data.init_task"))) =
{ INIT_THREAD_INFO(init_task) };
struct task_struct init_task = INIT_TASK(init_task);
EXPORT_SYMBOL(init_task);
/*
* arch/xtensa/io.c
*
* IO primitives
*
* 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.
*
* Copied from sparc.
*
* Chris Zankel <chris@zankel.net>
*
*/
#include <asm/io.h>
#include <asm/byteorder.h>
void outsb(unsigned long addr, const void *src, unsigned long count) {
while (count) {
count -= 1;
writeb(*(const char *)src, addr);
src += 1;
addr += 1;
}
}
void outsw(unsigned long addr, const void *src, unsigned long count) {
while (count) {
count -= 2;
writew(*(const short *)src, addr);
src += 2;
addr += 2;
}
}
void outsl(unsigned long addr, const void *src, unsigned long count) {
while (count) {
count -= 4;
writel(*(const long *)src, addr);
src += 4;
addr += 4;
}
}
void insb(unsigned long addr, void *dst, unsigned long count) {
while (count) {
count -= 1;
*(unsigned char *)dst = readb(addr);
dst += 1;
addr += 1;
}
}
void insw(unsigned long addr, void *dst, unsigned long count) {
while (count) {
count -= 2;
*(unsigned short *)dst = readw(addr);
dst += 2;
addr += 2;
}
}
void insl(unsigned long addr, void *dst, unsigned long count) {
while (count) {
count -= 4;
/*
* XXX I am sure we are in for an unaligned trap here.
*/
*(unsigned long *)dst = readl(addr);
dst += 4;
addr += 4;
}
}
......@@ -7,7 +7,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2001 - 2005 Tensilica Inc.
* Copyright (C) 2001 - 2006 Tensilica Inc.
*
* Chris Zankel <chris@zankel.net>
*
......@@ -22,57 +22,216 @@
#include <linux/kernel.h>
#include <linux/cache.h>
LIST_HEAD(module_buf_list);
#undef DEBUG_RELOCATE
void *module_alloc(unsigned long size)
{
panic("module_alloc not implemented");
if (size == 0)
return NULL;
return vmalloc(size);
}
void module_free(struct module *mod, void *module_region)
{
panic("module_free not implemented");
vfree(module_region);
/* FIXME: If module_region == mod->init_region, trim exception
table entries. */
}
int module_frob_arch_sections(Elf32_Ehdr *hdr,
Elf32_Shdr *sechdrs,
char *secstrings,
struct module *me)
struct module *mod)
{
panic("module_frob_arch_sections not implemented");
return 0;
}
static int
decode_calln_opcode (unsigned char *location)
{
#ifdef __XTENSA_EB__
return (location[0] & 0xf0) == 0x50;
#endif
#ifdef __XTENSA_EL__
return (location[0] & 0xf) == 0x5;
#endif
}
static int
decode_l32r_opcode (unsigned char *location)
{
#ifdef __XTENSA_EB__
return (location[0] & 0xf0) == 0x10;
#endif
#ifdef __XTENSA_EL__
return (location[0] & 0xf) == 0x1;
#endif
}
int apply_relocate(Elf32_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
unsigned int relsec,
struct module *module)
struct module *mod)
{
panic ("apply_relocate not implemented");
printk(KERN_ERR "module %s: REL RELOCATION unsupported\n",
mod->name);
return -ENOEXEC;
}
int apply_relocate_add(Elf32_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
unsigned int relsec,
struct module *module)
struct module *mod)
{
panic("apply_relocate_add not implemented");
unsigned int i;
Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
Elf32_Sym *sym;
unsigned char *location;
uint32_t value;
#ifdef DEBUG_RELOCATE
printk("Applying relocate section %u to %u\n", relsec,
sechdrs[relsec].sh_info);
#endif
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
location = (char *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ rela[i].r_offset;
sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ ELF32_R_SYM(rela[i].r_info);
value = sym->st_value + rela[i].r_addend;
switch (ELF32_R_TYPE(rela[i].r_info)) {
case R_XTENSA_NONE:
case R_XTENSA_DIFF8:
case R_XTENSA_DIFF16:
case R_XTENSA_DIFF32:
case R_XTENSA_ASM_EXPAND:
break;
case R_XTENSA_32:
case R_XTENSA_PLT:
*(uint32_t *)location += value;
break;
case R_XTENSA_SLOT0_OP:
if (decode_calln_opcode(location)) {
value -= ((unsigned long)location & -4) + 4;
if ((value & 3) != 0 ||
((value + (1 << 19)) >> 20) != 0) {
printk("%s: relocation out of range, "
"section %d reloc %d "
"sym '%s'\n",
mod->name, relsec, i,
strtab + sym->st_name);
return -ENOEXEC;
}
value = (signed int)value >> 2;
#ifdef __XTENSA_EB__
location[0] = ((location[0] & ~0x3) |
((value >> 16) & 0x3));
location[1] = (value >> 8) & 0xff;
location[2] = value & 0xff;
#endif
#ifdef __XTENSA_EL__
location[0] = ((location[0] & ~0xc0) |
((value << 6) & 0xc0));
location[1] = (value >> 2) & 0xff;
location[2] = (value >> 10) & 0xff;
#endif
} else if (decode_l32r_opcode(location)) {
value -= (((unsigned long)location + 3) & -4);
if ((value & 3) != 0 ||
(signed int)value >> 18 != -1) {
printk("%s: relocation out of range, "
"section %d reloc %d "
"sym '%s'\n",
mod->name, relsec, i,
strtab + sym->st_name);
return -ENOEXEC;
}
value = (signed int)value >> 2;
#ifdef __XTENSA_EB__
location[1] = (value >> 8) & 0xff;
location[2] = value & 0xff;
#endif
#ifdef __XTENSA_EL__
location[1] = value & 0xff;
location[2] = (value >> 8) & 0xff;
#endif
}
/* FIXME: Ignore any other opcodes. The Xtensa
assembler currently assumes that the linker will
always do relaxation and so all PC-relative
operands need relocations. (The assembler also
writes out the tentative PC-relative values,
assuming no link-time relaxation, so it is usually
safe to ignore the relocations.) If the
assembler's "--no-link-relax" flag can be made to
work, and if all kernel modules can be assembled
with that flag, then unexpected relocations could
be detected here. */
break;
case R_XTENSA_SLOT1_OP:
case R_XTENSA_SLOT2_OP:
case R_XTENSA_SLOT3_OP:
case R_XTENSA_SLOT4_OP:
case R_XTENSA_SLOT5_OP:
case R_XTENSA_SLOT6_OP:
case R_XTENSA_SLOT7_OP:
case R_XTENSA_SLOT8_OP:
case R_XTENSA_SLOT9_OP:
case R_XTENSA_SLOT10_OP:
case R_XTENSA_SLOT11_OP:
case R_XTENSA_SLOT12_OP:
case R_XTENSA_SLOT13_OP:
case R_XTENSA_SLOT14_OP:
printk("%s: unexpected FLIX relocation: %u\n",
mod->name,
ELF32_R_TYPE(rela[i].r_info));
return -ENOEXEC;
case R_XTENSA_SLOT0_ALT:
case R_XTENSA_SLOT1_ALT:
case R_XTENSA_SLOT2_ALT:
case R_XTENSA_SLOT3_ALT:
case R_XTENSA_SLOT4_ALT:
case R_XTENSA_SLOT5_ALT:
case R_XTENSA_SLOT6_ALT:
case R_XTENSA_SLOT7_ALT:
case R_XTENSA_SLOT8_ALT:
case R_XTENSA_SLOT9_ALT:
case R_XTENSA_SLOT10_ALT:
case R_XTENSA_SLOT11_ALT:
case R_XTENSA_SLOT12_ALT:
case R_XTENSA_SLOT13_ALT:
case R_XTENSA_SLOT14_ALT:
printk("%s: unexpected ALT relocation: %u\n",
mod->name,
ELF32_R_TYPE(rela[i].r_info));
return -ENOEXEC;
default:
printk("%s: unexpected relocation: %u\n",
mod->name,
ELF32_R_TYPE(rela[i].r_info));
return -ENOEXEC;
}
}
return 0;
}
int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *me)
struct module *mod)
{
panic ("module_finalize not implemented");
return 0;
}
void module_arch_cleanup(struct module *mod)
{
panic("module_arch_cleanup not implemented");
}
struct bug_entry *module_find_bug(unsigned long bugaddr)
{
panic("module_find_bug not implemented");
}
......@@ -394,72 +394,3 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
return ret;
}
/*
* This probably belongs here rather than ioport.c because
* we do not want this crud linked into SBus kernels.
* Also, think for a moment about likes of floppy.c that
* include architecture specific parts. They may want to redefine ins/outs.
*
* We do not use horrible macros here because we want to
* advance pointer by sizeof(size).
*/
void outsb(unsigned long addr, const void *src, unsigned long count) {
while (count) {
count -= 1;
writeb(*(const char *)src, addr);
src += 1;
addr += 1;
}
}
void outsw(unsigned long addr, const void *src, unsigned long count) {
while (count) {
count -= 2;
writew(*(const short *)src, addr);
src += 2;
addr += 2;
}
}
void outsl(unsigned long addr, const void *src, unsigned long count) {
while (count) {
count -= 4;
writel(*(const long *)src, addr);
src += 4;
addr += 4;
}
}
void insb(unsigned long addr, void *dst, unsigned long count) {
while (count) {
count -= 1;
*(unsigned char *)dst = readb(addr);
dst += 1;
addr += 1;
}
}
void insw(unsigned long addr, void *dst, unsigned long count) {
while (count) {
count -= 2;
*(unsigned short *)dst = readw(addr);
dst += 2;
addr += 2;
}
}
void insl(unsigned long addr, void *dst, unsigned long count) {
while (count) {
count -= 4;
/*
* XXX I am sure we are in for an unaligned trap here.
*/
*(unsigned long *)dst = readl(addr);
dst += 4;
addr += 4;
}
}
......@@ -46,20 +46,6 @@
extern void ret_from_fork(void);
static struct fs_struct init_fs = INIT_FS;
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
EXPORT_SYMBOL(init_mm);
union thread_union init_thread_union
__attribute__((__section__(".data.init_task"))) =
{ INIT_THREAD_INFO(init_task) };
struct task_struct init_task = INIT_TASK(init_task);
EXPORT_SYMBOL(init_task);
struct task_struct *current_set[NR_CPUS] = {&init_task, };
void (*pm_power_off)(void) = NULL;
......
......@@ -100,7 +100,7 @@ static __inline__ int waking_non_zero_trylock(struct semaphore *sem)
return ret;
}
spinlock_t semaphore_wake_lock;
DEFINE_SPINLOCK(semaphore_wake_lock);
/*
* Semaphores are implemented using a two-way counter:
......
......@@ -93,3 +93,8 @@ asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
return (long)ret;
}
asmlinkage long xtensa_fadvise64_64(int fd, int advice, unsigned long long offset, unsigned long long len)
{
return sys_fadvise64_64(fd, offset, len, advice);
}
......@@ -32,12 +32,20 @@ EXPORT_SYMBOL(rtc_lock);
#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
unsigned long ccount_per_jiffy; /* per 1/HZ */
unsigned long ccount_nsec; /* nsec per ccount increment */
unsigned long nsec_per_ccount; /* nsec per ccount increment */
#endif
unsigned int last_ccount_stamp;
static long last_rtc_update = 0;
/*
* Scheduler clock - returns current tim in nanosec units.
*/
unsigned long long sched_clock(void)
{
return (unsigned long long)jiffies * (1000000000 / HZ);
}
static irqreturn_t timer_interrupt(int irq, void *dev_id);
static struct irqaction timer_irqaction = {
.handler = timer_interrupt,
......@@ -69,7 +77,6 @@ void __init time_init(void)
xtime.tv_nsec = 0;
last_rtc_update = xtime.tv_sec = sec_n;
last_ccount_stamp = get_ccount();
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
......@@ -85,7 +92,7 @@ int do_settimeofday(struct timespec *tv)
{
time_t wtm_sec, sec = tv->tv_sec;
long wtm_nsec, nsec = tv->tv_nsec;
unsigned long ccount;
unsigned long delta;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
......@@ -97,8 +104,10 @@ int do_settimeofday(struct timespec *tv)
* wall time. Discover what correction gettimeofday() would have
* made, and then undo it!
*/
ccount = get_ccount();
nsec -= (ccount - last_ccount_stamp) * CCOUNT_NSEC;
delta = CCOUNT_PER_JIFFY;
delta += get_ccount() - get_linux_timer();
nsec -= delta * NSEC_PER_CCOUNT;
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
......@@ -117,17 +126,21 @@ EXPORT_SYMBOL(do_settimeofday);
void do_gettimeofday(struct timeval *tv)
{
unsigned long flags;
unsigned long sec, usec, delta, seq;
unsigned long volatile sec, usec, delta, seq;
do {
seq = read_seqbegin_irqsave(&xtime_lock, flags);
delta = get_ccount() - last_ccount_stamp;
sec = xtime.tv_sec;
usec = (xtime.tv_nsec / NSEC_PER_USEC);
delta = get_linux_timer() - get_ccount();
} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
usec += (delta * CCOUNT_NSEC) / NSEC_PER_USEC;
usec += (((unsigned long) CCOUNT_PER_JIFFY - delta)
* (unsigned long) NSEC_PER_CCOUNT) / NSEC_PER_USEC;
for (; usec >= 1000000; sec++, usec -= 1000000)
;
......@@ -158,9 +171,12 @@ irqreturn_t timer_interrupt (int irq, void *dev_id)
write_seqlock(&xtime_lock);
last_ccount_stamp = next;
do_timer(1); /* Linux handler in kernel/timer.c */
/* Note that writing CCOMPARE clears the interrupt. */
next += CCOUNT_PER_JIFFY;
do_timer (1); /* Linux handler in kernel/timer.c */
set_linux_timer(next);
if (ntp_synced() &&
xtime.tv_sec - last_rtc_update >= 659 &&
......@@ -175,19 +191,15 @@ irqreturn_t timer_interrupt (int irq, void *dev_id)
write_sequnlock(&xtime_lock);
}
/* NOTE: writing CCOMPAREn clears the interrupt. */
/* Allow platform to do something useful (Wdog). */
set_linux_timer (next);
platform_heartbeat();
/* Make sure we didn't miss any tick... */
if ((signed long)(get_ccount() - next) > 0)
goto again;
/* Allow platform to do something useful (Wdog). */
platform_heartbeat();
return IRQ_HANDLED;
}
......
......@@ -83,7 +83,7 @@ typedef struct {
void* handler;
} dispatch_init_table_t;
dispatch_init_table_t __init dispatch_init_table[] = {
static dispatch_init_table_t __initdata dispatch_init_table[] = {
{ EXCCAUSE_ILLEGAL_INSTRUCTION, 0, do_illegal_instruction},
{ EXCCAUSE_SYSTEM_CALL, KRNL, fast_syscall_kernel },
......@@ -305,7 +305,7 @@ do_debug(struct pt_regs *regs)
#define set_handler(idx,handler) (exc_table[idx] = (unsigned long) (handler))
void trap_init(void)
void __init trap_init(void)
{
int i;
......
......@@ -5,9 +5,5 @@
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
# Note 2! The CFLAGS definition is now in the main makefile...
obj-y := init.o fault.o tlb.o misc.o
obj-m :=
obj-n :=
obj- :=
obj-y := init.o fault.o tlb.o misc.o cache.o
/*
* arch/xtensa/mm/cache.c
*
* 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) 2001-2006 Tensilica Inc.
*
* Chris Zankel <chris@zankel.net>
* Joe Taylor
* Marc Gauthier
*
*/
#include <linux/init.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/bootmem.h>
#include <linux/swap.h>
#include <linux/pagemap.h>
#include <asm/pgtable.h>
#include <asm/bootparam.h>
#include <asm/mmu_context.h>
#include <asm/tlb.h>
#include <asm/tlbflush.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
//#define printd(x...) printk(x)
#define printd(x...) do { } while(0)
/*
* Note:
* The kernel provides one architecture bit PG_arch_1 in the page flags that
* can be used for cache coherency.
*
* I$-D$ coherency.
*
* The Xtensa architecture doesn't keep the instruction cache coherent with
* the data cache. We use the architecture bit to indicate if the caches
* are coherent. The kernel clears this bit whenever a page is added to the
* page cache. At that time, the caches might not be in sync. We, therefore,
* define this flag as 'clean' if set.
*
* D-cache aliasing.
*
* With cache aliasing, we have to always flush the cache when pages are
* unmapped (see tlb_start_vma(). So, we use this flag to indicate a dirty
* page.
*
*
*
*/
#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
/*
* Any time the kernel writes to a user page cache page, or it is about to
* read from a page cache page this routine is called.
*
*/
void flush_dcache_page(struct page *page)
{
struct address_space *mapping = page_mapping(page);
/*
* If we have a mapping but the page is not mapped to user-space
* yet, we simply mark this page dirty and defer flushing the
* caches until update_mmu().
*/
if (mapping && !mapping_mapped(mapping)) {
if (!test_bit(PG_arch_1, &page->flags))
set_bit(PG_arch_1, &page->flags);
return;
} else {
unsigned long phys = page_to_phys(page);
unsigned long temp = page->index << PAGE_SHIFT;
unsigned long alias = !(DCACHE_ALIAS_EQ(temp, phys));
unsigned long virt;
/*
* Flush the page in kernel space and user space.
* Note that we can omit that step if aliasing is not
* an issue, but we do have to synchronize I$ and D$
* if we have a mapping.
*/
if (!alias && !mapping)
return;
__flush_invalidate_dcache_page((long)page_address(page));
virt = TLBTEMP_BASE_1 + (temp & DCACHE_ALIAS_MASK);
if (alias)
__flush_invalidate_dcache_page_alias(virt, phys);
if (mapping)
__invalidate_icache_page_alias(virt, phys);
}
/* There shouldn't be an entry in the cache for this page anymore. */
}
/*
* For now, flush the whole cache. FIXME??
*/
void flush_cache_range(struct vm_area_struct* vma,
unsigned long start, unsigned long end)
{
__flush_invalidate_dcache_all();
__invalidate_icache_all();
}
/*
* Remove any entry in the cache for this page.
*
* Note that this function is only called for user pages, so use the
* alias versions of the cache flush functions.
*/
void flush_cache_page(struct vm_area_struct* vma, unsigned long address,
unsigned long pfn)
{
/* Note that we have to use the 'alias' address to avoid multi-hit */
unsigned long phys = page_to_phys(pfn_to_page(pfn));
unsigned long virt = TLBTEMP_BASE_1 + (address & DCACHE_ALIAS_MASK);
__flush_invalidate_dcache_page_alias(virt, phys);
__invalidate_icache_page_alias(virt, phys);
}
#endif
void
update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t pte)
{
unsigned long pfn = pte_pfn(pte);
struct page *page;
if (!pfn_valid(pfn))
return;
page = pfn_to_page(pfn);
/* Invalidate old entry in TLBs */
invalidate_itlb_mapping(addr);
invalidate_dtlb_mapping(addr);
#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
if (!PageReserved(page) && test_bit(PG_arch_1, &page->flags)) {
unsigned long vaddr = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK);
unsigned long paddr = (unsigned long) page_address(page);
unsigned long phys = page_to_phys(page);
__flush_invalidate_dcache_page(paddr);
__flush_invalidate_dcache_page_alias(vaddr, phys);
__invalidate_icache_page_alias(vaddr, phys);
clear_bit(PG_arch_1, &page->flags);
}
#else
if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags)
&& (vma->vm_flags & VM_EXEC) != 0) {
unsigned long vaddr = addr & PAGE_MASK;
__flush_dcache_page(vaddr);
__invalidate_icache_page(vaddr);
set_bit(PG_arch_1, &page->flags);
}
#endif
}
/*
* access_process_vm() has called get_user_pages(), which has done a
* flush_dcache_page() on the page.
*/
#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long vaddr, void *dst, const void *src,
unsigned long len)
{
unsigned long phys = page_to_phys(page);
unsigned long alias = !(DCACHE_ALIAS_EQ(vaddr, phys));
/* Flush and invalidate user page if aliased. */
if (alias) {
unsigned long temp = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
__flush_invalidate_dcache_page_alias(temp, phys);
}
/* Copy data */
memcpy(dst, src, len);
/*
* Flush and invalidate kernel page if aliased and synchronize
* data and instruction caches for executable pages.
*/
if (alias) {
unsigned long temp = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
__flush_invalidate_dcache_range((unsigned long) dst, len);
if ((vma->vm_flags & VM_EXEC) != 0) {
__invalidate_icache_page_alias(temp, phys);
}
} else if ((vma->vm_flags & VM_EXEC) != 0) {
__flush_dcache_range((unsigned long)dst,len);
__invalidate_icache_range((unsigned long) dst, len);
}
}
extern void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long vaddr, void *dst, const void *src,
unsigned long len)
{
unsigned long phys = page_to_phys(page);
unsigned long alias = !(DCACHE_ALIAS_EQ(vaddr, phys));
/*
* Flush user page if aliased.
* (Note: a simply flush would be sufficient)
*/
if (alias) {
unsigned long temp = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
__flush_invalidate_dcache_page_alias(temp, phys);
}
memcpy(dst, src, len);
}
#endif
......@@ -24,6 +24,8 @@
unsigned long asid_cache = ASID_USER_FIRST;
void bad_page_fault(struct pt_regs*, unsigned long, int);
#undef DEBUG_PAGE_FAULT
/*
* This routine handles page faults. It determines the address,
* and the problem, and then passes it off to one of the appropriate
......@@ -64,7 +66,7 @@ void do_page_fault(struct pt_regs *regs)
exccause == EXCCAUSE_ITLB_MISS ||
exccause == EXCCAUSE_FETCH_CACHE_ATTRIBUTE) ? 1 : 0;
#if 0
#ifdef DEBUG_PAGE_FAULT
printk("[%s:%d:%08x:%d:%08x:%s%s]\n", current->comm, current->pid,
address, exccause, regs->pc, is_write? "w":"", is_exec? "x":"");
#endif
......@@ -219,7 +221,7 @@ bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
/* Are we prepared to handle this kernel fault? */
if ((entry = search_exception_tables(regs->pc)) != NULL) {
#if 1
#ifdef DEBUG_PAGE_FAULT
printk(KERN_DEBUG "%s: Exception at pc=%#010lx (%lx)\n",
current->comm, regs->pc, entry->fixup);
#endif
......
......@@ -15,40 +15,24 @@
* Kevin Chea
*/
#include <linux/init.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/bootmem.h>
#include <linux/swap.h>
#include <linux/mman.h>
#include <linux/nodemask.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <asm/pgtable.h>
#include <asm/bootparam.h>
#include <asm/mmu_context.h>
#include <asm/tlb.h>
#include <asm/tlbflush.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#define DEBUG 0
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
//static DEFINE_SPINLOCK(tlb_lock);
/*
* This flag is used to indicate that the page was mapped and modified in
* kernel space, so the cache is probably dirty at that address.
* If cache aliasing is enabled and the page color mismatches, update_mmu_cache
* synchronizes the caches if this bit is set.
*/
#define PG_cache_clean PG_arch_1
/* References to section boundaries */
......@@ -323,228 +307,22 @@ void show_mem(void)
printk("%d free pages\n", free);
}
/* ------------------------------------------------------------------------- */
#if (DCACHE_WAY_SIZE > PAGE_SIZE)
/*
* With cache aliasing, the page color of the page in kernel space and user
* space might mismatch. We temporarily map the page to a different virtual
* address with the same color and clear the page there.
*/
void clear_user_page(void *kaddr, unsigned long vaddr, struct page* page)
{
/* There shouldn't be any entries for this page. */
__flush_invalidate_dcache_page_phys(__pa(page_address(page)));
if (!PAGE_COLOR_EQ(vaddr, kaddr)) {
unsigned long v, p;
/* Temporarily map page to DTLB_WAY_DCACHE_ALIAS0. */
spin_lock(&tlb_lock);
p = (unsigned long)pte_val((mk_pte(page,PAGE_KERNEL)));
kaddr = (void*)PAGE_COLOR_MAP0(vaddr);
v = (unsigned long)kaddr | DTLB_WAY_DCACHE_ALIAS0;
__asm__ __volatile__("wdtlb %0,%1; dsync" : :"a" (p), "a" (v));
clear_page(kaddr);
spin_unlock(&tlb_lock);
} else {
clear_page(kaddr);
}
/* We need to make sure that i$ and d$ are coherent. */
clear_bit(PG_cache_clean, &page->flags);
}
/*
* With cache aliasing, we have to make sure that the page color of the page
* in kernel space matches that of the virtual user address before we read
* the page. If the page color differ, we create a temporary DTLB entry with
* the corrent page color and use this 'temporary' address as the source.
* We then use the same approach as in clear_user_page and copy the data
* to the kernel space and clear the PG_cache_clean bit to synchronize caches
* later.
*
* Note:
* Instead of using another 'way' for the temporary DTLB entry, we could
* probably use the same entry that points to the kernel address (after
* saving the original value and restoring it when we are done).
*/
struct kmem_cache *pgtable_cache __read_mostly;
void copy_user_page(void* to, void* from, unsigned long vaddr,
struct page* to_page)
static void pgd_ctor(void *addr, struct kmem_cache *cache, unsigned long flags)
{
/* There shouldn't be any entries for the new page. */
__flush_invalidate_dcache_page_phys(__pa(page_address(to_page)));
spin_lock(&tlb_lock);
if (!PAGE_COLOR_EQ(vaddr, from)) {
unsigned long v, p, t;
__asm__ __volatile__ ("pdtlb %1,%2; rdtlb1 %0,%1"
: "=a"(p), "=a"(t) : "a"(from));
from = (void*)PAGE_COLOR_MAP0(vaddr);
v = (unsigned long)from | DTLB_WAY_DCACHE_ALIAS0;
__asm__ __volatile__ ("wdtlb %0,%1; dsync" ::"a" (p), "a" (v));
}
if (!PAGE_COLOR_EQ(vaddr, to)) {
unsigned long v, p;
p = (unsigned long)pte_val((mk_pte(to_page,PAGE_KERNEL)));
to = (void*)PAGE_COLOR_MAP1(vaddr);
v = (unsigned long)to | DTLB_WAY_DCACHE_ALIAS1;
__asm__ __volatile__ ("wdtlb %0,%1; dsync" ::"a" (p), "a" (v));
}
copy_page(to, from);
spin_unlock(&tlb_lock);
/* We need to make sure that i$ and d$ are coherent. */
clear_bit(PG_cache_clean, &to_page->flags);
}
/*
* Any time the kernel writes to a user page cache page, or it is about to
* read from a page cache page this routine is called.
*
* Note:
* The kernel currently only provides one architecture bit in the page
* flags that we use for I$/D$ coherency. Maybe, in future, we can
* use a sepearte bit for deferred dcache aliasing:
* If the page is not mapped yet, we only need to set a flag,
* if mapped, we need to invalidate the page.
*/
// FIXME: we probably need this for WB caches not only for Page Coloring..
void flush_dcache_page(struct page *page)
{
unsigned long addr = __pa(page_address(page));
struct address_space *mapping = page_mapping(page);
__flush_invalidate_dcache_page_phys(addr);
if (!test_bit(PG_cache_clean, &page->flags))
return;
/* If this page hasn't been mapped, yet, handle I$/D$ coherency later.*/
#if 0
if (mapping && !mapping_mapped(mapping))
clear_bit(PG_cache_clean, &page->flags);
else
#endif
__invalidate_icache_page_phys(addr);
}
void flush_cache_range(struct vm_area_struct* vma, unsigned long s,
unsigned long e)
{
__flush_invalidate_cache_all();
}
void flush_cache_page(struct vm_area_struct* vma, unsigned long address,
unsigned long pfn)
{
struct page *page = pfn_to_page(pfn);
/* Remove any entry for the old mapping. */
if (current->active_mm == vma->vm_mm) {
unsigned long addr = __pa(page_address(page));
__flush_invalidate_dcache_page_phys(addr);
if ((vma->vm_flags & VM_EXEC) != 0)
__invalidate_icache_page_phys(addr);
} else {
BUG();
}
}
#endif /* (DCACHE_WAY_SIZE > PAGE_SIZE) */
pte_t* pte_alloc_one_kernel (struct mm_struct* mm, unsigned long addr)
{
pte_t* pte = (pte_t*)__get_free_pages(GFP_KERNEL|__GFP_REPEAT, 0);
if (likely(pte)) {
pte_t* ptep = (pte_t*)(pte_val(*pte) + PAGE_OFFSET);
int i;
for (i = 0; i < 1024; i++, ptep++)
pte_clear(mm, addr, ptep);
}
return pte;
}
struct page* pte_alloc_one(struct mm_struct *mm, unsigned long addr)
{
struct page *page;
page = alloc_pages(GFP_KERNEL | __GFP_REPEAT, 0);
if (likely(page)) {
pte_t* ptep = kmap_atomic(page, KM_USER0);
int i;
pte_t* ptep = (pte_t*)addr;
int i;
for (i = 0; i < 1024; i++, ptep++)
pte_clear(mm, addr, ptep);
for (i = 0; i < 1024; i++, ptep++)
pte_clear(NULL, 0, ptep);
kunmap_atomic(ptep, KM_USER0);
}
return page;
}
/*
* Handle D$/I$ coherency.
*
* Note:
* We only have one architecture bit for the page flags, so we cannot handle
* cache aliasing, yet.
*/
void
update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t pte)
void __init pgtable_cache_init(void)
{
unsigned long pfn = pte_pfn(pte);
struct page *page;
unsigned long vaddr = addr & PAGE_MASK;
if (!pfn_valid(pfn))
return;
page = pfn_to_page(pfn);
invalidate_itlb_mapping(addr);
invalidate_dtlb_mapping(addr);
/* We have a new mapping. Use it. */
write_dtlb_entry(pte, dtlb_probe(addr));
/* If the processor can execute from this page, synchronize D$/I$. */
if ((vma->vm_flags & VM_EXEC) != 0) {
write_itlb_entry(pte, itlb_probe(addr));
/* Synchronize caches, if not clean. */
if (!test_and_set_bit(PG_cache_clean, &page->flags)) {
__flush_dcache_page(vaddr);
__invalidate_icache_page(vaddr);
}
}
pgtable_cache = kmem_cache_create("pgd",
PAGE_SIZE, PAGE_SIZE,
SLAB_HWCACHE_ALIGN,
pgd_ctor);
}
......@@ -7,29 +7,33 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2001 - 2005 Tensilica Inc.
* Copyright (C) 2001 - 2007 Tensilica Inc.
*
* Chris Zankel <chris@zankel.net>
*/
/* Note: we might want to implement some of the loops as zero-overhead-loops,
* where applicable and if supported by the processor.
*/
#include <linux/linkage.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/asmmacro.h>
#include <asm/cacheasm.h>
#include <asm/tlbflush.h>
/* clear_page (page) */
/*
* clear_page and clear_user_page are the same for non-cache-aliased configs.
*
* clear_page (unsigned long page)
* a2
*/
ENTRY(clear_page)
entry a1, 16
addi a4, a2, PAGE_SIZE
movi a3, 0
1: s32i a3, a2, 0
movi a3, 0
__loopi a2, a7, PAGE_SIZE, 32
s32i a3, a2, 0
s32i a3, a2, 4
s32i a3, a2, 8
s32i a3, a2, 12
......@@ -37,42 +41,277 @@ ENTRY(clear_page)
s32i a3, a2, 20
s32i a3, a2, 24
s32i a3, a2, 28
addi a2, a2, 32
blt a2, a4, 1b
__endla a2, a7, 32
retw
/*
* copy_page and copy_user_page are the same for non-cache-aliased configs.
*
* copy_page (void *to, void *from)
* a2 a3
* a2 a3
*/
ENTRY(copy_page)
entry a1, 16
addi a4, a2, PAGE_SIZE
1: l32i a5, a3, 0
l32i a6, a3, 4
l32i a7, a3, 8
s32i a5, a2, 0
s32i a6, a2, 4
s32i a7, a2, 8
l32i a5, a3, 12
l32i a6, a3, 16
l32i a7, a3, 20
s32i a5, a2, 12
s32i a6, a2, 16
s32i a7, a2, 20
l32i a5, a3, 24
l32i a6, a3, 28
s32i a5, a2, 24
s32i a6, a2, 28
addi a2, a2, 32
addi a3, a3, 32
blt a2, a4, 1b
__loopi a2, a4, PAGE_SIZE, 32
l32i a8, a3, 0
l32i a9, a3, 4
s32i a8, a2, 0
s32i a9, a2, 4
l32i a8, a3, 8
l32i a9, a3, 12
s32i a8, a2, 8
s32i a9, a2, 12
l32i a8, a3, 16
l32i a9, a3, 20
s32i a8, a2, 16
s32i a9, a2, 20
l32i a8, a3, 24
l32i a9, a3, 28
s32i a8, a2, 24
s32i a9, a2, 28
addi a2, a2, 32
addi a3, a3, 32
__endl a2, a4
retw
/*
* If we have to deal with cache aliasing, we use temporary memory mappings
* to ensure that the source and destination pages have the same color as
* the virtual address. We use way 0 and 1 for temporary mappings in such cases.
*
* The temporary DTLB entries shouldn't be flushed by interrupts, but are
* flushed by preemptive task switches. Special code in the
* fast_second_level_miss handler re-established the temporary mapping.
* It requires that the PPNs for the destination and source addresses are
* in a6, and a7, respectively.
*/
/* TLB miss exceptions are treated special in the following region */
ENTRY(__tlbtemp_mapping_start)
#if (DCACHE_WAY_SIZE > PAGE_SIZE)
/*
* clear_user_page (void *addr, unsigned long vaddr, struct page *page)
* a2 a3 a4
*/
ENTRY(clear_user_page)
entry a1, 32
/* Mark page dirty and determine alias. */
movi a7, (1 << PG_ARCH_1)
l32i a5, a4, PAGE_FLAGS
xor a6, a2, a3
extui a3, a3, PAGE_SHIFT, DCACHE_ALIAS_ORDER
extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
or a5, a5, a7
slli a3, a3, PAGE_SHIFT
s32i a5, a4, PAGE_FLAGS
/* Skip setting up a temporary DTLB if not aliased. */
beqz a6, 1f
/* Invalidate kernel page. */
mov a10, a2
call8 __invalidate_dcache_page
/* Setup a temporary DTLB with the color of the VPN */
movi a4, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)
movi a5, TLBTEMP_BASE_1 # virt
add a6, a2, a4 # ppn
add a2, a5, a3 # add 'color'
wdtlb a6, a2
dsync
1: movi a3, 0
__loopi a2, a7, PAGE_SIZE, 32
s32i a3, a2, 0
s32i a3, a2, 4
s32i a3, a2, 8
s32i a3, a2, 12
s32i a3, a2, 16
s32i a3, a2, 20
s32i a3, a2, 24
s32i a3, a2, 28
__endla a2, a7, 32
bnez a6, 1f
retw
/* We need to invalidate the temporary idtlb entry, if any. */
1: addi a2, a2, -PAGE_SIZE
idtlb a2
dsync
retw
/*
* copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page)
* a2 a3 a4 a5
*/
ENTRY(copy_user_page)
entry a1, 32
/* Mark page dirty and determine alias for destination. */
movi a8, (1 << PG_ARCH_1)
l32i a9, a5, PAGE_FLAGS
xor a6, a2, a4
xor a7, a3, a4
extui a4, a4, PAGE_SHIFT, DCACHE_ALIAS_ORDER
extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
extui a7, a7, PAGE_SHIFT, DCACHE_ALIAS_ORDER
or a9, a9, a8
slli a4, a4, PAGE_SHIFT
s32i a9, a5, PAGE_FLAGS
movi a5, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)
beqz a6, 1f
/* Invalidate dcache */
mov a10, a2
call8 __invalidate_dcache_page
/* Setup a temporary DTLB with a matching color. */
movi a8, TLBTEMP_BASE_1 # base
add a6, a2, a5 # ppn
add a2, a8, a4 # add 'color'
wdtlb a6, a2
dsync
/* Skip setting up a temporary DTLB for destination if not aliased. */
1: beqz a7, 1f
/* Setup a temporary DTLB with a matching color. */
movi a8, TLBTEMP_BASE_2 # base
add a7, a3, a5 # ppn
add a3, a8, a4
addi a8, a3, 1 # way1
wdtlb a7, a8
dsync
1: __loopi a2, a4, PAGE_SIZE, 32
l32i a8, a3, 0
l32i a9, a3, 4
s32i a8, a2, 0
s32i a9, a2, 4
l32i a8, a3, 8
l32i a9, a3, 12
s32i a8, a2, 8
s32i a9, a2, 12
l32i a8, a3, 16
l32i a9, a3, 20
s32i a8, a2, 16
s32i a9, a2, 20
l32i a8, a3, 24
l32i a9, a3, 28
s32i a8, a2, 24
s32i a9, a2, 28
addi a2, a2, 32
addi a3, a3, 32
__endl a2, a4
/* We need to invalidate any temporary mapping! */
bnez a6, 1f
bnez a7, 2f
retw
1: addi a2, a2, -PAGE_SIZE
idtlb a2
dsync
bnez a7, 2f
retw
2: addi a3, a3, -PAGE_SIZE+1
idtlb a3
dsync
retw
#endif
#if (DCACHE_WAY_SIZE > PAGE_SIZE)
/*
* void __flush_invalidate_dcache_page_alias (addr, phys)
* a2 a3
*/
ENTRY(__flush_invalidate_dcache_page_alias)
entry sp, 16
movi a7, 0 # required for exception handler
addi a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
mov a4, a2
wdtlb a6, a2
dsync
___flush_invalidate_dcache_page a2 a3
idtlb a4
dsync
retw
#endif
ENTRY(__tlbtemp_mapping_itlb)
#if (ICACHE_WAY_SIZE > PAGE_SIZE)
ENTRY(__invalidate_icache_page_alias)
entry sp, 16
addi a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
mov a4, a2
witlb a6, a2
isync
___invalidate_icache_page a2 a3
iitlb a4
isync
retw
#endif
/* End of special treatment in tlb miss exception */
ENTRY(__tlbtemp_mapping_end)
/*
* void __invalidate_icache_page(ulong start)
*/
......@@ -121,8 +360,6 @@ ENTRY(__flush_dcache_page)
dsync
retw
/*
* void __invalidate_icache_range(ulong start, ulong size)
*/
......@@ -168,7 +405,6 @@ ENTRY(__invalidate_dcache_range)
___invalidate_dcache_range a2 a3 a4
retw
/*
......
......@@ -20,7 +20,6 @@
#include <linux/param.h>
#include <linux/serial.h>
#include <linux/serialP.h>
#include <linux/console.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
......
......@@ -1075,12 +1075,6 @@ void blk_queue_end_tag(struct request_queue *q, struct request *rq)
*/
return;
if (unlikely(!__test_and_clear_bit(tag, bqt->tag_map))) {
printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n",
__FUNCTION__, tag);
return;
}
list_del_init(&rq->queuelist);
rq->cmd_flags &= ~REQ_QUEUED;
rq->tag = -1;
......@@ -1090,6 +1084,19 @@ void blk_queue_end_tag(struct request_queue *q, struct request *rq)
__FUNCTION__, tag);
bqt->tag_index[tag] = NULL;
/*
* We use test_and_clear_bit's memory ordering properties here.
* The tag_map bit acts as a lock for tag_index[bit], so we need
* a barrer before clearing the bit (precisely: release semantics).
* Could use clear_bit_unlock when it is merged.
*/
if (unlikely(!test_and_clear_bit(tag, bqt->tag_map))) {
printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n",
__FUNCTION__, tag);
return;
}
bqt->busy--;
}
......@@ -1136,6 +1143,10 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq)
return 1;
} while (test_and_set_bit(tag, bqt->tag_map));
/*
* We rely on test_and_set_bit providing lock memory ordering semantics
* (could use test_and_set_bit_lock when it is merged).
*/
rq->cmd_flags |= REQ_QUEUED;
rq->tag = tag;
......
......@@ -240,7 +240,7 @@ int acpi_bus_generate_netlink_event(const char *device_class,
return 0;
}
EXPORT_SYMBOL(acpi_generate_netlink_event);
EXPORT_SYMBOL(acpi_bus_generate_netlink_event);
static int acpi_event_genetlink_init(void)
{
......
......@@ -724,6 +724,25 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
return;
}
static int acpi_cpu_soft_notify(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
struct acpi_processor *pr = processors[cpu];
if (action == CPU_ONLINE && pr) {
acpi_processor_ppc_has_changed(pr);
acpi_processor_cst_has_changed(pr);
acpi_processor_tstate_has_changed(pr);
}
return NOTIFY_OK;
}
static struct notifier_block acpi_cpu_notifier =
{
.notifier_call = acpi_cpu_soft_notify,
};
static int acpi_processor_add(struct acpi_device *device)
{
struct acpi_processor *pr = NULL;
......@@ -987,6 +1006,7 @@ void acpi_processor_install_hotplug_notify(void)
ACPI_UINT32_MAX,
processor_walk_namespace_cb, &action, NULL);
#endif
register_hotcpu_notifier(&acpi_cpu_notifier);
}
static
......@@ -999,6 +1019,7 @@ void acpi_processor_uninstall_hotplug_notify(void)
ACPI_UINT32_MAX,
processor_walk_namespace_cb, &action, NULL);
#endif
unregister_hotcpu_notifier(&acpi_cpu_notifier);
}
/*
......
......@@ -23,7 +23,7 @@
*/
ACPI_MODULE_NAME("sleep")
#ifdef CONFIG_ACPI_PROCFS_SLEEP
#ifdef CONFIG_ACPI_PROCFS
static int acpi_system_sleep_seq_show(struct seq_file *seq, void *offset)
{
int i;
......@@ -76,7 +76,7 @@ acpi_system_write_sleep(struct file *file,
Done:
return error ? error : count;
}
#endif /* CONFIG_ACPI_PROCFS_SLEEP */
#endif /* CONFIG_ACPI_PROCFS */
#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || !defined(CONFIG_X86)
/* use /sys/class/rtc/rtcX/wakealarm instead; it's not ACPI-specific */
......@@ -471,7 +471,7 @@ static const struct file_operations acpi_system_wakeup_device_fops = {
.release = single_release,
};
#ifdef CONFIG_ACPI_PROCFS_SLEEP
#ifdef CONFIG_ACPI_PROCFS
static const struct file_operations acpi_system_sleep_fops = {
.open = acpi_system_sleep_open_fs,
.read = seq_read,
......@@ -479,7 +479,7 @@ static const struct file_operations acpi_system_sleep_fops = {
.llseek = seq_lseek,
.release = single_release,
};
#endif /* CONFIG_ACPI_PROCFS_SLEEP */
#endif /* CONFIG_ACPI_PROCFS */
#ifdef HAVE_ACPI_LEGACY_ALARM
static const struct file_operations acpi_system_alarm_fops = {
......@@ -506,7 +506,7 @@ static int __init acpi_sleep_proc_init(void)
if (acpi_disabled)
return 0;
#ifdef CONFIG_ACPI_PROCFS_SLEEP
#ifdef CONFIG_ACPI_PROCFS
/* 'sleep' [R/W] */
entry =
create_proc_entry("sleep", S_IFREG | S_IRUGO | S_IWUSR,
......
......@@ -679,14 +679,26 @@ static int device_add_class_symlinks(struct device *dev)
goto out_subsys;
}
if (dev->parent) {
error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
"device");
if (error)
goto out_busid;
#ifdef CONFIG_SYSFS_DEPRECATED
{
char * class_name = make_class_name(dev->class->name,
&dev->kobj);
struct device *parent = dev->parent;
char *class_name;
/*
* In old sysfs stacked class devices had 'device'
* link pointing to real device instead of parent
*/
while (parent->class && !parent->bus && parent->parent)
parent = parent->parent;
error = sysfs_create_link(&dev->kobj,
&parent->kobj,
"device");
if (error)
goto out_busid;
class_name = make_class_name(dev->class->name,
&dev->kobj);
if (class_name)
error = sysfs_create_link(&dev->parent->kobj,
&dev->kobj, class_name);
......@@ -694,6 +706,11 @@ static int device_add_class_symlinks(struct device *dev)
if (error)
goto out_device;
}
#else
error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
"device");
if (error)
goto out_busid;
#endif
}
return 0;
......
......@@ -31,6 +31,7 @@
#include <linux/genhd.h>
#include <linux/hdreg.h>
#include <linux/blkpg.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/mm.h>
......
......@@ -176,7 +176,7 @@ struct agp_bridge_data {
#define I830_GMCH_MEM_MASK 0x1
#define I830_GMCH_MEM_64M 0x1
#define I830_GMCH_MEM_128M 0
#define I830_GMCH_GMS_MASK 0xF0
#define I830_GMCH_GMS_MASK 0x70
#define I830_GMCH_GMS_DISABLED 0x00
#define I830_GMCH_GMS_LOCAL 0x10
#define I830_GMCH_GMS_STOLEN_512 0x20
......@@ -190,6 +190,7 @@ struct agp_bridge_data {
#define INTEL_I830_ERRSTS 0x92
/* Intel 855GM/852GM registers */
#define I855_GMCH_GMS_MASK 0xF0
#define I855_GMCH_GMS_STOLEN_0M 0x0
#define I855_GMCH_GMS_STOLEN_1M (0x1 << 4)
#define I855_GMCH_GMS_STOLEN_4M (0x2 << 4)
......
......@@ -511,7 +511,7 @@ static void intel_i830_init_gtt_entries(void)
*/
if (IS_G33)
size = 0;
switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
case I855_GMCH_GMS_STOLEN_1M:
gtt_entries = MB(1) - KB(size);
break;
......
......@@ -2215,7 +2215,8 @@ static int ipmi_pci_resume(struct pci_dev *pdev)
static struct pci_device_id ipmi_pci_devices[] = {
{ PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) },
{ PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) }
{ PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, ipmi_pci_devices);
......
......@@ -67,7 +67,7 @@
/*
* Page types allocated by the device.
*/
enum {
enum mspec_page_type {
MSPEC_FETCHOP = 1,
MSPEC_CACHED,
MSPEC_UNCACHED
......@@ -83,15 +83,25 @@ static int is_sn2;
* One of these structures is allocated when an mspec region is mmaped. The
* structure is pointed to by the vma->vm_private_data field in the vma struct.
* This structure is used to record the addresses of the mspec pages.
* This structure is shared by all vma's that are split off from the
* original vma when split_vma()'s are done.
*
* The refcnt is incremented atomically because mm->mmap_sem does not
* protect in fork case where multiple tasks share the vma_data.
*/
struct vma_data {
atomic_t refcnt; /* Number of vmas sharing the data. */
spinlock_t lock; /* Serialize access to the vma. */
spinlock_t lock; /* Serialize access to this structure. */
int count; /* Number of pages allocated. */
int type; /* Type of pages allocated. */
enum mspec_page_type type; /* Type of pages allocated. */
int flags; /* See VMD_xxx below. */
unsigned long vm_start; /* Original (unsplit) base. */
unsigned long vm_end; /* Original (unsplit) end. */
unsigned long maddr[0]; /* Array of MSPEC addresses. */
};
#define VMD_VMALLOCED 0x1 /* vmalloc'd rather than kmalloc'd */
/* used on shub2 to clear FOP cache in the HUB */
static unsigned long scratch_page[MAX_NUMNODES];
#define SH2_AMO_CACHE_ENTRIES 4
......@@ -129,8 +139,8 @@ mspec_zero_block(unsigned long addr, int len)
* mspec_open
*
* Called when a device mapping is created by a means other than mmap
* (via fork, etc.). Increments the reference count on the underlying
* mspec data so it is not freed prematurely.
* (via fork, munmap, etc.). Increments the reference count on the
* underlying mspec data so it is not freed prematurely.
*/
static void
mspec_open(struct vm_area_struct *vma)
......@@ -151,34 +161,44 @@ static void
mspec_close(struct vm_area_struct *vma)
{
struct vma_data *vdata;
int i, pages, result, vdata_size;
int index, last_index, result;
unsigned long my_page;
vdata = vma->vm_private_data;
if (!atomic_dec_and_test(&vdata->refcnt))
return;
pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
vdata_size = sizeof(struct vma_data) + pages * sizeof(long);
for (i = 0; i < pages; i++) {
if (vdata->maddr[i] == 0)
BUG_ON(vma->vm_start < vdata->vm_start || vma->vm_end > vdata->vm_end);
spin_lock(&vdata->lock);
index = (vma->vm_start - vdata->vm_start) >> PAGE_SHIFT;
last_index = (vma->vm_end - vdata->vm_start) >> PAGE_SHIFT;
for (; index < last_index; index++) {
if (vdata->maddr[index] == 0)
continue;
/*
* Clear the page before sticking it back
* into the pool.
*/
result = mspec_zero_block(vdata->maddr[i], PAGE_SIZE);
my_page = vdata->maddr[index];
vdata->maddr[index] = 0;
spin_unlock(&vdata->lock);
result = mspec_zero_block(my_page, PAGE_SIZE);
if (!result)
uncached_free_page(vdata->maddr[i]);
uncached_free_page(my_page);
else
printk(KERN_WARNING "mspec_close(): "
"failed to zero page %i\n",
result);
spin_lock(&vdata->lock);
}
spin_unlock(&vdata->lock);
if (vdata_size <= PAGE_SIZE)
kfree(vdata);
else
if (!atomic_dec_and_test(&vdata->refcnt))
return;
if (vdata->flags & VMD_VMALLOCED)
vfree(vdata);
else
kfree(vdata);
}
......@@ -195,7 +215,8 @@ mspec_nopfn(struct vm_area_struct *vma, unsigned long address)
int index;
struct vma_data *vdata = vma->vm_private_data;
index = (address - vma->vm_start) >> PAGE_SHIFT;
BUG_ON(address < vdata->vm_start || address >= vdata->vm_end);
index = (address - vdata->vm_start) >> PAGE_SHIFT;
maddr = (volatile unsigned long) vdata->maddr[index];
if (maddr == 0) {
maddr = uncached_alloc_page(numa_node_id());
......@@ -237,10 +258,11 @@ static struct vm_operations_struct mspec_vm_ops = {
* underlying pages.
*/
static int
mspec_mmap(struct file *file, struct vm_area_struct *vma, int type)
mspec_mmap(struct file *file, struct vm_area_struct *vma,
enum mspec_page_type type)
{
struct vma_data *vdata;
int pages, vdata_size;
int pages, vdata_size, flags = 0;
if (vma->vm_pgoff != 0)
return -EINVAL;
......@@ -255,12 +277,17 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, int type)
vdata_size = sizeof(struct vma_data) + pages * sizeof(long);
if (vdata_size <= PAGE_SIZE)
vdata = kmalloc(vdata_size, GFP_KERNEL);
else
else {
vdata = vmalloc(vdata_size);
flags = VMD_VMALLOCED;
}
if (!vdata)
return -ENOMEM;
memset(vdata, 0, vdata_size);
vdata->vm_start = vma->vm_start;
vdata->vm_end = vma->vm_end;
vdata->flags = flags;
vdata->type = type;
spin_lock_init(&vdata->lock);
vdata->refcnt = ATOMIC_INIT(1);
......
......@@ -795,6 +795,19 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
if (L_ICANON(tty))
retval = inq_canon(tty);
return put_user(retval, (unsigned int __user *) arg);
#ifndef TCGETS2
case TIOCGLCKTRMIOS:
if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
return -EFAULT;
return 0;
case TIOCSLCKTRMIOS:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
return -EFAULT;
return 0;
#else
case TIOCGLCKTRMIOS:
if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
return -EFAULT;
......@@ -806,6 +819,7 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg))
return -EFAULT;
return 0;
#endif
case TIOCPKT:
{
......
......@@ -487,6 +487,7 @@ static inline int idedisk_supports_lba48(const struct hd_driveid *id)
*/
static const struct drive_list_entry hpa_list[] = {
{ "ST340823A", NULL },
{ "ST320413A", NULL },
{ NULL, NULL }
};
......
......@@ -1802,9 +1802,7 @@ pmac_ide_dma_check(ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
ide_hwif_t *hwif = HWIF(drive);
pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
int enable = 1;
int map;
drive->using_dma = 0;
if (drive->media == ide_floppy)
......
......@@ -619,7 +619,7 @@ unsigned long segment_base(u16 selector);
void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
const u8 *old, const u8 *new, int bytes);
int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva);
void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu);
void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu);
int kvm_mmu_load(struct kvm_vcpu *vcpu);
void kvm_mmu_unload(struct kvm_vcpu *vcpu);
......@@ -628,11 +628,15 @@ int kvm_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run);
static inline int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
u32 error_code)
{
if (unlikely(vcpu->kvm->n_free_mmu_pages < KVM_MIN_FREE_MMU_PAGES))
kvm_mmu_free_some_pages(vcpu);
return vcpu->mmu.page_fault(vcpu, gva, error_code);
}
static inline void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
{
if (unlikely(vcpu->kvm->n_free_mmu_pages < KVM_MIN_FREE_MMU_PAGES))
__kvm_mmu_free_some_pages(vcpu);
}
static inline int kvm_mmu_reload(struct kvm_vcpu *vcpu)
{
if (likely(vcpu->mmu.root_hpa != INVALID_PAGE))
......
......@@ -273,12 +273,14 @@ static int mmu_topup_memory_caches(struct kvm_vcpu *vcpu)
int r;
r = __mmu_topup_memory_caches(vcpu, GFP_NOWAIT);
kvm_mmu_free_some_pages(vcpu);
if (r < 0) {
spin_unlock(&vcpu->kvm->lock);
kvm_arch_ops->vcpu_put(vcpu);
r = __mmu_topup_memory_caches(vcpu, GFP_KERNEL);
kvm_arch_ops->vcpu_load(vcpu);
spin_lock(&vcpu->kvm->lock);
kvm_mmu_free_some_pages(vcpu);
}
return r;
}
......@@ -1208,7 +1210,7 @@ int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva)
return kvm_mmu_unprotect_page(vcpu, gpa >> PAGE_SHIFT);
}
void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
{
while (vcpu->kvm->n_free_mmu_pages < KVM_REFILL_PAGES) {
struct kvm_mmu_page *page;
......@@ -1218,7 +1220,6 @@ void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
kvm_mmu_zap_page(vcpu->kvm, page);
}
}
EXPORT_SYMBOL_GPL(kvm_mmu_free_some_pages);
static void free_mmu_pages(struct kvm_vcpu *vcpu)
{
......
......@@ -9,6 +9,8 @@
#include <linux/bio.h>
#ifdef CONFIG_BLOCK
struct bio_list {
struct bio *head;
struct bio *tail;
......@@ -106,4 +108,5 @@ static inline struct bio *bio_list_get(struct bio_list *bl)
return bio;
}
#endif /* CONFIG_BLOCK */
#endif
......@@ -580,7 +580,7 @@ struct cx8802_dev * cx8802_get_device(struct inode *inode)
list_for_each(list,&cx8802_devlist) {
h = list_entry(list, struct cx8802_dev, devlist);
if (h->mpeg_dev->minor == minor)
if (h->mpeg_dev && h->mpeg_dev->minor == minor)
return h;
}
......
......@@ -190,7 +190,9 @@ static void ivtv_update_pgm_info(struct ivtv *itv)
int idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num;
struct v4l2_enc_idx_entry *e = itv->pgm_info + idx;
u32 addr = itv->pgm_info_offset + 4 + idx * 24;
const int mapping[] = { V4L2_ENC_IDX_FRAME_P, V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_B, 0 };
const int mapping[8] = { -1, V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_P, -1,
V4L2_ENC_IDX_FRAME_B, -1, -1, -1 };
// 1=I, 2=P, 4=B
e->offset = read_enc(addr + 4) + ((u64)read_enc(addr + 8) << 32);
if (e->offset > itv->mpg_data_received) {
......@@ -199,7 +201,7 @@ static void ivtv_update_pgm_info(struct ivtv *itv)
e->offset += itv->vbi_data_inserted;
e->length = read_enc(addr);
e->pts = read_enc(addr + 16) + ((u64)(read_enc(addr + 20) & 1) << 32);
e->flags = mapping[read_enc(addr + 12) & 3];
e->flags = mapping[read_enc(addr + 12) & 7];
i++;
}
itv->pgm_info_write_idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num;
......
......@@ -1099,14 +1099,21 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
case VIDIOC_G_ENC_INDEX: {
struct v4l2_enc_idx *idx = arg;
struct v4l2_enc_idx_entry *e = idx->entry;
int entries;
int i;
idx->entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
IVTV_MAX_PGM_INDEX;
if (idx->entries > V4L2_ENC_IDX_ENTRIES)
idx->entries = V4L2_ENC_IDX_ENTRIES;
for (i = 0; i < idx->entries; i++) {
idx->entry[i] = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
if (entries > V4L2_ENC_IDX_ENTRIES)
entries = V4L2_ENC_IDX_ENTRIES;
idx->entries = 0;
for (i = 0; i < entries; i++) {
*e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
idx->entries++;
e++;
}
}
itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
break;
......
......@@ -1243,7 +1243,7 @@ static int pwc_video_close(struct inode *inode, struct file *file)
PWC_ERROR("Failed to power down camera (%d)\n", i);
}
pdev->vopen--;
PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", i);
PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
} else {
pwc_cleanup(pdev);
/* Free memory (don't set pdev to 0 just yet) */
......
......@@ -1537,18 +1537,18 @@ struct saa7134_board saa7134_boards[] = {
},{
.name = name_comp1,
.vmux = 0,
.amux = LINE2,
.gpio = 0x00,
.amux = LINE1,
.gpio = 0x02,
},{
.name = name_comp2,
.vmux = 3,
.amux = LINE2,
.gpio = 0x00,
.amux = LINE1,
.gpio = 0x02,
},{
.name = name_svideo,
.vmux = 8,
.amux = LINE2,
.gpio = 0x00,
.amux = LINE1,
.gpio = 0x02,
}},
.radio = {
.name = name_radio,
......
......@@ -130,7 +130,7 @@ static int saa7191_write_reg(struct i2c_client *client, u8 reg,
/* the first byte of data must be the first subaddress number (register) */
static int saa7191_write_block(struct i2c_client *client,
u8 length, u8 *data)
u8 length, const u8 *data)
{
int i;
int ret;
......@@ -592,7 +592,7 @@ static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind)
if (err)
goto out_free_decoder;
err = saa7191_write_block(client, sizeof(initseq), (u8 *)initseq);
err = saa7191_write_block(client, sizeof(initseq), initseq);
if (err) {
printk(KERN_ERR "SAA7191 initialization failed\n");
goto out_detach_client;
......
......@@ -1081,6 +1081,7 @@ struct usb_device_id usbvision_table [] = {
{ USB_DEVICE(0x2304, 0x0301), .driver_info=PINNA_LINX_VD_IN_CAB_PAL },
{ USB_DEVICE(0x2304, 0x0419), .driver_info=PINNA_PCTV_BUNGEE_PAL_FM },
{ USB_DEVICE(0x2400, 0x4200), .driver_info=HPG_WINTV },
{ }, /* terminate list */
};
MODULE_DEVICE_TABLE (usb, usbvision_table);
......@@ -202,25 +202,5 @@ config THINKPAD_ACPI_BAY
If you are not sure, say Y here.
config THINKPAD_ACPI_INPUT_ENABLED
bool "Enable input layer support by default"
depends on THINKPAD_ACPI
default n
---help---
This option enables thinkpad-acpi hot key handling over the input
layer at driver load time. When it is unset, the driver does not
enable hot key handling by default, and also starts up with a mostly
empty keymap.
This option should be enabled if you have a new enough HAL or other
userspace support that properly handles the thinkpad-acpi event
device. It auto-tunes the hot key support to those reported by the
firmware and enables it automatically.
If unsure, say N here to retain the old behaviour of ibm-acpi, and
thinkpad-acpi up to kernel 2.6.21: userspace will have to enable and
set up the thinkpad-acpi hot key handling using the sysfs interace
after loading the driver.
endif # MISC_DEVICES
......@@ -353,7 +353,7 @@ static int __init msi_init(void)
if (IS_ERR(msibl_device))
return PTR_ERR(msibl_device);
msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1,
msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1;
ret = platform_driver_register(&msipf_driver);
if (ret)
......
......@@ -21,7 +21,7 @@
* 02110-1301, USA.
*/
#define IBM_VERSION "0.15"
#define IBM_VERSION "0.16"
#define TPACPI_SYSFS_VERSION 0x010000
/*
......@@ -906,9 +906,26 @@ static ssize_t hotkey_radio_sw_show(struct device *dev,
static struct device_attribute dev_attr_hotkey_radio_sw =
__ATTR(hotkey_radio_sw, S_IRUGO, hotkey_radio_sw_show, NULL);
/* sysfs hotkey report_mode -------------------------------------------- */
static ssize_t hotkey_report_mode_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n",
(hotkey_report_mode != 0) ? hotkey_report_mode : 1);
}
static struct device_attribute dev_attr_hotkey_report_mode =
__ATTR(hotkey_report_mode, S_IRUGO, hotkey_report_mode_show, NULL);
/* --------------------------------------------------------------------- */
static struct attribute *hotkey_mask_attributes[] = {
static struct attribute *hotkey_attributes[] __initdata = {
&dev_attr_hotkey_enable.attr,
&dev_attr_hotkey_report_mode.attr,
};
static struct attribute *hotkey_mask_attributes[] __initdata = {
&dev_attr_hotkey_mask.attr,
&dev_attr_hotkey_bios_enabled.attr,
&dev_attr_hotkey_bios_mask.attr,
......@@ -987,11 +1004,12 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
str_supported(tp_features.hotkey));
if (tp_features.hotkey) {
hotkey_dev_attributes = create_attr_set(7, NULL);
hotkey_dev_attributes = create_attr_set(8, NULL);
if (!hotkey_dev_attributes)
return -ENOMEM;
res = add_to_attr_set(hotkey_dev_attributes,
&dev_attr_hotkey_enable.attr);
res = add_many_to_attr_set(hotkey_dev_attributes,
hotkey_attributes,
ARRAY_SIZE(hotkey_attributes));
if (res)
return res;
......@@ -1055,11 +1073,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
TPACPI_HOTKEY_MAP_SIZE);
}
#ifndef CONFIG_THINKPAD_ACPI_INPUT_ENABLED
for (i = 0; i < 12; i++)
hotkey_keycode_map[i] = KEY_UNKNOWN;
#endif /* ! CONFIG_THINKPAD_ACPI_INPUT_ENABLED */
set_bit(EV_KEY, tpacpi_inputdev->evbit);
set_bit(EV_MSC, tpacpi_inputdev->evbit);
set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
......@@ -1081,14 +1094,17 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
set_bit(SW_RADIO, tpacpi_inputdev->swbit);
}
#ifdef CONFIG_THINKPAD_ACPI_INPUT_ENABLED
dbg_printk(TPACPI_DBG_INIT,
"enabling hot key handling\n");
res = hotkey_set(1, (hotkey_all_mask & ~hotkey_reserved_mask)
| hotkey_orig_mask);
if (res)
return res;
#endif /* CONFIG_THINKPAD_ACPI_INPUT_ENABLED */
dbg_printk(TPACPI_DBG_INIT,
"legacy hot key reporting over procfs %s\n",
(hotkey_report_mode < 2) ?
"enabled" : "disabled");
}
return (tp_features.hotkey)? 0 : 1;
......@@ -1142,58 +1158,65 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
{
u32 hkey;
unsigned int keycode, scancode;
int sendacpi = 1;
int send_acpi_ev = 0;
if (event == 0x80 && acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) {
if (tpacpi_inputdev->users > 0) {
switch (hkey >> 12) {
case 1:
/* 0x1000-0x1FFF: key presses */
scancode = hkey & 0xfff;
if (scancode > 0 && scancode < 0x21) {
scancode--;
keycode = hotkey_keycode_map[scancode];
tpacpi_input_send_key(scancode, keycode);
sendacpi = (keycode == KEY_RESERVED
|| keycode == KEY_UNKNOWN);
} else {
printk(IBM_ERR
"hotkey 0x%04x out of range for keyboard map\n",
hkey);
}
break;
case 5:
/* 0x5000-0x5FFF: LID */
/* we don't handle it through this path, just
* eat up known LID events */
if (hkey != 0x5001 && hkey != 0x5002) {
printk(IBM_ERR
"unknown LID-related hotkey event: 0x%04x\n",
hkey);
}
switch (hkey >> 12) {
case 1:
/* 0x1000-0x1FFF: key presses */
scancode = hkey & 0xfff;
if (scancode > 0 && scancode < 0x21) {
scancode--;
keycode = hotkey_keycode_map[scancode];
tpacpi_input_send_key(scancode, keycode);
} else {
printk(IBM_ERR
"hotkey 0x%04x out of range for keyboard map\n",
hkey);
send_acpi_ev = 1;
}
break;
case 5:
/* 0x5000-0x5FFF: LID */
/* we don't handle it through this path, just
* eat up known LID events */
if (hkey != 0x5001 && hkey != 0x5002) {
printk(IBM_ERR
"unknown LID-related hotkey event: 0x%04x\n",
hkey);
send_acpi_ev = 1;
}
break;
case 7:
/* 0x7000-0x7FFF: misc */
if (tp_features.hotkey_wlsw && hkey == 0x7000) {
tpacpi_input_send_radiosw();
break;
case 7:
/* 0x7000-0x7FFF: misc */
if (tp_features.hotkey_wlsw && hkey == 0x7000) {
tpacpi_input_send_radiosw();
sendacpi = 0;
break;
}
/* fallthrough to default */
default:
/* case 2: dock-related */
/* 0x2305 - T43 waking up due to bay lever eject while aslept */
/* case 3: ultra-bay related. maybe bay in dock? */
/* 0x3003 - T43 after wake up by bay lever eject (0x2305) */
printk(IBM_NOTICE "unhandled hotkey event 0x%04x\n", hkey);
}
/* fallthrough to default */
default:
/* case 2: dock-related */
/* 0x2305 - T43 waking up due to bay lever eject while aslept */
/* case 3: ultra-bay related. maybe bay in dock? */
/* 0x3003 - T43 after wake up by bay lever eject (0x2305) */
printk(IBM_NOTICE "unhandled HKEY event 0x%04x\n", hkey);
send_acpi_ev = 1;
}
if (sendacpi)
acpi_bus_generate_proc_event(ibm->acpi->device, event, hkey);
} else {
printk(IBM_ERR "unknown hotkey notification event %d\n", event);
acpi_bus_generate_proc_event(ibm->acpi->device, event, 0);
hkey = 0;
send_acpi_ev = 1;
}
/* Legacy events */
if (send_acpi_ev || hotkey_report_mode < 2)
acpi_bus_generate_proc_event(ibm->acpi->device, event, hkey);
/* netlink events */
if (send_acpi_ev) {
acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
ibm->acpi->device->dev.bus_id,
event, hkey);
}
}
......@@ -4623,6 +4646,9 @@ module_param_named(fan_control, fan_control_allowed, bool, 0);
static int brightness_mode;
module_param_named(brightness_mode, brightness_mode, int, 0);
static unsigned int hotkey_report_mode;
module_param(hotkey_report_mode, uint, 0);
#define IBM_PARAM(feature) \
module_param_call(feature, set_ibm_param, NULL, NULL, 0)
......@@ -4648,6 +4674,10 @@ static int __init thinkpad_acpi_module_init(void)
{
int ret, i;
/* Parameter checking */
if (hotkey_report_mode > 2)
return -EINVAL;
/* Driver-level probe */
get_thinkpad_model_data(&thinkpad_id);
......
......@@ -181,6 +181,7 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv);
static int experimental;
static u32 dbg_level;
static int force_load;
static unsigned int hotkey_report_mode;
static int thinkpad_acpi_module_init(void);
static void thinkpad_acpi_module_exit(void);
......
......@@ -816,7 +816,8 @@ static void __devexit cafe_nand_remove(struct pci_dev *pdev)
}
static struct pci_device_id cafe_nand_tbl[] = {
{ 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MEMORY_FLASH << 8, 0xFFFF0 }
{ 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MEMORY_FLASH << 8, 0xFFFF0 },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, cafe_nand_tbl);
......
......@@ -2177,7 +2177,7 @@ config SKGE
with better performance and more complete ethtool support.
It does not support the link failover and network management
features available in the hardware.
features that "portable" vendor supplied sk98lin driver does.
This driver supports adapters based on the original Yukon chipset:
Marvell 88E8001, Belkin F5D5005, CNet GigaCard, DLink DGE-530T,
......@@ -2215,6 +2215,93 @@ config SKY2_DEBUG
If unsure, say N.
config SK98LIN
tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support (DEPRECATED)"
depends on PCI
---help---
Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx
compliant Gigabit Ethernet Adapter.
This driver supports the original Yukon chipset. This driver is
deprecated and will be removed from the kernel in the near future,
it has been replaced by the skge driver. skge is cleaner and
seems to work better.
This driver does not support the newer Yukon2 chipset. A separate
driver, sky2, is provided to support Yukon2-based adapters.
The following adapters are supported by this driver:
- 3Com 3C940 Gigabit LOM Ethernet Adapter
- 3Com 3C941 Gigabit LOM Ethernet Adapter
- Allied Telesyn AT-2970LX Gigabit Ethernet Adapter
- Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter
- Allied Telesyn AT-2970SX Gigabit Ethernet Adapter
- Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter
- Allied Telesyn AT-2970TX Gigabit Ethernet Adapter
- Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter
- Allied Telesyn AT-2971SX Gigabit Ethernet Adapter
- Allied Telesyn AT-2971T Gigabit Ethernet Adapter
- Belkin Gigabit Desktop Card 10/100/1000Base-T Adapter, Copper RJ-45
- EG1032 v2 Instant Gigabit Network Adapter
- EG1064 v2 Instant Gigabit Network Adapter
- Marvell 88E8001 Gigabit LOM Ethernet Adapter (Abit)
- Marvell 88E8001 Gigabit LOM Ethernet Adapter (Albatron)
- Marvell 88E8001 Gigabit LOM Ethernet Adapter (Asus)
- Marvell 88E8001 Gigabit LOM Ethernet Adapter (ECS)
- Marvell 88E8001 Gigabit LOM Ethernet Adapter (Epox)
- Marvell 88E8001 Gigabit LOM Ethernet Adapter (Foxconn)
- Marvell 88E8001 Gigabit LOM Ethernet Adapter (Gigabyte)
- Marvell 88E8001 Gigabit LOM Ethernet Adapter (Iwill)
- Marvell 88E8050 Gigabit LOM Ethernet Adapter (Intel)
- Marvell RDK-8001 Adapter
- Marvell RDK-8002 Adapter
- Marvell RDK-8003 Adapter
- Marvell RDK-8004 Adapter
- Marvell RDK-8006 Adapter
- Marvell RDK-8007 Adapter
- Marvell RDK-8008 Adapter
- Marvell RDK-8009 Adapter
- Marvell RDK-8010 Adapter
- Marvell RDK-8011 Adapter
- Marvell RDK-8012 Adapter
- Marvell RDK-8052 Adapter
- Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (32 bit)
- Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (64 bit)
- N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L)
- SK-9521 10/100/1000Base-T Adapter
- SK-9521 V2.0 10/100/1000Base-T Adapter
- SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T)
- SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter
- SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link)
- SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX)
- SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter
- SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link)
- SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX)
- SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter
- SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link)
- SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter
- SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition)
- SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter
- SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link)
- SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX)
- SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter
- SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link)
- SMC EZ Card 1000 (SMC9452TXV.2)
The adapters support Jumbo Frames.
The dual link adapters support link-failover and dual port features.
Both Marvell Yukon and SysKonnect SK-98xx/SK-95xx adapters support
the scatter-gather functionality with sendfile(). Please refer to
<file:Documentation/networking/sk98lin.txt> for more information about
optional driver parameters.
Questions concerning this driver may be addressed to:
<linux@syskonnect.de>
If you want to compile this driver as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
say M here and read <file:Documentation/kbuild/modules.txt>. The module will
be called sk98lin. This is recommended.
config VIA_VELOCITY
tristate "VIA Velocity support"
depends on PCI
......
......@@ -66,6 +66,7 @@ ps3_gelic-objs += ps3_gelic_net.o
obj-$(CONFIG_TC35815) += tc35815.o
obj-$(CONFIG_SKGE) += skge.o
obj-$(CONFIG_SKY2) += sky2.o
obj-$(CONFIG_SK98LIN) += sk98lin/
obj-$(CONFIG_SKFP) += skfp/
obj-$(CONFIG_VIA_RHINE) += via-rhine.o
obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
......
......@@ -2203,21 +2203,20 @@ static int __devinit atl1_probe(struct pci_dev *pdev,
struct net_device *netdev;
struct atl1_adapter *adapter;
static int cards_found = 0;
bool pci_using_64 = true;
int err;
err = pci_enable_device(pdev);
if (err)
return err;
err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
/*
* 64-bit DMA currently has data corruption problems, so let's just
* use 32-bit DMA for now. This is a big hack that is probably wrong.
*/
err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (err) {
err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (err) {
dev_err(&pdev->dev, "no usable DMA configuration\n");
goto err_dma;
}
pci_using_64 = false;
dev_err(&pdev->dev, "no usable DMA configuration\n");
goto err_dma;
}
/* Mark all PCI regions associated with PCI device
* pdev as being reserved by owner atl1_driver_name
......@@ -2282,7 +2281,6 @@ static int __devinit atl1_probe(struct pci_dev *pdev,
netdev->ethtool_ops = &atl1_ethtool_ops;
adapter->bd_number = cards_found;
adapter->pci_using_64 = pci_using_64;
/* setup the private structure */
err = atl1_sw_init(adapter);
......@@ -2299,9 +2297,6 @@ static int __devinit atl1_probe(struct pci_dev *pdev,
*/
/* netdev->features |= NETIF_F_TSO; */
if (pci_using_64)
netdev->features |= NETIF_F_HIGHDMA;
netdev->features |= NETIF_F_LLTX;
/*
......
......@@ -39,7 +39,7 @@
#include <asm/io.h>
#define DRV_NAME "ehea"
#define DRV_VERSION "EHEA_0073"
#define DRV_VERSION "EHEA_0074"
/* eHEA capability flags */
#define DLPAR_PORT_ADD_REM 1
......@@ -402,6 +402,8 @@ struct ehea_mc_list {
#define EHEA_PORT_UP 1
#define EHEA_PORT_DOWN 0
#define EHEA_PHY_LINK_UP 1
#define EHEA_PHY_LINK_DOWN 0
#define EHEA_MAX_PORT_RES 16
struct ehea_port {
struct ehea_adapter *adapter; /* adapter that owns this port */
......@@ -427,6 +429,7 @@ struct ehea_port {
u32 msg_enable;
u32 sig_comp_iv;
u32 state;
u8 phy_link;
u8 full_duplex;
u8 autoneg;
u8 num_def_qps;
......
......@@ -53,17 +53,21 @@ static int rq3_entries = EHEA_DEF_ENTRIES_RQ3;
static int sq_entries = EHEA_DEF_ENTRIES_SQ;
static int use_mcs = 0;
static int num_tx_qps = EHEA_NUM_TX_QP;
static int prop_carrier_state = 0;
module_param(msg_level, int, 0);
module_param(rq1_entries, int, 0);
module_param(rq2_entries, int, 0);
module_param(rq3_entries, int, 0);
module_param(sq_entries, int, 0);
module_param(prop_carrier_state, int, 0);
module_param(use_mcs, int, 0);
module_param(num_tx_qps, int, 0);
MODULE_PARM_DESC(num_tx_qps, "Number of TX-QPS");
MODULE_PARM_DESC(msg_level, "msg_level");
MODULE_PARM_DESC(prop_carrier_state, "Propagate carrier state of physical "
"port to stack. 1:yes, 0:no. Default = 0 ");
MODULE_PARM_DESC(rq3_entries, "Number of entries for Receive Queue 3 "
"[2^x - 1], x = [6..14]. Default = "
__MODULE_STRING(EHEA_DEF_ENTRIES_RQ3) ")");
......@@ -467,7 +471,7 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev,
else
netif_receive_skb(skb);
dev->last_rx = jiffies;
port->netdev->last_rx = jiffies;
} else {
pr->p_stats.poll_receive_errors++;
port_reset = ehea_treat_poll_error(pr, rq, cqe,
......@@ -814,7 +818,9 @@ int ehea_set_portspeed(struct ehea_port *port, u32 port_speed)
ehea_error("Failed setting port speed");
}
}
netif_carrier_on(port->netdev);
if (!prop_carrier_state || (port->phy_link == EHEA_PHY_LINK_UP))
netif_carrier_on(port->netdev);
kfree(cb4);
out:
return ret;
......@@ -869,13 +875,19 @@ static void ehea_parse_eqe(struct ehea_adapter *adapter, u64 eqe)
}
if (EHEA_BMASK_GET(NEQE_EXTSWITCH_PORT_UP, eqe)) {
port->phy_link = EHEA_PHY_LINK_UP;
if (netif_msg_link(port))
ehea_info("%s: Physical port up",
port->netdev->name);
if (prop_carrier_state)
netif_carrier_on(port->netdev);
} else {
port->phy_link = EHEA_PHY_LINK_DOWN;
if (netif_msg_link(port))
ehea_info("%s: Physical port down",
port->netdev->name);
if (prop_carrier_state)
netif_carrier_off(port->netdev);
}
if (EHEA_BMASK_GET(NEQE_EXTSWITCH_PRIMARY, eqe))
......
......@@ -1222,7 +1222,7 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_lock_irqsave(&mp->lock, flags);
eth_tx_submit_descs_for_skb(mp, skb);
stats->tx_bytes = skb->len;
stats->tx_bytes += skb->len;
stats->tx_packets++;
dev->trans_start = jiffies;
......
......@@ -116,7 +116,7 @@ struct el3_private {
spinlock_t lock;
};
static const char *if_names[] = { "auto", "10baseT", "10base2", "AUI" };
static const char *if_names[] = { "auto", "10base2", "10baseT", "AUI" };
/*====================================================================*/
......
......@@ -755,7 +755,7 @@ void phy_stop(struct phy_device *phydev)
*/
void phy_start(struct phy_device *phydev)
{
spin_lock(&phydev->lock);
spin_lock_bh(&phydev->lock);
switch (phydev->state) {
case PHY_STARTING:
......@@ -769,7 +769,7 @@ void phy_start(struct phy_device *phydev)
default:
break;
}
spin_unlock(&phydev->lock);
spin_unlock_bh(&phydev->lock);
}
EXPORT_SYMBOL(phy_stop);
EXPORT_SYMBOL(phy_start);
......
......@@ -644,7 +644,7 @@ static int phy_probe(struct device *dev)
if (!(phydrv->flags & PHY_HAS_INTERRUPT))
phydev->irq = PHY_POLL;
spin_lock(&phydev->lock);
spin_lock_bh(&phydev->lock);
/* Start out supporting everything. Eventually,
* a controller will attach, and may modify one
......@@ -658,7 +658,7 @@ static int phy_probe(struct device *dev)
if (phydev->drv->probe)
err = phydev->drv->probe(phydev);
spin_unlock(&phydev->lock);
spin_unlock_bh(&phydev->lock);
return err;
......
......@@ -899,17 +899,9 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Put the 2-byte PPP protocol number on the front,
making sure there is room for the address and control fields. */
if (skb_headroom(skb) < PPP_HDRLEN) {
struct sk_buff *ns;
ns = alloc_skb(skb->len + dev->hard_header_len, GFP_ATOMIC);
if (ns == 0)
goto outf;
skb_reserve(ns, dev->hard_header_len);
skb_copy_bits(skb, 0, skb_put(ns, skb->len), skb->len);
kfree_skb(skb);
skb = ns;
}
if (skb_cow_head(skb, PPP_HDRLEN))
goto outf;
pp = skb_push(skb, 2);
proto = npindex_to_proto[npi];
pp[0] = proto >> 8;
......@@ -1533,7 +1525,7 @@ ppp_input_error(struct ppp_channel *chan, int code)
static void
ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
{
if (skb->len >= 2) {
if (pskb_may_pull(skb, 2)) {
#ifdef CONFIG_PPP_MULTILINK
/* XXX do channel-level decompression here */
if (PPP_PROTO(skb) == PPP_MP)
......@@ -1585,7 +1577,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP))
goto err;
if (skb_tailroom(skb) < 124) {
if (skb_tailroom(skb) < 124 || skb_cloned(skb)) {
/* copy to a new sk_buff with more tailroom */
ns = dev_alloc_skb(skb->len + 128);
if (ns == 0) {
......@@ -1656,23 +1648,29 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
/* check if the packet passes the pass and active filters */
/* the filter instructions are constructed assuming
a four-byte PPP header on each packet */
*skb_push(skb, 2) = 0;
if (ppp->pass_filter
&& sk_run_filter(skb, ppp->pass_filter,
ppp->pass_len) == 0) {
if (ppp->debug & 1)
printk(KERN_DEBUG "PPP: inbound frame not passed\n");
kfree_skb(skb);
return;
}
if (!(ppp->active_filter
&& sk_run_filter(skb, ppp->active_filter,
ppp->active_len) == 0))
ppp->last_recv = jiffies;
skb_pull(skb, 2);
#else
ppp->last_recv = jiffies;
if (ppp->pass_filter || ppp->active_filter) {
if (skb_cloned(skb) &&
pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
goto err;
*skb_push(skb, 2) = 0;
if (ppp->pass_filter
&& sk_run_filter(skb, ppp->pass_filter,
ppp->pass_len) == 0) {
if (ppp->debug & 1)
printk(KERN_DEBUG "PPP: inbound frame "
"not passed\n");
kfree_skb(skb);
return;
}
if (!(ppp->active_filter
&& sk_run_filter(skb, ppp->active_filter,
ppp->active_len) == 0))
ppp->last_recv = jiffies;
__skb_pull(skb, 2);
} else
#endif /* CONFIG_PPP_FILTER */
ppp->last_recv = jiffies;
if ((ppp->dev->flags & IFF_UP) == 0
|| ppp->npmode[npi] != NPMODE_PASS) {
......@@ -1770,7 +1768,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
struct channel *ch;
int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
if (!pskb_may_pull(skb, mphdrlen) || ppp->mrru == 0)
if (!pskb_may_pull(skb, mphdrlen + 1) || ppp->mrru == 0)
goto err; /* no good, throw it away */
/* Decode sequence number and begin/end bits */
......
......@@ -385,12 +385,12 @@ static int pppoe_rcv(struct sk_buff *skb,
struct pppoe_hdr *ph;
struct pppox_sock *po;
if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
goto drop;
if (!(skb = skb_share_check(skb, GFP_ATOMIC)))
goto out;
if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
goto drop;
ph = pppoe_hdr(skb);
po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source, dev->ifindex);
......@@ -848,71 +848,45 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
{
struct pppox_sock *po = pppox_sk(sk);
struct net_device *dev = po->pppoe_dev;
struct pppoe_hdr hdr;
struct pppoe_hdr *ph;
int headroom = skb_headroom(skb);
int data_len = skb->len;
struct sk_buff *skb2;
if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED))
goto abort;
hdr.ver = 1;
hdr.type = 1;
hdr.code = 0;
hdr.sid = po->num;
hdr.length = htons(skb->len);
if (!dev)
goto abort;
/* Copy the skb if there is no space for the header. */
if (headroom < (sizeof(struct pppoe_hdr) + dev->hard_header_len)) {
skb2 = dev_alloc_skb(32+skb->len +
sizeof(struct pppoe_hdr) +
dev->hard_header_len);
if (skb2 == NULL)
goto abort;
skb_reserve(skb2, dev->hard_header_len + sizeof(struct pppoe_hdr));
skb_copy_from_linear_data(skb, skb_put(skb2, skb->len),
skb->len);
} else {
/* Make a clone so as to not disturb the original skb,
* give dev_queue_xmit something it can free.
*/
skb2 = skb_clone(skb, GFP_ATOMIC);
if (skb2 == NULL)
goto abort;
}
/* Copy the data if there is no space for the header or if it's
* read-only.
*/
if (skb_cow_head(skb, sizeof(*ph) + dev->hard_header_len))
goto abort;
ph = (struct pppoe_hdr *) skb_push(skb2, sizeof(struct pppoe_hdr));
memcpy(ph, &hdr, sizeof(struct pppoe_hdr));
skb2->protocol = __constant_htons(ETH_P_PPP_SES);
__skb_push(skb, sizeof(*ph));
skb_reset_network_header(skb);
skb_reset_network_header(skb2);
ph = pppoe_hdr(skb);
ph->ver = 1;
ph->type = 1;
ph->code = 0;
ph->sid = po->num;
ph->length = htons(data_len);
skb2->dev = dev;
skb->protocol = __constant_htons(ETH_P_PPP_SES);
skb->dev = dev;
dev->hard_header(skb2, dev, ETH_P_PPP_SES,
dev->hard_header(skb, dev, ETH_P_PPP_SES,
po->pppoe_pa.remote, NULL, data_len);
/* We're transmitting skb2, and assuming that dev_queue_xmit
* will free it. The generic ppp layer however, is expecting
* that we give back 'skb' (not 'skb2') in case of failure,
* but free it in case of success.
*/
if (dev_queue_xmit(skb2) < 0)
if (dev_queue_xmit(skb) < 0)
goto abort;
kfree_skb(skb);
return 1;
abort:
return 0;
kfree_skb(skb);
return 1;
}
......
#
# Makefile for the SysKonnect SK-98xx device driver.
#
#
# Standalone driver params
# SKPARAM += -DSK_KERNEL_24
# SKPARAM += -DSK_KERNEL_24_26
# SKPARAM += -DSK_KERNEL_26
# SKPARAM += -DSK_KERNEL_22_24
obj-$(CONFIG_SK98LIN) += sk98lin.o
sk98lin-objs := \
skge.o \
skethtool.o \
skdim.o \
skaddr.o \
skgehwt.o \
skgeinit.o \
skgepnmi.o \
skgesirq.o \
ski2c.o \
sklm80.o \
skqueue.o \
skrlmt.o \
sktimer.o \
skvpd.o \
skxmac2.o
# DBGDEF = \
# -DDEBUG
ifdef DEBUG
DBGDEF += \
-DSK_DEBUG_CHKMOD=0x00000000L \
-DSK_DEBUG_CHKCAT=0x00000000L
endif
# **** possible debug modules for SK_DEBUG_CHKMOD *****************
# SK_DBGMOD_MERR 0x00000001L /* general module error indication */
# SK_DBGMOD_HWM 0x00000002L /* Hardware init module */
# SK_DBGMOD_RLMT 0x00000004L /* RLMT module */
# SK_DBGMOD_VPD 0x00000008L /* VPD module */
# SK_DBGMOD_I2C 0x00000010L /* I2C module */
# SK_DBGMOD_PNMI 0x00000020L /* PNMI module */
# SK_DBGMOD_CSUM 0x00000040L /* CSUM module */
# SK_DBGMOD_ADDR 0x00000080L /* ADDR module */
# SK_DBGMOD_DRV 0x00010000L /* DRV module */
# **** possible debug categories for SK_DEBUG_CHKCAT **************
# *** common modules ***
# SK_DBGCAT_INIT 0x00000001L module/driver initialization
# SK_DBGCAT_CTRL 0x00000002L controlling: add/rmv MCA/MAC and other controls (IOCTL)
# SK_DBGCAT_ERR 0x00000004L error handling paths
# SK_DBGCAT_TX 0x00000008L transmit path
# SK_DBGCAT_RX 0x00000010L receive path
# SK_DBGCAT_IRQ 0x00000020L general IRQ handling
# SK_DBGCAT_QUEUE 0x00000040L any queue management
# SK_DBGCAT_DUMP 0x00000080L large data output e.g. hex dump
# SK_DBGCAT_FATAL 0x00000100L large data output e.g. hex dump
# *** driver (file skge.c) ***
# SK_DBGCAT_DRV_ENTRY 0x00010000 entry points
# SK_DBGCAT_DRV_??? 0x00020000 not used
# SK_DBGCAT_DRV_MCA 0x00040000 multicast
# SK_DBGCAT_DRV_TX_PROGRESS 0x00080000 tx path
# SK_DBGCAT_DRV_RX_PROGRESS 0x00100000 rx path
# SK_DBGCAT_DRV_PROGRESS 0x00200000 general runtime
# SK_DBGCAT_DRV_??? 0x00400000 not used
# SK_DBGCAT_DRV_PROM 0x00800000 promiscuous mode
# SK_DBGCAT_DRV_TX_FRAME 0x01000000 display tx frames
# SK_DBGCAT_DRV_ERROR 0x02000000 error conditions
# SK_DBGCAT_DRV_INT_SRC 0x04000000 interrupts sources
# SK_DBGCAT_DRV_EVENT 0x08000000 driver events
EXTRA_CFLAGS += -Idrivers/net/sk98lin -DSK_DIAG_SUPPORT -DGENESIS -DYUKON $(DBGDEF) $(SKPARAM)
clean:
rm -f core *.o *.a *.s
/******************************************************************************
*
* Name: lm80.h
* Project: Gigabit Ethernet Adapters, Common Modules
* Version: $Revision: 1.6 $
* Date: $Date: 2003/05/13 17:26:52 $
* Purpose: Contains all defines for the LM80 Chip
* (National Semiconductor).
*
******************************************************************************/
/******************************************************************************
*
* (C)Copyright 1998-2002 SysKonnect.
* (C)Copyright 2002-2003 Marvell.
*
* 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.
*
* The information in this file is provided "AS IS" without warranty.
*
******************************************************************************/
#ifndef __INC_LM80_H
#define __INC_LM80_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* defines ********************************************************************/
/*
* LM80 register definition
*
* All registers are 8 bit wide
*/
#define LM80_CFG 0x00 /* Configuration Register */
#define LM80_ISRC_1 0x01 /* Interrupt Status Register 1 */
#define LM80_ISRC_2 0x02 /* Interrupt Status Register 2 */
#define LM80_IMSK_1 0x03 /* Interrupt Mask Register 1 */
#define LM80_IMSK_2 0x04 /* Interrupt Mask Register 2 */
#define LM80_FAN_CTRL 0x05 /* Fan Devisor/RST#/OS# Register */
#define LM80_TEMP_CTRL 0x06 /* OS# Config, Temp Res. Reg */
/* 0x07 - 0x1f reserved */
/* current values */
#define LM80_VT0_IN 0x20 /* current Voltage 0 value */
#define LM80_VT1_IN 0x21 /* current Voltage 1 value */
#define LM80_VT2_IN 0x22 /* current Voltage 2 value */
#define LM80_VT3_IN 0x23 /* current Voltage 3 value */
#define LM80_VT4_IN 0x24 /* current Voltage 4 value */
#define LM80_VT5_IN 0x25 /* current Voltage 5 value */
#define LM80_VT6_IN 0x26 /* current Voltage 6 value */
#define LM80_TEMP_IN 0x27 /* current Temperature value */
#define LM80_FAN1_IN 0x28 /* current Fan 1 count */
#define LM80_FAN2_IN 0x29 /* current Fan 2 count */
/* limit values */
#define LM80_VT0_HIGH_LIM 0x2a /* high limit val for Voltage 0 */
#define LM80_VT0_LOW_LIM 0x2b /* low limit val for Voltage 0 */
#define LM80_VT1_HIGH_LIM 0x2c /* high limit val for Voltage 1 */
#define LM80_VT1_LOW_LIM 0x2d /* low limit val for Voltage 1 */
#define LM80_VT2_HIGH_LIM 0x2e /* high limit val for Voltage 2 */
#define LM80_VT2_LOW_LIM 0x2f /* low limit val for Voltage 2 */
#define LM80_VT3_HIGH_LIM 0x30 /* high limit val for Voltage 3 */
#define LM80_VT3_LOW_LIM 0x31 /* low limit val for Voltage 3 */
#define LM80_VT4_HIGH_LIM 0x32 /* high limit val for Voltage 4 */
#define LM80_VT4_LOW_LIM 0x33 /* low limit val for Voltage 4 */
#define LM80_VT5_HIGH_LIM 0x34 /* high limit val for Voltage 5 */
#define LM80_VT5_LOW_LIM 0x35 /* low limit val for Voltage 5 */
#define LM80_VT6_HIGH_LIM 0x36 /* high limit val for Voltage 6 */
#define LM80_VT6_LOW_LIM 0x37 /* low limit val for Voltage 6 */
#define LM80_THOT_LIM_UP 0x38 /* hot temperature limit (high) */
#define LM80_THOT_LIM_LO 0x39 /* hot temperature limit (low) */
#define LM80_TOS_LIM_UP 0x3a /* OS temperature limit (high) */
#define LM80_TOS_LIM_LO 0x3b /* OS temperature limit (low) */
#define LM80_FAN1_COUNT_LIM 0x3c /* Fan 1 count limit (high) */
#define LM80_FAN2_COUNT_LIM 0x3d /* Fan 2 count limit (low) */
/* 0x3e - 0x3f reserved */
/*
* LM80 bit definitions
*/
/* LM80_CFG Configuration Register */
#define LM80_CFG_START (1<<0) /* start monitoring operation */
#define LM80_CFG_INT_ENA (1<<1) /* enables the INT# Interrupt output */
#define LM80_CFG_INT_POL (1<<2) /* INT# pol: 0 act low, 1 act high */
#define LM80_CFG_INT_CLR (1<<3) /* disables INT#/RST_OUT#/OS# outputs */
#define LM80_CFG_RESET (1<<4) /* signals a reset */
#define LM80_CFG_CHASS_CLR (1<<5) /* clears Chassis Intrusion (CI) pin */
#define LM80_CFG_GPO (1<<6) /* drives the GPO# pin */
#define LM80_CFG_INIT (1<<7) /* restore power on defaults */
/* LM80_ISRC_1 Interrupt Status Register 1 */
/* LM80_IMSK_1 Interrupt Mask Register 1 */
#define LM80_IS_VT0 (1<<0) /* limit exceeded for Voltage 0 */
#define LM80_IS_VT1 (1<<1) /* limit exceeded for Voltage 1 */
#define LM80_IS_VT2 (1<<2) /* limit exceeded for Voltage 2 */
#define LM80_IS_VT3 (1<<3) /* limit exceeded for Voltage 3 */
#define LM80_IS_VT4 (1<<4) /* limit exceeded for Voltage 4 */
#define LM80_IS_VT5 (1<<5) /* limit exceeded for Voltage 5 */
#define LM80_IS_VT6 (1<<6) /* limit exceeded for Voltage 6 */
#define LM80_IS_INT_IN (1<<7) /* state of INT_IN# */
/* LM80_ISRC_2 Interrupt Status Register 2 */
/* LM80_IMSK_2 Interrupt Mask Register 2 */
#define LM80_IS_TEMP (1<<0) /* HOT temperature limit exceeded */
#define LM80_IS_BTI (1<<1) /* state of BTI# pin */
#define LM80_IS_FAN1 (1<<2) /* count limit exceeded for Fan 1 */
#define LM80_IS_FAN2 (1<<3) /* count limit exceeded for Fan 2 */
#define LM80_IS_CI (1<<4) /* Chassis Intrusion occured */
#define LM80_IS_OS (1<<5) /* OS temperature limit exceeded */
/* bit 6 and 7 are reserved in LM80_ISRC_2 */
#define LM80_IS_HT_IRQ_MD (1<<6) /* Hot temperature interrupt mode */
#define LM80_IS_OT_IRQ_MD (1<<7) /* OS temperature interrupt mode */
/* LM80_FAN_CTRL Fan Devisor/RST#/OS# Register */
#define LM80_FAN1_MD_SEL (1<<0) /* Fan 1 mode select */
#define LM80_FAN2_MD_SEL (1<<1) /* Fan 2 mode select */
#define LM80_FAN1_PRM_CTL (3<<2) /* Fan 1 speed control */
#define LM80_FAN2_PRM_CTL (3<<4) /* Fan 2 speed control */
#define LM80_FAN_OS_ENA (1<<6) /* enable OS mode on RST_OUT#/OS# pins*/
#define LM80_FAN_RST_ENA (1<<7) /* sets RST_OUT#/OS# pins in RST mode */
/* LM80_TEMP_CTRL OS# Config, Temp Res. Reg */
#define LM80_TEMP_OS_STAT (1<<0) /* mirrors the state of RST_OUT#/OS# */
#define LM80_TEMP_OS_POL (1<<1) /* select OS# polarity */
#define LM80_TEMP_OS_MODE (1<<2) /* selects Interrupt mode */
#define LM80_TEMP_RES (1<<3) /* selects 9 or 11 bit temp resulution*/
#define LM80_TEMP_LSB (0xf<<4)/* 4 LSBs of 11 bit temp data */
#define LM80_TEMP_LSB_9 (1<<7) /* LSB of 9 bit temperature data */
/* 0x07 - 0x1f reserved */
/* LM80_VT0_IN current Voltage 0 value */
/* LM80_VT1_IN current Voltage 1 value */
/* LM80_VT2_IN current Voltage 2 value */
/* LM80_VT3_IN current Voltage 3 value */
/* LM80_VT4_IN current Voltage 4 value */
/* LM80_VT5_IN current Voltage 5 value */
/* LM80_VT6_IN current Voltage 6 value */
/* LM80_TEMP_IN current temperature value */
/* LM80_FAN1_IN current Fan 1 count */
/* LM80_FAN2_IN current Fan 2 count */
/* LM80_VT0_HIGH_LIM high limit val for Voltage 0 */
/* LM80_VT0_LOW_LIM low limit val for Voltage 0 */
/* LM80_VT1_HIGH_LIM high limit val for Voltage 1 */
/* LM80_VT1_LOW_LIM low limit val for Voltage 1 */
/* LM80_VT2_HIGH_LIM high limit val for Voltage 2 */
/* LM80_VT2_LOW_LIM low limit val for Voltage 2 */
/* LM80_VT3_HIGH_LIM high limit val for Voltage 3 */
/* LM80_VT3_LOW_LIM low limit val for Voltage 3 */
/* LM80_VT4_HIGH_LIM high limit val for Voltage 4 */
/* LM80_VT4_LOW_LIM low limit val for Voltage 4 */
/* LM80_VT5_HIGH_LIM high limit val for Voltage 5 */
/* LM80_VT5_LOW_LIM low limit val for Voltage 5 */
/* LM80_VT6_HIGH_LIM high limit val for Voltage 6 */
/* LM80_VT6_LOW_LIM low limit val for Voltage 6 */
/* LM80_THOT_LIM_UP hot temperature limit (high) */
/* LM80_THOT_LIM_LO hot temperature limit (low) */
/* LM80_TOS_LIM_UP OS temperature limit (high) */
/* LM80_TOS_LIM_LO OS temperature limit (low) */
/* LM80_FAN1_COUNT_LIM Fan 1 count limit (high) */
/* LM80_FAN2_COUNT_LIM Fan 2 count limit (low) */
/* 0x3e - 0x3f reserved */
#define LM80_ADDR 0x28 /* LM80 default addr */
/* typedefs *******************************************************************/
/* function prototypes ********************************************************/
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __INC_LM80_H */
/******************************************************************************
*
* Name: skaddr.h
* Project: Gigabit Ethernet Adapters, ADDR-Modul
* Version: $Revision: 1.29 $
* Date: $Date: 2003/05/13 16:57:24 $
* Purpose: Header file for Address Management (MC, UC, Prom).
*
******************************************************************************/
/******************************************************************************
*
* (C)Copyright 1998-2002 SysKonnect GmbH.
* (C)Copyright 2002-2003 Marvell.
*
* 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.
*
* The information in this file is provided "AS IS" without warranty.
*
******************************************************************************/
/******************************************************************************
*
* Description:
*
* This module is intended to manage multicast addresses and promiscuous mode
* on GEnesis adapters.
*
* Include File Hierarchy:
*
* "skdrv1st.h"
* ...
* "sktypes.h"
* "skqueue.h"
* "skaddr.h"
* ...
* "skdrv2nd.h"
*
******************************************************************************/
#ifndef __INC_SKADDR_H
#define __INC_SKADDR_H
#ifdef __cplusplus
extern "C" {
#endif /* cplusplus */
/* defines ********************************************************************/
#define SK_MAC_ADDR_LEN 6 /* Length of MAC address. */
#define SK_MAX_ADDRS 14 /* #Addrs for exact match. */
/* ----- Common return values ----- */
#define SK_ADDR_SUCCESS 0 /* Function returned successfully. */
#define SK_ADDR_ILLEGAL_PORT 100 /* Port number too high. */
#define SK_ADDR_TOO_EARLY 101 /* Function called too early. */
/* ----- Clear/Add flag bits ----- */
#define SK_ADDR_PERMANENT 1 /* RLMT Address */
/* ----- Additional Clear flag bits ----- */
#define SK_MC_SW_ONLY 2 /* Do not update HW when clearing. */
/* ----- Override flag bits ----- */
#define SK_ADDR_LOGICAL_ADDRESS 0
#define SK_ADDR_VIRTUAL_ADDRESS (SK_ADDR_LOGICAL_ADDRESS) /* old */
#define SK_ADDR_PHYSICAL_ADDRESS 1
#define SK_ADDR_CLEAR_LOGICAL 2
#define SK_ADDR_SET_LOGICAL 4
/* ----- Override return values ----- */
#define SK_ADDR_OVERRIDE_SUCCESS (SK_ADDR_SUCCESS)
#define SK_ADDR_DUPLICATE_ADDRESS 1
#define SK_ADDR_MULTICAST_ADDRESS 2
/* ----- Partitioning of excact match table ----- */
#define SK_ADDR_EXACT_MATCHES 16 /* #Exact match entries. */
#define SK_ADDR_FIRST_MATCH_RLMT 1
#define SK_ADDR_LAST_MATCH_RLMT 2
#define SK_ADDR_FIRST_MATCH_DRV 3
#define SK_ADDR_LAST_MATCH_DRV (SK_ADDR_EXACT_MATCHES - 1)
/* ----- SkAddrMcAdd/SkAddrMcUpdate return values ----- */
#define SK_MC_FILTERING_EXACT 0 /* Exact filtering. */
#define SK_MC_FILTERING_INEXACT 1 /* Inexact filtering. */
/* ----- Additional SkAddrMcAdd return values ----- */
#define SK_MC_ILLEGAL_ADDRESS 2 /* Illegal address. */
#define SK_MC_ILLEGAL_PORT 3 /* Illegal port (not the active one). */
#define SK_MC_RLMT_OVERFLOW 4 /* Too many RLMT mc addresses. */
/* Promiscuous mode bits ----- */
#define SK_PROM_MODE_NONE 0 /* Normal receive. */
#define SK_PROM_MODE_LLC 1 /* Receive all LLC frames. */
#define SK_PROM_MODE_ALL_MC 2 /* Receive all multicast frames. */
/* #define SK_PROM_MODE_NON_LLC 4 */ /* Receive all non-LLC frames. */
/* Macros */
#ifdef OLD_STUFF
#ifndef SK_ADDR_EQUAL
/*
* "&" instead of "&&" allows better optimization on IA-64.
* The replacement is safe here, as all bytes exist.
*/
#ifndef SK_ADDR_DWORD_COMPARE
#define SK_ADDR_EQUAL(A1,A2) ( \
(((SK_U8 *)(A1))[5] == ((SK_U8 *)(A2))[5]) & \
(((SK_U8 *)(A1))[4] == ((SK_U8 *)(A2))[4]) & \
(((SK_U8 *)(A1))[3] == ((SK_U8 *)(A2))[3]) & \
(((SK_U8 *)(A1))[2] == ((SK_U8 *)(A2))[2]) & \
(((SK_U8 *)(A1))[1] == ((SK_U8 *)(A2))[1]) & \
(((SK_U8 *)(A1))[0] == ((SK_U8 *)(A2))[0]))
#else /* SK_ADDR_DWORD_COMPARE */
#define SK_ADDR_EQUAL(A1,A2) ( \
(*(SK_U32 *)&(((SK_U8 *)(A1))[2]) == *(SK_U32 *)&(((SK_U8 *)(A2))[2])) & \
(*(SK_U32 *)&(((SK_U8 *)(A1))[0]) == *(SK_U32 *)&(((SK_U8 *)(A2))[0])))
#endif /* SK_ADDR_DWORD_COMPARE */
#endif /* SK_ADDR_EQUAL */
#endif /* 0 */
#ifndef SK_ADDR_EQUAL
#ifndef SK_ADDR_DWORD_COMPARE
#define SK_ADDR_EQUAL(A1,A2) ( \
(((SK_U8 SK_FAR *)(A1))[5] == ((SK_U8 SK_FAR *)(A2))[5]) & \
(((SK_U8 SK_FAR *)(A1))[4] == ((SK_U8 SK_FAR *)(A2))[4]) & \
(((SK_U8 SK_FAR *)(A1))[3] == ((SK_U8 SK_FAR *)(A2))[3]) & \
(((SK_U8 SK_FAR *)(A1))[2] == ((SK_U8 SK_FAR *)(A2))[2]) & \
(((SK_U8 SK_FAR *)(A1))[1] == ((SK_U8 SK_FAR *)(A2))[1]) & \
(((SK_U8 SK_FAR *)(A1))[0] == ((SK_U8 SK_FAR *)(A2))[0]))
#else /* SK_ADDR_DWORD_COMPARE */
#define SK_ADDR_EQUAL(A1,A2) ( \
(*(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[4]) == \
*(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[4])) && \
(*(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[0]) == \
*(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[0])))
#endif /* SK_ADDR_DWORD_COMPARE */
#endif /* SK_ADDR_EQUAL */
/* typedefs *******************************************************************/
typedef struct s_MacAddr {
SK_U8 a[SK_MAC_ADDR_LEN];
} SK_MAC_ADDR;
/* SK_FILTER is used to ensure alignment of the filter. */
typedef union s_InexactFilter {
SK_U8 Bytes[8];
SK_U64 Val; /* Dummy entry for alignment only. */
} SK_FILTER64;
typedef struct s_AddrNet SK_ADDR_NET;
typedef struct s_AddrPort {
/* ----- Public part (read-only) ----- */
SK_MAC_ADDR CurrentMacAddress; /* Current physical MAC Address. */
SK_MAC_ADDR PermanentMacAddress; /* Permanent physical MAC Address. */
int PromMode; /* Promiscuous Mode. */
/* ----- Private part ----- */
SK_MAC_ADDR PreviousMacAddress; /* Prev. phys. MAC Address. */
SK_BOOL CurrentMacAddressSet; /* CurrentMacAddress is set. */
SK_U8 Align01;
SK_U32 FirstExactMatchRlmt;
SK_U32 NextExactMatchRlmt;
SK_U32 FirstExactMatchDrv;
SK_U32 NextExactMatchDrv;
SK_MAC_ADDR Exact[SK_ADDR_EXACT_MATCHES];
SK_FILTER64 InexactFilter; /* For 64-bit hash register. */
SK_FILTER64 InexactRlmtFilter; /* For 64-bit hash register. */
SK_FILTER64 InexactDrvFilter; /* For 64-bit hash register. */
} SK_ADDR_PORT;
struct s_AddrNet {
/* ----- Public part (read-only) ----- */
SK_MAC_ADDR CurrentMacAddress; /* Logical MAC Address. */
SK_MAC_ADDR PermanentMacAddress; /* Logical MAC Address. */
/* ----- Private part ----- */
SK_U32 ActivePort; /* View of module ADDR. */
SK_BOOL CurrentMacAddressSet; /* CurrentMacAddress is set. */
SK_U8 Align01;
SK_U16 Align02;
};
typedef struct s_Addr {
/* ----- Public part (read-only) ----- */
SK_ADDR_NET Net[SK_MAX_NETS];
SK_ADDR_PORT Port[SK_MAX_MACS];
/* ----- Private part ----- */
} SK_ADDR;
/* function prototypes ********************************************************/
#ifndef SK_KR_PROTO
/* Functions provided by SkAddr */
/* ANSI/C++ compliant function prototypes */
extern int SkAddrInit(
SK_AC *pAC,
SK_IOC IoC,
int Level);
extern int SkAddrMcClear(
SK_AC *pAC,
SK_IOC IoC,
SK_U32 PortNumber,
int Flags);
extern int SkAddrMcAdd(
SK_AC *pAC,
SK_IOC IoC,
SK_U32 PortNumber,
SK_MAC_ADDR *pMc,
int Flags);
extern int SkAddrMcUpdate(
SK_AC *pAC,
SK_IOC IoC,
SK_U32 PortNumber);
extern int SkAddrOverride(
SK_AC *pAC,
SK_IOC IoC,
SK_U32 PortNumber,
SK_MAC_ADDR SK_FAR *pNewAddr,
int Flags);
extern int SkAddrPromiscuousChange(
SK_AC *pAC,
SK_IOC IoC,
SK_U32 PortNumber,
int NewPromMode);
#ifndef SK_SLIM
extern int SkAddrSwap(
SK_AC *pAC,
SK_IOC IoC,
SK_U32 FromPortNumber,
SK_U32 ToPortNumber);
#endif
#else /* defined(SK_KR_PROTO)) */
/* Non-ANSI/C++ compliant function prototypes */
#error KR-style prototypes are not yet provided.
#endif /* defined(SK_KR_PROTO)) */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __INC_SKADDR_H */
此差异已折叠。
/******************************************************************************
*
* Name: skdebug.h
* Project: Gigabit Ethernet Adapters, Common Modules
* Version: $Revision: 1.14 $
* Date: $Date: 2003/05/13 17:26:00 $
* Purpose: SK specific DEBUG support
*
******************************************************************************/
/******************************************************************************
*
* (C)Copyright 1998-2002 SysKonnect.
* (C)Copyright 2002-2003 Marvell.
*
* 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.
*
* The information in this file is provided "AS IS" without warranty.
*
******************************************************************************/
#ifndef __INC_SKDEBUG_H
#define __INC_SKDEBUG_H
#ifdef DEBUG
#ifndef SK_DBG_MSG
#define SK_DBG_MSG(pAC,comp,cat,arg) \
if ( ((comp) & SK_DBG_CHKMOD(pAC)) && \
((cat) & SK_DBG_CHKCAT(pAC)) ) { \
SK_DBG_PRINTF arg ; \
}
#endif
#else
#define SK_DBG_MSG(pAC,comp,lev,arg)
#endif
/* PLS NOTE:
* =========
* Due to any restrictions of kernel printf routines do not use other
* format identifiers as: %x %d %c %s .
* Never use any combined format identifiers such as: %lx %ld in your
* printf - argument (arg) because some OS specific kernel printfs may
* only support some basic identifiers.
*/
/* Debug modules */
#define SK_DBGMOD_MERR 0x00000001L /* general module error indication */
#define SK_DBGMOD_HWM 0x00000002L /* Hardware init module */
#define SK_DBGMOD_RLMT 0x00000004L /* RLMT module */
#define SK_DBGMOD_VPD 0x00000008L /* VPD module */
#define SK_DBGMOD_I2C 0x00000010L /* I2C module */
#define SK_DBGMOD_PNMI 0x00000020L /* PNMI module */
#define SK_DBGMOD_CSUM 0x00000040L /* CSUM module */
#define SK_DBGMOD_ADDR 0x00000080L /* ADDR module */
#define SK_DBGMOD_PECP 0x00000100L /* PECP module */
#define SK_DBGMOD_POWM 0x00000200L /* Power Management module */
/* Debug events */
#define SK_DBGCAT_INIT 0x00000001L /* module/driver initialization */
#define SK_DBGCAT_CTRL 0x00000002L /* controlling devices */
#define SK_DBGCAT_ERR 0x00000004L /* error handling paths */
#define SK_DBGCAT_TX 0x00000008L /* transmit path */
#define SK_DBGCAT_RX 0x00000010L /* receive path */
#define SK_DBGCAT_IRQ 0x00000020L /* general IRQ handling */
#define SK_DBGCAT_QUEUE 0x00000040L /* any queue management */
#define SK_DBGCAT_DUMP 0x00000080L /* large data output e.g. hex dump */
#define SK_DBGCAT_FATAL 0x00000100L /* fatal error */
#endif /* __INC_SKDEBUG_H */
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册