From 24f287e412ae90de8d281543c8b1043b6ed6c019 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 15 Oct 2007 16:41:44 -0700 Subject: [PATCH 1/6] [SPARC64]: Implement atomic backoff. When the cpu count is high and contention hits an atomic object, the processors can synchronize such that some cpus continually get knocked out and cannot complete the atomic update. So implement an exponential backoff when SMP. Signed-off-by: David S. Miller --- arch/sparc64/lib/atomic.S | 38 +++++++++++++++++++++++++---------- arch/sparc64/lib/bitops.S | 30 ++++++++++++++++++--------- include/asm-sparc64/backoff.h | 28 ++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 20 deletions(-) create mode 100644 include/asm-sparc64/backoff.h diff --git a/arch/sparc64/lib/atomic.S b/arch/sparc64/lib/atomic.S index 9633750167d0..70ac4186f62b 100644 --- a/arch/sparc64/lib/atomic.S +++ b/arch/sparc64/lib/atomic.S @@ -1,10 +1,10 @@ -/* $Id: atomic.S,v 1.4 2001/11/18 00:12:56 davem Exp $ - * atomic.S: These things are too big to do inline. +/* atomic.S: These things are too big to do inline. * - * Copyright (C) 1999 David S. Miller (davem@redhat.com) + * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net) */ #include +#include .text @@ -16,27 +16,31 @@ .globl atomic_add .type atomic_add,#function atomic_add: /* %o0 = increment, %o1 = atomic_ptr */ + BACKOFF_SETUP(%o2) 1: lduw [%o1], %g1 add %g1, %o0, %g7 cas [%o1], %g1, %g7 cmp %g1, %g7 - bne,pn %icc, 1b + bne,pn %icc, 2f nop retl nop +2: BACKOFF_SPIN(%o2, %o3, 1b) .size atomic_add, .-atomic_add .globl atomic_sub .type atomic_sub,#function atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */ + BACKOFF_SETUP(%o2) 1: lduw [%o1], %g1 sub %g1, %o0, %g7 cas [%o1], %g1, %g7 cmp %g1, %g7 - bne,pn %icc, 1b + bne,pn %icc, 2f nop retl nop +2: BACKOFF_SPIN(%o2, %o3, 1b) .size atomic_sub, .-atomic_sub /* On SMP we need to use memory barriers to ensure @@ -60,89 +64,101 @@ atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */ .globl atomic_add_ret .type atomic_add_ret,#function atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ + BACKOFF_SETUP(%o2) ATOMIC_PRE_BARRIER 1: lduw [%o1], %g1 add %g1, %o0, %g7 cas [%o1], %g1, %g7 cmp %g1, %g7 - bne,pn %icc, 1b + bne,pn %icc, 2f add %g7, %o0, %g7 sra %g7, 0, %o0 ATOMIC_POST_BARRIER retl nop +2: BACKOFF_SPIN(%o2, %o3, 1b) .size atomic_add_ret, .-atomic_add_ret .globl atomic_sub_ret .type atomic_sub_ret,#function atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */ + BACKOFF_SETUP(%o2) ATOMIC_PRE_BARRIER 1: lduw [%o1], %g1 sub %g1, %o0, %g7 cas [%o1], %g1, %g7 cmp %g1, %g7 - bne,pn %icc, 1b + bne,pn %icc, 2f sub %g7, %o0, %g7 sra %g7, 0, %o0 ATOMIC_POST_BARRIER retl nop +2: BACKOFF_SPIN(%o2, %o3, 1b) .size atomic_sub_ret, .-atomic_sub_ret .globl atomic64_add .type atomic64_add,#function atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */ + BACKOFF_SETUP(%o2) 1: ldx [%o1], %g1 add %g1, %o0, %g7 casx [%o1], %g1, %g7 cmp %g1, %g7 - bne,pn %xcc, 1b + bne,pn %xcc, 2f nop retl nop +2: BACKOFF_SPIN(%o2, %o3, 1b) .size atomic64_add, .-atomic64_add .globl atomic64_sub .type atomic64_sub,#function atomic64_sub: /* %o0 = decrement, %o1 = atomic_ptr */ + BACKOFF_SETUP(%o2) 1: ldx [%o1], %g1 sub %g1, %o0, %g7 casx [%o1], %g1, %g7 cmp %g1, %g7 - bne,pn %xcc, 1b + bne,pn %xcc, 2f nop retl nop +2: BACKOFF_SPIN(%o2, %o3, 1b) .size atomic64_sub, .-atomic64_sub .globl atomic64_add_ret .type atomic64_add_ret,#function atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ + BACKOFF_SETUP(%o2) ATOMIC_PRE_BARRIER 1: ldx [%o1], %g1 add %g1, %o0, %g7 casx [%o1], %g1, %g7 cmp %g1, %g7 - bne,pn %xcc, 1b + bne,pn %xcc, 2f add %g7, %o0, %g7 mov %g7, %o0 ATOMIC_POST_BARRIER retl nop +2: BACKOFF_SPIN(%o2, %o3, 1b) .size atomic64_add_ret, .-atomic64_add_ret .globl atomic64_sub_ret .type atomic64_sub_ret,#function atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */ + BACKOFF_SETUP(%o2) ATOMIC_PRE_BARRIER 1: ldx [%o1], %g1 sub %g1, %o0, %g7 casx [%o1], %g1, %g7 cmp %g1, %g7 - bne,pn %xcc, 1b + bne,pn %xcc, 2f sub %g7, %o0, %g7 mov %g7, %o0 ATOMIC_POST_BARRIER retl nop +2: BACKOFF_SPIN(%o2, %o3, 1b) .size atomic64_sub_ret, .-atomic64_sub_ret diff --git a/arch/sparc64/lib/bitops.S b/arch/sparc64/lib/bitops.S index 892431a82131..6b015a6eefb5 100644 --- a/arch/sparc64/lib/bitops.S +++ b/arch/sparc64/lib/bitops.S @@ -1,10 +1,10 @@ -/* $Id: bitops.S,v 1.3 2001/11/18 00:12:56 davem Exp $ - * bitops.S: Sparc64 atomic bit operations. +/* bitops.S: Sparc64 atomic bit operations. * - * Copyright (C) 2000 David S. Miller (davem@redhat.com) + * Copyright (C) 2000, 2007 David S. Miller (davem@davemloft.net) */ #include +#include .text @@ -29,6 +29,7 @@ .globl test_and_set_bit .type test_and_set_bit,#function test_and_set_bit: /* %o0=nr, %o1=addr */ + BACKOFF_SETUP(%o3) BITOP_PRE_BARRIER srlx %o0, 6, %g1 mov 1, %o2 @@ -40,18 +41,20 @@ test_and_set_bit: /* %o0=nr, %o1=addr */ or %g7, %o2, %g1 casx [%o1], %g7, %g1 cmp %g7, %g1 - bne,pn %xcc, 1b + bne,pn %xcc, 2f and %g7, %o2, %g2 clr %o0 movrne %g2, 1, %o0 BITOP_POST_BARRIER retl nop +2: BACKOFF_SPIN(%o3, %o4, 1b) .size test_and_set_bit, .-test_and_set_bit .globl test_and_clear_bit .type test_and_clear_bit,#function test_and_clear_bit: /* %o0=nr, %o1=addr */ + BACKOFF_SETUP(%o3) BITOP_PRE_BARRIER srlx %o0, 6, %g1 mov 1, %o2 @@ -63,18 +66,20 @@ test_and_clear_bit: /* %o0=nr, %o1=addr */ andn %g7, %o2, %g1 casx [%o1], %g7, %g1 cmp %g7, %g1 - bne,pn %xcc, 1b + bne,pn %xcc, 2f and %g7, %o2, %g2 clr %o0 movrne %g2, 1, %o0 BITOP_POST_BARRIER retl nop +2: BACKOFF_SPIN(%o3, %o4, 1b) .size test_and_clear_bit, .-test_and_clear_bit .globl test_and_change_bit .type test_and_change_bit,#function test_and_change_bit: /* %o0=nr, %o1=addr */ + BACKOFF_SETUP(%o3) BITOP_PRE_BARRIER srlx %o0, 6, %g1 mov 1, %o2 @@ -86,18 +91,20 @@ test_and_change_bit: /* %o0=nr, %o1=addr */ xor %g7, %o2, %g1 casx [%o1], %g7, %g1 cmp %g7, %g1 - bne,pn %xcc, 1b + bne,pn %xcc, 2f and %g7, %o2, %g2 clr %o0 movrne %g2, 1, %o0 BITOP_POST_BARRIER retl nop +2: BACKOFF_SPIN(%o3, %o4, 1b) .size test_and_change_bit, .-test_and_change_bit .globl set_bit .type set_bit,#function set_bit: /* %o0=nr, %o1=addr */ + BACKOFF_SETUP(%o3) srlx %o0, 6, %g1 mov 1, %o2 sllx %g1, 3, %g3 @@ -108,15 +115,17 @@ set_bit: /* %o0=nr, %o1=addr */ or %g7, %o2, %g1 casx [%o1], %g7, %g1 cmp %g7, %g1 - bne,pn %xcc, 1b + bne,pn %xcc, 2f nop retl nop +2: BACKOFF_SPIN(%o3, %o4, 1b) .size set_bit, .-set_bit .globl clear_bit .type clear_bit,#function clear_bit: /* %o0=nr, %o1=addr */ + BACKOFF_SETUP(%o3) srlx %o0, 6, %g1 mov 1, %o2 sllx %g1, 3, %g3 @@ -127,15 +136,17 @@ clear_bit: /* %o0=nr, %o1=addr */ andn %g7, %o2, %g1 casx [%o1], %g7, %g1 cmp %g7, %g1 - bne,pn %xcc, 1b + bne,pn %xcc, 2f nop retl nop +2: BACKOFF_SPIN(%o3, %o4, 1b) .size clear_bit, .-clear_bit .globl change_bit .type change_bit,#function change_bit: /* %o0=nr, %o1=addr */ + BACKOFF_SETUP(%o3) srlx %o0, 6, %g1 mov 1, %o2 sllx %g1, 3, %g3 @@ -146,8 +157,9 @@ change_bit: /* %o0=nr, %o1=addr */ xor %g7, %o2, %g1 casx [%o1], %g7, %g1 cmp %g7, %g1 - bne,pn %xcc, 1b + bne,pn %xcc, 2f nop retl nop +2: BACKOFF_SPIN(%o3, %o4, 1b) .size change_bit, .-change_bit diff --git a/include/asm-sparc64/backoff.h b/include/asm-sparc64/backoff.h new file mode 100644 index 000000000000..0e32f8b62fd2 --- /dev/null +++ b/include/asm-sparc64/backoff.h @@ -0,0 +1,28 @@ +#ifndef _SPARC64_BACKOFF_H +#define _SPARC64_BACKOFF_H + +#define BACKOFF_LIMIT (4 * 1024) + +#ifdef CONFIG_SMP + +#define BACKOFF_SETUP(reg) \ + mov 1, reg + +#define BACKOFF_SPIN(reg, tmp, label) \ + mov reg, tmp; \ +88: brnz,pt tmp, 88b; \ + sub tmp, 1, tmp; \ + cmp reg, BACKOFF_LIMIT; \ + bg,pn %xcc, label; \ + nop; \ + ba,pt %xcc, label; \ + sllx reg, 1, reg; + +#else + +#define BACKOFF_SETUP(reg) +#define BACKOFF_SPIN(reg, tmp, label) + +#endif + +#endif /* _SPARC64_BACKOFF_H */ From 719023fb90009855c4515a16349fc6d0a2f93a74 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 15 Oct 2007 16:43:19 -0700 Subject: [PATCH 2/6] [SPARC64]: Fix boot failures due to bootmem. Do not use *alloc_bootmem_low*(), because ARCH_LOW_ADDRESS_LIMIT is 4GB and this results in boot failures if all of the physical memory in the machine is above 4GB. Signed-off-by: David S. Miller --- arch/sparc64/kernel/irq.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index f3922e5a89f6..2c3bea228159 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -877,7 +877,7 @@ void __cpuinit sun4v_register_mondo_queues(int this_cpu) static void __init alloc_one_mondo(unsigned long *pa_ptr, unsigned long qmask) { unsigned long size = PAGE_ALIGN(qmask + 1); - void *p = __alloc_bootmem_low(size, size, 0); + void *p = __alloc_bootmem(size, size, 0); if (!p) { prom_printf("SUN4V: Error, cannot allocate mondo queue.\n"); prom_halt(); @@ -889,7 +889,7 @@ static void __init alloc_one_mondo(unsigned long *pa_ptr, unsigned long qmask) static void __init alloc_one_kbuf(unsigned long *pa_ptr, unsigned long qmask) { unsigned long size = PAGE_ALIGN(qmask + 1); - void *p = __alloc_bootmem_low(size, size, 0); + void *p = __alloc_bootmem(size, size, 0); if (!p) { prom_printf("SUN4V: Error, cannot allocate kbuf page.\n"); @@ -906,7 +906,7 @@ static void __init init_cpu_send_mondo_info(struct trap_per_cpu *tb) BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > (PAGE_SIZE - 64)); - page = alloc_bootmem_low_pages(PAGE_SIZE); + page = alloc_bootmem_pages(PAGE_SIZE); if (!page) { prom_printf("SUN4V: Error, cannot allocate cpu mondo page.\n"); prom_halt(); @@ -953,7 +953,7 @@ void __init init_IRQ(void) kill_prom_timer(); size = sizeof(struct ino_bucket) * NUM_IVECS; - ivector_table = alloc_bootmem_low(size); + ivector_table = alloc_bootmem(size); if (!ivector_table) { prom_printf("Fatal error, cannot allocate ivector_table\n"); prom_halt(); From 4209ab098c61b1a9684bb4d3fc287352fc2438c3 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 15 Oct 2007 20:45:32 -0700 Subject: [PATCH 3/6] [SPARC64]: Check of_get_property() return in pci_determine_mem_io_space(). If the PCI controller lacks the 'ranges' property nothing is going to work. Noticed by Al Viro. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_common.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index c76bfbb7da08..923e0bcc3bfd 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c @@ -396,6 +396,13 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm) saw_mem = saw_io = 0; pbm_ranges = of_get_property(pbm->prom_node, "ranges", &i); + if (!pbm_ranges) { + prom_printf("PCI: Fatal error, missing PBM ranges property " + " for %s\n", + pbm->name); + prom_halt(); + } + num_pbm_ranges = i / sizeof(*pbm_ranges); for (i = 0; i < num_pbm_ranges; i++) { From 6050afbbb01d1f5a867f7839be6460bac801f5bc Mon Sep 17 00:00:00 2001 From: David Miller Date: Wed, 17 Oct 2007 19:38:10 -0700 Subject: [PATCH 4/6] [SPARC]: Support for new termios. [akpm@linux-foundation.org: coding-style tweaks] Signed-off-by: David Miller Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- include/asm-sparc/ioctls.h | 4 +++ include/asm-sparc/termbits.h | 15 +++++++++++ include/asm-sparc/termios.h | 48 +++++++++++++++++++++++++++++++--- include/asm-sparc64/ioctls.h | 4 +++ include/asm-sparc64/termbits.h | 17 ++++++++++-- include/asm-sparc64/termios.h | 42 +++++++++++++++++++++++++++++ 6 files changed, 125 insertions(+), 5 deletions(-) diff --git a/include/asm-sparc/ioctls.h b/include/asm-sparc/ioctls.h index bdf77b0dfd8e..058c2064f706 100644 --- a/include/asm-sparc/ioctls.h +++ b/include/asm-sparc/ioctls.h @@ -15,6 +15,10 @@ #define TCSETS _IOW('T', 9, struct termios) #define TCSETSW _IOW('T', 10, struct termios) #define TCSETSF _IOW('T', 11, struct termios) +#define TCGETS2 _IOR('T', 12, struct termios2) +#define TCSETS2 _IOW('T', 13, struct termios2) +#define TCSETSW2 _IOW('T', 14, struct termios2) +#define TCSETSF2 _IOW('T', 15, struct termios2) /* Note that all the ioctls that are not available in Linux have a * double underscore on the front to: a) avoid some programs to diff --git a/include/asm-sparc/termbits.h b/include/asm-sparc/termbits.h index 5eb00a105d7c..90cf2210118b 100644 --- a/include/asm-sparc/termbits.h +++ b/include/asm-sparc/termbits.h @@ -31,6 +31,18 @@ struct termios { #endif }; +struct termios2 { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + cc_t _x_cc[2]; /* padding to match ktermios */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + struct ktermios { tcflag_t c_iflag; /* input mode flags */ tcflag_t c_oflag; /* output mode flags */ @@ -160,6 +172,7 @@ struct ktermios { #define CLOCAL 0x00000800 #define CBAUDEX 0x00001000 /* We'll never see these speeds with the Zilogs, but for completeness... */ +#define BOTHER 0x00001000 #define B57600 0x00001001 #define B115200 0x00001002 #define B230400 0x00001003 @@ -189,6 +202,8 @@ struct ktermios { #define CMSPAR 0x40000000 /* mark or space (stick) parity */ #define CRTSCTS 0x80000000 /* flow control */ +#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */ + /* c_lflag bits */ #define ISIG 0x00000001 #define ICANON 0x00000002 diff --git a/include/asm-sparc/termios.h b/include/asm-sparc/termios.h index d767f206ab33..4333232abb9f 100644 --- a/include/asm-sparc/termios.h +++ b/include/asm-sparc/termios.h @@ -107,6 +107,48 @@ struct winsize { }) #define user_termios_to_kernel_termios(k, u) \ +({ \ + int err; \ + err = get_user((k)->c_iflag, &(u)->c_iflag); \ + err |= get_user((k)->c_oflag, &(u)->c_oflag); \ + err |= get_user((k)->c_cflag, &(u)->c_cflag); \ + err |= get_user((k)->c_lflag, &(u)->c_lflag); \ + err |= get_user((k)->c_line, &(u)->c_line); \ + err |= copy_from_user((k)->c_cc, (u)->c_cc, NCCS); \ + if ((k)->c_lflag & ICANON) { \ + err |= get_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \ + err |= get_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \ + } else { \ + err |= get_user((k)->c_cc[VMIN], &(u)->c_cc[_VMIN]); \ + err |= get_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \ + } \ + err |= get_user((k)->c_ispeed, &(u)->c_ispeed); \ + err |= get_user((k)->c_ospeed, &(u)->c_ospeed); \ + err; \ +}) + +#define kernel_termios_to_user_termios(u, k) \ +({ \ + int err; \ + err = put_user((k)->c_iflag, &(u)->c_iflag); \ + err |= put_user((k)->c_oflag, &(u)->c_oflag); \ + err |= put_user((k)->c_cflag, &(u)->c_cflag); \ + err |= put_user((k)->c_lflag, &(u)->c_lflag); \ + err |= put_user((k)->c_line, &(u)->c_line); \ + err |= copy_to_user((u)->c_cc, (k)->c_cc, NCCS); \ + if (!((k)->c_lflag & ICANON)) { \ + err |= put_user((k)->c_cc[VMIN], &(u)->c_cc[_VMIN]); \ + err |= put_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \ + } else { \ + err |= put_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \ + err |= put_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \ + } \ + err |= put_user((k)->c_ispeed, &(u)->c_ispeed); \ + err |= put_user((k)->c_ospeed, &(u)->c_ospeed); \ + err; \ +}) + +#define user_termios_to_kernel_termios_1(k, u) \ ({ \ get_user((k)->c_iflag, &(u)->c_iflag); \ get_user((k)->c_oflag, &(u)->c_oflag); \ @@ -114,7 +156,7 @@ struct winsize { get_user((k)->c_lflag, &(u)->c_lflag); \ get_user((k)->c_line, &(u)->c_line); \ copy_from_user((k)->c_cc, (u)->c_cc, NCCS); \ - if((k)->c_lflag & ICANON) { \ + if ((k)->c_lflag & ICANON) { \ get_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \ get_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \ } else { \ @@ -124,7 +166,7 @@ struct winsize { 0; \ }) -#define kernel_termios_to_user_termios(u, k) \ +#define kernel_termios_to_user_termios_1(u, k) \ ({ \ put_user((k)->c_iflag, &(u)->c_iflag); \ put_user((k)->c_oflag, &(u)->c_oflag); \ @@ -132,7 +174,7 @@ struct winsize { put_user((k)->c_lflag, &(u)->c_lflag); \ put_user((k)->c_line, &(u)->c_line); \ copy_to_user((u)->c_cc, (k)->c_cc, NCCS); \ - if(!((k)->c_lflag & ICANON)) { \ + if (!((k)->c_lflag & ICANON)) { \ put_user((k)->c_cc[VMIN], &(u)->c_cc[_VMIN]); \ put_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \ } else { \ diff --git a/include/asm-sparc64/ioctls.h b/include/asm-sparc64/ioctls.h index 2223b6d0e5ed..083c9a0f37de 100644 --- a/include/asm-sparc64/ioctls.h +++ b/include/asm-sparc64/ioctls.h @@ -16,6 +16,10 @@ #define TCSETS _IOW('T', 9, struct termios) #define TCSETSW _IOW('T', 10, struct termios) #define TCSETSF _IOW('T', 11, struct termios) +#define TCGETS2 _IOR('T', 12, struct termios2) +#define TCSETS2 _IOW('T', 13, struct termios2) +#define TCSETSW2 _IOW('T', 14, struct termios2) +#define TCSETSF2 _IOW('T', 15, struct termios2) /* Note that all the ioctls that are not available in Linux have a * double underscore on the front to: a) avoid some programs to diff --git a/include/asm-sparc64/termbits.h b/include/asm-sparc64/termbits.h index 705cd44b4173..ebe31c152f16 100644 --- a/include/asm-sparc64/termbits.h +++ b/include/asm-sparc64/termbits.h @@ -5,8 +5,6 @@ typedef unsigned char cc_t; typedef unsigned int speed_t; - -/* XXX is this right for sparc64? it was an unsigned long... XXX */ typedef unsigned int tcflag_t; #define NCC 8 @@ -33,6 +31,18 @@ struct termios { #endif }; +struct termios2 { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + cc_t _x_cc[2]; /* padding to match ktermios */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + struct ktermios { tcflag_t c_iflag; /* input mode flags */ tcflag_t c_oflag; /* output mode flags */ @@ -161,6 +171,7 @@ struct ktermios { #define HUPCL 0x00000400 #define CLOCAL 0x00000800 #define CBAUDEX 0x00001000 +#define BOTHER 0x00001000 #define B57600 0x00001001 #define B115200 0x00001002 #define B230400 0x00001003 @@ -190,6 +201,8 @@ struct ktermios { #define CMSPAR 0x40000000 /* mark or space (stick) parity */ #define CRTSCTS 0x80000000 /* flow control */ +#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */ + /* c_lflag bits */ #define ISIG 0x00000001 #define ICANON 0x00000002 diff --git a/include/asm-sparc64/termios.h b/include/asm-sparc64/termios.h index f05d390993d5..ef527211f8a8 100644 --- a/include/asm-sparc64/termios.h +++ b/include/asm-sparc64/termios.h @@ -123,10 +123,52 @@ struct winsize { err |= get_user((k)->c_cc[VMIN], &(u)->c_cc[_VMIN]); \ err |= get_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \ } \ + err |= get_user((k)->c_ispeed, &(u)->c_ispeed); \ + err |= get_user((k)->c_ospeed, &(u)->c_ospeed); \ err; \ }) #define kernel_termios_to_user_termios(u, k) \ +({ \ + int err; \ + err = put_user((k)->c_iflag, &(u)->c_iflag); \ + err |= put_user((k)->c_oflag, &(u)->c_oflag); \ + err |= put_user((k)->c_cflag, &(u)->c_cflag); \ + err |= put_user((k)->c_lflag, &(u)->c_lflag); \ + err |= put_user((k)->c_line, &(u)->c_line); \ + err |= copy_to_user((u)->c_cc, (k)->c_cc, NCCS); \ + if(!((k)->c_lflag & ICANON)) { \ + err |= put_user((k)->c_cc[VMIN], &(u)->c_cc[_VMIN]); \ + err |= put_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \ + } else { \ + err |= put_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \ + err |= put_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \ + } \ + err |= put_user((k)->c_ispeed, &(u)->c_ispeed); \ + err |= put_user((k)->c_ospeed, &(u)->c_ospeed); \ + err; \ +}) + +#define user_termios_to_kernel_termios_1(k, u) \ +({ \ + int err; \ + err = get_user((k)->c_iflag, &(u)->c_iflag); \ + err |= get_user((k)->c_oflag, &(u)->c_oflag); \ + err |= get_user((k)->c_cflag, &(u)->c_cflag); \ + err |= get_user((k)->c_lflag, &(u)->c_lflag); \ + err |= get_user((k)->c_line, &(u)->c_line); \ + err |= copy_from_user((k)->c_cc, (u)->c_cc, NCCS); \ + if((k)->c_lflag & ICANON) { \ + err |= get_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \ + err |= get_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \ + } else { \ + err |= get_user((k)->c_cc[VMIN], &(u)->c_cc[_VMIN]); \ + err |= get_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \ + } \ + err; \ +}) + +#define kernel_termios_to_user_termios_1(u, k) \ ({ \ int err; \ err = put_user((k)->c_iflag, &(u)->c_iflag); \ From 7b96dc023a1b487bce59256fde14b8bb28b45aea Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Wed, 17 Oct 2007 19:40:31 -0700 Subject: [PATCH 5/6] [SPARC] Videopix Frame Grabber: Convert device_lock_sem to mutex Videopix Frame Grabber: Convert the semaphore device_lock_sem to the mutex API Signed-off-by: Matthias Kaehlcke Signed-off-by: David S. Miller --- drivers/sbus/char/vfc.h | 2 +- drivers/sbus/char/vfc_dev.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/sbus/char/vfc.h b/drivers/sbus/char/vfc.h index 63941a259b92..f1aa1389ea4a 100644 --- a/drivers/sbus/char/vfc.h +++ b/drivers/sbus/char/vfc.h @@ -126,7 +126,7 @@ struct vfc_dev { volatile struct vfc_regs __iomem *regs; struct vfc_regs *phys_regs; unsigned int control_reg; - struct semaphore device_lock_sem; + struct mutex device_lock_mtx; int instance; int busy; unsigned long which_io; diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c index 9269f7fbd363..e7a1642b2aa4 100644 --- a/drivers/sbus/char/vfc_dev.c +++ b/drivers/sbus/char/vfc_dev.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -54,12 +55,12 @@ static unsigned char saa9051_init_array[VFC_SAA9051_NR] = { void vfc_lock_device(struct vfc_dev *dev) { - down(&dev->device_lock_sem); + mutex_lock(&dev->device_lock_mtx); } void vfc_unlock_device(struct vfc_dev *dev) { - up(&dev->device_lock_sem); + mutex_unlock(&dev->device_lock_mtx); } From 5c45708352a040f19caceb683c78bc86aad466f6 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Wed, 17 Oct 2007 21:17:42 -0700 Subject: [PATCH 6/6] [SPARC/64]: Consolidate of_register_driver Also of_unregister_driver. These will be shortly also used by the PowerPC code. Signed-off-by: Stephen Rothwell Signed-off-by: David S. Miller --- arch/sparc/kernel/of_device.c | 20 -------------------- arch/sparc64/kernel/of_device.c | 20 -------------------- drivers/of/platform.c | 21 +++++++++++++++++++++ include/asm-sparc/of_platform.h | 5 +---- include/asm-sparc64/of_platform.h | 5 +---- include/linux/of_platform.h | 4 ++++ 6 files changed, 27 insertions(+), 48 deletions(-) diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index fb2caef79cec..3ea000d15e3a 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c @@ -585,24 +585,6 @@ static int __init of_debug(char *str) __setup("of_debug=", of_debug); -int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) -{ - /* initialize common driver fields */ - if (!drv->driver.name) - drv->driver.name = drv->name; - if (!drv->driver.owner) - drv->driver.owner = drv->owner; - drv->driver.bus = bus; - - /* register with core */ - return driver_register(&drv->driver); -} - -void of_unregister_driver(struct of_platform_driver *drv) -{ - driver_unregister(&drv->driver); -} - struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id, struct device *parent, @@ -628,6 +610,4 @@ struct of_device* of_platform_device_create(struct device_node *np, return dev; } -EXPORT_SYMBOL(of_register_driver); -EXPORT_SYMBOL(of_unregister_driver); EXPORT_SYMBOL(of_platform_device_create); diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 42d779866fba..fc5c0cc793b8 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -869,26 +869,6 @@ static int __init of_debug(char *str) __setup("of_debug=", of_debug); -int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) -{ - /* initialize common driver fields */ - if (!drv->driver.name) - drv->driver.name = drv->name; - if (!drv->driver.owner) - drv->driver.owner = drv->owner; - drv->driver.bus = bus; - - /* register with core */ - return driver_register(&drv->driver); -} -EXPORT_SYMBOL(of_register_driver); - -void of_unregister_driver(struct of_platform_driver *drv) -{ - driver_unregister(&drv->driver); -} -EXPORT_SYMBOL(of_unregister_driver); - struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id, struct device *parent, diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 864f09fd9f86..b47bb2d7476a 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -12,6 +12,7 @@ * */ #include +#include #include #include #include @@ -94,3 +95,23 @@ int of_bus_type_init(struct bus_type *bus, const char *name) bus->resume = of_platform_device_resume; return bus_register(bus); } + +int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) +{ + /* initialize common driver fields */ + if (!drv->driver.name) + drv->driver.name = drv->name; + if (!drv->driver.owner) + drv->driver.owner = drv->owner; + drv->driver.bus = bus; + + /* register with core */ + return driver_register(&drv->driver); +} +EXPORT_SYMBOL(of_register_driver); + +void of_unregister_driver(struct of_platform_driver *drv) +{ + driver_unregister(&drv->driver); +} +EXPORT_SYMBOL(of_unregister_driver); diff --git a/include/asm-sparc/of_platform.h b/include/asm-sparc/of_platform.h index 64a230064ef2..d638737ff13c 100644 --- a/include/asm-sparc/of_platform.h +++ b/include/asm-sparc/of_platform.h @@ -18,12 +18,9 @@ extern struct bus_type ebus_bus_type; extern struct bus_type sbus_bus_type; -extern struct bus_type of_platform_bus_type; + #define of_bus_type of_platform_bus_type /* for compatibility */ -extern int of_register_driver(struct of_platform_driver *drv, - struct bus_type *bus); -extern void of_unregister_driver(struct of_platform_driver *drv); extern struct of_device *of_platform_device_create(struct device_node *np, const char *bus_id, struct device *parent, diff --git a/include/asm-sparc64/of_platform.h b/include/asm-sparc64/of_platform.h index f7c1f17c7d52..f15cfa723916 100644 --- a/include/asm-sparc64/of_platform.h +++ b/include/asm-sparc64/of_platform.h @@ -19,12 +19,9 @@ extern struct bus_type isa_bus_type; extern struct bus_type ebus_bus_type; extern struct bus_type sbus_bus_type; -extern struct bus_type of_platform_bus_type; + #define of_bus_type of_platform_bus_type /* for compatibility */ -extern int of_register_driver(struct of_platform_driver *drv, - struct bus_type *bus); -extern void of_unregister_driver(struct of_platform_driver *drv); extern struct of_device *of_platform_device_create(struct device_node *np, const char *bus_id, struct device *parent, diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h index 448f70b30a0c..a8efcfeea732 100644 --- a/include/linux/of_platform.h +++ b/include/linux/of_platform.h @@ -48,6 +48,10 @@ struct of_platform_driver #define to_of_platform_driver(drv) \ container_of(drv,struct of_platform_driver, driver) +extern int of_register_driver(struct of_platform_driver *drv, + struct bus_type *bus); +extern void of_unregister_driver(struct of_platform_driver *drv); + #include extern struct of_device *of_find_device_by_node(struct device_node *np);