Commit 049711bf authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next

Pull sparc updates from David Miller:

 1) Add sparc RAM output to /proc/iomem, from Bob Picco.

 2) Allow seeks on /dev/mdesc, from Khalid Aziz.

 3) Cleanup sparc64 I/O accessors, from Sam Ravnborg.

 4) If update_mmu_cache{,_pmd}() is called with an not-valid mapping, do
    not insert it into the TLB miss hash tables otherwise we'll
    livelock.  Based upon work by Christopher Alexander Tobias Schulze.

 5) Fix BREAK detection in sunsab driver when no actual characters are
    pending, from Christopher Alexander Tobias Schulze.

 6) Because we have modules --> openfirmware --> vmalloc ordering of
    virtual memory, the lazy VMAP TLB flusher can cons up an invocation
    of flush_tlb_kernel_range() that covers the openfirmware address
    range.  Unfortunately this will flush out the firmware's locked TLB
    mapping which causes all kinds of trouble.  Just split up the flush
    request if this happens, but in the long term the lazy VMAP flusher
    should probably be made a little bit smarter.

    Based upon work by Christopher Alexander Tobias Schulze.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next:
  sparc64: Fix up merge thinko.
  sparc: Add "install" target
  arch/sparc/math-emu/math_32.c: drop stray break operator
  sparc64: ldc_connect() should not return EINVAL when handshake is in progress.
  sparc64: Guard against flushing openfirmware mappings.
  sunsab: Fix detection of BREAK on sunsab serial console
  bbc-i2c: Fix BBC I2C envctrl on SunBlade 2000
  sparc64: Do not insert non-valid PTEs into the TSB hash table.
  sparc64: avoid code duplication in io_64.h
  sparc64: reorder functions in io_64.h
  sparc64: drop unused SLOW_DOWN_IO definitions
  sparc64: remove macro indirection in io_64.h
  sparc64: update IO access functions in PeeCeeI
  sparcspkr: use sbus_*() primitives for IO
  sparc: Add support for seek and shorter read to /dev/mdesc
  sparc: use %s for unaligned panic
  drivers/sbus/char: Micro-optimization in display7seg.c
  display7seg: Introduce the use of the managed version of kzalloc
  sparc64 - add mem to iomem resource
