Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: [PATCH] powerpc: Use the ibm,pa-features property if available powerpc: Fix incorrect might_sleep in __get_user/__put_user on kernel addresses [PATCH] ppc32 CPM_UART: fixes and improvements [PATCH] ppc32 CPM_UART: Fixed break send on SCC [PATCH] powerpc/kprobes: fix singlestep out-of-line [PATCH] powerpc/pseries: avoid crash in PCI code if mem system not up
This commit is contained in:
commit
d98550e334
12 changed files with 209 additions and 27 deletions
|
@ -90,15 +90,15 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
|
|||
|
||||
static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
|
||||
{
|
||||
kprobe_opcode_t insn = *p->ainsn.insn;
|
||||
|
||||
regs->msr |= MSR_SE;
|
||||
|
||||
/* single step inline if it is a trap variant */
|
||||
if (is_trap(insn))
|
||||
regs->nip = (unsigned long)p->addr;
|
||||
else
|
||||
regs->nip = (unsigned long)p->ainsn.insn;
|
||||
/*
|
||||
* On powerpc we should single step on the original
|
||||
* instruction even if the probed insn is a trap
|
||||
* variant as values in regs could play a part in
|
||||
* if the trap is taken or not
|
||||
*/
|
||||
regs->nip = (unsigned long)p->ainsn.insn;
|
||||
}
|
||||
|
||||
static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
|
||||
|
|
|
@ -885,6 +885,74 @@ void __init unflatten_device_tree(void)
|
|||
DBG(" <- unflatten_device_tree()\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* ibm,pa-features is a per-cpu property that contains a string of
|
||||
* attribute descriptors, each of which has a 2 byte header plus up
|
||||
* to 254 bytes worth of processor attribute bits. First header
|
||||
* byte specifies the number of bytes following the header.
|
||||
* Second header byte is an "attribute-specifier" type, of which
|
||||
* zero is the only currently-defined value.
|
||||
* Implementation: Pass in the byte and bit offset for the feature
|
||||
* that we are interested in. The function will return -1 if the
|
||||
* pa-features property is missing, or a 1/0 to indicate if the feature
|
||||
* is supported/not supported. Note that the bit numbers are
|
||||
* big-endian to match the definition in PAPR.
|
||||
*/
|
||||
static struct ibm_pa_feature {
|
||||
unsigned long cpu_features; /* CPU_FTR_xxx bit */
|
||||
unsigned int cpu_user_ftrs; /* PPC_FEATURE_xxx bit */
|
||||
unsigned char pabyte; /* byte number in ibm,pa-features */
|
||||
unsigned char pabit; /* bit number (big-endian) */
|
||||
unsigned char invert; /* if 1, pa bit set => clear feature */
|
||||
} ibm_pa_features[] __initdata = {
|
||||
{0, PPC_FEATURE_HAS_MMU, 0, 0, 0},
|
||||
{0, PPC_FEATURE_HAS_FPU, 0, 1, 0},
|
||||
{CPU_FTR_SLB, 0, 0, 2, 0},
|
||||
{CPU_FTR_CTRL, 0, 0, 3, 0},
|
||||
{CPU_FTR_NOEXECUTE, 0, 0, 6, 0},
|
||||
{CPU_FTR_NODSISRALIGN, 0, 1, 1, 1},
|
||||
{CPU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0},
|
||||
};
|
||||
|
||||
static void __init check_cpu_pa_features(unsigned long node)
|
||||
{
|
||||
unsigned char *pa_ftrs;
|
||||
unsigned long len, tablelen, i, bit;
|
||||
|
||||
pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen);
|
||||
if (pa_ftrs == NULL)
|
||||
return;
|
||||
|
||||
/* find descriptor with type == 0 */
|
||||
for (;;) {
|
||||
if (tablelen < 3)
|
||||
return;
|
||||
len = 2 + pa_ftrs[0];
|
||||
if (tablelen < len)
|
||||
return; /* descriptor 0 not found */
|
||||
if (pa_ftrs[1] == 0)
|
||||
break;
|
||||
tablelen -= len;
|
||||
pa_ftrs += len;
|
||||
}
|
||||
|
||||
/* loop over bits we know about */
|
||||
for (i = 0; i < ARRAY_SIZE(ibm_pa_features); ++i) {
|
||||
struct ibm_pa_feature *fp = &ibm_pa_features[i];
|
||||
|
||||
if (fp->pabyte >= pa_ftrs[0])
|
||||
continue;
|
||||
bit = (pa_ftrs[2 + fp->pabyte] >> (7 - fp->pabit)) & 1;
|
||||
if (bit ^ fp->invert) {
|
||||
cur_cpu_spec->cpu_features |= fp->cpu_features;
|
||||
cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftrs;
|
||||
} else {
|
||||
cur_cpu_spec->cpu_features &= ~fp->cpu_features;
|
||||
cur_cpu_spec->cpu_user_features &= ~fp->cpu_user_ftrs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int __init early_init_dt_scan_cpus(unsigned long node,
|
||||
const char *uname, int depth,
|
||||
void *data)
|
||||
|
@ -969,6 +1037,8 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
|
|||
}
|
||||
#endif /* CONFIG_ALTIVEC */
|
||||
|
||||
check_cpu_pa_features(node);
|
||||
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
if (nthreads > 1)
|
||||
cur_cpu_spec->cpu_features |= CPU_FTR_SMT;
|
||||
|
|
|
@ -118,7 +118,15 @@ int eeh_send_failure_event (struct device_node *dn,
|
|||
{
|
||||
unsigned long flags;
|
||||
struct eeh_event *event;
|
||||
char *location;
|
||||
|
||||
if (!mem_init_done) {
|
||||
printk(KERN_ERR "EEH: event during early boot not handled\n");
|
||||
location = (char *) get_property(dn, "ibm,loc-code", NULL);
|
||||
printk(KERN_ERR "EEH: device node = %s\n", dn->full_name);
|
||||
printk(KERN_ERR "EEH: PCI location = %s\n", location);
|
||||
return 1;
|
||||
}
|
||||
event = kmalloc(sizeof(*event), GFP_ATOMIC);
|
||||
if (event == NULL) {
|
||||
printk (KERN_ERR "EEH: out of memory, event not handled\n");
|
||||
|
|
|
@ -378,7 +378,7 @@ int __init mpc866ads_init(void)
|
|||
ppc_sys_device_setfunc(MPC8xx_CPM_SMC1, PPC_SYS_FUNC_UART);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_CPM_SMCer
|
||||
#ifdef CONFIG_SERIAL_CPM_SMC
|
||||
ppc_sys_device_enable(MPC8xx_CPM_SMC2);
|
||||
ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART);
|
||||
#endif
|
||||
|
|
|
@ -5,6 +5,13 @@
|
|||
*
|
||||
* Copyright (C) 2004 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* 2006 (c) MontaVista Software, Inc.
|
||||
* Vitaly Bordug <vbordug@ru.mvista.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public License
|
||||
* version 2. This program is licensed "as is" without any warranty of any
|
||||
* kind, whether express or implied.
|
||||
*
|
||||
*/
|
||||
#ifndef CPM_UART_H
|
||||
#define CPM_UART_H
|
||||
|
@ -101,12 +108,13 @@ static inline unsigned long cpu2cpm_addr(void* addr, struct uart_cpm_port *pinfo
|
|||
int offset;
|
||||
u32 val = (u32)addr;
|
||||
/* sane check */
|
||||
if ((val >= (u32)pinfo->mem_addr) &&
|
||||
if (likely((val >= (u32)pinfo->mem_addr)) &&
|
||||
(val<((u32)pinfo->mem_addr + pinfo->mem_size))) {
|
||||
offset = val - (u32)pinfo->mem_addr;
|
||||
return pinfo->dma_addr+offset;
|
||||
}
|
||||
printk("%s(): address %x to translate out of range!\n", __FUNCTION__, val);
|
||||
/* something nasty happened */
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -115,12 +123,13 @@ static inline void *cpm2cpu_addr(unsigned long addr, struct uart_cpm_port *pinfo
|
|||
int offset;
|
||||
u32 val = addr;
|
||||
/* sane check */
|
||||
if ((val >= pinfo->dma_addr) &&
|
||||
(val<(pinfo->dma_addr + pinfo->mem_size))) {
|
||||
if (likely((val >= pinfo->dma_addr) &&
|
||||
(val<(pinfo->dma_addr + pinfo->mem_size)))) {
|
||||
offset = val - (u32)pinfo->dma_addr;
|
||||
return (void*)(pinfo->mem_addr+offset);
|
||||
}
|
||||
printk("%s(): address %x to translate out of range!\n", __FUNCTION__, val);
|
||||
/* something nasty happened */
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
*
|
||||
* Copyright (C) 2004 Freescale Semiconductor, Inc.
|
||||
* (C) 2004 Intracom, S.A.
|
||||
* (C) 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com>
|
||||
* (C) 2005-2006 MontaVista Software, Inc.
|
||||
* Vitaly Bordug <vbordug@ru.mvista.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -81,7 +82,7 @@ early_uart_get_pdev(int index)
|
|||
}
|
||||
|
||||
|
||||
void cpm_uart_count(void)
|
||||
static void cpm_uart_count(void)
|
||||
{
|
||||
cpm_uart_nr = 0;
|
||||
#ifdef CONFIG_SERIAL_CPM_SMC1
|
||||
|
@ -104,6 +105,21 @@ void cpm_uart_count(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* Get UART number by its id */
|
||||
static int cpm_uart_id2nr(int id)
|
||||
{
|
||||
int i;
|
||||
if (id < UART_NR) {
|
||||
for (i=0; i<UART_NR; i++) {
|
||||
if (cpm_uart_port_map[i] == id)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
/* not found or invalid argument */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check, if transmit buffers are processed
|
||||
*/
|
||||
|
@ -457,7 +473,11 @@ static void cpm_uart_shutdown(struct uart_port *port)
|
|||
}
|
||||
|
||||
/* Shut them really down and reinit buffer descriptors */
|
||||
cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
|
||||
if (IS_SMC(pinfo))
|
||||
cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
|
||||
else
|
||||
cpm_line_cr_cmd(line, CPM_CR_GRA_STOP_TX);
|
||||
|
||||
cpm_uart_initbd(pinfo);
|
||||
}
|
||||
}
|
||||
|
@ -1008,7 +1028,11 @@ int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
|
|||
int line;
|
||||
u32 mem, pram;
|
||||
|
||||
for (line=0; line<UART_NR && cpm_uart_port_map[line]!=pdata->fs_no; line++);
|
||||
line = cpm_uart_id2nr(idx);
|
||||
if(line < 0) {
|
||||
printk(KERN_ERR"%s(): port %d is not registered", __FUNCTION__, idx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pinfo = (struct uart_cpm_port *) &cpm_uart_ports[idx];
|
||||
|
||||
|
@ -1241,8 +1265,7 @@ static int cpm_uart_drv_probe(struct device *dev)
|
|||
}
|
||||
|
||||
pdata = pdev->dev.platform_data;
|
||||
pr_debug("cpm_uart_drv_probe: Adding CPM UART %d\n",
|
||||
cpm_uart_port_map[pdata->fs_no]);
|
||||
pr_debug("cpm_uart_drv_probe: Adding CPM UART %d\n", cpm_uart_id2nr(pdata->fs_no));
|
||||
|
||||
if ((ret = cpm_uart_drv_get_platform_data(pdev, 0)))
|
||||
return ret;
|
||||
|
@ -1261,7 +1284,7 @@ static int cpm_uart_drv_remove(struct device *dev)
|
|||
struct fs_uart_platform_info *pdata = pdev->dev.platform_data;
|
||||
|
||||
pr_debug("cpm_uart_drv_remove: Removing CPM UART %d\n",
|
||||
cpm_uart_port_map[pdata->fs_no]);
|
||||
cpm_uart_id2nr(pdata->fs_no));
|
||||
|
||||
uart_remove_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port);
|
||||
return 0;
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
*
|
||||
* Copyright (C) 2004 Freescale Semiconductor, Inc.
|
||||
* (C) 2004 Intracom, S.A.
|
||||
* (C) 2006 MontaVista Software, Inc.
|
||||
* Vitaly Bordug <vbordug@ru.mvista.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
*
|
||||
* Copyright (C) 2004 Freescale Semiconductor, Inc.
|
||||
* (C) 2004 Intracom, S.A.
|
||||
* (C) 2006 MontaVista Software, Inc.
|
||||
* Vitaly Bordug <vbordug@ru.mvista.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
#define VERIFY_READ 0
|
||||
#define VERIFY_WRITE 1
|
||||
|
@ -179,9 +180,11 @@ do { \
|
|||
#define __put_user_nocheck(x, ptr, size) \
|
||||
({ \
|
||||
long __pu_err; \
|
||||
might_sleep(); \
|
||||
__typeof__(*(ptr)) __user *__pu_addr = (ptr); \
|
||||
if (!is_kernel_addr((unsigned long)__pu_addr)) \
|
||||
might_sleep(); \
|
||||
__chk_user_ptr(ptr); \
|
||||
__put_user_size((x), (ptr), (size), __pu_err); \
|
||||
__put_user_size((x), __pu_addr, (size), __pu_err); \
|
||||
__pu_err; \
|
||||
})
|
||||
|
||||
|
@ -258,9 +261,11 @@ do { \
|
|||
({ \
|
||||
long __gu_err; \
|
||||
unsigned long __gu_val; \
|
||||
const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
|
||||
__chk_user_ptr(ptr); \
|
||||
might_sleep(); \
|
||||
__get_user_size(__gu_val, (ptr), (size), __gu_err); \
|
||||
if (!is_kernel_addr((unsigned long)__gu_addr)) \
|
||||
might_sleep(); \
|
||||
__get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
|
||||
(x) = (__typeof__(*(ptr)))__gu_val; \
|
||||
__gu_err; \
|
||||
})
|
||||
|
@ -270,9 +275,11 @@ do { \
|
|||
({ \
|
||||
long __gu_err; \
|
||||
long long __gu_val; \
|
||||
const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
|
||||
__chk_user_ptr(ptr); \
|
||||
might_sleep(); \
|
||||
__get_user_size(__gu_val, (ptr), (size), __gu_err); \
|
||||
if (!is_kernel_addr((unsigned long)__gu_addr)) \
|
||||
might_sleep(); \
|
||||
__get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
|
||||
(x) = (__typeof__(*(ptr)))__gu_val; \
|
||||
__gu_err; \
|
||||
})
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#define CPM_CR_INIT_TX ((ushort)0x0002)
|
||||
#define CPM_CR_HUNT_MODE ((ushort)0x0003)
|
||||
#define CPM_CR_STOP_TX ((ushort)0x0004)
|
||||
#define CPM_CR_GRA_STOP_TX ((ushort)0x0005)
|
||||
#define CPM_CR_RESTART_TX ((ushort)0x0006)
|
||||
#define CPM_CR_CLOSE_RX_BD ((ushort)0x0007)
|
||||
#define CPM_CR_SET_GADDR ((ushort)0x0008)
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
#define CPM_CR_INIT_TX ((ushort)0x0002)
|
||||
#define CPM_CR_HUNT_MODE ((ushort)0x0003)
|
||||
#define CPM_CR_STOP_TX ((ushort)0x0004)
|
||||
#define CPM_CR_GRA_STOP_TX ((ushort)0x0005)
|
||||
#define CPM_CR_GRA_STOP_TX ((ushort)0x0005)
|
||||
#define CPM_CR_RESTART_TX ((ushort)0x0006)
|
||||
#define CPM_CR_SET_GADDR ((ushort)0x0008)
|
||||
#define CPM_CR_START_IDMA ((ushort)0x0009)
|
||||
|
|
60
include/linux/fs_uart_pd.h
Normal file
60
include/linux/fs_uart_pd.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Platform information definitions for the CPM Uart driver.
|
||||
*
|
||||
* 2006 (c) MontaVista Software, Inc.
|
||||
* Vitaly Bordug <vbordug@ru.mvista.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public License
|
||||
* version 2. This program is licensed "as is" without any warranty of any
|
||||
* kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#ifndef FS_UART_PD_H
|
||||
#define FS_UART_PD_H
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <asm/types.h>
|
||||
|
||||
enum fs_uart_id {
|
||||
fsid_smc1_uart,
|
||||
fsid_smc2_uart,
|
||||
fsid_scc1_uart,
|
||||
fsid_scc2_uart,
|
||||
fsid_scc3_uart,
|
||||
fsid_scc4_uart,
|
||||
fs_uart_nr,
|
||||
};
|
||||
|
||||
static inline int fs_uart_id_scc2fsid(int id)
|
||||
{
|
||||
return fsid_scc1_uart + id - 1;
|
||||
}
|
||||
|
||||
static inline int fs_uart_id_fsid2scc(int id)
|
||||
{
|
||||
return id - fsid_scc1_uart + 1;
|
||||
}
|
||||
|
||||
static inline int fs_uart_id_smc2fsid(int id)
|
||||
{
|
||||
return fsid_smc1_uart + id - 1;
|
||||
}
|
||||
|
||||
static inline int fs_uart_id_fsid2smc(int id)
|
||||
{
|
||||
return id - fsid_smc1_uart + 1;
|
||||
}
|
||||
|
||||
struct fs_uart_platform_info {
|
||||
void(*init_ioports)(void);
|
||||
/* device specific information */
|
||||
int fs_no; /* controller index */
|
||||
u32 uart_clk;
|
||||
u8 tx_num_fifo;
|
||||
u8 tx_buf_size;
|
||||
u8 rx_num_fifo;
|
||||
u8 rx_buf_size;
|
||||
u8 brg;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue