diff options
author | Paul Mundt <lethal@linux-sh.org> | 2009-07-23 05:43:48 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-07-23 05:43:48 -0400 |
commit | a3beddd0aa267986de7b13b6d9cd0e1869fcf1fc (patch) | |
tree | bfdc42183f5aac21f605a30a4a511298ab91e3c5 | |
parent | 955c9863bb5855a994751843e7066017edc00410 (diff) | |
parent | 5bdef865eb358b6f3760e25e591ae115e9eeddef (diff) |
Merge branch 'sh/kfr2r09'
125 files changed, 5755 insertions, 534 deletions
@@ -1856,7 +1856,7 @@ E: rfkoenig@immd4.informatik.uni-erlangen.de | |||
1856 | D: The Linux Support Team Erlangen | 1856 | D: The Linux Support Team Erlangen |
1857 | 1857 | ||
1858 | N: Andreas Koensgen | 1858 | N: Andreas Koensgen |
1859 | E: ajk@iehk.rwth-aachen.de | 1859 | E: ajk@comnets.uni-bremen.de |
1860 | D: 6pack driver for AX.25 | 1860 | D: 6pack driver for AX.25 |
1861 | 1861 | ||
1862 | N: Harald Koerfgen | 1862 | N: Harald Koerfgen |
diff --git a/Documentation/RCU/rculist_nulls.txt b/Documentation/RCU/rculist_nulls.txt index 93cb28d05dcd..18f9651ff23d 100644 --- a/Documentation/RCU/rculist_nulls.txt +++ b/Documentation/RCU/rculist_nulls.txt | |||
@@ -83,11 +83,12 @@ not detect it missed following items in original chain. | |||
83 | obj = kmem_cache_alloc(...); | 83 | obj = kmem_cache_alloc(...); |
84 | lock_chain(); // typically a spin_lock() | 84 | lock_chain(); // typically a spin_lock() |
85 | obj->key = key; | 85 | obj->key = key; |
86 | atomic_inc(&obj->refcnt); | ||
87 | /* | 86 | /* |
88 | * we need to make sure obj->key is updated before obj->next | 87 | * we need to make sure obj->key is updated before obj->next |
88 | * or obj->refcnt | ||
89 | */ | 89 | */ |
90 | smp_wmb(); | 90 | smp_wmb(); |
91 | atomic_set(&obj->refcnt, 1); | ||
91 | hlist_add_head_rcu(&obj->obj_node, list); | 92 | hlist_add_head_rcu(&obj->obj_node, list); |
92 | unlock_chain(); // typically a spin_unlock() | 93 | unlock_chain(); // typically a spin_unlock() |
93 | 94 | ||
@@ -159,6 +160,10 @@ out: | |||
159 | obj = kmem_cache_alloc(cachep); | 160 | obj = kmem_cache_alloc(cachep); |
160 | lock_chain(); // typically a spin_lock() | 161 | lock_chain(); // typically a spin_lock() |
161 | obj->key = key; | 162 | obj->key = key; |
163 | /* | ||
164 | * changes to obj->key must be visible before refcnt one | ||
165 | */ | ||
166 | smp_wmb(); | ||
162 | atomic_set(&obj->refcnt, 1); | 167 | atomic_set(&obj->refcnt, 1); |
163 | /* | 168 | /* |
164 | * insert obj in RCU way (readers might be traversing chain) | 169 | * insert obj in RCU way (readers might be traversing chain) |
diff --git a/Documentation/connector/cn_test.c b/Documentation/connector/cn_test.c index f688eba87704..6a5be5d5c8e4 100644 --- a/Documentation/connector/cn_test.c +++ b/Documentation/connector/cn_test.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * cn_test.c | 2 | * cn_test.c |
3 | * | 3 | * |
4 | * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru> | 4 | * 2004+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> |
5 | * All rights reserved. | 5 | * All rights reserved. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -194,5 +194,5 @@ module_init(cn_test_init); | |||
194 | module_exit(cn_test_fini); | 194 | module_exit(cn_test_fini); |
195 | 195 | ||
196 | MODULE_LICENSE("GPL"); | 196 | MODULE_LICENSE("GPL"); |
197 | MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>"); | 197 | MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>"); |
198 | MODULE_DESCRIPTION("Connector's test module"); | 198 | MODULE_DESCRIPTION("Connector's test module"); |
diff --git a/Documentation/connector/ucon.c b/Documentation/connector/ucon.c index d738cde2a8d5..c5092ad0ce4b 100644 --- a/Documentation/connector/ucon.c +++ b/Documentation/connector/ucon.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * ucon.c | 2 | * ucon.c |
3 | * | 3 | * |
4 | * Copyright (c) 2004+ Evgeniy Polyakov <johnpol@2ka.mipt.ru> | 4 | * Copyright (c) 2004+ Evgeniy Polyakov <zbr@ioremap.net> |
5 | * | 5 | * |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
diff --git a/Documentation/networking/6pack.txt b/Documentation/networking/6pack.txt index d0777a1200e1..8f339428fdf4 100644 --- a/Documentation/networking/6pack.txt +++ b/Documentation/networking/6pack.txt | |||
@@ -1,7 +1,7 @@ | |||
1 | This is the 6pack-mini-HOWTO, written by | 1 | This is the 6pack-mini-HOWTO, written by |
2 | 2 | ||
3 | Andreas Könsgen DG3KQ | 3 | Andreas Könsgen DG3KQ |
4 | Internet: ajk@iehk.rwth-aachen.de | 4 | Internet: ajk@comnets.uni-bremen.de |
5 | AMPR-net: dg3kq@db0pra.ampr.org | 5 | AMPR-net: dg3kq@db0pra.ampr.org |
6 | AX.25: dg3kq@db0ach.#nrw.deu.eu | 6 | AX.25: dg3kq@db0ach.#nrw.deu.eu |
7 | 7 | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 18c3f0c41c95..ebc269152faf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -150,7 +150,7 @@ F: drivers/scsi/53c700* | |||
150 | 150 | ||
151 | 6PACK NETWORK DRIVER FOR AX.25 | 151 | 6PACK NETWORK DRIVER FOR AX.25 |
152 | P: Andreas Koensgen | 152 | P: Andreas Koensgen |
153 | M: ajk@iehk.rwth-aachen.de | 153 | M: ajk@comnets.uni-bremen.de |
154 | L: linux-hams@vger.kernel.org | 154 | L: linux-hams@vger.kernel.org |
155 | S: Maintained | 155 | S: Maintained |
156 | F: drivers/net/hamradio/6pack.c | 156 | F: drivers/net/hamradio/6pack.c |
@@ -1612,6 +1612,13 @@ S: Supported | |||
1612 | F: fs/configfs/ | 1612 | F: fs/configfs/ |
1613 | F: include/linux/configfs.h | 1613 | F: include/linux/configfs.h |
1614 | 1614 | ||
1615 | CONNECTOR | ||
1616 | P: Evgeniy Polyakov | ||
1617 | M: zbr@ioremap.net | ||
1618 | L: netdev@vger.kernel.org | ||
1619 | S: Maintained | ||
1620 | F: drivers/connector/ | ||
1621 | |||
1615 | CONTROL GROUPS (CGROUPS) | 1622 | CONTROL GROUPS (CGROUPS) |
1616 | P: Paul Menage | 1623 | P: Paul Menage |
1617 | M: menage@google.com | 1624 | M: menage@google.com |
@@ -4089,6 +4096,7 @@ L: netfilter@vger.kernel.org | |||
4089 | L: coreteam@netfilter.org | 4096 | L: coreteam@netfilter.org |
4090 | W: http://www.netfilter.org/ | 4097 | W: http://www.netfilter.org/ |
4091 | W: http://www.iptables.org/ | 4098 | W: http://www.iptables.org/ |
4099 | T: git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-2.6.git | ||
4092 | S: Supported | 4100 | S: Supported |
4093 | F: include/linux/netfilter* | 4101 | F: include/linux/netfilter* |
4094 | F: include/linux/netfilter/ | 4102 | F: include/linux/netfilter/ |
@@ -5586,7 +5594,6 @@ S: Odd Fixes | |||
5586 | F: drivers/net/starfire* | 5594 | F: drivers/net/starfire* |
5587 | 5595 | ||
5588 | STARMODE RADIO IP (STRIP) PROTOCOL DRIVER | 5596 | STARMODE RADIO IP (STRIP) PROTOCOL DRIVER |
5589 | W: http://mosquitonet.Stanford.EDU/strip.html | ||
5590 | S: Orphan | 5597 | S: Orphan |
5591 | F: drivers/net/wireless/strip.c | 5598 | F: drivers/net/wireless/strip.c |
5592 | F: include/linux/if_strip.h | 5599 | F: include/linux/if_strip.h |
@@ -1,7 +1,7 @@ | |||
1 | VERSION = 2 | 1 | VERSION = 2 |
2 | PATCHLEVEL = 6 | 2 | PATCHLEVEL = 6 |
3 | SUBLEVEL = 31 | 3 | SUBLEVEL = 31 |
4 | EXTRAVERSION = -rc3 | 4 | EXTRAVERSION = -rc4 |
5 | NAME = Man-Eating Seals of Antiquity | 5 | NAME = Man-Eating Seals of Antiquity |
6 | 6 | ||
7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 34ad114279bf..c46b3d508f22 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile | |||
@@ -136,6 +136,7 @@ machdir-$(CONFIG_SH_7751_SYSTEMH) += mach-systemh | |||
136 | machdir-$(CONFIG_SH_EDOSK7705) += mach-edosk7705 | 136 | machdir-$(CONFIG_SH_EDOSK7705) += mach-edosk7705 |
137 | machdir-$(CONFIG_SH_HIGHLANDER) += mach-highlander | 137 | machdir-$(CONFIG_SH_HIGHLANDER) += mach-highlander |
138 | machdir-$(CONFIG_SH_MIGOR) += mach-migor | 138 | machdir-$(CONFIG_SH_MIGOR) += mach-migor |
139 | machdir-$(CONFIG_SH_KFR2R09) += mach-kfr2r09 | ||
139 | machdir-$(CONFIG_SH_SDK7780) += mach-sdk7780 | 140 | machdir-$(CONFIG_SH_SDK7780) += mach-sdk7780 |
140 | machdir-$(CONFIG_SH_X3PROTO) += mach-x3proto | 141 | machdir-$(CONFIG_SH_X3PROTO) += mach-x3proto |
141 | machdir-$(CONFIG_SH_SH7763RDP) += mach-sh7763rdp | 142 | machdir-$(CONFIG_SH_SH7763RDP) += mach-sh7763rdp |
diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index 2b1af0eefa6a..db04c85971ad 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig | |||
@@ -193,6 +193,13 @@ config SH_AP325RXA | |||
193 | Renesas "AP-325RXA" support. | 193 | Renesas "AP-325RXA" support. |
194 | Compatible with ALGO SYSTEM CO.,LTD. "AP-320A" | 194 | Compatible with ALGO SYSTEM CO.,LTD. "AP-320A" |
195 | 195 | ||
196 | config SH_KFR2R09 | ||
197 | bool "KFR2R09" | ||
198 | depends on CPU_SUBTYPE_SH7724 | ||
199 | select ARCH_REQUIRE_GPIOLIB | ||
200 | help | ||
201 | "Kit For R2R for 2009" support. | ||
202 | |||
196 | config SH_SH7763RDP | 203 | config SH_SH7763RDP |
197 | bool "SH7763RDP" | 204 | bool "SH7763RDP" |
198 | depends on CPU_SUBTYPE_SH7763 | 205 | depends on CPU_SUBTYPE_SH7763 |
diff --git a/arch/sh/boards/mach-kfr2r09/Makefile b/arch/sh/boards/mach-kfr2r09/Makefile new file mode 100644 index 000000000000..77037567633b --- /dev/null +++ b/arch/sh/boards/mach-kfr2r09/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-y := setup.o | |||
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c new file mode 100644 index 000000000000..bf5f8f8d3b5f --- /dev/null +++ b/arch/sh/boards/mach-kfr2r09/setup.c | |||
@@ -0,0 +1,153 @@ | |||
1 | /* | ||
2 | * KFR2R09 board support code | ||
3 | * | ||
4 | * Copyright (C) 2009 Magnus Damm | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file "COPYING" in the main directory of this archive | ||
8 | * for more details. | ||
9 | */ | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/mtd/physmap.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/clk.h> | ||
16 | #include <linux/gpio.h> | ||
17 | #include <linux/input.h> | ||
18 | #include <asm/clock.h> | ||
19 | #include <asm/machvec.h> | ||
20 | #include <asm/io.h> | ||
21 | #include <asm/sh_keysc.h> | ||
22 | #include <cpu/sh7724.h> | ||
23 | |||
24 | static struct mtd_partition kfr2r09_nor_flash_partitions[] = | ||
25 | { | ||
26 | { | ||
27 | .name = "boot", | ||
28 | .offset = 0, | ||
29 | .size = (4 * 1024 * 1024), | ||
30 | .mask_flags = MTD_WRITEABLE, /* Read-only */ | ||
31 | }, | ||
32 | { | ||
33 | .name = "other", | ||
34 | .offset = MTDPART_OFS_APPEND, | ||
35 | .size = MTDPART_SIZ_FULL, | ||
36 | }, | ||
37 | }; | ||
38 | |||
39 | static struct physmap_flash_data kfr2r09_nor_flash_data = { | ||
40 | .width = 2, | ||
41 | .parts = kfr2r09_nor_flash_partitions, | ||
42 | .nr_parts = ARRAY_SIZE(kfr2r09_nor_flash_partitions), | ||
43 | }; | ||
44 | |||
45 | static struct resource kfr2r09_nor_flash_resources[] = { | ||
46 | [0] = { | ||
47 | .name = "NOR Flash", | ||
48 | .start = 0x00000000, | ||
49 | .end = 0x03ffffff, | ||
50 | .flags = IORESOURCE_MEM, | ||
51 | } | ||
52 | }; | ||
53 | |||
54 | static struct platform_device kfr2r09_nor_flash_device = { | ||
55 | .name = "physmap-flash", | ||
56 | .resource = kfr2r09_nor_flash_resources, | ||
57 | .num_resources = ARRAY_SIZE(kfr2r09_nor_flash_resources), | ||
58 | .dev = { | ||
59 | .platform_data = &kfr2r09_nor_flash_data, | ||
60 | }, | ||
61 | }; | ||
62 | |||
63 | static struct sh_keysc_info kfr2r09_sh_keysc_info = { | ||
64 | .mode = SH_KEYSC_MODE_1, /* KEYOUT0->4, KEYIN0->4 */ | ||
65 | .scan_timing = 3, | ||
66 | .delay = 10, | ||
67 | .keycodes = { | ||
68 | KEY_PHONE, KEY_CLEAR, KEY_MAIL, KEY_WWW, KEY_ENTER, | ||
69 | KEY_1, KEY_2, KEY_3, 0, KEY_UP, | ||
70 | KEY_4, KEY_5, KEY_6, 0, KEY_LEFT, | ||
71 | KEY_7, KEY_8, KEY_9, KEY_PROG1, KEY_RIGHT, | ||
72 | KEY_S, KEY_0, KEY_P, KEY_PROG2, KEY_DOWN, | ||
73 | 0, 0, 0, 0, 0 | ||
74 | }, | ||
75 | }; | ||
76 | |||
77 | static struct resource kfr2r09_sh_keysc_resources[] = { | ||
78 | [0] = { | ||
79 | .name = "KEYSC", | ||
80 | .start = 0x044b0000, | ||
81 | .end = 0x044b000f, | ||
82 | .flags = IORESOURCE_MEM, | ||
83 | }, | ||
84 | [1] = { | ||
85 | .start = 79, | ||
86 | .flags = IORESOURCE_IRQ, | ||
87 | }, | ||
88 | }; | ||
89 | |||
90 | static struct platform_device kfr2r09_sh_keysc_device = { | ||
91 | .name = "sh_keysc", | ||
92 | .id = 0, /* "keysc0" clock */ | ||
93 | .num_resources = ARRAY_SIZE(kfr2r09_sh_keysc_resources), | ||
94 | .resource = kfr2r09_sh_keysc_resources, | ||
95 | .dev = { | ||
96 | .platform_data = &kfr2r09_sh_keysc_info, | ||
97 | }, | ||
98 | }; | ||
99 | |||
100 | static struct platform_device *kfr2r09_devices[] __initdata = { | ||
101 | &kfr2r09_nor_flash_device, | ||
102 | &kfr2r09_sh_keysc_device, | ||
103 | }; | ||
104 | |||
105 | #define BSC_CS0BCR 0xfec10004 | ||
106 | #define BSC_CS0WCR 0xfec10024 | ||
107 | |||
108 | static int __init kfr2r09_devices_setup(void) | ||
109 | { | ||
110 | /* enable SCIF1 serial port for YC401 console support */ | ||
111 | gpio_request(GPIO_FN_SCIF1_RXD, NULL); | ||
112 | gpio_request(GPIO_FN_SCIF1_TXD, NULL); | ||
113 | |||
114 | /* setup NOR flash at CS0 */ | ||
115 | ctrl_outl(0x36db0400, BSC_CS0BCR); | ||
116 | ctrl_outl(0x00000500, BSC_CS0WCR); | ||
117 | |||
118 | /* setup KEYSC pins */ | ||
119 | gpio_request(GPIO_FN_KEYOUT0, NULL); | ||
120 | gpio_request(GPIO_FN_KEYOUT1, NULL); | ||
121 | gpio_request(GPIO_FN_KEYOUT2, NULL); | ||
122 | gpio_request(GPIO_FN_KEYOUT3, NULL); | ||
123 | gpio_request(GPIO_FN_KEYOUT4_IN6, NULL); | ||
124 | gpio_request(GPIO_FN_KEYIN0, NULL); | ||
125 | gpio_request(GPIO_FN_KEYIN1, NULL); | ||
126 | gpio_request(GPIO_FN_KEYIN2, NULL); | ||
127 | gpio_request(GPIO_FN_KEYIN3, NULL); | ||
128 | gpio_request(GPIO_FN_KEYIN4, NULL); | ||
129 | gpio_request(GPIO_FN_KEYOUT5_IN5, NULL); | ||
130 | |||
131 | return platform_add_devices(kfr2r09_devices, | ||
132 | ARRAY_SIZE(kfr2r09_devices)); | ||
133 | } | ||
134 | device_initcall(kfr2r09_devices_setup); | ||
135 | |||
136 | /* Return the board specific boot mode pin configuration */ | ||
137 | static int kfr2r09_mode_pins(void) | ||
138 | { | ||
139 | /* MD0=1, MD1=1, MD2=0: Clock Mode 3 | ||
140 | * MD3=0: 16-bit Area0 Bus Width | ||
141 | * MD5=1: Little Endian | ||
142 | * MD8=1: Test Mode Disabled | ||
143 | */ | ||
144 | return MODE_PIN0 | MODE_PIN1 | MODE_PIN5 | MODE_PIN8; | ||
145 | } | ||
146 | |||
147 | /* | ||
148 | * The Machine Vector | ||
149 | */ | ||
150 | static struct sh_machine_vector mv_kfr2r09 __initmv = { | ||
151 | .mv_name = "kfr2r09", | ||
152 | .mv_mode_pins = kfr2r09_mode_pins, | ||
153 | }; | ||
diff --git a/arch/sh/configs/kfr2r09_defconfig b/arch/sh/configs/kfr2r09_defconfig new file mode 100644 index 000000000000..90e575c34d58 --- /dev/null +++ b/arch/sh/configs/kfr2r09_defconfig | |||
@@ -0,0 +1,877 @@ | |||
1 | # | ||
2 | # Automatically generated make config: don't edit | ||
3 | # Linux kernel version: 2.6.31-rc3 | ||
4 | # Thu Jul 23 17:45:09 2009 | ||
5 | # | ||
6 | CONFIG_SUPERH=y | ||
7 | CONFIG_SUPERH32=y | ||
8 | # CONFIG_SUPERH64 is not set | ||
9 | CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig" | ||
10 | CONFIG_RWSEM_GENERIC_SPINLOCK=y | ||
11 | CONFIG_GENERIC_BUG=y | ||
12 | CONFIG_GENERIC_FIND_NEXT_BIT=y | ||
13 | CONFIG_GENERIC_HWEIGHT=y | ||
14 | CONFIG_GENERIC_HARDIRQS=y | ||
15 | CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y | ||
16 | CONFIG_GENERIC_IRQ_PROBE=y | ||
17 | CONFIG_IRQ_PER_CPU=y | ||
18 | CONFIG_GENERIC_GPIO=y | ||
19 | CONFIG_GENERIC_TIME=y | ||
20 | CONFIG_GENERIC_CLOCKEVENTS=y | ||
21 | CONFIG_ARCH_SUSPEND_POSSIBLE=y | ||
22 | CONFIG_ARCH_HIBERNATION_POSSIBLE=y | ||
23 | CONFIG_SYS_SUPPORTS_CMT=y | ||
24 | CONFIG_SYS_SUPPORTS_TMU=y | ||
25 | CONFIG_STACKTRACE_SUPPORT=y | ||
26 | CONFIG_LOCKDEP_SUPPORT=y | ||
27 | CONFIG_HAVE_LATENCYTOP_SUPPORT=y | ||
28 | # CONFIG_ARCH_HAS_ILOG2_U32 is not set | ||
29 | # CONFIG_ARCH_HAS_ILOG2_U64 is not set | ||
30 | CONFIG_ARCH_NO_VIRT_TO_BUS=y | ||
31 | CONFIG_ARCH_HAS_DEFAULT_IDLE=y | ||
32 | CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y | ||
33 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" | ||
34 | CONFIG_CONSTRUCTORS=y | ||
35 | |||
36 | # | ||
37 | # General setup | ||
38 | # | ||
39 | CONFIG_EXPERIMENTAL=y | ||
40 | CONFIG_BROKEN_ON_SMP=y | ||
41 | CONFIG_INIT_ENV_ARG_LIMIT=32 | ||
42 | CONFIG_LOCALVERSION="" | ||
43 | # CONFIG_LOCALVERSION_AUTO is not set | ||
44 | CONFIG_HAVE_KERNEL_GZIP=y | ||
45 | CONFIG_HAVE_KERNEL_BZIP2=y | ||
46 | CONFIG_HAVE_KERNEL_LZMA=y | ||
47 | CONFIG_KERNEL_GZIP=y | ||
48 | # CONFIG_KERNEL_BZIP2 is not set | ||
49 | # CONFIG_KERNEL_LZMA is not set | ||
50 | CONFIG_SWAP=y | ||
51 | CONFIG_SYSVIPC=y | ||
52 | CONFIG_SYSVIPC_SYSCTL=y | ||
53 | # CONFIG_POSIX_MQUEUE is not set | ||
54 | CONFIG_BSD_PROCESS_ACCT=y | ||
55 | # CONFIG_BSD_PROCESS_ACCT_V3 is not set | ||
56 | # CONFIG_TASKSTATS is not set | ||
57 | # CONFIG_AUDIT is not set | ||
58 | |||
59 | # | ||
60 | # RCU Subsystem | ||
61 | # | ||
62 | CONFIG_CLASSIC_RCU=y | ||
63 | # CONFIG_TREE_RCU is not set | ||
64 | # CONFIG_PREEMPT_RCU is not set | ||
65 | # CONFIG_TREE_RCU_TRACE is not set | ||
66 | # CONFIG_PREEMPT_RCU_TRACE is not set | ||
67 | CONFIG_IKCONFIG=y | ||
68 | CONFIG_IKCONFIG_PROC=y | ||
69 | CONFIG_LOG_BUF_SHIFT=14 | ||
70 | CONFIG_GROUP_SCHED=y | ||
71 | CONFIG_FAIR_GROUP_SCHED=y | ||
72 | # CONFIG_RT_GROUP_SCHED is not set | ||
73 | CONFIG_USER_SCHED=y | ||
74 | # CONFIG_CGROUP_SCHED is not set | ||
75 | # CONFIG_CGROUPS is not set | ||
76 | CONFIG_SYSFS_DEPRECATED=y | ||
77 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
78 | # CONFIG_RELAY is not set | ||
79 | # CONFIG_NAMESPACES is not set | ||
80 | CONFIG_BLK_DEV_INITRD=y | ||
81 | CONFIG_INITRAMFS_SOURCE="" | ||
82 | CONFIG_RD_GZIP=y | ||
83 | # CONFIG_RD_BZIP2 is not set | ||
84 | # CONFIG_RD_LZMA is not set | ||
85 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y | ||
86 | CONFIG_SYSCTL=y | ||
87 | CONFIG_ANON_INODES=y | ||
88 | CONFIG_EMBEDDED=y | ||
89 | CONFIG_UID16=y | ||
90 | CONFIG_SYSCTL_SYSCALL=y | ||
91 | # CONFIG_KALLSYMS is not set | ||
92 | CONFIG_HOTPLUG=y | ||
93 | CONFIG_PRINTK=y | ||
94 | CONFIG_BUG=y | ||
95 | CONFIG_ELF_CORE=y | ||
96 | CONFIG_BASE_FULL=y | ||
97 | CONFIG_FUTEX=y | ||
98 | CONFIG_EPOLL=y | ||
99 | CONFIG_SIGNALFD=y | ||
100 | CONFIG_TIMERFD=y | ||
101 | CONFIG_EVENTFD=y | ||
102 | CONFIG_SHMEM=y | ||
103 | CONFIG_AIO=y | ||
104 | CONFIG_HAVE_PERF_COUNTERS=y | ||
105 | |||
106 | # | ||
107 | # Performance Counters | ||
108 | # | ||
109 | # CONFIG_PERF_COUNTERS is not set | ||
110 | CONFIG_VM_EVENT_COUNTERS=y | ||
111 | # CONFIG_STRIP_ASM_SYMS is not set | ||
112 | CONFIG_COMPAT_BRK=y | ||
113 | CONFIG_SLAB=y | ||
114 | # CONFIG_SLUB is not set | ||
115 | # CONFIG_SLOB is not set | ||
116 | # CONFIG_PROFILING is not set | ||
117 | # CONFIG_MARKERS is not set | ||
118 | CONFIG_HAVE_OPROFILE=y | ||
119 | CONFIG_HAVE_IOREMAP_PROT=y | ||
120 | CONFIG_HAVE_KPROBES=y | ||
121 | CONFIG_HAVE_KRETPROBES=y | ||
122 | CONFIG_HAVE_ARCH_TRACEHOOK=y | ||
123 | CONFIG_HAVE_CLK=y | ||
124 | CONFIG_HAVE_DMA_API_DEBUG=y | ||
125 | |||
126 | # | ||
127 | # GCOV-based kernel profiling | ||
128 | # | ||
129 | # CONFIG_GCOV_KERNEL is not set | ||
130 | # CONFIG_SLOW_WORK is not set | ||
131 | CONFIG_HAVE_GENERIC_DMA_COHERENT=y | ||
132 | CONFIG_SLABINFO=y | ||
133 | CONFIG_RT_MUTEXES=y | ||
134 | CONFIG_BASE_SMALL=0 | ||
135 | # CONFIG_MODULES is not set | ||
136 | CONFIG_BLOCK=y | ||
137 | CONFIG_LBDAF=y | ||
138 | # CONFIG_BLK_DEV_BSG is not set | ||
139 | # CONFIG_BLK_DEV_INTEGRITY is not set | ||
140 | |||
141 | # | ||
142 | # IO Schedulers | ||
143 | # | ||
144 | CONFIG_IOSCHED_NOOP=y | ||
145 | # CONFIG_IOSCHED_AS is not set | ||
146 | # CONFIG_IOSCHED_DEADLINE is not set | ||
147 | # CONFIG_IOSCHED_CFQ is not set | ||
148 | # CONFIG_DEFAULT_AS is not set | ||
149 | # CONFIG_DEFAULT_DEADLINE is not set | ||
150 | # CONFIG_DEFAULT_CFQ is not set | ||
151 | CONFIG_DEFAULT_NOOP=y | ||
152 | CONFIG_DEFAULT_IOSCHED="noop" | ||
153 | # CONFIG_FREEZER is not set | ||
154 | |||
155 | # | ||
156 | # System type | ||
157 | # | ||
158 | CONFIG_CPU_SH4=y | ||
159 | CONFIG_CPU_SH4A=y | ||
160 | CONFIG_CPU_SHX2=y | ||
161 | CONFIG_ARCH_SHMOBILE=y | ||
162 | # CONFIG_CPU_SUBTYPE_SH7619 is not set | ||
163 | # CONFIG_CPU_SUBTYPE_SH7201 is not set | ||
164 | # CONFIG_CPU_SUBTYPE_SH7203 is not set | ||
165 | # CONFIG_CPU_SUBTYPE_SH7206 is not set | ||
166 | # CONFIG_CPU_SUBTYPE_SH7263 is not set | ||
167 | # CONFIG_CPU_SUBTYPE_MXG is not set | ||
168 | # CONFIG_CPU_SUBTYPE_SH7705 is not set | ||
169 | # CONFIG_CPU_SUBTYPE_SH7706 is not set | ||
170 | # CONFIG_CPU_SUBTYPE_SH7707 is not set | ||
171 | # CONFIG_CPU_SUBTYPE_SH7708 is not set | ||
172 | # CONFIG_CPU_SUBTYPE_SH7709 is not set | ||
173 | # CONFIG_CPU_SUBTYPE_SH7710 is not set | ||
174 | # CONFIG_CPU_SUBTYPE_SH7712 is not set | ||
175 | # CONFIG_CPU_SUBTYPE_SH7720 is not set | ||
176 | # CONFIG_CPU_SUBTYPE_SH7721 is not set | ||
177 | # CONFIG_CPU_SUBTYPE_SH7750 is not set | ||
178 | # CONFIG_CPU_SUBTYPE_SH7091 is not set | ||
179 | # CONFIG_CPU_SUBTYPE_SH7750R is not set | ||
180 | # CONFIG_CPU_SUBTYPE_SH7750S is not set | ||
181 | # CONFIG_CPU_SUBTYPE_SH7751 is not set | ||
182 | # CONFIG_CPU_SUBTYPE_SH7751R is not set | ||
183 | # CONFIG_CPU_SUBTYPE_SH7760 is not set | ||
184 | # CONFIG_CPU_SUBTYPE_SH4_202 is not set | ||
185 | # CONFIG_CPU_SUBTYPE_SH7723 is not set | ||
186 | CONFIG_CPU_SUBTYPE_SH7724=y | ||
187 | # CONFIG_CPU_SUBTYPE_SH7763 is not set | ||
188 | # CONFIG_CPU_SUBTYPE_SH7770 is not set | ||
189 | # CONFIG_CPU_SUBTYPE_SH7780 is not set | ||
190 | # CONFIG_CPU_SUBTYPE_SH7785 is not set | ||
191 | # CONFIG_CPU_SUBTYPE_SH7786 is not set | ||
192 | # CONFIG_CPU_SUBTYPE_SHX3 is not set | ||
193 | # CONFIG_CPU_SUBTYPE_SH7343 is not set | ||
194 | # CONFIG_CPU_SUBTYPE_SH7722 is not set | ||
195 | # CONFIG_CPU_SUBTYPE_SH7366 is not set | ||
196 | |||
197 | # | ||
198 | # Memory management options | ||
199 | # | ||
200 | CONFIG_QUICKLIST=y | ||
201 | CONFIG_MMU=y | ||
202 | CONFIG_PAGE_OFFSET=0x80000000 | ||
203 | CONFIG_FORCE_MAX_ZONEORDER=11 | ||
204 | CONFIG_MEMORY_START=0x08000000 | ||
205 | CONFIG_MEMORY_SIZE=0x08000000 | ||
206 | CONFIG_29BIT=y | ||
207 | # CONFIG_X2TLB is not set | ||
208 | CONFIG_VSYSCALL=y | ||
209 | CONFIG_ARCH_FLATMEM_ENABLE=y | ||
210 | CONFIG_ARCH_SPARSEMEM_ENABLE=y | ||
211 | CONFIG_ARCH_SPARSEMEM_DEFAULT=y | ||
212 | CONFIG_MAX_ACTIVE_REGIONS=1 | ||
213 | CONFIG_ARCH_POPULATES_NODE_MAP=y | ||
214 | CONFIG_ARCH_SELECT_MEMORY_MODEL=y | ||
215 | CONFIG_PAGE_SIZE_4KB=y | ||
216 | # CONFIG_PAGE_SIZE_8KB is not set | ||
217 | # CONFIG_PAGE_SIZE_16KB is not set | ||
218 | # CONFIG_PAGE_SIZE_64KB is not set | ||
219 | CONFIG_SELECT_MEMORY_MODEL=y | ||
220 | CONFIG_FLATMEM_MANUAL=y | ||
221 | # CONFIG_DISCONTIGMEM_MANUAL is not set | ||
222 | # CONFIG_SPARSEMEM_MANUAL is not set | ||
223 | CONFIG_FLATMEM=y | ||
224 | CONFIG_FLAT_NODE_MEM_MAP=y | ||
225 | CONFIG_SPARSEMEM_STATIC=y | ||
226 | CONFIG_PAGEFLAGS_EXTENDED=y | ||
227 | CONFIG_SPLIT_PTLOCK_CPUS=4 | ||
228 | # CONFIG_PHYS_ADDR_T_64BIT is not set | ||
229 | CONFIG_ZONE_DMA_FLAG=0 | ||
230 | CONFIG_NR_QUICK=2 | ||
231 | CONFIG_HAVE_MLOCK=y | ||
232 | CONFIG_HAVE_MLOCKED_PAGE_BIT=y | ||
233 | CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 | ||
234 | |||
235 | # | ||
236 | # Cache configuration | ||
237 | # | ||
238 | CONFIG_CACHE_WRITEBACK=y | ||
239 | # CONFIG_CACHE_WRITETHROUGH is not set | ||
240 | # CONFIG_CACHE_OFF is not set | ||
241 | |||
242 | # | ||
243 | # Processor features | ||
244 | # | ||
245 | CONFIG_CPU_LITTLE_ENDIAN=y | ||
246 | # CONFIG_CPU_BIG_ENDIAN is not set | ||
247 | CONFIG_SH_FPU=y | ||
248 | # CONFIG_SH_STORE_QUEUES is not set | ||
249 | CONFIG_CPU_HAS_INTEVT=y | ||
250 | CONFIG_CPU_HAS_SR_RB=y | ||
251 | CONFIG_CPU_HAS_FPU=y | ||
252 | |||
253 | # | ||
254 | # Board support | ||
255 | # | ||
256 | # CONFIG_SH_7724_SOLUTION_ENGINE is not set | ||
257 | CONFIG_SH_KFR2R09=y | ||
258 | |||
259 | # | ||
260 | # Timer and clock configuration | ||
261 | # | ||
262 | # CONFIG_SH_TIMER_TMU is not set | ||
263 | CONFIG_SH_TIMER_CMT=y | ||
264 | CONFIG_SH_PCLK_FREQ=33333333 | ||
265 | CONFIG_SH_CLK_CPG=y | ||
266 | CONFIG_TICK_ONESHOT=y | ||
267 | CONFIG_NO_HZ=y | ||
268 | # CONFIG_HIGH_RES_TIMERS is not set | ||
269 | CONFIG_GENERIC_CLOCKEVENTS_BUILD=y | ||
270 | |||
271 | # | ||
272 | # CPU Frequency scaling | ||
273 | # | ||
274 | # CONFIG_CPU_FREQ is not set | ||
275 | |||
276 | # | ||
277 | # DMA support | ||
278 | # | ||
279 | # CONFIG_SH_DMA is not set | ||
280 | |||
281 | # | ||
282 | # Companion Chips | ||
283 | # | ||
284 | |||
285 | # | ||
286 | # Additional SuperH Device Drivers | ||
287 | # | ||
288 | # CONFIG_HEARTBEAT is not set | ||
289 | # CONFIG_PUSH_SWITCH is not set | ||
290 | |||
291 | # | ||
292 | # Kernel features | ||
293 | # | ||
294 | # CONFIG_HZ_100 is not set | ||
295 | # CONFIG_HZ_250 is not set | ||
296 | # CONFIG_HZ_300 is not set | ||
297 | CONFIG_HZ_1000=y | ||
298 | CONFIG_HZ=1000 | ||
299 | # CONFIG_SCHED_HRTICK is not set | ||
300 | CONFIG_KEXEC=y | ||
301 | # CONFIG_CRASH_DUMP is not set | ||
302 | # CONFIG_SECCOMP is not set | ||
303 | # CONFIG_PREEMPT_NONE is not set | ||
304 | CONFIG_PREEMPT_VOLUNTARY=y | ||
305 | # CONFIG_PREEMPT is not set | ||
306 | CONFIG_GUSA=y | ||
307 | # CONFIG_SPARSE_IRQ is not set | ||
308 | |||
309 | # | ||
310 | # Boot options | ||
311 | # | ||
312 | CONFIG_ZERO_PAGE_OFFSET=0x00001000 | ||
313 | CONFIG_BOOT_LINK_OFFSET=0x00800000 | ||
314 | CONFIG_ENTRY_OFFSET=0x00001000 | ||
315 | CONFIG_CMDLINE_BOOL=y | ||
316 | CONFIG_CMDLINE="console=ttySC1,115200" | ||
317 | |||
318 | # | ||
319 | # Bus options | ||
320 | # | ||
321 | # CONFIG_ARCH_SUPPORTS_MSI is not set | ||
322 | # CONFIG_PCCARD is not set | ||
323 | |||
324 | # | ||
325 | # Executable file formats | ||
326 | # | ||
327 | CONFIG_BINFMT_ELF=y | ||
328 | # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set | ||
329 | # CONFIG_HAVE_AOUT is not set | ||
330 | # CONFIG_BINFMT_MISC is not set | ||
331 | |||
332 | # | ||
333 | # Power management options (EXPERIMENTAL) | ||
334 | # | ||
335 | CONFIG_PM=y | ||
336 | # CONFIG_PM_DEBUG is not set | ||
337 | # CONFIG_SUSPEND is not set | ||
338 | # CONFIG_HIBERNATION is not set | ||
339 | CONFIG_CPU_IDLE=y | ||
340 | CONFIG_CPU_IDLE_GOV_LADDER=y | ||
341 | CONFIG_CPU_IDLE_GOV_MENU=y | ||
342 | CONFIG_NET=y | ||
343 | |||
344 | # | ||
345 | # Networking options | ||
346 | # | ||
347 | CONFIG_PACKET=y | ||
348 | CONFIG_PACKET_MMAP=y | ||
349 | CONFIG_UNIX=y | ||
350 | # CONFIG_NET_KEY is not set | ||
351 | CONFIG_INET=y | ||
352 | # CONFIG_IP_MULTICAST is not set | ||
353 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
354 | CONFIG_IP_FIB_HASH=y | ||
355 | # CONFIG_IP_PNP is not set | ||
356 | # CONFIG_NET_IPIP is not set | ||
357 | # CONFIG_NET_IPGRE is not set | ||
358 | # CONFIG_ARPD is not set | ||
359 | # CONFIG_SYN_COOKIES is not set | ||
360 | # CONFIG_INET_AH is not set | ||
361 | # CONFIG_INET_ESP is not set | ||
362 | # CONFIG_INET_IPCOMP is not set | ||
363 | # CONFIG_INET_XFRM_TUNNEL is not set | ||
364 | # CONFIG_INET_TUNNEL is not set | ||
365 | # CONFIG_INET_XFRM_MODE_TRANSPORT is not set | ||
366 | # CONFIG_INET_XFRM_MODE_TUNNEL is not set | ||
367 | # CONFIG_INET_XFRM_MODE_BEET is not set | ||
368 | # CONFIG_INET_LRO is not set | ||
369 | # CONFIG_INET_DIAG is not set | ||
370 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
371 | CONFIG_TCP_CONG_CUBIC=y | ||
372 | CONFIG_DEFAULT_TCP_CONG="cubic" | ||
373 | # CONFIG_TCP_MD5SIG is not set | ||
374 | # CONFIG_IPV6 is not set | ||
375 | # CONFIG_NETWORK_SECMARK is not set | ||
376 | # CONFIG_NETFILTER is not set | ||
377 | # CONFIG_IP_DCCP is not set | ||
378 | # CONFIG_IP_SCTP is not set | ||
379 | # CONFIG_TIPC is not set | ||
380 | # CONFIG_ATM is not set | ||
381 | # CONFIG_BRIDGE is not set | ||
382 | # CONFIG_NET_DSA is not set | ||
383 | # CONFIG_VLAN_8021Q is not set | ||
384 | # CONFIG_DECNET is not set | ||
385 | # CONFIG_LLC2 is not set | ||
386 | # CONFIG_IPX is not set | ||
387 | # CONFIG_ATALK is not set | ||
388 | # CONFIG_X25 is not set | ||
389 | # CONFIG_LAPB is not set | ||
390 | # CONFIG_ECONET is not set | ||
391 | # CONFIG_WAN_ROUTER is not set | ||
392 | # CONFIG_PHONET is not set | ||
393 | # CONFIG_IEEE802154 is not set | ||
394 | # CONFIG_NET_SCHED is not set | ||
395 | # CONFIG_DCB is not set | ||
396 | |||
397 | # | ||
398 | # Network testing | ||
399 | # | ||
400 | # CONFIG_NET_PKTGEN is not set | ||
401 | # CONFIG_HAMRADIO is not set | ||
402 | # CONFIG_CAN is not set | ||
403 | # CONFIG_IRDA is not set | ||
404 | # CONFIG_BT is not set | ||
405 | # CONFIG_AF_RXRPC is not set | ||
406 | # CONFIG_WIRELESS is not set | ||
407 | # CONFIG_WIMAX is not set | ||
408 | # CONFIG_RFKILL is not set | ||
409 | # CONFIG_NET_9P is not set | ||
410 | |||
411 | # | ||
412 | # Device Drivers | ||
413 | # | ||
414 | |||
415 | # | ||
416 | # Generic Driver Options | ||
417 | # | ||
418 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
419 | CONFIG_STANDALONE=y | ||
420 | CONFIG_PREVENT_FIRMWARE_BUILD=y | ||
421 | CONFIG_FW_LOADER=y | ||
422 | CONFIG_FIRMWARE_IN_KERNEL=y | ||
423 | CONFIG_EXTRA_FIRMWARE="" | ||
424 | # CONFIG_SYS_HYPERVISOR is not set | ||
425 | # CONFIG_CONNECTOR is not set | ||
426 | CONFIG_MTD=y | ||
427 | # CONFIG_MTD_DEBUG is not set | ||
428 | CONFIG_MTD_CONCAT=y | ||
429 | CONFIG_MTD_PARTITIONS=y | ||
430 | # CONFIG_MTD_REDBOOT_PARTS is not set | ||
431 | CONFIG_MTD_CMDLINE_PARTS=y | ||
432 | # CONFIG_MTD_AR7_PARTS is not set | ||
433 | |||
434 | # | ||
435 | # User Modules And Translation Layers | ||
436 | # | ||
437 | CONFIG_MTD_CHAR=y | ||
438 | CONFIG_MTD_BLKDEVS=y | ||
439 | CONFIG_MTD_BLOCK=y | ||
440 | # CONFIG_FTL is not set | ||
441 | # CONFIG_NFTL is not set | ||
442 | # CONFIG_INFTL is not set | ||
443 | # CONFIG_RFD_FTL is not set | ||
444 | # CONFIG_SSFDC is not set | ||
445 | # CONFIG_MTD_OOPS is not set | ||
446 | |||
447 | # | ||
448 | # RAM/ROM/Flash chip drivers | ||
449 | # | ||
450 | CONFIG_MTD_CFI=y | ||
451 | # CONFIG_MTD_JEDECPROBE is not set | ||
452 | CONFIG_MTD_GEN_PROBE=y | ||
453 | # CONFIG_MTD_CFI_ADV_OPTIONS is not set | ||
454 | CONFIG_MTD_MAP_BANK_WIDTH_1=y | ||
455 | CONFIG_MTD_MAP_BANK_WIDTH_2=y | ||
456 | CONFIG_MTD_MAP_BANK_WIDTH_4=y | ||
457 | # CONFIG_MTD_MAP_BANK_WIDTH_8 is not set | ||
458 | # CONFIG_MTD_MAP_BANK_WIDTH_16 is not set | ||
459 | # CONFIG_MTD_MAP_BANK_WIDTH_32 is not set | ||
460 | CONFIG_MTD_CFI_I1=y | ||
461 | CONFIG_MTD_CFI_I2=y | ||
462 | # CONFIG_MTD_CFI_I4 is not set | ||
463 | # CONFIG_MTD_CFI_I8 is not set | ||
464 | CONFIG_MTD_CFI_INTELEXT=y | ||
465 | # CONFIG_MTD_CFI_AMDSTD is not set | ||
466 | # CONFIG_MTD_CFI_STAA is not set | ||
467 | CONFIG_MTD_CFI_UTIL=y | ||
468 | # CONFIG_MTD_RAM is not set | ||
469 | # CONFIG_MTD_ROM is not set | ||
470 | # CONFIG_MTD_ABSENT is not set | ||
471 | |||
472 | # | ||
473 | # Mapping drivers for chip access | ||
474 | # | ||
475 | # CONFIG_MTD_COMPLEX_MAPPINGS is not set | ||
476 | CONFIG_MTD_PHYSMAP=y | ||
477 | # CONFIG_MTD_PHYSMAP_COMPAT is not set | ||
478 | # CONFIG_MTD_PLATRAM is not set | ||
479 | |||
480 | # | ||
481 | # Self-contained MTD device drivers | ||
482 | # | ||
483 | # CONFIG_MTD_SLRAM is not set | ||
484 | # CONFIG_MTD_PHRAM is not set | ||
485 | # CONFIG_MTD_MTDRAM is not set | ||
486 | # CONFIG_MTD_BLOCK2MTD is not set | ||
487 | |||
488 | # | ||
489 | # Disk-On-Chip Device Drivers | ||
490 | # | ||
491 | # CONFIG_MTD_DOC2000 is not set | ||
492 | # CONFIG_MTD_DOC2001 is not set | ||
493 | # CONFIG_MTD_DOC2001PLUS is not set | ||
494 | # CONFIG_MTD_NAND is not set | ||
495 | # CONFIG_MTD_ONENAND is not set | ||
496 | |||
497 | # | ||
498 | # LPDDR flash memory drivers | ||
499 | # | ||
500 | # CONFIG_MTD_LPDDR is not set | ||
501 | |||
502 | # | ||
503 | # UBI - Unsorted block images | ||
504 | # | ||
505 | CONFIG_MTD_UBI=y | ||
506 | CONFIG_MTD_UBI_WL_THRESHOLD=4096 | ||
507 | CONFIG_MTD_UBI_BEB_RESERVE=1 | ||
508 | # CONFIG_MTD_UBI_GLUEBI is not set | ||
509 | |||
510 | # | ||
511 | # UBI debugging options | ||
512 | # | ||
513 | # CONFIG_MTD_UBI_DEBUG is not set | ||
514 | # CONFIG_PARPORT is not set | ||
515 | CONFIG_BLK_DEV=y | ||
516 | # CONFIG_BLK_DEV_COW_COMMON is not set | ||
517 | # CONFIG_BLK_DEV_LOOP is not set | ||
518 | # CONFIG_BLK_DEV_NBD is not set | ||
519 | # CONFIG_BLK_DEV_RAM is not set | ||
520 | # CONFIG_CDROM_PKTCDVD is not set | ||
521 | # CONFIG_ATA_OVER_ETH is not set | ||
522 | # CONFIG_BLK_DEV_HD is not set | ||
523 | # CONFIG_MISC_DEVICES is not set | ||
524 | CONFIG_HAVE_IDE=y | ||
525 | # CONFIG_IDE is not set | ||
526 | |||
527 | # | ||
528 | # SCSI device support | ||
529 | # | ||
530 | # CONFIG_RAID_ATTRS is not set | ||
531 | # CONFIG_SCSI is not set | ||
532 | # CONFIG_SCSI_DMA is not set | ||
533 | # CONFIG_SCSI_NETLINK is not set | ||
534 | # CONFIG_ATA is not set | ||
535 | # CONFIG_MD is not set | ||
536 | # CONFIG_NETDEVICES is not set | ||
537 | # CONFIG_ISDN is not set | ||
538 | # CONFIG_PHONE is not set | ||
539 | |||
540 | # | ||
541 | # Input device support | ||
542 | # | ||
543 | CONFIG_INPUT=y | ||
544 | # CONFIG_INPUT_FF_MEMLESS is not set | ||
545 | # CONFIG_INPUT_POLLDEV is not set | ||
546 | |||
547 | # | ||
548 | # Userland interfaces | ||
549 | # | ||
550 | # CONFIG_INPUT_MOUSEDEV is not set | ||
551 | # CONFIG_INPUT_JOYDEV is not set | ||
552 | CONFIG_INPUT_EVDEV=y | ||
553 | # CONFIG_INPUT_EVBUG is not set | ||
554 | |||
555 | # | ||
556 | # Input Device Drivers | ||
557 | # | ||
558 | CONFIG_INPUT_KEYBOARD=y | ||
559 | # CONFIG_KEYBOARD_ATKBD is not set | ||
560 | # CONFIG_KEYBOARD_LKKBD is not set | ||
561 | # CONFIG_KEYBOARD_GPIO is not set | ||
562 | # CONFIG_KEYBOARD_MATRIX is not set | ||
563 | # CONFIG_KEYBOARD_NEWTON is not set | ||
564 | # CONFIG_KEYBOARD_STOWAWAY is not set | ||
565 | # CONFIG_KEYBOARD_SUNKBD is not set | ||
566 | CONFIG_KEYBOARD_SH_KEYSC=y | ||
567 | # CONFIG_KEYBOARD_XTKBD is not set | ||
568 | # CONFIG_INPUT_MOUSE is not set | ||
569 | # CONFIG_INPUT_JOYSTICK is not set | ||
570 | # CONFIG_INPUT_TABLET is not set | ||
571 | # CONFIG_INPUT_TOUCHSCREEN is not set | ||
572 | # CONFIG_INPUT_MISC is not set | ||
573 | |||
574 | # | ||
575 | # Hardware I/O ports | ||
576 | # | ||
577 | # CONFIG_SERIO is not set | ||
578 | # CONFIG_GAMEPORT is not set | ||
579 | |||
580 | # | ||
581 | # Character devices | ||
582 | # | ||
583 | CONFIG_VT=y | ||
584 | CONFIG_CONSOLE_TRANSLATIONS=y | ||
585 | CONFIG_VT_CONSOLE=y | ||
586 | CONFIG_HW_CONSOLE=y | ||
587 | CONFIG_VT_HW_CONSOLE_BINDING=y | ||
588 | CONFIG_DEVKMEM=y | ||
589 | # CONFIG_SERIAL_NONSTANDARD is not set | ||
590 | |||
591 | # | ||
592 | # Serial drivers | ||
593 | # | ||
594 | # CONFIG_SERIAL_8250 is not set | ||
595 | |||
596 | # | ||
597 | # Non-8250 serial port support | ||
598 | # | ||
599 | CONFIG_SERIAL_SH_SCI=y | ||
600 | CONFIG_SERIAL_SH_SCI_NR_UARTS=6 | ||
601 | CONFIG_SERIAL_SH_SCI_CONSOLE=y | ||
602 | CONFIG_SERIAL_CORE=y | ||
603 | CONFIG_SERIAL_CORE_CONSOLE=y | ||
604 | CONFIG_UNIX98_PTYS=y | ||
605 | # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set | ||
606 | CONFIG_LEGACY_PTYS=y | ||
607 | CONFIG_LEGACY_PTY_COUNT=256 | ||
608 | # CONFIG_IPMI_HANDLER is not set | ||
609 | CONFIG_HW_RANDOM=y | ||
610 | # CONFIG_HW_RANDOM_TIMERIOMEM is not set | ||
611 | # CONFIG_R3964 is not set | ||
612 | # CONFIG_RAW_DRIVER is not set | ||
613 | # CONFIG_TCG_TPM is not set | ||
614 | CONFIG_I2C=y | ||
615 | CONFIG_I2C_BOARDINFO=y | ||
616 | # CONFIG_I2C_CHARDEV is not set | ||
617 | CONFIG_I2C_HELPER_AUTO=y | ||
618 | |||
619 | # | ||
620 | # I2C Hardware Bus support | ||
621 | # | ||
622 | |||
623 | # | ||
624 | # I2C system bus drivers (mostly embedded / system-on-chip) | ||
625 | # | ||
626 | # CONFIG_I2C_DESIGNWARE is not set | ||
627 | # CONFIG_I2C_GPIO is not set | ||
628 | # CONFIG_I2C_OCORES is not set | ||
629 | CONFIG_I2C_SH_MOBILE=y | ||
630 | # CONFIG_I2C_SIMTEC is not set | ||
631 | |||
632 | # | ||
633 | # External I2C/SMBus adapter drivers | ||
634 | # | ||
635 | # CONFIG_I2C_PARPORT_LIGHT is not set | ||
636 | # CONFIG_I2C_TAOS_EVM is not set | ||
637 | |||
638 | # | ||
639 | # Other I2C/SMBus bus drivers | ||
640 | # | ||
641 | # CONFIG_I2C_PCA_PLATFORM is not set | ||
642 | |||
643 | # | ||
644 | # Miscellaneous I2C Chip support | ||
645 | # | ||
646 | # CONFIG_DS1682 is not set | ||
647 | # CONFIG_SENSORS_PCF8574 is not set | ||
648 | # CONFIG_PCF8575 is not set | ||
649 | # CONFIG_SENSORS_PCA9539 is not set | ||
650 | # CONFIG_SENSORS_TSL2550 is not set | ||
651 | # CONFIG_I2C_DEBUG_CORE is not set | ||
652 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
653 | # CONFIG_I2C_DEBUG_BUS is not set | ||
654 | # CONFIG_I2C_DEBUG_CHIP is not set | ||
655 | # CONFIG_SPI is not set | ||
656 | |||
657 | # | ||
658 | # PPS support | ||
659 | # | ||
660 | # CONFIG_PPS is not set | ||
661 | CONFIG_ARCH_REQUIRE_GPIOLIB=y | ||
662 | CONFIG_GPIOLIB=y | ||
663 | CONFIG_GPIO_SYSFS=y | ||
664 | |||
665 | # | ||
666 | # Memory mapped GPIO expanders: | ||
667 | # | ||
668 | |||
669 | # | ||
670 | # I2C GPIO expanders: | ||
671 | # | ||
672 | # CONFIG_GPIO_MAX732X is not set | ||
673 | # CONFIG_GPIO_PCA953X is not set | ||
674 | # CONFIG_GPIO_PCF857X is not set | ||
675 | |||
676 | # | ||
677 | # PCI GPIO expanders: | ||
678 | # | ||
679 | |||
680 | # | ||
681 | # SPI GPIO expanders: | ||
682 | # | ||
683 | # CONFIG_W1 is not set | ||
684 | # CONFIG_POWER_SUPPLY is not set | ||
685 | # CONFIG_HWMON is not set | ||
686 | # CONFIG_THERMAL is not set | ||
687 | # CONFIG_THERMAL_HWMON is not set | ||
688 | # CONFIG_WATCHDOG is not set | ||
689 | CONFIG_SSB_POSSIBLE=y | ||
690 | |||
691 | # | ||
692 | # Sonics Silicon Backplane | ||
693 | # | ||
694 | # CONFIG_SSB is not set | ||
695 | |||
696 | # | ||
697 | # Multifunction device drivers | ||
698 | # | ||
699 | # CONFIG_MFD_CORE is not set | ||
700 | # CONFIG_MFD_SM501 is not set | ||
701 | # CONFIG_HTC_PASIC3 is not set | ||
702 | # CONFIG_TPS65010 is not set | ||
703 | # CONFIG_TWL4030_CORE is not set | ||
704 | # CONFIG_MFD_TMIO is not set | ||
705 | # CONFIG_PMIC_DA903X is not set | ||
706 | # CONFIG_MFD_WM8400 is not set | ||
707 | # CONFIG_MFD_WM8350_I2C is not set | ||
708 | # CONFIG_MFD_PCF50633 is not set | ||
709 | # CONFIG_AB3100_CORE is not set | ||
710 | # CONFIG_REGULATOR is not set | ||
711 | # CONFIG_MEDIA_SUPPORT is not set | ||
712 | |||
713 | # | ||
714 | # Graphics support | ||
715 | # | ||
716 | # CONFIG_VGASTATE is not set | ||
717 | # CONFIG_VIDEO_OUTPUT_CONTROL is not set | ||
718 | # CONFIG_FB is not set | ||
719 | # CONFIG_BACKLIGHT_LCD_SUPPORT is not set | ||
720 | |||
721 | # | ||
722 | # Display device support | ||
723 | # | ||
724 | # CONFIG_DISPLAY_SUPPORT is not set | ||
725 | |||
726 | # | ||
727 | # Console display driver support | ||
728 | # | ||
729 | CONFIG_DUMMY_CONSOLE=y | ||
730 | # CONFIG_SOUND is not set | ||
731 | # CONFIG_HID_SUPPORT is not set | ||
732 | # CONFIG_USB_SUPPORT is not set | ||
733 | # CONFIG_MMC is not set | ||
734 | # CONFIG_MEMSTICK is not set | ||
735 | # CONFIG_NEW_LEDS is not set | ||
736 | # CONFIG_ACCESSIBILITY is not set | ||
737 | CONFIG_RTC_LIB=y | ||
738 | # CONFIG_RTC_CLASS is not set | ||
739 | # CONFIG_DMADEVICES is not set | ||
740 | # CONFIG_AUXDISPLAY is not set | ||
741 | CONFIG_UIO=y | ||
742 | # CONFIG_UIO_PDRV is not set | ||
743 | CONFIG_UIO_PDRV_GENIRQ=y | ||
744 | # CONFIG_UIO_SMX is not set | ||
745 | # CONFIG_UIO_SERCOS3 is not set | ||
746 | |||
747 | # | ||
748 | # TI VLYNQ | ||
749 | # | ||
750 | # CONFIG_STAGING is not set | ||
751 | |||
752 | # | ||
753 | # File systems | ||
754 | # | ||
755 | # CONFIG_EXT2_FS is not set | ||
756 | # CONFIG_EXT3_FS is not set | ||
757 | # CONFIG_EXT4_FS is not set | ||
758 | # CONFIG_REISERFS_FS is not set | ||
759 | # CONFIG_JFS_FS is not set | ||
760 | # CONFIG_FS_POSIX_ACL is not set | ||
761 | # CONFIG_XFS_FS is not set | ||
762 | # CONFIG_GFS2_FS is not set | ||
763 | # CONFIG_OCFS2_FS is not set | ||
764 | # CONFIG_BTRFS_FS is not set | ||
765 | CONFIG_FILE_LOCKING=y | ||
766 | # CONFIG_FSNOTIFY is not set | ||
767 | # CONFIG_INOTIFY is not set | ||
768 | # CONFIG_QUOTA is not set | ||
769 | # CONFIG_AUTOFS_FS is not set | ||
770 | # CONFIG_AUTOFS4_FS is not set | ||
771 | # CONFIG_FUSE_FS is not set | ||
772 | |||
773 | # | ||
774 | # Caches | ||
775 | # | ||
776 | # CONFIG_FSCACHE is not set | ||
777 | |||
778 | # | ||
779 | # CD-ROM/DVD Filesystems | ||
780 | # | ||
781 | # CONFIG_ISO9660_FS is not set | ||
782 | # CONFIG_UDF_FS is not set | ||
783 | |||
784 | # | ||
785 | # DOS/FAT/NT Filesystems | ||
786 | # | ||
787 | # CONFIG_MSDOS_FS is not set | ||
788 | # CONFIG_VFAT_FS is not set | ||
789 | # CONFIG_NTFS_FS is not set | ||
790 | |||
791 | # | ||
792 | # Pseudo filesystems | ||
793 | # | ||
794 | CONFIG_PROC_FS=y | ||
795 | CONFIG_PROC_KCORE=y | ||
796 | CONFIG_PROC_SYSCTL=y | ||
797 | CONFIG_PROC_PAGE_MONITOR=y | ||
798 | CONFIG_SYSFS=y | ||
799 | CONFIG_TMPFS=y | ||
800 | # CONFIG_TMPFS_POSIX_ACL is not set | ||
801 | # CONFIG_HUGETLBFS is not set | ||
802 | # CONFIG_HUGETLB_PAGE is not set | ||
803 | # CONFIG_CONFIGFS_FS is not set | ||
804 | # CONFIG_MISC_FILESYSTEMS is not set | ||
805 | # CONFIG_NETWORK_FILESYSTEMS is not set | ||
806 | |||
807 | # | ||
808 | # Partition Types | ||
809 | # | ||
810 | # CONFIG_PARTITION_ADVANCED is not set | ||
811 | CONFIG_MSDOS_PARTITION=y | ||
812 | # CONFIG_NLS is not set | ||
813 | # CONFIG_DLM is not set | ||
814 | |||
815 | # | ||
816 | # Kernel hacking | ||
817 | # | ||
818 | CONFIG_TRACE_IRQFLAGS_SUPPORT=y | ||
819 | # CONFIG_PRINTK_TIME is not set | ||
820 | CONFIG_ENABLE_WARN_DEPRECATED=y | ||
821 | # CONFIG_ENABLE_MUST_CHECK is not set | ||
822 | CONFIG_FRAME_WARN=1024 | ||
823 | # CONFIG_MAGIC_SYSRQ is not set | ||
824 | # CONFIG_UNUSED_SYMBOLS is not set | ||
825 | CONFIG_DEBUG_FS=y | ||
826 | # CONFIG_HEADERS_CHECK is not set | ||
827 | # CONFIG_DEBUG_KERNEL is not set | ||
828 | # CONFIG_DEBUG_BUGVERBOSE is not set | ||
829 | # CONFIG_DEBUG_MEMORY_INIT is not set | ||
830 | # CONFIG_RCU_CPU_STALL_DETECTOR is not set | ||
831 | # CONFIG_LATENCYTOP is not set | ||
832 | CONFIG_SYSCTL_SYSCALL_CHECK=y | ||
833 | CONFIG_HAVE_FUNCTION_TRACER=y | ||
834 | CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y | ||
835 | CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y | ||
836 | CONFIG_HAVE_DYNAMIC_FTRACE=y | ||
837 | CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y | ||
838 | CONFIG_HAVE_FTRACE_SYSCALLS=y | ||
839 | CONFIG_TRACING_SUPPORT=y | ||
840 | # CONFIG_FTRACE is not set | ||
841 | # CONFIG_DYNAMIC_DEBUG is not set | ||
842 | # CONFIG_DMA_API_DEBUG is not set | ||
843 | # CONFIG_SAMPLES is not set | ||
844 | CONFIG_HAVE_ARCH_KGDB=y | ||
845 | # CONFIG_SH_STANDARD_BIOS is not set | ||
846 | # CONFIG_EARLY_SCIF_CONSOLE is not set | ||
847 | |||
848 | # | ||
849 | # Security options | ||
850 | # | ||
851 | # CONFIG_KEYS is not set | ||
852 | # CONFIG_SECURITY is not set | ||
853 | # CONFIG_SECURITYFS is not set | ||
854 | # CONFIG_SECURITY_FILE_CAPABILITIES is not set | ||
855 | # CONFIG_CRYPTO is not set | ||
856 | # CONFIG_BINARY_PRINTF is not set | ||
857 | |||
858 | # | ||
859 | # Library routines | ||
860 | # | ||
861 | CONFIG_BITREVERSE=y | ||
862 | CONFIG_GENERIC_FIND_LAST_BIT=y | ||
863 | # CONFIG_CRC_CCITT is not set | ||
864 | # CONFIG_CRC16 is not set | ||
865 | CONFIG_CRC_T10DIF=y | ||
866 | CONFIG_CRC_ITU_T=y | ||
867 | CONFIG_CRC32=y | ||
868 | CONFIG_CRC7=y | ||
869 | # CONFIG_LIBCRC32C is not set | ||
870 | CONFIG_ZLIB_INFLATE=y | ||
871 | CONFIG_DECOMPRESS_GZIP=y | ||
872 | CONFIG_HAS_IOMEM=y | ||
873 | CONFIG_HAS_IOPORT=y | ||
874 | CONFIG_HAS_DMA=y | ||
875 | CONFIG_HAVE_LMB=y | ||
876 | CONFIG_NLATTR=y | ||
877 | CONFIG_GENERIC_ATOMIC64=y | ||
diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types index fec3a53b8650..09eef360dde1 100644 --- a/arch/sh/tools/mach-types +++ b/arch/sh/tools/mach-types | |||
@@ -56,3 +56,4 @@ SH7785LCR SH_SH7785LCR | |||
56 | URQUELL SH_URQUELL | 56 | URQUELL SH_URQUELL |
57 | ESPT SH_ESPT | 57 | ESPT SH_ESPT |
58 | POLARIS SH_POLARIS | 58 | POLARIS SH_POLARIS |
59 | KFR2R09 SH_KFR2R09 | ||
diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c index 36c3dc7b8991..a7aa8f900954 100644 --- a/arch/x86/kernel/cpu/perf_counter.c +++ b/arch/x86/kernel/cpu/perf_counter.c | |||
@@ -66,6 +66,52 @@ static DEFINE_PER_CPU(struct cpu_hw_counters, cpu_hw_counters) = { | |||
66 | }; | 66 | }; |
67 | 67 | ||
68 | /* | 68 | /* |
69 | * Not sure about some of these | ||
70 | */ | ||
71 | static const u64 p6_perfmon_event_map[] = | ||
72 | { | ||
73 | [PERF_COUNT_HW_CPU_CYCLES] = 0x0079, | ||
74 | [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, | ||
75 | [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0000, | ||
76 | [PERF_COUNT_HW_CACHE_MISSES] = 0x0000, | ||
77 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, | ||
78 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, | ||
79 | [PERF_COUNT_HW_BUS_CYCLES] = 0x0062, | ||
80 | }; | ||
81 | |||
82 | static u64 p6_pmu_event_map(int event) | ||
83 | { | ||
84 | return p6_perfmon_event_map[event]; | ||
85 | } | ||
86 | |||
87 | /* | ||
88 | * Counter setting that is specified not to count anything. | ||
89 | * We use this to effectively disable a counter. | ||
90 | * | ||
91 | * L2_RQSTS with 0 MESI unit mask. | ||
92 | */ | ||
93 | #define P6_NOP_COUNTER 0x0000002EULL | ||
94 | |||
95 | static u64 p6_pmu_raw_event(u64 event) | ||
96 | { | ||
97 | #define P6_EVNTSEL_EVENT_MASK 0x000000FFULL | ||
98 | #define P6_EVNTSEL_UNIT_MASK 0x0000FF00ULL | ||
99 | #define P6_EVNTSEL_EDGE_MASK 0x00040000ULL | ||
100 | #define P6_EVNTSEL_INV_MASK 0x00800000ULL | ||
101 | #define P6_EVNTSEL_COUNTER_MASK 0xFF000000ULL | ||
102 | |||
103 | #define P6_EVNTSEL_MASK \ | ||
104 | (P6_EVNTSEL_EVENT_MASK | \ | ||
105 | P6_EVNTSEL_UNIT_MASK | \ | ||
106 | P6_EVNTSEL_EDGE_MASK | \ | ||
107 | P6_EVNTSEL_INV_MASK | \ | ||
108 | P6_EVNTSEL_COUNTER_MASK) | ||
109 | |||
110 | return event & P6_EVNTSEL_MASK; | ||
111 | } | ||
112 | |||
113 | |||
114 | /* | ||
69 | * Intel PerfMon v3. Used on Core2 and later. | 115 | * Intel PerfMon v3. Used on Core2 and later. |
70 | */ | 116 | */ |
71 | static const u64 intel_perfmon_event_map[] = | 117 | static const u64 intel_perfmon_event_map[] = |
@@ -666,6 +712,7 @@ static int __hw_perf_counter_init(struct perf_counter *counter) | |||
666 | { | 712 | { |
667 | struct perf_counter_attr *attr = &counter->attr; | 713 | struct perf_counter_attr *attr = &counter->attr; |
668 | struct hw_perf_counter *hwc = &counter->hw; | 714 | struct hw_perf_counter *hwc = &counter->hw; |
715 | u64 config; | ||
669 | int err; | 716 | int err; |
670 | 717 | ||
671 | if (!x86_pmu_initialized()) | 718 | if (!x86_pmu_initialized()) |
@@ -718,14 +765,40 @@ static int __hw_perf_counter_init(struct perf_counter *counter) | |||
718 | 765 | ||
719 | if (attr->config >= x86_pmu.max_events) | 766 | if (attr->config >= x86_pmu.max_events) |
720 | return -EINVAL; | 767 | return -EINVAL; |
768 | |||
721 | /* | 769 | /* |
722 | * The generic map: | 770 | * The generic map: |
723 | */ | 771 | */ |
724 | hwc->config |= x86_pmu.event_map(attr->config); | 772 | config = x86_pmu.event_map(attr->config); |
773 | |||
774 | if (config == 0) | ||
775 | return -ENOENT; | ||
776 | |||
777 | if (config == -1LL) | ||
778 | return -EINVAL; | ||
779 | |||
780 | hwc->config |= config; | ||
725 | 781 | ||
726 | return 0; | 782 | return 0; |
727 | } | 783 | } |
728 | 784 | ||
785 | static void p6_pmu_disable_all(void) | ||
786 | { | ||
787 | struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); | ||
788 | u64 val; | ||
789 | |||
790 | if (!cpuc->enabled) | ||
791 | return; | ||
792 | |||
793 | cpuc->enabled = 0; | ||
794 | barrier(); | ||
795 | |||
796 | /* p6 only has one enable register */ | ||
797 | rdmsrl(MSR_P6_EVNTSEL0, val); | ||
798 | val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE; | ||
799 | wrmsrl(MSR_P6_EVNTSEL0, val); | ||
800 | } | ||
801 | |||
729 | static void intel_pmu_disable_all(void) | 802 | static void intel_pmu_disable_all(void) |
730 | { | 803 | { |
731 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0); | 804 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0); |
@@ -767,6 +840,23 @@ void hw_perf_disable(void) | |||
767 | return x86_pmu.disable_all(); | 840 | return x86_pmu.disable_all(); |
768 | } | 841 | } |
769 | 842 | ||
843 | static void p6_pmu_enable_all(void) | ||
844 | { | ||
845 | struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); | ||
846 | unsigned long val; | ||
847 | |||
848 | if (cpuc->enabled) | ||
849 | return; | ||
850 | |||
851 | cpuc->enabled = 1; | ||
852 | barrier(); | ||
853 | |||
854 | /* p6 only has one enable register */ | ||
855 | rdmsrl(MSR_P6_EVNTSEL0, val); | ||
856 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; | ||
857 | wrmsrl(MSR_P6_EVNTSEL0, val); | ||
858 | } | ||
859 | |||
770 | static void intel_pmu_enable_all(void) | 860 | static void intel_pmu_enable_all(void) |
771 | { | 861 | { |
772 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl); | 862 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl); |
@@ -784,13 +874,13 @@ static void amd_pmu_enable_all(void) | |||
784 | barrier(); | 874 | barrier(); |
785 | 875 | ||
786 | for (idx = 0; idx < x86_pmu.num_counters; idx++) { | 876 | for (idx = 0; idx < x86_pmu.num_counters; idx++) { |
877 | struct perf_counter *counter = cpuc->counters[idx]; | ||
787 | u64 val; | 878 | u64 val; |
788 | 879 | ||
789 | if (!test_bit(idx, cpuc->active_mask)) | 880 | if (!test_bit(idx, cpuc->active_mask)) |
790 | continue; | 881 | continue; |
791 | rdmsrl(MSR_K7_EVNTSEL0 + idx, val); | 882 | |
792 | if (val & ARCH_PERFMON_EVENTSEL0_ENABLE) | 883 | val = counter->hw.config; |
793 | continue; | ||
794 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; | 884 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; |
795 | wrmsrl(MSR_K7_EVNTSEL0 + idx, val); | 885 | wrmsrl(MSR_K7_EVNTSEL0 + idx, val); |
796 | } | 886 | } |
@@ -819,16 +909,13 @@ static inline void intel_pmu_ack_status(u64 ack) | |||
819 | 909 | ||
820 | static inline void x86_pmu_enable_counter(struct hw_perf_counter *hwc, int idx) | 910 | static inline void x86_pmu_enable_counter(struct hw_perf_counter *hwc, int idx) |
821 | { | 911 | { |
822 | int err; | 912 | (void)checking_wrmsrl(hwc->config_base + idx, |
823 | err = checking_wrmsrl(hwc->config_base + idx, | ||
824 | hwc->config | ARCH_PERFMON_EVENTSEL0_ENABLE); | 913 | hwc->config | ARCH_PERFMON_EVENTSEL0_ENABLE); |
825 | } | 914 | } |
826 | 915 | ||
827 | static inline void x86_pmu_disable_counter(struct hw_perf_counter *hwc, int idx) | 916 | static inline void x86_pmu_disable_counter(struct hw_perf_counter *hwc, int idx) |
828 | { | 917 | { |
829 | int err; | 918 | (void)checking_wrmsrl(hwc->config_base + idx, hwc->config); |
830 | err = checking_wrmsrl(hwc->config_base + idx, | ||
831 | hwc->config); | ||
832 | } | 919 | } |
833 | 920 | ||
834 | static inline void | 921 | static inline void |
@@ -836,13 +923,24 @@ intel_pmu_disable_fixed(struct hw_perf_counter *hwc, int __idx) | |||
836 | { | 923 | { |
837 | int idx = __idx - X86_PMC_IDX_FIXED; | 924 | int idx = __idx - X86_PMC_IDX_FIXED; |
838 | u64 ctrl_val, mask; | 925 | u64 ctrl_val, mask; |
839 | int err; | ||
840 | 926 | ||
841 | mask = 0xfULL << (idx * 4); | 927 | mask = 0xfULL << (idx * 4); |
842 | 928 | ||
843 | rdmsrl(hwc->config_base, ctrl_val); | 929 | rdmsrl(hwc->config_base, ctrl_val); |
844 | ctrl_val &= ~mask; | 930 | ctrl_val &= ~mask; |
845 | err = checking_wrmsrl(hwc->config_base, ctrl_val); | 931 | (void)checking_wrmsrl(hwc->config_base, ctrl_val); |
932 | } | ||
933 | |||
934 | static inline void | ||
935 | p6_pmu_disable_counter(struct hw_perf_counter *hwc, int idx) | ||
936 | { | ||
937 | struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); | ||
938 | u64 val = P6_NOP_COUNTER; | ||
939 | |||
940 | if (cpuc->enabled) | ||
941 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; | ||
942 | |||
943 | (void)checking_wrmsrl(hwc->config_base + idx, val); | ||
846 | } | 944 | } |
847 | 945 | ||
848 | static inline void | 946 | static inline void |
@@ -943,6 +1041,19 @@ intel_pmu_enable_fixed(struct hw_perf_counter *hwc, int __idx) | |||
943 | err = checking_wrmsrl(hwc->config_base, ctrl_val); | 1041 | err = checking_wrmsrl(hwc->config_base, ctrl_val); |
944 | } | 1042 | } |
945 | 1043 | ||
1044 | static void p6_pmu_enable_counter(struct hw_perf_counter *hwc, int idx) | ||
1045 | { | ||
1046 | struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); | ||
1047 | u64 val; | ||
1048 | |||
1049 | val = hwc->config; | ||
1050 | if (cpuc->enabled) | ||
1051 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; | ||
1052 | |||
1053 | (void)checking_wrmsrl(hwc->config_base + idx, val); | ||
1054 | } | ||
1055 | |||
1056 | |||
946 | static void intel_pmu_enable_counter(struct hw_perf_counter *hwc, int idx) | 1057 | static void intel_pmu_enable_counter(struct hw_perf_counter *hwc, int idx) |
947 | { | 1058 | { |
948 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { | 1059 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { |
@@ -959,8 +1070,6 @@ static void amd_pmu_enable_counter(struct hw_perf_counter *hwc, int idx) | |||
959 | 1070 | ||
960 | if (cpuc->enabled) | 1071 | if (cpuc->enabled) |
961 | x86_pmu_enable_counter(hwc, idx); | 1072 | x86_pmu_enable_counter(hwc, idx); |
962 | else | ||
963 | x86_pmu_disable_counter(hwc, idx); | ||
964 | } | 1073 | } |
965 | 1074 | ||
966 | static int | 1075 | static int |
@@ -1176,6 +1285,49 @@ static void intel_pmu_reset(void) | |||
1176 | local_irq_restore(flags); | 1285 | local_irq_restore(flags); |
1177 | } | 1286 | } |
1178 | 1287 | ||
1288 | static int p6_pmu_handle_irq(struct pt_regs *regs) | ||
1289 | { | ||
1290 | struct perf_sample_data data; | ||
1291 | struct cpu_hw_counters *cpuc; | ||
1292 | struct perf_counter *counter; | ||
1293 | struct hw_perf_counter *hwc; | ||
1294 | int idx, handled = 0; | ||
1295 | u64 val; | ||
1296 | |||
1297 | data.regs = regs; | ||
1298 | data.addr = 0; | ||
1299 | |||
1300 | cpuc = &__get_cpu_var(cpu_hw_counters); | ||
1301 | |||
1302 | for (idx = 0; idx < x86_pmu.num_counters; idx++) { | ||
1303 | if (!test_bit(idx, cpuc->active_mask)) | ||
1304 | continue; | ||
1305 | |||
1306 | counter = cpuc->counters[idx]; | ||
1307 | hwc = &counter->hw; | ||
1308 | |||
1309 | val = x86_perf_counter_update(counter, hwc, idx); | ||
1310 | if (val & (1ULL << (x86_pmu.counter_bits - 1))) | ||
1311 | continue; | ||
1312 | |||
1313 | /* | ||
1314 | * counter overflow | ||
1315 | */ | ||
1316 | handled = 1; | ||
1317 | data.period = counter->hw.last_period; | ||
1318 | |||
1319 | if (!x86_perf_counter_set_period(counter, hwc, idx)) | ||
1320 | continue; | ||
1321 | |||
1322 | if (perf_counter_overflow(counter, 1, &data)) | ||
1323 | p6_pmu_disable_counter(hwc, idx); | ||
1324 | } | ||
1325 | |||
1326 | if (handled) | ||
1327 | inc_irq_stat(apic_perf_irqs); | ||
1328 | |||
1329 | return handled; | ||
1330 | } | ||
1179 | 1331 | ||
1180 | /* | 1332 | /* |
1181 | * This handler is triggered by the local APIC, so the APIC IRQ handling | 1333 | * This handler is triggered by the local APIC, so the APIC IRQ handling |
@@ -1185,14 +1337,13 @@ static int intel_pmu_handle_irq(struct pt_regs *regs) | |||
1185 | { | 1337 | { |
1186 | struct perf_sample_data data; | 1338 | struct perf_sample_data data; |
1187 | struct cpu_hw_counters *cpuc; | 1339 | struct cpu_hw_counters *cpuc; |
1188 | int bit, cpu, loops; | 1340 | int bit, loops; |
1189 | u64 ack, status; | 1341 | u64 ack, status; |
1190 | 1342 | ||
1191 | data.regs = regs; | 1343 | data.regs = regs; |
1192 | data.addr = 0; | 1344 | data.addr = 0; |
1193 | 1345 | ||
1194 | cpu = smp_processor_id(); | 1346 | cpuc = &__get_cpu_var(cpu_hw_counters); |
1195 | cpuc = &per_cpu(cpu_hw_counters, cpu); | ||
1196 | 1347 | ||
1197 | perf_disable(); | 1348 | perf_disable(); |
1198 | status = intel_pmu_get_status(); | 1349 | status = intel_pmu_get_status(); |
@@ -1249,14 +1400,13 @@ static int amd_pmu_handle_irq(struct pt_regs *regs) | |||
1249 | struct cpu_hw_counters *cpuc; | 1400 | struct cpu_hw_counters *cpuc; |
1250 | struct perf_counter *counter; | 1401 | struct perf_counter *counter; |
1251 | struct hw_perf_counter *hwc; | 1402 | struct hw_perf_counter *hwc; |
1252 | int cpu, idx, handled = 0; | 1403 | int idx, handled = 0; |
1253 | u64 val; | 1404 | u64 val; |
1254 | 1405 | ||
1255 | data.regs = regs; | 1406 | data.regs = regs; |
1256 | data.addr = 0; | 1407 | data.addr = 0; |
1257 | 1408 | ||
1258 | cpu = smp_processor_id(); | 1409 | cpuc = &__get_cpu_var(cpu_hw_counters); |
1259 | cpuc = &per_cpu(cpu_hw_counters, cpu); | ||
1260 | 1410 | ||
1261 | for (idx = 0; idx < x86_pmu.num_counters; idx++) { | 1411 | for (idx = 0; idx < x86_pmu.num_counters; idx++) { |
1262 | if (!test_bit(idx, cpuc->active_mask)) | 1412 | if (!test_bit(idx, cpuc->active_mask)) |
@@ -1353,6 +1503,32 @@ static __read_mostly struct notifier_block perf_counter_nmi_notifier = { | |||
1353 | .priority = 1 | 1503 | .priority = 1 |
1354 | }; | 1504 | }; |
1355 | 1505 | ||
1506 | static struct x86_pmu p6_pmu = { | ||
1507 | .name = "p6", | ||
1508 | .handle_irq = p6_pmu_handle_irq, | ||
1509 | .disable_all = p6_pmu_disable_all, | ||
1510 | .enable_all = p6_pmu_enable_all, | ||
1511 | .enable = p6_pmu_enable_counter, | ||
1512 | .disable = p6_pmu_disable_counter, | ||
1513 | .eventsel = MSR_P6_EVNTSEL0, | ||
1514 | .perfctr = MSR_P6_PERFCTR0, | ||
1515 | .event_map = p6_pmu_event_map, | ||
1516 | .raw_event = p6_pmu_raw_event, | ||
1517 | .max_events = ARRAY_SIZE(p6_perfmon_event_map), | ||
1518 | .max_period = (1ULL << 31) - 1, | ||
1519 | .version = 0, | ||
1520 | .num_counters = 2, | ||
1521 | /* | ||
1522 | * Counters have 40 bits implemented. However they are designed such | ||
1523 | * that bits [32-39] are sign extensions of bit 31. As such the | ||
1524 | * effective width of a counter for P6-like PMU is 32 bits only. | ||
1525 | * | ||
1526 | * See IA-32 Intel Architecture Software developer manual Vol 3B | ||
1527 | */ | ||
1528 | .counter_bits = 32, | ||
1529 | .counter_mask = (1ULL << 32) - 1, | ||
1530 | }; | ||
1531 | |||
1356 | static struct x86_pmu intel_pmu = { | 1532 | static struct x86_pmu intel_pmu = { |
1357 | .name = "Intel", | 1533 | .name = "Intel", |
1358 | .handle_irq = intel_pmu_handle_irq, | 1534 | .handle_irq = intel_pmu_handle_irq, |
@@ -1392,6 +1568,37 @@ static struct x86_pmu amd_pmu = { | |||
1392 | .max_period = (1ULL << 47) - 1, | 1568 | .max_period = (1ULL << 47) - 1, |
1393 | }; | 1569 | }; |
1394 | 1570 | ||
1571 | static int p6_pmu_init(void) | ||
1572 | { | ||
1573 | switch (boot_cpu_data.x86_model) { | ||
1574 | case 1: | ||
1575 | case 3: /* Pentium Pro */ | ||
1576 | case 5: | ||
1577 | case 6: /* Pentium II */ | ||
1578 | case 7: | ||
1579 | case 8: | ||
1580 | case 11: /* Pentium III */ | ||
1581 | break; | ||
1582 | case 9: | ||
1583 | case 13: | ||
1584 | /* Pentium M */ | ||
1585 | break; | ||
1586 | default: | ||
1587 | pr_cont("unsupported p6 CPU model %d ", | ||
1588 | boot_cpu_data.x86_model); | ||
1589 | return -ENODEV; | ||
1590 | } | ||
1591 | |||
1592 | if (!cpu_has_apic) { | ||
1593 | pr_info("no Local APIC, try rebooting with lapic"); | ||
1594 | return -ENODEV; | ||
1595 | } | ||
1596 | |||
1597 | x86_pmu = p6_pmu; | ||
1598 | |||
1599 | return 0; | ||
1600 | } | ||
1601 | |||
1395 | static int intel_pmu_init(void) | 1602 | static int intel_pmu_init(void) |
1396 | { | 1603 | { |
1397 | union cpuid10_edx edx; | 1604 | union cpuid10_edx edx; |
@@ -1400,8 +1607,14 @@ static int intel_pmu_init(void) | |||
1400 | unsigned int ebx; | 1607 | unsigned int ebx; |
1401 | int version; | 1608 | int version; |
1402 | 1609 | ||
1403 | if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) | 1610 | if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { |
1611 | /* check for P6 processor family */ | ||
1612 | if (boot_cpu_data.x86 == 6) { | ||
1613 | return p6_pmu_init(); | ||
1614 | } else { | ||
1404 | return -ENODEV; | 1615 | return -ENODEV; |
1616 | } | ||
1617 | } | ||
1405 | 1618 | ||
1406 | /* | 1619 | /* |
1407 | * Check whether the Architectural PerfMon supports | 1620 | * Check whether the Architectural PerfMon supports |
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index b1cd04087d6a..418d63619680 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c | |||
@@ -16,9 +16,9 @@ struct queue_sysfs_entry { | |||
16 | }; | 16 | }; |
17 | 17 | ||
18 | static ssize_t | 18 | static ssize_t |
19 | queue_var_show(unsigned int var, char *page) | 19 | queue_var_show(unsigned long var, char *page) |
20 | { | 20 | { |
21 | return sprintf(page, "%d\n", var); | 21 | return sprintf(page, "%lu\n", var); |
22 | } | 22 | } |
23 | 23 | ||
24 | static ssize_t | 24 | static ssize_t |
@@ -77,7 +77,8 @@ queue_requests_store(struct request_queue *q, const char *page, size_t count) | |||
77 | 77 | ||
78 | static ssize_t queue_ra_show(struct request_queue *q, char *page) | 78 | static ssize_t queue_ra_show(struct request_queue *q, char *page) |
79 | { | 79 | { |
80 | int ra_kb = q->backing_dev_info.ra_pages << (PAGE_CACHE_SHIFT - 10); | 80 | unsigned long ra_kb = q->backing_dev_info.ra_pages << |
81 | (PAGE_CACHE_SHIFT - 10); | ||
81 | 82 | ||
82 | return queue_var_show(ra_kb, (page)); | 83 | return queue_var_show(ra_kb, (page)); |
83 | } | 84 | } |
@@ -189,9 +190,9 @@ static ssize_t queue_nomerges_store(struct request_queue *q, const char *page, | |||
189 | 190 | ||
190 | static ssize_t queue_rq_affinity_show(struct request_queue *q, char *page) | 191 | static ssize_t queue_rq_affinity_show(struct request_queue *q, char *page) |
191 | { | 192 | { |
192 | unsigned int set = test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags); | 193 | bool set = test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags); |
193 | 194 | ||
194 | return queue_var_show(set != 0, page); | 195 | return queue_var_show(set, page); |
195 | } | 196 | } |
196 | 197 | ||
197 | static ssize_t | 198 | static ssize_t |
diff --git a/block/elevator.c b/block/elevator.c index 6f2375339a99..2d511f9105e1 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
@@ -101,11 +101,16 @@ int elv_rq_merge_ok(struct request *rq, struct bio *bio) | |||
101 | return 0; | 101 | return 0; |
102 | 102 | ||
103 | /* | 103 | /* |
104 | * Don't merge if failfast settings don't match | 104 | * Don't merge if failfast settings don't match. |
105 | * | ||
106 | * FIXME: The negation in front of each condition is necessary | ||
107 | * because bio and request flags use different bit positions | ||
108 | * and the accessors return those bits directly. This | ||
109 | * ugliness will soon go away. | ||
105 | */ | 110 | */ |
106 | if (bio_failfast_dev(bio) != blk_failfast_dev(rq) || | 111 | if (!bio_failfast_dev(bio) != !blk_failfast_dev(rq) || |
107 | bio_failfast_transport(bio) != blk_failfast_transport(rq) || | 112 | !bio_failfast_transport(bio) != !blk_failfast_transport(rq) || |
108 | bio_failfast_driver(bio) != blk_failfast_driver(rq)) | 113 | !bio_failfast_driver(bio) != !blk_failfast_driver(rq)) |
109 | return 0; | 114 | return 0; |
110 | 115 | ||
111 | if (!elv_iosched_allow_merge(rq, bio)) | 116 | if (!elv_iosched_allow_merge(rq, bio)) |
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index f5e7180d7f47..3ff02941b3dd 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c | |||
@@ -1627,7 +1627,7 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, | |||
1627 | drive, dtp->blocks, dtp->spt, dtp->stretch); | 1627 | drive, dtp->blocks, dtp->spt, dtp->stretch); |
1628 | 1628 | ||
1629 | /* sanity check */ | 1629 | /* sanity check */ |
1630 | if (!dtp || setprm.track != dtp->blocks/dtp->spt/2 || | 1630 | if (setprm.track != dtp->blocks/dtp->spt/2 || |
1631 | setprm.head != 2) { | 1631 | setprm.head != 2) { |
1632 | redo_fd_request(); | 1632 | redo_fd_request(); |
1633 | return -EINVAL; | 1633 | return -EINVAL; |
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index fbeefb68a31f..aa1a3d5a3e2b 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -427,7 +427,12 @@ static unsigned int features[] = { | |||
427 | VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_IDENTIFY | 427 | VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_IDENTIFY |
428 | }; | 428 | }; |
429 | 429 | ||
430 | static struct virtio_driver virtio_blk = { | 430 | /* |
431 | * virtio_blk causes spurious section mismatch warning by | ||
432 | * simultaneously referring to a __devinit and a __devexit function. | ||
433 | * Use __refdata to avoid this warning. | ||
434 | */ | ||
435 | static struct virtio_driver __refdata virtio_blk = { | ||
431 | .feature_table = features, | 436 | .feature_table = features, |
432 | .feature_table_size = ARRAY_SIZE(features), | 437 | .feature_table_size = ARRAY_SIZE(features), |
433 | .driver.name = KBUILD_MODNAME, | 438 | .driver.name = KBUILD_MODNAME, |
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index 4575171e5beb..b2590409f25e 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c | |||
@@ -374,7 +374,7 @@ err: | |||
374 | static void __exit z2_exit(void) | 374 | static void __exit z2_exit(void) |
375 | { | 375 | { |
376 | int i, j; | 376 | int i, j; |
377 | blk_unregister_region(MKDEV(Z2RAM_MAJOR, 0), 256); | 377 | blk_unregister_region(MKDEV(Z2RAM_MAJOR, 0), Z2MINOR_COUNT); |
378 | unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME); | 378 | unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME); |
379 | del_gendisk(z2ram_gendisk); | 379 | del_gendisk(z2ram_gendisk); |
380 | put_disk(z2ram_gendisk); | 380 | put_disk(z2ram_gendisk); |
diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c index c769ef269fb5..408c2af25d50 100644 --- a/drivers/connector/cn_queue.c +++ b/drivers/connector/cn_queue.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * cn_queue.c | 2 | * cn_queue.c |
3 | * | 3 | * |
4 | * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru> | 4 | * 2004+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> |
5 | * All rights reserved. | 5 | * All rights reserved. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index fd336c5a9057..08b2500f21ec 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * connector.c | 2 | * connector.c |
3 | * | 3 | * |
4 | * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru> | 4 | * 2004+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> |
5 | * All rights reserved. | 5 | * All rights reserved. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -33,7 +33,7 @@ | |||
33 | #include <net/sock.h> | 33 | #include <net/sock.h> |
34 | 34 | ||
35 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
36 | MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>"); | 36 | MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>"); |
37 | MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector."); | 37 | MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector."); |
38 | 38 | ||
39 | static u32 cn_idx = CN_IDX_CONNECTOR; | 39 | static u32 cn_idx = CN_IDX_CONNECTOR; |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index f2c21d5d24e8..5eb10c2ce665 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1075,14 +1075,16 @@ EXPORT_SYMBOL_GPL(hid_report_raw_event); | |||
1075 | */ | 1075 | */ |
1076 | int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt) | 1076 | int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt) |
1077 | { | 1077 | { |
1078 | struct hid_report_enum *report_enum = hid->report_enum + type; | 1078 | struct hid_report_enum *report_enum; |
1079 | struct hid_driver *hdrv = hid->driver; | 1079 | struct hid_driver *hdrv; |
1080 | struct hid_report *report; | 1080 | struct hid_report *report; |
1081 | unsigned int i; | 1081 | unsigned int i; |
1082 | int ret; | 1082 | int ret; |
1083 | 1083 | ||
1084 | if (!hid || !hid->driver) | 1084 | if (!hid || !hid->driver) |
1085 | return -ENODEV; | 1085 | return -ENODEV; |
1086 | report_enum = hid->report_enum + type; | ||
1087 | hdrv = hid->driver; | ||
1086 | 1088 | ||
1087 | if (!size) { | 1089 | if (!size) { |
1088 | dbg_hid("empty report\n"); | 1090 | dbg_hid("empty report\n"); |
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 9e9421525fb9..215b2addddbb 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c | |||
@@ -527,8 +527,10 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd, | |||
527 | goto goodreturn; | 527 | goto goodreturn; |
528 | 528 | ||
529 | case HIDIOCGCOLLECTIONINDEX: | 529 | case HIDIOCGCOLLECTIONINDEX: |
530 | i = field->usage[uref->usage_index].collection_index; | ||
531 | unlock_kernel(); | ||
530 | kfree(uref_multi); | 532 | kfree(uref_multi); |
531 | return field->usage[uref->usage_index].collection_index; | 533 | return i; |
532 | case HIDIOCGUSAGES: | 534 | case HIDIOCGUSAGES: |
533 | for (i = 0; i < uref_multi->num_values; i++) | 535 | for (i = 0; i < uref_multi->num_values; i++) |
534 | uref_multi->values[i] = | 536 | uref_multi->values[i] = |
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 695181120cdb..7f878017b736 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
@@ -455,6 +455,7 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) | |||
455 | 455 | ||
456 | rq->cmd_type = REQ_TYPE_ATA_TASKFILE; | 456 | rq->cmd_type = REQ_TYPE_ATA_TASKFILE; |
457 | rq->special = cmd; | 457 | rq->special = cmd; |
458 | cmd->rq = rq; | ||
458 | } | 459 | } |
459 | 460 | ||
460 | ide_devset_get(multcount, mult_count); | 461 | ide_devset_get(multcount, mult_count); |
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 013dc595fab6..bc5fb12b913c 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
@@ -1064,6 +1064,7 @@ static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd, | |||
1064 | tape->best_dsc_rw_freq = config.dsc_rw_frequency; | 1064 | tape->best_dsc_rw_freq = config.dsc_rw_frequency; |
1065 | break; | 1065 | break; |
1066 | case 0x0350: | 1066 | case 0x0350: |
1067 | memset(&config, 0, sizeof(config)); | ||
1067 | config.dsc_rw_frequency = (int) tape->best_dsc_rw_freq; | 1068 | config.dsc_rw_frequency = (int) tape->best_dsc_rw_freq; |
1068 | config.nr_stages = 1; | 1069 | config.nr_stages = 1; |
1069 | if (copy_to_user(argp, &config, sizeof(config))) | 1070 | if (copy_to_user(argp, &config, sizeof(config))) |
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 114efd8dc8f5..1148140d08a1 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -608,8 +608,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
608 | p, compat_mode); | 608 | p, compat_mode); |
609 | 609 | ||
610 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) | 610 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) |
611 | return str_to_user(dev_name(&evdev->dev), | 611 | return str_to_user(dev->name, _IOC_SIZE(cmd), p); |
612 | _IOC_SIZE(cmd), p); | ||
613 | 612 | ||
614 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) | 613 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) |
615 | return str_to_user(dev->phys, _IOC_SIZE(cmd), p); | 614 | return str_to_user(dev->phys, _IOC_SIZE(cmd), p); |
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 0e12f89276a3..4cfd084fa897 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
@@ -536,7 +536,7 @@ static int joydev_ioctl_common(struct joydev *joydev, | |||
536 | default: | 536 | default: |
537 | if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) { | 537 | if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) { |
538 | int len; | 538 | int len; |
539 | const char *name = dev_name(&dev->dev); | 539 | const char *name = dev->name; |
540 | 540 | ||
541 | if (!name) | 541 | if (!name) |
542 | return 0; | 542 | return 0; |
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index b868b8d5fbb3..f155ad8cdae7 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
@@ -470,20 +470,20 @@ static void xpad_irq_out(struct urb *urb) | |||
470 | status = urb->status; | 470 | status = urb->status; |
471 | 471 | ||
472 | switch (status) { | 472 | switch (status) { |
473 | case 0: | 473 | case 0: |
474 | /* success */ | 474 | /* success */ |
475 | break; | 475 | return; |
476 | case -ECONNRESET: | 476 | |
477 | case -ENOENT: | 477 | case -ECONNRESET: |
478 | case -ESHUTDOWN: | 478 | case -ENOENT: |
479 | /* this urb is terminated, clean up */ | 479 | case -ESHUTDOWN: |
480 | dbg("%s - urb shutting down with status: %d", | 480 | /* this urb is terminated, clean up */ |
481 | __func__, status); | 481 | dbg("%s - urb shutting down with status: %d", __func__, status); |
482 | return; | 482 | return; |
483 | default: | 483 | |
484 | dbg("%s - nonzero urb status received: %d", | 484 | default: |
485 | __func__, status); | 485 | dbg("%s - nonzero urb status received: %d", __func__, status); |
486 | goto exit; | 486 | goto exit; |
487 | } | 487 | } |
488 | 488 | ||
489 | exit: | 489 | exit: |
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index df3f8aa68115..95fe0452dae4 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -895,6 +895,13 @@ static unsigned int atkbd_amilo_pa1510_forced_release_keys[] = { | |||
895 | }; | 895 | }; |
896 | 896 | ||
897 | /* | 897 | /* |
898 | * Amilo Pi 3525 key release for Fn+Volume keys not working | ||
899 | */ | ||
900 | static unsigned int atkbd_amilo_pi3525_forced_release_keys[] = { | ||
901 | 0x20, 0xa0, 0x2e, 0xae, 0x30, 0xb0, -1U | ||
902 | }; | ||
903 | |||
904 | /* | ||
898 | * Amilo Xi 3650 key release for light touch bar not working | 905 | * Amilo Xi 3650 key release for light touch bar not working |
899 | */ | 906 | */ |
900 | static unsigned int atkbd_amilo_xi3650_forced_release_keys[] = { | 907 | static unsigned int atkbd_amilo_xi3650_forced_release_keys[] = { |
@@ -902,6 +909,13 @@ static unsigned int atkbd_amilo_xi3650_forced_release_keys[] = { | |||
902 | }; | 909 | }; |
903 | 910 | ||
904 | /* | 911 | /* |
912 | * Soltech TA12 system with broken key release on volume keys and mute key | ||
913 | */ | ||
914 | static unsigned int atkdb_soltech_ta12_forced_release_keys[] = { | ||
915 | 0xa0, 0xae, 0xb0, -1U | ||
916 | }; | ||
917 | |||
918 | /* | ||
905 | * atkbd_set_keycode_table() initializes keyboard's keycode table | 919 | * atkbd_set_keycode_table() initializes keyboard's keycode table |
906 | * according to the selected scancode set | 920 | * according to the selected scancode set |
907 | */ | 921 | */ |
@@ -1568,6 +1582,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1568 | .driver_data = atkbd_amilo_pa1510_forced_release_keys, | 1582 | .driver_data = atkbd_amilo_pa1510_forced_release_keys, |
1569 | }, | 1583 | }, |
1570 | { | 1584 | { |
1585 | .ident = "Fujitsu Amilo Pi 3525", | ||
1586 | .matches = { | ||
1587 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
1588 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 3525"), | ||
1589 | }, | ||
1590 | .callback = atkbd_setup_forced_release, | ||
1591 | .driver_data = atkbd_amilo_pi3525_forced_release_keys, | ||
1592 | }, | ||
1593 | { | ||
1571 | .ident = "Fujitsu Amilo Xi 3650", | 1594 | .ident = "Fujitsu Amilo Xi 3650", |
1572 | .matches = { | 1595 | .matches = { |
1573 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 1596 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
@@ -1576,6 +1599,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1576 | .callback = atkbd_setup_forced_release, | 1599 | .callback = atkbd_setup_forced_release, |
1577 | .driver_data = atkbd_amilo_xi3650_forced_release_keys, | 1600 | .driver_data = atkbd_amilo_xi3650_forced_release_keys, |
1578 | }, | 1601 | }, |
1602 | { | ||
1603 | .ident = "Soltech Corporation TA12", | ||
1604 | .matches = { | ||
1605 | DMI_MATCH(DMI_SYS_VENDOR, "Soltech Corporation"), | ||
1606 | DMI_MATCH(DMI_PRODUCT_NAME, "TA12"), | ||
1607 | }, | ||
1608 | .callback = atkbd_setup_forced_release, | ||
1609 | .driver_data = atkdb_soltech_ta12_forced_release_keys, | ||
1610 | }, | ||
1579 | { } | 1611 | { } |
1580 | }; | 1612 | }; |
1581 | 1613 | ||
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index 6d67af5387ad..21cb755a54fb 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c | |||
@@ -114,7 +114,7 @@ static int __devexit pcspkr_remove(struct platform_device *dev) | |||
114 | return 0; | 114 | return 0; |
115 | } | 115 | } |
116 | 116 | ||
117 | static int pcspkr_suspend(struct platform_device *dev, pm_message_t state) | 117 | static int pcspkr_suspend(struct device *dev) |
118 | { | 118 | { |
119 | pcspkr_event(NULL, EV_SND, SND_BELL, 0); | 119 | pcspkr_event(NULL, EV_SND, SND_BELL, 0); |
120 | 120 | ||
@@ -127,14 +127,18 @@ static void pcspkr_shutdown(struct platform_device *dev) | |||
127 | pcspkr_event(NULL, EV_SND, SND_BELL, 0); | 127 | pcspkr_event(NULL, EV_SND, SND_BELL, 0); |
128 | } | 128 | } |
129 | 129 | ||
130 | static struct dev_pm_ops pcspkr_pm_ops = { | ||
131 | .suspend = pcspkr_suspend, | ||
132 | }; | ||
133 | |||
130 | static struct platform_driver pcspkr_platform_driver = { | 134 | static struct platform_driver pcspkr_platform_driver = { |
131 | .driver = { | 135 | .driver = { |
132 | .name = "pcspkr", | 136 | .name = "pcspkr", |
133 | .owner = THIS_MODULE, | 137 | .owner = THIS_MODULE, |
138 | .pm = &pcspkr_pm_ops, | ||
134 | }, | 139 | }, |
135 | .probe = pcspkr_probe, | 140 | .probe = pcspkr_probe, |
136 | .remove = __devexit_p(pcspkr_remove), | 141 | .remove = __devexit_p(pcspkr_remove), |
137 | .suspend = pcspkr_suspend, | ||
138 | .shutdown = pcspkr_shutdown, | 142 | .shutdown = pcspkr_shutdown, |
139 | }; | 143 | }; |
140 | 144 | ||
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 7c8957dd22c0..26e17a9a22eb 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
@@ -646,6 +646,15 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
646 | }, | 646 | }, |
647 | { | 647 | { |
648 | .callback = dmi_matched, | 648 | .callback = dmi_matched, |
649 | .ident = "Maxdata Pro 7000 DX", | ||
650 | .matches = { | ||
651 | DMI_MATCH(DMI_SYS_VENDOR, "MAXDATA"), | ||
652 | DMI_MATCH(DMI_PRODUCT_NAME, "Pro 7000"), | ||
653 | }, | ||
654 | .driver_data = keymap_fs_amilo_pro_v2000 | ||
655 | }, | ||
656 | { | ||
657 | .callback = dmi_matched, | ||
649 | .ident = "Fujitsu N3510", | 658 | .ident = "Fujitsu N3510", |
650 | .matches = { | 659 | .matches = { |
651 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | 660 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), |
diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c index 95aaac03f938..b5e478fa2661 100644 --- a/drivers/mtd/ubi/gluebi.c +++ b/drivers/mtd/ubi/gluebi.c | |||
@@ -332,6 +332,7 @@ static int gluebi_create(struct ubi_device_info *di, | |||
332 | } | 332 | } |
333 | 333 | ||
334 | gluebi->vol_id = vi->vol_id; | 334 | gluebi->vol_id = vi->vol_id; |
335 | gluebi->ubi_num = vi->ubi_num; | ||
335 | mtd->type = MTD_UBIVOLUME; | 336 | mtd->type = MTD_UBIVOLUME; |
336 | if (!di->ro_mode) | 337 | if (!di->ro_mode) |
337 | mtd->flags = MTD_WRITEABLE; | 338 | mtd->flags = MTD_WRITEABLE; |
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index f60895ee0aeb..a423131b6171 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c | |||
@@ -781,7 +781,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, | |||
781 | return -EINVAL; | 781 | return -EINVAL; |
782 | } | 782 | } |
783 | 783 | ||
784 | image_seq = be32_to_cpu(ech->ec); | 784 | image_seq = be32_to_cpu(ech->image_seq); |
785 | if (!si->image_seq_set) { | 785 | if (!si->image_seq_set) { |
786 | ubi->image_seq = image_seq; | 786 | ubi->image_seq = image_seq; |
787 | si->image_seq_set = 1; | 787 | si->image_seq_set = 1; |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index c155bd3ec9f1..b5a7513df4eb 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -1729,6 +1729,12 @@ config KS8842 | |||
1729 | help | 1729 | help |
1730 | This platform driver is for Micrel KSZ8842 chip. | 1730 | This platform driver is for Micrel KSZ8842 chip. |
1731 | 1731 | ||
1732 | config KS8851 | ||
1733 | tristate "Micrel KS8851 SPI" | ||
1734 | depends on SPI | ||
1735 | help | ||
1736 | SPI driver for Micrel KS8851 SPI attached network chip. | ||
1737 | |||
1732 | config VIA_RHINE | 1738 | config VIA_RHINE |
1733 | tristate "VIA Rhine support" | 1739 | tristate "VIA Rhine support" |
1734 | depends on NET_PCI && PCI | 1740 | depends on NET_PCI && PCI |
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 4b58a59f211b..ead8cab3cfe1 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile | |||
@@ -88,6 +88,7 @@ obj-$(CONFIG_SKGE) += skge.o | |||
88 | obj-$(CONFIG_SKY2) += sky2.o | 88 | obj-$(CONFIG_SKY2) += sky2.o |
89 | obj-$(CONFIG_SKFP) += skfp/ | 89 | obj-$(CONFIG_SKFP) += skfp/ |
90 | obj-$(CONFIG_KS8842) += ks8842.o | 90 | obj-$(CONFIG_KS8842) += ks8842.o |
91 | obj-$(CONFIG_KS8851) += ks8851.o | ||
91 | obj-$(CONFIG_VIA_RHINE) += via-rhine.o | 92 | obj-$(CONFIG_VIA_RHINE) += via-rhine.o |
92 | obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o | 93 | obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o |
93 | obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o | 94 | obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o |
diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig index 2895db13bfa4..c37ee9e6b67b 100644 --- a/drivers/net/arm/Kconfig +++ b/drivers/net/arm/Kconfig | |||
@@ -63,3 +63,11 @@ config IXP4XX_ETH | |||
63 | help | 63 | help |
64 | Say Y here if you want to use built-in Ethernet ports | 64 | Say Y here if you want to use built-in Ethernet ports |
65 | on IXP4xx processor. | 65 | on IXP4xx processor. |
66 | |||
67 | config W90P910_ETH | ||
68 | tristate "Nuvoton w90p910 Ethernet support" | ||
69 | depends on ARM && ARCH_W90X900 | ||
70 | select PHYLIB | ||
71 | help | ||
72 | Say Y here if you want to use built-in Ethernet ports | ||
73 | on w90p910 processor. | ||
diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile index 811a3ccd14c1..303171f589e6 100644 --- a/drivers/net/arm/Makefile +++ b/drivers/net/arm/Makefile | |||
@@ -11,3 +11,4 @@ obj-$(CONFIG_ARM_AT91_ETHER) += at91_ether.o | |||
11 | obj-$(CONFIG_ARM_KS8695_ETHER) += ks8695net.o | 11 | obj-$(CONFIG_ARM_KS8695_ETHER) += ks8695net.o |
12 | obj-$(CONFIG_EP93XX_ETH) += ep93xx_eth.o | 12 | obj-$(CONFIG_EP93XX_ETH) += ep93xx_eth.o |
13 | obj-$(CONFIG_IXP4XX_ETH) += ixp4xx_eth.o | 13 | obj-$(CONFIG_IXP4XX_ETH) += ixp4xx_eth.o |
14 | obj-$(CONFIG_W90P910_ETH) += w90p910_ether.o | ||
diff --git a/drivers/net/arm/w90p910_ether.c b/drivers/net/arm/w90p910_ether.c new file mode 100644 index 000000000000..616fb7985a34 --- /dev/null +++ b/drivers/net/arm/w90p910_ether.c | |||
@@ -0,0 +1,1105 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Nuvoton technology corporation. | ||
3 | * | ||
4 | * Wan ZongShun <mcuos.com@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation;version 2 of the License. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/mii.h> | ||
15 | #include <linux/netdevice.h> | ||
16 | #include <linux/etherdevice.h> | ||
17 | #include <linux/skbuff.h> | ||
18 | #include <linux/ethtool.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/clk.h> | ||
21 | |||
22 | #define DRV_MODULE_NAME "w90p910-emc" | ||
23 | #define DRV_MODULE_VERSION "0.1" | ||
24 | |||
25 | /* Ethernet MAC Registers */ | ||
26 | #define REG_CAMCMR 0x00 | ||
27 | #define REG_CAMEN 0x04 | ||
28 | #define REG_CAMM_BASE 0x08 | ||
29 | #define REG_CAML_BASE 0x0c | ||
30 | #define REG_TXDLSA 0x88 | ||
31 | #define REG_RXDLSA 0x8C | ||
32 | #define REG_MCMDR 0x90 | ||
33 | #define REG_MIID 0x94 | ||
34 | #define REG_MIIDA 0x98 | ||
35 | #define REG_FFTCR 0x9C | ||
36 | #define REG_TSDR 0xa0 | ||
37 | #define REG_RSDR 0xa4 | ||
38 | #define REG_DMARFC 0xa8 | ||
39 | #define REG_MIEN 0xac | ||
40 | #define REG_MISTA 0xb0 | ||
41 | #define REG_CTXDSA 0xcc | ||
42 | #define REG_CTXBSA 0xd0 | ||
43 | #define REG_CRXDSA 0xd4 | ||
44 | #define REG_CRXBSA 0xd8 | ||
45 | |||
46 | /* mac controller bit */ | ||
47 | #define MCMDR_RXON 0x01 | ||
48 | #define MCMDR_ACP (0x01 << 3) | ||
49 | #define MCMDR_SPCRC (0x01 << 5) | ||
50 | #define MCMDR_TXON (0x01 << 8) | ||
51 | #define MCMDR_FDUP (0x01 << 18) | ||
52 | #define MCMDR_ENMDC (0x01 << 19) | ||
53 | #define MCMDR_OPMOD (0x01 << 20) | ||
54 | #define SWR (0x01 << 24) | ||
55 | |||
56 | /* cam command regiser */ | ||
57 | #define CAMCMR_AUP 0x01 | ||
58 | #define CAMCMR_AMP (0x01 << 1) | ||
59 | #define CAMCMR_ABP (0x01 << 2) | ||
60 | #define CAMCMR_CCAM (0x01 << 3) | ||
61 | #define CAMCMR_ECMP (0x01 << 4) | ||
62 | #define CAM0EN 0x01 | ||
63 | |||
64 | /* mac mii controller bit */ | ||
65 | #define MDCCR (0x0a << 20) | ||
66 | #define PHYAD (0x01 << 8) | ||
67 | #define PHYWR (0x01 << 16) | ||
68 | #define PHYBUSY (0x01 << 17) | ||
69 | #define PHYPRESP (0x01 << 18) | ||
70 | #define CAM_ENTRY_SIZE 0x08 | ||
71 | |||
72 | /* rx and tx status */ | ||
73 | #define TXDS_TXCP (0x01 << 19) | ||
74 | #define RXDS_CRCE (0x01 << 17) | ||
75 | #define RXDS_PTLE (0x01 << 19) | ||
76 | #define RXDS_RXGD (0x01 << 20) | ||
77 | #define RXDS_ALIE (0x01 << 21) | ||
78 | #define RXDS_RP (0x01 << 22) | ||
79 | |||
80 | /* mac interrupt status*/ | ||
81 | #define MISTA_EXDEF (0x01 << 19) | ||
82 | #define MISTA_TXBERR (0x01 << 24) | ||
83 | #define MISTA_TDU (0x01 << 23) | ||
84 | #define MISTA_RDU (0x01 << 10) | ||
85 | #define MISTA_RXBERR (0x01 << 11) | ||
86 | |||
87 | #define ENSTART 0x01 | ||
88 | #define ENRXINTR 0x01 | ||
89 | #define ENRXGD (0x01 << 4) | ||
90 | #define ENRXBERR (0x01 << 11) | ||
91 | #define ENTXINTR (0x01 << 16) | ||
92 | #define ENTXCP (0x01 << 18) | ||
93 | #define ENTXABT (0x01 << 21) | ||
94 | #define ENTXBERR (0x01 << 24) | ||
95 | #define ENMDC (0x01 << 19) | ||
96 | #define PHYBUSY (0x01 << 17) | ||
97 | #define MDCCR_VAL 0xa00000 | ||
98 | |||
99 | /* rx and tx owner bit */ | ||
100 | #define RX_OWEN_DMA (0x01 << 31) | ||
101 | #define RX_OWEN_CPU (~(0x03 << 30)) | ||
102 | #define TX_OWEN_DMA (0x01 << 31) | ||
103 | #define TX_OWEN_CPU (~(0x01 << 31)) | ||
104 | |||
105 | /* tx frame desc controller bit */ | ||
106 | #define MACTXINTEN 0x04 | ||
107 | #define CRCMODE 0x02 | ||
108 | #define PADDINGMODE 0x01 | ||
109 | |||
110 | /* fftcr controller bit */ | ||
111 | #define TXTHD (0x03 << 8) | ||
112 | #define BLENGTH (0x01 << 20) | ||
113 | |||
114 | /* global setting for driver */ | ||
115 | #define RX_DESC_SIZE 50 | ||
116 | #define TX_DESC_SIZE 10 | ||
117 | #define MAX_RBUFF_SZ 0x600 | ||
118 | #define MAX_TBUFF_SZ 0x600 | ||
119 | #define TX_TIMEOUT 50 | ||
120 | #define DELAY 1000 | ||
121 | #define CAM0 0x0 | ||
122 | |||
123 | static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg); | ||
124 | |||
125 | struct w90p910_rxbd { | ||
126 | unsigned int sl; | ||
127 | unsigned int buffer; | ||
128 | unsigned int reserved; | ||
129 | unsigned int next; | ||
130 | }; | ||
131 | |||
132 | struct w90p910_txbd { | ||
133 | unsigned int mode; | ||
134 | unsigned int buffer; | ||
135 | unsigned int sl; | ||
136 | unsigned int next; | ||
137 | }; | ||
138 | |||
139 | struct recv_pdesc { | ||
140 | struct w90p910_rxbd desclist[RX_DESC_SIZE]; | ||
141 | char recv_buf[RX_DESC_SIZE][MAX_RBUFF_SZ]; | ||
142 | }; | ||
143 | |||
144 | struct tran_pdesc { | ||
145 | struct w90p910_txbd desclist[TX_DESC_SIZE]; | ||
146 | char tran_buf[RX_DESC_SIZE][MAX_TBUFF_SZ]; | ||
147 | }; | ||
148 | |||
149 | struct w90p910_ether { | ||
150 | struct recv_pdesc *rdesc; | ||
151 | struct recv_pdesc *rdesc_phys; | ||
152 | struct tran_pdesc *tdesc; | ||
153 | struct tran_pdesc *tdesc_phys; | ||
154 | struct net_device_stats stats; | ||
155 | struct platform_device *pdev; | ||
156 | struct sk_buff *skb; | ||
157 | struct clk *clk; | ||
158 | struct clk *rmiiclk; | ||
159 | struct mii_if_info mii; | ||
160 | struct timer_list check_timer; | ||
161 | void __iomem *reg; | ||
162 | unsigned int rxirq; | ||
163 | unsigned int txirq; | ||
164 | unsigned int cur_tx; | ||
165 | unsigned int cur_rx; | ||
166 | unsigned int finish_tx; | ||
167 | unsigned int rx_packets; | ||
168 | unsigned int rx_bytes; | ||
169 | unsigned int start_tx_ptr; | ||
170 | unsigned int start_rx_ptr; | ||
171 | unsigned int linkflag; | ||
172 | spinlock_t lock; | ||
173 | }; | ||
174 | |||
175 | static void update_linkspeed_register(struct net_device *dev, | ||
176 | unsigned int speed, unsigned int duplex) | ||
177 | { | ||
178 | struct w90p910_ether *ether = netdev_priv(dev); | ||
179 | unsigned int val; | ||
180 | |||
181 | val = __raw_readl(ether->reg + REG_MCMDR); | ||
182 | |||
183 | if (speed == SPEED_100) { | ||
184 | /* 100 full/half duplex */ | ||
185 | if (duplex == DUPLEX_FULL) { | ||
186 | val |= (MCMDR_OPMOD | MCMDR_FDUP); | ||
187 | } else { | ||
188 | val |= MCMDR_OPMOD; | ||
189 | val &= ~MCMDR_FDUP; | ||
190 | } | ||
191 | } else { | ||
192 | /* 10 full/half duplex */ | ||
193 | if (duplex == DUPLEX_FULL) { | ||
194 | val |= MCMDR_FDUP; | ||
195 | val &= ~MCMDR_OPMOD; | ||
196 | } else { | ||
197 | val &= ~(MCMDR_FDUP | MCMDR_OPMOD); | ||
198 | } | ||
199 | } | ||
200 | |||
201 | __raw_writel(val, ether->reg + REG_MCMDR); | ||
202 | } | ||
203 | |||
204 | static void update_linkspeed(struct net_device *dev) | ||
205 | { | ||
206 | struct w90p910_ether *ether = netdev_priv(dev); | ||
207 | struct platform_device *pdev; | ||
208 | unsigned int bmsr, bmcr, lpa, speed, duplex; | ||
209 | |||
210 | pdev = ether->pdev; | ||
211 | |||
212 | if (!mii_link_ok(ðer->mii)) { | ||
213 | ether->linkflag = 0x0; | ||
214 | netif_carrier_off(dev); | ||
215 | dev_warn(&pdev->dev, "%s: Link down.\n", dev->name); | ||
216 | return; | ||
217 | } | ||
218 | |||
219 | if (ether->linkflag == 1) | ||
220 | return; | ||
221 | |||
222 | bmsr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMSR); | ||
223 | bmcr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMCR); | ||
224 | |||
225 | if (bmcr & BMCR_ANENABLE) { | ||
226 | if (!(bmsr & BMSR_ANEGCOMPLETE)) | ||
227 | return; | ||
228 | |||
229 | lpa = w90p910_mdio_read(dev, ether->mii.phy_id, MII_LPA); | ||
230 | |||
231 | if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) | ||
232 | speed = SPEED_100; | ||
233 | else | ||
234 | speed = SPEED_10; | ||
235 | |||
236 | if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) | ||
237 | duplex = DUPLEX_FULL; | ||
238 | else | ||
239 | duplex = DUPLEX_HALF; | ||
240 | |||
241 | } else { | ||
242 | speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10; | ||
243 | duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; | ||
244 | } | ||
245 | |||
246 | update_linkspeed_register(dev, speed, duplex); | ||
247 | |||
248 | dev_info(&pdev->dev, "%s: Link now %i-%s\n", dev->name, speed, | ||
249 | (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex"); | ||
250 | ether->linkflag = 0x01; | ||
251 | |||
252 | netif_carrier_on(dev); | ||
253 | } | ||
254 | |||
255 | static void w90p910_check_link(unsigned long dev_id) | ||
256 | { | ||
257 | struct net_device *dev = (struct net_device *) dev_id; | ||
258 | struct w90p910_ether *ether = netdev_priv(dev); | ||
259 | |||
260 | update_linkspeed(dev); | ||
261 | mod_timer(ðer->check_timer, jiffies + msecs_to_jiffies(1000)); | ||
262 | } | ||
263 | |||
264 | static void w90p910_write_cam(struct net_device *dev, | ||
265 | unsigned int x, unsigned char *pval) | ||
266 | { | ||
267 | struct w90p910_ether *ether = netdev_priv(dev); | ||
268 | unsigned int msw, lsw; | ||
269 | |||
270 | msw = (pval[0] << 24) | (pval[1] << 16) | (pval[2] << 8) | pval[3]; | ||
271 | |||
272 | lsw = (pval[4] << 24) | (pval[5] << 16); | ||
273 | |||
274 | __raw_writel(lsw, ether->reg + REG_CAML_BASE + x * CAM_ENTRY_SIZE); | ||
275 | __raw_writel(msw, ether->reg + REG_CAMM_BASE + x * CAM_ENTRY_SIZE); | ||
276 | } | ||
277 | |||
278 | static void w90p910_init_desc(struct net_device *dev) | ||
279 | { | ||
280 | struct w90p910_ether *ether; | ||
281 | struct w90p910_txbd *tdesc, *tdesc_phys; | ||
282 | struct w90p910_rxbd *rdesc, *rdesc_phys; | ||
283 | unsigned int i, j; | ||
284 | |||
285 | ether = netdev_priv(dev); | ||
286 | |||
287 | ether->tdesc = (struct tran_pdesc *) | ||
288 | dma_alloc_coherent(NULL, sizeof(struct tran_pdesc), | ||
289 | (dma_addr_t *) ðer->tdesc_phys, GFP_KERNEL); | ||
290 | |||
291 | ether->rdesc = (struct recv_pdesc *) | ||
292 | dma_alloc_coherent(NULL, sizeof(struct recv_pdesc), | ||
293 | (dma_addr_t *) ðer->rdesc_phys, GFP_KERNEL); | ||
294 | |||
295 | for (i = 0; i < TX_DESC_SIZE; i++) { | ||
296 | tdesc = &(ether->tdesc->desclist[i]); | ||
297 | |||
298 | j = ((i + 1) / TX_DESC_SIZE); | ||
299 | |||
300 | if (j != 0) { | ||
301 | tdesc_phys = &(ether->tdesc_phys->desclist[0]); | ||
302 | ether->start_tx_ptr = (unsigned int)tdesc_phys; | ||
303 | tdesc->next = (unsigned int)ether->start_tx_ptr; | ||
304 | } else { | ||
305 | tdesc_phys = &(ether->tdesc_phys->desclist[i+1]); | ||
306 | tdesc->next = (unsigned int)tdesc_phys; | ||
307 | } | ||
308 | |||
309 | tdesc->buffer = (unsigned int)ether->tdesc_phys->tran_buf[i]; | ||
310 | tdesc->sl = 0; | ||
311 | tdesc->mode = 0; | ||
312 | } | ||
313 | |||
314 | for (i = 0; i < RX_DESC_SIZE; i++) { | ||
315 | rdesc = &(ether->rdesc->desclist[i]); | ||
316 | |||
317 | j = ((i + 1) / RX_DESC_SIZE); | ||
318 | |||
319 | if (j != 0) { | ||
320 | rdesc_phys = &(ether->rdesc_phys->desclist[0]); | ||
321 | ether->start_rx_ptr = (unsigned int)rdesc_phys; | ||
322 | rdesc->next = (unsigned int)ether->start_rx_ptr; | ||
323 | } else { | ||
324 | rdesc_phys = &(ether->rdesc_phys->desclist[i+1]); | ||
325 | rdesc->next = (unsigned int)rdesc_phys; | ||
326 | } | ||
327 | |||
328 | rdesc->sl = RX_OWEN_DMA; | ||
329 | rdesc->buffer = (unsigned int)ether->rdesc_phys->recv_buf[i]; | ||
330 | } | ||
331 | } | ||
332 | |||
333 | static void w90p910_set_fifo_threshold(struct net_device *dev) | ||
334 | { | ||
335 | struct w90p910_ether *ether = netdev_priv(dev); | ||
336 | unsigned int val; | ||
337 | |||
338 | val = TXTHD | BLENGTH; | ||
339 | __raw_writel(val, ether->reg + REG_FFTCR); | ||
340 | } | ||
341 | |||
342 | static void w90p910_return_default_idle(struct net_device *dev) | ||
343 | { | ||
344 | struct w90p910_ether *ether = netdev_priv(dev); | ||
345 | unsigned int val; | ||
346 | |||
347 | val = __raw_readl(ether->reg + REG_MCMDR); | ||
348 | val |= SWR; | ||
349 | __raw_writel(val, ether->reg + REG_MCMDR); | ||
350 | } | ||
351 | |||
352 | static void w90p910_trigger_rx(struct net_device *dev) | ||
353 | { | ||
354 | struct w90p910_ether *ether = netdev_priv(dev); | ||
355 | |||
356 | __raw_writel(ENSTART, ether->reg + REG_RSDR); | ||
357 | } | ||
358 | |||
359 | static void w90p910_trigger_tx(struct net_device *dev) | ||
360 | { | ||
361 | struct w90p910_ether *ether = netdev_priv(dev); | ||
362 | |||
363 | __raw_writel(ENSTART, ether->reg + REG_TSDR); | ||
364 | } | ||
365 | |||
366 | static void w90p910_enable_mac_interrupt(struct net_device *dev) | ||
367 | { | ||
368 | struct w90p910_ether *ether = netdev_priv(dev); | ||
369 | unsigned int val; | ||
370 | |||
371 | val = ENTXINTR | ENRXINTR | ENRXGD | ENTXCP; | ||
372 | val |= ENTXBERR | ENRXBERR | ENTXABT; | ||
373 | |||
374 | __raw_writel(val, ether->reg + REG_MIEN); | ||
375 | } | ||
376 | |||
377 | static void w90p910_get_and_clear_int(struct net_device *dev, | ||
378 | unsigned int *val) | ||
379 | { | ||
380 | struct w90p910_ether *ether = netdev_priv(dev); | ||
381 | |||
382 | *val = __raw_readl(ether->reg + REG_MISTA); | ||
383 | __raw_writel(*val, ether->reg + REG_MISTA); | ||
384 | } | ||
385 | |||
386 | static void w90p910_set_global_maccmd(struct net_device *dev) | ||
387 | { | ||
388 | struct w90p910_ether *ether = netdev_priv(dev); | ||
389 | unsigned int val; | ||
390 | |||
391 | val = __raw_readl(ether->reg + REG_MCMDR); | ||
392 | val |= MCMDR_SPCRC | MCMDR_ENMDC | MCMDR_ACP | ENMDC; | ||
393 | __raw_writel(val, ether->reg + REG_MCMDR); | ||
394 | } | ||
395 | |||
396 | static void w90p910_enable_cam(struct net_device *dev) | ||
397 | { | ||
398 | struct w90p910_ether *ether = netdev_priv(dev); | ||
399 | unsigned int val; | ||
400 | |||
401 | w90p910_write_cam(dev, CAM0, dev->dev_addr); | ||
402 | |||
403 | val = __raw_readl(ether->reg + REG_CAMEN); | ||
404 | val |= CAM0EN; | ||
405 | __raw_writel(val, ether->reg + REG_CAMEN); | ||
406 | } | ||
407 | |||
408 | static void w90p910_enable_cam_command(struct net_device *dev) | ||
409 | { | ||
410 | struct w90p910_ether *ether = netdev_priv(dev); | ||
411 | unsigned int val; | ||
412 | |||
413 | val = CAMCMR_ECMP | CAMCMR_ABP | CAMCMR_AMP; | ||
414 | __raw_writel(val, ether->reg + REG_CAMCMR); | ||
415 | } | ||
416 | |||
417 | static void w90p910_enable_tx(struct net_device *dev, unsigned int enable) | ||
418 | { | ||
419 | struct w90p910_ether *ether = netdev_priv(dev); | ||
420 | unsigned int val; | ||
421 | |||
422 | val = __raw_readl(ether->reg + REG_MCMDR); | ||
423 | |||
424 | if (enable) | ||
425 | val |= MCMDR_TXON; | ||
426 | else | ||
427 | val &= ~MCMDR_TXON; | ||
428 | |||
429 | __raw_writel(val, ether->reg + REG_MCMDR); | ||
430 | } | ||
431 | |||
432 | static void w90p910_enable_rx(struct net_device *dev, unsigned int enable) | ||
433 | { | ||
434 | struct w90p910_ether *ether = netdev_priv(dev); | ||
435 | unsigned int val; | ||
436 | |||
437 | val = __raw_readl(ether->reg + REG_MCMDR); | ||
438 | |||
439 | if (enable) | ||
440 | val |= MCMDR_RXON; | ||
441 | else | ||
442 | val &= ~MCMDR_RXON; | ||
443 | |||
444 | __raw_writel(val, ether->reg + REG_MCMDR); | ||
445 | } | ||
446 | |||
447 | static void w90p910_set_curdest(struct net_device *dev) | ||
448 | { | ||
449 | struct w90p910_ether *ether = netdev_priv(dev); | ||
450 | |||
451 | __raw_writel(ether->start_rx_ptr, ether->reg + REG_RXDLSA); | ||
452 | __raw_writel(ether->start_tx_ptr, ether->reg + REG_TXDLSA); | ||
453 | } | ||
454 | |||
455 | static void w90p910_reset_mac(struct net_device *dev) | ||
456 | { | ||
457 | struct w90p910_ether *ether = netdev_priv(dev); | ||
458 | |||
459 | spin_lock(ðer->lock); | ||
460 | |||
461 | w90p910_enable_tx(dev, 0); | ||
462 | w90p910_enable_rx(dev, 0); | ||
463 | w90p910_set_fifo_threshold(dev); | ||
464 | w90p910_return_default_idle(dev); | ||
465 | |||
466 | if (!netif_queue_stopped(dev)) | ||
467 | netif_stop_queue(dev); | ||
468 | |||
469 | w90p910_init_desc(dev); | ||
470 | |||
471 | dev->trans_start = jiffies; | ||
472 | ether->cur_tx = 0x0; | ||
473 | ether->finish_tx = 0x0; | ||
474 | ether->cur_rx = 0x0; | ||
475 | |||
476 | w90p910_set_curdest(dev); | ||
477 | w90p910_enable_cam(dev); | ||
478 | w90p910_enable_cam_command(dev); | ||
479 | w90p910_enable_mac_interrupt(dev); | ||
480 | w90p910_enable_tx(dev, 1); | ||
481 | w90p910_enable_rx(dev, 1); | ||
482 | w90p910_trigger_tx(dev); | ||
483 | w90p910_trigger_rx(dev); | ||
484 | |||
485 | dev->trans_start = jiffies; | ||
486 | |||
487 | if (netif_queue_stopped(dev)) | ||
488 | netif_wake_queue(dev); | ||
489 | |||
490 | spin_unlock(ðer->lock); | ||
491 | } | ||
492 | |||
493 | static void w90p910_mdio_write(struct net_device *dev, | ||
494 | int phy_id, int reg, int data) | ||
495 | { | ||
496 | struct w90p910_ether *ether = netdev_priv(dev); | ||
497 | struct platform_device *pdev; | ||
498 | unsigned int val, i; | ||
499 | |||
500 | pdev = ether->pdev; | ||
501 | |||
502 | __raw_writel(data, ether->reg + REG_MIID); | ||
503 | |||
504 | val = (phy_id << 0x08) | reg; | ||
505 | val |= PHYBUSY | PHYWR | MDCCR_VAL; | ||
506 | __raw_writel(val, ether->reg + REG_MIIDA); | ||
507 | |||
508 | for (i = 0; i < DELAY; i++) { | ||
509 | if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0) | ||
510 | break; | ||
511 | } | ||
512 | |||
513 | if (i == DELAY) | ||
514 | dev_warn(&pdev->dev, "mdio write timed out\n"); | ||
515 | } | ||
516 | |||
517 | static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg) | ||
518 | { | ||
519 | struct w90p910_ether *ether = netdev_priv(dev); | ||
520 | struct platform_device *pdev; | ||
521 | unsigned int val, i, data; | ||
522 | |||
523 | pdev = ether->pdev; | ||
524 | |||
525 | val = (phy_id << 0x08) | reg; | ||
526 | val |= PHYBUSY | MDCCR_VAL; | ||
527 | __raw_writel(val, ether->reg + REG_MIIDA); | ||
528 | |||
529 | for (i = 0; i < DELAY; i++) { | ||
530 | if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0) | ||
531 | break; | ||
532 | } | ||
533 | |||
534 | if (i == DELAY) { | ||
535 | dev_warn(&pdev->dev, "mdio read timed out\n"); | ||
536 | data = 0xffff; | ||
537 | } else { | ||
538 | data = __raw_readl(ether->reg + REG_MIID); | ||
539 | } | ||
540 | |||
541 | return data; | ||
542 | } | ||
543 | |||
544 | static int set_mac_address(struct net_device *dev, void *addr) | ||
545 | { | ||
546 | struct sockaddr *address = addr; | ||
547 | |||
548 | if (!is_valid_ether_addr(address->sa_data)) | ||
549 | return -EADDRNOTAVAIL; | ||
550 | |||
551 | memcpy(dev->dev_addr, address->sa_data, dev->addr_len); | ||
552 | w90p910_write_cam(dev, CAM0, dev->dev_addr); | ||
553 | |||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | static int w90p910_ether_close(struct net_device *dev) | ||
558 | { | ||
559 | struct w90p910_ether *ether = netdev_priv(dev); | ||
560 | |||
561 | dma_free_writecombine(NULL, sizeof(struct w90p910_rxbd), | ||
562 | ether->rdesc, (dma_addr_t)ether->rdesc_phys); | ||
563 | dma_free_writecombine(NULL, sizeof(struct w90p910_txbd), | ||
564 | ether->tdesc, (dma_addr_t)ether->tdesc_phys); | ||
565 | |||
566 | netif_stop_queue(dev); | ||
567 | |||
568 | del_timer_sync(ðer->check_timer); | ||
569 | clk_disable(ether->rmiiclk); | ||
570 | clk_disable(ether->clk); | ||
571 | |||
572 | free_irq(ether->txirq, dev); | ||
573 | free_irq(ether->rxirq, dev); | ||
574 | |||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | static struct net_device_stats *w90p910_ether_stats(struct net_device *dev) | ||
579 | { | ||
580 | struct w90p910_ether *ether; | ||
581 | |||
582 | ether = netdev_priv(dev); | ||
583 | |||
584 | return ðer->stats; | ||
585 | } | ||
586 | |||
587 | static int w90p910_send_frame(struct net_device *dev, | ||
588 | unsigned char *data, int length) | ||
589 | { | ||
590 | struct w90p910_ether *ether; | ||
591 | struct w90p910_txbd *txbd; | ||
592 | struct platform_device *pdev; | ||
593 | unsigned char *buffer; | ||
594 | |||
595 | ether = netdev_priv(dev); | ||
596 | pdev = ether->pdev; | ||
597 | |||
598 | txbd = ðer->tdesc->desclist[ether->cur_tx]; | ||
599 | buffer = ether->tdesc->tran_buf[ether->cur_tx]; | ||
600 | if (length > 1514) { | ||
601 | dev_err(&pdev->dev, "send data %d bytes, check it\n", length); | ||
602 | length = 1514; | ||
603 | } | ||
604 | |||
605 | txbd->sl = length & 0xFFFF; | ||
606 | |||
607 | memcpy(buffer, data, length); | ||
608 | |||
609 | txbd->mode = TX_OWEN_DMA | PADDINGMODE | CRCMODE | MACTXINTEN; | ||
610 | |||
611 | w90p910_enable_tx(dev, 1); | ||
612 | |||
613 | w90p910_trigger_tx(dev); | ||
614 | |||
615 | ether->cur_tx = (ether->cur_tx+1) % TX_DESC_SIZE; | ||
616 | txbd = ðer->tdesc->desclist[ether->cur_tx]; | ||
617 | |||
618 | dev->trans_start = jiffies; | ||
619 | |||
620 | if (txbd->mode & TX_OWEN_DMA) | ||
621 | netif_stop_queue(dev); | ||
622 | |||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | static int w90p910_ether_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
627 | { | ||
628 | struct w90p910_ether *ether = netdev_priv(dev); | ||
629 | |||
630 | if (!(w90p910_send_frame(dev, skb->data, skb->len))) { | ||
631 | ether->skb = skb; | ||
632 | dev_kfree_skb_irq(skb); | ||
633 | return 0; | ||
634 | } | ||
635 | return -1; | ||
636 | } | ||
637 | |||
638 | static irqreturn_t w90p910_tx_interrupt(int irq, void *dev_id) | ||
639 | { | ||
640 | struct w90p910_ether *ether; | ||
641 | struct w90p910_txbd *txbd; | ||
642 | struct platform_device *pdev; | ||
643 | struct tran_pdesc *tran_pdesc; | ||
644 | struct net_device *dev; | ||
645 | unsigned int cur_entry, entry, status; | ||
646 | |||
647 | dev = (struct net_device *)dev_id; | ||
648 | ether = netdev_priv(dev); | ||
649 | pdev = ether->pdev; | ||
650 | |||
651 | spin_lock(ðer->lock); | ||
652 | |||
653 | w90p910_get_and_clear_int(dev, &status); | ||
654 | |||
655 | cur_entry = __raw_readl(ether->reg + REG_CTXDSA); | ||
656 | |||
657 | tran_pdesc = ether->tdesc_phys; | ||
658 | entry = (unsigned int)(&tran_pdesc->desclist[ether->finish_tx]); | ||
659 | |||
660 | while (entry != cur_entry) { | ||
661 | txbd = ðer->tdesc->desclist[ether->finish_tx]; | ||
662 | |||
663 | ether->finish_tx = (ether->finish_tx + 1) % TX_DESC_SIZE; | ||
664 | |||
665 | if (txbd->sl & TXDS_TXCP) { | ||
666 | ether->stats.tx_packets++; | ||
667 | ether->stats.tx_bytes += txbd->sl & 0xFFFF; | ||
668 | } else { | ||
669 | ether->stats.tx_errors++; | ||
670 | } | ||
671 | |||
672 | txbd->sl = 0x0; | ||
673 | txbd->mode = 0x0; | ||
674 | |||
675 | if (netif_queue_stopped(dev)) | ||
676 | netif_wake_queue(dev); | ||
677 | |||
678 | entry = (unsigned int)(&tran_pdesc->desclist[ether->finish_tx]); | ||
679 | } | ||
680 | |||
681 | if (status & MISTA_EXDEF) { | ||
682 | dev_err(&pdev->dev, "emc defer exceed interrupt\n"); | ||
683 | } else if (status & MISTA_TXBERR) { | ||
684 | dev_err(&pdev->dev, "emc bus error interrupt\n"); | ||
685 | w90p910_reset_mac(dev); | ||
686 | } else if (status & MISTA_TDU) { | ||
687 | if (netif_queue_stopped(dev)) | ||
688 | netif_wake_queue(dev); | ||
689 | } | ||
690 | |||
691 | spin_unlock(ðer->lock); | ||
692 | |||
693 | return IRQ_HANDLED; | ||
694 | } | ||
695 | |||
696 | static void netdev_rx(struct net_device *dev) | ||
697 | { | ||
698 | struct w90p910_ether *ether; | ||
699 | struct w90p910_rxbd *rxbd; | ||
700 | struct platform_device *pdev; | ||
701 | struct recv_pdesc *rdesc_phys; | ||
702 | struct sk_buff *skb; | ||
703 | unsigned char *data; | ||
704 | unsigned int length, status, val, entry; | ||
705 | |||
706 | ether = netdev_priv(dev); | ||
707 | pdev = ether->pdev; | ||
708 | rdesc_phys = ether->rdesc_phys; | ||
709 | |||
710 | rxbd = ðer->rdesc->desclist[ether->cur_rx]; | ||
711 | |||
712 | do { | ||
713 | val = __raw_readl(ether->reg + REG_CRXDSA); | ||
714 | entry = (unsigned int)&rdesc_phys->desclist[ether->cur_rx]; | ||
715 | |||
716 | if (val == entry) | ||
717 | break; | ||
718 | |||
719 | status = rxbd->sl; | ||
720 | length = status & 0xFFFF; | ||
721 | |||
722 | if (status & RXDS_RXGD) { | ||
723 | data = ether->rdesc->recv_buf[ether->cur_rx]; | ||
724 | skb = dev_alloc_skb(length+2); | ||
725 | if (!skb) { | ||
726 | dev_err(&pdev->dev, "get skb buffer error\n"); | ||
727 | ether->stats.rx_dropped++; | ||
728 | return; | ||
729 | } | ||
730 | |||
731 | skb->dev = dev; | ||
732 | skb_reserve(skb, 2); | ||
733 | skb_put(skb, length); | ||
734 | skb_copy_to_linear_data(skb, data, length); | ||
735 | skb->protocol = eth_type_trans(skb, dev); | ||
736 | ether->stats.rx_packets++; | ||
737 | ether->stats.rx_bytes += length; | ||
738 | netif_rx(skb); | ||
739 | } else { | ||
740 | ether->stats.rx_errors++; | ||
741 | |||
742 | if (status & RXDS_RP) { | ||
743 | dev_err(&pdev->dev, "rx runt err\n"); | ||
744 | ether->stats.rx_length_errors++; | ||
745 | } else if (status & RXDS_CRCE) { | ||
746 | dev_err(&pdev->dev, "rx crc err\n"); | ||
747 | ether->stats.rx_crc_errors++; | ||
748 | } | ||
749 | |||
750 | if (status & RXDS_ALIE) { | ||
751 | dev_err(&pdev->dev, "rx aligment err\n"); | ||
752 | ether->stats.rx_frame_errors++; | ||
753 | } else if (status & RXDS_PTLE) { | ||
754 | dev_err(&pdev->dev, "rx longer err\n"); | ||
755 | ether->stats.rx_over_errors++; | ||
756 | } | ||
757 | } | ||
758 | |||
759 | rxbd->sl = RX_OWEN_DMA; | ||
760 | rxbd->reserved = 0x0; | ||
761 | ether->cur_rx = (ether->cur_rx+1) % RX_DESC_SIZE; | ||
762 | rxbd = ðer->rdesc->desclist[ether->cur_rx]; | ||
763 | |||
764 | dev->last_rx = jiffies; | ||
765 | } while (1); | ||
766 | } | ||
767 | |||
768 | static irqreturn_t w90p910_rx_interrupt(int irq, void *dev_id) | ||
769 | { | ||
770 | struct net_device *dev; | ||
771 | struct w90p910_ether *ether; | ||
772 | struct platform_device *pdev; | ||
773 | unsigned int status; | ||
774 | |||
775 | dev = (struct net_device *)dev_id; | ||
776 | ether = netdev_priv(dev); | ||
777 | pdev = ether->pdev; | ||
778 | |||
779 | spin_lock(ðer->lock); | ||
780 | |||
781 | w90p910_get_and_clear_int(dev, &status); | ||
782 | |||
783 | if (status & MISTA_RDU) { | ||
784 | netdev_rx(dev); | ||
785 | |||
786 | w90p910_trigger_rx(dev); | ||
787 | |||
788 | spin_unlock(ðer->lock); | ||
789 | return IRQ_HANDLED; | ||
790 | } else if (status & MISTA_RXBERR) { | ||
791 | dev_err(&pdev->dev, "emc rx bus error\n"); | ||
792 | w90p910_reset_mac(dev); | ||
793 | } | ||
794 | |||
795 | netdev_rx(dev); | ||
796 | spin_unlock(ðer->lock); | ||
797 | return IRQ_HANDLED; | ||
798 | } | ||
799 | |||
800 | static int w90p910_ether_open(struct net_device *dev) | ||
801 | { | ||
802 | struct w90p910_ether *ether; | ||
803 | struct platform_device *pdev; | ||
804 | |||
805 | ether = netdev_priv(dev); | ||
806 | pdev = ether->pdev; | ||
807 | |||
808 | w90p910_reset_mac(dev); | ||
809 | w90p910_set_fifo_threshold(dev); | ||
810 | w90p910_set_curdest(dev); | ||
811 | w90p910_enable_cam(dev); | ||
812 | w90p910_enable_cam_command(dev); | ||
813 | w90p910_enable_mac_interrupt(dev); | ||
814 | w90p910_set_global_maccmd(dev); | ||
815 | w90p910_enable_rx(dev, 1); | ||
816 | |||
817 | ether->rx_packets = 0x0; | ||
818 | ether->rx_bytes = 0x0; | ||
819 | |||
820 | if (request_irq(ether->txirq, w90p910_tx_interrupt, | ||
821 | 0x0, pdev->name, dev)) { | ||
822 | dev_err(&pdev->dev, "register irq tx failed\n"); | ||
823 | return -EAGAIN; | ||
824 | } | ||
825 | |||
826 | if (request_irq(ether->rxirq, w90p910_rx_interrupt, | ||
827 | 0x0, pdev->name, dev)) { | ||
828 | dev_err(&pdev->dev, "register irq rx failed\n"); | ||
829 | return -EAGAIN; | ||
830 | } | ||
831 | |||
832 | mod_timer(ðer->check_timer, jiffies + msecs_to_jiffies(1000)); | ||
833 | netif_start_queue(dev); | ||
834 | w90p910_trigger_rx(dev); | ||
835 | |||
836 | dev_info(&pdev->dev, "%s is OPENED\n", dev->name); | ||
837 | |||
838 | return 0; | ||
839 | } | ||
840 | |||
841 | static void w90p910_ether_set_multicast_list(struct net_device *dev) | ||
842 | { | ||
843 | struct w90p910_ether *ether; | ||
844 | unsigned int rx_mode; | ||
845 | |||
846 | ether = netdev_priv(dev); | ||
847 | |||
848 | if (dev->flags & IFF_PROMISC) | ||
849 | rx_mode = CAMCMR_AUP | CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP; | ||
850 | else if ((dev->flags & IFF_ALLMULTI) || dev->mc_list) | ||
851 | rx_mode = CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP; | ||
852 | else | ||
853 | rx_mode = CAMCMR_ECMP | CAMCMR_ABP; | ||
854 | __raw_writel(rx_mode, ether->reg + REG_CAMCMR); | ||
855 | } | ||
856 | |||
857 | static int w90p910_ether_ioctl(struct net_device *dev, | ||
858 | struct ifreq *ifr, int cmd) | ||
859 | { | ||
860 | struct w90p910_ether *ether = netdev_priv(dev); | ||
861 | struct mii_ioctl_data *data = if_mii(ifr); | ||
862 | |||
863 | return generic_mii_ioctl(ðer->mii, data, cmd, NULL); | ||
864 | } | ||
865 | |||
866 | static void w90p910_get_drvinfo(struct net_device *dev, | ||
867 | struct ethtool_drvinfo *info) | ||
868 | { | ||
869 | strcpy(info->driver, DRV_MODULE_NAME); | ||
870 | strcpy(info->version, DRV_MODULE_VERSION); | ||
871 | } | ||
872 | |||
873 | static int w90p910_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
874 | { | ||
875 | struct w90p910_ether *ether = netdev_priv(dev); | ||
876 | return mii_ethtool_gset(ðer->mii, cmd); | ||
877 | } | ||
878 | |||
879 | static int w90p910_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
880 | { | ||
881 | struct w90p910_ether *ether = netdev_priv(dev); | ||
882 | return mii_ethtool_sset(ðer->mii, cmd); | ||
883 | } | ||
884 | |||
885 | static int w90p910_nway_reset(struct net_device *dev) | ||
886 | { | ||
887 | struct w90p910_ether *ether = netdev_priv(dev); | ||
888 | return mii_nway_restart(ðer->mii); | ||
889 | } | ||
890 | |||
891 | static u32 w90p910_get_link(struct net_device *dev) | ||
892 | { | ||
893 | struct w90p910_ether *ether = netdev_priv(dev); | ||
894 | return mii_link_ok(ðer->mii); | ||
895 | } | ||
896 | |||
897 | static const struct ethtool_ops w90p910_ether_ethtool_ops = { | ||
898 | .get_settings = w90p910_get_settings, | ||
899 | .set_settings = w90p910_set_settings, | ||
900 | .get_drvinfo = w90p910_get_drvinfo, | ||
901 | .nway_reset = w90p910_nway_reset, | ||
902 | .get_link = w90p910_get_link, | ||
903 | }; | ||
904 | |||
905 | static const struct net_device_ops w90p910_ether_netdev_ops = { | ||
906 | .ndo_open = w90p910_ether_open, | ||
907 | .ndo_stop = w90p910_ether_close, | ||
908 | .ndo_start_xmit = w90p910_ether_start_xmit, | ||
909 | .ndo_get_stats = w90p910_ether_stats, | ||
910 | .ndo_set_multicast_list = w90p910_ether_set_multicast_list, | ||
911 | .ndo_set_mac_address = set_mac_address, | ||
912 | .ndo_do_ioctl = w90p910_ether_ioctl, | ||
913 | .ndo_validate_addr = eth_validate_addr, | ||
914 | .ndo_change_mtu = eth_change_mtu, | ||
915 | }; | ||
916 | |||
917 | static void __init get_mac_address(struct net_device *dev) | ||
918 | { | ||
919 | struct w90p910_ether *ether = netdev_priv(dev); | ||
920 | struct platform_device *pdev; | ||
921 | char addr[6]; | ||
922 | |||
923 | pdev = ether->pdev; | ||
924 | |||
925 | addr[0] = 0x00; | ||
926 | addr[1] = 0x02; | ||
927 | addr[2] = 0xac; | ||
928 | addr[3] = 0x55; | ||
929 | addr[4] = 0x88; | ||
930 | addr[5] = 0xa8; | ||
931 | |||
932 | if (is_valid_ether_addr(addr)) | ||
933 | memcpy(dev->dev_addr, &addr, 0x06); | ||
934 | else | ||
935 | dev_err(&pdev->dev, "invalid mac address\n"); | ||
936 | } | ||
937 | |||
938 | static int w90p910_ether_setup(struct net_device *dev) | ||
939 | { | ||
940 | struct w90p910_ether *ether = netdev_priv(dev); | ||
941 | |||
942 | ether_setup(dev); | ||
943 | dev->netdev_ops = &w90p910_ether_netdev_ops; | ||
944 | dev->ethtool_ops = &w90p910_ether_ethtool_ops; | ||
945 | |||
946 | dev->tx_queue_len = 16; | ||
947 | dev->dma = 0x0; | ||
948 | dev->watchdog_timeo = TX_TIMEOUT; | ||
949 | |||
950 | get_mac_address(dev); | ||
951 | |||
952 | spin_lock_init(ðer->lock); | ||
953 | |||
954 | ether->cur_tx = 0x0; | ||
955 | ether->cur_rx = 0x0; | ||
956 | ether->finish_tx = 0x0; | ||
957 | ether->linkflag = 0x0; | ||
958 | ether->mii.phy_id = 0x01; | ||
959 | ether->mii.phy_id_mask = 0x1f; | ||
960 | ether->mii.reg_num_mask = 0x1f; | ||
961 | ether->mii.dev = dev; | ||
962 | ether->mii.mdio_read = w90p910_mdio_read; | ||
963 | ether->mii.mdio_write = w90p910_mdio_write; | ||
964 | |||
965 | setup_timer(ðer->check_timer, w90p910_check_link, | ||
966 | (unsigned long)dev); | ||
967 | |||
968 | return 0; | ||
969 | } | ||
970 | |||
971 | static int __devinit w90p910_ether_probe(struct platform_device *pdev) | ||
972 | { | ||
973 | struct w90p910_ether *ether; | ||
974 | struct net_device *dev; | ||
975 | struct resource *res; | ||
976 | int error; | ||
977 | |||
978 | dev = alloc_etherdev(sizeof(struct w90p910_ether)); | ||
979 | if (!dev) | ||
980 | return -ENOMEM; | ||
981 | |||
982 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
983 | if (res == NULL) { | ||
984 | dev_err(&pdev->dev, "failed to get I/O memory\n"); | ||
985 | error = -ENXIO; | ||
986 | goto failed_free; | ||
987 | } | ||
988 | |||
989 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
990 | if (res == NULL) { | ||
991 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | ||
992 | error = -EBUSY; | ||
993 | goto failed_free; | ||
994 | } | ||
995 | |||
996 | ether = netdev_priv(dev); | ||
997 | |||
998 | ether->reg = ioremap(res->start, resource_size(res)); | ||
999 | if (ether->reg == NULL) { | ||
1000 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | ||
1001 | error = -ENXIO; | ||
1002 | goto failed_free_mem; | ||
1003 | } | ||
1004 | |||
1005 | ether->txirq = platform_get_irq(pdev, 0); | ||
1006 | if (ether->txirq < 0) { | ||
1007 | dev_err(&pdev->dev, "failed to get ether tx irq\n"); | ||
1008 | error = -ENXIO; | ||
1009 | goto failed_free_io; | ||
1010 | } | ||
1011 | |||
1012 | ether->rxirq = platform_get_irq(pdev, 1); | ||
1013 | if (ether->rxirq < 0) { | ||
1014 | dev_err(&pdev->dev, "failed to get ether rx irq\n"); | ||
1015 | error = -ENXIO; | ||
1016 | goto failed_free_txirq; | ||
1017 | } | ||
1018 | |||
1019 | platform_set_drvdata(pdev, dev); | ||
1020 | |||
1021 | ether->clk = clk_get(&pdev->dev, NULL); | ||
1022 | if (IS_ERR(ether->clk)) { | ||
1023 | dev_err(&pdev->dev, "failed to get ether clock\n"); | ||
1024 | error = PTR_ERR(ether->clk); | ||
1025 | goto failed_free_rxirq; | ||
1026 | } | ||
1027 | |||
1028 | ether->rmiiclk = clk_get(&pdev->dev, "RMII"); | ||
1029 | if (IS_ERR(ether->rmiiclk)) { | ||
1030 | dev_err(&pdev->dev, "failed to get ether clock\n"); | ||
1031 | error = PTR_ERR(ether->rmiiclk); | ||
1032 | goto failed_put_clk; | ||
1033 | } | ||
1034 | |||
1035 | ether->pdev = pdev; | ||
1036 | |||
1037 | w90p910_ether_setup(dev); | ||
1038 | |||
1039 | error = register_netdev(dev); | ||
1040 | if (error != 0) { | ||
1041 | dev_err(&pdev->dev, "Regiter EMC w90p910 FAILED\n"); | ||
1042 | error = -ENODEV; | ||
1043 | goto failed_put_rmiiclk; | ||
1044 | } | ||
1045 | |||
1046 | return 0; | ||
1047 | failed_put_rmiiclk: | ||
1048 | clk_put(ether->rmiiclk); | ||
1049 | failed_put_clk: | ||
1050 | clk_put(ether->clk); | ||
1051 | failed_free_rxirq: | ||
1052 | free_irq(ether->rxirq, pdev); | ||
1053 | platform_set_drvdata(pdev, NULL); | ||
1054 | failed_free_txirq: | ||
1055 | free_irq(ether->txirq, pdev); | ||
1056 | failed_free_io: | ||
1057 | iounmap(ether->reg); | ||
1058 | failed_free_mem: | ||
1059 | release_mem_region(res->start, resource_size(res)); | ||
1060 | failed_free: | ||
1061 | free_netdev(dev); | ||
1062 | return error; | ||
1063 | } | ||
1064 | |||
1065 | static int __devexit w90p910_ether_remove(struct platform_device *pdev) | ||
1066 | { | ||
1067 | struct net_device *dev = platform_get_drvdata(pdev); | ||
1068 | struct w90p910_ether *ether = netdev_priv(dev); | ||
1069 | |||
1070 | unregister_netdev(dev); | ||
1071 | clk_put(ether->rmiiclk); | ||
1072 | clk_put(ether->clk); | ||
1073 | del_timer_sync(ðer->check_timer); | ||
1074 | platform_set_drvdata(pdev, NULL); | ||
1075 | free_netdev(dev); | ||
1076 | return 0; | ||
1077 | } | ||
1078 | |||
1079 | static struct platform_driver w90p910_ether_driver = { | ||
1080 | .probe = w90p910_ether_probe, | ||
1081 | .remove = __devexit_p(w90p910_ether_remove), | ||
1082 | .driver = { | ||
1083 | .name = "w90p910-emc", | ||
1084 | .owner = THIS_MODULE, | ||
1085 | }, | ||
1086 | }; | ||
1087 | |||
1088 | static int __init w90p910_ether_init(void) | ||
1089 | { | ||
1090 | return platform_driver_register(&w90p910_ether_driver); | ||
1091 | } | ||
1092 | |||
1093 | static void __exit w90p910_ether_exit(void) | ||
1094 | { | ||
1095 | platform_driver_unregister(&w90p910_ether_driver); | ||
1096 | } | ||
1097 | |||
1098 | module_init(w90p910_ether_init); | ||
1099 | module_exit(w90p910_ether_exit); | ||
1100 | |||
1101 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); | ||
1102 | MODULE_DESCRIPTION("w90p910 MAC driver!"); | ||
1103 | MODULE_LICENSE("GPL"); | ||
1104 | MODULE_ALIAS("platform:w90p910-emc"); | ||
1105 | |||
diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h index e1658ef3fcdf..2a1120ad2e74 100644 --- a/drivers/net/atl1c/atl1c.h +++ b/drivers/net/atl1c/atl1c.h | |||
@@ -188,14 +188,14 @@ struct atl1c_tpd_ext_desc { | |||
188 | #define RRS_HDS_TYPE_DATA 2 | 188 | #define RRS_HDS_TYPE_DATA 2 |
189 | 189 | ||
190 | #define RRS_IS_NO_HDS_TYPE(flag) \ | 190 | #define RRS_IS_NO_HDS_TYPE(flag) \ |
191 | (((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == 0) | 191 | ((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == 0) |
192 | 192 | ||
193 | #define RRS_IS_HDS_HEAD(flag) \ | 193 | #define RRS_IS_HDS_HEAD(flag) \ |
194 | (((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == \ | 194 | ((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \ |
195 | RRS_HDS_TYPE_HEAD) | 195 | RRS_HDS_TYPE_HEAD) |
196 | 196 | ||
197 | #define RRS_IS_HDS_DATA(flag) \ | 197 | #define RRS_IS_HDS_DATA(flag) \ |
198 | (((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == \ | 198 | ((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \ |
199 | RRS_HDS_TYPE_DATA) | 199 | RRS_HDS_TYPE_DATA) |
200 | 200 | ||
201 | /* rrs word 3 bit 0:31 */ | 201 | /* rrs word 3 bit 0:31 */ |
@@ -245,7 +245,7 @@ struct atl1c_tpd_ext_desc { | |||
245 | #define RRS_PACKET_TYPE_802_3 1 | 245 | #define RRS_PACKET_TYPE_802_3 1 |
246 | #define RRS_PACKET_TYPE_ETH 0 | 246 | #define RRS_PACKET_TYPE_ETH 0 |
247 | #define RRS_PACKET_IS_ETH(word) \ | 247 | #define RRS_PACKET_IS_ETH(word) \ |
248 | (((word) >> RRS_PACKET_TYPE_SHIFT) & RRS_PACKET_TYPE_MASK == \ | 248 | ((((word) >> RRS_PACKET_TYPE_SHIFT) & RRS_PACKET_TYPE_MASK) == \ |
249 | RRS_PACKET_TYPE_ETH) | 249 | RRS_PACKET_TYPE_ETH) |
250 | #define RRS_RXD_IS_VALID(word) \ | 250 | #define RRS_RXD_IS_VALID(word) \ |
251 | ((((word) >> RRS_RXD_UPDATED_SHIFT) & RRS_RXD_UPDATED_MASK) == 1) | 251 | ((((word) >> RRS_RXD_UPDATED_SHIFT) & RRS_RXD_UPDATED_MASK) == 1) |
diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index cd547a205fb9..a383122679de 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c | |||
@@ -1689,7 +1689,7 @@ static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que, | |||
1689 | if (likely(RRS_RXD_IS_VALID(rrs->word3))) { | 1689 | if (likely(RRS_RXD_IS_VALID(rrs->word3))) { |
1690 | rfd_num = (rrs->word0 >> RRS_RX_RFD_CNT_SHIFT) & | 1690 | rfd_num = (rrs->word0 >> RRS_RX_RFD_CNT_SHIFT) & |
1691 | RRS_RX_RFD_CNT_MASK; | 1691 | RRS_RX_RFD_CNT_MASK; |
1692 | if (unlikely(rfd_num) != 1) | 1692 | if (unlikely(rfd_num != 1)) |
1693 | /* TODO support mul rfd*/ | 1693 | /* TODO support mul rfd*/ |
1694 | if (netif_msg_rx_err(adapter)) | 1694 | if (netif_msg_rx_err(adapter)) |
1695 | dev_warn(&pdev->dev, | 1695 | dev_warn(&pdev->dev, |
diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index ed648acef7cf..2ee581a2cdec 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c | |||
@@ -4212,13 +4212,14 @@ static void bnx2x_turn_off_sf(struct bnx2x *bp, u8 port) | |||
4212 | u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded, | 4212 | u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded, |
4213 | u8 *version, u16 len) | 4213 | u8 *version, u16 len) |
4214 | { | 4214 | { |
4215 | struct bnx2x *bp = params->bp; | 4215 | struct bnx2x *bp; |
4216 | u32 ext_phy_type = 0; | 4216 | u32 ext_phy_type = 0; |
4217 | u32 spirom_ver = 0; | 4217 | u32 spirom_ver = 0; |
4218 | u8 status = 0 ; | 4218 | u8 status = 0 ; |
4219 | 4219 | ||
4220 | if (version == NULL || params == NULL) | 4220 | if (version == NULL || params == NULL) |
4221 | return -EINVAL; | 4221 | return -EINVAL; |
4222 | bp = params->bp; | ||
4222 | 4223 | ||
4223 | spirom_ver = REG_RD(bp, params->shmem_base + | 4224 | spirom_ver = REG_RD(bp, params->shmem_base + |
4224 | offsetof(struct shmem_region, | 4225 | offsetof(struct shmem_region, |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index d927f71af8a3..aa1be1feceed 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -1459,8 +1459,16 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1459 | * ether type (eg ARPHRD_ETHER and ARPHRD_INFINIBAND) share the same bond | 1459 | * ether type (eg ARPHRD_ETHER and ARPHRD_INFINIBAND) share the same bond |
1460 | */ | 1460 | */ |
1461 | if (bond->slave_cnt == 0) { | 1461 | if (bond->slave_cnt == 0) { |
1462 | if (slave_dev->type != ARPHRD_ETHER) | 1462 | if (bond_dev->type != slave_dev->type) { |
1463 | bond_setup_by_slave(bond_dev, slave_dev); | 1463 | dev_close(bond_dev); |
1464 | pr_debug("%s: change device type from %d to %d\n", | ||
1465 | bond_dev->name, bond_dev->type, slave_dev->type); | ||
1466 | if (slave_dev->type != ARPHRD_ETHER) | ||
1467 | bond_setup_by_slave(bond_dev, slave_dev); | ||
1468 | else | ||
1469 | ether_setup(bond_dev); | ||
1470 | dev_open(bond_dev); | ||
1471 | } | ||
1464 | } else if (bond_dev->type != slave_dev->type) { | 1472 | } else if (bond_dev->type != slave_dev->type) { |
1465 | pr_err(DRV_NAME ": %s ether type (%d) is different " | 1473 | pr_err(DRV_NAME ": %s ether type (%d) is different " |
1466 | "from other slaves (%d), can not enslave it.\n", | 1474 | "from other slaves (%d), can not enslave it.\n", |
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 574daddc21bf..9e4283aff828 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c | |||
@@ -346,7 +346,7 @@ void can_restart(unsigned long data) | |||
346 | skb = dev_alloc_skb(sizeof(struct can_frame)); | 346 | skb = dev_alloc_skb(sizeof(struct can_frame)); |
347 | if (skb == NULL) { | 347 | if (skb == NULL) { |
348 | err = -ENOMEM; | 348 | err = -ENOMEM; |
349 | goto out; | 349 | goto restart; |
350 | } | 350 | } |
351 | skb->dev = dev; | 351 | skb->dev = dev; |
352 | skb->protocol = htons(ETH_P_CAN); | 352 | skb->protocol = htons(ETH_P_CAN); |
@@ -361,13 +361,13 @@ void can_restart(unsigned long data) | |||
361 | stats->rx_packets++; | 361 | stats->rx_packets++; |
362 | stats->rx_bytes += cf->can_dlc; | 362 | stats->rx_bytes += cf->can_dlc; |
363 | 363 | ||
364 | restart: | ||
364 | dev_dbg(dev->dev.parent, "restarted\n"); | 365 | dev_dbg(dev->dev.parent, "restarted\n"); |
365 | priv->can_stats.restarts++; | 366 | priv->can_stats.restarts++; |
366 | 367 | ||
367 | /* Now restart the device */ | 368 | /* Now restart the device */ |
368 | err = priv->do_set_mode(dev, CAN_MODE_START); | 369 | err = priv->do_set_mode(dev, CAN_MODE_START); |
369 | 370 | ||
370 | out: | ||
371 | netif_carrier_on(dev); | 371 | netif_carrier_on(dev); |
372 | if (err) | 372 | if (err) |
373 | dev_err(dev->dev.parent, "Error %d during restart", err); | 373 | dev_err(dev->dev.parent, "Error %d during restart", err); |
@@ -473,6 +473,10 @@ int open_candev(struct net_device *dev) | |||
473 | return -EINVAL; | 473 | return -EINVAL; |
474 | } | 474 | } |
475 | 475 | ||
476 | /* Switch carrier on if device was stopped while in bus-off state */ | ||
477 | if (!netif_carrier_ok(dev)) | ||
478 | netif_carrier_on(dev); | ||
479 | |||
476 | setup_timer(&priv->restart_timer, can_restart, (unsigned long)dev); | 480 | setup_timer(&priv->restart_timer, can_restart, (unsigned long)dev); |
477 | 481 | ||
478 | return 0; | 482 | return 0; |
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 571f133a8fec..08ebee79d8a6 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c | |||
@@ -63,7 +63,6 @@ | |||
63 | #include <linux/can.h> | 63 | #include <linux/can.h> |
64 | #include <linux/can/dev.h> | 64 | #include <linux/can/dev.h> |
65 | #include <linux/can/error.h> | 65 | #include <linux/can/error.h> |
66 | #include <linux/can/dev.h> | ||
67 | 66 | ||
68 | #include "sja1000.h" | 67 | #include "sja1000.h" |
69 | 68 | ||
diff --git a/drivers/net/e100.c b/drivers/net/e100.c index efa680f4b8dd..41b648a67fec 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c | |||
@@ -1897,6 +1897,9 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, | |||
1897 | 1897 | ||
1898 | if (ioread8(&nic->csr->scb.status) & rus_no_res) | 1898 | if (ioread8(&nic->csr->scb.status) & rus_no_res) |
1899 | nic->ru_running = RU_SUSPENDED; | 1899 | nic->ru_running = RU_SUSPENDED; |
1900 | pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, | ||
1901 | sizeof(struct rfd), | ||
1902 | PCI_DMA_BIDIRECTIONAL); | ||
1900 | return -ENODATA; | 1903 | return -ENODATA; |
1901 | } | 1904 | } |
1902 | 1905 | ||
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 155160052c8b..981ab530e9ac 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * devices like TTY. It interfaces between a raw TTY and the | 3 | * devices like TTY. It interfaces between a raw TTY and the |
4 | * kernel's AX.25 protocol layers. | 4 | * kernel's AX.25 protocol layers. |
5 | * | 5 | * |
6 | * Authors: Andreas Könsgen <ajk@iehk.rwth-aachen.de> | 6 | * Authors: Andreas Könsgen <ajk@comnets.uni-bremen.de> |
7 | * Ralf Baechle DL5RB <ralf@linux-mips.org> | 7 | * Ralf Baechle DL5RB <ralf@linux-mips.org> |
8 | * | 8 | * |
9 | * Quite a lot of stuff "stolen" by Joerg Reuter from slip.c, written by | 9 | * Quite a lot of stuff "stolen" by Joerg Reuter from slip.c, written by |
diff --git a/drivers/net/ibm_newemac/rgmii.c b/drivers/net/ibm_newemac/rgmii.c index 1d5379de6900..8d76cb89dbd6 100644 --- a/drivers/net/ibm_newemac/rgmii.c +++ b/drivers/net/ibm_newemac/rgmii.c | |||
@@ -188,11 +188,12 @@ void rgmii_put_mdio(struct of_device *ofdev, int input) | |||
188 | void rgmii_detach(struct of_device *ofdev, int input) | 188 | void rgmii_detach(struct of_device *ofdev, int input) |
189 | { | 189 | { |
190 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 190 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
191 | struct rgmii_regs __iomem *p = dev->base; | 191 | struct rgmii_regs __iomem *p; |
192 | |||
193 | mutex_lock(&dev->lock); | ||
194 | 192 | ||
195 | BUG_ON(!dev || dev->users == 0); | 193 | BUG_ON(!dev || dev->users == 0); |
194 | p = dev->base; | ||
195 | |||
196 | mutex_lock(&dev->lock); | ||
196 | 197 | ||
197 | RGMII_DBG(dev, "detach(%d)" NL, input); | 198 | RGMII_DBG(dev, "detach(%d)" NL, input); |
198 | 199 | ||
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index 7c5978ad929a..da2c8514b8d0 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c | |||
@@ -106,8 +106,6 @@ static u8 ixgbe_dcbnl_get_state(struct net_device *netdev) | |||
106 | { | 106 | { |
107 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 107 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
108 | 108 | ||
109 | DPRINTK(DRV, INFO, "Get DCB Admin Mode.\n"); | ||
110 | |||
111 | return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED); | 109 | return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED); |
112 | } | 110 | } |
113 | 111 | ||
@@ -116,8 +114,6 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) | |||
116 | u8 err = 0; | 114 | u8 err = 0; |
117 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 115 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
118 | 116 | ||
119 | DPRINTK(DRV, INFO, "Set DCB Admin Mode.\n"); | ||
120 | |||
121 | if (state > 0) { | 117 | if (state > 0) { |
122 | /* Turn on DCB */ | 118 | /* Turn on DCB */ |
123 | if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) | 119 | if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) |
@@ -175,6 +171,8 @@ static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev, | |||
175 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 171 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
176 | int i, j; | 172 | int i, j; |
177 | 173 | ||
174 | memset(perm_addr, 0xff, MAX_ADDR_LEN); | ||
175 | |||
178 | for (i = 0; i < netdev->addr_len; i++) | 176 | for (i = 0; i < netdev->addr_len; i++) |
179 | perm_addr[i] = adapter->hw.mac.perm_addr[i]; | 177 | perm_addr[i] = adapter->hw.mac.perm_addr[i]; |
180 | 178 | ||
diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c index d12106b47bf2..2f286091394d 100644 --- a/drivers/net/jazzsonic.c +++ b/drivers/net/jazzsonic.c | |||
@@ -229,6 +229,7 @@ static int __init jazz_sonic_probe(struct platform_device *pdev) | |||
229 | lp = netdev_priv(dev); | 229 | lp = netdev_priv(dev); |
230 | lp->device = &pdev->dev; | 230 | lp->device = &pdev->dev; |
231 | SET_NETDEV_DEV(dev, &pdev->dev); | 231 | SET_NETDEV_DEV(dev, &pdev->dev); |
232 | platform_set_drvdata(pdev, dev); | ||
232 | 233 | ||
233 | netdev_boot_setup_check(dev); | 234 | netdev_boot_setup_check(dev); |
234 | 235 | ||
diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c new file mode 100644 index 000000000000..9a1dea60c1c4 --- /dev/null +++ b/drivers/net/ks8851.c | |||
@@ -0,0 +1,1322 @@ | |||
1 | /* drivers/net/ks8651.c | ||
2 | * | ||
3 | * Copyright 2009 Simtec Electronics | ||
4 | * http://www.simtec.co.uk/ | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #define DEBUG | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/netdevice.h> | ||
17 | #include <linux/etherdevice.h> | ||
18 | #include <linux/ethtool.h> | ||
19 | #include <linux/cache.h> | ||
20 | #include <linux/crc32.h> | ||
21 | #include <linux/mii.h> | ||
22 | |||
23 | #include <linux/spi/spi.h> | ||
24 | |||
25 | #include "ks8851.h" | ||
26 | |||
27 | /** | ||
28 | * struct ks8851_rxctrl - KS8851 driver rx control | ||
29 | * @mchash: Multicast hash-table data. | ||
30 | * @rxcr1: KS_RXCR1 register setting | ||
31 | * @rxcr2: KS_RXCR2 register setting | ||
32 | * | ||
33 | * Representation of the settings needs to control the receive filtering | ||
34 | * such as the multicast hash-filter and the receive register settings. This | ||
35 | * is used to make the job of working out if the receive settings change and | ||
36 | * then issuing the new settings to the worker that will send the necessary | ||
37 | * commands. | ||
38 | */ | ||
39 | struct ks8851_rxctrl { | ||
40 | u16 mchash[4]; | ||
41 | u16 rxcr1; | ||
42 | u16 rxcr2; | ||
43 | }; | ||
44 | |||
45 | /** | ||
46 | * union ks8851_tx_hdr - tx header data | ||
47 | * @txb: The header as bytes | ||
48 | * @txw: The header as 16bit, little-endian words | ||
49 | * | ||
50 | * A dual representation of the tx header data to allow | ||
51 | * access to individual bytes, and to allow 16bit accesses | ||
52 | * with 16bit alignment. | ||
53 | */ | ||
54 | union ks8851_tx_hdr { | ||
55 | u8 txb[6]; | ||
56 | __le16 txw[3]; | ||
57 | }; | ||
58 | |||
59 | /** | ||
60 | * struct ks8851_net - KS8851 driver private data | ||
61 | * @netdev: The network device we're bound to | ||
62 | * @spidev: The spi device we're bound to. | ||
63 | * @lock: Lock to ensure that the device is not accessed when busy. | ||
64 | * @statelock: Lock on this structure for tx list. | ||
65 | * @mii: The MII state information for the mii calls. | ||
66 | * @rxctrl: RX settings for @rxctrl_work. | ||
67 | * @tx_work: Work queue for tx packets | ||
68 | * @irq_work: Work queue for servicing interrupts | ||
69 | * @rxctrl_work: Work queue for updating RX mode and multicast lists | ||
70 | * @txq: Queue of packets for transmission. | ||
71 | * @spi_msg1: pre-setup SPI transfer with one message, @spi_xfer1. | ||
72 | * @spi_msg2: pre-setup SPI transfer with two messages, @spi_xfer2. | ||
73 | * @txh: Space for generating packet TX header in DMA-able data | ||
74 | * @rxd: Space for receiving SPI data, in DMA-able space. | ||
75 | * @txd: Space for transmitting SPI data, in DMA-able space. | ||
76 | * @msg_enable: The message flags controlling driver output (see ethtool). | ||
77 | * @fid: Incrementing frame id tag. | ||
78 | * @rc_ier: Cached copy of KS_IER. | ||
79 | * @rc_rxqcr: Cached copy of KS_RXQCR. | ||
80 | * | ||
81 | * The @lock ensures that the chip is protected when certain operations are | ||
82 | * in progress. When the read or write packet transfer is in progress, most | ||
83 | * of the chip registers are not ccessible until the transfer is finished and | ||
84 | * the DMA has been de-asserted. | ||
85 | * | ||
86 | * The @statelock is used to protect information in the structure which may | ||
87 | * need to be accessed via several sources, such as the network driver layer | ||
88 | * or one of the work queues. | ||
89 | * | ||
90 | * We align the buffers we may use for rx/tx to ensure that if the SPI driver | ||
91 | * wants to DMA map them, it will not have any problems with data the driver | ||
92 | * modifies. | ||
93 | */ | ||
94 | struct ks8851_net { | ||
95 | struct net_device *netdev; | ||
96 | struct spi_device *spidev; | ||
97 | struct mutex lock; | ||
98 | spinlock_t statelock; | ||
99 | |||
100 | union ks8851_tx_hdr txh ____cacheline_aligned; | ||
101 | u8 rxd[8]; | ||
102 | u8 txd[8]; | ||
103 | |||
104 | u32 msg_enable ____cacheline_aligned; | ||
105 | u16 tx_space; | ||
106 | u8 fid; | ||
107 | |||
108 | u16 rc_ier; | ||
109 | u16 rc_rxqcr; | ||
110 | |||
111 | struct mii_if_info mii; | ||
112 | struct ks8851_rxctrl rxctrl; | ||
113 | |||
114 | struct work_struct tx_work; | ||
115 | struct work_struct irq_work; | ||
116 | struct work_struct rxctrl_work; | ||
117 | |||
118 | struct sk_buff_head txq; | ||
119 | |||
120 | struct spi_message spi_msg1; | ||
121 | struct spi_message spi_msg2; | ||
122 | struct spi_transfer spi_xfer1; | ||
123 | struct spi_transfer spi_xfer2[2]; | ||
124 | }; | ||
125 | |||
126 | static int msg_enable; | ||
127 | |||
128 | #define ks_info(_ks, _msg...) dev_info(&(_ks)->spidev->dev, _msg) | ||
129 | #define ks_warn(_ks, _msg...) dev_warn(&(_ks)->spidev->dev, _msg) | ||
130 | #define ks_dbg(_ks, _msg...) dev_dbg(&(_ks)->spidev->dev, _msg) | ||
131 | #define ks_err(_ks, _msg...) dev_err(&(_ks)->spidev->dev, _msg) | ||
132 | |||
133 | /* shift for byte-enable data */ | ||
134 | #define BYTE_EN(_x) ((_x) << 2) | ||
135 | |||
136 | /* turn register number and byte-enable mask into data for start of packet */ | ||
137 | #define MK_OP(_byteen, _reg) (BYTE_EN(_byteen) | (_reg) << (8+2) | (_reg) >> 6) | ||
138 | |||
139 | /* SPI register read/write calls. | ||
140 | * | ||
141 | * All these calls issue SPI transactions to access the chip's registers. They | ||
142 | * all require that the necessary lock is held to prevent accesses when the | ||
143 | * chip is busy transfering packet data (RX/TX FIFO accesses). | ||
144 | */ | ||
145 | |||
146 | /** | ||
147 | * ks8851_wrreg16 - write 16bit register value to chip | ||
148 | * @ks: The chip state | ||
149 | * @reg: The register address | ||
150 | * @val: The value to write | ||
151 | * | ||
152 | * Issue a write to put the value @val into the register specified in @reg. | ||
153 | */ | ||
154 | static void ks8851_wrreg16(struct ks8851_net *ks, unsigned reg, unsigned val) | ||
155 | { | ||
156 | struct spi_transfer *xfer = &ks->spi_xfer1; | ||
157 | struct spi_message *msg = &ks->spi_msg1; | ||
158 | __le16 txb[2]; | ||
159 | int ret; | ||
160 | |||
161 | txb[0] = cpu_to_le16(MK_OP(reg & 2 ? 0xC : 0x03, reg) | KS_SPIOP_WR); | ||
162 | txb[1] = cpu_to_le16(val); | ||
163 | |||
164 | xfer->tx_buf = txb; | ||
165 | xfer->rx_buf = NULL; | ||
166 | xfer->len = 4; | ||
167 | |||
168 | ret = spi_sync(ks->spidev, msg); | ||
169 | if (ret < 0) | ||
170 | ks_err(ks, "spi_sync() failed\n"); | ||
171 | } | ||
172 | |||
173 | /** | ||
174 | * ks8851_rx_1msg - select whether to use one or two messages for spi read | ||
175 | * @ks: The device structure | ||
176 | * | ||
177 | * Return whether to generate a single message with a tx and rx buffer | ||
178 | * supplied to spi_sync(), or alternatively send the tx and rx buffers | ||
179 | * as separate messages. | ||
180 | * | ||
181 | * Depending on the hardware in use, a single message may be more efficient | ||
182 | * on interrupts or work done by the driver. | ||
183 | * | ||
184 | * This currently always returns true until we add some per-device data passed | ||
185 | * from the platform code to specify which mode is better. | ||
186 | */ | ||
187 | static inline bool ks8851_rx_1msg(struct ks8851_net *ks) | ||
188 | { | ||
189 | return true; | ||
190 | } | ||
191 | |||
192 | /** | ||
193 | * ks8851_rdreg - issue read register command and return the data | ||
194 | * @ks: The device state | ||
195 | * @op: The register address and byte enables in message format. | ||
196 | * @rxb: The RX buffer to return the result into | ||
197 | * @rxl: The length of data expected. | ||
198 | * | ||
199 | * This is the low level read call that issues the necessary spi message(s) | ||
200 | * to read data from the register specified in @op. | ||
201 | */ | ||
202 | static void ks8851_rdreg(struct ks8851_net *ks, unsigned op, | ||
203 | u8 *rxb, unsigned rxl) | ||
204 | { | ||
205 | struct spi_transfer *xfer; | ||
206 | struct spi_message *msg; | ||
207 | __le16 *txb = (__le16 *)ks->txd; | ||
208 | u8 *trx = ks->rxd; | ||
209 | int ret; | ||
210 | |||
211 | txb[0] = cpu_to_le16(op | KS_SPIOP_RD); | ||
212 | |||
213 | if (ks8851_rx_1msg(ks)) { | ||
214 | msg = &ks->spi_msg1; | ||
215 | xfer = &ks->spi_xfer1; | ||
216 | |||
217 | xfer->tx_buf = txb; | ||
218 | xfer->rx_buf = trx; | ||
219 | xfer->len = rxl + 2; | ||
220 | } else { | ||
221 | msg = &ks->spi_msg2; | ||
222 | xfer = ks->spi_xfer2; | ||
223 | |||
224 | xfer->tx_buf = txb; | ||
225 | xfer->rx_buf = NULL; | ||
226 | xfer->len = 2; | ||
227 | |||
228 | xfer++; | ||
229 | xfer->tx_buf = NULL; | ||
230 | xfer->rx_buf = trx; | ||
231 | xfer->len = rxl; | ||
232 | } | ||
233 | |||
234 | ret = spi_sync(ks->spidev, msg); | ||
235 | if (ret < 0) | ||
236 | ks_err(ks, "read: spi_sync() failed\n"); | ||
237 | else if (ks8851_rx_1msg(ks)) | ||
238 | memcpy(rxb, trx + 2, rxl); | ||
239 | else | ||
240 | memcpy(rxb, trx, rxl); | ||
241 | } | ||
242 | |||
243 | /** | ||
244 | * ks8851_rdreg8 - read 8 bit register from device | ||
245 | * @ks: The chip information | ||
246 | * @reg: The register address | ||
247 | * | ||
248 | * Read a 8bit register from the chip, returning the result | ||
249 | */ | ||
250 | static unsigned ks8851_rdreg8(struct ks8851_net *ks, unsigned reg) | ||
251 | { | ||
252 | u8 rxb[1]; | ||
253 | |||
254 | ks8851_rdreg(ks, MK_OP(1 << (reg & 3), reg), rxb, 1); | ||
255 | return rxb[0]; | ||
256 | } | ||
257 | |||
258 | /** | ||
259 | * ks8851_rdreg16 - read 16 bit register from device | ||
260 | * @ks: The chip information | ||
261 | * @reg: The register address | ||
262 | * | ||
263 | * Read a 16bit register from the chip, returning the result | ||
264 | */ | ||
265 | static unsigned ks8851_rdreg16(struct ks8851_net *ks, unsigned reg) | ||
266 | { | ||
267 | __le16 rx = 0; | ||
268 | |||
269 | ks8851_rdreg(ks, MK_OP(reg & 2 ? 0xC : 0x3, reg), (u8 *)&rx, 2); | ||
270 | return le16_to_cpu(rx); | ||
271 | } | ||
272 | |||
273 | /** | ||
274 | * ks8851_rdreg32 - read 32 bit register from device | ||
275 | * @ks: The chip information | ||
276 | * @reg: The register address | ||
277 | * | ||
278 | * Read a 32bit register from the chip. | ||
279 | * | ||
280 | * Note, this read requires the address be aligned to 4 bytes. | ||
281 | */ | ||
282 | static unsigned ks8851_rdreg32(struct ks8851_net *ks, unsigned reg) | ||
283 | { | ||
284 | __le32 rx = 0; | ||
285 | |||
286 | WARN_ON(reg & 3); | ||
287 | |||
288 | ks8851_rdreg(ks, MK_OP(0xf, reg), (u8 *)&rx, 4); | ||
289 | return le32_to_cpu(rx); | ||
290 | } | ||
291 | |||
292 | /** | ||
293 | * ks8851_soft_reset - issue one of the soft reset to the device | ||
294 | * @ks: The device state. | ||
295 | * @op: The bit(s) to set in the GRR | ||
296 | * | ||
297 | * Issue the relevant soft-reset command to the device's GRR register | ||
298 | * specified by @op. | ||
299 | * | ||
300 | * Note, the delays are in there as a caution to ensure that the reset | ||
301 | * has time to take effect and then complete. Since the datasheet does | ||
302 | * not currently specify the exact sequence, we have chosen something | ||
303 | * that seems to work with our device. | ||
304 | */ | ||
305 | static void ks8851_soft_reset(struct ks8851_net *ks, unsigned op) | ||
306 | { | ||
307 | ks8851_wrreg16(ks, KS_GRR, op); | ||
308 | mdelay(1); /* wait a short time to effect reset */ | ||
309 | ks8851_wrreg16(ks, KS_GRR, 0); | ||
310 | mdelay(1); /* wait for condition to clear */ | ||
311 | } | ||
312 | |||
313 | /** | ||
314 | * ks8851_write_mac_addr - write mac address to device registers | ||
315 | * @dev: The network device | ||
316 | * | ||
317 | * Update the KS8851 MAC address registers from the address in @dev. | ||
318 | * | ||
319 | * This call assumes that the chip is not running, so there is no need to | ||
320 | * shutdown the RXQ process whilst setting this. | ||
321 | */ | ||
322 | static int ks8851_write_mac_addr(struct net_device *dev) | ||
323 | { | ||
324 | struct ks8851_net *ks = netdev_priv(dev); | ||
325 | u16 *mcp = (u16 *)dev->dev_addr; | ||
326 | |||
327 | mutex_lock(&ks->lock); | ||
328 | |||
329 | ks8851_wrreg16(ks, KS_MARL, mcp[0]); | ||
330 | ks8851_wrreg16(ks, KS_MARM, mcp[1]); | ||
331 | ks8851_wrreg16(ks, KS_MARH, mcp[2]); | ||
332 | |||
333 | mutex_unlock(&ks->lock); | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | /** | ||
339 | * ks8851_init_mac - initialise the mac address | ||
340 | * @ks: The device structure | ||
341 | * | ||
342 | * Get or create the initial mac address for the device and then set that | ||
343 | * into the station address register. Currently we assume that the device | ||
344 | * does not have a valid mac address in it, and so we use random_ether_addr() | ||
345 | * to create a new one. | ||
346 | * | ||
347 | * In future, the driver should check to see if the device has an EEPROM | ||
348 | * attached and whether that has a valid ethernet address in it. | ||
349 | */ | ||
350 | static void ks8851_init_mac(struct ks8851_net *ks) | ||
351 | { | ||
352 | struct net_device *dev = ks->netdev; | ||
353 | |||
354 | random_ether_addr(dev->dev_addr); | ||
355 | ks8851_write_mac_addr(dev); | ||
356 | } | ||
357 | |||
358 | /** | ||
359 | * ks8851_irq - device interrupt handler | ||
360 | * @irq: Interrupt number passed from the IRQ hnalder. | ||
361 | * @pw: The private word passed to register_irq(), our struct ks8851_net. | ||
362 | * | ||
363 | * Disable the interrupt from happening again until we've processed the | ||
364 | * current status by scheduling ks8851_irq_work(). | ||
365 | */ | ||
366 | static irqreturn_t ks8851_irq(int irq, void *pw) | ||
367 | { | ||
368 | struct ks8851_net *ks = pw; | ||
369 | |||
370 | disable_irq_nosync(irq); | ||
371 | schedule_work(&ks->irq_work); | ||
372 | return IRQ_HANDLED; | ||
373 | } | ||
374 | |||
375 | /** | ||
376 | * ks8851_rdfifo - read data from the receive fifo | ||
377 | * @ks: The device state. | ||
378 | * @buff: The buffer address | ||
379 | * @len: The length of the data to read | ||
380 | * | ||
381 | * Issue an RXQ FIFO read command and read the @len ammount of data from | ||
382 | * the FIFO into the buffer specified by @buff. | ||
383 | */ | ||
384 | static void ks8851_rdfifo(struct ks8851_net *ks, u8 *buff, unsigned len) | ||
385 | { | ||
386 | struct spi_transfer *xfer = ks->spi_xfer2; | ||
387 | struct spi_message *msg = &ks->spi_msg2; | ||
388 | u8 txb[1]; | ||
389 | int ret; | ||
390 | |||
391 | if (netif_msg_rx_status(ks)) | ||
392 | ks_dbg(ks, "%s: %d@%p\n", __func__, len, buff); | ||
393 | |||
394 | /* set the operation we're issuing */ | ||
395 | txb[0] = KS_SPIOP_RXFIFO; | ||
396 | |||
397 | xfer->tx_buf = txb; | ||
398 | xfer->rx_buf = NULL; | ||
399 | xfer->len = 1; | ||
400 | |||
401 | xfer++; | ||
402 | xfer->rx_buf = buff; | ||
403 | xfer->tx_buf = NULL; | ||
404 | xfer->len = len; | ||
405 | |||
406 | ret = spi_sync(ks->spidev, msg); | ||
407 | if (ret < 0) | ||
408 | ks_err(ks, "%s: spi_sync() failed\n", __func__); | ||
409 | } | ||
410 | |||
411 | /** | ||
412 | * ks8851_dbg_dumpkkt - dump initial packet contents to debug | ||
413 | * @ks: The device state | ||
414 | * @rxpkt: The data for the received packet | ||
415 | * | ||
416 | * Dump the initial data from the packet to dev_dbg(). | ||
417 | */ | ||
418 | static void ks8851_dbg_dumpkkt(struct ks8851_net *ks, u8 *rxpkt) | ||
419 | { | ||
420 | ks_dbg(ks, "pkt %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n", | ||
421 | rxpkt[4], rxpkt[5], rxpkt[6], rxpkt[7], | ||
422 | rxpkt[8], rxpkt[9], rxpkt[10], rxpkt[11], | ||
423 | rxpkt[12], rxpkt[13], rxpkt[14], rxpkt[15]); | ||
424 | } | ||
425 | |||
426 | /** | ||
427 | * ks8851_rx_pkts - receive packets from the host | ||
428 | * @ks: The device information. | ||
429 | * | ||
430 | * This is called from the IRQ work queue when the system detects that there | ||
431 | * are packets in the receive queue. Find out how many packets there are and | ||
432 | * read them from the FIFO. | ||
433 | */ | ||
434 | static void ks8851_rx_pkts(struct ks8851_net *ks) | ||
435 | { | ||
436 | struct sk_buff *skb; | ||
437 | unsigned rxfc; | ||
438 | unsigned rxlen; | ||
439 | unsigned rxstat; | ||
440 | u32 rxh; | ||
441 | u8 *rxpkt; | ||
442 | |||
443 | rxfc = ks8851_rdreg8(ks, KS_RXFC); | ||
444 | |||
445 | if (netif_msg_rx_status(ks)) | ||
446 | ks_dbg(ks, "%s: %d packets\n", __func__, rxfc); | ||
447 | |||
448 | /* Currently we're issuing a read per packet, but we could possibly | ||
449 | * improve the code by issuing a single read, getting the receive | ||
450 | * header, allocating the packet and then reading the packet data | ||
451 | * out in one go. | ||
452 | * | ||
453 | * This form of operation would require us to hold the SPI bus' | ||
454 | * chipselect low during the entie transaction to avoid any | ||
455 | * reset to the data stream comming from the chip. | ||
456 | */ | ||
457 | |||
458 | for (; rxfc != 0; rxfc--) { | ||
459 | rxh = ks8851_rdreg32(ks, KS_RXFHSR); | ||
460 | rxstat = rxh & 0xffff; | ||
461 | rxlen = rxh >> 16; | ||
462 | |||
463 | if (netif_msg_rx_status(ks)) | ||
464 | ks_dbg(ks, "rx: stat 0x%04x, len 0x%04x\n", | ||
465 | rxstat, rxlen); | ||
466 | |||
467 | /* the length of the packet includes the 32bit CRC */ | ||
468 | |||
469 | /* set dma read address */ | ||
470 | ks8851_wrreg16(ks, KS_RXFDPR, RXFDPR_RXFPAI | 0x00); | ||
471 | |||
472 | /* start the packet dma process, and set auto-dequeue rx */ | ||
473 | ks8851_wrreg16(ks, KS_RXQCR, | ||
474 | ks->rc_rxqcr | RXQCR_SDA | RXQCR_ADRFE); | ||
475 | |||
476 | if (rxlen > 0) { | ||
477 | skb = netdev_alloc_skb(ks->netdev, rxlen + 2 + 8); | ||
478 | if (!skb) { | ||
479 | /* todo - dump frame and move on */ | ||
480 | } | ||
481 | |||
482 | /* two bytes to ensure ip is aligned, and four bytes | ||
483 | * for the status header and 4 bytes of garbage */ | ||
484 | skb_reserve(skb, 2 + 4 + 4); | ||
485 | |||
486 | rxpkt = skb_put(skb, rxlen - 4) - 8; | ||
487 | |||
488 | /* align the packet length to 4 bytes, and add 4 bytes | ||
489 | * as we're getting the rx status header as well */ | ||
490 | ks8851_rdfifo(ks, rxpkt, ALIGN(rxlen, 4) + 8); | ||
491 | |||
492 | if (netif_msg_pktdata(ks)) | ||
493 | ks8851_dbg_dumpkkt(ks, rxpkt); | ||
494 | |||
495 | skb->protocol = eth_type_trans(skb, ks->netdev); | ||
496 | netif_rx(skb); | ||
497 | |||
498 | ks->netdev->stats.rx_packets++; | ||
499 | ks->netdev->stats.rx_bytes += rxlen - 4; | ||
500 | } | ||
501 | |||
502 | ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); | ||
503 | } | ||
504 | } | ||
505 | |||
506 | /** | ||
507 | * ks8851_irq_work - work queue handler for dealing with interrupt requests | ||
508 | * @work: The work structure that was scheduled by schedule_work() | ||
509 | * | ||
510 | * This is the handler invoked when the ks8851_irq() is called to find out | ||
511 | * what happened, as we cannot allow ourselves to sleep whilst waiting for | ||
512 | * anything other process has the chip's lock. | ||
513 | * | ||
514 | * Read the interrupt status, work out what needs to be done and then clear | ||
515 | * any of the interrupts that are not needed. | ||
516 | */ | ||
517 | static void ks8851_irq_work(struct work_struct *work) | ||
518 | { | ||
519 | struct ks8851_net *ks = container_of(work, struct ks8851_net, irq_work); | ||
520 | unsigned status; | ||
521 | unsigned handled = 0; | ||
522 | |||
523 | mutex_lock(&ks->lock); | ||
524 | |||
525 | status = ks8851_rdreg16(ks, KS_ISR); | ||
526 | |||
527 | if (netif_msg_intr(ks)) | ||
528 | dev_dbg(&ks->spidev->dev, "%s: status 0x%04x\n", | ||
529 | __func__, status); | ||
530 | |||
531 | if (status & IRQ_LCI) { | ||
532 | /* should do something about checking link status */ | ||
533 | handled |= IRQ_LCI; | ||
534 | } | ||
535 | |||
536 | if (status & IRQ_LDI) { | ||
537 | u16 pmecr = ks8851_rdreg16(ks, KS_PMECR); | ||
538 | pmecr &= ~PMECR_WKEVT_MASK; | ||
539 | ks8851_wrreg16(ks, KS_PMECR, pmecr | PMECR_WKEVT_LINK); | ||
540 | |||
541 | handled |= IRQ_LDI; | ||
542 | } | ||
543 | |||
544 | if (status & IRQ_RXPSI) | ||
545 | handled |= IRQ_RXPSI; | ||
546 | |||
547 | if (status & IRQ_TXI) { | ||
548 | handled |= IRQ_TXI; | ||
549 | |||
550 | /* no lock here, tx queue should have been stopped */ | ||
551 | |||
552 | /* update our idea of how much tx space is available to the | ||
553 | * system */ | ||
554 | ks->tx_space = ks8851_rdreg16(ks, KS_TXMIR); | ||
555 | |||
556 | if (netif_msg_intr(ks)) | ||
557 | ks_dbg(ks, "%s: txspace %d\n", __func__, ks->tx_space); | ||
558 | } | ||
559 | |||
560 | if (status & IRQ_RXI) | ||
561 | handled |= IRQ_RXI; | ||
562 | |||
563 | if (status & IRQ_SPIBEI) { | ||
564 | dev_err(&ks->spidev->dev, "%s: spi bus error\n", __func__); | ||
565 | handled |= IRQ_SPIBEI; | ||
566 | } | ||
567 | |||
568 | ks8851_wrreg16(ks, KS_ISR, handled); | ||
569 | |||
570 | if (status & IRQ_RXI) { | ||
571 | /* the datasheet says to disable the rx interrupt during | ||
572 | * packet read-out, however we're masking the interrupt | ||
573 | * from the device so do not bother masking just the RX | ||
574 | * from the device. */ | ||
575 | |||
576 | ks8851_rx_pkts(ks); | ||
577 | } | ||
578 | |||
579 | /* if something stopped the rx process, probably due to wanting | ||
580 | * to change the rx settings, then do something about restarting | ||
581 | * it. */ | ||
582 | if (status & IRQ_RXPSI) { | ||
583 | struct ks8851_rxctrl *rxc = &ks->rxctrl; | ||
584 | |||
585 | /* update the multicast hash table */ | ||
586 | ks8851_wrreg16(ks, KS_MAHTR0, rxc->mchash[0]); | ||
587 | ks8851_wrreg16(ks, KS_MAHTR1, rxc->mchash[1]); | ||
588 | ks8851_wrreg16(ks, KS_MAHTR2, rxc->mchash[2]); | ||
589 | ks8851_wrreg16(ks, KS_MAHTR3, rxc->mchash[3]); | ||
590 | |||
591 | ks8851_wrreg16(ks, KS_RXCR2, rxc->rxcr2); | ||
592 | ks8851_wrreg16(ks, KS_RXCR1, rxc->rxcr1); | ||
593 | } | ||
594 | |||
595 | mutex_unlock(&ks->lock); | ||
596 | |||
597 | if (status & IRQ_TXI) | ||
598 | netif_wake_queue(ks->netdev); | ||
599 | |||
600 | enable_irq(ks->netdev->irq); | ||
601 | } | ||
602 | |||
603 | /** | ||
604 | * calc_txlen - calculate size of message to send packet | ||
605 | * @len: Lenght of data | ||
606 | * | ||
607 | * Returns the size of the TXFIFO message needed to send | ||
608 | * this packet. | ||
609 | */ | ||
610 | static inline unsigned calc_txlen(unsigned len) | ||
611 | { | ||
612 | return ALIGN(len + 4, 4); | ||
613 | } | ||
614 | |||
615 | /** | ||
616 | * ks8851_wrpkt - write packet to TX FIFO | ||
617 | * @ks: The device state. | ||
618 | * @txp: The sk_buff to transmit. | ||
619 | * @irq: IRQ on completion of the packet. | ||
620 | * | ||
621 | * Send the @txp to the chip. This means creating the relevant packet header | ||
622 | * specifying the length of the packet and the other information the chip | ||
623 | * needs, such as IRQ on completion. Send the header and the packet data to | ||
624 | * the device. | ||
625 | */ | ||
626 | static void ks8851_wrpkt(struct ks8851_net *ks, struct sk_buff *txp, bool irq) | ||
627 | { | ||
628 | struct spi_transfer *xfer = ks->spi_xfer2; | ||
629 | struct spi_message *msg = &ks->spi_msg2; | ||
630 | unsigned fid = 0; | ||
631 | int ret; | ||
632 | |||
633 | if (netif_msg_tx_queued(ks)) | ||
634 | dev_dbg(&ks->spidev->dev, "%s: skb %p, %d@%p, irq %d\n", | ||
635 | __func__, txp, txp->len, txp->data, irq); | ||
636 | |||
637 | fid = ks->fid++; | ||
638 | fid &= TXFR_TXFID_MASK; | ||
639 | |||
640 | if (irq) | ||
641 | fid |= TXFR_TXIC; /* irq on completion */ | ||
642 | |||
643 | /* start header at txb[1] to align txw entries */ | ||
644 | ks->txh.txb[1] = KS_SPIOP_TXFIFO; | ||
645 | ks->txh.txw[1] = cpu_to_le16(fid); | ||
646 | ks->txh.txw[2] = cpu_to_le16(txp->len); | ||
647 | |||
648 | xfer->tx_buf = &ks->txh.txb[1]; | ||
649 | xfer->rx_buf = NULL; | ||
650 | xfer->len = 5; | ||
651 | |||
652 | xfer++; | ||
653 | xfer->tx_buf = txp->data; | ||
654 | xfer->rx_buf = NULL; | ||
655 | xfer->len = ALIGN(txp->len, 4); | ||
656 | |||
657 | ret = spi_sync(ks->spidev, msg); | ||
658 | if (ret < 0) | ||
659 | ks_err(ks, "%s: spi_sync() failed\n", __func__); | ||
660 | } | ||
661 | |||
662 | /** | ||
663 | * ks8851_done_tx - update and then free skbuff after transmitting | ||
664 | * @ks: The device state | ||
665 | * @txb: The buffer transmitted | ||
666 | */ | ||
667 | static void ks8851_done_tx(struct ks8851_net *ks, struct sk_buff *txb) | ||
668 | { | ||
669 | struct net_device *dev = ks->netdev; | ||
670 | |||
671 | dev->stats.tx_bytes += txb->len; | ||
672 | dev->stats.tx_packets++; | ||
673 | |||
674 | dev_kfree_skb(txb); | ||
675 | } | ||
676 | |||
677 | /** | ||
678 | * ks8851_tx_work - process tx packet(s) | ||
679 | * @work: The work strucutre what was scheduled. | ||
680 | * | ||
681 | * This is called when a number of packets have been scheduled for | ||
682 | * transmission and need to be sent to the device. | ||
683 | */ | ||
684 | static void ks8851_tx_work(struct work_struct *work) | ||
685 | { | ||
686 | struct ks8851_net *ks = container_of(work, struct ks8851_net, tx_work); | ||
687 | struct sk_buff *txb; | ||
688 | bool last = false; | ||
689 | |||
690 | mutex_lock(&ks->lock); | ||
691 | |||
692 | while (!last) { | ||
693 | txb = skb_dequeue(&ks->txq); | ||
694 | last = skb_queue_empty(&ks->txq); | ||
695 | |||
696 | ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA); | ||
697 | ks8851_wrpkt(ks, txb, last); | ||
698 | ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); | ||
699 | ks8851_wrreg16(ks, KS_TXQCR, TXQCR_METFE); | ||
700 | |||
701 | ks8851_done_tx(ks, txb); | ||
702 | } | ||
703 | |||
704 | mutex_unlock(&ks->lock); | ||
705 | } | ||
706 | |||
707 | /** | ||
708 | * ks8851_set_powermode - set power mode of the device | ||
709 | * @ks: The device state | ||
710 | * @pwrmode: The power mode value to write to KS_PMECR. | ||
711 | * | ||
712 | * Change the power mode of the chip. | ||
713 | */ | ||
714 | static void ks8851_set_powermode(struct ks8851_net *ks, unsigned pwrmode) | ||
715 | { | ||
716 | unsigned pmecr; | ||
717 | |||
718 | if (netif_msg_hw(ks)) | ||
719 | ks_dbg(ks, "setting power mode %d\n", pwrmode); | ||
720 | |||
721 | pmecr = ks8851_rdreg16(ks, KS_PMECR); | ||
722 | pmecr &= ~PMECR_PM_MASK; | ||
723 | pmecr |= pwrmode; | ||
724 | |||
725 | ks8851_wrreg16(ks, KS_PMECR, pmecr); | ||
726 | } | ||
727 | |||
728 | /** | ||
729 | * ks8851_net_open - open network device | ||
730 | * @dev: The network device being opened. | ||
731 | * | ||
732 | * Called when the network device is marked active, such as a user executing | ||
733 | * 'ifconfig up' on the device. | ||
734 | */ | ||
735 | static int ks8851_net_open(struct net_device *dev) | ||
736 | { | ||
737 | struct ks8851_net *ks = netdev_priv(dev); | ||
738 | |||
739 | /* lock the card, even if we may not actually be doing anything | ||
740 | * else at the moment */ | ||
741 | mutex_lock(&ks->lock); | ||
742 | |||
743 | if (netif_msg_ifup(ks)) | ||
744 | ks_dbg(ks, "opening %s\n", dev->name); | ||
745 | |||
746 | /* bring chip out of any power saving mode it was in */ | ||
747 | ks8851_set_powermode(ks, PMECR_PM_NORMAL); | ||
748 | |||
749 | /* issue a soft reset to the RX/TX QMU to put it into a known | ||
750 | * state. */ | ||
751 | ks8851_soft_reset(ks, GRR_QMU); | ||
752 | |||
753 | /* setup transmission parameters */ | ||
754 | |||
755 | ks8851_wrreg16(ks, KS_TXCR, (TXCR_TXE | /* enable transmit process */ | ||
756 | TXCR_TXPE | /* pad to min length */ | ||
757 | TXCR_TXCRC | /* add CRC */ | ||
758 | TXCR_TXFCE)); /* enable flow control */ | ||
759 | |||
760 | /* auto-increment tx data, reset tx pointer */ | ||
761 | ks8851_wrreg16(ks, KS_TXFDPR, TXFDPR_TXFPAI); | ||
762 | |||
763 | /* setup receiver control */ | ||
764 | |||
765 | ks8851_wrreg16(ks, KS_RXCR1, (RXCR1_RXPAFMA | /* from mac filter */ | ||
766 | RXCR1_RXFCE | /* enable flow control */ | ||
767 | RXCR1_RXBE | /* broadcast enable */ | ||
768 | RXCR1_RXUE | /* unicast enable */ | ||
769 | RXCR1_RXE)); /* enable rx block */ | ||
770 | |||
771 | /* transfer entire frames out in one go */ | ||
772 | ks8851_wrreg16(ks, KS_RXCR2, RXCR2_SRDBL_FRAME); | ||
773 | |||
774 | /* set receive counter timeouts */ | ||
775 | ks8851_wrreg16(ks, KS_RXDTTR, 1000); /* 1ms after first frame to IRQ */ | ||
776 | ks8851_wrreg16(ks, KS_RXDBCTR, 4096); /* >4Kbytes in buffer to IRQ */ | ||
777 | ks8851_wrreg16(ks, KS_RXFCTR, 10); /* 10 frames to IRQ */ | ||
778 | |||
779 | ks->rc_rxqcr = (RXQCR_RXFCTE | /* IRQ on frame count exceeded */ | ||
780 | RXQCR_RXDBCTE | /* IRQ on byte count exceeded */ | ||
781 | RXQCR_RXDTTE); /* IRQ on time exceeded */ | ||
782 | |||
783 | ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); | ||
784 | |||
785 | /* clear then enable interrupts */ | ||
786 | |||
787 | #define STD_IRQ (IRQ_LCI | /* Link Change */ \ | ||
788 | IRQ_TXI | /* TX done */ \ | ||
789 | IRQ_RXI | /* RX done */ \ | ||
790 | IRQ_SPIBEI | /* SPI bus error */ \ | ||
791 | IRQ_TXPSI | /* TX process stop */ \ | ||
792 | IRQ_RXPSI) /* RX process stop */ | ||
793 | |||
794 | ks->rc_ier = STD_IRQ; | ||
795 | ks8851_wrreg16(ks, KS_ISR, STD_IRQ); | ||
796 | ks8851_wrreg16(ks, KS_IER, STD_IRQ); | ||
797 | |||
798 | netif_start_queue(ks->netdev); | ||
799 | |||
800 | if (netif_msg_ifup(ks)) | ||
801 | ks_dbg(ks, "network device %s up\n", dev->name); | ||
802 | |||
803 | mutex_unlock(&ks->lock); | ||
804 | return 0; | ||
805 | } | ||
806 | |||
807 | /** | ||
808 | * ks8851_net_stop - close network device | ||
809 | * @dev: The device being closed. | ||
810 | * | ||
811 | * Called to close down a network device which has been active. Cancell any | ||
812 | * work, shutdown the RX and TX process and then place the chip into a low | ||
813 | * power state whilst it is not being used. | ||
814 | */ | ||
815 | static int ks8851_net_stop(struct net_device *dev) | ||
816 | { | ||
817 | struct ks8851_net *ks = netdev_priv(dev); | ||
818 | |||
819 | if (netif_msg_ifdown(ks)) | ||
820 | ks_info(ks, "%s: shutting down\n", dev->name); | ||
821 | |||
822 | netif_stop_queue(dev); | ||
823 | |||
824 | mutex_lock(&ks->lock); | ||
825 | |||
826 | /* stop any outstanding work */ | ||
827 | flush_work(&ks->irq_work); | ||
828 | flush_work(&ks->tx_work); | ||
829 | flush_work(&ks->rxctrl_work); | ||
830 | |||
831 | /* turn off the IRQs and ack any outstanding */ | ||
832 | ks8851_wrreg16(ks, KS_IER, 0x0000); | ||
833 | ks8851_wrreg16(ks, KS_ISR, 0xffff); | ||
834 | |||
835 | /* shutdown RX process */ | ||
836 | ks8851_wrreg16(ks, KS_RXCR1, 0x0000); | ||
837 | |||
838 | /* shutdown TX process */ | ||
839 | ks8851_wrreg16(ks, KS_TXCR, 0x0000); | ||
840 | |||
841 | /* set powermode to soft power down to save power */ | ||
842 | ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN); | ||
843 | |||
844 | /* ensure any queued tx buffers are dumped */ | ||
845 | while (!skb_queue_empty(&ks->txq)) { | ||
846 | struct sk_buff *txb = skb_dequeue(&ks->txq); | ||
847 | |||
848 | if (netif_msg_ifdown(ks)) | ||
849 | ks_dbg(ks, "%s: freeing txb %p\n", __func__, txb); | ||
850 | |||
851 | dev_kfree_skb(txb); | ||
852 | } | ||
853 | |||
854 | mutex_unlock(&ks->lock); | ||
855 | return 0; | ||
856 | } | ||
857 | |||
858 | /** | ||
859 | * ks8851_start_xmit - transmit packet | ||
860 | * @skb: The buffer to transmit | ||
861 | * @dev: The device used to transmit the packet. | ||
862 | * | ||
863 | * Called by the network layer to transmit the @skb. Queue the packet for | ||
864 | * the device and schedule the necessary work to transmit the packet when | ||
865 | * it is free. | ||
866 | * | ||
867 | * We do this to firstly avoid sleeping with the network device locked, | ||
868 | * and secondly so we can round up more than one packet to transmit which | ||
869 | * means we can try and avoid generating too many transmit done interrupts. | ||
870 | */ | ||
871 | static int ks8851_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
872 | { | ||
873 | struct ks8851_net *ks = netdev_priv(dev); | ||
874 | unsigned needed = calc_txlen(skb->len); | ||
875 | int ret = NETDEV_TX_OK; | ||
876 | |||
877 | if (netif_msg_tx_queued(ks)) | ||
878 | ks_dbg(ks, "%s: skb %p, %d@%p\n", __func__, | ||
879 | skb, skb->len, skb->data); | ||
880 | |||
881 | spin_lock(&ks->statelock); | ||
882 | |||
883 | if (needed > ks->tx_space) { | ||
884 | netif_stop_queue(dev); | ||
885 | ret = NETDEV_TX_BUSY; | ||
886 | } else { | ||
887 | ks->tx_space -= needed; | ||
888 | skb_queue_tail(&ks->txq, skb); | ||
889 | } | ||
890 | |||
891 | spin_unlock(&ks->statelock); | ||
892 | schedule_work(&ks->tx_work); | ||
893 | |||
894 | return ret; | ||
895 | } | ||
896 | |||
897 | /** | ||
898 | * ks8851_rxctrl_work - work handler to change rx mode | ||
899 | * @work: The work structure this belongs to. | ||
900 | * | ||
901 | * Lock the device and issue the necessary changes to the receive mode from | ||
902 | * the network device layer. This is done so that we can do this without | ||
903 | * having to sleep whilst holding the network device lock. | ||
904 | * | ||
905 | * Since the recommendation from Micrel is that the RXQ is shutdown whilst the | ||
906 | * receive parameters are programmed, we issue a write to disable the RXQ and | ||
907 | * then wait for the interrupt handler to be triggered once the RXQ shutdown is | ||
908 | * complete. The interrupt handler then writes the new values into the chip. | ||
909 | */ | ||
910 | static void ks8851_rxctrl_work(struct work_struct *work) | ||
911 | { | ||
912 | struct ks8851_net *ks = container_of(work, struct ks8851_net, rxctrl_work); | ||
913 | |||
914 | mutex_lock(&ks->lock); | ||
915 | |||
916 | /* need to shutdown RXQ before modifying filter parameters */ | ||
917 | ks8851_wrreg16(ks, KS_RXCR1, 0x00); | ||
918 | |||
919 | mutex_unlock(&ks->lock); | ||
920 | } | ||
921 | |||
922 | static void ks8851_set_rx_mode(struct net_device *dev) | ||
923 | { | ||
924 | struct ks8851_net *ks = netdev_priv(dev); | ||
925 | struct ks8851_rxctrl rxctrl; | ||
926 | |||
927 | memset(&rxctrl, 0, sizeof(rxctrl)); | ||
928 | |||
929 | if (dev->flags & IFF_PROMISC) { | ||
930 | /* interface to receive everything */ | ||
931 | |||
932 | rxctrl.rxcr1 = RXCR1_RXAE | RXCR1_RXINVF; | ||
933 | } else if (dev->flags & IFF_ALLMULTI) { | ||
934 | /* accept all multicast packets */ | ||
935 | |||
936 | rxctrl.rxcr1 = (RXCR1_RXME | RXCR1_RXAE | | ||
937 | RXCR1_RXPAFMA | RXCR1_RXMAFMA); | ||
938 | } else if (dev->flags & IFF_MULTICAST && dev->mc_count > 0) { | ||
939 | struct dev_mc_list *mcptr = dev->mc_list; | ||
940 | u32 crc; | ||
941 | int i; | ||
942 | |||
943 | /* accept some multicast */ | ||
944 | |||
945 | for (i = dev->mc_count; i > 0; i--) { | ||
946 | crc = ether_crc(ETH_ALEN, mcptr->dmi_addr); | ||
947 | crc >>= (32 - 6); /* get top six bits */ | ||
948 | |||
949 | rxctrl.mchash[crc >> 4] |= (1 << (crc & 0xf)); | ||
950 | mcptr = mcptr->next; | ||
951 | } | ||
952 | |||
953 | rxctrl.rxcr1 = RXCR1_RXME | RXCR1_RXAE | RXCR1_RXPAFMA; | ||
954 | } else { | ||
955 | /* just accept broadcast / unicast */ | ||
956 | rxctrl.rxcr1 = RXCR1_RXPAFMA; | ||
957 | } | ||
958 | |||
959 | rxctrl.rxcr1 |= (RXCR1_RXUE | /* unicast enable */ | ||
960 | RXCR1_RXBE | /* broadcast enable */ | ||
961 | RXCR1_RXE | /* RX process enable */ | ||
962 | RXCR1_RXFCE); /* enable flow control */ | ||
963 | |||
964 | rxctrl.rxcr2 |= RXCR2_SRDBL_FRAME; | ||
965 | |||
966 | /* schedule work to do the actual set of the data if needed */ | ||
967 | |||
968 | spin_lock(&ks->statelock); | ||
969 | |||
970 | if (memcmp(&rxctrl, &ks->rxctrl, sizeof(rxctrl)) != 0) { | ||
971 | memcpy(&ks->rxctrl, &rxctrl, sizeof(ks->rxctrl)); | ||
972 | schedule_work(&ks->rxctrl_work); | ||
973 | } | ||
974 | |||
975 | spin_unlock(&ks->statelock); | ||
976 | } | ||
977 | |||
978 | static int ks8851_set_mac_address(struct net_device *dev, void *addr) | ||
979 | { | ||
980 | struct sockaddr *sa = addr; | ||
981 | |||
982 | if (netif_running(dev)) | ||
983 | return -EBUSY; | ||
984 | |||
985 | if (!is_valid_ether_addr(sa->sa_data)) | ||
986 | return -EADDRNOTAVAIL; | ||
987 | |||
988 | memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN); | ||
989 | return ks8851_write_mac_addr(dev); | ||
990 | } | ||
991 | |||
992 | static int ks8851_net_ioctl(struct net_device *dev, struct ifreq *req, int cmd) | ||
993 | { | ||
994 | struct ks8851_net *ks = netdev_priv(dev); | ||
995 | |||
996 | if (!netif_running(dev)) | ||
997 | return -EINVAL; | ||
998 | |||
999 | return generic_mii_ioctl(&ks->mii, if_mii(req), cmd, NULL); | ||
1000 | } | ||
1001 | |||
1002 | static const struct net_device_ops ks8851_netdev_ops = { | ||
1003 | .ndo_open = ks8851_net_open, | ||
1004 | .ndo_stop = ks8851_net_stop, | ||
1005 | .ndo_do_ioctl = ks8851_net_ioctl, | ||
1006 | .ndo_start_xmit = ks8851_start_xmit, | ||
1007 | .ndo_set_mac_address = ks8851_set_mac_address, | ||
1008 | .ndo_set_rx_mode = ks8851_set_rx_mode, | ||
1009 | .ndo_change_mtu = eth_change_mtu, | ||
1010 | .ndo_validate_addr = eth_validate_addr, | ||
1011 | }; | ||
1012 | |||
1013 | /* ethtool support */ | ||
1014 | |||
1015 | static void ks8851_get_drvinfo(struct net_device *dev, | ||
1016 | struct ethtool_drvinfo *di) | ||
1017 | { | ||
1018 | strlcpy(di->driver, "KS8851", sizeof(di->driver)); | ||
1019 | strlcpy(di->version, "1.00", sizeof(di->version)); | ||
1020 | strlcpy(di->bus_info, dev_name(dev->dev.parent), sizeof(di->bus_info)); | ||
1021 | } | ||
1022 | |||
1023 | static u32 ks8851_get_msglevel(struct net_device *dev) | ||
1024 | { | ||
1025 | struct ks8851_net *ks = netdev_priv(dev); | ||
1026 | return ks->msg_enable; | ||
1027 | } | ||
1028 | |||
1029 | static void ks8851_set_msglevel(struct net_device *dev, u32 to) | ||
1030 | { | ||
1031 | struct ks8851_net *ks = netdev_priv(dev); | ||
1032 | ks->msg_enable = to; | ||
1033 | } | ||
1034 | |||
1035 | static int ks8851_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
1036 | { | ||
1037 | struct ks8851_net *ks = netdev_priv(dev); | ||
1038 | return mii_ethtool_gset(&ks->mii, cmd); | ||
1039 | } | ||
1040 | |||
1041 | static int ks8851_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
1042 | { | ||
1043 | struct ks8851_net *ks = netdev_priv(dev); | ||
1044 | return mii_ethtool_sset(&ks->mii, cmd); | ||
1045 | } | ||
1046 | |||
1047 | static u32 ks8851_get_link(struct net_device *dev) | ||
1048 | { | ||
1049 | struct ks8851_net *ks = netdev_priv(dev); | ||
1050 | return mii_link_ok(&ks->mii); | ||
1051 | } | ||
1052 | |||
1053 | static int ks8851_nway_reset(struct net_device *dev) | ||
1054 | { | ||
1055 | struct ks8851_net *ks = netdev_priv(dev); | ||
1056 | return mii_nway_restart(&ks->mii); | ||
1057 | } | ||
1058 | |||
1059 | static const struct ethtool_ops ks8851_ethtool_ops = { | ||
1060 | .get_drvinfo = ks8851_get_drvinfo, | ||
1061 | .get_msglevel = ks8851_get_msglevel, | ||
1062 | .set_msglevel = ks8851_set_msglevel, | ||
1063 | .get_settings = ks8851_get_settings, | ||
1064 | .set_settings = ks8851_set_settings, | ||
1065 | .get_link = ks8851_get_link, | ||
1066 | .nway_reset = ks8851_nway_reset, | ||
1067 | }; | ||
1068 | |||
1069 | /* MII interface controls */ | ||
1070 | |||
1071 | /** | ||
1072 | * ks8851_phy_reg - convert MII register into a KS8851 register | ||
1073 | * @reg: MII register number. | ||
1074 | * | ||
1075 | * Return the KS8851 register number for the corresponding MII PHY register | ||
1076 | * if possible. Return zero if the MII register has no direct mapping to the | ||
1077 | * KS8851 register set. | ||
1078 | */ | ||
1079 | static int ks8851_phy_reg(int reg) | ||
1080 | { | ||
1081 | switch (reg) { | ||
1082 | case MII_BMCR: | ||
1083 | return KS_P1MBCR; | ||
1084 | case MII_BMSR: | ||
1085 | return KS_P1MBSR; | ||
1086 | case MII_PHYSID1: | ||
1087 | return KS_PHY1ILR; | ||
1088 | case MII_PHYSID2: | ||
1089 | return KS_PHY1IHR; | ||
1090 | case MII_ADVERTISE: | ||
1091 | return KS_P1ANAR; | ||
1092 | case MII_LPA: | ||
1093 | return KS_P1ANLPR; | ||
1094 | } | ||
1095 | |||
1096 | return 0x0; | ||
1097 | } | ||
1098 | |||
1099 | /** | ||
1100 | * ks8851_phy_read - MII interface PHY register read. | ||
1101 | * @dev: The network device the PHY is on. | ||
1102 | * @phy_addr: Address of PHY (ignored as we only have one) | ||
1103 | * @reg: The register to read. | ||
1104 | * | ||
1105 | * This call reads data from the PHY register specified in @reg. Since the | ||
1106 | * device does not support all the MII registers, the non-existant values | ||
1107 | * are always returned as zero. | ||
1108 | * | ||
1109 | * We return zero for unsupported registers as the MII code does not check | ||
1110 | * the value returned for any error status, and simply returns it to the | ||
1111 | * caller. The mii-tool that the driver was tested with takes any -ve error | ||
1112 | * as real PHY capabilities, thus displaying incorrect data to the user. | ||
1113 | */ | ||
1114 | static int ks8851_phy_read(struct net_device *dev, int phy_addr, int reg) | ||
1115 | { | ||
1116 | struct ks8851_net *ks = netdev_priv(dev); | ||
1117 | int ksreg; | ||
1118 | int result; | ||
1119 | |||
1120 | ksreg = ks8851_phy_reg(reg); | ||
1121 | if (!ksreg) | ||
1122 | return 0x0; /* no error return allowed, so use zero */ | ||
1123 | |||
1124 | mutex_lock(&ks->lock); | ||
1125 | result = ks8851_rdreg16(ks, ksreg); | ||
1126 | mutex_unlock(&ks->lock); | ||
1127 | |||
1128 | return result; | ||
1129 | } | ||
1130 | |||
1131 | static void ks8851_phy_write(struct net_device *dev, | ||
1132 | int phy, int reg, int value) | ||
1133 | { | ||
1134 | struct ks8851_net *ks = netdev_priv(dev); | ||
1135 | int ksreg; | ||
1136 | |||
1137 | ksreg = ks8851_phy_reg(reg); | ||
1138 | if (ksreg) { | ||
1139 | mutex_lock(&ks->lock); | ||
1140 | ks8851_wrreg16(ks, ksreg, value); | ||
1141 | mutex_unlock(&ks->lock); | ||
1142 | } | ||
1143 | } | ||
1144 | |||
1145 | /** | ||
1146 | * ks8851_read_selftest - read the selftest memory info. | ||
1147 | * @ks: The device state | ||
1148 | * | ||
1149 | * Read and check the TX/RX memory selftest information. | ||
1150 | */ | ||
1151 | static int ks8851_read_selftest(struct ks8851_net *ks) | ||
1152 | { | ||
1153 | unsigned both_done = MBIR_TXMBF | MBIR_RXMBF; | ||
1154 | int ret = 0; | ||
1155 | unsigned rd; | ||
1156 | |||
1157 | rd = ks8851_rdreg16(ks, KS_MBIR); | ||
1158 | |||
1159 | if ((rd & both_done) != both_done) { | ||
1160 | ks_warn(ks, "Memory selftest not finished\n"); | ||
1161 | return 0; | ||
1162 | } | ||
1163 | |||
1164 | if (rd & MBIR_TXMBFA) { | ||
1165 | ks_err(ks, "TX memory selftest fail\n"); | ||
1166 | ret |= 1; | ||
1167 | } | ||
1168 | |||
1169 | if (rd & MBIR_RXMBFA) { | ||
1170 | ks_err(ks, "RX memory selftest fail\n"); | ||
1171 | ret |= 2; | ||
1172 | } | ||
1173 | |||
1174 | return 0; | ||
1175 | } | ||
1176 | |||
1177 | /* driver bus management functions */ | ||
1178 | |||
1179 | static int __devinit ks8851_probe(struct spi_device *spi) | ||
1180 | { | ||
1181 | struct net_device *ndev; | ||
1182 | struct ks8851_net *ks; | ||
1183 | int ret; | ||
1184 | |||
1185 | ndev = alloc_etherdev(sizeof(struct ks8851_net)); | ||
1186 | if (!ndev) { | ||
1187 | dev_err(&spi->dev, "failed to alloc ethernet device\n"); | ||
1188 | return -ENOMEM; | ||
1189 | } | ||
1190 | |||
1191 | spi->bits_per_word = 8; | ||
1192 | |||
1193 | ks = netdev_priv(ndev); | ||
1194 | |||
1195 | ks->netdev = ndev; | ||
1196 | ks->spidev = spi; | ||
1197 | ks->tx_space = 6144; | ||
1198 | |||
1199 | mutex_init(&ks->lock); | ||
1200 | spin_lock_init(&ks->statelock); | ||
1201 | |||
1202 | INIT_WORK(&ks->tx_work, ks8851_tx_work); | ||
1203 | INIT_WORK(&ks->irq_work, ks8851_irq_work); | ||
1204 | INIT_WORK(&ks->rxctrl_work, ks8851_rxctrl_work); | ||
1205 | |||
1206 | /* initialise pre-made spi transfer messages */ | ||
1207 | |||
1208 | spi_message_init(&ks->spi_msg1); | ||
1209 | spi_message_add_tail(&ks->spi_xfer1, &ks->spi_msg1); | ||
1210 | |||
1211 | spi_message_init(&ks->spi_msg2); | ||
1212 | spi_message_add_tail(&ks->spi_xfer2[0], &ks->spi_msg2); | ||
1213 | spi_message_add_tail(&ks->spi_xfer2[1], &ks->spi_msg2); | ||
1214 | |||
1215 | /* setup mii state */ | ||
1216 | ks->mii.dev = ndev; | ||
1217 | ks->mii.phy_id = 1, | ||
1218 | ks->mii.phy_id_mask = 1; | ||
1219 | ks->mii.reg_num_mask = 0xf; | ||
1220 | ks->mii.mdio_read = ks8851_phy_read; | ||
1221 | ks->mii.mdio_write = ks8851_phy_write; | ||
1222 | |||
1223 | dev_info(&spi->dev, "message enable is %d\n", msg_enable); | ||
1224 | |||
1225 | /* set the default message enable */ | ||
1226 | ks->msg_enable = netif_msg_init(msg_enable, (NETIF_MSG_DRV | | ||
1227 | NETIF_MSG_PROBE | | ||
1228 | NETIF_MSG_LINK)); | ||
1229 | |||
1230 | skb_queue_head_init(&ks->txq); | ||
1231 | |||
1232 | SET_ETHTOOL_OPS(ndev, &ks8851_ethtool_ops); | ||
1233 | SET_NETDEV_DEV(ndev, &spi->dev); | ||
1234 | |||
1235 | dev_set_drvdata(&spi->dev, ks); | ||
1236 | |||
1237 | ndev->if_port = IF_PORT_100BASET; | ||
1238 | ndev->netdev_ops = &ks8851_netdev_ops; | ||
1239 | ndev->irq = spi->irq; | ||
1240 | |||
1241 | /* simple check for a valid chip being connected to the bus */ | ||
1242 | |||
1243 | if ((ks8851_rdreg16(ks, KS_CIDER) & ~CIDER_REV_MASK) != CIDER_ID) { | ||
1244 | dev_err(&spi->dev, "failed to read device ID\n"); | ||
1245 | ret = -ENODEV; | ||
1246 | goto err_id; | ||
1247 | } | ||
1248 | |||
1249 | ks8851_read_selftest(ks); | ||
1250 | ks8851_init_mac(ks); | ||
1251 | |||
1252 | ret = request_irq(spi->irq, ks8851_irq, IRQF_TRIGGER_LOW, | ||
1253 | ndev->name, ks); | ||
1254 | if (ret < 0) { | ||
1255 | dev_err(&spi->dev, "failed to get irq\n"); | ||
1256 | goto err_irq; | ||
1257 | } | ||
1258 | |||
1259 | ret = register_netdev(ndev); | ||
1260 | if (ret) { | ||
1261 | dev_err(&spi->dev, "failed to register network device\n"); | ||
1262 | goto err_netdev; | ||
1263 | } | ||
1264 | |||
1265 | dev_info(&spi->dev, "revision %d, MAC %pM, IRQ %d\n", | ||
1266 | CIDER_REV_GET(ks8851_rdreg16(ks, KS_CIDER)), | ||
1267 | ndev->dev_addr, ndev->irq); | ||
1268 | |||
1269 | return 0; | ||
1270 | |||
1271 | |||
1272 | err_netdev: | ||
1273 | free_irq(ndev->irq, ndev); | ||
1274 | |||
1275 | err_id: | ||
1276 | err_irq: | ||
1277 | free_netdev(ndev); | ||
1278 | return ret; | ||
1279 | } | ||
1280 | |||
1281 | static int __devexit ks8851_remove(struct spi_device *spi) | ||
1282 | { | ||
1283 | struct ks8851_net *priv = dev_get_drvdata(&spi->dev); | ||
1284 | |||
1285 | if (netif_msg_drv(priv)) | ||
1286 | dev_info(&spi->dev, "remove"); | ||
1287 | |||
1288 | unregister_netdev(priv->netdev); | ||
1289 | free_irq(spi->irq, priv); | ||
1290 | free_netdev(priv->netdev); | ||
1291 | |||
1292 | return 0; | ||
1293 | } | ||
1294 | |||
1295 | static struct spi_driver ks8851_driver = { | ||
1296 | .driver = { | ||
1297 | .name = "ks8851", | ||
1298 | .owner = THIS_MODULE, | ||
1299 | }, | ||
1300 | .probe = ks8851_probe, | ||
1301 | .remove = __devexit_p(ks8851_remove), | ||
1302 | }; | ||
1303 | |||
1304 | static int __init ks8851_init(void) | ||
1305 | { | ||
1306 | return spi_register_driver(&ks8851_driver); | ||
1307 | } | ||
1308 | |||
1309 | static void __exit ks8851_exit(void) | ||
1310 | { | ||
1311 | spi_unregister_driver(&ks8851_driver); | ||
1312 | } | ||
1313 | |||
1314 | module_init(ks8851_init); | ||
1315 | module_exit(ks8851_exit); | ||
1316 | |||
1317 | MODULE_DESCRIPTION("KS8851 Network driver"); | ||
1318 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | ||
1319 | MODULE_LICENSE("GPL"); | ||
1320 | |||
1321 | module_param_named(message, msg_enable, int, 0); | ||
1322 | MODULE_PARM_DESC(message, "Message verbosity level (0=none, 31=all)"); | ||
diff --git a/drivers/net/ks8851.h b/drivers/net/ks8851.h new file mode 100644 index 000000000000..85abe147afbf --- /dev/null +++ b/drivers/net/ks8851.h | |||
@@ -0,0 +1,296 @@ | |||
1 | /* drivers/net/ks8851.h | ||
2 | * | ||
3 | * Copyright 2009 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * KS8851 register definitions | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #define KS_CCR 0x08 | ||
14 | #define CCR_EEPROM (1 << 9) | ||
15 | #define CCR_SPI (1 << 8) | ||
16 | #define CCR_32PIN (1 << 0) | ||
17 | |||
18 | /* MAC address registers */ | ||
19 | #define KS_MARL 0x10 | ||
20 | #define KS_MARM 0x12 | ||
21 | #define KS_MARH 0x14 | ||
22 | |||
23 | #define KS_OBCR 0x20 | ||
24 | #define OBCR_ODS_16mA (1 << 6) | ||
25 | |||
26 | #define KS_EEPCR 0x22 | ||
27 | #define EEPCR_EESA (1 << 4) | ||
28 | #define EEPCR_EESB (1 << 3) | ||
29 | #define EEPCR_EEDO (1 << 2) | ||
30 | #define EEPCR_EESCK (1 << 1) | ||
31 | #define EEPCR_EECS (1 << 0) | ||
32 | |||
33 | #define KS_MBIR 0x24 | ||
34 | #define MBIR_TXMBF (1 << 12) | ||
35 | #define MBIR_TXMBFA (1 << 11) | ||
36 | #define MBIR_RXMBF (1 << 4) | ||
37 | #define MBIR_RXMBFA (1 << 3) | ||
38 | |||
39 | #define KS_GRR 0x26 | ||
40 | #define GRR_QMU (1 << 1) | ||
41 | #define GRR_GSR (1 << 0) | ||
42 | |||
43 | #define KS_WFCR 0x2A | ||
44 | #define WFCR_MPRXE (1 << 7) | ||
45 | #define WFCR_WF3E (1 << 3) | ||
46 | #define WFCR_WF2E (1 << 2) | ||
47 | #define WFCR_WF1E (1 << 1) | ||
48 | #define WFCR_WF0E (1 << 0) | ||
49 | |||
50 | #define KS_WF0CRC0 0x30 | ||
51 | #define KS_WF0CRC1 0x32 | ||
52 | #define KS_WF0BM0 0x34 | ||
53 | #define KS_WF0BM1 0x36 | ||
54 | #define KS_WF0BM2 0x38 | ||
55 | #define KS_WF0BM3 0x3A | ||
56 | |||
57 | #define KS_WF1CRC0 0x40 | ||
58 | #define KS_WF1CRC1 0x42 | ||
59 | #define KS_WF1BM0 0x44 | ||
60 | #define KS_WF1BM1 0x46 | ||
61 | #define KS_WF1BM2 0x48 | ||
62 | #define KS_WF1BM3 0x4A | ||
63 | |||
64 | #define KS_WF2CRC0 0x50 | ||
65 | #define KS_WF2CRC1 0x52 | ||
66 | #define KS_WF2BM0 0x54 | ||
67 | #define KS_WF2BM1 0x56 | ||
68 | #define KS_WF2BM2 0x58 | ||
69 | #define KS_WF2BM3 0x5A | ||
70 | |||
71 | #define KS_WF3CRC0 0x60 | ||
72 | #define KS_WF3CRC1 0x62 | ||
73 | #define KS_WF3BM0 0x64 | ||
74 | #define KS_WF3BM1 0x66 | ||
75 | #define KS_WF3BM2 0x68 | ||
76 | #define KS_WF3BM3 0x6A | ||
77 | |||
78 | #define KS_TXCR 0x70 | ||
79 | #define TXCR_TCGICMP (1 << 8) | ||
80 | #define TXCR_TCGUDP (1 << 7) | ||
81 | #define TXCR_TCGTCP (1 << 6) | ||
82 | #define TXCR_TCGIP (1 << 5) | ||
83 | #define TXCR_FTXQ (1 << 4) | ||
84 | #define TXCR_TXFCE (1 << 3) | ||
85 | #define TXCR_TXPE (1 << 2) | ||
86 | #define TXCR_TXCRC (1 << 1) | ||
87 | #define TXCR_TXE (1 << 0) | ||
88 | |||
89 | #define KS_TXSR 0x72 | ||
90 | #define TXSR_TXLC (1 << 13) | ||
91 | #define TXSR_TXMC (1 << 12) | ||
92 | #define TXSR_TXFID_MASK (0x3f << 0) | ||
93 | #define TXSR_TXFID_SHIFT (0) | ||
94 | #define TXSR_TXFID_GET(_v) (((_v) >> 0) & 0x3f) | ||
95 | |||
96 | #define KS_RXCR1 0x74 | ||
97 | #define RXCR1_FRXQ (1 << 15) | ||
98 | #define RXCR1_RXUDPFCC (1 << 14) | ||
99 | #define RXCR1_RXTCPFCC (1 << 13) | ||
100 | #define RXCR1_RXIPFCC (1 << 12) | ||
101 | #define RXCR1_RXPAFMA (1 << 11) | ||
102 | #define RXCR1_RXFCE (1 << 10) | ||
103 | #define RXCR1_RXEFE (1 << 9) | ||
104 | #define RXCR1_RXMAFMA (1 << 8) | ||
105 | #define RXCR1_RXBE (1 << 7) | ||
106 | #define RXCR1_RXME (1 << 6) | ||
107 | #define RXCR1_RXUE (1 << 5) | ||
108 | #define RXCR1_RXAE (1 << 4) | ||
109 | #define RXCR1_RXINVF (1 << 1) | ||
110 | #define RXCR1_RXE (1 << 0) | ||
111 | |||
112 | #define KS_RXCR2 0x76 | ||
113 | #define RXCR2_SRDBL_MASK (0x7 << 5) | ||
114 | #define RXCR2_SRDBL_SHIFT (5) | ||
115 | #define RXCR2_SRDBL_4B (0x0 << 5) | ||
116 | #define RXCR2_SRDBL_8B (0x1 << 5) | ||
117 | #define RXCR2_SRDBL_16B (0x2 << 5) | ||
118 | #define RXCR2_SRDBL_32B (0x3 << 5) | ||
119 | #define RXCR2_SRDBL_FRAME (0x4 << 5) | ||
120 | #define RXCR2_IUFFP (1 << 4) | ||
121 | #define RXCR2_RXIUFCEZ (1 << 3) | ||
122 | #define RXCR2_UDPLFE (1 << 2) | ||
123 | #define RXCR2_RXICMPFCC (1 << 1) | ||
124 | #define RXCR2_RXSAF (1 << 0) | ||
125 | |||
126 | #define KS_TXMIR 0x78 | ||
127 | |||
128 | #define KS_RXFHSR 0x7C | ||
129 | #define RXFSHR_RXFV (1 << 15) | ||
130 | #define RXFSHR_RXICMPFCS (1 << 13) | ||
131 | #define RXFSHR_RXIPFCS (1 << 12) | ||
132 | #define RXFSHR_RXTCPFCS (1 << 11) | ||
133 | #define RXFSHR_RXUDPFCS (1 << 10) | ||
134 | #define RXFSHR_RXBF (1 << 7) | ||
135 | #define RXFSHR_RXMF (1 << 6) | ||
136 | #define RXFSHR_RXUF (1 << 5) | ||
137 | #define RXFSHR_RXMR (1 << 4) | ||
138 | #define RXFSHR_RXFT (1 << 3) | ||
139 | #define RXFSHR_RXFTL (1 << 2) | ||
140 | #define RXFSHR_RXRF (1 << 1) | ||
141 | #define RXFSHR_RXCE (1 << 0) | ||
142 | |||
143 | #define KS_RXFHBCR 0x7E | ||
144 | #define KS_TXQCR 0x80 | ||
145 | #define TXQCR_AETFE (1 << 2) | ||
146 | #define TXQCR_TXQMAM (1 << 1) | ||
147 | #define TXQCR_METFE (1 << 0) | ||
148 | |||
149 | #define KS_RXQCR 0x82 | ||
150 | #define RXQCR_RXDTTS (1 << 12) | ||
151 | #define RXQCR_RXDBCTS (1 << 11) | ||
152 | #define RXQCR_RXFCTS (1 << 10) | ||
153 | #define RXQCR_RXIPHTOE (1 << 9) | ||
154 | #define RXQCR_RXDTTE (1 << 7) | ||
155 | #define RXQCR_RXDBCTE (1 << 6) | ||
156 | #define RXQCR_RXFCTE (1 << 5) | ||
157 | #define RXQCR_ADRFE (1 << 4) | ||
158 | #define RXQCR_SDA (1 << 3) | ||
159 | #define RXQCR_RRXEF (1 << 0) | ||
160 | |||
161 | #define KS_TXFDPR 0x84 | ||
162 | #define TXFDPR_TXFPAI (1 << 14) | ||
163 | #define TXFDPR_TXFP_MASK (0x7ff << 0) | ||
164 | #define TXFDPR_TXFP_SHIFT (0) | ||
165 | |||
166 | #define KS_RXFDPR 0x86 | ||
167 | #define RXFDPR_RXFPAI (1 << 14) | ||
168 | |||
169 | #define KS_RXDTTR 0x8C | ||
170 | #define KS_RXDBCTR 0x8E | ||
171 | |||
172 | #define KS_IER 0x90 | ||
173 | #define KS_ISR 0x92 | ||
174 | #define IRQ_LCI (1 << 15) | ||
175 | #define IRQ_TXI (1 << 14) | ||
176 | #define IRQ_RXI (1 << 13) | ||
177 | #define IRQ_RXOI (1 << 11) | ||
178 | #define IRQ_TXPSI (1 << 9) | ||
179 | #define IRQ_RXPSI (1 << 8) | ||
180 | #define IRQ_TXSAI (1 << 6) | ||
181 | #define IRQ_RXWFDI (1 << 5) | ||
182 | #define IRQ_RXMPDI (1 << 4) | ||
183 | #define IRQ_LDI (1 << 3) | ||
184 | #define IRQ_EDI (1 << 2) | ||
185 | #define IRQ_SPIBEI (1 << 1) | ||
186 | #define IRQ_DEDI (1 << 0) | ||
187 | |||
188 | #define KS_RXFCTR 0x9C | ||
189 | #define KS_RXFC 0x9D | ||
190 | #define RXFCTR_RXFC_MASK (0xff << 8) | ||
191 | #define RXFCTR_RXFC_SHIFT (8) | ||
192 | #define RXFCTR_RXFC_GET(_v) (((_v) >> 8) & 0xff) | ||
193 | #define RXFCTR_RXFCT_MASK (0xff << 0) | ||
194 | #define RXFCTR_RXFCT_SHIFT (0) | ||
195 | |||
196 | #define KS_TXNTFSR 0x9E | ||
197 | |||
198 | #define KS_MAHTR0 0xA0 | ||
199 | #define KS_MAHTR1 0xA2 | ||
200 | #define KS_MAHTR2 0xA4 | ||
201 | #define KS_MAHTR3 0xA6 | ||
202 | |||
203 | #define KS_FCLWR 0xB0 | ||
204 | #define KS_FCHWR 0xB2 | ||
205 | #define KS_FCOWR 0xB4 | ||
206 | |||
207 | #define KS_CIDER 0xC0 | ||
208 | #define CIDER_ID 0x8870 | ||
209 | #define CIDER_REV_MASK (0x7 << 1) | ||
210 | #define CIDER_REV_SHIFT (1) | ||
211 | #define CIDER_REV_GET(_v) (((_v) >> 1) & 0x7) | ||
212 | |||
213 | #define KS_CGCR 0xC6 | ||
214 | |||
215 | #define KS_IACR 0xC8 | ||
216 | #define IACR_RDEN (1 << 12) | ||
217 | #define IACR_TSEL_MASK (0x3 << 10) | ||
218 | #define IACR_TSEL_SHIFT (10) | ||
219 | #define IACR_TSEL_MIB (0x3 << 10) | ||
220 | #define IACR_ADDR_MASK (0x1f << 0) | ||
221 | #define IACR_ADDR_SHIFT (0) | ||
222 | |||
223 | #define KS_IADLR 0xD0 | ||
224 | #define KS_IAHDR 0xD2 | ||
225 | |||
226 | #define KS_PMECR 0xD4 | ||
227 | #define PMECR_PME_DELAY (1 << 14) | ||
228 | #define PMECR_PME_POL (1 << 12) | ||
229 | #define PMECR_WOL_WAKEUP (1 << 11) | ||
230 | #define PMECR_WOL_MAGICPKT (1 << 10) | ||
231 | #define PMECR_WOL_LINKUP (1 << 9) | ||
232 | #define PMECR_WOL_ENERGY (1 << 8) | ||
233 | #define PMECR_AUTO_WAKE_EN (1 << 7) | ||
234 | #define PMECR_WAKEUP_NORMAL (1 << 6) | ||
235 | #define PMECR_WKEVT_MASK (0xf << 2) | ||
236 | #define PMECR_WKEVT_SHIFT (2) | ||
237 | #define PMECR_WKEVT_GET(_v) (((_v) >> 2) & 0xf) | ||
238 | #define PMECR_WKEVT_ENERGY (0x1 << 2) | ||
239 | #define PMECR_WKEVT_LINK (0x2 << 2) | ||
240 | #define PMECR_WKEVT_MAGICPKT (0x4 << 2) | ||
241 | #define PMECR_WKEVT_FRAME (0x8 << 2) | ||
242 | #define PMECR_PM_MASK (0x3 << 0) | ||
243 | #define PMECR_PM_SHIFT (0) | ||
244 | #define PMECR_PM_NORMAL (0x0 << 0) | ||
245 | #define PMECR_PM_ENERGY (0x1 << 0) | ||
246 | #define PMECR_PM_SOFTDOWN (0x2 << 0) | ||
247 | #define PMECR_PM_POWERSAVE (0x3 << 0) | ||
248 | |||
249 | /* Standard MII PHY data */ | ||
250 | #define KS_P1MBCR 0xE4 | ||
251 | #define KS_P1MBSR 0xE6 | ||
252 | #define KS_PHY1ILR 0xE8 | ||
253 | #define KS_PHY1IHR 0xEA | ||
254 | #define KS_P1ANAR 0xEC | ||
255 | #define KS_P1ANLPR 0xEE | ||
256 | |||
257 | #define KS_P1SCLMD 0xF4 | ||
258 | #define P1SCLMD_LEDOFF (1 << 15) | ||
259 | #define P1SCLMD_TXIDS (1 << 14) | ||
260 | #define P1SCLMD_RESTARTAN (1 << 13) | ||
261 | #define P1SCLMD_DISAUTOMDIX (1 << 10) | ||
262 | #define P1SCLMD_FORCEMDIX (1 << 9) | ||
263 | #define P1SCLMD_AUTONEGEN (1 << 7) | ||
264 | #define P1SCLMD_FORCE100 (1 << 6) | ||
265 | #define P1SCLMD_FORCEFDX (1 << 5) | ||
266 | #define P1SCLMD_ADV_FLOW (1 << 4) | ||
267 | #define P1SCLMD_ADV_100BT_FDX (1 << 3) | ||
268 | #define P1SCLMD_ADV_100BT_HDX (1 << 2) | ||
269 | #define P1SCLMD_ADV_10BT_FDX (1 << 1) | ||
270 | #define P1SCLMD_ADV_10BT_HDX (1 << 0) | ||
271 | |||
272 | #define KS_P1CR 0xF6 | ||
273 | #define P1CR_HP_MDIX (1 << 15) | ||
274 | #define P1CR_REV_POL (1 << 13) | ||
275 | #define P1CR_OP_100M (1 << 10) | ||
276 | #define P1CR_OP_FDX (1 << 9) | ||
277 | #define P1CR_OP_MDI (1 << 7) | ||
278 | #define P1CR_AN_DONE (1 << 6) | ||
279 | #define P1CR_LINK_GOOD (1 << 5) | ||
280 | #define P1CR_PNTR_FLOW (1 << 4) | ||
281 | #define P1CR_PNTR_100BT_FDX (1 << 3) | ||
282 | #define P1CR_PNTR_100BT_HDX (1 << 2) | ||
283 | #define P1CR_PNTR_10BT_FDX (1 << 1) | ||
284 | #define P1CR_PNTR_10BT_HDX (1 << 0) | ||
285 | |||
286 | /* TX Frame control */ | ||
287 | |||
288 | #define TXFR_TXIC (1 << 15) | ||
289 | #define TXFR_TXFID_MASK (0x3f << 0) | ||
290 | #define TXFR_TXFID_SHIFT (0) | ||
291 | |||
292 | /* SPI frame opcodes */ | ||
293 | #define KS_SPIOP_RD (0x00) | ||
294 | #define KS_SPIOP_WR (0x40) | ||
295 | #define KS_SPIOP_RXFIFO (0x80) | ||
296 | #define KS_SPIOP_TXFIFO (0xC0) | ||
diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c index acd143da161d..61eabcac734c 100644 --- a/drivers/net/macsonic.c +++ b/drivers/net/macsonic.c | |||
@@ -179,7 +179,7 @@ static const struct net_device_ops macsonic_netdev_ops = { | |||
179 | .ndo_set_mac_address = eth_mac_addr, | 179 | .ndo_set_mac_address = eth_mac_addr, |
180 | }; | 180 | }; |
181 | 181 | ||
182 | static int __init macsonic_init(struct net_device *dev) | 182 | static int __devinit macsonic_init(struct net_device *dev) |
183 | { | 183 | { |
184 | struct sonic_local* lp = netdev_priv(dev); | 184 | struct sonic_local* lp = netdev_priv(dev); |
185 | 185 | ||
@@ -223,7 +223,7 @@ static int __init macsonic_init(struct net_device *dev) | |||
223 | return 0; | 223 | return 0; |
224 | } | 224 | } |
225 | 225 | ||
226 | static int __init mac_onboard_sonic_ethernet_addr(struct net_device *dev) | 226 | static int __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev) |
227 | { | 227 | { |
228 | struct sonic_local *lp = netdev_priv(dev); | 228 | struct sonic_local *lp = netdev_priv(dev); |
229 | const int prom_addr = ONBOARD_SONIC_PROM_BASE; | 229 | const int prom_addr = ONBOARD_SONIC_PROM_BASE; |
@@ -288,7 +288,7 @@ static int __init mac_onboard_sonic_ethernet_addr(struct net_device *dev) | |||
288 | } else return 0; | 288 | } else return 0; |
289 | } | 289 | } |
290 | 290 | ||
291 | static int __init mac_onboard_sonic_probe(struct net_device *dev) | 291 | static int __devinit mac_onboard_sonic_probe(struct net_device *dev) |
292 | { | 292 | { |
293 | /* Bwahahaha */ | 293 | /* Bwahahaha */ |
294 | static int once_is_more_than_enough; | 294 | static int once_is_more_than_enough; |
@@ -409,7 +409,7 @@ static int __init mac_onboard_sonic_probe(struct net_device *dev) | |||
409 | return macsonic_init(dev); | 409 | return macsonic_init(dev); |
410 | } | 410 | } |
411 | 411 | ||
412 | static int __init mac_nubus_sonic_ethernet_addr(struct net_device *dev, | 412 | static int __devinit mac_nubus_sonic_ethernet_addr(struct net_device *dev, |
413 | unsigned long prom_addr, | 413 | unsigned long prom_addr, |
414 | int id) | 414 | int id) |
415 | { | 415 | { |
@@ -424,7 +424,7 @@ static int __init mac_nubus_sonic_ethernet_addr(struct net_device *dev, | |||
424 | return 0; | 424 | return 0; |
425 | } | 425 | } |
426 | 426 | ||
427 | static int __init macsonic_ident(struct nubus_dev *ndev) | 427 | static int __devinit macsonic_ident(struct nubus_dev *ndev) |
428 | { | 428 | { |
429 | if (ndev->dr_hw == NUBUS_DRHW_ASANTE_LC && | 429 | if (ndev->dr_hw == NUBUS_DRHW_ASANTE_LC && |
430 | ndev->dr_sw == NUBUS_DRSW_SONIC_LC) | 430 | ndev->dr_sw == NUBUS_DRSW_SONIC_LC) |
@@ -449,7 +449,7 @@ static int __init macsonic_ident(struct nubus_dev *ndev) | |||
449 | return -1; | 449 | return -1; |
450 | } | 450 | } |
451 | 451 | ||
452 | static int __init mac_nubus_sonic_probe(struct net_device *dev) | 452 | static int __devinit mac_nubus_sonic_probe(struct net_device *dev) |
453 | { | 453 | { |
454 | static int slots; | 454 | static int slots; |
455 | struct nubus_dev* ndev = NULL; | 455 | struct nubus_dev* ndev = NULL; |
@@ -562,7 +562,7 @@ static int __init mac_nubus_sonic_probe(struct net_device *dev) | |||
562 | return macsonic_init(dev); | 562 | return macsonic_init(dev); |
563 | } | 563 | } |
564 | 564 | ||
565 | static int __init mac_sonic_probe(struct platform_device *pdev) | 565 | static int __devinit mac_sonic_probe(struct platform_device *pdev) |
566 | { | 566 | { |
567 | struct net_device *dev; | 567 | struct net_device *dev; |
568 | struct sonic_local *lp; | 568 | struct sonic_local *lp; |
@@ -575,6 +575,7 @@ static int __init mac_sonic_probe(struct platform_device *pdev) | |||
575 | lp = netdev_priv(dev); | 575 | lp = netdev_priv(dev); |
576 | lp->device = &pdev->dev; | 576 | lp->device = &pdev->dev; |
577 | SET_NETDEV_DEV(dev, &pdev->dev); | 577 | SET_NETDEV_DEV(dev, &pdev->dev); |
578 | platform_set_drvdata(pdev, dev); | ||
578 | 579 | ||
579 | /* This will catch fatal stuff like -ENOMEM as well as success */ | 580 | /* This will catch fatal stuff like -ENOMEM as well as success */ |
580 | err = mac_onboard_sonic_probe(dev); | 581 | err = mac_onboard_sonic_probe(dev); |
diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c index 091f99052c91..86467b444ac6 100644 --- a/drivers/net/mlx4/en_ethtool.c +++ b/drivers/net/mlx4/en_ethtool.c | |||
@@ -220,7 +220,7 @@ static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
220 | { | 220 | { |
221 | cmd->autoneg = AUTONEG_DISABLE; | 221 | cmd->autoneg = AUTONEG_DISABLE; |
222 | cmd->supported = SUPPORTED_10000baseT_Full; | 222 | cmd->supported = SUPPORTED_10000baseT_Full; |
223 | cmd->advertising = SUPPORTED_10000baseT_Full; | 223 | cmd->advertising = ADVERTISED_1000baseT_Full; |
224 | if (netif_carrier_ok(dev)) { | 224 | if (netif_carrier_ok(dev)) { |
225 | cmd->speed = SPEED_10000; | 225 | cmd->speed = SPEED_10000; |
226 | cmd->duplex = DUPLEX_FULL; | 226 | cmd->duplex = DUPLEX_FULL; |
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index e1cdba752e09..f86e05047d19 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h | |||
@@ -210,6 +210,7 @@ | |||
210 | #define NETXEN_CTX_SIGNATURE 0xdee0 | 210 | #define NETXEN_CTX_SIGNATURE 0xdee0 |
211 | #define NETXEN_CTX_SIGNATURE_V2 0x0002dee0 | 211 | #define NETXEN_CTX_SIGNATURE_V2 0x0002dee0 |
212 | #define NETXEN_CTX_RESET 0xbad0 | 212 | #define NETXEN_CTX_RESET 0xbad0 |
213 | #define NETXEN_CTX_D3_RESET 0xacc0 | ||
213 | #define NETXEN_RCV_PRODUCER(ringid) (ringid) | 214 | #define NETXEN_RCV_PRODUCER(ringid) (ringid) |
214 | 215 | ||
215 | #define PHAN_PEG_RCV_INITIALIZED 0xff01 | 216 | #define PHAN_PEG_RCV_INITIALIZED 0xff01 |
@@ -773,6 +774,8 @@ struct nx_host_tx_ring { | |||
773 | u32 crb_cmd_consumer; | 774 | u32 crb_cmd_consumer; |
774 | u32 num_desc; | 775 | u32 num_desc; |
775 | 776 | ||
777 | struct netdev_queue *txq; | ||
778 | |||
776 | struct netxen_cmd_buffer *cmd_buf_arr; | 779 | struct netxen_cmd_buffer *cmd_buf_arr; |
777 | struct cmd_desc_type0 *desc_head; | 780 | struct cmd_desc_type0 *desc_head; |
778 | dma_addr_t phys_addr; | 781 | dma_addr_t phys_addr; |
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index 4754f5cffad0..9f8ae4719e2f 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c | |||
@@ -684,10 +684,8 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) | |||
684 | goto err_out_free; | 684 | goto err_out_free; |
685 | } else { | 685 | } else { |
686 | err = netxen_init_old_ctx(adapter); | 686 | err = netxen_init_old_ctx(adapter); |
687 | if (err) { | 687 | if (err) |
688 | netxen_free_hw_resources(adapter); | 688 | goto err_out_free; |
689 | return err; | ||
690 | } | ||
691 | } | 689 | } |
692 | 690 | ||
693 | return 0; | 691 | return 0; |
@@ -708,15 +706,18 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) | |||
708 | int port = adapter->portnum; | 706 | int port = adapter->portnum; |
709 | 707 | ||
710 | if (adapter->fw_major >= 4) { | 708 | if (adapter->fw_major >= 4) { |
711 | nx_fw_cmd_destroy_tx_ctx(adapter); | ||
712 | nx_fw_cmd_destroy_rx_ctx(adapter); | 709 | nx_fw_cmd_destroy_rx_ctx(adapter); |
710 | nx_fw_cmd_destroy_tx_ctx(adapter); | ||
713 | } else { | 711 | } else { |
714 | netxen_api_lock(adapter); | 712 | netxen_api_lock(adapter); |
715 | NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port), | 713 | NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port), |
716 | NETXEN_CTX_RESET | port); | 714 | NETXEN_CTX_D3_RESET | port); |
717 | netxen_api_unlock(adapter); | 715 | netxen_api_unlock(adapter); |
718 | } | 716 | } |
719 | 717 | ||
718 | /* Allow dma queues to drain after context reset */ | ||
719 | msleep(20); | ||
720 | |||
720 | recv_ctx = &adapter->recv_ctx; | 721 | recv_ctx = &adapter->recv_ctx; |
721 | 722 | ||
722 | if (recv_ctx->hwctx != NULL) { | 723 | if (recv_ctx->hwctx != NULL) { |
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index ce3b89d2cbb6..b9123d445c96 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c | |||
@@ -461,13 +461,14 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter, | |||
461 | i = 0; | 461 | i = 0; |
462 | 462 | ||
463 | tx_ring = adapter->tx_ring; | 463 | tx_ring = adapter->tx_ring; |
464 | netif_tx_lock_bh(adapter->netdev); | 464 | __netif_tx_lock_bh(tx_ring->txq); |
465 | 465 | ||
466 | producer = tx_ring->producer; | 466 | producer = tx_ring->producer; |
467 | consumer = tx_ring->sw_consumer; | 467 | consumer = tx_ring->sw_consumer; |
468 | 468 | ||
469 | if (nr_desc >= find_diff_among(producer, consumer, tx_ring->num_desc)) { | 469 | if (nr_desc >= netxen_tx_avail(tx_ring)) { |
470 | netif_tx_unlock_bh(adapter->netdev); | 470 | netif_tx_stop_queue(tx_ring->txq); |
471 | __netif_tx_unlock_bh(tx_ring->txq); | ||
471 | return -EBUSY; | 472 | return -EBUSY; |
472 | } | 473 | } |
473 | 474 | ||
@@ -490,7 +491,7 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter, | |||
490 | 491 | ||
491 | netxen_nic_update_cmd_producer(adapter, tx_ring); | 492 | netxen_nic_update_cmd_producer(adapter, tx_ring); |
492 | 493 | ||
493 | netif_tx_unlock_bh(adapter->netdev); | 494 | __netif_tx_unlock_bh(tx_ring->txq); |
494 | 495 | ||
495 | return 0; | 496 | return 0; |
496 | } | 497 | } |
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index b899bd51fcd8..5d3343ef3d86 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c | |||
@@ -214,6 +214,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) | |||
214 | adapter->tx_ring = tx_ring; | 214 | adapter->tx_ring = tx_ring; |
215 | 215 | ||
216 | tx_ring->num_desc = adapter->num_txd; | 216 | tx_ring->num_desc = adapter->num_txd; |
217 | tx_ring->txq = netdev_get_tx_queue(netdev, 0); | ||
217 | 218 | ||
218 | cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring)); | 219 | cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring)); |
219 | if (cmd_buf_arr == NULL) { | 220 | if (cmd_buf_arr == NULL) { |
@@ -1400,10 +1401,10 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) | |||
1400 | smp_mb(); | 1401 | smp_mb(); |
1401 | 1402 | ||
1402 | if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { | 1403 | if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { |
1403 | netif_tx_lock(netdev); | 1404 | __netif_tx_lock(tx_ring->txq, smp_processor_id()); |
1404 | if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH) | 1405 | if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH) |
1405 | netif_wake_queue(netdev); | 1406 | netif_wake_queue(netdev); |
1406 | netif_tx_unlock(netdev); | 1407 | __netif_tx_unlock(tx_ring->txq); |
1407 | } | 1408 | } |
1408 | } | 1409 | } |
1409 | /* | 1410 | /* |
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 27539ddf94c4..637ac8b89bac 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c | |||
@@ -215,9 +215,9 @@ netxen_napi_disable(struct netxen_adapter *adapter) | |||
215 | 215 | ||
216 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | 216 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { |
217 | sds_ring = &recv_ctx->sds_rings[ring]; | 217 | sds_ring = &recv_ctx->sds_rings[ring]; |
218 | napi_disable(&sds_ring->napi); | ||
219 | netxen_nic_disable_int(sds_ring); | 218 | netxen_nic_disable_int(sds_ring); |
220 | synchronize_irq(sds_ring->irq); | 219 | napi_synchronize(&sds_ring->napi); |
220 | napi_disable(&sds_ring->napi); | ||
221 | } | 221 | } |
222 | } | 222 | } |
223 | 223 | ||
@@ -833,11 +833,11 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) | |||
833 | 833 | ||
834 | adapter->ahw.linkup = 0; | 834 | adapter->ahw.linkup = 0; |
835 | 835 | ||
836 | netxen_napi_enable(adapter); | ||
837 | |||
838 | if (adapter->max_sds_rings > 1) | 836 | if (adapter->max_sds_rings > 1) |
839 | netxen_config_rss(adapter, 1); | 837 | netxen_config_rss(adapter, 1); |
840 | 838 | ||
839 | netxen_napi_enable(adapter); | ||
840 | |||
841 | if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION) | 841 | if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION) |
842 | netxen_linkevent_request(adapter, 1); | 842 | netxen_linkevent_request(adapter, 1); |
843 | else | 843 | else |
@@ -851,8 +851,9 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) | |||
851 | static void | 851 | static void |
852 | netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) | 852 | netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) |
853 | { | 853 | { |
854 | spin_lock(&adapter->tx_clean_lock); | ||
854 | netif_carrier_off(netdev); | 855 | netif_carrier_off(netdev); |
855 | netif_stop_queue(netdev); | 856 | netif_tx_disable(netdev); |
856 | 857 | ||
857 | if (adapter->stop_port) | 858 | if (adapter->stop_port) |
858 | adapter->stop_port(adapter); | 859 | adapter->stop_port(adapter); |
@@ -863,9 +864,10 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) | |||
863 | netxen_napi_disable(adapter); | 864 | netxen_napi_disable(adapter); |
864 | 865 | ||
865 | netxen_release_tx_buffers(adapter); | 866 | netxen_release_tx_buffers(adapter); |
867 | spin_unlock(&adapter->tx_clean_lock); | ||
866 | 868 | ||
867 | FLUSH_SCHEDULED_WORK(); | ||
868 | del_timer_sync(&adapter->watchdog_timer); | 869 | del_timer_sync(&adapter->watchdog_timer); |
870 | FLUSH_SCHEDULED_WORK(); | ||
869 | } | 871 | } |
870 | 872 | ||
871 | 873 | ||
@@ -943,8 +945,8 @@ err_out_free_sw: | |||
943 | static void | 945 | static void |
944 | netxen_nic_detach(struct netxen_adapter *adapter) | 946 | netxen_nic_detach(struct netxen_adapter *adapter) |
945 | { | 947 | { |
946 | netxen_release_rx_buffers(adapter); | ||
947 | netxen_free_hw_resources(adapter); | 948 | netxen_free_hw_resources(adapter); |
949 | netxen_release_rx_buffers(adapter); | ||
948 | netxen_nic_free_irq(adapter); | 950 | netxen_nic_free_irq(adapter); |
949 | netxen_free_sw_resources(adapter); | 951 | netxen_free_sw_resources(adapter); |
950 | 952 | ||
@@ -1533,10 +1535,12 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter) | |||
1533 | printk(KERN_ALERT | 1535 | printk(KERN_ALERT |
1534 | "%s: Device temperature %d degrees C exceeds" | 1536 | "%s: Device temperature %d degrees C exceeds" |
1535 | " maximum allowed. Hardware has been shut down.\n", | 1537 | " maximum allowed. Hardware has been shut down.\n", |
1536 | netxen_nic_driver_name, temp_val); | 1538 | netdev->name, temp_val); |
1539 | |||
1540 | netif_device_detach(netdev); | ||
1541 | netxen_nic_down(adapter, netdev); | ||
1542 | netxen_nic_detach(adapter); | ||
1537 | 1543 | ||
1538 | netif_carrier_off(netdev); | ||
1539 | netif_stop_queue(netdev); | ||
1540 | rv = 1; | 1544 | rv = 1; |
1541 | } else if (temp_state == NX_TEMP_WARN) { | 1545 | } else if (temp_state == NX_TEMP_WARN) { |
1542 | if (adapter->temp == NX_TEMP_NORMAL) { | 1546 | if (adapter->temp == NX_TEMP_NORMAL) { |
@@ -1544,13 +1548,13 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter) | |||
1544 | "%s: Device temperature %d degrees C " | 1548 | "%s: Device temperature %d degrees C " |
1545 | "exceeds operating range." | 1549 | "exceeds operating range." |
1546 | " Immediate action needed.\n", | 1550 | " Immediate action needed.\n", |
1547 | netxen_nic_driver_name, temp_val); | 1551 | netdev->name, temp_val); |
1548 | } | 1552 | } |
1549 | } else { | 1553 | } else { |
1550 | if (adapter->temp == NX_TEMP_WARN) { | 1554 | if (adapter->temp == NX_TEMP_WARN) { |
1551 | printk(KERN_INFO | 1555 | printk(KERN_INFO |
1552 | "%s: Device temperature is now %d degrees C" | 1556 | "%s: Device temperature is now %d degrees C" |
1553 | " in normal range.\n", netxen_nic_driver_name, | 1557 | " in normal range.\n", netdev->name, |
1554 | temp_val); | 1558 | temp_val); |
1555 | } | 1559 | } |
1556 | } | 1560 | } |
@@ -1623,7 +1627,7 @@ void netxen_watchdog_task(struct work_struct *work) | |||
1623 | struct netxen_adapter *adapter = | 1627 | struct netxen_adapter *adapter = |
1624 | container_of(work, struct netxen_adapter, watchdog_task); | 1628 | container_of(work, struct netxen_adapter, watchdog_task); |
1625 | 1629 | ||
1626 | if ((adapter->portnum == 0) && netxen_nic_check_temp(adapter)) | 1630 | if (netxen_nic_check_temp(adapter)) |
1627 | return; | 1631 | return; |
1628 | 1632 | ||
1629 | if (!adapter->has_link_events) | 1633 | if (!adapter->has_link_events) |
@@ -1645,6 +1649,9 @@ static void netxen_tx_timeout_task(struct work_struct *work) | |||
1645 | struct netxen_adapter *adapter = | 1649 | struct netxen_adapter *adapter = |
1646 | container_of(work, struct netxen_adapter, tx_timeout_task); | 1650 | container_of(work, struct netxen_adapter, tx_timeout_task); |
1647 | 1651 | ||
1652 | if (!netif_running(adapter->netdev)) | ||
1653 | return; | ||
1654 | |||
1648 | printk(KERN_ERR "%s %s: transmit timeout, resetting.\n", | 1655 | printk(KERN_ERR "%s %s: transmit timeout, resetting.\n", |
1649 | netxen_nic_driver_name, adapter->netdev->name); | 1656 | netxen_nic_driver_name, adapter->netdev->name); |
1650 | 1657 | ||
@@ -1757,7 +1764,8 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget) | |||
1757 | 1764 | ||
1758 | if ((work_done < budget) && tx_complete) { | 1765 | if ((work_done < budget) && tx_complete) { |
1759 | napi_complete(&sds_ring->napi); | 1766 | napi_complete(&sds_ring->napi); |
1760 | netxen_nic_enable_int(sds_ring); | 1767 | if (netif_running(adapter->netdev)) |
1768 | netxen_nic_enable_int(sds_ring); | ||
1761 | } | 1769 | } |
1762 | 1770 | ||
1763 | return work_done; | 1771 | return work_done; |
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index ec7cf5ac4f05..690b9c76d34e 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c | |||
@@ -156,6 +156,7 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev); | |||
156 | static int el3_rx(struct net_device *dev); | 156 | static int el3_rx(struct net_device *dev); |
157 | static int el3_close(struct net_device *dev); | 157 | static int el3_close(struct net_device *dev); |
158 | static void el3_tx_timeout(struct net_device *dev); | 158 | static void el3_tx_timeout(struct net_device *dev); |
159 | static void set_rx_mode(struct net_device *dev); | ||
159 | static void set_multicast_list(struct net_device *dev); | 160 | static void set_multicast_list(struct net_device *dev); |
160 | static const struct ethtool_ops netdev_ethtool_ops; | 161 | static const struct ethtool_ops netdev_ethtool_ops; |
161 | 162 | ||
@@ -488,8 +489,7 @@ static void tc589_reset(struct net_device *dev) | |||
488 | /* Switch to register set 1 for normal use. */ | 489 | /* Switch to register set 1 for normal use. */ |
489 | EL3WINDOW(1); | 490 | EL3WINDOW(1); |
490 | 491 | ||
491 | /* Accept b-cast and phys addr only. */ | 492 | set_rx_mode(dev); |
492 | outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD); | ||
493 | outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ | 493 | outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ |
494 | outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ | 494 | outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ |
495 | outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ | 495 | outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ |
@@ -700,7 +700,7 @@ static irqreturn_t el3_interrupt(int irq, void *dev_id) | |||
700 | if (fifo_diag & 0x2000) { | 700 | if (fifo_diag & 0x2000) { |
701 | /* Rx underrun */ | 701 | /* Rx underrun */ |
702 | tc589_wait_for_completion(dev, RxReset); | 702 | tc589_wait_for_completion(dev, RxReset); |
703 | set_multicast_list(dev); | 703 | set_rx_mode(dev); |
704 | outw(RxEnable, ioaddr + EL3_CMD); | 704 | outw(RxEnable, ioaddr + EL3_CMD); |
705 | } | 705 | } |
706 | outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD); | 706 | outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD); |
@@ -905,14 +905,11 @@ static int el3_rx(struct net_device *dev) | |||
905 | return 0; | 905 | return 0; |
906 | } | 906 | } |
907 | 907 | ||
908 | static void set_multicast_list(struct net_device *dev) | 908 | static void set_rx_mode(struct net_device *dev) |
909 | { | 909 | { |
910 | struct el3_private *lp = netdev_priv(dev); | ||
911 | struct pcmcia_device *link = lp->p_dev; | ||
912 | unsigned int ioaddr = dev->base_addr; | 910 | unsigned int ioaddr = dev->base_addr; |
913 | u16 opts = SetRxFilter | RxStation | RxBroadcast; | 911 | u16 opts = SetRxFilter | RxStation | RxBroadcast; |
914 | 912 | ||
915 | if (!pcmcia_dev_present(link)) return; | ||
916 | if (dev->flags & IFF_PROMISC) | 913 | if (dev->flags & IFF_PROMISC) |
917 | opts |= RxMulticast | RxProm; | 914 | opts |= RxMulticast | RxProm; |
918 | else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) | 915 | else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) |
@@ -920,6 +917,16 @@ static void set_multicast_list(struct net_device *dev) | |||
920 | outw(opts, ioaddr + EL3_CMD); | 917 | outw(opts, ioaddr + EL3_CMD); |
921 | } | 918 | } |
922 | 919 | ||
920 | static void set_multicast_list(struct net_device *dev) | ||
921 | { | ||
922 | struct el3_private *priv = netdev_priv(dev); | ||
923 | unsigned long flags; | ||
924 | |||
925 | spin_lock_irqsave(&priv->lock, flags); | ||
926 | set_rx_mode(dev); | ||
927 | spin_unlock_irqrestore(&priv->lock, flags); | ||
928 | } | ||
929 | |||
923 | static int el3_close(struct net_device *dev) | 930 | static int el3_close(struct net_device *dev) |
924 | { | 931 | { |
925 | struct el3_private *lp = netdev_priv(dev); | 932 | struct el3_private *lp = netdev_priv(dev); |
diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index 18821f217e19..e3156c97bb58 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c | |||
@@ -1593,6 +1593,7 @@ out: | |||
1593 | static struct pci_device_id sc92031_pci_device_id_table[] __devinitdata = { | 1593 | static struct pci_device_id sc92031_pci_device_id_table[] __devinitdata = { |
1594 | { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x2031) }, | 1594 | { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x2031) }, |
1595 | { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x8139) }, | 1595 | { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x8139) }, |
1596 | { PCI_DEVICE(0x1088, 0x2031) }, | ||
1596 | { 0, } | 1597 | { 0, } |
1597 | }; | 1598 | }; |
1598 | MODULE_DEVICE_TABLE(pci, sc92031_pci_device_id_table); | 1599 | MODULE_DEVICE_TABLE(pci, sc92031_pci_device_id_table); |
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index daf961ab68bc..3550c5dcd93c 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -1151,14 +1151,7 @@ stopped: | |||
1151 | 1151 | ||
1152 | /* reset the Rx prefetch unit */ | 1152 | /* reset the Rx prefetch unit */ |
1153 | sky2_write32(hw, Y2_QADDR(rxq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); | 1153 | sky2_write32(hw, Y2_QADDR(rxq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); |
1154 | 1154 | mmiowb(); | |
1155 | /* Reset the RAM Buffer receive queue */ | ||
1156 | sky2_write8(hw, RB_ADDR(rxq, RB_CTRL), RB_RST_SET); | ||
1157 | |||
1158 | /* Reset Rx MAC FIFO */ | ||
1159 | sky2_write8(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), GMF_RST_SET); | ||
1160 | |||
1161 | sky2_read8(hw, B0_CTST); | ||
1162 | } | 1155 | } |
1163 | 1156 | ||
1164 | /* Clean out receive buffer area, assumes receiver hardware stopped */ | 1157 | /* Clean out receive buffer area, assumes receiver hardware stopped */ |
@@ -1825,12 +1818,6 @@ static int sky2_down(struct net_device *dev) | |||
1825 | if (netif_msg_ifdown(sky2)) | 1818 | if (netif_msg_ifdown(sky2)) |
1826 | printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); | 1819 | printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); |
1827 | 1820 | ||
1828 | /* Disable port IRQ */ | ||
1829 | imask = sky2_read32(hw, B0_IMSK); | ||
1830 | imask &= ~portirq_msk[port]; | ||
1831 | sky2_write32(hw, B0_IMSK, imask); | ||
1832 | sky2_read32(hw, B0_IMSK); | ||
1833 | |||
1834 | /* Force flow control off */ | 1821 | /* Force flow control off */ |
1835 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); | 1822 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); |
1836 | 1823 | ||
@@ -1870,8 +1857,6 @@ static int sky2_down(struct net_device *dev) | |||
1870 | 1857 | ||
1871 | sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET); | 1858 | sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET); |
1872 | 1859 | ||
1873 | sky2_rx_stop(sky2); | ||
1874 | |||
1875 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); | 1860 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); |
1876 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); | 1861 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); |
1877 | 1862 | ||
@@ -1881,6 +1866,14 @@ static int sky2_down(struct net_device *dev) | |||
1881 | sky2_write32(hw, STAT_ISR_TIMER_CNT, 0); | 1866 | sky2_write32(hw, STAT_ISR_TIMER_CNT, 0); |
1882 | sky2_read8(hw, STAT_ISR_TIMER_CTRL); | 1867 | sky2_read8(hw, STAT_ISR_TIMER_CTRL); |
1883 | 1868 | ||
1869 | sky2_rx_stop(sky2); | ||
1870 | |||
1871 | /* Disable port IRQ */ | ||
1872 | imask = sky2_read32(hw, B0_IMSK); | ||
1873 | imask &= ~portirq_msk[port]; | ||
1874 | sky2_write32(hw, B0_IMSK, imask); | ||
1875 | sky2_read32(hw, B0_IMSK); | ||
1876 | |||
1884 | synchronize_irq(hw->pdev->irq); | 1877 | synchronize_irq(hw->pdev->irq); |
1885 | napi_synchronize(&hw->napi); | 1878 | napi_synchronize(&hw->napi); |
1886 | 1879 | ||
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index a906d3998131..c47237c2d638 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig | |||
@@ -369,4 +369,12 @@ config USB_NET_INT51X1 | |||
369 | (Powerline Communications) solution with an Intellon | 369 | (Powerline Communications) solution with an Intellon |
370 | INT51x1/INT5200 chip, like the "devolo dLan duo". | 370 | INT51x1/INT5200 chip, like the "devolo dLan duo". |
371 | 371 | ||
372 | config USB_CDC_PHONET | ||
373 | tristate "CDC Phonet support" | ||
374 | depends on PHONET | ||
375 | help | ||
376 | Choose this option to support the Phonet interface to a Nokia | ||
377 | cellular modem, as found on most Nokia handsets with the | ||
378 | "PC suite" USB profile. | ||
379 | |||
372 | endmenu | 380 | endmenu |
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index b870b0b1cbe0..e17afb78f372 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile | |||
@@ -21,4 +21,5 @@ obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o | |||
21 | obj-$(CONFIG_USB_NET_MCS7830) += mcs7830.o | 21 | obj-$(CONFIG_USB_NET_MCS7830) += mcs7830.o |
22 | obj-$(CONFIG_USB_USBNET) += usbnet.o | 22 | obj-$(CONFIG_USB_USBNET) += usbnet.o |
23 | obj-$(CONFIG_USB_NET_INT51X1) += int51x1.o | 23 | obj-$(CONFIG_USB_NET_INT51X1) += int51x1.o |
24 | obj-$(CONFIG_USB_CDC_PHONET) += cdc-phonet.o | ||
24 | 25 | ||
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c new file mode 100644 index 000000000000..792af72da8ac --- /dev/null +++ b/drivers/net/usb/cdc-phonet.c | |||
@@ -0,0 +1,461 @@ | |||
1 | /* | ||
2 | * phonet.c -- USB CDC Phonet host driver | ||
3 | * | ||
4 | * Copyright (C) 2008-2009 Nokia Corporation. All rights reserved. | ||
5 | * | ||
6 | * Author: Rémi Denis-Courmont | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Â See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/usb.h> | ||
26 | #include <linux/usb/cdc.h> | ||
27 | #include <linux/netdevice.h> | ||
28 | #include <linux/if_arp.h> | ||
29 | #include <linux/if_phonet.h> | ||
30 | |||
31 | #define PN_MEDIA_USB 0x1B | ||
32 | |||
33 | static const unsigned rxq_size = 17; | ||
34 | |||
35 | struct usbpn_dev { | ||
36 | struct net_device *dev; | ||
37 | |||
38 | struct usb_interface *intf, *data_intf; | ||
39 | struct usb_device *usb; | ||
40 | unsigned int tx_pipe, rx_pipe; | ||
41 | u8 active_setting; | ||
42 | u8 disconnected; | ||
43 | |||
44 | unsigned tx_queue; | ||
45 | spinlock_t tx_lock; | ||
46 | |||
47 | spinlock_t rx_lock; | ||
48 | struct sk_buff *rx_skb; | ||
49 | struct urb *urbs[0]; | ||
50 | }; | ||
51 | |||
52 | static void tx_complete(struct urb *req); | ||
53 | static void rx_complete(struct urb *req); | ||
54 | |||
55 | /* | ||
56 | * Network device callbacks | ||
57 | */ | ||
58 | static int usbpn_xmit(struct sk_buff *skb, struct net_device *dev) | ||
59 | { | ||
60 | struct usbpn_dev *pnd = netdev_priv(dev); | ||
61 | struct urb *req = NULL; | ||
62 | unsigned long flags; | ||
63 | int err; | ||
64 | |||
65 | if (skb->protocol != htons(ETH_P_PHONET)) | ||
66 | goto drop; | ||
67 | |||
68 | req = usb_alloc_urb(0, GFP_ATOMIC); | ||
69 | if (!req) | ||
70 | goto drop; | ||
71 | usb_fill_bulk_urb(req, pnd->usb, pnd->tx_pipe, skb->data, skb->len, | ||
72 | tx_complete, skb); | ||
73 | req->transfer_flags = URB_ZERO_PACKET; | ||
74 | err = usb_submit_urb(req, GFP_ATOMIC); | ||
75 | if (err) { | ||
76 | usb_free_urb(req); | ||
77 | goto drop; | ||
78 | } | ||
79 | |||
80 | spin_lock_irqsave(&pnd->tx_lock, flags); | ||
81 | pnd->tx_queue++; | ||
82 | if (pnd->tx_queue >= dev->tx_queue_len) | ||
83 | netif_stop_queue(dev); | ||
84 | spin_unlock_irqrestore(&pnd->tx_lock, flags); | ||
85 | return 0; | ||
86 | |||
87 | drop: | ||
88 | dev_kfree_skb(skb); | ||
89 | dev->stats.tx_dropped++; | ||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | static void tx_complete(struct urb *req) | ||
94 | { | ||
95 | struct sk_buff *skb = req->context; | ||
96 | struct net_device *dev = skb->dev; | ||
97 | struct usbpn_dev *pnd = netdev_priv(dev); | ||
98 | |||
99 | switch (req->status) { | ||
100 | case 0: | ||
101 | dev->stats.tx_bytes += skb->len; | ||
102 | break; | ||
103 | |||
104 | case -ENOENT: | ||
105 | case -ECONNRESET: | ||
106 | case -ESHUTDOWN: | ||
107 | dev->stats.tx_aborted_errors++; | ||
108 | default: | ||
109 | dev->stats.tx_errors++; | ||
110 | dev_dbg(&dev->dev, "TX error (%d)\n", req->status); | ||
111 | } | ||
112 | dev->stats.tx_packets++; | ||
113 | |||
114 | spin_lock(&pnd->tx_lock); | ||
115 | pnd->tx_queue--; | ||
116 | netif_wake_queue(dev); | ||
117 | spin_unlock(&pnd->tx_lock); | ||
118 | |||
119 | dev_kfree_skb_any(skb); | ||
120 | usb_free_urb(req); | ||
121 | } | ||
122 | |||
123 | static int rx_submit(struct usbpn_dev *pnd, struct urb *req, gfp_t gfp_flags) | ||
124 | { | ||
125 | struct net_device *dev = pnd->dev; | ||
126 | struct page *page; | ||
127 | int err; | ||
128 | |||
129 | page = __netdev_alloc_page(dev, gfp_flags); | ||
130 | if (!page) | ||
131 | return -ENOMEM; | ||
132 | |||
133 | usb_fill_bulk_urb(req, pnd->usb, pnd->rx_pipe, page_address(page), | ||
134 | PAGE_SIZE, rx_complete, dev); | ||
135 | req->transfer_flags = 0; | ||
136 | err = usb_submit_urb(req, gfp_flags); | ||
137 | if (unlikely(err)) { | ||
138 | dev_dbg(&dev->dev, "RX submit error (%d)\n", err); | ||
139 | netdev_free_page(dev, page); | ||
140 | } | ||
141 | return err; | ||
142 | } | ||
143 | |||
144 | static void rx_complete(struct urb *req) | ||
145 | { | ||
146 | struct net_device *dev = req->context; | ||
147 | struct usbpn_dev *pnd = netdev_priv(dev); | ||
148 | struct page *page = virt_to_page(req->transfer_buffer); | ||
149 | struct sk_buff *skb; | ||
150 | unsigned long flags; | ||
151 | |||
152 | switch (req->status) { | ||
153 | case 0: | ||
154 | spin_lock_irqsave(&pnd->rx_lock, flags); | ||
155 | skb = pnd->rx_skb; | ||
156 | if (!skb) { | ||
157 | skb = pnd->rx_skb = netdev_alloc_skb(dev, 12); | ||
158 | if (likely(skb)) { | ||
159 | /* Can't use pskb_pull() on page in IRQ */ | ||
160 | memcpy(skb_put(skb, 1), page_address(page), 1); | ||
161 | skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, | ||
162 | page, 1, req->actual_length); | ||
163 | page = NULL; | ||
164 | } | ||
165 | } else { | ||
166 | skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, | ||
167 | page, 0, req->actual_length); | ||
168 | page = NULL; | ||
169 | } | ||
170 | if (req->actual_length < PAGE_SIZE) | ||
171 | pnd->rx_skb = NULL; /* Last fragment */ | ||
172 | else | ||
173 | skb = NULL; | ||
174 | spin_unlock_irqrestore(&pnd->rx_lock, flags); | ||
175 | if (skb) { | ||
176 | skb->protocol = htons(ETH_P_PHONET); | ||
177 | skb_reset_mac_header(skb); | ||
178 | __skb_pull(skb, 1); | ||
179 | skb->dev = dev; | ||
180 | dev->stats.rx_packets++; | ||
181 | dev->stats.rx_bytes += skb->len; | ||
182 | |||
183 | netif_rx(skb); | ||
184 | } | ||
185 | goto resubmit; | ||
186 | |||
187 | case -ENOENT: | ||
188 | case -ECONNRESET: | ||
189 | case -ESHUTDOWN: | ||
190 | req = NULL; | ||
191 | break; | ||
192 | |||
193 | case -EOVERFLOW: | ||
194 | dev->stats.rx_over_errors++; | ||
195 | dev_dbg(&dev->dev, "RX overflow\n"); | ||
196 | break; | ||
197 | |||
198 | case -EILSEQ: | ||
199 | dev->stats.rx_crc_errors++; | ||
200 | break; | ||
201 | } | ||
202 | |||
203 | dev->stats.rx_errors++; | ||
204 | resubmit: | ||
205 | if (page) | ||
206 | netdev_free_page(dev, page); | ||
207 | if (req) | ||
208 | rx_submit(pnd, req, GFP_ATOMIC); | ||
209 | } | ||
210 | |||
211 | static int usbpn_close(struct net_device *dev); | ||
212 | |||
213 | static int usbpn_open(struct net_device *dev) | ||
214 | { | ||
215 | struct usbpn_dev *pnd = netdev_priv(dev); | ||
216 | int err; | ||
217 | unsigned i; | ||
218 | unsigned num = pnd->data_intf->cur_altsetting->desc.bInterfaceNumber; | ||
219 | |||
220 | err = usb_set_interface(pnd->usb, num, pnd->active_setting); | ||
221 | if (err) | ||
222 | return err; | ||
223 | |||
224 | for (i = 0; i < rxq_size; i++) { | ||
225 | struct urb *req = usb_alloc_urb(0, GFP_KERNEL); | ||
226 | |||
227 | if (!req || rx_submit(pnd, req, GFP_KERNEL)) { | ||
228 | usbpn_close(dev); | ||
229 | return -ENOMEM; | ||
230 | } | ||
231 | pnd->urbs[i] = req; | ||
232 | } | ||
233 | |||
234 | netif_wake_queue(dev); | ||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | static int usbpn_close(struct net_device *dev) | ||
239 | { | ||
240 | struct usbpn_dev *pnd = netdev_priv(dev); | ||
241 | unsigned i; | ||
242 | unsigned num = pnd->data_intf->cur_altsetting->desc.bInterfaceNumber; | ||
243 | |||
244 | netif_stop_queue(dev); | ||
245 | |||
246 | for (i = 0; i < rxq_size; i++) { | ||
247 | struct urb *req = pnd->urbs[i]; | ||
248 | |||
249 | if (!req) | ||
250 | continue; | ||
251 | usb_kill_urb(req); | ||
252 | usb_free_urb(req); | ||
253 | pnd->urbs[i] = NULL; | ||
254 | } | ||
255 | |||
256 | return usb_set_interface(pnd->usb, num, !pnd->active_setting); | ||
257 | } | ||
258 | |||
259 | static int usbpn_set_mtu(struct net_device *dev, int new_mtu) | ||
260 | { | ||
261 | if ((new_mtu < PHONET_MIN_MTU) || (new_mtu > PHONET_MAX_MTU)) | ||
262 | return -EINVAL; | ||
263 | |||
264 | dev->mtu = new_mtu; | ||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | static const struct net_device_ops usbpn_ops = { | ||
269 | .ndo_open = usbpn_open, | ||
270 | .ndo_stop = usbpn_close, | ||
271 | .ndo_start_xmit = usbpn_xmit, | ||
272 | .ndo_change_mtu = usbpn_set_mtu, | ||
273 | }; | ||
274 | |||
275 | static void usbpn_setup(struct net_device *dev) | ||
276 | { | ||
277 | dev->features = 0; | ||
278 | dev->netdev_ops = &usbpn_ops, | ||
279 | dev->header_ops = &phonet_header_ops; | ||
280 | dev->type = ARPHRD_PHONET; | ||
281 | dev->flags = IFF_POINTOPOINT | IFF_NOARP; | ||
282 | dev->mtu = PHONET_MAX_MTU; | ||
283 | dev->hard_header_len = 1; | ||
284 | dev->dev_addr[0] = PN_MEDIA_USB; | ||
285 | dev->addr_len = 1; | ||
286 | dev->tx_queue_len = 3; | ||
287 | |||
288 | dev->destructor = free_netdev; | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * USB driver callbacks | ||
293 | */ | ||
294 | static struct usb_device_id usbpn_ids[] = { | ||
295 | { | ||
296 | .match_flags = USB_DEVICE_ID_MATCH_VENDOR | ||
297 | | USB_DEVICE_ID_MATCH_INT_CLASS | ||
298 | | USB_DEVICE_ID_MATCH_INT_SUBCLASS, | ||
299 | .idVendor = 0x0421, /* Nokia */ | ||
300 | .bInterfaceClass = USB_CLASS_COMM, | ||
301 | .bInterfaceSubClass = 0xFE, | ||
302 | }, | ||
303 | { }, | ||
304 | }; | ||
305 | |||
306 | MODULE_DEVICE_TABLE(usb, usbpn_ids); | ||
307 | |||
308 | static struct usb_driver usbpn_driver; | ||
309 | |||
310 | int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
311 | { | ||
312 | static const char ifname[] = "usbpn%d"; | ||
313 | const struct usb_cdc_union_desc *union_header = NULL; | ||
314 | const struct usb_cdc_header_desc *phonet_header = NULL; | ||
315 | const struct usb_host_interface *data_desc; | ||
316 | struct usb_interface *data_intf; | ||
317 | struct usb_device *usbdev = interface_to_usbdev(intf); | ||
318 | struct net_device *dev; | ||
319 | struct usbpn_dev *pnd; | ||
320 | u8 *data; | ||
321 | int len, err; | ||
322 | |||
323 | data = intf->altsetting->extra; | ||
324 | len = intf->altsetting->extralen; | ||
325 | while (len >= 3) { | ||
326 | u8 dlen = data[0]; | ||
327 | if (dlen < 3) | ||
328 | return -EINVAL; | ||
329 | |||
330 | /* bDescriptorType */ | ||
331 | if (data[1] == USB_DT_CS_INTERFACE) { | ||
332 | /* bDescriptorSubType */ | ||
333 | switch (data[2]) { | ||
334 | case USB_CDC_UNION_TYPE: | ||
335 | if (union_header || dlen < 5) | ||
336 | break; | ||
337 | union_header = | ||
338 | (struct usb_cdc_union_desc *)data; | ||
339 | break; | ||
340 | case 0xAB: | ||
341 | if (phonet_header || dlen < 5) | ||
342 | break; | ||
343 | phonet_header = | ||
344 | (struct usb_cdc_header_desc *)data; | ||
345 | break; | ||
346 | } | ||
347 | } | ||
348 | data += dlen; | ||
349 | len -= dlen; | ||
350 | } | ||
351 | |||
352 | if (!union_header || !phonet_header) | ||
353 | return -EINVAL; | ||
354 | |||
355 | data_intf = usb_ifnum_to_if(usbdev, union_header->bSlaveInterface0); | ||
356 | if (data_intf == NULL) | ||
357 | return -ENODEV; | ||
358 | /* Data interface has one inactive and one active setting */ | ||
359 | if (data_intf->num_altsetting != 2) | ||
360 | return -EINVAL; | ||
361 | if (data_intf->altsetting[0].desc.bNumEndpoints == 0 | ||
362 | && data_intf->altsetting[1].desc.bNumEndpoints == 2) | ||
363 | data_desc = data_intf->altsetting + 1; | ||
364 | else | ||
365 | if (data_intf->altsetting[0].desc.bNumEndpoints == 2 | ||
366 | && data_intf->altsetting[1].desc.bNumEndpoints == 0) | ||
367 | data_desc = data_intf->altsetting; | ||
368 | else | ||
369 | return -EINVAL; | ||
370 | |||
371 | dev = alloc_netdev(sizeof(*pnd) + sizeof(pnd->urbs[0]) * rxq_size, | ||
372 | ifname, usbpn_setup); | ||
373 | if (!dev) | ||
374 | return -ENOMEM; | ||
375 | |||
376 | pnd = netdev_priv(dev); | ||
377 | SET_NETDEV_DEV(dev, &intf->dev); | ||
378 | netif_stop_queue(dev); | ||
379 | |||
380 | pnd->dev = dev; | ||
381 | pnd->usb = usb_get_dev(usbdev); | ||
382 | pnd->intf = intf; | ||
383 | pnd->data_intf = data_intf; | ||
384 | spin_lock_init(&pnd->tx_lock); | ||
385 | spin_lock_init(&pnd->rx_lock); | ||
386 | /* Endpoints */ | ||
387 | if (usb_pipein(data_desc->endpoint[0].desc.bEndpointAddress)) { | ||
388 | pnd->rx_pipe = usb_rcvbulkpipe(usbdev, | ||
389 | data_desc->endpoint[0].desc.bEndpointAddress); | ||
390 | pnd->tx_pipe = usb_sndbulkpipe(usbdev, | ||
391 | data_desc->endpoint[1].desc.bEndpointAddress); | ||
392 | } else { | ||
393 | pnd->rx_pipe = usb_rcvbulkpipe(usbdev, | ||
394 | data_desc->endpoint[1].desc.bEndpointAddress); | ||
395 | pnd->tx_pipe = usb_sndbulkpipe(usbdev, | ||
396 | data_desc->endpoint[0].desc.bEndpointAddress); | ||
397 | } | ||
398 | pnd->active_setting = data_desc - data_intf->altsetting; | ||
399 | |||
400 | err = usb_driver_claim_interface(&usbpn_driver, data_intf, pnd); | ||
401 | if (err) | ||
402 | goto out; | ||
403 | |||
404 | /* Force inactive mode until the network device is brought UP */ | ||
405 | usb_set_interface(usbdev, union_header->bSlaveInterface0, | ||
406 | !pnd->active_setting); | ||
407 | usb_set_intfdata(intf, pnd); | ||
408 | |||
409 | err = register_netdev(dev); | ||
410 | if (err) { | ||
411 | usb_driver_release_interface(&usbpn_driver, data_intf); | ||
412 | goto out; | ||
413 | } | ||
414 | |||
415 | dev_dbg(&dev->dev, "USB CDC Phonet device found\n"); | ||
416 | return 0; | ||
417 | |||
418 | out: | ||
419 | usb_set_intfdata(intf, NULL); | ||
420 | free_netdev(dev); | ||
421 | return err; | ||
422 | } | ||
423 | |||
424 | static void usbpn_disconnect(struct usb_interface *intf) | ||
425 | { | ||
426 | struct usbpn_dev *pnd = usb_get_intfdata(intf); | ||
427 | struct usb_device *usb = pnd->usb; | ||
428 | |||
429 | if (pnd->disconnected) | ||
430 | return; | ||
431 | |||
432 | pnd->disconnected = 1; | ||
433 | usb_driver_release_interface(&usbpn_driver, | ||
434 | (pnd->intf == intf) ? pnd->data_intf : pnd->intf); | ||
435 | unregister_netdev(pnd->dev); | ||
436 | usb_put_dev(usb); | ||
437 | } | ||
438 | |||
439 | static struct usb_driver usbpn_driver = { | ||
440 | .name = "cdc_phonet", | ||
441 | .probe = usbpn_probe, | ||
442 | .disconnect = usbpn_disconnect, | ||
443 | .id_table = usbpn_ids, | ||
444 | }; | ||
445 | |||
446 | static int __init usbpn_init(void) | ||
447 | { | ||
448 | return usb_register(&usbpn_driver); | ||
449 | } | ||
450 | |||
451 | static void __exit usbpn_exit(void) | ||
452 | { | ||
453 | usb_deregister(&usbpn_driver); | ||
454 | } | ||
455 | |||
456 | module_init(usbpn_init); | ||
457 | module_exit(usbpn_exit); | ||
458 | |||
459 | MODULE_AUTHOR("Remi Denis-Courmont"); | ||
460 | MODULE_DESCRIPTION("USB CDC Phonet host interface"); | ||
461 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c index cd35d50e46d4..45cebfb302cf 100644 --- a/drivers/net/usb/cdc_eem.c +++ b/drivers/net/usb/cdc_eem.c | |||
@@ -311,7 +311,7 @@ static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
311 | * bmCRC = 0 : CRC = 0xDEADBEEF | 311 | * bmCRC = 0 : CRC = 0xDEADBEEF |
312 | */ | 312 | */ |
313 | if (header & BIT(14)) | 313 | if (header & BIT(14)) |
314 | crc2 = ~crc32_le(~0, skb2->data, len); | 314 | crc2 = ~crc32_le(~0, skb2->data, skb2->len); |
315 | else | 315 | else |
316 | crc2 = 0xdeadbeef; | 316 | crc2 = 0xdeadbeef; |
317 | 317 | ||
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index 5c1a2c01778f..9ae9cd32bd06 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c | |||
@@ -256,8 +256,8 @@ static void fix_edid(unsigned char *edid, int fix) | |||
256 | 256 | ||
257 | static int edid_checksum(unsigned char *edid) | 257 | static int edid_checksum(unsigned char *edid) |
258 | { | 258 | { |
259 | unsigned char i, csum = 0, all_null = 0; | 259 | unsigned char csum = 0, all_null = 0; |
260 | int err = 0, fix = check_edid(edid); | 260 | int i, err = 0, fix = check_edid(edid); |
261 | 261 | ||
262 | if (fix) | 262 | if (fix) |
263 | fix_edid(edid, fix); | 263 | fix_edid(edid, fix); |
diff --git a/fs/Kconfig b/fs/Kconfig index a97263be6a91..0e7da7bb5d93 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -186,32 +186,7 @@ source "fs/romfs/Kconfig" | |||
186 | source "fs/sysv/Kconfig" | 186 | source "fs/sysv/Kconfig" |
187 | source "fs/ufs/Kconfig" | 187 | source "fs/ufs/Kconfig" |
188 | source "fs/exofs/Kconfig" | 188 | source "fs/exofs/Kconfig" |
189 | 189 | source "fs/nilfs2/Kconfig" | |
190 | config NILFS2_FS | ||
191 | tristate "NILFS2 file system support (EXPERIMENTAL)" | ||
192 | depends on BLOCK && EXPERIMENTAL | ||
193 | select CRC32 | ||
194 | help | ||
195 | NILFS2 is a log-structured file system (LFS) supporting continuous | ||
196 | snapshotting. In addition to versioning capability of the entire | ||
197 | file system, users can even restore files mistakenly overwritten or | ||
198 | destroyed just a few seconds ago. Since this file system can keep | ||
199 | consistency like conventional LFS, it achieves quick recovery after | ||
200 | system crashes. | ||
201 | |||
202 | NILFS2 creates a number of checkpoints every few seconds or per | ||
203 | synchronous write basis (unless there is no change). Users can | ||
204 | select significant versions among continuously created checkpoints, | ||
205 | and can change them into snapshots which will be preserved for long | ||
206 | periods until they are changed back to checkpoints. Each | ||
207 | snapshot is mountable as a read-only file system concurrently with | ||
208 | its writable mount, and this feature is convenient for online backup. | ||
209 | |||
210 | Some features including atime, extended attributes, and POSIX ACLs, | ||
211 | are not supported yet. | ||
212 | |||
213 | To compile this file system support as a module, choose M here: the | ||
214 | module will be called nilfs2. If unsure, say N. | ||
215 | 190 | ||
216 | endif # MISC_FILESYSTEMS | 191 | endif # MISC_FILESYSTEMS |
217 | 192 | ||
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index c2d061675d80..8d25ccb2d51d 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -1242,20 +1242,6 @@ error: | |||
1242 | return error; | 1242 | return error; |
1243 | } | 1243 | } |
1244 | 1244 | ||
1245 | /* | ||
1246 | * Initialize a session. | ||
1247 | * Note: save the mount rsize and wsize for create_server negotiation. | ||
1248 | */ | ||
1249 | static void nfs4_init_session(struct nfs_client *clp, | ||
1250 | unsigned int wsize, unsigned int rsize) | ||
1251 | { | ||
1252 | #if defined(CONFIG_NFS_V4_1) | ||
1253 | if (nfs4_has_session(clp)) { | ||
1254 | clp->cl_session->fc_attrs.max_rqst_sz = wsize; | ||
1255 | clp->cl_session->fc_attrs.max_resp_sz = rsize; | ||
1256 | } | ||
1257 | #endif /* CONFIG_NFS_V4_1 */ | ||
1258 | } | ||
1259 | 1245 | ||
1260 | /* | 1246 | /* |
1261 | * Session has been established, and the client marked ready. | 1247 | * Session has been established, and the client marked ready. |
@@ -1350,7 +1336,9 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, | |||
1350 | BUG_ON(!server->nfs_client->rpc_ops); | 1336 | BUG_ON(!server->nfs_client->rpc_ops); |
1351 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | 1337 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); |
1352 | 1338 | ||
1353 | nfs4_init_session(server->nfs_client, server->wsize, server->rsize); | 1339 | error = nfs4_init_session(server); |
1340 | if (error < 0) | ||
1341 | goto error; | ||
1354 | 1342 | ||
1355 | /* Probe the root fh to retrieve its FSID */ | 1343 | /* Probe the root fh to retrieve its FSID */ |
1356 | error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path); | 1344 | error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path); |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 38d42c29fb92..32062c33c859 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -1025,12 +1025,12 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
1025 | res = NULL; | 1025 | res = NULL; |
1026 | goto out; | 1026 | goto out; |
1027 | /* This turned out not to be a regular file */ | 1027 | /* This turned out not to be a regular file */ |
1028 | case -EISDIR: | ||
1029 | case -ENOTDIR: | 1028 | case -ENOTDIR: |
1030 | goto no_open; | 1029 | goto no_open; |
1031 | case -ELOOP: | 1030 | case -ELOOP: |
1032 | if (!(nd->intent.open.flags & O_NOFOLLOW)) | 1031 | if (!(nd->intent.open.flags & O_NOFOLLOW)) |
1033 | goto no_open; | 1032 | goto no_open; |
1033 | /* case -EISDIR: */ | ||
1034 | /* case -EINVAL: */ | 1034 | /* case -EINVAL: */ |
1035 | default: | 1035 | default: |
1036 | goto out; | 1036 | goto out; |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 61bc3a32e1e2..6ea07a3c75d4 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -220,6 +220,7 @@ extern void nfs4_destroy_session(struct nfs4_session *session); | |||
220 | extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp); | 220 | extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp); |
221 | extern int nfs4_proc_create_session(struct nfs_client *, int reset); | 221 | extern int nfs4_proc_create_session(struct nfs_client *, int reset); |
222 | extern int nfs4_proc_destroy_session(struct nfs4_session *); | 222 | extern int nfs4_proc_destroy_session(struct nfs4_session *); |
223 | extern int nfs4_init_session(struct nfs_server *server); | ||
223 | #else /* CONFIG_NFS_v4_1 */ | 224 | #else /* CONFIG_NFS_v4_1 */ |
224 | static inline int nfs4_setup_sequence(struct nfs_client *clp, | 225 | static inline int nfs4_setup_sequence(struct nfs_client *clp, |
225 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, | 226 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, |
@@ -227,6 +228,11 @@ static inline int nfs4_setup_sequence(struct nfs_client *clp, | |||
227 | { | 228 | { |
228 | return 0; | 229 | return 0; |
229 | } | 230 | } |
231 | |||
232 | static inline int nfs4_init_session(struct nfs_server *server) | ||
233 | { | ||
234 | return 0; | ||
235 | } | ||
230 | #endif /* CONFIG_NFS_V4_1 */ | 236 | #endif /* CONFIG_NFS_V4_1 */ |
231 | 237 | ||
232 | extern struct nfs4_state_maintenance_ops *nfs4_state_renewal_ops[]; | 238 | extern struct nfs4_state_maintenance_ops *nfs4_state_renewal_ops[]; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index ff0c080db59b..6917311f201c 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2040,15 +2040,9 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2040 | .rpc_argp = &args, | 2040 | .rpc_argp = &args, |
2041 | .rpc_resp = &res, | 2041 | .rpc_resp = &res, |
2042 | }; | 2042 | }; |
2043 | int status; | ||
2044 | 2043 | ||
2045 | nfs_fattr_init(info->fattr); | 2044 | nfs_fattr_init(info->fattr); |
2046 | status = nfs4_recover_expired_lease(server); | 2045 | return nfs4_call_sync(server, &msg, &args, &res, 0); |
2047 | if (!status) | ||
2048 | status = nfs4_check_client_ready(server->nfs_client); | ||
2049 | if (!status) | ||
2050 | status = nfs4_call_sync(server, &msg, &args, &res, 0); | ||
2051 | return status; | ||
2052 | } | 2046 | } |
2053 | 2047 | ||
2054 | static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | 2048 | static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, |
@@ -4099,15 +4093,23 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request) | |||
4099 | if (request->fl_start < 0 || request->fl_end < 0) | 4093 | if (request->fl_start < 0 || request->fl_end < 0) |
4100 | return -EINVAL; | 4094 | return -EINVAL; |
4101 | 4095 | ||
4102 | if (IS_GETLK(cmd)) | 4096 | if (IS_GETLK(cmd)) { |
4103 | return nfs4_proc_getlk(state, F_GETLK, request); | 4097 | if (state != NULL) |
4098 | return nfs4_proc_getlk(state, F_GETLK, request); | ||
4099 | return 0; | ||
4100 | } | ||
4104 | 4101 | ||
4105 | if (!(IS_SETLK(cmd) || IS_SETLKW(cmd))) | 4102 | if (!(IS_SETLK(cmd) || IS_SETLKW(cmd))) |
4106 | return -EINVAL; | 4103 | return -EINVAL; |
4107 | 4104 | ||
4108 | if (request->fl_type == F_UNLCK) | 4105 | if (request->fl_type == F_UNLCK) { |
4109 | return nfs4_proc_unlck(state, cmd, request); | 4106 | if (state != NULL) |
4107 | return nfs4_proc_unlck(state, cmd, request); | ||
4108 | return 0; | ||
4109 | } | ||
4110 | 4110 | ||
4111 | if (state == NULL) | ||
4112 | return -ENOLCK; | ||
4111 | do { | 4113 | do { |
4112 | status = nfs4_proc_setlk(state, cmd, request); | 4114 | status = nfs4_proc_setlk(state, cmd, request); |
4113 | if ((status != -EAGAIN) || IS_SETLK(cmd)) | 4115 | if ((status != -EAGAIN) || IS_SETLK(cmd)) |
@@ -4793,6 +4795,22 @@ int nfs4_proc_destroy_session(struct nfs4_session *session) | |||
4793 | return status; | 4795 | return status; |
4794 | } | 4796 | } |
4795 | 4797 | ||
4798 | int nfs4_init_session(struct nfs_server *server) | ||
4799 | { | ||
4800 | struct nfs_client *clp = server->nfs_client; | ||
4801 | int ret; | ||
4802 | |||
4803 | if (!nfs4_has_session(clp)) | ||
4804 | return 0; | ||
4805 | |||
4806 | clp->cl_session->fc_attrs.max_rqst_sz = server->wsize; | ||
4807 | clp->cl_session->fc_attrs.max_resp_sz = server->rsize; | ||
4808 | ret = nfs4_recover_expired_lease(server); | ||
4809 | if (!ret) | ||
4810 | ret = nfs4_check_client_ready(clp); | ||
4811 | return ret; | ||
4812 | } | ||
4813 | |||
4796 | /* | 4814 | /* |
4797 | * Renew the cl_session lease. | 4815 | * Renew the cl_session lease. |
4798 | */ | 4816 | */ |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index b73c5a728655..65ca8c18476f 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -553,6 +553,7 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f | |||
553 | INIT_LIST_HEAD(&lsp->ls_sequence.list); | 553 | INIT_LIST_HEAD(&lsp->ls_sequence.list); |
554 | lsp->ls_seqid.sequence = &lsp->ls_sequence; | 554 | lsp->ls_seqid.sequence = &lsp->ls_sequence; |
555 | atomic_set(&lsp->ls_count, 1); | 555 | atomic_set(&lsp->ls_count, 1); |
556 | lsp->ls_state = state; | ||
556 | lsp->ls_owner = fl_owner; | 557 | lsp->ls_owner = fl_owner; |
557 | spin_lock(&clp->cl_lock); | 558 | spin_lock(&clp->cl_lock); |
558 | nfs_alloc_unique_id(&clp->cl_lockowner_id, &lsp->ls_id, 1, 64); | 559 | nfs_alloc_unique_id(&clp->cl_lockowner_id, &lsp->ls_id, 1, 64); |
@@ -587,7 +588,6 @@ static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_ | |||
587 | if (lsp != NULL) | 588 | if (lsp != NULL) |
588 | break; | 589 | break; |
589 | if (new != NULL) { | 590 | if (new != NULL) { |
590 | new->ls_state = state; | ||
591 | list_add(&new->ls_locks, &state->lock_states); | 591 | list_add(&new->ls_locks, &state->lock_states); |
592 | set_bit(LK_STATE_IN_USE, &state->flags); | 592 | set_bit(LK_STATE_IN_USE, &state->flags); |
593 | lsp = new; | 593 | lsp = new; |
diff --git a/fs/nilfs2/Kconfig b/fs/nilfs2/Kconfig new file mode 100644 index 000000000000..72da095d4009 --- /dev/null +++ b/fs/nilfs2/Kconfig | |||
@@ -0,0 +1,25 @@ | |||
1 | config NILFS2_FS | ||
2 | tristate "NILFS2 file system support (EXPERIMENTAL)" | ||
3 | depends on BLOCK && EXPERIMENTAL | ||
4 | select CRC32 | ||
5 | help | ||
6 | NILFS2 is a log-structured file system (LFS) supporting continuous | ||
7 | snapshotting. In addition to versioning capability of the entire | ||
8 | file system, users can even restore files mistakenly overwritten or | ||
9 | destroyed just a few seconds ago. Since this file system can keep | ||
10 | consistency like conventional LFS, it achieves quick recovery after | ||
11 | system crashes. | ||
12 | |||
13 | NILFS2 creates a number of checkpoints every few seconds or per | ||
14 | synchronous write basis (unless there is no change). Users can | ||
15 | select significant versions among continuously created checkpoints, | ||
16 | and can change them into snapshots which will be preserved for long | ||
17 | periods until they are changed back to checkpoints. Each | ||
18 | snapshot is mountable as a read-only file system concurrently with | ||
19 | its writable mount, and this feature is convenient for online backup. | ||
20 | |||
21 | Some features including atime, extended attributes, and POSIX ACLs, | ||
22 | are not supported yet. | ||
23 | |||
24 | To compile this file system support as a module, choose M here: the | ||
25 | module will be called nilfs2. If unsure, say N. | ||
@@ -68,8 +68,8 @@ void pipe_double_lock(struct pipe_inode_info *pipe1, | |||
68 | pipe_lock_nested(pipe1, I_MUTEX_PARENT); | 68 | pipe_lock_nested(pipe1, I_MUTEX_PARENT); |
69 | pipe_lock_nested(pipe2, I_MUTEX_CHILD); | 69 | pipe_lock_nested(pipe2, I_MUTEX_CHILD); |
70 | } else { | 70 | } else { |
71 | pipe_lock_nested(pipe2, I_MUTEX_CHILD); | 71 | pipe_lock_nested(pipe2, I_MUTEX_PARENT); |
72 | pipe_lock_nested(pipe1, I_MUTEX_PARENT); | 72 | pipe_lock_nested(pipe1, I_MUTEX_CHILD); |
73 | } | 73 | } |
74 | } | 74 | } |
75 | 75 | ||
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 2721f07e9354..35e7df1e9f30 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/irqflags.h> | 14 | #include <linux/irqflags.h> |
15 | #include <linux/smp.h> | 15 | #include <linux/smp.h> |
16 | #include <linux/percpu.h> | 16 | #include <linux/percpu.h> |
17 | #include <linux/hrtimer.h> | ||
17 | 18 | ||
18 | #include <asm/atomic.h> | 19 | #include <asm/atomic.h> |
19 | #include <asm/ptrace.h> | 20 | #include <asm/ptrace.h> |
@@ -64,11 +65,13 @@ | |||
64 | * IRQTF_RUNTHREAD - signals that the interrupt handler thread should run | 65 | * IRQTF_RUNTHREAD - signals that the interrupt handler thread should run |
65 | * IRQTF_DIED - handler thread died | 66 | * IRQTF_DIED - handler thread died |
66 | * IRQTF_WARNED - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed | 67 | * IRQTF_WARNED - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed |
68 | * IRQTF_AFFINITY - irq thread is requested to adjust affinity | ||
67 | */ | 69 | */ |
68 | enum { | 70 | enum { |
69 | IRQTF_RUNTHREAD, | 71 | IRQTF_RUNTHREAD, |
70 | IRQTF_DIED, | 72 | IRQTF_DIED, |
71 | IRQTF_WARNED, | 73 | IRQTF_WARNED, |
74 | IRQTF_AFFINITY, | ||
72 | }; | 75 | }; |
73 | 76 | ||
74 | typedef irqreturn_t (*irq_handler_t)(int, void *); | 77 | typedef irqreturn_t (*irq_handler_t)(int, void *); |
@@ -517,6 +520,31 @@ extern void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu); | |||
517 | extern void tasklet_init(struct tasklet_struct *t, | 520 | extern void tasklet_init(struct tasklet_struct *t, |
518 | void (*func)(unsigned long), unsigned long data); | 521 | void (*func)(unsigned long), unsigned long data); |
519 | 522 | ||
523 | struct tasklet_hrtimer { | ||
524 | struct hrtimer timer; | ||
525 | struct tasklet_struct tasklet; | ||
526 | enum hrtimer_restart (*function)(struct hrtimer *); | ||
527 | }; | ||
528 | |||
529 | extern void | ||
530 | tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer, | ||
531 | enum hrtimer_restart (*function)(struct hrtimer *), | ||
532 | clockid_t which_clock, enum hrtimer_mode mode); | ||
533 | |||
534 | static inline | ||
535 | int tasklet_hrtimer_start(struct tasklet_hrtimer *ttimer, ktime_t time, | ||
536 | const enum hrtimer_mode mode) | ||
537 | { | ||
538 | return hrtimer_start(&ttimer->timer, time, mode); | ||
539 | } | ||
540 | |||
541 | static inline | ||
542 | void tasklet_hrtimer_cancel(struct tasklet_hrtimer *ttimer) | ||
543 | { | ||
544 | hrtimer_cancel(&ttimer->timer); | ||
545 | tasklet_kill(&ttimer->tasklet); | ||
546 | } | ||
547 | |||
520 | /* | 548 | /* |
521 | * Autoprobing for irqs: | 549 | * Autoprobing for irqs: |
522 | * | 550 | * |
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h index 5e970c7d3fd5..bd15d7a5f5ce 100644 --- a/include/linux/perf_counter.h +++ b/include/linux/perf_counter.h | |||
@@ -120,8 +120,9 @@ enum perf_counter_sample_format { | |||
120 | PERF_SAMPLE_ID = 1U << 6, | 120 | PERF_SAMPLE_ID = 1U << 6, |
121 | PERF_SAMPLE_CPU = 1U << 7, | 121 | PERF_SAMPLE_CPU = 1U << 7, |
122 | PERF_SAMPLE_PERIOD = 1U << 8, | 122 | PERF_SAMPLE_PERIOD = 1U << 8, |
123 | PERF_SAMPLE_STREAM_ID = 1U << 9, | ||
123 | 124 | ||
124 | PERF_SAMPLE_MAX = 1U << 9, /* non-ABI */ | 125 | PERF_SAMPLE_MAX = 1U << 10, /* non-ABI */ |
125 | }; | 126 | }; |
126 | 127 | ||
127 | /* | 128 | /* |
@@ -312,16 +313,7 @@ enum perf_event_type { | |||
312 | * struct perf_event_header header; | 313 | * struct perf_event_header header; |
313 | * u64 time; | 314 | * u64 time; |
314 | * u64 id; | 315 | * u64 id; |
315 | * u64 sample_period; | 316 | * u64 stream_id; |
316 | * }; | ||
317 | */ | ||
318 | PERF_EVENT_PERIOD = 4, | ||
319 | |||
320 | /* | ||
321 | * struct { | ||
322 | * struct perf_event_header header; | ||
323 | * u64 time; | ||
324 | * u64 id; | ||
325 | * }; | 317 | * }; |
326 | */ | 318 | */ |
327 | PERF_EVENT_THROTTLE = 5, | 319 | PERF_EVENT_THROTTLE = 5, |
@@ -356,6 +348,7 @@ enum perf_event_type { | |||
356 | * { u64 time; } && PERF_SAMPLE_TIME | 348 | * { u64 time; } && PERF_SAMPLE_TIME |
357 | * { u64 addr; } && PERF_SAMPLE_ADDR | 349 | * { u64 addr; } && PERF_SAMPLE_ADDR |
358 | * { u64 id; } && PERF_SAMPLE_ID | 350 | * { u64 id; } && PERF_SAMPLE_ID |
351 | * { u64 stream_id;} && PERF_SAMPLE_STREAM_ID | ||
359 | * { u32 cpu, res; } && PERF_SAMPLE_CPU | 352 | * { u32 cpu, res; } && PERF_SAMPLE_CPU |
360 | * { u64 period; } && PERF_SAMPLE_PERIOD | 353 | * { u64 period; } && PERF_SAMPLE_PERIOD |
361 | * | 354 | * |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 16a982e389fb..3ab08e4bb6b8 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -209,7 +209,7 @@ extern unsigned long long time_sync_thresh; | |||
209 | ((task->state & (__TASK_STOPPED | __TASK_TRACED)) != 0) | 209 | ((task->state & (__TASK_STOPPED | __TASK_TRACED)) != 0) |
210 | #define task_contributes_to_load(task) \ | 210 | #define task_contributes_to_load(task) \ |
211 | ((task->state & TASK_UNINTERRUPTIBLE) != 0 && \ | 211 | ((task->state & TASK_UNINTERRUPTIBLE) != 0 && \ |
212 | (task->flags & PF_FROZEN) == 0) | 212 | (task->flags & PF_FREEZING) == 0) |
213 | 213 | ||
214 | #define __set_task_state(tsk, state_value) \ | 214 | #define __set_task_state(tsk, state_value) \ |
215 | do { (tsk)->state = (state_value); } while (0) | 215 | do { (tsk)->state = (state_value); } while (0) |
@@ -1680,6 +1680,7 @@ extern cputime_t task_gtime(struct task_struct *p); | |||
1680 | #define PF_MEMALLOC 0x00000800 /* Allocating memory */ | 1680 | #define PF_MEMALLOC 0x00000800 /* Allocating memory */ |
1681 | #define PF_FLUSHER 0x00001000 /* responsible for disk writeback */ | 1681 | #define PF_FLUSHER 0x00001000 /* responsible for disk writeback */ |
1682 | #define PF_USED_MATH 0x00002000 /* if unset the fpu must be initialized before use */ | 1682 | #define PF_USED_MATH 0x00002000 /* if unset the fpu must be initialized before use */ |
1683 | #define PF_FREEZING 0x00004000 /* freeze in progress. do not account to load */ | ||
1683 | #define PF_NOFREEZE 0x00008000 /* this thread should not be frozen */ | 1684 | #define PF_NOFREEZE 0x00008000 /* this thread should not be frozen */ |
1684 | #define PF_FROZEN 0x00010000 /* frozen for system suspend */ | 1685 | #define PF_FROZEN 0x00010000 /* frozen for system suspend */ |
1685 | #define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */ | 1686 | #define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */ |
diff --git a/include/net/sock.h b/include/net/sock.h index 2c0da9239b95..950409dcec3d 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -104,15 +104,15 @@ struct net; | |||
104 | 104 | ||
105 | /** | 105 | /** |
106 | * struct sock_common - minimal network layer representation of sockets | 106 | * struct sock_common - minimal network layer representation of sockets |
107 | * @skc_node: main hash linkage for various protocol lookup tables | ||
108 | * @skc_nulls_node: main hash linkage for UDP/UDP-Lite protocol | ||
109 | * @skc_refcnt: reference count | ||
110 | * @skc_hash: hash value used with various protocol lookup tables | ||
107 | * @skc_family: network address family | 111 | * @skc_family: network address family |
108 | * @skc_state: Connection state | 112 | * @skc_state: Connection state |
109 | * @skc_reuse: %SO_REUSEADDR setting | 113 | * @skc_reuse: %SO_REUSEADDR setting |
110 | * @skc_bound_dev_if: bound device index if != 0 | 114 | * @skc_bound_dev_if: bound device index if != 0 |
111 | * @skc_node: main hash linkage for various protocol lookup tables | ||
112 | * @skc_nulls_node: main hash linkage for UDP/UDP-Lite protocol | ||
113 | * @skc_bind_node: bind hash linkage for various protocol lookup tables | 115 | * @skc_bind_node: bind hash linkage for various protocol lookup tables |
114 | * @skc_refcnt: reference count | ||
115 | * @skc_hash: hash value used with various protocol lookup tables | ||
116 | * @skc_prot: protocol handlers inside a network family | 116 | * @skc_prot: protocol handlers inside a network family |
117 | * @skc_net: reference to the network namespace of this socket | 117 | * @skc_net: reference to the network namespace of this socket |
118 | * | 118 | * |
@@ -120,17 +120,21 @@ struct net; | |||
120 | * for struct sock and struct inet_timewait_sock. | 120 | * for struct sock and struct inet_timewait_sock. |
121 | */ | 121 | */ |
122 | struct sock_common { | 122 | struct sock_common { |
123 | unsigned short skc_family; | 123 | /* |
124 | volatile unsigned char skc_state; | 124 | * first fields are not copied in sock_copy() |
125 | unsigned char skc_reuse; | 125 | */ |
126 | int skc_bound_dev_if; | ||
127 | union { | 126 | union { |
128 | struct hlist_node skc_node; | 127 | struct hlist_node skc_node; |
129 | struct hlist_nulls_node skc_nulls_node; | 128 | struct hlist_nulls_node skc_nulls_node; |
130 | }; | 129 | }; |
131 | struct hlist_node skc_bind_node; | ||
132 | atomic_t skc_refcnt; | 130 | atomic_t skc_refcnt; |
131 | |||
133 | unsigned int skc_hash; | 132 | unsigned int skc_hash; |
133 | unsigned short skc_family; | ||
134 | volatile unsigned char skc_state; | ||
135 | unsigned char skc_reuse; | ||
136 | int skc_bound_dev_if; | ||
137 | struct hlist_node skc_bind_node; | ||
134 | struct proto *skc_prot; | 138 | struct proto *skc_prot; |
135 | #ifdef CONFIG_NET_NS | 139 | #ifdef CONFIG_NET_NS |
136 | struct net *skc_net; | 140 | struct net *skc_net; |
@@ -208,15 +212,17 @@ struct sock { | |||
208 | * don't add nothing before this first member (__sk_common) --acme | 212 | * don't add nothing before this first member (__sk_common) --acme |
209 | */ | 213 | */ |
210 | struct sock_common __sk_common; | 214 | struct sock_common __sk_common; |
215 | #define sk_node __sk_common.skc_node | ||
216 | #define sk_nulls_node __sk_common.skc_nulls_node | ||
217 | #define sk_refcnt __sk_common.skc_refcnt | ||
218 | |||
219 | #define sk_copy_start __sk_common.skc_hash | ||
220 | #define sk_hash __sk_common.skc_hash | ||
211 | #define sk_family __sk_common.skc_family | 221 | #define sk_family __sk_common.skc_family |
212 | #define sk_state __sk_common.skc_state | 222 | #define sk_state __sk_common.skc_state |
213 | #define sk_reuse __sk_common.skc_reuse | 223 | #define sk_reuse __sk_common.skc_reuse |
214 | #define sk_bound_dev_if __sk_common.skc_bound_dev_if | 224 | #define sk_bound_dev_if __sk_common.skc_bound_dev_if |
215 | #define sk_node __sk_common.skc_node | ||
216 | #define sk_nulls_node __sk_common.skc_nulls_node | ||
217 | #define sk_bind_node __sk_common.skc_bind_node | 225 | #define sk_bind_node __sk_common.skc_bind_node |
218 | #define sk_refcnt __sk_common.skc_refcnt | ||
219 | #define sk_hash __sk_common.skc_hash | ||
220 | #define sk_prot __sk_common.skc_prot | 226 | #define sk_prot __sk_common.skc_prot |
221 | #define sk_net __sk_common.skc_net | 227 | #define sk_net __sk_common.skc_net |
222 | kmemcheck_bitfield_begin(flags); | 228 | kmemcheck_bitfield_begin(flags); |
diff --git a/include/net/tcp.h b/include/net/tcp.h index 19f4150f4d4d..88af84306471 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -1425,6 +1425,11 @@ struct tcp_request_sock_ops { | |||
1425 | #ifdef CONFIG_TCP_MD5SIG | 1425 | #ifdef CONFIG_TCP_MD5SIG |
1426 | struct tcp_md5sig_key *(*md5_lookup) (struct sock *sk, | 1426 | struct tcp_md5sig_key *(*md5_lookup) (struct sock *sk, |
1427 | struct request_sock *req); | 1427 | struct request_sock *req); |
1428 | int (*calc_md5_hash) (char *location, | ||
1429 | struct tcp_md5sig_key *md5, | ||
1430 | struct sock *sk, | ||
1431 | struct request_sock *req, | ||
1432 | struct sk_buff *skb); | ||
1428 | #endif | 1433 | #endif |
1429 | }; | 1434 | }; |
1430 | 1435 | ||
diff --git a/init/Kconfig b/init/Kconfig index 1ce05a4cb5f6..cb2c09270226 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -962,7 +962,7 @@ config PERF_COUNTERS | |||
962 | 962 | ||
963 | config EVENT_PROFILE | 963 | config EVENT_PROFILE |
964 | bool "Tracepoint profile sources" | 964 | bool "Tracepoint profile sources" |
965 | depends on PERF_COUNTERS && EVENT_TRACER | 965 | depends on PERF_COUNTERS && EVENT_TRACING |
966 | default y | 966 | default y |
967 | 967 | ||
968 | endmenu | 968 | endmenu |
diff --git a/kernel/fork.c b/kernel/fork.c index bd2959228871..9b42695f0d14 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -1407,14 +1407,11 @@ long do_fork(unsigned long clone_flags, | |||
1407 | if (clone_flags & CLONE_VFORK) { | 1407 | if (clone_flags & CLONE_VFORK) { |
1408 | p->vfork_done = &vfork; | 1408 | p->vfork_done = &vfork; |
1409 | init_completion(&vfork); | 1409 | init_completion(&vfork); |
1410 | } else if (!(clone_flags & CLONE_VM)) { | ||
1411 | /* | ||
1412 | * vfork will do an exec which will call | ||
1413 | * set_task_comm() | ||
1414 | */ | ||
1415 | perf_counter_fork(p); | ||
1416 | } | 1410 | } |
1417 | 1411 | ||
1412 | if (!(clone_flags & CLONE_THREAD)) | ||
1413 | perf_counter_fork(p); | ||
1414 | |||
1418 | audit_finish_fork(p); | 1415 | audit_finish_fork(p); |
1419 | tracehook_report_clone(regs, clone_flags, nr, p); | 1416 | tracehook_report_clone(regs, clone_flags, nr, p); |
1420 | 1417 | ||
diff --git a/kernel/freezer.c b/kernel/freezer.c index 2f4936cf7083..bd1d42b17cb2 100644 --- a/kernel/freezer.c +++ b/kernel/freezer.c | |||
@@ -44,12 +44,19 @@ void refrigerator(void) | |||
44 | recalc_sigpending(); /* We sent fake signal, clean it up */ | 44 | recalc_sigpending(); /* We sent fake signal, clean it up */ |
45 | spin_unlock_irq(¤t->sighand->siglock); | 45 | spin_unlock_irq(¤t->sighand->siglock); |
46 | 46 | ||
47 | /* prevent accounting of that task to load */ | ||
48 | current->flags |= PF_FREEZING; | ||
49 | |||
47 | for (;;) { | 50 | for (;;) { |
48 | set_current_state(TASK_UNINTERRUPTIBLE); | 51 | set_current_state(TASK_UNINTERRUPTIBLE); |
49 | if (!frozen(current)) | 52 | if (!frozen(current)) |
50 | break; | 53 | break; |
51 | schedule(); | 54 | schedule(); |
52 | } | 55 | } |
56 | |||
57 | /* Remove the accounting blocker */ | ||
58 | current->flags &= ~PF_FREEZING; | ||
59 | |||
53 | pr_debug("%s left refrigerator\n", current->comm); | 60 | pr_debug("%s left refrigerator\n", current->comm); |
54 | __set_current_state(save); | 61 | __set_current_state(save); |
55 | } | 62 | } |
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index 73468253143b..e70ed5592eb9 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h | |||
@@ -42,8 +42,7 @@ static inline void unregister_handler_proc(unsigned int irq, | |||
42 | 42 | ||
43 | extern int irq_select_affinity_usr(unsigned int irq); | 43 | extern int irq_select_affinity_usr(unsigned int irq); |
44 | 44 | ||
45 | extern void | 45 | extern void irq_set_thread_affinity(struct irq_desc *desc); |
46 | irq_set_thread_affinity(struct irq_desc *desc, const struct cpumask *cpumask); | ||
47 | 46 | ||
48 | /* | 47 | /* |
49 | * Debugging printout: | 48 | * Debugging printout: |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 50da67672901..61c679db4687 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -80,14 +80,22 @@ int irq_can_set_affinity(unsigned int irq) | |||
80 | return 1; | 80 | return 1; |
81 | } | 81 | } |
82 | 82 | ||
83 | void | 83 | /** |
84 | irq_set_thread_affinity(struct irq_desc *desc, const struct cpumask *cpumask) | 84 | * irq_set_thread_affinity - Notify irq threads to adjust affinity |
85 | * @desc: irq descriptor which has affitnity changed | ||
86 | * | ||
87 | * We just set IRQTF_AFFINITY and delegate the affinity setting | ||
88 | * to the interrupt thread itself. We can not call | ||
89 | * set_cpus_allowed_ptr() here as we hold desc->lock and this | ||
90 | * code can be called from hard interrupt context. | ||
91 | */ | ||
92 | void irq_set_thread_affinity(struct irq_desc *desc) | ||
85 | { | 93 | { |
86 | struct irqaction *action = desc->action; | 94 | struct irqaction *action = desc->action; |
87 | 95 | ||
88 | while (action) { | 96 | while (action) { |
89 | if (action->thread) | 97 | if (action->thread) |
90 | set_cpus_allowed_ptr(action->thread, cpumask); | 98 | set_bit(IRQTF_AFFINITY, &action->thread_flags); |
91 | action = action->next; | 99 | action = action->next; |
92 | } | 100 | } |
93 | } | 101 | } |
@@ -112,7 +120,7 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask) | |||
112 | if (desc->status & IRQ_MOVE_PCNTXT) { | 120 | if (desc->status & IRQ_MOVE_PCNTXT) { |
113 | if (!desc->chip->set_affinity(irq, cpumask)) { | 121 | if (!desc->chip->set_affinity(irq, cpumask)) { |
114 | cpumask_copy(desc->affinity, cpumask); | 122 | cpumask_copy(desc->affinity, cpumask); |
115 | irq_set_thread_affinity(desc, cpumask); | 123 | irq_set_thread_affinity(desc); |
116 | } | 124 | } |
117 | } | 125 | } |
118 | else { | 126 | else { |
@@ -122,7 +130,7 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask) | |||
122 | #else | 130 | #else |
123 | if (!desc->chip->set_affinity(irq, cpumask)) { | 131 | if (!desc->chip->set_affinity(irq, cpumask)) { |
124 | cpumask_copy(desc->affinity, cpumask); | 132 | cpumask_copy(desc->affinity, cpumask); |
125 | irq_set_thread_affinity(desc, cpumask); | 133 | irq_set_thread_affinity(desc); |
126 | } | 134 | } |
127 | #endif | 135 | #endif |
128 | desc->status |= IRQ_AFFINITY_SET; | 136 | desc->status |= IRQ_AFFINITY_SET; |
@@ -176,7 +184,7 @@ int irq_select_affinity_usr(unsigned int irq) | |||
176 | spin_lock_irqsave(&desc->lock, flags); | 184 | spin_lock_irqsave(&desc->lock, flags); |
177 | ret = setup_affinity(irq, desc); | 185 | ret = setup_affinity(irq, desc); |
178 | if (!ret) | 186 | if (!ret) |
179 | irq_set_thread_affinity(desc, desc->affinity); | 187 | irq_set_thread_affinity(desc); |
180 | spin_unlock_irqrestore(&desc->lock, flags); | 188 | spin_unlock_irqrestore(&desc->lock, flags); |
181 | 189 | ||
182 | return ret; | 190 | return ret; |
@@ -443,6 +451,39 @@ static int irq_wait_for_interrupt(struct irqaction *action) | |||
443 | return -1; | 451 | return -1; |
444 | } | 452 | } |
445 | 453 | ||
454 | #ifdef CONFIG_SMP | ||
455 | /* | ||
456 | * Check whether we need to change the affinity of the interrupt thread. | ||
457 | */ | ||
458 | static void | ||
459 | irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) | ||
460 | { | ||
461 | cpumask_var_t mask; | ||
462 | |||
463 | if (!test_and_clear_bit(IRQTF_AFFINITY, &action->thread_flags)) | ||
464 | return; | ||
465 | |||
466 | /* | ||
467 | * In case we are out of memory we set IRQTF_AFFINITY again and | ||
468 | * try again next time | ||
469 | */ | ||
470 | if (!alloc_cpumask_var(&mask, GFP_KERNEL)) { | ||
471 | set_bit(IRQTF_AFFINITY, &action->thread_flags); | ||
472 | return; | ||
473 | } | ||
474 | |||
475 | spin_lock_irq(&desc->lock); | ||
476 | cpumask_copy(mask, desc->affinity); | ||
477 | spin_unlock_irq(&desc->lock); | ||
478 | |||
479 | set_cpus_allowed_ptr(current, mask); | ||
480 | free_cpumask_var(mask); | ||
481 | } | ||
482 | #else | ||
483 | static inline void | ||
484 | irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) { } | ||
485 | #endif | ||
486 | |||
446 | /* | 487 | /* |
447 | * Interrupt handler thread | 488 | * Interrupt handler thread |
448 | */ | 489 | */ |
@@ -458,6 +499,8 @@ static int irq_thread(void *data) | |||
458 | 499 | ||
459 | while (!irq_wait_for_interrupt(action)) { | 500 | while (!irq_wait_for_interrupt(action)) { |
460 | 501 | ||
502 | irq_thread_check_affinity(desc, action); | ||
503 | |||
461 | atomic_inc(&desc->threads_active); | 504 | atomic_inc(&desc->threads_active); |
462 | 505 | ||
463 | spin_lock_irq(&desc->lock); | 506 | spin_lock_irq(&desc->lock); |
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c index cfe767ca1545..fcb6c96f2627 100644 --- a/kernel/irq/migration.c +++ b/kernel/irq/migration.c | |||
@@ -45,7 +45,7 @@ void move_masked_irq(int irq) | |||
45 | < nr_cpu_ids)) | 45 | < nr_cpu_ids)) |
46 | if (!desc->chip->set_affinity(irq, desc->pending_mask)) { | 46 | if (!desc->chip->set_affinity(irq, desc->pending_mask)) { |
47 | cpumask_copy(desc->affinity, desc->pending_mask); | 47 | cpumask_copy(desc->affinity, desc->pending_mask); |
48 | irq_set_thread_affinity(desc, desc->pending_mask); | 48 | irq_set_thread_affinity(desc); |
49 | } | 49 | } |
50 | 50 | ||
51 | cpumask_clear(desc->pending_mask); | 51 | cpumask_clear(desc->pending_mask); |
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index a641eb753b8c..950931041954 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c | |||
@@ -146,6 +146,28 @@ static void put_ctx(struct perf_counter_context *ctx) | |||
146 | } | 146 | } |
147 | } | 147 | } |
148 | 148 | ||
149 | static void unclone_ctx(struct perf_counter_context *ctx) | ||
150 | { | ||
151 | if (ctx->parent_ctx) { | ||
152 | put_ctx(ctx->parent_ctx); | ||
153 | ctx->parent_ctx = NULL; | ||
154 | } | ||
155 | } | ||
156 | |||
157 | /* | ||
158 | * If we inherit counters we want to return the parent counter id | ||
159 | * to userspace. | ||
160 | */ | ||
161 | static u64 primary_counter_id(struct perf_counter *counter) | ||
162 | { | ||
163 | u64 id = counter->id; | ||
164 | |||
165 | if (counter->parent) | ||
166 | id = counter->parent->id; | ||
167 | |||
168 | return id; | ||
169 | } | ||
170 | |||
149 | /* | 171 | /* |
150 | * Get the perf_counter_context for a task and lock it. | 172 | * Get the perf_counter_context for a task and lock it. |
151 | * This has to cope with with the fact that until it is locked, | 173 | * This has to cope with with the fact that until it is locked, |
@@ -1288,7 +1310,6 @@ static void perf_counter_cpu_sched_in(struct perf_cpu_context *cpuctx, int cpu) | |||
1288 | #define MAX_INTERRUPTS (~0ULL) | 1310 | #define MAX_INTERRUPTS (~0ULL) |
1289 | 1311 | ||
1290 | static void perf_log_throttle(struct perf_counter *counter, int enable); | 1312 | static void perf_log_throttle(struct perf_counter *counter, int enable); |
1291 | static void perf_log_period(struct perf_counter *counter, u64 period); | ||
1292 | 1313 | ||
1293 | static void perf_adjust_period(struct perf_counter *counter, u64 events) | 1314 | static void perf_adjust_period(struct perf_counter *counter, u64 events) |
1294 | { | 1315 | { |
@@ -1307,8 +1328,6 @@ static void perf_adjust_period(struct perf_counter *counter, u64 events) | |||
1307 | if (!sample_period) | 1328 | if (!sample_period) |
1308 | sample_period = 1; | 1329 | sample_period = 1; |
1309 | 1330 | ||
1310 | perf_log_period(counter, sample_period); | ||
1311 | |||
1312 | hwc->sample_period = sample_period; | 1331 | hwc->sample_period = sample_period; |
1313 | } | 1332 | } |
1314 | 1333 | ||
@@ -1463,10 +1482,8 @@ static void perf_counter_enable_on_exec(struct task_struct *task) | |||
1463 | /* | 1482 | /* |
1464 | * Unclone this context if we enabled any counter. | 1483 | * Unclone this context if we enabled any counter. |
1465 | */ | 1484 | */ |
1466 | if (enabled && ctx->parent_ctx) { | 1485 | if (enabled) |
1467 | put_ctx(ctx->parent_ctx); | 1486 | unclone_ctx(ctx); |
1468 | ctx->parent_ctx = NULL; | ||
1469 | } | ||
1470 | 1487 | ||
1471 | spin_unlock(&ctx->lock); | 1488 | spin_unlock(&ctx->lock); |
1472 | 1489 | ||
@@ -1526,7 +1543,6 @@ __perf_counter_init_context(struct perf_counter_context *ctx, | |||
1526 | 1543 | ||
1527 | static struct perf_counter_context *find_get_context(pid_t pid, int cpu) | 1544 | static struct perf_counter_context *find_get_context(pid_t pid, int cpu) |
1528 | { | 1545 | { |
1529 | struct perf_counter_context *parent_ctx; | ||
1530 | struct perf_counter_context *ctx; | 1546 | struct perf_counter_context *ctx; |
1531 | struct perf_cpu_context *cpuctx; | 1547 | struct perf_cpu_context *cpuctx; |
1532 | struct task_struct *task; | 1548 | struct task_struct *task; |
@@ -1586,11 +1602,7 @@ static struct perf_counter_context *find_get_context(pid_t pid, int cpu) | |||
1586 | retry: | 1602 | retry: |
1587 | ctx = perf_lock_task_context(task, &flags); | 1603 | ctx = perf_lock_task_context(task, &flags); |
1588 | if (ctx) { | 1604 | if (ctx) { |
1589 | parent_ctx = ctx->parent_ctx; | 1605 | unclone_ctx(ctx); |
1590 | if (parent_ctx) { | ||
1591 | put_ctx(parent_ctx); | ||
1592 | ctx->parent_ctx = NULL; /* no longer a clone */ | ||
1593 | } | ||
1594 | spin_unlock_irqrestore(&ctx->lock, flags); | 1606 | spin_unlock_irqrestore(&ctx->lock, flags); |
1595 | } | 1607 | } |
1596 | 1608 | ||
@@ -1704,7 +1716,7 @@ perf_read_hw(struct perf_counter *counter, char __user *buf, size_t count) | |||
1704 | values[n++] = counter->total_time_running + | 1716 | values[n++] = counter->total_time_running + |
1705 | atomic64_read(&counter->child_total_time_running); | 1717 | atomic64_read(&counter->child_total_time_running); |
1706 | if (counter->attr.read_format & PERF_FORMAT_ID) | 1718 | if (counter->attr.read_format & PERF_FORMAT_ID) |
1707 | values[n++] = counter->id; | 1719 | values[n++] = primary_counter_id(counter); |
1708 | mutex_unlock(&counter->child_mutex); | 1720 | mutex_unlock(&counter->child_mutex); |
1709 | 1721 | ||
1710 | if (count < n * sizeof(u64)) | 1722 | if (count < n * sizeof(u64)) |
@@ -1811,8 +1823,6 @@ static int perf_counter_period(struct perf_counter *counter, u64 __user *arg) | |||
1811 | 1823 | ||
1812 | counter->attr.sample_freq = value; | 1824 | counter->attr.sample_freq = value; |
1813 | } else { | 1825 | } else { |
1814 | perf_log_period(counter, value); | ||
1815 | |||
1816 | counter->attr.sample_period = value; | 1826 | counter->attr.sample_period = value; |
1817 | counter->hw.sample_period = value; | 1827 | counter->hw.sample_period = value; |
1818 | } | 1828 | } |
@@ -2661,10 +2671,14 @@ static void perf_counter_output(struct perf_counter *counter, int nmi, | |||
2661 | if (sample_type & PERF_SAMPLE_ID) | 2671 | if (sample_type & PERF_SAMPLE_ID) |
2662 | header.size += sizeof(u64); | 2672 | header.size += sizeof(u64); |
2663 | 2673 | ||
2674 | if (sample_type & PERF_SAMPLE_STREAM_ID) | ||
2675 | header.size += sizeof(u64); | ||
2676 | |||
2664 | if (sample_type & PERF_SAMPLE_CPU) { | 2677 | if (sample_type & PERF_SAMPLE_CPU) { |
2665 | header.size += sizeof(cpu_entry); | 2678 | header.size += sizeof(cpu_entry); |
2666 | 2679 | ||
2667 | cpu_entry.cpu = raw_smp_processor_id(); | 2680 | cpu_entry.cpu = raw_smp_processor_id(); |
2681 | cpu_entry.reserved = 0; | ||
2668 | } | 2682 | } |
2669 | 2683 | ||
2670 | if (sample_type & PERF_SAMPLE_PERIOD) | 2684 | if (sample_type & PERF_SAMPLE_PERIOD) |
@@ -2703,7 +2717,13 @@ static void perf_counter_output(struct perf_counter *counter, int nmi, | |||
2703 | if (sample_type & PERF_SAMPLE_ADDR) | 2717 | if (sample_type & PERF_SAMPLE_ADDR) |
2704 | perf_output_put(&handle, data->addr); | 2718 | perf_output_put(&handle, data->addr); |
2705 | 2719 | ||
2706 | if (sample_type & PERF_SAMPLE_ID) | 2720 | if (sample_type & PERF_SAMPLE_ID) { |
2721 | u64 id = primary_counter_id(counter); | ||
2722 | |||
2723 | perf_output_put(&handle, id); | ||
2724 | } | ||
2725 | |||
2726 | if (sample_type & PERF_SAMPLE_STREAM_ID) | ||
2707 | perf_output_put(&handle, counter->id); | 2727 | perf_output_put(&handle, counter->id); |
2708 | 2728 | ||
2709 | if (sample_type & PERF_SAMPLE_CPU) | 2729 | if (sample_type & PERF_SAMPLE_CPU) |
@@ -2726,7 +2746,7 @@ static void perf_counter_output(struct perf_counter *counter, int nmi, | |||
2726 | if (sub != counter) | 2746 | if (sub != counter) |
2727 | sub->pmu->read(sub); | 2747 | sub->pmu->read(sub); |
2728 | 2748 | ||
2729 | group_entry.id = sub->id; | 2749 | group_entry.id = primary_counter_id(sub); |
2730 | group_entry.counter = atomic64_read(&sub->count); | 2750 | group_entry.counter = atomic64_read(&sub->count); |
2731 | 2751 | ||
2732 | perf_output_put(&handle, group_entry); | 2752 | perf_output_put(&handle, group_entry); |
@@ -2786,15 +2806,8 @@ perf_counter_read_event(struct perf_counter *counter, | |||
2786 | } | 2806 | } |
2787 | 2807 | ||
2788 | if (counter->attr.read_format & PERF_FORMAT_ID) { | 2808 | if (counter->attr.read_format & PERF_FORMAT_ID) { |
2789 | u64 id; | ||
2790 | |||
2791 | event.header.size += sizeof(u64); | 2809 | event.header.size += sizeof(u64); |
2792 | if (counter->parent) | 2810 | event.format[i++] = primary_counter_id(counter); |
2793 | id = counter->parent->id; | ||
2794 | else | ||
2795 | id = counter->id; | ||
2796 | |||
2797 | event.format[i++] = id; | ||
2798 | } | 2811 | } |
2799 | 2812 | ||
2800 | ret = perf_output_begin(&handle, counter, event.header.size, 0, 0); | 2813 | ret = perf_output_begin(&handle, counter, event.header.size, 0, 0); |
@@ -2895,8 +2908,11 @@ void perf_counter_fork(struct task_struct *task) | |||
2895 | .event = { | 2908 | .event = { |
2896 | .header = { | 2909 | .header = { |
2897 | .type = PERF_EVENT_FORK, | 2910 | .type = PERF_EVENT_FORK, |
2911 | .misc = 0, | ||
2898 | .size = sizeof(fork_event.event), | 2912 | .size = sizeof(fork_event.event), |
2899 | }, | 2913 | }, |
2914 | /* .pid */ | ||
2915 | /* .ppid */ | ||
2900 | }, | 2916 | }, |
2901 | }; | 2917 | }; |
2902 | 2918 | ||
@@ -2968,8 +2984,10 @@ static void perf_counter_comm_event(struct perf_comm_event *comm_event) | |||
2968 | struct perf_cpu_context *cpuctx; | 2984 | struct perf_cpu_context *cpuctx; |
2969 | struct perf_counter_context *ctx; | 2985 | struct perf_counter_context *ctx; |
2970 | unsigned int size; | 2986 | unsigned int size; |
2971 | char *comm = comm_event->task->comm; | 2987 | char comm[TASK_COMM_LEN]; |
2972 | 2988 | ||
2989 | memset(comm, 0, sizeof(comm)); | ||
2990 | strncpy(comm, comm_event->task->comm, sizeof(comm)); | ||
2973 | size = ALIGN(strlen(comm)+1, sizeof(u64)); | 2991 | size = ALIGN(strlen(comm)+1, sizeof(u64)); |
2974 | 2992 | ||
2975 | comm_event->comm = comm; | 2993 | comm_event->comm = comm; |
@@ -3004,8 +3022,16 @@ void perf_counter_comm(struct task_struct *task) | |||
3004 | 3022 | ||
3005 | comm_event = (struct perf_comm_event){ | 3023 | comm_event = (struct perf_comm_event){ |
3006 | .task = task, | 3024 | .task = task, |
3025 | /* .comm */ | ||
3026 | /* .comm_size */ | ||
3007 | .event = { | 3027 | .event = { |
3008 | .header = { .type = PERF_EVENT_COMM, }, | 3028 | .header = { |
3029 | .type = PERF_EVENT_COMM, | ||
3030 | .misc = 0, | ||
3031 | /* .size */ | ||
3032 | }, | ||
3033 | /* .pid */ | ||
3034 | /* .tid */ | ||
3009 | }, | 3035 | }, |
3010 | }; | 3036 | }; |
3011 | 3037 | ||
@@ -3088,8 +3114,15 @@ static void perf_counter_mmap_event(struct perf_mmap_event *mmap_event) | |||
3088 | char *buf = NULL; | 3114 | char *buf = NULL; |
3089 | const char *name; | 3115 | const char *name; |
3090 | 3116 | ||
3117 | memset(tmp, 0, sizeof(tmp)); | ||
3118 | |||
3091 | if (file) { | 3119 | if (file) { |
3092 | buf = kzalloc(PATH_MAX, GFP_KERNEL); | 3120 | /* |
3121 | * d_path works from the end of the buffer backwards, so we | ||
3122 | * need to add enough zero bytes after the string to handle | ||
3123 | * the 64bit alignment we do later. | ||
3124 | */ | ||
3125 | buf = kzalloc(PATH_MAX + sizeof(u64), GFP_KERNEL); | ||
3093 | if (!buf) { | 3126 | if (!buf) { |
3094 | name = strncpy(tmp, "//enomem", sizeof(tmp)); | 3127 | name = strncpy(tmp, "//enomem", sizeof(tmp)); |
3095 | goto got_name; | 3128 | goto got_name; |
@@ -3100,9 +3133,11 @@ static void perf_counter_mmap_event(struct perf_mmap_event *mmap_event) | |||
3100 | goto got_name; | 3133 | goto got_name; |
3101 | } | 3134 | } |
3102 | } else { | 3135 | } else { |
3103 | name = arch_vma_name(mmap_event->vma); | 3136 | if (arch_vma_name(mmap_event->vma)) { |
3104 | if (name) | 3137 | name = strncpy(tmp, arch_vma_name(mmap_event->vma), |
3138 | sizeof(tmp)); | ||
3105 | goto got_name; | 3139 | goto got_name; |
3140 | } | ||
3106 | 3141 | ||
3107 | if (!vma->vm_mm) { | 3142 | if (!vma->vm_mm) { |
3108 | name = strncpy(tmp, "[vdso]", sizeof(tmp)); | 3143 | name = strncpy(tmp, "[vdso]", sizeof(tmp)); |
@@ -3147,8 +3182,16 @@ void __perf_counter_mmap(struct vm_area_struct *vma) | |||
3147 | 3182 | ||
3148 | mmap_event = (struct perf_mmap_event){ | 3183 | mmap_event = (struct perf_mmap_event){ |
3149 | .vma = vma, | 3184 | .vma = vma, |
3185 | /* .file_name */ | ||
3186 | /* .file_size */ | ||
3150 | .event = { | 3187 | .event = { |
3151 | .header = { .type = PERF_EVENT_MMAP, }, | 3188 | .header = { |
3189 | .type = PERF_EVENT_MMAP, | ||
3190 | .misc = 0, | ||
3191 | /* .size */ | ||
3192 | }, | ||
3193 | /* .pid */ | ||
3194 | /* .tid */ | ||
3152 | .start = vma->vm_start, | 3195 | .start = vma->vm_start, |
3153 | .len = vma->vm_end - vma->vm_start, | 3196 | .len = vma->vm_end - vma->vm_start, |
3154 | .pgoff = vma->vm_pgoff, | 3197 | .pgoff = vma->vm_pgoff, |
@@ -3159,49 +3202,6 @@ void __perf_counter_mmap(struct vm_area_struct *vma) | |||
3159 | } | 3202 | } |
3160 | 3203 | ||
3161 | /* | 3204 | /* |
3162 | * Log sample_period changes so that analyzing tools can re-normalize the | ||
3163 | * event flow. | ||
3164 | */ | ||
3165 | |||
3166 | struct freq_event { | ||
3167 | struct perf_event_header header; | ||
3168 | u64 time; | ||
3169 | u64 id; | ||
3170 | u64 period; | ||
3171 | }; | ||
3172 | |||
3173 | static void perf_log_period(struct perf_counter *counter, u64 period) | ||
3174 | { | ||
3175 | struct perf_output_handle handle; | ||
3176 | struct freq_event event; | ||
3177 | int ret; | ||
3178 | |||
3179 | if (counter->hw.sample_period == period) | ||
3180 | return; | ||
3181 | |||
3182 | if (counter->attr.sample_type & PERF_SAMPLE_PERIOD) | ||
3183 | return; | ||
3184 | |||
3185 | event = (struct freq_event) { | ||
3186 | .header = { | ||
3187 | .type = PERF_EVENT_PERIOD, | ||
3188 | .misc = 0, | ||
3189 | .size = sizeof(event), | ||
3190 | }, | ||
3191 | .time = sched_clock(), | ||
3192 | .id = counter->id, | ||
3193 | .period = period, | ||
3194 | }; | ||
3195 | |||
3196 | ret = perf_output_begin(&handle, counter, sizeof(event), 1, 0); | ||
3197 | if (ret) | ||
3198 | return; | ||
3199 | |||
3200 | perf_output_put(&handle, event); | ||
3201 | perf_output_end(&handle); | ||
3202 | } | ||
3203 | |||
3204 | /* | ||
3205 | * IRQ throttle logging | 3205 | * IRQ throttle logging |
3206 | */ | 3206 | */ |
3207 | 3207 | ||
@@ -3214,16 +3214,21 @@ static void perf_log_throttle(struct perf_counter *counter, int enable) | |||
3214 | struct perf_event_header header; | 3214 | struct perf_event_header header; |
3215 | u64 time; | 3215 | u64 time; |
3216 | u64 id; | 3216 | u64 id; |
3217 | u64 stream_id; | ||
3217 | } throttle_event = { | 3218 | } throttle_event = { |
3218 | .header = { | 3219 | .header = { |
3219 | .type = PERF_EVENT_THROTTLE + 1, | 3220 | .type = PERF_EVENT_THROTTLE, |
3220 | .misc = 0, | 3221 | .misc = 0, |
3221 | .size = sizeof(throttle_event), | 3222 | .size = sizeof(throttle_event), |
3222 | }, | 3223 | }, |
3223 | .time = sched_clock(), | 3224 | .time = sched_clock(), |
3224 | .id = counter->id, | 3225 | .id = primary_counter_id(counter), |
3226 | .stream_id = counter->id, | ||
3225 | }; | 3227 | }; |
3226 | 3228 | ||
3229 | if (enable) | ||
3230 | throttle_event.header.type = PERF_EVENT_UNTHROTTLE; | ||
3231 | |||
3227 | ret = perf_output_begin(&handle, counter, sizeof(throttle_event), 1, 0); | 3232 | ret = perf_output_begin(&handle, counter, sizeof(throttle_event), 1, 0); |
3228 | if (ret) | 3233 | if (ret) |
3229 | return; | 3234 | return; |
@@ -3671,7 +3676,7 @@ static const struct pmu perf_ops_task_clock = { | |||
3671 | void perf_tpcounter_event(int event_id) | 3676 | void perf_tpcounter_event(int event_id) |
3672 | { | 3677 | { |
3673 | struct perf_sample_data data = { | 3678 | struct perf_sample_data data = { |
3674 | .regs = get_irq_regs(); | 3679 | .regs = get_irq_regs(), |
3675 | .addr = 0, | 3680 | .addr = 0, |
3676 | }; | 3681 | }; |
3677 | 3682 | ||
@@ -3687,16 +3692,12 @@ extern void ftrace_profile_disable(int); | |||
3687 | 3692 | ||
3688 | static void tp_perf_counter_destroy(struct perf_counter *counter) | 3693 | static void tp_perf_counter_destroy(struct perf_counter *counter) |
3689 | { | 3694 | { |
3690 | ftrace_profile_disable(perf_event_id(&counter->attr)); | 3695 | ftrace_profile_disable(counter->attr.config); |
3691 | } | 3696 | } |
3692 | 3697 | ||
3693 | static const struct pmu *tp_perf_counter_init(struct perf_counter *counter) | 3698 | static const struct pmu *tp_perf_counter_init(struct perf_counter *counter) |
3694 | { | 3699 | { |
3695 | int event_id = perf_event_id(&counter->attr); | 3700 | if (ftrace_profile_enable(counter->attr.config)) |
3696 | int ret; | ||
3697 | |||
3698 | ret = ftrace_profile_enable(event_id); | ||
3699 | if (ret) | ||
3700 | return NULL; | 3701 | return NULL; |
3701 | 3702 | ||
3702 | counter->destroy = tp_perf_counter_destroy; | 3703 | counter->destroy = tp_perf_counter_destroy; |
@@ -4255,15 +4256,12 @@ void perf_counter_exit_task(struct task_struct *child) | |||
4255 | */ | 4256 | */ |
4256 | spin_lock(&child_ctx->lock); | 4257 | spin_lock(&child_ctx->lock); |
4257 | child->perf_counter_ctxp = NULL; | 4258 | child->perf_counter_ctxp = NULL; |
4258 | if (child_ctx->parent_ctx) { | 4259 | /* |
4259 | /* | 4260 | * If this context is a clone; unclone it so it can't get |
4260 | * This context is a clone; unclone it so it can't get | 4261 | * swapped to another process while we're removing all |
4261 | * swapped to another process while we're removing all | 4262 | * the counters from it. |
4262 | * the counters from it. | 4263 | */ |
4263 | */ | 4264 | unclone_ctx(child_ctx); |
4264 | put_ctx(child_ctx->parent_ctx); | ||
4265 | child_ctx->parent_ctx = NULL; | ||
4266 | } | ||
4267 | spin_unlock(&child_ctx->lock); | 4265 | spin_unlock(&child_ctx->lock); |
4268 | local_irq_restore(flags); | 4266 | local_irq_restore(flags); |
4269 | 4267 | ||
diff --git a/kernel/sched.c b/kernel/sched.c index 98972d366fdc..1b59e265273b 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -7289,6 +7289,7 @@ static void migrate_dead_tasks(unsigned int dead_cpu) | |||
7289 | static void calc_global_load_remove(struct rq *rq) | 7289 | static void calc_global_load_remove(struct rq *rq) |
7290 | { | 7290 | { |
7291 | atomic_long_sub(rq->calc_load_active, &calc_load_tasks); | 7291 | atomic_long_sub(rq->calc_load_active, &calc_load_tasks); |
7292 | rq->calc_load_active = 0; | ||
7292 | } | 7293 | } |
7293 | #endif /* CONFIG_HOTPLUG_CPU */ | 7294 | #endif /* CONFIG_HOTPLUG_CPU */ |
7294 | 7295 | ||
@@ -7515,6 +7516,7 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) | |||
7515 | task_rq_unlock(rq, &flags); | 7516 | task_rq_unlock(rq, &flags); |
7516 | get_task_struct(p); | 7517 | get_task_struct(p); |
7517 | cpu_rq(cpu)->migration_thread = p; | 7518 | cpu_rq(cpu)->migration_thread = p; |
7519 | rq->calc_load_update = calc_load_update; | ||
7518 | break; | 7520 | break; |
7519 | 7521 | ||
7520 | case CPU_ONLINE: | 7522 | case CPU_ONLINE: |
@@ -7525,8 +7527,6 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) | |||
7525 | /* Update our root-domain */ | 7527 | /* Update our root-domain */ |
7526 | rq = cpu_rq(cpu); | 7528 | rq = cpu_rq(cpu); |
7527 | spin_lock_irqsave(&rq->lock, flags); | 7529 | spin_lock_irqsave(&rq->lock, flags); |
7528 | rq->calc_load_update = calc_load_update; | ||
7529 | rq->calc_load_active = 0; | ||
7530 | if (rq->rd) { | 7530 | if (rq->rd) { |
7531 | BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); | 7531 | BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); |
7532 | 7532 | ||
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 7c248dc30f41..9ffb2b2ceba4 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c | |||
@@ -266,6 +266,12 @@ static inline u64 min_vruntime(u64 min_vruntime, u64 vruntime) | |||
266 | return min_vruntime; | 266 | return min_vruntime; |
267 | } | 267 | } |
268 | 268 | ||
269 | static inline int entity_before(struct sched_entity *a, | ||
270 | struct sched_entity *b) | ||
271 | { | ||
272 | return (s64)(a->vruntime - b->vruntime) < 0; | ||
273 | } | ||
274 | |||
269 | static inline s64 entity_key(struct cfs_rq *cfs_rq, struct sched_entity *se) | 275 | static inline s64 entity_key(struct cfs_rq *cfs_rq, struct sched_entity *se) |
270 | { | 276 | { |
271 | return se->vruntime - cfs_rq->min_vruntime; | 277 | return se->vruntime - cfs_rq->min_vruntime; |
@@ -1017,7 +1023,7 @@ static void yield_task_fair(struct rq *rq) | |||
1017 | /* | 1023 | /* |
1018 | * Already in the rightmost position? | 1024 | * Already in the rightmost position? |
1019 | */ | 1025 | */ |
1020 | if (unlikely(!rightmost || rightmost->vruntime < se->vruntime)) | 1026 | if (unlikely(!rightmost || entity_before(rightmost, se))) |
1021 | return; | 1027 | return; |
1022 | 1028 | ||
1023 | /* | 1029 | /* |
@@ -1713,7 +1719,7 @@ static void task_new_fair(struct rq *rq, struct task_struct *p) | |||
1713 | 1719 | ||
1714 | /* 'curr' will be NULL if the child belongs to a different group */ | 1720 | /* 'curr' will be NULL if the child belongs to a different group */ |
1715 | if (sysctl_sched_child_runs_first && this_cpu == task_cpu(p) && | 1721 | if (sysctl_sched_child_runs_first && this_cpu == task_cpu(p) && |
1716 | curr && curr->vruntime < se->vruntime) { | 1722 | curr && entity_before(curr, se)) { |
1717 | /* | 1723 | /* |
1718 | * Upon rescheduling, sched_class::put_prev_task() will place | 1724 | * Upon rescheduling, sched_class::put_prev_task() will place |
1719 | * 'current' within the tree based on its new key value. | 1725 | * 'current' within the tree based on its new key value. |
diff --git a/kernel/softirq.c b/kernel/softirq.c index 3a94905fa5d2..eb5e131a0485 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
@@ -345,7 +345,9 @@ void open_softirq(int nr, void (*action)(struct softirq_action *)) | |||
345 | softirq_vec[nr].action = action; | 345 | softirq_vec[nr].action = action; |
346 | } | 346 | } |
347 | 347 | ||
348 | /* Tasklets */ | 348 | /* |
349 | * Tasklets | ||
350 | */ | ||
349 | struct tasklet_head | 351 | struct tasklet_head |
350 | { | 352 | { |
351 | struct tasklet_struct *head; | 353 | struct tasklet_struct *head; |
@@ -493,6 +495,66 @@ void tasklet_kill(struct tasklet_struct *t) | |||
493 | 495 | ||
494 | EXPORT_SYMBOL(tasklet_kill); | 496 | EXPORT_SYMBOL(tasklet_kill); |
495 | 497 | ||
498 | /* | ||
499 | * tasklet_hrtimer | ||
500 | */ | ||
501 | |||
502 | /* | ||
503 | * The trampoline is called when the hrtimer expires. If this is | ||
504 | * called from the hrtimer interrupt then we schedule the tasklet as | ||
505 | * the timer callback function expects to run in softirq context. If | ||
506 | * it's called in softirq context anyway (i.e. high resolution timers | ||
507 | * disabled) then the hrtimer callback is called right away. | ||
508 | */ | ||
509 | static enum hrtimer_restart __hrtimer_tasklet_trampoline(struct hrtimer *timer) | ||
510 | { | ||
511 | struct tasklet_hrtimer *ttimer = | ||
512 | container_of(timer, struct tasklet_hrtimer, timer); | ||
513 | |||
514 | if (hrtimer_is_hres_active(timer)) { | ||
515 | tasklet_hi_schedule(&ttimer->tasklet); | ||
516 | return HRTIMER_NORESTART; | ||
517 | } | ||
518 | return ttimer->function(timer); | ||
519 | } | ||
520 | |||
521 | /* | ||
522 | * Helper function which calls the hrtimer callback from | ||
523 | * tasklet/softirq context | ||
524 | */ | ||
525 | static void __tasklet_hrtimer_trampoline(unsigned long data) | ||
526 | { | ||
527 | struct tasklet_hrtimer *ttimer = (void *)data; | ||
528 | enum hrtimer_restart restart; | ||
529 | |||
530 | restart = ttimer->function(&ttimer->timer); | ||
531 | if (restart != HRTIMER_NORESTART) | ||
532 | hrtimer_restart(&ttimer->timer); | ||
533 | } | ||
534 | |||
535 | /** | ||
536 | * tasklet_hrtimer_init - Init a tasklet/hrtimer combo for softirq callbacks | ||
537 | * @ttimer: tasklet_hrtimer which is initialized | ||
538 | * @function: hrtimer callback funtion which gets called from softirq context | ||
539 | * @which_clock: clock id (CLOCK_MONOTONIC/CLOCK_REALTIME) | ||
540 | * @mode: hrtimer mode (HRTIMER_MODE_ABS/HRTIMER_MODE_REL) | ||
541 | */ | ||
542 | void tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer, | ||
543 | enum hrtimer_restart (*function)(struct hrtimer *), | ||
544 | clockid_t which_clock, enum hrtimer_mode mode) | ||
545 | { | ||
546 | hrtimer_init(&ttimer->timer, which_clock, mode); | ||
547 | ttimer->timer.function = __hrtimer_tasklet_trampoline; | ||
548 | tasklet_init(&ttimer->tasklet, __tasklet_hrtimer_trampoline, | ||
549 | (unsigned long)ttimer); | ||
550 | ttimer->function = function; | ||
551 | } | ||
552 | EXPORT_SYMBOL_GPL(tasklet_hrtimer_init); | ||
553 | |||
554 | /* | ||
555 | * Remote softirq bits | ||
556 | */ | ||
557 | |||
496 | DEFINE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list); | 558 | DEFINE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list); |
497 | EXPORT_PER_CPU_SYMBOL(softirq_work_list); | 559 | EXPORT_PER_CPU_SYMBOL(softirq_work_list); |
498 | 560 | ||
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index 592bf584d1d2..7466cb811251 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c | |||
@@ -513,7 +513,7 @@ static ssize_t sysfs_override_clocksource(struct sys_device *dev, | |||
513 | * Check to make sure we don't switch to a non-highres capable | 513 | * Check to make sure we don't switch to a non-highres capable |
514 | * clocksource if the tick code is in oneshot mode (highres or nohz) | 514 | * clocksource if the tick code is in oneshot mode (highres or nohz) |
515 | */ | 515 | */ |
516 | if (tick_oneshot_mode_active() && | 516 | if (tick_oneshot_mode_active() && ovr && |
517 | !(ovr->flags & CLOCK_SOURCE_VALID_FOR_HRES)) { | 517 | !(ovr->flags & CLOCK_SOURCE_VALID_FOR_HRES)) { |
518 | printk(KERN_WARNING "%s clocksource is not HRT compatible. " | 518 | printk(KERN_WARNING "%s clocksource is not HRT compatible. " |
519 | "Cannot switch while in HRT/NOHZ mode\n", ovr->name); | 519 | "Cannot switch while in HRT/NOHZ mode\n", ovr->name); |
diff --git a/kernel/timer.c b/kernel/timer.c index 0b36b9e5cc8b..a7f07d5a6241 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -714,7 +714,7 @@ int mod_timer(struct timer_list *timer, unsigned long expires) | |||
714 | * networking code - if the timer is re-modified | 714 | * networking code - if the timer is re-modified |
715 | * to be the same thing then just return: | 715 | * to be the same thing then just return: |
716 | */ | 716 | */ |
717 | if (timer->expires == expires && timer_pending(timer)) | 717 | if (timer_pending(timer) && timer->expires == expires) |
718 | return 1; | 718 | return 1; |
719 | 719 | ||
720 | return __mod_timer(timer, expires, false, TIMER_NOT_PINNED); | 720 | return __mod_timer(timer, expires, false, TIMER_NOT_PINNED); |
diff --git a/net/can/bcm.c b/net/can/bcm.c index 95d7f32643ae..72720c710351 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c | |||
@@ -75,6 +75,7 @@ static __initdata const char banner[] = KERN_INFO | |||
75 | MODULE_DESCRIPTION("PF_CAN broadcast manager protocol"); | 75 | MODULE_DESCRIPTION("PF_CAN broadcast manager protocol"); |
76 | MODULE_LICENSE("Dual BSD/GPL"); | 76 | MODULE_LICENSE("Dual BSD/GPL"); |
77 | MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>"); | 77 | MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>"); |
78 | MODULE_ALIAS("can-proto-2"); | ||
78 | 79 | ||
79 | /* easy access to can_frame payload */ | 80 | /* easy access to can_frame payload */ |
80 | static inline u64 GET_U64(const struct can_frame *cp) | 81 | static inline u64 GET_U64(const struct can_frame *cp) |
@@ -1469,6 +1470,9 @@ static int bcm_release(struct socket *sock) | |||
1469 | bo->ifindex = 0; | 1470 | bo->ifindex = 0; |
1470 | } | 1471 | } |
1471 | 1472 | ||
1473 | sock_orphan(sk); | ||
1474 | sock->sk = NULL; | ||
1475 | |||
1472 | release_sock(sk); | 1476 | release_sock(sk); |
1473 | sock_put(sk); | 1477 | sock_put(sk); |
1474 | 1478 | ||
diff --git a/net/can/raw.c b/net/can/raw.c index 6aa154e806ae..f4cc44548bda 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
@@ -62,6 +62,7 @@ static __initdata const char banner[] = | |||
62 | MODULE_DESCRIPTION("PF_CAN raw protocol"); | 62 | MODULE_DESCRIPTION("PF_CAN raw protocol"); |
63 | MODULE_LICENSE("Dual BSD/GPL"); | 63 | MODULE_LICENSE("Dual BSD/GPL"); |
64 | MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>"); | 64 | MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>"); |
65 | MODULE_ALIAS("can-proto-1"); | ||
65 | 66 | ||
66 | #define MASK_ALL 0 | 67 | #define MASK_ALL 0 |
67 | 68 | ||
@@ -306,6 +307,9 @@ static int raw_release(struct socket *sock) | |||
306 | ro->bound = 0; | 307 | ro->bound = 0; |
307 | ro->count = 0; | 308 | ro->count = 0; |
308 | 309 | ||
310 | sock_orphan(sk); | ||
311 | sock->sk = NULL; | ||
312 | |||
309 | release_sock(sk); | 313 | release_sock(sk); |
310 | sock_put(sk); | 314 | sock_put(sk); |
311 | 315 | ||
diff --git a/net/core/sock.c b/net/core/sock.c index ba5d2116aea1..bbb25be7ddfe 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -631,7 +631,7 @@ set_rcvbuf: | |||
631 | 631 | ||
632 | case SO_TIMESTAMPING: | 632 | case SO_TIMESTAMPING: |
633 | if (val & ~SOF_TIMESTAMPING_MASK) { | 633 | if (val & ~SOF_TIMESTAMPING_MASK) { |
634 | ret = EINVAL; | 634 | ret = -EINVAL; |
635 | break; | 635 | break; |
636 | } | 636 | } |
637 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE, | 637 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE, |
@@ -919,13 +919,19 @@ static inline void sock_lock_init(struct sock *sk) | |||
919 | af_family_keys + sk->sk_family); | 919 | af_family_keys + sk->sk_family); |
920 | } | 920 | } |
921 | 921 | ||
922 | /* | ||
923 | * Copy all fields from osk to nsk but nsk->sk_refcnt must not change yet, | ||
924 | * even temporarly, because of RCU lookups. sk_node should also be left as is. | ||
925 | */ | ||
922 | static void sock_copy(struct sock *nsk, const struct sock *osk) | 926 | static void sock_copy(struct sock *nsk, const struct sock *osk) |
923 | { | 927 | { |
924 | #ifdef CONFIG_SECURITY_NETWORK | 928 | #ifdef CONFIG_SECURITY_NETWORK |
925 | void *sptr = nsk->sk_security; | 929 | void *sptr = nsk->sk_security; |
926 | #endif | 930 | #endif |
927 | 931 | BUILD_BUG_ON(offsetof(struct sock, sk_copy_start) != | |
928 | memcpy(nsk, osk, osk->sk_prot->obj_size); | 932 | sizeof(osk->sk_node) + sizeof(osk->sk_refcnt)); |
933 | memcpy(&nsk->sk_copy_start, &osk->sk_copy_start, | ||
934 | osk->sk_prot->obj_size - offsetof(struct sock, sk_copy_start)); | ||
929 | #ifdef CONFIG_SECURITY_NETWORK | 935 | #ifdef CONFIG_SECURITY_NETWORK |
930 | nsk->sk_security = sptr; | 936 | nsk->sk_security = sptr; |
931 | security_sk_clone(osk, nsk); | 937 | security_sk_clone(osk, nsk); |
@@ -1140,6 +1146,11 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) | |||
1140 | 1146 | ||
1141 | newsk->sk_err = 0; | 1147 | newsk->sk_err = 0; |
1142 | newsk->sk_priority = 0; | 1148 | newsk->sk_priority = 0; |
1149 | /* | ||
1150 | * Before updating sk_refcnt, we must commit prior changes to memory | ||
1151 | * (Documentation/RCU/rculist_nulls.txt for details) | ||
1152 | */ | ||
1153 | smp_wmb(); | ||
1143 | atomic_set(&newsk->sk_refcnt, 2); | 1154 | atomic_set(&newsk->sk_refcnt, 2); |
1144 | 1155 | ||
1145 | /* | 1156 | /* |
@@ -1855,6 +1866,11 @@ void sock_init_data(struct socket *sock, struct sock *sk) | |||
1855 | 1866 | ||
1856 | sk->sk_stamp = ktime_set(-1L, 0); | 1867 | sk->sk_stamp = ktime_set(-1L, 0); |
1857 | 1868 | ||
1869 | /* | ||
1870 | * Before updating sk_refcnt, we must commit prior changes to memory | ||
1871 | * (Documentation/RCU/rculist_nulls.txt for details) | ||
1872 | */ | ||
1873 | smp_wmb(); | ||
1858 | atomic_set(&sk->sk_refcnt, 1); | 1874 | atomic_set(&sk->sk_refcnt, 1); |
1859 | atomic_set(&sk->sk_wmem_alloc, 1); | 1875 | atomic_set(&sk->sk_wmem_alloc, 1); |
1860 | atomic_set(&sk->sk_drops, 0); | 1876 | atomic_set(&sk->sk_drops, 0); |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 5a1ca2698c88..6d88219c5e22 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1160,6 +1160,7 @@ struct request_sock_ops tcp_request_sock_ops __read_mostly = { | |||
1160 | #ifdef CONFIG_TCP_MD5SIG | 1160 | #ifdef CONFIG_TCP_MD5SIG |
1161 | static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { | 1161 | static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { |
1162 | .md5_lookup = tcp_v4_reqsk_md5_lookup, | 1162 | .md5_lookup = tcp_v4_reqsk_md5_lookup, |
1163 | .calc_md5_hash = tcp_v4_md5_hash_skb, | ||
1163 | }; | 1164 | }; |
1164 | #endif | 1165 | #endif |
1165 | 1166 | ||
@@ -1373,7 +1374,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1373 | */ | 1374 | */ |
1374 | char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); | 1375 | char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); |
1375 | if (newkey != NULL) | 1376 | if (newkey != NULL) |
1376 | tcp_v4_md5_do_add(newsk, inet_sk(sk)->daddr, | 1377 | tcp_v4_md5_do_add(newsk, newinet->daddr, |
1377 | newkey, key->keylen); | 1378 | newkey, key->keylen); |
1378 | newsk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 1379 | newsk->sk_route_caps &= ~NETIF_F_GSO_MASK; |
1379 | } | 1380 | } |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 5bdf08d312d9..bd62712848fa 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -2261,7 +2261,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2261 | #ifdef CONFIG_TCP_MD5SIG | 2261 | #ifdef CONFIG_TCP_MD5SIG |
2262 | /* Okay, we have all we need - do the md5 hash if needed */ | 2262 | /* Okay, we have all we need - do the md5 hash if needed */ |
2263 | if (md5) { | 2263 | if (md5) { |
2264 | tp->af_specific->calc_md5_hash(md5_hash_location, | 2264 | tcp_rsk(req)->af_specific->calc_md5_hash(md5_hash_location, |
2265 | md5, NULL, req, skb); | 2265 | md5, NULL, req, skb); |
2266 | } | 2266 | } |
2267 | #endif | 2267 | #endif |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 58810c65b635..d849dd53b788 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -896,6 +896,7 @@ struct request_sock_ops tcp6_request_sock_ops __read_mostly = { | |||
896 | #ifdef CONFIG_TCP_MD5SIG | 896 | #ifdef CONFIG_TCP_MD5SIG |
897 | static struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { | 897 | static struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { |
898 | .md5_lookup = tcp_v6_reqsk_md5_lookup, | 898 | .md5_lookup = tcp_v6_reqsk_md5_lookup, |
899 | .calc_md5_hash = tcp_v6_md5_hash_skb, | ||
899 | }; | 900 | }; |
900 | #endif | 901 | #endif |
901 | 902 | ||
@@ -1441,7 +1442,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1441 | */ | 1442 | */ |
1442 | char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); | 1443 | char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); |
1443 | if (newkey != NULL) | 1444 | if (newkey != NULL) |
1444 | tcp_v6_md5_do_add(newsk, &inet6_sk(sk)->daddr, | 1445 | tcp_v6_md5_do_add(newsk, &newnp->daddr, |
1445 | newkey, key->keylen); | 1446 | newkey, key->keylen); |
1446 | } | 1447 | } |
1447 | #endif | 1448 | #endif |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 7508f11c5b39..b5869b9574b0 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -561,23 +561,38 @@ struct nf_conn *nf_conntrack_alloc(struct net *net, | |||
561 | } | 561 | } |
562 | } | 562 | } |
563 | 563 | ||
564 | ct = kmem_cache_zalloc(nf_conntrack_cachep, gfp); | 564 | /* |
565 | * Do not use kmem_cache_zalloc(), as this cache uses | ||
566 | * SLAB_DESTROY_BY_RCU. | ||
567 | */ | ||
568 | ct = kmem_cache_alloc(nf_conntrack_cachep, gfp); | ||
565 | if (ct == NULL) { | 569 | if (ct == NULL) { |
566 | pr_debug("nf_conntrack_alloc: Can't alloc conntrack.\n"); | 570 | pr_debug("nf_conntrack_alloc: Can't alloc conntrack.\n"); |
567 | atomic_dec(&net->ct.count); | 571 | atomic_dec(&net->ct.count); |
568 | return ERR_PTR(-ENOMEM); | 572 | return ERR_PTR(-ENOMEM); |
569 | } | 573 | } |
570 | 574 | /* | |
575 | * Let ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.next | ||
576 | * and ct->tuplehash[IP_CT_DIR_REPLY].hnnode.next unchanged. | ||
577 | */ | ||
578 | memset(&ct->tuplehash[IP_CT_DIR_MAX], 0, | ||
579 | sizeof(*ct) - offsetof(struct nf_conn, tuplehash[IP_CT_DIR_MAX])); | ||
571 | spin_lock_init(&ct->lock); | 580 | spin_lock_init(&ct->lock); |
572 | atomic_set(&ct->ct_general.use, 1); | ||
573 | ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; | 581 | ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; |
582 | ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.pprev = NULL; | ||
574 | ct->tuplehash[IP_CT_DIR_REPLY].tuple = *repl; | 583 | ct->tuplehash[IP_CT_DIR_REPLY].tuple = *repl; |
584 | ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev = NULL; | ||
575 | /* Don't set timer yet: wait for confirmation */ | 585 | /* Don't set timer yet: wait for confirmation */ |
576 | setup_timer(&ct->timeout, death_by_timeout, (unsigned long)ct); | 586 | setup_timer(&ct->timeout, death_by_timeout, (unsigned long)ct); |
577 | #ifdef CONFIG_NET_NS | 587 | #ifdef CONFIG_NET_NS |
578 | ct->ct_net = net; | 588 | ct->ct_net = net; |
579 | #endif | 589 | #endif |
580 | 590 | ||
591 | /* | ||
592 | * changes to lookup keys must be done before setting refcnt to 1 | ||
593 | */ | ||
594 | smp_wmb(); | ||
595 | atomic_set(&ct->ct_general.use, 1); | ||
581 | return ct; | 596 | return ct; |
582 | } | 597 | } |
583 | EXPORT_SYMBOL_GPL(nf_conntrack_alloc); | 598 | EXPORT_SYMBOL_GPL(nf_conntrack_alloc); |
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c index 863e40977a4d..0f482e2440b4 100644 --- a/net/netfilter/xt_osf.c +++ b/net/netfilter/xt_osf.c | |||
@@ -330,7 +330,8 @@ static bool xt_osf_match_packet(const struct sk_buff *skb, | |||
330 | fcount++; | 330 | fcount++; |
331 | 331 | ||
332 | if (info->flags & XT_OSF_LOG) | 332 | if (info->flags & XT_OSF_LOG) |
333 | nf_log_packet(p->hooknum, 0, skb, p->in, p->out, NULL, | 333 | nf_log_packet(p->family, p->hooknum, skb, |
334 | p->in, p->out, NULL, | ||
334 | "%s [%s:%s] : %pi4:%d -> %pi4:%d hops=%d\n", | 335 | "%s [%s:%s] : %pi4:%d -> %pi4:%d hops=%d\n", |
335 | f->genre, f->version, f->subtype, | 336 | f->genre, f->version, f->subtype, |
336 | &ip->saddr, ntohs(tcp->source), | 337 | &ip->saddr, ntohs(tcp->source), |
@@ -345,7 +346,7 @@ static bool xt_osf_match_packet(const struct sk_buff *skb, | |||
345 | rcu_read_unlock(); | 346 | rcu_read_unlock(); |
346 | 347 | ||
347 | if (!fcount && (info->flags & XT_OSF_LOG)) | 348 | if (!fcount && (info->flags & XT_OSF_LOG)) |
348 | nf_log_packet(p->hooknum, 0, skb, p->in, p->out, NULL, | 349 | nf_log_packet(p->family, p->hooknum, skb, p->in, p->out, NULL, |
349 | "Remote OS is not known: %pi4:%u -> %pi4:%u\n", | 350 | "Remote OS is not known: %pi4:%u -> %pi4:%u\n", |
350 | &ip->saddr, ntohs(tcp->source), | 351 | &ip->saddr, ntohs(tcp->source), |
351 | &ip->daddr, ntohs(tcp->dest)); | 352 | &ip->daddr, ntohs(tcp->dest)); |
diff --git a/sound/core/seq/Makefile b/sound/core/seq/Makefile index 1bcb360330e5..941f64a853eb 100644 --- a/sound/core/seq/Makefile +++ b/sound/core/seq/Makefile | |||
@@ -3,10 +3,6 @@ | |||
3 | # Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> | 3 | # Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) | ||
7 | obj-$(CONFIG_SND_SEQUENCER) += oss/ | ||
8 | endif | ||
9 | |||
10 | snd-seq-device-objs := seq_device.o | 6 | snd-seq-device-objs := seq_device.o |
11 | snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \ | 7 | snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \ |
12 | seq_fifo.o seq_prioq.o seq_timer.o \ | 8 | seq_fifo.o seq_prioq.o seq_timer.o \ |
@@ -19,7 +15,8 @@ snd-seq-virmidi-objs := seq_virmidi.o | |||
19 | 15 | ||
20 | obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o snd-seq-device.o | 16 | obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o snd-seq-device.o |
21 | ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) | 17 | ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) |
22 | obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o | 18 | obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o |
19 | obj-$(CONFIG_SND_SEQUENCER) += oss/ | ||
23 | endif | 20 | endif |
24 | obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o | 21 | obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o |
25 | 22 | ||
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c index edb11eefdfe3..2dcf45bf7293 100644 --- a/sound/isa/gus/gus_pcm.c +++ b/sound/isa/gus/gus_pcm.c | |||
@@ -795,13 +795,13 @@ static int snd_gf1_pcm_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
795 | if (!(pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE)) | 795 | if (!(pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE)) |
796 | continue; | 796 | continue; |
797 | /* load real volume - better precision */ | 797 | /* load real volume - better precision */ |
798 | spin_lock_irqsave(&gus->reg_lock, flags); | 798 | spin_lock(&gus->reg_lock); |
799 | snd_gf1_select_voice(gus, pvoice->number); | 799 | snd_gf1_select_voice(gus, pvoice->number); |
800 | snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); | 800 | snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); |
801 | vol = pvoice == pcmp->pvoices[0] ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right; | 801 | vol = pvoice == pcmp->pvoices[0] ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right; |
802 | snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, vol); | 802 | snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, vol); |
803 | pcmp->final_volume = 1; | 803 | pcmp->final_volume = 1; |
804 | spin_unlock_irqrestore(&gus->reg_lock, flags); | 804 | spin_unlock(&gus->reg_lock); |
805 | } | 805 | } |
806 | spin_unlock_irqrestore(&gus->voice_alloc, flags); | 806 | spin_unlock_irqrestore(&gus->voice_alloc, flags); |
807 | return change; | 807 | return change; |
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index f24bf1ecb36d..15e4138bce17 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -325,9 +325,9 @@ static struct snd_pcm_hardware snd_ca0106_capture_hw = { | |||
325 | .rate_max = 192000, | 325 | .rate_max = 192000, |
326 | .channels_min = 2, | 326 | .channels_min = 2, |
327 | .channels_max = 2, | 327 | .channels_max = 2, |
328 | .buffer_bytes_max = ((65536 - 64) * 8), | 328 | .buffer_bytes_max = 65536 - 128, |
329 | .period_bytes_min = 64, | 329 | .period_bytes_min = 64, |
330 | .period_bytes_max = (65536 - 64), | 330 | .period_bytes_max = 32768 - 64, |
331 | .periods_min = 2, | 331 | .periods_min = 2, |
332 | .periods_max = 2, | 332 | .periods_max = 2, |
333 | .fifo_size = 0, | 333 | .fifo_size = 0, |
diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c index 082e35c08c02..deb6cfa73600 100644 --- a/sound/pci/ctxfi/ctdaio.c +++ b/sound/pci/ctxfi/ctdaio.c | |||
@@ -57,9 +57,9 @@ struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = { | |||
57 | 57 | ||
58 | struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = { | 58 | struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = { |
59 | [LINEO1] = {.left = 0x40, .right = 0x41}, | 59 | [LINEO1] = {.left = 0x40, .right = 0x41}, |
60 | [LINEO2] = {.left = 0x70, .right = 0x71}, | 60 | [LINEO2] = {.left = 0x60, .right = 0x61}, |
61 | [LINEO3] = {.left = 0x50, .right = 0x51}, | 61 | [LINEO3] = {.left = 0x50, .right = 0x51}, |
62 | [LINEO4] = {.left = 0x60, .right = 0x61}, | 62 | [LINEO4] = {.left = 0x70, .right = 0x71}, |
63 | [LINEIM] = {.left = 0x45, .right = 0xc5}, | 63 | [LINEIM] = {.left = 0x45, .right = 0xc5}, |
64 | [SPDIFOO] = {.left = 0x00, .right = 0x01}, | 64 | [SPDIFOO] = {.left = 0x00, .right = 0x01}, |
65 | [SPDIFIO] = {.left = 0x05, .right = 0x85}, | 65 | [SPDIFIO] = {.left = 0x05, .right = 0x85}, |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 26d255de6beb..88480c0c58a0 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -332,6 +332,12 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, | |||
332 | AC_VERB_GET_CONNECT_LIST, i); | 332 | AC_VERB_GET_CONNECT_LIST, i); |
333 | range_val = !!(parm & (1 << (shift-1))); /* ranges */ | 333 | range_val = !!(parm & (1 << (shift-1))); /* ranges */ |
334 | val = parm & mask; | 334 | val = parm & mask; |
335 | if (val == 0) { | ||
336 | snd_printk(KERN_WARNING "hda_codec: " | ||
337 | "invalid CONNECT_LIST verb %x[%i]:%x\n", | ||
338 | nid, i, parm); | ||
339 | return 0; | ||
340 | } | ||
335 | parm >>= shift; | 341 | parm >>= shift; |
336 | if (range_val) { | 342 | if (range_val) { |
337 | /* ranges between the previous and this one */ | 343 | /* ranges between the previous and this one */ |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 41b5b3a18c1e..da7f9f65c047 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -2378,6 +2378,7 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = { | |||
2378 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228, | 2378 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228, |
2379 | "Dell Vostro 1500", STAC_9205_DELL_M42), | 2379 | "Dell Vostro 1500", STAC_9205_DELL_M42), |
2380 | /* Gateway */ | 2380 | /* Gateway */ |
2381 | SND_PCI_QUIRK(0x107b, 0x0560, "Gateway T6834c", STAC_9205_EAPD), | ||
2381 | SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD), | 2382 | SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD), |
2382 | {} /* terminator */ | 2383 | {} /* terminator */ |
2383 | }; | 2384 | }; |
@@ -5854,6 +5855,8 @@ static unsigned int *stac9872_brd_tbl[STAC_9872_MODELS] = { | |||
5854 | }; | 5855 | }; |
5855 | 5856 | ||
5856 | static struct snd_pci_quirk stac9872_cfg_tbl[] = { | 5857 | static struct snd_pci_quirk stac9872_cfg_tbl[] = { |
5858 | SND_PCI_QUIRK_MASK(0x104d, 0xfff0, 0x81e0, | ||
5859 | "Sony VAIO F/S", STAC_9872_VAIO), | ||
5857 | {} /* terminator */ | 5860 | {} /* terminator */ |
5858 | }; | 5861 | }; |
5859 | 5862 | ||
@@ -5866,6 +5869,8 @@ static int patch_stac9872(struct hda_codec *codec) | |||
5866 | if (spec == NULL) | 5869 | if (spec == NULL) |
5867 | return -ENOMEM; | 5870 | return -ENOMEM; |
5868 | codec->spec = spec; | 5871 | codec->spec = spec; |
5872 | spec->num_pins = ARRAY_SIZE(stac9872_pin_nids); | ||
5873 | spec->pin_nids = stac9872_pin_nids; | ||
5869 | 5874 | ||
5870 | spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS, | 5875 | spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS, |
5871 | stac9872_models, | 5876 | stac9872_models, |
@@ -5877,8 +5882,6 @@ static int patch_stac9872(struct hda_codec *codec) | |||
5877 | stac92xx_set_config_regs(codec, | 5882 | stac92xx_set_config_regs(codec, |
5878 | stac9872_brd_tbl[spec->board_config]); | 5883 | stac9872_brd_tbl[spec->board_config]); |
5879 | 5884 | ||
5880 | spec->num_pins = ARRAY_SIZE(stac9872_pin_nids); | ||
5881 | spec->pin_nids = stac9872_pin_nids; | ||
5882 | spec->multiout.dac_nids = spec->dac_nids; | 5885 | spec->multiout.dac_nids = spec->dac_nids; |
5883 | spec->num_adcs = ARRAY_SIZE(stac9872_adc_nids); | 5886 | spec->num_adcs = ARRAY_SIZE(stac9872_adc_nids); |
5884 | spec->adc_nids = stac9872_adc_nids; | 5887 | spec->adc_nids = stac9872_adc_nids; |
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 8aa3f8c88707..e72e93110782 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt | |||
@@ -24,6 +24,9 @@ OPTIONS | |||
24 | --dsos=:: | 24 | --dsos=:: |
25 | Only consider symbols in these dsos. CSV that understands | 25 | Only consider symbols in these dsos. CSV that understands |
26 | file://filename entries. | 26 | file://filename entries. |
27 | -n | ||
28 | --show-nr-samples | ||
29 | Show the number of samples for each symbol | ||
27 | -C:: | 30 | -C:: |
28 | --comms=:: | 31 | --comms=:: |
29 | Only consider symbols in these comms. CSV that understands | 32 | Only consider symbols in these comms. CSV that understands |
@@ -33,6 +36,18 @@ OPTIONS | |||
33 | Only consider these symbols. CSV that understands | 36 | Only consider these symbols. CSV that understands |
34 | file://filename entries. | 37 | file://filename entries. |
35 | 38 | ||
39 | -w:: | ||
40 | --field-width=:: | ||
41 | Force each column width to the provided list, for large terminal | ||
42 | readability. | ||
43 | |||
44 | -t:: | ||
45 | --field-separator=:: | ||
46 | |||
47 | Use a special separator character and don't pad with spaces, replacing | ||
48 | all occurances of this separator in symbol names (and other output) | ||
49 | with a '.' character, that thus it's the only non valid separator. | ||
50 | |||
36 | SEE ALSO | 51 | SEE ALSO |
37 | -------- | 52 | -------- |
38 | linkperf:perf-stat[1] | 53 | linkperf:perf-stat[1] |
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 7822b3d6baca..a5e9b876ca09 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
@@ -345,7 +345,7 @@ BUILTIN_OBJS += builtin-stat.o | |||
345 | BUILTIN_OBJS += builtin-top.o | 345 | BUILTIN_OBJS += builtin-top.o |
346 | 346 | ||
347 | PERFLIBS = $(LIB_FILE) | 347 | PERFLIBS = $(LIB_FILE) |
348 | EXTLIBS = | 348 | EXTLIBS = -lbfd |
349 | 349 | ||
350 | # | 350 | # |
351 | # Platform specific tweaks | 351 | # Platform specific tweaks |
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 5f9eefecc574..1dba568e1941 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -74,20 +74,12 @@ struct fork_event { | |||
74 | u32 pid, ppid; | 74 | u32 pid, ppid; |
75 | }; | 75 | }; |
76 | 76 | ||
77 | struct period_event { | ||
78 | struct perf_event_header header; | ||
79 | u64 time; | ||
80 | u64 id; | ||
81 | u64 sample_period; | ||
82 | }; | ||
83 | |||
84 | typedef union event_union { | 77 | typedef union event_union { |
85 | struct perf_event_header header; | 78 | struct perf_event_header header; |
86 | struct ip_event ip; | 79 | struct ip_event ip; |
87 | struct mmap_event mmap; | 80 | struct mmap_event mmap; |
88 | struct comm_event comm; | 81 | struct comm_event comm; |
89 | struct fork_event fork; | 82 | struct fork_event fork; |
90 | struct period_event period; | ||
91 | } event_t; | 83 | } event_t; |
92 | 84 | ||
93 | 85 | ||
@@ -998,19 +990,6 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head) | |||
998 | } | 990 | } |
999 | 991 | ||
1000 | static int | 992 | static int |
1001 | process_period_event(event_t *event, unsigned long offset, unsigned long head) | ||
1002 | { | ||
1003 | dprintf("%p [%p]: PERF_EVENT_PERIOD: time:%Ld, id:%Ld: period:%Ld\n", | ||
1004 | (void *)(offset + head), | ||
1005 | (void *)(long)(event->header.size), | ||
1006 | event->period.time, | ||
1007 | event->period.id, | ||
1008 | event->period.sample_period); | ||
1009 | |||
1010 | return 0; | ||
1011 | } | ||
1012 | |||
1013 | static int | ||
1014 | process_event(event_t *event, unsigned long offset, unsigned long head) | 993 | process_event(event_t *event, unsigned long offset, unsigned long head) |
1015 | { | 994 | { |
1016 | switch (event->header.type) { | 995 | switch (event->header.type) { |
@@ -1025,9 +1004,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head) | |||
1025 | 1004 | ||
1026 | case PERF_EVENT_FORK: | 1005 | case PERF_EVENT_FORK: |
1027 | return process_fork_event(event, offset, head); | 1006 | return process_fork_event(event, offset, head); |
1028 | |||
1029 | case PERF_EVENT_PERIOD: | ||
1030 | return process_period_event(event, offset, head); | ||
1031 | /* | 1007 | /* |
1032 | * We dont process them right now but they are fine: | 1008 | * We dont process them right now but they are fine: |
1033 | */ | 1009 | */ |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 4ef78a5e6f32..6da09928130f 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -43,6 +43,7 @@ static int call_graph = 0; | |||
43 | static int verbose = 0; | 43 | static int verbose = 0; |
44 | static int inherit_stat = 0; | 44 | static int inherit_stat = 0; |
45 | static int no_samples = 0; | 45 | static int no_samples = 0; |
46 | static int sample_address = 0; | ||
46 | 47 | ||
47 | static long samples; | 48 | static long samples; |
48 | static struct timeval last_read; | 49 | static struct timeval last_read; |
@@ -313,6 +314,10 @@ static void pid_synthesize_mmap_samples(pid_t pid) | |||
313 | if (*pbf == 'x') { /* vm_exec */ | 314 | if (*pbf == 'x') { /* vm_exec */ |
314 | char *execname = strchr(bf, '/'); | 315 | char *execname = strchr(bf, '/'); |
315 | 316 | ||
317 | /* Catch VDSO */ | ||
318 | if (execname == NULL) | ||
319 | execname = strstr(bf, "[vdso]"); | ||
320 | |||
316 | if (execname == NULL) | 321 | if (execname == NULL) |
317 | continue; | 322 | continue; |
318 | 323 | ||
@@ -401,6 +406,9 @@ static void create_counter(int counter, int cpu, pid_t pid) | |||
401 | if (inherit_stat) | 406 | if (inherit_stat) |
402 | attr->inherit_stat = 1; | 407 | attr->inherit_stat = 1; |
403 | 408 | ||
409 | if (sample_address) | ||
410 | attr->sample_type |= PERF_SAMPLE_ADDR; | ||
411 | |||
404 | if (call_graph) | 412 | if (call_graph) |
405 | attr->sample_type |= PERF_SAMPLE_CALLCHAIN; | 413 | attr->sample_type |= PERF_SAMPLE_CALLCHAIN; |
406 | 414 | ||
@@ -645,6 +653,8 @@ static const struct option options[] = { | |||
645 | "be more verbose (show counter open errors, etc)"), | 653 | "be more verbose (show counter open errors, etc)"), |
646 | OPT_BOOLEAN('s', "stat", &inherit_stat, | 654 | OPT_BOOLEAN('s', "stat", &inherit_stat, |
647 | "per thread counts"), | 655 | "per thread counts"), |
656 | OPT_BOOLEAN('d', "data", &sample_address, | ||
657 | "Sample addresses"), | ||
648 | OPT_BOOLEAN('n', "no-samples", &no_samples, | 658 | OPT_BOOLEAN('n', "no-samples", &no_samples, |
649 | "don't sample"), | 659 | "don't sample"), |
650 | OPT_END() | 660 | OPT_END() |
@@ -654,7 +664,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) | |||
654 | { | 664 | { |
655 | int counter; | 665 | int counter; |
656 | 666 | ||
657 | argc = parse_options(argc, argv, options, record_usage, 0); | 667 | argc = parse_options(argc, argv, options, record_usage, |
668 | PARSE_OPT_STOP_AT_NON_OPTION); | ||
658 | if (!argc && target_pid == -1 && !system_wide) | 669 | if (!argc && target_pid == -1 && !system_wide) |
659 | usage_with_options(record_usage, options); | 670 | usage_with_options(record_usage, options); |
660 | 671 | ||
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 4e5cc266311e..b20a4b6e31b7 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -33,8 +33,10 @@ static char *vmlinux = NULL; | |||
33 | 33 | ||
34 | static char default_sort_order[] = "comm,dso"; | 34 | static char default_sort_order[] = "comm,dso"; |
35 | static char *sort_order = default_sort_order; | 35 | static char *sort_order = default_sort_order; |
36 | static char *dso_list_str, *comm_list_str, *sym_list_str; | 36 | static char *dso_list_str, *comm_list_str, *sym_list_str, |
37 | *col_width_list_str; | ||
37 | static struct strlist *dso_list, *comm_list, *sym_list; | 38 | static struct strlist *dso_list, *comm_list, *sym_list; |
39 | static char *field_sep; | ||
38 | 40 | ||
39 | static int input; | 41 | static int input; |
40 | static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; | 42 | static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; |
@@ -49,6 +51,7 @@ static int verbose; | |||
49 | static int modules; | 51 | static int modules; |
50 | 52 | ||
51 | static int full_paths; | 53 | static int full_paths; |
54 | static int show_nr_samples; | ||
52 | 55 | ||
53 | static unsigned long page_size; | 56 | static unsigned long page_size; |
54 | static unsigned long mmap_window = 32; | 57 | static unsigned long mmap_window = 32; |
@@ -98,13 +101,6 @@ struct fork_event { | |||
98 | u32 pid, ppid; | 101 | u32 pid, ppid; |
99 | }; | 102 | }; |
100 | 103 | ||
101 | struct period_event { | ||
102 | struct perf_event_header header; | ||
103 | u64 time; | ||
104 | u64 id; | ||
105 | u64 sample_period; | ||
106 | }; | ||
107 | |||
108 | struct lost_event { | 104 | struct lost_event { |
109 | struct perf_event_header header; | 105 | struct perf_event_header header; |
110 | u64 id; | 106 | u64 id; |
@@ -124,11 +120,37 @@ typedef union event_union { | |||
124 | struct mmap_event mmap; | 120 | struct mmap_event mmap; |
125 | struct comm_event comm; | 121 | struct comm_event comm; |
126 | struct fork_event fork; | 122 | struct fork_event fork; |
127 | struct period_event period; | ||
128 | struct lost_event lost; | 123 | struct lost_event lost; |
129 | struct read_event read; | 124 | struct read_event read; |
130 | } event_t; | 125 | } event_t; |
131 | 126 | ||
127 | static int repsep_fprintf(FILE *fp, const char *fmt, ...) | ||
128 | { | ||
129 | int n; | ||
130 | va_list ap; | ||
131 | |||
132 | va_start(ap, fmt); | ||
133 | if (!field_sep) | ||
134 | n = vfprintf(fp, fmt, ap); | ||
135 | else { | ||
136 | char *bf = NULL; | ||
137 | n = vasprintf(&bf, fmt, ap); | ||
138 | if (n > 0) { | ||
139 | char *sep = bf; | ||
140 | while (1) { | ||
141 | sep = strchr(sep, *field_sep); | ||
142 | if (sep == NULL) | ||
143 | break; | ||
144 | *sep = '.'; | ||
145 | } | ||
146 | } | ||
147 | fputs(bf, fp); | ||
148 | free(bf); | ||
149 | } | ||
150 | va_end(ap); | ||
151 | return n; | ||
152 | } | ||
153 | |||
132 | static LIST_HEAD(dsos); | 154 | static LIST_HEAD(dsos); |
133 | static struct dso *kernel_dso; | 155 | static struct dso *kernel_dso; |
134 | static struct dso *vdso; | 156 | static struct dso *vdso; |
@@ -360,12 +382,28 @@ static struct thread *thread__new(pid_t pid) | |||
360 | return self; | 382 | return self; |
361 | } | 383 | } |
362 | 384 | ||
385 | static unsigned int dsos__col_width, | ||
386 | comms__col_width, | ||
387 | threads__col_width; | ||
388 | |||
363 | static int thread__set_comm(struct thread *self, const char *comm) | 389 | static int thread__set_comm(struct thread *self, const char *comm) |
364 | { | 390 | { |
365 | if (self->comm) | 391 | if (self->comm) |
366 | free(self->comm); | 392 | free(self->comm); |
367 | self->comm = strdup(comm); | 393 | self->comm = strdup(comm); |
368 | return self->comm ? 0 : -ENOMEM; | 394 | if (!self->comm) |
395 | return -ENOMEM; | ||
396 | |||
397 | if (!col_width_list_str && !field_sep && | ||
398 | (!comm_list || strlist__has_entry(comm_list, comm))) { | ||
399 | unsigned int slen = strlen(comm); | ||
400 | if (slen > comms__col_width) { | ||
401 | comms__col_width = slen; | ||
402 | threads__col_width = slen + 6; | ||
403 | } | ||
404 | } | ||
405 | |||
406 | return 0; | ||
369 | } | 407 | } |
370 | 408 | ||
371 | static size_t thread__fprintf(struct thread *self, FILE *fp) | 409 | static size_t thread__fprintf(struct thread *self, FILE *fp) |
@@ -536,7 +574,9 @@ struct sort_entry { | |||
536 | 574 | ||
537 | int64_t (*cmp)(struct hist_entry *, struct hist_entry *); | 575 | int64_t (*cmp)(struct hist_entry *, struct hist_entry *); |
538 | int64_t (*collapse)(struct hist_entry *, struct hist_entry *); | 576 | int64_t (*collapse)(struct hist_entry *, struct hist_entry *); |
539 | size_t (*print)(FILE *fp, struct hist_entry *); | 577 | size_t (*print)(FILE *fp, struct hist_entry *, unsigned int width); |
578 | unsigned int *width; | ||
579 | bool elide; | ||
540 | }; | 580 | }; |
541 | 581 | ||
542 | static int64_t cmp_null(void *l, void *r) | 582 | static int64_t cmp_null(void *l, void *r) |
@@ -558,15 +598,17 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right) | |||
558 | } | 598 | } |
559 | 599 | ||
560 | static size_t | 600 | static size_t |
561 | sort__thread_print(FILE *fp, struct hist_entry *self) | 601 | sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width) |
562 | { | 602 | { |
563 | return fprintf(fp, "%16s:%5d", self->thread->comm ?: "", self->thread->pid); | 603 | return repsep_fprintf(fp, "%*s:%5d", width - 6, |
604 | self->thread->comm ?: "", self->thread->pid); | ||
564 | } | 605 | } |
565 | 606 | ||
566 | static struct sort_entry sort_thread = { | 607 | static struct sort_entry sort_thread = { |
567 | .header = " Command: Pid", | 608 | .header = "Command: Pid", |
568 | .cmp = sort__thread_cmp, | 609 | .cmp = sort__thread_cmp, |
569 | .print = sort__thread_print, | 610 | .print = sort__thread_print, |
611 | .width = &threads__col_width, | ||
570 | }; | 612 | }; |
571 | 613 | ||
572 | /* --sort comm */ | 614 | /* --sort comm */ |
@@ -590,16 +632,17 @@ sort__comm_collapse(struct hist_entry *left, struct hist_entry *right) | |||
590 | } | 632 | } |
591 | 633 | ||
592 | static size_t | 634 | static size_t |
593 | sort__comm_print(FILE *fp, struct hist_entry *self) | 635 | sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width) |
594 | { | 636 | { |
595 | return fprintf(fp, "%16s", self->thread->comm); | 637 | return repsep_fprintf(fp, "%*s", width, self->thread->comm); |
596 | } | 638 | } |
597 | 639 | ||
598 | static struct sort_entry sort_comm = { | 640 | static struct sort_entry sort_comm = { |
599 | .header = " Command", | 641 | .header = "Command", |
600 | .cmp = sort__comm_cmp, | 642 | .cmp = sort__comm_cmp, |
601 | .collapse = sort__comm_collapse, | 643 | .collapse = sort__comm_collapse, |
602 | .print = sort__comm_print, | 644 | .print = sort__comm_print, |
645 | .width = &comms__col_width, | ||
603 | }; | 646 | }; |
604 | 647 | ||
605 | /* --sort dso */ | 648 | /* --sort dso */ |
@@ -617,18 +660,19 @@ sort__dso_cmp(struct hist_entry *left, struct hist_entry *right) | |||
617 | } | 660 | } |
618 | 661 | ||
619 | static size_t | 662 | static size_t |
620 | sort__dso_print(FILE *fp, struct hist_entry *self) | 663 | sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width) |
621 | { | 664 | { |
622 | if (self->dso) | 665 | if (self->dso) |
623 | return fprintf(fp, "%-25s", self->dso->name); | 666 | return repsep_fprintf(fp, "%-*s", width, self->dso->name); |
624 | 667 | ||
625 | return fprintf(fp, "%016llx ", (u64)self->ip); | 668 | return repsep_fprintf(fp, "%*llx", width, (u64)self->ip); |
626 | } | 669 | } |
627 | 670 | ||
628 | static struct sort_entry sort_dso = { | 671 | static struct sort_entry sort_dso = { |
629 | .header = "Shared Object ", | 672 | .header = "Shared Object", |
630 | .cmp = sort__dso_cmp, | 673 | .cmp = sort__dso_cmp, |
631 | .print = sort__dso_print, | 674 | .print = sort__dso_print, |
675 | .width = &dsos__col_width, | ||
632 | }; | 676 | }; |
633 | 677 | ||
634 | /* --sort symbol */ | 678 | /* --sort symbol */ |
@@ -648,22 +692,22 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) | |||
648 | } | 692 | } |
649 | 693 | ||
650 | static size_t | 694 | static size_t |
651 | sort__sym_print(FILE *fp, struct hist_entry *self) | 695 | sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used) |
652 | { | 696 | { |
653 | size_t ret = 0; | 697 | size_t ret = 0; |
654 | 698 | ||
655 | if (verbose) | 699 | if (verbose) |
656 | ret += fprintf(fp, "%#018llx ", (u64)self->ip); | 700 | ret += repsep_fprintf(fp, "%#018llx ", (u64)self->ip); |
657 | 701 | ||
702 | ret += repsep_fprintf(fp, "[%c] ", self->level); | ||
658 | if (self->sym) { | 703 | if (self->sym) { |
659 | ret += fprintf(fp, "[%c] %s", | 704 | ret += repsep_fprintf(fp, "%s", self->sym->name); |
660 | self->dso == kernel_dso ? 'k' : | ||
661 | self->dso == hypervisor_dso ? 'h' : '.', self->sym->name); | ||
662 | 705 | ||
663 | if (self->sym->module) | 706 | if (self->sym->module) |
664 | ret += fprintf(fp, "\t[%s]", self->sym->module->name); | 707 | ret += repsep_fprintf(fp, "\t[%s]", |
708 | self->sym->module->name); | ||
665 | } else { | 709 | } else { |
666 | ret += fprintf(fp, "%#016llx", (u64)self->ip); | 710 | ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip); |
667 | } | 711 | } |
668 | 712 | ||
669 | return ret; | 713 | return ret; |
@@ -690,19 +734,19 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right) | |||
690 | } | 734 | } |
691 | 735 | ||
692 | static size_t | 736 | static size_t |
693 | sort__parent_print(FILE *fp, struct hist_entry *self) | 737 | sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width) |
694 | { | 738 | { |
695 | size_t ret = 0; | 739 | return repsep_fprintf(fp, "%-*s", width, |
696 | 740 | self->parent ? self->parent->name : "[other]"); | |
697 | ret += fprintf(fp, "%-20s", self->parent ? self->parent->name : "[other]"); | ||
698 | |||
699 | return ret; | ||
700 | } | 741 | } |
701 | 742 | ||
743 | static unsigned int parent_symbol__col_width; | ||
744 | |||
702 | static struct sort_entry sort_parent = { | 745 | static struct sort_entry sort_parent = { |
703 | .header = "Parent symbol ", | 746 | .header = "Parent symbol", |
704 | .cmp = sort__parent_cmp, | 747 | .cmp = sort__parent_cmp, |
705 | .print = sort__parent_print, | 748 | .print = sort__parent_print, |
749 | .width = &parent_symbol__col_width, | ||
706 | }; | 750 | }; |
707 | 751 | ||
708 | static int sort__need_collapse = 0; | 752 | static int sort__need_collapse = 0; |
@@ -967,17 +1011,25 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples) | |||
967 | return 0; | 1011 | return 0; |
968 | 1012 | ||
969 | if (total_samples) | 1013 | if (total_samples) |
970 | ret = percent_color_fprintf(fp, " %6.2f%%", | 1014 | ret = percent_color_fprintf(fp, |
971 | (self->count * 100.0) / total_samples); | 1015 | field_sep ? "%.2f" : " %6.2f%%", |
1016 | (self->count * 100.0) / total_samples); | ||
972 | else | 1017 | else |
973 | ret = fprintf(fp, "%12Ld ", self->count); | 1018 | ret = fprintf(fp, field_sep ? "%lld" : "%12lld ", self->count); |
1019 | |||
1020 | if (show_nr_samples) { | ||
1021 | if (field_sep) | ||
1022 | fprintf(fp, "%c%lld", *field_sep, self->count); | ||
1023 | else | ||
1024 | fprintf(fp, "%11lld", self->count); | ||
1025 | } | ||
974 | 1026 | ||
975 | list_for_each_entry(se, &hist_entry__sort_list, list) { | 1027 | list_for_each_entry(se, &hist_entry__sort_list, list) { |
976 | if (exclude_other && (se == &sort_parent)) | 1028 | if (se->elide) |
977 | continue; | 1029 | continue; |
978 | 1030 | ||
979 | fprintf(fp, " "); | 1031 | fprintf(fp, "%s", field_sep ?: " "); |
980 | ret += se->print(fp, self); | 1032 | ret += se->print(fp, self, se->width ? *se->width : 0); |
981 | } | 1033 | } |
982 | 1034 | ||
983 | ret += fprintf(fp, "\n"); | 1035 | ret += fprintf(fp, "\n"); |
@@ -992,6 +1044,18 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples) | |||
992 | * | 1044 | * |
993 | */ | 1045 | */ |
994 | 1046 | ||
1047 | static void dso__calc_col_width(struct dso *self) | ||
1048 | { | ||
1049 | if (!col_width_list_str && !field_sep && | ||
1050 | (!dso_list || strlist__has_entry(dso_list, self->name))) { | ||
1051 | unsigned int slen = strlen(self->name); | ||
1052 | if (slen > dsos__col_width) | ||
1053 | dsos__col_width = slen; | ||
1054 | } | ||
1055 | |||
1056 | self->slen_calculated = 1; | ||
1057 | } | ||
1058 | |||
995 | static struct symbol * | 1059 | static struct symbol * |
996 | resolve_symbol(struct thread *thread, struct map **mapp, | 1060 | resolve_symbol(struct thread *thread, struct map **mapp, |
997 | struct dso **dsop, u64 *ipp) | 1061 | struct dso **dsop, u64 *ipp) |
@@ -1011,6 +1075,14 @@ resolve_symbol(struct thread *thread, struct map **mapp, | |||
1011 | 1075 | ||
1012 | map = thread__find_map(thread, ip); | 1076 | map = thread__find_map(thread, ip); |
1013 | if (map != NULL) { | 1077 | if (map != NULL) { |
1078 | /* | ||
1079 | * We have to do this here as we may have a dso | ||
1080 | * with no symbol hit that has a name longer than | ||
1081 | * the ones with symbols sampled. | ||
1082 | */ | ||
1083 | if (!sort_dso.elide && !map->dso->slen_calculated) | ||
1084 | dso__calc_col_width(map->dso); | ||
1085 | |||
1014 | if (mapp) | 1086 | if (mapp) |
1015 | *mapp = map; | 1087 | *mapp = map; |
1016 | got_map: | 1088 | got_map: |
@@ -1282,35 +1354,67 @@ static size_t output__fprintf(FILE *fp, u64 total_samples) | |||
1282 | struct sort_entry *se; | 1354 | struct sort_entry *se; |
1283 | struct rb_node *nd; | 1355 | struct rb_node *nd; |
1284 | size_t ret = 0; | 1356 | size_t ret = 0; |
1357 | unsigned int width; | ||
1358 | char *col_width = col_width_list_str; | ||
1285 | 1359 | ||
1286 | fprintf(fp, "\n"); | 1360 | fprintf(fp, "# Samples: %Ld\n", (u64)total_samples); |
1287 | fprintf(fp, "#\n"); | ||
1288 | fprintf(fp, "# (%Ld samples)\n", (u64)total_samples); | ||
1289 | fprintf(fp, "#\n"); | 1361 | fprintf(fp, "#\n"); |
1290 | 1362 | ||
1291 | fprintf(fp, "# Overhead"); | 1363 | fprintf(fp, "# Overhead"); |
1364 | if (show_nr_samples) { | ||
1365 | if (field_sep) | ||
1366 | fprintf(fp, "%cSamples", *field_sep); | ||
1367 | else | ||
1368 | fputs(" Samples ", fp); | ||
1369 | } | ||
1292 | list_for_each_entry(se, &hist_entry__sort_list, list) { | 1370 | list_for_each_entry(se, &hist_entry__sort_list, list) { |
1293 | if (exclude_other && (se == &sort_parent)) | 1371 | if (se->elide) |
1294 | continue; | 1372 | continue; |
1295 | fprintf(fp, " %s", se->header); | 1373 | if (field_sep) { |
1374 | fprintf(fp, "%c%s", *field_sep, se->header); | ||
1375 | continue; | ||
1376 | } | ||
1377 | width = strlen(se->header); | ||
1378 | if (se->width) { | ||
1379 | if (col_width_list_str) { | ||
1380 | if (col_width) { | ||
1381 | *se->width = atoi(col_width); | ||
1382 | col_width = strchr(col_width, ','); | ||
1383 | if (col_width) | ||
1384 | ++col_width; | ||
1385 | } | ||
1386 | } | ||
1387 | width = *se->width = max(*se->width, width); | ||
1388 | } | ||
1389 | fprintf(fp, " %*s", width, se->header); | ||
1296 | } | 1390 | } |
1297 | fprintf(fp, "\n"); | 1391 | fprintf(fp, "\n"); |
1298 | 1392 | ||
1393 | if (field_sep) | ||
1394 | goto print_entries; | ||
1395 | |||
1299 | fprintf(fp, "# ........"); | 1396 | fprintf(fp, "# ........"); |
1397 | if (show_nr_samples) | ||
1398 | fprintf(fp, " .........."); | ||
1300 | list_for_each_entry(se, &hist_entry__sort_list, list) { | 1399 | list_for_each_entry(se, &hist_entry__sort_list, list) { |
1301 | unsigned int i; | 1400 | unsigned int i; |
1302 | 1401 | ||
1303 | if (exclude_other && (se == &sort_parent)) | 1402 | if (se->elide) |
1304 | continue; | 1403 | continue; |
1305 | 1404 | ||
1306 | fprintf(fp, " "); | 1405 | fprintf(fp, " "); |
1307 | for (i = 0; i < strlen(se->header); i++) | 1406 | if (se->width) |
1407 | width = *se->width; | ||
1408 | else | ||
1409 | width = strlen(se->header); | ||
1410 | for (i = 0; i < width; i++) | ||
1308 | fprintf(fp, "."); | 1411 | fprintf(fp, "."); |
1309 | } | 1412 | } |
1310 | fprintf(fp, "\n"); | 1413 | fprintf(fp, "\n"); |
1311 | 1414 | ||
1312 | fprintf(fp, "#\n"); | 1415 | fprintf(fp, "#\n"); |
1313 | 1416 | ||
1417 | print_entries: | ||
1314 | for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) { | 1418 | for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) { |
1315 | pos = rb_entry(nd, struct hist_entry, rb_node); | 1419 | pos = rb_entry(nd, struct hist_entry, rb_node); |
1316 | ret += hist_entry__fprintf(fp, pos, total_samples); | 1420 | ret += hist_entry__fprintf(fp, pos, total_samples); |
@@ -1524,19 +1628,6 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head) | |||
1524 | } | 1628 | } |
1525 | 1629 | ||
1526 | static int | 1630 | static int |
1527 | process_period_event(event_t *event, unsigned long offset, unsigned long head) | ||
1528 | { | ||
1529 | dprintf("%p [%p]: PERF_EVENT_PERIOD: time:%Ld, id:%Ld: period:%Ld\n", | ||
1530 | (void *)(offset + head), | ||
1531 | (void *)(long)(event->header.size), | ||
1532 | event->period.time, | ||
1533 | event->period.id, | ||
1534 | event->period.sample_period); | ||
1535 | |||
1536 | return 0; | ||
1537 | } | ||
1538 | |||
1539 | static int | ||
1540 | process_lost_event(event_t *event, unsigned long offset, unsigned long head) | 1631 | process_lost_event(event_t *event, unsigned long offset, unsigned long head) |
1541 | { | 1632 | { |
1542 | dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n", | 1633 | dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n", |
@@ -1617,9 +1708,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head) | |||
1617 | case PERF_EVENT_FORK: | 1708 | case PERF_EVENT_FORK: |
1618 | return process_fork_event(event, offset, head); | 1709 | return process_fork_event(event, offset, head); |
1619 | 1710 | ||
1620 | case PERF_EVENT_PERIOD: | ||
1621 | return process_period_event(event, offset, head); | ||
1622 | |||
1623 | case PERF_EVENT_LOST: | 1711 | case PERF_EVENT_LOST: |
1624 | return process_lost_event(event, offset, head); | 1712 | return process_lost_event(event, offset, head); |
1625 | 1713 | ||
@@ -1883,6 +1971,8 @@ static const struct option options[] = { | |||
1883 | OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), | 1971 | OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), |
1884 | OPT_BOOLEAN('m', "modules", &modules, | 1972 | OPT_BOOLEAN('m', "modules", &modules, |
1885 | "load module symbols - WARNING: use only with -k and LIVE kernel"), | 1973 | "load module symbols - WARNING: use only with -k and LIVE kernel"), |
1974 | OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples, | ||
1975 | "Show a column with the number of samples"), | ||
1886 | OPT_STRING('s', "sort", &sort_order, "key[,key2...]", | 1976 | OPT_STRING('s', "sort", &sort_order, "key[,key2...]", |
1887 | "sort by key(s): pid, comm, dso, symbol, parent"), | 1977 | "sort by key(s): pid, comm, dso, symbol, parent"), |
1888 | OPT_BOOLEAN('P', "full-paths", &full_paths, | 1978 | OPT_BOOLEAN('P', "full-paths", &full_paths, |
@@ -1891,15 +1981,21 @@ static const struct option options[] = { | |||
1891 | "regex filter to identify parent, see: '--sort parent'"), | 1981 | "regex filter to identify parent, see: '--sort parent'"), |
1892 | OPT_BOOLEAN('x', "exclude-other", &exclude_other, | 1982 | OPT_BOOLEAN('x', "exclude-other", &exclude_other, |
1893 | "Only display entries with parent-match"), | 1983 | "Only display entries with parent-match"), |
1894 | OPT_CALLBACK_DEFAULT('c', "callchain", NULL, "output_type,min_percent", | 1984 | OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent", |
1895 | "Display callchains using output_type and min percent threshold. " | 1985 | "Display callchains using output_type and min percent threshold. " |
1896 | "Default: flat,0", &parse_callchain_opt, callchain_default_opt), | 1986 | "Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt), |
1897 | OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]", | 1987 | OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]", |
1898 | "only consider symbols in these dsos"), | 1988 | "only consider symbols in these dsos"), |
1899 | OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]", | 1989 | OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]", |
1900 | "only consider symbols in these comms"), | 1990 | "only consider symbols in these comms"), |
1901 | OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]", | 1991 | OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]", |
1902 | "only consider these symbols"), | 1992 | "only consider these symbols"), |
1993 | OPT_STRING('w', "column-widths", &col_width_list_str, | ||
1994 | "width[,width...]", | ||
1995 | "don't try to adjust column width, use these fixed values"), | ||
1996 | OPT_STRING('t', "field-separator", &field_sep, "separator", | ||
1997 | "separator for columns, no spaces will be added between " | ||
1998 | "columns '.' is reserved."), | ||
1903 | OPT_END() | 1999 | OPT_END() |
1904 | }; | 2000 | }; |
1905 | 2001 | ||
@@ -1919,7 +2015,8 @@ static void setup_sorting(void) | |||
1919 | } | 2015 | } |
1920 | 2016 | ||
1921 | static void setup_list(struct strlist **list, const char *list_str, | 2017 | static void setup_list(struct strlist **list, const char *list_str, |
1922 | const char *list_name) | 2018 | struct sort_entry *se, const char *list_name, |
2019 | FILE *fp) | ||
1923 | { | 2020 | { |
1924 | if (list_str) { | 2021 | if (list_str) { |
1925 | *list = strlist__new(true, list_str); | 2022 | *list = strlist__new(true, list_str); |
@@ -1928,6 +2025,11 @@ static void setup_list(struct strlist **list, const char *list_str, | |||
1928 | list_name); | 2025 | list_name); |
1929 | exit(129); | 2026 | exit(129); |
1930 | } | 2027 | } |
2028 | if (strlist__nr_entries(*list) == 1) { | ||
2029 | fprintf(fp, "# %s: %s\n", list_name, | ||
2030 | strlist__entry(*list, 0)->s); | ||
2031 | se->elide = true; | ||
2032 | } | ||
1931 | } | 2033 | } |
1932 | } | 2034 | } |
1933 | 2035 | ||
@@ -1941,9 +2043,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) | |||
1941 | 2043 | ||
1942 | setup_sorting(); | 2044 | setup_sorting(); |
1943 | 2045 | ||
1944 | if (parent_pattern != default_parent_pattern) | 2046 | if (parent_pattern != default_parent_pattern) { |
1945 | sort_dimension__add("parent"); | 2047 | sort_dimension__add("parent"); |
1946 | else | 2048 | sort_parent.elide = 1; |
2049 | } else | ||
1947 | exclude_other = 0; | 2050 | exclude_other = 0; |
1948 | 2051 | ||
1949 | /* | 2052 | /* |
@@ -1952,11 +2055,17 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) | |||
1952 | if (argc) | 2055 | if (argc) |
1953 | usage_with_options(report_usage, options); | 2056 | usage_with_options(report_usage, options); |
1954 | 2057 | ||
1955 | setup_list(&dso_list, dso_list_str, "dso"); | ||
1956 | setup_list(&comm_list, comm_list_str, "comm"); | ||
1957 | setup_list(&sym_list, sym_list_str, "symbol"); | ||
1958 | |||
1959 | setup_pager(); | 2058 | setup_pager(); |
1960 | 2059 | ||
2060 | setup_list(&dso_list, dso_list_str, &sort_dso, "dso", stdout); | ||
2061 | setup_list(&comm_list, comm_list_str, &sort_comm, "comm", stdout); | ||
2062 | setup_list(&sym_list, sym_list_str, &sort_sym, "symbol", stdout); | ||
2063 | |||
2064 | if (field_sep && *field_sep == '.') { | ||
2065 | fputs("'.' is the only non valid --field-separator argument\n", | ||
2066 | stderr); | ||
2067 | exit(129); | ||
2068 | } | ||
2069 | |||
1961 | return __cmd_report(); | 2070 | return __cmd_report(); |
1962 | } | 2071 | } |
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 27921a8ce1a9..f9510eeeb6c7 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -511,7 +511,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used) | |||
511 | { | 511 | { |
512 | int status; | 512 | int status; |
513 | 513 | ||
514 | argc = parse_options(argc, argv, options, stat_usage, 0); | 514 | argc = parse_options(argc, argv, options, stat_usage, |
515 | PARSE_OPT_STOP_AT_NON_OPTION); | ||
515 | if (!argc) | 516 | if (!argc) |
516 | usage_with_options(stat_usage, options); | 517 | usage_with_options(stat_usage, options); |
517 | if (run_count <= 0 || run_count > MAX_RUN) | 518 | if (run_count <= 0 || run_count > MAX_RUN) |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 95d5c0ae375a..c0a423004e15 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -58,6 +58,7 @@ static u64 count_filter = 5; | |||
58 | static int print_entries = 15; | 58 | static int print_entries = 15; |
59 | 59 | ||
60 | static int target_pid = -1; | 60 | static int target_pid = -1; |
61 | static int inherit = 0; | ||
61 | static int profile_cpu = -1; | 62 | static int profile_cpu = -1; |
62 | static int nr_cpus = 0; | 63 | static int nr_cpus = 0; |
63 | static unsigned int realtime_prio = 0; | 64 | static unsigned int realtime_prio = 0; |
@@ -549,7 +550,7 @@ int group_fd; | |||
549 | static void start_counter(int i, int counter) | 550 | static void start_counter(int i, int counter) |
550 | { | 551 | { |
551 | struct perf_counter_attr *attr; | 552 | struct perf_counter_attr *attr; |
552 | unsigned int cpu; | 553 | int cpu; |
553 | 554 | ||
554 | cpu = profile_cpu; | 555 | cpu = profile_cpu; |
555 | if (target_pid == -1 && profile_cpu == -1) | 556 | if (target_pid == -1 && profile_cpu == -1) |
@@ -559,6 +560,7 @@ static void start_counter(int i, int counter) | |||
559 | 560 | ||
560 | attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; | 561 | attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; |
561 | attr->freq = freq; | 562 | attr->freq = freq; |
563 | attr->inherit = (cpu < 0) && inherit; | ||
562 | 564 | ||
563 | try_again: | 565 | try_again: |
564 | fd[i][counter] = sys_perf_counter_open(attr, target_pid, cpu, group_fd, 0); | 566 | fd[i][counter] = sys_perf_counter_open(attr, target_pid, cpu, group_fd, 0); |
@@ -685,6 +687,8 @@ static const struct option options[] = { | |||
685 | "only display functions with more events than this"), | 687 | "only display functions with more events than this"), |
686 | OPT_BOOLEAN('g', "group", &group, | 688 | OPT_BOOLEAN('g', "group", &group, |
687 | "put the counters into a counter group"), | 689 | "put the counters into a counter group"), |
690 | OPT_BOOLEAN('i', "inherit", &inherit, | ||
691 | "child tasks inherit counters"), | ||
688 | OPT_STRING('s', "sym-filter", &sym_filter, "pattern", | 692 | OPT_STRING('s', "sym-filter", &sym_filter, "pattern", |
689 | "only display symbols matchig this pattern"), | 693 | "only display symbols matchig this pattern"), |
690 | OPT_BOOLEAN('z', "zero", &zero, | 694 | OPT_BOOLEAN('z', "zero", &zero, |
diff --git a/tools/perf/perf.c b/tools/perf/perf.c index c5656784c61d..31982ad064b4 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c | |||
@@ -12,6 +12,8 @@ | |||
12 | #include "util/cache.h" | 12 | #include "util/cache.h" |
13 | #include "util/quote.h" | 13 | #include "util/quote.h" |
14 | #include "util/run-command.h" | 14 | #include "util/run-command.h" |
15 | #include "util/parse-events.h" | ||
16 | #include "util/string.h" | ||
15 | 17 | ||
16 | const char perf_usage_string[] = | 18 | const char perf_usage_string[] = |
17 | "perf [--version] [--help] COMMAND [ARGS]"; | 19 | "perf [--version] [--help] COMMAND [ARGS]"; |
@@ -25,6 +27,8 @@ struct pager_config { | |||
25 | int val; | 27 | int val; |
26 | }; | 28 | }; |
27 | 29 | ||
30 | static char debugfs_mntpt[MAXPATHLEN]; | ||
31 | |||
28 | static int pager_command_config(const char *var, const char *value, void *data) | 32 | static int pager_command_config(const char *var, const char *value, void *data) |
29 | { | 33 | { |
30 | struct pager_config *c = data; | 34 | struct pager_config *c = data; |
@@ -56,6 +60,15 @@ static void commit_pager_choice(void) { | |||
56 | } | 60 | } |
57 | } | 61 | } |
58 | 62 | ||
63 | static void set_debugfs_path(void) | ||
64 | { | ||
65 | char *path; | ||
66 | |||
67 | path = getenv(PERF_DEBUGFS_ENVIRONMENT); | ||
68 | snprintf(debugfs_path, MAXPATHLEN, "%s/%s", path ?: debugfs_mntpt, | ||
69 | "tracing/events"); | ||
70 | } | ||
71 | |||
59 | static int handle_options(const char*** argv, int* argc, int* envchanged) | 72 | static int handle_options(const char*** argv, int* argc, int* envchanged) |
60 | { | 73 | { |
61 | int handled = 0; | 74 | int handled = 0; |
@@ -122,6 +135,22 @@ static int handle_options(const char*** argv, int* argc, int* envchanged) | |||
122 | setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + 12, 1); | 135 | setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + 12, 1); |
123 | if (envchanged) | 136 | if (envchanged) |
124 | *envchanged = 1; | 137 | *envchanged = 1; |
138 | } else if (!strcmp(cmd, "--debugfs-dir")) { | ||
139 | if (*argc < 2) { | ||
140 | fprintf(stderr, "No directory given for --debugfs-dir.\n"); | ||
141 | usage(perf_usage_string); | ||
142 | } | ||
143 | strncpy(debugfs_mntpt, (*argv)[1], MAXPATHLEN); | ||
144 | debugfs_mntpt[MAXPATHLEN - 1] = '\0'; | ||
145 | if (envchanged) | ||
146 | *envchanged = 1; | ||
147 | (*argv)++; | ||
148 | (*argc)--; | ||
149 | } else if (!prefixcmp(cmd, "--debugfs-dir=")) { | ||
150 | strncpy(debugfs_mntpt, cmd + 14, MAXPATHLEN); | ||
151 | debugfs_mntpt[MAXPATHLEN - 1] = '\0'; | ||
152 | if (envchanged) | ||
153 | *envchanged = 1; | ||
125 | } else { | 154 | } else { |
126 | fprintf(stderr, "Unknown option: %s\n", cmd); | 155 | fprintf(stderr, "Unknown option: %s\n", cmd); |
127 | usage(perf_usage_string); | 156 | usage(perf_usage_string); |
@@ -228,6 +257,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) | |||
228 | if (use_pager == -1 && p->option & USE_PAGER) | 257 | if (use_pager == -1 && p->option & USE_PAGER) |
229 | use_pager = 1; | 258 | use_pager = 1; |
230 | commit_pager_choice(); | 259 | commit_pager_choice(); |
260 | set_debugfs_path(); | ||
231 | 261 | ||
232 | status = p->fn(argc, argv, prefix); | 262 | status = p->fn(argc, argv, prefix); |
233 | if (status) | 263 | if (status) |
@@ -346,6 +376,49 @@ static int run_argv(int *argcp, const char ***argv) | |||
346 | return done_alias; | 376 | return done_alias; |
347 | } | 377 | } |
348 | 378 | ||
379 | /* mini /proc/mounts parser: searching for "^blah /mount/point debugfs" */ | ||
380 | static void get_debugfs_mntpt(void) | ||
381 | { | ||
382 | FILE *file; | ||
383 | char fs_type[100]; | ||
384 | char debugfs[MAXPATHLEN]; | ||
385 | |||
386 | /* | ||
387 | * try the standard location | ||
388 | */ | ||
389 | if (valid_debugfs_mount("/sys/kernel/debug/") == 0) { | ||
390 | strcpy(debugfs_mntpt, "/sys/kernel/debug/"); | ||
391 | return; | ||
392 | } | ||
393 | |||
394 | /* | ||
395 | * try the sane location | ||
396 | */ | ||
397 | if (valid_debugfs_mount("/debug/") == 0) { | ||
398 | strcpy(debugfs_mntpt, "/debug/"); | ||
399 | return; | ||
400 | } | ||
401 | |||
402 | /* | ||
403 | * give up and parse /proc/mounts | ||
404 | */ | ||
405 | file = fopen("/proc/mounts", "r"); | ||
406 | if (file == NULL) | ||
407 | return; | ||
408 | |||
409 | while (fscanf(file, "%*s %" | ||
410 | STR(MAXPATHLEN) | ||
411 | "s %99s %*s %*d %*d\n", | ||
412 | debugfs, fs_type) == 2) { | ||
413 | if (strcmp(fs_type, "debugfs") == 0) | ||
414 | break; | ||
415 | } | ||
416 | fclose(file); | ||
417 | if (strcmp(fs_type, "debugfs") == 0) { | ||
418 | strncpy(debugfs_mntpt, debugfs, MAXPATHLEN); | ||
419 | debugfs_mntpt[MAXPATHLEN - 1] = '\0'; | ||
420 | } | ||
421 | } | ||
349 | 422 | ||
350 | int main(int argc, const char **argv) | 423 | int main(int argc, const char **argv) |
351 | { | 424 | { |
@@ -354,7 +427,8 @@ int main(int argc, const char **argv) | |||
354 | cmd = perf_extract_argv0_path(argv[0]); | 427 | cmd = perf_extract_argv0_path(argv[0]); |
355 | if (!cmd) | 428 | if (!cmd) |
356 | cmd = "perf-help"; | 429 | cmd = "perf-help"; |
357 | 430 | /* get debugfs mount point from /proc/mounts */ | |
431 | get_debugfs_mntpt(); | ||
358 | /* | 432 | /* |
359 | * "perf-xxxx" is the same as "perf xxxx", but we obviously: | 433 | * "perf-xxxx" is the same as "perf xxxx", but we obviously: |
360 | * | 434 | * |
@@ -377,6 +451,7 @@ int main(int argc, const char **argv) | |||
377 | argc--; | 451 | argc--; |
378 | handle_options(&argv, &argc, NULL); | 452 | handle_options(&argv, &argc, NULL); |
379 | commit_pager_choice(); | 453 | commit_pager_choice(); |
454 | set_debugfs_path(); | ||
380 | if (argc > 0) { | 455 | if (argc > 0) { |
381 | if (!prefixcmp(argv[0], "--")) | 456 | if (!prefixcmp(argv[0], "--")) |
382 | argv[0] += 2; | 457 | argv[0] += 2; |
diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 63e67cc5487b..e5148e2b6134 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h | |||
@@ -1,7 +1,13 @@ | |||
1 | #ifndef _PERF_PERF_H | 1 | #ifndef _PERF_PERF_H |
2 | #define _PERF_PERF_H | 2 | #define _PERF_PERF_H |
3 | 3 | ||
4 | #if defined(__x86_64__) || defined(__i386__) | 4 | #if defined(__i386__) |
5 | #include "../../arch/x86/include/asm/unistd.h" | ||
6 | #define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") | ||
7 | #define cpu_relax() asm volatile("rep; nop" ::: "memory"); | ||
8 | #endif | ||
9 | |||
10 | #if defined(__x86_64__) | ||
5 | #include "../../arch/x86/include/asm/unistd.h" | 11 | #include "../../arch/x86/include/asm/unistd.h" |
6 | #define rmb() asm volatile("lfence" ::: "memory") | 12 | #define rmb() asm volatile("lfence" ::: "memory") |
7 | #define cpu_relax() asm volatile("rep; nop" ::: "memory"); | 13 | #define cpu_relax() asm volatile("rep; nop" ::: "memory"); |
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 161d5f413e28..4b50c412b9c5 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #define PERFATTRIBUTES_FILE ".perfattributes" | 18 | #define PERFATTRIBUTES_FILE ".perfattributes" |
19 | #define INFOATTRIBUTES_FILE "info/attributes" | 19 | #define INFOATTRIBUTES_FILE "info/attributes" |
20 | #define ATTRIBUTE_MACRO_PREFIX "[attr]" | 20 | #define ATTRIBUTE_MACRO_PREFIX "[attr]" |
21 | #define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR" | ||
21 | 22 | ||
22 | typedef int (*config_fn_t)(const char *, const char *, void *); | 23 | typedef int (*config_fn_t)(const char *, const char *, void *); |
23 | extern int perf_default_config(const char *, const char *, void *); | 24 | extern int perf_default_config(const char *, const char *, void *); |
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index b5ef53ad4c7a..bf280449fcfd 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h | |||
@@ -16,7 +16,7 @@ struct perf_header { | |||
16 | int frozen; | 16 | int frozen; |
17 | int attrs, size; | 17 | int attrs, size; |
18 | struct perf_header_attr **attr; | 18 | struct perf_header_attr **attr; |
19 | off_t attr_offset; | 19 | s64 attr_offset; |
20 | u64 data_offset; | 20 | u64 data_offset; |
21 | u64 data_size; | 21 | u64 data_size; |
22 | }; | 22 | }; |
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h index 99c1b3d1edd9..a6b87390cb52 100644 --- a/tools/perf/util/include/linux/kernel.h +++ b/tools/perf/util/include/linux/kernel.h | |||
@@ -18,4 +18,12 @@ | |||
18 | (type *)((char *)__mptr - offsetof(type, member)); }) | 18 | (type *)((char *)__mptr - offsetof(type, member)); }) |
19 | #endif | 19 | #endif |
20 | 20 | ||
21 | #ifndef max | ||
22 | #define max(x, y) ({ \ | ||
23 | typeof(x) _max1 = (x); \ | ||
24 | typeof(y) _max2 = (y); \ | ||
25 | (void) (&_max1 == &_max2); \ | ||
26 | _max1 > _max2 ? _max1 : _max2; }) | ||
27 | #endif | ||
28 | |||
21 | #endif | 29 | #endif |
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 5184959e0615..7bdad8df22a6 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include "parse-events.h" | 5 | #include "parse-events.h" |
6 | #include "exec_cmd.h" | 6 | #include "exec_cmd.h" |
7 | #include "string.h" | 7 | #include "string.h" |
8 | #include "cache.h" | ||
8 | 9 | ||
9 | extern char *strcasestr(const char *haystack, const char *needle); | 10 | extern char *strcasestr(const char *haystack, const char *needle); |
10 | 11 | ||
@@ -19,6 +20,8 @@ struct event_symbol { | |||
19 | char *alias; | 20 | char *alias; |
20 | }; | 21 | }; |
21 | 22 | ||
23 | char debugfs_path[MAXPATHLEN]; | ||
24 | |||
22 | #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x | 25 | #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x |
23 | #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x | 26 | #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x |
24 | 27 | ||
@@ -71,8 +74,8 @@ static char *sw_event_names[] = { | |||
71 | #define MAX_ALIASES 8 | 74 | #define MAX_ALIASES 8 |
72 | 75 | ||
73 | static char *hw_cache[][MAX_ALIASES] = { | 76 | static char *hw_cache[][MAX_ALIASES] = { |
74 | { "L1-d$", "l1-d", "l1d", "L1-data", }, | 77 | { "L1-dcache", "l1-d", "l1d", "L1-data", }, |
75 | { "L1-i$", "l1-i", "l1i", "L1-instruction", }, | 78 | { "L1-icache", "l1-i", "l1i", "L1-instruction", }, |
76 | { "LLC", "L2" }, | 79 | { "LLC", "L2" }, |
77 | { "dTLB", "d-tlb", "Data-TLB", }, | 80 | { "dTLB", "d-tlb", "Data-TLB", }, |
78 | { "iTLB", "i-tlb", "Instruction-TLB", }, | 81 | { "iTLB", "i-tlb", "Instruction-TLB", }, |
@@ -110,6 +113,88 @@ static unsigned long hw_cache_stat[C(MAX)] = { | |||
110 | [C(BPU)] = (CACHE_READ), | 113 | [C(BPU)] = (CACHE_READ), |
111 | }; | 114 | }; |
112 | 115 | ||
116 | #define for_each_subsystem(sys_dir, sys_dirent, sys_next, file, st) \ | ||
117 | while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \ | ||
118 | if (snprintf(file, MAXPATHLEN, "%s/%s", debugfs_path, \ | ||
119 | sys_dirent.d_name) && \ | ||
120 | (!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \ | ||
121 | (strcmp(sys_dirent.d_name, ".")) && \ | ||
122 | (strcmp(sys_dirent.d_name, ".."))) | ||
123 | |||
124 | #define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, file, st) \ | ||
125 | while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \ | ||
126 | if (snprintf(file, MAXPATHLEN, "%s/%s/%s", debugfs_path, \ | ||
127 | sys_dirent.d_name, evt_dirent.d_name) && \ | ||
128 | (!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \ | ||
129 | (strcmp(evt_dirent.d_name, ".")) && \ | ||
130 | (strcmp(evt_dirent.d_name, ".."))) | ||
131 | |||
132 | #define MAX_EVENT_LENGTH 30 | ||
133 | |||
134 | int valid_debugfs_mount(const char *debugfs) | ||
135 | { | ||
136 | struct statfs st_fs; | ||
137 | |||
138 | if (statfs(debugfs, &st_fs) < 0) | ||
139 | return -ENOENT; | ||
140 | else if (st_fs.f_type != (long) DEBUGFS_MAGIC) | ||
141 | return -ENOENT; | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static char *tracepoint_id_to_name(u64 config) | ||
146 | { | ||
147 | static char tracepoint_name[2 * MAX_EVENT_LENGTH]; | ||
148 | DIR *sys_dir, *evt_dir; | ||
149 | struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; | ||
150 | struct stat st; | ||
151 | char id_buf[4]; | ||
152 | int fd; | ||
153 | u64 id; | ||
154 | char evt_path[MAXPATHLEN]; | ||
155 | |||
156 | if (valid_debugfs_mount(debugfs_path)) | ||
157 | return "unkown"; | ||
158 | |||
159 | sys_dir = opendir(debugfs_path); | ||
160 | if (!sys_dir) | ||
161 | goto cleanup; | ||
162 | |||
163 | for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) { | ||
164 | evt_dir = opendir(evt_path); | ||
165 | if (!evt_dir) | ||
166 | goto cleanup; | ||
167 | for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, | ||
168 | evt_path, st) { | ||
169 | snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", | ||
170 | debugfs_path, sys_dirent.d_name, | ||
171 | evt_dirent.d_name); | ||
172 | fd = open(evt_path, O_RDONLY); | ||
173 | if (fd < 0) | ||
174 | continue; | ||
175 | if (read(fd, id_buf, sizeof(id_buf)) < 0) { | ||
176 | close(fd); | ||
177 | continue; | ||
178 | } | ||
179 | close(fd); | ||
180 | id = atoll(id_buf); | ||
181 | if (id == config) { | ||
182 | closedir(evt_dir); | ||
183 | closedir(sys_dir); | ||
184 | snprintf(tracepoint_name, 2 * MAX_EVENT_LENGTH, | ||
185 | "%s:%s", sys_dirent.d_name, | ||
186 | evt_dirent.d_name); | ||
187 | return tracepoint_name; | ||
188 | } | ||
189 | } | ||
190 | closedir(evt_dir); | ||
191 | } | ||
192 | |||
193 | cleanup: | ||
194 | closedir(sys_dir); | ||
195 | return "unkown"; | ||
196 | } | ||
197 | |||
113 | static int is_cache_op_valid(u8 cache_type, u8 cache_op) | 198 | static int is_cache_op_valid(u8 cache_type, u8 cache_op) |
114 | { | 199 | { |
115 | if (hw_cache_stat[cache_type] & COP(cache_op)) | 200 | if (hw_cache_stat[cache_type] & COP(cache_op)) |
@@ -177,6 +262,9 @@ char *event_name(int counter) | |||
177 | return sw_event_names[config]; | 262 | return sw_event_names[config]; |
178 | return "unknown-software"; | 263 | return "unknown-software"; |
179 | 264 | ||
265 | case PERF_TYPE_TRACEPOINT: | ||
266 | return tracepoint_id_to_name(config); | ||
267 | |||
180 | default: | 268 | default: |
181 | break; | 269 | break; |
182 | } | 270 | } |
@@ -265,6 +353,53 @@ parse_generic_hw_event(const char **str, struct perf_counter_attr *attr) | |||
265 | return 1; | 353 | return 1; |
266 | } | 354 | } |
267 | 355 | ||
356 | static int parse_tracepoint_event(const char **strp, | ||
357 | struct perf_counter_attr *attr) | ||
358 | { | ||
359 | const char *evt_name; | ||
360 | char sys_name[MAX_EVENT_LENGTH]; | ||
361 | char id_buf[4]; | ||
362 | int fd; | ||
363 | unsigned int sys_length, evt_length; | ||
364 | u64 id; | ||
365 | char evt_path[MAXPATHLEN]; | ||
366 | |||
367 | if (valid_debugfs_mount(debugfs_path)) | ||
368 | return 0; | ||
369 | |||
370 | evt_name = strchr(*strp, ':'); | ||
371 | if (!evt_name) | ||
372 | return 0; | ||
373 | |||
374 | sys_length = evt_name - *strp; | ||
375 | if (sys_length >= MAX_EVENT_LENGTH) | ||
376 | return 0; | ||
377 | |||
378 | strncpy(sys_name, *strp, sys_length); | ||
379 | sys_name[sys_length] = '\0'; | ||
380 | evt_name = evt_name + 1; | ||
381 | evt_length = strlen(evt_name); | ||
382 | if (evt_length >= MAX_EVENT_LENGTH) | ||
383 | return 0; | ||
384 | |||
385 | snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, | ||
386 | sys_name, evt_name); | ||
387 | fd = open(evt_path, O_RDONLY); | ||
388 | if (fd < 0) | ||
389 | return 0; | ||
390 | |||
391 | if (read(fd, id_buf, sizeof(id_buf)) < 0) { | ||
392 | close(fd); | ||
393 | return 0; | ||
394 | } | ||
395 | close(fd); | ||
396 | id = atoll(id_buf); | ||
397 | attr->config = id; | ||
398 | attr->type = PERF_TYPE_TRACEPOINT; | ||
399 | *strp = evt_name + evt_length; | ||
400 | return 1; | ||
401 | } | ||
402 | |||
268 | static int check_events(const char *str, unsigned int i) | 403 | static int check_events(const char *str, unsigned int i) |
269 | { | 404 | { |
270 | int n; | 405 | int n; |
@@ -374,7 +509,8 @@ parse_event_modifier(const char **strp, struct perf_counter_attr *attr) | |||
374 | */ | 509 | */ |
375 | static int parse_event_symbols(const char **str, struct perf_counter_attr *attr) | 510 | static int parse_event_symbols(const char **str, struct perf_counter_attr *attr) |
376 | { | 511 | { |
377 | if (!(parse_raw_event(str, attr) || | 512 | if (!(parse_tracepoint_event(str, attr) || |
513 | parse_raw_event(str, attr) || | ||
378 | parse_numeric_event(str, attr) || | 514 | parse_numeric_event(str, attr) || |
379 | parse_symbolic_event(str, attr) || | 515 | parse_symbolic_event(str, attr) || |
380 | parse_generic_hw_event(str, attr))) | 516 | parse_generic_hw_event(str, attr))) |
@@ -423,6 +559,42 @@ static const char * const event_type_descriptors[] = { | |||
423 | }; | 559 | }; |
424 | 560 | ||
425 | /* | 561 | /* |
562 | * Print the events from <debugfs_mount_point>/tracing/events | ||
563 | */ | ||
564 | |||
565 | static void print_tracepoint_events(void) | ||
566 | { | ||
567 | DIR *sys_dir, *evt_dir; | ||
568 | struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; | ||
569 | struct stat st; | ||
570 | char evt_path[MAXPATHLEN]; | ||
571 | |||
572 | if (valid_debugfs_mount(debugfs_path)) | ||
573 | return; | ||
574 | |||
575 | sys_dir = opendir(debugfs_path); | ||
576 | if (!sys_dir) | ||
577 | goto cleanup; | ||
578 | |||
579 | for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) { | ||
580 | evt_dir = opendir(evt_path); | ||
581 | if (!evt_dir) | ||
582 | goto cleanup; | ||
583 | for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, | ||
584 | evt_path, st) { | ||
585 | snprintf(evt_path, MAXPATHLEN, "%s:%s", | ||
586 | sys_dirent.d_name, evt_dirent.d_name); | ||
587 | fprintf(stderr, " %-40s [%s]\n", evt_path, | ||
588 | event_type_descriptors[PERF_TYPE_TRACEPOINT+1]); | ||
589 | } | ||
590 | closedir(evt_dir); | ||
591 | } | ||
592 | |||
593 | cleanup: | ||
594 | closedir(sys_dir); | ||
595 | } | ||
596 | |||
597 | /* | ||
426 | * Print the help text for the event symbols: | 598 | * Print the help text for the event symbols: |
427 | */ | 599 | */ |
428 | void print_events(void) | 600 | void print_events(void) |
@@ -436,7 +608,7 @@ void print_events(void) | |||
436 | 608 | ||
437 | for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { | 609 | for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { |
438 | type = syms->type + 1; | 610 | type = syms->type + 1; |
439 | if (type > ARRAY_SIZE(event_type_descriptors)) | 611 | if (type >= ARRAY_SIZE(event_type_descriptors)) |
440 | type = 0; | 612 | type = 0; |
441 | 613 | ||
442 | if (type != prev_type) | 614 | if (type != prev_type) |
@@ -472,5 +644,7 @@ void print_events(void) | |||
472 | "rNNN"); | 644 | "rNNN"); |
473 | fprintf(stderr, "\n"); | 645 | fprintf(stderr, "\n"); |
474 | 646 | ||
647 | print_tracepoint_events(); | ||
648 | |||
475 | exit(129); | 649 | exit(129); |
476 | } | 650 | } |
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index e3d552908e60..1ea5d09b6eb1 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h | |||
@@ -3,6 +3,8 @@ | |||
3 | * Parse symbolic events/counts passed in as options: | 3 | * Parse symbolic events/counts passed in as options: |
4 | */ | 4 | */ |
5 | 5 | ||
6 | struct option; | ||
7 | |||
6 | extern int nr_counters; | 8 | extern int nr_counters; |
7 | 9 | ||
8 | extern struct perf_counter_attr attrs[MAX_COUNTERS]; | 10 | extern struct perf_counter_attr attrs[MAX_COUNTERS]; |
@@ -15,3 +17,6 @@ extern int parse_events(const struct option *opt, const char *str, int unset); | |||
15 | 17 | ||
16 | extern void print_events(void); | 18 | extern void print_events(void); |
17 | 19 | ||
20 | extern char debugfs_path[]; | ||
21 | extern int valid_debugfs_mount(const char *debugfs); | ||
22 | |||
diff --git a/tools/perf/util/string.h b/tools/perf/util/string.h index 3dca2f654cd0..bf39dfadfd24 100644 --- a/tools/perf/util/string.h +++ b/tools/perf/util/string.h | |||
@@ -5,4 +5,7 @@ | |||
5 | 5 | ||
6 | int hex2u64(const char *ptr, u64 *val); | 6 | int hex2u64(const char *ptr, u64 *val); |
7 | 7 | ||
8 | #define _STR(x) #x | ||
9 | #define STR(x) _STR(x) | ||
10 | |||
8 | #endif | 11 | #endif |
diff --git a/tools/perf/util/strlist.c b/tools/perf/util/strlist.c index 025a78edfffe..7ad38171dc2b 100644 --- a/tools/perf/util/strlist.c +++ b/tools/perf/util/strlist.c | |||
@@ -64,6 +64,7 @@ int strlist__add(struct strlist *self, const char *new_entry) | |||
64 | 64 | ||
65 | rb_link_node(&sn->rb_node, parent, p); | 65 | rb_link_node(&sn->rb_node, parent, p); |
66 | rb_insert_color(&sn->rb_node, &self->entries); | 66 | rb_insert_color(&sn->rb_node, &self->entries); |
67 | ++self->nr_entries; | ||
67 | 68 | ||
68 | return 0; | 69 | return 0; |
69 | } | 70 | } |
@@ -155,8 +156,9 @@ struct strlist *strlist__new(bool dupstr, const char *slist) | |||
155 | struct strlist *self = malloc(sizeof(*self)); | 156 | struct strlist *self = malloc(sizeof(*self)); |
156 | 157 | ||
157 | if (self != NULL) { | 158 | if (self != NULL) { |
158 | self->entries = RB_ROOT; | 159 | self->entries = RB_ROOT; |
159 | self->dupstr = dupstr; | 160 | self->dupstr = dupstr; |
161 | self->nr_entries = 0; | ||
160 | if (slist && strlist__parse_list(self, slist) != 0) | 162 | if (slist && strlist__parse_list(self, slist) != 0) |
161 | goto out_error; | 163 | goto out_error; |
162 | } | 164 | } |
@@ -182,3 +184,17 @@ void strlist__delete(struct strlist *self) | |||
182 | free(self); | 184 | free(self); |
183 | } | 185 | } |
184 | } | 186 | } |
187 | |||
188 | struct str_node *strlist__entry(const struct strlist *self, unsigned int idx) | ||
189 | { | ||
190 | struct rb_node *nd; | ||
191 | |||
192 | for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { | ||
193 | struct str_node *pos = rb_entry(nd, struct str_node, rb_node); | ||
194 | |||
195 | if (!idx--) | ||
196 | return pos; | ||
197 | } | ||
198 | |||
199 | return NULL; | ||
200 | } | ||
diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h index 2fdcfee87586..921818e44a54 100644 --- a/tools/perf/util/strlist.h +++ b/tools/perf/util/strlist.h | |||
@@ -11,7 +11,8 @@ struct str_node { | |||
11 | 11 | ||
12 | struct strlist { | 12 | struct strlist { |
13 | struct rb_root entries; | 13 | struct rb_root entries; |
14 | bool dupstr; | 14 | unsigned int nr_entries; |
15 | bool dupstr; | ||
15 | }; | 16 | }; |
16 | 17 | ||
17 | struct strlist *strlist__new(bool dupstr, const char *slist); | 18 | struct strlist *strlist__new(bool dupstr, const char *slist); |
@@ -21,11 +22,17 @@ void strlist__remove(struct strlist *self, struct str_node *sn); | |||
21 | int strlist__load(struct strlist *self, const char *filename); | 22 | int strlist__load(struct strlist *self, const char *filename); |
22 | int strlist__add(struct strlist *self, const char *str); | 23 | int strlist__add(struct strlist *self, const char *str); |
23 | 24 | ||
25 | struct str_node *strlist__entry(const struct strlist *self, unsigned int idx); | ||
24 | bool strlist__has_entry(struct strlist *self, const char *entry); | 26 | bool strlist__has_entry(struct strlist *self, const char *entry); |
25 | 27 | ||
26 | static inline bool strlist__empty(const struct strlist *self) | 28 | static inline bool strlist__empty(const struct strlist *self) |
27 | { | 29 | { |
28 | return rb_first(&self->entries) == NULL; | 30 | return self->nr_entries == 0; |
31 | } | ||
32 | |||
33 | static inline unsigned int strlist__nr_entries(const struct strlist *self) | ||
34 | { | ||
35 | return self->nr_entries; | ||
29 | } | 36 | } |
30 | 37 | ||
31 | int strlist__parse_list(struct strlist *self, const char *s); | 38 | int strlist__parse_list(struct strlist *self, const char *s); |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 4683b67b5ee4..28106059bf12 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -6,9 +6,15 @@ | |||
6 | #include <libelf.h> | 6 | #include <libelf.h> |
7 | #include <gelf.h> | 7 | #include <gelf.h> |
8 | #include <elf.h> | 8 | #include <elf.h> |
9 | #include <bfd.h> | ||
9 | 10 | ||
10 | const char *sym_hist_filter; | 11 | const char *sym_hist_filter; |
11 | 12 | ||
13 | #ifndef DMGL_PARAMS | ||
14 | #define DMGL_PARAMS (1 << 0) /* Include function args */ | ||
15 | #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ | ||
16 | #endif | ||
17 | |||
12 | static struct symbol *symbol__new(u64 start, u64 len, | 18 | static struct symbol *symbol__new(u64 start, u64 len, |
13 | const char *name, unsigned int priv_size, | 19 | const char *name, unsigned int priv_size, |
14 | u64 obj_start, int verbose) | 20 | u64 obj_start, int verbose) |
@@ -65,6 +71,7 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size) | |||
65 | self->syms = RB_ROOT; | 71 | self->syms = RB_ROOT; |
66 | self->sym_priv_size = sym_priv_size; | 72 | self->sym_priv_size = sym_priv_size; |
67 | self->find_symbol = dso__find_symbol; | 73 | self->find_symbol = dso__find_symbol; |
74 | self->slen_calculated = 0; | ||
68 | } | 75 | } |
69 | 76 | ||
70 | return self; | 77 | return self; |
@@ -373,36 +380,61 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, | |||
373 | idx < nr_entries; \ | 380 | idx < nr_entries; \ |
374 | ++idx, pos = gelf_getrela(reldata, idx, &pos_mem)) | 381 | ++idx, pos = gelf_getrela(reldata, idx, &pos_mem)) |
375 | 382 | ||
376 | static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf, | 383 | /* |
377 | GElf_Ehdr *ehdr, Elf_Scn *scn_dynsym, | 384 | * We need to check if we have a .dynsym, so that we can handle the |
378 | GElf_Shdr *shdr_dynsym, | 385 | * .plt, synthesizing its symbols, that aren't on the symtabs (be it |
379 | size_t dynsym_idx, int verbose) | 386 | * .dynsym or .symtab). |
387 | * And always look at the original dso, not at debuginfo packages, that | ||
388 | * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS). | ||
389 | */ | ||
390 | static int dso__synthesize_plt_symbols(struct dso *self, int verbose) | ||
380 | { | 391 | { |
381 | uint32_t nr_rel_entries, idx; | 392 | uint32_t nr_rel_entries, idx; |
382 | GElf_Sym sym; | 393 | GElf_Sym sym; |
383 | u64 plt_offset; | 394 | u64 plt_offset; |
384 | GElf_Shdr shdr_plt; | 395 | GElf_Shdr shdr_plt; |
385 | struct symbol *f; | 396 | struct symbol *f; |
386 | GElf_Shdr shdr_rel_plt; | 397 | GElf_Shdr shdr_rel_plt, shdr_dynsym; |
387 | Elf_Data *reldata, *syms, *symstrs; | 398 | Elf_Data *reldata, *syms, *symstrs; |
388 | Elf_Scn *scn_plt_rel, *scn_symstrs; | 399 | Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym; |
400 | size_t dynsym_idx; | ||
401 | GElf_Ehdr ehdr; | ||
389 | char sympltname[1024]; | 402 | char sympltname[1024]; |
390 | int nr = 0, symidx; | 403 | Elf *elf; |
404 | int nr = 0, symidx, fd, err = 0; | ||
405 | |||
406 | fd = open(self->name, O_RDONLY); | ||
407 | if (fd < 0) | ||
408 | goto out; | ||
409 | |||
410 | elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); | ||
411 | if (elf == NULL) | ||
412 | goto out_close; | ||
413 | |||
414 | if (gelf_getehdr(elf, &ehdr) == NULL) | ||
415 | goto out_elf_end; | ||
416 | |||
417 | scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym, | ||
418 | ".dynsym", &dynsym_idx); | ||
419 | if (scn_dynsym == NULL) | ||
420 | goto out_elf_end; | ||
391 | 421 | ||
392 | scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, | 422 | scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt, |
393 | ".rela.plt", NULL); | 423 | ".rela.plt", NULL); |
394 | if (scn_plt_rel == NULL) { | 424 | if (scn_plt_rel == NULL) { |
395 | scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, | 425 | scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt, |
396 | ".rel.plt", NULL); | 426 | ".rel.plt", NULL); |
397 | if (scn_plt_rel == NULL) | 427 | if (scn_plt_rel == NULL) |
398 | return 0; | 428 | goto out_elf_end; |
399 | } | 429 | } |
400 | 430 | ||
431 | err = -1; | ||
432 | |||
401 | if (shdr_rel_plt.sh_link != dynsym_idx) | 433 | if (shdr_rel_plt.sh_link != dynsym_idx) |
402 | return 0; | 434 | goto out_elf_end; |
403 | 435 | ||
404 | if (elf_section_by_name(elf, ehdr, &shdr_plt, ".plt", NULL) == NULL) | 436 | if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL) |
405 | return 0; | 437 | goto out_elf_end; |
406 | 438 | ||
407 | /* | 439 | /* |
408 | * Fetch the relocation section to find the indexes to the GOT | 440 | * Fetch the relocation section to find the indexes to the GOT |
@@ -410,19 +442,19 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf, | |||
410 | */ | 442 | */ |
411 | reldata = elf_getdata(scn_plt_rel, NULL); | 443 | reldata = elf_getdata(scn_plt_rel, NULL); |
412 | if (reldata == NULL) | 444 | if (reldata == NULL) |
413 | return -1; | 445 | goto out_elf_end; |
414 | 446 | ||
415 | syms = elf_getdata(scn_dynsym, NULL); | 447 | syms = elf_getdata(scn_dynsym, NULL); |
416 | if (syms == NULL) | 448 | if (syms == NULL) |
417 | return -1; | 449 | goto out_elf_end; |
418 | 450 | ||
419 | scn_symstrs = elf_getscn(elf, shdr_dynsym->sh_link); | 451 | scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link); |
420 | if (scn_symstrs == NULL) | 452 | if (scn_symstrs == NULL) |
421 | return -1; | 453 | goto out_elf_end; |
422 | 454 | ||
423 | symstrs = elf_getdata(scn_symstrs, NULL); | 455 | symstrs = elf_getdata(scn_symstrs, NULL); |
424 | if (symstrs == NULL) | 456 | if (symstrs == NULL) |
425 | return -1; | 457 | goto out_elf_end; |
426 | 458 | ||
427 | nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; | 459 | nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; |
428 | plt_offset = shdr_plt.sh_offset; | 460 | plt_offset = shdr_plt.sh_offset; |
@@ -441,7 +473,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf, | |||
441 | f = symbol__new(plt_offset, shdr_plt.sh_entsize, | 473 | f = symbol__new(plt_offset, shdr_plt.sh_entsize, |
442 | sympltname, self->sym_priv_size, 0, verbose); | 474 | sympltname, self->sym_priv_size, 0, verbose); |
443 | if (!f) | 475 | if (!f) |
444 | return -1; | 476 | goto out_elf_end; |
445 | 477 | ||
446 | dso__insert_symbol(self, f); | 478 | dso__insert_symbol(self, f); |
447 | ++nr; | 479 | ++nr; |
@@ -459,19 +491,25 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf, | |||
459 | f = symbol__new(plt_offset, shdr_plt.sh_entsize, | 491 | f = symbol__new(plt_offset, shdr_plt.sh_entsize, |
460 | sympltname, self->sym_priv_size, 0, verbose); | 492 | sympltname, self->sym_priv_size, 0, verbose); |
461 | if (!f) | 493 | if (!f) |
462 | return -1; | 494 | goto out_elf_end; |
463 | 495 | ||
464 | dso__insert_symbol(self, f); | 496 | dso__insert_symbol(self, f); |
465 | ++nr; | 497 | ++nr; |
466 | } | 498 | } |
467 | } else { | ||
468 | /* | ||
469 | * TODO: There are still one more shdr_rel_plt.sh_type | ||
470 | * I have to investigate, but probably should be ignored. | ||
471 | */ | ||
472 | } | 499 | } |
473 | 500 | ||
474 | return nr; | 501 | err = 0; |
502 | out_elf_end: | ||
503 | elf_end(elf); | ||
504 | out_close: | ||
505 | close(fd); | ||
506 | |||
507 | if (err == 0) | ||
508 | return nr; | ||
509 | out: | ||
510 | fprintf(stderr, "%s: problems reading %s PLT info.\n", | ||
511 | __func__, self->name); | ||
512 | return 0; | ||
475 | } | 513 | } |
476 | 514 | ||
477 | static int dso__load_sym(struct dso *self, int fd, const char *name, | 515 | static int dso__load_sym(struct dso *self, int fd, const char *name, |
@@ -485,10 +523,9 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, | |||
485 | GElf_Shdr shdr; | 523 | GElf_Shdr shdr; |
486 | Elf_Data *syms; | 524 | Elf_Data *syms; |
487 | GElf_Sym sym; | 525 | GElf_Sym sym; |
488 | Elf_Scn *sec, *sec_dynsym, *sec_strndx; | 526 | Elf_Scn *sec, *sec_strndx; |
489 | Elf *elf; | 527 | Elf *elf; |
490 | size_t dynsym_idx; | 528 | int nr = 0, kernel = !strcmp("[kernel]", self->name); |
491 | int nr = 0; | ||
492 | 529 | ||
493 | elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); | 530 | elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); |
494 | if (elf == NULL) { | 531 | if (elf == NULL) { |
@@ -504,32 +541,11 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, | |||
504 | goto out_elf_end; | 541 | goto out_elf_end; |
505 | } | 542 | } |
506 | 543 | ||
507 | /* | ||
508 | * We need to check if we have a .dynsym, so that we can handle the | ||
509 | * .plt, synthesizing its symbols, that aren't on the symtabs (be it | ||
510 | * .dynsym or .symtab) | ||
511 | */ | ||
512 | sec_dynsym = elf_section_by_name(elf, &ehdr, &shdr, | ||
513 | ".dynsym", &dynsym_idx); | ||
514 | if (sec_dynsym != NULL) { | ||
515 | nr = dso__synthesize_plt_symbols(self, elf, &ehdr, | ||
516 | sec_dynsym, &shdr, | ||
517 | dynsym_idx, verbose); | ||
518 | if (nr < 0) | ||
519 | goto out_elf_end; | ||
520 | } | ||
521 | |||
522 | /* | ||
523 | * But if we have a full .symtab (that is a superset of .dynsym) we | ||
524 | * should add the symbols not in the .dynsyn | ||
525 | */ | ||
526 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); | 544 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); |
527 | if (sec == NULL) { | 545 | if (sec == NULL) { |
528 | if (sec_dynsym == NULL) | 546 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL); |
547 | if (sec == NULL) | ||
529 | goto out_elf_end; | 548 | goto out_elf_end; |
530 | |||
531 | sec = sec_dynsym; | ||
532 | gelf_getshdr(sec, &shdr); | ||
533 | } | 549 | } |
534 | 550 | ||
535 | syms = elf_getdata(sec, NULL); | 551 | syms = elf_getdata(sec, NULL); |
@@ -555,12 +571,17 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, | |||
555 | nr_syms = shdr.sh_size / shdr.sh_entsize; | 571 | nr_syms = shdr.sh_size / shdr.sh_entsize; |
556 | 572 | ||
557 | memset(&sym, 0, sizeof(sym)); | 573 | memset(&sym, 0, sizeof(sym)); |
558 | self->adjust_symbols = (ehdr.e_type == ET_EXEC || | 574 | if (!kernel) { |
575 | self->adjust_symbols = (ehdr.e_type == ET_EXEC || | ||
559 | elf_section_by_name(elf, &ehdr, &shdr, | 576 | elf_section_by_name(elf, &ehdr, &shdr, |
560 | ".gnu.prelink_undo", | 577 | ".gnu.prelink_undo", |
561 | NULL) != NULL); | 578 | NULL) != NULL); |
579 | } else self->adjust_symbols = 0; | ||
580 | |||
562 | elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { | 581 | elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { |
563 | struct symbol *f; | 582 | struct symbol *f; |
583 | const char *name; | ||
584 | char *demangled; | ||
564 | u64 obj_start; | 585 | u64 obj_start; |
565 | struct section *section = NULL; | 586 | struct section *section = NULL; |
566 | int is_label = elf_sym__is_label(&sym); | 587 | int is_label = elf_sym__is_label(&sym); |
@@ -599,10 +620,19 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, | |||
599 | goto out_elf_end; | 620 | goto out_elf_end; |
600 | } | 621 | } |
601 | } | 622 | } |
623 | /* | ||
624 | * We need to figure out if the object was created from C++ sources | ||
625 | * DWARF DW_compile_unit has this, but we don't always have access | ||
626 | * to it... | ||
627 | */ | ||
628 | name = elf_sym__name(&sym, symstrs); | ||
629 | demangled = bfd_demangle(NULL, name, DMGL_PARAMS | DMGL_ANSI); | ||
630 | if (demangled != NULL) | ||
631 | name = demangled; | ||
602 | 632 | ||
603 | f = symbol__new(sym.st_value, sym.st_size, | 633 | f = symbol__new(sym.st_value, sym.st_size, name, |
604 | elf_sym__name(&sym, symstrs), | ||
605 | self->sym_priv_size, obj_start, verbose); | 634 | self->sym_priv_size, obj_start, verbose); |
635 | free(demangled); | ||
606 | if (!f) | 636 | if (!f) |
607 | goto out_elf_end; | 637 | goto out_elf_end; |
608 | 638 | ||
@@ -668,6 +698,11 @@ more: | |||
668 | if (!ret) | 698 | if (!ret) |
669 | goto more; | 699 | goto more; |
670 | 700 | ||
701 | if (ret > 0) { | ||
702 | int nr_plt = dso__synthesize_plt_symbols(self, verbose); | ||
703 | if (nr_plt > 0) | ||
704 | ret += nr_plt; | ||
705 | } | ||
671 | out: | 706 | out: |
672 | free(name); | 707 | free(name); |
673 | return ret; | 708 | return ret; |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 7918cffb23cd..2f92b21c712d 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -25,6 +25,7 @@ struct dso { | |||
25 | struct symbol *(*find_symbol)(struct dso *, u64 ip); | 25 | struct symbol *(*find_symbol)(struct dso *, u64 ip); |
26 | unsigned int sym_priv_size; | 26 | unsigned int sym_priv_size; |
27 | unsigned char adjust_symbols; | 27 | unsigned char adjust_symbols; |
28 | unsigned char slen_calculated; | ||
28 | char name[0]; | 29 | char name[0]; |
29 | }; | 30 | }; |
30 | 31 | ||
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index b4be6071c105..68fe157d72fb 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <unistd.h> | 50 | #include <unistd.h> |
51 | #include <stdio.h> | 51 | #include <stdio.h> |
52 | #include <sys/stat.h> | 52 | #include <sys/stat.h> |
53 | #include <sys/statfs.h> | ||
53 | #include <fcntl.h> | 54 | #include <fcntl.h> |
54 | #include <stddef.h> | 55 | #include <stddef.h> |
55 | #include <stdlib.h> | 56 | #include <stdlib.h> |
@@ -80,6 +81,7 @@ | |||
80 | #include <netdb.h> | 81 | #include <netdb.h> |
81 | #include <pwd.h> | 82 | #include <pwd.h> |
82 | #include <inttypes.h> | 83 | #include <inttypes.h> |
84 | #include "../../../include/linux/magic.h" | ||
83 | 85 | ||
84 | #ifndef NO_ICONV | 86 | #ifndef NO_ICONV |
85 | #include <iconv.h> | 87 | #include <iconv.h> |