diff --git a/[refs] b/[refs] index 9190a4e48ded..2421645da278 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: b685004f8dea2daae0306edcd358ed7de751aee9 +refs/heads/master: c3a1c9c75b986e5a2c5d878ef0700a1ca6bb895a diff --git a/trunk/arch/arm/Kconfig b/trunk/arch/arm/Kconfig index a583c0bf8203..4039a133006e 100644 --- a/trunk/arch/arm/Kconfig +++ b/trunk/arch/arm/Kconfig @@ -255,7 +255,6 @@ config ARCH_EP93XX select ARM_AMBA select ARM_VIC select GENERIC_GPIO - select HAVE_GPIO_LIB help This enables support for the Cirrus EP93xx series of CPUs. diff --git a/trunk/arch/arm/mach-ep93xx/Makefile b/trunk/arch/arm/mach-ep93xx/Makefile index c1252ca9648e..0ecf99761feb 100644 --- a/trunk/arch/arm/mach-ep93xx/Makefile +++ b/trunk/arch/arm/mach-ep93xx/Makefile @@ -1,7 +1,7 @@ # # Makefile for the linux kernel. # -obj-y := core.o clock.o gpio.o +obj-y := core.o clock.o obj-m := obj-n := obj- := diff --git a/trunk/arch/arm/mach-ep93xx/core.c b/trunk/arch/arm/mach-ep93xx/core.c index 8bc187240542..91f6a07a51d5 100644 --- a/trunk/arch/arm/mach-ep93xx/core.c +++ b/trunk/arch/arm/mach-ep93xx/core.c @@ -159,7 +159,7 @@ static const u8 int_type2_register_offset[3] = { 0x94, 0xb0, 0x50 }; static const u8 eoi_register_offset[3] = { 0x98, 0xb4, 0x54 }; static const u8 int_en_register_offset[3] = { 0x9c, 0xb8, 0x5c }; -void ep93xx_gpio_update_int_params(unsigned port) +static void update_gpio_int_params(unsigned port) { BUG_ON(port > 2); @@ -175,10 +175,98 @@ void ep93xx_gpio_update_int_params(unsigned port) EP93XX_GPIO_REG(int_en_register_offset[port])); } -void ep93xx_gpio_int_mask(unsigned line) +/* Port ordering is: A B F D E C G H */ +static const u8 data_register_offset[8] = { + 0x00, 0x04, 0x30, 0x0c, 0x20, 0x08, 0x38, 0x40, +}; + +static const u8 data_direction_register_offset[8] = { + 0x10, 0x14, 0x34, 0x1c, 0x24, 0x18, 0x3c, 0x44, +}; + +#define GPIO_IN 0 +#define GPIO_OUT 1 + +static void ep93xx_gpio_set_direction(unsigned line, int direction) +{ + unsigned int data_direction_register; + unsigned long flags; + unsigned char v; + + data_direction_register = + EP93XX_GPIO_REG(data_direction_register_offset[line >> 3]); + + local_irq_save(flags); + if (direction == GPIO_OUT) { + if (line >= 0 && line <= EP93XX_GPIO_LINE_MAX_IRQ) { + /* Port A/B/F */ + gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7)); + update_gpio_int_params(line >> 3); + } + + v = __raw_readb(data_direction_register); + v |= 1 << (line & 7); + __raw_writeb(v, data_direction_register); + } else if (direction == GPIO_IN) { + v = __raw_readb(data_direction_register); + v &= ~(1 << (line & 7)); + __raw_writeb(v, data_direction_register); + } + local_irq_restore(flags); +} + +int gpio_direction_input(unsigned gpio) +{ + if (gpio > EP93XX_GPIO_LINE_MAX) + return -EINVAL; + + ep93xx_gpio_set_direction(gpio, GPIO_IN); + + return 0; +} +EXPORT_SYMBOL(gpio_direction_input); + +int gpio_direction_output(unsigned gpio, int value) +{ + if (gpio > EP93XX_GPIO_LINE_MAX) + return -EINVAL; + + gpio_set_value(gpio, value); + ep93xx_gpio_set_direction(gpio, GPIO_OUT); + + return 0; +} +EXPORT_SYMBOL(gpio_direction_output); + +int gpio_get_value(unsigned gpio) +{ + unsigned int data_register; + + data_register = EP93XX_GPIO_REG(data_register_offset[gpio >> 3]); + + return !!(__raw_readb(data_register) & (1 << (gpio & 7))); +} +EXPORT_SYMBOL(gpio_get_value); + +void gpio_set_value(unsigned gpio, int value) { - gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7)); + unsigned int data_register; + unsigned long flags; + unsigned char v; + + data_register = EP93XX_GPIO_REG(data_register_offset[gpio >> 3]); + + local_irq_save(flags); + v = __raw_readb(data_register); + if (value) + v |= 1 << (gpio & 7); + else + v &= ~(1 << (gpio & 7)); + __raw_writeb(v, data_register); + local_irq_restore(flags); } +EXPORT_SYMBOL(gpio_set_value); + /************************************************************************* * EP93xx IRQ handling @@ -228,7 +316,7 @@ static void ep93xx_gpio_irq_ack(unsigned int irq) if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE) { gpio_int_type2[port] ^= port_mask; /* switch edge direction */ - ep93xx_gpio_update_int_params(port); + update_gpio_int_params(port); } __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port])); @@ -244,7 +332,7 @@ static void ep93xx_gpio_irq_mask_ack(unsigned int irq) gpio_int_type2[port] ^= port_mask; /* switch edge direction */ gpio_int_unmasked[port] &= ~port_mask; - ep93xx_gpio_update_int_params(port); + update_gpio_int_params(port); __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port])); } @@ -255,7 +343,7 @@ static void ep93xx_gpio_irq_mask(unsigned int irq) int port = line >> 3; gpio_int_unmasked[port] &= ~(1 << (line & 7)); - ep93xx_gpio_update_int_params(port); + update_gpio_int_params(port); } static void ep93xx_gpio_irq_unmask(unsigned int irq) @@ -264,7 +352,7 @@ static void ep93xx_gpio_irq_unmask(unsigned int irq) int port = line >> 3; gpio_int_unmasked[port] |= 1 << (line & 7); - ep93xx_gpio_update_int_params(port); + update_gpio_int_params(port); } @@ -280,7 +368,7 @@ static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) const int port = gpio >> 3; const int port_mask = 1 << (gpio & 7); - gpio_direction_output(gpio, gpio_get_value(gpio)); + ep93xx_gpio_set_direction(gpio, GPIO_IN); switch (type) { case IRQT_RISING: @@ -323,7 +411,7 @@ static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) desc->status &= ~IRQ_TYPE_SENSE_MASK; desc->status |= type & IRQ_TYPE_SENSE_MASK; - ep93xx_gpio_update_int_params(port); + update_gpio_int_params(port); return 0; } @@ -461,7 +549,6 @@ static struct platform_device ep93xx_ohci_device = { .resource = ep93xx_ohci_resources, }; -extern void ep93xx_gpio_init(void); void __init ep93xx_init_devices(void) { @@ -475,8 +562,6 @@ void __init ep93xx_init_devices(void) __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); __raw_writel(v, EP93XX_SYSCON_DEVICE_CONFIG); - ep93xx_gpio_init(); - amba_device_register(&uart1_device, &iomem_resource); amba_device_register(&uart2_device, &iomem_resource); amba_device_register(&uart3_device, &iomem_resource); diff --git a/trunk/arch/arm/mach-ep93xx/gpio.c b/trunk/arch/arm/mach-ep93xx/gpio.c deleted file mode 100644 index dc2e4c00d989..000000000000 --- a/trunk/arch/arm/mach-ep93xx/gpio.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * linux/arch/arm/mach-ep93xx/gpio.c - * - * Generic EP93xx GPIO handling - * - * Copyright (c) 2008 Ryan Mallon - * - * Based on code originally from: - * linux/arch/arm/mach-ep93xx/core.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include -#include -#include - -struct ep93xx_gpio_chip { - struct gpio_chip chip; - - unsigned int data_reg; - unsigned int data_dir_reg; -}; - -#define to_ep93xx_gpio_chip(c) container_of(c, struct ep93xx_gpio_chip, chip) - -/* From core.c */ -extern void ep93xx_gpio_int_mask(unsigned line); -extern void ep93xx_gpio_update_int_params(unsigned port); - -static int ep93xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); - unsigned long flags; - u8 v; - - local_irq_save(flags); - v = __raw_readb(ep93xx_chip->data_dir_reg); - v &= ~(1 << offset); - __raw_writeb(v, ep93xx_chip->data_dir_reg); - local_irq_restore(flags); - - return 0; -} - -static int ep93xx_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int val) -{ - struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); - unsigned long flags; - int line; - u8 v; - - local_irq_save(flags); - - /* Set the value */ - v = __raw_readb(ep93xx_chip->data_reg); - if (val) - v |= (1 << offset); - else - v &= ~(1 << offset); - __raw_writeb(v, ep93xx_chip->data_reg); - - /* Drive as an output */ - line = chip->base + offset; - if (line <= EP93XX_GPIO_LINE_MAX_IRQ) { - /* Ports A/B/F */ - ep93xx_gpio_int_mask(line); - ep93xx_gpio_update_int_params(line >> 3); - } - - v = __raw_readb(ep93xx_chip->data_dir_reg); - v |= (1 << offset); - __raw_writeb(v, ep93xx_chip->data_dir_reg); - - local_irq_restore(flags); - - return 0; -} - -static int ep93xx_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); - - return !!(__raw_readb(ep93xx_chip->data_reg) & (1 << offset)); -} - -static void ep93xx_gpio_set(struct gpio_chip *chip, unsigned offset, int val) -{ - struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); - unsigned long flags; - u8 v; - - local_irq_save(flags); - v = __raw_readb(ep93xx_chip->data_reg); - if (val) - v |= (1 << offset); - else - v &= ~(1 << offset); - __raw_writeb(v, ep93xx_chip->data_reg); - local_irq_restore(flags); -} - -static void ep93xx_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) -{ - struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); - u8 data_reg, data_dir_reg; - int i; - - data_reg = __raw_readb(ep93xx_chip->data_reg); - data_dir_reg = __raw_readb(ep93xx_chip->data_dir_reg); - - for (i = 0; i < chip->ngpio; i++) - seq_printf(s, "GPIO %s%d: %s %s\n", chip->label, i, - (data_reg & (1 << i)) ? "set" : "clear", - (data_dir_reg & (1 << i)) ? "out" : "in"); -} - -#define EP93XX_GPIO_BANK(name, dr, ddr, base_gpio) \ - { \ - .chip = { \ - .label = name, \ - .direction_input = ep93xx_gpio_direction_input, \ - .direction_output = ep93xx_gpio_direction_output, \ - .get = ep93xx_gpio_get, \ - .set = ep93xx_gpio_set, \ - .dbg_show = ep93xx_gpio_dbg_show, \ - .base = base_gpio, \ - .ngpio = 8, \ - }, \ - .data_reg = EP93XX_GPIO_REG(dr), \ - .data_dir_reg = EP93XX_GPIO_REG(ddr), \ - } - -static struct ep93xx_gpio_chip ep93xx_gpio_banks[] = { - EP93XX_GPIO_BANK("A", 0x00, 0x10, 0), - EP93XX_GPIO_BANK("B", 0x04, 0x14, 8), - EP93XX_GPIO_BANK("C", 0x30, 0x34, 40), - EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24), - EP93XX_GPIO_BANK("E", 0x20, 0x24, 32), - EP93XX_GPIO_BANK("F", 0x08, 0x18, 16), - EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48), - EP93XX_GPIO_BANK("H", 0x40, 0x44, 56), -}; - -void __init ep93xx_gpio_init(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) - gpiochip_add(&ep93xx_gpio_banks[i].chip); -} diff --git a/trunk/arch/arm/plat-iop/pci.c b/trunk/arch/arm/plat-iop/pci.c index 98d01517b563..9e83066cc056 100644 --- a/trunk/arch/arm/plat-iop/pci.c +++ b/trunk/arch/arm/plat-iop/pci.c @@ -329,23 +329,28 @@ void __init iop3xx_pci_preinit(void) iop3xx_atu_setup(); } - DBG("PCI: Intel 803xx PCI init code.\n"); + DBG("PCI: Intel IOP3xx PCI init.\n"); + DBG("PCI: Outbound memory window 0: PCI 0x%08x%08x\n", + *IOP3XX_OUMWTVR0, *IOP3XX_OMWTVR0); + DBG("PCI: Outbound memory window 1: PCI 0x%08x%08x\n", + *IOP3XX_OUMWTVR1, *IOP3XX_OMWTVR1); + DBG("PCI: Outbound IO window: PCI 0x%08x\n", + *IOP3XX_OIOWTVR); + + DBG("PCI: Inbound memory window 0: PCI 0x%08x%08x 0x%08x -> 0x%08x\n", + *IOP3XX_IAUBAR0, *IOP3XX_IABAR0, *IOP3XX_IALR0, *IOP3XX_IATVR0); + DBG("PCI: Inbound memory window 1: PCI 0x%08x%08x 0x%08x\n", + *IOP3XX_IAUBAR1, *IOP3XX_IABAR1, *IOP3XX_IALR1); + DBG("PCI: Inbound memory window 2: PCI 0x%08x%08x 0x%08x -> 0x%08x\n", + *IOP3XX_IAUBAR2, *IOP3XX_IABAR2, *IOP3XX_IALR2, *IOP3XX_IATVR2); + DBG("PCI: Inbound memory window 3: PCI 0x%08x%08x 0x%08x -> 0x%08x\n", + *IOP3XX_IAUBAR3, *IOP3XX_IABAR3, *IOP3XX_IALR3, *IOP3XX_IATVR3); + + DBG("PCI: Expansion ROM window: PCI 0x%08x%08x 0x%08x -> 0x%08x\n", + 0, *IOP3XX_ERBAR, *IOP3XX_ERLR, *IOP3XX_ERTVR); + DBG("ATU: IOP3XX_ATUCMD=0x%04x\n", *IOP3XX_ATUCMD); - DBG("ATU: IOP3XX_OMWTVR0=0x%04x, IOP3XX_OIOWTVR=0x%04x\n", - *IOP3XX_OMWTVR0, - *IOP3XX_OIOWTVR); DBG("ATU: IOP3XX_ATUCR=0x%08x\n", *IOP3XX_ATUCR); - DBG("ATU: IOP3XX_IABAR0=0x%08x IOP3XX_IALR0=0x%08x IOP3XX_IATVR0=%08x\n", - *IOP3XX_IABAR0, *IOP3XX_IALR0, *IOP3XX_IATVR0); - DBG("ATU: IOP3XX_OMWTVR0=0x%08x\n", *IOP3XX_OMWTVR0); - DBG("ATU: IOP3XX_IABAR1=0x%08x IOP3XX_IALR1=0x%08x\n", - *IOP3XX_IABAR1, *IOP3XX_IALR1); - DBG("ATU: IOP3XX_ERBAR=0x%08x IOP3XX_ERLR=0x%08x IOP3XX_ERTVR=%08x\n", - *IOP3XX_ERBAR, *IOP3XX_ERLR, *IOP3XX_ERTVR); - DBG("ATU: IOP3XX_IABAR2=0x%08x IOP3XX_IALR2=0x%08x IOP3XX_IATVR2=%08x\n", - *IOP3XX_IABAR2, *IOP3XX_IALR2, *IOP3XX_IATVR2); - DBG("ATU: IOP3XX_IABAR3=0x%08x IOP3XX_IALR3=0x%08x IOP3XX_IATVR3=%08x\n", - *IOP3XX_IABAR3, *IOP3XX_IALR3, *IOP3XX_IATVR3); hook_fault_code(16+6, iop3xx_pci_abort, SIGBUS, "imprecise external abort"); } diff --git a/trunk/drivers/pci/setup-bus.c b/trunk/drivers/pci/setup-bus.c index 125e7b7f34ff..f7cb8e0758b4 100644 --- a/trunk/drivers/pci/setup-bus.c +++ b/trunk/drivers/pci/setup-bus.c @@ -486,12 +486,7 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus) break; case PCI_CLASS_BRIDGE_PCI: - /* don't size subtractive decoding (transparent) - * PCI-to-PCI bridges */ - if (bus->self->transparent) - break; pci_bridge_check_ranges(bus); - /* fall through */ default: pbus_size_io(bus); /* If the bridge supports prefetchable range, size it diff --git a/trunk/include/asm-arm/arch-ep93xx/gpio.h b/trunk/include/asm-arm/arch-ep93xx/gpio.h index 186e7c715f8a..9b1864bbd9a8 100644 --- a/trunk/include/asm-arm/arch-ep93xx/gpio.h +++ b/trunk/include/asm-arm/arch-ep93xx/gpio.h @@ -101,17 +101,30 @@ /* new generic GPIO API - see Documentation/gpio.txt */ -#include +static inline int gpio_request(unsigned gpio, const char *label) +{ + if (gpio > EP93XX_GPIO_LINE_MAX) + return -EINVAL; + return 0; +} -#define gpio_get_value __gpio_get_value -#define gpio_set_value __gpio_set_value -#define gpio_cansleep __gpio_cansleep +static inline void gpio_free(unsigned gpio) +{ +} + +int gpio_direction_input(unsigned gpio); +int gpio_direction_output(unsigned gpio, int value); +int gpio_get_value(unsigned gpio); +void gpio_set_value(unsigned gpio, int value); + +#include /* cansleep wrappers */ /* * Map GPIO A0..A7 (0..7) to irq 64..71, * B0..B7 (7..15) to irq 72..79, and * F0..F7 (16..24) to irq 80..87. */ + static inline int gpio_to_irq(unsigned gpio) { if (gpio <= EP93XX_GPIO_LINE_MAX_IRQ) diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index fed07d03364e..6a1e7afb099b 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -1541,6 +1541,12 @@ static inline void idle_task_exit(void) {} extern void sched_idle_next(void); +#if defined(CONFIG_NO_HZ) && defined(CONFIG_SMP) +extern void wake_up_idle_cpu(int cpu); +#else +static inline void wake_up_idle_cpu(int cpu) { } +#endif + #ifdef CONFIG_SCHED_DEBUG extern unsigned int sysctl_sched_latency; extern unsigned int sysctl_sched_min_granularity; diff --git a/trunk/kernel/relay.c b/trunk/kernel/relay.c index 4c035a8a248c..d6204a485818 100644 --- a/trunk/kernel/relay.c +++ b/trunk/kernel/relay.c @@ -736,7 +736,7 @@ static int relay_file_open(struct inode *inode, struct file *filp) kref_get(&buf->kref); filp->private_data = buf; - return 0; + return nonseekable_open(inode, filp); } /** @@ -1056,6 +1056,10 @@ static struct pipe_buf_operations relay_pipe_buf_ops = { .get = generic_pipe_buf_get, }; +static void relay_page_release(struct splice_pipe_desc *spd, unsigned int i) +{ +} + /* * subbuf_splice_actor - splice up to one subbuf's worth of data */ @@ -1083,6 +1087,7 @@ static int subbuf_splice_actor(struct file *in, .partial = partial, .flags = flags, .ops = &relay_pipe_buf_ops, + .spd_release = relay_page_release, }; if (rbuf->subbufs_produced == rbuf->subbufs_consumed) diff --git a/trunk/kernel/sched.c b/trunk/kernel/sched.c index 28c73f07efb2..8dcdec6fe0fe 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -1052,6 +1052,49 @@ static void resched_cpu(int cpu) resched_task(cpu_curr(cpu)); spin_unlock_irqrestore(&rq->lock, flags); } + +#ifdef CONFIG_NO_HZ +/* + * When add_timer_on() enqueues a timer into the timer wheel of an + * idle CPU then this timer might expire before the next timer event + * which is scheduled to wake up that CPU. In case of a completely + * idle system the next event might even be infinite time into the + * future. wake_up_idle_cpu() ensures that the CPU is woken up and + * leaves the inner idle loop so the newly added timer is taken into + * account when the CPU goes back to idle and evaluates the timer + * wheel for the next timer event. + */ +void wake_up_idle_cpu(int cpu) +{ + struct rq *rq = cpu_rq(cpu); + + if (cpu == smp_processor_id()) + return; + + /* + * This is safe, as this function is called with the timer + * wheel base lock of (cpu) held. When the CPU is on the way + * to idle and has not yet set rq->curr to idle then it will + * be serialized on the timer wheel base lock and take the new + * timer into account automatically. + */ + if (rq->curr != rq->idle) + return; + + /* + * We can set TIF_RESCHED on the idle task of the other CPU + * lockless. The worst case is that the other CPU runs the + * idle task through an additional NOOP schedule() + */ + set_tsk_thread_flag(rq->idle, TIF_NEED_RESCHED); + + /* NEED_RESCHED must be visible before we test polling */ + smp_mb(); + if (!tsk_is_polling(rq->idle)) + smp_send_reschedule(cpu); +} +#endif + #else static void __resched_task(struct task_struct *p, int tif_bit) { diff --git a/trunk/kernel/time/clocksource.c b/trunk/kernel/time/clocksource.c index 278534bbca95..7f60097d443a 100644 --- a/trunk/kernel/time/clocksource.c +++ b/trunk/kernel/time/clocksource.c @@ -174,7 +174,7 @@ static void clocksource_check_watchdog(struct clocksource *cs) if (watchdog) del_timer(&watchdog_timer); watchdog = cs; - init_timer_deferrable(&watchdog_timer); + init_timer(&watchdog_timer); watchdog_timer.function = clocksource_watchdog; /* Reset watchdog cycles */ diff --git a/trunk/kernel/timer.c b/trunk/kernel/timer.c index 99b00a25f88b..b024106daa70 100644 --- a/trunk/kernel/timer.c +++ b/trunk/kernel/timer.c @@ -451,10 +451,18 @@ void add_timer_on(struct timer_list *timer, int cpu) spin_lock_irqsave(&base->lock, flags); timer_set_base(timer, base); internal_add_timer(base, timer); + /* + * Check whether the other CPU is idle and needs to be + * triggered to reevaluate the timer wheel when nohz is + * active. We are protected against the other CPU fiddling + * with the timer by holding the timer base lock. This also + * makes sure that a CPU on the way to idle can not evaluate + * the timer wheel. + */ + wake_up_idle_cpu(cpu); spin_unlock_irqrestore(&base->lock, flags); } - /** * mod_timer - modify a timer's timeout * @timer: the timer to be modified diff --git a/trunk/mm/slab.c b/trunk/mm/slab.c index bb4070e1079f..04b308c3bc54 100644 --- a/trunk/mm/slab.c +++ b/trunk/mm/slab.c @@ -1481,7 +1481,7 @@ void __init kmem_cache_init(void) list_add(&cache_cache.next, &cache_chain); cache_cache.colour_off = cache_line_size(); cache_cache.array[smp_processor_id()] = &initarray_cache.cache; - cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE]; + cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE + node]; /* * struct kmem_cache size depends on nr_node_ids, which @@ -1602,7 +1602,7 @@ void __init kmem_cache_init(void) int nid; for_each_online_node(nid) { - init_list(&cache_cache, &initkmem_list3[CACHE_CACHE], nid); + init_list(&cache_cache, &initkmem_list3[CACHE_CACHE + nid], nid); init_list(malloc_sizes[INDEX_AC].cs_cachep, &initkmem_list3[SIZE_AC + nid], nid); diff --git a/trunk/mm/slub.c b/trunk/mm/slub.c index ca71d5b81e4a..b72bc98e2dc1 100644 --- a/trunk/mm/slub.c +++ b/trunk/mm/slub.c @@ -2685,6 +2685,7 @@ void kfree(const void *x) } EXPORT_SYMBOL(kfree); +#if defined(SLUB_DEBUG) || defined(CONFIG_SLABINFO) static unsigned long count_partial(struct kmem_cache_node *n) { unsigned long flags; @@ -2697,6 +2698,7 @@ static unsigned long count_partial(struct kmem_cache_node *n) spin_unlock_irqrestore(&n->list_lock, flags); return x; } +#endif /* * kmem_cache_shrink removes empty slabs from the partial lists and sorts diff --git a/trunk/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/trunk/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index 971271602dd0..c22d6b6f2db4 100644 --- a/trunk/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/trunk/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c @@ -322,15 +322,6 @@ static int rdma_read_xdr(struct svcxprt_rdma *xprt, ctxt->direction = DMA_FROM_DEVICE; clear_bit(RDMACTXT_F_READ_DONE, &ctxt->flags); clear_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags); - if ((ch+1)->rc_discrim == 0) { - /* - * Checked in sq_cq_reap to see if we need to - * be enqueued - */ - set_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags); - ctxt->next = hdr_ctxt; - hdr_ctxt->next = head; - } /* Prepare READ WR */ memset(&read_wr, 0, sizeof read_wr); @@ -348,7 +339,17 @@ static int rdma_read_xdr(struct svcxprt_rdma *xprt, rdma_set_ctxt_sge(ctxt, &sge[ch_sge_ary[ch_no].start], &sgl_offset, read_wr.num_sge); - + if (((ch+1)->rc_discrim == 0) && + (read_wr.num_sge == ch_sge_ary[ch_no].count)) { + /* + * Mark the last RDMA_READ with a bit to + * indicate all RPC data has been fetched from + * the client and the RPC needs to be enqueued. + */ + set_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags); + ctxt->next = hdr_ctxt; + hdr_ctxt->next = head; + } /* Post the read */ err = svc_rdma_send(xprt, &read_wr); if (err) {