diff options
98 files changed, 1343 insertions, 743 deletions
diff --git a/Documentation/devices.txt b/Documentation/devices.txt index 8de132a02ba..6c46730c631 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt @@ -94,6 +94,8 @@ Your cooperation is appreciated. 9 = /dev/urandom Faster, less secure random number gen. 10 = /dev/aio Asynchronous I/O notification interface 11 = /dev/kmsg Writes to this come out as printk's + 12 = /dev/oldmem Used by crashdump kernels to access + the memory of the kernel that crashed. 1 block RAM disk 0 = /dev/ram0 First RAM disk diff --git a/Documentation/lockstat.txt b/Documentation/lockstat.txt new file mode 100644 index 00000000000..4ba4664ce5c --- /dev/null +++ b/Documentation/lockstat.txt @@ -0,0 +1,120 @@ + +LOCK STATISTICS + +- WHAT + +As the name suggests, it provides statistics on locks. + +- WHY + +Because things like lock contention can severely impact performance. + +- HOW + +Lockdep already has hooks in the lock functions and maps lock instances to +lock classes. We build on that. The graph below shows the relation between +the lock functions and the various hooks therein. + + __acquire + | + lock _____ + | \ + | __contended + | | + | <wait> + | _______/ + |/ + | + __acquired + | + . + <hold> + . + | + __release + | + unlock + +lock, unlock - the regular lock functions +__* - the hooks +<> - states + +With these hooks we provide the following statistics: + + con-bounces - number of lock contention that involved x-cpu data + contentions - number of lock acquisitions that had to wait + wait time min - shortest (non-0) time we ever had to wait for a lock + max - longest time we ever had to wait for a lock + total - total time we spend waiting on this lock + acq-bounces - number of lock acquisitions that involved x-cpu data + acquisitions - number of times we took the lock + hold time min - shortest (non-0) time we ever held the lock + max - longest time we ever held the lock + total - total time this lock was held + +From these number various other statistics can be derived, such as: + + hold time average = hold time total / acquisitions + +These numbers are gathered per lock class, per read/write state (when +applicable). + +It also tracks 4 contention points per class. A contention point is a call site +that had to wait on lock acquisition. + + - USAGE + +Look at the current lock statistics: + +( line numbers not part of actual output, done for clarity in the explanation + below ) + +# less /proc/lock_stat + +01 lock_stat version 0.2 +02 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +03 class name con-bounces contentions waittime-min waittime-max waittime-total acq-bounces acquisitions holdtime-min holdtime-max holdtime-total +04 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +05 +06 &inode->i_data.tree_lock-W: 15 21657 0.18 1093295.30 11547131054.85 58 10415 0.16 87.51 6387.60 +07 &inode->i_data.tree_lock-R: 0 0 0.00 0.00 0.00 23302 231198 0.25 8.45 98023.38 +08 -------------------------- +09 &inode->i_data.tree_lock 0 [<ffffffff8027c08f>] add_to_page_cache+0x5f/0x190 +10 +11 ............................................................................................................................................................................................... +12 +13 dcache_lock: 1037 1161 0.38 45.32 774.51 6611 243371 0.15 306.48 77387.24 +14 ----------- +15 dcache_lock 180 [<ffffffff802c0d7e>] sys_getcwd+0x11e/0x230 +16 dcache_lock 165 [<ffffffff802c002a>] d_alloc+0x15a/0x210 +17 dcache_lock 33 [<ffffffff8035818d>] _atomic_dec_and_lock+0x4d/0x70 +18 dcache_lock 1 [<ffffffff802beef8>] shrink_dcache_parent+0x18/0x130 + +This excerpt shows the first two lock class statistics. Line 01 shows the +output version - each time the format changes this will be updated. Line 02-04 +show the header with column descriptions. Lines 05-10 and 13-18 show the actual +statistics. These statistics come in two parts; the actual stats separated by a +short separator (line 08, 14) from the contention points. + +The first lock (05-10) is a read/write lock, and shows two lines above the +short separator. The contention points don't match the column descriptors, +they have two: contentions and [<IP>] symbol. + + +View the top contending locks: + +# grep : /proc/lock_stat | head + &inode->i_data.tree_lock-W: 15 21657 0.18 1093295.30 11547131054.85 58 10415 0.16 87.51 6387.60 + &inode->i_data.tree_lock-R: 0 0 0.00 0.00 0.00 23302 231198 0.25 8.45 98023.38 + dcache_lock: 1037 1161 0.38 45.32 774.51 6611 243371 0.15 306.48 77387.24 + &inode->i_mutex: 161 286 18446744073709 62882.54 1244614.55 3653 20598 18446744073709 62318.60 1693822.74 + &zone->lru_lock: 94 94 0.53 7.33 92.10 4366 32690 0.29 59.81 16350.06 + &inode->i_data.i_mmap_lock: 79 79 0.40 3.77 53.03 11779 87755 0.28 116.93 29898.44 + &q->__queue_lock: 48 50 0.52 31.62 86.31 774 13131 0.17 113.08 12277.52 + &rq->rq_lock_key: 43 47 0.74 68.50 170.63 3706 33929 0.22 107.99 17460.62 + &rq->rq_lock_key#2: 39 46 0.75 6.68 49.03 2979 32292 0.17 125.17 17137.63 + tasklist_lock-W: 15 15 1.45 10.87 32.70 1201 7390 0.58 62.55 13648.47 + +Clear the statistics: + +# echo 0 > /proc/lock_stat diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt index ef19142896c..10c8f6922ef 100644 --- a/Documentation/sysrq.txt +++ b/Documentation/sysrq.txt @@ -43,7 +43,7 @@ On x86 - You press the key combo 'ALT-SysRq-<command key>'. Note - Some keyboards may not have a key labeled 'SysRq'. The 'SysRq' key is also known as the 'Print Screen' key. Also some keyboards cannot handle so many keys being pressed at the same time, so you might - have better luck with "press Alt", "press SysRq", "release Alt", + have better luck with "press Alt", "press SysRq", "release SysRq", "press <command key>", release everything. On SPARC - You press 'ALT-STOP-<command key>', I believe. @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 23 -EXTRAVERSION =-rc8 +EXTRAVERSION = NAME = Arr Matey! A Hairy Bilge Rat! # *DOCUMENTATION* diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 240c448ec31..a2dd930d11e 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -338,7 +338,7 @@ pbus_assign_bus_resources(struct pci_bus *bus, struct pci_sys_data *root) * pcibios_fixup_bus - Called after each bus is probed, * but before its children are examined. */ -void __devinit pcibios_fixup_bus(struct pci_bus *bus) +void pcibios_fixup_bus(struct pci_bus *bus) { struct pci_sys_data *root = bus->sysdata; struct pci_dev *dev; @@ -419,7 +419,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) /* * Convert from Linux-centric to bus-centric addresses for bridge devices. */ -void __devinit +void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, struct resource *res) { diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c index 0ba7e9060c7..c326983f4a8 100644 --- a/arch/arm/mach-s3c2440/mach-osiris.c +++ b/arch/arm/mach-s3c2440/mach-osiris.c @@ -276,7 +276,21 @@ static unsigned char pm_osiris_ctrl0; static int osiris_pm_suspend(struct sys_device *sd, pm_message_t state) { + unsigned int tmp; + pm_osiris_ctrl0 = __raw_readb(OSIRIS_VA_CTRL0); + tmp = pm_osiris_ctrl0 & ~OSIRIS_CTRL0_NANDSEL; + + /* ensure correct NAND slot is selected on resume */ + if ((pm_osiris_ctrl0 & OSIRIS_CTRL0_BOOT_INT) == 0) + tmp |= 2; + + __raw_writeb(tmp, OSIRIS_VA_CTRL0); + + /* ensure that an nRESET is not generated on resume. */ + s3c2410_gpio_setpin(S3C2410_GPA21, 1); + s3c2410_gpio_cfgpin(S3C2410_GPA21, S3C2410_GPA21_OUT); + return 0; } @@ -285,6 +299,10 @@ static int osiris_pm_resume(struct sys_device *sd) if (pm_osiris_ctrl0 & OSIRIS_CTRL0_FIX8) __raw_writeb(OSIRIS_CTRL1_FIX8, OSIRIS_VA_CTRL1); + __raw_writeb(pm_osiris_ctrl0, OSIRIS_VA_CTRL0); + + s3c2410_gpio_cfgpin(S3C2410_GPA21, S3C2410_GPA21_nRSTOUT); + return 0; } diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index bafcfa52142..5d488ef965c 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -84,6 +84,7 @@ #include <linux/err.h> #include <asm/blackfin.h> #include <asm/gpio.h> +#include <asm/portmux.h> #include <linux/irq.h> #ifdef BF533_FAMILY @@ -115,7 +116,11 @@ static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = { }; #endif -static unsigned short reserved_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; +static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; +static unsigned short reserved_peri_map[gpio_bank(MAX_BLACKFIN_GPIOS + 16)]; +char *str_ident = NULL; + +#define RESOURCE_LABEL_SIZE 16 #ifdef CONFIG_PM static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; @@ -143,22 +148,100 @@ inline int check_gpio(unsigned short gpio) return 0; } +static void set_label(unsigned short ident, const char *label) +{ + + if (label && str_ident) { + strncpy(str_ident + ident * RESOURCE_LABEL_SIZE, label, + RESOURCE_LABEL_SIZE); + str_ident[ident * RESOURCE_LABEL_SIZE + + RESOURCE_LABEL_SIZE - 1] = 0; + } +} + +static char *get_label(unsigned short ident) +{ + if (!str_ident) + return "UNKNOWN"; + + return (str_ident[ident * RESOURCE_LABEL_SIZE] ? + (str_ident + ident * RESOURCE_LABEL_SIZE) : "UNKNOWN"); +} + +static int cmp_label(unsigned short ident, const char *label) +{ + if (label && str_ident) + return strncmp(str_ident + ident * RESOURCE_LABEL_SIZE, + label, strlen(label)); + else + return -EINVAL; +} + #ifdef BF537_FAMILY static void port_setup(unsigned short gpio, unsigned short usage) { - if (usage == GPIO_USAGE) { - if (*port_fer[gpio_bank(gpio)] & gpio_bit(gpio)) - printk(KERN_WARNING "bfin-gpio: Possible Conflict with Peripheral " - "usage and GPIO %d detected!\n", gpio); - *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); - } else - *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); - SSYNC(); + if (!check_gpio(gpio)) { + if (usage == GPIO_USAGE) { + *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); + } else + *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); + SSYNC(); + } } #else # define port_setup(...) do { } while (0) #endif +#ifdef BF537_FAMILY + +#define PMUX_LUT_RES 0 +#define PMUX_LUT_OFFSET 1 +#define PMUX_LUT_ENTRIES 41 +#define PMUX_LUT_SIZE 2 + +static unsigned short port_mux_lut[PMUX_LUT_ENTRIES][PMUX_LUT_SIZE] = { + {P_PPI0_D13, 11}, {P_PPI0_D14, 11}, {P_PPI0_D15, 11}, + {P_SPORT1_TFS, 11}, {P_SPORT1_TSCLK, 11}, {P_SPORT1_DTPRI, 11}, + {P_PPI0_D10, 10}, {P_PPI0_D11, 10}, {P_PPI0_D12, 10}, + {P_SPORT1_RSCLK, 10}, {P_SPORT1_RFS, 10}, {P_SPORT1_DRPRI, 10}, + {P_PPI0_D8, 9}, {P_PPI0_D9, 9}, {P_SPORT1_DRSEC, 9}, + {P_SPORT1_DTSEC, 9}, {P_TMR2, 8}, {P_PPI0_FS3, 8}, {P_TMR3, 7}, + {P_SPI0_SSEL4, 7}, {P_TMR4, 6}, {P_SPI0_SSEL5, 6}, {P_TMR5, 5}, + {P_SPI0_SSEL6, 5}, {P_UART1_RX, 4}, {P_UART1_TX, 4}, {P_TMR6, 4}, + {P_TMR7, 4}, {P_UART0_RX, 3}, {P_UART0_TX, 3}, {P_DMAR0, 3}, + {P_DMAR1, 3}, {P_SPORT0_DTSEC, 1}, {P_SPORT0_DRSEC, 1}, + {P_CAN0_RX, 1}, {P_CAN0_TX, 1}, {P_SPI0_SSEL7, 1}, + {P_SPORT0_TFS, 0}, {P_SPORT0_DTPRI, 0}, {P_SPI0_SSEL2, 0}, + {P_SPI0_SSEL3, 0} +}; + +static void portmux_setup(unsigned short per, unsigned short function) +{ + u16 y, muxreg, offset; + + for (y = 0; y < PMUX_LUT_ENTRIES; y++) { + if (port_mux_lut[y][PMUX_LUT_RES] == per) { + + /* SET PORTMUX REG */ + + offset = port_mux_lut[y][PMUX_LUT_OFFSET]; + muxreg = bfin_read_PORT_MUX(); + + if (offset != 1) { + muxreg &= ~(1 << offset); + } else { + muxreg &= ~(3 << 1); + } + + muxreg |= (function << offset); + bfin_write_PORT_MUX(muxreg); + } + } +} + +#else +# define portmux_setup(...) do { } while (0) +#endif static void default_gpio(unsigned short gpio) { @@ -179,22 +262,15 @@ static void default_gpio(unsigned short gpio) static int __init bfin_gpio_init(void) { - int i; - - printk(KERN_INFO "Blackfin GPIO Controller\n"); - for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) - reserved_map[gpio_bank(i)] = 0; + str_ident = kzalloc(RESOURCE_LABEL_SIZE * 256, GFP_KERNEL); + if (!str_ident) + return -ENOMEM; -#if defined(BF537_FAMILY) && (defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)) -# if defined(CONFIG_BFIN_MAC_RMII) - reserved_map[gpio_bank(PORT_H)] = 0xC373; -# else - reserved_map[gpio_bank(PORT_H)] = 0xFFFF; -# endif -#endif + printk(KERN_INFO "Blackfin GPIO Controller\n"); return 0; + } arch_initcall(bfin_gpio_init); @@ -223,7 +299,7 @@ arch_initcall(bfin_gpio_init); void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ { \ unsigned long flags; \ - BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); \ + BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); \ local_irq_save(flags); \ if (arg) \ gpio_bankb[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ @@ -243,7 +319,7 @@ SET_GPIO(both) #define SET_GPIO_SC(name) \ void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ { \ - BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); \ + BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); \ if (arg) \ gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ else \ @@ -258,7 +334,7 @@ SET_GPIO_SC(maskb) void set_gpio_data(unsigned short gpio, unsigned short arg) { unsigned long flags; - BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); + BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); local_irq_save(flags); if (arg) gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio); @@ -277,7 +353,7 @@ SET_GPIO_SC(data) void set_gpio_toggle(unsigned short gpio) { unsigned long flags; - BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); + BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); local_irq_save(flags); gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio); bfin_read_CHIPID(); @@ -286,7 +362,7 @@ void set_gpio_toggle(unsigned short gpio) #else void set_gpio_toggle(unsigned short gpio) { - BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); + BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio); } #endif @@ -350,7 +426,7 @@ unsigned short get_gpio_data(unsigned short gpio) { unsigned long flags; unsigned short ret; - BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); + BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); local_irq_save(flags); ret = 0x01 & (gpio_bankb[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)); bfin_read_CHIPID(); @@ -494,13 +570,14 @@ u32 gpio_pm_setup(void) gpio_bank_saved[bank].dir = gpio_bankb[bank]->dir; gpio_bank_saved[bank].edge = gpio_bankb[bank]->edge; gpio_bank_saved[bank].both = gpio_bankb[bank]->both; - gpio_bank_saved[bank].reserved = reserved_map[bank]; + gpio_bank_saved[bank].reserved = + reserved_gpio_map[bank]; gpio = i; while (mask) { if (mask & 1) { - reserved_map[gpio_bank(gpio)] |= + reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio); bfin_gpio_wakeup_type(gpio, wakeup_flags_map[gpio]); @@ -540,7 +617,8 @@ void gpio_pm_restore(void) gpio_bankb[bank]->edge = gpio_bank_saved[bank].edge; gpio_bankb[bank]->both = gpio_bank_saved[bank].both; - reserved_map[bank] = gpio_bank_saved[bank].reserved; + reserved_gpio_map[bank] = + gpio_bank_saved[bank].reserved; } @@ -550,6 +628,141 @@ void gpio_pm_restore(void) #endif + + + +int peripheral_request(unsigned short per, const char *label) +{ + unsigned long flags; + unsigned short ident = P_IDENT(per); + + /* + * Don't cares are pins with only one dedicated function + */ + + if (per & P_DONTCARE) + return 0; + + if (!(per & P_DEFINED)) + return -ENODEV; + + local_irq_save(flags); + + if (!check_gpio(ident)) { + + if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) { + printk(KERN_ERR + "%s: Peripheral %d is already reserved as GPIO by %s !\n", + __FUNCTION__, ident, get_label(ident)); + dump_stack(); + local_irq_restore(flags); + return -EBUSY; + } + + } + + if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) { + + /* + * Pin functions like AMC address strobes my + * be requested and used by several drivers + */ + + if (!(per & P_MAYSHARE)) { + + /* + * Allow that the identical pin function can + * be requested from the same driver twice + */ + + if (cmp_label(ident, label) == 0) + goto anyway; + + printk(KERN_ERR + "%s: Peripheral %d function %d is already" + "reserved by %s !\n", + __FUNCTION__, ident, P_FUNCT2MUX(per), + get_label(ident)); + dump_stack(); + local_irq_restore(flags); + return -EBUSY; + } + + } + +anyway: + + + portmux_setup(per, P_FUNCT2MUX(per)); + + port_setup(ident, PERIPHERAL_USAGE); + + reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident); + local_irq_restore(flags); + set_label(ident, label); + + return 0; +} +EXPORT_SYMBOL(peripheral_request); + +int peripheral_request_list(unsigned short per[], const char *label) +{ + u16 cnt; + int ret; + + for (cnt = 0; per[cnt] != 0; cnt++) { + ret = peripheral_request(per[cnt], label); + if (ret < 0) + return ret; + } + + return 0; +} +EXPORT_SYMBOL(peripheral_request_list); + +void peripheral_free(unsigned short per) +{ + unsigned long flags; + unsigned short ident = P_IDENT(per); + + if (per & P_DONTCARE) + return; + + if (!(per & P_DEFINED)) + return; + + if (check_gpio(ident) < 0) + return; + + local_irq_save(flags); + + if (unlikely(!(reserved_peri_map[gpio_bank(ident)] + & gpio_bit(ident)))) { + local_irq_restore(flags); + return; + } + + if (!(per & P_MAYSHARE)) { + port_setup(ident, GPIO_USAGE); + } + + reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident); + + local_irq_restore(flags); +} +EXPORT_SYMBOL(peripheral_free); + +void peripheral_free_list(unsigned short per[]) +{ + u16 cnt; + + for (cnt = 0; per[cnt] != 0; cnt++) { + peripheral_free(per[cnt]); + } + +} +EXPORT_SYMBOL(peripheral_free_list); + /*********************************************************** * * FUNCTIONS: Blackfin GPIO Driver @@ -574,13 +787,13 @@ int gpio_request(unsigned short gpio, const char *label) local_irq_save(flags); - if (unlikely(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))) { + if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved!\n", gpio); dump_stack(); local_irq_restore(flags); return -EBUSY; } - reserved_map[gpio_bank(gpio)] |= gpio_bit(gpio); + reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio); local_irq_restore(flags); @@ -599,7 +812,7 @@ void gpio_free(unsigned short gpio) local_irq_save(flags); - if (unlikely(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)))) { + if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) { printk(KERN_ERR "bfin-gpio: GPIO %d wasn't reserved!\n", gpio); dump_stack(); local_irq_restore(flags); @@ -608,7 +821,7 @@ void gpio_free(unsigned short gpio) default_gpio(gpio); - reserved_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); + reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); local_irq_restore(flags); } @@ -618,7 +831,7 @@ void gpio_direction_input(unsigned short gpio) { unsigned long flags; - BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); + BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); local_irq_save(flags); gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); @@ -631,7 +844,7 @@ void gpio_direction_output(unsigned short gpio) { unsigned long flags; - BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); + BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); local_irq_save(flags); gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index d61bba98fb5..96045880834 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -815,7 +815,7 @@ _extable: ALIGN ENTRY(_sys_call_table) - .long _sys_ni_syscall /* 0 - old "setup()" system call*/ + .long _sys_restart_syscall /* 0 */ .long _sys_exit .long _sys_fork .long _sys_read @@ -978,13 +978,13 @@ ENTRY(_sys_call_table) .long _sys_sched_get_priority_min /* 160 */ .long _sys_sched_rr_get_interval .long _sys_nanosleep - .long _sys_ni_syscall /* sys_mremap */ + .long _sys_mremap .long _sys_setresuid /* setresuid16 */ .long _sys_getresuid /* getresuid16 */ /* 165 */ .long _sys_ni_syscall /* for vm86 */ .long _sys_ni_syscall /* old "query_module" */ .long _sys_ni_syscall /* sys_poll */ - .long _sys_ni_syscall /* sys_nfsservctl */ + .long _sys_nfsservctl .long _sys_setresgid /* setresgid16 */ /* 170 */ .long _sys_getresgid /* getresgid16 */ .long _sys_prctl @@ -1040,7 +1040,7 @@ ENTRY(_sys_call_table) .long _sys_ni_syscall /* reserved for TUX */ .long _sys_ni_syscall .long _sys_gettid - .long _sys_ni_syscall /* 225 */ /* sys_readahead */ + .long _sys_readahead /* 225 */ .long _sys_setxattr .long _sys_lsetxattr .long _sys_fsetxattr @@ -1157,6 +1157,21 @@ ENTRY(_sys_call_table) .long _sys_shmctl .long _sys_shmdt /* 340 */ .long _sys_shmget + .long _sys_splice + .long _sys_sync_file_range + .long _sys_tee + .long _sys_vmsplice /* 345 */ + .long _sys_epoll_pwait + .long _sys_utimensat + .long _sys_signalfd + .long _sys_timerfd + .long _sys_eventfd /* 350 */ + .long _sys_pread64 + .long _sys_pwrite64 + .long _sys_fadvise64 + .long _sys_set_robust_list + .long _sys_get_robust_list /* 355 */ + .long _sys_fallocate .rept NR_syscalls-(.-_sys_call_table)/4 .long _sys_ni_syscall .endr diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index ef8f0bc3fc7..f0cce3c2dc3 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -76,6 +76,7 @@ static unsigned int longhaul_index; /* Module parameters */ static int scale_voltage; static int disable_acpi_c3; +static int revid_errata; #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg) @@ -168,7 +169,10 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index, rdmsrl(MSR_VIA_LONGHAUL, longhaul.val); /* Setup new frequency */ - longhaul.bits.RevisionKey = longhaul.bits.RevisionID; + if (!revid_errata) + longhaul.bits.RevisionKey = longhaul.bits.RevisionID; + else + longhaul.bits.RevisionKey = 0; longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf; longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; /* Setup new voltage */ @@ -272,7 +276,7 @@ static void longhaul_setstate(unsigned int table_index) dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n", fsb, mult/10, mult%10, print_speed(speed/1000)); - +retry_loop: preempt_disable(); local_irq_save(flags); @@ -344,6 +348,47 @@ static void longhaul_setstate(unsigned int table_index) preempt_enable(); freqs.new = calc_speed(longhaul_get_cpu_mult()); + /* Check if requested frequency is set. */ + if (unlikely(freqs.new != speed)) { + printk(KERN_INFO PFX "Failed to set requested frequency!\n"); + /* Revision ID = 1 but processor is expecting revision key + * equal to 0. Jumpers at the bottom of processor will change + * multiplier and FSB, but will not change bits in Longhaul + * MSR nor enable voltage scaling. */ + if (!revid_errata) { + printk(KERN_INFO PFX "Enabling \"Ignore Revision ID\" " + "option.\n"); + revid_errata = 1; + msleep(200); + goto retry_loop; + } + /* Why ACPI C3 sometimes doesn't work is a mystery for me. + * But it does happen. Processor is entering ACPI C3 state, + * but it doesn't change frequency. I tried poking various + * bits in northbridge registers, but without success. */ + if (longhaul_flags & USE_ACPI_C3) { + printk(KERN_INFO PFX "Disabling ACPI C3 support.\n"); + longhaul_flags &= ~USE_ACPI_C3; + if (revid_errata) { + printk(KERN_INFO PFX "Disabling \"Ignore " + "Revision ID\" option.\n"); + revid_errata = 0; + } + msleep(200); + goto retry_loop; + } + /* This shouldn't happen. Longhaul ver. 2 was reported not + * working on processors without voltage scaling, but with + * RevID = 1. RevID errata will make things right. Just + * to be 100% sure. */ + if (longhaul_version == TYPE_LONGHAUL_V2) { + printk(KERN_INFO PFX "Switching to Longhaul ver. 1\n"); + longhaul_version = TYPE_LONGHAUL_V1; + msleep(200); + goto retry_loop; + } + } + /* Report true CPU frequency */ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); if (!bm_timeout) @@ -956,11 +1001,20 @@ static void __exit longhaul_exit(void) kfree(longhaul_table); } +/* Even if BIOS is exporting ACPI C3 state, and it is used + * with success when CPU is idle, this state doesn't + * trigger frequency transition in some cases. */ module_param (disable_acpi_c3, int, 0644); MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support"); - +/* Change CPU voltage with frequency. Very usefull to save + * power, but most VIA C3 processors aren't supporting it. */ module_param (scale_voltage, int, 0644); MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor"); +/* Force revision key to 0 for processors which doesn't + * support voltage scaling, but are introducing itself as + * such. */ +module_param(revid_errata, int, 0644); +MODULE_PARM_DESC(revid_errata, "Ignore CPU Revision ID"); MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>"); MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); diff --git a/arch/mips/au1000/common/pci.c b/arch/mips/au1000/common/pci.c index 6c25e6c09f7..9be99a68932 100644 --- a/arch/mips/au1000/common/pci.c +++ b/arch/mips/au1000/common/pci.c @@ -74,6 +74,7 @@ static int __init au1x_pci_setup(void) printk(KERN_ERR "Unable to ioremap pci space\n"); return 1; } + au1x_controller.io_map_base = virt_io_addr; #ifdef CONFIG_DMA_NONCOHERENT { diff --git a/arch/mips/au1000/mtx-1/board_setup.c b/arch/mips/au1000/mtx-1/board_setup.c index 7bc5af8917d..2c460c11657 100644 --- a/arch/mips/au1000/mtx-1/board_setup.c +++ b/arch/mips/au1000/mtx-1/board_setup.c @@ -54,11 +54,11 @@ void board_reset (void) void __init board_setup(void) { -#ifdef CONFIG_USB_OHCI +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) // enable USB power switch au_writel( au_readl(GPIO2_DIR) | 0x10, GPIO2_DIR ); au_writel( 0x100000, GPIO2_OUTPUT ); -#endif // defined (CONFIG_USB_OHCI) +#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ #ifdef CONFIG_PCI #if defined(__MIPSEB__) diff --git a/arch/mips/au1000/pb1000/board_setup.c b/arch/mips/au1000/pb1000/board_setup.c index 824cfafaff9..0aed89114bf 100644 --- a/arch/mips/au1000/pb1000/board_setup.c +++ b/arch/mips/au1000/pb1000/board_setup.c @@ -54,7 +54,7 @@ void __init board_setup(void) au_writel(0, SYS_PINSTATERD); udelay(100); -#ifdef CONFIG_USB_OHCI +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) /* zero and disable FREQ2 */ sys_freqctrl = au_readl(SYS_FREQCTRL0); sys_freqctrl &= ~0xFFF00000; @@ -102,7 +102,7 @@ void __init board_setup(void) /* * Route 48MHz FREQ2 into USB Host and/or Device */ -#ifdef CONFIG_USB_OHCI +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) sys_clksrc |= ((4<<12) | (0<<11) | (0<<10)); #endif au_writel(sys_clksrc, SYS_CLKSRC); @@ -116,7 +116,7 @@ void __init board_setup(void) au_writel(pin_func, SYS_PINFUNC); au_writel(0x2800, SYS_TRIOUTCLR); au_writel(0x0030, SYS_OUTPUTCLR); -#endif // defined (CONFIG_USB_OHCI) +#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ // make gpio 15 an input (for interrupt line) pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x100); diff --git a/arch/mips/au1000/pb1100/board_setup.c b/arch/mips/au1000/pb1100/board_setup.c index 6bc1f8e1b60..259ca05860c 100644 --- a/arch/mips/au1000/pb1100/board_setup.c +++ b/arch/mips/au1000/pb1100/board_setup.c @@ -54,7 +54,7 @@ void __init board_setup(void) au_writel(0, SYS_PININPUTEN); udelay(100); -#ifdef CONFIG_USB_OHCI +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) { u32 pin_func, sys_freqctrl, sys_clksrc; @@ -98,7 +98,7 @@ void __init board_setup(void) pin_func |= 0x8000; au_writel(pin_func, SYS_PINFUNC); } -#endif // defined (CONFIG_USB_OHCI) +#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ /* Enable sys bus clock divider when IDLE state or no bus activity. */ au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL); diff --git a/arch/mips/au1000/pb1500/board_setup.c b/arch/mips/au1000/pb1500/board_setup.c index c9b655616fb..a2d850db890 100644 --- a/arch/mips/au1000/pb1500/board_setup.c +++ b/arch/mips/au1000/pb1500/board_setup.c @@ -56,7 +56,7 @@ void __init board_setup(void) au_writel(0, SYS_PINSTATERD); udelay(100); -#ifdef CONFIG_USB_OHCI +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) /* GPIO201 is input for PCMCIA card detect */ /* GPIO203 is input for PCMCIA interrupt request */ @@ -85,7 +85,7 @@ void __init board_setup(void) /* * Route 48MHz FREQ2 into USB Host and/or Device */ -#ifdef CONFIG_USB_OHCI +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) sys_clksrc |= ((4<<12) | (0<<11) | (0<<10)); #endif au_writel(sys_clksrc, SYS_CLKSRC); @@ -95,7 +95,7 @@ void __init board_setup(void) // 2nd USB port is USB host pin_func |= 0x8000; au_writel(pin_func, SYS_PINFUNC); -#endif // defined (CONFIG_USB_OHCI) +#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 60bbaecde18..087ab997487 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -45,6 +45,8 @@ SECTIONS __dbe_table : { *(__dbe_table) } __stop___dbe_table = .; + NOTES + RODATA /* writeable */ diff --git a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c index dc795be6280..e47e9e9486b 100644 --- a/arch/mips/mm/pg-r4k.c +++ b/arch/mips/mm/pg-r4k.c @@ -209,7 +209,7 @@ static inline void build_cdex_p(void) } if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) - build_insn_word(0x3c01a000); /* lui $at, 0xa000 */ + build_insn_word(0x8c200000); /* lw $zero, ($at) */ mi.c_format.opcode = cache_op; mi.c_format.rs = 4; /* $a0 */ diff --git a/arch/mips/pci/ops-mace.c b/arch/mips/pci/ops-mace.c index 8008e31c5e8..fe545144930 100644 --- a/arch/mips/pci/ops-mace.c +++ b/arch/mips/pci/ops-mace.c @@ -29,22 +29,20 @@ * 4 N/C */ -#define chkslot(_bus,_devfn) \ -do { \ - if ((_bus)->number > 0 || PCI_SLOT (_devfn) < 1 \ - || PCI_SLOT (_devfn) > 3) \ - return PCIBIOS_DEVICE_NOT_FOUND; \ -} while (0) +static inline int mkaddr(struct pci_bus *bus, unsigned int devfn, + unsigned int reg) +{ + return ((bus->number & 0xff) << 16) | + ((devfn & 0xff) << 8) | + (reg & 0xfc); +} -#define mkaddr(_devfn, _reg) \ -((((_devfn) & 0xffUL) << 8) | ((_reg) & 0xfcUL)) static int mace_pci_read_config(struct pci_bus *bus, unsigned int devfn, int reg, int size, u32 *val) { - chkslot(bus, devfn); - mace->pci.config_addr = mkaddr(devfn, reg); + mace->pci.config_addr = mkaddr(bus, devfn, reg); switch (size) { case 1: *val = mace->pci.config_data.b[(reg & 3) ^ 3]; @@ -66,8 +64,7 @@ static int mace_pci_write_config(struct pci_bus *bus, unsigned int devfn, int reg, int size, u32 val) { - chkslot(bus, devfn); - mace->pci.config_addr = mkaddr(devfn, reg); + mace->pci.config_addr = mkaddr(bus, devfn, reg); switch (size) { case 1: mace->pci.config_data.b[(reg & 3) ^ 3] = val; diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 5bd90a7eb76..f0b5ff17d86 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -419,7 +419,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) * For the moment only implement delivery to all cpus or one cpu. * Get current irq_server for the given irq */ - irq_server = get_irq_server(irq, 1); + irq_server = get_irq_server(virq, 1); if (irq_server == -1) { char cpulist[128]; cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask); diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c index e2d02fd13f3..d850785b208 100644 --- a/arch/sparc/kernel/ebus.c +++ b/arch/sparc/kernel/ebus.c @@ -156,6 +156,8 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d dev->prom_node = dp; regs = of_get_property(dp, "reg", &len); + if (!regs) + len = 0; if (len % sizeof(struct linux_prom_registers)) { prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", dev->prom_node->name, len, diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c index f205fc7cbcd..d208cc7804f 100644 --- a/arch/sparc64/kernel/binfmt_aout32.c +++ b/arch/sparc64/kernel/binfmt_aout32.c @@ -177,7 +177,7 @@ static u32 __user *create_aout32_tables(char __user *p, struct linux_binprm *bpr get_user(c,p++); } while (c); } - put_user(NULL,argv); + put_user(0,argv); current->mm->arg_end = current->mm->env_start = (unsigned long) p; while (envc-->0) { char c; @@ -186,7 +186,7 @@ static u32 __user *create_aout32_tables(char __user *p, struct linux_binprm *bpr get_user(c,p++); } while (c); } - put_user(NULL,envp); + put_user(0,envp); current->mm->env_end = (unsigned long) p; return sp; } diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index bc9ae36f7a4..04ab81cb4f4 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -375,7 +375,10 @@ static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_de dev->num_addrs = 0; dev->num_irqs = 0; } else { - (void) of_get_property(dp, "reg", &len); + const int *regs = of_get_property(dp, "reg", &len); + + if (!regs) + len = 0; dev->num_addrs = len / sizeof(struct linux_prom_registers); for (i = 0; i < dev->num_addrs; i++) diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 2f61c4b1259..c76bfbb7da0 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c @@ -264,7 +264,7 @@ static int sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, unsigned int func = PCI_FUNC(devfn); unsigned long ret; - if (bus_dev == pbm->pci_bus && devfn == 0x00) + if (!bus && devfn == 0x00) return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, size, value); if (config_out_of_range(pbm, bus, devfn, where)) { @@ -300,7 +300,7 @@ static int sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, unsigned int func = PCI_FUNC(devfn); unsigned long ret; - if (bus_dev == pbm->pci_bus && devfn == 0x00) + if (!bus && devfn == 0x00) return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, size, value); if (config_out_of_range(pbm, bus, devfn, where)) { diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 0614dff63d7..a246e962e5a 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c @@ -1046,7 +1046,8 @@ static void __init irq_trans_init(struct device_node *dp) if (!strcmp(dp->name, "fhc") && !strcmp(dp->parent->name, "central")) return central_irq_trans_init(dp); - if (!strcmp(dp->name, "virtual-devices")) + if (!strcmp(dp->name, "virtual-devices") || + !strcmp(dp->name, "niu")) return sun4v_vdev_irq_trans_init(dp); } diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index b84c49e3697..c73b7a48b03 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -353,6 +353,8 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu) int timeout, ret; p = fork_idle(cpu); + if (IS_ERR(p)) + return PTR_ERR(p); callin_flag = 0; cpu_new_thread = task_thread_info(p); diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c index 1550ac5673d..0c1ee619d81 100644 --- a/arch/sparc64/kernel/vio.c +++ b/arch/sparc64/kernel/vio.c @@ -292,7 +292,7 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, } vdev->dp = dp; - printk(KERN_ERR "VIO: Adding device %s\n", vdev->dev.bus_id); + printk(KERN_INFO "VIO: Adding device %s\n", vdev->dev.bus_id); err = device_register(&vdev->dev); if (err) { @@ -342,8 +342,33 @@ static struct mdesc_notifier_client vio_device_notifier = { .node_name = "virtual-device-port", }; +/* We are only interested in domain service ports under the + * "domain-services" node. On control nodes there is another port + * under "openboot" that we should not mess with as aparently that is + * reserved exclusively for OBP use. + */ +static void vio_add_ds(struct mdesc_handle *hp, u64 node) +{ + int found; + u64 a; + + found = 0; + mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) { + u64 target = mdesc_arc_target(hp, a); + const char *name = mdesc_node_name(hp, target); + + if (!strcmp(name, "domain-services")) { + found = 1; + break; + } + } + + if (found) + (void) vio_create_one(hp, node, &root_vdev->dev); +} + static struct mdesc_notifier_client vio_ds_notifier = { - .add = vio_add, + .add = vio_add_ds, .remove = vio_remove, .node_name = "domain-services-port", }; diff --git a/arch/sparc64/lib/NGcopy_from_user.S b/arch/sparc64/lib/NGcopy_from_user.S index 2d93456f76d..e7f433f71b4 100644 --- a/arch/sparc64/lib/NGcopy_from_user.S +++ b/arch/sparc64/lib/NGcopy_from_user.S @@ -1,6 +1,6 @@ /* NGcopy_from_user.S: Niagara optimized copy from userspace. * - * Copyright (C) 2006 David S. Miller (davem@davemloft.net) + * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net) */ #define EX_LD(x) \ @@ -8,8 +8,8 @@ .section .fixup; \ .align 4; \ 99: wr %g0, ASI_AIUS, %asi;\ - retl; \ - mov 1, %o0; \ + ret; \ + restore %g0, 1, %o0; \ .section __ex_table,"a";\ .align 4; \ .word 98b, 99b; \ @@ -24,7 +24,7 @@ #define LOAD(type,addr,dest) type##a [addr] ASI_AIUS, dest #define LOAD_TWIN(addr_reg,dest0,dest1) \ ldda [addr_reg] ASI_BLK_INIT_QUAD_LDD_AIUS, dest0 -#define EX_RETVAL(x) 0 +#define EX_RETVAL(x) %g0 #ifdef __KERNEL__ #define PREAMBLE \ diff --git a/arch/sparc64/lib/NGcopy_to_user.S b/arch/sparc64/lib/NGcopy_to_user.S index 34112d5054e..6ea01c5532a 100644 --- a/arch/sparc64/lib/NGcopy_to_user.S +++ b/arch/sparc64/lib/NGcopy_to_user.S @@ -1,6 +1,6 @@ /* NGcopy_to_user.S: Niagara optimized copy to userspace. * - * Copyright (C) 2006 David S. Miller (davem@davemloft.net) + * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net) */ #define EX_ST(x) \ @@ -8,8 +8,8 @@ .section .fixup; \ .align 4; \ 99: wr %g0, ASI_AIUS, %asi;\ - retl; \ - mov 1, %o0; \ + ret; \ + restore %g0, 1, %o0; \ .section __ex_table,"a";\ .align 4; \ .word 98b, 99b; \ @@ -23,7 +23,7 @@ #define FUNC_NAME NGcopy_to_user #define STORE(type,src,addr) type##a src, [addr] ASI_AIUS #define STORE_ASI ASI_BLK_INIT_QUAD_LDD_AIUS -#define EX_RETVAL(x) 0 +#define EX_RETVAL(x) %g0 #ifdef __KERNEL__ /* Writing to %asi is _expensive_ so we hardcode it. diff --git a/arch/sparc64/lib/NGmemcpy.S b/arch/sparc64/lib/NGmemcpy.S index 66063a9a66b..96a14caf696 100644 --- a/arch/sparc64/lib/NGmemcpy.S +++ b/arch/sparc64/lib/NGmemcpy.S @@ -1,6 +1,6 @@ /* NGmemcpy.S: Niagara optimized memcpy. * - * Copyright (C) 2006 David S. Miller (davem@davemloft.net) + * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net) */ #ifdef __KERNEL__ @@ -16,6 +16,12 @@ wr %g0, ASI_PNF, %asi #endif +#ifdef __sparc_v9__ +#define SAVE_AMOUNT 128 +#else +#define SAVE_AMOUNT 64 +#endif + #ifndef STORE_ASI #define STORE_ASI ASI_BLK_INIT_QUAD_LDD_P #endif @@ -50,7 +56,11 @@ #endif #ifndef STORE_INIT +#ifndef SIMULATE_NIAGARA_ON_NON_NIAGARA #define STORE_INIT(src,addr) stxa src, [addr] %asi +#else +#define STORE_INIT(src,addr) stx src, [addr + 0x00] +#endif #endif #ifndef FUNC_NAME @@ -73,18 +83,19 @@ .globl FUNC_NAME .type FUNC_NAME,#function -FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - srlx %o2, 31, %g2 +FUNC_NAME: /* %i0=dst, %i1=src, %i2=len */ + PREAMBLE + save %sp, -SAVE_AMOUNT, %sp + srlx %i2, 31, %g2 cmp %g2, 0 tne %xcc, 5 - PREAMBLE - mov %o0, GLOBAL_SPARE - cmp %o2, 0 + mov %i0, %o0 + cmp %i2, 0 be,pn %XCC, 85f - or %o0, %o1, %o3 - cmp %o2, 16 + or %o0, %i1, %i3 + cmp %i2, 16 blu,a,pn %XCC, 80f - or %o3, %o2, %o3 + or %i3, %i2, %i3 /* 2 blocks (128 bytes) is the minimum we can do the block * copy with. We need to ensure that we'll iterate at least @@ -93,31 +104,31 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ * to (64 - 1) bytes from the length before we perform the * block copy loop. */ - cmp %o2, (2 * 64) + cmp %i2, (2 * 64) blu,pt %XCC, 70f - andcc %o3, 0x7, %g0 + andcc %i3, 0x7, %g0 /* %o0: dst - * %o1: src - * %o2: len (known to be >= 128) + * %i1: src + * %i2: len (known to be >= 128) * - * The block copy loops will use %o4/%o5,%g2/%g3 as + * The block copy loops will use %i4/%i5,%g2/%g3 as * temporaries while copying the data. */ - LOAD(prefetch, %o1, #one_read) + LOAD(prefetch, %i1, #one_read) wr %g0, STORE_ASI, %asi /* Align destination on 64-byte boundary. */ - andcc %o0, (64 - 1), %o4 + andcc %o0, (64 - 1), %i4 be,pt %XCC, 2f - sub %o4, 64, %o4 - sub %g0, %o4, %o4 ! bytes to align dst - sub %o2, %o4, %o2 -1: subcc %o4, 1, %o4 - EX_LD(LOAD(ldub, %o1, %g1)) + sub %i4, 64, %i4 + sub %g0, %i4, %i4 ! bytes to align dst + sub %i2, %i4, %i2 +1: subcc %i4, 1, %i4 + EX_LD(LOAD(ldub, %i1, %g1)) EX_ST(STORE(stb, %g1, %o0)) - add %o1, 1, %o1 + add %i1, 1, %i1 bne,pt %XCC, 1b add %o0, 1, %o0 @@ -136,111 +147,155 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ * aligned store data at a time, this is easy to ensure. */ 2: - andcc %o1, (16 - 1), %o4 - andn %o2, (64 - 1), %g1 ! block copy loop iterator - sub %o2, %g1, %o2 ! final sub-block copy bytes + andcc %i1, (16 - 1), %i4 + andn %i2, (64 - 1), %g1 ! block copy loop iterator be,pt %XCC, 50f - cmp %o4, 8 - be,a,pt %XCC, 10f - sub %o1, 0x8, %o1 + sub %i2, %g1, %i2 ! final sub-block copy bytes + + cmp %i4, 8 + be,pt %XCC, 10f + sub %i1, %i4, %i1 /* Neither 8-byte nor 16-byte aligned, shift and mask. */ - mov %g1, %o4 - and %o1, 0x7, %g1 - sll %g1, 3, %g1 - mov 64, %o3 - andn %o1, 0x7, %o1 - EX_LD(LOAD(ldx, %o1, %g2)) - sub %o3, %g1, %o3 - sllx %g2, %g1, %g2 + and %i4, 0x7, GLOBAL_SPARE + sll GLOBAL_SPARE, 3, GLOBAL_SPARE + mov 64, %i5 + EX_LD(LOAD_TWIN(%i1, %g2, %g3)) + sub %i5, GLOBAL_SPARE, %i5 + mov 16, %o4 + mov 32, %o5 + mov 48, %o7 + mov 64, %i3 + + bg,pn %XCC, 9f + nop -#define SWIVEL_ONE_DWORD(SRC, TMP1, TMP2, PRE_VAL, PRE_SHIFT, POST_SHIFT, DST)\ - EX_LD(LOAD(ldx, SRC, TMP1)); \ - srlx TMP1, PRE_SHIFT, TMP2; \ - or TMP2, PRE_VAL, TMP2; \ - EX_ST(STORE_INIT(TMP2, DST)); \ - sllx TMP1, POST_SHIFT, PRE_VAL; - -1: add %o1, 0x8, %o1 - SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x00) - add %o1, 0x8, %o1 - SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x08) - add %o1, 0x8, %o1 - SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x10) - add %o1, 0x8, %o1 - SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x18) - add %o1, 32, %o1 - LOAD(prefetch, %o1, #one_read) - sub %o1, 32 - 8, %o1 - SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x20) - add %o1, 8, %o1 - SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x28) - add %o1, 8, %o1 - SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x30) - add %o1, 8, %o1 - SWIVEL_ONE_DWORD(%o1, %g3, %o5, %g2, %o3, %g1, %o0 + 0x38) - subcc %o4, 64, %o4 - bne,pt %XCC, 1b +#define MIX_THREE_WORDS(WORD1, WORD2, WORD3, PRE_SHIFT, POST_SHIFT, TMP) \ + sllx WORD1, POST_SHIFT, WORD1; \ + srlx WORD2, PRE_SHIFT, TMP; \ + sllx WORD2, POST_SHIFT, WORD2; \ + or WORD1, TMP, WORD1; \ + srlx WORD3, PRE_SHIFT, TMP; \ + or WORD2, TMP, WORD2; + +8: EX_LD(LOAD_TWIN(%i1 + %o4, %o2, %o3)) + MIX_THREE_WORDS(%g2, %g3, %o2, %i5, GLOBAL_SPARE, %o1) + LOAD(prefetch, %i1 + %i3, #one_read) + + EX_ST(STORE_INIT(%g2, %o0 + 0x00)) + EX_ST(STORE_INIT(%g3, %o0 + 0x08)) + + EX_LD(LOAD_TWIN(%i1 + %o5, %g2, %g3)) + MIX_THREE_WORDS(%o2, %o3, %g2, %i5, GLOBAL_SPARE, %o1) + + EX_ST(STORE_INIT(%o2, %o0 + 0x10)) + EX_ST(STORE_INIT(%o3, %o0 + 0x18)) + + EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3)) + MIX_THREE_WORDS(%g2, %g3, %o2, %i5, GLOBAL_SPARE, %o1) + + EX_ST(STORE_INIT(%g2, %o0 + 0x20)) + EX_ST(STORE_INIT(%g3, %o0 + 0x28)) + + EX_LD(LOAD_TWIN(%i1 + %i3, %g2, %g3)) + add %i1, 64, %i1 + MIX_THREE_WORDS(%o2, %o3, %g2, %i5, GLOBAL_SPARE, %o1) + + EX_ST(STORE_INIT(%o2, %o0 + 0x30)) + EX_ST(STORE_INIT(%o3, %o0 + 0x38)) + + subcc %g1, 64, %g1 + bne,pt %XCC, 8b add %o0, 64, %o0 -#undef SWIVEL_ONE_DWORD + ba,pt %XCC, 60f + add %i1, %i4, %i1 + +9: EX_LD(LOAD_TWIN(%i1 + %o4, %o2, %o3)) + MIX_THREE_WORDS(%g3, %o2, %o3, %i5, GLOBAL_SPARE, %o1) + LOAD(prefetch, %i1 + %i3, #one_read) + + EX_ST(STORE_INIT(%g3, %o0 + 0x00)) + EX_ST(STORE_INIT(%o2, %o0 + 0x08)) + + EX_LD(LOAD_TWIN(%i1 + %o5, %g2, %g3)) + MIX_THREE_WORDS(%o3, %g2, %g3, %i5, GLOBAL_SPARE, %o1) + + EX_ST(STORE_INIT(%o3, %o0 + 0x10)) + EX_ST(STORE_INIT(%g2, %o0 + 0x18)) + + EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3)) + MIX_THREE_WORDS(%g3, %o2, %o3, %i5, GLOBAL_SPARE, %o1) + + EX_ST(STORE_INIT(%g3, %o0 + 0x20)) + EX_ST(STORE_INIT(%o2, %o0 + 0x28)) + + EX_LD(LOAD_TWIN(%i1 + %i3, %g2, %g3)) + add %i1, 64, %i1 + MIX_THREE_WORDS(%o3, %g2, %g3, %i5, GLOBAL_SPARE, %o1) + + EX_ST(STORE_INIT(%o3, %o0 + 0x30)) + EX_ST(STORE_INIT(%g2, %o0 + 0x38)) + + subcc %g1, 64, %g1 + bne,pt %XCC, 9b + add %o0, 64, %o0 - srl %g1, 3, %g1 ba,pt %XCC, 60f - add %o1, %g1, %o1 + add %i1, %i4, %i1 10: /* Destination is 64-byte aligned, source was only 8-byte * aligned but it has been subtracted by 8 and we perform * one twin load ahead, then add 8 back into source when * we finish the loop. */ - EX_LD(LOAD_TWIN(%o1, %o4, %o5)) -1: add %o1, 16, %o1 - EX_LD(LOAD_TWIN(%o1, %g2, %g3)) - add %o1, 16 + 32, %o1 - LOAD(prefetch, %o1, #one_read) - sub %o1, 32, %o1 + EX_LD(LOAD_TWIN(%i1, %o4, %o5)) + mov 16, %o7 + mov 32, %g2 + mov 48, %g3 + mov 64, %o1 +1: EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3)) + LOAD(prefetch, %i1 + %o1, #one_read) EX_ST(STORE_INIT(%o5, %o0 + 0x00)) ! initializes cache line - EX_ST(STORE_INIT(%g2, %o0 + 0x08)) - EX_LD(LOAD_TWIN(%o1, %o4, %o5)) - add %o1, 16, %o1 - EX_ST(STORE_INIT(%g3, %o0 + 0x10)) + EX_ST(STORE_INIT(%o2, %o0 + 0x08)) + EX_LD(LOAD_TWIN(%i1 + %g2, %o4, %o5)) + EX_ST(STORE_INIT(%o3, %o0 + 0x10)) EX_ST(STORE_INIT(%o4, %o0 + 0x18)) - EX_LD(LOAD_TWIN(%o1, %g2, %g3)) - add %o1, 16, %o1 + EX_LD(LOAD_TWIN(%i1 + %g3, %o2, %o3)) EX_ST(STORE_INIT(%o5, %o0 + 0x20)) - EX_ST(STORE_INIT(%g2, %o0 + 0x28)) - EX_LD(LOAD_TWIN(%o1, %o4, %o5)) - EX_ST(STORE_INIT(%g3, %o0 + 0x30)) + EX_ST(STORE_INIT(%o2, %o0 + 0x28)) + EX_LD(LOAD_TWIN(%i1 + %o1, %o4, %o5)) + add %i1, 64, %i1 + EX_ST(STORE_INIT(%o3, %o0 + 0x30)) EX_ST(STORE_INIT(%o4, %o0 + 0x38)) subcc %g1, 64, %g1 bne,pt %XCC, 1b add %o0, 64, %o0 ba,pt %XCC, 60f - add %o1, 0x8, %o1 + add %i1, 0x8, %i1 50: /* Destination is 64-byte aligned, and source is 16-byte * aligned. */ -1: EX_LD(LOAD_TWIN(%o1, %o4, %o5)) - add %o1, 16, %o1 - EX_LD(LOAD_TWIN(%o1, %g2, %g3)) - add %o1, 16 + 32, %o1 - LOAD(prefetch, %o1, #one_read) - sub %o1, 32, %o1 + mov 16, %o7 + mov 32, %g2 + mov 48, %g3 + mov 64, %o1 +1: EX_LD(LOAD_TWIN(%i1 + %g0, %o4, %o5)) + EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3)) + LOAD(prefetch, %i1 + %o1, #one_read) EX_ST(STORE_INIT(%o4, %o0 + 0x00)) ! initializes cache line EX_ST(STORE_INIT(%o5, %o0 + 0x08)) - EX_LD(LOAD_TWIN(%o1, %o4, %o5)) - add %o1, 16, %o1 - EX_ST(STORE_INIT(%g2, %o0 + 0x10)) - EX_ST(STORE_INIT(%g3, %o0 + 0x18)) - EX_LD(LOAD_TWIN(%o1, %g2, %g3)) - add %o1, 16, %o1 + EX_LD(LOAD_TWIN(%i1 + %g2, %o4, %o5)) + EX_ST(STORE_INIT(%o2, %o0 + 0x10)) + EX_ST(STORE_INIT(%o3, %o0 + 0x18)) + EX_LD(LOAD_TWIN(%i1 + %g3, %o2, %o3)) + add %i1, 64, %i1 EX_ST(STORE_INIT(%o4, %o0 + 0x20)) EX_ST(STORE_INIT(%o5, %o0 + 0x28)) - EX_ST(STORE_INIT(%g2, %o0 + 0x30)) - EX_ST(STORE_INIT(%g3, %o0 + 0x38)) + EX_ST(STORE_INIT(%o2, %o0 + 0x30)) + EX_ST(STORE_INIT(%o3, %o0 + 0x38)) subcc %g1, 64, %g1 bne,pt %XCC, 1b add %o0, 64, %o0 @@ -249,47 +304,47 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ 60: membar #Sync - /* %o2 contains any final bytes still needed to be copied + /* %i2 contains any final bytes still needed to be copied * over. If anything is left, we copy it one byte at a time. */ - RESTORE_ASI(%o3) - brz,pt %o2, 85f - sub %o0, %o1, %o3 + RESTORE_ASI(%i3) + brz,pt %i2, 85f + sub %o0, %i1, %i3 ba,a,pt %XCC, 90f .align 64 70: /* 16 < len <= 64 */ bne,pn %XCC, 75f - sub %o0, %o1, %o3 + sub %o0, %i1, %i3 72: - andn %o2, 0xf, %o4 - and %o2, 0xf, %o2 -1: subcc %o4, 0x10, %o4 - EX_LD(LOAD(ldx, %o1, %o5)) - add %o1, 0x08, %o1 - EX_LD(LOAD(ldx, %o1, %g1)) - sub %o1, 0x08, %o1 - EX_ST(STORE(stx, %o5, %o1 + %o3)) - add %o1, 0x8, %o1 - EX_ST(STORE(stx, %g1, %o1 + %o3)) + andn %i2, 0xf, %i4 + and %i2, 0xf, %i2 +1: subcc %i4, 0x10, %i4 + EX_LD(LOAD(ldx, %i1, %o4)) + add %i1, 0x08, %i1 + EX_LD(LOAD(ldx, %i1, %g1)) + sub %i1, 0x08, %i1 + EX_ST(STORE(stx, %o4, %i1 + %i3)) + add %i1, 0x8, %i1 + EX_ST(STORE(stx, %g1, %i1 + %i3)) bgu,pt %XCC, 1b - add %o1, 0x8, %o1 -73: andcc %o2, 0x8, %g0 + add %i1, 0x8, %i1 +73: andcc %i2, 0x8, %g0 be,pt %XCC, 1f nop - sub %o2, 0x8, %o2 - EX_LD(LOAD(ldx, %o1, %o5)) - EX_ST(STORE(stx, %o5, %o1 + %o3)) - add %o1, 0x8, %o1 -1: andcc %o2, 0x4, %g0 + sub %i2, 0x8, %i2 + EX_LD(LOAD(ldx, %i1, %o4)) + EX_ST(STORE(stx, %o4, %i1 + %i3)) + add %i1, 0x8, %i1 +1: andcc %i2, 0x4, %g0 be,pt %XCC, 1f nop - sub %o2, 0x4, %o2 - EX_LD(LOAD(lduw, %o1, %o5)) - EX_ST(STORE(stw, %o5, %o1 + %o3)) - add %o1, 0x4, %o1 -1: cmp %o2, 0 + sub %i2, 0x4, %i2 + EX_LD(LOAD(lduw, %i1, %i5)) + EX_ST(STORE(stw, %i5, %i1 + %i3)) + add %i1, 0x4, %i1 +1: cmp %i2, 0 be,pt %XCC, 85f nop ba,pt %xcc, 90f @@ -300,71 +355,71 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ sub %g1, 0x8, %g1 be,pn %icc, 2f sub %g0, %g1, %g1 - sub %o2, %g1, %o2 + sub %i2, %g1, %i2 1: subcc %g1, 1, %g1 - EX_LD(LOAD(ldub, %o1, %o5)) - EX_ST(STORE(stb, %o5, %o1 + %o3)) + EX_LD(LOAD(ldub, %i1, %i5)) + EX_ST(STORE(stb, %i5, %i1 + %i3)) bgu,pt %icc, 1b - add %o1, 1, %o1 + add %i1, 1, %i1 -2: add %o1, %o3, %o0 - andcc %o1, 0x7, %g1 +2: add %i1, %i3, %o0 + andcc %i1, 0x7, %g1 bne,pt %icc, 8f sll %g1, 3, %g1 - cmp %o2, 16 + cmp %i2, 16 bgeu,pt %icc, 72b nop ba,a,pt %xcc, 73b -8: mov 64, %o3 - andn %o1, 0x7, %o1 - EX_LD(LOAD(ldx, %o1, %g2)) - sub %o3, %g1, %o3 - andn %o2, 0x7, %o4 +8: mov 64, %i3 + andn %i1, 0x7, %i1 + EX_LD(LOAD(ldx, %i1, %g2)) + sub %i3, %g1, %i3 + andn %i2, 0x7, %i4 sllx %g2, %g1, %g2 -1: add %o1, 0x8, %o1 - EX_LD(LOAD(ldx, %o1, %g3)) - subcc %o4, 0x8, %o4 - srlx %g3, %o3, %o5 - or %o5, %g2, %o5 - EX_ST(STORE(stx, %o5, %o0)) +1: add %i1, 0x8, %i1 + EX_LD(LOAD(ldx, %i1, %g3)) + subcc %i4, 0x8, %i4 + srlx %g3, %i3, %i5 + or %i5, %g2, %i5 + EX_ST(STORE(stx, %i5, %o0)) add %o0, 0x8, %o0 bgu,pt %icc, 1b sllx %g3, %g1, %g2 srl %g1, 3, %g1 - andcc %o2, 0x7, %o2 + andcc %i2, 0x7, %i2 be,pn %icc, 85f - add %o1, %g1, %o1 + add %i1, %g1, %i1 ba,pt %xcc, 90f - sub %o0, %o1, %o3 + sub %o0, %i1, %i3 .align 64 80: /* 0 < len <= 16 */ - andcc %o3, 0x3, %g0 + andcc %i3, 0x3, %g0 bne,pn %XCC, 90f - sub %o0, %o1, %o3 + sub %o0, %i1, %i3 1: - subcc %o2, 4, %o2 - EX_LD(LOAD(lduw, %o1, %g1)) - EX_ST(STORE(stw, %g1, %o1 + %o3)) + subcc %i2, 4, %i2 + EX_LD(LOAD(lduw, %i1, %g1)) + EX_ST(STORE(stw, %g1, %i1 + %i3)) bgu,pt %XCC, 1b - add %o1, 4, %o1 + add %i1, 4, %i1 -85: retl - mov EX_RETVAL(GLOBAL_SPARE), %o0 +85: ret + restore EX_RETVAL(%i0), %g0, %o0 .align 32 90: - subcc %o2, 1, %o2 - EX_LD(LOAD(ldub, %o1, %g1)) - EX_ST(STORE(stb, %g1, %o1 + %o3)) + subcc %i2, 1, %i2 + EX_LD(LOAD(ldub, %i1, %g1)) + EX_ST(STORE(stb, %g1, %i1 + %i3)) bgu,pt %XCC, 90b - add %o1, 1, %o1 - retl - mov EX_RETVAL(GLOBAL_SPARE), %o0 + add %i1, 1, %i1 + ret + restore EX_RETVAL(%i0), %g0, %o0 .size FUNC_NAME, .-FUNC_NAME diff --git a/arch/x86_64/vdso/voffset.h b/arch/x86_64/vdso/voffset.h index 5304204911f..4af67c79085 100644 --- a/arch/x86_64/vdso/voffset.h +++ b/arch/x86_64/vdso/voffset.h @@ -1 +1 @@ -#define VDSO_TEXT_OFFSET 0x500 +#define VDSO_TEXT_OFFSET 0x600 diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 3b8bf1812dc..6996eb5b750 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -921,6 +921,13 @@ static int piix_broken_suspend(void) { static struct dmi_system_id sysids[] = { { + .ident = "TECRA M3", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M3"), + }, + }, + { .ident = "TECRA M5", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c index 4ca7fd6118d..5dea3584c6c 100644 --- a/drivers/ata/pata_ixp4xx_cf.c +++ b/drivers/ata/pata_ixp4xx_cf.c @@ -189,6 +189,9 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev) data->cs0 = devm_ioremap(&pdev->dev, cs0->start, 0x1000); data->cs1 = devm_ioremap(&pdev->dev, cs1->start, 0x1000); + if (!data->cs0 || !data->cs1) + return -ENOMEM; + irq = platform_get_irq(pdev, 0); if (irq) set_irq_type(irq, IRQT_RISING); diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index ae206f35f74..b45506f1ef7 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -44,10 +44,10 @@ static int marvell_pre_reset(struct ata_port *ap, unsigned long deadline) return -ENOMEM; printk("BAR5:"); for(i = 0; i <= 0x0F; i++) - printk("%02X:%02X ", i, readb(barp + i)); + printk("%02X:%02X ", i, ioread8(barp + i)); printk("\n"); - devices = readl(barp + 0x0C); + devices = ioread32(barp + 0x0C); pci_iounmap(pdev, barp); if ((pdev->device == 0x6145) && (ap->port_no == 0) && diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 11bf6c7ac12..cb7dec97fee 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -313,7 +313,10 @@ enum { #define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE) enum { - MV_DMA_BOUNDARY = 0xffffffffU, + /* DMA boundary 0xffff is required by the s/g splitting + * we need on /length/ in mv_fill-sg(). + */ + MV_DMA_BOUNDARY = 0xffffU, /* mask of register bits containing lower 32 bits * of EDMA request queue DMA address @@ -448,7 +451,7 @@ static struct scsi_host_template mv5_sht = { .queuecommand = ata_scsi_queuecmd, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = MV_MAX_SG_CT, + .sg_tablesize = MV_MAX_SG_CT / 2, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = 1, @@ -466,7 +469,7 @@ static struct scsi_host_template mv6_sht = { .queuecommand = ata_scsi_queuecmd, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = MV_MAX_SG_CT, + .sg_tablesize = MV_MAX_SG_CT / 2, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = 1, @@ -1139,15 +1142,27 @@ static unsigned int mv_fill_sg(struct ata_queued_cmd *qc) dma_addr_t addr = sg_dma_address(sg); u32 sg_len = sg_dma_len(sg); - mv_sg->addr = cpu_to_le32(addr & 0xffffffff); - mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16); - mv_sg->flags_size = cpu_to_le32(sg_len & 0xffff); + while (sg_len) { + u32 offset = addr & 0xffff; + u32 len = sg_len; + + if ((offset + sg_len > 0x10000)) + len = 0x10000 - offset; + + mv_sg->addr = cpu_to_le32(addr & 0xffffffff); + mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16); + mv_sg->flags_size = cpu_to_le32(len); - if (ata_sg_is_last(sg, qc)) - mv_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); + sg_len -= len; + addr += len; + + if (!sg_len && ata_sg_is_last(sg, qc)) + mv_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); + + mv_sg++; + n_sg++; + } - mv_sg++; - n_sg++; } return n_sg; diff --git a/drivers/base/core.c b/drivers/base/core.c index 67c92582d6e..ec86d6fc236 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -586,9 +586,13 @@ void device_initialize(struct device *dev) static struct kobject * get_device_parent(struct device *dev, struct device *parent) { - /* Set the parent to the class, not the parent device */ - /* this keeps sysfs from having a symlink to make old udevs happy */ - if (dev->class) + /* + * Set the parent to the class, not the parent device + * for topmost devices in class hierarchy. + * This keeps sysfs from having a symlink to make old + * udevs happy + */ + if (dev->class && (!parent || parent->class != dev->class)) return &dev->class->subsys.kobj; else if (parent) return &parent->kobj; diff --git a/drivers/char/Makefile b/drivers/char/Makefile index d68ddbe70f7..c78ff26647e 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -129,7 +129,7 @@ $(obj)/defkeymap.o: $(obj)/defkeymap.c ifdef GENERATE_KEYMAP -$(obj)/defkeymap.c $(obj)/%.c: $(src)/%.map +$(obj)/defkeymap.c: $(obj)/%.c: $(src)/%.map loadkeys --mktable $< > $@.tmp sed -e 's/^static *//' $@.tmp > $@ rm $@.tmp diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index a5d0e95a227..141ca176c39 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -506,11 +506,6 @@ static void intel_i830_init_gtt_entries(void) break; } } else { - /* G33's GTT stolen memory is separate from gfx data - * stolen memory. - */ - if (IS_G33) - size = 0; switch (gmch_ctrl & I855_GMCH_GMS_MASK) { case I855_GMCH_GMS_STOLEN_1M: gtt_entries = MB(1) - KB(size); diff --git a/drivers/char/random.c b/drivers/char/random.c index 397c714cf2b..af274e5a25e 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1550,11 +1550,13 @@ __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, * As close as possible to RFC 793, which * suggests using a 250 kHz clock. * Further reading shows this assumes 2 Mb/s networks. - * For 10 Gb/s Ethernet, a 1 GHz clock is appropriate. - * That's funny, Linux has one built in! Use it! - * (Networks are faster now - should this be increased?) + * For 10 Mb/s Ethernet, a 1 MHz clock is appropriate. + * For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but + * we also need to limit the resolution so that the u32 seq + * overlaps less than one time per MSL (2 minutes). + * Choosing a clock of 64 ns period is OK. (period of 274 s) */ - seq += ktime_get_real().tv64; + seq += ktime_get_real().tv64 >> 6; #if 0 printk("init_seq(%lx, %lx, %d, %d) = %d\n", saddr, daddr, sport, dport, seq); diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index 045e6888d15..7a61a2a9aaf 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -770,6 +770,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, /* * Switching-from response */ + acquire_console_sem(); if (vc->vt_newvt >= 0) { if (arg == 0) /* @@ -784,7 +785,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, * complete the switch. */ int newvt; - acquire_console_sem(); newvt = vc->vt_newvt; vc->vt_newvt = -1; i = vc_allocate(newvt); @@ -798,7 +798,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, * other console switches.. */ complete_change_console(vc_cons[newvt].d); - release_console_sem(); } } @@ -810,9 +809,12 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, /* * If it's just an ACK, ignore it */ - if (arg != VT_ACKACQ) + if (arg != VT_ACKACQ) { + release_console_sem(); return -EINVAL; + } } + release_console_sem(); return 0; @@ -1030,7 +1032,7 @@ static DECLARE_WAIT_QUEUE_HEAD(vt_activate_queue); /* * Sleeps until a vt is activated, or the task is interrupted. Returns - * 0 if activation, -EINTR if interrupted. + * 0 if activation, -EINTR if interrupted by a signal handler. */ int vt_waitactive(int vt) { @@ -1055,7 +1057,7 @@ int vt_waitactive(int vt) break; } release_console_sem(); - retval = -EINTR; + retval = -ERESTARTNOHAND; if (signal_pending(current)) break; schedule(); diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig index d011a76f8e7..fe9e768cfbc 100644 --- a/drivers/firewire/Kconfig +++ b/drivers/firewire/Kconfig @@ -11,7 +11,8 @@ config FIREWIRE This is the "Juju" FireWire stack, a new alternative implementation designed for robustness and simplicity. You can build either this stack, or the classic stack (the ieee1394 driver, ohci1394 etc.) - or both. + or both. Please read http://wiki.linux1394.org/JujuMigration before + you enable the new stack. To compile this driver as a module, say M here: the module will be called firewire-core. It functionally replaces ieee1394, raw1394, diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index f19eb6daeef..2fb047b898a 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -1546,6 +1546,7 @@ static struct pci_device_id pmac_ide_pci_match[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {}, }; static struct pci_driver pmac_ide_pci_driver = { diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index ec5f4046412..4910bca5264 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -1135,7 +1135,7 @@ isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off) if (count > dev->drv[drvidx]->stavail) count = dev->drv[drvidx]->stavail; len = dev->drv[drvidx]->interface->readstat(buf, count, - drvidx, isdn_minor2chan(minor)); + drvidx, isdn_minor2chan(minor - ISDN_MINOR_CTRL)); if (len < 0) { retval = len; goto out; @@ -1207,7 +1207,8 @@ isdn_write(struct file *file, const char __user *buf, size_t count, loff_t * off */ if (dev->drv[drvidx]->interface->writecmd) retval = dev->drv[drvidx]->interface-> - writecmd(buf, count, drvidx, isdn_minor2chan(minor)); + writecmd(buf, count, drvidx, + isdn_minor2chan(minor - ISDN_MINOR_CTRL)); else retval = count; goto out; diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 0285c4a830e..66ea3cbc369 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -754,9 +754,11 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts) ivtv_yuv_close(itv); } if (s->type == IVTV_DEC_STREAM_TYPE_YUV && itv->output_mode == OUT_YUV) - itv->output_mode = OUT_NONE; + itv->output_mode = OUT_NONE; + else if (s->type == IVTV_DEC_STREAM_TYPE_YUV && itv->output_mode == OUT_UDMA_YUV) + itv->output_mode = OUT_NONE; else if (s->type == IVTV_DEC_STREAM_TYPE_MPG && itv->output_mode == OUT_MPG) - itv->output_mode = OUT_NONE; + itv->output_mode = OUT_NONE; itv->speed = 0; clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags); diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 34288fe038c..315335671f0 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -1357,7 +1357,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev) #endif dev->watchdog_timeo = 2 * HZ; - dev->tx_queue_len = mp->tx_ring_size; dev->base_addr = 0; dev->change_mtu = mv643xx_eth_change_mtu; dev->do_ioctl = mv643xx_eth_do_ioctl; diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 69da95b5ad0..ea151315050 100755 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -2248,6 +2248,13 @@ static int ql_tx_rx_clean(struct ql3_adapter *qdev, qdev->rsp_consumer_index) && (work_done < work_to_do)) { net_rsp = qdev->rsp_current; + rmb(); + /* + * Fix 4032 chipe undocumented "feature" where bit-8 is set if the + * inbound completion is for a VLAN. + */ + if (qdev->device_id == QL3032_DEVICE_ID) + net_rsp->opcode &= 0x7f; switch (net_rsp->opcode) { case OPCODE_OB_MAC_IOCB_FN0: diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index c921ec32c23..c76dd29c8e9 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1918,7 +1918,11 @@ static void rtl_hw_start_8169(struct net_device *dev) rtl_set_rx_max_size(ioaddr); - rtl_set_rx_tx_config_registers(tp); + if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || + (tp->mac_version == RTL_GIGA_MAC_VER_02) || + (tp->mac_version == RTL_GIGA_MAC_VER_03) || + (tp->mac_version == RTL_GIGA_MAC_VER_04)) + rtl_set_rx_tx_config_registers(tp); tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; @@ -1941,6 +1945,14 @@ static void rtl_hw_start_8169(struct net_device *dev) rtl_set_rx_tx_desc_registers(tp, ioaddr); + if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && + (tp->mac_version != RTL_GIGA_MAC_VER_02) && + (tp->mac_version != RTL_GIGA_MAC_VER_03) && + (tp->mac_version != RTL_GIGA_MAC_VER_04)) { + RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); + rtl_set_rx_tx_config_registers(tp); + } + RTL_W8(Cfg9346, Cfg9346_Lock); /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ @@ -1955,8 +1967,6 @@ static void rtl_hw_start_8169(struct net_device *dev) /* Enable all known interrupts by setting the interrupt mask. */ RTL_W16(IntrMask, tp->intr_event); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); } static void rtl_hw_start_8168(struct net_device *dev) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 162489b9f59..ea117fc3d5e 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2163,9 +2163,6 @@ static struct sk_buff *sky2_receive(struct net_device *dev, sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending; prefetch(sky2->rx_ring + sky2->rx_next); - if (length < ETH_ZLEN || length > sky2->rx_data_size) - goto len_error; - /* This chip has hardware problems that generates bogus status. * So do only marginal checking and expect higher level protocols * to handle crap frames. diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 16c7a0e8785..a2de32fabc1 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -405,7 +405,7 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->ethtool_ops = &dm9601_ethtool_ops; dev->net->hard_header_len += DM_TX_OVERHEAD; dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; - dev->rx_urb_size = dev->net->mtu + DM_RX_OVERHEAD; + dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD; dev->mii.dev = dev->net; dev->mii.mdio_read = dm9601_mdio_read; diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index ef35bc6c4a2..4eb6d975288 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -43,7 +43,7 @@ obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o obj-$(CONFIG_USB_ZD1201) += zd1201.o -obj-$(CONFIG_LIBERTAS_USB) += libertas/ +obj-$(CONFIG_LIBERTAS) += libertas/ rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o obj-$(CONFIG_RTL8187) += rtl8187.o diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index d6d9413d7f2..6acfdc49dcc 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -444,7 +444,7 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, u16 maxpower; if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) { - printk(PFX KERN_ERR "TX power not in dBm.\n"); + printk(KERN_ERR PFX "TX power not in dBm.\n"); return -EOPNOTSUPP; } diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c index d5d8caba356..ab13824df85 100644 --- a/drivers/scsi/aic94xx/aic94xx_task.c +++ b/drivers/scsi/aic94xx/aic94xx_task.c @@ -451,7 +451,7 @@ static int asd_build_smp_ascb(struct asd_ascb *ascb, struct sas_task *task, struct scb *scb; pci_map_sg(asd_ha->pcidev, &task->smp_task.smp_req, 1, - PCI_DMA_FROMDEVICE); + PCI_DMA_TODEVICE); pci_map_sg(asd_ha->pcidev, &task->smp_task.smp_resp, 1, PCI_DMA_FROMDEVICE); @@ -486,7 +486,7 @@ static void asd_unbuild_smp_ascb(struct asd_ascb *a) BUG_ON(!task); pci_unmap_sg(a->ha->pcidev, &task->smp_task.smp_req, 1, - PCI_DMA_FROMDEVICE); + PCI_DMA_TODEVICE); pci_unmap_sg(a->ha->pcidev, &task->smp_task.smp_resp, 1, PCI_DMA_FROMDEVICE); } diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 3907f6718ed..da56163c30a 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -1753,6 +1753,14 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len) *len = 0; + if (scsi_sg_count(cmd) == 1 && !adapter->has_64bit_addr) { + sg = scsi_sglist(cmd); + scb->dma_h_bulkdata = sg_dma_address(sg); + *buf = (u32)scb->dma_h_bulkdata; + *len = sg_dma_len(sg); + return 0; + } + scsi_for_each_sg(cmd, sg, sgcnt, idx) { if (adapter->has_64bit_addr) { scb->sgl64[idx].address = sg_dma_address(sg); diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index a0ea4359851..7c8d78fbbbf 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -943,6 +943,7 @@ static struct pcmcia_device_id serial_ids[] = { PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), PCMCIA_MFC_DEVICE_PROD_ID12(2,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), PCMCIA_MFC_DEVICE_PROD_ID12(3,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), + PCMCIA_DEVICE_MANF_CARD(0x0279, 0x950b), /* too generic */ /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */ /* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */ @@ -1562,6 +1562,7 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, fput(file); return -EAGAIN; } + req->ki_filp = file; if (iocb->aio_flags & IOCB_FLAG_RESFD) { /* * If the IOCB_FLAG_RESFD flag of aio_flags is set, get an @@ -1576,7 +1577,6 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, } } - req->ki_filp = file; ret = put_user(req->ki_key, &user_iocb->aio_key); if (unlikely(ret)) { dprintk("EFAULT: aio_key\n"); diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 861141b4f6d..fcb3405bb14 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -742,6 +742,7 @@ static int load_flat_file(struct linux_binprm * bprm, * __start to address 4 so that is okay). */ if (rev > OLD_FLAT_VERSION) { + unsigned long persistent = 0; for (i=0; i < relocs; i++) { unsigned long addr, relval; @@ -749,6 +750,8 @@ static int load_flat_file(struct linux_binprm * bprm, relocated (of course, the address has to be relocated first). */ relval = ntohl(reloc[i]); + if (flat_set_persistent (relval, &persistent)) + continue; addr = flat_get_relocate_addr(relval); rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1); if (rp == (unsigned long *)RELOC_FAILED) { @@ -757,7 +760,8 @@ static int load_flat_file(struct linux_binprm * bprm, } /* Get the pointer's value. */ - addr = flat_get_addr_from_rp(rp, relval, flags); + addr = flat_get_addr_from_rp(rp, relval, flags, + &persistent); if (addr != 0) { /* * Do the relocation. PIC relocs in the data section are diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index d098c7af0d2..d120ec39bcb 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -485,8 +485,10 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file, return nlm_granted; /* Create host handle for callback */ host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len); - if (host == NULL) + if (host == NULL) { + kfree(conf); return nlm_lck_denied_nolocks; + } block = nlmsvc_create_block(rqstp, host, file, lock, cookie); if (block == NULL) { kfree(conf); diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index de984d27257..d272847d5a0 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -514,8 +514,10 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, ac->ac_bh = osb->local_alloc_bh; status = 0; bail: - if (status < 0 && local_alloc_inode) + if (status < 0 && local_alloc_inode) { + mutex_unlock(&local_alloc_inode->i_mutex); iput(local_alloc_inode); + } mlog_exit(status); return status; diff --git a/fs/splice.c b/fs/splice.c index c010a72ca2d..e95a3622886 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -1224,6 +1224,33 @@ static long do_splice(struct file *in, loff_t __user *off_in, } /* + * Do a copy-from-user while holding the mmap_semaphore for reading, in a + * manner safe from deadlocking with simultaneous mmap() (grabbing mmap_sem + * for writing) and page faulting on the user memory pointed to by src. + * This assumes that we will very rarely hit the partial != 0 path, or this + * will not be a win. + */ +static int copy_from_user_mmap_sem(void *dst, const void __user *src, size_t n) +{ + int partial; + + pagefault_disable(); + partial = __copy_from_user_inatomic(dst, src, n); + pagefault_enable(); + + /* + * Didn't copy everything, drop the mmap_sem and do a faulting copy + */ + if (unlikely(partial)) { + up_read(¤t->mm->mmap_sem); + partial = copy_from_user(dst, src, n); + down_read(¤t->mm->mmap_sem); + } + + return partial; +} + +/* * Map an iov into an array of pages and offset/length tupples. With the * partial_page structure, we can map several non-contiguous ranges into * our ones pages[] map instead of splitting that operation into pieces. @@ -1236,31 +1263,26 @@ static int get_iovec_page_array(const struct iovec __user *iov, { int buffers = 0, error = 0; - /* - * It's ok to take the mmap_sem for reading, even - * across a "get_user()". - */ down_read(¤t->mm->mmap_sem); while (nr_vecs) { unsigned long off, npages; + struct iovec entry; void __user *base; size_t len; int i; - /* - * Get user address base and length for this iovec. - */ - error = get_user(base, &iov->iov_base); - if (unlikely(error)) - break; - error = get_user(len, &iov->iov_len); - if (unlikely(error)) + error = -EFAULT; + if (copy_from_user_mmap_sem(&entry, iov, sizeof(entry))) break; + base = entry.iov_base; + len = entry.iov_len; + /* * Sanity check this iovec. 0 read succeeds. */ + error = 0; if (unlikely(!len)) break; error = -EFAULT; diff --git a/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h index e043cafa3c4..69b9f8e120e 100644 --- a/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h +++ b/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h @@ -1,5 +1,6 @@ #include <linux/serial.h> #include <asm/dma.h> +#include <asm/portmux.h> #define NR_PORTS 1 @@ -92,18 +93,24 @@ struct bfin_serial_res bfin_serial_resource[] = { } }; +#define DRIVER_NAME "bfin-uart" int nr_ports = NR_PORTS; static void bfin_serial_hw_init(struct bfin_serial_port *uart) { +#ifdef CONFIG_SERIAL_BFIN_UART0 + peripheral_request(P_UART0_TX, DRIVER_NAME); + peripheral_request(P_UART0_RX, DRIVER_NAME); +#endif + #ifdef CONFIG_SERIAL_BFIN_CTSRTS if (uart->cts_pin >= 0) { - gpio_request(uart->cts_pin, NULL); + gpio_request(uart->cts_pin, DRIVER_NAME); gpio_direction_input(uart->cts_pin); } if (uart->rts_pin >= 0) { - gpio_request(uart->rts_pin, NULL); + gpio_request(uart->rts_pin, DRIVER_NAME); gpio_direction_input(uart->rts_pin); } #endif diff --git a/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h index 8f5d9c4d8d5..6fb328f5186 100644 --- a/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h +++ b/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h @@ -1,5 +1,6 @@ #include <linux/serial.h> #include <asm/dma.h> +#include <asm/portmux.h> #define NR_PORTS 2 @@ -122,25 +123,29 @@ struct bfin_serial_res bfin_serial_resource[] = { int nr_ports = ARRAY_SIZE(bfin_serial_resource); +#define DRIVER_NAME "bfin-uart" + static void bfin_serial_hw_init(struct bfin_serial_port *uart) { - unsigned short val; - val = bfin_read16(BFIN_PORT_MUX); - val &= ~(PFDE | PFTE); - bfin_write16(BFIN_PORT_MUX, val); - val = bfin_read16(PORTF_FER); - val |= 0xF; - bfin_write16(PORTF_FER, val); +#ifdef CONFIG_SERIAL_BFIN_UART0 + peripheral_request(P_UART0_TX, DRIVER_NAME); + peripheral_request(P_UART0_RX, DRIVER_NAME); +#endif + +#ifdef CONFIG_SERIAL_BFIN_UART1 + peripheral_request(P_UART1_TX, DRIVER_NAME); + peripheral_request(P_UART1_RX, DRIVER_NAME); +#endif #ifdef CONFIG_SERIAL_BFIN_CTSRTS if (uart->cts_pin >= 0) { - gpio_request(uart->cts_pin, NULL); + gpio_request(uart->cts_pin, DRIVER_NAME); gpio_direction_input(uart->cts_pin); } if (uart->rts_pin >= 0) { - gpio_request(uart->rts_pin, NULL); + gpio_request(uart->rts_pin, DRIVER_NAME); gpio_direction_output(uart->rts_pin); } #endif diff --git a/include/asm-blackfin/mach-bf537/portmux.h b/include/asm-blackfin/mach-bf537/portmux.h index 23e13c5abc4..ae6c53b2845 100644 --- a/include/asm-blackfin/mach-bf537/portmux.h +++ b/include/asm-blackfin/mach-bf537/portmux.h @@ -106,4 +106,37 @@ #define P_SPI0_SSEL2 (P_DEFINED | P_IDENT(PORT_PJ11) | P_FUNCT(1)) #define P_SPI0_SSEL7 (P_DEFINED | P_IDENT(PORT_PJ5) | P_FUNCT(2)) -#endif /* _MACH_PORTMUX_H_ */ +#define P_MII0 {\ + P_MII0_ETxD0, \ + P_MII0_ETxD1, \ + P_MII0_ETxD2, \ + P_MII0_ETxD3, \ + P_MII0_ETxEN, \ + P_MII0_TxCLK, \ + P_MII0_PHYINT, \ + P_MII0_COL, \ + P_MII0_ERxD0, \ + P_MII0_ERxD1, \ + P_MII0_ERxD2, \ + P_MII0_ERxD3, \ + P_MII0_ERxDV, \ + P_MII0_ERxCLK, \ + P_MII0_ERxER, \ + P_MII0_CRS, \ + P_MDC, \ + P_MDIO, 0} + + +#define P_RMII0 {\ + P_MII0_ETxD0, \ + P_MII0_ETxD1, \ + P_MII0_ETxEN, \ + P_MII0_ERxD0, \ + P_MII0_ERxD1, \ + P_MII0_ERxER, \ + P_RMII0_REF_CLK, \ + P_RMII0_MDINT, \ + P_RMII0_CRS_DV, \ + P_MDC, \ + P_MDIO, 0} +#endif /* _MACH_PORTMUX_H_ */ diff --git a/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h index e043cafa3c4..69b9f8e120e 100644 --- a/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h +++ b/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h @@ -1,5 +1,6 @@ #include <linux/serial.h> #include <asm/dma.h> +#include <asm/portmux.h> #define NR_PORTS 1 @@ -92,18 +93,24 @@ struct bfin_serial_res bfin_serial_resource[] = { } }; +#define DRIVER_NAME "bfin-uart" int nr_ports = NR_PORTS; static void bfin_serial_hw_init(struct bfin_serial_port *uart) { +#ifdef CONFIG_SERIAL_BFIN_UART0 + peripheral_request(P_UART0_TX, DRIVER_NAME); + peripheral_request(P_UART0_RX, DRIVER_NAME); +#endif + #ifdef CONFIG_SERIAL_BFIN_CTSRTS if (uart->cts_pin >= 0) { - gpio_request(uart->cts_pin, NULL); + gpio_request(uart->cts_pin, DRIVER_NAME); gpio_direction_input(uart->cts_pin); } if (uart->rts_pin >= 0) { - gpio_request(uart->rts_pin, NULL); + gpio_request(uart->rts_pin, DRIVER_NAME); gpio_direction_input(uart->rts_pin); } #endif diff --git a/include/asm-blackfin/portmux.h b/include/asm-blackfin/portmux.h index 9d3681e4211..0d3f650d2d9 100644 --- a/include/asm-blackfin/portmux.h +++ b/include/asm-blackfin/portmux.h @@ -14,6 +14,12 @@ #define P_MAYSHARE 0x2000 #define P_DONTCARE 0x1000 + +int peripheral_request(unsigned short per, const char *label); +void peripheral_free(unsigned short per); +int peripheral_request_list(unsigned short per[], const char *label); +void peripheral_free_list(unsigned short per[]); + #include <asm/gpio.h> #include <asm/mach/portmux.h> @@ -145,6 +151,22 @@ #define P_SPI2_SSEL3 P_UNDEF #endif +#ifndef P_SPI2_SSEL4 +#define P_SPI2_SSEL4 P_UNDEF +#endif + +#ifndef P_SPI2_SSEL5 +#define P_SPI2_SSEL5 P_UNDEF +#endif + +#ifndef P_SPI2_SSEL6 +#define P_SPI2_SSEL6 P_UNDEF +#endif + +#ifndef P_SPI2_SSEL7 +#define P_SPI2_SSEL7 P_UNDEF +#endif + #ifndef P_SPI2_SCK #define P_SPI2_SCK P_UNDEF #endif @@ -513,6 +535,22 @@ #define P_SPI0_SSEL3 P_UNDEF #endif +#ifndef P_SPI0_SSEL4 +#define P_SPI0_SSEL4 P_UNDEF +#endif + +#ifndef P_SPI0_SSEL5 +#define P_SPI0_SSEL5 P_UNDEF +#endif + +#ifndef P_SPI0_SSEL6 +#define P_SPI0_SSEL6 P_UNDEF +#endif + +#ifndef P_SPI0_SSEL7 +#define P_SPI0_SSEL7 P_UNDEF +#endif + #ifndef P_UART0_TX #define P_UART0_TX P_UNDEF #endif @@ -741,6 +779,23 @@ #define P_SPI1_SSEL3 P_UNDEF #endif + +#ifndef P_SPI1_SSEL4 +#define P_SPI1_SSEL4 P_UNDEF +#endif + +#ifndef P_SPI1_SSEL5 +#define P_SPI1_SSEL5 P_UNDEF +#endif + +#ifndef P_SPI1_SSEL6 +#define P_SPI1_SSEL6 P_UNDEF +#endif + +#ifndef P_SPI1_SSEL7 +#define P_SPI1_SSEL7 P_UNDEF +#endif + #ifndef P_SPI1_SCK #define P_SPI1_SCK P_UNDEF #endif diff --git a/include/asm-blackfin/unistd.h b/include/asm-blackfin/unistd.h index 0df9f2d322a..07ffe8b718c 100644 --- a/include/asm-blackfin/unistd.h +++ b/include/asm-blackfin/unistd.h @@ -3,6 +3,7 @@ /* * This file contains the system call numbers. */ +#define __NR_restart_syscall 0 #define __NR_exit 1 #define __NR_fork 2 #define __NR_read 3 @@ -165,13 +166,13 @@ #define __NR_sched_get_priority_min 160 #define __NR_sched_rr_get_interval 161 #define __NR_nanosleep 162 - /* 163 __NR_mremap */ +#define __NR_mremap 163 #define __NR_setresuid 164 #define __NR_getresuid 165 /* 166 __NR_vm86 */ /* 167 __NR_query_module */ /* 168 __NR_poll */ - /* 169 __NR_nfsservctl */ +#define __NR_nfsservctl 169 #define __NR_setresgid 170 #define __NR_getresgid 171 #define __NR_prctl 172 @@ -227,7 +228,7 @@ /* 222 reserved for TUX */ /* 223 reserved for TUX */ #define __NR_gettid 224 - /* 225 __NR_readahead */ +#define __NR_readahead 225 #define __NR_setxattr 226 #define __NR_lsetxattr 227 #define __NR_fsetxattr 228 @@ -287,7 +288,7 @@ #define __NR_mq_timedreceive (__NR_mq_open+3) #define __NR_mq_notify (__NR_mq_open+4) #define __NR_mq_getsetattr (__NR_mq_open+5) - /* 284 __NR_sys_kexec_load */ +#define __NR_kexec_load 284 #define __NR_waitid 285 #define __NR_add_key 286 #define __NR_request_key 287 @@ -352,9 +353,54 @@ #define __NR_shmdt 340 #define __NR_shmget 341 -#define __NR_syscall 342 +#define __NR_splice 342 +#define __NR_sync_file_range 343 +#define __NR_tee 344 +#define __NR_vmsplice 345 + +#define __NR_epoll_pwait 346 +#define __NR_utimensat 347 +#define __NR_signalfd 348 +#define __NR_timerfd 349 +#define __NR_eventfd 350 +#define __NR_pread64 351 +#define __NR_pwrite64 352 +#define __NR_fadvise64 353 +#define __NR_set_robust_list 354 +#define __NR_get_robust_list 355 +#define __NR_fallocate 356 + +#define __NR_syscall 357 #define NR_syscalls __NR_syscall +/* Old optional stuff no one actually uses */ +#define __IGNORE_sysfs +#define __IGNORE_uselib + +/* Implement the newer interfaces */ +#define __IGNORE_mmap +#define __IGNORE_poll +#define __IGNORE_select +#define __IGNORE_utime + +/* Not relevant on no-mmu */ +#define __IGNORE_swapon +#define __IGNORE_swapoff +#define __IGNORE_msync +#define __IGNORE_mlock +#define __IGNORE_munlock +#define __IGNORE_mlockall +#define __IGNORE_munlockall +#define __IGNORE_mincore +#define __IGNORE_madvise +#define __IGNORE_remap_file_pages +#define __IGNORE_mbind +#define __IGNORE_get_mempolicy +#define __IGNORE_set_mempolicy +#define __IGNORE_migrate_pages +#define __IGNORE_move_pages +#define __IGNORE_getcpu + #ifdef __KERNEL__ #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_STAT64 diff --git a/include/asm-h8300/flat.h b/include/asm-h8300/flat.h index c20eee767d6..2a873508a9a 100644 --- a/include/asm-h8300/flat.h +++ b/include/asm-h8300/flat.h @@ -9,6 +9,7 @@ #define flat_argvp_envp_on_stack() 1 #define flat_old_ram_flag(flags) 1 #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) +#define flat_set_persistent(relval, p) 0 /* * on the H8 a couple of the relocations have an instruction in the @@ -18,7 +19,7 @@ */ #define flat_get_relocate_addr(rel) (rel) -#define flat_get_addr_from_rp(rp, relval, flags) \ +#define flat_get_addr_from_rp(rp, relval, flags, persistent) \ (get_unaligned(rp) & ((flags & FLAT_FLAG_GOTPIC) ? 0xffffffff: 0x00ffffff)) #define flat_put_addr_at_rp(rp, addr, rel) \ put_unaligned (((*(char *)(rp)) << 24) | ((addr) & 0x00ffffff), rp) diff --git a/include/asm-m32r/flat.h b/include/asm-m32r/flat.h index 1b285f65cab..d851cf0c4aa 100644 --- a/include/asm-m32r/flat.h +++ b/include/asm-m32r/flat.h @@ -15,9 +15,10 @@ #define flat_stack_align(sp) (*sp += (*sp & 3 ? (4 - (*sp & 3)): 0)) #define flat_argvp_envp_on_stack() 0 #define flat_old_ram_flag(flags) (flags) +#define flat_set_persistent(relval, p) 0 #define flat_reloc_valid(reloc, size) \ (((reloc) - textlen_for_m32r_lo16_data) <= (size)) -#define flat_get_addr_from_rp(rp, relval, flags) \ +#define flat_get_addr_from_rp(rp, relval, flags, persistent) \ m32r_flat_get_addr_from_rp(rp, relval, (text_len) ) #define flat_put_addr_at_rp(rp, addr, relval) \ diff --git a/include/asm-m68knommu/flat.h b/include/asm-m68knommu/flat.h index 2d836edc434..814b5174a8e 100644 --- a/include/asm-m68knommu/flat.h +++ b/include/asm-m68knommu/flat.h @@ -9,8 +9,9 @@ #define flat_argvp_envp_on_stack() 1 #define flat_old_ram_flag(flags) (flags) #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) -#define flat_get_addr_from_rp(rp, relval, flags) get_unaligned(rp) +#define flat_get_addr_from_rp(rp, relval, flags, p) get_unaligned(rp) #define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp) #define flat_get_relocate_addr(rel) (rel) +#define flat_set_persistent(relval, p) 0 #endif /* __M68KNOMMU_FLAT_H__ */ diff --git a/include/asm-mips/cmpxchg.h b/include/asm-mips/cmpxchg.h new file mode 100644 index 00000000000..c5b4708e003 --- /dev/null +++ b/include/asm-mips/cmpxchg.h @@ -0,0 +1,107 @@ +/* + * 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) 2003, 06, 07 by Ralf Baechle (ralf@linux-mips.org) + */ +#ifndef __ASM_CMPXCHG_H +#define __ASM_CMPXCHG_H + +#include <linux/irqflags.h> + +#define __HAVE_ARCH_CMPXCHG 1 + +#define __cmpxchg_asm(ld, st, m, old, new) \ +({ \ + __typeof(*(m)) __ret; \ + \ + if (cpu_has_llsc && R10000_LLSC_WAR) { \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " .set mips3 \n" \ + "1: " ld " %0, %2 # __cmpxchg_asm \n" \ + " bne %0, %z3, 2f \n" \ + " .set mips0 \n" \ + " move $1, %z4 \n" \ + " .set mips3 \n" \ + " " st " $1, %1 \n" \ + " beqzl $1, 1b \n" \ + "2: \n" \ + " .set pop \n" \ + : "=&r" (__ret), "=R" (*m) \ + : "R" (*m), "Jr" (old), "Jr" (new) \ + : "memory"); \ + } else if (cpu_has_llsc) { \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " .set mips3 \n" \ + "1: " ld " %0, %2 # __cmpxchg_asm \n" \ + " bne %0, %z3, 2f \n" \ + " .set mips0 \n" \ + " move $1, %z4 \n" \ + " .set mips3 \n" \ + " " st " $1, %1 \n" \ + " beqz $1, 3f \n" \ + "2: \n" \ + " .subsection 2 \n" \ + "3: b 1b \n" \ + " .previous \n" \ + " .set pop \n" \ + : "=&r" (__ret), "=R" (*m) \ + : "R" (*m), "Jr" (old), "Jr" (new) \ + : "memory"); \ + } else { \ + unsigned long __flags; \ + \ + raw_local_irq_save(__flags); \ + __ret = *m; \ + if (__ret == old) \ + *m = new; \ + raw_local_irq_restore(__flags); \ + } \ + \ + __ret; \ +}) + +/* + * This function doesn't exist, so you'll get a linker error + * if something tries to do an invalid cmpxchg(). + */ +extern void __cmpxchg_called_with_bad_pointer(void); + +#define __cmpxchg(ptr,old,new,barrier) \ +({ \ + __typeof__(ptr) __ptr = (ptr); \ + __typeof__(*(ptr)) __old = (old); \ + __typeof__(*(ptr)) __new = (new); \ + __typeof__(*(ptr)) __res = 0; \ + \ + barrier; \ + \ + switch (sizeof(*(__ptr))) { \ + case 4: \ + __res = __cmpxchg_asm("ll", "sc", __ptr, __old, __new); \ + break; \ + case 8: \ + if (sizeof(long) == 8) { \ + __res = __cmpxchg_asm("lld", "scd", __ptr, \ + __old, __new); \ + break; \ + } \ + default: \ + __cmpxchg_called_with_bad_pointer(); \ + break; \ + } \ + \ + barrier; \ + \ + __res; \ +}) + +#define cmpxchg(ptr, old, new) __cmpxchg(ptr, old, new, smp_llsc_mb()) +#define cmpxchg_local(ptr, old, new) __cmpxchg(ptr, old, new,) + +#endif /* __ASM_CMPXCHG_H */ diff --git a/include/asm-mips/fcntl.h b/include/asm-mips/fcntl.h index 00a50ec1c19..2a52333a062 100644 --- a/include/asm-mips/fcntl.h +++ b/include/asm-mips/fcntl.h @@ -13,6 +13,7 @@ #define O_SYNC 0x0010 #define O_NONBLOCK 0x0080 #define O_CREAT 0x0100 /* not fcntl */ +#define O_TRUNC 0x0200 /* not fcntl */ #define O_EXCL 0x0400 /* not fcntl */ #define O_NOCTTY 0x0800 /* not fcntl */ #define FASYNC 0x1000 /* fcntl, for BSD compatibility */ diff --git a/include/asm-mips/local.h b/include/asm-mips/local.h index ed882c88e0c..f9a5ce5c9af 100644 --- a/include/asm-mips/local.h +++ b/include/asm-mips/local.h @@ -4,6 +4,7 @@ #include <linux/percpu.h> #include <linux/bitops.h> #include <asm/atomic.h> +#include <asm/cmpxchg.h> #include <asm/war.h> typedef struct @@ -114,68 +115,6 @@ static __inline__ long local_sub_return(long i, local_t * l) return result; } -/* - * local_sub_if_positive - conditionally subtract integer from atomic variable - * @i: integer value to subtract - * @l: pointer of type local_t - * - * Atomically test @l and subtract @i if @l is greater or equal than @i. - * The function returns the old value of @l minus @i. - */ -static __inline__ long local_sub_if_positive(long i, local_t * l) -{ - unsigned long result; - - if (cpu_has_llsc && R10000_LLSC_WAR) { - unsigned long temp; - - __asm__ __volatile__( - " .set mips3 \n" - "1:" __LL "%1, %2 # local_sub_if_positive\n" - " dsubu %0, %1, %3 \n" - " bltz %0, 1f \n" - __SC "%0, %2 \n" - " .set noreorder \n" - " beqzl %0, 1b \n" - " dsubu %0, %1, %3 \n" - " .set reorder \n" - "1: \n" - " .set mips0 \n" - : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) - : "Ir" (i), "m" (l->a.counter) - : "memory"); - } else if (cpu_has_llsc) { - unsigned long temp; - - __asm__ __volatile__( - " .set mips3 \n" - "1:" __LL "%1, %2 # local_sub_if_positive\n" - " dsubu %0, %1, %3 \n" - " bltz %0, 1f \n" - __SC "%0, %2 \n" - " .set noreorder \n" - " beqz %0, 1b \n" - " dsubu %0, %1, %3 \n" - " .set reorder \n" - "1: \n" - " .set mips0 \n" - : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) - : "Ir" (i), "m" (l->a.counter) - : "memory"); - } else { - unsigned long flags; - - local_irq_save(flags); - result = l->a.counter; - result -= i; - if (result >= 0) - l->a.counter = result; - local_irq_restore(flags); - } - - return result; -} - #define local_cmpxchg(l, o, n) \ ((long)cmpxchg_local(&((l)->a.counter), (o), (n))) #define local_xchg(l, n) (xchg_local(&((l)->a.counter),(n))) @@ -234,12 +173,6 @@ static __inline__ long local_sub_if_positive(long i, local_t * l) #define local_dec_and_test(l) (local_sub_return(1, (l)) == 0) /* - * local_dec_if_positive - decrement by 1 if old value positive - * @l: pointer of type local_t - */ -#define local_dec_if_positive(l) local_sub_if_positive(1, l) - -/* * local_add_negative - add and test if negative * @l: pointer of type local_t * @i: integer value to add diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h index 357251f4251..480b574e248 100644 --- a/include/asm-mips/system.h +++ b/include/asm-mips/system.h @@ -17,6 +17,7 @@ #include <asm/addrspace.h> #include <asm/barrier.h> +#include <asm/cmpxchg.h> #include <asm/cpu-features.h> #include <asm/dsp.h> #include <asm/war.h> @@ -194,266 +195,6 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) -#define __HAVE_ARCH_CMPXCHG 1 - -static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old, - unsigned long new) -{ - __u32 retval; - - if (cpu_has_llsc && R10000_LLSC_WAR) { - __asm__ __volatile__( - " .set push \n" - " .set noat \n" - " .set mips3 \n" - "1: ll %0, %2 # __cmpxchg_u32 \n" - " bne %0, %z3, 2f \n" - " .set mips0 \n" - " move $1, %z4 \n" - " .set mips3 \n" - " sc $1, %1 \n" - " beqzl $1, 1b \n" - "2: \n" - " .set pop \n" - : "=&r" (retval), "=R" (*m) - : "R" (*m), "Jr" (old), "Jr" (new) - : "memory"); - } else if (cpu_has_llsc) { - __asm__ __volatile__( - " .set push \n" - " .set noat \n" - " .set mips3 \n" - "1: ll %0, %2 # __cmpxchg_u32 \n" - " bne %0, %z3, 2f \n" - " .set mips0 \n" - " move $1, %z4 \n" - " .set mips3 \n" - " sc $1, %1 \n" - " beqz $1, 3f \n" - "2: \n" - " .subsection 2 \n" - "3: b 1b \n" - " .previous \n" - " .set pop \n" - : "=&r" (retval), "=R" (*m) - : "R" (*m), "Jr" (old), "Jr" (new) - : "memory"); - } else { - unsigned long flags; - - raw_local_irq_save(flags); - retval = *m; - if (retval == old) - *m = new; - raw_local_irq_restore(flags); /* implies memory barrier */ - } - - smp_llsc_mb(); - - return retval; -} - -static inline unsigned long __cmpxchg_u32_local(volatile int * m, - unsigned long old, unsigned long new) -{ - __u32 retval; - - if (cpu_has_llsc && R10000_LLSC_WAR) { - __asm__ __volatile__( - " .set push \n" - " .set noat \n" - " .set mips3 \n" - "1: ll %0, %2 # __cmpxchg_u32 \n" - " bne %0, %z3, 2f \n" - " .set mips0 \n" - " move $1, %z4 \n" - " .set mips3 \n" - " sc $1, %1 \n" - " beqzl $1, 1b \n" - "2: \n" - " .set pop \n" - : "=&r" (retval), "=R" (*m) - : "R" (*m), "Jr" (old), "Jr" (new) - : "memory"); - } else if (cpu_has_llsc) { - __asm__ __volatile__( - " .set push \n" - " .set noat \n" - " .set mips3 \n" - "1: ll %0, %2 # __cmpxchg_u32 \n" - " bne %0, %z3, 2f \n" - " .set mips0 \n" - " move $1, %z4 \n" - " .set mips3 \n" - " sc $1, %1 \n" - " beqz $1, 1b \n" - "2: \n" - " .set pop \n" - : "=&r" (retval), "=R" (*m) - : "R" (*m), "Jr" (old), "Jr" (new) - : "memory"); - } else { - unsigned long flags; - - local_irq_save(flags); - retval = *m; - if (retval == old) - *m = new; - local_irq_restore(flags); /* implies memory barrier */ - } - - return retval; -} - -#ifdef CONFIG_64BIT -static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old, - unsigned long new) -{ - __u64 retval; - - if (cpu_has_llsc && R10000_LLSC_WAR) { - __asm__ __volatile__( - " .set push \n" - " .set noat \n" - " .set mips3 \n" - "1: lld %0, %2 # __cmpxchg_u64 \n" - " bne %0, %z3, 2f \n" - " move $1, %z4 \n" - " scd $1, %1 \n" - " beqzl $1, 1b \n" - "2: \n" - " .set pop \n" - : "=&r" (retval), "=R" (*m) - : "R" (*m), "Jr" (old), "Jr" (new) - : "memory"); - } else if (cpu_has_llsc) { - __asm__ __volatile__( - " .set push \n" - " .set noat \n" - " .set mips3 \n" - "1: lld %0, %2 # __cmpxchg_u64 \n" - " bne %0, %z3, 2f \n" - " move $1, %z4 \n" - " scd $1, %1 \n" - " beqz $1, 3f \n" - "2: \n" - " .subsection 2 \n" - "3: b 1b \n" - " .previous \n" - " .set pop \n" - : "=&r" (retval), "=R" (*m) - : "R" (*m), "Jr" (old), "Jr" (new) - : "memory"); - } else { - unsigned long flags; - - raw_local_irq_save(flags); - retval = *m; - if (retval == old) - *m = new; - raw_local_irq_restore(flags); /* implies memory barrier */ - } - - smp_llsc_mb(); - - return retval; -} - -static inline unsigned long __cmpxchg_u64_local(volatile int * m, - unsigned long old, unsigned long new) -{ - __u64 retval; - - if (cpu_has_llsc && R10000_LLSC_WAR) { - __asm__ __volatile__( - " .set push \n" - " .set noat \n" - " .set mips3 \n" - "1: lld %0, %2 # __cmpxchg_u64 \n" - " bne %0, %z3, 2f \n" - " move $1, %z4 \n" - " scd $1, %1 \n" - " beqzl $1, 1b \n" - "2: \n" - " .set pop \n" - : "=&r" (retval), "=R" (*m) - : "R" (*m), "Jr" (old), "Jr" (new) - : "memory"); - } else if (cpu_has_llsc) { - __asm__ __volatile__( - " .set push \n" - " .set noat \n" - " .set mips3 \n" - "1: lld %0, %2 # __cmpxchg_u64 \n" - " bne %0, %z3, 2f \n" - " move $1, %z4 \n" - " scd $1, %1 \n" - " beqz $1, 1b \n" - "2: \n" - " .set pop \n" - : "=&r" (retval), "=R" (*m) - : "R" (*m), "Jr" (old), "Jr" (new) - : "memory"); - } else { - unsigned long flags; - - local_irq_save(flags); - retval = *m; - if (retval == old) - *m = new; - local_irq_restore(flags); /* implies memory barrier */ - } - - return retval; -} - -#else -extern unsigned long __cmpxchg_u64_unsupported_on_32bit_kernels( - volatile int * m, unsigned long old, unsigned long new); -#define __cmpxchg_u64 __cmpxchg_u64_unsupported_on_32bit_kernels -extern unsigned long __cmpxchg_u64_local_unsupported_on_32bit_kernels( - volatile int * m, unsigned long old, unsigned long new); -#define __cmpxchg_u64_local __cmpxchg_u64_local_unsupported_on_32bit_kernels -#endif - -/* This function doesn't exist, so you'll get a linker error - if something tries to do an invalid cmpxchg(). */ -extern void __cmpxchg_called_with_bad_pointer(void); - -static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old, - unsigned long new, int size) -{ - switch (size) { - case 4: - return __cmpxchg_u32(ptr, old, new); - case 8: - return __cmpxchg_u64(ptr, old, new); - } - __cmpxchg_called_with_bad_pointer(); - return old; -} - -static inline unsigned long __cmpxchg_local(volatile void * ptr, - unsigned long old, unsigned long new, int size) -{ - switch (size) { - case 4: - return __cmpxchg_u32_local(ptr, old, new); - case 8: - return __cmpxchg_u64_local(ptr, old, new); - } - __cmpxchg_called_with_bad_pointer(); - return old; -} - -#define cmpxchg(ptr,old,new) \ - ((__typeof__(*(ptr)))__cmpxchg((ptr), \ - (unsigned long)(old), (unsigned long)(new),sizeof(*(ptr)))) - -#define cmpxchg_local(ptr,old,new) \ - ((__typeof__(*(ptr)))__cmpxchg_local((ptr), \ - (unsigned long)(old), (unsigned long)(new),sizeof(*(ptr)))) - extern void set_handler (unsigned long offset, void *addr, unsigned long len); extern void set_uncached_handler (unsigned long offset, void *addr, unsigned long len); diff --git a/include/asm-sh/flat.h b/include/asm-sh/flat.h index 0d5cc04ab00..dc4f5950daf 100644 --- a/include/asm-sh/flat.h +++ b/include/asm-sh/flat.h @@ -16,8 +16,9 @@ #define flat_argvp_envp_on_stack() 0 #define flat_old_ram_flag(flags) (flags) #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) -#define flat_get_addr_from_rp(rp, relval, flags) get_unaligned(rp) +#define flat_get_addr_from_rp(rp, relval, flags, p) get_unaligned(rp) #define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp) #define flat_get_relocate_addr(rel) (rel) +#define flat_set_persistent(relval, p) 0 #endif /* __ASM_SH_FLAT_H */ diff --git a/include/asm-v850/flat.h b/include/asm-v850/flat.h index 3888f59d688..17f0ea56661 100644 --- a/include/asm-v850/flat.h +++ b/include/asm-v850/flat.h @@ -25,6 +25,7 @@ #define flat_stack_align(sp) /* nothing needed */ #define flat_argvp_envp_on_stack() 0 #define flat_old_ram_flag(flags) (flags) +#define flat_set_persistent(relval, p) 0 /* We store the type of relocation in the top 4 bits of the `relval.' */ @@ -46,7 +47,8 @@ flat_get_relocate_addr (unsigned long relval) For the v850, RP should always be half-word aligned. */ static inline unsigned long flat_get_addr_from_rp (unsigned long *rp, unsigned long relval, - unsigned long flags) + unsigned long flags, + unsigned long *persistent) { short *srp = (short *)rp; diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h index 19525175b91..31f579b828f 100644 --- a/include/asm-x86_64/processor.h +++ b/include/asm-x86_64/processor.h @@ -371,7 +371,7 @@ static inline void sync_core(void) #define ARCH_HAS_PREFETCH static inline void prefetch(void *x) { - asm volatile("prefetcht0 %0" :: "m" (*(unsigned long *)x)); + asm volatile("prefetcht0 (%0)" :: "r" (x)); } #define ARCH_HAS_PREFETCHW 1 diff --git a/include/linux/sched.h b/include/linux/sched.h index a01ac6dd5f5..313c6b6e774 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -113,7 +113,7 @@ extern unsigned long avenrun[]; /* Load averages */ #define FSHIFT 11 /* nr of bits of precision */ #define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */ -#define LOAD_FREQ (5*HZ) /* 5 sec intervals */ +#define LOAD_FREQ (5*HZ+1) /* 5 sec intervals */ #define EXP_1 1884 /* 1/exp(5sec/1min) as fixed-point */ #define EXP_5 2014 /* 1/exp(5sec/5min) */ #define EXP_15 2037 /* 1/exp(5sec/15min) */ diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 4ef4d22e5e4..b4af6bcb7b7 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -127,7 +127,7 @@ int sync_page_range(struct inode *inode, struct address_space *mapping, loff_t pos, loff_t count); int sync_page_range_nolock(struct inode *inode, struct address_space *mapping, loff_t pos, loff_t count); -void set_page_dirty_balance(struct page *page); +void set_page_dirty_balance(struct page *page, int page_mkwrite); void writeback_set_ratelimit(void); /* pdflush.c */ diff --git a/include/net/rose.h b/include/net/rose.h index a4047d3cf5d..e5bb084d875 100644 --- a/include/net/rose.h +++ b/include/net/rose.h @@ -188,7 +188,7 @@ extern void rose_kick(struct sock *); extern void rose_enquiry_response(struct sock *); /* rose_route.c */ -extern struct rose_neigh rose_loopback_neigh; +extern struct rose_neigh *rose_loopback_neigh; extern const struct file_operations rose_neigh_fops; extern const struct file_operations rose_nodes_fops; extern const struct file_operations rose_routes_fops; diff --git a/kernel/futex.c b/kernel/futex.c index e8935b195e8..fcc94e7b408 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -1943,9 +1943,10 @@ static inline int fetch_robust_entry(struct robust_list __user **entry, void exit_robust_list(struct task_struct *curr) { struct robust_list_head __user *head = curr->robust_list; - struct robust_list __user *entry, *pending; - unsigned int limit = ROBUST_LIST_LIMIT, pi, pip; + struct robust_list __user *entry, *next_entry, *pending; + unsigned int limit = ROBUST_LIST_LIMIT, pi, next_pi, pip; unsigned long futex_offset; + int rc; /* * Fetch the list head (which was registered earlier, via @@ -1965,12 +1966,14 @@ void exit_robust_list(struct task_struct *curr) if (fetch_robust_entry(&pending, &head->list_op_pending, &pip)) return; - if (pending) - handle_futex_death((void __user *)pending + futex_offset, - curr, pip); - + next_entry = NULL; /* avoid warning with gcc */ while (entry != &head->list) { /* + * Fetch the next entry in the list before calling + * handle_futex_death: + */ + rc = fetch_robust_entry(&next_entry, &entry->next, &next_pi); + /* * A pending lock might already be on the list, so * don't process it twice: */ @@ -1978,11 +1981,10 @@ void exit_robust_list(struct task_struct *curr) if (handle_futex_death((void __user *)entry + futex_offset, curr, pi)) return; - /* - * Fetch the next entry in the list: - */ - if (fetch_robust_entry(&entry, &entry->next, &pi)) + if (rc) return; + entry = next_entry; + pi = next_pi; /* * Avoid excessively long or circular lists: */ @@ -1991,6 +1993,10 @@ void exit_robust_list(struct task_struct *curr) cond_resched(); } + + if (pending) + handle_futex_death((void __user *)pending + futex_offset, + curr, pip); } long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c index 7e52eb051f2..2c2e2954b71 100644 --- a/kernel/futex_compat.c +++ b/kernel/futex_compat.c @@ -38,10 +38,11 @@ fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **entry, void compat_exit_robust_list(struct task_struct *curr) { struct compat_robust_list_head __user *head = curr->compat_robust_list; - struct robust_list __user *entry, *pending; - unsigned int limit = ROBUST_LIST_LIMIT, pi, pip; - compat_uptr_t uentry, upending; + struct robust_list __user *entry, *next_entry, *pending; + unsigned int limit = ROBUST_LIST_LIMIT, pi, next_pi, pip; + compat_uptr_t uentry, next_uentry, upending; compat_long_t futex_offset; + int rc; /* * Fetch the list head (which was registered earlier, via @@ -61,11 +62,16 @@ void compat_exit_robust_list(struct task_struct *curr) if (fetch_robust_entry(&upending, &pending, &head->list_op_pending, &pip)) return; - if (pending) - handle_futex_death((void __user *)pending + futex_offset, curr, pip); + next_entry = NULL; /* avoid warning with gcc */ while (entry != (struct robust_list __user *) &head->list) { /* + * Fetch the next entry in the list before calling + * handle_futex_death: + */ + rc = fetch_robust_entry(&next_uentry, &next_entry, + (compat_uptr_t __user *)&entry->next, &next_pi); + /* * A pending lock might already be on the list, so * dont process it twice: */ @@ -74,12 +80,11 @@ void compat_exit_robust_list(struct task_struct *curr) curr, pi)) return; - /* - * Fetch the next entry in the list: - */ - if (fetch_robust_entry(&uentry, &entry, - (compat_uptr_t __user *)&entry->next, &pi)) + if (rc) return; + uentry = next_uentry; + entry = next_entry; + pi = next_pi; /* * Avoid excessively long or circular lists: */ @@ -88,6 +93,9 @@ void compat_exit_robust_list(struct task_struct *curr) cond_resched(); } + if (pending) + handle_futex_death((void __user *)pending + futex_offset, + curr, pip); } asmlinkage long diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index c9fbe8e73a4..67c67a87146 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -639,6 +639,16 @@ static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se) se->block_start = 0; se->sum_sleep_runtime += delta; + + /* + * Blocking time is in units of nanosecs, so shift by 20 to + * get a milliseconds-range estimation of the amount of + * time that the task spent sleeping: + */ + if (unlikely(prof_on == SLEEP_PROFILING)) { + profile_hits(SLEEP_PROFILING, (void *)get_wchan(tsk), + delta >> 20); + } } #endif } diff --git a/kernel/signal.c b/kernel/signal.c index 9fb91a32edd..79295238109 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -531,18 +531,18 @@ static int check_kill_permission(int sig, struct siginfo *info, if (!valid_signal(sig)) return error; - error = audit_signal_info(sig, t); /* Let audit system see the signal */ - if (error) - return error; - - error = -EPERM; - if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) - && ((sig != SIGCONT) || - (process_session(current) != process_session(t))) - && (current->euid ^ t->suid) && (current->euid ^ t->uid) - && (current->uid ^ t->suid) && (current->uid ^ t->uid) - && !capable(CAP_KILL)) + if (info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) { + error = audit_signal_info(sig, t); /* Let audit system see the signal */ + if (error) + return error; + error = -EPERM; + if (((sig != SIGCONT) || + (process_session(current) != process_session(t))) + && (current->euid ^ t->suid) && (current->euid ^ t->uid) + && (current->uid ^ t->suid) && (current->uid ^ t->uid) + && !capable(CAP_KILL)) return error; + } return security_task_kill(t, info, sig, 0); } diff --git a/kernel/sys.c b/kernel/sys.c index 1b33b05d346..8ae2e636eb1 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -32,6 +32,7 @@ #include <linux/getcpu.h> #include <linux/task_io_accounting_ops.h> #include <linux/seccomp.h> +#include <linux/cpu.h> #include <linux/compat.h> #include <linux/syscalls.h> @@ -878,6 +879,7 @@ void kernel_power_off(void) kernel_shutdown_prepare(SYSTEM_POWER_OFF); if (pm_power_off_prepare) pm_power_off_prepare(); + disable_nonboot_cpus(); sysdev_shutdown(); printk(KERN_EMERG "Power down.\n"); machine_power_off(); diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c index 3c38fb5eae1..c36bb7ed030 100644 --- a/kernel/time/timer_stats.c +++ b/kernel/time/timer_stats.c @@ -327,8 +327,9 @@ static int tstats_show(struct seq_file *m, void *v) ms = 1; if (events && period.tv_sec) - seq_printf(m, "%ld total events, %ld.%ld events/sec\n", events, - events / period.tv_sec, events * 1000 / ms); + seq_printf(m, "%ld total events, %ld.%03ld events/sec\n", + events, events * 1000 / ms, + (events * 1000000 / ms) % 1000); else seq_printf(m, "%ld total events\n", events); diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 495863a500c..cdc9b099e62 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -294,6 +294,8 @@ config LOCK_STAT help This feature enables tracking lock contention points + For more details, see Documentation/lockstat.txt + config DEBUG_LOCKDEP bool "Lock dependency engine debugging" depends on DEBUG_KERNEL && LOCKDEP diff --git a/lib/Makefile b/lib/Makefile index 6b0ba8cf4e5..4f3f3e25650 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -2,7 +2,7 @@ # Makefile for some libs needed in the kernel. # -lib-y := ctype.o string.o vsprintf.o kasprintf.o cmdline.o \ +lib-y := ctype.o string.o vsprintf.o cmdline.o \ rbtree.o radix-tree.o dump_stack.o \ idr.o int_sqrt.o bitmap.o extable.o prio_tree.o \ sha1.o irq_regs.o reciprocal_div.o argv_split.o @@ -13,7 +13,7 @@ lib-$(CONFIG_SMP) += cpumask.o lib-y += kobject.o kref.o kobject_uevent.o klist.o obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ - bust_spinlocks.o hexdump.o + bust_spinlocks.o hexdump.o kasprintf.o ifeq ($(CONFIG_DEBUG_KOBJECT),y) CFLAGS_kobject.o += -DDEBUG diff --git a/mm/Kconfig b/mm/Kconfig index e24d348083c..a7609cbcb00 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -137,6 +137,7 @@ config SPLIT_PTLOCK_CPUS int default "4096" if ARM && !CPU_CACHE_VIPT default "4096" if PARISC && !PA20 + default "4096" if XEN default "4" # diff --git a/mm/filemap.c b/mm/filemap.c index 90b657b50f8..15c8413ee92 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1388,6 +1388,7 @@ retry_find: size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; if (unlikely(vmf->pgoff >= size)) { unlock_page(page); + page_cache_release(page); goto outside_data_content; } diff --git a/mm/fremap.c b/mm/fremap.c index c395b1abf08..95bcb5641c7 100644 --- a/mm/fremap.c +++ b/mm/fremap.c @@ -160,7 +160,7 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, if (vma->vm_private_data && !(vma->vm_flags & VM_NONLINEAR)) goto out; - if (!vma->vm_flags & VM_CAN_NONLINEAR) + if (!(vma->vm_flags & VM_CAN_NONLINEAR)) goto out; if (end <= start || start < vma->vm_start || end > vma->vm_end) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 84c795ee2d6..eab8c428cc9 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -42,7 +42,7 @@ static void clear_huge_page(struct page *page, unsigned long addr) might_sleep(); for (i = 0; i < (HPAGE_SIZE/PAGE_SIZE); i++) { cond_resched(); - clear_user_highpage(page + i, addr); + clear_user_highpage(page + i, addr + i * PAGE_SIZE); } } diff --git a/mm/memory.c b/mm/memory.c index ca8cac11bd2..f82b359b274 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1639,6 +1639,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, struct page *old_page, *new_page; pte_t entry; int reuse = 0, ret = 0; + int page_mkwrite = 0; struct page *dirty_page = NULL; old_page = vm_normal_page(vma, address, orig_pte); @@ -1687,6 +1688,8 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, page_cache_release(old_page); if (!pte_same(*page_table, orig_pte)) goto unlock; + + page_mkwrite = 1; } dirty_page = old_page; get_page(dirty_page); @@ -1774,7 +1777,7 @@ unlock: * do_no_page is protected similarly. */ wait_on_page_locked(dirty_page); - set_page_dirty_balance(dirty_page); + set_page_dirty_balance(dirty_page, page_mkwrite); put_page(dirty_page); } return ret; @@ -2307,13 +2310,14 @@ oom: * do not need to flush old virtual caches or the TLB. * * We enter with non-exclusive mmap_sem (to exclude vma changes, - * but allow concurrent faults), and pte mapped but not yet locked. + * but allow concurrent faults), and pte neither mapped nor locked. * We return with mmap_sem still held, but pte unmapped and unlocked. */ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, - unsigned long address, pte_t *page_table, pmd_t *pmd, + unsigned long address, pmd_t *pmd, pgoff_t pgoff, unsigned int flags, pte_t orig_pte) { + pte_t *page_table; spinlock_t *ptl; struct page *page; pte_t entry; @@ -2321,13 +2325,13 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, struct page *dirty_page = NULL; struct vm_fault vmf; int ret; + int page_mkwrite = 0; vmf.virtual_address = (void __user *)(address & PAGE_MASK); vmf.pgoff = pgoff; vmf.flags = flags; vmf.page = NULL; - pte_unmap(page_table); BUG_ON(vma->vm_flags & VM_PFNMAP); if (likely(vma->vm_ops->fault)) { @@ -2398,6 +2402,7 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, anon = 1; /* no anon but release vmf.page */ goto out; } + page_mkwrite = 1; } } @@ -2453,7 +2458,7 @@ out_unlocked: if (anon) page_cache_release(vmf.page); else if (dirty_page) { - set_page_dirty_balance(dirty_page); + set_page_dirty_balance(dirty_page, page_mkwrite); put_page(dirty_page); } @@ -2468,8 +2473,8 @@ static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma, - vma->vm_start) >> PAGE_CACHE_SHIFT) + vma->vm_pgoff; unsigned int flags = (write_access ? FAULT_FLAG_WRITE : 0); - return __do_fault(mm, vma, address, page_table, pmd, pgoff, - flags, orig_pte); + pte_unmap(page_table); + return __do_fault(mm, vma, address, pmd, pgoff, flags, orig_pte); } @@ -2552,9 +2557,7 @@ static int do_nonlinear_fault(struct mm_struct *mm, struct vm_area_struct *vma, } pgoff = pte_to_pgoff(orig_pte); - - return __do_fault(mm, vma, address, page_table, pmd, pgoff, - flags, orig_pte); + return __do_fault(mm, vma, address, pmd, pgoff, flags, orig_pte); } /* diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 63512a9ed57..44720363374 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -274,9 +274,9 @@ static void balance_dirty_pages(struct address_space *mapping) pdflush_operation(background_writeout, 0); } -void set_page_dirty_balance(struct page *page) +void set_page_dirty_balance(struct page *page, int page_mkwrite) { - if (set_page_dirty(page)) { + if (set_page_dirty(page) || page_mkwrite) { struct address_space *mapping = page_mapping(page); if (mapping) diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index f2de2e48b02..6284c99b456 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -366,6 +366,12 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, frag = WLAN_GET_SEQ_FRAG(sc); hdrlen = ieee80211_get_hdrlen(fc); + if (skb->len < hdrlen) { + printk(KERN_INFO "%s: invalid SKB length %d\n", + dev->name, skb->len); + goto rx_dropped; + } + /* Put this code here so that we avoid duplicating it in all * Rx paths. - Jean II */ #ifdef CONFIG_WIRELESS_EXT diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c index 442b9875f3f..5742dc803b7 100644 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c @@ -114,7 +114,7 @@ check_assoc_again: sm->associnfo.associating = 1; /* queue lower level code to do work (if necessary) */ schedule_delayed_work(&sm->associnfo.work, 0); -out: + mutex_unlock(&sm->associnfo.mutex); return 0; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index bbad2cdb74b..f893e90061e 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2420,6 +2420,9 @@ static int tcp_tso_acked(struct sock *sk, struct sk_buff *skb, __u32 dval = min(tp->fackets_out, packets_acked); tp->fackets_out -= dval; } + /* hint's skb might be NULL but we don't need to care */ + tp->fastpath_cnt_hint -= min_t(u32, packets_acked, + tp->fastpath_cnt_hint); tp->packets_out -= packets_acked; BUG_ON(tcp_skb_pcount(skb) == 0); diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 73a894a2152..5b596659177 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1268,9 +1268,10 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) if (ipv6_addr_equal(dest, target)) { on_link = 1; - } else if (!(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) { + } else if (ipv6_addr_type(target) != + (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) { ND_PRINTK2(KERN_WARNING - "ICMPv6 Redirect: target address is not link-local.\n"); + "ICMPv6 Redirect: target address is not link-local unicast.\n"); return; } @@ -1344,9 +1345,9 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, } if (!ipv6_addr_equal(&ipv6_hdr(skb)->daddr, target) && - !(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) { + ipv6_addr_type(target) != (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) { ND_PRINTK2(KERN_WARNING - "ICMPv6 Redirect: target address is not link-local.\n"); + "ICMPv6 Redirect: target address is not link-local unicast.\n"); return; } diff --git a/net/rose/rose_loopback.c b/net/rose/rose_loopback.c index cd01642f049..114df6eec8c 100644 --- a/net/rose/rose_loopback.c +++ b/net/rose/rose_loopback.c @@ -79,7 +79,7 @@ static void rose_loopback_timer(unsigned long param) skb_reset_transport_header(skb); - sk = rose_find_socket(lci_o, &rose_loopback_neigh); + sk = rose_find_socket(lci_o, rose_loopback_neigh); if (sk) { if (rose_process_rx_frame(sk, skb) == 0) kfree_skb(skb); @@ -88,7 +88,7 @@ static void rose_loopback_timer(unsigned long param) if (frametype == ROSE_CALL_REQUEST) { if ((dev = rose_dev_get(dest)) != NULL) { - if (rose_rx_call_request(skb, dev, &rose_loopback_neigh, lci_o) == 0) + if (rose_rx_call_request(skb, dev, rose_loopback_neigh, lci_o) == 0) kfree_skb(skb); } else { kfree_skb(skb); diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index bbcbad1da0d..96f61a71b25 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c @@ -45,7 +45,7 @@ static DEFINE_SPINLOCK(rose_neigh_list_lock); static struct rose_route *rose_route_list; static DEFINE_SPINLOCK(rose_route_list_lock); -struct rose_neigh rose_loopback_neigh; +struct rose_neigh *rose_loopback_neigh; /* * Add a new route to a node, and in the process add the node and the @@ -362,7 +362,12 @@ out: */ void rose_add_loopback_neigh(void) { - struct rose_neigh *sn = &rose_loopback_neigh; + struct rose_neigh *sn; + + rose_loopback_neigh = kmalloc(sizeof(struct rose_neigh), GFP_KERNEL); + if (!rose_loopback_neigh) + return; + sn = rose_loopback_neigh; sn->callsign = null_ax25_address; sn->digipeat = NULL; @@ -417,13 +422,13 @@ int rose_add_loopback_node(rose_address *address) rose_node->mask = 10; rose_node->count = 1; rose_node->loopback = 1; - rose_node->neighbour[0] = &rose_loopback_neigh; + rose_node->neighbour[0] = rose_loopback_neigh; /* Insert at the head of list. Address is always mask=10 */ rose_node->next = rose_node_list; rose_node_list = rose_node; - rose_loopback_neigh.count++; + rose_loopback_neigh->count++; out: spin_unlock_bh(&rose_node_list_lock); @@ -454,7 +459,7 @@ void rose_del_loopback_node(rose_address *address) rose_remove_node(rose_node); - rose_loopback_neigh.count--; + rose_loopback_neigh->count--; out: spin_unlock_bh(&rose_node_list_lock); diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 8dbe36912ec..d4d5d2f271d 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -502,7 +502,7 @@ static int u32_set_parms(struct tcf_proto *tp, unsigned long base, #ifdef CONFIG_NET_CLS_IND if (tb[TCA_U32_INDEV-1]) { - int err = tcf_change_indev(tp, n->indev, tb[TCA_U32_INDEV-1]); + err = tcf_change_indev(tp, n->indev, tb[TCA_U32_INDEV-1]); if (err < 0) goto errout; } diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 3a23e30bc79..b542c875e15 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -19,6 +19,7 @@ #include <linux/init.h> #include <linux/ipv6.h> #include <linux/skbuff.h> +#include <linux/jhash.h> #include <net/ip.h> #include <net/netlink.h> #include <net/pkt_sched.h> @@ -95,7 +96,7 @@ struct sfq_sched_data /* Variables */ struct timer_list perturb_timer; - int perturbation; + u32 perturbation; sfq_index tail; /* Index of current slot in round */ sfq_index max_depth; /* Maximal depth */ @@ -109,12 +110,7 @@ struct sfq_sched_data static __inline__ unsigned sfq_fold_hash(struct sfq_sched_data *q, u32 h, u32 h1) { - int pert = q->perturbation; - - /* Have we any rotation primitives? If not, WHY? */ - h ^= (h1<<pert) ^ (h1>>(0x1F - pert)); - h ^= h>>10; - return h & 0x3FF; + return jhash_2words(h, h1, q->perturbation) & (SFQ_HASH_DIVISOR - 1); } static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) @@ -256,6 +252,13 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc* sch) q->ht[hash] = x = q->dep[SFQ_DEPTH].next; q->hash[x] = hash; } + /* If selected queue has length q->limit, this means that + * all another queues are empty and that we do simple tail drop, + * i.e. drop _this_ packet. + */ + if (q->qs[x].qlen >= q->limit) + return qdisc_drop(skb, sch); + sch->qstats.backlog += skb->len; __skb_queue_tail(&q->qs[x], skb); sfq_inc(q, x); @@ -294,6 +297,19 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc* sch) } sch->qstats.backlog += skb->len; __skb_queue_head(&q->qs[x], skb); + /* If selected queue has length q->limit+1, this means that + * all another queues are empty and we do simple tail drop. + * This packet is still requeued at head of queue, tail packet + * is dropped. + */ + if (q->qs[x].qlen > q->limit) { + skb = q->qs[x].prev; + __skb_unlink(skb, &q->qs[x]); + sch->qstats.drops++; + sch->qstats.backlog -= skb->len; + kfree_skb(skb); + return NET_XMIT_CN; + } sfq_inc(q, x); if (q->qs[x].qlen == 1) { /* The flow is new */ if (q->tail == SFQ_DEPTH) { /* It is the first flow */ @@ -370,12 +386,10 @@ static void sfq_perturbation(unsigned long arg) struct Qdisc *sch = (struct Qdisc*)arg; struct sfq_sched_data *q = qdisc_priv(sch); - q->perturbation = net_random()&0x1F; + get_random_bytes(&q->perturbation, 4); - if (q->perturb_period) { - q->perturb_timer.expires = jiffies + q->perturb_period; - add_timer(&q->perturb_timer); - } + if (q->perturb_period) + mod_timer(&q->perturb_timer, jiffies + q->perturb_period); } static int sfq_change(struct Qdisc *sch, struct rtattr *opt) @@ -391,7 +405,7 @@ static int sfq_change(struct Qdisc *sch, struct rtattr *opt) q->quantum = ctl->quantum ? : psched_mtu(sch->dev); q->perturb_period = ctl->perturb_period*HZ; if (ctl->limit) - q->limit = min_t(u32, ctl->limit, SFQ_DEPTH - 2); + q->limit = min_t(u32, ctl->limit, SFQ_DEPTH - 1); qlen = sch->q.qlen; while (sch->q.qlen > q->limit) @@ -400,8 +414,8 @@ static int sfq_change(struct Qdisc *sch, struct rtattr *opt) del_timer(&q->perturb_timer); if (q->perturb_period) { - q->perturb_timer.expires = jiffies + q->perturb_period; - add_timer(&q->perturb_timer); + mod_timer(&q->perturb_timer, jiffies + q->perturb_period); + get_random_bytes(&q->perturbation, 4); } sch_tree_unlock(sch); return 0; @@ -423,12 +437,13 @@ static int sfq_init(struct Qdisc *sch, struct rtattr *opt) q->dep[i+SFQ_DEPTH].next = i+SFQ_DEPTH; q->dep[i+SFQ_DEPTH].prev = i+SFQ_DEPTH; } - q->limit = SFQ_DEPTH - 2; + q->limit = SFQ_DEPTH - 1; q->max_depth = 0; q->tail = SFQ_DEPTH; if (opt == NULL) { q->quantum = psched_mtu(sch->dev); q->perturb_period = 0; + get_random_bytes(&q->perturbation, 4); } else { int err = sfq_change(sch, opt); if (err) |