diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-01-26 21:06:54 +0000 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-01-26 21:06:54 +0000 |
commit | 9a95b9e7416c2e7fa799e54078a1adf84a7ed0bf (patch) | |
tree | 158cd337307a4a4e09a3fb5110f29ab0136bef6c | |
parent | 4e7682d077d693e34a993ae7a2831b522930ebcb (diff) | |
parent | 0af5e4c36e70cfd4ae96d3704a425c414f530f2a (diff) |
Merge branch 'sa11x0-mcp-fixes' into fixes
37 files changed, 596 insertions, 509 deletions
@@ -1,7 +1,7 @@ VERSION = 3 -PATCHLEVEL = 2 +PATCHLEVEL = 3 SUBLEVEL = 0 -EXTRAVERSION = +EXTRAVERSION = -rc1 NAME = Saber-toothed Squirrel # *DOCUMENTATION* diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index ebafe8aa895..0c4b76ab4d8 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -202,7 +202,6 @@ static struct irda_platform_data assabet_irda_data = { static struct mcp_plat_data assabet_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, - .codec = "ucb1x00", }; static void __init assabet_init(void) @@ -253,17 +252,6 @@ static void __init assabet_init(void) sa11x0_register_mtd(&assabet_flash_data, assabet_flash_resources, ARRAY_SIZE(assabet_flash_resources)); sa11x0_register_irda(&assabet_irda_data); - - /* - * Setup the PPC unit correctly. - */ - PPDR &= ~PPC_RXD4; - PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; - PSDR |= PPC_RXD4; - PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - - ASSABET_BCR_set(ASSABET_BCR_CODEC_RST); sa11x0_register_mcp(&assabet_mcp_data); } diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c index d12d0f48b1d..11bb6d0b9be 100644 --- a/arch/arm/mach-sa1100/cerf.c +++ b/arch/arm/mach-sa1100/cerf.c @@ -124,23 +124,12 @@ static void __init cerf_map_io(void) static struct mcp_plat_data cerf_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, - .codec = "ucb1x00", }; static void __init cerf_init(void) { platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices)); sa11x0_register_mtd(&cerf_flash_data, &cerf_flash_resource, 1); - - /* - * Setup the PPC unit correctly. - */ - PPDR &= ~PPC_RXD4; - PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; - PSDR |= PPC_RXD4; - PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - sa11x0_register_mcp(&cerf_mcp_data); } diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index cce8763d083..fd5652118ed 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -27,7 +27,6 @@ #include <linux/timer.h> #include <linux/gpio.h> #include <linux/pda_power.h> -#include <linux/mfd/ucb1x00.h> #include <mach/hardware.h> #include <asm/mach-types.h> @@ -86,15 +85,10 @@ static struct scoop_pcmcia_config collie_pcmcia_config = { .num_devs = 1, }; -static struct ucb1x00_plat_data collie_ucb1x00_data = { - .gpio_base = COLLIE_TC35143_GPIO_BASE, -}; - static struct mcp_plat_data collie_mcp_data = { .mccr0 = MCCR0_ADM | MCCR0_ExtClk, .sclk_rate = 9216000, - .codec = "ucb1x00", - .codec_pdata = &collie_ucb1x00_data, + .gpio_base = COLLIE_TC35143_GPIO_BASE, }; /* @@ -356,16 +350,6 @@ static void __init collie_init(void) sa11x0_register_mtd(&collie_flash_data, collie_flash_resources, ARRAY_SIZE(collie_flash_resources)); - - /* - * Setup the PPC unit correctly. - */ - PPDR &= ~PPC_RXD4; - PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; - PSDR |= PPC_RXD4; - PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - sa11x0_register_mcp(&collie_mcp_data); sharpsl_save_param(); diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index a7c0df6e670..bb10ee2cb89 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -217,15 +217,10 @@ static struct platform_device sa11x0uart3_device = { static struct resource sa11x0mcp_resources[] = { [0] = { .start = __PREG(Ser4MCCR0), - .end = __PREG(Ser4MCCR0) + 0x1C - 1, + .end = __PREG(Ser4MCCR0) + 0xffff, .flags = IORESOURCE_MEM, }, [1] = { - .start = __PREG(Ser4MCCR1), - .end = __PREG(Ser4MCCR1) + 0x4 - 1, - .flags = IORESOURCE_MEM, - }, - [2] = { .start = IRQ_Ser4MCP, .end = IRQ_Ser4MCP, .flags = IORESOURCE_IRQ, diff --git a/arch/arm/mach-sa1100/include/mach/mcp.h b/arch/arm/mach-sa1100/include/mach/mcp.h index 586cec898b3..ed1a331508a 100644 --- a/arch/arm/mach-sa1100/include/mach/mcp.h +++ b/arch/arm/mach-sa1100/include/mach/mcp.h @@ -17,8 +17,6 @@ struct mcp_plat_data { u32 mccr1; unsigned int sclk_rate; int gpio_base; - const char *codec; - void *codec_pdata; }; #endif diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c index d117ceab621..af4e2761f3d 100644 --- a/arch/arm/mach-sa1100/lart.c +++ b/arch/arm/mach-sa1100/lart.c @@ -24,20 +24,10 @@ static struct mcp_plat_data lart_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, - .codec = "ucb1x00", }; static void __init lart_init(void) { - /* - * Setup the PPC unit correctly. - */ - PPDR &= ~PPC_RXD4; - PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; - PSDR |= PPC_RXD4; - PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - sa11x0_register_mcp(&lart_mcp_data); } diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c index 748d34435b3..318b2b766a0 100644 --- a/arch/arm/mach-sa1100/shannon.c +++ b/arch/arm/mach-sa1100/shannon.c @@ -55,22 +55,11 @@ static struct resource shannon_flash_resource = { static struct mcp_plat_data shannon_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, - .codec = "ucb1x00", }; static void __init shannon_init(void) { sa11x0_register_mtd(&shannon_flash_data, &shannon_flash_resource, 1); - - /* - * Setup the PPC unit correctly. - */ - PPDR &= ~PPC_RXD4; - PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; - PSDR |= PPC_RXD4; - PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - sa11x0_register_mcp(&shannon_mcp_data); } diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c index 458ececefa5..e17c04d6e32 100644 --- a/arch/arm/mach-sa1100/simpad.c +++ b/arch/arm/mach-sa1100/simpad.c @@ -14,7 +14,6 @@ #include <linux/mtd/partitions.h> #include <linux/io.h> #include <linux/gpio.h> -#include <linux/mfd/ucb1x00.h> #include <asm/irq.h> #include <mach/hardware.h> @@ -188,15 +187,10 @@ static struct resource simpad_flash_resources [] = { } }; -static struct ucb1x00_plat_data simpad_ucb1x00_data = { - .gpio_base = SIMPAD_UCB1X00_GPIO_BASE, -}; - static struct mcp_plat_data simpad_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, - .codec = "ucb1300", - .codec_pdata = &simpad_ucb1x00_data, + .gpio_base = SIMPAD_UCB1X00_GPIO_BASE, }; @@ -384,16 +378,6 @@ static int __init simpad_init(void) sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources, ARRAY_SIZE(simpad_flash_resources)); - - /* - * Setup the PPC unit correctly. - */ - PPDR &= ~PPC_RXD4; - PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; - PSDR |= PPC_RXD4; - PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - sa11x0_register_mcp(&simpad_mcp_data); ret = platform_add_devices(devices, ARRAY_SIZE(devices)); diff --git a/arch/x86/.gitignore b/arch/x86/.gitignore index 028079065af..7cab8c08e6d 100644 --- a/arch/x86/.gitignore +++ b/arch/x86/.gitignore @@ -1,3 +1,4 @@ boot/compressed/vmlinux tools/test_get_len +tools/insn_sanity diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 6c14ecd851d..864cc6e6ac8 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -125,16 +125,6 @@ config HAVE_LATENCYTOP_SUPPORT config MMU def_bool y -config ZONE_DMA - bool "DMA memory allocation support" if EXPERT - default y - help - DMA memory allocation support allows devices with less than 32-bit - addressing to allocate within the first 16MB of address space. - Disable if no such devices will be used. - - If unsure, say Y. - config SBUS bool @@ -255,6 +245,16 @@ source "kernel/Kconfig.freezer" menu "Processor type and features" +config ZONE_DMA + bool "DMA memory allocation support" if EXPERT + default y + help + DMA memory allocation support allows devices with less than 32-bit + addressing to allocate within the first 16MB of address space. + Disable if no such devices will be used. + + If unsure, say Y. + source "kernel/time/Kconfig" config SMP diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h index b4a3db7ce14..21f77b89e47 100644 --- a/arch/x86/include/asm/unistd.h +++ b/arch/x86/include/asm/unistd.h @@ -7,6 +7,7 @@ # include <asm/unistd_32.h> # define __ARCH_WANT_IPC_PARSE_VERSION # define __ARCH_WANT_STAT64 +# define __ARCH_WANT_SYS_IPC # define __ARCH_WANT_SYS_OLD_MMAP # define __ARCH_WANT_SYS_OLD_SELECT diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h index 8e862aaf0d9..becf47b8173 100644 --- a/arch/x86/include/asm/uv/uv_bau.h +++ b/arch/x86/include/asm/uv/uv_bau.h @@ -65,7 +65,7 @@ * UV2: Bit 19 selects between * (0): 10 microsecond timebase and * (1): 80 microseconds - * we're using 655us, similar to UV1: 65 units of 10us + * we're using 560us, similar to UV1: 65 units of 10us */ #define UV1_INTD_SOFT_ACK_TIMEOUT_PERIOD (9UL) #define UV2_INTD_SOFT_ACK_TIMEOUT_PERIOD (15UL) @@ -167,6 +167,7 @@ #define FLUSH_RETRY_TIMEOUT 2 #define FLUSH_GIVEUP 3 #define FLUSH_COMPLETE 4 +#define FLUSH_RETRY_BUSYBUG 5 /* * tuning the action when the numalink network is extremely delayed @@ -235,10 +236,10 @@ struct bau_msg_payload { /* - * Message header: 16 bytes (128 bits) (bytes 0x30-0x3f of descriptor) + * UV1 Message header: 16 bytes (128 bits) (bytes 0x30-0x3f of descriptor) * see table 4.2.3.0.1 in broacast_assist spec. */ -struct bau_msg_header { +struct uv1_bau_msg_header { unsigned int dest_subnodeid:6; /* must be 0x10, for the LB */ /* bits 5:0 */ unsigned int base_dest_nasid:15; /* nasid of the first bit */ @@ -318,19 +319,87 @@ struct bau_msg_header { }; /* + * UV2 Message header: 16 bytes (128 bits) (bytes 0x30-0x3f of descriptor) + * see figure 9-2 of harp_sys.pdf + */ +struct uv2_bau_msg_header { + unsigned int base_dest_nasid:15; /* nasid of the first bit */ + /* bits 14:0 */ /* in uvhub map */ + unsigned int dest_subnodeid:5; /* must be 0x10, for the LB */ + /* bits 19:15 */ + unsigned int rsvd_1:1; /* must be zero */ + /* bit 20 */ + /* Address bits 59:21 */ + /* bits 25:2 of address (44:21) are payload */ + /* these next 24 bits become bytes 12-14 of msg */ + /* bits 28:21 land in byte 12 */ + unsigned int replied_to:1; /* sent as 0 by the source to + byte 12 */ + /* bit 21 */ + unsigned int msg_type:3; /* software type of the + message */ + /* bits 24:22 */ + unsigned int canceled:1; /* message canceled, resource + is to be freed*/ + /* bit 25 */ + unsigned int payload_1:3; /* not currently used */ + /* bits 28:26 */ + + /* bits 36:29 land in byte 13 */ + unsigned int payload_2a:3; /* not currently used */ + unsigned int payload_2b:5; /* not currently used */ + /* bits 36:29 */ + + /* bits 44:37 land in byte 14 */ + unsigned int payload_3:8; /* not currently used */ + /* bits 44:37 */ + + unsigned int rsvd_2:7; /* reserved */ + /* bits 51:45 */ + unsigned int swack_flag:1; /* software acknowledge flag */ + /* bit 52 */ + unsigned int rsvd_3a:3; /* must be zero */ + unsigned int rsvd_3b:8; /* must be zero */ + unsigned int rsvd_3c:8; /* must be zero */ + unsigned int rsvd_3d:3; /* must be zero */ + /* bits 74:53 */ + unsigned int fairness:3; /* usually zero */ + /* bits 77:75 */ + + unsigned int sequence:16; /* message sequence number */ + /* bits 93:78 Suppl_A */ + unsigned int chaining:1; /* next descriptor is part of + this activation*/ + /* bit 94 */ + unsigned int multilevel:1; /* multi-level multicast + format */ + /* bit 95 */ + unsigned int rsvd_4:24; /* ordered / source node / + source subnode / aging + must be zero */ + /* bits 119:96 */ + unsigned int command:8; /* message type */ + /* bits 127:120 */ +}; + +/* * The activation descriptor: * The format of the message to send, plus all accompanying control * Should be 64 bytes */ struct bau_desc { - struct pnmask distribution; + struct pnmask distribution; /* * message template, consisting of header and payload: */ - struct bau_msg_header header; - struct bau_msg_payload payload; + union bau_msg_header { + struct uv1_bau_msg_header uv1_hdr; + struct uv2_bau_msg_header uv2_hdr; + } header; + + struct bau_msg_payload payload; }; -/* +/* UV1: * -payload-- ---------header------ * bytes 0-11 bits 41-56 bits 58-81 * A B (2) C (3) @@ -340,6 +409,16 @@ struct bau_desc { * bytes 0-11 bytes 12-14 bytes 16-17 (byte 15 filled in by hw as vector) * ------------payload queue----------- */ +/* UV2: + * -payload-- ---------header------ + * bytes 0-11 bits 70-78 bits 21-44 + * A B (2) C (3) + * + * A/B/C are moved to: + * A C B + * bytes 0-11 bytes 12-14 bytes 16-17 (byte 15 filled in by hw as vector) + * ------------payload queue----------- + */ /* * The payload queue on the destination side is an array of these. @@ -385,7 +464,6 @@ struct bau_pq_entry { struct msg_desc { struct bau_pq_entry *msg; int msg_slot; - int swack_slot; struct bau_pq_entry *queue_first; struct bau_pq_entry *queue_last; }; @@ -405,6 +483,7 @@ struct ptc_stats { requests */ unsigned long s_stimeout; /* source side timeouts */ unsigned long s_dtimeout; /* destination side timeouts */ + unsigned long s_strongnacks; /* number of strong nack's */ unsigned long s_time; /* time spent in sending side */ unsigned long s_retriesok; /* successful retries */ unsigned long s_ntargcpu; /* total number of cpu's @@ -439,6 +518,9 @@ struct ptc_stats { unsigned long s_retry_messages; /* retry broadcasts */ unsigned long s_bau_reenabled; /* for bau enable/disable */ unsigned long s_bau_disabled; /* for bau enable/disable */ + unsigned long s_uv2_wars; /* uv2 workaround, perm. busy */ + unsigned long s_uv2_wars_hw; /* uv2 workaround, hiwater */ + unsigned long s_uv2_war_waits; /* uv2 workaround, long waits */ /* destination statistics */ unsigned long d_alltlb; /* times all tlb's on this cpu were flushed */ @@ -511,9 +593,12 @@ struct bau_control { short osnode; short uvhub_cpu; short uvhub; + short uvhub_version; short cpus_in_socket; short cpus_in_uvhub; short partition_base_pnode; + short using_desc; /* an index, like uvhub_cpu */ + unsigned int inuse_map; unsigned short message_number; unsigned short uvhub_quiesce; short socket_acknowledge_count[DEST_Q_SIZE]; @@ -531,6 +616,7 @@ struct bau_control { int cong_response_us; int cong_reps; int cong_period; + unsigned long clocks_per_100_usec; cycles_t period_time; long period_requests; struct hub_and_pnode *thp; @@ -591,6 +677,11 @@ static inline void write_mmr_sw_ack(unsigned long mr) uv_write_local_mmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS, mr); } +static inline void write_gmmr_sw_ack(int pnode, unsigned long mr) +{ + write_gmmr(pnode, UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS, mr); +} + static inline unsigned long read_mmr_sw_ack(void) { return read_lmmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE); diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index c0dd5b60374..a62c201c97e 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -290,14 +290,15 @@ static inline int pit_verify_msb(unsigned char val) static inline int pit_expect_msb(unsigned char val, u64 *tscp, unsigned long *deltap) { int count; - u64 tsc = 0; + u64 tsc = 0, prev_tsc = 0; for (count = 0; count < 50000; count++) { if (!pit_verify_msb(val)) break; + prev_tsc = tsc; tsc = get_cycles(); } - *deltap = get_cycles() - tsc; + *deltap = get_cycles() - prev_tsc; *tscp = tsc; /* @@ -311,9 +312,9 @@ static inline int pit_expect_msb(unsigned char val, u64 *tscp, unsigned long *de * How many MSB values do we want to see? We aim for * a maximum error rate of 500ppm (in practice the * real error is much smaller), but refuse to spend - * more than 25ms on it. + * more than 50ms on it. */ -#define MAX_QUICK_PIT_MS 25 +#define MAX_QUICK_PIT_MS 50 #define MAX_QUICK_PIT_ITERATIONS (MAX_QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256) static unsigned long quick_pit_calibrate(void) @@ -383,15 +384,12 @@ success: * * As a result, we can depend on there not being * any odd delays anywhere, and the TSC reads are - * reliable (within the error). We also adjust the - * delta to the middle of the error bars, just - * because it looks nicer. + * reliable (within the error). * * kHz = ticks / time-in-seconds / 1000; * kHz = (t2 - t1) / (I * 256 / PIT_TICK_RATE) / 1000 * kHz = ((t2 - t1) * PIT_TICK_RATE) / (I * 256 * 1000) */ - delta += (long)(d2 - d1)/2; delta *= PIT_TICK_RATE; do_div(delta, i*256*1000); printk("Fast TSC calibration using PIT\n"); diff --git a/arch/x86/lib/x86-opcode-map.txt b/arch/x86/lib/x86-opcode-map.txt index 5b83c51c12e..81913790442 100644 --- a/arch/x86/lib/x86-opcode-map.txt +++ b/arch/x86/lib/x86-opcode-map.txt @@ -219,7 +219,9 @@ ab: STOS/W/D/Q Yv,rAX ac: LODS/B AL,Xb ad: LODS/W/D/Q rAX,Xv ae: SCAS/B AL,Yb -af: SCAS/W/D/Q rAX,Xv +# Note: The May 2011 Intel manual shows Xv for the second parameter of the +# next instruction but Yv is correct +af: SCAS/W/D/Q rAX,Yv # 0xb0 - 0xbf b0: MOV AL/R8L,Ib b1: MOV CL/R9L,Ib @@ -729,8 +731,8 @@ de: VAESDEC Vdq,Hdq,Wdq (66),(v1) df: VAESDECLAST Vdq,Hdq,Wdq (66),(v1) f0: MOVBE Gy,My | MOVBE Gw,Mw (66) | CRC32 Gd,Eb (F2) f1: MOVBE My,Gy | MOVBE Mw,Gw (66) | CRC32 Gd,Ey (F2) -f3: ANDN Gy,By,Ey (v) -f4: Grp17 (1A) +f2: ANDN Gy,By,Ey (v) +f3: Grp17 (1A) f5: BZHI Gy,Ey,By (v) | PEXT Gy,By,Ey (F3),(v) | PDEP Gy,By,Ey (F2),(v) f6: MULX By,Gy,rDX,Ey (F2),(v) f7: BEXTR Gy,Ey,By (v) | SHLX Gy,Ey,By (66),(v) | SARX Gy,Ey,By (F3),(v) | SHRX Gy,Ey,By (F2),(v) diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index 5b552198f77..9be4cff00a2 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c @@ -157,13 +157,14 @@ static int __init uvhub_to_first_apicid(int uvhub) * clear of the Timeout bit (as well) will free the resource. No reply will * be sent (the hardware will only do one reply per message). */ -static void reply_to_message(struct msg_desc *mdp, struct bau_control *bcp) +static void reply_to_message(struct msg_desc *mdp, struct bau_control *bcp, + int do_acknowledge) { unsigned long dw; struct bau_pq_entry *msg; msg = mdp->msg; - if (!msg->canceled) { + if (!msg->canceled && do_acknowledge) { dw = (msg->swack_vec << UV_SW_ACK_NPENDING) | msg->swack_vec; write_mmr_sw_ack(dw); } @@ -212,8 +213,8 @@ static void bau_process_retry_msg(struct msg_desc *mdp, if (mmr & (msg_res << UV_SW_ACK_NPENDING)) { unsigned long mr; /* - * is the resource timed out? - * make everyone ignore the cancelled message. + * Is the resource timed out? + * Make everyone ignore the cancelled message. */ msg2->canceled = 1; stat->d_canceled++; @@ -231,8 +232,8 @@ static void bau_process_retry_msg(struct msg_desc *mdp, * Do all the things a cpu should do for a TLB shootdown message. * Other cpu's may come here at the same time for this message. */ -static void bau_process_message(struct msg_desc *mdp, - struct bau_control *bcp) +static void bau_process_message(struct msg_desc *mdp, struct bau_control *bcp, + int do_acknowledge) { short socket_ack_count = 0; short *sp; @@ -284,8 +285,9 @@ static void bau_process_message(struct msg_desc *mdp, if (msg_ack_count == bcp->cpus_in_uvhub) { /* * All cpus in uvhub saw it; reply + * (unless we are in the UV2 workaround) */ - reply_to_message(mdp, bcp); + reply_to_message(mdp, bcp, do_acknowledge); } } @@ -491,27 +493,138 @@ static int uv1_wait_completion(struct bau_desc *bau_desc, /* * UV2 has an extra bit of status in the ACTIVATION_STATUS_2 register. */ -static unsigned long uv2_read_status(unsigned long offset, int rshft, int cpu) +static unsigned long uv2_read_status(unsigned long offset, int rshft, int desc) { unsigned long descriptor_status; unsigned long descriptor_status2; descriptor_status = ((read_lmmr(offset) >> rshft) & UV_ACT_STATUS_MASK); - descriptor_status2 = (read_mmr_uv2_status() >> cpu) & 0x1UL; + descriptor_status2 = (read_mmr_uv2_status() >> desc) & 0x1UL; descriptor_status = (descriptor_status << 1) | descriptor_status2; return descriptor_status; } +/* + * Return whether the status of the descriptor that is normally used for this + * cpu (the one indexed by its hub-relative cpu number) is busy. + * The status of the original 32 descriptors is always reflected in the 64 + * bits of UVH_LB_BAU_SB_ACTIVATION_STATUS_0. + * The bit provided by the activation_status_2 register is irrelevant to + * the status if it is only being tested for busy or not busy. + */ +int normal_busy(struct bau_control *bcp) +{ + int cpu = bcp->uvhub_cpu; + int mmr_offset; + int right_shift; + + mmr_offset = UVH_LB_BAU_SB_ACTIVATION_STATUS_0; + right_shift = cpu * UV_ACT_STATUS_SIZE; + return (((((read_lmmr(mmr_offset) >> right_shift) & + UV_ACT_STATUS_MASK)) << 1) == UV2H_DESC_BUSY); +} + +/* + * Entered when a bau descriptor has gone into a permanent busy wait because + * of a hardware bug. + * Workaround the bug. + */ +int handle_uv2_busy(struct bau_control *bcp) +{ + int busy_one = bcp->using_desc; + int normal = bcp->uvhub_cpu; + int selected = -1; + int i; + unsigned long descriptor_status; + unsigned long status; + int mmr_offset; + struct bau_desc *bau_desc_old; + struct bau_desc *bau_desc_new; + struct bau_control *hmaster = bcp->uvhub_master; + struct ptc_stats *stat = bcp->statp; + cycles_t ttm; + + stat->s_uv2_wars++; + spin_lock(&hmaster->uvhub_lock); + /* try for the original first */ + if (busy_one != normal) { + if (!normal_busy(bcp)) + selected = normal; + } + if (selected < 0) { + /* can't use the normal, select an alternate */ + mmr_offset = UVH_LB_BAU_SB_ACTIVATION_STATUS_1; + descriptor_status = read_lmmr(mmr_offset); + + /* scan available descriptors 32-63 */ + for (i = 0; i < UV_CPUS_PER_AS; i++) { + if ((hmaster->inuse_map & (1 << i)) == 0) { + status = ((descriptor_status >> + (i * UV_ACT_STATUS_SIZE)) & + UV_ACT_STATUS_MASK) << 1; + if (status != UV2H_DESC_BUSY) { + selected = i + UV_CPUS_PER_AS; + break; + } + } + } + } + + if (busy_one != normal) + /* mark the busy alternate as not in-use */ + hmaster->inuse_map &= ~(1 << (busy_one - UV_CPUS_PER_AS)); + + if (selected >= 0) { + /* switch to the selected descriptor */ + if (selected != normal) { + /* set the selected alternate as in-use */ + hmaster->inuse_map |= + (1 << (selected - UV_CPUS_PER_AS)); + if (selected > stat->s_uv2_wars_hw) + stat->s_uv2_wars_hw = selected; + } + bau_desc_old = bcp->descriptor_base; + bau_desc_old += (ITEMS_PER_DESC * busy_one); + bcp->using_desc = selected; + bau_desc_new = bcp->descriptor_base; + bau_desc_new += (ITEMS_PER_DESC * selected); + *bau_desc_new = *bau_desc_old; + } else { + /* + * All are busy. Wait for the normal one for this cpu to + * free up. + */ + stat->s_uv2_war_waits++; + spin_unlock(&hmaster->uvhub_lock); + ttm = get_cycles(); + do { + cpu_relax(); + } while (normal_busy(bcp)); + spin_lock(&hmaster->uvhub_lock); + /* switch to the original descriptor */ + bcp->using_desc = normal; + bau_desc_old = bcp->descriptor_base; + bau_desc_old += (ITEMS_PER_DESC * bcp->using_desc); + bcp->using_desc = (ITEMS_PER_DESC * normal); + bau_desc_new = bcp->descriptor_base; + bau_desc_new += (ITEMS_PER_DESC * normal); + *bau_desc_new = *bau_desc_old; /* copy the entire descriptor */ + } + spin_unlock(&hmaster->uvhub_lock); + return FLUSH_RETRY_BUSYBUG; +} + static int uv2_wait_completion(struct bau_desc *bau_desc, unsigned long mmr_offset, int right_shift, struct bau_control *bcp, long try) { unsigned long descriptor_stat; cycles_t ttm; - int cpu = bcp->uvhub_cpu; + int desc = bcp->using_desc; + long busy_reps = 0; struct ptc_stats *stat = bcp->statp; - descriptor_stat = uv2_read_status(mmr_offset, right_shift, cpu); + descriptor_stat = uv2_read_status(mmr_offset, right_shift, desc); /* spin on the status MMR, waiting for it to go idle */ while (descriptor_stat != UV2H_DESC_IDLE) { @@ -522,32 +635,35 @@ static int uv2_wait_completion(struct bau_desc *bau_desc, * our message and its state will stay IDLE. */ if ((descriptor_stat == UV2H_DESC_SOURCE_TIMEOUT) || - (descriptor_stat == UV2H_DESC_DEST_STRONG_NACK) || (descriptor_stat == UV2H_DESC_DEST_PUT_ERR)) { stat->s_stimeout++; return FLUSH_GIVEUP; + } else if (descriptor_stat == UV2H_DESC_DEST_STRONG_NACK) { + stat->s_strongnacks++; + bcp->conseccompletes = 0; + return FLUSH_GIVEUP; } else if (descriptor_stat == UV2H_DESC_DEST_TIMEOUT) { stat->s_dtimeout++; - ttm = get_cycles(); - /* - * Our retries may be blocked by all destination - * swack resources being consumed, and a timeout - * pending. In that case hardware returns the - * ERROR that looks like a destination timeout. - */ - if (cycles_2_us(ttm - bcp->send_message) < timeout_us) { - bcp->conseccompletes = 0; - return FLUSH_RETRY_PLUGGED; - } bcp->conseccompletes = 0; return FLUSH_RETRY_TIMEOUT; } else { + busy_reps++; + if (busy_reps > 1000000) { + /* not to hammer on the clock */ + busy_reps = 0; + ttm = get_cycles(); + if ((ttm - bcp->send_message) > + (bcp->clocks_per_100_usec)) { + return handle_uv2_busy(bcp); + } + } /* * descriptor_stat is still BUSY */ cpu_relax(); } - descriptor_stat = uv2_read_status(mmr_offset, right_shift, cpu); + descriptor_stat = uv2_read_status(mmr_offset, right_shift, + desc); } bcp->conseccompletes++; return FLUSH_COMPLETE; @@ -563,17 +679,17 @@ static int wait_completion(struct bau_desc *bau_desc, { int right_shift; unsigned long mmr_offset; - int cpu = bcp->uvhub_cpu; + int desc = bcp->using_desc; - if (cpu < UV_CPUS_PER_AS) { + if (desc < UV_CPUS_PER_AS) { mmr_offset = UVH_LB_BAU_SB_ACTIVATION_STATUS_0; - right_shift = cpu * UV_ACT_STATUS_SIZE; + right_shift = desc * UV_ACT_STATUS_SIZE; } else { mmr_offset = UVH_LB_BAU_SB_ACTIVATION_STATUS_1; - right_shift = ((cpu - UV_CPUS_PER_AS) * UV_ACT_STATUS_SIZE); + right_shift = ((desc - UV_CPUS_PER_AS) * UV_ACT_STATUS_SIZE); } - if (is_uv1_hub()) + if (bcp->uvhub_version == 1) return uv1_wait_completion(bau_desc, mmr_offset, right_shift, bcp, try); else @@ -752,19 +868,22 @@ static void handle_cmplt(int completion_status, struct bau_desc *bau_desc, * Returns 1 if it gives up entirely and the original cpu mask is to be * returned to the kernel. */ -int uv_flush_send_and_wait(struct bau_desc *bau_desc, - struct cpumask *flush_mask, struct bau_control *bcp) +int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp) { int seq_number = 0; int completion_stat = 0; + int uv1 = 0; long try = 0; unsigned long index; cycles_t time1; cycles_t time2; struct ptc_stats *stat = bcp->statp; struct bau_control *hmaster = bcp->uvhub_master; + struct uv1_bau_msg_header *uv1_hdr = NULL; + struct uv2_bau_msg_header *uv2_hdr = NULL; + struct bau_desc *bau_desc; - if (is_uv1_hub()) + if (bcp->uvhub_version == 1) uv1_throttle(hmaster, stat); while (hmaster->uvhub_quiesce) @@ -772,22 +891,39 @@ int uv_flush_send_and_wait(struct bau_desc *bau_desc, time1 = get_cycles(); do { - if (try == 0) { - bau_desc->header.msg_type = MSG_REGULAR; + bau_desc = bcp->descriptor_base; + bau_desc += (ITEMS_PER_DESC * bcp->using_desc); + if (bcp->uvhub_version == 1) { + uv1 = 1; + uv1_hdr = &bau_desc->header.uv1_hdr; + } else + uv2_hdr = &bau_desc->header.uv2_hdr; + if ((try == 0) || (completion_stat == FLUSH_RETRY_BUSYBUG)) { + if (uv1) + uv1_hdr->msg_type = MSG_REGULAR; + else + uv2_hdr->msg_type = MSG_REGULAR; seq_number = bcp->message_number++; } else { - bau_desc->header.msg_type = MSG_RETRY; + if (uv1) + uv1_hdr->msg_type = MSG_RETRY; + else + uv2_hdr->msg_type = MSG_RETRY; stat->s_retry_messages++; } - bau_desc->header.sequence = seq_number; - index = (1UL << AS_PUSH_SHIFT) | bcp->uvhub_cpu; + if (uv1) + uv1_hdr->sequence = seq_number; + else + uv2_hdr->sequence = seq_number; + index = (1UL << AS_PUSH_SHIFT) | bcp->using_desc; bcp->send_message = get_cycles(); write_mmr_activation(index); try++; completion_stat = wait_completion(bau_desc, bcp, try); + /* UV2: wait_completion() may change the bcp->using_desc */ handle_cmplt(completion_stat, bau_desc, bcp, hmaster, stat); @@ -798,6 +934,7 @@ int uv_flush_send_and_wait(struct bau_desc *bau_desc, } cpu_relax(); } while ((completion_stat == FLUSH_RETRY_PLUGGED) || + (completion_stat == FLUSH_RETRY_BUSYBUG) || (completion_stat == FLUSH_RETRY_TIMEOUT)); time2 = get_cycles(); @@ -812,6 +949,7 @@ int uv_flush_send_and_wait(struct bau_desc *bau_desc, record_send_stats(time1, time2, bcp, stat, completion_stat, try); if (completion_stat == FLUSH_GIVEUP) + /* FLUSH_GIVEUP will fall back to using IPI's for tlb flush */ return 1; return 0; } @@ -967,7 +1105,7 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, stat->s_ntargself++; bau_desc = bcp->descriptor_base; - bau_desc += ITEMS_PER_DESC * bcp->uvhub_cpu; + bau_desc += (ITEMS_PER_DESC * bcp->using_desc); bau_uvhubs_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE); if (set_distrib_bits(flush_mask, bcp, bau_desc, &locals, &remotes)) return NULL; @@ -980,13 +1118,86 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, * uv_flush_send_and_wait returns 0 if all cpu's were messaged, * or 1 if it gave up and the original cpumask should be returned. */ - if (!uv_flush_send_and_wait(bau_desc, flush_mask, bcp)) + if (!uv_flush_send_and_wait(flush_mask, bcp)) return NULL; else return cpumask; } /* + * Search the message queue for any 'other' message with the same software + * acknowledge resource bit vector. + */ +struct bau_pq_entry *find_another_by_swack(struct bau_pq_entry *msg, + struct bau_control *bcp, unsigned char swack_vec) +{ + struct bau_pq_entry *msg_next = msg + 1; + + if (msg_next > bcp->queue_last) + msg_next = bcp->queue_first; + while ((msg_next->swack_vec != 0) && (msg_next != msg)) { + if (msg_next->swack_vec == swack_vec) + return msg_next; + msg_next++; + if (msg_next > bcp->queue_last) + msg_next = bcp->queue_first; + } + return NULL; +} + +/* + * UV2 needs to work around a bug in which an arriving message has not + * set a bit in the UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE register. + * Such a message must be ignored. + */ +void process_uv2_message(struct msg_desc *mdp, struct bau_control *bcp) +{ + unsigned long mmr_image; + unsigned char swack_vec; + struct bau_pq_entry *msg = mdp->msg; + struct bau_pq_entry *other_msg; + + mmr_image = read_mmr_sw_ack(); + swack_vec = msg->swack_vec; + + if ((swack_vec & mmr_image) == 0) { + /* + * This message was assigned a swack resource, but no + * reserved acknowlegment is pending. + * The bug has prevented this message from setting the MMR. + * And no other message has used the same sw_ack resource. + * Do the requested shootdown but do not reply to the msg. + * (the 0 means make no acknowledge) + */ + bau_process_message(mdp, bcp, 0); + return; + } + + /* + * Some message has set the MMR 'pending' bit; it might have been + * another message. Look for that message. + */ + other_msg = find_another_by_swack(msg, bcp, msg->swack_vec); + if (other_msg) { + /* There is another. Do not ack the current one. */ + bau_process_message(mdp, bcp, 0); + /* + * Let the natural processing of that message acknowledge + * it. Don't get the processing of sw_ack's out of order. + */ + return; + } + + /* + * There is no other message using this sw_ack, so it is safe to + * acknowledge it. + */ + bau_process_message(mdp, bcp, 1); + + return; +} + +/* * The BAU message interrupt comes here. (registered by set_intr_gate) * See entry_64.S * @@ -1009,6 +1220,7 @@ void uv_bau_message_interrupt(struct pt_regs *regs) struct ptc_stats *stat; struct msg_desc msgdesc; + ack_APIC_irq(); time_start = get_cycles(); bcp = &per_cpu(bau_control, smp_processor_id()); @@ -1022,9 +1234,11 @@ void uv_bau_message_interrupt(struct pt_regs *regs) count++; msgdesc.msg_slot = msg - msgdesc.queue_first; - msgdesc.swack_slot = ffs(msg->swack_vec) - 1; msgdesc.msg = msg; - bau_process_message(&msgdesc, bcp); + if (bcp->uvhub_version == 2) + process_uv2_message(&msgdesc, bcp); + else + bau_process_message(&msgdesc, bcp, 1); msg++; if (msg > msgdesc.queue_last) @@ -1036,8 +1250,6 @@ void uv_bau_message_interrupt(struct pt_regs *regs) stat->d_nomsg++; else if (count > 1) stat->d_multmsg++; - - ack_APIC_irq(); } /* @@ -1083,7 +1295,7 @@ static void __init enable_timeouts(void) */ mmr_image |= (1L << SOFTACK_MSHIFT); if (is_uv2_hub()) { - mmr_image |= (1L << UV2_LEG_SHFT); + mmr_image &= ~(1L << UV2_LEG_SHFT); mmr_image |= (1L << UV2_EXT_SHFT); } write_mmr_misc_control(pnode, mmr_image); @@ -1136,13 +1348,13 @@ static int ptc_seq_show(struct seq_file *file, void *data) seq_printf(file, "remotehub numuvhubs numuvhubs16 numuvhubs8 "); seq_printf(file, - "numuvhubs4 numuvhubs2 numuvhubs1 dto retries rok "); + "numuvhubs4 numuvhubs2 numuvhubs1 dto snacks retries rok "); seq_printf(file, "resetp resett giveup sto bz throt swack recv rtime "); seq_printf(file, "all one mult none retry canc nocan reset rcan "); seq_printf(file, - "disable enable\n"); + "disable enable wars warshw warwaits\n"); } if (cpu < num_possible_cpus() && cpu_online(cpu)) { stat = &per_cpu(ptcstats, cpu); @@ -1154,10 +1366,10 @@ static int ptc_seq_show(struct seq_file *file, void *data) stat->s_ntargremotes, stat->s_ntargcpu, stat->s_ntarglocaluvhub, stat->s_ntargremoteuvhub, stat->s_ntarguvhub, stat->s_ntarguvhub16); - seq_printf(file, "%ld %ld %ld %ld %ld ", + seq_printf(file, "%ld %ld %ld %ld %ld %ld ", stat->s_ntarguvhub8, stat->s_ntarguvhub4, stat->s_ntarguvhub2, stat->s_ntarguvhub1, - stat->s_dtimeout); + stat->s_dtimeout, stat->s_strongnacks); seq_printf(file, "%ld %ld %ld %ld %ld %ld %ld %ld ", stat->s_retry_messages, stat->s_retriesok, stat->s_resets_plug, stat->s_resets_timeout, @@ -1173,8 +1385,10 @@ static int ptc_seq_show(struct seq_file *file, void *data) stat->d_nomsg, stat->d_retries, stat->d_canceled, stat->d_nocanceled, stat->d_resets, stat->d_rcanceled); - seq_printf(file, "%ld %ld\n", - stat->s_bau_disabled, stat->s_bau_reenabled); + seq_printf(file, "%ld %ld %ld %ld %ld\n", + stat->s_bau_disabled, stat->s_bau_reenabled, + stat->s_uv2_wars, stat->s_uv2_wars_hw, + stat->s_uv2_war_waits); } return 0; } @@ -1432,12 +1646,15 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode) { int i; int cpu; + int uv1 = 0; unsigned long gpa; unsigned long m; unsigned long n; size_t dsize; struct bau_desc *bau_desc; struct bau_desc *bd2; + struct uv1_bau_msg_header *uv1_hdr; + struct uv2_bau_msg_header *uv2_hdr; struct bau_control *bcp; /* @@ -1451,6 +1668,8 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode) gpa = uv_gpa(bau_desc); n = uv_gpa_to_gnode(gpa); m = uv_gpa_to_offset(gpa); + if (is_uv1_hub()) + uv1 = 1; /* the 14-bit pnode */ write_mmr_descriptor_base(pnode, (n << UV_DESC_PSHIFT | m)); @@ -1461,21 +1680,33 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode) */ for (i = 0, bd2 = bau_desc; i < (ADP_SZ * ITEMS_PER_DESC); i++, bd2++) { memset(bd2, 0, sizeof(struct bau_desc)); - bd2->header.swack_flag = 1; - /* - * The base_dest_nasid set in the message header is the nasid - * of the first uvhub in the partition. The bit map will - * indicate destination pnode numbers relative to that base. - * They may not be consecutive if nasid striding is being used. - */ - bd2->header.base_dest_nasid = UV_PNODE_TO_NASID(base_pnode); - bd2->header.dest_subnodeid = UV_LB_SUBNODEID; - bd2->header.command = UV_NET_ENDPOINT_INTD; - bd2->header.int_both = 1; - /* - * all others need to be set to zero: - * fairness chaining multilevel count replied_to - */ + if (uv1) { + uv1_hdr = &bd2->header.uv1_hdr; + uv1_hdr->swack_flag = 1; + /* + * The base_dest_nasid set in the message header + * is the nasid of the first uvhub in the partition. + * The bit map will indicate destination pnode numbers + * relative to that base. They may not be consecutive + * if nasid striding is being used. + */ + uv1_hdr->base_dest_nasid = + UV_PNODE_TO_NASID(base_pnode); + uv1_hdr->dest_subnodeid = UV_LB_SUBNODEID; + uv1_hdr->command = UV_NET_ENDPOINT_INTD; + uv1_hdr->int_both = 1; + /* + * all others need to be set to zero: + * fairness chaining multilevel count replied_to + */ + } else { + uv2_hdr = &bd2->header.uv2_hdr; + uv2_hdr->swack_flag = 1; + uv2_hdr->base_dest_nasid = + UV_PNODE_TO_NASID(base_pnode); + uv2_hdr->dest_subnodeid = UV_LB_SUBNODEID; + uv2_hdr->command = UV_NET_ENDPOINT_INTD; + } } for_each_present_cpu(cpu) { if (pnode != uv_blade_to_pnode(uv_cpu_to_blade_id(cpu))) @@ -1531,6 +1762,7 @@ static void pq_init(int node, int pnode) write_mmr_payload_first(pnode, pn_first); write_mmr_payload_tail(pnode, first); write_mmr_payload_last(pnode, last); + write_gmmr_sw_ack(pnode, 0xffffUL); /* in effect, all msg_type's are set to MSG_NOOP */ memset(pqp, 0, sizeof(struct bau_pq_entry) * DEST_Q_SIZE); @@ -1584,14 +1816,14 @@ static int calculate_destination_timeout(void) ts_ns = base * mult1 * mult2; ret = ts_ns / 1000; } else { - /* 4 bits 0/1 for 10/80us, 3 bits of multiplier */ - mmr_image = uv_read_local_mmr(UVH_AGING_PRESCALE_SEL); + /* 4 bits 0/1 for 10/80us base, 3 bits of multiplier */ + mmr_image = uv_read_local_mmr(UVH_LB_BAU_MISC_CONTROL); mmr_image = (mmr_image & UV_SA_MASK) >> UV_SA_SHFT; if (mmr_image & (1L << UV2_ACK_UNITS_SHFT)) - mult1 = 80; + base = 80; else - mult1 = 10; - base = mmr_image & UV2_ACK_MASK; + base = 10; + mult1 = mmr_image & UV2_ACK_MASK; ret = mult1 * base; } return ret; @@ -1618,6 +1850,7 @@ static void __init init_per_cpu_tunables(void) bcp->cong_response_us = congested_respns_us; bcp->cong_reps = congested_reps; bcp->cong_period = congested_period; + bcp->clocks_per_100_usec = usec_2_cycles(100); } } @@ -1728,8 +1961,17 @@ static int scan_sock(struct socket_desc *sdp, struct uvhub_desc *bdp, bcp->cpus_in_socket = sdp->num_cpus; bcp->socket_master = *smasterp; bcp->uvhub = bdp->uvhub; + if (is_uv1_hub()) + bcp->uvhub_version = 1; + else if (is_uv2_hub()) + bcp->uvhub_version = 2; + else { + printk(KERN_EMERG "uvhub version not 1 or 2\n"); + return 1; + } bcp->uvhub_master = *hmasterp; bcp->uvhub_cpu = uv_cpu_hub_info(cpu)->blade_processor_id; + bcp->using_desc = bcp->uvhub_cpu; if (bcp->uvhub_cpu >= MAX_CPUS_PER_UVHUB) { printk(KERN_EMERG "%d cpus per uvhub invalid\n", bcp->uvhub_cpu); @@ -1845,6 +2087,8 @@ static int __init uv_bau_init(void) uv_base_pnode = uv_blade_to_pnode(uvhub); } + enable_timeouts(); + if (init_per_cpu(nuvhubs, uv_base_pnode)) { nobau = 1; return 0; @@ -1855,7 +2099,6 @@ static int __init uv_bau_init(void) if (uv_blade_nr_possible_cpus(uvhub)) init_uvhub(uvhub, vector, uv_base_pnode); - enable_timeouts(); alloc_intr_gate(vector, uv_bau_message_intr1); for_each_possible_blade(uvhub) { @@ -1867,7 +2110,8 @@ static int __init uv_bau_init(void) val = 1L << 63; write_gmmr_activation(pnode, val); mmr = 1; /* should be 1 to broadcast to both sockets */ - write_mmr_data_broadcast(pnode, mmr); + if (!is_uv1_hub()) + write_mmr_data_broadcast(pnode, mmr); } } diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 37c4bd1cacd..d0c41188d4e 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -87,6 +87,7 @@ config GPIO_GENERIC_PLATFORM config GPIO_IT8761E tristate "IT8761E GPIO support" + depends on X86 # unconditional access to IO space. help Say yes here to support GPIO functionality of IT8761E super I/O chip. diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index 461958fc226..03d6dd5dcb7 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -248,7 +248,7 @@ static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port) static int ioh_irq_type(struct irq_data *d, unsigned int type) { u32 im; - u32 *im_reg; + void __iomem *im_reg; u32 ien; u32 im_pos; int ch; @@ -412,7 +412,7 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev, int i, j; struct ioh_gpio *chip; void __iomem *base; - void __iomem *chip_save; + void *chip_save; int irq_base; ret = pci_enable_device(pdev); @@ -428,7 +428,7 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev, } base = pci_iomap(pdev, 1, 0); - if (base == 0) { + if (!base) { dev_err(&pdev->dev, "%s : pci_iomap failed", __func__); ret = -ENOMEM; goto err_iomap; @@ -521,7 +521,7 @@ static void __devexit ioh_gpio_remove(struct pci_dev *pdev) int err; int i; struct ioh_gpio *chip = pci_get_drvdata(pdev); - void __iomem *chip_save; + void *chip_save; chip_save = chip; diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index f0603297f82..68fa55e86eb 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -231,7 +231,7 @@ static void pch_gpio_setup(struct pch_gpio *chip) static int pch_irq_type(struct irq_data *d, unsigned int type) { u32 im; - u32 *im_reg; + u32 __iomem *im_reg; u32 ien; u32 im_pos; int ch; @@ -376,7 +376,7 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev, } chip->base = pci_iomap(pdev, 1, 0); - if (chip->base == 0) { + if (!chip->base) { dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__); ret = -ENOMEM; goto err_iomap; diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c index b9c1c297669..91f45b965d1 100644 --- a/drivers/gpio/gpio-tps65910.c +++ b/drivers/gpio/gpio-tps65910.c @@ -52,7 +52,7 @@ static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset, struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); /* Set the initial value */ - tps65910_gpio_set(gc, 0, value); + tps65910_gpio_set(gc, offset, value); return tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset, GPIO_CFG_MASK); diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c index 63be60bc345..86cc3f7841c 100644 --- a/drivers/mfd/mcp-core.c +++ b/drivers/mfd/mcp-core.c @@ -26,35 +26,9 @@ #define to_mcp(d) container_of(d, struct mcp, attached_device) #define to_mcp_driver(d) container_of(d, struct mcp_driver, drv) -static const struct mcp_device_id *mcp_match_id(const struct mcp_device_id *id, - const char *codec) -{ - while (id->name[0]) { - if (strcmp(codec, id->name) == 0) - return id; - id++; - } - return NULL; -} - -const struct mcp_device_id *mcp_get_device_id(const struct mcp *mcp) -{ - const struct mcp_driver *driver = - to_mcp_driver(mcp->attached_device.driver); - - return mcp_match_id(driver->id_table, mcp->codec); -} -EXPORT_SYMBOL(mcp_get_device_id); - static int mcp_bus_match(struct device *dev, struct device_driver *drv) { - const struct mcp *mcp = to_mcp(dev); - const struct mcp_driver *driver = to_mcp_driver(drv); - - if (driver->id_table) - return !!mcp_match_id(driver->id_table, mcp->codec); - - return 0; + return 1; } static int mcp_bus_probe(struct device *dev) @@ -100,18 +74,9 @@ static int mcp_bus_resume(struct device *dev) return ret; } -static int mcp_bus_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - struct mcp *mcp = to_mcp(dev); - - add_uevent_var(env, "MODALIAS=%s%s", MCP_MODULE_PREFIX, mcp->codec); - return 0; -} - static struct bus_type mcp_bus_type = { .name = "mcp", .match = mcp_bus_match, - .uevent = mcp_bus_uevent, .probe = mcp_bus_probe, .remove = mcp_bus_remove, .suspend = mcp_bus_suspend, @@ -128,9 +93,11 @@ static struct bus_type mcp_bus_type = { */ void mcp_set_telecom_divisor(struct mcp *mcp, unsigned int div) { - spin_lock_irq(&mcp->lock); + unsigned long flags; + + spin_lock_irqsave(&mcp->lock, flags); mcp->ops->set_telecom_divisor(mcp, div); - spin_unlock_irq(&mcp->lock); + spin_unlock_irqrestore(&mcp->lock, flags); } EXPORT_SYMBOL(mcp_set_telecom_divisor); @@ -143,9 +110,11 @@ EXPORT_SYMBOL(mcp_set_telecom_divisor); */ void mcp_set_audio_divisor(struct mcp *mcp, unsigned int div) { - spin_lock_irq(&mcp->lock); + unsigned long flags; + + spin_lock_irqsave(&mcp->lock, flags); mcp->ops->set_audio_divisor(mcp, div); - spin_unlock_irq(&mcp->lock); + spin_unlock_irqrestore(&mcp->lock, flags); } EXPORT_SYMBOL(mcp_set_audio_divisor); @@ -198,10 +167,11 @@ EXPORT_SYMBOL(mcp_reg_read); */ void mcp_enable(struct mcp *mcp) { - spin_lock_irq(&mcp->lock); + unsigned long flags; + spin_lock_irqsave(&mcp->lock, flags); if (mcp->use_count++ == 0) mcp->ops->enable(mcp); - spin_unlock_irq(&mcp->lock); + spin_unlock_irqrestore(&mcp->lock, flags); } EXPORT_SYMBOL(mcp_enable); @@ -247,14 +217,9 @@ struct mcp *mcp_host_alloc(struct device *parent, size_t size) } EXPORT_SYMBOL(mcp_host_alloc); -int mcp_host_register(struct mcp *mcp, void *pdata) +int mcp_host_register(struct mcp *mcp) { - if (!mcp->codec) - return -EINVAL; - - mcp->attached_device.platform_data = pdata; dev_set_name(&mcp->attached_device, "mcp0"); - request_module("%s%s", MCP_MODULE_PREFIX, mcp->codec); return device_register(&mcp->attached_device); } EXPORT_SYMBOL(mcp_host_register); diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c index 9adc2eb6949..02c53a0766c 100644 --- a/drivers/mfd/mcp-sa11x0.c +++ b/drivers/mfd/mcp-sa11x0.c @@ -19,7 +19,6 @@ #include <linux/spinlock.h> #include <linux/platform_device.h> #include <linux/mfd/mcp.h> -#include <linux/io.h> #include <mach/dma.h> #include <mach/hardware.h> @@ -27,19 +26,12 @@ #include <asm/system.h> #include <mach/mcp.h> -/* Register offsets */ -#define MCCR0 0x00 -#define MCDR0 0x08 -#define MCDR1 0x0C -#define MCDR2 0x10 -#define MCSR 0x18 -#define MCCR1 0x00 +#include <mach/assabet.h> + struct mcp_sa11x0 { - u32 mccr0; - u32 mccr1; - unsigned char *mccr0_base; - unsigned char *mccr1_base; + u32 mccr0; + u32 mccr1; }; #define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp)) @@ -47,25 +39,25 @@ struct mcp_sa11x0 { static void mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor) { - struct mcp_sa11x0 *priv = priv(mcp); + unsigned int mccr0; divisor /= 32; - priv->mccr0 &= ~0x00007f00; - priv->mccr0 |= divisor << 8; - __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0); + mccr0 = Ser4MCCR0 & ~0x00007f00; + mccr0 |= divisor << 8; + Ser4MCCR0 = mccr0; } static void mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor) { - struct mcp_sa11x0 *priv = priv(mcp); + unsigned int mccr0; divisor /= 32; - priv->mccr0 &= ~0x0000007f; - priv->mccr0 |= divisor; - __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0); + mccr0 = Ser4MCCR0 & ~0x0000007f; + mccr0 |= divisor; + Ser4MCCR0 = mccr0; } /* @@ -79,16 +71,12 @@ mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val) { int ret = -ETIME; int i; - u32 mcpreg; - struct mcp_sa11x0 *priv = priv(mcp); - mcpreg = reg << 17 | MCDR2_Wr | (val & 0xffff); - __raw_writel(mcpreg, priv->mccr0_base + MCDR2); + Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff); for (i = 0; i < 2; i++) { udelay(mcp->rw_timeout); - mcpreg = __raw_readl(priv->mccr0_base + MCSR); - if (mcpreg & MCSR_CWC) { + if (Ser4MCSR & MCSR_CWC) { ret = 0; break; } @@ -109,18 +97,13 @@ mcp_sa11x0_read(struct mcp *mcp, unsigned int reg) { int ret = -ETIME; int i; - u32 mcpreg; - struct mcp_sa11x0 *priv = priv(mcp); - mcpreg = reg << 17 | MCDR2_Rd; - __raw_writel(mcpreg, priv->mccr0_base + MCDR2); + Ser4MCDR2 = reg << 17 | MCDR2_Rd; for (i = 0; i < 2; i++) { udelay(mcp->rw_timeout); - mcpreg = __raw_readl(priv->mccr0_base + MCSR); - if (mcpreg & MCSR_CRC) { - ret = __raw_readl(priv->mccr0_base + MCDR2) - & 0xffff; + if (Ser4MCSR & MCSR_CRC) { + ret = Ser4MCDR2 & 0xffff; break; } } @@ -133,19 +116,13 @@ mcp_sa11x0_read(struct mcp *mcp, unsigned int reg) static void mcp_sa11x0_enable(struct mcp *mcp) { - struct mcp_sa11x0 *priv = priv(mcp); - - __raw_writel(-1, priv->mccr0_base + MCSR); - priv->mccr0 |= MCCR0_MCE; - __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0); + Ser4MCSR = -1; + Ser4MCCR0 |= MCCR0_MCE; } static void mcp_sa11x0_disable(struct mcp *mcp) { - struct mcp_sa11x0 *priv = priv(mcp); - - priv->mccr0 &= ~MCCR0_MCE; - __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0); + Ser4MCCR0 &= ~MCCR0_MCE; } /* @@ -165,69 +142,50 @@ static int mcp_sa11x0_probe(struct platform_device *pdev) struct mcp_plat_data *data = pdev->dev.platform_data; struct mcp *mcp; int ret; - struct mcp_sa11x0 *priv; - struct resource *res_mem0, *res_mem1; - u32 size0, size1; if (!data) return -ENODEV; - if (!data->codec) - return -ENODEV; - - res_mem0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res_mem0) - return -ENODEV; - size0 = res_mem0->end - res_mem0->start + 1; - - res_mem1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!res_mem1) - return -ENODEV; - size1 = res_mem1->end - res_mem1->start + 1; - - if (!request_mem_region(res_mem0->start, size0, "sa11x0-mcp")) + if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp")) return -EBUSY; - if (!request_mem_region(res_mem1->start, size1, "sa11x0-mcp")) { - ret = -EBUSY; - goto release; - } - mcp = mcp_host_alloc(&pdev->dev, sizeof(struct mcp_sa11x0)); if (!mcp) { ret = -ENOMEM; - goto release2; + goto release; } - priv = priv(mcp); - mcp->owner = THIS_MODULE; mcp->ops = &mcp_sa11x0; mcp->sclk_rate = data->sclk_rate; - mcp->dma_audio_rd = DDAR_DevAdd(res_mem0->start + MCDR0) - + DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev; - mcp->dma_audio_wr = DDAR_DevAdd(res_mem0->start + MCDR0) - + DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev; - mcp->dma_telco_rd = DDAR_DevAdd(res_mem0->start + MCDR1) - + DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev; - mcp->dma_telco_wr = DDAR_DevAdd(res_mem0->start + MCDR1) - + DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev; - mcp->codec = data->codec; + mcp->dma_audio_rd = DMA_Ser4MCP0Rd; + mcp->dma_audio_wr = DMA_Ser4MCP0Wr; + mcp->dma_telco_rd = DMA_Ser4MCP1Rd; + mcp->dma_telco_wr = DMA_Ser4MCP1Wr; + mcp->gpio_base = data->gpio_base; platform_set_drvdata(pdev, mcp); + if (machine_is_assabet()) { + ASSABET_BCR_set(ASSABET_BCR_CODEC_RST); + } + + /* + * Setup the PPC unit correctly. + */ + PPDR &= ~PPC_RXD4; + PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; + PSDR |= PPC_RXD4; + PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); + PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); + /* * Initialise device. Note that we initially * set the sampling rate to minimum. */ - priv->mccr0_base = ioremap(res_mem0->start, size0); - priv->mccr1_base = ioremap(res_mem1->start, size1); - - __raw_writel(-1, priv->mccr0_base + MCSR); - priv->mccr1 = data->mccr1; - priv->mccr0 = data->mccr0 | 0x7f7f; - __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0); - __raw_writel(priv->mccr1, priv->mccr1_base + MCCR1); + Ser4MCSR = -1; + Ser4MCCR1 = data->mccr1; + Ser4MCCR0 = data->mccr0 | 0x7f7f; /* * Calculate the read/write timeout (us) from the bit clock @@ -237,53 +195,36 @@ static int mcp_sa11x0_probe(struct platform_device *pdev) mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) / mcp->sclk_rate; - ret = mcp_host_register(mcp, data->codec_pdata); + ret = mcp_host_register(mcp); if (ret == 0) goto out; - release2: - release_mem_region(res_mem1->start, size1); release: - release_mem_region(res_mem0->start, size0); + release_mem_region(0x80060000, 0x60); platform_set_drvdata(pdev, NULL); out: return ret; } -static int mcp_sa11x0_remove(struct platform_device *pdev) +static int mcp_sa11x0_remove(struct platform_device *dev) { - struct mcp *mcp = platform_get_drvdata(pdev); - struct mcp_sa11x0 *priv = priv(mcp); - struct resource *res_mem; - u32 size; + struct mcp *mcp = platform_get_drvdata(dev); - platform_set_drvdata(pdev, NULL); + platform_set_drvdata(dev, NULL); mcp_host_unregister(mcp); + release_mem_region(0x80060000, 0x60); - res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res_mem) { - size = res_mem->end - res_mem->start + 1; - release_mem_region(res_mem->start, size); - } - res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (res_mem) { - size = res_mem->end - res_mem->start + 1; - release_mem_region(res_mem->start, size); - } - iounmap(priv->mccr0_base); - iounmap(priv->mccr1_base); return 0; } static int mcp_sa11x0_suspend(struct platform_device *dev, pm_message_t state) { struct mcp *mcp = platform_get_drvdata(dev); - struct mcp_sa11x0 *priv = priv(mcp); - u32 mccr0; - mccr0 = priv->mccr0 & ~MCCR0_MCE; - __raw_writel(mccr0, priv->mccr0_base + MCCR0); + priv(mcp)->mccr0 = Ser4MCCR0; + priv(mcp)->mccr1 = Ser4MCCR1; + Ser4MCCR0 &= ~MCCR0_MCE; return 0; } @@ -291,10 +232,9 @@ static int mcp_sa11x0_suspend(struct platform_device *dev, pm_message_t state) static int mcp_sa11x0_resume(struct platform_device *dev) { struct mcp *mcp = platform_get_drvdata(dev); - struct mcp_sa11x0 *priv = priv(mcp); - __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0); - __raw_writel(priv->mccr1, priv->mccr1_base + MCCR1); + Ser4MCCR1 = priv(mcp)->mccr1; + Ser4MCCR0 = priv(mcp)->mccr0; return 0; } @@ -311,7 +251,6 @@ static struct platform_driver mcp_sa11x0_driver = { .resume = mcp_sa11x0_resume, .driver = { .name = "sa11x0-mcp", - .owner = THIS_MODULE, }, }; diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index 91c4f25e0e5..febc90cdef7 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c @@ -36,15 +36,6 @@ static DEFINE_MUTEX(ucb1x00_mutex); static LIST_HEAD(ucb1x00_drivers); static LIST_HEAD(ucb1x00_devices); -static struct mcp_device_id ucb1x00_id[] = { - { "ucb1x00", 0 }, /* auto-detection */ - { "ucb1200", UCB_ID_1200 }, - { "ucb1300", UCB_ID_1300 }, - { "tc35143", UCB_ID_TC35143 }, - { } -}; -MODULE_DEVICE_TABLE(mcp, ucb1x00_id); - /** * ucb1x00_io_set_dir - set IO direction * @ucb: UCB1x00 structure describing chip @@ -157,16 +148,22 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset { struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); unsigned long flags; + unsigned old, mask = 1 << offset; spin_lock_irqsave(&ucb->io_lock, flags); - ucb->io_dir |= (1 << offset); - ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); - + old = ucb->io_out; if (value) - ucb->io_out |= 1 << offset; + ucb->io_out |= mask; else - ucb->io_out &= ~(1 << offset); - ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); + ucb->io_out &= ~mask; + + if (old != ucb->io_out) + ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); + + if (!(ucb->io_dir & mask)) { + ucb->io_dir |= mask; + ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); + } spin_unlock_irqrestore(&ucb->io_lock, flags); return 0; @@ -536,33 +533,17 @@ static struct class ucb1x00_class = { static int ucb1x00_probe(struct mcp *mcp) { - const struct mcp_device_id *mid; struct ucb1x00 *ucb; struct ucb1x00_driver *drv; - struct ucb1x00_plat_data *pdata; unsigned int id; int ret = -ENODEV; int temp; mcp_enable(mcp); id = mcp_reg_read(mcp, UCB_ID); - mid = mcp_get_device_id(mcp); - if (mid && mid->driver_data) { - if (id != mid->driver_data) { - printk(KERN_WARNING "%s wrong ID %04x found: %04x\n", - mid->name, (unsigned int) mid->driver_data, id); - goto err_disable; - } - } else { - mid = &ucb1x00_id[1]; - while (mid->driver_data) { - if (id == mid->driver_data) - break; - mid++; - } - printk(KERN_WARNING "%s ID not found: %04x\n", - ucb1x00_id[0].name, id); + if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_TC35143) { + printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id); goto err_disable; } @@ -571,28 +552,28 @@ static int ucb1x00_probe(struct mcp *mcp) if (!ucb) goto err_disable; - pdata = mcp->attached_device.platform_data; + ucb->dev.class = &ucb1x00_class; ucb->dev.parent = &mcp->attached_device; - dev_set_name(&ucb->dev, mid->name); + dev_set_name(&ucb->dev, "ucb1x00"); spin_lock_init(&ucb->lock); spin_lock_init(&ucb->io_lock); sema_init(&ucb->adc_sem, 1); - ucb->id = mid; + ucb->id = id; ucb->mcp = mcp; ucb->irq = ucb1x00_detect_irq(ucb); if (ucb->irq == NO_IRQ) { - printk(KERN_ERR "%s: IRQ probe failed\n", mid->name); + printk(KERN_ERR "UCB1x00: IRQ probe failed\n"); ret = -ENODEV; goto err_free; } ucb->gpio.base = -1; - if (pdata && (pdata->gpio_base >= 0)) { + if (mcp->gpio_base != 0) { ucb->gpio.label = dev_name(&ucb->dev); - ucb->gpio.base = pdata->gpio_base; + ucb->gpio.base = mcp->gpio_base; ucb->gpio.ngpio = 10; ucb->gpio.set = ucb1x00_gpio_set; ucb->gpio.get = ucb1x00_gpio_get; @@ -605,10 +586,10 @@ static int ucb1x00_probe(struct mcp *mcp) dev_info(&ucb->dev, "gpio_base not set so no gpiolib support"); ret = request_irq(ucb->irq, ucb1x00_irq, IRQF_TRIGGER_RISING, - mid->name, ucb); + "UCB1x00", ucb); if (ret) { - printk(KERN_ERR "%s: unable to grab irq%d: %d\n", - mid->name, ucb->irq, ret); + printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n", + ucb->irq, ret); goto err_gpio; } @@ -712,6 +693,7 @@ static int ucb1x00_resume(struct mcp *mcp) struct ucb1x00 *ucb = mcp_get_drvdata(mcp); struct ucb1x00_dev *dev; + ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); mutex_lock(&ucb1x00_mutex); list_for_each_entry(dev, &ucb->devs, dev_node) { @@ -730,7 +712,6 @@ static struct mcp_driver ucb1x00_driver = { .remove = ucb1x00_remove, .suspend = ucb1x00_suspend, .resume = ucb1x00_resume, - .id_table = ucb1x00_id, }; static int __init ucb1x00_init(void) diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c index 40ec3c11886..63a3cbdfa3f 100644 --- a/drivers/mfd/ucb1x00-ts.c +++ b/drivers/mfd/ucb1x00-ts.c @@ -47,7 +47,6 @@ struct ucb1x00_ts { u16 x_res; u16 y_res; - unsigned int restart:1; unsigned int adcsync:1; }; @@ -207,15 +206,17 @@ static int ucb1x00_thread(void *_ts) { struct ucb1x00_ts *ts = _ts; DECLARE_WAITQUEUE(wait, current); + bool frozen, ignore = false; int valid = 0; set_freezable(); add_wait_queue(&ts->irq_wait, &wait); - while (!kthread_should_stop()) { + while (!kthread_freezable_should_stop(&frozen)) { unsigned int x, y, p; signed long timeout; - ts->restart = 0; + if (frozen) + ignore = true; ucb1x00_adc_enable(ts->ucb); @@ -258,7 +259,7 @@ static int ucb1x00_thread(void *_ts) * space. We therefore leave it to user space * to do any filtering they please. */ - if (!ts->restart) { + if (!ignore) { ucb1x00_ts_evt_add(ts, p, x, y); valid = 1; } @@ -267,8 +268,6 @@ static int ucb1x00_thread(void *_ts) timeout = HZ / 100; } - try_to_freeze(); - schedule_timeout(timeout); } @@ -340,26 +339,6 @@ static void ucb1x00_ts_close(struct input_dev *idev) ucb1x00_disable(ts->ucb); } -#ifdef CONFIG_PM -static int ucb1x00_ts_resume(struct ucb1x00_dev *dev) -{ - struct ucb1x00_ts *ts = dev->priv; - - if (ts->rtask != NULL) { - /* - * Restart the TS thread to ensure the - * TS interrupt mode is set up again - * after sleep. - */ - ts->restart = 1; - wake_up(&ts->irq_wait); - } - return 0; -} -#else -#define ucb1x00_ts_resume NULL -#endif - /* * Initialisation. @@ -382,7 +361,7 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev) ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC; idev->name = "Touchscreen panel"; - idev->id.product = ts->ucb->id->driver_data; + idev->id.product = ts->ucb->id; idev->open = ucb1x00_ts_open; idev->close = ucb1x00_ts_close; @@ -425,7 +404,6 @@ static void ucb1x00_ts_remove(struct ucb1x00_dev *dev) static struct ucb1x00_driver ucb1x00_ts_driver = { .add = ucb1x00_ts_add, .remove = ucb1x00_ts_remove, - .resume = ucb1x00_ts_resume, }; static int __init ucb1x00_ts_init(void) diff --git a/fs/inode.c b/fs/inode.c index 4fa4f0916af..fb10d86ffad 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -322,9 +322,6 @@ EXPORT_SYMBOL(clear_nlink); void set_nlink(struct inode *inode, unsigned int nlink) { if (!nlink) { - printk_ratelimited(KERN_INFO - "set_nlink() clearing i_nlink on %s inode %li\n", - inode->i_sb->s_type->name, inode->i_ino); clear_nlink(inode); } else { /* Yes, some filesystems do change nlink from zero to one */ diff --git a/fs/proc/stat.c b/fs/proc/stat.c index d76ca6ae2b1..121f77cfef7 100644 --- a/fs/proc/stat.c +++ b/fs/proc/stat.c @@ -77,6 +77,8 @@ static int show_stat(struct seq_file *p, void *v) steal += kcpustat_cpu(i).cpustat[CPUTIME_STEAL]; guest += kcpustat_cpu(i).cpustat[CPUTIME_GUEST]; guest_nice += kcpustat_cpu(i).cpustat[CPUTIME_GUEST_NICE]; + sum += kstat_cpu_irqs_sum(i); + sum += arch_irq_stat_cpu(i); for (j = 0; j < NR_SOFTIRQS; j++) { unsigned int softirq_stat = kstat_softirqs_cpu(j, i); diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index 2bfd987f485..6b009548d2e 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c @@ -179,47 +179,33 @@ static const char *qnx4_checkroot(struct super_block *sb) struct qnx4_inode_entry *rootdir; int rd, rl; int i, j; - int found = 0; - if (*(qnx4_sb(sb)->sb->RootDir.di_fname) != '/') { + if (*(qnx4_sb(sb)->sb->RootDir.di_fname) != '/') return "no qnx4 filesystem (no root dir)."; - } else { - QNX4DEBUG((KERN_NOTICE "QNX4 filesystem found on dev %s.\n", sb->s_id)); - rd = le32_to_cpu(qnx4_sb(sb)->sb->RootDir.di_first_xtnt.xtnt_blk) - 1; - rl = le32_to_cpu(qnx4_sb(sb)->sb->RootDir.di_first_xtnt.xtnt_size); - for (j = 0; j < rl; j++) { - bh = sb_bread(sb, rd + j); /* root dir, first block */ - if (bh == NULL) { - return "unable to read root entry."; - } - for (i = 0; i < QNX4_INODES_PER_BLOCK; i++) { - rootdir = (struct qnx4_inode_entry *) (bh->b_data + i * QNX4_DIR_ENTRY_SIZE); - if (rootdir->di_fname != NULL) { - QNX4DEBUG((KERN_INFO "rootdir entry found : [%s]\n", rootdir->di_fname)); - if (!strcmp(rootdir->di_fname, - QNX4_BMNAME)) { - found = 1; - qnx4_sb(sb)->BitMap = kmemdup(rootdir, - sizeof(struct qnx4_inode_entry), - GFP_KERNEL); - if (!qnx4_sb(sb)->BitMap) { - brelse (bh); - return "not enough memory for bitmap inode"; - }/* keep bitmap inode known */ - break; - } - } - } + QNX4DEBUG((KERN_NOTICE "QNX4 filesystem found on dev %s.\n", sb->s_id)); + rd = le32_to_cpu(qnx4_sb(sb)->sb->RootDir.di_first_xtnt.xtnt_blk) - 1; + rl = le32_to_cpu(qnx4_sb(sb)->sb->RootDir.di_first_xtnt.xtnt_size); + for (j = 0; j < rl; j++) { + bh = sb_bread(sb, rd + j); /* root dir, first block */ + if (bh == NULL) + return "unable to read root entry."; + rootdir = (struct qnx4_inode_entry *) bh->b_data; + for (i = 0; i < QNX4_INODES_PER_BLOCK; i++, rootdir++) { + QNX4DEBUG((KERN_INFO "rootdir entry found : [%s]\n", rootdir->di_fname)); + if (strcmp(rootdir->di_fname, QNX4_BMNAME) != 0) + continue; + qnx4_sb(sb)->BitMap = kmemdup(rootdir, + sizeof(struct qnx4_inode_entry), + GFP_KERNEL); brelse(bh); - if (found != 0) { - break; - } - } - if (found == 0) { - return "bitmap file not found."; + if (!qnx4_sb(sb)->BitMap) + return "not enough memory for bitmap inode"; + /* keep bitmap inode known */ + return NULL; } + brelse(bh); } - return NULL; + return "bitmap file not found."; } static int qnx4_fill_super(struct super_block *s, void *data, int silent) @@ -270,7 +256,7 @@ static int qnx4_fill_super(struct super_block *s, void *data, int silent) if (IS_ERR(root)) { printk(KERN_ERR "qnx4: get inode failed\n"); ret = PTR_ERR(root); - goto out; + goto outb; } ret = -ENOMEM; @@ -283,6 +269,8 @@ static int qnx4_fill_super(struct super_block *s, void *data, int silent) outi: iput(root); + outb: + kfree(qs->BitMap); out: brelse(bh); outnobh: diff --git a/fs/super.c b/fs/super.c index de41e1e46f0..6015c02296b 100644 --- a/fs/super.c +++ b/fs/super.c @@ -1186,6 +1186,8 @@ int freeze_super(struct super_block *sb) printk(KERN_ERR "VFS:Filesystem freeze failed\n"); sb->s_frozen = SB_UNFROZEN; + smp_wmb(); + wake_up(&sb->s_wait_unfrozen); deactivate_locked_super(sb); return ret; } diff --git a/include/linux/key.h b/include/linux/key.h index bfc014c5735..5253471cd2e 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -271,7 +271,7 @@ extern int keyring_add_key(struct key *keyring, extern struct key *key_lookup(key_serial_t id); -static inline key_serial_t key_serial(struct key *key) +static inline key_serial_t key_serial(const struct key *key) { return key ? key->serial : 0; } diff --git a/include/linux/mfd/mcp.h b/include/linux/mfd/mcp.h index 1515e64e366..f88c1cc0cb0 100644 --- a/include/linux/mfd/mcp.h +++ b/include/linux/mfd/mcp.h @@ -10,7 +10,6 @@ #ifndef MCP_H #define MCP_H -#include <linux/mod_devicetable.h> #include <mach/dma.h> struct mcp_ops; @@ -27,7 +26,7 @@ struct mcp { dma_device_t dma_telco_rd; dma_device_t dma_telco_wr; struct device attached_device; - const char *codec; + int gpio_base; }; struct mcp_ops { @@ -45,11 +44,10 @@ void mcp_reg_write(struct mcp *, unsigned int, unsigned int); unsigned int mcp_reg_read(struct mcp *, unsigned int); void mcp_enable(struct mcp *); void mcp_disable(struct mcp *); -const struct mcp_device_id *mcp_get_device_id(const struct mcp *mcp); #define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate) struct mcp *mcp_host_alloc(struct device *, size_t); -int mcp_host_register(struct mcp *, void *); +int mcp_host_register(struct mcp *); void mcp_host_unregister(struct mcp *); struct mcp_driver { @@ -58,7 +56,6 @@ struct mcp_driver { void (*remove)(struct mcp *); int (*suspend)(struct mcp *, pm_message_t); int (*resume)(struct mcp *); - const struct mcp_device_id *id_table; }; int mcp_driver_register(struct mcp_driver *); @@ -67,6 +64,9 @@ void mcp_driver_unregister(struct mcp_driver *); #define mcp_get_drvdata(mcp) dev_get_drvdata(&(mcp)->attached_device) #define mcp_set_drvdata(mcp,d) dev_set_drvdata(&(mcp)->attached_device, d) -#define mcp_priv(mcp) ((void *)((mcp)+1)) +static inline void *mcp_priv(struct mcp *mcp) +{ + return mcp + 1; +} #endif diff --git a/include/linux/mfd/ucb1x00.h b/include/linux/mfd/ucb1x00.h index bc19e5fb7ea..4321f044d1e 100644 --- a/include/linux/mfd/ucb1x00.h +++ b/include/linux/mfd/ucb1x00.h @@ -104,9 +104,6 @@ #define UCB_MODE_DYN_VFLAG_ENA (1 << 12) #define UCB_MODE_AUD_OFF_CAN (1 << 13) -struct ucb1x00_plat_data { - int gpio_base; -}; struct ucb1x00_irq { void *devid; @@ -119,7 +116,7 @@ struct ucb1x00 { unsigned int irq; struct semaphore adc_sem; spinlock_t io_lock; - const struct mcp_device_id *id; + u16 id; u16 io_dir; u16 io_out; u16 adc_cr; diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index b29e7f6f8fa..83ac0713ed0 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -436,17 +436,6 @@ struct spi_device_id { __attribute__((aligned(sizeof(kernel_ulong_t)))); }; -/* mcp */ - -#define MCP_NAME_SIZE 20 -#define MCP_MODULE_PREFIX "mcp:" - -struct mcp_device_id { - char name[MCP_NAME_SIZE]; - kernel_ulong_t driver_data /* Data private to the driver */ - __attribute__((aligned(sizeof(kernel_ulong_t)))); -}; - /* dmi */ enum dmi_field { DMI_NONE, diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c index db110b8ae03..f1539decd99 100644 --- a/kernel/tracepoint.c +++ b/kernel/tracepoint.c @@ -634,10 +634,11 @@ static int tracepoint_module_coming(struct module *mod) int ret = 0; /* - * We skip modules that tain the kernel, especially those with different - * module header (for forced load), to make sure we don't cause a crash. + * We skip modules that taint the kernel, especially those with different + * module headers (for forced load), to make sure we don't cause a crash. + * Staging and out-of-tree GPL modules are fine. */ - if (mod->taints) + if (mod->taints & ~((1 << TAINT_OOT_MODULE) | (1 << TAINT_CRAP))) return 0; mutex_lock(&tracepoints_mutex); tp_mod = kmalloc(sizeof(struct tp_module), GFP_KERNEL); diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index fe84bb978e3..716802b774e 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -255,6 +255,8 @@ void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign) if (!n) n++; /* avoid zero length allocation */ p = buffer = kmalloc(n, GFP_KERNEL); + if (!p) + return NULL; for (i = a->nlimbs - 1; i >= 0; i--) { alimb = a->d[i]; diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index c0e14b3f230..e8c96957776 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -823,16 +823,6 @@ static int do_spi_entry(const char *filename, struct spi_device_id *id, } ADD_TO_DEVTABLE("spi", struct spi_device_id, do_spi_entry); -/* Looks like: mcp:S */ -static int do_mcp_entry(const char *filename, struct mcp_device_id *id, - char *alias) -{ - sprintf(alias, MCP_MODULE_PREFIX "%s", id->name); - - return 1; -} -ADD_TO_DEVTABLE("mcp", struct mcp_device_id, do_mcp_entry); - static const struct dmifield { const char *prefix; int field; diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index d661afbe474..d45061d02fe 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -99,6 +99,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule, struct inode *inode, enum ima_hooks func, int mask) { struct task_struct *tsk = current; + const struct cred *cred = current_cred(); int i; if ((rule->flags & IMA_FUNC) && rule->func != func) @@ -108,7 +109,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule, if ((rule->flags & IMA_FSMAGIC) && rule->fsmagic != inode->i_sb->s_magic) return false; - if ((rule->flags & IMA_UID) && rule->uid != tsk->cred->uid) + if ((rule->flags & IMA_UID) && rule->uid != cred->uid) return false; for (i = 0; i < MAX_LSM_RULES; i++) { int rc = 0; diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index 69ff52c08e9..2aee3c5a3b9 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c @@ -59,7 +59,7 @@ int user_instantiate(struct key *key, const void *data, size_t datalen) /* attach the data */ upayload->datalen = datalen; memcpy(upayload->data, data, datalen); - rcu_assign_pointer(key->payload.data, upayload); + rcu_assign_keypointer(key, upayload); ret = 0; error: @@ -98,7 +98,7 @@ int user_update(struct key *key, const void *data, size_t datalen) if (ret == 0) { /* attach the new data, displacing the old */ zap = key->payload.data; - rcu_assign_pointer(key->payload.data, upayload); + rcu_assign_keypointer(key, upayload); key->expiry = 0; } @@ -133,7 +133,7 @@ void user_revoke(struct key *key) key_payload_reserve(key, 0); if (upayload) { - rcu_assign_pointer(key->payload.data, NULL); + rcu_assign_keypointer(key, NULL); kfree_rcu(upayload, rcu); } } |