parents ae045e24 5b6ff9df
......@@ -68,6 +68,9 @@ all: zImage
image zImage uImage tftpboot.img vmlinux.aout: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
install:
$(Q)$(MAKE) $(build)=$(boot) $@
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
......
......@@ -69,3 +69,7 @@ $(obj)/image: vmlinux FORCE
$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback System.map $(ROOT_IMG) FORCE
$(call if_changed,elftoaout)
$(call if_changed,piggy)
install:
sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(obj)/zImage \
System.map "$(INSTALL_PATH)"
#!/bin/sh
#
# 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) 1995 by Linus Torvalds
#
# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
#
# "make install" script for SPARC architecture
#
# Arguments:
# $1 - kernel version
# $2 - kernel image file
# $3 - kernel map file
# $4 - default install path (blank if root directory)
#
verify () {
if [ ! -f "$1" ]; then
echo "" 1>&2
echo " *** Missing file: $1" 1>&2
echo ' *** You need to run "make" before "make install".' 1>&2
echo "" 1>&2
exit 1
fi
}
# Make sure the files actually exist
verify "$2"
verify "$3"
# User may have a custom install script
if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi
if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi
# Default install - same as make zlilo
if [ -f $4/vmlinuz ]; then
mv $4/vmlinuz $4/vmlinuz.old
fi
if [ -f $4/System.map ]; then
mv $4/System.map $4/System.old
fi
cat $2 > $4/vmlinuz
cp $3 $4/System.map
This diff is collapsed.
......@@ -34,6 +34,8 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
{
}
void flush_tlb_kernel_range(unsigned long start, unsigned long end);
#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
void flush_tlb_pending(void);
......@@ -48,11 +50,6 @@ void __flush_tlb_kernel_range(unsigned long start, unsigned long end);
#ifndef CONFIG_SMP
#define flush_tlb_kernel_range(start,end) \
do { flush_tsb_kernel_range(start,end); \
__flush_tlb_kernel_range(start,end); \
} while (0)
static inline void global_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr)
{
__flush_tlb_page(CTX_HWBITS(mm->context), vaddr);
......@@ -63,11 +60,6 @@ static inline void global_flush_tlb_page(struct mm_struct *mm, unsigned long vad
void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end);
void smp_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr);
#define flush_tlb_kernel_range(start, end) \
do { flush_tsb_kernel_range(start,end); \
smp_flush_tlb_kernel_range(start, end); \
} while (0)
#define global_flush_tlb_page(mm, vaddr) \
smp_flush_tlb_page(mm, vaddr)
......
......@@ -1336,7 +1336,7 @@ int ldc_connect(struct ldc_channel *lp)
if (!(lp->flags & LDC_FLAG_ALLOCED_QUEUES) ||
!(lp->flags & LDC_FLAG_REGISTERED_QUEUES) ||
lp->hs_state != LDC_HS_OPEN)
err = -EINVAL;
err = ((lp->hs_state > LDC_HS_OPEN) ? 0 : -EINVAL);
else
err = start_handshake(lp);
......
......@@ -906,29 +906,85 @@ void mdesc_fill_in_cpu_data(cpumask_t *mask)
smp_fill_in_sib_core_maps();
}
static ssize_t mdesc_read(struct file *file, char __user *buf,
size_t len, loff_t *offp)
/* mdesc_open() - Grab a reference to mdesc_handle when /dev/mdesc is
* opened. Hold this reference until /dev/mdesc is closed to ensure
* mdesc data structure is not released underneath us. Store the
* pointer to mdesc structure in private_data for read and seek to use
*/
static int mdesc_open(struct inode *inode, struct file *file)
{
struct mdesc_handle *hp = mdesc_grab();
int err;
if (!hp)
return -ENODEV;
err = hp->handle_size;
if (len < hp->handle_size)
err = -EMSGSIZE;
else if (copy_to_user(buf, &hp->mdesc, hp->handle_size))
err = -EFAULT;
mdesc_release(hp);
file->private_data = hp;
return 0;
}
static ssize_t mdesc_read(struct file *file, char __user *buf,
size_t len, loff_t *offp)
{
struct mdesc_handle *hp = file->private_data;
unsigned char *mdesc;
int bytes_left, count = len;
if (*offp >= hp->handle_size)
return 0;
bytes_left = hp->handle_size - *offp;
if (count > bytes_left)
count = bytes_left;
mdesc = (unsigned char *)&hp->mdesc;
mdesc += *offp;
if (!copy_to_user(buf, mdesc, count)) {
*offp += count;
return count;
} else {
return -EFAULT;
}
}
return err;
static loff_t mdesc_llseek(struct file *file, loff_t offset, int whence)
{
struct mdesc_handle *hp;
switch (whence) {
case SEEK_CUR:
offset += file->f_pos;
break;
case SEEK_SET:
break;
default:
return -EINVAL;
}
hp = file->private_data;
if (offset > hp->handle_size)
return -EINVAL;
else
file->f_pos = offset;
return offset;
}
/* mdesc_close() - /dev/mdesc is being closed, release the reference to
* mdesc structure.
*/
static int mdesc_close(struct inode *inode, struct file *file)
{
mdesc_release(file->private_data);
return 0;
}
static const struct file_operations mdesc_fops = {
.read = mdesc_read,
.owner = THIS_MODULE,
.llseek = noop_llseek,
.open = mdesc_open,
.read = mdesc_read,
.llseek = mdesc_llseek,
.release = mdesc_close,
.owner = THIS_MODULE,
};
static struct miscdevice mdesc_misc = {
......
......@@ -166,7 +166,7 @@ unsigned long safe_compute_effective_address(struct pt_regs *regs,
/* This is just to make gcc think panic does return... */
static void unaligned_panic(char *str)
{
panic(str);
panic("%s", str);
}
/* una_asm.S */
......
......@@ -15,7 +15,7 @@ void outsb(unsigned long __addr, const void *src, unsigned long count)
const u8 *p = src;
while (count--)
outb(*p++, addr);
__raw_writeb(*p++, addr);
}
EXPORT_SYMBOL(outsb);
......@@ -93,21 +93,21 @@ void insb(unsigned long __addr, void *dst, unsigned long count)
u8 *pb = dst;
while ((((unsigned long)pb) & 0x3) && count--)
*pb++ = inb(addr);
*pb++ = __raw_readb(addr);
pi = (u32 *)pb;
while (count >= 4) {
u32 w;
w = (inb(addr) << 24);
w |= (inb(addr) << 16);
w |= (inb(addr) << 8);
w |= (inb(addr) << 0);
w = (__raw_readb(addr) << 24);
w |= (__raw_readb(addr) << 16);
w |= (__raw_readb(addr) << 8);
w |= (__raw_readb(addr) << 0);
*pi++ = w;
count -= 4;
}
pb = (u8 *)pi;
while (count--)
*pb++ = inb(addr);
*pb++ = __raw_readb(addr);
}
}
EXPORT_SYMBOL(insb);
......@@ -121,21 +121,21 @@ void insw(unsigned long __addr, void *dst, unsigned long count)
u32 *pi;
if (((unsigned long)ps) & 0x2) {
*ps++ = le16_to_cpu(inw(addr));
*ps++ = __raw_readw(addr);
count--;
}
pi = (u32 *)ps;
while (count >= 2) {
u32 w;
w = (le16_to_cpu(inw(addr)) << 16);
w |= (le16_to_cpu(inw(addr)) << 0);
w = __raw_readw(addr) << 16;
w |= __raw_readw(addr) << 0;
*pi++ = w;
count -= 2;
}
ps = (u16 *)pi;
if (count)
*ps = le16_to_cpu(inw(addr));
*ps = __raw_readw(addr);
}
}
EXPORT_SYMBOL(insw);
......@@ -148,7 +148,7 @@ void insl(unsigned long __addr, void *dst, unsigned long count)
if ((((unsigned long)dst) & 0x3) == 0) {
u32 *pi = dst;
while (count--)
*pi++ = le32_to_cpu(inl(addr));
*pi++ = __raw_readl(addr);
} else {
u32 l = 0, l2, *pi;
u16 *ps;
......@@ -158,11 +158,11 @@ void insl(unsigned long __addr, void *dst, unsigned long count)
case 0x2:
ps = dst;
count -= 1;
l = le32_to_cpu(inl(addr));
l = __raw_readl(addr);
*ps++ = l;
pi = (u32 *)ps;
while (count--) {
l2 = le32_to_cpu(inl(addr));
l2 = __raw_readl(addr);
*pi++ = (l << 16) | (l2 >> 16);
l = l2;
}
......@@ -173,13 +173,13 @@ void insl(unsigned long __addr, void *dst, unsigned long count)
case 0x1:
pb = dst;
count -= 1;
l = le32_to_cpu(inl(addr));
l = __raw_readl(addr);
*pb++ = l >> 24;
ps = (u16 *)pb;
*ps++ = ((l >> 8) & 0xffff);
pi = (u32 *)ps;
while (count--) {
l2 = le32_to_cpu(inl(addr));
l2 = __raw_readl(addr);
*pi++ = (l << 24) | (l2 >> 8);
l = l2;
}
......@@ -190,11 +190,11 @@ void insl(unsigned long __addr, void *dst, unsigned long count)
case 0x3:
pb = (u8 *)dst;
count -= 1;
l = le32_to_cpu(inl(addr));
l = __raw_readl(addr);
*pb++ = l >> 24;
pi = (u32 *)pb;
while (count--) {
l2 = le32_to_cpu(inl(addr));
l2 = __raw_readl(addr);
*pi++ = (l << 8) | (l2 >> 24);
l = l2;
}
......
......@@ -499,7 +499,7 @@ static int do_one_mathemu(u32 insn, unsigned long *pfsr, unsigned long *fregs)
case 0: fsr = *pfsr;
if (IR == -1) IR = 2;
/* fcc is always fcc0 */
fsr &= ~0xc00; fsr |= (IR << 10); break;
fsr &= ~0xc00; fsr |= (IR << 10);
*pfsr = fsr;
break;
case 1: rd->s = IR; break;
......
......@@ -22,6 +22,7 @@
#include <linux/kprobes.h>
#include <linux/cache.h>
#include <linux/sort.h>
#include <linux/ioport.h>
#include <linux/percpu.h>
#include <linux/memblock.h>
#include <linux/mmzone.h>
......@@ -351,6 +352,10 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *
mm = vma->vm_mm;
/* Don't insert a non-valid PTE into the TSB, we'll deadlock. */
if (!pte_accessible(mm, pte))
return;
spin_lock_irqsave(&mm->context.lock, flags);
#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
......@@ -2619,6 +2624,10 @@ void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
pte = pmd_val(entry);
/* Don't insert a non-valid PMD into the TSB, we'll deadlock. */
if (!(pte & _PAGE_VALID))
return;
/* We are fabricating 8MB pages using 4MB real hw pages. */
pte |= (addr & (1UL << REAL_HPAGE_SHIFT));
......@@ -2699,3 +2708,90 @@ void hugetlb_setup(struct pt_regs *regs)
}
}
#endif
static struct resource code_resource = {
.name = "Kernel code",
.flags = IORESOURCE_BUSY | IORESOURCE_MEM
};
static struct resource data_resource = {
.name = "Kernel data",
.flags = IORESOURCE_BUSY | IORESOURCE_MEM
};
static struct resource bss_resource = {
.name = "Kernel bss",
.flags = IORESOURCE_BUSY | IORESOURCE_MEM
};
static inline resource_size_t compute_kern_paddr(void *addr)
{
return (resource_size_t) (addr - KERNBASE + kern_base);
}
static void __init kernel_lds_init(void)
{
code_resource.start = compute_kern_paddr(_text);
code_resource.end = compute_kern_paddr(_etext - 1);
data_resource.start = compute_kern_paddr(_etext);
data_resource.end = compute_kern_paddr(_edata - 1);
bss_resource.start = compute_kern_paddr(__bss_start);
bss_resource.end = compute_kern_paddr(_end - 1);
}
static int __init report_memory(void)
{
int i;
struct resource *res;
kernel_lds_init();
for (i = 0; i < pavail_ents; i++) {
res = kzalloc(sizeof(struct resource), GFP_KERNEL);
if (!res) {
pr_warn("Failed to allocate source.\n");
break;
}
res->name = "System RAM";
res->start = pavail[i].phys_addr;
res->end = pavail[i].phys_addr + pavail[i].reg_size - 1;
res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
if (insert_resource(&iomem_resource, res) < 0) {
pr_warn("Resource insertion failed.\n");
break;
}
insert_resource(res, &code_resource);
insert_resource(res, &data_resource);
insert_resource(res, &bss_resource);
}
return 0;
}
device_initcall(report_memory);
#ifdef CONFIG_SMP
#define do_flush_tlb_kernel_range smp_flush_tlb_kernel_range
#else
#define do_flush_tlb_kernel_range __flush_tlb_kernel_range
#endif
void flush_tlb_kernel_range(unsigned long start, unsigned long end)
{
if (start < HI_OBP_ADDRESS && end > LOW_OBP_ADDRESS) {
if (start < LOW_OBP_ADDRESS) {
flush_tsb_kernel_range(start, LOW_OBP_ADDRESS);
do_flush_tlb_kernel_range(start, LOW_OBP_ADDRESS);
}
if (end > HI_OBP_ADDRESS) {
flush_tsb_kernel_range(end, HI_OBP_ADDRESS);
do_flush_tlb_kernel_range(end, HI_OBP_ADDRESS);
}
} else {
flush_tsb_kernel_range(start, end);
do_flush_tlb_kernel_range(start, end);
}
}
......@@ -86,13 +86,13 @@ static int bbc_spkr_event(struct input_dev *dev, unsigned int type, unsigned int
spin_lock_irqsave(&state->lock, flags);
if (count) {
outb(0x01, info->regs + 0);
outb(0x00, info->regs + 2);
outb((count >> 16) & 0xff, info->regs + 3);
outb((count >> 8) & 0xff, info->regs + 4);
outb(0x00, info->regs + 5);
sbus_writeb(0x01, info->regs + 0);
sbus_writeb(0x00, info->regs + 2);
sbus_writeb((count >> 16) & 0xff, info->regs + 3);
sbus_writeb((count >> 8) & 0xff, info->regs + 4);
sbus_writeb(0x00, info->regs + 5);
} else {
outb(0x00, info->regs + 0);
sbus_writeb(0x00, info->regs + 0);
}
spin_unlock_irqrestore(&state->lock, flags);
......@@ -123,15 +123,15 @@ static int grover_spkr_event(struct input_dev *dev, unsigned int type, unsigned
if (count) {
/* enable counter 2 */
outb(inb(info->enable_reg) | 3, info->enable_reg);
sbus_writeb(sbus_readb(info->enable_reg) | 3, info->enable_reg);
/* set command for counter 2, 2 byte write */
outb(0xB6, info->freq_regs + 1);
sbus_writeb(0xB6, info->freq_regs + 1);
/* select desired HZ */
outb(count & 0xff, info->freq_regs + 0);
outb((count >> 8) & 0xff, info->freq_regs + 0);
sbus_writeb(count & 0xff, info->freq_regs + 0);
sbus_writeb((count >> 8) & 0xff, info->freq_regs + 0);
} else {
/* disable counter 2 */
outb(inb_p(info->enable_reg) & 0xFC, info->enable_reg);
sbus_writeb(sbus_readb(info->enable_reg) & 0xFC, info->enable_reg);
}
spin_unlock_irqrestore(&state->lock, flags);
......
......@@ -452,6 +452,9 @@ static void attach_one_temp(struct bbc_i2c_bus *bp, struct platform_device *op,
if (!tp)
return;
INIT_LIST_HEAD(&tp->bp_list);
INIT_LIST_HEAD(&tp->glob_list);
tp->client = bbc_i2c_attach(bp, op);
if (!tp->client) {
kfree(tp);
......@@ -497,6 +500,9 @@ static void attach_one_fan(struct bbc_i2c_bus *bp, struct platform_device *op,
if (!fp)
return;
INIT_LIST_HEAD(&fp->bp_list);
INIT_LIST_HEAD(&fp->glob_list);
fp->client = bbc_i2c_attach(bp, op);
if (!fp->client) {
kfree(fp);
......
......@@ -300,13 +300,18 @@ static struct bbc_i2c_bus * attach_one_i2c(struct platform_device *op, int index
if (!bp)
return NULL;
INIT_LIST_HEAD(&bp->temps);
INIT_LIST_HEAD(&bp->fans);
bp->i2c_control_regs = of_ioremap(&op->resource[0], 0, 0x2, "bbc_i2c_regs");
if (!bp->i2c_control_regs)
goto fail;
bp->i2c_bussel_reg = of_ioremap(&op->resource[1], 0, 0x1, "bbc_i2c_bussel");
if (!bp->i2c_bussel_reg)
goto fail;
if (op->num_resources == 2) {
bp->i2c_bussel_reg = of_ioremap(&op->resource[1], 0, 0x1, "bbc_i2c_bussel");
if (!bp->i2c_bussel_reg)
goto fail;
}
bp->waiting = 0;
init_waitqueue_head(&bp->wq);
......
......@@ -4,6 +4,7 @@
* Copyright (c) 2000 Eric Brower (ebrower@usa.net)
*/
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
......@@ -143,10 +144,7 @@ static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case D7SIOCTM:
/* toggle device mode-- flip display orientation */
if (regs & D7S_FLIP)
regs &= ~D7S_FLIP;
else
regs |= D7S_FLIP;
regs ^= D7S_FLIP;
writeb(regs, p->regs);
break;
}
......@@ -180,7 +178,7 @@ static int d7s_probe(struct platform_device *op)
if (d7s_device)
goto out;
p = kzalloc(sizeof(*p), GFP_KERNEL);
p = devm_kzalloc(&op->dev, sizeof(*p), GFP_KERNEL);
err = -ENOMEM;
if (!p)
goto out;
......@@ -231,7 +229,6 @@ static int d7s_probe(struct platform_device *op)
of_iounmap(&op->resource[0], p->regs, sizeof(u8));
out_free:
kfree(p);
goto out;
}
......@@ -251,7 +248,6 @@ static int d7s_remove(struct platform_device *op)
misc_deregister(&d7s_miscdev);
of_iounmap(&op->resource[0], p->regs, sizeof(u8));
kfree(p);
return 0;
}
......
......@@ -157,6 +157,15 @@ receive_chars(struct uart_sunsab_port *up,
(up->port.line == up->port.cons->index))
saw_console_brk = 1;
if (count == 0) {
if (unlikely(stat->sreg.isr1 & SAB82532_ISR1_BRK)) {
stat->sreg.isr0 &= ~(SAB82532_ISR0_PERR |
SAB82532_ISR0_FERR);
up->port.icount.brk++;
uart_handle_break(&up->port);
}
}
for (i = 0; i < count; i++) {
unsigned char ch = buf[i], flag;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment