From 24f287e412ae90de8d281543c8b1043b6ed6c019 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 15 Oct 2007 16:41:44 -0700 Subject: [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 --- include/asm-sparc64/backoff.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 include/asm-sparc64/backoff.h (limited to 'include') 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 */ -- cgit v1.2.3 From 6050afbbb01d1f5a867f7839be6460bac801f5bc Mon Sep 17 00:00:00 2001 From: David Miller Date: Wed, 17 Oct 2007 19:38:10 -0700 Subject: [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(-) (limited to 'include') 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); \ -- cgit v1.2.3 From 5c45708352a040f19caceb683c78bc86aad466f6 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Wed, 17 Oct 2007 21:17:42 -0700 Subject: [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(-) (limited to 'include') 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); -- cgit v1.2.3