diff options
author | Denys Dmytriyenko <denys@ti.com> | 2013-09-28 15:54:37 -0400 |
---|---|---|
committer | Denys Dmytriyenko <denys@ti.com> | 2013-09-30 16:33:39 -0400 |
commit | 06afc3984d8e30e1c64db65373aa8e1378d44c16 (patch) | |
tree | 129b39157252737ccee5c406fc0ebf73c82874bf /recipes-kernel | |
parent | 9e595df2976144c996ec3abc20db8f6dc08d7f0f (diff) | |
download | meta-ti-06afc3984d8e30e1c64db65373aa8e1378d44c16.tar.gz |
linux-omap-2.6.39: remove old beagleboard-specific and not supported kernel
Beagleboard is supported by newer 3.x kernel recipes.
Signed-off-by: Denys Dmytriyenko <denys@ti.com>
Acked-by: Franklin Cooper Jr. <fcooper@ti.com>
Diffstat (limited to 'recipes-kernel')
95 files changed, 0 insertions, 29857 deletions
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/beagle/0001-OMAP3-beagle-add-support-for-beagleboard-xM-revision.patch b/recipes-kernel/linux/linux-omap-2.6.39/beagle/0001-OMAP3-beagle-add-support-for-beagleboard-xM-revision.patch deleted file mode 100644 index 7522d6c1..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/beagle/0001-OMAP3-beagle-add-support-for-beagleboard-xM-revision.patch +++ /dev/null | |||
@@ -1,117 +0,0 @@ | |||
1 | From 16c1bdb30f1bcd750b29dffd2ef3003be2d30610 Mon Sep 17 00:00:00 2001 | ||
2 | From: Koen Kooi <koen@dominion.thruhere.net> | ||
3 | Date: Fri, 20 May 2011 12:48:37 +0200 | ||
4 | Subject: [PATCH 1/7] OMAP3: beagle: add support for beagleboard xM revision C | ||
5 | |||
6 | The USB enable GPIO has been inverted and the USER button moved. | ||
7 | |||
8 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
9 | --- | ||
10 | arch/arm/mach-omap2/board-omap3beagle.c | 34 +++++++++++++++++++++++------- | ||
11 | 1 files changed, 26 insertions(+), 8 deletions(-) | ||
12 | |||
13 | diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c | ||
14 | index 2de4b02..77bafa8 100644 | ||
15 | --- a/arch/arm/mach-omap2/board-omap3beagle.c | ||
16 | +++ b/arch/arm/mach-omap2/board-omap3beagle.c | ||
17 | @@ -62,7 +62,9 @@ | ||
18 | * AXBX = GPIO173, GPIO172, GPIO171: 1 1 1 | ||
19 | * C1_3 = GPIO173, GPIO172, GPIO171: 1 1 0 | ||
20 | * C4 = GPIO173, GPIO172, GPIO171: 1 0 1 | ||
21 | - * XM = GPIO173, GPIO172, GPIO171: 0 0 0 | ||
22 | + * XMA = GPIO173, GPIO172, GPIO171: 0 0 0 | ||
23 | + * XMB = GPIO173, GPIO172, GPIO171: 0 0 1 | ||
24 | + * XMC = GPIO173, GPIO172, GPIO171: 0 1 0 | ||
25 | */ | ||
26 | enum { | ||
27 | OMAP3BEAGLE_BOARD_UNKN = 0, | ||
28 | @@ -70,6 +72,7 @@ enum { | ||
29 | OMAP3BEAGLE_BOARD_C1_3, | ||
30 | OMAP3BEAGLE_BOARD_C4, | ||
31 | OMAP3BEAGLE_BOARD_XM, | ||
32 | + OMAP3BEAGLE_BOARD_XMC, | ||
33 | }; | ||
34 | |||
35 | static u8 omap3_beagle_version; | ||
36 | @@ -124,9 +127,18 @@ static void __init omap3_beagle_init_rev(void) | ||
37 | printk(KERN_INFO "OMAP3 Beagle Rev: xM\n"); | ||
38 | omap3_beagle_version = OMAP3BEAGLE_BOARD_XM; | ||
39 | break; | ||
40 | + case 1: | ||
41 | + printk(KERN_INFO "OMAP3 Beagle Rev: xM B\n"); | ||
42 | + omap3_beagle_version = OMAP3BEAGLE_BOARD_XM; | ||
43 | + break; | ||
44 | + case 2: | ||
45 | + printk(KERN_INFO "OMAP3 Beagle Rev: xM C\n"); | ||
46 | + omap3_beagle_version = OMAP3BEAGLE_BOARD_XMC; | ||
47 | + break; | ||
48 | default: | ||
49 | - printk(KERN_INFO "OMAP3 Beagle Rev: unknown %hd\n", beagle_rev); | ||
50 | - omap3_beagle_version = OMAP3BEAGLE_BOARD_UNKN; | ||
51 | + printk(KERN_INFO | ||
52 | + "OMAP3 Beagle Rev: unknown %hd, assuming xM C or newer\n", beagle_rev); | ||
53 | + omap3_beagle_version = OMAP3BEAGLE_BOARD_XMC; | ||
54 | } | ||
55 | |||
56 | return; | ||
57 | @@ -278,7 +290,7 @@ static int beagle_twl_gpio_setup(struct device *dev, | ||
58 | { | ||
59 | int r; | ||
60 | |||
61 | - if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) { | ||
62 | + if (cpu_is_omap3630()) { | ||
63 | mmc[0].gpio_wp = -EINVAL; | ||
64 | } else if ((omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C1_3) || | ||
65 | (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C4)) { | ||
66 | @@ -298,7 +310,8 @@ static int beagle_twl_gpio_setup(struct device *dev, | ||
67 | /* REVISIT: need ehci-omap hooks for external VBUS | ||
68 | * power switch and overcurrent detect | ||
69 | */ | ||
70 | - if (omap3_beagle_get_rev() != OMAP3BEAGLE_BOARD_XM) { | ||
71 | + if (omap3_beagle_get_rev() != OMAP3BEAGLE_BOARD_XM | ||
72 | + && omap3_beagle_get_rev() != OMAP3BEAGLE_BOARD_XMC) { | ||
73 | r = gpio_request(gpio + 1, "EHCI_nOC"); | ||
74 | if (!r) { | ||
75 | r = gpio_direction_input(gpio + 1); | ||
76 | @@ -320,7 +333,7 @@ static int beagle_twl_gpio_setup(struct device *dev, | ||
77 | gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0); | ||
78 | |||
79 | /* DVI reset GPIO is different between beagle revisions */ | ||
80 | - if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) | ||
81 | + if (cpu_is_omap3630()) | ||
82 | beagle_dvi_device.reset_gpio = 129; | ||
83 | else | ||
84 | beagle_dvi_device.reset_gpio = 170; | ||
85 | @@ -334,7 +347,7 @@ static int beagle_twl_gpio_setup(struct device *dev, | ||
86 | * P7/P8 revisions(prototype): Camera EN | ||
87 | * A2+ revisions (production): LDO (supplies DVI, serial, led blocks) | ||
88 | */ | ||
89 | - if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) { | ||
90 | + if (cpu_is_omap3630()) { | ||
91 | r = gpio_request(gpio + 1, "nDVI_PWR_EN"); | ||
92 | if (!r) { | ||
93 | r = gpio_direction_output(gpio + 1, 0); | ||
94 | @@ -625,7 +638,7 @@ static void __init beagle_opp_init(void) | ||
95 | } | ||
96 | |||
97 | /* Custom OPP enabled for XM */ | ||
98 | - if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) { | ||
99 | + if (cpu_is_omap3630()) { | ||
100 | struct omap_hwmod *mh = omap_hwmod_lookup("mpu"); | ||
101 | struct omap_hwmod *dh = omap_hwmod_lookup("iva"); | ||
102 | struct device *dev; | ||
103 | @@ -665,6 +678,11 @@ static void __init omap3_beagle_init(void) | ||
104 | omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); | ||
105 | omap3_beagle_init_rev(); | ||
106 | omap3_beagle_i2c_init(); | ||
107 | + | ||
108 | + if (cpu_is_omap3630()) { | ||
109 | + gpio_buttons[0].gpio = 4; | ||
110 | + } | ||
111 | + | ||
112 | platform_add_devices(omap3_beagle_devices, | ||
113 | ARRAY_SIZE(omap3_beagle_devices)); | ||
114 | omap_display_init(&beagle_dss_data); | ||
115 | -- | ||
116 | 1.6.6.1 | ||
117 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/beagle/0002-OMAP3-beagle-add-support-for-expansionboards.patch b/recipes-kernel/linux/linux-omap-2.6.39/beagle/0002-OMAP3-beagle-add-support-for-expansionboards.patch deleted file mode 100644 index 2e95c763..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/beagle/0002-OMAP3-beagle-add-support-for-expansionboards.patch +++ /dev/null | |||
@@ -1,359 +0,0 @@ | |||
1 | From 27494059a5d005b8cad4e0e8640ff031b86220dc Mon Sep 17 00:00:00 2001 | ||
2 | From: Koen Kooi <koen@dominion.thruhere.net> | ||
3 | Date: Fri, 20 May 2011 13:06:24 +0200 | ||
4 | Subject: [PATCH 2/7] OMAP3: beagle: add support for expansionboards | ||
5 | |||
6 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
7 | --- | ||
8 | arch/arm/mach-omap2/board-omap3beagle.c | 272 ++++++++++++++++++++++++++++++- | ||
9 | 1 files changed, 269 insertions(+), 3 deletions(-) | ||
10 | |||
11 | diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c | ||
12 | index 77bafa8..db285e1 100644 | ||
13 | --- a/arch/arm/mach-omap2/board-omap3beagle.c | ||
14 | +++ b/arch/arm/mach-omap2/board-omap3beagle.c | ||
15 | @@ -21,6 +21,7 @@ | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/leds.h> | ||
18 | #include <linux/gpio.h> | ||
19 | +#include <linux/irq.h> | ||
20 | #include <linux/input.h> | ||
21 | #include <linux/gpio_keys.h> | ||
22 | #include <linux/opp.h> | ||
23 | @@ -154,6 +155,167 @@ fail0: | ||
24 | return; | ||
25 | } | ||
26 | |||
27 | +char expansionboard_name[16]; | ||
28 | + | ||
29 | +#if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE) | ||
30 | +#include <linux/regulator/fixed.h> | ||
31 | +#include <linux/wl12xx.h> | ||
32 | + | ||
33 | +#define OMAP_BEAGLE_WLAN_EN_GPIO (139) | ||
34 | +#define OMAP_BEAGLE_BT_EN_GPIO (138) | ||
35 | +#define OMAP_BEAGLE_WLAN_IRQ_GPIO (137) | ||
36 | +#define OMAP_BEAGLE_FM_EN_BT_WU (136) | ||
37 | + | ||
38 | +struct wl12xx_platform_data omap_beagle_wlan_data __initdata = { | ||
39 | + .irq = OMAP_GPIO_IRQ(OMAP_BEAGLE_WLAN_IRQ_GPIO), | ||
40 | + .board_ref_clock = 2, /* 38.4 MHz */ | ||
41 | +}; | ||
42 | + | ||
43 | +static int gpios[] = {OMAP_BEAGLE_BT_EN_GPIO, OMAP_BEAGLE_FM_EN_BT_WU, -1}; | ||
44 | +static struct platform_device wl12xx_device = { | ||
45 | + .name = "kim", | ||
46 | + .id = -1, | ||
47 | + .dev.platform_data = &gpios, | ||
48 | +}; | ||
49 | + | ||
50 | +static struct omap2_hsmmc_info mmcbbt[] = { | ||
51 | + { | ||
52 | + .mmc = 1, | ||
53 | + .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, | ||
54 | + .gpio_wp = 29, | ||
55 | + }, | ||
56 | + { | ||
57 | + .name = "wl1271", | ||
58 | + .mmc = 2, | ||
59 | + .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD, | ||
60 | + .gpio_wp = -EINVAL, | ||
61 | + .gpio_cd = -EINVAL, | ||
62 | + .ocr_mask = MMC_VDD_165_195, | ||
63 | + .nonremovable = true, | ||
64 | + }, | ||
65 | + {} /* Terminator */ | ||
66 | + }; | ||
67 | + | ||
68 | +static struct regulator_consumer_supply beagle_vmmc2_supply = | ||
69 | + REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"); | ||
70 | + | ||
71 | +static struct regulator_init_data beagle_vmmc2 = { | ||
72 | + .constraints = { | ||
73 | + .min_uV = 1850000, | ||
74 | + .max_uV = 1850000, | ||
75 | + .apply_uV = true, | ||
76 | + .valid_modes_mask = REGULATOR_MODE_NORMAL | ||
77 | + | REGULATOR_MODE_STANDBY, | ||
78 | + .valid_ops_mask = REGULATOR_CHANGE_MODE | ||
79 | + | REGULATOR_CHANGE_STATUS, | ||
80 | + }, | ||
81 | + .num_consumer_supplies = 1, | ||
82 | + .consumer_supplies = &beagle_vmmc2_supply, | ||
83 | +}; | ||
84 | + | ||
85 | +static struct fixed_voltage_config beagle_vwlan = { | ||
86 | + .supply_name = "vwl1271", | ||
87 | + .microvolts = 1800000, /* 1.8V */ | ||
88 | + .gpio = OMAP_BEAGLE_WLAN_EN_GPIO, | ||
89 | + .startup_delay = 70000, /* 70ms */ | ||
90 | + .enable_high = 1, | ||
91 | + .enabled_at_boot = 0, | ||
92 | + .init_data = &beagle_vmmc2, | ||
93 | +}; | ||
94 | + | ||
95 | +static struct platform_device omap_vwlan_device = { | ||
96 | + .name = "reg-fixed-voltage", | ||
97 | + .id = 1, | ||
98 | + .dev = { | ||
99 | + .platform_data = &beagle_vwlan, | ||
100 | + }, | ||
101 | +}; | ||
102 | +#endif | ||
103 | + | ||
104 | +#if defined(CONFIG_ENC28J60) || defined(CONFIG_ENC28J60_MODULE) | ||
105 | + | ||
106 | +#include <plat/mcspi.h> | ||
107 | +#include <linux/spi/spi.h> | ||
108 | + | ||
109 | +#define OMAP3BEAGLE_GPIO_ENC28J60_IRQ 157 | ||
110 | + | ||
111 | +static struct omap2_mcspi_device_config enc28j60_spi_chip_info = { | ||
112 | + .turbo_mode = 0, | ||
113 | + .single_channel = 1, /* 0: slave, 1: master */ | ||
114 | +}; | ||
115 | + | ||
116 | +static struct spi_board_info omap3beagle_zippy_spi_board_info[] __initdata = { | ||
117 | + { | ||
118 | + .modalias = "enc28j60", | ||
119 | + .bus_num = 4, | ||
120 | + .chip_select = 0, | ||
121 | + .max_speed_hz = 20000000, | ||
122 | + .controller_data = &enc28j60_spi_chip_info, | ||
123 | + }, | ||
124 | +}; | ||
125 | + | ||
126 | +static void __init omap3beagle_enc28j60_init(void) | ||
127 | +{ | ||
128 | + if ((gpio_request(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, "ENC28J60_IRQ") == 0) && | ||
129 | + (gpio_direction_input(OMAP3BEAGLE_GPIO_ENC28J60_IRQ) == 0)) { | ||
130 | + gpio_export(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, 0); | ||
131 | + omap3beagle_zippy_spi_board_info[0].irq = OMAP_GPIO_IRQ(OMAP3BEAGLE_GPIO_ENC28J60_IRQ); | ||
132 | + irq_set_irq_type(omap3beagle_zippy_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING); | ||
133 | + } else { | ||
134 | + printk(KERN_ERR "could not obtain gpio for ENC28J60_IRQ\n"); | ||
135 | + return; | ||
136 | + } | ||
137 | + | ||
138 | + spi_register_board_info(omap3beagle_zippy_spi_board_info, | ||
139 | + ARRAY_SIZE(omap3beagle_zippy_spi_board_info)); | ||
140 | +} | ||
141 | + | ||
142 | +#else | ||
143 | +static inline void __init omap3beagle_enc28j60_init(void) { return; } | ||
144 | +#endif | ||
145 | + | ||
146 | +#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE) | ||
147 | + | ||
148 | +#include <plat/mcspi.h> | ||
149 | +#include <linux/spi/spi.h> | ||
150 | + | ||
151 | +#define OMAP3BEAGLE_GPIO_KS8851_IRQ 157 | ||
152 | + | ||
153 | +static struct omap2_mcspi_device_config ks8851_spi_chip_info = { | ||
154 | + .turbo_mode = 0, | ||
155 | + .single_channel = 1, /* 0: slave, 1: master */ | ||
156 | +}; | ||
157 | + | ||
158 | +static struct spi_board_info omap3beagle_zippy2_spi_board_info[] __initdata = { | ||
159 | + { | ||
160 | + .modalias = "ks8851", | ||
161 | + .bus_num = 4, | ||
162 | + .chip_select = 0, | ||
163 | + .max_speed_hz = 36000000, | ||
164 | + .controller_data = &ks8851_spi_chip_info, | ||
165 | + }, | ||
166 | +}; | ||
167 | + | ||
168 | +static void __init omap3beagle_ks8851_init(void) | ||
169 | +{ | ||
170 | + if ((gpio_request(OMAP3BEAGLE_GPIO_KS8851_IRQ, "KS8851_IRQ") == 0) && | ||
171 | + (gpio_direction_input(OMAP3BEAGLE_GPIO_KS8851_IRQ) == 0)) { | ||
172 | + gpio_export(OMAP3BEAGLE_GPIO_KS8851_IRQ, 0); | ||
173 | + omap3beagle_zippy2_spi_board_info[0].irq = OMAP_GPIO_IRQ(OMAP3BEAGLE_GPIO_KS8851_IRQ); | ||
174 | + irq_set_irq_type(omap3beagle_zippy2_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING); | ||
175 | + } else { | ||
176 | + printk(KERN_ERR "could not obtain gpio for KS8851_IRQ\n"); | ||
177 | + return; | ||
178 | + } | ||
179 | + | ||
180 | + spi_register_board_info(omap3beagle_zippy2_spi_board_info, | ||
181 | + ARRAY_SIZE(omap3beagle_zippy2_spi_board_info)); | ||
182 | +} | ||
183 | + | ||
184 | +#else | ||
185 | +static inline void __init omap3beagle_ks8851_init(void) { return; } | ||
186 | +#endif | ||
187 | + | ||
188 | static struct mtd_partition omap3beagle_nand_partitions[] = { | ||
189 | /* All the partition sizes are listed in terms of NAND block size */ | ||
190 | { | ||
191 | @@ -272,6 +434,12 @@ static struct omap2_hsmmc_info mmc[] = { | ||
192 | .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, | ||
193 | .gpio_wp = 29, | ||
194 | }, | ||
195 | + { | ||
196 | + .mmc = 2, | ||
197 | + .caps = MMC_CAP_4_BIT_DATA, | ||
198 | + .transceiver = true, | ||
199 | + .ocr_mask = 0x00100000, /* 3.3V */ | ||
200 | + }, | ||
201 | {} /* Terminator */ | ||
202 | }; | ||
203 | |||
204 | @@ -301,11 +469,25 @@ static int beagle_twl_gpio_setup(struct device *dev, | ||
205 | } | ||
206 | /* gpio + 0 is "mmc0_cd" (input/IRQ) */ | ||
207 | mmc[0].gpio_cd = gpio + 0; | ||
208 | +#if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE) | ||
209 | + if(!strcmp(expansionboard_name, "bbtoys-wifi")) { | ||
210 | + omap2_hsmmc_init(mmcbbt); | ||
211 | + /* link regulators to MMC adapters */ | ||
212 | + beagle_vmmc1_supply.dev = mmcbbt[0].dev; | ||
213 | + beagle_vsim_supply.dev = mmcbbt[0].dev; | ||
214 | + } else { | ||
215 | + omap2_hsmmc_init(mmc); | ||
216 | + /* link regulators to MMC adapters */ | ||
217 | + beagle_vmmc1_supply.dev = mmc[0].dev; | ||
218 | + beagle_vsim_supply.dev = mmc[0].dev; | ||
219 | + } | ||
220 | +#else | ||
221 | omap2_hsmmc_init(mmc); | ||
222 | |||
223 | /* link regulators to MMC adapters */ | ||
224 | beagle_vmmc1_supply.dev = mmc[0].dev; | ||
225 | beagle_vsim_supply.dev = mmc[0].dev; | ||
226 | +#endif | ||
227 | |||
228 | /* REVISIT: need ehci-omap hooks for external VBUS | ||
229 | * power switch and overcurrent detect | ||
230 | @@ -466,7 +648,7 @@ static struct twl4030_platform_data beagle_twldata = { | ||
231 | .vpll2 = &beagle_vpll2, | ||
232 | }; | ||
233 | |||
234 | -static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = { | ||
235 | +static struct i2c_board_info __initdata beagle_i2c1_boardinfo[] = { | ||
236 | { | ||
237 | I2C_BOARD_INFO("twl4030", 0x48), | ||
238 | .flags = I2C_CLIENT_WAKE, | ||
239 | @@ -481,10 +663,24 @@ static struct i2c_board_info __initdata beagle_i2c_eeprom[] = { | ||
240 | }, | ||
241 | }; | ||
242 | |||
243 | +#if defined(CONFIG_RTC_DRV_DS1307) || \ | ||
244 | + defined(CONFIG_RTC_DRV_DS1307_MODULE) | ||
245 | + | ||
246 | +static struct i2c_board_info __initdata beagle_i2c2_boardinfo[] = { | ||
247 | + { | ||
248 | + I2C_BOARD_INFO("ds1307", 0x68), | ||
249 | + }, | ||
250 | +}; | ||
251 | +#else | ||
252 | +static struct i2c_board_info __initdata beagle_i2c2_boardinfo[] = {}; | ||
253 | +#endif | ||
254 | + | ||
255 | static int __init omap3_beagle_i2c_init(void) | ||
256 | { | ||
257 | - omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo, | ||
258 | - ARRAY_SIZE(beagle_i2c_boardinfo)); | ||
259 | + omap_register_i2c_bus(1, 2600, beagle_i2c1_boardinfo, | ||
260 | + ARRAY_SIZE(beagle_i2c1_boardinfo)); | ||
261 | + omap_register_i2c_bus(2, 400, beagle_i2c2_boardinfo, | ||
262 | + ARRAY_SIZE(beagle_i2c2_boardinfo)); | ||
263 | /* Bus 3 is attached to the DVI port where devices like the pico DLP | ||
264 | * projector don't work reliably with 400kHz */ | ||
265 | omap_register_i2c_bus(3, 100, beagle_i2c_eeprom, ARRAY_SIZE(beagle_i2c_eeprom)); | ||
266 | @@ -627,6 +823,15 @@ static struct omap_musb_board_data musb_board_data = { | ||
267 | .power = 100, | ||
268 | }; | ||
269 | |||
270 | +static int __init expansionboard_setup(char *str) | ||
271 | +{ | ||
272 | + if (!str) | ||
273 | + return -EINVAL; | ||
274 | + strncpy(expansionboard_name, str, 16); | ||
275 | + printk(KERN_INFO "Beagle expansionboard: %s\n", expansionboard_name); | ||
276 | + return 0; | ||
277 | +} | ||
278 | + | ||
279 | static void __init beagle_opp_init(void) | ||
280 | { | ||
281 | int r = 0; | ||
282 | @@ -693,6 +898,65 @@ static void __init omap3_beagle_init(void) | ||
283 | /* REVISIT leave DVI powered down until it's needed ... */ | ||
284 | gpio_direction_output(170, true); | ||
285 | |||
286 | + if(!strcmp(expansionboard_name, "zippy")) | ||
287 | + { | ||
288 | + printk(KERN_INFO "Beagle expansionboard: initializing enc28j60\n"); | ||
289 | + omap3beagle_enc28j60_init(); | ||
290 | + printk(KERN_INFO "Beagle expansionboard: assigning GPIO 141 and 162 to MMC1\n"); | ||
291 | + mmc[1].gpio_wp = 141; | ||
292 | + mmc[1].gpio_cd = 162; | ||
293 | + } | ||
294 | + | ||
295 | + if(!strcmp(expansionboard_name, "zippy2")) | ||
296 | + { | ||
297 | + printk(KERN_INFO "Beagle expansionboard: initializing ks_8851\n"); | ||
298 | + omap3beagle_ks8851_init(); | ||
299 | + printk(KERN_INFO "Beagle expansionboard: assigning GPIO 141 and 162 to MMC1\n"); | ||
300 | + mmc[1].gpio_wp = 141; | ||
301 | + mmc[1].gpio_cd = 162; | ||
302 | + } | ||
303 | + | ||
304 | + if(!strcmp(expansionboard_name, "trainer")) | ||
305 | + { | ||
306 | + printk(KERN_INFO "Beagle expansionboard: exporting GPIOs 130-141,162 to userspace\n"); | ||
307 | + gpio_request(130, "sysfs"); | ||
308 | + gpio_export(130, 1); | ||
309 | + gpio_request(131, "sysfs"); | ||
310 | + gpio_export(131, 1); | ||
311 | + gpio_request(132, "sysfs"); | ||
312 | + gpio_export(132, 1); | ||
313 | + gpio_request(133, "sysfs"); | ||
314 | + gpio_export(133, 1); | ||
315 | + gpio_request(134, "sysfs"); | ||
316 | + gpio_export(134, 1); | ||
317 | + gpio_request(135, "sysfs"); | ||
318 | + gpio_export(135, 1); | ||
319 | + gpio_request(136, "sysfs"); | ||
320 | + gpio_export(136, 1); | ||
321 | + gpio_request(137, "sysfs"); | ||
322 | + gpio_export(137, 1); | ||
323 | + gpio_request(138, "sysfs"); | ||
324 | + gpio_export(138, 1); | ||
325 | + gpio_request(139, "sysfs"); | ||
326 | + gpio_export(139, 1); | ||
327 | + gpio_request(140, "sysfs"); | ||
328 | + gpio_export(140, 1); | ||
329 | + gpio_request(141, "sysfs"); | ||
330 | + gpio_export(141, 1); | ||
331 | + gpio_request(162, "sysfs"); | ||
332 | + gpio_export(162, 1); | ||
333 | + } | ||
334 | + | ||
335 | + if(!strcmp(expansionboard_name, "bbtoys-wifi")) | ||
336 | + { | ||
337 | + if (wl12xx_set_platform_data(&omap_beagle_wlan_data)) | ||
338 | + pr_err("error setting wl12xx data\n"); | ||
339 | + printk(KERN_INFO "Beagle expansionboard: registering wl12xx bt platform device\n"); | ||
340 | + platform_device_register(&wl12xx_device); | ||
341 | + printk(KERN_INFO "Beagle expansionboard: registering wl12xx wifi platform device\n"); | ||
342 | + platform_device_register(&omap_vwlan_device); | ||
343 | + } | ||
344 | + | ||
345 | usb_musb_init(&musb_board_data); | ||
346 | usbhs_init(&usbhs_bdata); | ||
347 | omap3beagle_flash_init(); | ||
348 | @@ -705,6 +969,8 @@ static void __init omap3_beagle_init(void) | ||
349 | beagle_opp_init(); | ||
350 | } | ||
351 | |||
352 | +early_param("buddy", expansionboard_setup); | ||
353 | + | ||
354 | MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board") | ||
355 | /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */ | ||
356 | .boot_params = 0x80000100, | ||
357 | -- | ||
358 | 1.6.6.1 | ||
359 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/beagle/0003-OMAP3-beagle-add-MADC-support.patch b/recipes-kernel/linux/linux-omap-2.6.39/beagle/0003-OMAP3-beagle-add-MADC-support.patch deleted file mode 100644 index 79097dbf..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/beagle/0003-OMAP3-beagle-add-MADC-support.patch +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | From 91e701f3287923d11dd295b6a62186909e362503 Mon Sep 17 00:00:00 2001 | ||
2 | From: Koen Kooi <koen@dominion.thruhere.net> | ||
3 | Date: Sat, 21 May 2011 16:18:30 +0200 | ||
4 | Subject: [PATCH 3/7] OMAP3: beagle: add MADC support | ||
5 | |||
6 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
7 | --- | ||
8 | arch/arm/mach-omap2/board-omap3beagle.c | 5 +++++ | ||
9 | 1 files changed, 5 insertions(+), 0 deletions(-) | ||
10 | |||
11 | diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c | ||
12 | index db285e1..da4ba50 100644 | ||
13 | --- a/arch/arm/mach-omap2/board-omap3beagle.c | ||
14 | +++ b/arch/arm/mach-omap2/board-omap3beagle.c | ||
15 | @@ -634,6 +634,10 @@ static struct twl4030_codec_data beagle_codec_data = { | ||
16 | .audio = &beagle_audio_data, | ||
17 | }; | ||
18 | |||
19 | +static struct twl4030_madc_platform_data beagle_madc_data = { | ||
20 | + .irq_line = 1, | ||
21 | +}; | ||
22 | + | ||
23 | static struct twl4030_platform_data beagle_twldata = { | ||
24 | .irq_base = TWL4030_IRQ_BASE, | ||
25 | .irq_end = TWL4030_IRQ_END, | ||
26 | @@ -642,6 +646,7 @@ static struct twl4030_platform_data beagle_twldata = { | ||
27 | .usb = &beagle_usb_data, | ||
28 | .gpio = &beagle_gpio_data, | ||
29 | .codec = &beagle_codec_data, | ||
30 | + .madc = &beagle_madc_data, | ||
31 | .vmmc1 = &beagle_vmmc1, | ||
32 | .vsim = &beagle_vsim, | ||
33 | .vdac = &beagle_vdac, | ||
34 | -- | ||
35 | 1.6.6.1 | ||
36 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/beagle/0004-OMAP3-beagle-add-regulators-for-camera-interface.patch b/recipes-kernel/linux/linux-omap-2.6.39/beagle/0004-OMAP3-beagle-add-regulators-for-camera-interface.patch deleted file mode 100644 index 29e99569..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/beagle/0004-OMAP3-beagle-add-regulators-for-camera-interface.patch +++ /dev/null | |||
@@ -1,88 +0,0 @@ | |||
1 | From 9d7f46abab88c74e674461a2f4e9ab35b524a6ef Mon Sep 17 00:00:00 2001 | ||
2 | From: Koen Kooi <koen@dominion.thruhere.net> | ||
3 | Date: Wed, 25 May 2011 08:56:06 +0200 | ||
4 | Subject: [PATCH 4/7] OMAP3: beagle: add regulators for camera interface | ||
5 | |||
6 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
7 | --- | ||
8 | arch/arm/mach-omap2/board-omap3beagle.c | 50 +++++++++++++++++++++++++++++++ | ||
9 | 1 files changed, 50 insertions(+), 0 deletions(-) | ||
10 | |||
11 | diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c | ||
12 | index da4ba50..211cbdf 100644 | ||
13 | --- a/arch/arm/mach-omap2/board-omap3beagle.c | ||
14 | +++ b/arch/arm/mach-omap2/board-omap3beagle.c | ||
15 | @@ -453,6 +453,44 @@ static struct regulator_consumer_supply beagle_vsim_supply = { | ||
16 | |||
17 | static struct gpio_led gpio_leds[]; | ||
18 | |||
19 | +static struct regulator_consumer_supply beagle_vaux3_supply = { | ||
20 | + .supply = "cam_1v8", | ||
21 | +}; | ||
22 | + | ||
23 | +static struct regulator_consumer_supply beagle_vaux4_supply = { | ||
24 | + .supply = "cam_2v8", | ||
25 | +}; | ||
26 | + | ||
27 | +/* VAUX3 for CAM_1V8 */ | ||
28 | +static struct regulator_init_data beagle_vaux3 = { | ||
29 | + .constraints = { | ||
30 | + .min_uV = 1800000, | ||
31 | + .max_uV = 1800000, | ||
32 | + .apply_uV = true, | ||
33 | + .valid_modes_mask = REGULATOR_MODE_NORMAL | ||
34 | + | REGULATOR_MODE_STANDBY, | ||
35 | + .valid_ops_mask = REGULATOR_CHANGE_MODE | ||
36 | + | REGULATOR_CHANGE_STATUS, | ||
37 | + }, | ||
38 | + .num_consumer_supplies = 1, | ||
39 | + .consumer_supplies = &beagle_vaux3_supply, | ||
40 | +}; | ||
41 | + | ||
42 | +/* VAUX4 for CAM_2V8 */ | ||
43 | +static struct regulator_init_data beagle_vaux4 = { | ||
44 | + .constraints = { | ||
45 | + .min_uV = 1800000, | ||
46 | + .max_uV = 1800000, | ||
47 | + .apply_uV = true, | ||
48 | + .valid_modes_mask = REGULATOR_MODE_NORMAL | ||
49 | + | REGULATOR_MODE_STANDBY, | ||
50 | + .valid_ops_mask = REGULATOR_CHANGE_MODE | ||
51 | + | REGULATOR_CHANGE_STATUS, | ||
52 | + }, | ||
53 | + .num_consumer_supplies = 1, | ||
54 | + .consumer_supplies = &beagle_vaux4_supply, | ||
55 | +}; | ||
56 | + | ||
57 | static int beagle_twl_gpio_setup(struct device *dev, | ||
58 | unsigned gpio, unsigned ngpio) | ||
59 | { | ||
60 | @@ -504,6 +542,16 @@ static int beagle_twl_gpio_setup(struct device *dev, | ||
61 | pr_err("%s: unable to configure EHCI_nOC\n", __func__); | ||
62 | } | ||
63 | |||
64 | + if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) { | ||
65 | + /* | ||
66 | + * Power on camera interface - only on pre-production, not | ||
67 | + * needed on production boards | ||
68 | + */ | ||
69 | + gpio_request(gpio + 2, "CAM_EN"); | ||
70 | + gpio_direction_output(gpio + 2, 1); | ||
71 | + } | ||
72 | + | ||
73 | + | ||
74 | /* | ||
75 | * TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active | ||
76 | * high / others active low) | ||
77 | @@ -651,6 +699,8 @@ static struct twl4030_platform_data beagle_twldata = { | ||
78 | .vsim = &beagle_vsim, | ||
79 | .vdac = &beagle_vdac, | ||
80 | .vpll2 = &beagle_vpll2, | ||
81 | + .vaux3 = &beagle_vaux3, | ||
82 | + .vaux4 = &beagle_vaux4, | ||
83 | }; | ||
84 | |||
85 | static struct i2c_board_info __initdata beagle_i2c1_boardinfo[] = { | ||
86 | -- | ||
87 | 1.6.6.1 | ||
88 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/beagle/0005-OMAP3-beagle-HACK-add-in-1GHz-OPP.patch b/recipes-kernel/linux/linux-omap-2.6.39/beagle/0005-OMAP3-beagle-HACK-add-in-1GHz-OPP.patch deleted file mode 100644 index 8b65b76e..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/beagle/0005-OMAP3-beagle-HACK-add-in-1GHz-OPP.patch +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | From aa93263ed7827e33148396656b7e7ab4579509a5 Mon Sep 17 00:00:00 2001 | ||
2 | From: Koen Kooi <koen@dominion.thruhere.net> | ||
3 | Date: Wed, 25 May 2011 08:57:40 +0200 | ||
4 | Subject: [PATCH 5/7] OMAP3: beagle: HACK! add in 1GHz OPP | ||
5 | |||
6 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
7 | --- | ||
8 | arch/arm/mach-omap2/board-omap3beagle.c | 2 ++ | ||
9 | 1 files changed, 2 insertions(+), 0 deletions(-) | ||
10 | |||
11 | diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c | ||
12 | index 211cbdf..221bfda 100644 | ||
13 | --- a/arch/arm/mach-omap2/board-omap3beagle.c | ||
14 | +++ b/arch/arm/mach-omap2/board-omap3beagle.c | ||
15 | @@ -911,11 +911,13 @@ static void __init beagle_opp_init(void) | ||
16 | /* Enable MPU 1GHz and lower opps */ | ||
17 | dev = &mh->od->pdev.dev; | ||
18 | r = opp_enable(dev, 800000000); | ||
19 | + r |= opp_enable(dev, 1000000000); | ||
20 | /* TODO: MPU 1GHz needs SR and ABB */ | ||
21 | |||
22 | /* Enable IVA 800MHz and lower opps */ | ||
23 | dev = &dh->od->pdev.dev; | ||
24 | r |= opp_enable(dev, 660000000); | ||
25 | + r |= opp_enable(dev, 800000000); | ||
26 | /* TODO: DSP 800MHz needs SR and ABB */ | ||
27 | if (r) { | ||
28 | pr_err("%s: failed to enable higher opp %d\n", | ||
29 | -- | ||
30 | 1.6.6.1 | ||
31 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/beagle/0006-OMAP3-BEAGLE-fix-RTC.patch b/recipes-kernel/linux/linux-omap-2.6.39/beagle/0006-OMAP3-BEAGLE-fix-RTC.patch deleted file mode 100644 index 76443d94..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/beagle/0006-OMAP3-BEAGLE-fix-RTC.patch +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | From dd2c7ba245ec1b17e3d323a6c4a1cad9697dbbbe Mon Sep 17 00:00:00 2001 | ||
2 | From: Koen Kooi <koen@dominion.thruhere.net> | ||
3 | Date: Wed, 15 Jun 2011 16:25:50 +0200 | ||
4 | Subject: [PATCH 6/7] OMAP3: BEAGLE: fix RTC | ||
5 | |||
6 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
7 | --- | ||
8 | arch/arm/mach-omap2/board-omap3beagle.c | 3 +++ | ||
9 | 1 files changed, 3 insertions(+), 0 deletions(-) | ||
10 | |||
11 | diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c | ||
12 | index 221bfda..61564a4 100644 | ||
13 | --- a/arch/arm/mach-omap2/board-omap3beagle.c | ||
14 | +++ b/arch/arm/mach-omap2/board-omap3beagle.c | ||
15 | @@ -941,6 +941,9 @@ static void __init omap3_beagle_init(void) | ||
16 | omap3_beagle_init_rev(); | ||
17 | omap3_beagle_i2c_init(); | ||
18 | |||
19 | + /* Ensure msecure is mux'd to be able to set the RTC. */ | ||
20 | + omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH); | ||
21 | + | ||
22 | if (cpu_is_omap3630()) { | ||
23 | gpio_buttons[0].gpio = 4; | ||
24 | } | ||
25 | -- | ||
26 | 1.6.6.1 | ||
27 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/beagle/0007-omap-mmc-Adjust-dto-to-eliminate-timeout-errors.patch b/recipes-kernel/linux/linux-omap-2.6.39/beagle/0007-omap-mmc-Adjust-dto-to-eliminate-timeout-errors.patch deleted file mode 100644 index 8cd314c6..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/beagle/0007-omap-mmc-Adjust-dto-to-eliminate-timeout-errors.patch +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | From bd0b2f97c48aa6aac0c6a494f1c6ba5af5de486b Mon Sep 17 00:00:00 2001 | ||
2 | From: Steve Sakoman <steve@sakoman.com> | ||
3 | Date: Mon, 18 Jul 2011 23:13:41 -0500 | ||
4 | Subject: [PATCH] omap_hsmmc: Set dto to max value of 14 to avoid SD Card timeouts | ||
5 | |||
6 | This fixes MMC errors due to timeouts on certain SD Cards following suggestions | ||
7 | to set dto to 14 by Jason Kridner and Steven Kipisz | ||
8 | |||
9 | Details of the issue: | ||
10 | http://talk.maemo.org/showthread.php?p=1000707#post1000707 | ||
11 | |||
12 | This fix was originally proposed by Sukumar Ghoral of TI. | ||
13 | --- | ||
14 | drivers/mmc/host/omap_hsmmc.c | 3 +++ | ||
15 | 1 files changed, 3 insertions(+), 0 deletions(-) | ||
16 | |||
17 | diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c | ||
18 | index 9646a75..7443647 100644 | ||
19 | --- a/drivers/mmc/host/omap_hsmmc.c | ||
20 | +++ b/drivers/mmc/host/omap_hsmmc.c | ||
21 | @@ -1049,6 +1049,9 @@ static void set_data_timeout(struct omap_hsmmc_host *host, | ||
22 | dto = 14; | ||
23 | } | ||
24 | |||
25 | + /* Set dto to max value of 14 to avoid SD Card timeouts */ | ||
26 | + dto = 14; | ||
27 | + | ||
28 | reg &= ~DTO_MASK; | ||
29 | reg |= dto << DTO_SHIFT; | ||
30 | OMAP_HSMMC_WRITE(host->base, SYSCTL, reg); | ||
31 | -- | ||
32 | 1.7.0.4 | ||
33 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/beagle/0007-omap3-beagle-Use-GPTIMERi-1-for-clockevents.patch b/recipes-kernel/linux/linux-omap-2.6.39/beagle/0007-omap3-beagle-Use-GPTIMERi-1-for-clockevents.patch deleted file mode 100644 index d5a4cf67..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/beagle/0007-omap3-beagle-Use-GPTIMERi-1-for-clockevents.patch +++ /dev/null | |||
@@ -1,42 +0,0 @@ | |||
1 | From 101b0aedf8152711847e2f9f347d267a3ac7f287 Mon Sep 17 00:00:00 2001 | ||
2 | From: Sanjeev Premi <premi@ti.com> | ||
3 | Date: Fri, 24 Jun 2011 16:23:45 +0000 | ||
4 | Subject: [PATCH 7/7] omap3: beagle: Use GPTIMERi 1 for clockevents | ||
5 | |||
6 | The current selection of the GPTIMER on was result of | ||
7 | a hardware issue in early versions of the Beagleboards | ||
8 | (Ax and B1 thru B4). [1] [2] | ||
9 | |||
10 | Its been long since the hardware issue has been fixed. | ||
11 | This patch uses GPTIMER 1 for all newer board revisions | ||
12 | incl. Beagleboard XM. | ||
13 | |||
14 | [1] http://thread.gmane.org/gmane.comp.hardware.beagleboard.general/91 | ||
15 | [2] Errata #7 at http://elinux.org/BeagleBoard#Errata | ||
16 | |||
17 | Signed-off-by: Sanjeev Premi <premi@ti.com> | ||
18 | Cc: Paul Walmsley <paul@pwsan.com> | ||
19 | Reviewed-by: Paul Walmsley <paul@pwsan.com> | ||
20 | --- | ||
21 | arch/arm/mach-omap2/board-omap3beagle.c | 5 ++++- | ||
22 | 1 files changed, 4 insertions(+), 1 deletions(-) | ||
23 | |||
24 | diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c | ||
25 | index 61564a4..20d5912 100644 | ||
26 | --- a/arch/arm/mach-omap2/board-omap3beagle.c | ||
27 | +++ b/arch/arm/mach-omap2/board-omap3beagle.c | ||
28 | @@ -806,7 +806,10 @@ static void __init omap3_beagle_init_irq(void) | ||
29 | { | ||
30 | omap_init_irq(); | ||
31 | #ifdef CONFIG_OMAP_32K_TIMER | ||
32 | - omap2_gp_clockevent_set_gptimer(12); | ||
33 | + if (omap3_beagle_version == OMAP3BEAGLE_BOARD_AXBX) | ||
34 | + omap2_gp_clockevent_set_gptimer(12); | ||
35 | + else | ||
36 | + omap2_gp_clockevent_set_gptimer(1); | ||
37 | #endif | ||
38 | } | ||
39 | |||
40 | -- | ||
41 | 1.6.6.1 | ||
42 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/beagleboard/configs/stock b/recipes-kernel/linux/linux-omap-2.6.39/beagleboard/configs/stock deleted file mode 100644 index dd288e24..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/beagleboard/configs/stock +++ /dev/null | |||
@@ -1,3490 +0,0 @@ | |||
1 | # | ||
2 | # Automatically generated make config: don't edit | ||
3 | # Linux/arm 2.6.39 Kernel Configuration | ||
4 | # Fri May 20 13:11:13 2011 | ||
5 | # | ||
6 | CONFIG_ARM=y | ||
7 | CONFIG_HAVE_PWM=y | ||
8 | CONFIG_SYS_SUPPORTS_APM_EMULATION=y | ||
9 | CONFIG_HAVE_SCHED_CLOCK=y | ||
10 | CONFIG_GENERIC_GPIO=y | ||
11 | # CONFIG_ARCH_USES_GETTIMEOFFSET is not set | ||
12 | CONFIG_GENERIC_CLOCKEVENTS=y | ||
13 | CONFIG_KTIME_SCALAR=y | ||
14 | CONFIG_HAVE_PROC_CPU=y | ||
15 | CONFIG_STACKTRACE_SUPPORT=y | ||
16 | CONFIG_HAVE_LATENCYTOP_SUPPORT=y | ||
17 | CONFIG_LOCKDEP_SUPPORT=y | ||
18 | CONFIG_TRACE_IRQFLAGS_SUPPORT=y | ||
19 | CONFIG_HARDIRQS_SW_RESEND=y | ||
20 | CONFIG_GENERIC_IRQ_PROBE=y | ||
21 | CONFIG_RWSEM_GENERIC_SPINLOCK=y | ||
22 | CONFIG_ARCH_HAS_CPUFREQ=y | ||
23 | CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y | ||
24 | CONFIG_GENERIC_HWEIGHT=y | ||
25 | CONFIG_GENERIC_CALIBRATE_DELAY=y | ||
26 | CONFIG_NEED_DMA_MAP_STATE=y | ||
27 | CONFIG_VECTORS_BASE=0xffff0000 | ||
28 | # CONFIG_ARM_PATCH_PHYS_VIRT is not set | ||
29 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" | ||
30 | CONFIG_CONSTRUCTORS=y | ||
31 | CONFIG_HAVE_IRQ_WORK=y | ||
32 | CONFIG_IRQ_WORK=y | ||
33 | |||
34 | # | ||
35 | # General setup | ||
36 | # | ||
37 | CONFIG_EXPERIMENTAL=y | ||
38 | CONFIG_BROKEN_ON_SMP=y | ||
39 | CONFIG_INIT_ENV_ARG_LIMIT=32 | ||
40 | CONFIG_CROSS_COMPILE="" | ||
41 | CONFIG_LOCALVERSION="" | ||
42 | # CONFIG_LOCALVERSION_AUTO is not set | ||
43 | CONFIG_HAVE_KERNEL_GZIP=y | ||
44 | CONFIG_HAVE_KERNEL_LZMA=y | ||
45 | CONFIG_HAVE_KERNEL_LZO=y | ||
46 | CONFIG_KERNEL_GZIP=y | ||
47 | # CONFIG_KERNEL_LZMA is not set | ||
48 | # CONFIG_KERNEL_LZO is not set | ||
49 | CONFIG_SWAP=y | ||
50 | CONFIG_SYSVIPC=y | ||
51 | CONFIG_SYSVIPC_SYSCTL=y | ||
52 | # CONFIG_POSIX_MQUEUE is not set | ||
53 | CONFIG_BSD_PROCESS_ACCT=y | ||
54 | # CONFIG_BSD_PROCESS_ACCT_V3 is not set | ||
55 | CONFIG_FHANDLE=y | ||
56 | CONFIG_TASKSTATS=y | ||
57 | CONFIG_TASK_DELAY_ACCT=y | ||
58 | CONFIG_TASK_XACCT=y | ||
59 | CONFIG_TASK_IO_ACCOUNTING=y | ||
60 | # CONFIG_AUDIT is not set | ||
61 | CONFIG_HAVE_GENERIC_HARDIRQS=y | ||
62 | |||
63 | # | ||
64 | # IRQ subsystem | ||
65 | # | ||
66 | CONFIG_GENERIC_HARDIRQS=y | ||
67 | CONFIG_HAVE_SPARSE_IRQ=y | ||
68 | CONFIG_GENERIC_IRQ_SHOW=y | ||
69 | # CONFIG_SPARSE_IRQ is not set | ||
70 | |||
71 | # | ||
72 | # RCU Subsystem | ||
73 | # | ||
74 | CONFIG_TREE_PREEMPT_RCU=y | ||
75 | # CONFIG_TINY_RCU is not set | ||
76 | # CONFIG_TINY_PREEMPT_RCU is not set | ||
77 | CONFIG_PREEMPT_RCU=y | ||
78 | # CONFIG_RCU_TRACE is not set | ||
79 | CONFIG_RCU_FANOUT=32 | ||
80 | # CONFIG_RCU_FANOUT_EXACT is not set | ||
81 | # CONFIG_TREE_RCU_TRACE is not set | ||
82 | CONFIG_IKCONFIG=y | ||
83 | CONFIG_IKCONFIG_PROC=y | ||
84 | CONFIG_LOG_BUF_SHIFT=16 | ||
85 | CONFIG_CGROUPS=y | ||
86 | # CONFIG_CGROUP_DEBUG is not set | ||
87 | CONFIG_CGROUP_NS=y | ||
88 | CONFIG_CGROUP_FREEZER=y | ||
89 | CONFIG_CGROUP_DEVICE=y | ||
90 | CONFIG_CPUSETS=y | ||
91 | CONFIG_PROC_PID_CPUSET=y | ||
92 | CONFIG_CGROUP_CPUACCT=y | ||
93 | CONFIG_RESOURCE_COUNTERS=y | ||
94 | CONFIG_CGROUP_MEM_RES_CTLR=y | ||
95 | CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y | ||
96 | CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED=y | ||
97 | CONFIG_CGROUP_PERF=y | ||
98 | CONFIG_CGROUP_SCHED=y | ||
99 | CONFIG_FAIR_GROUP_SCHED=y | ||
100 | CONFIG_RT_GROUP_SCHED=y | ||
101 | # CONFIG_BLK_CGROUP is not set | ||
102 | # CONFIG_NAMESPACES is not set | ||
103 | CONFIG_SCHED_AUTOGROUP=y | ||
104 | CONFIG_MM_OWNER=y | ||
105 | # CONFIG_SYSFS_DEPRECATED is not set | ||
106 | # CONFIG_RELAY is not set | ||
107 | CONFIG_BLK_DEV_INITRD=y | ||
108 | CONFIG_INITRAMFS_SOURCE="" | ||
109 | CONFIG_RD_GZIP=y | ||
110 | # CONFIG_RD_BZIP2 is not set | ||
111 | # CONFIG_RD_LZMA is not set | ||
112 | CONFIG_RD_XZ=y | ||
113 | CONFIG_RD_LZO=y | ||
114 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y | ||
115 | CONFIG_SYSCTL=y | ||
116 | CONFIG_ANON_INODES=y | ||
117 | CONFIG_EXPERT=y | ||
118 | CONFIG_UID16=y | ||
119 | # CONFIG_SYSCTL_SYSCALL is not set | ||
120 | CONFIG_KALLSYMS=y | ||
121 | # CONFIG_KALLSYMS_ALL is not set | ||
122 | # CONFIG_KALLSYMS_EXTRA_PASS is not set | ||
123 | CONFIG_HOTPLUG=y | ||
124 | CONFIG_PRINTK=y | ||
125 | CONFIG_BUG=y | ||
126 | CONFIG_ELF_CORE=y | ||
127 | CONFIG_BASE_FULL=y | ||
128 | CONFIG_FUTEX=y | ||
129 | CONFIG_EPOLL=y | ||
130 | CONFIG_SIGNALFD=y | ||
131 | CONFIG_TIMERFD=y | ||
132 | CONFIG_EVENTFD=y | ||
133 | CONFIG_SHMEM=y | ||
134 | CONFIG_AIO=y | ||
135 | CONFIG_EMBEDDED=y | ||
136 | CONFIG_HAVE_PERF_EVENTS=y | ||
137 | CONFIG_PERF_USE_VMALLOC=y | ||
138 | |||
139 | # | ||
140 | # Kernel Performance Events And Counters | ||
141 | # | ||
142 | CONFIG_PERF_EVENTS=y | ||
143 | # CONFIG_PERF_COUNTERS is not set | ||
144 | # CONFIG_DEBUG_PERF_USE_VMALLOC is not set | ||
145 | CONFIG_VM_EVENT_COUNTERS=y | ||
146 | # CONFIG_COMPAT_BRK is not set | ||
147 | CONFIG_SLAB=y | ||
148 | # CONFIG_SLUB is not set | ||
149 | # CONFIG_SLOB is not set | ||
150 | CONFIG_PROFILING=y | ||
151 | CONFIG_OPROFILE=y | ||
152 | CONFIG_HAVE_OPROFILE=y | ||
153 | # CONFIG_KPROBES is not set | ||
154 | CONFIG_HAVE_KPROBES=y | ||
155 | CONFIG_HAVE_KRETPROBES=y | ||
156 | CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y | ||
157 | CONFIG_HAVE_CLK=y | ||
158 | CONFIG_HAVE_DMA_API_DEBUG=y | ||
159 | CONFIG_HAVE_HW_BREAKPOINT=y | ||
160 | |||
161 | # | ||
162 | # GCOV-based kernel profiling | ||
163 | # | ||
164 | # CONFIG_GCOV_KERNEL is not set | ||
165 | CONFIG_HAVE_GENERIC_DMA_COHERENT=y | ||
166 | CONFIG_SLABINFO=y | ||
167 | CONFIG_RT_MUTEXES=y | ||
168 | CONFIG_BASE_SMALL=0 | ||
169 | CONFIG_MODULES=y | ||
170 | CONFIG_MODULE_FORCE_LOAD=y | ||
171 | CONFIG_MODULE_UNLOAD=y | ||
172 | CONFIG_MODULE_FORCE_UNLOAD=y | ||
173 | CONFIG_MODVERSIONS=y | ||
174 | CONFIG_MODULE_SRCVERSION_ALL=y | ||
175 | CONFIG_BLOCK=y | ||
176 | CONFIG_LBDAF=y | ||
177 | CONFIG_BLK_DEV_BSG=y | ||
178 | # CONFIG_BLK_DEV_INTEGRITY is not set | ||
179 | |||
180 | # | ||
181 | # IO Schedulers | ||
182 | # | ||
183 | CONFIG_IOSCHED_NOOP=y | ||
184 | CONFIG_IOSCHED_DEADLINE=y | ||
185 | CONFIG_IOSCHED_CFQ=y | ||
186 | # CONFIG_DEFAULT_DEADLINE is not set | ||
187 | CONFIG_DEFAULT_CFQ=y | ||
188 | # CONFIG_DEFAULT_NOOP is not set | ||
189 | CONFIG_DEFAULT_IOSCHED="cfq" | ||
190 | # CONFIG_INLINE_SPIN_TRYLOCK is not set | ||
191 | # CONFIG_INLINE_SPIN_TRYLOCK_BH is not set | ||
192 | # CONFIG_INLINE_SPIN_LOCK is not set | ||
193 | # CONFIG_INLINE_SPIN_LOCK_BH is not set | ||
194 | # CONFIG_INLINE_SPIN_LOCK_IRQ is not set | ||
195 | # CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set | ||
196 | # CONFIG_INLINE_SPIN_UNLOCK is not set | ||
197 | # CONFIG_INLINE_SPIN_UNLOCK_BH is not set | ||
198 | # CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set | ||
199 | # CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set | ||
200 | # CONFIG_INLINE_READ_TRYLOCK is not set | ||
201 | # CONFIG_INLINE_READ_LOCK is not set | ||
202 | # CONFIG_INLINE_READ_LOCK_BH is not set | ||
203 | # CONFIG_INLINE_READ_LOCK_IRQ is not set | ||
204 | # CONFIG_INLINE_READ_LOCK_IRQSAVE is not set | ||
205 | # CONFIG_INLINE_READ_UNLOCK is not set | ||
206 | # CONFIG_INLINE_READ_UNLOCK_BH is not set | ||
207 | # CONFIG_INLINE_READ_UNLOCK_IRQ is not set | ||
208 | # CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set | ||
209 | # CONFIG_INLINE_WRITE_TRYLOCK is not set | ||
210 | # CONFIG_INLINE_WRITE_LOCK is not set | ||
211 | # CONFIG_INLINE_WRITE_LOCK_BH is not set | ||
212 | # CONFIG_INLINE_WRITE_LOCK_IRQ is not set | ||
213 | # CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set | ||
214 | # CONFIG_INLINE_WRITE_UNLOCK is not set | ||
215 | # CONFIG_INLINE_WRITE_UNLOCK_BH is not set | ||
216 | # CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set | ||
217 | # CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set | ||
218 | # CONFIG_MUTEX_SPIN_ON_OWNER is not set | ||
219 | CONFIG_FREEZER=y | ||
220 | |||
221 | # | ||
222 | # System Type | ||
223 | # | ||
224 | CONFIG_MMU=y | ||
225 | # CONFIG_ARCH_INTEGRATOR is not set | ||
226 | # CONFIG_ARCH_REALVIEW is not set | ||
227 | # CONFIG_ARCH_VERSATILE is not set | ||
228 | # CONFIG_ARCH_VEXPRESS is not set | ||
229 | # CONFIG_ARCH_AT91 is not set | ||
230 | # CONFIG_ARCH_BCMRING is not set | ||
231 | # CONFIG_ARCH_CLPS711X is not set | ||
232 | # CONFIG_ARCH_CNS3XXX is not set | ||
233 | # CONFIG_ARCH_GEMINI is not set | ||
234 | # CONFIG_ARCH_EBSA110 is not set | ||
235 | # CONFIG_ARCH_EP93XX is not set | ||
236 | # CONFIG_ARCH_FOOTBRIDGE is not set | ||
237 | # CONFIG_ARCH_MXC is not set | ||
238 | # CONFIG_ARCH_MXS is not set | ||
239 | # CONFIG_ARCH_STMP3XXX is not set | ||
240 | # CONFIG_ARCH_NETX is not set | ||
241 | # CONFIG_ARCH_H720X is not set | ||
242 | # CONFIG_ARCH_IOP13XX is not set | ||
243 | # CONFIG_ARCH_IOP32X is not set | ||
244 | # CONFIG_ARCH_IOP33X is not set | ||
245 | # CONFIG_ARCH_IXP23XX is not set | ||
246 | # CONFIG_ARCH_IXP2000 is not set | ||
247 | # CONFIG_ARCH_IXP4XX is not set | ||
248 | # CONFIG_ARCH_DOVE is not set | ||
249 | # CONFIG_ARCH_KIRKWOOD is not set | ||
250 | # CONFIG_ARCH_LOKI is not set | ||
251 | # CONFIG_ARCH_LPC32XX is not set | ||
252 | # CONFIG_ARCH_MV78XX0 is not set | ||
253 | # CONFIG_ARCH_ORION5X is not set | ||
254 | # CONFIG_ARCH_MMP is not set | ||
255 | # CONFIG_ARCH_KS8695 is not set | ||
256 | # CONFIG_ARCH_NS9XXX is not set | ||
257 | # CONFIG_ARCH_W90X900 is not set | ||
258 | # CONFIG_ARCH_NUC93X is not set | ||
259 | # CONFIG_ARCH_TEGRA is not set | ||
260 | # CONFIG_ARCH_PNX4008 is not set | ||
261 | # CONFIG_ARCH_PXA is not set | ||
262 | # CONFIG_ARCH_MSM is not set | ||
263 | # CONFIG_ARCH_SHMOBILE is not set | ||
264 | # CONFIG_ARCH_RPC is not set | ||
265 | # CONFIG_ARCH_SA1100 is not set | ||
266 | # CONFIG_ARCH_S3C2410 is not set | ||
267 | # CONFIG_ARCH_S3C64XX is not set | ||
268 | # CONFIG_ARCH_S5P64X0 is not set | ||
269 | # CONFIG_ARCH_S5P6442 is not set | ||
270 | # CONFIG_ARCH_S5PC100 is not set | ||
271 | # CONFIG_ARCH_S5PV210 is not set | ||
272 | # CONFIG_ARCH_EXYNOS4 is not set | ||
273 | # CONFIG_ARCH_SHARK is not set | ||
274 | # CONFIG_ARCH_TCC_926 is not set | ||
275 | # CONFIG_ARCH_U300 is not set | ||
276 | # CONFIG_ARCH_U8500 is not set | ||
277 | # CONFIG_ARCH_NOMADIK is not set | ||
278 | # CONFIG_ARCH_DAVINCI is not set | ||
279 | CONFIG_ARCH_OMAP=y | ||
280 | # CONFIG_PLAT_SPEAR is not set | ||
281 | # CONFIG_ARCH_VT8500 is not set | ||
282 | # CONFIG_GPIO_PCA953X is not set | ||
283 | # CONFIG_KEYBOARD_GPIO_POLLED is not set | ||
284 | |||
285 | # | ||
286 | # TI OMAP Common Features | ||
287 | # | ||
288 | CONFIG_ARCH_OMAP_OTG=y | ||
289 | # CONFIG_ARCH_OMAP1 is not set | ||
290 | CONFIG_ARCH_OMAP2PLUS=y | ||
291 | |||
292 | # | ||
293 | # OMAP Feature Selections | ||
294 | # | ||
295 | CONFIG_OMAP_SMARTREFLEX=y | ||
296 | CONFIG_OMAP_SMARTREFLEX_CLASS3=y | ||
297 | CONFIG_OMAP_RESET_CLOCKS=y | ||
298 | # CONFIG_OMAP_MUX is not set | ||
299 | CONFIG_OMAP_MCBSP=y | ||
300 | CONFIG_OMAP_MBOX_FWK=m | ||
301 | CONFIG_OMAP_MBOX_KFIFO_SIZE=256 | ||
302 | CONFIG_OMAP_IOMMU=y | ||
303 | CONFIG_OMAP_IOMMU_DEBUG=m | ||
304 | CONFIG_OMAP_32K_TIMER=y | ||
305 | # CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set | ||
306 | CONFIG_OMAP_32K_TIMER_HZ=128 | ||
307 | CONFIG_OMAP_DM_TIMER=y | ||
308 | # CONFIG_OMAP_PM_NONE is not set | ||
309 | CONFIG_OMAP_PM_NOOP=y | ||
310 | |||
311 | # | ||
312 | # TI OMAP2/3/4 Specific Features | ||
313 | # | ||
314 | CONFIG_ARCH_OMAP2PLUS_TYPICAL=y | ||
315 | # CONFIG_ARCH_OMAP2 is not set | ||
316 | CONFIG_ARCH_OMAP3=y | ||
317 | # CONFIG_ARCH_OMAP4 is not set | ||
318 | CONFIG_SOC_OMAP3430=y | ||
319 | # CONFIG_SOC_OMAPTI816X is not set | ||
320 | CONFIG_OMAP_PACKAGE_CBB=y | ||
321 | |||
322 | # | ||
323 | # OMAP Board Type | ||
324 | # | ||
325 | CONFIG_MACH_OMAP3_BEAGLE=y | ||
326 | # CONFIG_MACH_DEVKIT8000 is not set | ||
327 | # CONFIG_MACH_OMAP_LDP is not set | ||
328 | # CONFIG_MACH_OMAP3530_LV_SOM is not set | ||
329 | # CONFIG_MACH_OMAP3_TORPEDO is not set | ||
330 | CONFIG_MACH_OVERO=y | ||
331 | CONFIG_MACH_OMAP3EVM=y | ||
332 | # CONFIG_MACH_OMAP3517EVM is not set | ||
333 | # CONFIG_MACH_CRANEBOARD is not set | ||
334 | # CONFIG_MACH_OMAP3_PANDORA is not set | ||
335 | CONFIG_MACH_OMAP3_TOUCHBOOK=y | ||
336 | # CONFIG_MACH_OMAP_3430SDP is not set | ||
337 | # CONFIG_MACH_NOKIA_RM680 is not set | ||
338 | # CONFIG_MACH_NOKIA_RX51 is not set | ||
339 | CONFIG_MACH_OMAP_ZOOM2=y | ||
340 | # CONFIG_MACH_OMAP_ZOOM3 is not set | ||
341 | # CONFIG_MACH_CM_T35 is not set | ||
342 | # CONFIG_MACH_CM_T3517 is not set | ||
343 | # CONFIG_MACH_IGEP0020 is not set | ||
344 | # CONFIG_MACH_IGEP0030 is not set | ||
345 | # CONFIG_MACH_SBC3530 is not set | ||
346 | # CONFIG_MACH_OMAP_3630SDP is not set | ||
347 | # CONFIG_OMAP3_EMU is not set | ||
348 | # CONFIG_OMAP3_SDRC_AC_TIMING is not set | ||
349 | |||
350 | # | ||
351 | # System MMU | ||
352 | # | ||
353 | |||
354 | # | ||
355 | # Processor Type | ||
356 | # | ||
357 | CONFIG_CPU_V7=y | ||
358 | CONFIG_CPU_32v6K=y | ||
359 | CONFIG_CPU_32v7=y | ||
360 | CONFIG_CPU_ABRT_EV7=y | ||
361 | CONFIG_CPU_PABRT_V7=y | ||
362 | CONFIG_CPU_CACHE_V7=y | ||
363 | CONFIG_CPU_CACHE_VIPT=y | ||
364 | CONFIG_CPU_COPY_V6=y | ||
365 | CONFIG_CPU_TLB_V7=y | ||
366 | CONFIG_CPU_HAS_ASID=y | ||
367 | CONFIG_CPU_CP15=y | ||
368 | CONFIG_CPU_CP15_MMU=y | ||
369 | |||
370 | # | ||
371 | # Processor Features | ||
372 | # | ||
373 | CONFIG_ARM_THUMB=y | ||
374 | CONFIG_ARM_THUMBEE=y | ||
375 | # CONFIG_SWP_EMULATE is not set | ||
376 | # CONFIG_CPU_ICACHE_DISABLE is not set | ||
377 | # CONFIG_CPU_DCACHE_DISABLE is not set | ||
378 | # CONFIG_CPU_BPREDICT_DISABLE is not set | ||
379 | CONFIG_ARM_L1_CACHE_SHIFT_6=y | ||
380 | CONFIG_ARM_L1_CACHE_SHIFT=6 | ||
381 | CONFIG_ARM_DMA_MEM_BUFFERABLE=y | ||
382 | CONFIG_ARM_ERRATA_430973=y | ||
383 | # CONFIG_ARM_ERRATA_458693 is not set | ||
384 | # CONFIG_ARM_ERRATA_460075 is not set | ||
385 | # CONFIG_ARM_ERRATA_743622 is not set | ||
386 | # CONFIG_ARM_ERRATA_754322 is not set | ||
387 | |||
388 | # | ||
389 | # Bus support | ||
390 | # | ||
391 | # CONFIG_PCI_SYSCALL is not set | ||
392 | # CONFIG_ARCH_SUPPORTS_MSI is not set | ||
393 | # CONFIG_PCCARD is not set | ||
394 | |||
395 | # | ||
396 | # Kernel Features | ||
397 | # | ||
398 | CONFIG_TICK_ONESHOT=y | ||
399 | CONFIG_NO_HZ=y | ||
400 | CONFIG_HIGH_RES_TIMERS=y | ||
401 | CONFIG_GENERIC_CLOCKEVENTS_BUILD=y | ||
402 | CONFIG_VMSPLIT_3G=y | ||
403 | # CONFIG_VMSPLIT_2G is not set | ||
404 | # CONFIG_VMSPLIT_1G is not set | ||
405 | CONFIG_PAGE_OFFSET=0xC0000000 | ||
406 | # CONFIG_PREEMPT_NONE is not set | ||
407 | # CONFIG_PREEMPT_VOLUNTARY is not set | ||
408 | CONFIG_PREEMPT=y | ||
409 | CONFIG_HZ=128 | ||
410 | # CONFIG_THUMB2_KERNEL is not set | ||
411 | CONFIG_AEABI=y | ||
412 | # CONFIG_OABI_COMPAT is not set | ||
413 | CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y | ||
414 | # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set | ||
415 | # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set | ||
416 | # CONFIG_HIGHMEM is not set | ||
417 | CONFIG_SELECT_MEMORY_MODEL=y | ||
418 | CONFIG_FLATMEM_MANUAL=y | ||
419 | CONFIG_FLATMEM=y | ||
420 | CONFIG_FLAT_NODE_MEM_MAP=y | ||
421 | CONFIG_HAVE_MEMBLOCK=y | ||
422 | CONFIG_PAGEFLAGS_EXTENDED=y | ||
423 | CONFIG_SPLIT_PTLOCK_CPUS=4 | ||
424 | CONFIG_COMPACTION=y | ||
425 | CONFIG_MIGRATION=y | ||
426 | # CONFIG_PHYS_ADDR_T_64BIT is not set | ||
427 | CONFIG_ZONE_DMA_FLAG=0 | ||
428 | CONFIG_VIRT_TO_BUS=y | ||
429 | # CONFIG_KSM is not set | ||
430 | CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 | ||
431 | CONFIG_NEED_PER_CPU_KM=y | ||
432 | CONFIG_FORCE_MAX_ZONEORDER=11 | ||
433 | CONFIG_LEDS=y | ||
434 | CONFIG_ALIGNMENT_TRAP=y | ||
435 | # CONFIG_UACCESS_WITH_MEMCPY is not set | ||
436 | # CONFIG_SECCOMP is not set | ||
437 | # CONFIG_CC_STACKPROTECTOR is not set | ||
438 | # CONFIG_DEPRECATED_PARAM_STRUCT is not set | ||
439 | |||
440 | # | ||
441 | # Boot options | ||
442 | # | ||
443 | CONFIG_ZBOOT_ROM_TEXT=0x0 | ||
444 | CONFIG_ZBOOT_ROM_BSS=0x0 | ||
445 | CONFIG_CMDLINE=" debug " | ||
446 | # CONFIG_CMDLINE_FORCE is not set | ||
447 | # CONFIG_XIP_KERNEL is not set | ||
448 | CONFIG_KEXEC=y | ||
449 | CONFIG_ATAGS_PROC=y | ||
450 | # CONFIG_CRASH_DUMP is not set | ||
451 | # CONFIG_AUTO_ZRELADDR is not set | ||
452 | |||
453 | # | ||
454 | # CPU Power Management | ||
455 | # | ||
456 | CONFIG_CPU_FREQ=y | ||
457 | CONFIG_CPU_FREQ_TABLE=y | ||
458 | CONFIG_CPU_FREQ_DEBUG=y | ||
459 | CONFIG_CPU_FREQ_STAT=y | ||
460 | CONFIG_CPU_FREQ_STAT_DETAILS=y | ||
461 | # CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set | ||
462 | # CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set | ||
463 | CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y | ||
464 | # CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set | ||
465 | # CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set | ||
466 | CONFIG_CPU_FREQ_GOV_PERFORMANCE=y | ||
467 | CONFIG_CPU_FREQ_GOV_POWERSAVE=y | ||
468 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | ||
469 | CONFIG_CPU_FREQ_GOV_ONDEMAND=y | ||
470 | CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y | ||
471 | CONFIG_CPU_IDLE=y | ||
472 | CONFIG_CPU_IDLE_GOV_LADDER=y | ||
473 | CONFIG_CPU_IDLE_GOV_MENU=y | ||
474 | |||
475 | # | ||
476 | # Floating point emulation | ||
477 | # | ||
478 | |||
479 | # | ||
480 | # At least one emulation must be selected | ||
481 | # | ||
482 | CONFIG_VFP=y | ||
483 | CONFIG_VFPv3=y | ||
484 | CONFIG_NEON=y | ||
485 | |||
486 | # | ||
487 | # Userspace binary formats | ||
488 | # | ||
489 | CONFIG_BINFMT_ELF=y | ||
490 | # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set | ||
491 | CONFIG_HAVE_AOUT=y | ||
492 | CONFIG_BINFMT_AOUT=m | ||
493 | CONFIG_BINFMT_MISC=y | ||
494 | |||
495 | # | ||
496 | # Power management options | ||
497 | # | ||
498 | CONFIG_SUSPEND=y | ||
499 | CONFIG_SUSPEND_FREEZER=y | ||
500 | CONFIG_PM_SLEEP=y | ||
501 | CONFIG_PM_RUNTIME=y | ||
502 | CONFIG_PM=y | ||
503 | CONFIG_PM_DEBUG=y | ||
504 | # CONFIG_PM_VERBOSE is not set | ||
505 | # CONFIG_PM_ADVANCED_DEBUG is not set | ||
506 | # CONFIG_PM_TEST_SUSPEND is not set | ||
507 | CONFIG_CAN_PM_TRACE=y | ||
508 | # CONFIG_APM_EMULATION is not set | ||
509 | CONFIG_ARCH_HAS_OPP=y | ||
510 | CONFIG_PM_OPP=y | ||
511 | CONFIG_ARCH_SUSPEND_POSSIBLE=y | ||
512 | CONFIG_NET=y | ||
513 | |||
514 | # | ||
515 | # Networking options | ||
516 | # | ||
517 | CONFIG_PACKET=y | ||
518 | CONFIG_UNIX=y | ||
519 | CONFIG_XFRM=y | ||
520 | # CONFIG_XFRM_USER is not set | ||
521 | # CONFIG_XFRM_SUB_POLICY is not set | ||
522 | # CONFIG_XFRM_MIGRATE is not set | ||
523 | # CONFIG_XFRM_STATISTICS is not set | ||
524 | CONFIG_XFRM_IPCOMP=m | ||
525 | CONFIG_NET_KEY=y | ||
526 | # CONFIG_NET_KEY_MIGRATE is not set | ||
527 | CONFIG_INET=y | ||
528 | # CONFIG_IP_MULTICAST is not set | ||
529 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
530 | CONFIG_IP_ROUTE_CLASSID=y | ||
531 | CONFIG_IP_PNP=y | ||
532 | CONFIG_IP_PNP_DHCP=y | ||
533 | CONFIG_IP_PNP_BOOTP=y | ||
534 | CONFIG_IP_PNP_RARP=y | ||
535 | CONFIG_NET_IPIP=m | ||
536 | CONFIG_NET_IPGRE_DEMUX=m | ||
537 | CONFIG_NET_IPGRE=m | ||
538 | # CONFIG_ARPD is not set | ||
539 | # CONFIG_SYN_COOKIES is not set | ||
540 | CONFIG_INET_AH=m | ||
541 | CONFIG_INET_ESP=m | ||
542 | CONFIG_INET_IPCOMP=m | ||
543 | CONFIG_INET_XFRM_TUNNEL=m | ||
544 | CONFIG_INET_TUNNEL=m | ||
545 | CONFIG_INET_XFRM_MODE_TRANSPORT=y | ||
546 | CONFIG_INET_XFRM_MODE_TUNNEL=y | ||
547 | CONFIG_INET_XFRM_MODE_BEET=y | ||
548 | CONFIG_INET_LRO=y | ||
549 | CONFIG_INET_DIAG=m | ||
550 | CONFIG_INET_TCP_DIAG=m | ||
551 | CONFIG_TCP_CONG_ADVANCED=y | ||
552 | CONFIG_TCP_CONG_BIC=m | ||
553 | CONFIG_TCP_CONG_CUBIC=y | ||
554 | CONFIG_TCP_CONG_WESTWOOD=m | ||
555 | CONFIG_TCP_CONG_HTCP=m | ||
556 | CONFIG_TCP_CONG_HSTCP=m | ||
557 | CONFIG_TCP_CONG_HYBLA=m | ||
558 | CONFIG_TCP_CONG_VEGAS=m | ||
559 | CONFIG_TCP_CONG_SCALABLE=m | ||
560 | CONFIG_TCP_CONG_LP=m | ||
561 | CONFIG_TCP_CONG_VENO=m | ||
562 | CONFIG_TCP_CONG_YEAH=m | ||
563 | CONFIG_TCP_CONG_ILLINOIS=m | ||
564 | CONFIG_DEFAULT_CUBIC=y | ||
565 | # CONFIG_DEFAULT_RENO is not set | ||
566 | CONFIG_DEFAULT_TCP_CONG="cubic" | ||
567 | # CONFIG_TCP_MD5SIG is not set | ||
568 | CONFIG_IPV6=m | ||
569 | # CONFIG_IPV6_PRIVACY is not set | ||
570 | # CONFIG_IPV6_ROUTER_PREF is not set | ||
571 | # CONFIG_IPV6_OPTIMISTIC_DAD is not set | ||
572 | CONFIG_INET6_AH=m | ||
573 | CONFIG_INET6_ESP=m | ||
574 | CONFIG_INET6_IPCOMP=m | ||
575 | CONFIG_IPV6_MIP6=m | ||
576 | CONFIG_INET6_XFRM_TUNNEL=m | ||
577 | CONFIG_INET6_TUNNEL=m | ||
578 | CONFIG_INET6_XFRM_MODE_TRANSPORT=m | ||
579 | CONFIG_INET6_XFRM_MODE_TUNNEL=m | ||
580 | CONFIG_INET6_XFRM_MODE_BEET=m | ||
581 | CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m | ||
582 | CONFIG_IPV6_SIT=m | ||
583 | # CONFIG_IPV6_SIT_6RD is not set | ||
584 | CONFIG_IPV6_NDISC_NODETYPE=y | ||
585 | CONFIG_IPV6_TUNNEL=m | ||
586 | CONFIG_IPV6_MULTIPLE_TABLES=y | ||
587 | CONFIG_IPV6_SUBTREES=y | ||
588 | CONFIG_IPV6_MROUTE=y | ||
589 | CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y | ||
590 | # CONFIG_IPV6_PIMSM_V2 is not set | ||
591 | # CONFIG_NETWORK_SECMARK is not set | ||
592 | CONFIG_NETWORK_PHY_TIMESTAMPING=y | ||
593 | CONFIG_NETFILTER=y | ||
594 | # CONFIG_NETFILTER_DEBUG is not set | ||
595 | CONFIG_NETFILTER_ADVANCED=y | ||
596 | CONFIG_BRIDGE_NETFILTER=y | ||
597 | |||
598 | # | ||
599 | # Core Netfilter Configuration | ||
600 | # | ||
601 | CONFIG_NETFILTER_NETLINK=m | ||
602 | CONFIG_NETFILTER_NETLINK_QUEUE=m | ||
603 | CONFIG_NETFILTER_NETLINK_LOG=m | ||
604 | CONFIG_NF_CONNTRACK=m | ||
605 | CONFIG_NF_CONNTRACK_MARK=y | ||
606 | CONFIG_NF_CONNTRACK_ZONES=y | ||
607 | CONFIG_NF_CONNTRACK_EVENTS=y | ||
608 | CONFIG_NF_CONNTRACK_TIMESTAMP=y | ||
609 | CONFIG_NF_CT_PROTO_DCCP=m | ||
610 | CONFIG_NF_CT_PROTO_GRE=m | ||
611 | CONFIG_NF_CT_PROTO_SCTP=m | ||
612 | CONFIG_NF_CT_PROTO_UDPLITE=m | ||
613 | CONFIG_NF_CONNTRACK_AMANDA=m | ||
614 | CONFIG_NF_CONNTRACK_FTP=m | ||
615 | CONFIG_NF_CONNTRACK_H323=m | ||
616 | CONFIG_NF_CONNTRACK_IRC=m | ||
617 | CONFIG_NF_CONNTRACK_BROADCAST=m | ||
618 | CONFIG_NF_CONNTRACK_NETBIOS_NS=m | ||
619 | CONFIG_NF_CONNTRACK_SNMP=m | ||
620 | CONFIG_NF_CONNTRACK_PPTP=m | ||
621 | CONFIG_NF_CONNTRACK_SANE=m | ||
622 | CONFIG_NF_CONNTRACK_SIP=m | ||
623 | CONFIG_NF_CONNTRACK_TFTP=m | ||
624 | CONFIG_NF_CT_NETLINK=m | ||
625 | # CONFIG_NETFILTER_TPROXY is not set | ||
626 | CONFIG_NETFILTER_XTABLES=m | ||
627 | |||
628 | # | ||
629 | # Xtables combined modules | ||
630 | # | ||
631 | CONFIG_NETFILTER_XT_MARK=m | ||
632 | CONFIG_NETFILTER_XT_CONNMARK=m | ||
633 | CONFIG_NETFILTER_XT_SET=m | ||
634 | |||
635 | # | ||
636 | # Xtables targets | ||
637 | # | ||
638 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m | ||
639 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | ||
640 | CONFIG_NETFILTER_XT_TARGET_CONNMARK=m | ||
641 | CONFIG_NETFILTER_XT_TARGET_CT=m | ||
642 | # CONFIG_NETFILTER_XT_TARGET_DSCP is not set | ||
643 | CONFIG_NETFILTER_XT_TARGET_HL=m | ||
644 | CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m | ||
645 | # CONFIG_NETFILTER_XT_TARGET_LED is not set | ||
646 | CONFIG_NETFILTER_XT_TARGET_MARK=m | ||
647 | CONFIG_NETFILTER_XT_TARGET_NFLOG=m | ||
648 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | ||
649 | # CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set | ||
650 | CONFIG_NETFILTER_XT_TARGET_RATEEST=m | ||
651 | CONFIG_NETFILTER_XT_TARGET_TEE=m | ||
652 | # CONFIG_NETFILTER_XT_TARGET_TRACE is not set | ||
653 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m | ||
654 | # CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set | ||
655 | |||
656 | # | ||
657 | # Xtables matches | ||
658 | # | ||
659 | CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m | ||
660 | # CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set | ||
661 | CONFIG_NETFILTER_XT_MATCH_COMMENT=m | ||
662 | CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m | ||
663 | CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m | ||
664 | CONFIG_NETFILTER_XT_MATCH_CONNMARK=m | ||
665 | CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m | ||
666 | CONFIG_NETFILTER_XT_MATCH_CPU=m | ||
667 | CONFIG_NETFILTER_XT_MATCH_DCCP=m | ||
668 | CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m | ||
669 | CONFIG_NETFILTER_XT_MATCH_DSCP=m | ||
670 | CONFIG_NETFILTER_XT_MATCH_ESP=m | ||
671 | CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m | ||
672 | CONFIG_NETFILTER_XT_MATCH_HELPER=m | ||
673 | CONFIG_NETFILTER_XT_MATCH_HL=m | ||
674 | CONFIG_NETFILTER_XT_MATCH_IPRANGE=m | ||
675 | CONFIG_NETFILTER_XT_MATCH_IPVS=m | ||
676 | CONFIG_NETFILTER_XT_MATCH_LENGTH=m | ||
677 | CONFIG_NETFILTER_XT_MATCH_LIMIT=m | ||
678 | CONFIG_NETFILTER_XT_MATCH_MAC=m | ||
679 | CONFIG_NETFILTER_XT_MATCH_MARK=m | ||
680 | CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m | ||
681 | # CONFIG_NETFILTER_XT_MATCH_OSF is not set | ||
682 | CONFIG_NETFILTER_XT_MATCH_OWNER=m | ||
683 | CONFIG_NETFILTER_XT_MATCH_POLICY=m | ||
684 | # CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set | ||
685 | CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m | ||
686 | CONFIG_NETFILTER_XT_MATCH_QUOTA=m | ||
687 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m | ||
688 | CONFIG_NETFILTER_XT_MATCH_REALM=m | ||
689 | CONFIG_NETFILTER_XT_MATCH_RECENT=m | ||
690 | CONFIG_NETFILTER_XT_MATCH_SCTP=m | ||
691 | CONFIG_NETFILTER_XT_MATCH_STATE=m | ||
692 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m | ||
693 | CONFIG_NETFILTER_XT_MATCH_STRING=m | ||
694 | CONFIG_NETFILTER_XT_MATCH_TCPMSS=m | ||
695 | CONFIG_NETFILTER_XT_MATCH_TIME=m | ||
696 | CONFIG_NETFILTER_XT_MATCH_U32=m | ||
697 | CONFIG_IP_SET=m | ||
698 | CONFIG_IP_SET_MAX=256 | ||
699 | # CONFIG_IP_SET_BITMAP_IP is not set | ||
700 | # CONFIG_IP_SET_BITMAP_IPMAC is not set | ||
701 | # CONFIG_IP_SET_BITMAP_PORT is not set | ||
702 | # CONFIG_IP_SET_HASH_IP is not set | ||
703 | # CONFIG_IP_SET_HASH_IPPORT is not set | ||
704 | # CONFIG_IP_SET_HASH_IPPORTIP is not set | ||
705 | # CONFIG_IP_SET_HASH_IPPORTNET is not set | ||
706 | # CONFIG_IP_SET_HASH_NET is not set | ||
707 | # CONFIG_IP_SET_HASH_NETPORT is not set | ||
708 | # CONFIG_IP_SET_LIST_SET is not set | ||
709 | CONFIG_IP_VS=m | ||
710 | CONFIG_IP_VS_IPV6=y | ||
711 | CONFIG_IP_VS_DEBUG=y | ||
712 | CONFIG_IP_VS_TAB_BITS=12 | ||
713 | |||
714 | # | ||
715 | # IPVS transport protocol load balancing support | ||
716 | # | ||
717 | CONFIG_IP_VS_PROTO_TCP=y | ||
718 | CONFIG_IP_VS_PROTO_UDP=y | ||
719 | CONFIG_IP_VS_PROTO_AH_ESP=y | ||
720 | CONFIG_IP_VS_PROTO_ESP=y | ||
721 | CONFIG_IP_VS_PROTO_AH=y | ||
722 | # CONFIG_IP_VS_PROTO_SCTP is not set | ||
723 | |||
724 | # | ||
725 | # IPVS scheduler | ||
726 | # | ||
727 | CONFIG_IP_VS_RR=m | ||
728 | CONFIG_IP_VS_WRR=m | ||
729 | CONFIG_IP_VS_LC=m | ||
730 | CONFIG_IP_VS_WLC=m | ||
731 | CONFIG_IP_VS_LBLC=m | ||
732 | CONFIG_IP_VS_LBLCR=m | ||
733 | CONFIG_IP_VS_DH=m | ||
734 | CONFIG_IP_VS_SH=m | ||
735 | CONFIG_IP_VS_SED=m | ||
736 | CONFIG_IP_VS_NQ=m | ||
737 | |||
738 | # | ||
739 | # IPVS application helper | ||
740 | # | ||
741 | CONFIG_IP_VS_FTP=m | ||
742 | CONFIG_IP_VS_NFCT=y | ||
743 | CONFIG_IP_VS_PE_SIP=m | ||
744 | |||
745 | # | ||
746 | # IP: Netfilter Configuration | ||
747 | # | ||
748 | CONFIG_NF_DEFRAG_IPV4=m | ||
749 | CONFIG_NF_CONNTRACK_IPV4=m | ||
750 | CONFIG_NF_CONNTRACK_PROC_COMPAT=y | ||
751 | CONFIG_IP_NF_QUEUE=m | ||
752 | CONFIG_IP_NF_IPTABLES=m | ||
753 | CONFIG_IP_NF_MATCH_AH=m | ||
754 | CONFIG_IP_NF_MATCH_ECN=m | ||
755 | CONFIG_IP_NF_MATCH_TTL=m | ||
756 | CONFIG_IP_NF_FILTER=m | ||
757 | CONFIG_IP_NF_TARGET_REJECT=m | ||
758 | CONFIG_IP_NF_TARGET_LOG=m | ||
759 | CONFIG_IP_NF_TARGET_ULOG=m | ||
760 | CONFIG_NF_NAT=m | ||
761 | CONFIG_NF_NAT_NEEDED=y | ||
762 | CONFIG_IP_NF_TARGET_MASQUERADE=m | ||
763 | CONFIG_IP_NF_TARGET_NETMAP=m | ||
764 | CONFIG_IP_NF_TARGET_REDIRECT=m | ||
765 | CONFIG_NF_NAT_SNMP_BASIC=m | ||
766 | CONFIG_NF_NAT_PROTO_DCCP=m | ||
767 | CONFIG_NF_NAT_PROTO_GRE=m | ||
768 | CONFIG_NF_NAT_PROTO_UDPLITE=m | ||
769 | CONFIG_NF_NAT_PROTO_SCTP=m | ||
770 | CONFIG_NF_NAT_FTP=m | ||
771 | CONFIG_NF_NAT_IRC=m | ||
772 | CONFIG_NF_NAT_TFTP=m | ||
773 | CONFIG_NF_NAT_AMANDA=m | ||
774 | CONFIG_NF_NAT_PPTP=m | ||
775 | CONFIG_NF_NAT_H323=m | ||
776 | CONFIG_NF_NAT_SIP=m | ||
777 | CONFIG_IP_NF_MANGLE=m | ||
778 | CONFIG_IP_NF_TARGET_CLUSTERIP=m | ||
779 | CONFIG_IP_NF_TARGET_ECN=m | ||
780 | CONFIG_IP_NF_TARGET_TTL=m | ||
781 | CONFIG_IP_NF_RAW=m | ||
782 | CONFIG_IP_NF_ARPTABLES=m | ||
783 | CONFIG_IP_NF_ARPFILTER=m | ||
784 | CONFIG_IP_NF_ARP_MANGLE=m | ||
785 | |||
786 | # | ||
787 | # IPv6: Netfilter Configuration | ||
788 | # | ||
789 | CONFIG_NF_DEFRAG_IPV6=m | ||
790 | CONFIG_NF_CONNTRACK_IPV6=m | ||
791 | CONFIG_IP6_NF_QUEUE=m | ||
792 | CONFIG_IP6_NF_IPTABLES=m | ||
793 | CONFIG_IP6_NF_MATCH_AH=m | ||
794 | CONFIG_IP6_NF_MATCH_EUI64=m | ||
795 | CONFIG_IP6_NF_MATCH_FRAG=m | ||
796 | CONFIG_IP6_NF_MATCH_OPTS=m | ||
797 | CONFIG_IP6_NF_MATCH_HL=m | ||
798 | CONFIG_IP6_NF_MATCH_IPV6HEADER=m | ||
799 | CONFIG_IP6_NF_MATCH_MH=m | ||
800 | CONFIG_IP6_NF_MATCH_RT=m | ||
801 | CONFIG_IP6_NF_TARGET_HL=m | ||
802 | CONFIG_IP6_NF_TARGET_LOG=m | ||
803 | CONFIG_IP6_NF_FILTER=m | ||
804 | CONFIG_IP6_NF_TARGET_REJECT=m | ||
805 | CONFIG_IP6_NF_MANGLE=m | ||
806 | CONFIG_IP6_NF_RAW=m | ||
807 | # CONFIG_BRIDGE_NF_EBTABLES is not set | ||
808 | CONFIG_IP_DCCP=m | ||
809 | CONFIG_INET_DCCP_DIAG=m | ||
810 | |||
811 | # | ||
812 | # DCCP CCIDs Configuration (EXPERIMENTAL) | ||
813 | # | ||
814 | # CONFIG_IP_DCCP_CCID2_DEBUG is not set | ||
815 | CONFIG_IP_DCCP_CCID3=y | ||
816 | # CONFIG_IP_DCCP_CCID3_DEBUG is not set | ||
817 | CONFIG_IP_DCCP_TFRC_LIB=y | ||
818 | |||
819 | # | ||
820 | # DCCP Kernel Hacking | ||
821 | # | ||
822 | # CONFIG_IP_DCCP_DEBUG is not set | ||
823 | CONFIG_IP_SCTP=m | ||
824 | # CONFIG_SCTP_DBG_MSG is not set | ||
825 | # CONFIG_SCTP_DBG_OBJCNT is not set | ||
826 | # CONFIG_SCTP_HMAC_NONE is not set | ||
827 | # CONFIG_SCTP_HMAC_SHA1 is not set | ||
828 | CONFIG_SCTP_HMAC_MD5=y | ||
829 | # CONFIG_RDS is not set | ||
830 | CONFIG_TIPC=m | ||
831 | # CONFIG_TIPC_ADVANCED is not set | ||
832 | # CONFIG_TIPC_DEBUG is not set | ||
833 | CONFIG_ATM=m | ||
834 | CONFIG_ATM_CLIP=m | ||
835 | # CONFIG_ATM_CLIP_NO_ICMP is not set | ||
836 | CONFIG_ATM_LANE=m | ||
837 | CONFIG_ATM_MPOA=m | ||
838 | CONFIG_ATM_BR2684=m | ||
839 | # CONFIG_ATM_BR2684_IPFILTER is not set | ||
840 | CONFIG_L2TP=m | ||
841 | CONFIG_L2TP_DEBUGFS=m | ||
842 | CONFIG_L2TP_V3=y | ||
843 | CONFIG_L2TP_IP=m | ||
844 | CONFIG_L2TP_ETH=m | ||
845 | CONFIG_STP=m | ||
846 | CONFIG_GARP=m | ||
847 | CONFIG_BRIDGE=m | ||
848 | CONFIG_BRIDGE_IGMP_SNOOPING=y | ||
849 | # CONFIG_NET_DSA is not set | ||
850 | CONFIG_VLAN_8021Q=m | ||
851 | CONFIG_VLAN_8021Q_GVRP=y | ||
852 | # CONFIG_DECNET is not set | ||
853 | CONFIG_LLC=m | ||
854 | # CONFIG_LLC2 is not set | ||
855 | # CONFIG_IPX is not set | ||
856 | # CONFIG_ATALK is not set | ||
857 | # CONFIG_X25 is not set | ||
858 | # CONFIG_LAPB is not set | ||
859 | # CONFIG_ECONET is not set | ||
860 | CONFIG_WAN_ROUTER=m | ||
861 | # CONFIG_PHONET is not set | ||
862 | # CONFIG_IEEE802154 is not set | ||
863 | CONFIG_NET_SCHED=y | ||
864 | |||
865 | # | ||
866 | # Queueing/Scheduling | ||
867 | # | ||
868 | CONFIG_NET_SCH_CBQ=m | ||
869 | CONFIG_NET_SCH_HTB=m | ||
870 | CONFIG_NET_SCH_HFSC=m | ||
871 | CONFIG_NET_SCH_ATM=m | ||
872 | CONFIG_NET_SCH_PRIO=m | ||
873 | CONFIG_NET_SCH_MULTIQ=m | ||
874 | CONFIG_NET_SCH_RED=m | ||
875 | # CONFIG_NET_SCH_SFB is not set | ||
876 | CONFIG_NET_SCH_SFQ=m | ||
877 | CONFIG_NET_SCH_TEQL=m | ||
878 | CONFIG_NET_SCH_TBF=m | ||
879 | CONFIG_NET_SCH_GRED=m | ||
880 | CONFIG_NET_SCH_DSMARK=m | ||
881 | CONFIG_NET_SCH_NETEM=m | ||
882 | CONFIG_NET_SCH_DRR=m | ||
883 | CONFIG_NET_SCH_MQPRIO=m | ||
884 | CONFIG_NET_SCH_CHOKE=m | ||
885 | |||
886 | # | ||
887 | # Classification | ||
888 | # | ||
889 | CONFIG_NET_CLS=y | ||
890 | CONFIG_NET_CLS_BASIC=m | ||
891 | CONFIG_NET_CLS_TCINDEX=m | ||
892 | CONFIG_NET_CLS_ROUTE4=m | ||
893 | CONFIG_NET_CLS_FW=m | ||
894 | CONFIG_NET_CLS_U32=m | ||
895 | CONFIG_CLS_U32_PERF=y | ||
896 | CONFIG_CLS_U32_MARK=y | ||
897 | CONFIG_NET_CLS_RSVP=m | ||
898 | CONFIG_NET_CLS_RSVP6=m | ||
899 | CONFIG_NET_CLS_FLOW=m | ||
900 | CONFIG_NET_CLS_CGROUP=m | ||
901 | # CONFIG_NET_EMATCH is not set | ||
902 | # CONFIG_NET_CLS_ACT is not set | ||
903 | CONFIG_NET_CLS_IND=y | ||
904 | CONFIG_NET_SCH_FIFO=y | ||
905 | # CONFIG_DCB is not set | ||
906 | CONFIG_DNS_RESOLVER=y | ||
907 | # CONFIG_BATMAN_ADV is not set | ||
908 | |||
909 | # | ||
910 | # Network testing | ||
911 | # | ||
912 | # CONFIG_NET_PKTGEN is not set | ||
913 | # CONFIG_HAMRADIO is not set | ||
914 | CONFIG_CAN=m | ||
915 | CONFIG_CAN_RAW=m | ||
916 | CONFIG_CAN_BCM=m | ||
917 | |||
918 | # | ||
919 | # CAN Device Drivers | ||
920 | # | ||
921 | CONFIG_CAN_VCAN=m | ||
922 | CONFIG_CAN_SLCAN=m | ||
923 | # CONFIG_CAN_DEV is not set | ||
924 | # CONFIG_CAN_DEBUG_DEVICES is not set | ||
925 | CONFIG_IRDA=m | ||
926 | |||
927 | # | ||
928 | # IrDA protocols | ||
929 | # | ||
930 | CONFIG_IRLAN=m | ||
931 | CONFIG_IRNET=m | ||
932 | CONFIG_IRCOMM=m | ||
933 | CONFIG_IRDA_ULTRA=y | ||
934 | |||
935 | # | ||
936 | # IrDA options | ||
937 | # | ||
938 | CONFIG_IRDA_CACHE_LAST_LSAP=y | ||
939 | CONFIG_IRDA_FAST_RR=y | ||
940 | CONFIG_IRDA_DEBUG=y | ||
941 | |||
942 | # | ||
943 | # Infrared-port device drivers | ||
944 | # | ||
945 | |||
946 | # | ||
947 | # SIR device drivers | ||
948 | # | ||
949 | CONFIG_IRTTY_SIR=m | ||
950 | |||
951 | # | ||
952 | # Dongle support | ||
953 | # | ||
954 | CONFIG_DONGLE=y | ||
955 | CONFIG_ESI_DONGLE=m | ||
956 | CONFIG_ACTISYS_DONGLE=m | ||
957 | CONFIG_TEKRAM_DONGLE=m | ||
958 | CONFIG_TOIM3232_DONGLE=m | ||
959 | CONFIG_LITELINK_DONGLE=m | ||
960 | CONFIG_MA600_DONGLE=m | ||
961 | CONFIG_GIRBIL_DONGLE=m | ||
962 | CONFIG_MCP2120_DONGLE=m | ||
963 | CONFIG_OLD_BELKIN_DONGLE=m | ||
964 | # CONFIG_ACT200L_DONGLE is not set | ||
965 | CONFIG_KINGSUN_DONGLE=m | ||
966 | CONFIG_KSDAZZLE_DONGLE=m | ||
967 | CONFIG_KS959_DONGLE=m | ||
968 | |||
969 | # | ||
970 | # FIR device drivers | ||
971 | # | ||
972 | CONFIG_USB_IRDA=m | ||
973 | CONFIG_SIGMATEL_FIR=m | ||
974 | CONFIG_MCS_FIR=m | ||
975 | CONFIG_BT=m | ||
976 | CONFIG_BT_L2CAP=y | ||
977 | CONFIG_BT_SCO=y | ||
978 | CONFIG_BT_RFCOMM=m | ||
979 | CONFIG_BT_RFCOMM_TTY=y | ||
980 | CONFIG_BT_BNEP=m | ||
981 | CONFIG_BT_BNEP_MC_FILTER=y | ||
982 | CONFIG_BT_BNEP_PROTO_FILTER=y | ||
983 | CONFIG_BT_HIDP=m | ||
984 | |||
985 | # | ||
986 | # Bluetooth device drivers | ||
987 | # | ||
988 | CONFIG_BT_HCIBTUSB=m | ||
989 | CONFIG_BT_HCIBTSDIO=m | ||
990 | CONFIG_BT_HCIUART=m | ||
991 | CONFIG_BT_HCIUART_H4=y | ||
992 | CONFIG_BT_HCIUART_BCSP=y | ||
993 | CONFIG_BT_HCIUART_ATH3K=y | ||
994 | CONFIG_BT_HCIUART_LL=y | ||
995 | CONFIG_BT_HCIBCM203X=m | ||
996 | CONFIG_BT_HCIBPA10X=m | ||
997 | CONFIG_BT_HCIBFUSB=m | ||
998 | # CONFIG_BT_HCIVHCI is not set | ||
999 | # CONFIG_BT_MRVL is not set | ||
1000 | CONFIG_BT_ATH3K=m | ||
1001 | CONFIG_BT_WILINK=m | ||
1002 | CONFIG_AF_RXRPC=m | ||
1003 | # CONFIG_AF_RXRPC_DEBUG is not set | ||
1004 | # CONFIG_RXKAD is not set | ||
1005 | CONFIG_FIB_RULES=y | ||
1006 | CONFIG_WIRELESS=y | ||
1007 | CONFIG_WIRELESS_EXT=y | ||
1008 | CONFIG_WEXT_CORE=y | ||
1009 | CONFIG_WEXT_PROC=y | ||
1010 | CONFIG_WEXT_SPY=y | ||
1011 | CONFIG_WEXT_PRIV=y | ||
1012 | CONFIG_CFG80211=m | ||
1013 | CONFIG_NL80211_TESTMODE=y | ||
1014 | # CONFIG_CFG80211_DEVELOPER_WARNINGS is not set | ||
1015 | # CONFIG_CFG80211_REG_DEBUG is not set | ||
1016 | CONFIG_CFG80211_DEFAULT_PS=y | ||
1017 | # CONFIG_CFG80211_DEBUGFS is not set | ||
1018 | # CONFIG_CFG80211_INTERNAL_REGDB is not set | ||
1019 | CONFIG_CFG80211_WEXT=y | ||
1020 | CONFIG_WIRELESS_EXT_SYSFS=y | ||
1021 | CONFIG_LIB80211=y | ||
1022 | CONFIG_LIB80211_CRYPT_WEP=m | ||
1023 | CONFIG_LIB80211_CRYPT_CCMP=m | ||
1024 | CONFIG_LIB80211_CRYPT_TKIP=m | ||
1025 | # CONFIG_LIB80211_DEBUG is not set | ||
1026 | CONFIG_MAC80211=m | ||
1027 | CONFIG_MAC80211_HAS_RC=y | ||
1028 | CONFIG_MAC80211_RC_PID=y | ||
1029 | # CONFIG_MAC80211_RC_MINSTREL is not set | ||
1030 | CONFIG_MAC80211_RC_DEFAULT_PID=y | ||
1031 | CONFIG_MAC80211_RC_DEFAULT="pid" | ||
1032 | # CONFIG_MAC80211_MESH is not set | ||
1033 | CONFIG_MAC80211_LEDS=y | ||
1034 | # CONFIG_MAC80211_DEBUGFS is not set | ||
1035 | # CONFIG_MAC80211_DEBUG_MENU is not set | ||
1036 | CONFIG_WIMAX=m | ||
1037 | CONFIG_WIMAX_DEBUG_LEVEL=8 | ||
1038 | CONFIG_RFKILL=m | ||
1039 | CONFIG_RFKILL_LEDS=y | ||
1040 | CONFIG_RFKILL_INPUT=y | ||
1041 | CONFIG_NET_9P=m | ||
1042 | # CONFIG_NET_9P_DEBUG is not set | ||
1043 | # CONFIG_CAIF is not set | ||
1044 | CONFIG_CEPH_LIB=m | ||
1045 | # CONFIG_CEPH_LIB_PRETTYDEBUG is not set | ||
1046 | |||
1047 | # | ||
1048 | # Device Drivers | ||
1049 | # | ||
1050 | |||
1051 | # | ||
1052 | # Generic Driver Options | ||
1053 | # | ||
1054 | CONFIG_UEVENT_HELPER_PATH="" | ||
1055 | CONFIG_DEVTMPFS=y | ||
1056 | CONFIG_DEVTMPFS_MOUNT=y | ||
1057 | CONFIG_STANDALONE=y | ||
1058 | CONFIG_PREVENT_FIRMWARE_BUILD=y | ||
1059 | CONFIG_FW_LOADER=y | ||
1060 | CONFIG_FIRMWARE_IN_KERNEL=y | ||
1061 | CONFIG_EXTRA_FIRMWARE="" | ||
1062 | # CONFIG_DEBUG_DRIVER is not set | ||
1063 | # CONFIG_DEBUG_DEVRES is not set | ||
1064 | # CONFIG_SYS_HYPERVISOR is not set | ||
1065 | # CONFIG_CONNECTOR is not set | ||
1066 | CONFIG_MTD=y | ||
1067 | # CONFIG_MTD_DEBUG is not set | ||
1068 | # CONFIG_MTD_TESTS is not set | ||
1069 | CONFIG_MTD_PARTITIONS=y | ||
1070 | # CONFIG_MTD_REDBOOT_PARTS is not set | ||
1071 | # CONFIG_MTD_CMDLINE_PARTS is not set | ||
1072 | # CONFIG_MTD_AFS_PARTS is not set | ||
1073 | # CONFIG_MTD_AR7_PARTS is not set | ||
1074 | |||
1075 | # | ||
1076 | # User Modules And Translation Layers | ||
1077 | # | ||
1078 | CONFIG_MTD_CHAR=y | ||
1079 | CONFIG_MTD_BLKDEVS=y | ||
1080 | CONFIG_MTD_BLOCK=y | ||
1081 | # CONFIG_FTL is not set | ||
1082 | # CONFIG_NFTL is not set | ||
1083 | # CONFIG_INFTL is not set | ||
1084 | # CONFIG_RFD_FTL is not set | ||
1085 | # CONFIG_SSFDC is not set | ||
1086 | CONFIG_SM_FTL=m | ||
1087 | # CONFIG_MTD_OOPS is not set | ||
1088 | CONFIG_MTD_SWAP=m | ||
1089 | |||
1090 | # | ||
1091 | # RAM/ROM/Flash chip drivers | ||
1092 | # | ||
1093 | # CONFIG_MTD_CFI is not set | ||
1094 | # CONFIG_MTD_JEDECPROBE is not set | ||
1095 | CONFIG_MTD_MAP_BANK_WIDTH_1=y | ||
1096 | CONFIG_MTD_MAP_BANK_WIDTH_2=y | ||
1097 | CONFIG_MTD_MAP_BANK_WIDTH_4=y | ||
1098 | # CONFIG_MTD_MAP_BANK_WIDTH_8 is not set | ||
1099 | # CONFIG_MTD_MAP_BANK_WIDTH_16 is not set | ||
1100 | # CONFIG_MTD_MAP_BANK_WIDTH_32 is not set | ||
1101 | CONFIG_MTD_CFI_I1=y | ||
1102 | CONFIG_MTD_CFI_I2=y | ||
1103 | # CONFIG_MTD_CFI_I4 is not set | ||
1104 | # CONFIG_MTD_CFI_I8 is not set | ||
1105 | # CONFIG_MTD_RAM is not set | ||
1106 | # CONFIG_MTD_ROM is not set | ||
1107 | # CONFIG_MTD_ABSENT is not set | ||
1108 | |||
1109 | # | ||
1110 | # Mapping drivers for chip access | ||
1111 | # | ||
1112 | # CONFIG_MTD_COMPLEX_MAPPINGS is not set | ||
1113 | # CONFIG_MTD_PLATRAM is not set | ||
1114 | |||
1115 | # | ||
1116 | # Self-contained MTD device drivers | ||
1117 | # | ||
1118 | # CONFIG_MTD_DATAFLASH is not set | ||
1119 | # CONFIG_MTD_M25P80 is not set | ||
1120 | # CONFIG_MTD_SST25L is not set | ||
1121 | # CONFIG_MTD_SLRAM is not set | ||
1122 | # CONFIG_MTD_PHRAM is not set | ||
1123 | # CONFIG_MTD_MTDRAM is not set | ||
1124 | # CONFIG_MTD_BLOCK2MTD is not set | ||
1125 | |||
1126 | # | ||
1127 | # Disk-On-Chip Device Drivers | ||
1128 | # | ||
1129 | # CONFIG_MTD_DOC2000 is not set | ||
1130 | # CONFIG_MTD_DOC2001 is not set | ||
1131 | # CONFIG_MTD_DOC2001PLUS is not set | ||
1132 | CONFIG_MTD_NAND_ECC=y | ||
1133 | # CONFIG_MTD_NAND_ECC_SMC is not set | ||
1134 | CONFIG_MTD_NAND=y | ||
1135 | # CONFIG_MTD_NAND_VERIFY_WRITE is not set | ||
1136 | # CONFIG_MTD_NAND_ECC_BCH is not set | ||
1137 | # CONFIG_MTD_SM_COMMON is not set | ||
1138 | # CONFIG_MTD_NAND_MUSEUM_IDS is not set | ||
1139 | # CONFIG_MTD_NAND_GPIO is not set | ||
1140 | CONFIG_MTD_NAND_OMAP2=y | ||
1141 | CONFIG_MTD_NAND_IDS=y | ||
1142 | # CONFIG_MTD_NAND_DISKONCHIP is not set | ||
1143 | # CONFIG_MTD_NAND_NANDSIM is not set | ||
1144 | CONFIG_MTD_NAND_PLATFORM=y | ||
1145 | # CONFIG_MTD_ALAUDA is not set | ||
1146 | # CONFIG_MTD_ONENAND is not set | ||
1147 | |||
1148 | # | ||
1149 | # LPDDR flash memory drivers | ||
1150 | # | ||
1151 | # CONFIG_MTD_LPDDR is not set | ||
1152 | CONFIG_MTD_UBI=y | ||
1153 | CONFIG_MTD_UBI_WL_THRESHOLD=4096 | ||
1154 | CONFIG_MTD_UBI_BEB_RESERVE=1 | ||
1155 | # CONFIG_MTD_UBI_GLUEBI is not set | ||
1156 | # CONFIG_MTD_UBI_DEBUG is not set | ||
1157 | # CONFIG_PARPORT is not set | ||
1158 | CONFIG_BLK_DEV=y | ||
1159 | # CONFIG_BLK_DEV_COW_COMMON is not set | ||
1160 | CONFIG_BLK_DEV_LOOP=y | ||
1161 | CONFIG_BLK_DEV_CRYPTOLOOP=m | ||
1162 | |||
1163 | # | ||
1164 | # DRBD disabled because PROC_FS, INET or CONNECTOR not selected | ||
1165 | # | ||
1166 | # CONFIG_BLK_DEV_NBD is not set | ||
1167 | # CONFIG_BLK_DEV_UB is not set | ||
1168 | CONFIG_BLK_DEV_RAM=y | ||
1169 | CONFIG_BLK_DEV_RAM_COUNT=16 | ||
1170 | CONFIG_BLK_DEV_RAM_SIZE=16384 | ||
1171 | # CONFIG_BLK_DEV_XIP is not set | ||
1172 | CONFIG_CDROM_PKTCDVD=m | ||
1173 | CONFIG_CDROM_PKTCDVD_BUFFERS=8 | ||
1174 | # CONFIG_CDROM_PKTCDVD_WCACHE is not set | ||
1175 | # CONFIG_ATA_OVER_ETH is not set | ||
1176 | # CONFIG_MG_DISK is not set | ||
1177 | # CONFIG_BLK_DEV_RBD is not set | ||
1178 | # CONFIG_SENSORS_LIS3LV02D is not set | ||
1179 | CONFIG_MISC_DEVICES=y | ||
1180 | # CONFIG_AD525X_DPOT is not set | ||
1181 | # CONFIG_ICS932S401 is not set | ||
1182 | # CONFIG_ENCLOSURE_SERVICES is not set | ||
1183 | # CONFIG_APDS9802ALS is not set | ||
1184 | # CONFIG_ISL29003 is not set | ||
1185 | # CONFIG_ISL29020 is not set | ||
1186 | # CONFIG_SENSORS_TSL2550 is not set | ||
1187 | CONFIG_SENSORS_BH1780=m | ||
1188 | # CONFIG_SENSORS_BH1770 is not set | ||
1189 | # CONFIG_SENSORS_APDS990X is not set | ||
1190 | CONFIG_HMC6352=m | ||
1191 | # CONFIG_DS1682 is not set | ||
1192 | # CONFIG_TI_DAC7512 is not set | ||
1193 | CONFIG_BMP085=m | ||
1194 | # CONFIG_C2PORT is not set | ||
1195 | |||
1196 | # | ||
1197 | # EEPROM support | ||
1198 | # | ||
1199 | CONFIG_EEPROM_AT24=m | ||
1200 | # CONFIG_EEPROM_AT25 is not set | ||
1201 | # CONFIG_EEPROM_LEGACY is not set | ||
1202 | # CONFIG_EEPROM_MAX6875 is not set | ||
1203 | CONFIG_EEPROM_93CX6=y | ||
1204 | CONFIG_IWMC3200TOP=m | ||
1205 | # CONFIG_IWMC3200TOP_DEBUG is not set | ||
1206 | # CONFIG_IWMC3200TOP_DEBUGFS is not set | ||
1207 | |||
1208 | # | ||
1209 | # Texas Instruments shared transport line discipline | ||
1210 | # | ||
1211 | CONFIG_TI_ST=m | ||
1212 | # CONFIG_SENSORS_LIS3_SPI is not set | ||
1213 | # CONFIG_SENSORS_LIS3_I2C is not set | ||
1214 | CONFIG_HAVE_IDE=y | ||
1215 | # CONFIG_IDE is not set | ||
1216 | |||
1217 | # | ||
1218 | # SCSI device support | ||
1219 | # | ||
1220 | CONFIG_SCSI_MOD=y | ||
1221 | CONFIG_RAID_ATTRS=m | ||
1222 | CONFIG_SCSI=y | ||
1223 | CONFIG_SCSI_DMA=y | ||
1224 | # CONFIG_SCSI_TGT is not set | ||
1225 | # CONFIG_SCSI_NETLINK is not set | ||
1226 | CONFIG_SCSI_PROC_FS=y | ||
1227 | |||
1228 | # | ||
1229 | # SCSI support type (disk, tape, CD-ROM) | ||
1230 | # | ||
1231 | CONFIG_BLK_DEV_SD=y | ||
1232 | # CONFIG_CHR_DEV_ST is not set | ||
1233 | # CONFIG_CHR_DEV_OSST is not set | ||
1234 | CONFIG_BLK_DEV_SR=y | ||
1235 | CONFIG_BLK_DEV_SR_VENDOR=y | ||
1236 | CONFIG_CHR_DEV_SG=y | ||
1237 | CONFIG_CHR_DEV_SCH=m | ||
1238 | CONFIG_SCSI_MULTI_LUN=y | ||
1239 | # CONFIG_SCSI_CONSTANTS is not set | ||
1240 | # CONFIG_SCSI_LOGGING is not set | ||
1241 | # CONFIG_SCSI_SCAN_ASYNC is not set | ||
1242 | CONFIG_SCSI_WAIT_SCAN=m | ||
1243 | |||
1244 | # | ||
1245 | # SCSI Transports | ||
1246 | # | ||
1247 | # CONFIG_SCSI_SPI_ATTRS is not set | ||
1248 | # CONFIG_SCSI_FC_ATTRS is not set | ||
1249 | CONFIG_SCSI_ISCSI_ATTRS=m | ||
1250 | # CONFIG_SCSI_SAS_ATTRS is not set | ||
1251 | # CONFIG_SCSI_SAS_LIBSAS is not set | ||
1252 | # CONFIG_SCSI_SRP_ATTRS is not set | ||
1253 | CONFIG_SCSI_LOWLEVEL=y | ||
1254 | CONFIG_ISCSI_TCP=m | ||
1255 | CONFIG_ISCSI_BOOT_SYSFS=m | ||
1256 | # CONFIG_LIBFC is not set | ||
1257 | # CONFIG_LIBFCOE is not set | ||
1258 | # CONFIG_SCSI_DEBUG is not set | ||
1259 | # CONFIG_SCSI_DH is not set | ||
1260 | # CONFIG_SCSI_OSD_INITIATOR is not set | ||
1261 | # CONFIG_ATA is not set | ||
1262 | CONFIG_MD=y | ||
1263 | CONFIG_BLK_DEV_MD=m | ||
1264 | CONFIG_MD_LINEAR=m | ||
1265 | CONFIG_MD_RAID0=m | ||
1266 | CONFIG_MD_RAID1=m | ||
1267 | CONFIG_MD_RAID10=m | ||
1268 | CONFIG_MD_RAID456=m | ||
1269 | CONFIG_MD_MULTIPATH=m | ||
1270 | CONFIG_MD_FAULTY=m | ||
1271 | CONFIG_BLK_DEV_DM=m | ||
1272 | # CONFIG_DM_DEBUG is not set | ||
1273 | CONFIG_DM_CRYPT=m | ||
1274 | CONFIG_DM_SNAPSHOT=m | ||
1275 | CONFIG_DM_MIRROR=m | ||
1276 | CONFIG_DM_RAID=m | ||
1277 | # CONFIG_DM_LOG_USERSPACE is not set | ||
1278 | CONFIG_DM_ZERO=m | ||
1279 | CONFIG_DM_MULTIPATH=m | ||
1280 | # CONFIG_DM_MULTIPATH_QL is not set | ||
1281 | # CONFIG_DM_MULTIPATH_ST is not set | ||
1282 | CONFIG_DM_DELAY=m | ||
1283 | # CONFIG_DM_UEVENT is not set | ||
1284 | CONFIG_DM_FLAKEY=m | ||
1285 | CONFIG_TARGET_CORE=m | ||
1286 | CONFIG_TCM_IBLOCK=m | ||
1287 | CONFIG_TCM_FILEIO=m | ||
1288 | CONFIG_TCM_PSCSI=m | ||
1289 | CONFIG_LOOPBACK_TARGET=m | ||
1290 | # CONFIG_LOOPBACK_TARGET_CDB_DEBUG is not set | ||
1291 | CONFIG_NETDEVICES=y | ||
1292 | CONFIG_DUMMY=m | ||
1293 | CONFIG_BONDING=m | ||
1294 | CONFIG_MACVLAN=m | ||
1295 | CONFIG_MACVTAP=m | ||
1296 | CONFIG_EQUALIZER=m | ||
1297 | CONFIG_TUN=m | ||
1298 | CONFIG_VETH=m | ||
1299 | CONFIG_MII=y | ||
1300 | CONFIG_PHYLIB=y | ||
1301 | |||
1302 | # | ||
1303 | # MII PHY device drivers | ||
1304 | # | ||
1305 | # CONFIG_MARVELL_PHY is not set | ||
1306 | # CONFIG_DAVICOM_PHY is not set | ||
1307 | # CONFIG_QSEMI_PHY is not set | ||
1308 | # CONFIG_LXT_PHY is not set | ||
1309 | # CONFIG_CICADA_PHY is not set | ||
1310 | # CONFIG_VITESSE_PHY is not set | ||
1311 | # CONFIG_SMSC_PHY is not set | ||
1312 | # CONFIG_BROADCOM_PHY is not set | ||
1313 | CONFIG_BCM63XX_PHY=m | ||
1314 | # CONFIG_ICPLUS_PHY is not set | ||
1315 | # CONFIG_REALTEK_PHY is not set | ||
1316 | # CONFIG_NATIONAL_PHY is not set | ||
1317 | # CONFIG_STE10XP is not set | ||
1318 | # CONFIG_LSI_ET1011C_PHY is not set | ||
1319 | CONFIG_MICREL_PHY=m | ||
1320 | # CONFIG_FIXED_PHY is not set | ||
1321 | # CONFIG_MDIO_BITBANG is not set | ||
1322 | CONFIG_NET_ETHERNET=y | ||
1323 | # CONFIG_AX88796 is not set | ||
1324 | CONFIG_SMC91X=y | ||
1325 | # CONFIG_TI_DAVINCI_EMAC is not set | ||
1326 | CONFIG_TI_DAVINCI_MDIO=m | ||
1327 | CONFIG_TI_DAVINCI_CPDMA=m | ||
1328 | # CONFIG_DM9000 is not set | ||
1329 | CONFIG_ENC28J60=y | ||
1330 | # CONFIG_ENC28J60_WRITEVERIFY is not set | ||
1331 | # CONFIG_ETHOC is not set | ||
1332 | CONFIG_SMC911X=y | ||
1333 | CONFIG_SMSC911X=y | ||
1334 | # CONFIG_SMSC911X_ARCH_HOOKS is not set | ||
1335 | # CONFIG_DNET is not set | ||
1336 | # CONFIG_IBM_NEW_EMAC_ZMII is not set | ||
1337 | # CONFIG_IBM_NEW_EMAC_RGMII is not set | ||
1338 | # CONFIG_IBM_NEW_EMAC_TAH is not set | ||
1339 | # CONFIG_IBM_NEW_EMAC_EMAC4 is not set | ||
1340 | # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set | ||
1341 | # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set | ||
1342 | # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set | ||
1343 | # CONFIG_B44 is not set | ||
1344 | CONFIG_KS8842=m | ||
1345 | CONFIG_KS8851=y | ||
1346 | # CONFIG_KS8851_MLL is not set | ||
1347 | # CONFIG_FTMAC100 is not set | ||
1348 | # CONFIG_NETDEV_1000 is not set | ||
1349 | # CONFIG_NETDEV_10000 is not set | ||
1350 | CONFIG_WLAN=y | ||
1351 | # CONFIG_LIBERTAS_THINFIRM is not set | ||
1352 | CONFIG_AT76C50X_USB=m | ||
1353 | CONFIG_USB_ZD1201=m | ||
1354 | CONFIG_USB_NET_RNDIS_WLAN=m | ||
1355 | CONFIG_RTL8187=m | ||
1356 | CONFIG_RTL8187_LEDS=y | ||
1357 | # CONFIG_MAC80211_HWSIM is not set | ||
1358 | # CONFIG_ATH_COMMON is not set | ||
1359 | CONFIG_B43=m | ||
1360 | # CONFIG_B43_SDIO is not set | ||
1361 | CONFIG_B43_PIO=y | ||
1362 | CONFIG_B43_PHY_N=y | ||
1363 | CONFIG_B43_PHY_LP=y | ||
1364 | CONFIG_B43_LEDS=y | ||
1365 | CONFIG_B43_HWRNG=y | ||
1366 | # CONFIG_B43_DEBUG is not set | ||
1367 | # CONFIG_B43LEGACY is not set | ||
1368 | CONFIG_HOSTAP=m | ||
1369 | CONFIG_HOSTAP_FIRMWARE=y | ||
1370 | CONFIG_HOSTAP_FIRMWARE_NVRAM=y | ||
1371 | # CONFIG_IWM is not set | ||
1372 | CONFIG_LIBERTAS=m | ||
1373 | CONFIG_LIBERTAS_USB=m | ||
1374 | # CONFIG_LIBERTAS_SDIO is not set | ||
1375 | # CONFIG_LIBERTAS_SPI is not set | ||
1376 | # CONFIG_LIBERTAS_DEBUG is not set | ||
1377 | # CONFIG_LIBERTAS_MESH is not set | ||
1378 | CONFIG_P54_COMMON=m | ||
1379 | CONFIG_P54_USB=m | ||
1380 | # CONFIG_P54_SPI is not set | ||
1381 | CONFIG_P54_LEDS=y | ||
1382 | CONFIG_RT2X00=m | ||
1383 | CONFIG_RT2500USB=m | ||
1384 | CONFIG_RT73USB=m | ||
1385 | # CONFIG_RT2800USB is not set | ||
1386 | CONFIG_RT2X00_LIB_USB=m | ||
1387 | CONFIG_RT2X00_LIB=m | ||
1388 | CONFIG_RT2X00_LIB_FIRMWARE=y | ||
1389 | CONFIG_RT2X00_LIB_CRYPTO=y | ||
1390 | CONFIG_RT2X00_LIB_LEDS=y | ||
1391 | # CONFIG_RT2X00_DEBUG is not set | ||
1392 | CONFIG_RTL8192CU=m | ||
1393 | CONFIG_RTLWIFI=m | ||
1394 | CONFIG_RTL8192C_COMMON=m | ||
1395 | CONFIG_WL1251=m | ||
1396 | CONFIG_WL1251_SPI=m | ||
1397 | CONFIG_WL1251_SDIO=m | ||
1398 | CONFIG_WL12XX_MENU=m | ||
1399 | CONFIG_WL12XX=m | ||
1400 | CONFIG_WL12XX_HT=y | ||
1401 | CONFIG_WL12XX_SPI=m | ||
1402 | CONFIG_WL12XX_SDIO=m | ||
1403 | # CONFIG_WL12XX_SDIO_TEST is not set | ||
1404 | CONFIG_WL12XX_PLATFORM_DATA=y | ||
1405 | CONFIG_ZD1211RW=m | ||
1406 | # CONFIG_ZD1211RW_DEBUG is not set | ||
1407 | |||
1408 | # | ||
1409 | # WiMAX Wireless Broadband devices | ||
1410 | # | ||
1411 | CONFIG_WIMAX_I2400M=m | ||
1412 | CONFIG_WIMAX_I2400M_USB=m | ||
1413 | CONFIG_WIMAX_I2400M_SDIO=m | ||
1414 | CONFIG_WIMAX_IWMC3200_SDIO=y | ||
1415 | CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8 | ||
1416 | |||
1417 | # | ||
1418 | # USB Network Adapters | ||
1419 | # | ||
1420 | CONFIG_USB_CATC=y | ||
1421 | CONFIG_USB_KAWETH=y | ||
1422 | CONFIG_USB_PEGASUS=y | ||
1423 | CONFIG_USB_RTL8150=y | ||
1424 | CONFIG_USB_USBNET=y | ||
1425 | CONFIG_USB_NET_AX8817X=y | ||
1426 | CONFIG_USB_NET_CDCETHER=y | ||
1427 | # CONFIG_USB_NET_CDC_EEM is not set | ||
1428 | CONFIG_USB_NET_CDC_NCM=m | ||
1429 | CONFIG_USB_NET_DM9601=y | ||
1430 | CONFIG_USB_NET_SMSC75XX=m | ||
1431 | CONFIG_USB_NET_SMSC95XX=y | ||
1432 | CONFIG_USB_NET_GL620A=y | ||
1433 | CONFIG_USB_NET_NET1080=y | ||
1434 | CONFIG_USB_NET_PLUSB=y | ||
1435 | CONFIG_USB_NET_MCS7830=y | ||
1436 | CONFIG_USB_NET_RNDIS_HOST=y | ||
1437 | CONFIG_USB_NET_CDC_SUBSET=y | ||
1438 | CONFIG_USB_ALI_M5632=y | ||
1439 | CONFIG_USB_AN2720=y | ||
1440 | CONFIG_USB_BELKIN=y | ||
1441 | CONFIG_USB_ARMLINUX=y | ||
1442 | CONFIG_USB_EPSON2888=y | ||
1443 | CONFIG_USB_KC2190=y | ||
1444 | CONFIG_USB_NET_ZAURUS=y | ||
1445 | CONFIG_USB_NET_CX82310_ETH=m | ||
1446 | CONFIG_USB_HSO=m | ||
1447 | CONFIG_USB_NET_INT51X1=m | ||
1448 | CONFIG_USB_IPHETH=m | ||
1449 | CONFIG_USB_SIERRA_NET=m | ||
1450 | CONFIG_USB_VL600=m | ||
1451 | # CONFIG_WAN is not set | ||
1452 | CONFIG_ATM_DRIVERS=y | ||
1453 | # CONFIG_ATM_DUMMY is not set | ||
1454 | # CONFIG_ATM_TCP is not set | ||
1455 | |||
1456 | # | ||
1457 | # CAIF transport drivers | ||
1458 | # | ||
1459 | CONFIG_PPP=m | ||
1460 | CONFIG_PPP_MULTILINK=y | ||
1461 | CONFIG_PPP_FILTER=y | ||
1462 | CONFIG_PPP_ASYNC=m | ||
1463 | CONFIG_PPP_SYNC_TTY=m | ||
1464 | CONFIG_PPP_DEFLATE=m | ||
1465 | CONFIG_PPP_BSDCOMP=m | ||
1466 | CONFIG_PPP_MPPE=m | ||
1467 | CONFIG_PPPOE=m | ||
1468 | CONFIG_PPTP=m | ||
1469 | # CONFIG_PPPOATM is not set | ||
1470 | CONFIG_PPPOL2TP=m | ||
1471 | # CONFIG_SLIP is not set | ||
1472 | CONFIG_SLHC=m | ||
1473 | CONFIG_NETCONSOLE=m | ||
1474 | CONFIG_NETCONSOLE_DYNAMIC=y | ||
1475 | CONFIG_NETPOLL=y | ||
1476 | CONFIG_NETPOLL_TRAP=y | ||
1477 | CONFIG_NET_POLL_CONTROLLER=y | ||
1478 | # CONFIG_ISDN is not set | ||
1479 | # CONFIG_PHONE is not set | ||
1480 | |||
1481 | # | ||
1482 | # Input device support | ||
1483 | # | ||
1484 | CONFIG_INPUT=y | ||
1485 | CONFIG_INPUT_FF_MEMLESS=y | ||
1486 | CONFIG_INPUT_POLLDEV=y | ||
1487 | # CONFIG_INPUT_SPARSEKMAP is not set | ||
1488 | |||
1489 | # | ||
1490 | # Userland interfaces | ||
1491 | # | ||
1492 | CONFIG_INPUT_MOUSEDEV=y | ||
1493 | CONFIG_INPUT_MOUSEDEV_PSAUX=y | ||
1494 | CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 | ||
1495 | CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 | ||
1496 | # CONFIG_INPUT_JOYDEV is not set | ||
1497 | CONFIG_INPUT_EVDEV=y | ||
1498 | # CONFIG_INPUT_EVBUG is not set | ||
1499 | |||
1500 | # | ||
1501 | # Input Device Drivers | ||
1502 | # | ||
1503 | CONFIG_INPUT_KEYBOARD=y | ||
1504 | # CONFIG_KEYBOARD_ADP5588 is not set | ||
1505 | # CONFIG_KEYBOARD_ATKBD is not set | ||
1506 | CONFIG_KEYBOARD_QT1070=m | ||
1507 | CONFIG_KEYBOARD_QT2160=m | ||
1508 | # CONFIG_KEYBOARD_LKKBD is not set | ||
1509 | CONFIG_KEYBOARD_GPIO=y | ||
1510 | # CONFIG_KEYBOARD_TCA6416 is not set | ||
1511 | # CONFIG_KEYBOARD_MATRIX is not set | ||
1512 | # CONFIG_KEYBOARD_LM8323 is not set | ||
1513 | # CONFIG_KEYBOARD_MAX7359 is not set | ||
1514 | CONFIG_KEYBOARD_MCS=m | ||
1515 | # CONFIG_KEYBOARD_NEWTON is not set | ||
1516 | # CONFIG_KEYBOARD_OPENCORES is not set | ||
1517 | # CONFIG_KEYBOARD_STOWAWAY is not set | ||
1518 | # CONFIG_KEYBOARD_SUNKBD is not set | ||
1519 | # CONFIG_KEYBOARD_TWL4030 is not set | ||
1520 | # CONFIG_KEYBOARD_XTKBD is not set | ||
1521 | CONFIG_INPUT_MOUSE=y | ||
1522 | CONFIG_MOUSE_PS2=y | ||
1523 | CONFIG_MOUSE_PS2_ALPS=y | ||
1524 | CONFIG_MOUSE_PS2_LOGIPS2PP=y | ||
1525 | CONFIG_MOUSE_PS2_SYNAPTICS=y | ||
1526 | CONFIG_MOUSE_PS2_TRACKPOINT=y | ||
1527 | # CONFIG_MOUSE_PS2_ELANTECH is not set | ||
1528 | # CONFIG_MOUSE_PS2_SENTELIC is not set | ||
1529 | # CONFIG_MOUSE_PS2_TOUCHKIT is not set | ||
1530 | # CONFIG_MOUSE_SERIAL is not set | ||
1531 | # CONFIG_MOUSE_APPLETOUCH is not set | ||
1532 | # CONFIG_MOUSE_BCM5974 is not set | ||
1533 | # CONFIG_MOUSE_VSXXXAA is not set | ||
1534 | # CONFIG_MOUSE_GPIO is not set | ||
1535 | # CONFIG_MOUSE_SYNAPTICS_I2C is not set | ||
1536 | # CONFIG_INPUT_JOYSTICK is not set | ||
1537 | # CONFIG_INPUT_TABLET is not set | ||
1538 | # CONFIG_INPUT_TOUCHSCREEN is not set | ||
1539 | CONFIG_INPUT_MISC=y | ||
1540 | CONFIG_INPUT_AD714X=m | ||
1541 | CONFIG_INPUT_AD714X_I2C=m | ||
1542 | CONFIG_INPUT_AD714X_SPI=m | ||
1543 | # CONFIG_INPUT_ATI_REMOTE is not set | ||
1544 | # CONFIG_INPUT_ATI_REMOTE2 is not set | ||
1545 | # CONFIG_INPUT_KEYSPAN_REMOTE is not set | ||
1546 | # CONFIG_INPUT_POWERMATE is not set | ||
1547 | # CONFIG_INPUT_YEALINK is not set | ||
1548 | # CONFIG_INPUT_CM109 is not set | ||
1549 | CONFIG_INPUT_TWL4030_PWRBUTTON=y | ||
1550 | CONFIG_INPUT_TWL4030_VIBRA=m | ||
1551 | CONFIG_INPUT_UINPUT=y | ||
1552 | CONFIG_INPUT_PCF8574=m | ||
1553 | CONFIG_INPUT_PWM_BEEPER=m | ||
1554 | # CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set | ||
1555 | CONFIG_INPUT_ADXL34X=m | ||
1556 | CONFIG_INPUT_ADXL34X_I2C=m | ||
1557 | CONFIG_INPUT_ADXL34X_SPI=m | ||
1558 | CONFIG_INPUT_CMA3000=m | ||
1559 | CONFIG_INPUT_CMA3000_I2C=m | ||
1560 | |||
1561 | # | ||
1562 | # Hardware I/O ports | ||
1563 | # | ||
1564 | CONFIG_SERIO=y | ||
1565 | CONFIG_SERIO_SERPORT=y | ||
1566 | CONFIG_SERIO_LIBPS2=y | ||
1567 | # CONFIG_SERIO_RAW is not set | ||
1568 | # CONFIG_SERIO_ALTERA_PS2 is not set | ||
1569 | # CONFIG_SERIO_PS2MULT is not set | ||
1570 | # CONFIG_GAMEPORT is not set | ||
1571 | |||
1572 | # | ||
1573 | # Character devices | ||
1574 | # | ||
1575 | CONFIG_VT=y | ||
1576 | CONFIG_CONSOLE_TRANSLATIONS=y | ||
1577 | CONFIG_VT_CONSOLE=y | ||
1578 | CONFIG_HW_CONSOLE=y | ||
1579 | CONFIG_VT_HW_CONSOLE_BINDING=y | ||
1580 | CONFIG_UNIX98_PTYS=y | ||
1581 | # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set | ||
1582 | # CONFIG_LEGACY_PTYS is not set | ||
1583 | # CONFIG_SERIAL_NONSTANDARD is not set | ||
1584 | CONFIG_N_GSM=m | ||
1585 | CONFIG_DEVKMEM=y | ||
1586 | |||
1587 | # | ||
1588 | # Serial drivers | ||
1589 | # | ||
1590 | CONFIG_SERIAL_8250=y | ||
1591 | CONFIG_SERIAL_8250_CONSOLE=y | ||
1592 | CONFIG_SERIAL_8250_NR_UARTS=32 | ||
1593 | CONFIG_SERIAL_8250_RUNTIME_UARTS=4 | ||
1594 | CONFIG_SERIAL_8250_EXTENDED=y | ||
1595 | CONFIG_SERIAL_8250_MANY_PORTS=y | ||
1596 | CONFIG_SERIAL_8250_SHARE_IRQ=y | ||
1597 | CONFIG_SERIAL_8250_DETECT_IRQ=y | ||
1598 | CONFIG_SERIAL_8250_RSA=y | ||
1599 | |||
1600 | # | ||
1601 | # Non-8250 serial port support | ||
1602 | # | ||
1603 | # CONFIG_SERIAL_MAX3100 is not set | ||
1604 | # CONFIG_SERIAL_MAX3107 is not set | ||
1605 | CONFIG_SERIAL_CORE=y | ||
1606 | CONFIG_SERIAL_CORE_CONSOLE=y | ||
1607 | CONFIG_SERIAL_OMAP=y | ||
1608 | CONFIG_SERIAL_OMAP_CONSOLE=y | ||
1609 | # CONFIG_SERIAL_TIMBERDALE is not set | ||
1610 | # CONFIG_SERIAL_ALTERA_JTAGUART is not set | ||
1611 | # CONFIG_SERIAL_ALTERA_UART is not set | ||
1612 | CONFIG_SERIAL_IFX6X60=m | ||
1613 | CONFIG_TTY_PRINTK=y | ||
1614 | # CONFIG_HVC_DCC is not set | ||
1615 | # CONFIG_IPMI_HANDLER is not set | ||
1616 | CONFIG_HW_RANDOM=y | ||
1617 | # CONFIG_HW_RANDOM_TIMERIOMEM is not set | ||
1618 | # CONFIG_R3964 is not set | ||
1619 | # CONFIG_RAW_DRIVER is not set | ||
1620 | # CONFIG_TCG_TPM is not set | ||
1621 | # CONFIG_RAMOOPS is not set | ||
1622 | CONFIG_I2C=y | ||
1623 | CONFIG_I2C_BOARDINFO=y | ||
1624 | CONFIG_I2C_COMPAT=y | ||
1625 | CONFIG_I2C_CHARDEV=y | ||
1626 | CONFIG_I2C_MUX=m | ||
1627 | |||
1628 | # | ||
1629 | # Multiplexer I2C Chip support | ||
1630 | # | ||
1631 | CONFIG_I2C_MUX_GPIO=m | ||
1632 | # CONFIG_I2C_MUX_PCA9541 is not set | ||
1633 | # CONFIG_I2C_MUX_PCA954x is not set | ||
1634 | CONFIG_I2C_HELPER_AUTO=y | ||
1635 | CONFIG_I2C_ALGOBIT=m | ||
1636 | |||
1637 | # | ||
1638 | # I2C Hardware Bus support | ||
1639 | # | ||
1640 | |||
1641 | # | ||
1642 | # I2C system bus drivers (mostly embedded / system-on-chip) | ||
1643 | # | ||
1644 | # CONFIG_I2C_DESIGNWARE is not set | ||
1645 | # CONFIG_I2C_GPIO is not set | ||
1646 | # CONFIG_I2C_OCORES is not set | ||
1647 | CONFIG_I2C_OMAP=y | ||
1648 | # CONFIG_I2C_PCA_PLATFORM is not set | ||
1649 | # CONFIG_I2C_PXA_PCI is not set | ||
1650 | # CONFIG_I2C_SIMTEC is not set | ||
1651 | # CONFIG_I2C_XILINX is not set | ||
1652 | |||
1653 | # | ||
1654 | # External I2C/SMBus adapter drivers | ||
1655 | # | ||
1656 | CONFIG_I2C_DIOLAN_U2C=m | ||
1657 | # CONFIG_I2C_PARPORT_LIGHT is not set | ||
1658 | # CONFIG_I2C_TAOS_EVM is not set | ||
1659 | # CONFIG_I2C_TINY_USB is not set | ||
1660 | |||
1661 | # | ||
1662 | # Other I2C/SMBus bus drivers | ||
1663 | # | ||
1664 | # CONFIG_I2C_STUB is not set | ||
1665 | # CONFIG_I2C_DEBUG_CORE is not set | ||
1666 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
1667 | # CONFIG_I2C_DEBUG_BUS is not set | ||
1668 | CONFIG_SPI=y | ||
1669 | # CONFIG_SPI_DEBUG is not set | ||
1670 | CONFIG_SPI_MASTER=y | ||
1671 | |||
1672 | # | ||
1673 | # SPI Master Controller Drivers | ||
1674 | # | ||
1675 | # CONFIG_SPI_ALTERA is not set | ||
1676 | # CONFIG_SPI_BITBANG is not set | ||
1677 | # CONFIG_SPI_GPIO is not set | ||
1678 | # CONFIG_SPI_OC_TINY is not set | ||
1679 | CONFIG_SPI_OMAP24XX=y | ||
1680 | # CONFIG_SPI_PXA2XX_PCI is not set | ||
1681 | # CONFIG_SPI_XILINX is not set | ||
1682 | # CONFIG_SPI_DESIGNWARE is not set | ||
1683 | |||
1684 | # | ||
1685 | # SPI Protocol Masters | ||
1686 | # | ||
1687 | CONFIG_SPI_SPIDEV=y | ||
1688 | # CONFIG_SPI_TLE62X0 is not set | ||
1689 | |||
1690 | # | ||
1691 | # PPS support | ||
1692 | # | ||
1693 | # CONFIG_PPS is not set | ||
1694 | |||
1695 | # | ||
1696 | # PPS generators support | ||
1697 | # | ||
1698 | CONFIG_ARCH_REQUIRE_GPIOLIB=y | ||
1699 | CONFIG_GPIOLIB=y | ||
1700 | # CONFIG_DEBUG_GPIO is not set | ||
1701 | CONFIG_GPIO_SYSFS=y | ||
1702 | CONFIG_GPIO_MAX730X=m | ||
1703 | |||
1704 | # | ||
1705 | # Memory mapped GPIO expanders: | ||
1706 | # | ||
1707 | # CONFIG_GPIO_BASIC_MMIO is not set | ||
1708 | # CONFIG_GPIO_IT8761E is not set | ||
1709 | |||
1710 | # | ||
1711 | # I2C GPIO expanders: | ||
1712 | # | ||
1713 | CONFIG_GPIO_MAX7300=m | ||
1714 | # CONFIG_GPIO_MAX732X is not set | ||
1715 | # CONFIG_GPIO_PCF857X is not set | ||
1716 | # CONFIG_GPIO_SX150X is not set | ||
1717 | CONFIG_GPIO_TWL4030=y | ||
1718 | CONFIG_GPIO_ADP5588=m | ||
1719 | |||
1720 | # | ||
1721 | # PCI GPIO expanders: | ||
1722 | # | ||
1723 | |||
1724 | # | ||
1725 | # SPI GPIO expanders: | ||
1726 | # | ||
1727 | # CONFIG_GPIO_MAX7301 is not set | ||
1728 | # CONFIG_GPIO_MCP23S08 is not set | ||
1729 | # CONFIG_GPIO_MC33880 is not set | ||
1730 | # CONFIG_GPIO_74X164 is not set | ||
1731 | |||
1732 | # | ||
1733 | # AC97 GPIO expanders: | ||
1734 | # | ||
1735 | |||
1736 | # | ||
1737 | # MODULbus GPIO expanders: | ||
1738 | # | ||
1739 | # CONFIG_W1 is not set | ||
1740 | CONFIG_POWER_SUPPLY=m | ||
1741 | # CONFIG_POWER_SUPPLY_DEBUG is not set | ||
1742 | # CONFIG_PDA_POWER is not set | ||
1743 | CONFIG_TEST_POWER=m | ||
1744 | # CONFIG_BATTERY_DS2782 is not set | ||
1745 | # CONFIG_BATTERY_BQ20Z75 is not set | ||
1746 | # CONFIG_BATTERY_BQ27x00 is not set | ||
1747 | # CONFIG_BATTERY_MAX17040 is not set | ||
1748 | CONFIG_BATTERY_MAX17042=m | ||
1749 | CONFIG_CHARGER_ISP1704=m | ||
1750 | CONFIG_CHARGER_TWL4030=m | ||
1751 | CONFIG_CHARGER_GPIO=m | ||
1752 | CONFIG_HWMON=y | ||
1753 | # CONFIG_HWMON_VID is not set | ||
1754 | # CONFIG_HWMON_DEBUG_CHIP is not set | ||
1755 | |||
1756 | # | ||
1757 | # Native drivers | ||
1758 | # | ||
1759 | # CONFIG_SENSORS_AD7414 is not set | ||
1760 | # CONFIG_SENSORS_AD7418 is not set | ||
1761 | # CONFIG_SENSORS_ADCXX is not set | ||
1762 | # CONFIG_SENSORS_ADM1021 is not set | ||
1763 | # CONFIG_SENSORS_ADM1025 is not set | ||
1764 | # CONFIG_SENSORS_ADM1026 is not set | ||
1765 | # CONFIG_SENSORS_ADM1029 is not set | ||
1766 | # CONFIG_SENSORS_ADM1031 is not set | ||
1767 | # CONFIG_SENSORS_ADM9240 is not set | ||
1768 | CONFIG_SENSORS_ADT7411=m | ||
1769 | # CONFIG_SENSORS_ADT7462 is not set | ||
1770 | # CONFIG_SENSORS_ADT7470 is not set | ||
1771 | # CONFIG_SENSORS_ADT7475 is not set | ||
1772 | CONFIG_SENSORS_ASC7621=m | ||
1773 | # CONFIG_SENSORS_ATXP1 is not set | ||
1774 | CONFIG_SENSORS_DS620=m | ||
1775 | # CONFIG_SENSORS_DS1621 is not set | ||
1776 | # CONFIG_SENSORS_F71805F is not set | ||
1777 | # CONFIG_SENSORS_F71882FG is not set | ||
1778 | # CONFIG_SENSORS_F75375S is not set | ||
1779 | # CONFIG_SENSORS_G760A is not set | ||
1780 | # CONFIG_SENSORS_GL518SM is not set | ||
1781 | # CONFIG_SENSORS_GL520SM is not set | ||
1782 | CONFIG_SENSORS_GPIO_FAN=m | ||
1783 | # CONFIG_SENSORS_IT87 is not set | ||
1784 | CONFIG_SENSORS_JC42=m | ||
1785 | # CONFIG_SENSORS_LINEAGE is not set | ||
1786 | # CONFIG_SENSORS_LM63 is not set | ||
1787 | # CONFIG_SENSORS_LM70 is not set | ||
1788 | # CONFIG_SENSORS_LM73 is not set | ||
1789 | # CONFIG_SENSORS_LM75 is not set | ||
1790 | # CONFIG_SENSORS_LM77 is not set | ||
1791 | # CONFIG_SENSORS_LM78 is not set | ||
1792 | # CONFIG_SENSORS_LM80 is not set | ||
1793 | # CONFIG_SENSORS_LM83 is not set | ||
1794 | # CONFIG_SENSORS_LM85 is not set | ||
1795 | # CONFIG_SENSORS_LM87 is not set | ||
1796 | # CONFIG_SENSORS_LM90 is not set | ||
1797 | # CONFIG_SENSORS_LM92 is not set | ||
1798 | # CONFIG_SENSORS_LM93 is not set | ||
1799 | # CONFIG_SENSORS_LTC4151 is not set | ||
1800 | # CONFIG_SENSORS_LTC4215 is not set | ||
1801 | # CONFIG_SENSORS_LTC4245 is not set | ||
1802 | # CONFIG_SENSORS_LTC4261 is not set | ||
1803 | # CONFIG_SENSORS_LM95241 is not set | ||
1804 | # CONFIG_SENSORS_MAX1111 is not set | ||
1805 | # CONFIG_SENSORS_MAX1619 is not set | ||
1806 | # CONFIG_SENSORS_MAX6639 is not set | ||
1807 | # CONFIG_SENSORS_MAX6650 is not set | ||
1808 | # CONFIG_SENSORS_PC87360 is not set | ||
1809 | # CONFIG_SENSORS_PC87427 is not set | ||
1810 | # CONFIG_SENSORS_PCF8591 is not set | ||
1811 | # CONFIG_PMBUS is not set | ||
1812 | # CONFIG_SENSORS_SHT15 is not set | ||
1813 | # CONFIG_SENSORS_SHT21 is not set | ||
1814 | CONFIG_SENSORS_SMM665=m | ||
1815 | # CONFIG_SENSORS_DME1737 is not set | ||
1816 | CONFIG_SENSORS_EMC1403=m | ||
1817 | CONFIG_SENSORS_EMC2103=m | ||
1818 | # CONFIG_SENSORS_SMSC47M1 is not set | ||
1819 | # CONFIG_SENSORS_SMSC47M192 is not set | ||
1820 | # CONFIG_SENSORS_SMSC47B397 is not set | ||
1821 | # CONFIG_SENSORS_SCH5627 is not set | ||
1822 | # CONFIG_SENSORS_ADS1015 is not set | ||
1823 | # CONFIG_SENSORS_ADS7828 is not set | ||
1824 | CONFIG_SENSORS_ADS7871=m | ||
1825 | CONFIG_SENSORS_AMC6821=m | ||
1826 | # CONFIG_SENSORS_THMC50 is not set | ||
1827 | CONFIG_SENSORS_TMP102=m | ||
1828 | # CONFIG_SENSORS_TMP401 is not set | ||
1829 | # CONFIG_SENSORS_TMP421 is not set | ||
1830 | CONFIG_SENSORS_TWL4030_MADC=m | ||
1831 | # CONFIG_SENSORS_VT1211 is not set | ||
1832 | # CONFIG_SENSORS_W83781D is not set | ||
1833 | # CONFIG_SENSORS_W83791D is not set | ||
1834 | # CONFIG_SENSORS_W83792D is not set | ||
1835 | # CONFIG_SENSORS_W83793 is not set | ||
1836 | # CONFIG_SENSORS_W83795 is not set | ||
1837 | # CONFIG_SENSORS_W83L785TS is not set | ||
1838 | # CONFIG_SENSORS_W83L786NG is not set | ||
1839 | # CONFIG_SENSORS_W83627HF is not set | ||
1840 | # CONFIG_SENSORS_W83627EHF is not set | ||
1841 | CONFIG_THERMAL=y | ||
1842 | CONFIG_THERMAL_HWMON=y | ||
1843 | CONFIG_WATCHDOG=y | ||
1844 | CONFIG_WATCHDOG_NOWAYOUT=y | ||
1845 | |||
1846 | # | ||
1847 | # Watchdog Device Drivers | ||
1848 | # | ||
1849 | # CONFIG_SOFT_WATCHDOG is not set | ||
1850 | CONFIG_OMAP_WATCHDOG=y | ||
1851 | # CONFIG_TWL4030_WATCHDOG is not set | ||
1852 | # CONFIG_MAX63XX_WATCHDOG is not set | ||
1853 | |||
1854 | # | ||
1855 | # USB-based Watchdog Cards | ||
1856 | # | ||
1857 | # CONFIG_USBPCWATCHDOG is not set | ||
1858 | CONFIG_SSB_POSSIBLE=y | ||
1859 | |||
1860 | # | ||
1861 | # Sonics Silicon Backplane | ||
1862 | # | ||
1863 | CONFIG_SSB=y | ||
1864 | CONFIG_SSB_BLOCKIO=y | ||
1865 | CONFIG_SSB_SDIOHOST_POSSIBLE=y | ||
1866 | # CONFIG_SSB_SDIOHOST is not set | ||
1867 | # CONFIG_SSB_SILENT is not set | ||
1868 | # CONFIG_SSB_DEBUG is not set | ||
1869 | CONFIG_MFD_SUPPORT=y | ||
1870 | CONFIG_MFD_CORE=y | ||
1871 | # CONFIG_MFD_88PM860X is not set | ||
1872 | # CONFIG_MFD_SM501 is not set | ||
1873 | # CONFIG_MFD_ASIC3 is not set | ||
1874 | # CONFIG_HTC_EGPIO is not set | ||
1875 | # CONFIG_HTC_PASIC3 is not set | ||
1876 | # CONFIG_HTC_I2CPLD is not set | ||
1877 | CONFIG_TPS6105X=m | ||
1878 | # CONFIG_TPS65010 is not set | ||
1879 | CONFIG_TPS6507X=m | ||
1880 | CONFIG_TWL4030_CORE=y | ||
1881 | CONFIG_TWL4030_MADC=m | ||
1882 | CONFIG_TWL4030_POWER=y | ||
1883 | CONFIG_TWL4030_CODEC=y | ||
1884 | CONFIG_TWL4030_POWEROFF=y | ||
1885 | CONFIG_TWL6030_PWM=m | ||
1886 | # CONFIG_MFD_STMPE is not set | ||
1887 | # CONFIG_MFD_TC3589X is not set | ||
1888 | # CONFIG_MFD_TMIO is not set | ||
1889 | # CONFIG_MFD_T7L66XB is not set | ||
1890 | # CONFIG_MFD_TC6387XB is not set | ||
1891 | # CONFIG_MFD_TC6393XB is not set | ||
1892 | # CONFIG_PMIC_DA903X is not set | ||
1893 | # CONFIG_PMIC_ADP5520 is not set | ||
1894 | # CONFIG_MFD_MAX8925 is not set | ||
1895 | # CONFIG_MFD_MAX8997 is not set | ||
1896 | # CONFIG_MFD_MAX8998 is not set | ||
1897 | # CONFIG_MFD_WM8400 is not set | ||
1898 | # CONFIG_MFD_WM831X_I2C is not set | ||
1899 | # CONFIG_MFD_WM831X_SPI is not set | ||
1900 | # CONFIG_MFD_WM8350_I2C is not set | ||
1901 | # CONFIG_MFD_WM8994 is not set | ||
1902 | # CONFIG_MFD_PCF50633 is not set | ||
1903 | # CONFIG_MFD_MC13XXX is not set | ||
1904 | # CONFIG_ABX500_CORE is not set | ||
1905 | # CONFIG_EZX_PCAP is not set | ||
1906 | CONFIG_MFD_TPS6586X=y | ||
1907 | CONFIG_MFD_WL1273_CORE=m | ||
1908 | CONFIG_MFD_OMAP_USB_HOST=y | ||
1909 | CONFIG_REGULATOR=y | ||
1910 | # CONFIG_REGULATOR_DEBUG is not set | ||
1911 | CONFIG_REGULATOR_DUMMY=y | ||
1912 | CONFIG_REGULATOR_FIXED_VOLTAGE=y | ||
1913 | # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set | ||
1914 | # CONFIG_REGULATOR_USERSPACE_CONSUMER is not set | ||
1915 | # CONFIG_REGULATOR_BQ24022 is not set | ||
1916 | # CONFIG_REGULATOR_MAX1586 is not set | ||
1917 | # CONFIG_REGULATOR_MAX8649 is not set | ||
1918 | # CONFIG_REGULATOR_MAX8660 is not set | ||
1919 | # CONFIG_REGULATOR_MAX8952 is not set | ||
1920 | CONFIG_REGULATOR_TWL4030=y | ||
1921 | # CONFIG_REGULATOR_LP3971 is not set | ||
1922 | # CONFIG_REGULATOR_LP3972 is not set | ||
1923 | CONFIG_REGULATOR_TPS6105X=m | ||
1924 | # CONFIG_REGULATOR_TPS65023 is not set | ||
1925 | # CONFIG_REGULATOR_TPS6507X is not set | ||
1926 | # CONFIG_REGULATOR_ISL6271A is not set | ||
1927 | # CONFIG_REGULATOR_AD5398 is not set | ||
1928 | CONFIG_REGULATOR_TPS6586X=m | ||
1929 | CONFIG_REGULATOR_TPS6524X=m | ||
1930 | CONFIG_MEDIA_SUPPORT=y | ||
1931 | |||
1932 | # | ||
1933 | # Multimedia core support | ||
1934 | # | ||
1935 | CONFIG_MEDIA_CONTROLLER=y | ||
1936 | CONFIG_VIDEO_DEV=y | ||
1937 | CONFIG_VIDEO_V4L2_COMMON=y | ||
1938 | CONFIG_VIDEO_V4L2_SUBDEV_API=y | ||
1939 | CONFIG_DVB_CORE=m | ||
1940 | CONFIG_VIDEO_MEDIA=m | ||
1941 | |||
1942 | # | ||
1943 | # Multimedia drivers | ||
1944 | # | ||
1945 | CONFIG_RC_CORE=m | ||
1946 | CONFIG_LIRC=m | ||
1947 | CONFIG_RC_MAP=m | ||
1948 | CONFIG_IR_NEC_DECODER=m | ||
1949 | CONFIG_IR_RC5_DECODER=m | ||
1950 | CONFIG_IR_RC6_DECODER=m | ||
1951 | CONFIG_IR_JVC_DECODER=m | ||
1952 | CONFIG_IR_SONY_DECODER=m | ||
1953 | CONFIG_IR_RC5_SZ_DECODER=m | ||
1954 | CONFIG_IR_LIRC_CODEC=m | ||
1955 | # CONFIG_IR_IMON is not set | ||
1956 | # CONFIG_IR_MCEUSB is not set | ||
1957 | # CONFIG_IR_STREAMZAP is not set | ||
1958 | CONFIG_RC_LOOPBACK=m | ||
1959 | CONFIG_MEDIA_ATTACH=y | ||
1960 | CONFIG_MEDIA_TUNER=m | ||
1961 | CONFIG_MEDIA_TUNER_CUSTOMISE=y | ||
1962 | |||
1963 | # | ||
1964 | # Customize TV tuners | ||
1965 | # | ||
1966 | CONFIG_MEDIA_TUNER_SIMPLE=m | ||
1967 | CONFIG_MEDIA_TUNER_TDA8290=m | ||
1968 | CONFIG_MEDIA_TUNER_TDA827X=m | ||
1969 | CONFIG_MEDIA_TUNER_TDA18271=m | ||
1970 | CONFIG_MEDIA_TUNER_TDA9887=m | ||
1971 | CONFIG_MEDIA_TUNER_TEA5761=m | ||
1972 | CONFIG_MEDIA_TUNER_TEA5767=m | ||
1973 | CONFIG_MEDIA_TUNER_MT20XX=m | ||
1974 | CONFIG_MEDIA_TUNER_MT2060=m | ||
1975 | CONFIG_MEDIA_TUNER_MT2266=m | ||
1976 | CONFIG_MEDIA_TUNER_MT2131=m | ||
1977 | CONFIG_MEDIA_TUNER_QT1010=m | ||
1978 | CONFIG_MEDIA_TUNER_XC2028=m | ||
1979 | CONFIG_MEDIA_TUNER_XC5000=m | ||
1980 | CONFIG_MEDIA_TUNER_MXL5005S=m | ||
1981 | CONFIG_MEDIA_TUNER_MXL5007T=m | ||
1982 | CONFIG_MEDIA_TUNER_MC44S803=m | ||
1983 | CONFIG_MEDIA_TUNER_MAX2165=m | ||
1984 | CONFIG_MEDIA_TUNER_TDA18218=m | ||
1985 | CONFIG_VIDEO_V4L2=y | ||
1986 | CONFIG_VIDEOBUF_GEN=y | ||
1987 | CONFIG_VIDEOBUF_VMALLOC=m | ||
1988 | CONFIG_VIDEOBUF_DMA_CONTIG=y | ||
1989 | CONFIG_VIDEOBUF_DVB=m | ||
1990 | CONFIG_VIDEO_TVEEPROM=m | ||
1991 | CONFIG_VIDEO_TUNER=m | ||
1992 | CONFIG_V4L2_MEM2MEM_DEV=m | ||
1993 | CONFIG_VIDEOBUF2_CORE=m | ||
1994 | CONFIG_VIDEOBUF2_MEMOPS=m | ||
1995 | CONFIG_VIDEOBUF2_VMALLOC=m | ||
1996 | CONFIG_VIDEO_CAPTURE_DRIVERS=y | ||
1997 | # CONFIG_VIDEO_ADV_DEBUG is not set | ||
1998 | # CONFIG_VIDEO_FIXED_MINOR_RANGES is not set | ||
1999 | # CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set | ||
2000 | CONFIG_VIDEO_IR_I2C=m | ||
2001 | |||
2002 | # | ||
2003 | # Encoders/decoders and other helper chips | ||
2004 | # | ||
2005 | |||
2006 | # | ||
2007 | # Audio decoders | ||
2008 | # | ||
2009 | # CONFIG_VIDEO_TVAUDIO is not set | ||
2010 | # CONFIG_VIDEO_TDA7432 is not set | ||
2011 | # CONFIG_VIDEO_TDA9840 is not set | ||
2012 | # CONFIG_VIDEO_TEA6415C is not set | ||
2013 | # CONFIG_VIDEO_TEA6420 is not set | ||
2014 | CONFIG_VIDEO_MSP3400=m | ||
2015 | # CONFIG_VIDEO_CS5345 is not set | ||
2016 | CONFIG_VIDEO_CS53L32A=m | ||
2017 | # CONFIG_VIDEO_M52790 is not set | ||
2018 | # CONFIG_VIDEO_TLV320AIC23B is not set | ||
2019 | CONFIG_VIDEO_WM8775=m | ||
2020 | # CONFIG_VIDEO_WM8739 is not set | ||
2021 | # CONFIG_VIDEO_VP27SMPX is not set | ||
2022 | |||
2023 | # | ||
2024 | # RDS decoders | ||
2025 | # | ||
2026 | # CONFIG_VIDEO_SAA6588 is not set | ||
2027 | |||
2028 | # | ||
2029 | # Video decoders | ||
2030 | # | ||
2031 | CONFIG_VIDEO_ADV7180=m | ||
2032 | # CONFIG_VIDEO_BT819 is not set | ||
2033 | # CONFIG_VIDEO_BT856 is not set | ||
2034 | # CONFIG_VIDEO_BT866 is not set | ||
2035 | # CONFIG_VIDEO_KS0127 is not set | ||
2036 | # CONFIG_VIDEO_OV7670 is not set | ||
2037 | CONFIG_VIDEO_MT9V011=m | ||
2038 | # CONFIG_VIDEO_TCM825X is not set | ||
2039 | # CONFIG_VIDEO_SAA7110 is not set | ||
2040 | CONFIG_VIDEO_SAA711X=m | ||
2041 | # CONFIG_VIDEO_SAA717X is not set | ||
2042 | # CONFIG_VIDEO_SAA7191 is not set | ||
2043 | # CONFIG_VIDEO_TVP514X is not set | ||
2044 | # CONFIG_VIDEO_TVP5150 is not set | ||
2045 | # CONFIG_VIDEO_TVP7002 is not set | ||
2046 | # CONFIG_VIDEO_VPX3220 is not set | ||
2047 | |||
2048 | # | ||
2049 | # Video and audio decoders | ||
2050 | # | ||
2051 | CONFIG_VIDEO_CX25840=m | ||
2052 | |||
2053 | # | ||
2054 | # MPEG video encoders | ||
2055 | # | ||
2056 | CONFIG_VIDEO_CX2341X=m | ||
2057 | |||
2058 | # | ||
2059 | # Video encoders | ||
2060 | # | ||
2061 | # CONFIG_VIDEO_SAA7127 is not set | ||
2062 | # CONFIG_VIDEO_SAA7185 is not set | ||
2063 | # CONFIG_VIDEO_ADV7170 is not set | ||
2064 | # CONFIG_VIDEO_ADV7175 is not set | ||
2065 | # CONFIG_VIDEO_THS7303 is not set | ||
2066 | # CONFIG_VIDEO_ADV7343 is not set | ||
2067 | # CONFIG_VIDEO_AK881X is not set | ||
2068 | |||
2069 | # | ||
2070 | # Video improvement chips | ||
2071 | # | ||
2072 | # CONFIG_VIDEO_UPD64031A is not set | ||
2073 | # CONFIG_VIDEO_UPD64083 is not set | ||
2074 | CONFIG_VIDEO_VIVI=m | ||
2075 | CONFIG_VIDEO_VPFE_CAPTURE=y | ||
2076 | # CONFIG_VIDEO_DM6446_CCDC is not set | ||
2077 | CONFIG_VIDEO_OMAP2_VOUT=y | ||
2078 | # CONFIG_VIDEO_CPIA2 is not set | ||
2079 | CONFIG_VIDEO_TIMBERDALE=m | ||
2080 | # CONFIG_VIDEO_AU0828 is not set | ||
2081 | CONFIG_VIDEO_SR030PC30=m | ||
2082 | CONFIG_VIDEO_NOON010PC30=m | ||
2083 | CONFIG_VIDEO_OMAP3=y | ||
2084 | # CONFIG_VIDEO_OMAP3_DEBUG is not set | ||
2085 | # CONFIG_SOC_CAMERA is not set | ||
2086 | CONFIG_V4L_USB_DRIVERS=y | ||
2087 | CONFIG_USB_VIDEO_CLASS=m | ||
2088 | CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y | ||
2089 | CONFIG_USB_GSPCA=m | ||
2090 | CONFIG_USB_M5602=m | ||
2091 | CONFIG_USB_STV06XX=m | ||
2092 | # CONFIG_USB_GL860 is not set | ||
2093 | CONFIG_USB_GSPCA_BENQ=m | ||
2094 | CONFIG_USB_GSPCA_CONEX=m | ||
2095 | CONFIG_USB_GSPCA_CPIA1=m | ||
2096 | CONFIG_USB_GSPCA_ETOMS=m | ||
2097 | CONFIG_USB_GSPCA_FINEPIX=m | ||
2098 | # CONFIG_USB_GSPCA_JEILINJ is not set | ||
2099 | CONFIG_USB_GSPCA_KONICA=m | ||
2100 | CONFIG_USB_GSPCA_MARS=m | ||
2101 | # CONFIG_USB_GSPCA_MR97310A is not set | ||
2102 | CONFIG_USB_GSPCA_NW80X=m | ||
2103 | CONFIG_USB_GSPCA_OV519=m | ||
2104 | CONFIG_USB_GSPCA_OV534=m | ||
2105 | CONFIG_USB_GSPCA_OV534_9=m | ||
2106 | CONFIG_USB_GSPCA_PAC207=m | ||
2107 | # CONFIG_USB_GSPCA_PAC7302 is not set | ||
2108 | CONFIG_USB_GSPCA_PAC7311=m | ||
2109 | CONFIG_USB_GSPCA_SN9C2028=m | ||
2110 | # CONFIG_USB_GSPCA_SN9C20X is not set | ||
2111 | CONFIG_USB_GSPCA_SONIXB=m | ||
2112 | CONFIG_USB_GSPCA_SONIXJ=m | ||
2113 | CONFIG_USB_GSPCA_SPCA500=m | ||
2114 | CONFIG_USB_GSPCA_SPCA501=m | ||
2115 | CONFIG_USB_GSPCA_SPCA505=m | ||
2116 | CONFIG_USB_GSPCA_SPCA506=m | ||
2117 | CONFIG_USB_GSPCA_SPCA508=m | ||
2118 | CONFIG_USB_GSPCA_SPCA561=m | ||
2119 | CONFIG_USB_GSPCA_SPCA1528=m | ||
2120 | # CONFIG_USB_GSPCA_SQ905 is not set | ||
2121 | # CONFIG_USB_GSPCA_SQ905C is not set | ||
2122 | CONFIG_USB_GSPCA_SQ930X=m | ||
2123 | CONFIG_USB_GSPCA_STK014=m | ||
2124 | # CONFIG_USB_GSPCA_STV0680 is not set | ||
2125 | CONFIG_USB_GSPCA_SUNPLUS=m | ||
2126 | CONFIG_USB_GSPCA_T613=m | ||
2127 | CONFIG_USB_GSPCA_TV8532=m | ||
2128 | CONFIG_USB_GSPCA_VC032X=m | ||
2129 | CONFIG_USB_GSPCA_VICAM=m | ||
2130 | CONFIG_USB_GSPCA_XIRLINK_CIT=m | ||
2131 | CONFIG_USB_GSPCA_ZC3XX=m | ||
2132 | CONFIG_VIDEO_PVRUSB2=m | ||
2133 | CONFIG_VIDEO_PVRUSB2_SYSFS=y | ||
2134 | CONFIG_VIDEO_PVRUSB2_DVB=y | ||
2135 | # CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set | ||
2136 | CONFIG_VIDEO_HDPVR=m | ||
2137 | CONFIG_VIDEO_EM28XX=m | ||
2138 | CONFIG_VIDEO_EM28XX_ALSA=m | ||
2139 | CONFIG_VIDEO_EM28XX_DVB=m | ||
2140 | CONFIG_VIDEO_TLG2300=m | ||
2141 | CONFIG_VIDEO_CX231XX=m | ||
2142 | CONFIG_VIDEO_CX231XX_RC=y | ||
2143 | # CONFIG_VIDEO_CX231XX_ALSA is not set | ||
2144 | CONFIG_VIDEO_CX231XX_DVB=m | ||
2145 | CONFIG_VIDEO_USBVISION=m | ||
2146 | CONFIG_USB_ET61X251=m | ||
2147 | CONFIG_USB_SN9C102=m | ||
2148 | CONFIG_USB_PWC=m | ||
2149 | # CONFIG_USB_PWC_DEBUG is not set | ||
2150 | CONFIG_USB_PWC_INPUT_EVDEV=y | ||
2151 | CONFIG_USB_ZR364XX=m | ||
2152 | CONFIG_USB_STKWEBCAM=m | ||
2153 | CONFIG_USB_S2255=m | ||
2154 | CONFIG_V4L_MEM2MEM_DRIVERS=y | ||
2155 | CONFIG_VIDEO_MEM2MEM_TESTDEV=m | ||
2156 | CONFIG_RADIO_ADAPTERS=y | ||
2157 | # CONFIG_I2C_SI4713 is not set | ||
2158 | # CONFIG_RADIO_SI4713 is not set | ||
2159 | # CONFIG_USB_DSBR is not set | ||
2160 | # CONFIG_RADIO_SI470X is not set | ||
2161 | # CONFIG_USB_MR800 is not set | ||
2162 | # CONFIG_RADIO_TEA5764 is not set | ||
2163 | CONFIG_RADIO_SAA7706H=m | ||
2164 | # CONFIG_RADIO_TEF6862 is not set | ||
2165 | CONFIG_RADIO_WL1273=m | ||
2166 | |||
2167 | # | ||
2168 | # Texas Instruments WL128x FM driver (ST based) | ||
2169 | # | ||
2170 | CONFIG_RADIO_WL128X=m | ||
2171 | CONFIG_DVB_MAX_ADAPTERS=8 | ||
2172 | CONFIG_DVB_DYNAMIC_MINORS=y | ||
2173 | CONFIG_DVB_CAPTURE_DRIVERS=y | ||
2174 | # CONFIG_TTPCI_EEPROM is not set | ||
2175 | |||
2176 | # | ||
2177 | # Supported USB Adapters | ||
2178 | # | ||
2179 | CONFIG_DVB_USB=m | ||
2180 | # CONFIG_DVB_USB_DEBUG is not set | ||
2181 | CONFIG_DVB_USB_A800=m | ||
2182 | CONFIG_DVB_USB_DIBUSB_MB=m | ||
2183 | # CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set | ||
2184 | CONFIG_DVB_USB_DIBUSB_MC=m | ||
2185 | CONFIG_DVB_USB_DIB0700=m | ||
2186 | CONFIG_DVB_USB_UMT_010=m | ||
2187 | CONFIG_DVB_USB_CXUSB=m | ||
2188 | CONFIG_DVB_USB_M920X=m | ||
2189 | CONFIG_DVB_USB_GL861=m | ||
2190 | CONFIG_DVB_USB_AU6610=m | ||
2191 | CONFIG_DVB_USB_DIGITV=m | ||
2192 | CONFIG_DVB_USB_VP7045=m | ||
2193 | CONFIG_DVB_USB_VP702X=m | ||
2194 | CONFIG_DVB_USB_GP8PSK=m | ||
2195 | CONFIG_DVB_USB_NOVA_T_USB2=m | ||
2196 | CONFIG_DVB_USB_TTUSB2=m | ||
2197 | CONFIG_DVB_USB_DTT200U=m | ||
2198 | CONFIG_DVB_USB_OPERA1=m | ||
2199 | CONFIG_DVB_USB_AF9005=m | ||
2200 | CONFIG_DVB_USB_AF9005_REMOTE=m | ||
2201 | CONFIG_DVB_USB_DW2102=m | ||
2202 | CONFIG_DVB_USB_CINERGY_T2=m | ||
2203 | CONFIG_DVB_USB_ANYSEE=m | ||
2204 | CONFIG_DVB_USB_DTV5100=m | ||
2205 | CONFIG_DVB_USB_AF9015=m | ||
2206 | # CONFIG_DVB_USB_CE6230 is not set | ||
2207 | # CONFIG_DVB_USB_FRIIO is not set | ||
2208 | # CONFIG_DVB_USB_EC168 is not set | ||
2209 | CONFIG_DVB_USB_AZ6027=m | ||
2210 | CONFIG_DVB_USB_LME2510=m | ||
2211 | CONFIG_DVB_USB_TECHNISAT_USB2=m | ||
2212 | # CONFIG_SMS_SIANO_MDTV is not set | ||
2213 | |||
2214 | # | ||
2215 | # Supported FlexCopII (B2C2) Adapters | ||
2216 | # | ||
2217 | CONFIG_DVB_B2C2_FLEXCOP=m | ||
2218 | CONFIG_DVB_B2C2_FLEXCOP_USB=m | ||
2219 | # CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set | ||
2220 | |||
2221 | # | ||
2222 | # Supported DVB Frontends | ||
2223 | # | ||
2224 | # CONFIG_DVB_FE_CUSTOMISE is not set | ||
2225 | |||
2226 | # | ||
2227 | # Multistandard (satellite) frontends | ||
2228 | # | ||
2229 | CONFIG_DVB_STB0899=m | ||
2230 | CONFIG_DVB_STB6100=m | ||
2231 | CONFIG_DVB_STV090x=m | ||
2232 | CONFIG_DVB_STV6110x=m | ||
2233 | |||
2234 | # | ||
2235 | # DVB-S (satellite) frontends | ||
2236 | # | ||
2237 | CONFIG_DVB_CX24123=m | ||
2238 | CONFIG_DVB_MT312=m | ||
2239 | CONFIG_DVB_ZL10039=m | ||
2240 | CONFIG_DVB_S5H1420=m | ||
2241 | CONFIG_DVB_STV0288=m | ||
2242 | CONFIG_DVB_STB6000=m | ||
2243 | CONFIG_DVB_STV0299=m | ||
2244 | CONFIG_DVB_STV6110=m | ||
2245 | CONFIG_DVB_STV0900=m | ||
2246 | CONFIG_DVB_TDA10086=m | ||
2247 | CONFIG_DVB_TUNER_ITD1000=m | ||
2248 | CONFIG_DVB_TUNER_CX24113=m | ||
2249 | CONFIG_DVB_TDA826X=m | ||
2250 | CONFIG_DVB_CX24116=m | ||
2251 | CONFIG_DVB_SI21XX=m | ||
2252 | CONFIG_DVB_DS3000=m | ||
2253 | |||
2254 | # | ||
2255 | # DVB-T (terrestrial) frontends | ||
2256 | # | ||
2257 | CONFIG_DVB_CX22702=m | ||
2258 | CONFIG_DVB_TDA1004X=m | ||
2259 | CONFIG_DVB_NXT6000=m | ||
2260 | CONFIG_DVB_MT352=m | ||
2261 | CONFIG_DVB_ZL10353=m | ||
2262 | CONFIG_DVB_DIB3000MB=m | ||
2263 | CONFIG_DVB_DIB3000MC=m | ||
2264 | CONFIG_DVB_DIB7000M=m | ||
2265 | CONFIG_DVB_DIB7000P=m | ||
2266 | CONFIG_DVB_TDA10048=m | ||
2267 | CONFIG_DVB_AF9013=m | ||
2268 | |||
2269 | # | ||
2270 | # DVB-C (cable) frontends | ||
2271 | # | ||
2272 | CONFIG_DVB_TDA10023=m | ||
2273 | CONFIG_DVB_STV0297=m | ||
2274 | |||
2275 | # | ||
2276 | # ATSC (North American/Korean Terrestrial/Cable DTV) frontends | ||
2277 | # | ||
2278 | CONFIG_DVB_NXT200X=m | ||
2279 | CONFIG_DVB_BCM3510=m | ||
2280 | CONFIG_DVB_LGDT330X=m | ||
2281 | CONFIG_DVB_LGDT3305=m | ||
2282 | CONFIG_DVB_S5H1409=m | ||
2283 | CONFIG_DVB_S5H1411=m | ||
2284 | |||
2285 | # | ||
2286 | # ISDB-T (terrestrial) frontends | ||
2287 | # | ||
2288 | CONFIG_DVB_S921=m | ||
2289 | CONFIG_DVB_DIB8000=m | ||
2290 | CONFIG_DVB_MB86A20S=m | ||
2291 | |||
2292 | # | ||
2293 | # Digital terrestrial only tuners/PLL | ||
2294 | # | ||
2295 | CONFIG_DVB_PLL=m | ||
2296 | CONFIG_DVB_TUNER_DIB0070=m | ||
2297 | CONFIG_DVB_TUNER_DIB0090=m | ||
2298 | |||
2299 | # | ||
2300 | # SEC control devices for DVB-S | ||
2301 | # | ||
2302 | CONFIG_DVB_LNBP21=m | ||
2303 | CONFIG_DVB_ISL6421=m | ||
2304 | CONFIG_DVB_LGS8GXX=m | ||
2305 | CONFIG_DVB_ATBM8830=m | ||
2306 | CONFIG_DVB_IX2505V=m | ||
2307 | |||
2308 | # | ||
2309 | # Tools to develop new frontends | ||
2310 | # | ||
2311 | # CONFIG_DVB_DUMMY_FE is not set | ||
2312 | |||
2313 | # | ||
2314 | # Graphics support | ||
2315 | # | ||
2316 | CONFIG_DRM=m | ||
2317 | # CONFIG_VGASTATE is not set | ||
2318 | # CONFIG_VIDEO_OUTPUT_CONTROL is not set | ||
2319 | CONFIG_FB=y | ||
2320 | # CONFIG_FIRMWARE_EDID is not set | ||
2321 | # CONFIG_FB_DDC is not set | ||
2322 | # CONFIG_FB_BOOT_VESA_SUPPORT is not set | ||
2323 | CONFIG_FB_CFB_FILLRECT=y | ||
2324 | CONFIG_FB_CFB_COPYAREA=y | ||
2325 | CONFIG_FB_CFB_IMAGEBLIT=y | ||
2326 | # CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set | ||
2327 | CONFIG_FB_SYS_FILLRECT=m | ||
2328 | CONFIG_FB_SYS_COPYAREA=m | ||
2329 | CONFIG_FB_SYS_IMAGEBLIT=m | ||
2330 | # CONFIG_FB_FOREIGN_ENDIAN is not set | ||
2331 | CONFIG_FB_SYS_FOPS=m | ||
2332 | # CONFIG_FB_WMT_GE_ROPS is not set | ||
2333 | CONFIG_FB_DEFERRED_IO=y | ||
2334 | # CONFIG_FB_SVGALIB is not set | ||
2335 | # CONFIG_FB_MACMODES is not set | ||
2336 | # CONFIG_FB_BACKLIGHT is not set | ||
2337 | CONFIG_FB_MODE_HELPERS=y | ||
2338 | # CONFIG_FB_TILEBLITTING is not set | ||
2339 | |||
2340 | # | ||
2341 | # Frame buffer hardware drivers | ||
2342 | # | ||
2343 | # CONFIG_FB_S1D13XXX is not set | ||
2344 | # CONFIG_FB_TMIO is not set | ||
2345 | CONFIG_FB_UDL=m | ||
2346 | # CONFIG_FB_VIRTUAL is not set | ||
2347 | # CONFIG_FB_METRONOME is not set | ||
2348 | # CONFIG_FB_MB862XX is not set | ||
2349 | # CONFIG_FB_BROADSHEET is not set | ||
2350 | # CONFIG_FB_OMAP_BOOTLOADER_INIT is not set | ||
2351 | CONFIG_OMAP2_VRAM=y | ||
2352 | CONFIG_OMAP2_VRFB=y | ||
2353 | CONFIG_OMAP2_DSS=y | ||
2354 | CONFIG_OMAP2_VRAM_SIZE=14 | ||
2355 | CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y | ||
2356 | # CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set | ||
2357 | CONFIG_OMAP2_DSS_DPI=y | ||
2358 | # CONFIG_OMAP2_DSS_RFBI is not set | ||
2359 | CONFIG_OMAP2_DSS_VENC=y | ||
2360 | # CONFIG_OMAP2_DSS_SDI is not set | ||
2361 | CONFIG_OMAP2_DSS_DSI=y | ||
2362 | CONFIG_OMAP2_DSS_USE_DSI_PLL=y | ||
2363 | # CONFIG_OMAP2_DSS_FAKE_VSYNC is not set | ||
2364 | CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 | ||
2365 | CONFIG_FB_OMAP2=y | ||
2366 | CONFIG_FB_OMAP2_DEBUG_SUPPORT=y | ||
2367 | CONFIG_FB_OMAP2_NUM_FBS=2 | ||
2368 | |||
2369 | # | ||
2370 | # OMAP2/3 Display Device Drivers | ||
2371 | # | ||
2372 | CONFIG_PANEL_GENERIC_DPI=y | ||
2373 | # CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set | ||
2374 | CONFIG_PANEL_SHARP_LS037V7DW01=y | ||
2375 | CONFIG_PANEL_NEC_NL8048HL11_01B=y | ||
2376 | # CONFIG_PANEL_TAAL is not set | ||
2377 | CONFIG_PANEL_TPO_TD043MTEA1=m | ||
2378 | # CONFIG_BACKLIGHT_LCD_SUPPORT is not set | ||
2379 | CONFIG_BACKLIGHT_CLASS_DEVICE=y | ||
2380 | |||
2381 | # | ||
2382 | # Display device support | ||
2383 | # | ||
2384 | CONFIG_DISPLAY_SUPPORT=y | ||
2385 | |||
2386 | # | ||
2387 | # Display hardware drivers | ||
2388 | # | ||
2389 | |||
2390 | # | ||
2391 | # Console display driver support | ||
2392 | # | ||
2393 | CONFIG_DUMMY_CONSOLE=y | ||
2394 | CONFIG_FRAMEBUFFER_CONSOLE=y | ||
2395 | # CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set | ||
2396 | CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y | ||
2397 | # CONFIG_FONTS is not set | ||
2398 | CONFIG_FONT_8x8=y | ||
2399 | CONFIG_FONT_8x16=y | ||
2400 | CONFIG_LOGO=y | ||
2401 | # CONFIG_LOGO_LINUX_MONO is not set | ||
2402 | # CONFIG_LOGO_LINUX_VGA16 is not set | ||
2403 | CONFIG_LOGO_LINUX_CLUT224=y | ||
2404 | CONFIG_SOUND=y | ||
2405 | CONFIG_SOUND_OSS_CORE=y | ||
2406 | CONFIG_SOUND_OSS_CORE_PRECLAIM=y | ||
2407 | CONFIG_SND=y | ||
2408 | CONFIG_SND_TIMER=y | ||
2409 | CONFIG_SND_PCM=y | ||
2410 | CONFIG_SND_HWDEP=y | ||
2411 | CONFIG_SND_RAWMIDI=y | ||
2412 | CONFIG_SND_JACK=y | ||
2413 | CONFIG_SND_SEQUENCER=m | ||
2414 | # CONFIG_SND_SEQ_DUMMY is not set | ||
2415 | CONFIG_SND_OSSEMUL=y | ||
2416 | CONFIG_SND_MIXER_OSS=y | ||
2417 | CONFIG_SND_PCM_OSS=y | ||
2418 | CONFIG_SND_PCM_OSS_PLUGINS=y | ||
2419 | CONFIG_SND_SEQUENCER_OSS=y | ||
2420 | CONFIG_SND_HRTIMER=m | ||
2421 | CONFIG_SND_SEQ_HRTIMER_DEFAULT=y | ||
2422 | CONFIG_SND_DYNAMIC_MINORS=y | ||
2423 | CONFIG_SND_SUPPORT_OLD_API=y | ||
2424 | CONFIG_SND_VERBOSE_PROCFS=y | ||
2425 | # CONFIG_SND_VERBOSE_PRINTK is not set | ||
2426 | # CONFIG_SND_DEBUG is not set | ||
2427 | CONFIG_SND_RAWMIDI_SEQ=m | ||
2428 | # CONFIG_SND_OPL3_LIB_SEQ is not set | ||
2429 | # CONFIG_SND_OPL4_LIB_SEQ is not set | ||
2430 | # CONFIG_SND_SBAWE_SEQ is not set | ||
2431 | # CONFIG_SND_EMU10K1_SEQ is not set | ||
2432 | CONFIG_SND_DRIVERS=y | ||
2433 | # CONFIG_SND_DUMMY is not set | ||
2434 | CONFIG_SND_ALOOP=m | ||
2435 | # CONFIG_SND_VIRMIDI is not set | ||
2436 | # CONFIG_SND_MTPAV is not set | ||
2437 | # CONFIG_SND_SERIAL_U16550 is not set | ||
2438 | # CONFIG_SND_MPU401 is not set | ||
2439 | # CONFIG_SND_ARM is not set | ||
2440 | CONFIG_SND_SPI=y | ||
2441 | CONFIG_SND_USB=y | ||
2442 | CONFIG_SND_USB_AUDIO=y | ||
2443 | CONFIG_SND_USB_UA101=m | ||
2444 | CONFIG_SND_USB_CAIAQ=m | ||
2445 | CONFIG_SND_USB_CAIAQ_INPUT=y | ||
2446 | CONFIG_SND_USB_6FIRE=m | ||
2447 | CONFIG_SND_SOC=y | ||
2448 | CONFIG_SND_SOC_CACHE_LZO=y | ||
2449 | CONFIG_SND_OMAP_SOC=y | ||
2450 | CONFIG_SND_OMAP_SOC_MCBSP=y | ||
2451 | CONFIG_SND_OMAP_SOC_OVERO=y | ||
2452 | CONFIG_SND_OMAP_SOC_OMAP3EVM=y | ||
2453 | CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y | ||
2454 | CONFIG_SND_OMAP_SOC_ZOOM2=y | ||
2455 | CONFIG_SND_SOC_I2C_AND_SPI=y | ||
2456 | # CONFIG_SND_SOC_ALL_CODECS is not set | ||
2457 | CONFIG_SND_SOC_TWL4030=y | ||
2458 | # CONFIG_SOUND_PRIME is not set | ||
2459 | CONFIG_HID_SUPPORT=y | ||
2460 | CONFIG_HID=y | ||
2461 | # CONFIG_HIDRAW is not set | ||
2462 | |||
2463 | # | ||
2464 | # USB Input Devices | ||
2465 | # | ||
2466 | CONFIG_USB_HID=y | ||
2467 | # CONFIG_HID_PID is not set | ||
2468 | # CONFIG_USB_HIDDEV is not set | ||
2469 | |||
2470 | # | ||
2471 | # Special HID drivers | ||
2472 | # | ||
2473 | # CONFIG_HID_3M_PCT is not set | ||
2474 | CONFIG_HID_A4TECH=y | ||
2475 | CONFIG_HID_ACRUX=m | ||
2476 | # CONFIG_HID_ACRUX_FF is not set | ||
2477 | CONFIG_HID_APPLE=y | ||
2478 | CONFIG_HID_BELKIN=y | ||
2479 | # CONFIG_HID_CANDO is not set | ||
2480 | CONFIG_HID_CHERRY=y | ||
2481 | CONFIG_HID_CHICONY=y | ||
2482 | # CONFIG_HID_PRODIKEYS is not set | ||
2483 | CONFIG_HID_CYPRESS=y | ||
2484 | # CONFIG_HID_DRAGONRISE is not set | ||
2485 | CONFIG_HID_EMS_FF=m | ||
2486 | # CONFIG_HID_ELECOM is not set | ||
2487 | CONFIG_HID_EZKEY=y | ||
2488 | CONFIG_HID_KEYTOUCH=m | ||
2489 | # CONFIG_HID_KYE is not set | ||
2490 | CONFIG_HID_UCLOGIC=m | ||
2491 | CONFIG_HID_WALTOP=m | ||
2492 | CONFIG_HID_GYRATION=y | ||
2493 | # CONFIG_HID_TWINHAN is not set | ||
2494 | # CONFIG_HID_KENSINGTON is not set | ||
2495 | CONFIG_HID_LCPOWER=m | ||
2496 | CONFIG_HID_LOGITECH=y | ||
2497 | # CONFIG_LOGITECH_FF is not set | ||
2498 | # CONFIG_LOGIRUMBLEPAD2_FF is not set | ||
2499 | # CONFIG_LOGIG940_FF is not set | ||
2500 | # CONFIG_LOGIWII_FF is not set | ||
2501 | CONFIG_HID_MAGICMOUSE=m | ||
2502 | CONFIG_HID_MICROSOFT=y | ||
2503 | # CONFIG_HID_MOSART is not set | ||
2504 | CONFIG_HID_MONTEREY=y | ||
2505 | CONFIG_HID_MULTITOUCH=m | ||
2506 | CONFIG_HID_NTRIG=y | ||
2507 | # CONFIG_HID_ORTEK is not set | ||
2508 | CONFIG_HID_PANTHERLORD=y | ||
2509 | # CONFIG_PANTHERLORD_FF is not set | ||
2510 | CONFIG_HID_PETALYNX=y | ||
2511 | CONFIG_HID_PICOLCD=m | ||
2512 | CONFIG_HID_PICOLCD_FB=y | ||
2513 | CONFIG_HID_PICOLCD_BACKLIGHT=y | ||
2514 | CONFIG_HID_PICOLCD_LEDS=y | ||
2515 | CONFIG_HID_QUANTA=m | ||
2516 | CONFIG_HID_ROCCAT=m | ||
2517 | CONFIG_HID_ROCCAT_COMMON=m | ||
2518 | CONFIG_HID_ROCCAT_ARVO=m | ||
2519 | CONFIG_HID_ROCCAT_KONE=m | ||
2520 | CONFIG_HID_ROCCAT_KONEPLUS=m | ||
2521 | CONFIG_HID_ROCCAT_KOVAPLUS=m | ||
2522 | # CONFIG_HID_ROCCAT_PYRA is not set | ||
2523 | CONFIG_HID_SAMSUNG=y | ||
2524 | CONFIG_HID_SONY=y | ||
2525 | CONFIG_HID_STANTUM=m | ||
2526 | CONFIG_HID_SUNPLUS=y | ||
2527 | # CONFIG_HID_GREENASIA is not set | ||
2528 | # CONFIG_HID_SMARTJOYPLUS is not set | ||
2529 | CONFIG_HID_TOPSEED=y | ||
2530 | # CONFIG_HID_THRUSTMASTER is not set | ||
2531 | # CONFIG_HID_WACOM is not set | ||
2532 | # CONFIG_HID_ZEROPLUS is not set | ||
2533 | # CONFIG_HID_ZYDACRON is not set | ||
2534 | CONFIG_USB_SUPPORT=y | ||
2535 | CONFIG_USB_ARCH_HAS_HCD=y | ||
2536 | CONFIG_USB_ARCH_HAS_OHCI=y | ||
2537 | CONFIG_USB_ARCH_HAS_EHCI=y | ||
2538 | CONFIG_USB=y | ||
2539 | # CONFIG_USB_DEBUG is not set | ||
2540 | CONFIG_USB_ANNOUNCE_NEW_DEVICES=y | ||
2541 | |||
2542 | # | ||
2543 | # Miscellaneous USB options | ||
2544 | # | ||
2545 | CONFIG_USB_DEVICEFS=y | ||
2546 | CONFIG_USB_DEVICE_CLASS=y | ||
2547 | # CONFIG_USB_DYNAMIC_MINORS is not set | ||
2548 | CONFIG_USB_SUSPEND=y | ||
2549 | CONFIG_USB_OTG=y | ||
2550 | # CONFIG_USB_OTG_WHITELIST is not set | ||
2551 | # CONFIG_USB_OTG_BLACKLIST_HUB is not set | ||
2552 | CONFIG_USB_MON=y | ||
2553 | # CONFIG_USB_WUSB is not set | ||
2554 | # CONFIG_USB_WUSB_CBAF is not set | ||
2555 | |||
2556 | # | ||
2557 | # USB Host Controller Drivers | ||
2558 | # | ||
2559 | # CONFIG_USB_C67X00_HCD is not set | ||
2560 | CONFIG_USB_EHCI_HCD=y | ||
2561 | # CONFIG_USB_EHCI_ROOT_HUB_TT is not set | ||
2562 | CONFIG_USB_EHCI_TT_NEWSCHED=y | ||
2563 | CONFIG_USB_EHCI_HCD_OMAP=y | ||
2564 | # CONFIG_USB_OXU210HP_HCD is not set | ||
2565 | # CONFIG_USB_ISP116X_HCD is not set | ||
2566 | # CONFIG_USB_ISP1760_HCD is not set | ||
2567 | # CONFIG_USB_ISP1362_HCD is not set | ||
2568 | # CONFIG_USB_OHCI_HCD is not set | ||
2569 | # CONFIG_USB_U132_HCD is not set | ||
2570 | # CONFIG_USB_SL811_HCD is not set | ||
2571 | # CONFIG_USB_R8A66597_HCD is not set | ||
2572 | # CONFIG_USB_HWA_HCD is not set | ||
2573 | CONFIG_USB_MUSB_HDRC=y | ||
2574 | # CONFIG_USB_MUSB_TUSB6010 is not set | ||
2575 | CONFIG_USB_MUSB_OMAP2PLUS=y | ||
2576 | # CONFIG_USB_MUSB_AM35X is not set | ||
2577 | # CONFIG_USB_MUSB_HOST is not set | ||
2578 | # CONFIG_USB_MUSB_PERIPHERAL is not set | ||
2579 | CONFIG_USB_MUSB_OTG=y | ||
2580 | CONFIG_USB_GADGET_MUSB_HDRC=y | ||
2581 | CONFIG_USB_MUSB_HDRC_HCD=y | ||
2582 | # CONFIG_MUSB_PIO_ONLY is not set | ||
2583 | CONFIG_USB_INVENTRA_DMA=y | ||
2584 | # CONFIG_USB_TI_CPPI_DMA is not set | ||
2585 | # CONFIG_USB_MUSB_DEBUG is not set | ||
2586 | |||
2587 | # | ||
2588 | # USB Device Class drivers | ||
2589 | # | ||
2590 | CONFIG_USB_ACM=m | ||
2591 | CONFIG_USB_PRINTER=m | ||
2592 | CONFIG_USB_WDM=m | ||
2593 | CONFIG_USB_TMC=m | ||
2594 | |||
2595 | # | ||
2596 | # NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may | ||
2597 | # | ||
2598 | |||
2599 | # | ||
2600 | # also be needed; see USB_STORAGE Help for more info | ||
2601 | # | ||
2602 | CONFIG_USB_STORAGE=y | ||
2603 | # CONFIG_USB_STORAGE_DEBUG is not set | ||
2604 | CONFIG_USB_STORAGE_REALTEK=m | ||
2605 | # CONFIG_USB_STORAGE_DATAFAB is not set | ||
2606 | # CONFIG_USB_STORAGE_FREECOM is not set | ||
2607 | # CONFIG_USB_STORAGE_ISD200 is not set | ||
2608 | # CONFIG_USB_STORAGE_USBAT is not set | ||
2609 | # CONFIG_USB_STORAGE_SDDR09 is not set | ||
2610 | # CONFIG_USB_STORAGE_SDDR55 is not set | ||
2611 | # CONFIG_USB_STORAGE_JUMPSHOT is not set | ||
2612 | # CONFIG_USB_STORAGE_ALAUDA is not set | ||
2613 | # CONFIG_USB_STORAGE_ONETOUCH is not set | ||
2614 | # CONFIG_USB_STORAGE_KARMA is not set | ||
2615 | # CONFIG_USB_STORAGE_CYPRESS_ATACB is not set | ||
2616 | CONFIG_USB_STORAGE_ENE_UB6250=m | ||
2617 | CONFIG_USB_UAS=m | ||
2618 | # CONFIG_USB_LIBUSUAL is not set | ||
2619 | |||
2620 | # | ||
2621 | # USB Imaging devices | ||
2622 | # | ||
2623 | # CONFIG_USB_MDC800 is not set | ||
2624 | # CONFIG_USB_MICROTEK is not set | ||
2625 | |||
2626 | # | ||
2627 | # USB port drivers | ||
2628 | # | ||
2629 | CONFIG_USB_SERIAL=m | ||
2630 | CONFIG_USB_EZUSB=y | ||
2631 | CONFIG_USB_SERIAL_GENERIC=y | ||
2632 | CONFIG_USB_SERIAL_AIRCABLE=m | ||
2633 | CONFIG_USB_SERIAL_ARK3116=m | ||
2634 | CONFIG_USB_SERIAL_BELKIN=m | ||
2635 | CONFIG_USB_SERIAL_CH341=m | ||
2636 | CONFIG_USB_SERIAL_WHITEHEAT=n | ||
2637 | CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m | ||
2638 | # CONFIG_USB_SERIAL_CP210X is not set | ||
2639 | CONFIG_USB_SERIAL_CYPRESS_M8=m | ||
2640 | CONFIG_USB_SERIAL_EMPEG=m | ||
2641 | CONFIG_USB_SERIAL_FTDI_SIO=m | ||
2642 | CONFIG_USB_SERIAL_FUNSOFT=m | ||
2643 | CONFIG_USB_SERIAL_VISOR=m | ||
2644 | CONFIG_USB_SERIAL_IPAQ=m | ||
2645 | CONFIG_USB_SERIAL_IR=m | ||
2646 | CONFIG_USB_SERIAL_EDGEPORT=m | ||
2647 | CONFIG_USB_SERIAL_EDGEPORT_TI=m | ||
2648 | CONFIG_USB_SERIAL_GARMIN=m | ||
2649 | CONFIG_USB_SERIAL_IPW=m | ||
2650 | CONFIG_USB_SERIAL_IUU=m | ||
2651 | CONFIG_USB_SERIAL_KEYSPAN_PDA=m | ||
2652 | CONFIG_USB_SERIAL_KEYSPAN=m | ||
2653 | CONFIG_USB_SERIAL_KEYSPAN_MPR=y | ||
2654 | CONFIG_USB_SERIAL_KEYSPAN_USA28=y | ||
2655 | CONFIG_USB_SERIAL_KEYSPAN_USA28X=y | ||
2656 | CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y | ||
2657 | CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y | ||
2658 | CONFIG_USB_SERIAL_KEYSPAN_USA19=y | ||
2659 | CONFIG_USB_SERIAL_KEYSPAN_USA18X=y | ||
2660 | CONFIG_USB_SERIAL_KEYSPAN_USA19W=y | ||
2661 | CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y | ||
2662 | CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y | ||
2663 | CONFIG_USB_SERIAL_KEYSPAN_USA49W=y | ||
2664 | CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y | ||
2665 | CONFIG_USB_SERIAL_KLSI=m | ||
2666 | CONFIG_USB_SERIAL_KOBIL_SCT=m | ||
2667 | CONFIG_USB_SERIAL_MCT_U232=m | ||
2668 | CONFIG_USB_SERIAL_MOS7720=m | ||
2669 | CONFIG_USB_SERIAL_MOS7840=m | ||
2670 | CONFIG_USB_SERIAL_MOTOROLA=m | ||
2671 | CONFIG_USB_SERIAL_NAVMAN=m | ||
2672 | CONFIG_USB_SERIAL_PL2303=m | ||
2673 | CONFIG_USB_SERIAL_OTI6858=m | ||
2674 | CONFIG_USB_SERIAL_QCAUX=m | ||
2675 | # CONFIG_USB_SERIAL_QUALCOMM is not set | ||
2676 | CONFIG_USB_SERIAL_SPCP8X5=m | ||
2677 | CONFIG_USB_SERIAL_HP4X=m | ||
2678 | CONFIG_USB_SERIAL_SAFE=m | ||
2679 | # CONFIG_USB_SERIAL_SAFE_PADDED is not set | ||
2680 | CONFIG_USB_SERIAL_SAMBA=m | ||
2681 | CONFIG_USB_SERIAL_SIEMENS_MPI=m | ||
2682 | CONFIG_USB_SERIAL_SIERRAWIRELESS=m | ||
2683 | # CONFIG_USB_SERIAL_SYMBOL is not set | ||
2684 | CONFIG_USB_SERIAL_TI=n | ||
2685 | CONFIG_USB_SERIAL_CYBERJACK=m | ||
2686 | CONFIG_USB_SERIAL_XIRCOM=n | ||
2687 | # CONFIG_USB_SERIAL_OPTION is not set | ||
2688 | CONFIG_USB_SERIAL_OMNINET=m | ||
2689 | CONFIG_USB_SERIAL_OPTICON=m | ||
2690 | CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m | ||
2691 | CONFIG_USB_SERIAL_ZIO=m | ||
2692 | CONFIG_USB_SERIAL_SSU100=m | ||
2693 | CONFIG_USB_SERIAL_DEBUG=m | ||
2694 | |||
2695 | # | ||
2696 | # USB Miscellaneous drivers | ||
2697 | # | ||
2698 | CONFIG_USB_EMI62=m | ||
2699 | CONFIG_USB_EMI26=m | ||
2700 | # CONFIG_USB_ADUTUX is not set | ||
2701 | # CONFIG_USB_SEVSEG is not set | ||
2702 | # CONFIG_USB_RIO500 is not set | ||
2703 | CONFIG_USB_LEGOTOWER=m | ||
2704 | CONFIG_USB_LCD=m | ||
2705 | CONFIG_USB_LED=m | ||
2706 | CONFIG_USB_CYPRESS_CY7C63=m | ||
2707 | CONFIG_USB_CYTHERM=m | ||
2708 | CONFIG_USB_IDMOUSE=m | ||
2709 | CONFIG_USB_FTDI_ELAN=m | ||
2710 | # CONFIG_USB_APPLEDISPLAY is not set | ||
2711 | CONFIG_USB_SISUSBVGA=m | ||
2712 | CONFIG_USB_SISUSBVGA_CON=y | ||
2713 | CONFIG_USB_LD=m | ||
2714 | CONFIG_USB_TRANCEVIBRATOR=m | ||
2715 | # CONFIG_USB_IOWARRIOR is not set | ||
2716 | CONFIG_USB_TEST=m | ||
2717 | # CONFIG_USB_ISIGHTFW is not set | ||
2718 | CONFIG_USB_YUREX=m | ||
2719 | CONFIG_USB_ATM=m | ||
2720 | CONFIG_USB_SPEEDTOUCH=m | ||
2721 | CONFIG_USB_CXACRU=m | ||
2722 | CONFIG_USB_UEAGLEATM=m | ||
2723 | CONFIG_USB_XUSBATM=m | ||
2724 | CONFIG_USB_GADGET=y | ||
2725 | # CONFIG_USB_GADGET_DEBUG is not set | ||
2726 | # CONFIG_USB_GADGET_DEBUG_FILES is not set | ||
2727 | CONFIG_USB_GADGET_DEBUG_FS=y | ||
2728 | CONFIG_USB_GADGET_VBUS_DRAW=480 | ||
2729 | CONFIG_USB_GADGET_SELECTED=y | ||
2730 | # CONFIG_USB_GADGET_FUSB300 is not set | ||
2731 | # CONFIG_USB_GADGET_OMAP is not set | ||
2732 | # CONFIG_USB_GADGET_R8A66597 is not set | ||
2733 | # CONFIG_USB_GADGET_PXA_U2O is not set | ||
2734 | # CONFIG_USB_GADGET_M66592 is not set | ||
2735 | # CONFIG_USB_GADGET_DUMMY_HCD is not set | ||
2736 | CONFIG_USB_GADGET_DUALSPEED=y | ||
2737 | # CONFIG_USB_ZERO is not set | ||
2738 | # CONFIG_USB_AUDIO is not set | ||
2739 | CONFIG_USB_ETH=m | ||
2740 | CONFIG_USB_ETH_RNDIS=y | ||
2741 | # CONFIG_USB_ETH_EEM is not set | ||
2742 | CONFIG_USB_G_NCM=m | ||
2743 | # CONFIG_USB_GADGETFS is not set | ||
2744 | CONFIG_USB_FUNCTIONFS=m | ||
2745 | # CONFIG_USB_FUNCTIONFS_ETH is not set | ||
2746 | CONFIG_USB_FUNCTIONFS_RNDIS=y | ||
2747 | # CONFIG_USB_FUNCTIONFS_GENERIC is not set | ||
2748 | # CONFIG_USB_FILE_STORAGE is not set | ||
2749 | # CONFIG_USB_MASS_STORAGE is not set | ||
2750 | # CONFIG_USB_G_SERIAL is not set | ||
2751 | # CONFIG_USB_MIDI_GADGET is not set | ||
2752 | # CONFIG_USB_G_PRINTER is not set | ||
2753 | # CONFIG_USB_CDC_COMPOSITE is not set | ||
2754 | # CONFIG_USB_G_MULTI is not set | ||
2755 | CONFIG_USB_G_HID=m | ||
2756 | CONFIG_USB_G_DBGP=m | ||
2757 | # CONFIG_USB_G_DBGP_PRINTK is not set | ||
2758 | CONFIG_USB_G_DBGP_SERIAL=y | ||
2759 | CONFIG_USB_G_WEBCAM=m | ||
2760 | |||
2761 | # | ||
2762 | # OTG and related infrastructure | ||
2763 | # | ||
2764 | CONFIG_USB_OTG_UTILS=y | ||
2765 | CONFIG_USB_GPIO_VBUS=y | ||
2766 | # CONFIG_ISP1301_OMAP is not set | ||
2767 | # CONFIG_USB_ULPI is not set | ||
2768 | CONFIG_TWL4030_USB=y | ||
2769 | CONFIG_TWL6030_USB=m | ||
2770 | CONFIG_NOP_USB_XCEIV=y | ||
2771 | CONFIG_MMC=y | ||
2772 | # CONFIG_MMC_DEBUG is not set | ||
2773 | CONFIG_MMC_UNSAFE_RESUME=y | ||
2774 | # CONFIG_MMC_CLKGATE is not set | ||
2775 | |||
2776 | # | ||
2777 | # MMC/SD/SDIO Card Drivers | ||
2778 | # | ||
2779 | CONFIG_MMC_BLOCK=y | ||
2780 | CONFIG_MMC_BLOCK_MINORS=8 | ||
2781 | CONFIG_MMC_BLOCK_BOUNCE=y | ||
2782 | CONFIG_SDIO_UART=y | ||
2783 | # CONFIG_MMC_TEST is not set | ||
2784 | |||
2785 | # | ||
2786 | # MMC/SD/SDIO Host Controller Drivers | ||
2787 | # | ||
2788 | # CONFIG_MMC_SDHCI is not set | ||
2789 | # CONFIG_MMC_OMAP is not set | ||
2790 | CONFIG_MMC_OMAP_HS=y | ||
2791 | CONFIG_MMC_SPI=m | ||
2792 | # CONFIG_MMC_DW is not set | ||
2793 | CONFIG_MMC_USHC=m | ||
2794 | # CONFIG_MEMSTICK is not set | ||
2795 | CONFIG_NEW_LEDS=y | ||
2796 | CONFIG_LEDS_CLASS=y | ||
2797 | |||
2798 | # | ||
2799 | # LED drivers | ||
2800 | # | ||
2801 | # CONFIG_LEDS_LM3530 is not set | ||
2802 | # CONFIG_LEDS_PCA9532 is not set | ||
2803 | CONFIG_LEDS_GPIO=y | ||
2804 | CONFIG_LEDS_GPIO_PLATFORM=y | ||
2805 | # CONFIG_LEDS_LP3944 is not set | ||
2806 | CONFIG_LEDS_LP5521=m | ||
2807 | CONFIG_LEDS_LP5523=m | ||
2808 | # CONFIG_LEDS_PCA955X is not set | ||
2809 | # CONFIG_LEDS_DAC124S085 is not set | ||
2810 | CONFIG_LEDS_PWM=m | ||
2811 | CONFIG_LEDS_REGULATOR=m | ||
2812 | # CONFIG_LEDS_BD2802 is not set | ||
2813 | # CONFIG_LEDS_LT3593 is not set | ||
2814 | CONFIG_LEDS_TRIGGERS=y | ||
2815 | |||
2816 | # | ||
2817 | # LED Triggers | ||
2818 | # | ||
2819 | CONFIG_LEDS_TRIGGER_TIMER=m | ||
2820 | CONFIG_LEDS_TRIGGER_HEARTBEAT=y | ||
2821 | CONFIG_LEDS_TRIGGER_BACKLIGHT=m | ||
2822 | CONFIG_LEDS_TRIGGER_GPIO=m | ||
2823 | CONFIG_LEDS_TRIGGER_DEFAULT_ON=m | ||
2824 | |||
2825 | # | ||
2826 | # iptables trigger is under Netfilter config (LED target) | ||
2827 | # | ||
2828 | CONFIG_NFC_DEVICES=y | ||
2829 | CONFIG_PN544_NFC=m | ||
2830 | # CONFIG_ACCESSIBILITY is not set | ||
2831 | CONFIG_RTC_LIB=y | ||
2832 | CONFIG_RTC_CLASS=y | ||
2833 | CONFIG_RTC_HCTOSYS=y | ||
2834 | CONFIG_RTC_HCTOSYS_DEVICE="rtc0" | ||
2835 | # CONFIG_RTC_DEBUG is not set | ||
2836 | |||
2837 | # | ||
2838 | # RTC interfaces | ||
2839 | # | ||
2840 | CONFIG_RTC_INTF_SYSFS=y | ||
2841 | CONFIG_RTC_INTF_PROC=y | ||
2842 | CONFIG_RTC_INTF_DEV=y | ||
2843 | # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set | ||
2844 | # CONFIG_RTC_DRV_TEST is not set | ||
2845 | |||
2846 | # | ||
2847 | # I2C RTC drivers | ||
2848 | # | ||
2849 | CONFIG_RTC_DRV_DS1307=y | ||
2850 | # CONFIG_RTC_DRV_DS1374 is not set | ||
2851 | # CONFIG_RTC_DRV_DS1672 is not set | ||
2852 | # CONFIG_RTC_DRV_DS3232 is not set | ||
2853 | # CONFIG_RTC_DRV_MAX6900 is not set | ||
2854 | # CONFIG_RTC_DRV_RS5C372 is not set | ||
2855 | # CONFIG_RTC_DRV_ISL1208 is not set | ||
2856 | # CONFIG_RTC_DRV_ISL12022 is not set | ||
2857 | # CONFIG_RTC_DRV_X1205 is not set | ||
2858 | # CONFIG_RTC_DRV_PCF8563 is not set | ||
2859 | # CONFIG_RTC_DRV_PCF8583 is not set | ||
2860 | # CONFIG_RTC_DRV_M41T80 is not set | ||
2861 | CONFIG_RTC_DRV_BQ32K=m | ||
2862 | CONFIG_RTC_DRV_TWL4030=m | ||
2863 | # CONFIG_RTC_DRV_S35390A is not set | ||
2864 | # CONFIG_RTC_DRV_FM3130 is not set | ||
2865 | # CONFIG_RTC_DRV_RX8581 is not set | ||
2866 | # CONFIG_RTC_DRV_RX8025 is not set | ||
2867 | |||
2868 | # | ||
2869 | # SPI RTC drivers | ||
2870 | # | ||
2871 | # CONFIG_RTC_DRV_M41T94 is not set | ||
2872 | # CONFIG_RTC_DRV_DS1305 is not set | ||
2873 | # CONFIG_RTC_DRV_DS1390 is not set | ||
2874 | # CONFIG_RTC_DRV_MAX6902 is not set | ||
2875 | # CONFIG_RTC_DRV_R9701 is not set | ||
2876 | # CONFIG_RTC_DRV_RS5C348 is not set | ||
2877 | # CONFIG_RTC_DRV_DS3234 is not set | ||
2878 | # CONFIG_RTC_DRV_PCF2123 is not set | ||
2879 | |||
2880 | # | ||
2881 | # Platform RTC drivers | ||
2882 | # | ||
2883 | # CONFIG_RTC_DRV_CMOS is not set | ||
2884 | # CONFIG_RTC_DRV_DS1286 is not set | ||
2885 | # CONFIG_RTC_DRV_DS1511 is not set | ||
2886 | # CONFIG_RTC_DRV_DS1553 is not set | ||
2887 | # CONFIG_RTC_DRV_DS1742 is not set | ||
2888 | # CONFIG_RTC_DRV_STK17TA8 is not set | ||
2889 | # CONFIG_RTC_DRV_M48T86 is not set | ||
2890 | # CONFIG_RTC_DRV_M48T35 is not set | ||
2891 | # CONFIG_RTC_DRV_M48T59 is not set | ||
2892 | # CONFIG_RTC_DRV_MSM6242 is not set | ||
2893 | # CONFIG_RTC_DRV_BQ4802 is not set | ||
2894 | # CONFIG_RTC_DRV_RP5C01 is not set | ||
2895 | # CONFIG_RTC_DRV_V3020 is not set | ||
2896 | |||
2897 | # | ||
2898 | # on-CPU RTC drivers | ||
2899 | # | ||
2900 | # CONFIG_DMADEVICES is not set | ||
2901 | CONFIG_TIMB_DMA=m | ||
2902 | CONFIG_DMA_ENGINE=y | ||
2903 | # CONFIG_AUXDISPLAY is not set | ||
2904 | CONFIG_UIO=m | ||
2905 | CONFIG_UIO_PDRV=m | ||
2906 | CONFIG_UIO_PDRV_GENIRQ=m | ||
2907 | CONFIG_STAGING=y | ||
2908 | # CONFIG_STAGING_EXCLUDE_BUILD is not set | ||
2909 | # CONFIG_VIDEO_TM6000 is not set | ||
2910 | # CONFIG_USB_IP_COMMON is not set | ||
2911 | CONFIG_W35UND=m | ||
2912 | CONFIG_PRISM2_USB=m | ||
2913 | CONFIG_ECHO=m | ||
2914 | CONFIG_BRCM80211=m | ||
2915 | CONFIG_BRCMFMAC=y | ||
2916 | # CONFIG_BRCMDBG is not set | ||
2917 | CONFIG_RT2870=m | ||
2918 | # CONFIG_COMEDI is not set | ||
2919 | # CONFIG_ASUS_OLED is not set | ||
2920 | CONFIG_R8712U=m | ||
2921 | CONFIG_R8712_AP=y | ||
2922 | # CONFIG_TRANZPORT is not set | ||
2923 | # CONFIG_POHMELFS is not set | ||
2924 | # CONFIG_LINE6_USB is not set | ||
2925 | # CONFIG_USB_SERIAL_QUATECH2 is not set | ||
2926 | # CONFIG_USB_SERIAL_QUATECH_USB2 is not set | ||
2927 | # CONFIG_VT6656 is not set | ||
2928 | # CONFIG_IIO is not set | ||
2929 | CONFIG_XVMALLOC=y | ||
2930 | CONFIG_ZRAM=m | ||
2931 | # CONFIG_ZRAM_DEBUG is not set | ||
2932 | # CONFIG_FB_SM7XX is not set | ||
2933 | # CONFIG_LIRC_STAGING is not set | ||
2934 | # CONFIG_EASYCAP is not set | ||
2935 | # CONFIG_TIDSPBRIDGE is not set | ||
2936 | # CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL is not set | ||
2937 | CONFIG_MACH_NO_WESTBRIDGE=y | ||
2938 | # CONFIG_ATH6K_LEGACY is not set | ||
2939 | CONFIG_USB_ENESTORAGE=m | ||
2940 | CONFIG_BCM_WIMAX=m | ||
2941 | CONFIG_FT1000=m | ||
2942 | CONFIG_FT1000_USB=m | ||
2943 | |||
2944 | # | ||
2945 | # Speakup console speech | ||
2946 | # | ||
2947 | # CONFIG_SPEAKUP is not set | ||
2948 | CONFIG_TOUCHSCREEN_CLEARPAD_TM1217=m | ||
2949 | CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=m | ||
2950 | |||
2951 | # | ||
2952 | # Altera FPGA firmware download module | ||
2953 | # | ||
2954 | # CONFIG_ALTERA_STAPL is not set | ||
2955 | CONFIG_CLKDEV_LOOKUP=y | ||
2956 | |||
2957 | # | ||
2958 | # File systems | ||
2959 | # | ||
2960 | CONFIG_EXT2_FS=y | ||
2961 | # CONFIG_EXT2_FS_XATTR is not set | ||
2962 | # CONFIG_EXT2_FS_XIP is not set | ||
2963 | CONFIG_EXT3_FS=y | ||
2964 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
2965 | # CONFIG_EXT3_FS_XATTR is not set | ||
2966 | CONFIG_EXT4_FS=y | ||
2967 | CONFIG_EXT4_FS_XATTR=y | ||
2968 | # CONFIG_EXT4_FS_POSIX_ACL is not set | ||
2969 | # CONFIG_EXT4_FS_SECURITY is not set | ||
2970 | # CONFIG_EXT4_DEBUG is not set | ||
2971 | CONFIG_JBD=y | ||
2972 | # CONFIG_JBD_DEBUG is not set | ||
2973 | CONFIG_JBD2=y | ||
2974 | # CONFIG_JBD2_DEBUG is not set | ||
2975 | CONFIG_FS_MBCACHE=y | ||
2976 | CONFIG_REISERFS_FS=m | ||
2977 | # CONFIG_REISERFS_CHECK is not set | ||
2978 | CONFIG_REISERFS_PROC_INFO=y | ||
2979 | CONFIG_REISERFS_FS_XATTR=y | ||
2980 | # CONFIG_REISERFS_FS_POSIX_ACL is not set | ||
2981 | # CONFIG_REISERFS_FS_SECURITY is not set | ||
2982 | CONFIG_JFS_FS=m | ||
2983 | # CONFIG_JFS_POSIX_ACL is not set | ||
2984 | # CONFIG_JFS_SECURITY is not set | ||
2985 | # CONFIG_JFS_DEBUG is not set | ||
2986 | # CONFIG_JFS_STATISTICS is not set | ||
2987 | CONFIG_XFS_FS=m | ||
2988 | # CONFIG_XFS_QUOTA is not set | ||
2989 | # CONFIG_XFS_POSIX_ACL is not set | ||
2990 | # CONFIG_XFS_RT is not set | ||
2991 | # CONFIG_XFS_DEBUG is not set | ||
2992 | CONFIG_GFS2_FS=m | ||
2993 | # CONFIG_GFS2_FS_LOCKING_DLM is not set | ||
2994 | CONFIG_OCFS2_FS=m | ||
2995 | CONFIG_OCFS2_FS_O2CB=m | ||
2996 | CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m | ||
2997 | CONFIG_OCFS2_FS_STATS=y | ||
2998 | CONFIG_OCFS2_DEBUG_MASKLOG=y | ||
2999 | # CONFIG_OCFS2_DEBUG_FS is not set | ||
3000 | CONFIG_BTRFS_FS=m | ||
3001 | # CONFIG_BTRFS_FS_POSIX_ACL is not set | ||
3002 | # CONFIG_NILFS2_FS is not set | ||
3003 | CONFIG_FS_POSIX_ACL=y | ||
3004 | CONFIG_EXPORTFS=y | ||
3005 | CONFIG_FILE_LOCKING=y | ||
3006 | CONFIG_FSNOTIFY=y | ||
3007 | CONFIG_DNOTIFY=y | ||
3008 | CONFIG_INOTIFY_USER=y | ||
3009 | CONFIG_FANOTIFY=y | ||
3010 | CONFIG_QUOTA=y | ||
3011 | # CONFIG_QUOTA_NETLINK_INTERFACE is not set | ||
3012 | CONFIG_PRINT_QUOTA_WARNING=y | ||
3013 | # CONFIG_QUOTA_DEBUG is not set | ||
3014 | CONFIG_QUOTA_TREE=y | ||
3015 | # CONFIG_QFMT_V1 is not set | ||
3016 | CONFIG_QFMT_V2=y | ||
3017 | CONFIG_QUOTACTL=y | ||
3018 | CONFIG_AUTOFS4_FS=m | ||
3019 | CONFIG_FUSE_FS=m | ||
3020 | # CONFIG_CUSE is not set | ||
3021 | CONFIG_GENERIC_ACL=y | ||
3022 | |||
3023 | # | ||
3024 | # Caches | ||
3025 | # | ||
3026 | # CONFIG_FSCACHE is not set | ||
3027 | |||
3028 | # | ||
3029 | # CD-ROM/DVD Filesystems | ||
3030 | # | ||
3031 | CONFIG_ISO9660_FS=m | ||
3032 | CONFIG_JOLIET=y | ||
3033 | CONFIG_ZISOFS=y | ||
3034 | CONFIG_UDF_FS=m | ||
3035 | CONFIG_UDF_NLS=y | ||
3036 | |||
3037 | # | ||
3038 | # DOS/FAT/NT Filesystems | ||
3039 | # | ||
3040 | CONFIG_FAT_FS=y | ||
3041 | CONFIG_MSDOS_FS=y | ||
3042 | CONFIG_VFAT_FS=y | ||
3043 | CONFIG_FAT_DEFAULT_CODEPAGE=437 | ||
3044 | CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" | ||
3045 | CONFIG_NTFS_FS=m | ||
3046 | # CONFIG_NTFS_DEBUG is not set | ||
3047 | CONFIG_NTFS_RW=y | ||
3048 | |||
3049 | # | ||
3050 | # Pseudo filesystems | ||
3051 | # | ||
3052 | CONFIG_PROC_FS=y | ||
3053 | CONFIG_PROC_SYSCTL=y | ||
3054 | CONFIG_PROC_PAGE_MONITOR=y | ||
3055 | CONFIG_SYSFS=y | ||
3056 | CONFIG_TMPFS=y | ||
3057 | CONFIG_TMPFS_POSIX_ACL=y | ||
3058 | # CONFIG_HUGETLB_PAGE is not set | ||
3059 | CONFIG_CONFIGFS_FS=m | ||
3060 | CONFIG_MISC_FILESYSTEMS=y | ||
3061 | CONFIG_ADFS_FS=m | ||
3062 | # CONFIG_ADFS_FS_RW is not set | ||
3063 | CONFIG_AFFS_FS=m | ||
3064 | # CONFIG_ECRYPT_FS is not set | ||
3065 | CONFIG_UNION_FS=m | ||
3066 | CONFIG_UNION_FS_XATTR=y | ||
3067 | # CONFIG_UNION_FS_DEBUG is not set | ||
3068 | CONFIG_HFS_FS=m | ||
3069 | CONFIG_HFSPLUS_FS=m | ||
3070 | CONFIG_BEFS_FS=m | ||
3071 | # CONFIG_BEFS_DEBUG is not set | ||
3072 | CONFIG_BFS_FS=m | ||
3073 | CONFIG_EFS_FS=m | ||
3074 | CONFIG_JFFS2_FS=y | ||
3075 | CONFIG_JFFS2_FS_DEBUG=0 | ||
3076 | CONFIG_JFFS2_FS_WRITEBUFFER=y | ||
3077 | # CONFIG_JFFS2_FS_WBUF_VERIFY is not set | ||
3078 | CONFIG_JFFS2_SUMMARY=y | ||
3079 | CONFIG_JFFS2_FS_XATTR=y | ||
3080 | CONFIG_JFFS2_FS_POSIX_ACL=y | ||
3081 | CONFIG_JFFS2_FS_SECURITY=y | ||
3082 | CONFIG_JFFS2_COMPRESSION_OPTIONS=y | ||
3083 | CONFIG_JFFS2_ZLIB=y | ||
3084 | CONFIG_JFFS2_LZO=y | ||
3085 | CONFIG_JFFS2_RTIME=y | ||
3086 | CONFIG_JFFS2_RUBIN=y | ||
3087 | # CONFIG_JFFS2_CMODE_NONE is not set | ||
3088 | # CONFIG_JFFS2_CMODE_PRIORITY is not set | ||
3089 | # CONFIG_JFFS2_CMODE_SIZE is not set | ||
3090 | CONFIG_JFFS2_CMODE_FAVOURLZO=y | ||
3091 | CONFIG_UBIFS_FS=y | ||
3092 | CONFIG_UBIFS_FS_XATTR=y | ||
3093 | CONFIG_UBIFS_FS_ADVANCED_COMPR=y | ||
3094 | CONFIG_UBIFS_FS_LZO=y | ||
3095 | CONFIG_UBIFS_FS_ZLIB=y | ||
3096 | # CONFIG_UBIFS_FS_DEBUG is not set | ||
3097 | CONFIG_LOGFS=m | ||
3098 | CONFIG_CRAMFS=m | ||
3099 | CONFIG_SQUASHFS=y | ||
3100 | # CONFIG_SQUASHFS_XATTR is not set | ||
3101 | CONFIG_SQUASHFS_LZO=y | ||
3102 | CONFIG_SQUASHFS_XZ=y | ||
3103 | # CONFIG_SQUASHFS_EMBEDDED is not set | ||
3104 | CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 | ||
3105 | CONFIG_VXFS_FS=m | ||
3106 | CONFIG_MINIX_FS=m | ||
3107 | CONFIG_OMFS_FS=m | ||
3108 | CONFIG_HPFS_FS=m | ||
3109 | CONFIG_QNX4FS_FS=m | ||
3110 | CONFIG_ROMFS_FS=m | ||
3111 | CONFIG_ROMFS_BACKED_BY_BLOCK=y | ||
3112 | # CONFIG_ROMFS_BACKED_BY_MTD is not set | ||
3113 | # CONFIG_ROMFS_BACKED_BY_BOTH is not set | ||
3114 | CONFIG_ROMFS_ON_BLOCK=y | ||
3115 | CONFIG_PSTORE=y | ||
3116 | CONFIG_SYSV_FS=m | ||
3117 | CONFIG_UFS_FS=m | ||
3118 | # CONFIG_UFS_FS_WRITE is not set | ||
3119 | # CONFIG_UFS_DEBUG is not set | ||
3120 | CONFIG_NETWORK_FILESYSTEMS=y | ||
3121 | CONFIG_NFS_FS=y | ||
3122 | CONFIG_NFS_V3=y | ||
3123 | # CONFIG_NFS_V3_ACL is not set | ||
3124 | CONFIG_NFS_V4=y | ||
3125 | # CONFIG_NFS_V4_1 is not set | ||
3126 | CONFIG_ROOT_NFS=y | ||
3127 | # CONFIG_NFS_USE_LEGACY_DNS is not set | ||
3128 | CONFIG_NFS_USE_KERNEL_DNS=y | ||
3129 | # CONFIG_NFS_USE_NEW_IDMAPPER is not set | ||
3130 | CONFIG_NFSD=m | ||
3131 | CONFIG_NFSD_DEPRECATED=y | ||
3132 | CONFIG_NFSD_V2_ACL=y | ||
3133 | CONFIG_NFSD_V3=y | ||
3134 | CONFIG_NFSD_V3_ACL=y | ||
3135 | CONFIG_NFSD_V4=y | ||
3136 | CONFIG_LOCKD=y | ||
3137 | CONFIG_LOCKD_V4=y | ||
3138 | CONFIG_NFS_ACL_SUPPORT=m | ||
3139 | CONFIG_NFS_COMMON=y | ||
3140 | CONFIG_SUNRPC=y | ||
3141 | CONFIG_SUNRPC_GSS=y | ||
3142 | CONFIG_RPCSEC_GSS_KRB5=m | ||
3143 | CONFIG_CEPH_FS=m | ||
3144 | CONFIG_CIFS=m | ||
3145 | CONFIG_CIFS_STATS=y | ||
3146 | CONFIG_CIFS_STATS2=y | ||
3147 | # CONFIG_CIFS_WEAK_PW_HASH is not set | ||
3148 | # CONFIG_CIFS_UPCALL is not set | ||
3149 | # CONFIG_CIFS_XATTR is not set | ||
3150 | # CONFIG_CIFS_DEBUG2 is not set | ||
3151 | # CONFIG_CIFS_DFS_UPCALL is not set | ||
3152 | CONFIG_CIFS_EXPERIMENTAL=y | ||
3153 | CONFIG_NCP_FS=m | ||
3154 | # CONFIG_NCPFS_PACKET_SIGNING is not set | ||
3155 | # CONFIG_NCPFS_IOCTL_LOCKING is not set | ||
3156 | # CONFIG_NCPFS_STRONG is not set | ||
3157 | # CONFIG_NCPFS_NFS_NS is not set | ||
3158 | # CONFIG_NCPFS_OS2_NS is not set | ||
3159 | # CONFIG_NCPFS_SMALLDOS is not set | ||
3160 | # CONFIG_NCPFS_NLS is not set | ||
3161 | # CONFIG_NCPFS_EXTRAS is not set | ||
3162 | CONFIG_CODA_FS=m | ||
3163 | CONFIG_AFS_FS=m | ||
3164 | # CONFIG_AFS_DEBUG is not set | ||
3165 | CONFIG_9P_FS=m | ||
3166 | # CONFIG_9P_FS_POSIX_ACL is not set | ||
3167 | |||
3168 | # | ||
3169 | # Partition Types | ||
3170 | # | ||
3171 | CONFIG_PARTITION_ADVANCED=y | ||
3172 | # CONFIG_ACORN_PARTITION is not set | ||
3173 | # CONFIG_OSF_PARTITION is not set | ||
3174 | # CONFIG_AMIGA_PARTITION is not set | ||
3175 | # CONFIG_ATARI_PARTITION is not set | ||
3176 | CONFIG_MAC_PARTITION=y | ||
3177 | CONFIG_MSDOS_PARTITION=y | ||
3178 | CONFIG_BSD_DISKLABEL=y | ||
3179 | CONFIG_MINIX_SUBPARTITION=y | ||
3180 | CONFIG_SOLARIS_X86_PARTITION=y | ||
3181 | # CONFIG_UNIXWARE_DISKLABEL is not set | ||
3182 | CONFIG_LDM_PARTITION=y | ||
3183 | CONFIG_LDM_DEBUG=y | ||
3184 | # CONFIG_SGI_PARTITION is not set | ||
3185 | # CONFIG_ULTRIX_PARTITION is not set | ||
3186 | # CONFIG_SUN_PARTITION is not set | ||
3187 | # CONFIG_KARMA_PARTITION is not set | ||
3188 | CONFIG_EFI_PARTITION=y | ||
3189 | # CONFIG_SYSV68_PARTITION is not set | ||
3190 | CONFIG_NLS=y | ||
3191 | CONFIG_NLS_DEFAULT="iso8859-1" | ||
3192 | CONFIG_NLS_CODEPAGE_437=y | ||
3193 | CONFIG_NLS_CODEPAGE_737=m | ||
3194 | CONFIG_NLS_CODEPAGE_775=m | ||
3195 | CONFIG_NLS_CODEPAGE_850=m | ||
3196 | CONFIG_NLS_CODEPAGE_852=m | ||
3197 | CONFIG_NLS_CODEPAGE_855=m | ||
3198 | CONFIG_NLS_CODEPAGE_857=m | ||
3199 | CONFIG_NLS_CODEPAGE_860=m | ||
3200 | CONFIG_NLS_CODEPAGE_861=m | ||
3201 | CONFIG_NLS_CODEPAGE_862=m | ||
3202 | CONFIG_NLS_CODEPAGE_863=m | ||
3203 | CONFIG_NLS_CODEPAGE_864=m | ||
3204 | CONFIG_NLS_CODEPAGE_865=m | ||
3205 | CONFIG_NLS_CODEPAGE_866=m | ||
3206 | CONFIG_NLS_CODEPAGE_869=m | ||
3207 | CONFIG_NLS_CODEPAGE_936=m | ||
3208 | CONFIG_NLS_CODEPAGE_950=m | ||
3209 | CONFIG_NLS_CODEPAGE_932=m | ||
3210 | CONFIG_NLS_CODEPAGE_949=m | ||
3211 | CONFIG_NLS_CODEPAGE_874=m | ||
3212 | CONFIG_NLS_ISO8859_8=m | ||
3213 | CONFIG_NLS_CODEPAGE_1250=m | ||
3214 | CONFIG_NLS_CODEPAGE_1251=m | ||
3215 | CONFIG_NLS_ASCII=m | ||
3216 | CONFIG_NLS_ISO8859_1=y | ||
3217 | CONFIG_NLS_ISO8859_2=m | ||
3218 | CONFIG_NLS_ISO8859_3=m | ||
3219 | CONFIG_NLS_ISO8859_4=m | ||
3220 | CONFIG_NLS_ISO8859_5=m | ||
3221 | CONFIG_NLS_ISO8859_6=m | ||
3222 | CONFIG_NLS_ISO8859_7=m | ||
3223 | CONFIG_NLS_ISO8859_9=m | ||
3224 | CONFIG_NLS_ISO8859_13=m | ||
3225 | CONFIG_NLS_ISO8859_14=m | ||
3226 | CONFIG_NLS_ISO8859_15=m | ||
3227 | CONFIG_NLS_KOI8_R=m | ||
3228 | CONFIG_NLS_KOI8_U=m | ||
3229 | CONFIG_NLS_UTF8=y | ||
3230 | CONFIG_DLM=m | ||
3231 | # CONFIG_DLM_DEBUG is not set | ||
3232 | |||
3233 | # | ||
3234 | # Kernel hacking | ||
3235 | # | ||
3236 | CONFIG_PRINTK_TIME=y | ||
3237 | CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 | ||
3238 | CONFIG_ENABLE_WARN_DEPRECATED=y | ||
3239 | CONFIG_ENABLE_MUST_CHECK=y | ||
3240 | CONFIG_FRAME_WARN=1024 | ||
3241 | CONFIG_MAGIC_SYSRQ=y | ||
3242 | # CONFIG_STRIP_ASM_SYMS is not set | ||
3243 | # CONFIG_UNUSED_SYMBOLS is not set | ||
3244 | CONFIG_DEBUG_FS=y | ||
3245 | # CONFIG_HEADERS_CHECK is not set | ||
3246 | # CONFIG_DEBUG_SECTION_MISMATCH is not set | ||
3247 | CONFIG_DEBUG_KERNEL=y | ||
3248 | # CONFIG_DEBUG_SHIRQ is not set | ||
3249 | # CONFIG_LOCKUP_DETECTOR is not set | ||
3250 | # CONFIG_HARDLOCKUP_DETECTOR is not set | ||
3251 | CONFIG_DETECT_HUNG_TASK=y | ||
3252 | # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set | ||
3253 | CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 | ||
3254 | CONFIG_SCHED_DEBUG=y | ||
3255 | CONFIG_SCHEDSTATS=y | ||
3256 | CONFIG_TIMER_STATS=y | ||
3257 | # CONFIG_DEBUG_OBJECTS is not set | ||
3258 | # CONFIG_DEBUG_SLAB is not set | ||
3259 | # CONFIG_DEBUG_KMEMLEAK is not set | ||
3260 | CONFIG_DEBUG_PREEMPT=y | ||
3261 | # CONFIG_DEBUG_RT_MUTEXES is not set | ||
3262 | # CONFIG_RT_MUTEX_TESTER is not set | ||
3263 | # CONFIG_DEBUG_SPINLOCK is not set | ||
3264 | CONFIG_DEBUG_MUTEXES=y | ||
3265 | # CONFIG_DEBUG_LOCK_ALLOC is not set | ||
3266 | # CONFIG_PROVE_LOCKING is not set | ||
3267 | # CONFIG_SPARSE_RCU_POINTER is not set | ||
3268 | # CONFIG_LOCK_STAT is not set | ||
3269 | # CONFIG_DEBUG_SPINLOCK_SLEEP is not set | ||
3270 | # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set | ||
3271 | # CONFIG_DEBUG_KOBJECT is not set | ||
3272 | # CONFIG_DEBUG_BUGVERBOSE is not set | ||
3273 | # CONFIG_DEBUG_INFO is not set | ||
3274 | # CONFIG_DEBUG_VM is not set | ||
3275 | # CONFIG_DEBUG_WRITECOUNT is not set | ||
3276 | # CONFIG_DEBUG_MEMORY_INIT is not set | ||
3277 | # CONFIG_DEBUG_LIST is not set | ||
3278 | # CONFIG_TEST_LIST_SORT is not set | ||
3279 | # CONFIG_DEBUG_SG is not set | ||
3280 | # CONFIG_DEBUG_NOTIFIERS is not set | ||
3281 | # CONFIG_DEBUG_CREDENTIALS is not set | ||
3282 | # CONFIG_BOOT_PRINTK_DELAY is not set | ||
3283 | # CONFIG_RCU_TORTURE_TEST is not set | ||
3284 | # CONFIG_RCU_CPU_STALL_DETECTOR is not set | ||
3285 | # CONFIG_BACKTRACE_SELF_TEST is not set | ||
3286 | # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set | ||
3287 | # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set | ||
3288 | # CONFIG_LKDTM is not set | ||
3289 | # CONFIG_FAULT_INJECTION is not set | ||
3290 | # CONFIG_LATENCYTOP is not set | ||
3291 | # CONFIG_SYSCTL_SYSCALL_CHECK is not set | ||
3292 | # CONFIG_DEBUG_PAGEALLOC is not set | ||
3293 | CONFIG_HAVE_FUNCTION_TRACER=y | ||
3294 | CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y | ||
3295 | CONFIG_HAVE_DYNAMIC_FTRACE=y | ||
3296 | CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y | ||
3297 | CONFIG_HAVE_C_RECORDMCOUNT=y | ||
3298 | CONFIG_RING_BUFFER=y | ||
3299 | CONFIG_RING_BUFFER_ALLOW_SWAP=y | ||
3300 | CONFIG_TRACING_SUPPORT=y | ||
3301 | CONFIG_FTRACE=y | ||
3302 | # CONFIG_FUNCTION_TRACER is not set | ||
3303 | # CONFIG_IRQSOFF_TRACER is not set | ||
3304 | # CONFIG_PREEMPT_TRACER is not set | ||
3305 | # CONFIG_SCHED_TRACER is not set | ||
3306 | # CONFIG_ENABLE_DEFAULT_TRACERS is not set | ||
3307 | CONFIG_BRANCH_PROFILE_NONE=y | ||
3308 | # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set | ||
3309 | # CONFIG_PROFILE_ALL_BRANCHES is not set | ||
3310 | # CONFIG_STACK_TRACER is not set | ||
3311 | # CONFIG_BLK_DEV_IO_TRACE is not set | ||
3312 | # CONFIG_RING_BUFFER_BENCHMARK is not set | ||
3313 | # CONFIG_DYNAMIC_DEBUG is not set | ||
3314 | # CONFIG_DMA_API_DEBUG is not set | ||
3315 | # CONFIG_ATOMIC64_SELFTEST is not set | ||
3316 | # CONFIG_ASYNC_RAID6_TEST is not set | ||
3317 | # CONFIG_SAMPLES is not set | ||
3318 | CONFIG_HAVE_ARCH_KGDB=y | ||
3319 | # CONFIG_KGDB is not set | ||
3320 | # CONFIG_TEST_KSTRTOX is not set | ||
3321 | # CONFIG_STRICT_DEVMEM is not set | ||
3322 | CONFIG_ARM_UNWIND=y | ||
3323 | # CONFIG_DEBUG_USER is not set | ||
3324 | # CONFIG_DEBUG_STACK_USAGE is not set | ||
3325 | # CONFIG_DEBUG_LL is not set | ||
3326 | # CONFIG_OC_ETM is not set | ||
3327 | |||
3328 | # | ||
3329 | # Security options | ||
3330 | # | ||
3331 | CONFIG_KEYS=y | ||
3332 | # CONFIG_KEYS_DEBUG_PROC_KEYS is not set | ||
3333 | # CONFIG_SECURITY_DMESG_RESTRICT is not set | ||
3334 | # CONFIG_SECURITY is not set | ||
3335 | # CONFIG_SECURITYFS is not set | ||
3336 | CONFIG_DEFAULT_SECURITY_DAC=y | ||
3337 | CONFIG_DEFAULT_SECURITY="" | ||
3338 | CONFIG_XOR_BLOCKS=m | ||
3339 | CONFIG_ASYNC_CORE=m | ||
3340 | CONFIG_ASYNC_MEMCPY=m | ||
3341 | CONFIG_ASYNC_XOR=m | ||
3342 | CONFIG_ASYNC_PQ=m | ||
3343 | CONFIG_ASYNC_RAID6_RECOV=m | ||
3344 | CONFIG_CRYPTO=y | ||
3345 | |||
3346 | # | ||
3347 | # Crypto core or helper | ||
3348 | # | ||
3349 | CONFIG_CRYPTO_ALGAPI=y | ||
3350 | CONFIG_CRYPTO_ALGAPI2=y | ||
3351 | CONFIG_CRYPTO_AEAD=m | ||
3352 | CONFIG_CRYPTO_AEAD2=y | ||
3353 | CONFIG_CRYPTO_BLKCIPHER=y | ||
3354 | CONFIG_CRYPTO_BLKCIPHER2=y | ||
3355 | CONFIG_CRYPTO_HASH=y | ||
3356 | CONFIG_CRYPTO_HASH2=y | ||
3357 | CONFIG_CRYPTO_RNG=m | ||
3358 | CONFIG_CRYPTO_RNG2=y | ||
3359 | CONFIG_CRYPTO_PCOMP2=y | ||
3360 | CONFIG_CRYPTO_MANAGER=y | ||
3361 | CONFIG_CRYPTO_MANAGER2=y | ||
3362 | CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y | ||
3363 | CONFIG_CRYPTO_GF128MUL=m | ||
3364 | CONFIG_CRYPTO_NULL=m | ||
3365 | CONFIG_CRYPTO_WORKQUEUE=y | ||
3366 | CONFIG_CRYPTO_CRYPTD=m | ||
3367 | CONFIG_CRYPTO_AUTHENC=m | ||
3368 | CONFIG_CRYPTO_TEST=m | ||
3369 | |||
3370 | # | ||
3371 | # Authenticated Encryption with Associated Data | ||
3372 | # | ||
3373 | CONFIG_CRYPTO_CCM=m | ||
3374 | CONFIG_CRYPTO_GCM=m | ||
3375 | CONFIG_CRYPTO_SEQIV=m | ||
3376 | |||
3377 | # | ||
3378 | # Block modes | ||
3379 | # | ||
3380 | CONFIG_CRYPTO_CBC=y | ||
3381 | CONFIG_CRYPTO_CTR=m | ||
3382 | CONFIG_CRYPTO_CTS=m | ||
3383 | CONFIG_CRYPTO_ECB=y | ||
3384 | CONFIG_CRYPTO_LRW=m | ||
3385 | CONFIG_CRYPTO_PCBC=m | ||
3386 | CONFIG_CRYPTO_XTS=m | ||
3387 | |||
3388 | # | ||
3389 | # Hash modes | ||
3390 | # | ||
3391 | CONFIG_CRYPTO_HMAC=m | ||
3392 | CONFIG_CRYPTO_XCBC=m | ||
3393 | # CONFIG_CRYPTO_VMAC is not set | ||
3394 | |||
3395 | # | ||
3396 | # Digest | ||
3397 | # | ||
3398 | CONFIG_CRYPTO_CRC32C=y | ||
3399 | CONFIG_CRYPTO_GHASH=m | ||
3400 | CONFIG_CRYPTO_MD4=m | ||
3401 | CONFIG_CRYPTO_MD5=y | ||
3402 | CONFIG_CRYPTO_MICHAEL_MIC=y | ||
3403 | CONFIG_CRYPTO_RMD128=m | ||
3404 | CONFIG_CRYPTO_RMD160=m | ||
3405 | CONFIG_CRYPTO_RMD256=m | ||
3406 | CONFIG_CRYPTO_RMD320=m | ||
3407 | CONFIG_CRYPTO_SHA1=m | ||
3408 | CONFIG_CRYPTO_SHA256=m | ||
3409 | CONFIG_CRYPTO_SHA512=m | ||
3410 | CONFIG_CRYPTO_TGR192=m | ||
3411 | CONFIG_CRYPTO_WP512=m | ||
3412 | |||
3413 | # | ||
3414 | # Ciphers | ||
3415 | # | ||
3416 | CONFIG_CRYPTO_AES=y | ||
3417 | CONFIG_CRYPTO_ANUBIS=m | ||
3418 | CONFIG_CRYPTO_ARC4=y | ||
3419 | CONFIG_CRYPTO_BLOWFISH=m | ||
3420 | CONFIG_CRYPTO_CAMELLIA=m | ||
3421 | CONFIG_CRYPTO_CAST5=m | ||
3422 | CONFIG_CRYPTO_CAST6=m | ||
3423 | CONFIG_CRYPTO_DES=y | ||
3424 | CONFIG_CRYPTO_FCRYPT=m | ||
3425 | CONFIG_CRYPTO_KHAZAD=m | ||
3426 | CONFIG_CRYPTO_SALSA20=m | ||
3427 | CONFIG_CRYPTO_SEED=m | ||
3428 | CONFIG_CRYPTO_SERPENT=m | ||
3429 | CONFIG_CRYPTO_TEA=m | ||
3430 | CONFIG_CRYPTO_TWOFISH=m | ||
3431 | CONFIG_CRYPTO_TWOFISH_COMMON=m | ||
3432 | |||
3433 | # | ||
3434 | # Compression | ||
3435 | # | ||
3436 | CONFIG_CRYPTO_DEFLATE=y | ||
3437 | # CONFIG_CRYPTO_ZLIB is not set | ||
3438 | CONFIG_CRYPTO_LZO=y | ||
3439 | |||
3440 | # | ||
3441 | # Random Number Generation | ||
3442 | # | ||
3443 | CONFIG_CRYPTO_ANSI_CPRNG=m | ||
3444 | CONFIG_CRYPTO_USER_API=m | ||
3445 | CONFIG_CRYPTO_USER_API_HASH=m | ||
3446 | CONFIG_CRYPTO_USER_API_SKCIPHER=m | ||
3447 | CONFIG_CRYPTO_HW=y | ||
3448 | CONFIG_CRYPTO_DEV_OMAP_SHAM=m | ||
3449 | CONFIG_CRYPTO_DEV_OMAP_AES=m | ||
3450 | # CONFIG_BINARY_PRINTF is not set | ||
3451 | |||
3452 | # | ||
3453 | # Library routines | ||
3454 | # | ||
3455 | CONFIG_RAID6_PQ=m | ||
3456 | CONFIG_BITREVERSE=y | ||
3457 | CONFIG_GENERIC_FIND_LAST_BIT=y | ||
3458 | CONFIG_CRC_CCITT=y | ||
3459 | CONFIG_CRC16=y | ||
3460 | CONFIG_CRC_T10DIF=y | ||
3461 | CONFIG_CRC_ITU_T=y | ||
3462 | CONFIG_CRC32=y | ||
3463 | CONFIG_CRC7=y | ||
3464 | CONFIG_LIBCRC32C=y | ||
3465 | CONFIG_ZLIB_INFLATE=y | ||
3466 | CONFIG_ZLIB_DEFLATE=y | ||
3467 | CONFIG_LZO_COMPRESS=y | ||
3468 | CONFIG_LZO_DECOMPRESS=y | ||
3469 | CONFIG_XZ_DEC=y | ||
3470 | CONFIG_XZ_DEC_X86=y | ||
3471 | CONFIG_XZ_DEC_POWERPC=y | ||
3472 | CONFIG_XZ_DEC_IA64=y | ||
3473 | CONFIG_XZ_DEC_ARM=y | ||
3474 | CONFIG_XZ_DEC_ARMTHUMB=y | ||
3475 | CONFIG_XZ_DEC_SPARC=y | ||
3476 | CONFIG_XZ_DEC_BCJ=y | ||
3477 | CONFIG_XZ_DEC_TEST=m | ||
3478 | CONFIG_DECOMPRESS_GZIP=y | ||
3479 | CONFIG_DECOMPRESS_XZ=y | ||
3480 | CONFIG_DECOMPRESS_LZO=y | ||
3481 | CONFIG_TEXTSEARCH=y | ||
3482 | CONFIG_TEXTSEARCH_KMP=m | ||
3483 | CONFIG_TEXTSEARCH_BM=m | ||
3484 | CONFIG_TEXTSEARCH_FSM=m | ||
3485 | CONFIG_BTREE=y | ||
3486 | CONFIG_HAS_IOMEM=y | ||
3487 | CONFIG_HAS_IOPORT=y | ||
3488 | CONFIG_HAS_DMA=y | ||
3489 | CONFIG_NLATTR=y | ||
3490 | CONFIG_AVERAGE=y | ||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/beagleboard/defconfig b/recipes-kernel/linux/linux-omap-2.6.39/beagleboard/defconfig deleted file mode 100644 index 6f97d93b..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/beagleboard/defconfig +++ /dev/null | |||
@@ -1,3517 +0,0 @@ | |||
1 | # | ||
2 | # Automatically generated make config: don't edit | ||
3 | # Linux/arm 2.6.39 Kernel Configuration | ||
4 | # Sun Jun 5 11:03:19 2011 | ||
5 | # | ||
6 | CONFIG_ARM=y | ||
7 | CONFIG_HAVE_PWM=y | ||
8 | CONFIG_SYS_SUPPORTS_APM_EMULATION=y | ||
9 | CONFIG_HAVE_SCHED_CLOCK=y | ||
10 | CONFIG_GENERIC_GPIO=y | ||
11 | # CONFIG_ARCH_USES_GETTIMEOFFSET is not set | ||
12 | CONFIG_GENERIC_CLOCKEVENTS=y | ||
13 | CONFIG_KTIME_SCALAR=y | ||
14 | CONFIG_HAVE_PROC_CPU=y | ||
15 | CONFIG_STACKTRACE_SUPPORT=y | ||
16 | CONFIG_HAVE_LATENCYTOP_SUPPORT=y | ||
17 | CONFIG_LOCKDEP_SUPPORT=y | ||
18 | CONFIG_TRACE_IRQFLAGS_SUPPORT=y | ||
19 | CONFIG_HARDIRQS_SW_RESEND=y | ||
20 | CONFIG_GENERIC_IRQ_PROBE=y | ||
21 | CONFIG_RWSEM_GENERIC_SPINLOCK=y | ||
22 | CONFIG_ARCH_HAS_CPUFREQ=y | ||
23 | CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y | ||
24 | CONFIG_GENERIC_HWEIGHT=y | ||
25 | CONFIG_GENERIC_CALIBRATE_DELAY=y | ||
26 | CONFIG_NEED_DMA_MAP_STATE=y | ||
27 | CONFIG_VECTORS_BASE=0xffff0000 | ||
28 | # CONFIG_ARM_PATCH_PHYS_VIRT is not set | ||
29 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" | ||
30 | CONFIG_CONSTRUCTORS=y | ||
31 | CONFIG_HAVE_IRQ_WORK=y | ||
32 | CONFIG_IRQ_WORK=y | ||
33 | |||
34 | # | ||
35 | # General setup | ||
36 | # | ||
37 | CONFIG_EXPERIMENTAL=y | ||
38 | CONFIG_BROKEN_ON_SMP=y | ||
39 | CONFIG_INIT_ENV_ARG_LIMIT=32 | ||
40 | CONFIG_CROSS_COMPILE="" | ||
41 | CONFIG_LOCALVERSION="" | ||
42 | # CONFIG_LOCALVERSION_AUTO is not set | ||
43 | CONFIG_HAVE_KERNEL_GZIP=y | ||
44 | CONFIG_HAVE_KERNEL_LZMA=y | ||
45 | CONFIG_HAVE_KERNEL_LZO=y | ||
46 | CONFIG_KERNEL_GZIP=y | ||
47 | # CONFIG_KERNEL_LZMA is not set | ||
48 | # CONFIG_KERNEL_LZO is not set | ||
49 | CONFIG_SWAP=y | ||
50 | CONFIG_SYSVIPC=y | ||
51 | CONFIG_SYSVIPC_SYSCTL=y | ||
52 | CONFIG_POSIX_MQUEUE=y | ||
53 | CONFIG_POSIX_MQUEUE_SYSCTL=y | ||
54 | CONFIG_BSD_PROCESS_ACCT=y | ||
55 | # CONFIG_BSD_PROCESS_ACCT_V3 is not set | ||
56 | CONFIG_FHANDLE=y | ||
57 | CONFIG_TASKSTATS=y | ||
58 | CONFIG_TASK_DELAY_ACCT=y | ||
59 | CONFIG_TASK_XACCT=y | ||
60 | CONFIG_TASK_IO_ACCOUNTING=y | ||
61 | # CONFIG_AUDIT is not set | ||
62 | CONFIG_HAVE_GENERIC_HARDIRQS=y | ||
63 | |||
64 | # | ||
65 | # IRQ subsystem | ||
66 | # | ||
67 | CONFIG_GENERIC_HARDIRQS=y | ||
68 | CONFIG_HAVE_SPARSE_IRQ=y | ||
69 | CONFIG_GENERIC_IRQ_SHOW=y | ||
70 | # CONFIG_SPARSE_IRQ is not set | ||
71 | |||
72 | # | ||
73 | # RCU Subsystem | ||
74 | # | ||
75 | CONFIG_TINY_RCU=y | ||
76 | # CONFIG_PREEMPT_RCU is not set | ||
77 | # CONFIG_RCU_TRACE is not set | ||
78 | # CONFIG_TREE_RCU_TRACE is not set | ||
79 | CONFIG_IKCONFIG=y | ||
80 | CONFIG_IKCONFIG_PROC=y | ||
81 | CONFIG_LOG_BUF_SHIFT=16 | ||
82 | CONFIG_CGROUPS=y | ||
83 | # CONFIG_CGROUP_DEBUG is not set | ||
84 | CONFIG_CGROUP_NS=y | ||
85 | CONFIG_CGROUP_FREEZER=y | ||
86 | CONFIG_CGROUP_DEVICE=y | ||
87 | CONFIG_CPUSETS=y | ||
88 | CONFIG_PROC_PID_CPUSET=y | ||
89 | CONFIG_CGROUP_CPUACCT=y | ||
90 | CONFIG_RESOURCE_COUNTERS=y | ||
91 | CONFIG_CGROUP_MEM_RES_CTLR=y | ||
92 | CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y | ||
93 | CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED=y | ||
94 | CONFIG_CGROUP_PERF=y | ||
95 | CONFIG_CGROUP_SCHED=y | ||
96 | CONFIG_FAIR_GROUP_SCHED=y | ||
97 | CONFIG_RT_GROUP_SCHED=y | ||
98 | CONFIG_BLK_CGROUP=y | ||
99 | # CONFIG_DEBUG_BLK_CGROUP is not set | ||
100 | CONFIG_NAMESPACES=y | ||
101 | CONFIG_UTS_NS=y | ||
102 | CONFIG_IPC_NS=y | ||
103 | CONFIG_USER_NS=y | ||
104 | CONFIG_PID_NS=y | ||
105 | CONFIG_NET_NS=y | ||
106 | CONFIG_SCHED_AUTOGROUP=y | ||
107 | CONFIG_MM_OWNER=y | ||
108 | # CONFIG_SYSFS_DEPRECATED is not set | ||
109 | # CONFIG_RELAY is not set | ||
110 | CONFIG_BLK_DEV_INITRD=y | ||
111 | CONFIG_INITRAMFS_SOURCE="" | ||
112 | CONFIG_RD_GZIP=y | ||
113 | CONFIG_RD_BZIP2=y | ||
114 | CONFIG_RD_LZMA=y | ||
115 | CONFIG_RD_XZ=y | ||
116 | CONFIG_RD_LZO=y | ||
117 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y | ||
118 | CONFIG_SYSCTL=y | ||
119 | CONFIG_ANON_INODES=y | ||
120 | CONFIG_EXPERT=y | ||
121 | CONFIG_UID16=y | ||
122 | # CONFIG_SYSCTL_SYSCALL is not set | ||
123 | CONFIG_KALLSYMS=y | ||
124 | # CONFIG_KALLSYMS_ALL is not set | ||
125 | # CONFIG_KALLSYMS_EXTRA_PASS is not set | ||
126 | CONFIG_HOTPLUG=y | ||
127 | CONFIG_PRINTK=y | ||
128 | CONFIG_BUG=y | ||
129 | CONFIG_ELF_CORE=y | ||
130 | CONFIG_BASE_FULL=y | ||
131 | CONFIG_FUTEX=y | ||
132 | CONFIG_EPOLL=y | ||
133 | CONFIG_SIGNALFD=y | ||
134 | CONFIG_TIMERFD=y | ||
135 | CONFIG_EVENTFD=y | ||
136 | CONFIG_SHMEM=y | ||
137 | CONFIG_AIO=y | ||
138 | CONFIG_EMBEDDED=y | ||
139 | CONFIG_HAVE_PERF_EVENTS=y | ||
140 | CONFIG_PERF_USE_VMALLOC=y | ||
141 | |||
142 | # | ||
143 | # Kernel Performance Events And Counters | ||
144 | # | ||
145 | CONFIG_PERF_EVENTS=y | ||
146 | # CONFIG_PERF_COUNTERS is not set | ||
147 | # CONFIG_DEBUG_PERF_USE_VMALLOC is not set | ||
148 | CONFIG_VM_EVENT_COUNTERS=y | ||
149 | # CONFIG_COMPAT_BRK is not set | ||
150 | CONFIG_SLAB=y | ||
151 | # CONFIG_SLUB is not set | ||
152 | # CONFIG_SLOB is not set | ||
153 | CONFIG_PROFILING=y | ||
154 | CONFIG_OPROFILE=y | ||
155 | CONFIG_HAVE_OPROFILE=y | ||
156 | # CONFIG_KPROBES is not set | ||
157 | CONFIG_HAVE_KPROBES=y | ||
158 | CONFIG_HAVE_KRETPROBES=y | ||
159 | CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y | ||
160 | CONFIG_HAVE_CLK=y | ||
161 | CONFIG_HAVE_DMA_API_DEBUG=y | ||
162 | CONFIG_HAVE_HW_BREAKPOINT=y | ||
163 | |||
164 | # | ||
165 | # GCOV-based kernel profiling | ||
166 | # | ||
167 | # CONFIG_GCOV_KERNEL is not set | ||
168 | CONFIG_HAVE_GENERIC_DMA_COHERENT=y | ||
169 | CONFIG_SLABINFO=y | ||
170 | CONFIG_RT_MUTEXES=y | ||
171 | CONFIG_BASE_SMALL=0 | ||
172 | CONFIG_MODULES=y | ||
173 | CONFIG_MODULE_FORCE_LOAD=y | ||
174 | CONFIG_MODULE_UNLOAD=y | ||
175 | CONFIG_MODULE_FORCE_UNLOAD=y | ||
176 | CONFIG_MODVERSIONS=y | ||
177 | CONFIG_MODULE_SRCVERSION_ALL=y | ||
178 | CONFIG_BLOCK=y | ||
179 | CONFIG_LBDAF=y | ||
180 | CONFIG_BLK_DEV_BSG=y | ||
181 | CONFIG_BLK_DEV_INTEGRITY=y | ||
182 | CONFIG_BLK_DEV_THROTTLING=y | ||
183 | |||
184 | # | ||
185 | # IO Schedulers | ||
186 | # | ||
187 | CONFIG_IOSCHED_NOOP=y | ||
188 | CONFIG_IOSCHED_DEADLINE=y | ||
189 | CONFIG_IOSCHED_CFQ=y | ||
190 | CONFIG_CFQ_GROUP_IOSCHED=y | ||
191 | # CONFIG_DEFAULT_DEADLINE is not set | ||
192 | CONFIG_DEFAULT_CFQ=y | ||
193 | # CONFIG_DEFAULT_NOOP is not set | ||
194 | CONFIG_DEFAULT_IOSCHED="cfq" | ||
195 | # CONFIG_INLINE_SPIN_TRYLOCK is not set | ||
196 | # CONFIG_INLINE_SPIN_TRYLOCK_BH is not set | ||
197 | # CONFIG_INLINE_SPIN_LOCK is not set | ||
198 | # CONFIG_INLINE_SPIN_LOCK_BH is not set | ||
199 | # CONFIG_INLINE_SPIN_LOCK_IRQ is not set | ||
200 | # CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set | ||
201 | CONFIG_INLINE_SPIN_UNLOCK=y | ||
202 | # CONFIG_INLINE_SPIN_UNLOCK_BH is not set | ||
203 | CONFIG_INLINE_SPIN_UNLOCK_IRQ=y | ||
204 | # CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set | ||
205 | # CONFIG_INLINE_READ_TRYLOCK is not set | ||
206 | # CONFIG_INLINE_READ_LOCK is not set | ||
207 | # CONFIG_INLINE_READ_LOCK_BH is not set | ||
208 | # CONFIG_INLINE_READ_LOCK_IRQ is not set | ||
209 | # CONFIG_INLINE_READ_LOCK_IRQSAVE is not set | ||
210 | CONFIG_INLINE_READ_UNLOCK=y | ||
211 | # CONFIG_INLINE_READ_UNLOCK_BH is not set | ||
212 | CONFIG_INLINE_READ_UNLOCK_IRQ=y | ||
213 | # CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set | ||
214 | # CONFIG_INLINE_WRITE_TRYLOCK is not set | ||
215 | # CONFIG_INLINE_WRITE_LOCK is not set | ||
216 | # CONFIG_INLINE_WRITE_LOCK_BH is not set | ||
217 | # CONFIG_INLINE_WRITE_LOCK_IRQ is not set | ||
218 | # CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set | ||
219 | CONFIG_INLINE_WRITE_UNLOCK=y | ||
220 | # CONFIG_INLINE_WRITE_UNLOCK_BH is not set | ||
221 | CONFIG_INLINE_WRITE_UNLOCK_IRQ=y | ||
222 | # CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set | ||
223 | # CONFIG_MUTEX_SPIN_ON_OWNER is not set | ||
224 | CONFIG_FREEZER=y | ||
225 | |||
226 | # | ||
227 | # System Type | ||
228 | # | ||
229 | CONFIG_MMU=y | ||
230 | # CONFIG_ARCH_INTEGRATOR is not set | ||
231 | # CONFIG_ARCH_REALVIEW is not set | ||
232 | # CONFIG_ARCH_VERSATILE is not set | ||
233 | # CONFIG_ARCH_VEXPRESS is not set | ||
234 | # CONFIG_ARCH_AT91 is not set | ||
235 | # CONFIG_ARCH_BCMRING is not set | ||
236 | # CONFIG_ARCH_CLPS711X is not set | ||
237 | # CONFIG_ARCH_CNS3XXX is not set | ||
238 | # CONFIG_ARCH_GEMINI is not set | ||
239 | # CONFIG_ARCH_EBSA110 is not set | ||
240 | # CONFIG_ARCH_EP93XX is not set | ||
241 | # CONFIG_ARCH_FOOTBRIDGE is not set | ||
242 | # CONFIG_ARCH_MXC is not set | ||
243 | # CONFIG_ARCH_MXS is not set | ||
244 | # CONFIG_ARCH_STMP3XXX is not set | ||
245 | # CONFIG_ARCH_NETX is not set | ||
246 | # CONFIG_ARCH_H720X is not set | ||
247 | # CONFIG_ARCH_IOP13XX is not set | ||
248 | # CONFIG_ARCH_IOP32X is not set | ||
249 | # CONFIG_ARCH_IOP33X is not set | ||
250 | # CONFIG_ARCH_IXP23XX is not set | ||
251 | # CONFIG_ARCH_IXP2000 is not set | ||
252 | # CONFIG_ARCH_IXP4XX is not set | ||
253 | # CONFIG_ARCH_DOVE is not set | ||
254 | # CONFIG_ARCH_KIRKWOOD is not set | ||
255 | # CONFIG_ARCH_LOKI is not set | ||
256 | # CONFIG_ARCH_LPC32XX is not set | ||
257 | # CONFIG_ARCH_MV78XX0 is not set | ||
258 | # CONFIG_ARCH_ORION5X is not set | ||
259 | # CONFIG_ARCH_MMP is not set | ||
260 | # CONFIG_ARCH_KS8695 is not set | ||
261 | # CONFIG_ARCH_NS9XXX is not set | ||
262 | # CONFIG_ARCH_W90X900 is not set | ||
263 | # CONFIG_ARCH_NUC93X is not set | ||
264 | # CONFIG_ARCH_TEGRA is not set | ||
265 | # CONFIG_ARCH_PNX4008 is not set | ||
266 | # CONFIG_ARCH_PXA is not set | ||
267 | # CONFIG_ARCH_MSM is not set | ||
268 | # CONFIG_ARCH_SHMOBILE is not set | ||
269 | # CONFIG_ARCH_RPC is not set | ||
270 | # CONFIG_ARCH_SA1100 is not set | ||
271 | # CONFIG_ARCH_S3C2410 is not set | ||
272 | # CONFIG_ARCH_S3C64XX is not set | ||
273 | # CONFIG_ARCH_S5P64X0 is not set | ||
274 | # CONFIG_ARCH_S5P6442 is not set | ||
275 | # CONFIG_ARCH_S5PC100 is not set | ||
276 | # CONFIG_ARCH_S5PV210 is not set | ||
277 | # CONFIG_ARCH_EXYNOS4 is not set | ||
278 | # CONFIG_ARCH_SHARK is not set | ||
279 | # CONFIG_ARCH_TCC_926 is not set | ||
280 | # CONFIG_ARCH_U300 is not set | ||
281 | # CONFIG_ARCH_U8500 is not set | ||
282 | # CONFIG_ARCH_NOMADIK is not set | ||
283 | # CONFIG_ARCH_DAVINCI is not set | ||
284 | CONFIG_ARCH_OMAP=y | ||
285 | # CONFIG_PLAT_SPEAR is not set | ||
286 | # CONFIG_ARCH_VT8500 is not set | ||
287 | # CONFIG_GPIO_PCA953X is not set | ||
288 | # CONFIG_KEYBOARD_GPIO_POLLED is not set | ||
289 | |||
290 | # | ||
291 | # TI OMAP Common Features | ||
292 | # | ||
293 | CONFIG_ARCH_OMAP_OTG=y | ||
294 | # CONFIG_ARCH_OMAP1 is not set | ||
295 | CONFIG_ARCH_OMAP2PLUS=y | ||
296 | |||
297 | # | ||
298 | # OMAP Feature Selections | ||
299 | # | ||
300 | CONFIG_OMAP_SMARTREFLEX=y | ||
301 | CONFIG_OMAP_SMARTREFLEX_CLASS3=y | ||
302 | CONFIG_OMAP_RESET_CLOCKS=y | ||
303 | # CONFIG_OMAP_MUX is not set | ||
304 | CONFIG_OMAP_MCBSP=y | ||
305 | CONFIG_OMAP_MBOX_FWK=m | ||
306 | CONFIG_OMAP_MBOX_KFIFO_SIZE=256 | ||
307 | CONFIG_OMAP_IOMMU=y | ||
308 | CONFIG_OMAP_IOMMU_DEBUG=m | ||
309 | CONFIG_OMAP_32K_TIMER=y | ||
310 | # CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set | ||
311 | CONFIG_OMAP_32K_TIMER_HZ=128 | ||
312 | CONFIG_OMAP_DM_TIMER=y | ||
313 | # CONFIG_OMAP_PM_NONE is not set | ||
314 | CONFIG_OMAP_PM_NOOP=y | ||
315 | |||
316 | # | ||
317 | # TI OMAP2/3/4 Specific Features | ||
318 | # | ||
319 | CONFIG_ARCH_OMAP2PLUS_TYPICAL=y | ||
320 | # CONFIG_ARCH_OMAP2 is not set | ||
321 | CONFIG_ARCH_OMAP3=y | ||
322 | # CONFIG_ARCH_OMAP4 is not set | ||
323 | CONFIG_SOC_OMAP3430=y | ||
324 | # CONFIG_SOC_OMAPTI816X is not set | ||
325 | CONFIG_OMAP_PACKAGE_CBB=y | ||
326 | |||
327 | # | ||
328 | # OMAP Board Type | ||
329 | # | ||
330 | CONFIG_MACH_OMAP3_BEAGLE=y | ||
331 | # CONFIG_MACH_DEVKIT8000 is not set | ||
332 | # CONFIG_MACH_OMAP_LDP is not set | ||
333 | # CONFIG_MACH_OMAP3530_LV_SOM is not set | ||
334 | # CONFIG_MACH_OMAP3_TORPEDO is not set | ||
335 | CONFIG_MACH_OVERO=y | ||
336 | CONFIG_MACH_OMAP3EVM=y | ||
337 | # CONFIG_MACH_OMAP3517EVM is not set | ||
338 | # CONFIG_MACH_CRANEBOARD is not set | ||
339 | # CONFIG_MACH_OMAP3_PANDORA is not set | ||
340 | CONFIG_MACH_OMAP3_TOUCHBOOK=y | ||
341 | # CONFIG_MACH_OMAP_3430SDP is not set | ||
342 | # CONFIG_MACH_NOKIA_RM680 is not set | ||
343 | # CONFIG_MACH_NOKIA_RX51 is not set | ||
344 | CONFIG_MACH_OMAP_ZOOM2=y | ||
345 | # CONFIG_MACH_OMAP_ZOOM3 is not set | ||
346 | # CONFIG_MACH_CM_T35 is not set | ||
347 | # CONFIG_MACH_CM_T3517 is not set | ||
348 | # CONFIG_MACH_IGEP0020 is not set | ||
349 | # CONFIG_MACH_IGEP0030 is not set | ||
350 | # CONFIG_MACH_SBC3530 is not set | ||
351 | # CONFIG_MACH_OMAP_3630SDP is not set | ||
352 | # CONFIG_OMAP3_EMU is not set | ||
353 | # CONFIG_OMAP3_SDRC_AC_TIMING is not set | ||
354 | |||
355 | # | ||
356 | # System MMU | ||
357 | # | ||
358 | |||
359 | # | ||
360 | # Processor Type | ||
361 | # | ||
362 | CONFIG_CPU_V7=y | ||
363 | CONFIG_CPU_32v6K=y | ||
364 | CONFIG_CPU_32v7=y | ||
365 | CONFIG_CPU_ABRT_EV7=y | ||
366 | CONFIG_CPU_PABRT_V7=y | ||
367 | CONFIG_CPU_CACHE_V7=y | ||
368 | CONFIG_CPU_CACHE_VIPT=y | ||
369 | CONFIG_CPU_COPY_V6=y | ||
370 | CONFIG_CPU_TLB_V7=y | ||
371 | CONFIG_CPU_HAS_ASID=y | ||
372 | CONFIG_CPU_CP15=y | ||
373 | CONFIG_CPU_CP15_MMU=y | ||
374 | |||
375 | # | ||
376 | # Processor Features | ||
377 | # | ||
378 | CONFIG_ARM_THUMB=y | ||
379 | CONFIG_ARM_THUMBEE=y | ||
380 | # CONFIG_SWP_EMULATE is not set | ||
381 | # CONFIG_CPU_ICACHE_DISABLE is not set | ||
382 | # CONFIG_CPU_DCACHE_DISABLE is not set | ||
383 | # CONFIG_CPU_BPREDICT_DISABLE is not set | ||
384 | CONFIG_ARM_L1_CACHE_SHIFT_6=y | ||
385 | CONFIG_ARM_L1_CACHE_SHIFT=6 | ||
386 | CONFIG_ARM_DMA_MEM_BUFFERABLE=y | ||
387 | CONFIG_ARM_ERRATA_430973=y | ||
388 | # CONFIG_ARM_ERRATA_458693 is not set | ||
389 | # CONFIG_ARM_ERRATA_460075 is not set | ||
390 | # CONFIG_ARM_ERRATA_743622 is not set | ||
391 | # CONFIG_ARM_ERRATA_754322 is not set | ||
392 | |||
393 | # | ||
394 | # Bus support | ||
395 | # | ||
396 | # CONFIG_PCI_SYSCALL is not set | ||
397 | # CONFIG_ARCH_SUPPORTS_MSI is not set | ||
398 | # CONFIG_PCCARD is not set | ||
399 | |||
400 | # | ||
401 | # Kernel Features | ||
402 | # | ||
403 | CONFIG_TICK_ONESHOT=y | ||
404 | CONFIG_NO_HZ=y | ||
405 | CONFIG_HIGH_RES_TIMERS=y | ||
406 | CONFIG_GENERIC_CLOCKEVENTS_BUILD=y | ||
407 | CONFIG_VMSPLIT_3G=y | ||
408 | # CONFIG_VMSPLIT_2G is not set | ||
409 | # CONFIG_VMSPLIT_1G is not set | ||
410 | CONFIG_PAGE_OFFSET=0xC0000000 | ||
411 | # CONFIG_PREEMPT_NONE is not set | ||
412 | CONFIG_PREEMPT_VOLUNTARY=y | ||
413 | # CONFIG_PREEMPT is not set | ||
414 | CONFIG_HZ=128 | ||
415 | # CONFIG_THUMB2_KERNEL is not set | ||
416 | CONFIG_AEABI=y | ||
417 | # CONFIG_OABI_COMPAT is not set | ||
418 | CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y | ||
419 | # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set | ||
420 | # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set | ||
421 | # CONFIG_HIGHMEM is not set | ||
422 | CONFIG_SELECT_MEMORY_MODEL=y | ||
423 | CONFIG_FLATMEM_MANUAL=y | ||
424 | CONFIG_FLATMEM=y | ||
425 | CONFIG_FLAT_NODE_MEM_MAP=y | ||
426 | CONFIG_HAVE_MEMBLOCK=y | ||
427 | CONFIG_PAGEFLAGS_EXTENDED=y | ||
428 | CONFIG_SPLIT_PTLOCK_CPUS=4 | ||
429 | CONFIG_COMPACTION=y | ||
430 | CONFIG_MIGRATION=y | ||
431 | # CONFIG_PHYS_ADDR_T_64BIT is not set | ||
432 | CONFIG_ZONE_DMA_FLAG=0 | ||
433 | CONFIG_VIRT_TO_BUS=y | ||
434 | # CONFIG_KSM is not set | ||
435 | CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 | ||
436 | CONFIG_NEED_PER_CPU_KM=y | ||
437 | CONFIG_FORCE_MAX_ZONEORDER=11 | ||
438 | CONFIG_LEDS=y | ||
439 | CONFIG_ALIGNMENT_TRAP=y | ||
440 | # CONFIG_UACCESS_WITH_MEMCPY is not set | ||
441 | # CONFIG_SECCOMP is not set | ||
442 | # CONFIG_CC_STACKPROTECTOR is not set | ||
443 | # CONFIG_DEPRECATED_PARAM_STRUCT is not set | ||
444 | |||
445 | # | ||
446 | # Boot options | ||
447 | # | ||
448 | CONFIG_ZBOOT_ROM_TEXT=0x0 | ||
449 | CONFIG_ZBOOT_ROM_BSS=0x0 | ||
450 | CONFIG_CMDLINE=" debug " | ||
451 | # CONFIG_CMDLINE_FORCE is not set | ||
452 | # CONFIG_XIP_KERNEL is not set | ||
453 | CONFIG_KEXEC=y | ||
454 | CONFIG_ATAGS_PROC=y | ||
455 | # CONFIG_CRASH_DUMP is not set | ||
456 | CONFIG_AUTO_ZRELADDR=y | ||
457 | |||
458 | # | ||
459 | # CPU Power Management | ||
460 | # | ||
461 | CONFIG_CPU_FREQ=y | ||
462 | CONFIG_CPU_FREQ_TABLE=y | ||
463 | # CONFIG_CPU_FREQ_DEBUG is not set | ||
464 | CONFIG_CPU_FREQ_STAT=y | ||
465 | CONFIG_CPU_FREQ_STAT_DETAILS=y | ||
466 | # CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set | ||
467 | # CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set | ||
468 | CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y | ||
469 | # CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set | ||
470 | # CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set | ||
471 | # CONFIG_CPU_FREQ_DEFAULT_GOV_HOTPLUG is not set | ||
472 | CONFIG_CPU_FREQ_GOV_PERFORMANCE=y | ||
473 | CONFIG_CPU_FREQ_GOV_POWERSAVE=y | ||
474 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | ||
475 | CONFIG_CPU_FREQ_GOV_ONDEMAND=y | ||
476 | CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y | ||
477 | CONFIG_CPU_IDLE=y | ||
478 | CONFIG_CPU_IDLE_GOV_LADDER=y | ||
479 | CONFIG_CPU_IDLE_GOV_MENU=y | ||
480 | |||
481 | # | ||
482 | # Floating point emulation | ||
483 | # | ||
484 | |||
485 | # | ||
486 | # At least one emulation must be selected | ||
487 | # | ||
488 | CONFIG_VFP=y | ||
489 | CONFIG_VFPv3=y | ||
490 | CONFIG_NEON=y | ||
491 | |||
492 | # | ||
493 | # Userspace binary formats | ||
494 | # | ||
495 | CONFIG_BINFMT_ELF=y | ||
496 | # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set | ||
497 | CONFIG_HAVE_AOUT=y | ||
498 | CONFIG_BINFMT_AOUT=m | ||
499 | CONFIG_BINFMT_MISC=y | ||
500 | |||
501 | # | ||
502 | # Power management options | ||
503 | # | ||
504 | CONFIG_SUSPEND=y | ||
505 | CONFIG_SUSPEND_FREEZER=y | ||
506 | CONFIG_PM_SLEEP=y | ||
507 | CONFIG_PM_RUNTIME=y | ||
508 | CONFIG_PM=y | ||
509 | CONFIG_PM_DEBUG=y | ||
510 | # CONFIG_PM_VERBOSE is not set | ||
511 | # CONFIG_PM_ADVANCED_DEBUG is not set | ||
512 | # CONFIG_PM_TEST_SUSPEND is not set | ||
513 | CONFIG_CAN_PM_TRACE=y | ||
514 | # CONFIG_APM_EMULATION is not set | ||
515 | CONFIG_ARCH_HAS_OPP=y | ||
516 | CONFIG_PM_OPP=y | ||
517 | CONFIG_ARCH_SUSPEND_POSSIBLE=y | ||
518 | CONFIG_NET=y | ||
519 | |||
520 | # | ||
521 | # Networking options | ||
522 | # | ||
523 | CONFIG_PACKET=y | ||
524 | CONFIG_UNIX=y | ||
525 | CONFIG_XFRM=y | ||
526 | # CONFIG_XFRM_USER is not set | ||
527 | # CONFIG_XFRM_SUB_POLICY is not set | ||
528 | # CONFIG_XFRM_MIGRATE is not set | ||
529 | # CONFIG_XFRM_STATISTICS is not set | ||
530 | CONFIG_XFRM_IPCOMP=m | ||
531 | CONFIG_NET_KEY=y | ||
532 | # CONFIG_NET_KEY_MIGRATE is not set | ||
533 | CONFIG_INET=y | ||
534 | # CONFIG_IP_MULTICAST is not set | ||
535 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
536 | CONFIG_IP_ROUTE_CLASSID=y | ||
537 | CONFIG_IP_PNP=y | ||
538 | CONFIG_IP_PNP_DHCP=y | ||
539 | CONFIG_IP_PNP_BOOTP=y | ||
540 | CONFIG_IP_PNP_RARP=y | ||
541 | CONFIG_NET_IPIP=m | ||
542 | CONFIG_NET_IPGRE_DEMUX=m | ||
543 | CONFIG_NET_IPGRE=m | ||
544 | # CONFIG_ARPD is not set | ||
545 | # CONFIG_SYN_COOKIES is not set | ||
546 | CONFIG_INET_AH=m | ||
547 | CONFIG_INET_ESP=m | ||
548 | CONFIG_INET_IPCOMP=m | ||
549 | CONFIG_INET_XFRM_TUNNEL=m | ||
550 | CONFIG_INET_TUNNEL=m | ||
551 | CONFIG_INET_XFRM_MODE_TRANSPORT=y | ||
552 | CONFIG_INET_XFRM_MODE_TUNNEL=y | ||
553 | CONFIG_INET_XFRM_MODE_BEET=y | ||
554 | CONFIG_INET_LRO=y | ||
555 | CONFIG_INET_DIAG=m | ||
556 | CONFIG_INET_TCP_DIAG=m | ||
557 | CONFIG_TCP_CONG_ADVANCED=y | ||
558 | CONFIG_TCP_CONG_BIC=m | ||
559 | CONFIG_TCP_CONG_CUBIC=y | ||
560 | CONFIG_TCP_CONG_WESTWOOD=m | ||
561 | CONFIG_TCP_CONG_HTCP=m | ||
562 | CONFIG_TCP_CONG_HSTCP=m | ||
563 | CONFIG_TCP_CONG_HYBLA=m | ||
564 | CONFIG_TCP_CONG_VEGAS=m | ||
565 | CONFIG_TCP_CONG_SCALABLE=m | ||
566 | CONFIG_TCP_CONG_LP=m | ||
567 | CONFIG_TCP_CONG_VENO=m | ||
568 | CONFIG_TCP_CONG_YEAH=m | ||
569 | CONFIG_TCP_CONG_ILLINOIS=m | ||
570 | CONFIG_DEFAULT_CUBIC=y | ||
571 | # CONFIG_DEFAULT_RENO is not set | ||
572 | CONFIG_DEFAULT_TCP_CONG="cubic" | ||
573 | # CONFIG_TCP_MD5SIG is not set | ||
574 | CONFIG_IPV6=m | ||
575 | # CONFIG_IPV6_PRIVACY is not set | ||
576 | # CONFIG_IPV6_ROUTER_PREF is not set | ||
577 | # CONFIG_IPV6_OPTIMISTIC_DAD is not set | ||
578 | CONFIG_INET6_AH=m | ||
579 | CONFIG_INET6_ESP=m | ||
580 | CONFIG_INET6_IPCOMP=m | ||
581 | CONFIG_IPV6_MIP6=m | ||
582 | CONFIG_INET6_XFRM_TUNNEL=m | ||
583 | CONFIG_INET6_TUNNEL=m | ||
584 | CONFIG_INET6_XFRM_MODE_TRANSPORT=m | ||
585 | CONFIG_INET6_XFRM_MODE_TUNNEL=m | ||
586 | CONFIG_INET6_XFRM_MODE_BEET=m | ||
587 | CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m | ||
588 | CONFIG_IPV6_SIT=m | ||
589 | # CONFIG_IPV6_SIT_6RD is not set | ||
590 | CONFIG_IPV6_NDISC_NODETYPE=y | ||
591 | CONFIG_IPV6_TUNNEL=m | ||
592 | CONFIG_IPV6_MULTIPLE_TABLES=y | ||
593 | CONFIG_IPV6_SUBTREES=y | ||
594 | CONFIG_IPV6_MROUTE=y | ||
595 | CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y | ||
596 | # CONFIG_IPV6_PIMSM_V2 is not set | ||
597 | # CONFIG_NETWORK_SECMARK is not set | ||
598 | CONFIG_NETWORK_PHY_TIMESTAMPING=y | ||
599 | CONFIG_NETFILTER=y | ||
600 | # CONFIG_NETFILTER_DEBUG is not set | ||
601 | CONFIG_NETFILTER_ADVANCED=y | ||
602 | CONFIG_BRIDGE_NETFILTER=y | ||
603 | |||
604 | # | ||
605 | # Core Netfilter Configuration | ||
606 | # | ||
607 | CONFIG_NETFILTER_NETLINK=m | ||
608 | CONFIG_NETFILTER_NETLINK_QUEUE=m | ||
609 | CONFIG_NETFILTER_NETLINK_LOG=m | ||
610 | CONFIG_NF_CONNTRACK=m | ||
611 | CONFIG_NF_CONNTRACK_MARK=y | ||
612 | CONFIG_NF_CONNTRACK_ZONES=y | ||
613 | CONFIG_NF_CONNTRACK_EVENTS=y | ||
614 | CONFIG_NF_CONNTRACK_TIMESTAMP=y | ||
615 | CONFIG_NF_CT_PROTO_DCCP=m | ||
616 | CONFIG_NF_CT_PROTO_GRE=m | ||
617 | CONFIG_NF_CT_PROTO_SCTP=m | ||
618 | CONFIG_NF_CT_PROTO_UDPLITE=m | ||
619 | CONFIG_NF_CONNTRACK_AMANDA=m | ||
620 | CONFIG_NF_CONNTRACK_FTP=m | ||
621 | CONFIG_NF_CONNTRACK_H323=m | ||
622 | CONFIG_NF_CONNTRACK_IRC=m | ||
623 | CONFIG_NF_CONNTRACK_BROADCAST=m | ||
624 | CONFIG_NF_CONNTRACK_NETBIOS_NS=m | ||
625 | CONFIG_NF_CONNTRACK_SNMP=m | ||
626 | CONFIG_NF_CONNTRACK_PPTP=m | ||
627 | CONFIG_NF_CONNTRACK_SANE=m | ||
628 | CONFIG_NF_CONNTRACK_SIP=m | ||
629 | CONFIG_NF_CONNTRACK_TFTP=m | ||
630 | CONFIG_NF_CT_NETLINK=m | ||
631 | # CONFIG_NETFILTER_TPROXY is not set | ||
632 | CONFIG_NETFILTER_XTABLES=m | ||
633 | |||
634 | # | ||
635 | # Xtables combined modules | ||
636 | # | ||
637 | CONFIG_NETFILTER_XT_MARK=m | ||
638 | CONFIG_NETFILTER_XT_CONNMARK=m | ||
639 | CONFIG_NETFILTER_XT_SET=m | ||
640 | |||
641 | # | ||
642 | # Xtables targets | ||
643 | # | ||
644 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m | ||
645 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | ||
646 | CONFIG_NETFILTER_XT_TARGET_CONNMARK=m | ||
647 | CONFIG_NETFILTER_XT_TARGET_CT=m | ||
648 | # CONFIG_NETFILTER_XT_TARGET_DSCP is not set | ||
649 | CONFIG_NETFILTER_XT_TARGET_HL=m | ||
650 | CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m | ||
651 | # CONFIG_NETFILTER_XT_TARGET_LED is not set | ||
652 | CONFIG_NETFILTER_XT_TARGET_MARK=m | ||
653 | CONFIG_NETFILTER_XT_TARGET_NFLOG=m | ||
654 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | ||
655 | # CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set | ||
656 | CONFIG_NETFILTER_XT_TARGET_RATEEST=m | ||
657 | CONFIG_NETFILTER_XT_TARGET_TEE=m | ||
658 | # CONFIG_NETFILTER_XT_TARGET_TRACE is not set | ||
659 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m | ||
660 | # CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set | ||
661 | |||
662 | # | ||
663 | # Xtables matches | ||
664 | # | ||
665 | CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m | ||
666 | # CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set | ||
667 | CONFIG_NETFILTER_XT_MATCH_COMMENT=m | ||
668 | CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m | ||
669 | CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m | ||
670 | CONFIG_NETFILTER_XT_MATCH_CONNMARK=m | ||
671 | CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m | ||
672 | CONFIG_NETFILTER_XT_MATCH_CPU=m | ||
673 | CONFIG_NETFILTER_XT_MATCH_DCCP=m | ||
674 | CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m | ||
675 | CONFIG_NETFILTER_XT_MATCH_DSCP=m | ||
676 | CONFIG_NETFILTER_XT_MATCH_ESP=m | ||
677 | CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m | ||
678 | CONFIG_NETFILTER_XT_MATCH_HELPER=m | ||
679 | CONFIG_NETFILTER_XT_MATCH_HL=m | ||
680 | CONFIG_NETFILTER_XT_MATCH_IPRANGE=m | ||
681 | CONFIG_NETFILTER_XT_MATCH_IPVS=m | ||
682 | CONFIG_NETFILTER_XT_MATCH_LENGTH=m | ||
683 | CONFIG_NETFILTER_XT_MATCH_LIMIT=m | ||
684 | CONFIG_NETFILTER_XT_MATCH_MAC=m | ||
685 | CONFIG_NETFILTER_XT_MATCH_MARK=m | ||
686 | CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m | ||
687 | # CONFIG_NETFILTER_XT_MATCH_OSF is not set | ||
688 | CONFIG_NETFILTER_XT_MATCH_OWNER=m | ||
689 | CONFIG_NETFILTER_XT_MATCH_POLICY=m | ||
690 | # CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set | ||
691 | CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m | ||
692 | CONFIG_NETFILTER_XT_MATCH_QUOTA=m | ||
693 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m | ||
694 | CONFIG_NETFILTER_XT_MATCH_REALM=m | ||
695 | CONFIG_NETFILTER_XT_MATCH_RECENT=m | ||
696 | CONFIG_NETFILTER_XT_MATCH_SCTP=m | ||
697 | CONFIG_NETFILTER_XT_MATCH_STATE=m | ||
698 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m | ||
699 | CONFIG_NETFILTER_XT_MATCH_STRING=m | ||
700 | CONFIG_NETFILTER_XT_MATCH_TCPMSS=m | ||
701 | CONFIG_NETFILTER_XT_MATCH_TIME=m | ||
702 | CONFIG_NETFILTER_XT_MATCH_U32=m | ||
703 | CONFIG_IP_SET=m | ||
704 | CONFIG_IP_SET_MAX=256 | ||
705 | # CONFIG_IP_SET_BITMAP_IP is not set | ||
706 | # CONFIG_IP_SET_BITMAP_IPMAC is not set | ||
707 | # CONFIG_IP_SET_BITMAP_PORT is not set | ||
708 | # CONFIG_IP_SET_HASH_IP is not set | ||
709 | # CONFIG_IP_SET_HASH_IPPORT is not set | ||
710 | # CONFIG_IP_SET_HASH_IPPORTIP is not set | ||
711 | # CONFIG_IP_SET_HASH_IPPORTNET is not set | ||
712 | # CONFIG_IP_SET_HASH_NET is not set | ||
713 | # CONFIG_IP_SET_HASH_NETPORT is not set | ||
714 | # CONFIG_IP_SET_LIST_SET is not set | ||
715 | CONFIG_IP_VS=m | ||
716 | CONFIG_IP_VS_IPV6=y | ||
717 | CONFIG_IP_VS_DEBUG=y | ||
718 | CONFIG_IP_VS_TAB_BITS=12 | ||
719 | |||
720 | # | ||
721 | # IPVS transport protocol load balancing support | ||
722 | # | ||
723 | CONFIG_IP_VS_PROTO_TCP=y | ||
724 | CONFIG_IP_VS_PROTO_UDP=y | ||
725 | CONFIG_IP_VS_PROTO_AH_ESP=y | ||
726 | CONFIG_IP_VS_PROTO_ESP=y | ||
727 | CONFIG_IP_VS_PROTO_AH=y | ||
728 | # CONFIG_IP_VS_PROTO_SCTP is not set | ||
729 | |||
730 | # | ||
731 | # IPVS scheduler | ||
732 | # | ||
733 | CONFIG_IP_VS_RR=m | ||
734 | CONFIG_IP_VS_WRR=m | ||
735 | CONFIG_IP_VS_LC=m | ||
736 | CONFIG_IP_VS_WLC=m | ||
737 | CONFIG_IP_VS_LBLC=m | ||
738 | CONFIG_IP_VS_LBLCR=m | ||
739 | CONFIG_IP_VS_DH=m | ||
740 | CONFIG_IP_VS_SH=m | ||
741 | CONFIG_IP_VS_SED=m | ||
742 | CONFIG_IP_VS_NQ=m | ||
743 | |||
744 | # | ||
745 | # IPVS application helper | ||
746 | # | ||
747 | CONFIG_IP_VS_FTP=m | ||
748 | CONFIG_IP_VS_NFCT=y | ||
749 | CONFIG_IP_VS_PE_SIP=m | ||
750 | |||
751 | # | ||
752 | # IP: Netfilter Configuration | ||
753 | # | ||
754 | CONFIG_NF_DEFRAG_IPV4=m | ||
755 | CONFIG_NF_CONNTRACK_IPV4=m | ||
756 | CONFIG_NF_CONNTRACK_PROC_COMPAT=y | ||
757 | CONFIG_IP_NF_QUEUE=m | ||
758 | CONFIG_IP_NF_IPTABLES=m | ||
759 | CONFIG_IP_NF_MATCH_AH=m | ||
760 | CONFIG_IP_NF_MATCH_ECN=m | ||
761 | CONFIG_IP_NF_MATCH_TTL=m | ||
762 | CONFIG_IP_NF_FILTER=m | ||
763 | CONFIG_IP_NF_TARGET_REJECT=m | ||
764 | CONFIG_IP_NF_TARGET_LOG=m | ||
765 | CONFIG_IP_NF_TARGET_ULOG=m | ||
766 | CONFIG_NF_NAT=m | ||
767 | CONFIG_NF_NAT_NEEDED=y | ||
768 | CONFIG_IP_NF_TARGET_MASQUERADE=m | ||
769 | CONFIG_IP_NF_TARGET_NETMAP=m | ||
770 | CONFIG_IP_NF_TARGET_REDIRECT=m | ||
771 | CONFIG_NF_NAT_SNMP_BASIC=m | ||
772 | CONFIG_NF_NAT_PROTO_DCCP=m | ||
773 | CONFIG_NF_NAT_PROTO_GRE=m | ||
774 | CONFIG_NF_NAT_PROTO_UDPLITE=m | ||
775 | CONFIG_NF_NAT_PROTO_SCTP=m | ||
776 | CONFIG_NF_NAT_FTP=m | ||
777 | CONFIG_NF_NAT_IRC=m | ||
778 | CONFIG_NF_NAT_TFTP=m | ||
779 | CONFIG_NF_NAT_AMANDA=m | ||
780 | CONFIG_NF_NAT_PPTP=m | ||
781 | CONFIG_NF_NAT_H323=m | ||
782 | CONFIG_NF_NAT_SIP=m | ||
783 | CONFIG_IP_NF_MANGLE=m | ||
784 | CONFIG_IP_NF_TARGET_CLUSTERIP=m | ||
785 | CONFIG_IP_NF_TARGET_ECN=m | ||
786 | CONFIG_IP_NF_TARGET_TTL=m | ||
787 | CONFIG_IP_NF_RAW=m | ||
788 | CONFIG_IP_NF_ARPTABLES=m | ||
789 | CONFIG_IP_NF_ARPFILTER=m | ||
790 | CONFIG_IP_NF_ARP_MANGLE=m | ||
791 | |||
792 | # | ||
793 | # IPv6: Netfilter Configuration | ||
794 | # | ||
795 | CONFIG_NF_DEFRAG_IPV6=m | ||
796 | CONFIG_NF_CONNTRACK_IPV6=m | ||
797 | CONFIG_IP6_NF_QUEUE=m | ||
798 | CONFIG_IP6_NF_IPTABLES=m | ||
799 | CONFIG_IP6_NF_MATCH_AH=m | ||
800 | CONFIG_IP6_NF_MATCH_EUI64=m | ||
801 | CONFIG_IP6_NF_MATCH_FRAG=m | ||
802 | CONFIG_IP6_NF_MATCH_OPTS=m | ||
803 | CONFIG_IP6_NF_MATCH_HL=m | ||
804 | CONFIG_IP6_NF_MATCH_IPV6HEADER=m | ||
805 | CONFIG_IP6_NF_MATCH_MH=m | ||
806 | CONFIG_IP6_NF_MATCH_RT=m | ||
807 | CONFIG_IP6_NF_TARGET_HL=m | ||
808 | CONFIG_IP6_NF_TARGET_LOG=m | ||
809 | CONFIG_IP6_NF_FILTER=m | ||
810 | CONFIG_IP6_NF_TARGET_REJECT=m | ||
811 | CONFIG_IP6_NF_MANGLE=m | ||
812 | CONFIG_IP6_NF_RAW=m | ||
813 | # CONFIG_BRIDGE_NF_EBTABLES is not set | ||
814 | CONFIG_IP_DCCP=m | ||
815 | CONFIG_INET_DCCP_DIAG=m | ||
816 | |||
817 | # | ||
818 | # DCCP CCIDs Configuration (EXPERIMENTAL) | ||
819 | # | ||
820 | # CONFIG_IP_DCCP_CCID2_DEBUG is not set | ||
821 | CONFIG_IP_DCCP_CCID3=y | ||
822 | # CONFIG_IP_DCCP_CCID3_DEBUG is not set | ||
823 | CONFIG_IP_DCCP_TFRC_LIB=y | ||
824 | |||
825 | # | ||
826 | # DCCP Kernel Hacking | ||
827 | # | ||
828 | # CONFIG_IP_DCCP_DEBUG is not set | ||
829 | CONFIG_IP_SCTP=m | ||
830 | # CONFIG_SCTP_DBG_MSG is not set | ||
831 | # CONFIG_SCTP_DBG_OBJCNT is not set | ||
832 | # CONFIG_SCTP_HMAC_NONE is not set | ||
833 | # CONFIG_SCTP_HMAC_SHA1 is not set | ||
834 | CONFIG_SCTP_HMAC_MD5=y | ||
835 | # CONFIG_RDS is not set | ||
836 | CONFIG_TIPC=m | ||
837 | # CONFIG_TIPC_ADVANCED is not set | ||
838 | # CONFIG_TIPC_DEBUG is not set | ||
839 | CONFIG_ATM=m | ||
840 | CONFIG_ATM_CLIP=m | ||
841 | # CONFIG_ATM_CLIP_NO_ICMP is not set | ||
842 | CONFIG_ATM_LANE=m | ||
843 | CONFIG_ATM_MPOA=m | ||
844 | CONFIG_ATM_BR2684=m | ||
845 | # CONFIG_ATM_BR2684_IPFILTER is not set | ||
846 | CONFIG_L2TP=m | ||
847 | CONFIG_L2TP_DEBUGFS=m | ||
848 | CONFIG_L2TP_V3=y | ||
849 | CONFIG_L2TP_IP=m | ||
850 | CONFIG_L2TP_ETH=m | ||
851 | CONFIG_STP=m | ||
852 | CONFIG_GARP=m | ||
853 | CONFIG_BRIDGE=m | ||
854 | CONFIG_BRIDGE_IGMP_SNOOPING=y | ||
855 | # CONFIG_NET_DSA is not set | ||
856 | CONFIG_VLAN_8021Q=m | ||
857 | CONFIG_VLAN_8021Q_GVRP=y | ||
858 | # CONFIG_DECNET is not set | ||
859 | CONFIG_LLC=m | ||
860 | # CONFIG_LLC2 is not set | ||
861 | # CONFIG_IPX is not set | ||
862 | # CONFIG_ATALK is not set | ||
863 | # CONFIG_X25 is not set | ||
864 | # CONFIG_LAPB is not set | ||
865 | # CONFIG_ECONET is not set | ||
866 | CONFIG_WAN_ROUTER=m | ||
867 | # CONFIG_PHONET is not set | ||
868 | # CONFIG_IEEE802154 is not set | ||
869 | CONFIG_NET_SCHED=y | ||
870 | |||
871 | # | ||
872 | # Queueing/Scheduling | ||
873 | # | ||
874 | CONFIG_NET_SCH_CBQ=m | ||
875 | CONFIG_NET_SCH_HTB=m | ||
876 | CONFIG_NET_SCH_HFSC=m | ||
877 | CONFIG_NET_SCH_ATM=m | ||
878 | CONFIG_NET_SCH_PRIO=m | ||
879 | CONFIG_NET_SCH_MULTIQ=m | ||
880 | CONFIG_NET_SCH_RED=m | ||
881 | # CONFIG_NET_SCH_SFB is not set | ||
882 | CONFIG_NET_SCH_SFQ=m | ||
883 | CONFIG_NET_SCH_TEQL=m | ||
884 | CONFIG_NET_SCH_TBF=m | ||
885 | CONFIG_NET_SCH_GRED=m | ||
886 | CONFIG_NET_SCH_DSMARK=m | ||
887 | CONFIG_NET_SCH_NETEM=m | ||
888 | CONFIG_NET_SCH_DRR=m | ||
889 | CONFIG_NET_SCH_MQPRIO=m | ||
890 | CONFIG_NET_SCH_CHOKE=m | ||
891 | |||
892 | # | ||
893 | # Classification | ||
894 | # | ||
895 | CONFIG_NET_CLS=y | ||
896 | CONFIG_NET_CLS_BASIC=m | ||
897 | CONFIG_NET_CLS_TCINDEX=m | ||
898 | CONFIG_NET_CLS_ROUTE4=m | ||
899 | CONFIG_NET_CLS_FW=m | ||
900 | CONFIG_NET_CLS_U32=m | ||
901 | CONFIG_CLS_U32_PERF=y | ||
902 | CONFIG_CLS_U32_MARK=y | ||
903 | CONFIG_NET_CLS_RSVP=m | ||
904 | CONFIG_NET_CLS_RSVP6=m | ||
905 | CONFIG_NET_CLS_FLOW=m | ||
906 | CONFIG_NET_CLS_CGROUP=m | ||
907 | # CONFIG_NET_EMATCH is not set | ||
908 | # CONFIG_NET_CLS_ACT is not set | ||
909 | CONFIG_NET_CLS_IND=y | ||
910 | CONFIG_NET_SCH_FIFO=y | ||
911 | # CONFIG_DCB is not set | ||
912 | CONFIG_DNS_RESOLVER=y | ||
913 | # CONFIG_BATMAN_ADV is not set | ||
914 | |||
915 | # | ||
916 | # Network testing | ||
917 | # | ||
918 | # CONFIG_NET_PKTGEN is not set | ||
919 | # CONFIG_HAMRADIO is not set | ||
920 | CONFIG_CAN=m | ||
921 | CONFIG_CAN_RAW=m | ||
922 | CONFIG_CAN_BCM=m | ||
923 | |||
924 | # | ||
925 | # CAN Device Drivers | ||
926 | # | ||
927 | CONFIG_CAN_VCAN=m | ||
928 | CONFIG_CAN_SLCAN=m | ||
929 | # CONFIG_CAN_DEV is not set | ||
930 | # CONFIG_CAN_DEBUG_DEVICES is not set | ||
931 | CONFIG_IRDA=m | ||
932 | |||
933 | # | ||
934 | # IrDA protocols | ||
935 | # | ||
936 | CONFIG_IRLAN=m | ||
937 | CONFIG_IRNET=m | ||
938 | CONFIG_IRCOMM=m | ||
939 | CONFIG_IRDA_ULTRA=y | ||
940 | |||
941 | # | ||
942 | # IrDA options | ||
943 | # | ||
944 | CONFIG_IRDA_CACHE_LAST_LSAP=y | ||
945 | CONFIG_IRDA_FAST_RR=y | ||
946 | CONFIG_IRDA_DEBUG=y | ||
947 | |||
948 | # | ||
949 | # Infrared-port device drivers | ||
950 | # | ||
951 | |||
952 | # | ||
953 | # SIR device drivers | ||
954 | # | ||
955 | CONFIG_IRTTY_SIR=m | ||
956 | |||
957 | # | ||
958 | # Dongle support | ||
959 | # | ||
960 | CONFIG_DONGLE=y | ||
961 | CONFIG_ESI_DONGLE=m | ||
962 | CONFIG_ACTISYS_DONGLE=m | ||
963 | CONFIG_TEKRAM_DONGLE=m | ||
964 | CONFIG_TOIM3232_DONGLE=m | ||
965 | CONFIG_LITELINK_DONGLE=m | ||
966 | CONFIG_MA600_DONGLE=m | ||
967 | CONFIG_GIRBIL_DONGLE=m | ||
968 | CONFIG_MCP2120_DONGLE=m | ||
969 | CONFIG_OLD_BELKIN_DONGLE=m | ||
970 | # CONFIG_ACT200L_DONGLE is not set | ||
971 | CONFIG_KINGSUN_DONGLE=m | ||
972 | CONFIG_KSDAZZLE_DONGLE=m | ||
973 | CONFIG_KS959_DONGLE=m | ||
974 | |||
975 | # | ||
976 | # FIR device drivers | ||
977 | # | ||
978 | CONFIG_USB_IRDA=m | ||
979 | CONFIG_SIGMATEL_FIR=m | ||
980 | CONFIG_MCS_FIR=m | ||
981 | CONFIG_BT=y | ||
982 | CONFIG_BT_L2CAP=y | ||
983 | CONFIG_BT_SCO=y | ||
984 | CONFIG_BT_RFCOMM=m | ||
985 | CONFIG_BT_RFCOMM_TTY=y | ||
986 | CONFIG_BT_BNEP=m | ||
987 | CONFIG_BT_BNEP_MC_FILTER=y | ||
988 | CONFIG_BT_BNEP_PROTO_FILTER=y | ||
989 | CONFIG_BT_HIDP=m | ||
990 | |||
991 | # | ||
992 | # Bluetooth device drivers | ||
993 | # | ||
994 | CONFIG_BT_HCIBTUSB=y | ||
995 | CONFIG_BT_HCIBTSDIO=m | ||
996 | CONFIG_BT_HCIUART=y | ||
997 | CONFIG_BT_HCIUART_H4=y | ||
998 | CONFIG_BT_HCIUART_BCSP=y | ||
999 | CONFIG_BT_HCIUART_ATH3K=y | ||
1000 | CONFIG_BT_HCIUART_LL=y | ||
1001 | CONFIG_BT_HCIBCM203X=m | ||
1002 | CONFIG_BT_HCIBPA10X=m | ||
1003 | CONFIG_BT_HCIBFUSB=m | ||
1004 | # CONFIG_BT_HCIVHCI is not set | ||
1005 | CONFIG_BT_MRVL=m | ||
1006 | # CONFIG_BT_MRVL_SDIO is not set | ||
1007 | CONFIG_BT_ATH3K=m | ||
1008 | CONFIG_BT_WILINK=m | ||
1009 | CONFIG_AF_RXRPC=m | ||
1010 | # CONFIG_AF_RXRPC_DEBUG is not set | ||
1011 | # CONFIG_RXKAD is not set | ||
1012 | CONFIG_FIB_RULES=y | ||
1013 | CONFIG_WIRELESS=y | ||
1014 | CONFIG_WIRELESS_EXT=y | ||
1015 | CONFIG_WEXT_CORE=y | ||
1016 | CONFIG_WEXT_PROC=y | ||
1017 | CONFIG_WEXT_SPY=y | ||
1018 | CONFIG_WEXT_PRIV=y | ||
1019 | CONFIG_CFG80211=m | ||
1020 | CONFIG_NL80211_TESTMODE=y | ||
1021 | # CONFIG_CFG80211_DEVELOPER_WARNINGS is not set | ||
1022 | # CONFIG_CFG80211_REG_DEBUG is not set | ||
1023 | CONFIG_CFG80211_DEFAULT_PS=y | ||
1024 | # CONFIG_CFG80211_DEBUGFS is not set | ||
1025 | # CONFIG_CFG80211_INTERNAL_REGDB is not set | ||
1026 | CONFIG_CFG80211_WEXT=y | ||
1027 | CONFIG_WIRELESS_EXT_SYSFS=y | ||
1028 | CONFIG_LIB80211=y | ||
1029 | CONFIG_LIB80211_CRYPT_WEP=m | ||
1030 | CONFIG_LIB80211_CRYPT_CCMP=m | ||
1031 | CONFIG_LIB80211_CRYPT_TKIP=m | ||
1032 | # CONFIG_LIB80211_DEBUG is not set | ||
1033 | CONFIG_MAC80211=m | ||
1034 | CONFIG_MAC80211_HAS_RC=y | ||
1035 | CONFIG_MAC80211_RC_PID=y | ||
1036 | # CONFIG_MAC80211_RC_MINSTREL is not set | ||
1037 | CONFIG_MAC80211_RC_DEFAULT_PID=y | ||
1038 | CONFIG_MAC80211_RC_DEFAULT="pid" | ||
1039 | # CONFIG_MAC80211_MESH is not set | ||
1040 | CONFIG_MAC80211_LEDS=y | ||
1041 | # CONFIG_MAC80211_DEBUGFS is not set | ||
1042 | # CONFIG_MAC80211_DEBUG_MENU is not set | ||
1043 | CONFIG_WIMAX=m | ||
1044 | CONFIG_WIMAX_DEBUG_LEVEL=8 | ||
1045 | CONFIG_RFKILL=y | ||
1046 | CONFIG_RFKILL_LEDS=y | ||
1047 | CONFIG_RFKILL_INPUT=y | ||
1048 | CONFIG_NET_9P=m | ||
1049 | # CONFIG_NET_9P_DEBUG is not set | ||
1050 | # CONFIG_CAIF is not set | ||
1051 | CONFIG_CEPH_LIB=m | ||
1052 | # CONFIG_CEPH_LIB_PRETTYDEBUG is not set | ||
1053 | |||
1054 | # | ||
1055 | # Device Drivers | ||
1056 | # | ||
1057 | |||
1058 | # | ||
1059 | # Generic Driver Options | ||
1060 | # | ||
1061 | CONFIG_UEVENT_HELPER_PATH="" | ||
1062 | CONFIG_DEVTMPFS=y | ||
1063 | CONFIG_DEVTMPFS_MOUNT=y | ||
1064 | CONFIG_STANDALONE=y | ||
1065 | CONFIG_PREVENT_FIRMWARE_BUILD=y | ||
1066 | CONFIG_FW_LOADER=y | ||
1067 | CONFIG_FIRMWARE_IN_KERNEL=y | ||
1068 | CONFIG_EXTRA_FIRMWARE="" | ||
1069 | # CONFIG_DEBUG_DRIVER is not set | ||
1070 | # CONFIG_DEBUG_DEVRES is not set | ||
1071 | # CONFIG_SYS_HYPERVISOR is not set | ||
1072 | # CONFIG_CONNECTOR is not set | ||
1073 | CONFIG_MTD=y | ||
1074 | # CONFIG_MTD_DEBUG is not set | ||
1075 | # CONFIG_MTD_TESTS is not set | ||
1076 | CONFIG_MTD_PARTITIONS=y | ||
1077 | # CONFIG_MTD_REDBOOT_PARTS is not set | ||
1078 | # CONFIG_MTD_CMDLINE_PARTS is not set | ||
1079 | # CONFIG_MTD_AFS_PARTS is not set | ||
1080 | # CONFIG_MTD_AR7_PARTS is not set | ||
1081 | |||
1082 | # | ||
1083 | # User Modules And Translation Layers | ||
1084 | # | ||
1085 | CONFIG_MTD_CHAR=y | ||
1086 | CONFIG_MTD_BLKDEVS=y | ||
1087 | CONFIG_MTD_BLOCK=y | ||
1088 | # CONFIG_FTL is not set | ||
1089 | # CONFIG_NFTL is not set | ||
1090 | # CONFIG_INFTL is not set | ||
1091 | # CONFIG_RFD_FTL is not set | ||
1092 | # CONFIG_SSFDC is not set | ||
1093 | CONFIG_SM_FTL=m | ||
1094 | # CONFIG_MTD_OOPS is not set | ||
1095 | CONFIG_MTD_SWAP=m | ||
1096 | |||
1097 | # | ||
1098 | # RAM/ROM/Flash chip drivers | ||
1099 | # | ||
1100 | # CONFIG_MTD_CFI is not set | ||
1101 | # CONFIG_MTD_JEDECPROBE is not set | ||
1102 | CONFIG_MTD_MAP_BANK_WIDTH_1=y | ||
1103 | CONFIG_MTD_MAP_BANK_WIDTH_2=y | ||
1104 | CONFIG_MTD_MAP_BANK_WIDTH_4=y | ||
1105 | # CONFIG_MTD_MAP_BANK_WIDTH_8 is not set | ||
1106 | # CONFIG_MTD_MAP_BANK_WIDTH_16 is not set | ||
1107 | # CONFIG_MTD_MAP_BANK_WIDTH_32 is not set | ||
1108 | CONFIG_MTD_CFI_I1=y | ||
1109 | CONFIG_MTD_CFI_I2=y | ||
1110 | # CONFIG_MTD_CFI_I4 is not set | ||
1111 | # CONFIG_MTD_CFI_I8 is not set | ||
1112 | # CONFIG_MTD_RAM is not set | ||
1113 | # CONFIG_MTD_ROM is not set | ||
1114 | # CONFIG_MTD_ABSENT is not set | ||
1115 | |||
1116 | # | ||
1117 | # Mapping drivers for chip access | ||
1118 | # | ||
1119 | # CONFIG_MTD_COMPLEX_MAPPINGS is not set | ||
1120 | # CONFIG_MTD_PLATRAM is not set | ||
1121 | |||
1122 | # | ||
1123 | # Self-contained MTD device drivers | ||
1124 | # | ||
1125 | # CONFIG_MTD_DATAFLASH is not set | ||
1126 | # CONFIG_MTD_M25P80 is not set | ||
1127 | # CONFIG_MTD_SST25L is not set | ||
1128 | # CONFIG_MTD_SLRAM is not set | ||
1129 | # CONFIG_MTD_PHRAM is not set | ||
1130 | # CONFIG_MTD_MTDRAM is not set | ||
1131 | # CONFIG_MTD_BLOCK2MTD is not set | ||
1132 | |||
1133 | # | ||
1134 | # Disk-On-Chip Device Drivers | ||
1135 | # | ||
1136 | # CONFIG_MTD_DOC2000 is not set | ||
1137 | # CONFIG_MTD_DOC2001 is not set | ||
1138 | # CONFIG_MTD_DOC2001PLUS is not set | ||
1139 | CONFIG_MTD_NAND_ECC=y | ||
1140 | # CONFIG_MTD_NAND_ECC_SMC is not set | ||
1141 | CONFIG_MTD_NAND=y | ||
1142 | # CONFIG_MTD_NAND_VERIFY_WRITE is not set | ||
1143 | # CONFIG_MTD_NAND_ECC_BCH is not set | ||
1144 | # CONFIG_MTD_SM_COMMON is not set | ||
1145 | # CONFIG_MTD_NAND_MUSEUM_IDS is not set | ||
1146 | # CONFIG_MTD_NAND_GPIO is not set | ||
1147 | CONFIG_MTD_NAND_OMAP2=y | ||
1148 | CONFIG_MTD_NAND_IDS=y | ||
1149 | # CONFIG_MTD_NAND_DISKONCHIP is not set | ||
1150 | # CONFIG_MTD_NAND_NANDSIM is not set | ||
1151 | CONFIG_MTD_NAND_PLATFORM=y | ||
1152 | # CONFIG_MTD_ALAUDA is not set | ||
1153 | # CONFIG_MTD_ONENAND is not set | ||
1154 | |||
1155 | # | ||
1156 | # LPDDR flash memory drivers | ||
1157 | # | ||
1158 | # CONFIG_MTD_LPDDR is not set | ||
1159 | CONFIG_MTD_UBI=y | ||
1160 | CONFIG_MTD_UBI_WL_THRESHOLD=4096 | ||
1161 | CONFIG_MTD_UBI_BEB_RESERVE=1 | ||
1162 | # CONFIG_MTD_UBI_GLUEBI is not set | ||
1163 | # CONFIG_MTD_UBI_DEBUG is not set | ||
1164 | # CONFIG_PARPORT is not set | ||
1165 | CONFIG_BLK_DEV=y | ||
1166 | # CONFIG_BLK_DEV_COW_COMMON is not set | ||
1167 | CONFIG_BLK_DEV_LOOP=y | ||
1168 | CONFIG_BLK_DEV_CRYPTOLOOP=m | ||
1169 | |||
1170 | # | ||
1171 | # DRBD disabled because PROC_FS, INET or CONNECTOR not selected | ||
1172 | # | ||
1173 | # CONFIG_BLK_DEV_NBD is not set | ||
1174 | # CONFIG_BLK_DEV_UB is not set | ||
1175 | CONFIG_BLK_DEV_RAM=y | ||
1176 | CONFIG_BLK_DEV_RAM_COUNT=16 | ||
1177 | CONFIG_BLK_DEV_RAM_SIZE=16384 | ||
1178 | # CONFIG_BLK_DEV_XIP is not set | ||
1179 | CONFIG_CDROM_PKTCDVD=m | ||
1180 | CONFIG_CDROM_PKTCDVD_BUFFERS=8 | ||
1181 | # CONFIG_CDROM_PKTCDVD_WCACHE is not set | ||
1182 | # CONFIG_ATA_OVER_ETH is not set | ||
1183 | # CONFIG_MG_DISK is not set | ||
1184 | # CONFIG_BLK_DEV_RBD is not set | ||
1185 | # CONFIG_SENSORS_LIS3LV02D is not set | ||
1186 | CONFIG_MISC_DEVICES=y | ||
1187 | # CONFIG_AD525X_DPOT is not set | ||
1188 | # CONFIG_ICS932S401 is not set | ||
1189 | # CONFIG_ENCLOSURE_SERVICES is not set | ||
1190 | # CONFIG_APDS9802ALS is not set | ||
1191 | # CONFIG_ISL29003 is not set | ||
1192 | # CONFIG_ISL29020 is not set | ||
1193 | # CONFIG_SENSORS_TSL2550 is not set | ||
1194 | CONFIG_SENSORS_BH1780=m | ||
1195 | # CONFIG_SENSORS_BH1770 is not set | ||
1196 | # CONFIG_SENSORS_APDS990X is not set | ||
1197 | CONFIG_HMC6352=m | ||
1198 | # CONFIG_DS1682 is not set | ||
1199 | # CONFIG_TI_DAC7512 is not set | ||
1200 | CONFIG_BMP085=m | ||
1201 | # CONFIG_C2PORT is not set | ||
1202 | |||
1203 | # | ||
1204 | # EEPROM support | ||
1205 | # | ||
1206 | CONFIG_EEPROM_AT24=m | ||
1207 | # CONFIG_EEPROM_AT25 is not set | ||
1208 | # CONFIG_EEPROM_LEGACY is not set | ||
1209 | # CONFIG_EEPROM_MAX6875 is not set | ||
1210 | CONFIG_EEPROM_93CX6=y | ||
1211 | CONFIG_IWMC3200TOP=m | ||
1212 | # CONFIG_IWMC3200TOP_DEBUG is not set | ||
1213 | # CONFIG_IWMC3200TOP_DEBUGFS is not set | ||
1214 | |||
1215 | # | ||
1216 | # Texas Instruments shared transport line discipline | ||
1217 | # | ||
1218 | CONFIG_TI_ST=m | ||
1219 | # CONFIG_SENSORS_LIS3_SPI is not set | ||
1220 | # CONFIG_SENSORS_LIS3_I2C is not set | ||
1221 | CONFIG_HAVE_IDE=y | ||
1222 | # CONFIG_IDE is not set | ||
1223 | |||
1224 | # | ||
1225 | # SCSI device support | ||
1226 | # | ||
1227 | CONFIG_SCSI_MOD=y | ||
1228 | CONFIG_RAID_ATTRS=m | ||
1229 | CONFIG_SCSI=y | ||
1230 | CONFIG_SCSI_DMA=y | ||
1231 | # CONFIG_SCSI_TGT is not set | ||
1232 | # CONFIG_SCSI_NETLINK is not set | ||
1233 | CONFIG_SCSI_PROC_FS=y | ||
1234 | |||
1235 | # | ||
1236 | # SCSI support type (disk, tape, CD-ROM) | ||
1237 | # | ||
1238 | CONFIG_BLK_DEV_SD=y | ||
1239 | # CONFIG_CHR_DEV_ST is not set | ||
1240 | # CONFIG_CHR_DEV_OSST is not set | ||
1241 | CONFIG_BLK_DEV_SR=y | ||
1242 | CONFIG_BLK_DEV_SR_VENDOR=y | ||
1243 | CONFIG_CHR_DEV_SG=y | ||
1244 | CONFIG_CHR_DEV_SCH=m | ||
1245 | CONFIG_SCSI_MULTI_LUN=y | ||
1246 | # CONFIG_SCSI_CONSTANTS is not set | ||
1247 | # CONFIG_SCSI_LOGGING is not set | ||
1248 | # CONFIG_SCSI_SCAN_ASYNC is not set | ||
1249 | CONFIG_SCSI_WAIT_SCAN=m | ||
1250 | |||
1251 | # | ||
1252 | # SCSI Transports | ||
1253 | # | ||
1254 | # CONFIG_SCSI_SPI_ATTRS is not set | ||
1255 | # CONFIG_SCSI_FC_ATTRS is not set | ||
1256 | CONFIG_SCSI_ISCSI_ATTRS=m | ||
1257 | # CONFIG_SCSI_SAS_ATTRS is not set | ||
1258 | # CONFIG_SCSI_SAS_LIBSAS is not set | ||
1259 | # CONFIG_SCSI_SRP_ATTRS is not set | ||
1260 | CONFIG_SCSI_LOWLEVEL=y | ||
1261 | CONFIG_ISCSI_TCP=m | ||
1262 | CONFIG_ISCSI_BOOT_SYSFS=m | ||
1263 | # CONFIG_LIBFC is not set | ||
1264 | # CONFIG_LIBFCOE is not set | ||
1265 | # CONFIG_SCSI_DEBUG is not set | ||
1266 | # CONFIG_SCSI_DH is not set | ||
1267 | # CONFIG_SCSI_OSD_INITIATOR is not set | ||
1268 | # CONFIG_ATA is not set | ||
1269 | CONFIG_MD=y | ||
1270 | CONFIG_BLK_DEV_MD=m | ||
1271 | CONFIG_MD_LINEAR=m | ||
1272 | CONFIG_MD_RAID0=m | ||
1273 | CONFIG_MD_RAID1=m | ||
1274 | CONFIG_MD_RAID10=m | ||
1275 | CONFIG_MD_RAID456=m | ||
1276 | CONFIG_MD_MULTIPATH=m | ||
1277 | CONFIG_MD_FAULTY=m | ||
1278 | CONFIG_BLK_DEV_DM=m | ||
1279 | # CONFIG_DM_DEBUG is not set | ||
1280 | CONFIG_DM_CRYPT=m | ||
1281 | CONFIG_DM_SNAPSHOT=m | ||
1282 | CONFIG_DM_MIRROR=m | ||
1283 | CONFIG_DM_RAID=m | ||
1284 | # CONFIG_DM_LOG_USERSPACE is not set | ||
1285 | CONFIG_DM_ZERO=m | ||
1286 | CONFIG_DM_MULTIPATH=m | ||
1287 | # CONFIG_DM_MULTIPATH_QL is not set | ||
1288 | # CONFIG_DM_MULTIPATH_ST is not set | ||
1289 | CONFIG_DM_DELAY=m | ||
1290 | # CONFIG_DM_UEVENT is not set | ||
1291 | CONFIG_DM_FLAKEY=m | ||
1292 | CONFIG_TARGET_CORE=m | ||
1293 | CONFIG_TCM_IBLOCK=m | ||
1294 | CONFIG_TCM_FILEIO=m | ||
1295 | CONFIG_TCM_PSCSI=m | ||
1296 | CONFIG_LOOPBACK_TARGET=m | ||
1297 | # CONFIG_LOOPBACK_TARGET_CDB_DEBUG is not set | ||
1298 | CONFIG_NETDEVICES=y | ||
1299 | CONFIG_DUMMY=m | ||
1300 | CONFIG_BONDING=m | ||
1301 | CONFIG_MACVLAN=m | ||
1302 | CONFIG_MACVTAP=m | ||
1303 | CONFIG_EQUALIZER=m | ||
1304 | CONFIG_TUN=m | ||
1305 | CONFIG_VETH=m | ||
1306 | CONFIG_MII=y | ||
1307 | CONFIG_PHYLIB=y | ||
1308 | |||
1309 | # | ||
1310 | # MII PHY device drivers | ||
1311 | # | ||
1312 | # CONFIG_MARVELL_PHY is not set | ||
1313 | # CONFIG_DAVICOM_PHY is not set | ||
1314 | # CONFIG_QSEMI_PHY is not set | ||
1315 | # CONFIG_LXT_PHY is not set | ||
1316 | # CONFIG_CICADA_PHY is not set | ||
1317 | # CONFIG_VITESSE_PHY is not set | ||
1318 | # CONFIG_SMSC_PHY is not set | ||
1319 | # CONFIG_BROADCOM_PHY is not set | ||
1320 | CONFIG_BCM63XX_PHY=m | ||
1321 | # CONFIG_ICPLUS_PHY is not set | ||
1322 | # CONFIG_REALTEK_PHY is not set | ||
1323 | # CONFIG_NATIONAL_PHY is not set | ||
1324 | # CONFIG_STE10XP is not set | ||
1325 | # CONFIG_LSI_ET1011C_PHY is not set | ||
1326 | CONFIG_MICREL_PHY=m | ||
1327 | # CONFIG_FIXED_PHY is not set | ||
1328 | # CONFIG_MDIO_BITBANG is not set | ||
1329 | CONFIG_NET_ETHERNET=y | ||
1330 | # CONFIG_AX88796 is not set | ||
1331 | CONFIG_SMC91X=y | ||
1332 | # CONFIG_TI_DAVINCI_EMAC is not set | ||
1333 | CONFIG_TI_DAVINCI_MDIO=m | ||
1334 | CONFIG_TI_DAVINCI_CPDMA=m | ||
1335 | # CONFIG_DM9000 is not set | ||
1336 | CONFIG_ENC28J60=y | ||
1337 | # CONFIG_ENC28J60_WRITEVERIFY is not set | ||
1338 | # CONFIG_ETHOC is not set | ||
1339 | CONFIG_SMC911X=y | ||
1340 | CONFIG_SMSC911X=y | ||
1341 | # CONFIG_SMSC911X_ARCH_HOOKS is not set | ||
1342 | # CONFIG_DNET is not set | ||
1343 | # CONFIG_IBM_NEW_EMAC_ZMII is not set | ||
1344 | # CONFIG_IBM_NEW_EMAC_RGMII is not set | ||
1345 | # CONFIG_IBM_NEW_EMAC_TAH is not set | ||
1346 | # CONFIG_IBM_NEW_EMAC_EMAC4 is not set | ||
1347 | # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set | ||
1348 | # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set | ||
1349 | # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set | ||
1350 | # CONFIG_B44 is not set | ||
1351 | CONFIG_KS8842=m | ||
1352 | CONFIG_KS8851=y | ||
1353 | # CONFIG_KS8851_MLL is not set | ||
1354 | # CONFIG_FTMAC100 is not set | ||
1355 | # CONFIG_NETDEV_1000 is not set | ||
1356 | # CONFIG_NETDEV_10000 is not set | ||
1357 | CONFIG_WLAN=y | ||
1358 | # CONFIG_LIBERTAS_THINFIRM is not set | ||
1359 | CONFIG_AT76C50X_USB=m | ||
1360 | CONFIG_USB_ZD1201=m | ||
1361 | CONFIG_USB_NET_RNDIS_WLAN=m | ||
1362 | CONFIG_RTL8187=m | ||
1363 | CONFIG_RTL8187_LEDS=y | ||
1364 | # CONFIG_MAC80211_HWSIM is not set | ||
1365 | # CONFIG_ATH_COMMON is not set | ||
1366 | CONFIG_B43=m | ||
1367 | # CONFIG_B43_SDIO is not set | ||
1368 | CONFIG_B43_PIO=y | ||
1369 | CONFIG_B43_PHY_N=y | ||
1370 | CONFIG_B43_PHY_LP=y | ||
1371 | CONFIG_B43_LEDS=y | ||
1372 | CONFIG_B43_HWRNG=y | ||
1373 | # CONFIG_B43_DEBUG is not set | ||
1374 | # CONFIG_B43LEGACY is not set | ||
1375 | CONFIG_HOSTAP=m | ||
1376 | CONFIG_HOSTAP_FIRMWARE=y | ||
1377 | CONFIG_HOSTAP_FIRMWARE_NVRAM=y | ||
1378 | # CONFIG_IWM is not set | ||
1379 | CONFIG_LIBERTAS=m | ||
1380 | CONFIG_LIBERTAS_USB=m | ||
1381 | # CONFIG_LIBERTAS_SDIO is not set | ||
1382 | # CONFIG_LIBERTAS_SPI is not set | ||
1383 | # CONFIG_LIBERTAS_DEBUG is not set | ||
1384 | # CONFIG_LIBERTAS_MESH is not set | ||
1385 | CONFIG_P54_COMMON=m | ||
1386 | CONFIG_P54_USB=m | ||
1387 | # CONFIG_P54_SPI is not set | ||
1388 | CONFIG_P54_LEDS=y | ||
1389 | CONFIG_RT2X00=m | ||
1390 | CONFIG_RT2500USB=m | ||
1391 | CONFIG_RT73USB=m | ||
1392 | # CONFIG_RT2800USB is not set | ||
1393 | CONFIG_RT2X00_LIB_USB=m | ||
1394 | CONFIG_RT2X00_LIB=m | ||
1395 | CONFIG_RT2X00_LIB_FIRMWARE=y | ||
1396 | CONFIG_RT2X00_LIB_CRYPTO=y | ||
1397 | CONFIG_RT2X00_LIB_LEDS=y | ||
1398 | # CONFIG_RT2X00_DEBUG is not set | ||
1399 | CONFIG_RTL8192CU=m | ||
1400 | CONFIG_RTLWIFI=m | ||
1401 | CONFIG_RTL8192C_COMMON=m | ||
1402 | CONFIG_WL1251=m | ||
1403 | CONFIG_WL1251_SPI=m | ||
1404 | CONFIG_WL1251_SDIO=m | ||
1405 | CONFIG_WL12XX_MENU=m | ||
1406 | CONFIG_WL12XX=m | ||
1407 | CONFIG_WL12XX_HT=y | ||
1408 | CONFIG_WL12XX_SPI=m | ||
1409 | CONFIG_WL12XX_SDIO=m | ||
1410 | # CONFIG_WL12XX_SDIO_TEST is not set | ||
1411 | CONFIG_WL12XX_PLATFORM_DATA=y | ||
1412 | CONFIG_ZD1211RW=m | ||
1413 | # CONFIG_ZD1211RW_DEBUG is not set | ||
1414 | |||
1415 | # | ||
1416 | # WiMAX Wireless Broadband devices | ||
1417 | # | ||
1418 | CONFIG_WIMAX_I2400M=m | ||
1419 | CONFIG_WIMAX_I2400M_USB=m | ||
1420 | CONFIG_WIMAX_I2400M_SDIO=m | ||
1421 | CONFIG_WIMAX_IWMC3200_SDIO=y | ||
1422 | CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8 | ||
1423 | |||
1424 | # | ||
1425 | # USB Network Adapters | ||
1426 | # | ||
1427 | CONFIG_USB_CATC=y | ||
1428 | CONFIG_USB_KAWETH=y | ||
1429 | CONFIG_USB_PEGASUS=y | ||
1430 | CONFIG_USB_RTL8150=y | ||
1431 | CONFIG_USB_USBNET=y | ||
1432 | CONFIG_USB_NET_AX8817X=y | ||
1433 | CONFIG_USB_NET_CDCETHER=y | ||
1434 | # CONFIG_USB_NET_CDC_EEM is not set | ||
1435 | CONFIG_USB_NET_CDC_NCM=m | ||
1436 | CONFIG_USB_NET_DM9601=y | ||
1437 | CONFIG_USB_NET_SMSC75XX=m | ||
1438 | CONFIG_USB_NET_SMSC95XX=y | ||
1439 | CONFIG_USB_NET_GL620A=y | ||
1440 | CONFIG_USB_NET_NET1080=y | ||
1441 | CONFIG_USB_NET_PLUSB=y | ||
1442 | CONFIG_USB_NET_MCS7830=y | ||
1443 | CONFIG_USB_NET_RNDIS_HOST=y | ||
1444 | CONFIG_USB_NET_CDC_SUBSET=y | ||
1445 | CONFIG_USB_ALI_M5632=y | ||
1446 | CONFIG_USB_AN2720=y | ||
1447 | CONFIG_USB_BELKIN=y | ||
1448 | CONFIG_USB_ARMLINUX=y | ||
1449 | CONFIG_USB_EPSON2888=y | ||
1450 | CONFIG_USB_KC2190=y | ||
1451 | CONFIG_USB_NET_ZAURUS=y | ||
1452 | CONFIG_USB_NET_CX82310_ETH=m | ||
1453 | CONFIG_USB_HSO=m | ||
1454 | CONFIG_USB_NET_INT51X1=m | ||
1455 | CONFIG_USB_IPHETH=m | ||
1456 | CONFIG_USB_SIERRA_NET=m | ||
1457 | CONFIG_USB_VL600=m | ||
1458 | # CONFIG_WAN is not set | ||
1459 | CONFIG_ATM_DRIVERS=y | ||
1460 | # CONFIG_ATM_DUMMY is not set | ||
1461 | # CONFIG_ATM_TCP is not set | ||
1462 | |||
1463 | # | ||
1464 | # CAIF transport drivers | ||
1465 | # | ||
1466 | CONFIG_PPP=m | ||
1467 | CONFIG_PPP_MULTILINK=y | ||
1468 | CONFIG_PPP_FILTER=y | ||
1469 | CONFIG_PPP_ASYNC=m | ||
1470 | CONFIG_PPP_SYNC_TTY=m | ||
1471 | CONFIG_PPP_DEFLATE=m | ||
1472 | CONFIG_PPP_BSDCOMP=m | ||
1473 | CONFIG_PPP_MPPE=m | ||
1474 | CONFIG_PPPOE=m | ||
1475 | CONFIG_PPTP=m | ||
1476 | # CONFIG_PPPOATM is not set | ||
1477 | CONFIG_PPPOL2TP=m | ||
1478 | # CONFIG_SLIP is not set | ||
1479 | CONFIG_SLHC=m | ||
1480 | CONFIG_NETCONSOLE=m | ||
1481 | CONFIG_NETCONSOLE_DYNAMIC=y | ||
1482 | CONFIG_NETPOLL=y | ||
1483 | CONFIG_NETPOLL_TRAP=y | ||
1484 | CONFIG_NET_POLL_CONTROLLER=y | ||
1485 | # CONFIG_ISDN is not set | ||
1486 | # CONFIG_PHONE is not set | ||
1487 | |||
1488 | # | ||
1489 | # Input device support | ||
1490 | # | ||
1491 | CONFIG_INPUT=y | ||
1492 | CONFIG_INPUT_FF_MEMLESS=y | ||
1493 | CONFIG_INPUT_POLLDEV=y | ||
1494 | # CONFIG_INPUT_SPARSEKMAP is not set | ||
1495 | |||
1496 | # | ||
1497 | # Userland interfaces | ||
1498 | # | ||
1499 | CONFIG_INPUT_MOUSEDEV=y | ||
1500 | CONFIG_INPUT_MOUSEDEV_PSAUX=y | ||
1501 | CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 | ||
1502 | CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 | ||
1503 | # CONFIG_INPUT_JOYDEV is not set | ||
1504 | CONFIG_INPUT_EVDEV=y | ||
1505 | # CONFIG_INPUT_EVBUG is not set | ||
1506 | |||
1507 | # | ||
1508 | # Input Device Drivers | ||
1509 | # | ||
1510 | CONFIG_INPUT_KEYBOARD=y | ||
1511 | # CONFIG_KEYBOARD_ADP5588 is not set | ||
1512 | # CONFIG_KEYBOARD_ATKBD is not set | ||
1513 | CONFIG_KEYBOARD_QT1070=m | ||
1514 | CONFIG_KEYBOARD_QT2160=m | ||
1515 | # CONFIG_KEYBOARD_LKKBD is not set | ||
1516 | CONFIG_KEYBOARD_GPIO=y | ||
1517 | # CONFIG_KEYBOARD_TCA6416 is not set | ||
1518 | # CONFIG_KEYBOARD_MATRIX is not set | ||
1519 | # CONFIG_KEYBOARD_LM8323 is not set | ||
1520 | # CONFIG_KEYBOARD_MAX7359 is not set | ||
1521 | CONFIG_KEYBOARD_MCS=m | ||
1522 | # CONFIG_KEYBOARD_NEWTON is not set | ||
1523 | # CONFIG_KEYBOARD_OPENCORES is not set | ||
1524 | # CONFIG_KEYBOARD_STOWAWAY is not set | ||
1525 | # CONFIG_KEYBOARD_SUNKBD is not set | ||
1526 | # CONFIG_KEYBOARD_TWL4030 is not set | ||
1527 | # CONFIG_KEYBOARD_XTKBD is not set | ||
1528 | CONFIG_INPUT_MOUSE=y | ||
1529 | CONFIG_MOUSE_PS2=y | ||
1530 | CONFIG_MOUSE_PS2_ALPS=y | ||
1531 | CONFIG_MOUSE_PS2_LOGIPS2PP=y | ||
1532 | CONFIG_MOUSE_PS2_SYNAPTICS=y | ||
1533 | CONFIG_MOUSE_PS2_TRACKPOINT=y | ||
1534 | # CONFIG_MOUSE_PS2_ELANTECH is not set | ||
1535 | # CONFIG_MOUSE_PS2_SENTELIC is not set | ||
1536 | # CONFIG_MOUSE_PS2_TOUCHKIT is not set | ||
1537 | # CONFIG_MOUSE_SERIAL is not set | ||
1538 | # CONFIG_MOUSE_APPLETOUCH is not set | ||
1539 | # CONFIG_MOUSE_BCM5974 is not set | ||
1540 | # CONFIG_MOUSE_VSXXXAA is not set | ||
1541 | # CONFIG_MOUSE_GPIO is not set | ||
1542 | # CONFIG_MOUSE_SYNAPTICS_I2C is not set | ||
1543 | # CONFIG_INPUT_JOYSTICK is not set | ||
1544 | # CONFIG_INPUT_TABLET is not set | ||
1545 | # CONFIG_INPUT_TOUCHSCREEN is not set | ||
1546 | CONFIG_INPUT_MISC=y | ||
1547 | CONFIG_INPUT_AD714X=m | ||
1548 | CONFIG_INPUT_AD714X_I2C=m | ||
1549 | CONFIG_INPUT_AD714X_SPI=m | ||
1550 | # CONFIG_INPUT_ATI_REMOTE is not set | ||
1551 | # CONFIG_INPUT_ATI_REMOTE2 is not set | ||
1552 | # CONFIG_INPUT_KEYSPAN_REMOTE is not set | ||
1553 | # CONFIG_INPUT_POWERMATE is not set | ||
1554 | # CONFIG_INPUT_YEALINK is not set | ||
1555 | # CONFIG_INPUT_CM109 is not set | ||
1556 | CONFIG_INPUT_TWL4030_PWRBUTTON=y | ||
1557 | CONFIG_INPUT_TWL4030_VIBRA=m | ||
1558 | CONFIG_INPUT_UINPUT=y | ||
1559 | CONFIG_INPUT_PCF8574=m | ||
1560 | CONFIG_INPUT_PWM_BEEPER=m | ||
1561 | # CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set | ||
1562 | CONFIG_INPUT_ADXL34X=m | ||
1563 | CONFIG_INPUT_ADXL34X_I2C=m | ||
1564 | CONFIG_INPUT_ADXL34X_SPI=m | ||
1565 | CONFIG_INPUT_CMA3000=m | ||
1566 | CONFIG_INPUT_CMA3000_I2C=m | ||
1567 | |||
1568 | # | ||
1569 | # Hardware I/O ports | ||
1570 | # | ||
1571 | CONFIG_SERIO=y | ||
1572 | CONFIG_SERIO_SERPORT=y | ||
1573 | CONFIG_SERIO_LIBPS2=y | ||
1574 | # CONFIG_SERIO_RAW is not set | ||
1575 | # CONFIG_SERIO_ALTERA_PS2 is not set | ||
1576 | # CONFIG_SERIO_PS2MULT is not set | ||
1577 | # CONFIG_GAMEPORT is not set | ||
1578 | |||
1579 | # | ||
1580 | # Character devices | ||
1581 | # | ||
1582 | CONFIG_VT=y | ||
1583 | CONFIG_CONSOLE_TRANSLATIONS=y | ||
1584 | CONFIG_VT_CONSOLE=y | ||
1585 | CONFIG_HW_CONSOLE=y | ||
1586 | CONFIG_VT_HW_CONSOLE_BINDING=y | ||
1587 | CONFIG_UNIX98_PTYS=y | ||
1588 | # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set | ||
1589 | # CONFIG_LEGACY_PTYS is not set | ||
1590 | # CONFIG_SERIAL_NONSTANDARD is not set | ||
1591 | CONFIG_N_GSM=m | ||
1592 | CONFIG_DEVKMEM=y | ||
1593 | |||
1594 | # | ||
1595 | # Serial drivers | ||
1596 | # | ||
1597 | CONFIG_SERIAL_8250=y | ||
1598 | CONFIG_SERIAL_8250_CONSOLE=y | ||
1599 | CONFIG_SERIAL_8250_NR_UARTS=32 | ||
1600 | CONFIG_SERIAL_8250_RUNTIME_UARTS=4 | ||
1601 | CONFIG_SERIAL_8250_EXTENDED=y | ||
1602 | CONFIG_SERIAL_8250_MANY_PORTS=y | ||
1603 | CONFIG_SERIAL_8250_SHARE_IRQ=y | ||
1604 | CONFIG_SERIAL_8250_DETECT_IRQ=y | ||
1605 | CONFIG_SERIAL_8250_RSA=y | ||
1606 | |||
1607 | # | ||
1608 | # Non-8250 serial port support | ||
1609 | # | ||
1610 | # CONFIG_SERIAL_MAX3100 is not set | ||
1611 | # CONFIG_SERIAL_MAX3107 is not set | ||
1612 | CONFIG_SERIAL_CORE=y | ||
1613 | CONFIG_SERIAL_CORE_CONSOLE=y | ||
1614 | CONFIG_SERIAL_OMAP=y | ||
1615 | CONFIG_SERIAL_OMAP_CONSOLE=y | ||
1616 | # CONFIG_SERIAL_TIMBERDALE is not set | ||
1617 | # CONFIG_SERIAL_ALTERA_JTAGUART is not set | ||
1618 | # CONFIG_SERIAL_ALTERA_UART is not set | ||
1619 | CONFIG_SERIAL_IFX6X60=m | ||
1620 | CONFIG_TTY_PRINTK=y | ||
1621 | # CONFIG_HVC_DCC is not set | ||
1622 | # CONFIG_IPMI_HANDLER is not set | ||
1623 | CONFIG_HW_RANDOM=y | ||
1624 | # CONFIG_HW_RANDOM_TIMERIOMEM is not set | ||
1625 | # CONFIG_R3964 is not set | ||
1626 | # CONFIG_RAW_DRIVER is not set | ||
1627 | # CONFIG_TCG_TPM is not set | ||
1628 | # CONFIG_RAMOOPS is not set | ||
1629 | CONFIG_I2C=y | ||
1630 | CONFIG_I2C_BOARDINFO=y | ||
1631 | CONFIG_I2C_COMPAT=y | ||
1632 | CONFIG_I2C_CHARDEV=y | ||
1633 | CONFIG_I2C_MUX=m | ||
1634 | |||
1635 | # | ||
1636 | # Multiplexer I2C Chip support | ||
1637 | # | ||
1638 | CONFIG_I2C_MUX_GPIO=m | ||
1639 | # CONFIG_I2C_MUX_PCA9541 is not set | ||
1640 | # CONFIG_I2C_MUX_PCA954x is not set | ||
1641 | CONFIG_I2C_HELPER_AUTO=y | ||
1642 | CONFIG_I2C_ALGOBIT=m | ||
1643 | |||
1644 | # | ||
1645 | # I2C Hardware Bus support | ||
1646 | # | ||
1647 | |||
1648 | # | ||
1649 | # I2C system bus drivers (mostly embedded / system-on-chip) | ||
1650 | # | ||
1651 | # CONFIG_I2C_DESIGNWARE is not set | ||
1652 | # CONFIG_I2C_GPIO is not set | ||
1653 | # CONFIG_I2C_OCORES is not set | ||
1654 | CONFIG_I2C_OMAP=y | ||
1655 | # CONFIG_I2C_PCA_PLATFORM is not set | ||
1656 | # CONFIG_I2C_PXA_PCI is not set | ||
1657 | # CONFIG_I2C_SIMTEC is not set | ||
1658 | # CONFIG_I2C_XILINX is not set | ||
1659 | |||
1660 | # | ||
1661 | # External I2C/SMBus adapter drivers | ||
1662 | # | ||
1663 | CONFIG_I2C_DIOLAN_U2C=m | ||
1664 | # CONFIG_I2C_PARPORT_LIGHT is not set | ||
1665 | # CONFIG_I2C_TAOS_EVM is not set | ||
1666 | # CONFIG_I2C_TINY_USB is not set | ||
1667 | |||
1668 | # | ||
1669 | # Other I2C/SMBus bus drivers | ||
1670 | # | ||
1671 | # CONFIG_I2C_STUB is not set | ||
1672 | # CONFIG_I2C_DEBUG_CORE is not set | ||
1673 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
1674 | # CONFIG_I2C_DEBUG_BUS is not set | ||
1675 | CONFIG_SPI=y | ||
1676 | # CONFIG_SPI_DEBUG is not set | ||
1677 | CONFIG_SPI_MASTER=y | ||
1678 | |||
1679 | # | ||
1680 | # SPI Master Controller Drivers | ||
1681 | # | ||
1682 | # CONFIG_SPI_ALTERA is not set | ||
1683 | # CONFIG_SPI_BITBANG is not set | ||
1684 | # CONFIG_SPI_GPIO is not set | ||
1685 | # CONFIG_SPI_OC_TINY is not set | ||
1686 | CONFIG_SPI_OMAP24XX=y | ||
1687 | # CONFIG_SPI_PXA2XX_PCI is not set | ||
1688 | # CONFIG_SPI_XILINX is not set | ||
1689 | # CONFIG_SPI_DESIGNWARE is not set | ||
1690 | |||
1691 | # | ||
1692 | # SPI Protocol Masters | ||
1693 | # | ||
1694 | CONFIG_SPI_SPIDEV=y | ||
1695 | # CONFIG_SPI_TLE62X0 is not set | ||
1696 | |||
1697 | # | ||
1698 | # PPS support | ||
1699 | # | ||
1700 | # CONFIG_PPS is not set | ||
1701 | |||
1702 | # | ||
1703 | # PPS generators support | ||
1704 | # | ||
1705 | CONFIG_ARCH_REQUIRE_GPIOLIB=y | ||
1706 | CONFIG_GPIOLIB=y | ||
1707 | # CONFIG_DEBUG_GPIO is not set | ||
1708 | CONFIG_GPIO_SYSFS=y | ||
1709 | CONFIG_GPIO_MAX730X=m | ||
1710 | |||
1711 | # | ||
1712 | # Memory mapped GPIO expanders: | ||
1713 | # | ||
1714 | # CONFIG_GPIO_BASIC_MMIO is not set | ||
1715 | # CONFIG_GPIO_IT8761E is not set | ||
1716 | |||
1717 | # | ||
1718 | # I2C GPIO expanders: | ||
1719 | # | ||
1720 | CONFIG_GPIO_MAX7300=m | ||
1721 | # CONFIG_GPIO_MAX732X is not set | ||
1722 | # CONFIG_GPIO_PCF857X is not set | ||
1723 | # CONFIG_GPIO_SX150X is not set | ||
1724 | CONFIG_GPIO_TWL4030=y | ||
1725 | CONFIG_GPIO_ADP5588=m | ||
1726 | |||
1727 | # | ||
1728 | # PCI GPIO expanders: | ||
1729 | # | ||
1730 | |||
1731 | # | ||
1732 | # SPI GPIO expanders: | ||
1733 | # | ||
1734 | # CONFIG_GPIO_MAX7301 is not set | ||
1735 | # CONFIG_GPIO_MCP23S08 is not set | ||
1736 | # CONFIG_GPIO_MC33880 is not set | ||
1737 | # CONFIG_GPIO_74X164 is not set | ||
1738 | |||
1739 | # | ||
1740 | # AC97 GPIO expanders: | ||
1741 | # | ||
1742 | |||
1743 | # | ||
1744 | # MODULbus GPIO expanders: | ||
1745 | # | ||
1746 | # CONFIG_W1 is not set | ||
1747 | CONFIG_POWER_SUPPLY=m | ||
1748 | # CONFIG_POWER_SUPPLY_DEBUG is not set | ||
1749 | # CONFIG_PDA_POWER is not set | ||
1750 | CONFIG_TEST_POWER=m | ||
1751 | # CONFIG_BATTERY_DS2782 is not set | ||
1752 | # CONFIG_BATTERY_BQ20Z75 is not set | ||
1753 | # CONFIG_BATTERY_BQ27x00 is not set | ||
1754 | # CONFIG_BATTERY_MAX17040 is not set | ||
1755 | CONFIG_BATTERY_MAX17042=m | ||
1756 | CONFIG_CHARGER_ISP1704=m | ||
1757 | CONFIG_CHARGER_TWL4030=m | ||
1758 | CONFIG_CHARGER_GPIO=m | ||
1759 | CONFIG_HWMON=y | ||
1760 | # CONFIG_HWMON_VID is not set | ||
1761 | # CONFIG_HWMON_DEBUG_CHIP is not set | ||
1762 | |||
1763 | # | ||
1764 | # Native drivers | ||
1765 | # | ||
1766 | # CONFIG_SENSORS_AD7414 is not set | ||
1767 | # CONFIG_SENSORS_AD7418 is not set | ||
1768 | # CONFIG_SENSORS_ADCXX is not set | ||
1769 | # CONFIG_SENSORS_ADM1021 is not set | ||
1770 | # CONFIG_SENSORS_ADM1025 is not set | ||
1771 | # CONFIG_SENSORS_ADM1026 is not set | ||
1772 | # CONFIG_SENSORS_ADM1029 is not set | ||
1773 | # CONFIG_SENSORS_ADM1031 is not set | ||
1774 | # CONFIG_SENSORS_ADM9240 is not set | ||
1775 | CONFIG_SENSORS_ADT7411=m | ||
1776 | # CONFIG_SENSORS_ADT7462 is not set | ||
1777 | # CONFIG_SENSORS_ADT7470 is not set | ||
1778 | # CONFIG_SENSORS_ADT7475 is not set | ||
1779 | CONFIG_SENSORS_ASC7621=m | ||
1780 | # CONFIG_SENSORS_ATXP1 is not set | ||
1781 | CONFIG_SENSORS_DS620=m | ||
1782 | # CONFIG_SENSORS_DS1621 is not set | ||
1783 | # CONFIG_SENSORS_F71805F is not set | ||
1784 | # CONFIG_SENSORS_F71882FG is not set | ||
1785 | # CONFIG_SENSORS_F75375S is not set | ||
1786 | # CONFIG_SENSORS_G760A is not set | ||
1787 | # CONFIG_SENSORS_GL518SM is not set | ||
1788 | # CONFIG_SENSORS_GL520SM is not set | ||
1789 | CONFIG_SENSORS_GPIO_FAN=m | ||
1790 | # CONFIG_SENSORS_IT87 is not set | ||
1791 | CONFIG_SENSORS_JC42=m | ||
1792 | # CONFIG_SENSORS_LINEAGE is not set | ||
1793 | # CONFIG_SENSORS_LM63 is not set | ||
1794 | # CONFIG_SENSORS_LM70 is not set | ||
1795 | # CONFIG_SENSORS_LM73 is not set | ||
1796 | # CONFIG_SENSORS_LM75 is not set | ||
1797 | # CONFIG_SENSORS_LM77 is not set | ||
1798 | # CONFIG_SENSORS_LM78 is not set | ||
1799 | # CONFIG_SENSORS_LM80 is not set | ||
1800 | # CONFIG_SENSORS_LM83 is not set | ||
1801 | # CONFIG_SENSORS_LM85 is not set | ||
1802 | # CONFIG_SENSORS_LM87 is not set | ||
1803 | # CONFIG_SENSORS_LM90 is not set | ||
1804 | # CONFIG_SENSORS_LM92 is not set | ||
1805 | # CONFIG_SENSORS_LM93 is not set | ||
1806 | # CONFIG_SENSORS_LTC4151 is not set | ||
1807 | # CONFIG_SENSORS_LTC4215 is not set | ||
1808 | # CONFIG_SENSORS_LTC4245 is not set | ||
1809 | # CONFIG_SENSORS_LTC4261 is not set | ||
1810 | # CONFIG_SENSORS_LM95241 is not set | ||
1811 | # CONFIG_SENSORS_MAX1111 is not set | ||
1812 | # CONFIG_SENSORS_MAX1619 is not set | ||
1813 | # CONFIG_SENSORS_MAX6639 is not set | ||
1814 | # CONFIG_SENSORS_MAX6650 is not set | ||
1815 | # CONFIG_SENSORS_PC87360 is not set | ||
1816 | # CONFIG_SENSORS_PC87427 is not set | ||
1817 | # CONFIG_SENSORS_PCF8591 is not set | ||
1818 | # CONFIG_PMBUS is not set | ||
1819 | # CONFIG_SENSORS_SHT15 is not set | ||
1820 | # CONFIG_SENSORS_SHT21 is not set | ||
1821 | CONFIG_SENSORS_SMM665=m | ||
1822 | # CONFIG_SENSORS_DME1737 is not set | ||
1823 | CONFIG_SENSORS_EMC1403=m | ||
1824 | CONFIG_SENSORS_EMC2103=m | ||
1825 | # CONFIG_SENSORS_SMSC47M1 is not set | ||
1826 | # CONFIG_SENSORS_SMSC47M192 is not set | ||
1827 | # CONFIG_SENSORS_SMSC47B397 is not set | ||
1828 | # CONFIG_SENSORS_SCH5627 is not set | ||
1829 | # CONFIG_SENSORS_ADS1015 is not set | ||
1830 | # CONFIG_SENSORS_ADS7828 is not set | ||
1831 | CONFIG_SENSORS_ADS7871=m | ||
1832 | CONFIG_SENSORS_AMC6821=m | ||
1833 | # CONFIG_SENSORS_THMC50 is not set | ||
1834 | CONFIG_SENSORS_TMP102=m | ||
1835 | # CONFIG_SENSORS_TMP401 is not set | ||
1836 | # CONFIG_SENSORS_TMP421 is not set | ||
1837 | CONFIG_SENSORS_TWL4030_MADC=m | ||
1838 | # CONFIG_SENSORS_VT1211 is not set | ||
1839 | # CONFIG_SENSORS_W83781D is not set | ||
1840 | # CONFIG_SENSORS_W83791D is not set | ||
1841 | # CONFIG_SENSORS_W83792D is not set | ||
1842 | # CONFIG_SENSORS_W83793 is not set | ||
1843 | # CONFIG_SENSORS_W83795 is not set | ||
1844 | # CONFIG_SENSORS_W83L785TS is not set | ||
1845 | # CONFIG_SENSORS_W83L786NG is not set | ||
1846 | # CONFIG_SENSORS_W83627HF is not set | ||
1847 | # CONFIG_SENSORS_W83627EHF is not set | ||
1848 | CONFIG_THERMAL=y | ||
1849 | CONFIG_THERMAL_HWMON=y | ||
1850 | CONFIG_WATCHDOG=y | ||
1851 | CONFIG_WATCHDOG_NOWAYOUT=y | ||
1852 | |||
1853 | # | ||
1854 | # Watchdog Device Drivers | ||
1855 | # | ||
1856 | # CONFIG_SOFT_WATCHDOG is not set | ||
1857 | CONFIG_OMAP_WATCHDOG=y | ||
1858 | # CONFIG_TWL4030_WATCHDOG is not set | ||
1859 | # CONFIG_MAX63XX_WATCHDOG is not set | ||
1860 | |||
1861 | # | ||
1862 | # USB-based Watchdog Cards | ||
1863 | # | ||
1864 | # CONFIG_USBPCWATCHDOG is not set | ||
1865 | CONFIG_SSB_POSSIBLE=y | ||
1866 | |||
1867 | # | ||
1868 | # Sonics Silicon Backplane | ||
1869 | # | ||
1870 | CONFIG_SSB=y | ||
1871 | CONFIG_SSB_BLOCKIO=y | ||
1872 | CONFIG_SSB_SDIOHOST_POSSIBLE=y | ||
1873 | # CONFIG_SSB_SDIOHOST is not set | ||
1874 | # CONFIG_SSB_SILENT is not set | ||
1875 | # CONFIG_SSB_DEBUG is not set | ||
1876 | CONFIG_MFD_SUPPORT=y | ||
1877 | CONFIG_MFD_CORE=y | ||
1878 | # CONFIG_MFD_88PM860X is not set | ||
1879 | # CONFIG_MFD_SM501 is not set | ||
1880 | # CONFIG_MFD_ASIC3 is not set | ||
1881 | # CONFIG_HTC_EGPIO is not set | ||
1882 | # CONFIG_HTC_PASIC3 is not set | ||
1883 | # CONFIG_HTC_I2CPLD is not set | ||
1884 | CONFIG_TPS6105X=m | ||
1885 | # CONFIG_TPS65010 is not set | ||
1886 | CONFIG_TPS6507X=m | ||
1887 | CONFIG_TWL4030_CORE=y | ||
1888 | CONFIG_TWL4030_MADC=m | ||
1889 | CONFIG_TWL4030_POWER=y | ||
1890 | CONFIG_TWL4030_SCRIPT=y | ||
1891 | CONFIG_TWL4030_CODEC=y | ||
1892 | CONFIG_TWL4030_POWEROFF=y | ||
1893 | CONFIG_TWL6030_PWM=m | ||
1894 | # CONFIG_MFD_STMPE is not set | ||
1895 | # CONFIG_MFD_TC3589X is not set | ||
1896 | # CONFIG_MFD_TMIO is not set | ||
1897 | # CONFIG_MFD_T7L66XB is not set | ||
1898 | # CONFIG_MFD_TC6387XB is not set | ||
1899 | # CONFIG_MFD_TC6393XB is not set | ||
1900 | # CONFIG_PMIC_DA903X is not set | ||
1901 | # CONFIG_PMIC_ADP5520 is not set | ||
1902 | # CONFIG_MFD_MAX8925 is not set | ||
1903 | # CONFIG_MFD_MAX8997 is not set | ||
1904 | # CONFIG_MFD_MAX8998 is not set | ||
1905 | # CONFIG_MFD_WM8400 is not set | ||
1906 | # CONFIG_MFD_WM831X_I2C is not set | ||
1907 | # CONFIG_MFD_WM831X_SPI is not set | ||
1908 | # CONFIG_MFD_WM8350_I2C is not set | ||
1909 | # CONFIG_MFD_WM8994 is not set | ||
1910 | # CONFIG_MFD_PCF50633 is not set | ||
1911 | # CONFIG_MFD_MC13XXX is not set | ||
1912 | # CONFIG_ABX500_CORE is not set | ||
1913 | # CONFIG_EZX_PCAP is not set | ||
1914 | CONFIG_MFD_TPS6586X=y | ||
1915 | CONFIG_MFD_WL1273_CORE=m | ||
1916 | CONFIG_MFD_OMAP_USB_HOST=y | ||
1917 | CONFIG_REGULATOR=y | ||
1918 | # CONFIG_REGULATOR_DEBUG is not set | ||
1919 | CONFIG_REGULATOR_DUMMY=y | ||
1920 | CONFIG_REGULATOR_FIXED_VOLTAGE=y | ||
1921 | # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set | ||
1922 | # CONFIG_REGULATOR_USERSPACE_CONSUMER is not set | ||
1923 | # CONFIG_REGULATOR_BQ24022 is not set | ||
1924 | # CONFIG_REGULATOR_MAX1586 is not set | ||
1925 | # CONFIG_REGULATOR_MAX8649 is not set | ||
1926 | # CONFIG_REGULATOR_MAX8660 is not set | ||
1927 | # CONFIG_REGULATOR_MAX8952 is not set | ||
1928 | CONFIG_REGULATOR_TWL4030=y | ||
1929 | # CONFIG_REGULATOR_LP3971 is not set | ||
1930 | # CONFIG_REGULATOR_LP3972 is not set | ||
1931 | CONFIG_REGULATOR_TPS6105X=m | ||
1932 | # CONFIG_REGULATOR_TPS65023 is not set | ||
1933 | # CONFIG_REGULATOR_TPS6507X is not set | ||
1934 | # CONFIG_REGULATOR_ISL6271A is not set | ||
1935 | # CONFIG_REGULATOR_AD5398 is not set | ||
1936 | CONFIG_REGULATOR_TPS6586X=m | ||
1937 | CONFIG_REGULATOR_TPS6524X=m | ||
1938 | CONFIG_MEDIA_SUPPORT=y | ||
1939 | |||
1940 | # | ||
1941 | # Multimedia core support | ||
1942 | # | ||
1943 | CONFIG_MEDIA_CONTROLLER=y | ||
1944 | CONFIG_VIDEO_DEV=y | ||
1945 | CONFIG_VIDEO_V4L2_COMMON=y | ||
1946 | CONFIG_VIDEO_V4L2_SUBDEV_API=y | ||
1947 | CONFIG_DVB_CORE=m | ||
1948 | CONFIG_VIDEO_MEDIA=m | ||
1949 | |||
1950 | # | ||
1951 | # Multimedia drivers | ||
1952 | # | ||
1953 | CONFIG_RC_CORE=m | ||
1954 | CONFIG_LIRC=m | ||
1955 | CONFIG_RC_MAP=m | ||
1956 | CONFIG_IR_NEC_DECODER=m | ||
1957 | CONFIG_IR_RC5_DECODER=m | ||
1958 | CONFIG_IR_RC6_DECODER=m | ||
1959 | CONFIG_IR_JVC_DECODER=m | ||
1960 | CONFIG_IR_SONY_DECODER=m | ||
1961 | CONFIG_IR_RC5_SZ_DECODER=m | ||
1962 | CONFIG_IR_LIRC_CODEC=m | ||
1963 | # CONFIG_IR_IMON is not set | ||
1964 | # CONFIG_IR_MCEUSB is not set | ||
1965 | # CONFIG_IR_STREAMZAP is not set | ||
1966 | CONFIG_RC_LOOPBACK=m | ||
1967 | CONFIG_MEDIA_ATTACH=y | ||
1968 | CONFIG_MEDIA_TUNER=m | ||
1969 | CONFIG_MEDIA_TUNER_CUSTOMISE=y | ||
1970 | |||
1971 | # | ||
1972 | # Customize TV tuners | ||
1973 | # | ||
1974 | CONFIG_MEDIA_TUNER_SIMPLE=m | ||
1975 | CONFIG_MEDIA_TUNER_TDA8290=m | ||
1976 | CONFIG_MEDIA_TUNER_TDA827X=m | ||
1977 | CONFIG_MEDIA_TUNER_TDA18271=m | ||
1978 | CONFIG_MEDIA_TUNER_TDA9887=m | ||
1979 | CONFIG_MEDIA_TUNER_TEA5761=m | ||
1980 | CONFIG_MEDIA_TUNER_TEA5767=m | ||
1981 | CONFIG_MEDIA_TUNER_MT20XX=m | ||
1982 | CONFIG_MEDIA_TUNER_MT2060=m | ||
1983 | CONFIG_MEDIA_TUNER_MT2266=m | ||
1984 | CONFIG_MEDIA_TUNER_MT2131=m | ||
1985 | CONFIG_MEDIA_TUNER_QT1010=m | ||
1986 | CONFIG_MEDIA_TUNER_XC2028=m | ||
1987 | CONFIG_MEDIA_TUNER_XC5000=m | ||
1988 | CONFIG_MEDIA_TUNER_MXL5005S=m | ||
1989 | CONFIG_MEDIA_TUNER_MXL5007T=m | ||
1990 | CONFIG_MEDIA_TUNER_MC44S803=m | ||
1991 | CONFIG_MEDIA_TUNER_MAX2165=m | ||
1992 | CONFIG_MEDIA_TUNER_TDA18218=m | ||
1993 | CONFIG_VIDEO_V4L2=y | ||
1994 | CONFIG_VIDEOBUF_GEN=y | ||
1995 | CONFIG_VIDEOBUF_VMALLOC=m | ||
1996 | CONFIG_VIDEOBUF_DMA_CONTIG=y | ||
1997 | CONFIG_VIDEOBUF_DVB=m | ||
1998 | CONFIG_VIDEO_TVEEPROM=m | ||
1999 | CONFIG_VIDEO_TUNER=m | ||
2000 | CONFIG_V4L2_MEM2MEM_DEV=m | ||
2001 | CONFIG_VIDEOBUF2_CORE=m | ||
2002 | CONFIG_VIDEOBUF2_MEMOPS=m | ||
2003 | CONFIG_VIDEOBUF2_VMALLOC=m | ||
2004 | CONFIG_VIDEO_CAPTURE_DRIVERS=y | ||
2005 | # CONFIG_VIDEO_ADV_DEBUG is not set | ||
2006 | # CONFIG_VIDEO_FIXED_MINOR_RANGES is not set | ||
2007 | # CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set | ||
2008 | CONFIG_VIDEO_IR_I2C=m | ||
2009 | |||
2010 | # | ||
2011 | # Encoders/decoders and other helper chips | ||
2012 | # | ||
2013 | |||
2014 | # | ||
2015 | # Audio decoders | ||
2016 | # | ||
2017 | # CONFIG_VIDEO_TVAUDIO is not set | ||
2018 | # CONFIG_VIDEO_TDA7432 is not set | ||
2019 | # CONFIG_VIDEO_TDA9840 is not set | ||
2020 | # CONFIG_VIDEO_TEA6415C is not set | ||
2021 | # CONFIG_VIDEO_TEA6420 is not set | ||
2022 | CONFIG_VIDEO_MSP3400=m | ||
2023 | # CONFIG_VIDEO_CS5345 is not set | ||
2024 | CONFIG_VIDEO_CS53L32A=m | ||
2025 | # CONFIG_VIDEO_M52790 is not set | ||
2026 | # CONFIG_VIDEO_TLV320AIC23B is not set | ||
2027 | CONFIG_VIDEO_WM8775=m | ||
2028 | # CONFIG_VIDEO_WM8739 is not set | ||
2029 | # CONFIG_VIDEO_VP27SMPX is not set | ||
2030 | |||
2031 | # | ||
2032 | # RDS decoders | ||
2033 | # | ||
2034 | # CONFIG_VIDEO_SAA6588 is not set | ||
2035 | |||
2036 | # | ||
2037 | # Video decoders | ||
2038 | # | ||
2039 | CONFIG_VIDEO_ADV7180=m | ||
2040 | # CONFIG_VIDEO_BT819 is not set | ||
2041 | # CONFIG_VIDEO_BT856 is not set | ||
2042 | # CONFIG_VIDEO_BT866 is not set | ||
2043 | # CONFIG_VIDEO_KS0127 is not set | ||
2044 | CONFIG_VIDEO_OV7670=m | ||
2045 | CONFIG_VIDEO_MT9P031=y | ||
2046 | CONFIG_VIDEO_MT9V011=m | ||
2047 | CONFIG_VIDEO_MT9V032=y | ||
2048 | # CONFIG_VIDEO_TCM825X is not set | ||
2049 | # CONFIG_VIDEO_SAA7110 is not set | ||
2050 | CONFIG_VIDEO_SAA711X=m | ||
2051 | # CONFIG_VIDEO_SAA717X is not set | ||
2052 | # CONFIG_VIDEO_SAA7191 is not set | ||
2053 | CONFIG_VIDEO_TVP514X=m | ||
2054 | CONFIG_VIDEO_TVP5150=m | ||
2055 | CONFIG_VIDEO_TVP7002=m | ||
2056 | # CONFIG_VIDEO_VPX3220 is not set | ||
2057 | |||
2058 | # | ||
2059 | # Video and audio decoders | ||
2060 | # | ||
2061 | CONFIG_VIDEO_CX25840=m | ||
2062 | |||
2063 | # | ||
2064 | # MPEG video encoders | ||
2065 | # | ||
2066 | CONFIG_VIDEO_CX2341X=m | ||
2067 | |||
2068 | # | ||
2069 | # Video encoders | ||
2070 | # | ||
2071 | # CONFIG_VIDEO_SAA7127 is not set | ||
2072 | # CONFIG_VIDEO_SAA7185 is not set | ||
2073 | # CONFIG_VIDEO_ADV7170 is not set | ||
2074 | # CONFIG_VIDEO_ADV7175 is not set | ||
2075 | # CONFIG_VIDEO_THS7303 is not set | ||
2076 | # CONFIG_VIDEO_ADV7343 is not set | ||
2077 | # CONFIG_VIDEO_AK881X is not set | ||
2078 | |||
2079 | # | ||
2080 | # Video improvement chips | ||
2081 | # | ||
2082 | # CONFIG_VIDEO_UPD64031A is not set | ||
2083 | # CONFIG_VIDEO_UPD64083 is not set | ||
2084 | CONFIG_VIDEO_VIVI=m | ||
2085 | CONFIG_VIDEO_VPSS_SYSTEM=m | ||
2086 | CONFIG_VIDEO_VPFE_CAPTURE=y | ||
2087 | CONFIG_VIDEO_DM6446_CCDC=m | ||
2088 | CONFIG_VIDEO_OMAP2_VOUT=y | ||
2089 | # CONFIG_VIDEO_CPIA2 is not set | ||
2090 | CONFIG_VIDEO_TIMBERDALE=m | ||
2091 | # CONFIG_VIDEO_AU0828 is not set | ||
2092 | CONFIG_VIDEO_SR030PC30=m | ||
2093 | CONFIG_VIDEO_NOON010PC30=m | ||
2094 | CONFIG_VIDEO_OMAP3=y | ||
2095 | CONFIG_VIDEO_OMAP3_DEBUG=y | ||
2096 | # CONFIG_SOC_CAMERA is not set | ||
2097 | CONFIG_V4L_USB_DRIVERS=y | ||
2098 | CONFIG_USB_VIDEO_CLASS=m | ||
2099 | CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y | ||
2100 | CONFIG_USB_GSPCA=m | ||
2101 | CONFIG_USB_M5602=m | ||
2102 | CONFIG_USB_STV06XX=m | ||
2103 | # CONFIG_USB_GL860 is not set | ||
2104 | CONFIG_USB_GSPCA_BENQ=m | ||
2105 | CONFIG_USB_GSPCA_CONEX=m | ||
2106 | CONFIG_USB_GSPCA_CPIA1=m | ||
2107 | CONFIG_USB_GSPCA_ETOMS=m | ||
2108 | CONFIG_USB_GSPCA_FINEPIX=m | ||
2109 | # CONFIG_USB_GSPCA_JEILINJ is not set | ||
2110 | CONFIG_USB_GSPCA_KONICA=m | ||
2111 | CONFIG_USB_GSPCA_MARS=m | ||
2112 | # CONFIG_USB_GSPCA_MR97310A is not set | ||
2113 | CONFIG_USB_GSPCA_NW80X=m | ||
2114 | CONFIG_USB_GSPCA_OV519=m | ||
2115 | CONFIG_USB_GSPCA_OV534=m | ||
2116 | CONFIG_USB_GSPCA_OV534_9=m | ||
2117 | CONFIG_USB_GSPCA_PAC207=m | ||
2118 | # CONFIG_USB_GSPCA_PAC7302 is not set | ||
2119 | CONFIG_USB_GSPCA_PAC7311=m | ||
2120 | CONFIG_USB_GSPCA_SN9C2028=m | ||
2121 | # CONFIG_USB_GSPCA_SN9C20X is not set | ||
2122 | CONFIG_USB_GSPCA_SONIXB=m | ||
2123 | CONFIG_USB_GSPCA_SONIXJ=m | ||
2124 | CONFIG_USB_GSPCA_SPCA500=m | ||
2125 | CONFIG_USB_GSPCA_SPCA501=m | ||
2126 | CONFIG_USB_GSPCA_SPCA505=m | ||
2127 | CONFIG_USB_GSPCA_SPCA506=m | ||
2128 | CONFIG_USB_GSPCA_SPCA508=m | ||
2129 | CONFIG_USB_GSPCA_SPCA561=m | ||
2130 | CONFIG_USB_GSPCA_SPCA1528=m | ||
2131 | # CONFIG_USB_GSPCA_SQ905 is not set | ||
2132 | # CONFIG_USB_GSPCA_SQ905C is not set | ||
2133 | CONFIG_USB_GSPCA_SQ930X=m | ||
2134 | CONFIG_USB_GSPCA_STK014=m | ||
2135 | # CONFIG_USB_GSPCA_STV0680 is not set | ||
2136 | CONFIG_USB_GSPCA_SUNPLUS=m | ||
2137 | CONFIG_USB_GSPCA_T613=m | ||
2138 | CONFIG_USB_GSPCA_TV8532=m | ||
2139 | CONFIG_USB_GSPCA_VC032X=m | ||
2140 | CONFIG_USB_GSPCA_VICAM=m | ||
2141 | CONFIG_USB_GSPCA_XIRLINK_CIT=m | ||
2142 | CONFIG_USB_GSPCA_ZC3XX=m | ||
2143 | CONFIG_VIDEO_PVRUSB2=m | ||
2144 | CONFIG_VIDEO_PVRUSB2_SYSFS=y | ||
2145 | CONFIG_VIDEO_PVRUSB2_DVB=y | ||
2146 | # CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set | ||
2147 | CONFIG_VIDEO_HDPVR=m | ||
2148 | CONFIG_VIDEO_EM28XX=m | ||
2149 | CONFIG_VIDEO_EM28XX_ALSA=m | ||
2150 | CONFIG_VIDEO_EM28XX_DVB=m | ||
2151 | CONFIG_VIDEO_TLG2300=m | ||
2152 | CONFIG_VIDEO_CX231XX=m | ||
2153 | CONFIG_VIDEO_CX231XX_RC=y | ||
2154 | # CONFIG_VIDEO_CX231XX_ALSA is not set | ||
2155 | CONFIG_VIDEO_CX231XX_DVB=m | ||
2156 | CONFIG_VIDEO_USBVISION=m | ||
2157 | CONFIG_USB_ET61X251=m | ||
2158 | CONFIG_USB_SN9C102=m | ||
2159 | CONFIG_USB_PWC=m | ||
2160 | # CONFIG_USB_PWC_DEBUG is not set | ||
2161 | CONFIG_USB_PWC_INPUT_EVDEV=y | ||
2162 | CONFIG_USB_ZR364XX=m | ||
2163 | CONFIG_USB_STKWEBCAM=m | ||
2164 | CONFIG_USB_S2255=m | ||
2165 | CONFIG_V4L_MEM2MEM_DRIVERS=y | ||
2166 | CONFIG_VIDEO_MEM2MEM_TESTDEV=m | ||
2167 | CONFIG_RADIO_ADAPTERS=y | ||
2168 | # CONFIG_I2C_SI4713 is not set | ||
2169 | # CONFIG_RADIO_SI4713 is not set | ||
2170 | # CONFIG_USB_DSBR is not set | ||
2171 | # CONFIG_RADIO_SI470X is not set | ||
2172 | # CONFIG_USB_MR800 is not set | ||
2173 | # CONFIG_RADIO_TEA5764 is not set | ||
2174 | CONFIG_RADIO_SAA7706H=m | ||
2175 | # CONFIG_RADIO_TEF6862 is not set | ||
2176 | CONFIG_RADIO_WL1273=m | ||
2177 | |||
2178 | # | ||
2179 | # Texas Instruments WL128x FM driver (ST based) | ||
2180 | # | ||
2181 | CONFIG_RADIO_WL128X=m | ||
2182 | CONFIG_DVB_MAX_ADAPTERS=8 | ||
2183 | CONFIG_DVB_DYNAMIC_MINORS=y | ||
2184 | CONFIG_DVB_CAPTURE_DRIVERS=y | ||
2185 | # CONFIG_TTPCI_EEPROM is not set | ||
2186 | |||
2187 | # | ||
2188 | # Supported USB Adapters | ||
2189 | # | ||
2190 | CONFIG_DVB_USB=m | ||
2191 | # CONFIG_DVB_USB_DEBUG is not set | ||
2192 | CONFIG_DVB_USB_A800=m | ||
2193 | CONFIG_DVB_USB_DIBUSB_MB=m | ||
2194 | # CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set | ||
2195 | CONFIG_DVB_USB_DIBUSB_MC=m | ||
2196 | CONFIG_DVB_USB_DIB0700=m | ||
2197 | CONFIG_DVB_USB_UMT_010=m | ||
2198 | CONFIG_DVB_USB_CXUSB=m | ||
2199 | CONFIG_DVB_USB_M920X=m | ||
2200 | CONFIG_DVB_USB_GL861=m | ||
2201 | CONFIG_DVB_USB_AU6610=m | ||
2202 | CONFIG_DVB_USB_DIGITV=m | ||
2203 | CONFIG_DVB_USB_VP7045=m | ||
2204 | CONFIG_DVB_USB_VP702X=m | ||
2205 | CONFIG_DVB_USB_GP8PSK=m | ||
2206 | CONFIG_DVB_USB_NOVA_T_USB2=m | ||
2207 | CONFIG_DVB_USB_TTUSB2=m | ||
2208 | CONFIG_DVB_USB_DTT200U=m | ||
2209 | CONFIG_DVB_USB_OPERA1=m | ||
2210 | CONFIG_DVB_USB_AF9005=m | ||
2211 | CONFIG_DVB_USB_AF9005_REMOTE=m | ||
2212 | CONFIG_DVB_USB_DW2102=m | ||
2213 | CONFIG_DVB_USB_CINERGY_T2=m | ||
2214 | CONFIG_DVB_USB_ANYSEE=m | ||
2215 | CONFIG_DVB_USB_DTV5100=m | ||
2216 | CONFIG_DVB_USB_AF9015=m | ||
2217 | # CONFIG_DVB_USB_CE6230 is not set | ||
2218 | # CONFIG_DVB_USB_FRIIO is not set | ||
2219 | # CONFIG_DVB_USB_EC168 is not set | ||
2220 | CONFIG_DVB_USB_AZ6027=m | ||
2221 | CONFIG_DVB_USB_LME2510=m | ||
2222 | CONFIG_DVB_USB_TECHNISAT_USB2=m | ||
2223 | # CONFIG_SMS_SIANO_MDTV is not set | ||
2224 | |||
2225 | # | ||
2226 | # Supported FlexCopII (B2C2) Adapters | ||
2227 | # | ||
2228 | CONFIG_DVB_B2C2_FLEXCOP=m | ||
2229 | CONFIG_DVB_B2C2_FLEXCOP_USB=m | ||
2230 | # CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set | ||
2231 | |||
2232 | # | ||
2233 | # Supported DVB Frontends | ||
2234 | # | ||
2235 | # CONFIG_DVB_FE_CUSTOMISE is not set | ||
2236 | |||
2237 | # | ||
2238 | # Multistandard (satellite) frontends | ||
2239 | # | ||
2240 | CONFIG_DVB_STB0899=m | ||
2241 | CONFIG_DVB_STB6100=m | ||
2242 | CONFIG_DVB_STV090x=m | ||
2243 | CONFIG_DVB_STV6110x=m | ||
2244 | |||
2245 | # | ||
2246 | # DVB-S (satellite) frontends | ||
2247 | # | ||
2248 | CONFIG_DVB_CX24123=m | ||
2249 | CONFIG_DVB_MT312=m | ||
2250 | CONFIG_DVB_ZL10039=m | ||
2251 | CONFIG_DVB_S5H1420=m | ||
2252 | CONFIG_DVB_STV0288=m | ||
2253 | CONFIG_DVB_STB6000=m | ||
2254 | CONFIG_DVB_STV0299=m | ||
2255 | CONFIG_DVB_STV6110=m | ||
2256 | CONFIG_DVB_STV0900=m | ||
2257 | CONFIG_DVB_TDA10086=m | ||
2258 | CONFIG_DVB_TUNER_ITD1000=m | ||
2259 | CONFIG_DVB_TUNER_CX24113=m | ||
2260 | CONFIG_DVB_TDA826X=m | ||
2261 | CONFIG_DVB_CX24116=m | ||
2262 | CONFIG_DVB_SI21XX=m | ||
2263 | CONFIG_DVB_DS3000=m | ||
2264 | |||
2265 | # | ||
2266 | # DVB-T (terrestrial) frontends | ||
2267 | # | ||
2268 | CONFIG_DVB_CX22702=m | ||
2269 | CONFIG_DVB_TDA1004X=m | ||
2270 | CONFIG_DVB_NXT6000=m | ||
2271 | CONFIG_DVB_MT352=m | ||
2272 | CONFIG_DVB_ZL10353=m | ||
2273 | CONFIG_DVB_DIB3000MB=m | ||
2274 | CONFIG_DVB_DIB3000MC=m | ||
2275 | CONFIG_DVB_DIB7000M=m | ||
2276 | CONFIG_DVB_DIB7000P=m | ||
2277 | CONFIG_DVB_TDA10048=m | ||
2278 | CONFIG_DVB_AF9013=m | ||
2279 | |||
2280 | # | ||
2281 | # DVB-C (cable) frontends | ||
2282 | # | ||
2283 | CONFIG_DVB_TDA10023=m | ||
2284 | CONFIG_DVB_STV0297=m | ||
2285 | |||
2286 | # | ||
2287 | # ATSC (North American/Korean Terrestrial/Cable DTV) frontends | ||
2288 | # | ||
2289 | CONFIG_DVB_NXT200X=m | ||
2290 | CONFIG_DVB_BCM3510=m | ||
2291 | CONFIG_DVB_LGDT330X=m | ||
2292 | CONFIG_DVB_LGDT3305=m | ||
2293 | CONFIG_DVB_S5H1409=m | ||
2294 | CONFIG_DVB_S5H1411=m | ||
2295 | |||
2296 | # | ||
2297 | # ISDB-T (terrestrial) frontends | ||
2298 | # | ||
2299 | CONFIG_DVB_S921=m | ||
2300 | CONFIG_DVB_DIB8000=m | ||
2301 | CONFIG_DVB_MB86A20S=m | ||
2302 | |||
2303 | # | ||
2304 | # Digital terrestrial only tuners/PLL | ||
2305 | # | ||
2306 | CONFIG_DVB_PLL=m | ||
2307 | CONFIG_DVB_TUNER_DIB0070=m | ||
2308 | CONFIG_DVB_TUNER_DIB0090=m | ||
2309 | |||
2310 | # | ||
2311 | # SEC control devices for DVB-S | ||
2312 | # | ||
2313 | CONFIG_DVB_LNBP21=m | ||
2314 | CONFIG_DVB_ISL6421=m | ||
2315 | CONFIG_DVB_LGS8GXX=m | ||
2316 | CONFIG_DVB_ATBM8830=m | ||
2317 | CONFIG_DVB_IX2505V=m | ||
2318 | |||
2319 | # | ||
2320 | # Tools to develop new frontends | ||
2321 | # | ||
2322 | # CONFIG_DVB_DUMMY_FE is not set | ||
2323 | |||
2324 | # | ||
2325 | # Graphics support | ||
2326 | # | ||
2327 | CONFIG_DRM=m | ||
2328 | # CONFIG_VGASTATE is not set | ||
2329 | # CONFIG_VIDEO_OUTPUT_CONTROL is not set | ||
2330 | CONFIG_FB=y | ||
2331 | # CONFIG_FIRMWARE_EDID is not set | ||
2332 | # CONFIG_FB_DDC is not set | ||
2333 | # CONFIG_FB_BOOT_VESA_SUPPORT is not set | ||
2334 | CONFIG_FB_CFB_FILLRECT=y | ||
2335 | CONFIG_FB_CFB_COPYAREA=y | ||
2336 | CONFIG_FB_CFB_IMAGEBLIT=y | ||
2337 | # CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set | ||
2338 | CONFIG_FB_SYS_FILLRECT=m | ||
2339 | CONFIG_FB_SYS_COPYAREA=m | ||
2340 | CONFIG_FB_SYS_IMAGEBLIT=m | ||
2341 | # CONFIG_FB_FOREIGN_ENDIAN is not set | ||
2342 | CONFIG_FB_SYS_FOPS=m | ||
2343 | # CONFIG_FB_WMT_GE_ROPS is not set | ||
2344 | CONFIG_FB_DEFERRED_IO=y | ||
2345 | # CONFIG_FB_SVGALIB is not set | ||
2346 | # CONFIG_FB_MACMODES is not set | ||
2347 | # CONFIG_FB_BACKLIGHT is not set | ||
2348 | CONFIG_FB_MODE_HELPERS=y | ||
2349 | # CONFIG_FB_TILEBLITTING is not set | ||
2350 | |||
2351 | # | ||
2352 | # Frame buffer hardware drivers | ||
2353 | # | ||
2354 | # CONFIG_FB_S1D13XXX is not set | ||
2355 | # CONFIG_FB_TMIO is not set | ||
2356 | CONFIG_FB_UDL=m | ||
2357 | # CONFIG_FB_VIRTUAL is not set | ||
2358 | # CONFIG_FB_METRONOME is not set | ||
2359 | # CONFIG_FB_MB862XX is not set | ||
2360 | # CONFIG_FB_BROADSHEET is not set | ||
2361 | # CONFIG_FB_OMAP_BOOTLOADER_INIT is not set | ||
2362 | CONFIG_OMAP2_VRAM=y | ||
2363 | CONFIG_OMAP2_VRFB=y | ||
2364 | CONFIG_OMAP2_DSS=y | ||
2365 | CONFIG_OMAP2_VRAM_SIZE=14 | ||
2366 | CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y | ||
2367 | # CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set | ||
2368 | CONFIG_OMAP2_DSS_DPI=y | ||
2369 | # CONFIG_OMAP2_DSS_RFBI is not set | ||
2370 | CONFIG_OMAP2_DSS_VENC=y | ||
2371 | # CONFIG_OMAP2_DSS_SDI is not set | ||
2372 | CONFIG_OMAP2_DSS_DSI=y | ||
2373 | CONFIG_OMAP2_DSS_USE_DSI_PLL=y | ||
2374 | # CONFIG_OMAP2_DSS_FAKE_VSYNC is not set | ||
2375 | CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 | ||
2376 | CONFIG_FB_OMAP2=y | ||
2377 | CONFIG_FB_OMAP2_DEBUG_SUPPORT=y | ||
2378 | CONFIG_FB_OMAP2_NUM_FBS=2 | ||
2379 | |||
2380 | # | ||
2381 | # OMAP2/3 Display Device Drivers | ||
2382 | # | ||
2383 | CONFIG_PANEL_GENERIC_DPI=y | ||
2384 | # CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set | ||
2385 | CONFIG_PANEL_SHARP_LS037V7DW01=y | ||
2386 | CONFIG_PANEL_NEC_NL8048HL11_01B=y | ||
2387 | # CONFIG_PANEL_TAAL is not set | ||
2388 | CONFIG_PANEL_TPO_TD043MTEA1=m | ||
2389 | # CONFIG_BACKLIGHT_LCD_SUPPORT is not set | ||
2390 | CONFIG_BACKLIGHT_CLASS_DEVICE=y | ||
2391 | |||
2392 | # | ||
2393 | # Display device support | ||
2394 | # | ||
2395 | CONFIG_DISPLAY_SUPPORT=y | ||
2396 | |||
2397 | # | ||
2398 | # Display hardware drivers | ||
2399 | # | ||
2400 | |||
2401 | # | ||
2402 | # Console display driver support | ||
2403 | # | ||
2404 | CONFIG_DUMMY_CONSOLE=y | ||
2405 | CONFIG_FRAMEBUFFER_CONSOLE=y | ||
2406 | # CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set | ||
2407 | CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y | ||
2408 | # CONFIG_FONTS is not set | ||
2409 | CONFIG_FONT_8x8=y | ||
2410 | CONFIG_FONT_8x16=y | ||
2411 | CONFIG_LOGO=y | ||
2412 | # CONFIG_LOGO_LINUX_MONO is not set | ||
2413 | # CONFIG_LOGO_LINUX_VGA16 is not set | ||
2414 | CONFIG_LOGO_LINUX_CLUT224=y | ||
2415 | CONFIG_SOUND=y | ||
2416 | CONFIG_SOUND_OSS_CORE=y | ||
2417 | CONFIG_SOUND_OSS_CORE_PRECLAIM=y | ||
2418 | CONFIG_SND=y | ||
2419 | CONFIG_SND_TIMER=y | ||
2420 | CONFIG_SND_PCM=y | ||
2421 | CONFIG_SND_HWDEP=y | ||
2422 | CONFIG_SND_RAWMIDI=y | ||
2423 | CONFIG_SND_JACK=y | ||
2424 | CONFIG_SND_SEQUENCER=m | ||
2425 | # CONFIG_SND_SEQ_DUMMY is not set | ||
2426 | CONFIG_SND_OSSEMUL=y | ||
2427 | CONFIG_SND_MIXER_OSS=y | ||
2428 | CONFIG_SND_PCM_OSS=y | ||
2429 | CONFIG_SND_PCM_OSS_PLUGINS=y | ||
2430 | CONFIG_SND_SEQUENCER_OSS=y | ||
2431 | CONFIG_SND_HRTIMER=m | ||
2432 | CONFIG_SND_SEQ_HRTIMER_DEFAULT=y | ||
2433 | CONFIG_SND_DYNAMIC_MINORS=y | ||
2434 | CONFIG_SND_SUPPORT_OLD_API=y | ||
2435 | CONFIG_SND_VERBOSE_PROCFS=y | ||
2436 | # CONFIG_SND_VERBOSE_PRINTK is not set | ||
2437 | # CONFIG_SND_DEBUG is not set | ||
2438 | CONFIG_SND_RAWMIDI_SEQ=m | ||
2439 | # CONFIG_SND_OPL3_LIB_SEQ is not set | ||
2440 | # CONFIG_SND_OPL4_LIB_SEQ is not set | ||
2441 | # CONFIG_SND_SBAWE_SEQ is not set | ||
2442 | # CONFIG_SND_EMU10K1_SEQ is not set | ||
2443 | CONFIG_SND_DRIVERS=y | ||
2444 | # CONFIG_SND_DUMMY is not set | ||
2445 | CONFIG_SND_ALOOP=m | ||
2446 | # CONFIG_SND_VIRMIDI is not set | ||
2447 | # CONFIG_SND_MTPAV is not set | ||
2448 | # CONFIG_SND_SERIAL_U16550 is not set | ||
2449 | # CONFIG_SND_MPU401 is not set | ||
2450 | # CONFIG_SND_ARM is not set | ||
2451 | CONFIG_SND_SPI=y | ||
2452 | CONFIG_SND_USB=y | ||
2453 | CONFIG_SND_USB_AUDIO=y | ||
2454 | CONFIG_SND_USB_UA101=m | ||
2455 | CONFIG_SND_USB_CAIAQ=m | ||
2456 | CONFIG_SND_USB_CAIAQ_INPUT=y | ||
2457 | CONFIG_SND_USB_6FIRE=m | ||
2458 | CONFIG_SND_SOC=y | ||
2459 | CONFIG_SND_SOC_CACHE_LZO=y | ||
2460 | CONFIG_SND_OMAP_SOC=y | ||
2461 | CONFIG_SND_OMAP_SOC_MCBSP=y | ||
2462 | CONFIG_SND_OMAP_SOC_OVERO=y | ||
2463 | CONFIG_SND_OMAP_SOC_OMAP3EVM=y | ||
2464 | CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y | ||
2465 | CONFIG_SND_OMAP_SOC_ZOOM2=y | ||
2466 | CONFIG_SND_SOC_I2C_AND_SPI=y | ||
2467 | # CONFIG_SND_SOC_ALL_CODECS is not set | ||
2468 | CONFIG_SND_SOC_TWL4030=y | ||
2469 | # CONFIG_SOUND_PRIME is not set | ||
2470 | CONFIG_HID_SUPPORT=y | ||
2471 | CONFIG_HID=y | ||
2472 | # CONFIG_HIDRAW is not set | ||
2473 | |||
2474 | # | ||
2475 | # USB Input Devices | ||
2476 | # | ||
2477 | CONFIG_USB_HID=y | ||
2478 | # CONFIG_HID_PID is not set | ||
2479 | # CONFIG_USB_HIDDEV is not set | ||
2480 | |||
2481 | # | ||
2482 | # Special HID drivers | ||
2483 | # | ||
2484 | # CONFIG_HID_3M_PCT is not set | ||
2485 | CONFIG_HID_A4TECH=y | ||
2486 | CONFIG_HID_ACRUX=m | ||
2487 | # CONFIG_HID_ACRUX_FF is not set | ||
2488 | CONFIG_HID_APPLE=y | ||
2489 | CONFIG_HID_BELKIN=y | ||
2490 | # CONFIG_HID_CANDO is not set | ||
2491 | CONFIG_HID_CHERRY=y | ||
2492 | CONFIG_HID_CHICONY=y | ||
2493 | # CONFIG_HID_PRODIKEYS is not set | ||
2494 | CONFIG_HID_CYPRESS=y | ||
2495 | # CONFIG_HID_DRAGONRISE is not set | ||
2496 | CONFIG_HID_EMS_FF=m | ||
2497 | # CONFIG_HID_ELECOM is not set | ||
2498 | CONFIG_HID_EZKEY=y | ||
2499 | CONFIG_HID_KEYTOUCH=m | ||
2500 | # CONFIG_HID_KYE is not set | ||
2501 | CONFIG_HID_UCLOGIC=m | ||
2502 | CONFIG_HID_WALTOP=m | ||
2503 | CONFIG_HID_GYRATION=y | ||
2504 | # CONFIG_HID_TWINHAN is not set | ||
2505 | # CONFIG_HID_KENSINGTON is not set | ||
2506 | CONFIG_HID_LCPOWER=m | ||
2507 | CONFIG_HID_LOGITECH=y | ||
2508 | # CONFIG_LOGITECH_FF is not set | ||
2509 | # CONFIG_LOGIRUMBLEPAD2_FF is not set | ||
2510 | # CONFIG_LOGIG940_FF is not set | ||
2511 | # CONFIG_LOGIWII_FF is not set | ||
2512 | CONFIG_HID_MAGICMOUSE=m | ||
2513 | CONFIG_HID_MICROSOFT=y | ||
2514 | # CONFIG_HID_MOSART is not set | ||
2515 | CONFIG_HID_MONTEREY=y | ||
2516 | CONFIG_HID_MULTITOUCH=m | ||
2517 | CONFIG_HID_NTRIG=y | ||
2518 | # CONFIG_HID_ORTEK is not set | ||
2519 | CONFIG_HID_PANTHERLORD=y | ||
2520 | # CONFIG_PANTHERLORD_FF is not set | ||
2521 | CONFIG_HID_PETALYNX=y | ||
2522 | CONFIG_HID_PICOLCD=m | ||
2523 | CONFIG_HID_PICOLCD_FB=y | ||
2524 | CONFIG_HID_PICOLCD_BACKLIGHT=y | ||
2525 | CONFIG_HID_PICOLCD_LEDS=y | ||
2526 | CONFIG_HID_QUANTA=m | ||
2527 | CONFIG_HID_ROCCAT=m | ||
2528 | CONFIG_HID_ROCCAT_COMMON=m | ||
2529 | CONFIG_HID_ROCCAT_ARVO=m | ||
2530 | CONFIG_HID_ROCCAT_KONE=m | ||
2531 | CONFIG_HID_ROCCAT_KONEPLUS=m | ||
2532 | CONFIG_HID_ROCCAT_KOVAPLUS=m | ||
2533 | # CONFIG_HID_ROCCAT_PYRA is not set | ||
2534 | CONFIG_HID_SAMSUNG=y | ||
2535 | CONFIG_HID_SONY=y | ||
2536 | CONFIG_HID_STANTUM=m | ||
2537 | CONFIG_HID_SUNPLUS=y | ||
2538 | # CONFIG_HID_GREENASIA is not set | ||
2539 | # CONFIG_HID_SMARTJOYPLUS is not set | ||
2540 | CONFIG_HID_TOPSEED=y | ||
2541 | # CONFIG_HID_THRUSTMASTER is not set | ||
2542 | # CONFIG_HID_WACOM is not set | ||
2543 | # CONFIG_HID_ZEROPLUS is not set | ||
2544 | # CONFIG_HID_ZYDACRON is not set | ||
2545 | CONFIG_USB_SUPPORT=y | ||
2546 | CONFIG_USB_ARCH_HAS_HCD=y | ||
2547 | CONFIG_USB_ARCH_HAS_OHCI=y | ||
2548 | CONFIG_USB_ARCH_HAS_EHCI=y | ||
2549 | CONFIG_USB=y | ||
2550 | # CONFIG_USB_DEBUG is not set | ||
2551 | CONFIG_USB_ANNOUNCE_NEW_DEVICES=y | ||
2552 | |||
2553 | # | ||
2554 | # Miscellaneous USB options | ||
2555 | # | ||
2556 | CONFIG_USB_DEVICEFS=y | ||
2557 | CONFIG_USB_DEVICE_CLASS=y | ||
2558 | # CONFIG_USB_DYNAMIC_MINORS is not set | ||
2559 | CONFIG_USB_SUSPEND=y | ||
2560 | CONFIG_USB_OTG=y | ||
2561 | # CONFIG_USB_OTG_WHITELIST is not set | ||
2562 | # CONFIG_USB_OTG_BLACKLIST_HUB is not set | ||
2563 | CONFIG_USB_MON=y | ||
2564 | # CONFIG_USB_WUSB is not set | ||
2565 | # CONFIG_USB_WUSB_CBAF is not set | ||
2566 | |||
2567 | # | ||
2568 | # USB Host Controller Drivers | ||
2569 | # | ||
2570 | # CONFIG_USB_C67X00_HCD is not set | ||
2571 | CONFIG_USB_EHCI_HCD=y | ||
2572 | # CONFIG_USB_EHCI_ROOT_HUB_TT is not set | ||
2573 | CONFIG_USB_EHCI_TT_NEWSCHED=y | ||
2574 | CONFIG_USB_EHCI_HCD_OMAP=y | ||
2575 | # CONFIG_USB_OXU210HP_HCD is not set | ||
2576 | # CONFIG_USB_ISP116X_HCD is not set | ||
2577 | # CONFIG_USB_ISP1760_HCD is not set | ||
2578 | # CONFIG_USB_ISP1362_HCD is not set | ||
2579 | # CONFIG_USB_OHCI_HCD is not set | ||
2580 | # CONFIG_USB_U132_HCD is not set | ||
2581 | # CONFIG_USB_SL811_HCD is not set | ||
2582 | # CONFIG_USB_R8A66597_HCD is not set | ||
2583 | # CONFIG_USB_HWA_HCD is not set | ||
2584 | CONFIG_USB_MUSB_HDRC=y | ||
2585 | # CONFIG_USB_MUSB_TUSB6010 is not set | ||
2586 | CONFIG_USB_MUSB_OMAP2PLUS=y | ||
2587 | # CONFIG_USB_MUSB_AM35X is not set | ||
2588 | # CONFIG_USB_MUSB_HOST is not set | ||
2589 | # CONFIG_USB_MUSB_PERIPHERAL is not set | ||
2590 | CONFIG_USB_MUSB_OTG=y | ||
2591 | CONFIG_USB_GADGET_MUSB_HDRC=y | ||
2592 | CONFIG_USB_MUSB_HDRC_HCD=y | ||
2593 | # CONFIG_MUSB_PIO_ONLY is not set | ||
2594 | CONFIG_USB_INVENTRA_DMA=y | ||
2595 | # CONFIG_USB_TI_CPPI_DMA is not set | ||
2596 | # CONFIG_USB_MUSB_DEBUG is not set | ||
2597 | |||
2598 | # | ||
2599 | # USB Device Class drivers | ||
2600 | # | ||
2601 | CONFIG_USB_ACM=m | ||
2602 | CONFIG_USB_PRINTER=m | ||
2603 | CONFIG_USB_WDM=m | ||
2604 | CONFIG_USB_TMC=m | ||
2605 | |||
2606 | # | ||
2607 | # NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may | ||
2608 | # | ||
2609 | |||
2610 | # | ||
2611 | # also be needed; see USB_STORAGE Help for more info | ||
2612 | # | ||
2613 | CONFIG_USB_STORAGE=y | ||
2614 | # CONFIG_USB_STORAGE_DEBUG is not set | ||
2615 | CONFIG_USB_STORAGE_REALTEK=m | ||
2616 | # CONFIG_USB_STORAGE_DATAFAB is not set | ||
2617 | # CONFIG_USB_STORAGE_FREECOM is not set | ||
2618 | # CONFIG_USB_STORAGE_ISD200 is not set | ||
2619 | # CONFIG_USB_STORAGE_USBAT is not set | ||
2620 | # CONFIG_USB_STORAGE_SDDR09 is not set | ||
2621 | # CONFIG_USB_STORAGE_SDDR55 is not set | ||
2622 | # CONFIG_USB_STORAGE_JUMPSHOT is not set | ||
2623 | # CONFIG_USB_STORAGE_ALAUDA is not set | ||
2624 | # CONFIG_USB_STORAGE_ONETOUCH is not set | ||
2625 | # CONFIG_USB_STORAGE_KARMA is not set | ||
2626 | # CONFIG_USB_STORAGE_CYPRESS_ATACB is not set | ||
2627 | CONFIG_USB_STORAGE_ENE_UB6250=m | ||
2628 | CONFIG_USB_UAS=m | ||
2629 | # CONFIG_USB_LIBUSUAL is not set | ||
2630 | |||
2631 | # | ||
2632 | # USB Imaging devices | ||
2633 | # | ||
2634 | # CONFIG_USB_MDC800 is not set | ||
2635 | # CONFIG_USB_MICROTEK is not set | ||
2636 | |||
2637 | # | ||
2638 | # USB port drivers | ||
2639 | # | ||
2640 | CONFIG_USB_SERIAL=m | ||
2641 | CONFIG_USB_EZUSB=y | ||
2642 | CONFIG_USB_SERIAL_GENERIC=y | ||
2643 | CONFIG_USB_SERIAL_AIRCABLE=m | ||
2644 | CONFIG_USB_SERIAL_ARK3116=m | ||
2645 | CONFIG_USB_SERIAL_BELKIN=m | ||
2646 | CONFIG_USB_SERIAL_CH341=m | ||
2647 | # CONFIG_USB_SERIAL_WHITEHEAT is not set | ||
2648 | CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m | ||
2649 | # CONFIG_USB_SERIAL_CP210X is not set | ||
2650 | CONFIG_USB_SERIAL_CYPRESS_M8=m | ||
2651 | CONFIG_USB_SERIAL_EMPEG=m | ||
2652 | CONFIG_USB_SERIAL_FTDI_SIO=m | ||
2653 | CONFIG_USB_SERIAL_FUNSOFT=m | ||
2654 | CONFIG_USB_SERIAL_VISOR=m | ||
2655 | CONFIG_USB_SERIAL_IPAQ=m | ||
2656 | CONFIG_USB_SERIAL_IR=m | ||
2657 | CONFIG_USB_SERIAL_EDGEPORT=m | ||
2658 | CONFIG_USB_SERIAL_EDGEPORT_TI=m | ||
2659 | CONFIG_USB_SERIAL_GARMIN=m | ||
2660 | CONFIG_USB_SERIAL_IPW=m | ||
2661 | CONFIG_USB_SERIAL_IUU=m | ||
2662 | CONFIG_USB_SERIAL_KEYSPAN_PDA=m | ||
2663 | CONFIG_USB_SERIAL_KEYSPAN=m | ||
2664 | CONFIG_USB_SERIAL_KEYSPAN_MPR=y | ||
2665 | CONFIG_USB_SERIAL_KEYSPAN_USA28=y | ||
2666 | CONFIG_USB_SERIAL_KEYSPAN_USA28X=y | ||
2667 | CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y | ||
2668 | CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y | ||
2669 | CONFIG_USB_SERIAL_KEYSPAN_USA19=y | ||
2670 | CONFIG_USB_SERIAL_KEYSPAN_USA18X=y | ||
2671 | CONFIG_USB_SERIAL_KEYSPAN_USA19W=y | ||
2672 | CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y | ||
2673 | CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y | ||
2674 | CONFIG_USB_SERIAL_KEYSPAN_USA49W=y | ||
2675 | CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y | ||
2676 | CONFIG_USB_SERIAL_KLSI=m | ||
2677 | CONFIG_USB_SERIAL_KOBIL_SCT=m | ||
2678 | CONFIG_USB_SERIAL_MCT_U232=m | ||
2679 | CONFIG_USB_SERIAL_MOS7720=m | ||
2680 | CONFIG_USB_SERIAL_MOS7840=m | ||
2681 | CONFIG_USB_SERIAL_MOTOROLA=m | ||
2682 | CONFIG_USB_SERIAL_NAVMAN=m | ||
2683 | CONFIG_USB_SERIAL_PL2303=m | ||
2684 | CONFIG_USB_SERIAL_OTI6858=m | ||
2685 | CONFIG_USB_SERIAL_QCAUX=m | ||
2686 | # CONFIG_USB_SERIAL_QUALCOMM is not set | ||
2687 | CONFIG_USB_SERIAL_SPCP8X5=m | ||
2688 | CONFIG_USB_SERIAL_HP4X=m | ||
2689 | CONFIG_USB_SERIAL_SAFE=m | ||
2690 | # CONFIG_USB_SERIAL_SAFE_PADDED is not set | ||
2691 | CONFIG_USB_SERIAL_SAMBA=m | ||
2692 | CONFIG_USB_SERIAL_SIEMENS_MPI=m | ||
2693 | CONFIG_USB_SERIAL_SIERRAWIRELESS=m | ||
2694 | # CONFIG_USB_SERIAL_SYMBOL is not set | ||
2695 | # CONFIG_USB_SERIAL_TI is not set | ||
2696 | CONFIG_USB_SERIAL_CYBERJACK=m | ||
2697 | # CONFIG_USB_SERIAL_XIRCOM is not set | ||
2698 | # CONFIG_USB_SERIAL_OPTION is not set | ||
2699 | CONFIG_USB_SERIAL_OMNINET=m | ||
2700 | CONFIG_USB_SERIAL_OPTICON=m | ||
2701 | CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m | ||
2702 | CONFIG_USB_SERIAL_ZIO=m | ||
2703 | CONFIG_USB_SERIAL_SSU100=m | ||
2704 | CONFIG_USB_SERIAL_DEBUG=m | ||
2705 | |||
2706 | # | ||
2707 | # USB Miscellaneous drivers | ||
2708 | # | ||
2709 | CONFIG_USB_EMI62=m | ||
2710 | CONFIG_USB_EMI26=m | ||
2711 | # CONFIG_USB_ADUTUX is not set | ||
2712 | # CONFIG_USB_SEVSEG is not set | ||
2713 | # CONFIG_USB_RIO500 is not set | ||
2714 | CONFIG_USB_LEGOTOWER=m | ||
2715 | CONFIG_USB_LCD=m | ||
2716 | CONFIG_USB_LED=m | ||
2717 | CONFIG_USB_CYPRESS_CY7C63=m | ||
2718 | CONFIG_USB_CYTHERM=m | ||
2719 | CONFIG_USB_IDMOUSE=m | ||
2720 | CONFIG_USB_FTDI_ELAN=m | ||
2721 | # CONFIG_USB_APPLEDISPLAY is not set | ||
2722 | CONFIG_USB_SISUSBVGA=m | ||
2723 | CONFIG_USB_SISUSBVGA_CON=y | ||
2724 | CONFIG_USB_LD=m | ||
2725 | CONFIG_USB_TRANCEVIBRATOR=m | ||
2726 | # CONFIG_USB_IOWARRIOR is not set | ||
2727 | CONFIG_USB_TEST=m | ||
2728 | # CONFIG_USB_ISIGHTFW is not set | ||
2729 | CONFIG_USB_YUREX=m | ||
2730 | CONFIG_USB_ATM=m | ||
2731 | CONFIG_USB_SPEEDTOUCH=m | ||
2732 | CONFIG_USB_CXACRU=m | ||
2733 | CONFIG_USB_UEAGLEATM=m | ||
2734 | CONFIG_USB_XUSBATM=m | ||
2735 | CONFIG_USB_GADGET=y | ||
2736 | # CONFIG_USB_GADGET_DEBUG is not set | ||
2737 | # CONFIG_USB_GADGET_DEBUG_FILES is not set | ||
2738 | CONFIG_USB_GADGET_DEBUG_FS=y | ||
2739 | CONFIG_USB_GADGET_VBUS_DRAW=480 | ||
2740 | CONFIG_USB_GADGET_SELECTED=y | ||
2741 | # CONFIG_USB_GADGET_FUSB300 is not set | ||
2742 | # CONFIG_USB_GADGET_OMAP is not set | ||
2743 | # CONFIG_USB_GADGET_R8A66597 is not set | ||
2744 | # CONFIG_USB_GADGET_PXA_U2O is not set | ||
2745 | # CONFIG_USB_GADGET_M66592 is not set | ||
2746 | # CONFIG_USB_GADGET_DUMMY_HCD is not set | ||
2747 | CONFIG_USB_GADGET_DUALSPEED=y | ||
2748 | # CONFIG_USB_ZERO is not set | ||
2749 | # CONFIG_USB_AUDIO is not set | ||
2750 | CONFIG_USB_ETH=m | ||
2751 | CONFIG_USB_ETH_RNDIS=y | ||
2752 | # CONFIG_USB_ETH_EEM is not set | ||
2753 | CONFIG_USB_G_NCM=m | ||
2754 | # CONFIG_USB_GADGETFS is not set | ||
2755 | CONFIG_USB_FUNCTIONFS=m | ||
2756 | # CONFIG_USB_FUNCTIONFS_ETH is not set | ||
2757 | CONFIG_USB_FUNCTIONFS_RNDIS=y | ||
2758 | # CONFIG_USB_FUNCTIONFS_GENERIC is not set | ||
2759 | # CONFIG_USB_FILE_STORAGE is not set | ||
2760 | # CONFIG_USB_MASS_STORAGE is not set | ||
2761 | # CONFIG_USB_G_SERIAL is not set | ||
2762 | # CONFIG_USB_MIDI_GADGET is not set | ||
2763 | # CONFIG_USB_G_PRINTER is not set | ||
2764 | # CONFIG_USB_CDC_COMPOSITE is not set | ||
2765 | # CONFIG_USB_G_MULTI is not set | ||
2766 | CONFIG_USB_G_HID=m | ||
2767 | CONFIG_USB_G_DBGP=m | ||
2768 | # CONFIG_USB_G_DBGP_PRINTK is not set | ||
2769 | CONFIG_USB_G_DBGP_SERIAL=y | ||
2770 | CONFIG_USB_G_WEBCAM=m | ||
2771 | |||
2772 | # | ||
2773 | # OTG and related infrastructure | ||
2774 | # | ||
2775 | CONFIG_USB_OTG_UTILS=y | ||
2776 | CONFIG_USB_GPIO_VBUS=y | ||
2777 | # CONFIG_ISP1301_OMAP is not set | ||
2778 | # CONFIG_USB_ULPI is not set | ||
2779 | CONFIG_TWL4030_USB=y | ||
2780 | CONFIG_TWL6030_USB=m | ||
2781 | CONFIG_NOP_USB_XCEIV=y | ||
2782 | CONFIG_MMC=y | ||
2783 | # CONFIG_MMC_DEBUG is not set | ||
2784 | CONFIG_MMC_UNSAFE_RESUME=y | ||
2785 | # CONFIG_MMC_CLKGATE is not set | ||
2786 | |||
2787 | # | ||
2788 | # MMC/SD/SDIO Card Drivers | ||
2789 | # | ||
2790 | CONFIG_MMC_BLOCK=y | ||
2791 | CONFIG_MMC_BLOCK_MINORS=8 | ||
2792 | CONFIG_MMC_BLOCK_BOUNCE=y | ||
2793 | CONFIG_SDIO_UART=y | ||
2794 | # CONFIG_MMC_TEST is not set | ||
2795 | |||
2796 | # | ||
2797 | # MMC/SD/SDIO Host Controller Drivers | ||
2798 | # | ||
2799 | # CONFIG_MMC_SDHCI is not set | ||
2800 | # CONFIG_MMC_OMAP is not set | ||
2801 | CONFIG_MMC_OMAP_HS=y | ||
2802 | CONFIG_MMC_SPI=m | ||
2803 | # CONFIG_MMC_DW is not set | ||
2804 | CONFIG_MMC_USHC=m | ||
2805 | # CONFIG_MEMSTICK is not set | ||
2806 | CONFIG_NEW_LEDS=y | ||
2807 | CONFIG_LEDS_CLASS=y | ||
2808 | |||
2809 | # | ||
2810 | # LED drivers | ||
2811 | # | ||
2812 | # CONFIG_LEDS_LM3530 is not set | ||
2813 | # CONFIG_LEDS_PCA9532 is not set | ||
2814 | CONFIG_LEDS_GPIO=y | ||
2815 | CONFIG_LEDS_GPIO_PLATFORM=y | ||
2816 | # CONFIG_LEDS_LP3944 is not set | ||
2817 | CONFIG_LEDS_LP5521=m | ||
2818 | CONFIG_LEDS_LP5523=m | ||
2819 | # CONFIG_LEDS_PCA955X is not set | ||
2820 | # CONFIG_LEDS_DAC124S085 is not set | ||
2821 | CONFIG_LEDS_PWM=m | ||
2822 | CONFIG_LEDS_REGULATOR=m | ||
2823 | # CONFIG_LEDS_BD2802 is not set | ||
2824 | # CONFIG_LEDS_LT3593 is not set | ||
2825 | CONFIG_LEDS_TRIGGERS=y | ||
2826 | |||
2827 | # | ||
2828 | # LED Triggers | ||
2829 | # | ||
2830 | CONFIG_LEDS_TRIGGER_TIMER=m | ||
2831 | CONFIG_LEDS_TRIGGER_HEARTBEAT=y | ||
2832 | CONFIG_LEDS_TRIGGER_BACKLIGHT=m | ||
2833 | CONFIG_LEDS_TRIGGER_GPIO=m | ||
2834 | CONFIG_LEDS_TRIGGER_DEFAULT_ON=m | ||
2835 | |||
2836 | # | ||
2837 | # iptables trigger is under Netfilter config (LED target) | ||
2838 | # | ||
2839 | CONFIG_NFC_DEVICES=y | ||
2840 | CONFIG_PN544_NFC=m | ||
2841 | # CONFIG_ACCESSIBILITY is not set | ||
2842 | CONFIG_RTC_LIB=y | ||
2843 | CONFIG_RTC_CLASS=y | ||
2844 | CONFIG_RTC_HCTOSYS=y | ||
2845 | CONFIG_RTC_HCTOSYS_DEVICE="rtc0" | ||
2846 | # CONFIG_RTC_DEBUG is not set | ||
2847 | |||
2848 | # | ||
2849 | # RTC interfaces | ||
2850 | # | ||
2851 | CONFIG_RTC_INTF_SYSFS=y | ||
2852 | CONFIG_RTC_INTF_PROC=y | ||
2853 | CONFIG_RTC_INTF_DEV=y | ||
2854 | # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set | ||
2855 | # CONFIG_RTC_DRV_TEST is not set | ||
2856 | |||
2857 | # | ||
2858 | # I2C RTC drivers | ||
2859 | # | ||
2860 | CONFIG_RTC_DRV_DS1307=y | ||
2861 | # CONFIG_RTC_DRV_DS1374 is not set | ||
2862 | # CONFIG_RTC_DRV_DS1672 is not set | ||
2863 | # CONFIG_RTC_DRV_DS3232 is not set | ||
2864 | # CONFIG_RTC_DRV_MAX6900 is not set | ||
2865 | # CONFIG_RTC_DRV_RS5C372 is not set | ||
2866 | # CONFIG_RTC_DRV_ISL1208 is not set | ||
2867 | # CONFIG_RTC_DRV_ISL12022 is not set | ||
2868 | # CONFIG_RTC_DRV_X1205 is not set | ||
2869 | # CONFIG_RTC_DRV_PCF8563 is not set | ||
2870 | # CONFIG_RTC_DRV_PCF8583 is not set | ||
2871 | # CONFIG_RTC_DRV_M41T80 is not set | ||
2872 | CONFIG_RTC_DRV_BQ32K=m | ||
2873 | CONFIG_RTC_DRV_TWL4030=m | ||
2874 | # CONFIG_RTC_DRV_S35390A is not set | ||
2875 | # CONFIG_RTC_DRV_FM3130 is not set | ||
2876 | # CONFIG_RTC_DRV_RX8581 is not set | ||
2877 | # CONFIG_RTC_DRV_RX8025 is not set | ||
2878 | |||
2879 | # | ||
2880 | # SPI RTC drivers | ||
2881 | # | ||
2882 | # CONFIG_RTC_DRV_M41T94 is not set | ||
2883 | # CONFIG_RTC_DRV_DS1305 is not set | ||
2884 | # CONFIG_RTC_DRV_DS1390 is not set | ||
2885 | # CONFIG_RTC_DRV_MAX6902 is not set | ||
2886 | # CONFIG_RTC_DRV_R9701 is not set | ||
2887 | # CONFIG_RTC_DRV_RS5C348 is not set | ||
2888 | # CONFIG_RTC_DRV_DS3234 is not set | ||
2889 | # CONFIG_RTC_DRV_PCF2123 is not set | ||
2890 | |||
2891 | # | ||
2892 | # Platform RTC drivers | ||
2893 | # | ||
2894 | # CONFIG_RTC_DRV_CMOS is not set | ||
2895 | # CONFIG_RTC_DRV_DS1286 is not set | ||
2896 | # CONFIG_RTC_DRV_DS1511 is not set | ||
2897 | # CONFIG_RTC_DRV_DS1553 is not set | ||
2898 | # CONFIG_RTC_DRV_DS1742 is not set | ||
2899 | # CONFIG_RTC_DRV_STK17TA8 is not set | ||
2900 | # CONFIG_RTC_DRV_M48T86 is not set | ||
2901 | # CONFIG_RTC_DRV_M48T35 is not set | ||
2902 | # CONFIG_RTC_DRV_M48T59 is not set | ||
2903 | # CONFIG_RTC_DRV_MSM6242 is not set | ||
2904 | # CONFIG_RTC_DRV_BQ4802 is not set | ||
2905 | # CONFIG_RTC_DRV_RP5C01 is not set | ||
2906 | # CONFIG_RTC_DRV_V3020 is not set | ||
2907 | |||
2908 | # | ||
2909 | # on-CPU RTC drivers | ||
2910 | # | ||
2911 | # CONFIG_DMADEVICES is not set | ||
2912 | CONFIG_TIMB_DMA=m | ||
2913 | CONFIG_DMA_ENGINE=y | ||
2914 | # CONFIG_AUXDISPLAY is not set | ||
2915 | CONFIG_UIO=m | ||
2916 | CONFIG_UIO_PDRV=m | ||
2917 | CONFIG_UIO_PDRV_GENIRQ=m | ||
2918 | CONFIG_STAGING=y | ||
2919 | # CONFIG_STAGING_EXCLUDE_BUILD is not set | ||
2920 | # CONFIG_VIDEO_TM6000 is not set | ||
2921 | # CONFIG_USB_IP_COMMON is not set | ||
2922 | CONFIG_W35UND=m | ||
2923 | CONFIG_PRISM2_USB=m | ||
2924 | CONFIG_ECHO=m | ||
2925 | CONFIG_BRCM80211=m | ||
2926 | CONFIG_BRCMFMAC=y | ||
2927 | # CONFIG_BRCMDBG is not set | ||
2928 | CONFIG_RT2870=m | ||
2929 | # CONFIG_COMEDI is not set | ||
2930 | # CONFIG_ASUS_OLED is not set | ||
2931 | CONFIG_R8712U=m | ||
2932 | CONFIG_R8712_AP=y | ||
2933 | # CONFIG_TRANZPORT is not set | ||
2934 | # CONFIG_POHMELFS is not set | ||
2935 | # CONFIG_LINE6_USB is not set | ||
2936 | # CONFIG_USB_SERIAL_QUATECH2 is not set | ||
2937 | # CONFIG_USB_SERIAL_QUATECH_USB2 is not set | ||
2938 | # CONFIG_VT6656 is not set | ||
2939 | # CONFIG_IIO is not set | ||
2940 | CONFIG_XVMALLOC=y | ||
2941 | CONFIG_ZRAM=m | ||
2942 | # CONFIG_ZRAM_DEBUG is not set | ||
2943 | # CONFIG_FB_SM7XX is not set | ||
2944 | # CONFIG_LIRC_STAGING is not set | ||
2945 | # CONFIG_EASYCAP is not set | ||
2946 | # CONFIG_TIDSPBRIDGE is not set | ||
2947 | # CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL is not set | ||
2948 | CONFIG_MACH_NO_WESTBRIDGE=y | ||
2949 | # CONFIG_ATH6K_LEGACY is not set | ||
2950 | CONFIG_USB_ENESTORAGE=m | ||
2951 | CONFIG_BCM_WIMAX=m | ||
2952 | CONFIG_FT1000=m | ||
2953 | CONFIG_FT1000_USB=m | ||
2954 | |||
2955 | # | ||
2956 | # Speakup console speech | ||
2957 | # | ||
2958 | # CONFIG_SPEAKUP is not set | ||
2959 | CONFIG_TOUCHSCREEN_CLEARPAD_TM1217=m | ||
2960 | CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=m | ||
2961 | |||
2962 | # | ||
2963 | # Altera FPGA firmware download module | ||
2964 | # | ||
2965 | # CONFIG_ALTERA_STAPL is not set | ||
2966 | CONFIG_CLKDEV_LOOKUP=y | ||
2967 | |||
2968 | # | ||
2969 | # File systems | ||
2970 | # | ||
2971 | CONFIG_EXT2_FS=y | ||
2972 | CONFIG_EXT2_FS_XATTR=y | ||
2973 | CONFIG_EXT2_FS_POSIX_ACL=y | ||
2974 | CONFIG_EXT2_FS_SECURITY=y | ||
2975 | # CONFIG_EXT2_FS_XIP is not set | ||
2976 | CONFIG_EXT3_FS=y | ||
2977 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
2978 | CONFIG_EXT3_FS_XATTR=y | ||
2979 | CONFIG_EXT3_FS_POSIX_ACL=y | ||
2980 | # CONFIG_EXT3_FS_SECURITY is not set | ||
2981 | CONFIG_EXT4_FS=y | ||
2982 | CONFIG_EXT4_FS_XATTR=y | ||
2983 | CONFIG_EXT4_FS_POSIX_ACL=y | ||
2984 | CONFIG_EXT4_FS_SECURITY=y | ||
2985 | # CONFIG_EXT4_DEBUG is not set | ||
2986 | CONFIG_JBD=y | ||
2987 | # CONFIG_JBD_DEBUG is not set | ||
2988 | CONFIG_JBD2=y | ||
2989 | # CONFIG_JBD2_DEBUG is not set | ||
2990 | CONFIG_FS_MBCACHE=y | ||
2991 | CONFIG_REISERFS_FS=m | ||
2992 | # CONFIG_REISERFS_CHECK is not set | ||
2993 | CONFIG_REISERFS_PROC_INFO=y | ||
2994 | CONFIG_REISERFS_FS_XATTR=y | ||
2995 | # CONFIG_REISERFS_FS_POSIX_ACL is not set | ||
2996 | # CONFIG_REISERFS_FS_SECURITY is not set | ||
2997 | CONFIG_JFS_FS=m | ||
2998 | CONFIG_JFS_POSIX_ACL=y | ||
2999 | # CONFIG_JFS_SECURITY is not set | ||
3000 | # CONFIG_JFS_DEBUG is not set | ||
3001 | CONFIG_JFS_STATISTICS=y | ||
3002 | CONFIG_XFS_FS=m | ||
3003 | CONFIG_XFS_QUOTA=y | ||
3004 | CONFIG_XFS_POSIX_ACL=y | ||
3005 | CONFIG_XFS_RT=y | ||
3006 | # CONFIG_XFS_DEBUG is not set | ||
3007 | CONFIG_GFS2_FS=m | ||
3008 | CONFIG_GFS2_FS_LOCKING_DLM=y | ||
3009 | CONFIG_OCFS2_FS=m | ||
3010 | CONFIG_OCFS2_FS_O2CB=m | ||
3011 | CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m | ||
3012 | CONFIG_OCFS2_FS_STATS=y | ||
3013 | CONFIG_OCFS2_DEBUG_MASKLOG=y | ||
3014 | # CONFIG_OCFS2_DEBUG_FS is not set | ||
3015 | CONFIG_BTRFS_FS=m | ||
3016 | CONFIG_BTRFS_FS_POSIX_ACL=y | ||
3017 | CONFIG_NILFS2_FS=m | ||
3018 | CONFIG_FS_POSIX_ACL=y | ||
3019 | CONFIG_EXPORTFS=y | ||
3020 | CONFIG_FILE_LOCKING=y | ||
3021 | CONFIG_FSNOTIFY=y | ||
3022 | CONFIG_DNOTIFY=y | ||
3023 | CONFIG_INOTIFY_USER=y | ||
3024 | CONFIG_FANOTIFY=y | ||
3025 | CONFIG_QUOTA=y | ||
3026 | # CONFIG_QUOTA_NETLINK_INTERFACE is not set | ||
3027 | CONFIG_PRINT_QUOTA_WARNING=y | ||
3028 | # CONFIG_QUOTA_DEBUG is not set | ||
3029 | CONFIG_QUOTA_TREE=y | ||
3030 | # CONFIG_QFMT_V1 is not set | ||
3031 | CONFIG_QFMT_V2=y | ||
3032 | CONFIG_QUOTACTL=y | ||
3033 | CONFIG_AUTOFS4_FS=y | ||
3034 | CONFIG_FUSE_FS=m | ||
3035 | CONFIG_CUSE=m | ||
3036 | CONFIG_GENERIC_ACL=y | ||
3037 | |||
3038 | # | ||
3039 | # Caches | ||
3040 | # | ||
3041 | CONFIG_FSCACHE=m | ||
3042 | CONFIG_FSCACHE_STATS=y | ||
3043 | CONFIG_FSCACHE_HISTOGRAM=y | ||
3044 | # CONFIG_FSCACHE_DEBUG is not set | ||
3045 | # CONFIG_FSCACHE_OBJECT_LIST is not set | ||
3046 | CONFIG_CACHEFILES=m | ||
3047 | # CONFIG_CACHEFILES_DEBUG is not set | ||
3048 | CONFIG_CACHEFILES_HISTOGRAM=y | ||
3049 | |||
3050 | # | ||
3051 | # CD-ROM/DVD Filesystems | ||
3052 | # | ||
3053 | CONFIG_ISO9660_FS=m | ||
3054 | CONFIG_JOLIET=y | ||
3055 | CONFIG_ZISOFS=y | ||
3056 | CONFIG_UDF_FS=m | ||
3057 | CONFIG_UDF_NLS=y | ||
3058 | |||
3059 | # | ||
3060 | # DOS/FAT/NT Filesystems | ||
3061 | # | ||
3062 | CONFIG_FAT_FS=y | ||
3063 | CONFIG_MSDOS_FS=y | ||
3064 | CONFIG_VFAT_FS=y | ||
3065 | CONFIG_FAT_DEFAULT_CODEPAGE=437 | ||
3066 | CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" | ||
3067 | CONFIG_NTFS_FS=m | ||
3068 | # CONFIG_NTFS_DEBUG is not set | ||
3069 | # CONFIG_NTFS_RW is not set | ||
3070 | |||
3071 | # | ||
3072 | # Pseudo filesystems | ||
3073 | # | ||
3074 | CONFIG_PROC_FS=y | ||
3075 | CONFIG_PROC_SYSCTL=y | ||
3076 | CONFIG_PROC_PAGE_MONITOR=y | ||
3077 | CONFIG_SYSFS=y | ||
3078 | CONFIG_TMPFS=y | ||
3079 | CONFIG_TMPFS_POSIX_ACL=y | ||
3080 | # CONFIG_HUGETLB_PAGE is not set | ||
3081 | CONFIG_CONFIGFS_FS=m | ||
3082 | CONFIG_MISC_FILESYSTEMS=y | ||
3083 | CONFIG_ADFS_FS=m | ||
3084 | # CONFIG_ADFS_FS_RW is not set | ||
3085 | CONFIG_AFFS_FS=m | ||
3086 | # CONFIG_ECRYPT_FS is not set | ||
3087 | CONFIG_UNION_FS=m | ||
3088 | CONFIG_UNION_FS_XATTR=y | ||
3089 | # CONFIG_UNION_FS_DEBUG is not set | ||
3090 | CONFIG_HFS_FS=m | ||
3091 | CONFIG_HFSPLUS_FS=m | ||
3092 | CONFIG_BEFS_FS=m | ||
3093 | # CONFIG_BEFS_DEBUG is not set | ||
3094 | CONFIG_BFS_FS=m | ||
3095 | CONFIG_EFS_FS=m | ||
3096 | CONFIG_JFFS2_FS=y | ||
3097 | CONFIG_JFFS2_FS_DEBUG=0 | ||
3098 | CONFIG_JFFS2_FS_WRITEBUFFER=y | ||
3099 | # CONFIG_JFFS2_FS_WBUF_VERIFY is not set | ||
3100 | CONFIG_JFFS2_SUMMARY=y | ||
3101 | CONFIG_JFFS2_FS_XATTR=y | ||
3102 | CONFIG_JFFS2_FS_POSIX_ACL=y | ||
3103 | CONFIG_JFFS2_FS_SECURITY=y | ||
3104 | CONFIG_JFFS2_COMPRESSION_OPTIONS=y | ||
3105 | CONFIG_JFFS2_ZLIB=y | ||
3106 | CONFIG_JFFS2_LZO=y | ||
3107 | CONFIG_JFFS2_RTIME=y | ||
3108 | CONFIG_JFFS2_RUBIN=y | ||
3109 | # CONFIG_JFFS2_CMODE_NONE is not set | ||
3110 | # CONFIG_JFFS2_CMODE_PRIORITY is not set | ||
3111 | # CONFIG_JFFS2_CMODE_SIZE is not set | ||
3112 | CONFIG_JFFS2_CMODE_FAVOURLZO=y | ||
3113 | CONFIG_UBIFS_FS=y | ||
3114 | CONFIG_UBIFS_FS_XATTR=y | ||
3115 | CONFIG_UBIFS_FS_ADVANCED_COMPR=y | ||
3116 | CONFIG_UBIFS_FS_LZO=y | ||
3117 | CONFIG_UBIFS_FS_ZLIB=y | ||
3118 | # CONFIG_UBIFS_FS_DEBUG is not set | ||
3119 | CONFIG_LOGFS=m | ||
3120 | CONFIG_CRAMFS=m | ||
3121 | CONFIG_SQUASHFS=y | ||
3122 | # CONFIG_SQUASHFS_XATTR is not set | ||
3123 | CONFIG_SQUASHFS_LZO=y | ||
3124 | CONFIG_SQUASHFS_XZ=y | ||
3125 | # CONFIG_SQUASHFS_EMBEDDED is not set | ||
3126 | CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 | ||
3127 | CONFIG_VXFS_FS=m | ||
3128 | CONFIG_MINIX_FS=m | ||
3129 | CONFIG_OMFS_FS=m | ||
3130 | CONFIG_HPFS_FS=m | ||
3131 | CONFIG_QNX4FS_FS=m | ||
3132 | CONFIG_ROMFS_FS=m | ||
3133 | CONFIG_ROMFS_BACKED_BY_BLOCK=y | ||
3134 | # CONFIG_ROMFS_BACKED_BY_MTD is not set | ||
3135 | # CONFIG_ROMFS_BACKED_BY_BOTH is not set | ||
3136 | CONFIG_ROMFS_ON_BLOCK=y | ||
3137 | CONFIG_PSTORE=y | ||
3138 | CONFIG_SYSV_FS=m | ||
3139 | CONFIG_UFS_FS=m | ||
3140 | # CONFIG_UFS_FS_WRITE is not set | ||
3141 | # CONFIG_UFS_DEBUG is not set | ||
3142 | CONFIG_NETWORK_FILESYSTEMS=y | ||
3143 | CONFIG_NFS_FS=y | ||
3144 | CONFIG_NFS_V3=y | ||
3145 | CONFIG_NFS_V3_ACL=y | ||
3146 | CONFIG_NFS_V4=y | ||
3147 | CONFIG_NFS_V4_1=y | ||
3148 | CONFIG_PNFS_FILE_LAYOUT=y | ||
3149 | CONFIG_ROOT_NFS=y | ||
3150 | # CONFIG_NFS_USE_LEGACY_DNS is not set | ||
3151 | CONFIG_NFS_USE_KERNEL_DNS=y | ||
3152 | # CONFIG_NFS_USE_NEW_IDMAPPER is not set | ||
3153 | CONFIG_NFSD=m | ||
3154 | CONFIG_NFSD_DEPRECATED=y | ||
3155 | CONFIG_NFSD_V2_ACL=y | ||
3156 | CONFIG_NFSD_V3=y | ||
3157 | CONFIG_NFSD_V3_ACL=y | ||
3158 | CONFIG_NFSD_V4=y | ||
3159 | CONFIG_LOCKD=y | ||
3160 | CONFIG_LOCKD_V4=y | ||
3161 | CONFIG_NFS_ACL_SUPPORT=y | ||
3162 | CONFIG_NFS_COMMON=y | ||
3163 | CONFIG_SUNRPC=y | ||
3164 | CONFIG_SUNRPC_GSS=y | ||
3165 | CONFIG_RPCSEC_GSS_KRB5=m | ||
3166 | CONFIG_CEPH_FS=m | ||
3167 | CONFIG_CIFS=m | ||
3168 | CONFIG_CIFS_STATS=y | ||
3169 | CONFIG_CIFS_STATS2=y | ||
3170 | # CONFIG_CIFS_WEAK_PW_HASH is not set | ||
3171 | # CONFIG_CIFS_UPCALL is not set | ||
3172 | CONFIG_CIFS_XATTR=y | ||
3173 | CONFIG_CIFS_POSIX=y | ||
3174 | # CONFIG_CIFS_DEBUG2 is not set | ||
3175 | CONFIG_CIFS_DFS_UPCALL=y | ||
3176 | CONFIG_CIFS_FSCACHE=y | ||
3177 | CONFIG_CIFS_ACL=y | ||
3178 | CONFIG_CIFS_EXPERIMENTAL=y | ||
3179 | CONFIG_NCP_FS=m | ||
3180 | # CONFIG_NCPFS_PACKET_SIGNING is not set | ||
3181 | # CONFIG_NCPFS_IOCTL_LOCKING is not set | ||
3182 | # CONFIG_NCPFS_STRONG is not set | ||
3183 | # CONFIG_NCPFS_NFS_NS is not set | ||
3184 | # CONFIG_NCPFS_OS2_NS is not set | ||
3185 | # CONFIG_NCPFS_SMALLDOS is not set | ||
3186 | # CONFIG_NCPFS_NLS is not set | ||
3187 | # CONFIG_NCPFS_EXTRAS is not set | ||
3188 | CONFIG_CODA_FS=m | ||
3189 | CONFIG_AFS_FS=m | ||
3190 | # CONFIG_AFS_DEBUG is not set | ||
3191 | # CONFIG_AFS_FSCACHE is not set | ||
3192 | CONFIG_9P_FS=m | ||
3193 | CONFIG_9P_FSCACHE=y | ||
3194 | CONFIG_9P_FS_POSIX_ACL=y | ||
3195 | |||
3196 | # | ||
3197 | # Partition Types | ||
3198 | # | ||
3199 | CONFIG_PARTITION_ADVANCED=y | ||
3200 | # CONFIG_ACORN_PARTITION is not set | ||
3201 | # CONFIG_OSF_PARTITION is not set | ||
3202 | # CONFIG_AMIGA_PARTITION is not set | ||
3203 | # CONFIG_ATARI_PARTITION is not set | ||
3204 | CONFIG_MAC_PARTITION=y | ||
3205 | CONFIG_MSDOS_PARTITION=y | ||
3206 | CONFIG_BSD_DISKLABEL=y | ||
3207 | CONFIG_MINIX_SUBPARTITION=y | ||
3208 | CONFIG_SOLARIS_X86_PARTITION=y | ||
3209 | # CONFIG_UNIXWARE_DISKLABEL is not set | ||
3210 | CONFIG_LDM_PARTITION=y | ||
3211 | CONFIG_LDM_DEBUG=y | ||
3212 | # CONFIG_SGI_PARTITION is not set | ||
3213 | # CONFIG_ULTRIX_PARTITION is not set | ||
3214 | # CONFIG_SUN_PARTITION is not set | ||
3215 | # CONFIG_KARMA_PARTITION is not set | ||
3216 | CONFIG_EFI_PARTITION=y | ||
3217 | # CONFIG_SYSV68_PARTITION is not set | ||
3218 | CONFIG_NLS=y | ||
3219 | CONFIG_NLS_DEFAULT="iso8859-1" | ||
3220 | CONFIG_NLS_CODEPAGE_437=y | ||
3221 | CONFIG_NLS_CODEPAGE_737=m | ||
3222 | CONFIG_NLS_CODEPAGE_775=m | ||
3223 | CONFIG_NLS_CODEPAGE_850=m | ||
3224 | CONFIG_NLS_CODEPAGE_852=m | ||
3225 | CONFIG_NLS_CODEPAGE_855=m | ||
3226 | CONFIG_NLS_CODEPAGE_857=m | ||
3227 | CONFIG_NLS_CODEPAGE_860=m | ||
3228 | CONFIG_NLS_CODEPAGE_861=m | ||
3229 | CONFIG_NLS_CODEPAGE_862=m | ||
3230 | CONFIG_NLS_CODEPAGE_863=m | ||
3231 | CONFIG_NLS_CODEPAGE_864=m | ||
3232 | CONFIG_NLS_CODEPAGE_865=m | ||
3233 | CONFIG_NLS_CODEPAGE_866=m | ||
3234 | CONFIG_NLS_CODEPAGE_869=m | ||
3235 | CONFIG_NLS_CODEPAGE_936=m | ||
3236 | CONFIG_NLS_CODEPAGE_950=m | ||
3237 | CONFIG_NLS_CODEPAGE_932=m | ||
3238 | CONFIG_NLS_CODEPAGE_949=m | ||
3239 | CONFIG_NLS_CODEPAGE_874=m | ||
3240 | CONFIG_NLS_ISO8859_8=m | ||
3241 | CONFIG_NLS_CODEPAGE_1250=m | ||
3242 | CONFIG_NLS_CODEPAGE_1251=m | ||
3243 | CONFIG_NLS_ASCII=m | ||
3244 | CONFIG_NLS_ISO8859_1=y | ||
3245 | CONFIG_NLS_ISO8859_2=m | ||
3246 | CONFIG_NLS_ISO8859_3=m | ||
3247 | CONFIG_NLS_ISO8859_4=m | ||
3248 | CONFIG_NLS_ISO8859_5=m | ||
3249 | CONFIG_NLS_ISO8859_6=m | ||
3250 | CONFIG_NLS_ISO8859_7=m | ||
3251 | CONFIG_NLS_ISO8859_9=m | ||
3252 | CONFIG_NLS_ISO8859_13=m | ||
3253 | CONFIG_NLS_ISO8859_14=m | ||
3254 | CONFIG_NLS_ISO8859_15=m | ||
3255 | CONFIG_NLS_KOI8_R=m | ||
3256 | CONFIG_NLS_KOI8_U=m | ||
3257 | CONFIG_NLS_UTF8=y | ||
3258 | CONFIG_DLM=m | ||
3259 | # CONFIG_DLM_DEBUG is not set | ||
3260 | |||
3261 | # | ||
3262 | # Kernel hacking | ||
3263 | # | ||
3264 | CONFIG_PRINTK_TIME=y | ||
3265 | CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 | ||
3266 | CONFIG_ENABLE_WARN_DEPRECATED=y | ||
3267 | CONFIG_ENABLE_MUST_CHECK=y | ||
3268 | CONFIG_FRAME_WARN=1024 | ||
3269 | CONFIG_MAGIC_SYSRQ=y | ||
3270 | # CONFIG_STRIP_ASM_SYMS is not set | ||
3271 | # CONFIG_UNUSED_SYMBOLS is not set | ||
3272 | CONFIG_DEBUG_FS=y | ||
3273 | # CONFIG_HEADERS_CHECK is not set | ||
3274 | # CONFIG_DEBUG_SECTION_MISMATCH is not set | ||
3275 | CONFIG_DEBUG_KERNEL=y | ||
3276 | # CONFIG_DEBUG_SHIRQ is not set | ||
3277 | # CONFIG_LOCKUP_DETECTOR is not set | ||
3278 | # CONFIG_HARDLOCKUP_DETECTOR is not set | ||
3279 | CONFIG_DETECT_HUNG_TASK=y | ||
3280 | # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set | ||
3281 | CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 | ||
3282 | CONFIG_SCHED_DEBUG=y | ||
3283 | CONFIG_SCHEDSTATS=y | ||
3284 | CONFIG_TIMER_STATS=y | ||
3285 | # CONFIG_DEBUG_OBJECTS is not set | ||
3286 | # CONFIG_DEBUG_SLAB is not set | ||
3287 | # CONFIG_DEBUG_KMEMLEAK is not set | ||
3288 | # CONFIG_DEBUG_RT_MUTEXES is not set | ||
3289 | # CONFIG_RT_MUTEX_TESTER is not set | ||
3290 | # CONFIG_DEBUG_SPINLOCK is not set | ||
3291 | CONFIG_DEBUG_MUTEXES=y | ||
3292 | # CONFIG_DEBUG_LOCK_ALLOC is not set | ||
3293 | # CONFIG_PROVE_LOCKING is not set | ||
3294 | # CONFIG_SPARSE_RCU_POINTER is not set | ||
3295 | # CONFIG_LOCK_STAT is not set | ||
3296 | # CONFIG_DEBUG_SPINLOCK_SLEEP is not set | ||
3297 | # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set | ||
3298 | # CONFIG_DEBUG_KOBJECT is not set | ||
3299 | # CONFIG_DEBUG_BUGVERBOSE is not set | ||
3300 | # CONFIG_DEBUG_INFO is not set | ||
3301 | # CONFIG_DEBUG_VM is not set | ||
3302 | # CONFIG_DEBUG_WRITECOUNT is not set | ||
3303 | # CONFIG_DEBUG_MEMORY_INIT is not set | ||
3304 | # CONFIG_DEBUG_LIST is not set | ||
3305 | # CONFIG_TEST_LIST_SORT is not set | ||
3306 | # CONFIG_DEBUG_SG is not set | ||
3307 | # CONFIG_DEBUG_NOTIFIERS is not set | ||
3308 | # CONFIG_DEBUG_CREDENTIALS is not set | ||
3309 | # CONFIG_BOOT_PRINTK_DELAY is not set | ||
3310 | # CONFIG_RCU_TORTURE_TEST is not set | ||
3311 | # CONFIG_BACKTRACE_SELF_TEST is not set | ||
3312 | # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set | ||
3313 | # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set | ||
3314 | # CONFIG_LKDTM is not set | ||
3315 | # CONFIG_FAULT_INJECTION is not set | ||
3316 | # CONFIG_LATENCYTOP is not set | ||
3317 | # CONFIG_SYSCTL_SYSCALL_CHECK is not set | ||
3318 | # CONFIG_DEBUG_PAGEALLOC is not set | ||
3319 | CONFIG_HAVE_FUNCTION_TRACER=y | ||
3320 | CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y | ||
3321 | CONFIG_HAVE_DYNAMIC_FTRACE=y | ||
3322 | CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y | ||
3323 | CONFIG_HAVE_C_RECORDMCOUNT=y | ||
3324 | CONFIG_RING_BUFFER=y | ||
3325 | CONFIG_RING_BUFFER_ALLOW_SWAP=y | ||
3326 | CONFIG_TRACING_SUPPORT=y | ||
3327 | CONFIG_FTRACE=y | ||
3328 | # CONFIG_FUNCTION_TRACER is not set | ||
3329 | # CONFIG_IRQSOFF_TRACER is not set | ||
3330 | # CONFIG_SCHED_TRACER is not set | ||
3331 | # CONFIG_ENABLE_DEFAULT_TRACERS is not set | ||
3332 | CONFIG_BRANCH_PROFILE_NONE=y | ||
3333 | # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set | ||
3334 | # CONFIG_PROFILE_ALL_BRANCHES is not set | ||
3335 | # CONFIG_STACK_TRACER is not set | ||
3336 | # CONFIG_BLK_DEV_IO_TRACE is not set | ||
3337 | # CONFIG_RING_BUFFER_BENCHMARK is not set | ||
3338 | # CONFIG_DYNAMIC_DEBUG is not set | ||
3339 | # CONFIG_DMA_API_DEBUG is not set | ||
3340 | # CONFIG_ATOMIC64_SELFTEST is not set | ||
3341 | # CONFIG_ASYNC_RAID6_TEST is not set | ||
3342 | # CONFIG_SAMPLES is not set | ||
3343 | CONFIG_HAVE_ARCH_KGDB=y | ||
3344 | # CONFIG_KGDB is not set | ||
3345 | # CONFIG_TEST_KSTRTOX is not set | ||
3346 | # CONFIG_STRICT_DEVMEM is not set | ||
3347 | CONFIG_ARM_UNWIND=y | ||
3348 | # CONFIG_DEBUG_USER is not set | ||
3349 | # CONFIG_DEBUG_STACK_USAGE is not set | ||
3350 | # CONFIG_DEBUG_LL is not set | ||
3351 | # CONFIG_OC_ETM is not set | ||
3352 | |||
3353 | # | ||
3354 | # Security options | ||
3355 | # | ||
3356 | CONFIG_KEYS=y | ||
3357 | # CONFIG_KEYS_DEBUG_PROC_KEYS is not set | ||
3358 | # CONFIG_SECURITY_DMESG_RESTRICT is not set | ||
3359 | # CONFIG_SECURITY is not set | ||
3360 | # CONFIG_SECURITYFS is not set | ||
3361 | CONFIG_DEFAULT_SECURITY_DAC=y | ||
3362 | CONFIG_DEFAULT_SECURITY="" | ||
3363 | CONFIG_XOR_BLOCKS=m | ||
3364 | CONFIG_ASYNC_CORE=m | ||
3365 | CONFIG_ASYNC_MEMCPY=m | ||
3366 | CONFIG_ASYNC_XOR=m | ||
3367 | CONFIG_ASYNC_PQ=m | ||
3368 | CONFIG_ASYNC_RAID6_RECOV=m | ||
3369 | CONFIG_CRYPTO=y | ||
3370 | |||
3371 | # | ||
3372 | # Crypto core or helper | ||
3373 | # | ||
3374 | CONFIG_CRYPTO_ALGAPI=y | ||
3375 | CONFIG_CRYPTO_ALGAPI2=y | ||
3376 | CONFIG_CRYPTO_AEAD=m | ||
3377 | CONFIG_CRYPTO_AEAD2=y | ||
3378 | CONFIG_CRYPTO_BLKCIPHER=y | ||
3379 | CONFIG_CRYPTO_BLKCIPHER2=y | ||
3380 | CONFIG_CRYPTO_HASH=y | ||
3381 | CONFIG_CRYPTO_HASH2=y | ||
3382 | CONFIG_CRYPTO_RNG=m | ||
3383 | CONFIG_CRYPTO_RNG2=y | ||
3384 | CONFIG_CRYPTO_PCOMP2=y | ||
3385 | CONFIG_CRYPTO_MANAGER=y | ||
3386 | CONFIG_CRYPTO_MANAGER2=y | ||
3387 | CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y | ||
3388 | CONFIG_CRYPTO_GF128MUL=m | ||
3389 | CONFIG_CRYPTO_NULL=m | ||
3390 | CONFIG_CRYPTO_WORKQUEUE=y | ||
3391 | CONFIG_CRYPTO_CRYPTD=m | ||
3392 | CONFIG_CRYPTO_AUTHENC=m | ||
3393 | CONFIG_CRYPTO_TEST=m | ||
3394 | |||
3395 | # | ||
3396 | # Authenticated Encryption with Associated Data | ||
3397 | # | ||
3398 | CONFIG_CRYPTO_CCM=m | ||
3399 | CONFIG_CRYPTO_GCM=m | ||
3400 | CONFIG_CRYPTO_SEQIV=m | ||
3401 | |||
3402 | # | ||
3403 | # Block modes | ||
3404 | # | ||
3405 | CONFIG_CRYPTO_CBC=y | ||
3406 | CONFIG_CRYPTO_CTR=m | ||
3407 | CONFIG_CRYPTO_CTS=m | ||
3408 | CONFIG_CRYPTO_ECB=y | ||
3409 | CONFIG_CRYPTO_LRW=m | ||
3410 | CONFIG_CRYPTO_PCBC=m | ||
3411 | CONFIG_CRYPTO_XTS=m | ||
3412 | |||
3413 | # | ||
3414 | # Hash modes | ||
3415 | # | ||
3416 | CONFIG_CRYPTO_HMAC=m | ||
3417 | CONFIG_CRYPTO_XCBC=m | ||
3418 | # CONFIG_CRYPTO_VMAC is not set | ||
3419 | |||
3420 | # | ||
3421 | # Digest | ||
3422 | # | ||
3423 | CONFIG_CRYPTO_CRC32C=y | ||
3424 | CONFIG_CRYPTO_GHASH=m | ||
3425 | CONFIG_CRYPTO_MD4=m | ||
3426 | CONFIG_CRYPTO_MD5=y | ||
3427 | CONFIG_CRYPTO_MICHAEL_MIC=y | ||
3428 | CONFIG_CRYPTO_RMD128=m | ||
3429 | CONFIG_CRYPTO_RMD160=m | ||
3430 | CONFIG_CRYPTO_RMD256=m | ||
3431 | CONFIG_CRYPTO_RMD320=m | ||
3432 | CONFIG_CRYPTO_SHA1=m | ||
3433 | CONFIG_CRYPTO_SHA256=m | ||
3434 | CONFIG_CRYPTO_SHA512=m | ||
3435 | CONFIG_CRYPTO_TGR192=m | ||
3436 | CONFIG_CRYPTO_WP512=m | ||
3437 | |||
3438 | # | ||
3439 | # Ciphers | ||
3440 | # | ||
3441 | CONFIG_CRYPTO_AES=y | ||
3442 | CONFIG_CRYPTO_ANUBIS=m | ||
3443 | CONFIG_CRYPTO_ARC4=y | ||
3444 | CONFIG_CRYPTO_BLOWFISH=m | ||
3445 | CONFIG_CRYPTO_CAMELLIA=m | ||
3446 | CONFIG_CRYPTO_CAST5=m | ||
3447 | CONFIG_CRYPTO_CAST6=m | ||
3448 | CONFIG_CRYPTO_DES=y | ||
3449 | CONFIG_CRYPTO_FCRYPT=m | ||
3450 | CONFIG_CRYPTO_KHAZAD=m | ||
3451 | CONFIG_CRYPTO_SALSA20=m | ||
3452 | CONFIG_CRYPTO_SEED=m | ||
3453 | CONFIG_CRYPTO_SERPENT=m | ||
3454 | CONFIG_CRYPTO_TEA=m | ||
3455 | CONFIG_CRYPTO_TWOFISH=m | ||
3456 | CONFIG_CRYPTO_TWOFISH_COMMON=m | ||
3457 | |||
3458 | # | ||
3459 | # Compression | ||
3460 | # | ||
3461 | CONFIG_CRYPTO_DEFLATE=y | ||
3462 | # CONFIG_CRYPTO_ZLIB is not set | ||
3463 | CONFIG_CRYPTO_LZO=y | ||
3464 | |||
3465 | # | ||
3466 | # Random Number Generation | ||
3467 | # | ||
3468 | CONFIG_CRYPTO_ANSI_CPRNG=m | ||
3469 | CONFIG_CRYPTO_USER_API=m | ||
3470 | CONFIG_CRYPTO_USER_API_HASH=m | ||
3471 | CONFIG_CRYPTO_USER_API_SKCIPHER=m | ||
3472 | CONFIG_CRYPTO_HW=y | ||
3473 | CONFIG_CRYPTO_DEV_OMAP_SHAM=m | ||
3474 | CONFIG_CRYPTO_DEV_OMAP_AES=m | ||
3475 | # CONFIG_BINARY_PRINTF is not set | ||
3476 | |||
3477 | # | ||
3478 | # Library routines | ||
3479 | # | ||
3480 | CONFIG_RAID6_PQ=m | ||
3481 | CONFIG_BITREVERSE=y | ||
3482 | CONFIG_GENERIC_FIND_LAST_BIT=y | ||
3483 | CONFIG_CRC_CCITT=y | ||
3484 | CONFIG_CRC16=y | ||
3485 | CONFIG_CRC_T10DIF=y | ||
3486 | CONFIG_CRC_ITU_T=y | ||
3487 | CONFIG_CRC32=y | ||
3488 | CONFIG_CRC7=y | ||
3489 | CONFIG_LIBCRC32C=y | ||
3490 | CONFIG_ZLIB_INFLATE=y | ||
3491 | CONFIG_ZLIB_DEFLATE=y | ||
3492 | CONFIG_LZO_COMPRESS=y | ||
3493 | CONFIG_LZO_DECOMPRESS=y | ||
3494 | CONFIG_XZ_DEC=y | ||
3495 | CONFIG_XZ_DEC_X86=y | ||
3496 | CONFIG_XZ_DEC_POWERPC=y | ||
3497 | CONFIG_XZ_DEC_IA64=y | ||
3498 | CONFIG_XZ_DEC_ARM=y | ||
3499 | CONFIG_XZ_DEC_ARMTHUMB=y | ||
3500 | CONFIG_XZ_DEC_SPARC=y | ||
3501 | CONFIG_XZ_DEC_BCJ=y | ||
3502 | CONFIG_XZ_DEC_TEST=m | ||
3503 | CONFIG_DECOMPRESS_GZIP=y | ||
3504 | CONFIG_DECOMPRESS_BZIP2=y | ||
3505 | CONFIG_DECOMPRESS_LZMA=y | ||
3506 | CONFIG_DECOMPRESS_XZ=y | ||
3507 | CONFIG_DECOMPRESS_LZO=y | ||
3508 | CONFIG_TEXTSEARCH=y | ||
3509 | CONFIG_TEXTSEARCH_KMP=m | ||
3510 | CONFIG_TEXTSEARCH_BM=m | ||
3511 | CONFIG_TEXTSEARCH_FSM=m | ||
3512 | CONFIG_BTREE=y | ||
3513 | CONFIG_HAS_IOMEM=y | ||
3514 | CONFIG_HAS_IOPORT=y | ||
3515 | CONFIG_HAS_DMA=y | ||
3516 | CONFIG_NLATTR=y | ||
3517 | CONFIG_AVERAGE=y | ||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/camera/0001-Add-driver-for-Aptina-Micron-mt9p031-sensor.patch b/recipes-kernel/linux/linux-omap-2.6.39/camera/0001-Add-driver-for-Aptina-Micron-mt9p031-sensor.patch deleted file mode 100644 index cf9e116d..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/camera/0001-Add-driver-for-Aptina-Micron-mt9p031-sensor.patch +++ /dev/null | |||
@@ -1,859 +0,0 @@ | |||
1 | From e630a914bf14bf190feaf4a2cc57f6b27c4024e1 Mon Sep 17 00:00:00 2001 | ||
2 | From: Javier Martin <javier.martin@vista-silicon.com> | ||
3 | Date: Wed, 1 Jun 2011 17:36:48 +0200 | ||
4 | Subject: [PATCH 1/3] Add driver for Aptina (Micron) mt9p031 sensor. | ||
5 | |||
6 | Clock frequency of 57MHz used in previous version was wrong since | ||
7 | when VDD_IO is 1.8V it can only support 48MHz. | ||
8 | |||
9 | Two new platform flags have been added: | ||
10 | |||
11 | - vdd_io: indicates whether the chip is powered with 1.8 or 2.8 VDD_IO. | ||
12 | So that it can use the maximum allowed frequency. | ||
13 | - version: monochrome and color versions of the chip have exactly | ||
14 | the same ID, so the only way to select one of them is through | ||
15 | platform data. | ||
16 | |||
17 | Internal PLL is now used to generate PIXCLK depending on VDD_IO. | ||
18 | |||
19 | Signed-off-by: Javier Martin <javier.martin@vista-silicon.com> | ||
20 | --- | ||
21 | drivers/media/video/Kconfig | 7 + | ||
22 | drivers/media/video/Makefile | 1 + | ||
23 | drivers/media/video/mt9p031.c | 763 +++++++++++++++++++++++++++++++++++++++++ | ||
24 | include/media/mt9p031.h | 23 ++ | ||
25 | 4 files changed, 794 insertions(+), 0 deletions(-) | ||
26 | create mode 100644 drivers/media/video/mt9p031.c | ||
27 | create mode 100644 include/media/mt9p031.h | ||
28 | |||
29 | diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig | ||
30 | index 00f51dd..cb87e35 100644 | ||
31 | --- a/drivers/media/video/Kconfig | ||
32 | +++ b/drivers/media/video/Kconfig | ||
33 | @@ -329,6 +329,13 @@ config VIDEO_OV7670 | ||
34 | OV7670 VGA camera. It currently only works with the M88ALP01 | ||
35 | controller. | ||
36 | |||
37 | +config VIDEO_MT9P031 | ||
38 | + tristate "Aptina MT9P031 support" | ||
39 | + depends on I2C && VIDEO_V4L2 | ||
40 | + ---help--- | ||
41 | + This is a Video4Linux2 sensor-level driver for the Aptina | ||
42 | + (Micron) mt9p031 5 Mpixel camera. | ||
43 | + | ||
44 | config VIDEO_MT9V011 | ||
45 | tristate "Micron mt9v011 sensor support" | ||
46 | depends on I2C && VIDEO_V4L2 | ||
47 | diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile | ||
48 | index ace5d8b..912b29b 100644 | ||
49 | --- a/drivers/media/video/Makefile | ||
50 | +++ b/drivers/media/video/Makefile | ||
51 | @@ -65,6 +65,7 @@ obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o | ||
52 | obj-$(CONFIG_VIDEO_OV7670) += ov7670.o | ||
53 | obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o | ||
54 | obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o | ||
55 | +obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o | ||
56 | obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o | ||
57 | obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o | ||
58 | obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o | ||
59 | diff --git a/drivers/media/video/mt9p031.c b/drivers/media/video/mt9p031.c | ||
60 | new file mode 100644 | ||
61 | index 0000000..cd830b1 | ||
62 | --- /dev/null | ||
63 | +++ b/drivers/media/video/mt9p031.c | ||
64 | @@ -0,0 +1,763 @@ | ||
65 | +/* | ||
66 | + * Driver for MT9P031 CMOS Image Sensor from Aptina | ||
67 | + * | ||
68 | + * Copyright (C) 2011, Javier Martin <javier.martin@vista-silicon.com> | ||
69 | + * | ||
70 | + * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de> | ||
71 | + * | ||
72 | + * Based on the MT9V032 driver and Bastian Hecht's code. | ||
73 | + * | ||
74 | + * This program is free software; you can redistribute it and/or modify | ||
75 | + * it under the terms of the GNU General Public License version 2 as | ||
76 | + * published by the Free Software Foundation. | ||
77 | + */ | ||
78 | + | ||
79 | +#include <linux/delay.h> | ||
80 | +#include <linux/device.h> | ||
81 | +#include <linux/i2c.h> | ||
82 | +#include <linux/log2.h> | ||
83 | +#include <linux/pm.h> | ||
84 | +#include <linux/slab.h> | ||
85 | +#include <media/v4l2-subdev.h> | ||
86 | +#include <linux/videodev2.h> | ||
87 | + | ||
88 | +#include <media/mt9p031.h> | ||
89 | +#include <media/v4l2-chip-ident.h> | ||
90 | +#include <media/v4l2-subdev.h> | ||
91 | +#include <media/v4l2-device.h> | ||
92 | + | ||
93 | +#define MT9P031_EXTCLK_FREQ 20000000 | ||
94 | + | ||
95 | +#define MT9P031_CHIP_VERSION 0x00 | ||
96 | +#define MT9P031_CHIP_VERSION_VALUE 0x1801 | ||
97 | +#define MT9P031_ROW_START 0x01 | ||
98 | +#define MT9P031_ROW_START_MIN 1 | ||
99 | +#define MT9P031_ROW_START_MAX 2004 | ||
100 | +#define MT9P031_ROW_START_DEF 54 | ||
101 | +#define MT9P031_COLUMN_START 0x02 | ||
102 | +#define MT9P031_COLUMN_START_MIN 1 | ||
103 | +#define MT9P031_COLUMN_START_MAX 2750 | ||
104 | +#define MT9P031_COLUMN_START_DEF 16 | ||
105 | +#define MT9P031_WINDOW_HEIGHT 0x03 | ||
106 | +#define MT9P031_WINDOW_HEIGHT_MIN 2 | ||
107 | +#define MT9P031_WINDOW_HEIGHT_MAX 2003 | ||
108 | +#define MT9P031_WINDOW_HEIGHT_DEF 2003 | ||
109 | +#define MT9P031_WINDOW_WIDTH 0x04 | ||
110 | +#define MT9P031_WINDOW_WIDTH_MIN 18 | ||
111 | +#define MT9P031_WINDOW_WIDTH_MAX 2751 | ||
112 | +#define MT9P031_WINDOW_WIDTH_DEF 2751 | ||
113 | +#define MT9P031_H_BLANKING 0x05 | ||
114 | +#define MT9P031_H_BLANKING_VALUE 0 | ||
115 | +#define MT9P031_V_BLANKING 0x06 | ||
116 | +#define MT9P031_V_BLANKING_VALUE 25 | ||
117 | +#define MT9P031_OUTPUT_CONTROL 0x07 | ||
118 | +#define MT9P031_OUTPUT_CONTROL_CEN 2 | ||
119 | +#define MT9P031_OUTPUT_CONTROL_SYN 1 | ||
120 | +#define MT9P031_SHUTTER_WIDTH_UPPER 0x08 | ||
121 | +#define MT9P031_SHUTTER_WIDTH 0x09 | ||
122 | +#define MT9P031_PLL_CONTROL 0x10 | ||
123 | +#define MT9P031_PLL_CONTROL_PWROFF 0x0050 | ||
124 | +#define MT9P031_PLL_CONTROL_PWRON 0x0051 | ||
125 | +#define MT9P031_PLL_CONTROL_USEPLL 0x0052 | ||
126 | +#define MT9P031_PLL_CONFIG_1 0x11 | ||
127 | +#define MT9P031_PLL_CONFIG_1_M_48MHZ 0x5000 | ||
128 | +#define MT9P031_PLL_CONFIG_1_N_48MHZ 0x05 | ||
129 | +#define MT9P031_PLL_CONFIG_1_M_96MHZ 0x3600 | ||
130 | +#define MT9P031_PLL_CONFIG_1_N_96MHZ 0x05 | ||
131 | +#define MT9P031_PLL_CONFIG_2 0x12 | ||
132 | +#define MT9P031_PLL_CONFIG_2_P1_48MHZ 5 | ||
133 | +#define MT9P031_PLL_CONFIG_2_P1_96MHZ 2 | ||
134 | +#define MT9P031_PIXEL_CLOCK_CONTROL 0x0a | ||
135 | +#define MT9P031_FRAME_RESTART 0x0b | ||
136 | +#define MT9P031_SHUTTER_DELAY 0x0c | ||
137 | +#define MT9P031_RST 0x0d | ||
138 | +#define MT9P031_RST_ENABLE 1 | ||
139 | +#define MT9P031_RST_DISABLE 0 | ||
140 | +#define MT9P031_READ_MODE_1 0x1e | ||
141 | +#define MT9P031_READ_MODE_2 0x20 | ||
142 | +#define MT9P031_READ_MODE_2_ROW_MIR 0x8000 | ||
143 | +#define MT9P031_READ_MODE_2_COL_MIR 0x4000 | ||
144 | +#define MT9P031_ROW_ADDRESS_MODE 0x22 | ||
145 | +#define MT9P031_COLUMN_ADDRESS_MODE 0x23 | ||
146 | +#define MT9P031_GLOBAL_GAIN 0x35 | ||
147 | + | ||
148 | +struct mt9p031 { | ||
149 | + struct v4l2_subdev subdev; | ||
150 | + struct media_pad pad; | ||
151 | + struct v4l2_rect rect; /* Sensor window */ | ||
152 | + struct v4l2_mbus_framefmt format; | ||
153 | + struct mt9p031_platform_data *pdata; | ||
154 | + struct mutex power_lock; /* lock to protect power_count */ | ||
155 | + int power_count; | ||
156 | + u16 xskip; | ||
157 | + u16 yskip; | ||
158 | + /* cache register values */ | ||
159 | + u16 output_control; | ||
160 | +}; | ||
161 | + | ||
162 | +static struct mt9p031 *to_mt9p031(const struct i2c_client *client) | ||
163 | +{ | ||
164 | + return container_of(i2c_get_clientdata(client), struct mt9p031, subdev); | ||
165 | +} | ||
166 | + | ||
167 | +static int reg_read(struct i2c_client *client, const u8 reg) | ||
168 | +{ | ||
169 | + s32 data = i2c_smbus_read_word_data(client, reg); | ||
170 | + return data < 0 ? data : swab16(data); | ||
171 | +} | ||
172 | + | ||
173 | +static int reg_write(struct i2c_client *client, const u8 reg, | ||
174 | + const u16 data) | ||
175 | +{ | ||
176 | + return i2c_smbus_write_word_data(client, reg, swab16(data)); | ||
177 | +} | ||
178 | + | ||
179 | +static int mt9p031_set_output_control(struct mt9p031 *mt9p031, u16 clear, | ||
180 | + u16 set) | ||
181 | +{ | ||
182 | + struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); | ||
183 | + u16 value = (mt9p031->output_control & ~clear) | set; | ||
184 | + int ret; | ||
185 | + | ||
186 | + ret = reg_write(client, MT9P031_OUTPUT_CONTROL, value); | ||
187 | + if (ret < 0) | ||
188 | + return ret; | ||
189 | + mt9p031->output_control = value; | ||
190 | + return 0; | ||
191 | +} | ||
192 | + | ||
193 | +static int mt9p031_reset(struct i2c_client *client) | ||
194 | +{ | ||
195 | + struct mt9p031 *mt9p031 = to_mt9p031(client); | ||
196 | + int ret; | ||
197 | + | ||
198 | + /* Disable chip output, synchronous option update */ | ||
199 | + ret = reg_write(client, MT9P031_RST, MT9P031_RST_ENABLE); | ||
200 | + if (ret < 0) | ||
201 | + return ret; | ||
202 | + ret = reg_write(client, MT9P031_RST, MT9P031_RST_DISABLE); | ||
203 | + if (ret < 0) | ||
204 | + return ret; | ||
205 | + return mt9p031_set_output_control(mt9p031, | ||
206 | + MT9P031_OUTPUT_CONTROL_CEN, 0); | ||
207 | +} | ||
208 | + | ||
209 | +static int mt9p031_power_on(struct mt9p031 *mt9p031) | ||
210 | +{ | ||
211 | + struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); | ||
212 | + int ret; | ||
213 | + | ||
214 | + /* Ensure RESET_BAR is low */ | ||
215 | + if (mt9p031->pdata->reset) { | ||
216 | + mt9p031->pdata->reset(&mt9p031->subdev, 1); | ||
217 | + msleep(1); | ||
218 | + } | ||
219 | + /* Emable clock */ | ||
220 | + if (mt9p031->pdata->set_xclk) | ||
221 | + mt9p031->pdata->set_xclk(&mt9p031->subdev, MT9P031_EXTCLK_FREQ); | ||
222 | + /* Now RESET_BAR must be high */ | ||
223 | + if (mt9p031->pdata->reset) { | ||
224 | + mt9p031->pdata->reset(&mt9p031->subdev, 0); | ||
225 | + msleep(1); | ||
226 | + } | ||
227 | + /* soft reset */ | ||
228 | + ret = mt9p031_reset(client); | ||
229 | + if (ret < 0) { | ||
230 | + dev_err(&client->dev, "Failed to reset the camera\n"); | ||
231 | + return ret; | ||
232 | + } | ||
233 | + return 0; | ||
234 | +} | ||
235 | + | ||
236 | +static void mt9p031_power_off(struct mt9p031 *mt9p031) | ||
237 | +{ | ||
238 | + if (mt9p031->pdata->reset) { | ||
239 | + mt9p031->pdata->reset(&mt9p031->subdev, 1); | ||
240 | + msleep(1); | ||
241 | + } | ||
242 | + if (mt9p031->pdata->set_xclk) | ||
243 | + mt9p031->pdata->set_xclk(&mt9p031->subdev, 0); | ||
244 | +} | ||
245 | + | ||
246 | +static int mt9p031_enum_mbus_code(struct v4l2_subdev *sd, | ||
247 | + struct v4l2_subdev_fh *fh, | ||
248 | + struct v4l2_subdev_mbus_code_enum *code) | ||
249 | +{ | ||
250 | + struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev); | ||
251 | + | ||
252 | + if (code->pad || code->index) | ||
253 | + return -EINVAL; | ||
254 | + | ||
255 | + code->code = mt9p031->format.code; | ||
256 | + return 0; | ||
257 | +} | ||
258 | + | ||
259 | +static struct v4l2_mbus_framefmt *mt9p031_get_pad_format( | ||
260 | + struct mt9p031 *mt9p031, | ||
261 | + struct v4l2_subdev_fh *fh, | ||
262 | + unsigned int pad, u32 which) | ||
263 | +{ | ||
264 | + switch (which) { | ||
265 | + case V4L2_SUBDEV_FORMAT_TRY: | ||
266 | + return v4l2_subdev_get_try_format(fh, pad); | ||
267 | + case V4L2_SUBDEV_FORMAT_ACTIVE: | ||
268 | + return &mt9p031->format; | ||
269 | + default: | ||
270 | + return NULL; | ||
271 | + } | ||
272 | +} | ||
273 | + | ||
274 | +static struct v4l2_rect *mt9p031_get_pad_crop(struct mt9p031 *mt9p031, | ||
275 | + struct v4l2_subdev_fh *fh, unsigned int pad, u32 which) | ||
276 | +{ | ||
277 | + switch (which) { | ||
278 | + case V4L2_SUBDEV_FORMAT_TRY: | ||
279 | + return v4l2_subdev_get_try_crop(fh, pad); | ||
280 | + case V4L2_SUBDEV_FORMAT_ACTIVE: | ||
281 | + return &mt9p031->rect; | ||
282 | + default: | ||
283 | + return NULL; | ||
284 | + } | ||
285 | +} | ||
286 | + | ||
287 | +static int mt9p031_get_crop(struct v4l2_subdev *sd, | ||
288 | + struct v4l2_subdev_fh *fh, | ||
289 | + struct v4l2_subdev_crop *crop) | ||
290 | +{ | ||
291 | + struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev); | ||
292 | + struct v4l2_rect *rect = mt9p031_get_pad_crop(mt9p031, fh, crop->pad, | ||
293 | + crop->which); | ||
294 | + if (!rect) | ||
295 | + return -EINVAL; | ||
296 | + | ||
297 | + crop->rect = *rect; | ||
298 | + | ||
299 | + return 0; | ||
300 | +} | ||
301 | + | ||
302 | +static u16 mt9p031_skip_for_crop(s32 source, s32 *target, s32 max_skip) | ||
303 | +{ | ||
304 | + unsigned int skip; | ||
305 | + | ||
306 | + if (source - source / 4 < *target) { | ||
307 | + *target = source; | ||
308 | + return 1; | ||
309 | + } | ||
310 | + | ||
311 | + skip = DIV_ROUND_CLOSEST(source, *target); | ||
312 | + if (skip > max_skip) | ||
313 | + skip = max_skip; | ||
314 | + *target = 2 * DIV_ROUND_UP(source, 2 * skip); | ||
315 | + | ||
316 | + return skip; | ||
317 | +} | ||
318 | + | ||
319 | +static int mt9p031_set_params(struct i2c_client *client, | ||
320 | + struct v4l2_rect *rect, u16 xskip, u16 yskip) | ||
321 | +{ | ||
322 | + struct mt9p031 *mt9p031 = to_mt9p031(client); | ||
323 | + int ret; | ||
324 | + u16 xbin, ybin; | ||
325 | + const u16 hblank = MT9P031_H_BLANKING_VALUE, | ||
326 | + vblank = MT9P031_V_BLANKING_VALUE; | ||
327 | + __s32 left; | ||
328 | + | ||
329 | + /* | ||
330 | + * TODO: Attention! When implementing horizontal flipping, adjust | ||
331 | + * alignment according to R2 "Column Start" description in the datasheet | ||
332 | + */ | ||
333 | + if (xskip & 1) { | ||
334 | + xbin = 1; | ||
335 | + left = rect->left & (~3); | ||
336 | + } else if (xskip & 2) { | ||
337 | + xbin = 2; | ||
338 | + left = rect->left & (~7); | ||
339 | + } else { | ||
340 | + xbin = 4; | ||
341 | + left = rect->left & (~15); | ||
342 | + } | ||
343 | + ybin = min(yskip, (u16)4); | ||
344 | + | ||
345 | + /* Disable register update, reconfigure atomically */ | ||
346 | + ret = mt9p031_set_output_control(mt9p031, 0, | ||
347 | + MT9P031_OUTPUT_CONTROL_SYN); | ||
348 | + if (ret < 0) | ||
349 | + return ret; | ||
350 | + | ||
351 | + dev_dbg(&client->dev, "skip %u:%u, rect %ux%u@%u:%u\n", | ||
352 | + xskip, yskip, rect->width, rect->height, rect->left, rect->top); | ||
353 | + | ||
354 | + /* Blanking and start values - default... */ | ||
355 | + ret = reg_write(client, MT9P031_H_BLANKING, hblank); | ||
356 | + if (ret < 0) | ||
357 | + return ret; | ||
358 | + ret = reg_write(client, MT9P031_V_BLANKING, vblank); | ||
359 | + if (ret < 0) | ||
360 | + return ret; | ||
361 | + | ||
362 | + ret = reg_write(client, MT9P031_COLUMN_ADDRESS_MODE, | ||
363 | + ((xbin - 1) << 4) | (xskip - 1)); | ||
364 | + if (ret < 0) | ||
365 | + return ret; | ||
366 | + ret = reg_write(client, MT9P031_ROW_ADDRESS_MODE, | ||
367 | + ((ybin - 1) << 4) | (yskip - 1)); | ||
368 | + if (ret < 0) | ||
369 | + return ret; | ||
370 | + | ||
371 | + dev_dbg(&client->dev, "new physical left %u, top %u\n", | ||
372 | + rect->left, rect->top); | ||
373 | + | ||
374 | + ret = reg_write(client, MT9P031_COLUMN_START, | ||
375 | + rect->left); | ||
376 | + if (ret < 0) | ||
377 | + return ret; | ||
378 | + ret = reg_write(client, MT9P031_ROW_START, | ||
379 | + rect->top); | ||
380 | + if (ret < 0) | ||
381 | + return ret; | ||
382 | + | ||
383 | + ret = reg_write(client, MT9P031_WINDOW_WIDTH, | ||
384 | + rect->width - 1); | ||
385 | + if (ret < 0) | ||
386 | + return ret; | ||
387 | + ret = reg_write(client, MT9P031_WINDOW_HEIGHT, | ||
388 | + rect->height - 1); | ||
389 | + if (ret < 0) | ||
390 | + return ret; | ||
391 | + | ||
392 | + /* Re-enable register update, commit all changes */ | ||
393 | + ret = mt9p031_set_output_control(mt9p031, | ||
394 | + MT9P031_OUTPUT_CONTROL_SYN, 0); | ||
395 | + if (ret < 0) | ||
396 | + return ret; | ||
397 | + | ||
398 | + mt9p031->xskip = xskip; | ||
399 | + mt9p031->yskip = yskip; | ||
400 | + return ret; | ||
401 | +} | ||
402 | + | ||
403 | +static int mt9p031_set_crop(struct v4l2_subdev *sd, | ||
404 | + struct v4l2_subdev_fh *fh, | ||
405 | + struct v4l2_subdev_crop *crop) | ||
406 | +{ | ||
407 | + struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev); | ||
408 | + struct v4l2_mbus_framefmt *f; | ||
409 | + struct v4l2_rect *c; | ||
410 | + struct v4l2_rect rect; | ||
411 | + u16 xskip, yskip; | ||
412 | + s32 width, height; | ||
413 | + | ||
414 | + dev_dbg(mt9p031->subdev.v4l2_dev->dev, "%s(%ux%u@%u:%u : %u)\n", | ||
415 | + __func__, crop->rect.width, crop->rect.height, | ||
416 | + crop->rect.left, crop->rect.top, crop->which); | ||
417 | + | ||
418 | + /* | ||
419 | + * Clamp the crop rectangle boundaries and align them to a multiple of 2 | ||
420 | + * pixels. | ||
421 | + */ | ||
422 | + rect.width = ALIGN(clamp(crop->rect.width, | ||
423 | + MT9P031_WINDOW_WIDTH_MIN, | ||
424 | + MT9P031_WINDOW_WIDTH_MAX), 2); | ||
425 | + rect.height = ALIGN(clamp(crop->rect.height, | ||
426 | + MT9P031_WINDOW_HEIGHT_MIN, | ||
427 | + MT9P031_WINDOW_HEIGHT_MAX), 2); | ||
428 | + rect.left = ALIGN(clamp(crop->rect.left, | ||
429 | + MT9P031_COLUMN_START_MIN, | ||
430 | + MT9P031_COLUMN_START_MAX), 2); | ||
431 | + rect.top = ALIGN(clamp(crop->rect.top, | ||
432 | + MT9P031_ROW_START_MIN, | ||
433 | + MT9P031_ROW_START_MAX), 2); | ||
434 | + | ||
435 | + c = mt9p031_get_pad_crop(mt9p031, fh, crop->pad, crop->which); | ||
436 | + | ||
437 | + if (rect.width != c->width || rect.height != c->height) { | ||
438 | + /* | ||
439 | + * Reset the output image size if the crop rectangle size has | ||
440 | + * been modified. | ||
441 | + */ | ||
442 | + f = mt9p031_get_pad_format(mt9p031, fh, crop->pad, | ||
443 | + crop->which); | ||
444 | + width = f->width; | ||
445 | + height = f->height; | ||
446 | + | ||
447 | + xskip = mt9p031_skip_for_crop(rect.width, &width, 7); | ||
448 | + yskip = mt9p031_skip_for_crop(rect.height, &height, 8); | ||
449 | + } else { | ||
450 | + xskip = mt9p031->xskip; | ||
451 | + yskip = mt9p031->yskip; | ||
452 | + f = NULL; | ||
453 | + } | ||
454 | + if (f) { | ||
455 | + f->width = width; | ||
456 | + f->height = height; | ||
457 | + } | ||
458 | + | ||
459 | + *c = rect; | ||
460 | + crop->rect = rect; | ||
461 | + | ||
462 | + mt9p031->xskip = xskip; | ||
463 | + mt9p031->yskip = yskip; | ||
464 | + mt9p031->rect = *c; | ||
465 | + return 0; | ||
466 | +} | ||
467 | + | ||
468 | +static int mt9p031_get_format(struct v4l2_subdev *sd, | ||
469 | + struct v4l2_subdev_fh *fh, | ||
470 | + struct v4l2_subdev_format *fmt) | ||
471 | +{ | ||
472 | + struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev); | ||
473 | + | ||
474 | + fmt->format = | ||
475 | + *mt9p031_get_pad_format(mt9p031, fh, fmt->pad, fmt->which); | ||
476 | + return 0; | ||
477 | +} | ||
478 | + | ||
479 | +static u16 mt9p031_skip_for_scale(s32 *source, s32 target, | ||
480 | + s32 max_skip, s32 max) | ||
481 | +{ | ||
482 | + unsigned int skip; | ||
483 | + | ||
484 | + if (*source - *source / 4 < target) { | ||
485 | + *source = target; | ||
486 | + return 1; | ||
487 | + } | ||
488 | + | ||
489 | + skip = min(max, *source + target / 2) / target; | ||
490 | + if (skip > max_skip) | ||
491 | + skip = max_skip; | ||
492 | + *source = target * skip; | ||
493 | + | ||
494 | + return skip; | ||
495 | +} | ||
496 | + | ||
497 | +static int mt9p031_set_format(struct v4l2_subdev *sd, | ||
498 | + struct v4l2_subdev_fh *fh, | ||
499 | + struct v4l2_subdev_format *format) | ||
500 | +{ | ||
501 | + struct v4l2_mbus_framefmt *__format; | ||
502 | + struct v4l2_rect *__crop, rect; | ||
503 | + struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev); | ||
504 | + unsigned int width; | ||
505 | + unsigned int height; | ||
506 | + u16 xskip, yskip; | ||
507 | + | ||
508 | + __crop = mt9p031_get_pad_crop(mt9p031, fh, format->pad, format->which); | ||
509 | + | ||
510 | + width = clamp_t(int, ALIGN(format->format.width, 2), 2, | ||
511 | + MT9P031_WINDOW_WIDTH_MAX); | ||
512 | + height = clamp_t(int, ALIGN(format->format.height, 2), 2, | ||
513 | + MT9P031_WINDOW_HEIGHT_MAX); | ||
514 | + | ||
515 | + rect.width = __crop->width; | ||
516 | + rect.height = __crop->height; | ||
517 | + | ||
518 | + xskip = mt9p031_skip_for_scale(&rect.width, width, 7, | ||
519 | + MT9P031_WINDOW_WIDTH_MAX); | ||
520 | + if (rect.width + __crop->left > MT9P031_WINDOW_WIDTH_MAX) | ||
521 | + rect.left = (MT9P031_WINDOW_WIDTH_MAX - rect.width) / 2; | ||
522 | + else | ||
523 | + rect.left = __crop->left; | ||
524 | + yskip = mt9p031_skip_for_scale(&rect.height, height, 8, | ||
525 | + MT9P031_WINDOW_HEIGHT_MAX); | ||
526 | + if (rect.height + __crop->top > MT9P031_WINDOW_HEIGHT_MAX) | ||
527 | + rect.top = (MT9P031_WINDOW_HEIGHT_MAX - rect.height) / 2; | ||
528 | + else | ||
529 | + rect.top = __crop->top; | ||
530 | + | ||
531 | + dev_dbg(mt9p031->subdev.v4l2_dev->dev, "%s(%ux%u : %u)\n", __func__, | ||
532 | + width, height, format->which); | ||
533 | + if (__crop) | ||
534 | + *__crop = rect; | ||
535 | + | ||
536 | + __format = mt9p031_get_pad_format(mt9p031, fh, format->pad, | ||
537 | + format->which); | ||
538 | + __format->width = width; | ||
539 | + __format->height = height; | ||
540 | + format->format = *__format; | ||
541 | + | ||
542 | + mt9p031->xskip = xskip; | ||
543 | + mt9p031->yskip = yskip; | ||
544 | + mt9p031->rect = *__crop; | ||
545 | + return 0; | ||
546 | +} | ||
547 | + | ||
548 | +static int mt9p031_pll_enable(struct i2c_client *client) | ||
549 | +{ | ||
550 | + struct mt9p031 *mt9p031 = to_mt9p031(client); | ||
551 | + int ret; | ||
552 | + | ||
553 | + ret = reg_write(client, MT9P031_PLL_CONTROL, MT9P031_PLL_CONTROL_PWRON); | ||
554 | + if (ret < 0) | ||
555 | + return ret; | ||
556 | + | ||
557 | + /* Always set the maximum frequency allowed by VDD_IO */ | ||
558 | + if (mt9p031->pdata->vdd_io == MT9P031_VDD_IO_2V8) { | ||
559 | + ret = reg_write(client, MT9P031_PLL_CONFIG_1, | ||
560 | + MT9P031_PLL_CONFIG_1_M_96MHZ | | ||
561 | + MT9P031_PLL_CONFIG_1_N_96MHZ); | ||
562 | + if (ret < 0) | ||
563 | + return ret; | ||
564 | + ret = reg_write(client, MT9P031_PLL_CONFIG_2, | ||
565 | + MT9P031_PLL_CONFIG_2_P1_96MHZ); | ||
566 | + if (ret < 0) | ||
567 | + return ret; | ||
568 | + } else { | ||
569 | + ret = reg_write(client, MT9P031_PLL_CONFIG_1, | ||
570 | + MT9P031_PLL_CONFIG_1_M_48MHZ | | ||
571 | + MT9P031_PLL_CONFIG_1_N_48MHZ); | ||
572 | + if (ret < 0) | ||
573 | + return ret; | ||
574 | + ret = reg_write(client, MT9P031_PLL_CONFIG_2, | ||
575 | + MT9P031_PLL_CONFIG_2_P1_48MHZ); | ||
576 | + if (ret < 0) | ||
577 | + return ret; | ||
578 | + } | ||
579 | + mdelay(1); | ||
580 | + ret = reg_write(client, MT9P031_PLL_CONTROL, | ||
581 | + MT9P031_PLL_CONTROL_PWRON | | ||
582 | + MT9P031_PLL_CONTROL_USEPLL); | ||
583 | + mdelay(1); | ||
584 | + return ret; | ||
585 | +} | ||
586 | + | ||
587 | +static inline int mt9p031_pll_disable(struct i2c_client *client) | ||
588 | +{ | ||
589 | + return reg_write(client, MT9P031_PLL_CONTROL, | ||
590 | + MT9P031_PLL_CONTROL_PWROFF); | ||
591 | +} | ||
592 | + | ||
593 | +static int mt9p031_s_stream(struct v4l2_subdev *sd, int enable) | ||
594 | +{ | ||
595 | + struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev); | ||
596 | + struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); | ||
597 | + struct v4l2_rect rect = mt9p031->rect; | ||
598 | + u16 xskip = mt9p031->xskip; | ||
599 | + u16 yskip = mt9p031->yskip; | ||
600 | + int ret; | ||
601 | + | ||
602 | + if (enable) { | ||
603 | + ret = mt9p031_set_params(client, &rect, xskip, yskip); | ||
604 | + if (ret < 0) | ||
605 | + return ret; | ||
606 | + /* Switch to master "normal" mode */ | ||
607 | + ret = mt9p031_set_output_control(mt9p031, 0, | ||
608 | + MT9P031_OUTPUT_CONTROL_CEN); | ||
609 | + if (ret < 0) | ||
610 | + return ret; | ||
611 | + ret = mt9p031_pll_enable(client); | ||
612 | + } else { | ||
613 | + /* Stop sensor readout */ | ||
614 | + ret = mt9p031_set_output_control(mt9p031, | ||
615 | + MT9P031_OUTPUT_CONTROL_CEN, 0); | ||
616 | + if (ret < 0) | ||
617 | + return ret; | ||
618 | + ret = mt9p031_pll_disable(client); | ||
619 | + } | ||
620 | + return ret; | ||
621 | +} | ||
622 | + | ||
623 | +static int mt9p031_video_probe(struct i2c_client *client) | ||
624 | +{ | ||
625 | + s32 data; | ||
626 | + | ||
627 | + /* Read out the chip version register */ | ||
628 | + data = reg_read(client, MT9P031_CHIP_VERSION); | ||
629 | + if (data != MT9P031_CHIP_VERSION_VALUE) { | ||
630 | + dev_err(&client->dev, | ||
631 | + "No MT9P031 chip detected, register read %x\n", data); | ||
632 | + return -ENODEV; | ||
633 | + } | ||
634 | + | ||
635 | + dev_info(&client->dev, "Detected a MT9P031 chip ID %x\n", data); | ||
636 | + | ||
637 | + return 0; | ||
638 | +} | ||
639 | + | ||
640 | +static int mt9p031_set_power(struct v4l2_subdev *sd, int on) | ||
641 | +{ | ||
642 | + struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev); | ||
643 | + int ret = 0; | ||
644 | + | ||
645 | + mutex_lock(&mt9p031->power_lock); | ||
646 | + | ||
647 | + /* | ||
648 | + * If the power count is modified from 0 to != 0 or from != 0 to 0, | ||
649 | + * update the power state. | ||
650 | + */ | ||
651 | + if (mt9p031->power_count == !on) { | ||
652 | + if (on) { | ||
653 | + ret = mt9p031_power_on(mt9p031); | ||
654 | + if (ret) { | ||
655 | + dev_err(mt9p031->subdev.v4l2_dev->dev, | ||
656 | + "Failed to power on: %d\n", ret); | ||
657 | + goto out; | ||
658 | + } | ||
659 | + } else { | ||
660 | + mt9p031_power_off(mt9p031); | ||
661 | + } | ||
662 | + } | ||
663 | + | ||
664 | + /* Update the power count. */ | ||
665 | + mt9p031->power_count += on ? 1 : -1; | ||
666 | + WARN_ON(mt9p031->power_count < 0); | ||
667 | + | ||
668 | +out: | ||
669 | + mutex_unlock(&mt9p031->power_lock); | ||
670 | + return ret; | ||
671 | +} | ||
672 | + | ||
673 | +static int mt9p031_registered(struct v4l2_subdev *sd) | ||
674 | +{ | ||
675 | + struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev); | ||
676 | + struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); | ||
677 | + int ret; | ||
678 | + | ||
679 | + ret = mt9p031_set_power(&mt9p031->subdev, 1); | ||
680 | + if (ret) { | ||
681 | + dev_err(&client->dev, | ||
682 | + "Failed to power on device: %d\n", ret); | ||
683 | + return ret; | ||
684 | + } | ||
685 | + | ||
686 | + ret = mt9p031_video_probe(client); | ||
687 | + | ||
688 | + mt9p031_set_power(&mt9p031->subdev, 0); | ||
689 | + | ||
690 | + return ret; | ||
691 | +} | ||
692 | + | ||
693 | +static int mt9p031_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) | ||
694 | +{ | ||
695 | + struct mt9p031 *mt9p031; | ||
696 | + mt9p031 = container_of(sd, struct mt9p031, subdev); | ||
697 | + | ||
698 | + mt9p031->rect.width = MT9P031_WINDOW_WIDTH_DEF; | ||
699 | + mt9p031->rect.height = MT9P031_WINDOW_HEIGHT_DEF; | ||
700 | + mt9p031->rect.left = MT9P031_COLUMN_START_DEF; | ||
701 | + mt9p031->rect.top = MT9P031_ROW_START_DEF; | ||
702 | + | ||
703 | + if (mt9p031->pdata->version == MT9P031_MONOCHROME_VERSION) | ||
704 | + mt9p031->format.code = V4L2_MBUS_FMT_Y12_1X12; | ||
705 | + else | ||
706 | + mt9p031->format.code = V4L2_MBUS_FMT_SGRBG12_1X12; | ||
707 | + | ||
708 | + mt9p031->format.width = MT9P031_WINDOW_WIDTH_DEF; | ||
709 | + mt9p031->format.height = MT9P031_WINDOW_HEIGHT_DEF; | ||
710 | + mt9p031->format.field = V4L2_FIELD_NONE; | ||
711 | + mt9p031->format.colorspace = V4L2_COLORSPACE_SRGB; | ||
712 | + | ||
713 | + mt9p031->xskip = 1; | ||
714 | + mt9p031->yskip = 1; | ||
715 | + return mt9p031_set_power(sd, 1); | ||
716 | +} | ||
717 | + | ||
718 | +static int mt9p031_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) | ||
719 | +{ | ||
720 | + return mt9p031_set_power(sd, 0); | ||
721 | +} | ||
722 | + | ||
723 | +static struct v4l2_subdev_core_ops mt9p031_subdev_core_ops = { | ||
724 | + .s_power = mt9p031_set_power, | ||
725 | +}; | ||
726 | + | ||
727 | +static struct v4l2_subdev_video_ops mt9p031_subdev_video_ops = { | ||
728 | + .s_stream = mt9p031_s_stream, | ||
729 | +}; | ||
730 | + | ||
731 | +static struct v4l2_subdev_pad_ops mt9p031_subdev_pad_ops = { | ||
732 | + .enum_mbus_code = mt9p031_enum_mbus_code, | ||
733 | + .get_fmt = mt9p031_get_format, | ||
734 | + .set_fmt = mt9p031_set_format, | ||
735 | + .get_crop = mt9p031_get_crop, | ||
736 | + .set_crop = mt9p031_set_crop, | ||
737 | +}; | ||
738 | + | ||
739 | +static struct v4l2_subdev_ops mt9p031_subdev_ops = { | ||
740 | + .core = &mt9p031_subdev_core_ops, | ||
741 | + .video = &mt9p031_subdev_video_ops, | ||
742 | + .pad = &mt9p031_subdev_pad_ops, | ||
743 | +}; | ||
744 | + | ||
745 | +static const struct v4l2_subdev_internal_ops mt9p031_subdev_internal_ops = { | ||
746 | + .registered = mt9p031_registered, | ||
747 | + .open = mt9p031_open, | ||
748 | + .close = mt9p031_close, | ||
749 | +}; | ||
750 | + | ||
751 | +static int mt9p031_probe(struct i2c_client *client, | ||
752 | + const struct i2c_device_id *did) | ||
753 | +{ | ||
754 | + int ret; | ||
755 | + struct mt9p031 *mt9p031; | ||
756 | + struct mt9p031_platform_data *pdata = client->dev.platform_data; | ||
757 | + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | ||
758 | + | ||
759 | + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { | ||
760 | + dev_warn(&adapter->dev, | ||
761 | + "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); | ||
762 | + return -EIO; | ||
763 | + } | ||
764 | + | ||
765 | + mt9p031 = kzalloc(sizeof(struct mt9p031), GFP_KERNEL); | ||
766 | + if (!mt9p031) | ||
767 | + return -ENOMEM; | ||
768 | + | ||
769 | + mutex_init(&mt9p031->power_lock); | ||
770 | + v4l2_i2c_subdev_init(&mt9p031->subdev, client, &mt9p031_subdev_ops); | ||
771 | + mt9p031->subdev.internal_ops = &mt9p031_subdev_internal_ops; | ||
772 | + | ||
773 | + mt9p031->pdata = pdata; | ||
774 | + | ||
775 | + mt9p031->pad.flags = MEDIA_PAD_FL_SOURCE; | ||
776 | + ret = media_entity_init(&mt9p031->subdev.entity, 1, &mt9p031->pad, 0); | ||
777 | + if (ret) | ||
778 | + return ret; | ||
779 | + | ||
780 | + mt9p031->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
781 | + | ||
782 | + return 0; | ||
783 | +} | ||
784 | + | ||
785 | +static int mt9p031_remove(struct i2c_client *client) | ||
786 | +{ | ||
787 | + struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
788 | + struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev); | ||
789 | + | ||
790 | + v4l2_device_unregister_subdev(sd); | ||
791 | + media_entity_cleanup(&sd->entity); | ||
792 | + kfree(mt9p031); | ||
793 | + | ||
794 | + return 0; | ||
795 | +} | ||
796 | + | ||
797 | +static const struct i2c_device_id mt9p031_id[] = { | ||
798 | + { "mt9p031", 0 }, | ||
799 | + { } | ||
800 | +}; | ||
801 | +MODULE_DEVICE_TABLE(i2c, mt9p031_id); | ||
802 | + | ||
803 | +static struct i2c_driver mt9p031_i2c_driver = { | ||
804 | + .driver = { | ||
805 | + .name = "mt9p031", | ||
806 | + }, | ||
807 | + .probe = mt9p031_probe, | ||
808 | + .remove = mt9p031_remove, | ||
809 | + .id_table = mt9p031_id, | ||
810 | +}; | ||
811 | + | ||
812 | +static int __init mt9p031_mod_init(void) | ||
813 | +{ | ||
814 | + return i2c_add_driver(&mt9p031_i2c_driver); | ||
815 | +} | ||
816 | + | ||
817 | +static void __exit mt9p031_mod_exit(void) | ||
818 | +{ | ||
819 | + i2c_del_driver(&mt9p031_i2c_driver); | ||
820 | +} | ||
821 | + | ||
822 | +module_init(mt9p031_mod_init); | ||
823 | +module_exit(mt9p031_mod_exit); | ||
824 | + | ||
825 | +MODULE_DESCRIPTION("Aptina MT9P031 Camera driver"); | ||
826 | +MODULE_AUTHOR("Bastian Hecht <hechtb@gmail.com>"); | ||
827 | +MODULE_LICENSE("GPL v2"); | ||
828 | diff --git a/include/media/mt9p031.h b/include/media/mt9p031.h | ||
829 | new file mode 100644 | ||
830 | index 0000000..27b4c75 | ||
831 | --- /dev/null | ||
832 | +++ b/include/media/mt9p031.h | ||
833 | @@ -0,0 +1,23 @@ | ||
834 | +#ifndef MT9P031_H | ||
835 | +#define MT9P031_H | ||
836 | + | ||
837 | +struct v4l2_subdev; | ||
838 | + | ||
839 | +enum { | ||
840 | + MT9P031_COLOR_VERSION = 0, | ||
841 | + MT9P031_MONOCHROME_VERSION = 1, | ||
842 | +}; | ||
843 | + | ||
844 | +enum { | ||
845 | + MT9P031_VDD_IO_1V8 = 0, | ||
846 | + MT9P031_VDD_IO_2V8 = 1, | ||
847 | +}; | ||
848 | + | ||
849 | +struct mt9p031_platform_data { | ||
850 | + int (*set_xclk)(struct v4l2_subdev *subdev, int hz); | ||
851 | + int (*reset)(struct v4l2_subdev *subdev, int active); | ||
852 | + int vdd_io; /* MT9P031_VDD_IO_1V8 or MT9P031_VDD_IO_2V8 */ | ||
853 | + int version; /* MT9P031_COLOR_VERSION or MT9P031_MONOCHROME_VERSION */ | ||
854 | +}; | ||
855 | + | ||
856 | +#endif | ||
857 | -- | ||
858 | 1.6.6.1 | ||
859 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/camera/0002-v4l-Add-mt9v032-sensor-driver.patch b/recipes-kernel/linux/linux-omap-2.6.39/camera/0002-v4l-Add-mt9v032-sensor-driver.patch deleted file mode 100644 index fb7cd205..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/camera/0002-v4l-Add-mt9v032-sensor-driver.patch +++ /dev/null | |||
@@ -1,853 +0,0 @@ | |||
1 | From ba65e798c98e9c4d331deb2b51337964336d3f78 Mon Sep 17 00:00:00 2001 | ||
2 | From: Detlev Casanova <detlev.casanova@gmail.com> | ||
3 | Date: Sun, 28 Nov 2010 19:07:20 +0100 | ||
4 | Subject: [PATCH 2/3] v4l: Add mt9v032 sensor driver | ||
5 | |||
6 | The MT9V032 is a parallel wide VGA sensor from Aptina (formerly Micron) | ||
7 | controlled through I2C. | ||
8 | |||
9 | The driver creates a V4L2 subdevice. It currently supports binning and | ||
10 | cropping, and the gain, auto gain, exposure, auto exposure and test | ||
11 | pattern controls. | ||
12 | |||
13 | Signed-off-by: Detlev Casanova <detlev.casanova@gmail.com> | ||
14 | Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | ||
15 | --- | ||
16 | drivers/media/video/Kconfig | 7 + | ||
17 | drivers/media/video/Makefile | 1 + | ||
18 | drivers/media/video/mt9v032.c | 773 +++++++++++++++++++++++++++++++++++++++++ | ||
19 | include/media/mt9v032.h | 12 + | ||
20 | 4 files changed, 793 insertions(+), 0 deletions(-) | ||
21 | create mode 100644 drivers/media/video/mt9v032.c | ||
22 | create mode 100644 include/media/mt9v032.h | ||
23 | |||
24 | diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig | ||
25 | index cb87e35..3a5bc57 100644 | ||
26 | --- a/drivers/media/video/Kconfig | ||
27 | +++ b/drivers/media/video/Kconfig | ||
28 | @@ -344,6 +344,13 @@ config VIDEO_MT9V011 | ||
29 | mt0v011 1.3 Mpixel camera. It currently only works with the | ||
30 | em28xx driver. | ||
31 | |||
32 | +config VIDEO_MT9V032 | ||
33 | + tristate "Micron MT9V032 sensor support" | ||
34 | + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API | ||
35 | + ---help--- | ||
36 | + This is a Video4Linux2 sensor-level driver for the Micron | ||
37 | + MT9V032 752x480 CMOS sensor. | ||
38 | + | ||
39 | config VIDEO_TCM825X | ||
40 | tristate "TCM825x camera sensor support" | ||
41 | depends on I2C && VIDEO_V4L2 | ||
42 | diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile | ||
43 | index 912b29b..6679c6a 100644 | ||
44 | --- a/drivers/media/video/Makefile | ||
45 | +++ b/drivers/media/video/Makefile | ||
46 | @@ -67,6 +67,7 @@ obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o | ||
47 | obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o | ||
48 | obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o | ||
49 | obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o | ||
50 | +obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o | ||
51 | obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o | ||
52 | obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o | ||
53 | |||
54 | diff --git a/drivers/media/video/mt9v032.c b/drivers/media/video/mt9v032.c | ||
55 | new file mode 100644 | ||
56 | index 0000000..c64e1dc | ||
57 | --- /dev/null | ||
58 | +++ b/drivers/media/video/mt9v032.c | ||
59 | @@ -0,0 +1,773 @@ | ||
60 | +/* | ||
61 | + * Driver for MT9V032 CMOS Image Sensor from Micron | ||
62 | + * | ||
63 | + * Copyright (C) 2010, Laurent Pinchart <laurent.pinchart@ideasonboard.com> | ||
64 | + * | ||
65 | + * Based on the MT9M001 driver, | ||
66 | + * | ||
67 | + * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de> | ||
68 | + * | ||
69 | + * This program is free software; you can redistribute it and/or modify | ||
70 | + * it under the terms of the GNU General Public License version 2 as | ||
71 | + * published by the Free Software Foundation. | ||
72 | + */ | ||
73 | + | ||
74 | +#include <linux/delay.h> | ||
75 | +#include <linux/i2c.h> | ||
76 | +#include <linux/log2.h> | ||
77 | +#include <linux/mutex.h> | ||
78 | +#include <linux/slab.h> | ||
79 | +#include <linux/videodev2.h> | ||
80 | +#include <linux/v4l2-mediabus.h> | ||
81 | + | ||
82 | +#include <media/mt9v032.h> | ||
83 | +#include <media/v4l2-ctrls.h> | ||
84 | +#include <media/v4l2-device.h> | ||
85 | +#include <media/v4l2-subdev.h> | ||
86 | + | ||
87 | +#define MT9V032_PIXEL_ARRAY_HEIGHT 492 | ||
88 | +#define MT9V032_PIXEL_ARRAY_WIDTH 782 | ||
89 | + | ||
90 | +#define MT9V032_CHIP_VERSION 0x00 | ||
91 | +#define MT9V032_CHIP_ID_REV1 0x1311 | ||
92 | +#define MT9V032_CHIP_ID_REV3 0x1313 | ||
93 | +#define MT9V032_COLUMN_START 0x01 | ||
94 | +#define MT9V032_COLUMN_START_MIN 1 | ||
95 | +#define MT9V032_COLUMN_START_DEF 1 | ||
96 | +#define MT9V032_COLUMN_START_MAX 752 | ||
97 | +#define MT9V032_ROW_START 0x02 | ||
98 | +#define MT9V032_ROW_START_MIN 4 | ||
99 | +#define MT9V032_ROW_START_DEF 5 | ||
100 | +#define MT9V032_ROW_START_MAX 482 | ||
101 | +#define MT9V032_WINDOW_HEIGHT 0x03 | ||
102 | +#define MT9V032_WINDOW_HEIGHT_MIN 1 | ||
103 | +#define MT9V032_WINDOW_HEIGHT_DEF 480 | ||
104 | +#define MT9V032_WINDOW_HEIGHT_MAX 480 | ||
105 | +#define MT9V032_WINDOW_WIDTH 0x04 | ||
106 | +#define MT9V032_WINDOW_WIDTH_MIN 1 | ||
107 | +#define MT9V032_WINDOW_WIDTH_DEF 752 | ||
108 | +#define MT9V032_WINDOW_WIDTH_MAX 752 | ||
109 | +#define MT9V032_HORIZONTAL_BLANKING 0x05 | ||
110 | +#define MT9V032_HORIZONTAL_BLANKING_MIN 43 | ||
111 | +#define MT9V032_HORIZONTAL_BLANKING_MAX 1023 | ||
112 | +#define MT9V032_VERTICAL_BLANKING 0x06 | ||
113 | +#define MT9V032_VERTICAL_BLANKING_MIN 4 | ||
114 | +#define MT9V032_VERTICAL_BLANKING_MAX 3000 | ||
115 | +#define MT9V032_CHIP_CONTROL 0x07 | ||
116 | +#define MT9V032_CHIP_CONTROL_MASTER_MODE (1 << 3) | ||
117 | +#define MT9V032_CHIP_CONTROL_DOUT_ENABLE (1 << 7) | ||
118 | +#define MT9V032_CHIP_CONTROL_SEQUENTIAL (1 << 8) | ||
119 | +#define MT9V032_SHUTTER_WIDTH1 0x08 | ||
120 | +#define MT9V032_SHUTTER_WIDTH2 0x09 | ||
121 | +#define MT9V032_SHUTTER_WIDTH_CONTROL 0x0a | ||
122 | +#define MT9V032_TOTAL_SHUTTER_WIDTH 0x0b | ||
123 | +#define MT9V032_TOTAL_SHUTTER_WIDTH_MIN 1 | ||
124 | +#define MT9V032_TOTAL_SHUTTER_WIDTH_DEF 480 | ||
125 | +#define MT9V032_TOTAL_SHUTTER_WIDTH_MAX 32767 | ||
126 | +#define MT9V032_RESET 0x0c | ||
127 | +#define MT9V032_READ_MODE 0x0d | ||
128 | +#define MT9V032_READ_MODE_ROW_BIN_MASK (3 << 0) | ||
129 | +#define MT9V032_READ_MODE_ROW_BIN_SHIFT 0 | ||
130 | +#define MT9V032_READ_MODE_COLUMN_BIN_MASK (3 << 2) | ||
131 | +#define MT9V032_READ_MODE_COLUMN_BIN_SHIFT 2 | ||
132 | +#define MT9V032_READ_MODE_ROW_FLIP (1 << 4) | ||
133 | +#define MT9V032_READ_MODE_COLUMN_FLIP (1 << 5) | ||
134 | +#define MT9V032_READ_MODE_DARK_COLUMNS (1 << 6) | ||
135 | +#define MT9V032_READ_MODE_DARK_ROWS (1 << 7) | ||
136 | +#define MT9V032_PIXEL_OPERATION_MODE 0x0f | ||
137 | +#define MT9V032_PIXEL_OPERATION_MODE_COLOR (1 << 2) | ||
138 | +#define MT9V032_PIXEL_OPERATION_MODE_HDR (1 << 6) | ||
139 | +#define MT9V032_ANALOG_GAIN 0x35 | ||
140 | +#define MT9V032_ANALOG_GAIN_MIN 16 | ||
141 | +#define MT9V032_ANALOG_GAIN_DEF 16 | ||
142 | +#define MT9V032_ANALOG_GAIN_MAX 64 | ||
143 | +#define MT9V032_MAX_ANALOG_GAIN 0x36 | ||
144 | +#define MT9V032_MAX_ANALOG_GAIN_MAX 127 | ||
145 | +#define MT9V032_FRAME_DARK_AVERAGE 0x42 | ||
146 | +#define MT9V032_DARK_AVG_THRESH 0x46 | ||
147 | +#define MT9V032_DARK_AVG_LOW_THRESH_MASK (255 << 0) | ||
148 | +#define MT9V032_DARK_AVG_LOW_THRESH_SHIFT 0 | ||
149 | +#define MT9V032_DARK_AVG_HIGH_THRESH_MASK (255 << 8) | ||
150 | +#define MT9V032_DARK_AVG_HIGH_THRESH_SHIFT 8 | ||
151 | +#define MT9V032_ROW_NOISE_CORR_CONTROL 0x70 | ||
152 | +#define MT9V032_ROW_NOISE_CORR_ENABLE (1 << 5) | ||
153 | +#define MT9V032_ROW_NOISE_CORR_USE_BLK_AVG (1 << 7) | ||
154 | +#define MT9V032_PIXEL_CLOCK 0x74 | ||
155 | +#define MT9V032_PIXEL_CLOCK_INV_LINE (1 << 0) | ||
156 | +#define MT9V032_PIXEL_CLOCK_INV_FRAME (1 << 1) | ||
157 | +#define MT9V032_PIXEL_CLOCK_XOR_LINE (1 << 2) | ||
158 | +#define MT9V032_PIXEL_CLOCK_CONT_LINE (1 << 3) | ||
159 | +#define MT9V032_PIXEL_CLOCK_INV_PXL_CLK (1 << 4) | ||
160 | +#define MT9V032_TEST_PATTERN 0x7f | ||
161 | +#define MT9V032_TEST_PATTERN_DATA_MASK (1023 << 0) | ||
162 | +#define MT9V032_TEST_PATTERN_DATA_SHIFT 0 | ||
163 | +#define MT9V032_TEST_PATTERN_USE_DATA (1 << 10) | ||
164 | +#define MT9V032_TEST_PATTERN_GRAY_MASK (3 << 11) | ||
165 | +#define MT9V032_TEST_PATTERN_GRAY_NONE (0 << 11) | ||
166 | +#define MT9V032_TEST_PATTERN_GRAY_VERTICAL (1 << 11) | ||
167 | +#define MT9V032_TEST_PATTERN_GRAY_HORIZONTAL (2 << 11) | ||
168 | +#define MT9V032_TEST_PATTERN_GRAY_DIAGONAL (3 << 11) | ||
169 | +#define MT9V032_TEST_PATTERN_ENABLE (1 << 13) | ||
170 | +#define MT9V032_TEST_PATTERN_FLIP (1 << 14) | ||
171 | +#define MT9V032_AEC_AGC_ENABLE 0xaf | ||
172 | +#define MT9V032_AEC_ENABLE (1 << 0) | ||
173 | +#define MT9V032_AGC_ENABLE (1 << 1) | ||
174 | +#define MT9V032_THERMAL_INFO 0xc1 | ||
175 | + | ||
176 | +struct mt9v032 { | ||
177 | + struct v4l2_subdev subdev; | ||
178 | + struct media_pad pad; | ||
179 | + | ||
180 | + struct v4l2_mbus_framefmt format; | ||
181 | + struct v4l2_rect crop; | ||
182 | + | ||
183 | + struct v4l2_ctrl_handler ctrls; | ||
184 | + | ||
185 | + struct mutex power_lock; | ||
186 | + int power_count; | ||
187 | + | ||
188 | + struct mt9v032_platform_data *pdata; | ||
189 | + u16 chip_control; | ||
190 | + u16 aec_agc; | ||
191 | +}; | ||
192 | + | ||
193 | +static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd) | ||
194 | +{ | ||
195 | + return container_of(sd, struct mt9v032, subdev); | ||
196 | +} | ||
197 | + | ||
198 | +static int mt9v032_read(struct i2c_client *client, const u8 reg) | ||
199 | +{ | ||
200 | + s32 data = i2c_smbus_read_word_data(client, reg); | ||
201 | + dev_dbg(&client->dev, "%s: read 0x%04x from 0x%02x\n", __func__, | ||
202 | + swab16(data), reg); | ||
203 | + return data < 0 ? data : swab16(data); | ||
204 | +} | ||
205 | + | ||
206 | +static int mt9v032_write(struct i2c_client *client, const u8 reg, | ||
207 | + const u16 data) | ||
208 | +{ | ||
209 | + dev_dbg(&client->dev, "%s: writing 0x%04x to 0x%02x\n", __func__, | ||
210 | + data, reg); | ||
211 | + return i2c_smbus_write_word_data(client, reg, swab16(data)); | ||
212 | +} | ||
213 | + | ||
214 | +static int mt9v032_set_chip_control(struct mt9v032 *mt9v032, u16 clear, u16 set) | ||
215 | +{ | ||
216 | + struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); | ||
217 | + u16 value = (mt9v032->chip_control & ~clear) | set; | ||
218 | + int ret; | ||
219 | + | ||
220 | + ret = mt9v032_write(client, MT9V032_CHIP_CONTROL, value); | ||
221 | + if (ret < 0) | ||
222 | + return ret; | ||
223 | + | ||
224 | + mt9v032->chip_control = value; | ||
225 | + return 0; | ||
226 | +} | ||
227 | + | ||
228 | +static int | ||
229 | +mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable) | ||
230 | +{ | ||
231 | + struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); | ||
232 | + u16 value = mt9v032->aec_agc; | ||
233 | + int ret; | ||
234 | + | ||
235 | + if (enable) | ||
236 | + value |= which; | ||
237 | + else | ||
238 | + value &= ~which; | ||
239 | + | ||
240 | + ret = mt9v032_write(client, MT9V032_AEC_AGC_ENABLE, value); | ||
241 | + if (ret < 0) | ||
242 | + return ret; | ||
243 | + | ||
244 | + mt9v032->aec_agc = value; | ||
245 | + return 0; | ||
246 | +} | ||
247 | + | ||
248 | +static int mt9v032_power_on(struct mt9v032 *mt9v032) | ||
249 | +{ | ||
250 | + struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); | ||
251 | + int ret; | ||
252 | + | ||
253 | + if (mt9v032->pdata->set_clock) { | ||
254 | + mt9v032->pdata->set_clock(&mt9v032->subdev, 25000000); | ||
255 | + udelay(1); | ||
256 | + } | ||
257 | + | ||
258 | + /* Reset the chip and stop data read out */ | ||
259 | + ret = mt9v032_write(client, MT9V032_RESET, 1); | ||
260 | + if (ret < 0) | ||
261 | + return ret; | ||
262 | + | ||
263 | + ret = mt9v032_write(client, MT9V032_RESET, 0); | ||
264 | + if (ret < 0) | ||
265 | + return ret; | ||
266 | + | ||
267 | + return mt9v032_write(client, MT9V032_CHIP_CONTROL, 0); | ||
268 | +} | ||
269 | + | ||
270 | +static void mt9v032_power_off(struct mt9v032 *mt9v032) | ||
271 | +{ | ||
272 | + if (mt9v032->pdata->set_clock) | ||
273 | + mt9v032->pdata->set_clock(&mt9v032->subdev, 0); | ||
274 | +} | ||
275 | + | ||
276 | +static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on) | ||
277 | +{ | ||
278 | + struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); | ||
279 | + int ret; | ||
280 | + | ||
281 | + if (!on) { | ||
282 | + mt9v032_power_off(mt9v032); | ||
283 | + return 0; | ||
284 | + } | ||
285 | + | ||
286 | + ret = mt9v032_power_on(mt9v032); | ||
287 | + if (ret < 0) | ||
288 | + return ret; | ||
289 | + | ||
290 | + /* Configure the pixel clock polarity */ | ||
291 | + if (mt9v032->pdata && mt9v032->pdata->clk_pol) { | ||
292 | + ret = mt9v032_write(client, MT9V032_PIXEL_CLOCK, | ||
293 | + MT9V032_PIXEL_CLOCK_INV_PXL_CLK); | ||
294 | + if (ret < 0) | ||
295 | + return ret; | ||
296 | + } | ||
297 | + | ||
298 | + /* Disable the noise correction algorithm and restore the controls. */ | ||
299 | + ret = mt9v032_write(client, MT9V032_ROW_NOISE_CORR_CONTROL, 0); | ||
300 | + if (ret < 0) | ||
301 | + return ret; | ||
302 | + | ||
303 | + return v4l2_ctrl_handler_setup(&mt9v032->ctrls); | ||
304 | +} | ||
305 | + | ||
306 | +/* ----------------------------------------------------------------------------- | ||
307 | + * V4L2 subdev video operations | ||
308 | + */ | ||
309 | + | ||
310 | +static struct v4l2_mbus_framefmt * | ||
311 | +__mt9v032_get_pad_format(struct mt9v032 *mt9v032, struct v4l2_subdev_fh *fh, | ||
312 | + unsigned int pad, enum v4l2_subdev_format_whence which) | ||
313 | +{ | ||
314 | + switch (which) { | ||
315 | + case V4L2_SUBDEV_FORMAT_TRY: | ||
316 | + return v4l2_subdev_get_try_format(fh, pad); | ||
317 | + case V4L2_SUBDEV_FORMAT_ACTIVE: | ||
318 | + return &mt9v032->format; | ||
319 | + default: | ||
320 | + return NULL; | ||
321 | + } | ||
322 | +} | ||
323 | + | ||
324 | +static struct v4l2_rect * | ||
325 | +__mt9v032_get_pad_crop(struct mt9v032 *mt9v032, struct v4l2_subdev_fh *fh, | ||
326 | + unsigned int pad, enum v4l2_subdev_format_whence which) | ||
327 | +{ | ||
328 | + switch (which) { | ||
329 | + case V4L2_SUBDEV_FORMAT_TRY: | ||
330 | + return v4l2_subdev_get_try_crop(fh, pad); | ||
331 | + case V4L2_SUBDEV_FORMAT_ACTIVE: | ||
332 | + return &mt9v032->crop; | ||
333 | + default: | ||
334 | + return NULL; | ||
335 | + } | ||
336 | +} | ||
337 | + | ||
338 | +static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable) | ||
339 | +{ | ||
340 | + const u16 mode = MT9V032_CHIP_CONTROL_MASTER_MODE | ||
341 | + | MT9V032_CHIP_CONTROL_DOUT_ENABLE | ||
342 | + | MT9V032_CHIP_CONTROL_SEQUENTIAL; | ||
343 | + struct i2c_client *client = v4l2_get_subdevdata(subdev); | ||
344 | + struct mt9v032 *mt9v032 = to_mt9v032(subdev); | ||
345 | + struct v4l2_mbus_framefmt *format = &mt9v032->format; | ||
346 | + struct v4l2_rect *crop = &mt9v032->crop; | ||
347 | + unsigned int hratio; | ||
348 | + unsigned int vratio; | ||
349 | + int ret; | ||
350 | + | ||
351 | + if (!enable) | ||
352 | + return mt9v032_set_chip_control(mt9v032, mode, 0); | ||
353 | + | ||
354 | + /* Configure the window size and row/column bin */ | ||
355 | + hratio = DIV_ROUND_CLOSEST(crop->width, format->width); | ||
356 | + vratio = DIV_ROUND_CLOSEST(crop->height, format->height); | ||
357 | + | ||
358 | + ret = mt9v032_write(client, MT9V032_READ_MODE, | ||
359 | + (hratio - 1) << MT9V032_READ_MODE_ROW_BIN_SHIFT | | ||
360 | + (vratio - 1) << MT9V032_READ_MODE_COLUMN_BIN_SHIFT); | ||
361 | + if (ret < 0) | ||
362 | + return ret; | ||
363 | + | ||
364 | + ret = mt9v032_write(client, MT9V032_COLUMN_START, crop->left); | ||
365 | + if (ret < 0) | ||
366 | + return ret; | ||
367 | + | ||
368 | + ret = mt9v032_write(client, MT9V032_ROW_START, crop->top); | ||
369 | + if (ret < 0) | ||
370 | + return ret; | ||
371 | + | ||
372 | + ret = mt9v032_write(client, MT9V032_WINDOW_WIDTH, crop->width); | ||
373 | + if (ret < 0) | ||
374 | + return ret; | ||
375 | + | ||
376 | + ret = mt9v032_write(client, MT9V032_WINDOW_HEIGHT, crop->height); | ||
377 | + if (ret < 0) | ||
378 | + return ret; | ||
379 | + | ||
380 | + ret = mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING, | ||
381 | + max(43, 660 - crop->width)); | ||
382 | + if (ret < 0) | ||
383 | + return ret; | ||
384 | + | ||
385 | + /* Switch to master "normal" mode */ | ||
386 | + return mt9v032_set_chip_control(mt9v032, 0, mode); | ||
387 | +} | ||
388 | + | ||
389 | +static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev, | ||
390 | + struct v4l2_subdev_fh *fh, | ||
391 | + struct v4l2_subdev_mbus_code_enum *code) | ||
392 | +{ | ||
393 | + if (code->index > 0) | ||
394 | + return -EINVAL; | ||
395 | + | ||
396 | + code->code = V4L2_MBUS_FMT_SGRBG10_1X10; | ||
397 | + return 0; | ||
398 | +} | ||
399 | + | ||
400 | +static int mt9v032_enum_frame_size(struct v4l2_subdev *subdev, | ||
401 | + struct v4l2_subdev_fh *fh, | ||
402 | + struct v4l2_subdev_frame_size_enum *fse) | ||
403 | +{ | ||
404 | + if (fse->index >= 8 || fse->code != V4L2_MBUS_FMT_SGRBG10_1X10) | ||
405 | + return -EINVAL; | ||
406 | + | ||
407 | + fse->min_width = MT9V032_WINDOW_WIDTH_DEF / fse->index; | ||
408 | + fse->max_width = fse->min_width; | ||
409 | + fse->min_height = MT9V032_WINDOW_HEIGHT_DEF / fse->index; | ||
410 | + fse->max_height = fse->min_height; | ||
411 | + | ||
412 | + return 0; | ||
413 | +} | ||
414 | + | ||
415 | +static int mt9v032_get_format(struct v4l2_subdev *subdev, | ||
416 | + struct v4l2_subdev_fh *fh, | ||
417 | + struct v4l2_subdev_format *format) | ||
418 | +{ | ||
419 | + struct mt9v032 *mt9v032 = to_mt9v032(subdev); | ||
420 | + | ||
421 | + format->format = *__mt9v032_get_pad_format(mt9v032, fh, format->pad, | ||
422 | + format->which); | ||
423 | + return 0; | ||
424 | +} | ||
425 | + | ||
426 | +static int mt9v032_set_format(struct v4l2_subdev *subdev, | ||
427 | + struct v4l2_subdev_fh *fh, | ||
428 | + struct v4l2_subdev_format *format) | ||
429 | +{ | ||
430 | + struct mt9v032 *mt9v032 = to_mt9v032(subdev); | ||
431 | + struct v4l2_mbus_framefmt *__format; | ||
432 | + struct v4l2_rect *__crop; | ||
433 | + unsigned int width; | ||
434 | + unsigned int height; | ||
435 | + unsigned int hratio; | ||
436 | + unsigned int vratio; | ||
437 | + | ||
438 | + __crop = __mt9v032_get_pad_crop(mt9v032, fh, format->pad, | ||
439 | + format->which); | ||
440 | + | ||
441 | + /* Clamp the width and height to avoid dividing by zero. */ | ||
442 | + width = clamp_t(unsigned int, ALIGN(format->format.width, 2), | ||
443 | + max(__crop->width / 8, MT9V032_WINDOW_WIDTH_MIN), | ||
444 | + __crop->width); | ||
445 | + height = clamp_t(unsigned int, ALIGN(format->format.height, 2), | ||
446 | + max(__crop->height / 8, MT9V032_WINDOW_HEIGHT_MIN), | ||
447 | + __crop->height); | ||
448 | + | ||
449 | + hratio = DIV_ROUND_CLOSEST(__crop->width, width); | ||
450 | + vratio = DIV_ROUND_CLOSEST(__crop->height, height); | ||
451 | + | ||
452 | + __format = __mt9v032_get_pad_format(mt9v032, fh, format->pad, | ||
453 | + format->which); | ||
454 | + __format->width = __crop->width / hratio; | ||
455 | + __format->height = __crop->height / vratio; | ||
456 | + | ||
457 | + format->format = *__format; | ||
458 | + | ||
459 | + return 0; | ||
460 | +} | ||
461 | + | ||
462 | +static int mt9v032_get_crop(struct v4l2_subdev *subdev, | ||
463 | + struct v4l2_subdev_fh *fh, | ||
464 | + struct v4l2_subdev_crop *crop) | ||
465 | +{ | ||
466 | + struct mt9v032 *mt9v032 = to_mt9v032(subdev); | ||
467 | + | ||
468 | + crop->rect = *__mt9v032_get_pad_crop(mt9v032, fh, crop->pad, | ||
469 | + crop->which); | ||
470 | + return 0; | ||
471 | +} | ||
472 | + | ||
473 | +static int mt9v032_set_crop(struct v4l2_subdev *subdev, | ||
474 | + struct v4l2_subdev_fh *fh, | ||
475 | + struct v4l2_subdev_crop *crop) | ||
476 | +{ | ||
477 | + struct mt9v032 *mt9v032 = to_mt9v032(subdev); | ||
478 | + struct v4l2_mbus_framefmt *__format; | ||
479 | + struct v4l2_rect *__crop; | ||
480 | + struct v4l2_rect rect; | ||
481 | + | ||
482 | + /* Clamp the crop rectangle boundaries and align them to a non multiple | ||
483 | + * of 2 pixels to ensure a GRBG Bayer pattern. | ||
484 | + */ | ||
485 | + rect.left = clamp(ALIGN(crop->rect.left + 1, 2) - 1, | ||
486 | + MT9V032_COLUMN_START_MIN, | ||
487 | + MT9V032_COLUMN_START_MAX); | ||
488 | + rect.top = clamp(ALIGN(crop->rect.top + 1, 2) - 1, | ||
489 | + MT9V032_ROW_START_MIN, | ||
490 | + MT9V032_ROW_START_MAX); | ||
491 | + rect.width = clamp(ALIGN(crop->rect.width, 2), | ||
492 | + MT9V032_WINDOW_WIDTH_MIN, | ||
493 | + MT9V032_WINDOW_WIDTH_MAX); | ||
494 | + rect.height = clamp(ALIGN(crop->rect.height, 2), | ||
495 | + MT9V032_WINDOW_HEIGHT_MIN, | ||
496 | + MT9V032_WINDOW_HEIGHT_MAX); | ||
497 | + | ||
498 | + rect.width = min(rect.width, MT9V032_PIXEL_ARRAY_WIDTH - rect.left); | ||
499 | + rect.height = min(rect.height, MT9V032_PIXEL_ARRAY_HEIGHT - rect.top); | ||
500 | + | ||
501 | + __crop = __mt9v032_get_pad_crop(mt9v032, fh, crop->pad, crop->which); | ||
502 | + | ||
503 | + if (rect.width != __crop->width || rect.height != __crop->height) { | ||
504 | + /* Reset the output image size if the crop rectangle size has | ||
505 | + * been modified. | ||
506 | + */ | ||
507 | + __format = __mt9v032_get_pad_format(mt9v032, fh, crop->pad, | ||
508 | + crop->which); | ||
509 | + __format->width = rect.width; | ||
510 | + __format->height = rect.height; | ||
511 | + } | ||
512 | + | ||
513 | + *__crop = rect; | ||
514 | + crop->rect = rect; | ||
515 | + | ||
516 | + return 0; | ||
517 | +} | ||
518 | + | ||
519 | +/* ----------------------------------------------------------------------------- | ||
520 | + * V4L2 subdev control operations | ||
521 | + */ | ||
522 | + | ||
523 | +#define V4L2_CID_TEST_PATTERN (V4L2_CID_USER_BASE | 0x1001) | ||
524 | + | ||
525 | +static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl) | ||
526 | +{ | ||
527 | + struct mt9v032 *mt9v032 = | ||
528 | + container_of(ctrl->handler, struct mt9v032, ctrls); | ||
529 | + struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); | ||
530 | + u16 data; | ||
531 | + | ||
532 | + switch (ctrl->id) { | ||
533 | + case V4L2_CID_AUTOGAIN: | ||
534 | + return mt9v032_update_aec_agc(mt9v032, MT9V032_AGC_ENABLE, | ||
535 | + ctrl->val); | ||
536 | + | ||
537 | + case V4L2_CID_GAIN: | ||
538 | + return mt9v032_write(client, MT9V032_ANALOG_GAIN, ctrl->val); | ||
539 | + | ||
540 | + case V4L2_CID_EXPOSURE_AUTO: | ||
541 | + return mt9v032_update_aec_agc(mt9v032, MT9V032_AEC_ENABLE, | ||
542 | + ctrl->val); | ||
543 | + | ||
544 | + case V4L2_CID_EXPOSURE: | ||
545 | + return mt9v032_write(client, MT9V032_TOTAL_SHUTTER_WIDTH, | ||
546 | + ctrl->val); | ||
547 | + | ||
548 | + case V4L2_CID_TEST_PATTERN: | ||
549 | + switch (ctrl->val) { | ||
550 | + case 0: | ||
551 | + data = 0; | ||
552 | + break; | ||
553 | + case 1: | ||
554 | + data = MT9V032_TEST_PATTERN_GRAY_VERTICAL | ||
555 | + | MT9V032_TEST_PATTERN_ENABLE; | ||
556 | + break; | ||
557 | + case 2: | ||
558 | + data = MT9V032_TEST_PATTERN_GRAY_HORIZONTAL | ||
559 | + | MT9V032_TEST_PATTERN_ENABLE; | ||
560 | + break; | ||
561 | + case 3: | ||
562 | + data = MT9V032_TEST_PATTERN_GRAY_DIAGONAL | ||
563 | + | MT9V032_TEST_PATTERN_ENABLE; | ||
564 | + break; | ||
565 | + default: | ||
566 | + data = (ctrl->val << MT9V032_TEST_PATTERN_DATA_SHIFT) | ||
567 | + | MT9V032_TEST_PATTERN_USE_DATA | ||
568 | + | MT9V032_TEST_PATTERN_ENABLE | ||
569 | + | MT9V032_TEST_PATTERN_FLIP; | ||
570 | + break; | ||
571 | + } | ||
572 | + | ||
573 | + return mt9v032_write(client, MT9V032_TEST_PATTERN, data); | ||
574 | + } | ||
575 | + | ||
576 | + return 0; | ||
577 | +} | ||
578 | + | ||
579 | +static struct v4l2_ctrl_ops mt9v032_ctrl_ops = { | ||
580 | + .s_ctrl = mt9v032_s_ctrl, | ||
581 | +}; | ||
582 | + | ||
583 | +static const struct v4l2_ctrl_config mt9v032_ctrls[] = { | ||
584 | + { | ||
585 | + .ops = &mt9v032_ctrl_ops, | ||
586 | + .id = V4L2_CID_TEST_PATTERN, | ||
587 | + .type = V4L2_CTRL_TYPE_INTEGER, | ||
588 | + .name = "Test pattern", | ||
589 | + .min = 0, | ||
590 | + .max = 1023, | ||
591 | + .step = 1, | ||
592 | + .def = 0, | ||
593 | + .flags = 0, | ||
594 | + } | ||
595 | +}; | ||
596 | + | ||
597 | +/* ----------------------------------------------------------------------------- | ||
598 | + * V4L2 subdev core operations | ||
599 | + */ | ||
600 | + | ||
601 | +static int mt9v032_set_power(struct v4l2_subdev *subdev, int on) | ||
602 | +{ | ||
603 | + struct mt9v032 *mt9v032 = to_mt9v032(subdev); | ||
604 | + int ret = 0; | ||
605 | + | ||
606 | + mutex_lock(&mt9v032->power_lock); | ||
607 | + | ||
608 | + /* If the power count is modified from 0 to != 0 or from != 0 to 0, | ||
609 | + * update the power state. | ||
610 | + */ | ||
611 | + if (mt9v032->power_count == !on) { | ||
612 | + ret = __mt9v032_set_power(mt9v032, !!on); | ||
613 | + if (ret < 0) | ||
614 | + goto done; | ||
615 | + } | ||
616 | + | ||
617 | + /* Update the power count. */ | ||
618 | + mt9v032->power_count += on ? 1 : -1; | ||
619 | + WARN_ON(mt9v032->power_count < 0); | ||
620 | + | ||
621 | +done: | ||
622 | + mutex_unlock(&mt9v032->power_lock); | ||
623 | + return ret; | ||
624 | +} | ||
625 | + | ||
626 | +/* ----------------------------------------------------------------------------- | ||
627 | + * V4L2 subdev internal operations | ||
628 | + */ | ||
629 | + | ||
630 | +static int mt9v032_registered(struct v4l2_subdev *subdev) | ||
631 | +{ | ||
632 | + struct i2c_client *client = v4l2_get_subdevdata(subdev); | ||
633 | + struct mt9v032 *mt9v032 = to_mt9v032(subdev); | ||
634 | + s32 data; | ||
635 | + int ret; | ||
636 | + | ||
637 | + dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n", | ||
638 | + client->addr); | ||
639 | + | ||
640 | + ret = mt9v032_power_on(mt9v032); | ||
641 | + if (ret < 0) { | ||
642 | + dev_err(&client->dev, "MT9V032 power up failed\n"); | ||
643 | + return ret; | ||
644 | + } | ||
645 | + | ||
646 | + /* Read and check the sensor version */ | ||
647 | + data = mt9v032_read(client, MT9V032_CHIP_VERSION); | ||
648 | + if (data != MT9V032_CHIP_ID_REV1 && data != MT9V032_CHIP_ID_REV3) { | ||
649 | + dev_err(&client->dev, "MT9V032 not detected, wrong version " | ||
650 | + "0x%04x\n", data); | ||
651 | + return -ENODEV; | ||
652 | + } | ||
653 | + | ||
654 | + mt9v032_power_off(mt9v032); | ||
655 | + | ||
656 | + dev_info(&client->dev, "MT9V032 detected at address 0x%02x\n", | ||
657 | + client->addr); | ||
658 | + | ||
659 | + return ret; | ||
660 | +} | ||
661 | + | ||
662 | +static int mt9v032_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) | ||
663 | +{ | ||
664 | + struct v4l2_mbus_framefmt *format; | ||
665 | + struct v4l2_rect *crop; | ||
666 | + | ||
667 | + crop = v4l2_subdev_get_try_crop(fh, 0); | ||
668 | + crop->left = MT9V032_COLUMN_START_DEF; | ||
669 | + crop->top = MT9V032_ROW_START_DEF; | ||
670 | + crop->width = MT9V032_WINDOW_WIDTH_DEF; | ||
671 | + crop->height = MT9V032_WINDOW_HEIGHT_DEF; | ||
672 | + | ||
673 | + format = v4l2_subdev_get_try_format(fh, 0); | ||
674 | + format->code = V4L2_MBUS_FMT_SGRBG10_1X10; | ||
675 | + format->width = MT9V032_WINDOW_WIDTH_DEF; | ||
676 | + format->height = MT9V032_WINDOW_HEIGHT_DEF; | ||
677 | + format->field = V4L2_FIELD_NONE; | ||
678 | + format->colorspace = V4L2_COLORSPACE_SRGB; | ||
679 | + | ||
680 | + return mt9v032_set_power(subdev, 1); | ||
681 | +} | ||
682 | + | ||
683 | +static int mt9v032_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) | ||
684 | +{ | ||
685 | + return mt9v032_set_power(subdev, 0); | ||
686 | +} | ||
687 | + | ||
688 | +static struct v4l2_subdev_core_ops mt9v032_subdev_core_ops = { | ||
689 | + .s_power = mt9v032_set_power, | ||
690 | +}; | ||
691 | + | ||
692 | +static struct v4l2_subdev_video_ops mt9v032_subdev_video_ops = { | ||
693 | + .s_stream = mt9v032_s_stream, | ||
694 | +}; | ||
695 | + | ||
696 | +static struct v4l2_subdev_pad_ops mt9v032_subdev_pad_ops = { | ||
697 | + .enum_mbus_code = mt9v032_enum_mbus_code, | ||
698 | + .enum_frame_size = mt9v032_enum_frame_size, | ||
699 | + .get_fmt = mt9v032_get_format, | ||
700 | + .set_fmt = mt9v032_set_format, | ||
701 | + .get_crop = mt9v032_get_crop, | ||
702 | + .set_crop = mt9v032_set_crop, | ||
703 | +}; | ||
704 | + | ||
705 | +static struct v4l2_subdev_ops mt9v032_subdev_ops = { | ||
706 | + .core = &mt9v032_subdev_core_ops, | ||
707 | + .video = &mt9v032_subdev_video_ops, | ||
708 | + .pad = &mt9v032_subdev_pad_ops, | ||
709 | +}; | ||
710 | + | ||
711 | +static const struct v4l2_subdev_internal_ops mt9v032_subdev_internal_ops = { | ||
712 | + .registered = mt9v032_registered, | ||
713 | + .open = mt9v032_open, | ||
714 | + .close = mt9v032_close, | ||
715 | +}; | ||
716 | + | ||
717 | +/* ----------------------------------------------------------------------------- | ||
718 | + * Driver initialization and probing | ||
719 | + */ | ||
720 | + | ||
721 | +static int mt9v032_probe(struct i2c_client *client, | ||
722 | + const struct i2c_device_id *did) | ||
723 | +{ | ||
724 | + struct mt9v032 *mt9v032; | ||
725 | + unsigned int i; | ||
726 | + int ret; | ||
727 | + | ||
728 | + if (!i2c_check_functionality(client->adapter, | ||
729 | + I2C_FUNC_SMBUS_WORD_DATA)) { | ||
730 | + dev_warn(&client->adapter->dev, | ||
731 | + "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); | ||
732 | + return -EIO; | ||
733 | + } | ||
734 | + | ||
735 | + mt9v032 = kzalloc(sizeof(*mt9v032), GFP_KERNEL); | ||
736 | + if (!mt9v032) | ||
737 | + return -ENOMEM; | ||
738 | + | ||
739 | + mutex_init(&mt9v032->power_lock); | ||
740 | + mt9v032->pdata = client->dev.platform_data; | ||
741 | + | ||
742 | + v4l2_ctrl_handler_init(&mt9v032->ctrls, ARRAY_SIZE(mt9v032_ctrls) + 4); | ||
743 | + | ||
744 | + v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, | ||
745 | + V4L2_CID_AUTOGAIN, 0, 1, 1, 1); | ||
746 | + v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, | ||
747 | + V4L2_CID_GAIN, MT9V032_ANALOG_GAIN_MIN, | ||
748 | + MT9V032_ANALOG_GAIN_MAX, 1, MT9V032_ANALOG_GAIN_DEF); | ||
749 | + v4l2_ctrl_new_std_menu(&mt9v032->ctrls, &mt9v032_ctrl_ops, | ||
750 | + V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL, 0, | ||
751 | + V4L2_EXPOSURE_AUTO); | ||
752 | + v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, | ||
753 | + V4L2_CID_EXPOSURE, MT9V032_TOTAL_SHUTTER_WIDTH_MIN, | ||
754 | + MT9V032_TOTAL_SHUTTER_WIDTH_MAX, 1, | ||
755 | + MT9V032_TOTAL_SHUTTER_WIDTH_DEF); | ||
756 | + | ||
757 | + for (i = 0; i < ARRAY_SIZE(mt9v032_ctrls); ++i) | ||
758 | + v4l2_ctrl_new_custom(&mt9v032->ctrls, &mt9v032_ctrls[i], NULL); | ||
759 | + | ||
760 | + mt9v032->subdev.ctrl_handler = &mt9v032->ctrls; | ||
761 | + | ||
762 | + if (mt9v032->ctrls.error) | ||
763 | + printk(KERN_INFO "%s: control initialization error %d\n", | ||
764 | + __func__, mt9v032->ctrls.error); | ||
765 | + | ||
766 | + mt9v032->crop.left = MT9V032_COLUMN_START_DEF; | ||
767 | + mt9v032->crop.top = MT9V032_ROW_START_DEF; | ||
768 | + mt9v032->crop.width = MT9V032_WINDOW_WIDTH_DEF; | ||
769 | + mt9v032->crop.height = MT9V032_WINDOW_HEIGHT_DEF; | ||
770 | + | ||
771 | + mt9v032->format.code = V4L2_MBUS_FMT_SGRBG10_1X10; | ||
772 | + mt9v032->format.width = MT9V032_WINDOW_WIDTH_DEF; | ||
773 | + mt9v032->format.height = MT9V032_WINDOW_HEIGHT_DEF; | ||
774 | + mt9v032->format.field = V4L2_FIELD_NONE; | ||
775 | + mt9v032->format.colorspace = V4L2_COLORSPACE_SRGB; | ||
776 | + | ||
777 | + mt9v032->aec_agc = MT9V032_AEC_ENABLE | MT9V032_AGC_ENABLE; | ||
778 | + | ||
779 | + v4l2_i2c_subdev_init(&mt9v032->subdev, client, &mt9v032_subdev_ops); | ||
780 | + mt9v032->subdev.internal_ops = &mt9v032_subdev_internal_ops; | ||
781 | + mt9v032->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
782 | + | ||
783 | + mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE; | ||
784 | + ret = media_entity_init(&mt9v032->subdev.entity, 1, &mt9v032->pad, 0); | ||
785 | + if (ret < 0) | ||
786 | + kfree(mt9v032); | ||
787 | + | ||
788 | + return ret; | ||
789 | +} | ||
790 | + | ||
791 | +static int mt9v032_remove(struct i2c_client *client) | ||
792 | +{ | ||
793 | + struct v4l2_subdev *subdev = i2c_get_clientdata(client); | ||
794 | + struct mt9v032 *mt9v032 = to_mt9v032(subdev); | ||
795 | + | ||
796 | + v4l2_device_unregister_subdev(subdev); | ||
797 | + media_entity_cleanup(&subdev->entity); | ||
798 | + kfree(mt9v032); | ||
799 | + return 0; | ||
800 | +} | ||
801 | + | ||
802 | +static const struct i2c_device_id mt9v032_id[] = { | ||
803 | + { "mt9v032", 0 }, | ||
804 | + { } | ||
805 | +}; | ||
806 | +MODULE_DEVICE_TABLE(i2c, mt9v032_id); | ||
807 | + | ||
808 | +static struct i2c_driver mt9v032_driver = { | ||
809 | + .driver = { | ||
810 | + .name = "mt9v032", | ||
811 | + }, | ||
812 | + .probe = mt9v032_probe, | ||
813 | + .remove = mt9v032_remove, | ||
814 | + .id_table = mt9v032_id, | ||
815 | +}; | ||
816 | + | ||
817 | +static int __init mt9v032_init(void) | ||
818 | +{ | ||
819 | + return i2c_add_driver(&mt9v032_driver); | ||
820 | +} | ||
821 | + | ||
822 | +static void __exit mt9v032_exit(void) | ||
823 | +{ | ||
824 | + i2c_del_driver(&mt9v032_driver); | ||
825 | +} | ||
826 | + | ||
827 | +module_init(mt9v032_init); | ||
828 | +module_exit(mt9v032_exit); | ||
829 | + | ||
830 | +MODULE_DESCRIPTION("Aptina MT9V032 Camera driver"); | ||
831 | +MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); | ||
832 | +MODULE_LICENSE("GPL"); | ||
833 | diff --git a/include/media/mt9v032.h b/include/media/mt9v032.h | ||
834 | new file mode 100644 | ||
835 | index 0000000..5e27f9b | ||
836 | --- /dev/null | ||
837 | +++ b/include/media/mt9v032.h | ||
838 | @@ -0,0 +1,12 @@ | ||
839 | +#ifndef _MEDIA_MT9V032_H | ||
840 | +#define _MEDIA_MT9V032_H | ||
841 | + | ||
842 | +struct v4l2_subdev; | ||
843 | + | ||
844 | +struct mt9v032_platform_data { | ||
845 | + unsigned int clk_pol:1; | ||
846 | + | ||
847 | + void (*set_clock)(struct v4l2_subdev *subdev, unsigned int rate); | ||
848 | +}; | ||
849 | + | ||
850 | +#endif | ||
851 | -- | ||
852 | 1.6.6.1 | ||
853 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/camera/0003-Add-support-for-mt9p031-LI-5M03-module-in-Beagleboar.patch b/recipes-kernel/linux/linux-omap-2.6.39/camera/0003-Add-support-for-mt9p031-LI-5M03-module-in-Beagleboar.patch deleted file mode 100644 index a1807e73..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/camera/0003-Add-support-for-mt9p031-LI-5M03-module-in-Beagleboar.patch +++ /dev/null | |||
@@ -1,162 +0,0 @@ | |||
1 | From f662a8a2b9794121568903f5cc969e50eb151892 Mon Sep 17 00:00:00 2001 | ||
2 | From: Javier Martin <javier.martin@vista-silicon.com> | ||
3 | Date: Mon, 30 May 2011 10:37:17 +0200 | ||
4 | Subject: [PATCH 3/3] Add support for mt9p031 (LI-5M03 module) in Beagleboard xM. | ||
5 | |||
6 | Since isp clocks have not been exposed yet, this patch | ||
7 | includes a temporal solution for testing mt9p031 driver | ||
8 | in Beagleboard xM. | ||
9 | |||
10 | Signed-off-by: Javier Martin <javier.martin@vista-silicon.com> | ||
11 | --- | ||
12 | arch/arm/mach-omap2/Makefile | 1 + | ||
13 | arch/arm/mach-omap2/board-omap3beagle-camera.c | 95 ++++++++++++++++++++++++ | ||
14 | arch/arm/mach-omap2/board-omap3beagle.c | 5 + | ||
15 | 3 files changed, 101 insertions(+), 0 deletions(-) | ||
16 | create mode 100644 arch/arm/mach-omap2/board-omap3beagle-camera.c | ||
17 | |||
18 | diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile | ||
19 | index 512b152..05cd983 100644 | ||
20 | --- a/arch/arm/mach-omap2/Makefile | ||
21 | +++ b/arch/arm/mach-omap2/Makefile | ||
22 | @@ -179,6 +179,7 @@ obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o \ | ||
23 | hsmmc.o | ||
24 | obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o | ||
25 | obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o \ | ||
26 | + board-omap3beagle-camera.o \ | ||
27 | hsmmc.o | ||
28 | obj-$(CONFIG_MACH_DEVKIT8000) += board-devkit8000.o \ | ||
29 | hsmmc.o | ||
30 | diff --git a/arch/arm/mach-omap2/board-omap3beagle-camera.c b/arch/arm/mach-omap2/board-omap3beagle-camera.c | ||
31 | new file mode 100644 | ||
32 | index 0000000..2632557 | ||
33 | --- /dev/null | ||
34 | +++ b/arch/arm/mach-omap2/board-omap3beagle-camera.c | ||
35 | @@ -0,0 +1,95 @@ | ||
36 | +#include <linux/gpio.h> | ||
37 | +#include <linux/regulator/machine.h> | ||
38 | + | ||
39 | +#include <plat/i2c.h> | ||
40 | + | ||
41 | +#include <media/mt9p031.h> | ||
42 | +#include <asm/mach-types.h> | ||
43 | +#include "devices.h" | ||
44 | +#include "../../../drivers/media/video/omap3isp/isp.h" | ||
45 | + | ||
46 | +#define MT9P031_RESET_GPIO 98 | ||
47 | +#define MT9P031_XCLK ISP_XCLK_A | ||
48 | + | ||
49 | +static struct regulator *reg_1v8, *reg_2v8; | ||
50 | + | ||
51 | +static int beagle_cam_set_xclk(struct v4l2_subdev *subdev, int hz) | ||
52 | +{ | ||
53 | + struct isp_device *isp = v4l2_dev_to_isp_device(subdev->v4l2_dev); | ||
54 | + int ret; | ||
55 | + | ||
56 | + ret = isp->platform_cb.set_xclk(isp, hz, MT9P031_XCLK); | ||
57 | + return 0; | ||
58 | +} | ||
59 | + | ||
60 | +static int beagle_cam_reset(struct v4l2_subdev *subdev, int active) | ||
61 | +{ | ||
62 | + /* Set RESET_BAR to !active */ | ||
63 | + gpio_set_value(MT9P031_RESET_GPIO, !active); | ||
64 | + | ||
65 | + return 0; | ||
66 | +} | ||
67 | + | ||
68 | +static struct mt9p031_platform_data beagle_mt9p031_platform_data = { | ||
69 | + .set_xclk = beagle_cam_set_xclk, | ||
70 | + .reset = beagle_cam_reset, | ||
71 | + .vdd_io = MT9P031_VDD_IO_1V8, | ||
72 | + .version = MT9P031_COLOR_VERSION, | ||
73 | +}; | ||
74 | + | ||
75 | +static struct i2c_board_info mt9p031_camera_i2c_device = { | ||
76 | + I2C_BOARD_INFO("mt9p031", 0x48), | ||
77 | + .platform_data = &beagle_mt9p031_platform_data, | ||
78 | +}; | ||
79 | + | ||
80 | +static struct isp_subdev_i2c_board_info mt9p031_camera_subdevs[] = { | ||
81 | + { | ||
82 | + .board_info = &mt9p031_camera_i2c_device, | ||
83 | + .i2c_adapter_id = 2, | ||
84 | + }, | ||
85 | + { NULL, 0, }, | ||
86 | +}; | ||
87 | + | ||
88 | +static struct isp_v4l2_subdevs_group beagle_camera_subdevs[] = { | ||
89 | + { | ||
90 | + .subdevs = mt9p031_camera_subdevs, | ||
91 | + .interface = ISP_INTERFACE_PARALLEL, | ||
92 | + .bus = { | ||
93 | + .parallel = { | ||
94 | + .data_lane_shift = 0, | ||
95 | + .clk_pol = 1, | ||
96 | + .bridge = ISPCTRL_PAR_BRIDGE_DISABLE, | ||
97 | + } | ||
98 | + }, | ||
99 | + }, | ||
100 | + { }, | ||
101 | +}; | ||
102 | + | ||
103 | +static struct isp_platform_data beagle_isp_platform_data = { | ||
104 | + .subdevs = beagle_camera_subdevs, | ||
105 | +}; | ||
106 | + | ||
107 | +static int __init beagle_camera_init(void) | ||
108 | +{ | ||
109 | + if (!machine_is_omap3_beagle() || !cpu_is_omap3630()) | ||
110 | + return 0; | ||
111 | + | ||
112 | + reg_1v8 = regulator_get(NULL, "cam_1v8"); | ||
113 | + if (IS_ERR(reg_1v8)) | ||
114 | + pr_err("%s: cannot get cam_1v8 regulator\n", __func__); | ||
115 | + else | ||
116 | + regulator_enable(reg_1v8); | ||
117 | + | ||
118 | + reg_2v8 = regulator_get(NULL, "cam_2v8"); | ||
119 | + if (IS_ERR(reg_2v8)) | ||
120 | + pr_err("%s: cannot get cam_2v8 regulator\n", __func__); | ||
121 | + else | ||
122 | + regulator_enable(reg_2v8); | ||
123 | + | ||
124 | + omap_register_i2c_bus(2, 100, NULL, 0); | ||
125 | + gpio_request(MT9P031_RESET_GPIO, "cam_rst"); | ||
126 | + gpio_direction_output(MT9P031_RESET_GPIO, 0); | ||
127 | + omap3_init_camera(&beagle_isp_platform_data); | ||
128 | + return 0; | ||
129 | +} | ||
130 | +late_initcall(beagle_camera_init); | ||
131 | diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c | ||
132 | index 221bfda..dd6e31f 100644 | ||
133 | --- a/arch/arm/mach-omap2/board-omap3beagle.c | ||
134 | +++ b/arch/arm/mach-omap2/board-omap3beagle.c | ||
135 | @@ -25,12 +25,16 @@ | ||
136 | #include <linux/input.h> | ||
137 | #include <linux/gpio_keys.h> | ||
138 | #include <linux/opp.h> | ||
139 | +#include <linux/i2c.h> | ||
140 | +#include <linux/mm.h> | ||
141 | +#include <linux/videodev2.h> | ||
142 | |||
143 | #include <linux/mtd/mtd.h> | ||
144 | #include <linux/mtd/partitions.h> | ||
145 | #include <linux/mtd/nand.h> | ||
146 | #include <linux/mmc/host.h> | ||
147 | |||
148 | +#include <linux/gpio.h> | ||
149 | #include <linux/regulator/machine.h> | ||
150 | #include <linux/i2c/twl.h> | ||
151 | |||
152 | @@ -48,6 +52,7 @@ | ||
153 | #include <plat/nand.h> | ||
154 | #include <plat/usb.h> | ||
155 | #include <plat/omap_device.h> | ||
156 | +#include <plat/i2c.h> | ||
157 | |||
158 | #include "mux.h" | ||
159 | #include "hsmmc.h" | ||
160 | -- | ||
161 | 1.6.6.1 | ||
162 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0001-mfd-Fix-omap-usbhs-crash-when-rmmoding-ehci-or-ohci.patch b/recipes-kernel/linux/linux-omap-2.6.39/mfd/0001-mfd-Fix-omap-usbhs-crash-when-rmmoding-ehci-or-ohci.patch deleted file mode 100644 index c9f1e6a9..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0001-mfd-Fix-omap-usbhs-crash-when-rmmoding-ehci-or-ohci.patch +++ /dev/null | |||
@@ -1,67 +0,0 @@ | |||
1 | From 46be90d202c36db19e27c2991cbff401c6c3ee81 Mon Sep 17 00:00:00 2001 | ||
2 | From: Keshava Munegowda <Keshava_mgowda@ti.com> | ||
3 | Date: Mon, 16 May 2011 14:24:58 +0530 | ||
4 | Subject: [PATCH 01/13] mfd: Fix omap usbhs crash when rmmoding ehci or ohci | ||
5 | |||
6 | The disabling of clocks and freeing GPIO are changed | ||
7 | to fix the occurrence of the crash of rmmod of ehci and ohci | ||
8 | drivers. The GPIOs should be freed after the spin locks are | ||
9 | unlocked. | ||
10 | |||
11 | Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com> | ||
12 | Acked-by: Felipe Balbi <balbi@ti.com> | ||
13 | Cc: stable@kernel.org | ||
14 | Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> | ||
15 | --- | ||
16 | drivers/mfd/omap-usb-host.c | 27 +++++++++++++++++++-------- | ||
17 | 1 files changed, 19 insertions(+), 8 deletions(-) | ||
18 | |||
19 | diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c | ||
20 | index 3ab9ffa..55c5d47 100644 | ||
21 | --- a/drivers/mfd/omap-usb-host.c | ||
22 | +++ b/drivers/mfd/omap-usb-host.c | ||
23 | @@ -994,22 +994,33 @@ static void usbhs_disable(struct device *dev) | ||
24 | dev_dbg(dev, "operation timed out\n"); | ||
25 | } | ||
26 | |||
27 | - if (pdata->ehci_data->phy_reset) { | ||
28 | - if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) | ||
29 | - gpio_free(pdata->ehci_data->reset_gpio_port[0]); | ||
30 | - | ||
31 | - if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) | ||
32 | - gpio_free(pdata->ehci_data->reset_gpio_port[1]); | ||
33 | + if (is_omap_usbhs_rev2(omap)) { | ||
34 | + if (is_ehci_tll_mode(pdata->port_mode[0])) | ||
35 | + clk_enable(omap->usbtll_p1_fck); | ||
36 | + if (is_ehci_tll_mode(pdata->port_mode[1])) | ||
37 | + clk_enable(omap->usbtll_p2_fck); | ||
38 | + clk_disable(omap->utmi_p2_fck); | ||
39 | + clk_disable(omap->utmi_p1_fck); | ||
40 | } | ||
41 | |||
42 | - clk_disable(omap->utmi_p2_fck); | ||
43 | - clk_disable(omap->utmi_p1_fck); | ||
44 | clk_disable(omap->usbtll_ick); | ||
45 | clk_disable(omap->usbtll_fck); | ||
46 | clk_disable(omap->usbhost_fs_fck); | ||
47 | clk_disable(omap->usbhost_hs_fck); | ||
48 | clk_disable(omap->usbhost_ick); | ||
49 | |||
50 | + /* The gpio_free migh sleep; so unlock the spinlock */ | ||
51 | + spin_unlock_irqrestore(&omap->lock, flags); | ||
52 | + | ||
53 | + if (pdata->ehci_data->phy_reset) { | ||
54 | + if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) | ||
55 | + gpio_free(pdata->ehci_data->reset_gpio_port[0]); | ||
56 | + | ||
57 | + if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) | ||
58 | + gpio_free(pdata->ehci_data->reset_gpio_port[1]); | ||
59 | + } | ||
60 | + return; | ||
61 | + | ||
62 | end_disble: | ||
63 | spin_unlock_irqrestore(&omap->lock, flags); | ||
64 | } | ||
65 | -- | ||
66 | 1.6.6.1 | ||
67 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0002-mfd-Fix-omap_usbhs_alloc_children-error-handling.patch b/recipes-kernel/linux/linux-omap-2.6.39/mfd/0002-mfd-Fix-omap_usbhs_alloc_children-error-handling.patch deleted file mode 100644 index 380dd82a..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0002-mfd-Fix-omap_usbhs_alloc_children-error-handling.patch +++ /dev/null | |||
@@ -1,50 +0,0 @@ | |||
1 | From 89a903aca8fda3dcf1a6f9a424247e772afdd44e Mon Sep 17 00:00:00 2001 | ||
2 | From: Axel Lin <axel.lin@gmail.com> | ||
3 | Date: Sat, 14 May 2011 14:15:36 +0800 | ||
4 | Subject: [PATCH 02/13] mfd: Fix omap_usbhs_alloc_children error handling | ||
5 | |||
6 | 1. Return proper error if omap_usbhs_alloc_child fails | ||
7 | 2. In the case of goto err_ehci, we should call platform_device_unregister(ehci) | ||
8 | instead of platform_device_put(ehci) because we have already added the | ||
9 | platform device to device hierarchy. | ||
10 | |||
11 | Signed-off-by: Axel Lin <axel.lin@gmail.com> | ||
12 | Signed-off-by: Axel Lin <axel.lin@gmail.com> | ||
13 | Tested-by: Keshava Munegowda <keshava_mgowda@ti.com> | ||
14 | Acked-by: Felipe Balbi <balbi@ti.com> | ||
15 | Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> | ||
16 | --- | ||
17 | drivers/mfd/omap-usb-host.c | 4 +++- | ||
18 | 1 files changed, 3 insertions(+), 1 deletions(-) | ||
19 | |||
20 | diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c | ||
21 | index 55c5d47..1717144 100644 | ||
22 | --- a/drivers/mfd/omap-usb-host.c | ||
23 | +++ b/drivers/mfd/omap-usb-host.c | ||
24 | @@ -281,6 +281,7 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev) | ||
25 | |||
26 | if (!ehci) { | ||
27 | dev_err(dev, "omap_usbhs_alloc_child failed\n"); | ||
28 | + ret = -ENOMEM; | ||
29 | goto err_end; | ||
30 | } | ||
31 | |||
32 | @@ -304,13 +305,14 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev) | ||
33 | sizeof(*ohci_data), dev); | ||
34 | if (!ohci) { | ||
35 | dev_err(dev, "omap_usbhs_alloc_child failed\n"); | ||
36 | + ret = -ENOMEM; | ||
37 | goto err_ehci; | ||
38 | } | ||
39 | |||
40 | return 0; | ||
41 | |||
42 | err_ehci: | ||
43 | - platform_device_put(ehci); | ||
44 | + platform_device_unregister(ehci); | ||
45 | |||
46 | err_end: | ||
47 | return ret; | ||
48 | -- | ||
49 | 1.6.6.1 | ||
50 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0003-mfd-Add-omap-usbhs-runtime-PM-support.patch b/recipes-kernel/linux/linux-omap-2.6.39/mfd/0003-mfd-Add-omap-usbhs-runtime-PM-support.patch deleted file mode 100644 index b47deb2c..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0003-mfd-Add-omap-usbhs-runtime-PM-support.patch +++ /dev/null | |||
@@ -1,245 +0,0 @@ | |||
1 | From edc881f9c4897fab11542cd5c36a33b288f702be Mon Sep 17 00:00:00 2001 | ||
2 | From: Keshava Munegowda <Keshava_mgowda@ti.com> | ||
3 | Date: Sun, 22 May 2011 22:51:26 +0200 | ||
4 | Subject: [PATCH 03/13] mfd: Add omap-usbhs runtime PM support | ||
5 | |||
6 | The usbhs core driver does not enable/disable the interface and | ||
7 | functional clocks; These clocks are handled by hwmod and runtime pm, | ||
8 | hence insted of the clock enable/disable, the runtime pm APIS are | ||
9 | used. however,the port clocks and tll clocks are handled | ||
10 | by the usbhs core. | ||
11 | |||
12 | Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com> | ||
13 | Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> | ||
14 | --- | ||
15 | drivers/mfd/omap-usb-host.c | 131 +++---------------------------------------- | ||
16 | 1 files changed, 9 insertions(+), 122 deletions(-) | ||
17 | |||
18 | diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c | ||
19 | index 1717144..8552195 100644 | ||
20 | --- a/drivers/mfd/omap-usb-host.c | ||
21 | +++ b/drivers/mfd/omap-usb-host.c | ||
22 | @@ -26,6 +26,7 @@ | ||
23 | #include <linux/spinlock.h> | ||
24 | #include <linux/gpio.h> | ||
25 | #include <plat/usb.h> | ||
26 | +#include <linux/pm_runtime.h> | ||
27 | |||
28 | #define USBHS_DRIVER_NAME "usbhs-omap" | ||
29 | #define OMAP_EHCI_DEVICE "ehci-omap" | ||
30 | @@ -146,9 +147,6 @@ | ||
31 | |||
32 | |||
33 | struct usbhs_hcd_omap { | ||
34 | - struct clk *usbhost_ick; | ||
35 | - struct clk *usbhost_hs_fck; | ||
36 | - struct clk *usbhost_fs_fck; | ||
37 | struct clk *xclk60mhsp1_ck; | ||
38 | struct clk *xclk60mhsp2_ck; | ||
39 | struct clk *utmi_p1_fck; | ||
40 | @@ -158,8 +156,6 @@ struct usbhs_hcd_omap { | ||
41 | struct clk *usbhost_p2_fck; | ||
42 | struct clk *usbtll_p2_fck; | ||
43 | struct clk *init_60m_fclk; | ||
44 | - struct clk *usbtll_fck; | ||
45 | - struct clk *usbtll_ick; | ||
46 | |||
47 | void __iomem *uhh_base; | ||
48 | void __iomem *tll_base; | ||
49 | @@ -353,46 +349,13 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev) | ||
50 | omap->platdata.ehci_data = pdata->ehci_data; | ||
51 | omap->platdata.ohci_data = pdata->ohci_data; | ||
52 | |||
53 | - omap->usbhost_ick = clk_get(dev, "usbhost_ick"); | ||
54 | - if (IS_ERR(omap->usbhost_ick)) { | ||
55 | - ret = PTR_ERR(omap->usbhost_ick); | ||
56 | - dev_err(dev, "usbhost_ick failed error:%d\n", ret); | ||
57 | - goto err_end; | ||
58 | - } | ||
59 | - | ||
60 | - omap->usbhost_hs_fck = clk_get(dev, "hs_fck"); | ||
61 | - if (IS_ERR(omap->usbhost_hs_fck)) { | ||
62 | - ret = PTR_ERR(omap->usbhost_hs_fck); | ||
63 | - dev_err(dev, "usbhost_hs_fck failed error:%d\n", ret); | ||
64 | - goto err_usbhost_ick; | ||
65 | - } | ||
66 | - | ||
67 | - omap->usbhost_fs_fck = clk_get(dev, "fs_fck"); | ||
68 | - if (IS_ERR(omap->usbhost_fs_fck)) { | ||
69 | - ret = PTR_ERR(omap->usbhost_fs_fck); | ||
70 | - dev_err(dev, "usbhost_fs_fck failed error:%d\n", ret); | ||
71 | - goto err_usbhost_hs_fck; | ||
72 | - } | ||
73 | - | ||
74 | - omap->usbtll_fck = clk_get(dev, "usbtll_fck"); | ||
75 | - if (IS_ERR(omap->usbtll_fck)) { | ||
76 | - ret = PTR_ERR(omap->usbtll_fck); | ||
77 | - dev_err(dev, "usbtll_fck failed error:%d\n", ret); | ||
78 | - goto err_usbhost_fs_fck; | ||
79 | - } | ||
80 | - | ||
81 | - omap->usbtll_ick = clk_get(dev, "usbtll_ick"); | ||
82 | - if (IS_ERR(omap->usbtll_ick)) { | ||
83 | - ret = PTR_ERR(omap->usbtll_ick); | ||
84 | - dev_err(dev, "usbtll_ick failed error:%d\n", ret); | ||
85 | - goto err_usbtll_fck; | ||
86 | - } | ||
87 | + pm_runtime_enable(&pdev->dev); | ||
88 | |||
89 | omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); | ||
90 | if (IS_ERR(omap->utmi_p1_fck)) { | ||
91 | ret = PTR_ERR(omap->utmi_p1_fck); | ||
92 | dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); | ||
93 | - goto err_usbtll_ick; | ||
94 | + goto err_end; | ||
95 | } | ||
96 | |||
97 | omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); | ||
98 | @@ -522,22 +485,8 @@ err_xclk60mhsp1_ck: | ||
99 | err_utmi_p1_fck: | ||
100 | clk_put(omap->utmi_p1_fck); | ||
101 | |||
102 | -err_usbtll_ick: | ||
103 | - clk_put(omap->usbtll_ick); | ||
104 | - | ||
105 | -err_usbtll_fck: | ||
106 | - clk_put(omap->usbtll_fck); | ||
107 | - | ||
108 | -err_usbhost_fs_fck: | ||
109 | - clk_put(omap->usbhost_fs_fck); | ||
110 | - | ||
111 | -err_usbhost_hs_fck: | ||
112 | - clk_put(omap->usbhost_hs_fck); | ||
113 | - | ||
114 | -err_usbhost_ick: | ||
115 | - clk_put(omap->usbhost_ick); | ||
116 | - | ||
117 | err_end: | ||
118 | + pm_runtime_disable(&pdev->dev); | ||
119 | kfree(omap); | ||
120 | |||
121 | end_probe: | ||
122 | @@ -571,11 +520,7 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev) | ||
123 | clk_put(omap->utmi_p2_fck); | ||
124 | clk_put(omap->xclk60mhsp1_ck); | ||
125 | clk_put(omap->utmi_p1_fck); | ||
126 | - clk_put(omap->usbtll_ick); | ||
127 | - clk_put(omap->usbtll_fck); | ||
128 | - clk_put(omap->usbhost_fs_fck); | ||
129 | - clk_put(omap->usbhost_hs_fck); | ||
130 | - clk_put(omap->usbhost_ick); | ||
131 | + pm_runtime_disable(&pdev->dev); | ||
132 | kfree(omap); | ||
133 | |||
134 | return 0; | ||
135 | @@ -695,7 +640,6 @@ static int usbhs_enable(struct device *dev) | ||
136 | struct usbhs_omap_platform_data *pdata = &omap->platdata; | ||
137 | unsigned long flags = 0; | ||
138 | int ret = 0; | ||
139 | - unsigned long timeout; | ||
140 | unsigned reg; | ||
141 | |||
142 | dev_dbg(dev, "starting TI HSUSB Controller\n"); | ||
143 | @@ -708,11 +652,7 @@ static int usbhs_enable(struct device *dev) | ||
144 | if (omap->count > 0) | ||
145 | goto end_count; | ||
146 | |||
147 | - clk_enable(omap->usbhost_ick); | ||
148 | - clk_enable(omap->usbhost_hs_fck); | ||
149 | - clk_enable(omap->usbhost_fs_fck); | ||
150 | - clk_enable(omap->usbtll_fck); | ||
151 | - clk_enable(omap->usbtll_ick); | ||
152 | + pm_runtime_get_sync(dev); | ||
153 | |||
154 | if (pdata->ehci_data->phy_reset) { | ||
155 | if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) { | ||
156 | @@ -736,50 +676,6 @@ static int usbhs_enable(struct device *dev) | ||
157 | omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION); | ||
158 | dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev); | ||
159 | |||
160 | - /* perform TLL soft reset, and wait until reset is complete */ | ||
161 | - usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, | ||
162 | - OMAP_USBTLL_SYSCONFIG_SOFTRESET); | ||
163 | - | ||
164 | - /* Wait for TLL reset to complete */ | ||
165 | - timeout = jiffies + msecs_to_jiffies(1000); | ||
166 | - while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS) | ||
167 | - & OMAP_USBTLL_SYSSTATUS_RESETDONE)) { | ||
168 | - cpu_relax(); | ||
169 | - | ||
170 | - if (time_after(jiffies, timeout)) { | ||
171 | - dev_dbg(dev, "operation timed out\n"); | ||
172 | - ret = -EINVAL; | ||
173 | - goto err_tll; | ||
174 | - } | ||
175 | - } | ||
176 | - | ||
177 | - dev_dbg(dev, "TLL RESET DONE\n"); | ||
178 | - | ||
179 | - /* (1<<3) = no idle mode only for initial debugging */ | ||
180 | - usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, | ||
181 | - OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | | ||
182 | - OMAP_USBTLL_SYSCONFIG_SIDLEMODE | | ||
183 | - OMAP_USBTLL_SYSCONFIG_AUTOIDLE); | ||
184 | - | ||
185 | - /* Put UHH in NoIdle/NoStandby mode */ | ||
186 | - reg = usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG); | ||
187 | - if (is_omap_usbhs_rev1(omap)) { | ||
188 | - reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP | ||
189 | - | OMAP_UHH_SYSCONFIG_SIDLEMODE | ||
190 | - | OMAP_UHH_SYSCONFIG_CACTIVITY | ||
191 | - | OMAP_UHH_SYSCONFIG_MIDLEMODE); | ||
192 | - reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; | ||
193 | - | ||
194 | - | ||
195 | - } else if (is_omap_usbhs_rev2(omap)) { | ||
196 | - reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR; | ||
197 | - reg |= OMAP4_UHH_SYSCONFIG_NOIDLE; | ||
198 | - reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR; | ||
199 | - reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY; | ||
200 | - } | ||
201 | - | ||
202 | - usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); | ||
203 | - | ||
204 | reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG); | ||
205 | /* setup ULPI bypass and burst configurations */ | ||
206 | reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN | ||
207 | @@ -919,6 +815,8 @@ end_count: | ||
208 | return 0; | ||
209 | |||
210 | err_tll: | ||
211 | + pm_runtime_put_sync(dev); | ||
212 | + spin_unlock_irqrestore(&omap->lock, flags); | ||
213 | if (pdata->ehci_data->phy_reset) { | ||
214 | if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) | ||
215 | gpio_free(pdata->ehci_data->reset_gpio_port[0]); | ||
216 | @@ -926,13 +824,6 @@ err_tll: | ||
217 | if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) | ||
218 | gpio_free(pdata->ehci_data->reset_gpio_port[1]); | ||
219 | } | ||
220 | - | ||
221 | - clk_disable(omap->usbtll_ick); | ||
222 | - clk_disable(omap->usbtll_fck); | ||
223 | - clk_disable(omap->usbhost_fs_fck); | ||
224 | - clk_disable(omap->usbhost_hs_fck); | ||
225 | - clk_disable(omap->usbhost_ick); | ||
226 | - spin_unlock_irqrestore(&omap->lock, flags); | ||
227 | return ret; | ||
228 | } | ||
229 | |||
230 | @@ -1005,11 +896,7 @@ static void usbhs_disable(struct device *dev) | ||
231 | clk_disable(omap->utmi_p1_fck); | ||
232 | } | ||
233 | |||
234 | - clk_disable(omap->usbtll_ick); | ||
235 | - clk_disable(omap->usbtll_fck); | ||
236 | - clk_disable(omap->usbhost_fs_fck); | ||
237 | - clk_disable(omap->usbhost_hs_fck); | ||
238 | - clk_disable(omap->usbhost_ick); | ||
239 | + pm_runtime_put_sync(dev); | ||
240 | |||
241 | /* The gpio_free migh sleep; so unlock the spinlock */ | ||
242 | spin_unlock_irqrestore(&omap->lock, flags); | ||
243 | -- | ||
244 | 1.6.6.1 | ||
245 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0004-arm-omap-usb-ehci-and-ohci-hwmod-structures-for-omap.patch b/recipes-kernel/linux/linux-omap-2.6.39/mfd/0004-arm-omap-usb-ehci-and-ohci-hwmod-structures-for-omap.patch deleted file mode 100644 index 3d4d8a2d..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0004-arm-omap-usb-ehci-and-ohci-hwmod-structures-for-omap.patch +++ /dev/null | |||
@@ -1,406 +0,0 @@ | |||
1 | From 339b167f6f76707a2d6ae3a7c0b921b8278564af Mon Sep 17 00:00:00 2001 | ||
2 | From: Keshava Munegowda <Keshava_mgowda@ti.com> | ||
3 | Date: Wed, 1 Jun 2011 11:02:49 -0700 | ||
4 | Subject: [PATCH 04/13] arm: omap: usb: ehci and ohci hwmod structures for omap3 and omap4 | ||
5 | |||
6 | Following 2 hwmod strcuture are added: | ||
7 | UHH hwmod of usbhs with uhh base address and | ||
8 | EHCI , OHCI irq and base addresses. | ||
9 | TLL hwmod of usbhs with the TLL base address and irq. | ||
10 | |||
11 | Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com> | ||
12 | --- | ||
13 | arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 184 ++++++++++++++++++++++++++++ | ||
14 | arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 153 +++++++++++++++++++++++ | ||
15 | 2 files changed, 337 insertions(+), 0 deletions(-) | ||
16 | |||
17 | diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | ||
18 | index 909a84d..fe9a176 100644 | ||
19 | --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | ||
20 | +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | ||
21 | @@ -84,6 +84,8 @@ static struct omap_hwmod omap3xxx_mcbsp4_hwmod; | ||
22 | static struct omap_hwmod omap3xxx_mcbsp5_hwmod; | ||
23 | static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod; | ||
24 | static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod; | ||
25 | +static struct omap_hwmod omap34xx_usb_host_hs_hwmod; | ||
26 | +static struct omap_hwmod omap34xx_usb_tll_hs_hwmod; | ||
27 | |||
28 | /* L3 -> L4_CORE interface */ | ||
29 | static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = { | ||
30 | @@ -3574,6 +3576,185 @@ static struct omap_hwmod omap3xxx_mmc3_hwmod = { | ||
31 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), | ||
32 | }; | ||
33 | |||
34 | +/* | ||
35 | + * 'usb_host_hs' class | ||
36 | + * high-speed multi-port usb host controller | ||
37 | + */ | ||
38 | +static struct omap_hwmod_ocp_if omap34xx_usb_host_hs__l3_main_2 = { | ||
39 | + .master = &omap34xx_usb_host_hs_hwmod, | ||
40 | + .slave = &omap3xxx_l3_main_hwmod, | ||
41 | + .clk = "core_l3_ick", | ||
42 | + .user = OCP_USER_MPU, | ||
43 | +}; | ||
44 | + | ||
45 | +static struct omap_hwmod_class_sysconfig omap34xx_usb_host_hs_sysc = { | ||
46 | + .rev_offs = 0x0000, | ||
47 | + .sysc_offs = 0x0010, | ||
48 | + .syss_offs = 0x0014, | ||
49 | + .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE), | ||
50 | + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | | ||
51 | + MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), | ||
52 | + .sysc_fields = &omap_hwmod_sysc_type1, | ||
53 | +}; | ||
54 | + | ||
55 | +static struct omap_hwmod_class omap34xx_usb_host_hs_hwmod_class = { | ||
56 | + .name = "usbhs_uhh", | ||
57 | + .sysc = &omap34xx_usb_host_hs_sysc, | ||
58 | +}; | ||
59 | + | ||
60 | +static struct omap_hwmod_ocp_if *omap34xx_usb_host_hs_masters[] = { | ||
61 | + &omap34xx_usb_host_hs__l3_main_2, | ||
62 | +}; | ||
63 | + | ||
64 | +static struct omap_hwmod_irq_info omap34xx_usb_host_hs_irqs[] = { | ||
65 | + { .name = "ohci-irq", .irq = 76 }, | ||
66 | + { .name = "ehci-irq", .irq = 77 }, | ||
67 | +}; | ||
68 | + | ||
69 | +static struct omap_hwmod_addr_space omap34xx_usb_host_hs_addrs[] = { | ||
70 | + { | ||
71 | + .name = "uhh", | ||
72 | + .pa_start = 0x48064000, | ||
73 | + .pa_end = 0x480643ff, | ||
74 | + .flags = ADDR_TYPE_RT | ||
75 | + }, | ||
76 | + { | ||
77 | + .name = "ohci", | ||
78 | + .pa_start = 0x48064400, | ||
79 | + .pa_end = 0x480647FF, | ||
80 | + .flags = ADDR_MAP_ON_INIT | ||
81 | + }, | ||
82 | + { | ||
83 | + .name = "ehci", | ||
84 | + .pa_start = 0x48064800, | ||
85 | + .pa_end = 0x48064CFF, | ||
86 | + .flags = ADDR_MAP_ON_INIT | ||
87 | + } | ||
88 | +}; | ||
89 | + | ||
90 | +static struct omap_hwmod_ocp_if omap34xx_l4_cfg__usb_host_hs = { | ||
91 | + .master = &omap3xxx_l4_core_hwmod, | ||
92 | + .slave = &omap34xx_usb_host_hs_hwmod, | ||
93 | + .clk = "l4_ick", | ||
94 | + .addr = omap34xx_usb_host_hs_addrs, | ||
95 | + .addr_cnt = ARRAY_SIZE(omap34xx_usb_host_hs_addrs), | ||
96 | + .user = OCP_USER_MPU | OCP_USER_SDMA, | ||
97 | +}; | ||
98 | + | ||
99 | +static struct omap_hwmod_ocp_if omap34xx_f128m_cfg__usb_host_hs = { | ||
100 | + .clk = "usbhost_120m_fck", | ||
101 | + .user = OCP_USER_MPU, | ||
102 | + .flags = OCPIF_SWSUP_IDLE, | ||
103 | +}; | ||
104 | + | ||
105 | +static struct omap_hwmod_ocp_if omap34xx_f48m_cfg__usb_host_hs = { | ||
106 | + .clk = "usbhost_48m_fck", | ||
107 | + .user = OCP_USER_MPU, | ||
108 | + .flags = OCPIF_SWSUP_IDLE, | ||
109 | +}; | ||
110 | + | ||
111 | +static struct omap_hwmod_ocp_if *omap34xx_usb_host_hs_slaves[] = { | ||
112 | + &omap34xx_l4_cfg__usb_host_hs, | ||
113 | + &omap34xx_f128m_cfg__usb_host_hs, | ||
114 | + &omap34xx_f48m_cfg__usb_host_hs, | ||
115 | +}; | ||
116 | + | ||
117 | +static struct omap_hwmod omap34xx_usb_host_hs_hwmod = { | ||
118 | + .name = "usbhs_uhh", | ||
119 | + .class = &omap34xx_usb_host_hs_hwmod_class, | ||
120 | + .mpu_irqs = omap34xx_usb_host_hs_irqs, | ||
121 | + .mpu_irqs_cnt = ARRAY_SIZE(omap34xx_usb_host_hs_irqs), | ||
122 | + .main_clk = "usbhost_ick", | ||
123 | + .prcm = { | ||
124 | + .omap2 = { | ||
125 | + .module_offs = OMAP3430ES2_USBHOST_MOD, | ||
126 | + .prcm_reg_id = 1, | ||
127 | + .module_bit = 0, | ||
128 | + .idlest_reg_id = 1, | ||
129 | + .idlest_idle_bit = 1, | ||
130 | + .idlest_stdby_bit = 0, | ||
131 | + }, | ||
132 | + }, | ||
133 | + .slaves = omap34xx_usb_host_hs_slaves, | ||
134 | + .slaves_cnt = ARRAY_SIZE(omap34xx_usb_host_hs_slaves), | ||
135 | + .masters = omap34xx_usb_host_hs_masters, | ||
136 | + .masters_cnt = ARRAY_SIZE(omap34xx_usb_host_hs_masters), | ||
137 | + .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY, | ||
138 | + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), | ||
139 | +}; | ||
140 | + | ||
141 | +/* | ||
142 | + * 'usb_tll_hs' class | ||
143 | + * usb_tll_hs module is the adapter on the usb_host_hs ports | ||
144 | + */ | ||
145 | +static struct omap_hwmod_class_sysconfig omap34xx_usb_tll_hs_sysc = { | ||
146 | + .rev_offs = 0x0000, | ||
147 | + .sysc_offs = 0x0010, | ||
148 | + .syss_offs = 0x0014, | ||
149 | + .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE), | ||
150 | + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), | ||
151 | + .sysc_fields = &omap_hwmod_sysc_type1, | ||
152 | +}; | ||
153 | + | ||
154 | +static struct omap_hwmod_class omap34xx_usb_tll_hs_hwmod_class = { | ||
155 | + .name = "usbhs_tll", | ||
156 | + .sysc = &omap34xx_usb_tll_hs_sysc, | ||
157 | +}; | ||
158 | + | ||
159 | +static struct omap_hwmod_irq_info omap34xx_usb_tll_hs_irqs[] = { | ||
160 | + { .name = "tll-irq", .irq = 78 }, | ||
161 | +}; | ||
162 | + | ||
163 | +static struct omap_hwmod_addr_space omap34xx_usb_tll_hs_addrs[] = { | ||
164 | + { | ||
165 | + .name = "tll", | ||
166 | + .pa_start = 0x48062000, | ||
167 | + .pa_end = 0x48062fff, | ||
168 | + .flags = ADDR_TYPE_RT | ||
169 | + }, | ||
170 | +}; | ||
171 | + | ||
172 | +static struct omap_hwmod_ocp_if omap34xx_f_cfg__usb_tll_hs = { | ||
173 | + .clk = "usbtll_fck", | ||
174 | + .user = OCP_USER_MPU, | ||
175 | + .flags = OCPIF_SWSUP_IDLE, | ||
176 | +}; | ||
177 | + | ||
178 | +static struct omap_hwmod_ocp_if omap34xx_l4_cfg__usb_tll_hs = { | ||
179 | + .master = &omap3xxx_l4_core_hwmod, | ||
180 | + .slave = &omap34xx_usb_tll_hs_hwmod, | ||
181 | + .clk = "l4_ick", | ||
182 | + .addr = omap34xx_usb_tll_hs_addrs, | ||
183 | + .addr_cnt = ARRAY_SIZE(omap34xx_usb_tll_hs_addrs), | ||
184 | + .user = OCP_USER_MPU | OCP_USER_SDMA, | ||
185 | +}; | ||
186 | + | ||
187 | +static struct omap_hwmod_ocp_if *omap34xx_usb_tll_hs_slaves[] = { | ||
188 | + &omap34xx_l4_cfg__usb_tll_hs, | ||
189 | + &omap34xx_f_cfg__usb_tll_hs, | ||
190 | +}; | ||
191 | + | ||
192 | +static struct omap_hwmod omap34xx_usb_tll_hs_hwmod = { | ||
193 | + .name = "usbhs_tll", | ||
194 | + .class = &omap34xx_usb_tll_hs_hwmod_class, | ||
195 | + .mpu_irqs = omap34xx_usb_tll_hs_irqs, | ||
196 | + .mpu_irqs_cnt = ARRAY_SIZE(omap34xx_usb_tll_hs_irqs), | ||
197 | + .main_clk = "usbtll_ick", | ||
198 | + .prcm = { | ||
199 | + .omap2 = { | ||
200 | + .module_offs = CORE_MOD, | ||
201 | + .prcm_reg_id = 3, | ||
202 | + .module_bit = 2, | ||
203 | + .idlest_reg_id = 3, | ||
204 | + .idlest_idle_bit = 2, | ||
205 | + }, | ||
206 | + }, | ||
207 | + .slaves = omap34xx_usb_tll_hs_slaves, | ||
208 | + .slaves_cnt = ARRAY_SIZE(omap34xx_usb_tll_hs_slaves), | ||
209 | + .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY, | ||
210 | + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), | ||
211 | +}; | ||
212 | + | ||
213 | static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { | ||
214 | &omap3xxx_l3_main_hwmod, | ||
215 | &omap3xxx_l4_core_hwmod, | ||
216 | @@ -3656,6 +3837,9 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { | ||
217 | /* usbotg for am35x */ | ||
218 | &am35xx_usbhsotg_hwmod, | ||
219 | |||
220 | + &omap34xx_usb_host_hs_hwmod, | ||
221 | + &omap34xx_usb_tll_hs_hwmod, | ||
222 | + | ||
223 | NULL, | ||
224 | }; | ||
225 | |||
226 | diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c | ||
227 | index abc548a..d7112b0 100644 | ||
228 | --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c | ||
229 | +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c | ||
230 | @@ -66,6 +66,8 @@ static struct omap_hwmod omap44xx_mmc2_hwmod; | ||
231 | static struct omap_hwmod omap44xx_mpu_hwmod; | ||
232 | static struct omap_hwmod omap44xx_mpu_private_hwmod; | ||
233 | static struct omap_hwmod omap44xx_usb_otg_hs_hwmod; | ||
234 | +static struct omap_hwmod omap44xx_usb_host_hs_hwmod; | ||
235 | +static struct omap_hwmod omap44xx_usb_tll_hs_hwmod; | ||
236 | |||
237 | /* | ||
238 | * Interconnects omap_hwmod structures | ||
239 | @@ -5027,6 +5029,155 @@ static struct omap_hwmod omap44xx_wd_timer3_hwmod = { | ||
240 | .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), | ||
241 | }; | ||
242 | |||
243 | +/* | ||
244 | + * 'usb_host_hs' class | ||
245 | + * high-speed multi-port usb host controller | ||
246 | + */ | ||
247 | +static struct omap_hwmod_ocp_if omap44xx_usb_host_hs__l3_main_2 = { | ||
248 | + .master = &omap44xx_usb_host_hs_hwmod, | ||
249 | + .slave = &omap44xx_l3_main_2_hwmod, | ||
250 | + .clk = "l3_div_ck", | ||
251 | + .user = OCP_USER_MPU | OCP_USER_SDMA, | ||
252 | +}; | ||
253 | + | ||
254 | +static struct omap_hwmod_class_sysconfig omap44xx_usb_host_hs_sysc = { | ||
255 | + .rev_offs = 0x0000, | ||
256 | + .sysc_offs = 0x0010, | ||
257 | + .syss_offs = 0x0014, | ||
258 | + .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE), | ||
259 | + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | | ||
260 | + MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), | ||
261 | + .sysc_fields = &omap_hwmod_sysc_type2, | ||
262 | +}; | ||
263 | + | ||
264 | +static struct omap_hwmod_class omap44xx_usb_host_hs_hwmod_class = { | ||
265 | + .name = "usbhs_uhh", | ||
266 | + .sysc = &omap44xx_usb_host_hs_sysc, | ||
267 | +}; | ||
268 | + | ||
269 | +static struct omap_hwmod_ocp_if *omap44xx_usb_host_hs_masters[] = { | ||
270 | + &omap44xx_usb_host_hs__l3_main_2, | ||
271 | +}; | ||
272 | + | ||
273 | +static struct omap_hwmod_irq_info omap44xx_usb_host_hs_irqs[] = { | ||
274 | + { .name = "ohci-irq", .irq = 76 + OMAP44XX_IRQ_GIC_START }, | ||
275 | + { .name = "ehci-irq", .irq = 77 + OMAP44XX_IRQ_GIC_START }, | ||
276 | +}; | ||
277 | + | ||
278 | +static struct omap_hwmod_addr_space omap44xx_usb_host_hs_addrs[] = { | ||
279 | + { | ||
280 | + .name = "uhh", | ||
281 | + .pa_start = 0x4a064000, | ||
282 | + .pa_end = 0x4a0647ff, | ||
283 | + .flags = ADDR_TYPE_RT | ||
284 | + }, | ||
285 | + { | ||
286 | + .name = "ohci", | ||
287 | + .pa_start = 0x4A064800, | ||
288 | + .pa_end = 0x4A064BFF, | ||
289 | + .flags = ADDR_MAP_ON_INIT | ||
290 | + }, | ||
291 | + { | ||
292 | + .name = "ehci", | ||
293 | + .pa_start = 0x4A064C00, | ||
294 | + .pa_end = 0x4A064FFF, | ||
295 | + .flags = ADDR_MAP_ON_INIT | ||
296 | + } | ||
297 | +}; | ||
298 | + | ||
299 | +static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_host_hs = { | ||
300 | + .master = &omap44xx_l4_cfg_hwmod, | ||
301 | + .slave = &omap44xx_usb_host_hs_hwmod, | ||
302 | + .clk = "l4_div_ck", | ||
303 | + .addr = omap44xx_usb_host_hs_addrs, | ||
304 | + .addr_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_addrs), | ||
305 | + .user = OCP_USER_MPU | OCP_USER_SDMA, | ||
306 | +}; | ||
307 | + | ||
308 | +static struct omap_hwmod_ocp_if *omap44xx_usb_host_hs_slaves[] = { | ||
309 | + &omap44xx_l4_cfg__usb_host_hs, | ||
310 | +}; | ||
311 | + | ||
312 | +static struct omap_hwmod omap44xx_usb_host_hs_hwmod = { | ||
313 | + .name = "usbhs_uhh", | ||
314 | + .class = &omap44xx_usb_host_hs_hwmod_class, | ||
315 | + .mpu_irqs = omap44xx_usb_host_hs_irqs, | ||
316 | + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_irqs), | ||
317 | + .main_clk = "usb_host_hs_fck", | ||
318 | + .prcm = { | ||
319 | + .omap4 = { | ||
320 | + .clkctrl_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL, | ||
321 | + }, | ||
322 | + }, | ||
323 | + .slaves = omap44xx_usb_host_hs_slaves, | ||
324 | + .slaves_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_slaves), | ||
325 | + .masters = omap44xx_usb_host_hs_masters, | ||
326 | + .masters_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_masters), | ||
327 | + .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY, | ||
328 | + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), | ||
329 | +}; | ||
330 | + | ||
331 | +/* | ||
332 | + * 'usb_tll_hs' class | ||
333 | + * usb_tll_hs module is the adapter on the usb_host_hs ports | ||
334 | + */ | ||
335 | +static struct omap_hwmod_class_sysconfig omap44xx_usb_tll_hs_sysc = { | ||
336 | + .rev_offs = 0x0000, | ||
337 | + .sysc_offs = 0x0010, | ||
338 | + .syss_offs = 0x0014, | ||
339 | + .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE), | ||
340 | + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), | ||
341 | + .sysc_fields = &omap_hwmod_sysc_type1, | ||
342 | +}; | ||
343 | + | ||
344 | +static struct omap_hwmod_class omap44xx_usb_tll_hs_hwmod_class = { | ||
345 | + .name = "usbhs_tll", | ||
346 | + .sysc = &omap44xx_usb_tll_hs_sysc, | ||
347 | +}; | ||
348 | + | ||
349 | +static struct omap_hwmod_irq_info omap44xx_usb_tll_hs_irqs[] = { | ||
350 | + { .name = "tll-irq", .irq = 78 + OMAP44XX_IRQ_GIC_START }, | ||
351 | +}; | ||
352 | + | ||
353 | +static struct omap_hwmod_addr_space omap44xx_usb_tll_hs_addrs[] = { | ||
354 | + { | ||
355 | + .name = "tll", | ||
356 | + .pa_start = 0x4a062000, | ||
357 | + .pa_end = 0x4a063fff, | ||
358 | + .flags = ADDR_TYPE_RT | ||
359 | + }, | ||
360 | +}; | ||
361 | + | ||
362 | +static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_tll_hs = { | ||
363 | + .master = &omap44xx_l4_cfg_hwmod, | ||
364 | + .slave = &omap44xx_usb_tll_hs_hwmod, | ||
365 | + .clk = "l4_div_ck", | ||
366 | + .addr = omap44xx_usb_tll_hs_addrs, | ||
367 | + .addr_cnt = ARRAY_SIZE(omap44xx_usb_tll_hs_addrs), | ||
368 | + .user = OCP_USER_MPU | OCP_USER_SDMA, | ||
369 | +}; | ||
370 | + | ||
371 | +static struct omap_hwmod_ocp_if *omap44xx_usb_tll_hs_slaves[] = { | ||
372 | + &omap44xx_l4_cfg__usb_tll_hs, | ||
373 | +}; | ||
374 | + | ||
375 | +static struct omap_hwmod omap44xx_usb_tll_hs_hwmod = { | ||
376 | + .name = "usbhs_tll", | ||
377 | + .class = &omap44xx_usb_tll_hs_hwmod_class, | ||
378 | + .mpu_irqs = omap44xx_usb_tll_hs_irqs, | ||
379 | + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_usb_tll_hs_irqs), | ||
380 | + .main_clk = "usb_tll_hs_ick", | ||
381 | + .prcm = { | ||
382 | + .omap4 = { | ||
383 | + .clkctrl_reg = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL, | ||
384 | + }, | ||
385 | + }, | ||
386 | + .slaves = omap44xx_usb_tll_hs_slaves, | ||
387 | + .slaves_cnt = ARRAY_SIZE(omap44xx_usb_tll_hs_slaves), | ||
388 | + .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY, | ||
389 | + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), | ||
390 | +}; | ||
391 | + | ||
392 | static __initdata struct omap_hwmod *omap44xx_hwmods[] = { | ||
393 | |||
394 | /* dmm class */ | ||
395 | @@ -5173,6 +5324,8 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { | ||
396 | &omap44xx_wd_timer2_hwmod, | ||
397 | &omap44xx_wd_timer3_hwmod, | ||
398 | |||
399 | + &omap44xx_usb_host_hs_hwmod, | ||
400 | + &omap44xx_usb_tll_hs_hwmod, | ||
401 | NULL, | ||
402 | }; | ||
403 | |||
404 | -- | ||
405 | 1.6.6.1 | ||
406 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0005-arm-omap-usb-register-hwmods-of-usbhs.patch b/recipes-kernel/linux/linux-omap-2.6.39/mfd/0005-arm-omap-usb-register-hwmods-of-usbhs.patch deleted file mode 100644 index 8e9a4ba4..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0005-arm-omap-usb-register-hwmods-of-usbhs.patch +++ /dev/null | |||
@@ -1,160 +0,0 @@ | |||
1 | From 70f5e1a0e6639710503a9ffb9008ddcd2bb3f06e Mon Sep 17 00:00:00 2001 | ||
2 | From: Keshava Munegowda <Keshava_mgowda@ti.com> | ||
3 | Date: Wed, 1 Jun 2011 11:02:54 -0700 | ||
4 | Subject: [PATCH 05/13] arm: omap: usb: register hwmods of usbhs | ||
5 | |||
6 | The hwmod structure of uhh and tll are retrived | ||
7 | and registered with omap device | ||
8 | |||
9 | Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com> | ||
10 | --- | ||
11 | arch/arm/mach-omap2/usb-host.c | 99 ++++++++++++++-------------------------- | ||
12 | 1 files changed, 35 insertions(+), 64 deletions(-) | ||
13 | |||
14 | diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c | ||
15 | index 89ae298..9d762c4 100644 | ||
16 | --- a/arch/arm/mach-omap2/usb-host.c | ||
17 | +++ b/arch/arm/mach-omap2/usb-host.c | ||
18 | @@ -28,51 +28,28 @@ | ||
19 | #include <mach/hardware.h> | ||
20 | #include <mach/irqs.h> | ||
21 | #include <plat/usb.h> | ||
22 | +#include <plat/omap_device.h> | ||
23 | |||
24 | #include "mux.h" | ||
25 | |||
26 | #ifdef CONFIG_MFD_OMAP_USB_HOST | ||
27 | |||
28 | -#define OMAP_USBHS_DEVICE "usbhs-omap" | ||
29 | - | ||
30 | -static struct resource usbhs_resources[] = { | ||
31 | - { | ||
32 | - .name = "uhh", | ||
33 | - .flags = IORESOURCE_MEM, | ||
34 | - }, | ||
35 | - { | ||
36 | - .name = "tll", | ||
37 | - .flags = IORESOURCE_MEM, | ||
38 | - }, | ||
39 | - { | ||
40 | - .name = "ehci", | ||
41 | - .flags = IORESOURCE_MEM, | ||
42 | - }, | ||
43 | - { | ||
44 | - .name = "ehci-irq", | ||
45 | - .flags = IORESOURCE_IRQ, | ||
46 | - }, | ||
47 | - { | ||
48 | - .name = "ohci", | ||
49 | - .flags = IORESOURCE_MEM, | ||
50 | - }, | ||
51 | - { | ||
52 | - .name = "ohci-irq", | ||
53 | - .flags = IORESOURCE_IRQ, | ||
54 | - } | ||
55 | -}; | ||
56 | - | ||
57 | -static struct platform_device usbhs_device = { | ||
58 | - .name = OMAP_USBHS_DEVICE, | ||
59 | - .id = 0, | ||
60 | - .num_resources = ARRAY_SIZE(usbhs_resources), | ||
61 | - .resource = usbhs_resources, | ||
62 | -}; | ||
63 | +#define OMAP_USBHS_DEVICE "usbhs_omap" | ||
64 | +#define USBHS_UHH_HWMODNAME "usbhs_uhh" | ||
65 | +#define USBHS_TLL_HWMODNAME "usbhs_tll" | ||
66 | |||
67 | static struct usbhs_omap_platform_data usbhs_data; | ||
68 | static struct ehci_hcd_omap_platform_data ehci_data; | ||
69 | static struct ohci_hcd_omap_platform_data ohci_data; | ||
70 | |||
71 | +static struct omap_device_pm_latency omap_uhhtll_latency[] = { | ||
72 | + { | ||
73 | + .deactivate_func = omap_device_idle_hwmods, | ||
74 | + .activate_func = omap_device_enable_hwmods, | ||
75 | + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, | ||
76 | + }, | ||
77 | +}; | ||
78 | + | ||
79 | /* MUX settings for EHCI pins */ | ||
80 | /* | ||
81 | * setup_ehci_io_mux - initialize IO pad mux for USBHOST | ||
82 | @@ -508,7 +485,10 @@ static void setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode) | ||
83 | |||
84 | void __init usbhs_init(const struct usbhs_omap_board_data *pdata) | ||
85 | { | ||
86 | - int i; | ||
87 | + struct omap_hwmod *oh[2]; | ||
88 | + struct omap_device *od; | ||
89 | + int bus_id = -1; | ||
90 | + int i; | ||
91 | |||
92 | for (i = 0; i < OMAP3_HS_USB_PORTS; i++) { | ||
93 | usbhs_data.port_mode[i] = pdata->port_mode[i]; | ||
94 | @@ -523,44 +503,35 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata) | ||
95 | usbhs_data.ohci_data = &ohci_data; | ||
96 | |||
97 | if (cpu_is_omap34xx()) { | ||
98 | - usbhs_resources[0].start = OMAP34XX_UHH_CONFIG_BASE; | ||
99 | - usbhs_resources[0].end = OMAP34XX_UHH_CONFIG_BASE + SZ_1K - 1; | ||
100 | - usbhs_resources[1].start = OMAP34XX_USBTLL_BASE; | ||
101 | - usbhs_resources[1].end = OMAP34XX_USBTLL_BASE + SZ_4K - 1; | ||
102 | - usbhs_resources[2].start = OMAP34XX_EHCI_BASE; | ||
103 | - usbhs_resources[2].end = OMAP34XX_EHCI_BASE + SZ_1K - 1; | ||
104 | - usbhs_resources[3].start = INT_34XX_EHCI_IRQ; | ||
105 | - usbhs_resources[4].start = OMAP34XX_OHCI_BASE; | ||
106 | - usbhs_resources[4].end = OMAP34XX_OHCI_BASE + SZ_1K - 1; | ||
107 | - usbhs_resources[5].start = INT_34XX_OHCI_IRQ; | ||
108 | setup_ehci_io_mux(pdata->port_mode); | ||
109 | setup_ohci_io_mux(pdata->port_mode); | ||
110 | } else if (cpu_is_omap44xx()) { | ||
111 | - usbhs_resources[0].start = OMAP44XX_UHH_CONFIG_BASE; | ||
112 | - usbhs_resources[0].end = OMAP44XX_UHH_CONFIG_BASE + SZ_1K - 1; | ||
113 | - usbhs_resources[1].start = OMAP44XX_USBTLL_BASE; | ||
114 | - usbhs_resources[1].end = OMAP44XX_USBTLL_BASE + SZ_4K - 1; | ||
115 | - usbhs_resources[2].start = OMAP44XX_HSUSB_EHCI_BASE; | ||
116 | - usbhs_resources[2].end = OMAP44XX_HSUSB_EHCI_BASE + SZ_1K - 1; | ||
117 | - usbhs_resources[3].start = OMAP44XX_IRQ_EHCI; | ||
118 | - usbhs_resources[4].start = OMAP44XX_HSUSB_OHCI_BASE; | ||
119 | - usbhs_resources[4].end = OMAP44XX_HSUSB_OHCI_BASE + SZ_1K - 1; | ||
120 | - usbhs_resources[5].start = OMAP44XX_IRQ_OHCI; | ||
121 | setup_4430ehci_io_mux(pdata->port_mode); | ||
122 | setup_4430ohci_io_mux(pdata->port_mode); | ||
123 | } | ||
124 | |||
125 | - if (platform_device_add_data(&usbhs_device, | ||
126 | - &usbhs_data, sizeof(usbhs_data)) < 0) { | ||
127 | - printk(KERN_ERR "USBHS platform_device_add_data failed\n"); | ||
128 | - goto init_end; | ||
129 | + oh[0] = omap_hwmod_lookup(USBHS_UHH_HWMODNAME); | ||
130 | + if (!oh[0]) { | ||
131 | + pr_err("Could not look up %s\n", USBHS_UHH_HWMODNAME); | ||
132 | + return; | ||
133 | } | ||
134 | |||
135 | - if (platform_device_register(&usbhs_device) < 0) | ||
136 | - printk(KERN_ERR "USBHS platform_device_register failed\n"); | ||
137 | + oh[1] = omap_hwmod_lookup(USBHS_TLL_HWMODNAME); | ||
138 | + if (!oh[1]) { | ||
139 | + pr_err("Could not look up %s\n", USBHS_TLL_HWMODNAME); | ||
140 | + return; | ||
141 | + } | ||
142 | |||
143 | -init_end: | ||
144 | - return; | ||
145 | + od = omap_device_build_ss(OMAP_USBHS_DEVICE, bus_id, oh, 2, | ||
146 | + (void *)&usbhs_data, sizeof(usbhs_data), | ||
147 | + omap_uhhtll_latency, | ||
148 | + ARRAY_SIZE(omap_uhhtll_latency), false); | ||
149 | + | ||
150 | + if (IS_ERR(od)) { | ||
151 | + pr_err("Could not build hwmod devices %s, %s\n", | ||
152 | + USBHS_UHH_HWMODNAME, USBHS_TLL_HWMODNAME); | ||
153 | + return; | ||
154 | + } | ||
155 | } | ||
156 | |||
157 | #else | ||
158 | -- | ||
159 | 1.6.6.1 | ||
160 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0006-arm-omap-usb-device-name-change-for-the-clk-names-of.patch b/recipes-kernel/linux/linux-omap-2.6.39/mfd/0006-arm-omap-usb-device-name-change-for-the-clk-names-of.patch deleted file mode 100644 index c0ac58bf..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0006-arm-omap-usb-device-name-change-for-the-clk-names-of.patch +++ /dev/null | |||
@@ -1,123 +0,0 @@ | |||
1 | From 64bc651bb56435e4cd86d2ebfa4f301abdbac6e5 Mon Sep 17 00:00:00 2001 | ||
2 | From: Keshava Munegowda <Keshava_mgowda@ti.com> | ||
3 | Date: Wed, 1 Jun 2011 11:02:58 -0700 | ||
4 | Subject: [PATCH 06/13] arm: omap: usb: device name change for the clk names of usbhs | ||
5 | |||
6 | device name usbhs clocks are changed from | ||
7 | usbhs-omap.0 to usbhs_omap; this is because | ||
8 | in the hwmod registration the device name is set | ||
9 | as usbhs_omap | ||
10 | |||
11 | Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com> | ||
12 | --- | ||
13 | arch/arm/mach-omap2/clock3xxx_data.c | 28 ++++++++++++++-------------- | ||
14 | arch/arm/mach-omap2/clock44xx_data.c | 10 +++++----- | ||
15 | drivers/mfd/omap-usb-host.c | 2 +- | ||
16 | 3 files changed, 20 insertions(+), 20 deletions(-) | ||
17 | |||
18 | diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c | ||
19 | index 75b119b..fabe482 100644 | ||
20 | --- a/arch/arm/mach-omap2/clock3xxx_data.c | ||
21 | +++ b/arch/arm/mach-omap2/clock3xxx_data.c | ||
22 | @@ -3285,7 +3285,7 @@ static struct omap_clk omap3xxx_clks[] = { | ||
23 | CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | ||
24 | CLK(NULL, "ts_fck", &ts_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | ||
25 | CLK(NULL, "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | ||
26 | - CLK("usbhs-omap.0", "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | ||
27 | + CLK("usbhs_omap", "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | ||
28 | CLK("omap-mcbsp.1", "prcm_fck", &core_96m_fck, CK_3XXX), | ||
29 | CLK("omap-mcbsp.5", "prcm_fck", &core_96m_fck, CK_3XXX), | ||
30 | CLK(NULL, "core_96m_fck", &core_96m_fck, CK_3XXX), | ||
31 | @@ -3321,7 +3321,7 @@ static struct omap_clk omap3xxx_clks[] = { | ||
32 | CLK(NULL, "pka_ick", &pka_ick, CK_34XX | CK_36XX), | ||
33 | CLK(NULL, "core_l4_ick", &core_l4_ick, CK_3XXX), | ||
34 | CLK(NULL, "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | ||
35 | - CLK("usbhs-omap.0", "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | ||
36 | + CLK("usbhs_omap", "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | ||
37 | CLK("omap_hsmmc.2", "ick", &mmchs3_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | ||
38 | CLK(NULL, "icr_ick", &icr_ick, CK_34XX | CK_36XX), | ||
39 | CLK("omap-aes", "ick", &aes2_ick, CK_34XX | CK_36XX), | ||
40 | @@ -3367,20 +3367,20 @@ static struct omap_clk omap3xxx_clks[] = { | ||
41 | CLK(NULL, "cam_ick", &cam_ick, CK_34XX | CK_36XX), | ||
42 | CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_34XX | CK_36XX), | ||
43 | CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | ||
44 | - CLK("usbhs-omap.0", "hs_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | ||
45 | + CLK("usbhs_omap", "hs_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | ||
46 | CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | ||
47 | - CLK("usbhs-omap.0", "fs_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | ||
48 | + CLK("usbhs_omap", "fs_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | ||
49 | CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | ||
50 | - CLK("usbhs-omap.0", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | ||
51 | - CLK("usbhs-omap.0", "utmi_p1_gfclk", &dummy_ck, CK_3XXX), | ||
52 | - CLK("usbhs-omap.0", "utmi_p2_gfclk", &dummy_ck, CK_3XXX), | ||
53 | - CLK("usbhs-omap.0", "xclk60mhsp1_ck", &dummy_ck, CK_3XXX), | ||
54 | - CLK("usbhs-omap.0", "xclk60mhsp2_ck", &dummy_ck, CK_3XXX), | ||
55 | - CLK("usbhs-omap.0", "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX), | ||
56 | - CLK("usbhs-omap.0", "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX), | ||
57 | - CLK("usbhs-omap.0", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX), | ||
58 | - CLK("usbhs-omap.0", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX), | ||
59 | - CLK("usbhs-omap.0", "init_60m_fclk", &dummy_ck, CK_3XXX), | ||
60 | + CLK("usbhs_omap", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), | ||
61 | + CLK("usbhs_omap", "utmi_p1_gfclk", &dummy_ck, CK_3XXX), | ||
62 | + CLK("usbhs_omap", "utmi_p2_gfclk", &dummy_ck, CK_3XXX), | ||
63 | + CLK("usbhs_omap", "xclk60mhsp1_ck", &dummy_ck, CK_3XXX), | ||
64 | + CLK("usbhs_omap", "xclk60mhsp2_ck", &dummy_ck, CK_3XXX), | ||
65 | + CLK("usbhs_omap", "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX), | ||
66 | + CLK("usbhs_omap", "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX), | ||
67 | + CLK("usbhs_omap", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX), | ||
68 | + CLK("usbhs_omap", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX), | ||
69 | + CLK("usbhs_omap", "init_60m_fclk", &dummy_ck, CK_3XXX), | ||
70 | CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2PLUS | CK_36XX), | ||
71 | CLK(NULL, "gpt1_fck", &gpt1_fck, CK_3XXX), | ||
72 | CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_3XXX), | ||
73 | diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c | ||
74 | index 8c96567..34e91eb 100644 | ||
75 | --- a/arch/arm/mach-omap2/clock44xx_data.c | ||
76 | +++ b/arch/arm/mach-omap2/clock44xx_data.c | ||
77 | @@ -3205,7 +3205,7 @@ static struct omap_clk omap44xx_clks[] = { | ||
78 | CLK(NULL, "uart3_fck", &uart3_fck, CK_443X), | ||
79 | CLK(NULL, "uart4_fck", &uart4_fck, CK_443X), | ||
80 | CLK(NULL, "usb_host_fs_fck", &usb_host_fs_fck, CK_443X), | ||
81 | - CLK("usbhs-omap.0", "fs_fck", &usb_host_fs_fck, CK_443X), | ||
82 | + CLK("usbhs_omap", "fs_fck", &usb_host_fs_fck, CK_443X), | ||
83 | CLK(NULL, "utmi_p1_gfclk", &utmi_p1_gfclk, CK_443X), | ||
84 | CLK(NULL, "usb_host_hs_utmi_p1_clk", &usb_host_hs_utmi_p1_clk, CK_443X), | ||
85 | CLK(NULL, "utmi_p2_gfclk", &utmi_p2_gfclk, CK_443X), | ||
86 | @@ -3217,8 +3217,8 @@ static struct omap_clk omap44xx_clks[] = { | ||
87 | CLK(NULL, "usb_host_hs_hsic480m_p2_clk", &usb_host_hs_hsic480m_p2_clk, CK_443X), | ||
88 | CLK(NULL, "usb_host_hs_func48mclk", &usb_host_hs_func48mclk, CK_443X), | ||
89 | CLK(NULL, "usb_host_hs_fck", &usb_host_hs_fck, CK_443X), | ||
90 | - CLK("usbhs-omap.0", "hs_fck", &usb_host_hs_fck, CK_443X), | ||
91 | - CLK("usbhs-omap.0", "usbhost_ick", &dummy_ck, CK_443X), | ||
92 | + CLK("usbhs_omap", "hs_fck", &usb_host_hs_fck, CK_443X), | ||
93 | + CLK("usbhs_omap", "usbhost_ick", &dummy_ck, CK_443X), | ||
94 | CLK(NULL, "otg_60m_gfclk", &otg_60m_gfclk, CK_443X), | ||
95 | CLK(NULL, "usb_otg_hs_xclk", &usb_otg_hs_xclk, CK_443X), | ||
96 | CLK("musb-omap2430", "ick", &usb_otg_hs_ick, CK_443X), | ||
97 | @@ -3227,8 +3227,8 @@ static struct omap_clk omap44xx_clks[] = { | ||
98 | CLK(NULL, "usb_tll_hs_usb_ch0_clk", &usb_tll_hs_usb_ch0_clk, CK_443X), | ||
99 | CLK(NULL, "usb_tll_hs_usb_ch1_clk", &usb_tll_hs_usb_ch1_clk, CK_443X), | ||
100 | CLK(NULL, "usb_tll_hs_ick", &usb_tll_hs_ick, CK_443X), | ||
101 | - CLK("usbhs-omap.0", "usbtll_ick", &usb_tll_hs_ick, CK_443X), | ||
102 | - CLK("usbhs-omap.0", "usbtll_fck", &dummy_ck, CK_443X), | ||
103 | + CLK("usbhs_omap", "usbtll_ick", &usb_tll_hs_ick, CK_443X), | ||
104 | + CLK("usbhs_omap", "usbtll_fck", &dummy_ck, CK_443X), | ||
105 | CLK(NULL, "usim_ck", &usim_ck, CK_443X), | ||
106 | CLK(NULL, "usim_fclk", &usim_fclk, CK_443X), | ||
107 | CLK(NULL, "usim_fck", &usim_fck, CK_443X), | ||
108 | diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c | ||
109 | index 8552195..43de12a 100644 | ||
110 | --- a/drivers/mfd/omap-usb-host.c | ||
111 | +++ b/drivers/mfd/omap-usb-host.c | ||
112 | @@ -28,7 +28,7 @@ | ||
113 | #include <plat/usb.h> | ||
114 | #include <linux/pm_runtime.h> | ||
115 | |||
116 | -#define USBHS_DRIVER_NAME "usbhs-omap" | ||
117 | +#define USBHS_DRIVER_NAME "usbhs_omap" | ||
118 | #define OMAP_EHCI_DEVICE "ehci-omap" | ||
119 | #define OMAP_OHCI_DEVICE "ohci-omap3" | ||
120 | |||
121 | -- | ||
122 | 1.6.6.1 | ||
123 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0007-mfd-global-Suspend-and-resume-support-of-ehci-and-oh.patch b/recipes-kernel/linux/linux-omap-2.6.39/mfd/0007-mfd-global-Suspend-and-resume-support-of-ehci-and-oh.patch deleted file mode 100644 index 94d5f591..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0007-mfd-global-Suspend-and-resume-support-of-ehci-and-oh.patch +++ /dev/null | |||
@@ -1,165 +0,0 @@ | |||
1 | From bf583f2924fd9b2f0356cbd0bbfd58c48d98ef15 Mon Sep 17 00:00:00 2001 | ||
2 | From: Keshava Munegowda <Keshava_mgowda@ti.com> | ||
3 | Date: Wed, 1 Jun 2011 11:03:03 -0700 | ||
4 | Subject: [PATCH 07/13] mfd: global Suspend and resume support of ehci and ohci | ||
5 | |||
6 | The global suspend and resume functions for usbhs core driver | ||
7 | are implemented.These routine are called when the global suspend | ||
8 | and resume occurs. Before calling these functions, the | ||
9 | bus suspend and resume of ehci and ohci drivers are called | ||
10 | from runtime pm. | ||
11 | |||
12 | Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com> | ||
13 | --- | ||
14 | drivers/mfd/omap-usb-host.c | 103 +++++++++++++++++++++++++++++++++++++++++++ | ||
15 | 1 files changed, 103 insertions(+), 0 deletions(-) | ||
16 | |||
17 | diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c | ||
18 | index 43de12a..32d19e2 100644 | ||
19 | --- a/drivers/mfd/omap-usb-host.c | ||
20 | +++ b/drivers/mfd/omap-usb-host.c | ||
21 | @@ -146,6 +146,10 @@ | ||
22 | #define is_ehci_hsic_mode(x) (x == OMAP_EHCI_PORT_MODE_HSIC) | ||
23 | |||
24 | |||
25 | +/* USBHS state bits */ | ||
26 | +#define OMAP_USBHS_INIT 0 | ||
27 | +#define OMAP_USBHS_SUSPEND 4 | ||
28 | + | ||
29 | struct usbhs_hcd_omap { | ||
30 | struct clk *xclk60mhsp1_ck; | ||
31 | struct clk *xclk60mhsp2_ck; | ||
32 | @@ -165,6 +169,7 @@ struct usbhs_hcd_omap { | ||
33 | u32 usbhs_rev; | ||
34 | spinlock_t lock; | ||
35 | int count; | ||
36 | + unsigned long state; | ||
37 | }; | ||
38 | /*-------------------------------------------------------------------------*/ | ||
39 | |||
40 | @@ -809,6 +814,8 @@ static int usbhs_enable(struct device *dev) | ||
41 | (pdata->ehci_data->reset_gpio_port[1], 1); | ||
42 | } | ||
43 | |||
44 | + set_bit(OMAP_USBHS_INIT, &omap->state); | ||
45 | + | ||
46 | end_count: | ||
47 | omap->count++; | ||
48 | spin_unlock_irqrestore(&omap->lock, flags); | ||
49 | @@ -897,6 +904,7 @@ static void usbhs_disable(struct device *dev) | ||
50 | } | ||
51 | |||
52 | pm_runtime_put_sync(dev); | ||
53 | + clear_bit(OMAP_USBHS_INIT, &omap->state); | ||
54 | |||
55 | /* The gpio_free migh sleep; so unlock the spinlock */ | ||
56 | spin_unlock_irqrestore(&omap->lock, flags); | ||
57 | @@ -926,10 +934,105 @@ void omap_usbhs_disable(struct device *dev) | ||
58 | } | ||
59 | EXPORT_SYMBOL_GPL(omap_usbhs_disable); | ||
60 | |||
61 | +#ifdef CONFIG_PM | ||
62 | + | ||
63 | +static int usbhs_resume(struct device *dev) | ||
64 | +{ | ||
65 | + struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); | ||
66 | + struct usbhs_omap_platform_data *pdata = &omap->platdata; | ||
67 | + unsigned long flags = 0; | ||
68 | + | ||
69 | + dev_dbg(dev, "Resuming TI HSUSB Controller\n"); | ||
70 | + | ||
71 | + if (!pdata) { | ||
72 | + dev_dbg(dev, "missing platform_data\n"); | ||
73 | + return -ENODEV; | ||
74 | + } | ||
75 | + | ||
76 | + spin_lock_irqsave(&omap->lock, flags); | ||
77 | + | ||
78 | + if (!test_bit(OMAP_USBHS_INIT, &omap->state) || | ||
79 | + !test_bit(OMAP_USBHS_SUSPEND, &omap->state)) | ||
80 | + goto end_resume; | ||
81 | + | ||
82 | + pm_runtime_get_sync(dev); | ||
83 | + | ||
84 | + if (is_omap_usbhs_rev2(omap)) { | ||
85 | + if (is_ehci_tll_mode(pdata->port_mode[0])) { | ||
86 | + clk_enable(omap->usbhost_p1_fck); | ||
87 | + clk_enable(omap->usbtll_p1_fck); | ||
88 | + } | ||
89 | + if (is_ehci_tll_mode(pdata->port_mode[1])) { | ||
90 | + clk_enable(omap->usbhost_p2_fck); | ||
91 | + clk_enable(omap->usbtll_p2_fck); | ||
92 | + } | ||
93 | + clk_enable(omap->utmi_p1_fck); | ||
94 | + clk_enable(omap->utmi_p2_fck); | ||
95 | + } | ||
96 | + clear_bit(OMAP_USBHS_SUSPEND, &omap->state); | ||
97 | + | ||
98 | +end_resume: | ||
99 | + spin_unlock_irqrestore(&omap->lock, flags); | ||
100 | + return 0; | ||
101 | +} | ||
102 | + | ||
103 | + | ||
104 | +static int usbhs_suspend(struct device *dev) | ||
105 | +{ | ||
106 | + struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); | ||
107 | + struct usbhs_omap_platform_data *pdata = &omap->platdata; | ||
108 | + unsigned long flags = 0; | ||
109 | + | ||
110 | + dev_dbg(dev, "Suspending TI HSUSB Controller\n"); | ||
111 | + | ||
112 | + if (!pdata) { | ||
113 | + dev_dbg(dev, "missing platform_data\n"); | ||
114 | + return -ENODEV; | ||
115 | + } | ||
116 | + | ||
117 | + spin_lock_irqsave(&omap->lock, flags); | ||
118 | + | ||
119 | + if (!test_bit(OMAP_USBHS_INIT, &omap->state) || | ||
120 | + test_bit(OMAP_USBHS_SUSPEND, &omap->state)) | ||
121 | + goto end_suspend; | ||
122 | + | ||
123 | + if (is_omap_usbhs_rev2(omap)) { | ||
124 | + if (is_ehci_tll_mode(pdata->port_mode[0])) { | ||
125 | + clk_disable(omap->usbhost_p1_fck); | ||
126 | + clk_disable(omap->usbtll_p1_fck); | ||
127 | + } | ||
128 | + if (is_ehci_tll_mode(pdata->port_mode[1])) { | ||
129 | + clk_disable(omap->usbhost_p2_fck); | ||
130 | + clk_disable(omap->usbtll_p2_fck); | ||
131 | + } | ||
132 | + clk_disable(omap->utmi_p2_fck); | ||
133 | + clk_disable(omap->utmi_p1_fck); | ||
134 | + } | ||
135 | + | ||
136 | + set_bit(OMAP_USBHS_SUSPEND, &omap->state); | ||
137 | + pm_runtime_put_sync(dev); | ||
138 | + | ||
139 | +end_suspend: | ||
140 | + spin_unlock_irqrestore(&omap->lock, flags); | ||
141 | + return 0; | ||
142 | +} | ||
143 | + | ||
144 | + | ||
145 | +static const struct dev_pm_ops usbhsomap_dev_pm_ops = { | ||
146 | + .suspend = usbhs_suspend, | ||
147 | + .resume = usbhs_resume, | ||
148 | +}; | ||
149 | + | ||
150 | +#define USBHS_OMAP_DEV_PM_OPS (&usbhsomap_dev_pm_ops) | ||
151 | +#else | ||
152 | +#define USBHS_OMAP_DEV_PM_OPS NULL | ||
153 | +#endif | ||
154 | + | ||
155 | static struct platform_driver usbhs_omap_driver = { | ||
156 | .driver = { | ||
157 | .name = (char *)usbhs_driver_name, | ||
158 | .owner = THIS_MODULE, | ||
159 | + .pm = USBHS_OMAP_DEV_PM_OPS, | ||
160 | }, | ||
161 | .remove = __exit_p(usbhs_omap_remove), | ||
162 | }; | ||
163 | -- | ||
164 | 1.6.6.1 | ||
165 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0008-MFD-TWL4030-Correct-the-warning-print-during-script-.patch b/recipes-kernel/linux/linux-omap-2.6.39/mfd/0008-MFD-TWL4030-Correct-the-warning-print-during-script-.patch deleted file mode 100644 index e3de4672..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0008-MFD-TWL4030-Correct-the-warning-print-during-script-.patch +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | From 1f2e639755b920398d6592775e0e31f7fb1ca955 Mon Sep 17 00:00:00 2001 | ||
2 | From: Lesly A M <leslyam@ti.com> | ||
3 | Date: Wed, 1 Jun 2011 14:56:38 -0700 | ||
4 | Subject: [PATCH 08/13] MFD: TWL4030: Correct the warning print during script loading | ||
5 | |||
6 | Correcting the if condition check for printing the warning, | ||
7 | if wakeup script is not updated before updating the sleep script. | ||
8 | |||
9 | Since the flag 'order' is set to '1' while updating the wakeup script for P1P2, | ||
10 | the condition checking for printing the warning should be if(!order) | ||
11 | (ie: print the warning if wakeup script is not updated before updating the sleep script) | ||
12 | |||
13 | Signed-off-by: Lesly A M <leslyam@ti.com> | ||
14 | Cc: Nishanth Menon <nm@ti.com> | ||
15 | Cc: David Derrick <dderrick@ti.com> | ||
16 | Cc: Samuel Ortiz <sameo@linux.intel.com> | ||
17 | --- | ||
18 | drivers/mfd/twl4030-power.c | 2 +- | ||
19 | 1 files changed, 1 insertions(+), 1 deletions(-) | ||
20 | |||
21 | diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c | ||
22 | index 2c0d4d1..8373d79 100644 | ||
23 | --- a/drivers/mfd/twl4030-power.c | ||
24 | +++ b/drivers/mfd/twl4030-power.c | ||
25 | @@ -448,7 +448,7 @@ static int __init load_twl4030_script(struct twl4030_script *tscript, | ||
26 | goto out; | ||
27 | } | ||
28 | if (tscript->flags & TWL4030_SLEEP_SCRIPT) { | ||
29 | - if (order) | ||
30 | + if (!order) | ||
31 | pr_warning("TWL4030: Bad order of scripts (sleep "\ | ||
32 | "script before wakeup) Leads to boot"\ | ||
33 | "failure on some boards\n"); | ||
34 | -- | ||
35 | 1.6.6.1 | ||
36 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0009-MFD-TWL4030-Modifying-the-macro-name-Main_Ref-to-all.patch b/recipes-kernel/linux/linux-omap-2.6.39/mfd/0009-MFD-TWL4030-Modifying-the-macro-name-Main_Ref-to-all.patch deleted file mode 100644 index 6be454aa..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0009-MFD-TWL4030-Modifying-the-macro-name-Main_Ref-to-all.patch +++ /dev/null | |||
@@ -1,61 +0,0 @@ | |||
1 | From ea9acebfe2d3ca8fb3969eaf327665632142b85d Mon Sep 17 00:00:00 2001 | ||
2 | From: Lesly A M <leslyam@ti.com> | ||
3 | Date: Wed, 1 Jun 2011 14:56:45 -0700 | ||
4 | Subject: [PATCH 09/13] MFD: TWL4030: Modifying the macro name Main_Ref to all caps | ||
5 | |||
6 | Modifying the macro name Main_Ref to all caps(MAIN_REF). | ||
7 | |||
8 | Suggested by Nishanth Menon <nm@ti.com> | ||
9 | |||
10 | Signed-off-by: Lesly A M <leslyam@ti.com> | ||
11 | Cc: Nishanth Menon <nm@ti.com> | ||
12 | Cc: David Derrick <dderrick@ti.com> | ||
13 | Cc: Samuel Ortiz <sameo@linux.intel.com> | ||
14 | --- | ||
15 | arch/arm/mach-omap2/board-rx51-peripherals.c | 2 +- | ||
16 | drivers/mfd/twl4030-power.c | 2 +- | ||
17 | include/linux/i2c/twl.h | 2 +- | ||
18 | 3 files changed, 3 insertions(+), 3 deletions(-) | ||
19 | |||
20 | diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c | ||
21 | index bbcb677..01ee0a1 100644 | ||
22 | --- a/arch/arm/mach-omap2/board-rx51-peripherals.c | ||
23 | +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c | ||
24 | @@ -730,7 +730,7 @@ static struct twl4030_resconfig twl4030_rconfig[] __initdata = { | ||
25 | { .resource = RES_RESET, .devgroup = -1, | ||
26 | .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 | ||
27 | }, | ||
28 | - { .resource = RES_Main_Ref, .devgroup = -1, | ||
29 | + { .resource = RES_MAIN_REF, .devgroup = -1, | ||
30 | .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 | ||
31 | }, | ||
32 | { 0, 0}, | ||
33 | diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c | ||
34 | index 8373d79..8162e43 100644 | ||
35 | --- a/drivers/mfd/twl4030-power.c | ||
36 | +++ b/drivers/mfd/twl4030-power.c | ||
37 | @@ -120,7 +120,7 @@ static u8 res_config_addrs[] = { | ||
38 | [RES_HFCLKOUT] = 0x8b, | ||
39 | [RES_32KCLKOUT] = 0x8e, | ||
40 | [RES_RESET] = 0x91, | ||
41 | - [RES_Main_Ref] = 0x94, | ||
42 | + [RES_MAIN_REF] = 0x94, | ||
43 | }; | ||
44 | |||
45 | static int __init twl4030_write_script_byte(u8 address, u8 byte) | ||
46 | diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h | ||
47 | index cbbf3b3..aee3a22 100644 | ||
48 | --- a/include/linux/i2c/twl.h | ||
49 | +++ b/include/linux/i2c/twl.h | ||
50 | @@ -502,7 +502,7 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot) | ||
51 | #define RES_32KCLKOUT 26 | ||
52 | #define RES_RESET 27 | ||
53 | /* Power Reference */ | ||
54 | -#define RES_Main_Ref 28 | ||
55 | +#define RES_MAIN_REF 28 | ||
56 | |||
57 | #define TOTAL_RESOURCES 28 | ||
58 | /* | ||
59 | -- | ||
60 | 1.6.6.1 | ||
61 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0010-MFD-TWL4030-power-scripts-for-OMAP3-boards.patch b/recipes-kernel/linux/linux-omap-2.6.39/mfd/0010-MFD-TWL4030-power-scripts-for-OMAP3-boards.patch deleted file mode 100644 index 84e1ae7e..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0010-MFD-TWL4030-power-scripts-for-OMAP3-boards.patch +++ /dev/null | |||
@@ -1,705 +0,0 @@ | |||
1 | From 0b29e1f61b85dd2d04f035088b70dc287d15b9f0 Mon Sep 17 00:00:00 2001 | ||
2 | From: Lesly A M <leslyam@ti.com> | ||
3 | Date: Wed, 1 Jun 2011 14:56:49 -0700 | ||
4 | Subject: [PATCH 10/13] MFD: TWL4030: power scripts for OMAP3 boards | ||
5 | |||
6 | Power bus message sequence for TWL4030 to enter sleep/wakeup/warm_reset. | ||
7 | |||
8 | TWL4030 power scripts which can be used by different OMAP3 boards | ||
9 | with the power companion chip (TWL4030 series). | ||
10 | |||
11 | The twl4030 generic script can be used by any board file to update | ||
12 | the power data in twl4030_platform_data. | ||
13 | |||
14 | Since the TWL4030 power script has dependency with APIs in twl4030-power.c | ||
15 | removing the __init for these APIs. | ||
16 | |||
17 | For more information please see: | ||
18 | http://omapedia.org/wiki/TWL4030_power_scripts | ||
19 | |||
20 | Signed-off-by: Lesly A M <leslyam@ti.com> | ||
21 | Cc: Nishanth Menon <nm@ti.com> | ||
22 | Cc: David Derrick <dderrick@ti.com> | ||
23 | Cc: Samuel Ortiz <sameo@linux.intel.com> | ||
24 | --- | ||
25 | arch/arm/configs/omap2plus_defconfig | 1 + | ||
26 | arch/arm/mach-omap2/devices.c | 15 ++ | ||
27 | drivers/mfd/Kconfig | 11 + | ||
28 | drivers/mfd/Makefile | 1 + | ||
29 | drivers/mfd/twl4030-power.c | 31 ++-- | ||
30 | drivers/mfd/twl4030-script-omap.c | 373 ++++++++++++++++++++++++++++++++++ | ||
31 | include/linux/i2c/twl.h | 41 ++++- | ||
32 | 7 files changed, 454 insertions(+), 19 deletions(-) | ||
33 | create mode 100644 drivers/mfd/twl4030-script-omap.c | ||
34 | |||
35 | diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig | ||
36 | index 076db52..d9b9858 100644 | ||
37 | --- a/arch/arm/configs/omap2plus_defconfig | ||
38 | +++ b/arch/arm/configs/omap2plus_defconfig | ||
39 | @@ -184,6 +184,7 @@ CONFIG_TWL4030_WATCHDOG=y | ||
40 | CONFIG_MENELAUS=y | ||
41 | CONFIG_TWL4030_CORE=y | ||
42 | CONFIG_TWL4030_POWER=y | ||
43 | +CONFIG_TWL4030_SCRIPT=m | ||
44 | CONFIG_REGULATOR=y | ||
45 | CONFIG_REGULATOR_TWL4030=y | ||
46 | CONFIG_REGULATOR_TPS65023=y | ||
47 | diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c | ||
48 | index 7b85585..7653329 100644 | ||
49 | --- a/arch/arm/mach-omap2/devices.c | ||
50 | +++ b/arch/arm/mach-omap2/devices.c | ||
51 | @@ -329,6 +329,20 @@ static void omap_init_audio(void) | ||
52 | static inline void omap_init_audio(void) {} | ||
53 | #endif | ||
54 | |||
55 | +#ifdef CONFIG_ARCH_OMAP3 | ||
56 | +static struct platform_device omap_twl4030_script = { | ||
57 | + .name = "twl4030_script", | ||
58 | + .id = -1, | ||
59 | +}; | ||
60 | + | ||
61 | +static void omap_init_twl4030_script(void) | ||
62 | +{ | ||
63 | + platform_device_register(&omap_twl4030_script); | ||
64 | +} | ||
65 | +#else | ||
66 | +static inline void omap_init_twl4030_script(void) {} | ||
67 | +#endif | ||
68 | + | ||
69 | #if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE) | ||
70 | |||
71 | #include <plat/mcspi.h> | ||
72 | @@ -691,6 +705,7 @@ static int __init omap2_init_devices(void) | ||
73 | omap_init_sham(); | ||
74 | omap_init_aes(); | ||
75 | omap_init_vout(); | ||
76 | + omap_init_twl4030_script(); | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig | ||
81 | index fe2370a..ea25d93 100644 | ||
82 | --- a/drivers/mfd/Kconfig | ||
83 | +++ b/drivers/mfd/Kconfig | ||
84 | @@ -204,6 +204,17 @@ config TWL4030_POWER | ||
85 | and load scripts controlling which resources are switched off/on | ||
86 | or reset when a sleep, wakeup or warm reset event occurs. | ||
87 | |||
88 | +config TWL4030_SCRIPT | ||
89 | + tristate "Support TWL4030 script for OMAP3 boards" | ||
90 | + depends on TWL4030_CORE && TWL4030_POWER | ||
91 | + help | ||
92 | + Say yes here if you want to use the twl4030 power scripts | ||
93 | + for OMAP3 boards. Power bus message sequence for | ||
94 | + TWL4030 to enter sleep/wakeup/warm_reset. | ||
95 | + | ||
96 | + TWL4030 power scripts which can be used by different | ||
97 | + OMAP3 boards with the power companion chip (TWL4030 series). | ||
98 | + | ||
99 | config TWL4030_CODEC | ||
100 | bool | ||
101 | depends on TWL4030_CORE | ||
102 | diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile | ||
103 | index 419caa9..53ada21 100644 | ||
104 | --- a/drivers/mfd/Makefile | ||
105 | +++ b/drivers/mfd/Makefile | ||
106 | @@ -42,6 +42,7 @@ obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o | ||
107 | obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o | ||
108 | obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o | ||
109 | obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o | ||
110 | +obj-$(CONFIG_TWL4030_SCRIPT) += twl4030-script-omap.o | ||
111 | |||
112 | obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o | ||
113 | |||
114 | diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c | ||
115 | index 8162e43..91d5bc8 100644 | ||
116 | --- a/drivers/mfd/twl4030-power.c | ||
117 | +++ b/drivers/mfd/twl4030-power.c | ||
118 | @@ -123,7 +123,7 @@ static u8 res_config_addrs[] = { | ||
119 | [RES_MAIN_REF] = 0x94, | ||
120 | }; | ||
121 | |||
122 | -static int __init twl4030_write_script_byte(u8 address, u8 byte) | ||
123 | +static int twl4030_write_script_byte(u8 address, u8 byte) | ||
124 | { | ||
125 | int err; | ||
126 | |||
127 | @@ -137,7 +137,7 @@ out: | ||
128 | return err; | ||
129 | } | ||
130 | |||
131 | -static int __init twl4030_write_script_ins(u8 address, u16 pmb_message, | ||
132 | +static int twl4030_write_script_ins(u8 address, u16 pmb_message, | ||
133 | u8 delay, u8 next) | ||
134 | { | ||
135 | int err; | ||
136 | @@ -157,7 +157,7 @@ out: | ||
137 | return err; | ||
138 | } | ||
139 | |||
140 | -static int __init twl4030_write_script(u8 address, struct twl4030_ins *script, | ||
141 | +static int twl4030_write_script(u8 address, struct twl4030_ins *script, | ||
142 | int len) | ||
143 | { | ||
144 | int err; | ||
145 | @@ -182,7 +182,7 @@ static int __init twl4030_write_script(u8 address, struct twl4030_ins *script, | ||
146 | return err; | ||
147 | } | ||
148 | |||
149 | -static int __init twl4030_config_wakeup3_sequence(u8 address) | ||
150 | +static int twl4030_config_wakeup3_sequence(u8 address) | ||
151 | { | ||
152 | int err; | ||
153 | u8 data; | ||
154 | @@ -207,7 +207,7 @@ out: | ||
155 | return err; | ||
156 | } | ||
157 | |||
158 | -static int __init twl4030_config_wakeup12_sequence(u8 address) | ||
159 | +static int twl4030_config_wakeup12_sequence(u8 address) | ||
160 | { | ||
161 | int err = 0; | ||
162 | u8 data; | ||
163 | @@ -261,7 +261,7 @@ out: | ||
164 | return err; | ||
165 | } | ||
166 | |||
167 | -static int __init twl4030_config_sleep_sequence(u8 address) | ||
168 | +static int twl4030_config_sleep_sequence(u8 address) | ||
169 | { | ||
170 | int err; | ||
171 | |||
172 | @@ -275,7 +275,7 @@ static int __init twl4030_config_sleep_sequence(u8 address) | ||
173 | return err; | ||
174 | } | ||
175 | |||
176 | -static int __init twl4030_config_warmreset_sequence(u8 address) | ||
177 | +static int twl4030_config_warmreset_sequence(u8 address) | ||
178 | { | ||
179 | int err; | ||
180 | u8 rd_data; | ||
181 | @@ -323,7 +323,7 @@ out: | ||
182 | return err; | ||
183 | } | ||
184 | |||
185 | -static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig) | ||
186 | +static int twl4030_configure_resource(struct twl4030_resconfig *rconfig) | ||
187 | { | ||
188 | int rconfig_addr; | ||
189 | int err; | ||
190 | @@ -415,7 +415,7 @@ static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig) | ||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | -static int __init load_twl4030_script(struct twl4030_script *tscript, | ||
195 | +static int load_twl4030_script(struct twl4030_script *tscript, | ||
196 | u8 address) | ||
197 | { | ||
198 | int err; | ||
199 | @@ -510,8 +510,9 @@ int twl4030_remove_script(u8 flags) | ||
200 | |||
201 | return err; | ||
202 | } | ||
203 | +EXPORT_SYMBOL_GPL(twl4030_remove_script); | ||
204 | |||
205 | -void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) | ||
206 | +int twl4030_power_init(struct twl4030_power_data *twl4030_scripts) | ||
207 | { | ||
208 | int err = 0; | ||
209 | int i; | ||
210 | @@ -529,7 +530,6 @@ void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) | ||
211 | TWL4030_PM_MASTER_PROTECT_KEY); | ||
212 | if (err) | ||
213 | goto unlock; | ||
214 | - | ||
215 | for (i = 0; i < twl4030_scripts->num; i++) { | ||
216 | err = load_twl4030_script(twl4030_scripts->scripts[i], address); | ||
217 | if (err) | ||
218 | @@ -552,18 +552,19 @@ void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) | ||
219 | TWL4030_PM_MASTER_PROTECT_KEY); | ||
220 | if (err) | ||
221 | pr_err("TWL4030 Unable to relock registers\n"); | ||
222 | - return; | ||
223 | + return err; | ||
224 | |||
225 | unlock: | ||
226 | if (err) | ||
227 | pr_err("TWL4030 Unable to unlock registers\n"); | ||
228 | - return; | ||
229 | + return err; | ||
230 | load: | ||
231 | if (err) | ||
232 | pr_err("TWL4030 failed to load scripts\n"); | ||
233 | - return; | ||
234 | + return err; | ||
235 | resource: | ||
236 | if (err) | ||
237 | pr_err("TWL4030 failed to configure resource\n"); | ||
238 | - return; | ||
239 | + return err; | ||
240 | } | ||
241 | +EXPORT_SYMBOL_GPL(twl4030_power_init); | ||
242 | diff --git a/drivers/mfd/twl4030-script-omap.c b/drivers/mfd/twl4030-script-omap.c | ||
243 | new file mode 100644 | ||
244 | index 0000000..867a442 | ||
245 | --- /dev/null | ||
246 | +++ b/drivers/mfd/twl4030-script-omap.c | ||
247 | @@ -0,0 +1,373 @@ | ||
248 | +/* | ||
249 | + * OMAP power script for PMIC TWL4030 | ||
250 | + * | ||
251 | + * Author: Lesly A M <leslyam@ti.com> | ||
252 | + * | ||
253 | + * Copyright (C) 2010 Texas Instruments, Inc. | ||
254 | + * Lesly A M <leslyam@ti.com> | ||
255 | + * | ||
256 | + * This program is free software; you can redistribute it and/or modify | ||
257 | + * it under the terms of the GNU General Public License version 2 as | ||
258 | + * published by the Free Software Foundation. | ||
259 | + */ | ||
260 | + | ||
261 | +#include <linux/kernel.h> | ||
262 | +#include <linux/module.h> | ||
263 | +#include <linux/platform_device.h> | ||
264 | + | ||
265 | +#include <linux/i2c/twl.h> | ||
266 | + | ||
267 | +/* | ||
268 | + * power management signal connections for OMAP3430 with TWL5030 | ||
269 | + * | ||
270 | + * TWL5030 OMAP3430 | ||
271 | + * ______________________ _____________________ | ||
272 | + * | | | | | ||
273 | + * | (P1) NSLEEP1|<----------|SYS_OFFMODE | | ||
274 | + * | NRESWARM|<----------|NWARMRESET | | ||
275 | + * | (P2) NSLEEP2|---| | | | ||
276 | + * | | === | | | ||
277 | + * | | - | | | ||
278 | + * | | | | | ||
279 | + * | VDD1 |---------->| VDD1 | | ||
280 | + * | VDD2 |---------->| VDD2 | | ||
281 | + * | VIO |---------->| VDDS | | ||
282 | + * ________ | VAUX1 | | | | ||
283 | + * | | | ... | | | | ||
284 | + * | ENABLE|<--------|CLKEN CLKREQ|<----------|SYS_CLKREQ | | ||
285 | + * | CLKOUT|-------->|HFCLKIN (P3) HFCLKOUT|---------->|XTALIN | | ||
286 | + * |________| |______________________| |_____________________| | ||
287 | + * | ||
288 | + * | ||
289 | + * Signal descriptions: | ||
290 | + * | ||
291 | + * SYS_OFFMODE - OMAP drives this signal low only when the OMAP is in the | ||
292 | + * OFF idle mode. It is driven high when a wake up event is detected. | ||
293 | + * This signal should control the P1 device group in the PMIC. | ||
294 | + * | ||
295 | + * SYS_CLKREQ - OMAP should drive this signal low when the OMAP goes into | ||
296 | + * any idle mode. This signal should control the P3 device group | ||
297 | + * in the PMIC. It is used to notify PMIC when XTALIN is no longer needed. | ||
298 | + * | ||
299 | + * NSLEEP1(P1) - When this signal goes low the P1 sleep sequence is executed | ||
300 | + * in the PMIC turning off certain resources. When this signal goes high | ||
301 | + * the P1 active sequence is executed turning back on certain resources. | ||
302 | + * | ||
303 | + * NSLEEP2(P2) - This signal controls the P2 device group of the PMIC. | ||
304 | + * It is not used in this setup and should be tied to ground. | ||
305 | + * This can be used for connecting a different processor or MODEM chip. | ||
306 | + * | ||
307 | + * CLKREQ(P3) - When this signal goes low the P3 sleep sequence is executed | ||
308 | + * in the PMIC turning off HFCLKOUT. When this signal goes high | ||
309 | + * the P3 active sequence is executed turning back on HFCLKOUT and other | ||
310 | + * resources. | ||
311 | + * | ||
312 | + * CLKEN - Enable signal for oscillator. Should only go low when OMAP is | ||
313 | + * in the OFF idle mode due to long oscillator startup times. | ||
314 | + * | ||
315 | + * HFCLKIN - Oscillator output clock into PMIC. | ||
316 | + * | ||
317 | + * HFCLKOUT - System clock output from PMIC to OMAP. | ||
318 | + * | ||
319 | + * XTALIN - OMAP system clock input(HFCLKOUT). | ||
320 | + */ | ||
321 | + | ||
322 | +/* | ||
323 | + * Recommended sleep and active sequences for TWL5030 when connected to OMAP3 | ||
324 | + * | ||
325 | + * WARNING: If the board is using NSLEEP2(P2), should modify this script and | ||
326 | + * setuptime values accordingly. | ||
327 | + * | ||
328 | + * Chip Retention/Off (using i2c for scaling voltage): | ||
329 | + * When OMAP de-assert the SYS_CLKREQ signal, only HFCLKOUT is affected | ||
330 | + * since it is the only resource assigned to P3 only. | ||
331 | + * | ||
332 | + * Sysoff (using sys_off signal): | ||
333 | + * When OMAP de-assert the SYS_OFFMODE signal A2S(active to sleep sequence) | ||
334 | + * on the PMIC is executed. This will put resources of TYPE2=1 and TYPE2=2 | ||
335 | + * into sleep. At this point only resources assigned to P1 only will be | ||
336 | + * affected (VDD1, VDD2 & VPLL1). | ||
337 | + * | ||
338 | + * Next the OMAP will lower SYS_CLKREQ which will allow the A2S sequence | ||
339 | + * in PMIC to execute again. This will put resources of TYPE2=1 and TYPE2=2 | ||
340 | + * into sleep but will affect resources that are assigned to P3(HFCLKOUT) | ||
341 | + * only or assigned to P1 and P3. | ||
342 | + * | ||
343 | + * On wakeup event OMAP goes active and pulls the SYS_CLKREQ high, | ||
344 | + * which will execute the P3 S2A sequence on the PMIC. This will turn on | ||
345 | + * resources assigned to P3 or assigned to P1 and P3 and of TYPE2=2. | ||
346 | + * | ||
347 | + * Next the OMAP will wait the PRM_VOLTOFFSET time and then de-assert | ||
348 | + * the SYS_OFFMODE pin allowing the PMIC to execute the P1 S2A active | ||
349 | + * sequence. This will turn on resources assigned to P1 or assigned to | ||
350 | + * P1 and P3 and of TYPE2=1. | ||
351 | + * | ||
352 | + * Timing diagram for OMAP wakeup from OFFMODE using sys_off signal | ||
353 | + * _____________________________________________________________ | ||
354 | + * OMAP active __/ | ||
355 | + * |<--------------------PRM_CLKSETP-------------------->| | ||
356 | + * ______________________________________________________ | ||
357 | + * SYS_CLKREQ _________/ | ||
358 | + * ___________________________________________________ | ||
359 | + * CLKEN ____________/ | ||
360 | + * | ||
361 | + * HFCLKIN _______________________________________________///////////////// | ||
362 | + * | ||
363 | + * HFCLKOUT __________________________________________________////////////// | ||
364 | + * |<---PRM_VOLTOFFSET-->| | ||
365 | + * ________________________________ | ||
366 | + * SYS_OFFMODE _______________________________/ | ||
367 | + * |<--------PRM_VOLTSETUP2------->| | ||
368 | + * ___________ | ||
369 | + * VPLL1 ____________________________________________________/ | ||
370 | + * __ | ||
371 | + * VDD1 _____________________________________________________________/ | ||
372 | + * __ | ||
373 | + * VDD2 _____________________________________________________________/ | ||
374 | + * | ||
375 | + * Other resources which are not handled by this script should be | ||
376 | + * controlled by the respective drivers using them (VAUX1, VAUX2, VAUX3, | ||
377 | + * VAUX4, VMMC1, VMMC2, VPLL2, VSIM, VDAC, VUSB1V5, VUSB1V8 & VUSB3V1). | ||
378 | + * | ||
379 | + * More info: | ||
380 | + * http://omapedia.org/wiki/TWL4030_power_scripts | ||
381 | + */ | ||
382 | + | ||
383 | +/** | ||
384 | + * DOC: Sleep to active sequence for P1/P2 | ||
385 | + * | ||
386 | + * Sequence to control the TWL4030 Power resources, | ||
387 | + * when the system wakeup from sleep. | ||
388 | + * Executed upon P1_P2 transition for wakeup | ||
389 | + * (sys_offmode signal de-asserted on OMAP). | ||
390 | + */ | ||
391 | +static struct twl4030_ins wakeup_p12_seq[] __initdata = { | ||
392 | + /* | ||
393 | + * Broadcast message to put resources to active | ||
394 | + * | ||
395 | + * Since we are not using TYPE, resources which have TYPE2 configured | ||
396 | + * as 1 will be targeted (VPLL1, VDD1, VDD2, REGEN, NRES_PWRON, SYSEN). | ||
397 | + */ | ||
398 | + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1, | ||
399 | + RES_STATE_ACTIVE), 2}, | ||
400 | +}; | ||
401 | + | ||
402 | +static struct twl4030_script wakeup_p12_script __initdata = { | ||
403 | + .script = wakeup_p12_seq, | ||
404 | + .size = ARRAY_SIZE(wakeup_p12_seq), | ||
405 | + .flags = TWL4030_WAKEUP12_SCRIPT, | ||
406 | +}; | ||
407 | + | ||
408 | +/** | ||
409 | + * DOC: Sleep to active sequence for P3 | ||
410 | + * | ||
411 | + * Sequence to control the TWL4030 Power resources, | ||
412 | + * when the system wakeup from sleep. | ||
413 | + * Executed upon P3 transition for wakeup | ||
414 | + * (clkreq signal asserted on OMAP). | ||
415 | + */ | ||
416 | +static struct twl4030_ins wakeup_p3_seq[] __initdata = { | ||
417 | + /* | ||
418 | + * Broadcast message to put resources to active | ||
419 | + * | ||
420 | + * Since we are not using TYPE, resources which have TYPE2 configured | ||
421 | + * as 2 will be targeted | ||
422 | + * (VINTANA1, VINTANA2, VINTDIG, VIO, CLKEN, HFCLKOUT). | ||
423 | + */ | ||
424 | + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, | ||
425 | + RES_STATE_ACTIVE), 2}, | ||
426 | +}; | ||
427 | + | ||
428 | +static struct twl4030_script wakeup_p3_script __initdata = { | ||
429 | + .script = wakeup_p3_seq, | ||
430 | + .size = ARRAY_SIZE(wakeup_p3_seq), | ||
431 | + .flags = TWL4030_WAKEUP3_SCRIPT, | ||
432 | +}; | ||
433 | + | ||
434 | +/** | ||
435 | + * DOC: Active to sleep sequence for P1/P2/P3 | ||
436 | + * | ||
437 | + * Sequence to control the TWL4030 Power resources, | ||
438 | + * when the system goes into sleep. | ||
439 | + * Executed upon P1_P2/P3 transition for sleep. | ||
440 | + * (sys_offmode signal asserted/clkreq de-asserted on OMAP). | ||
441 | + */ | ||
442 | +static struct twl4030_ins sleep_on_seq[] __initdata = { | ||
443 | + /* Broadcast message to put res to sleep (TYPE2 = 1, 2) */ | ||
444 | + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1, | ||
445 | + RES_STATE_SLEEP), 2}, | ||
446 | + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, | ||
447 | + RES_STATE_SLEEP), 2}, | ||
448 | +}; | ||
449 | + | ||
450 | +static struct twl4030_script sleep_on_script __initdata = { | ||
451 | + .script = sleep_on_seq, | ||
452 | + .size = ARRAY_SIZE(sleep_on_seq), | ||
453 | + .flags = TWL4030_SLEEP_SCRIPT, | ||
454 | +}; | ||
455 | + | ||
456 | +/** | ||
457 | + * DOC: Warm reset sequence | ||
458 | + * | ||
459 | + * Sequence to reset the TWL4030 Power resources, | ||
460 | + * when the system gets warm reset. | ||
461 | + * Executed upon warm reset signal. | ||
462 | + * | ||
463 | + * First the device is put in reset, then the system clock is requested to | ||
464 | + * the external oscillator, and default ON power reference and power providers | ||
465 | + * are enabled. Next some additional resources which are software controlled | ||
466 | + * are enabled. Finally sequence is ended by the release of TWL5030 reset. | ||
467 | + */ | ||
468 | +static struct twl4030_ins wrst_seq[] __initdata = { | ||
469 | + /* | ||
470 | + * As a workaround for OMAP Erratum (ID: i537 - OMAP HS devices are | ||
471 | + * not recovering from warm reset while in OFF mode) | ||
472 | + * NRESPWRON is toggled to force a power on reset condition to OMAP | ||
473 | + */ | ||
474 | + /* Trun OFF NRES_PWRON */ | ||
475 | + {MSG_SINGULAR(DEV_GRP_NULL, RES_NRES_PWRON, RES_STATE_OFF), 2}, | ||
476 | + /* Reset twl4030 */ | ||
477 | + {MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_OFF), 2}, | ||
478 | + /* Reset MAIN_REF */ | ||
479 | + {MSG_SINGULAR(DEV_GRP_NULL, RES_MAIN_REF, RES_STATE_WRST), 2}, | ||
480 | + /* Reset All type2_group2 */ | ||
481 | + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, | ||
482 | + RES_STATE_WRST), 2}, | ||
483 | + /* Reset VUSB_3v1 */ | ||
484 | + {MSG_SINGULAR(DEV_GRP_NULL, RES_VUSB_3V1, RES_STATE_WRST), 2}, | ||
485 | + /* Reset All type2_group1 */ | ||
486 | + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1, | ||
487 | + RES_STATE_WRST), 2}, | ||
488 | + /* Reset the Reset & Contorl_signals */ | ||
489 | + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_RC, RES_TYPE_ALL, RES_TYPE2_R0, | ||
490 | + RES_STATE_WRST), 2}, | ||
491 | + /* Re-enable twl4030 */ | ||
492 | + {MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_ACTIVE), 2}, | ||
493 | + /* Trun ON NRES_PWRON */ | ||
494 | + {MSG_SINGULAR(DEV_GRP_NULL, RES_NRES_PWRON, RES_STATE_ACTIVE), 2}, | ||
495 | +}; | ||
496 | + | ||
497 | +static struct twl4030_script wrst_script __initdata = { | ||
498 | + .script = wrst_seq, | ||
499 | + .size = ARRAY_SIZE(wrst_seq), | ||
500 | + .flags = TWL4030_WRST_SCRIPT, | ||
501 | +}; | ||
502 | + | ||
503 | +/* TWL4030 script for sleep, wakeup & warm_reset */ | ||
504 | +static struct twl4030_script *twl4030_scripts[] __initdata = { | ||
505 | + &wakeup_p12_script, | ||
506 | + &wakeup_p3_script, | ||
507 | + &sleep_on_script, | ||
508 | + &wrst_script, | ||
509 | +}; | ||
510 | + | ||
511 | +/** | ||
512 | + * DOC: TWL4030 resource configuration | ||
513 | + * | ||
514 | + * Resource which are attached to P1 device group alone | ||
515 | + * will go to sleep state, when sys_off signal from OMAP is de-asserted. | ||
516 | + * (VPLL1, VDD1, VDD2) | ||
517 | + * | ||
518 | + * None of the resources are attached to P2 device group alone. | ||
519 | + * (WARNING: If MODEM or connectivity chip is connected to NSLEEP2 PIN on | ||
520 | + * TWL4030, should modify the resource configuration accordingly). | ||
521 | + * | ||
522 | + * Resource which are attached to P3 device group alone | ||
523 | + * will go to sleep state, when clk_req signal from OMAP is de-asserted. | ||
524 | + * (HFCLKOUT) | ||
525 | + * | ||
526 | + * Resource which are attached to more than one device group | ||
527 | + * will go to sleep state, when corresponding signals are de-asserted. | ||
528 | + * (VINTANA1, VINTANA2, VINTDIG, VIO, REGEN, NRESPWRON, CLKEN, SYSEN) | ||
529 | + * | ||
530 | + * REGEN is an output of the device which can be connected to slave power ICs | ||
531 | + * or external LDOs that power on before voltage for the IO interface (VIO). | ||
532 | + * | ||
533 | + * SYSEN is a bidirectional signal of the device that controls slave power ICs. | ||
534 | + * In master mode, the device sets SYSEN high to enable the slave power ICs. | ||
535 | + * In slave mode, when one of the power ICs drives the SYSEN signal low, | ||
536 | + * all devices of the platform stay in the wait-on state. | ||
537 | + * | ||
538 | + * Resource which are attached to none of the device group by default | ||
539 | + * will be in sleep state. These resource should be controlled by | ||
540 | + * the respective drivers using them. | ||
541 | + * Resource which are controlled by drivers are not modified here. | ||
542 | + * (VAUX1, VAUX2, VAUX3, VAUX4, VMMC1, VMMC2, VPLL2, VSIM, VDAC, | ||
543 | + * VUSB1V5, VUSB1V8, VUSB3V1) | ||
544 | + * | ||
545 | + * Resource using reset values. | ||
546 | + * (32KCLKOUT, TRITON_RESET, MAINREF) | ||
547 | + */ | ||
548 | +static struct twl4030_resconfig twl4030_rconfig[] __initdata = { | ||
549 | + { .resource = RES_VPLL1, .devgroup = DEV_GRP_P1, .type = 3, | ||
550 | + .type2 = 1, .remap_sleep = RES_STATE_OFF }, | ||
551 | + { .resource = RES_VINTANA1, .devgroup = DEV_GRP_ALL, .type = 1, | ||
552 | + .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, | ||
553 | + { .resource = RES_VINTANA2, .devgroup = DEV_GRP_ALL, .type = 0, | ||
554 | + .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, | ||
555 | + { .resource = RES_VINTDIG, .devgroup = DEV_GRP_ALL, .type = 1, | ||
556 | + .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, | ||
557 | + { .resource = RES_VIO, .devgroup = DEV_GRP_ALL, .type = 2, | ||
558 | + .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, | ||
559 | + { .resource = RES_VDD1, .devgroup = DEV_GRP_P1, | ||
560 | + .type = 4, .type2 = 1, .remap_sleep = RES_STATE_OFF }, | ||
561 | + { .resource = RES_VDD2, .devgroup = DEV_GRP_P1, | ||
562 | + .type = 3, .type2 = 1, .remap_sleep = RES_STATE_OFF }, | ||
563 | + { .resource = RES_REGEN, .devgroup = DEV_GRP_ALL, .type = 2, | ||
564 | + .type2 = 1, .remap_sleep = RES_STATE_SLEEP }, | ||
565 | + { .resource = RES_NRES_PWRON, .devgroup = DEV_GRP_ALL, .type = 0, | ||
566 | + .type2 = 1, .remap_sleep = RES_STATE_SLEEP }, | ||
567 | + { .resource = RES_CLKEN, .devgroup = DEV_GRP_ALL, .type = 3, | ||
568 | + .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, | ||
569 | + { .resource = RES_SYSEN, .devgroup = DEV_GRP_ALL, .type = 6, | ||
570 | + .type2 = 1, .remap_sleep = RES_STATE_SLEEP }, | ||
571 | + { .resource = RES_HFCLKOUT, .devgroup = DEV_GRP_P3, | ||
572 | + .type = 0, .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, | ||
573 | + { 0, 0}, | ||
574 | +}; | ||
575 | + | ||
576 | +struct twl4030_power_data twl4030_generic_script __initdata = { | ||
577 | + .scripts = twl4030_scripts, | ||
578 | + .num = ARRAY_SIZE(twl4030_scripts), | ||
579 | + .resource_config = twl4030_rconfig, | ||
580 | +}; | ||
581 | + | ||
582 | +static int __init twl4030_script_probe(struct platform_device *pdev) | ||
583 | +{ | ||
584 | + return twl4030_power_init(&twl4030_generic_script); | ||
585 | +} | ||
586 | + | ||
587 | +static int twl4030_script_remove(struct platform_device *pdev) | ||
588 | +{ | ||
589 | + return twl4030_remove_script(TWL4030_SLEEP_SCRIPT | | ||
590 | + TWL4030_WAKEUP12_SCRIPT | TWL4030_WAKEUP3_SCRIPT | | ||
591 | + TWL4030_WRST_SCRIPT); | ||
592 | +} | ||
593 | + | ||
594 | +static struct platform_driver twl4030_script_driver = { | ||
595 | + .remove = twl4030_script_remove, | ||
596 | + .driver = { | ||
597 | + .name = "twl4030_script", | ||
598 | + .owner = THIS_MODULE, | ||
599 | + }, | ||
600 | +}; | ||
601 | + | ||
602 | +static int __init twl4030_script_init(void) | ||
603 | +{ | ||
604 | + /* Register the TWL4030 script driver */ | ||
605 | + return platform_driver_probe(&twl4030_script_driver, | ||
606 | + twl4030_script_probe); | ||
607 | +} | ||
608 | + | ||
609 | +static void __exit twl4030_script_cleanup(void) | ||
610 | +{ | ||
611 | + /* Unregister TWL4030 script driver */ | ||
612 | + platform_driver_unregister(&twl4030_script_driver); | ||
613 | +} | ||
614 | + | ||
615 | +module_init(twl4030_script_init); | ||
616 | +module_exit(twl4030_script_cleanup); | ||
617 | + | ||
618 | +MODULE_DESCRIPTION("OMAP TWL4030 script driver"); | ||
619 | +MODULE_LICENSE("GPL"); | ||
620 | +MODULE_AUTHOR("Texas Instruments Inc"); | ||
621 | diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h | ||
622 | index aee3a22..f343974 100644 | ||
623 | --- a/include/linux/i2c/twl.h | ||
624 | +++ b/include/linux/i2c/twl.h | ||
625 | @@ -205,6 +205,12 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot) | ||
626 | return -EIO; | ||
627 | } | ||
628 | #endif | ||
629 | + | ||
630 | +#ifdef CONFIG_TWL4030_POWER | ||
631 | +extern struct twl4030_power_data twl4030_generic_script; | ||
632 | +#else | ||
633 | +#define twl4030_generic_script NULL; | ||
634 | +#endif | ||
635 | /*----------------------------------------------------------------------*/ | ||
636 | |||
637 | /* | ||
638 | @@ -437,9 +443,23 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot) | ||
639 | |||
640 | /* Power bus message definitions */ | ||
641 | |||
642 | -/* The TWL4030/5030 splits its power-management resources (the various | ||
643 | - * regulators, clock and reset lines) into 3 processor groups - P1, P2 and | ||
644 | - * P3. These groups can then be configured to transition between sleep, wait-on | ||
645 | +/* | ||
646 | + * The TWL4030/5030 splits its power-management resources (the various | ||
647 | + * regulators, clock and reset lines) into 3 processor groups - P1, P2 and P3. | ||
648 | + * | ||
649 | + * Resources attached to device group P1 is managed depending on the state of | ||
650 | + * NSLEEP1 pin of TWL4030, which is connected to sys_off signal from OMAP | ||
651 | + * | ||
652 | + * Resources attached to device group P2 is managed depending on the state of | ||
653 | + * NSLEEP2 pin of TWL4030, which is can be connected to a modem or | ||
654 | + * connectivity chip | ||
655 | + * | ||
656 | + * Resources attached to device group P3 is managed depending on the state of | ||
657 | + * CLKREQ pin of TWL4030, which is connected to clk request signal from OMAP | ||
658 | + * | ||
659 | + * If required these resources can be attached to combination of P1/P2/P3. | ||
660 | + * | ||
661 | + * These groups can then be configured to transition between sleep, wait-on | ||
662 | * and active states by sending messages to the power bus. See Section 5.4.2 | ||
663 | * Power Resources of TWL4030 TRM | ||
664 | */ | ||
665 | @@ -449,7 +469,17 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot) | ||
666 | #define DEV_GRP_P1 0x1 /* P1: all OMAP devices */ | ||
667 | #define DEV_GRP_P2 0x2 /* P2: all Modem devices */ | ||
668 | #define DEV_GRP_P3 0x4 /* P3: all peripheral devices */ | ||
669 | +#define DEV_GRP_ALL 0x7 /* P1/P2/P3: all devices */ | ||
670 | |||
671 | +/* | ||
672 | + * The 27 power resources in TWL4030 is again divided into | ||
673 | + * analog resources: | ||
674 | + * Power Providers - LDO regulators, dc-to-dc regulators | ||
675 | + * Power Reference - analog reference | ||
676 | + * | ||
677 | + * and digital resources: | ||
678 | + * Reset & Clock - reset and clock signals. | ||
679 | + */ | ||
680 | /* Resource groups */ | ||
681 | #define RES_GRP_RES 0x0 /* Reserved */ | ||
682 | #define RES_GRP_PP 0x1 /* Power providers */ | ||
683 | @@ -461,7 +491,10 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot) | ||
684 | #define RES_GRP_ALL 0x7 /* All resource groups */ | ||
685 | |||
686 | #define RES_TYPE2_R0 0x0 | ||
687 | +#define RES_TYPE2_R1 0x1 | ||
688 | +#define RES_TYPE2_R2 0x2 | ||
689 | |||
690 | +#define RES_TYPE_R0 0x0 | ||
691 | #define RES_TYPE_ALL 0x7 | ||
692 | |||
693 | /* Resource states */ | ||
694 | @@ -636,7 +669,7 @@ struct twl4030_power_data { | ||
695 | #define TWL4030_RESCONFIG_UNDEF ((u8)-1) | ||
696 | }; | ||
697 | |||
698 | -extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts); | ||
699 | +extern int twl4030_power_init(struct twl4030_power_data *triton2_scripts); | ||
700 | extern int twl4030_remove_script(u8 flags); | ||
701 | |||
702 | struct twl4030_codec_audio_data { | ||
703 | -- | ||
704 | 1.6.6.1 | ||
705 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0011-MFD-TWL4030-TWL-version-checking.patch b/recipes-kernel/linux/linux-omap-2.6.39/mfd/0011-MFD-TWL4030-TWL-version-checking.patch deleted file mode 100644 index 6de2193d..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0011-MFD-TWL4030-TWL-version-checking.patch +++ /dev/null | |||
@@ -1,164 +0,0 @@ | |||
1 | From 3ceb224732230934aba7d082f3e2ca96c14a9ca0 Mon Sep 17 00:00:00 2001 | ||
2 | From: Lesly A M <leslyam@ti.com> | ||
3 | Date: Wed, 1 Jun 2011 14:56:56 -0700 | ||
4 | Subject: [PATCH 11/13] MFD: TWL4030: TWL version checking | ||
5 | |||
6 | Added API to get the TWL5030 Si version from the IDCODE register. | ||
7 | It is used for enabling the workaround for TWL erratum 27. | ||
8 | |||
9 | Signed-off-by: Lesly A M <leslyam@ti.com> | ||
10 | Cc: Nishanth Menon <nm@ti.com> | ||
11 | Cc: David Derrick <dderrick@ti.com> | ||
12 | Cc: Samuel Ortiz <sameo@linux.intel.com> | ||
13 | --- | ||
14 | drivers/mfd/twl-core.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++ | ||
15 | include/linux/i2c/twl.h | 17 ++++++++++++- | ||
16 | 2 files changed, 78 insertions(+), 1 deletions(-) | ||
17 | |||
18 | diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c | ||
19 | index 9096d7d..a60601d 100644 | ||
20 | --- a/drivers/mfd/twl-core.c | ||
21 | +++ b/drivers/mfd/twl-core.c | ||
22 | @@ -251,6 +251,9 @@ | ||
23 | /* is driver active, bound to a chip? */ | ||
24 | static bool inuse; | ||
25 | |||
26 | +/* TWL IDCODE Register value */ | ||
27 | +static u32 twl_idcode; | ||
28 | + | ||
29 | static unsigned int twl_id; | ||
30 | unsigned int twl_rev(void) | ||
31 | { | ||
32 | @@ -509,6 +512,58 @@ EXPORT_SYMBOL(twl_i2c_read_u8); | ||
33 | |||
34 | /*----------------------------------------------------------------------*/ | ||
35 | |||
36 | +/** | ||
37 | + * twl_read_idcode_register - API to read the IDCODE register. | ||
38 | + * | ||
39 | + * Unlocks the IDCODE register and read the 32 bit value. | ||
40 | + */ | ||
41 | +static int twl_read_idcode_register(void) | ||
42 | +{ | ||
43 | + int err; | ||
44 | + | ||
45 | + err = twl_i2c_write_u8(TWL4030_MODULE_INTBR, TWL_EEPROM_R_UNLOCK, | ||
46 | + REG_UNLOCK_TEST_REG); | ||
47 | + if (err) { | ||
48 | + pr_err("TWL4030 Unable to unlock IDCODE registers -%d\n", err); | ||
49 | + goto fail; | ||
50 | + } | ||
51 | + | ||
52 | + err = twl_i2c_read(TWL4030_MODULE_INTBR, (u8 *)(&twl_idcode), | ||
53 | + REG_IDCODE_7_0, 4); | ||
54 | + if (err) { | ||
55 | + pr_err("TWL4030: unable to read IDCODE -%d\n", err); | ||
56 | + goto fail; | ||
57 | + } | ||
58 | + | ||
59 | + err = twl_i2c_write_u8(TWL4030_MODULE_INTBR, 0x0, REG_UNLOCK_TEST_REG); | ||
60 | + if (err) | ||
61 | + pr_err("TWL4030 Unable to relock IDCODE registers -%d\n", err); | ||
62 | +fail: | ||
63 | + return err; | ||
64 | +} | ||
65 | + | ||
66 | +/** | ||
67 | + * twl_get_type - API to get TWL Si type. | ||
68 | + * | ||
69 | + * Api to get the TWL Si type from IDCODE value. | ||
70 | + */ | ||
71 | +int twl_get_type(void) | ||
72 | +{ | ||
73 | + return TWL_SIL_TYPE(twl_idcode); | ||
74 | +} | ||
75 | +EXPORT_SYMBOL_GPL(twl_get_type); | ||
76 | + | ||
77 | +/** | ||
78 | + * twl_get_version - API to get TWL Si version. | ||
79 | + * | ||
80 | + * Api to get the TWL Si version from IDCODE value. | ||
81 | + */ | ||
82 | +int twl_get_version(void) | ||
83 | +{ | ||
84 | + return TWL_SIL_REV(twl_idcode); | ||
85 | +} | ||
86 | +EXPORT_SYMBOL_GPL(twl_get_version); | ||
87 | + | ||
88 | static struct device * | ||
89 | add_numbered_child(unsigned chip, const char *name, int num, | ||
90 | void *pdata, unsigned pdata_len, | ||
91 | @@ -1071,6 +1126,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
92 | unsigned i; | ||
93 | struct twl4030_platform_data *pdata = client->dev.platform_data; | ||
94 | u8 temp; | ||
95 | + int ret = 0; | ||
96 | |||
97 | if (!pdata) { | ||
98 | dev_dbg(&client->dev, "no platform data?\n"); | ||
99 | @@ -1117,6 +1173,12 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
100 | /* setup clock framework */ | ||
101 | clocks_init(&client->dev, pdata->clock); | ||
102 | |||
103 | + /* read TWL IDCODE Register */ | ||
104 | + if (twl_id == TWL4030_CLASS_ID) { | ||
105 | + ret = twl_read_idcode_register(); | ||
106 | + WARN(ret < 0, "Error: reading twl_idcode register value\n"); | ||
107 | + } | ||
108 | + | ||
109 | /* load power event scripts */ | ||
110 | if (twl_has_power() && pdata->power) | ||
111 | twl4030_power_init(pdata->power); | ||
112 | diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h | ||
113 | index f343974..23ec058 100644 | ||
114 | --- a/include/linux/i2c/twl.h | ||
115 | +++ b/include/linux/i2c/twl.h | ||
116 | @@ -151,7 +151,12 @@ | ||
117 | #define MMC_PU (0x1 << 3) | ||
118 | #define MMC_PD (0x1 << 2) | ||
119 | |||
120 | - | ||
121 | +#define TWL_SIL_TYPE(rev) ((rev) & 0x00FFFFFF) | ||
122 | +#define TWL_SIL_REV(rev) ((rev) >> 24) | ||
123 | +#define TWL_SIL_5030 0x09002F | ||
124 | +#define TWL5030_REV_1_0 0x00 | ||
125 | +#define TWL5030_REV_1_1 0x10 | ||
126 | +#define TWL5030_REV_1_2 0x30 | ||
127 | |||
128 | #define TWL4030_CLASS_ID 0x4030 | ||
129 | #define TWL6030_CLASS_ID 0x6030 | ||
130 | @@ -181,6 +186,9 @@ int twl_i2c_read_u8(u8 mod_no, u8 *val, u8 reg); | ||
131 | int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); | ||
132 | int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); | ||
133 | |||
134 | +int twl_get_type(void); | ||
135 | +int twl_get_version(void); | ||
136 | + | ||
137 | int twl6030_interrupt_unmask(u8 bit_mask, u8 offset); | ||
138 | int twl6030_interrupt_mask(u8 bit_mask, u8 offset); | ||
139 | |||
140 | @@ -286,7 +294,12 @@ extern struct twl4030_power_data twl4030_generic_script; | ||
141 | *(Use TWL_4030_MODULE_INTBR) | ||
142 | */ | ||
143 | |||
144 | +#define REG_IDCODE_7_0 0x00 | ||
145 | +#define REG_IDCODE_15_8 0x01 | ||
146 | +#define REG_IDCODE_16_23 0x02 | ||
147 | +#define REG_IDCODE_31_24 0x03 | ||
148 | #define REG_GPPUPDCTR1 0x0F | ||
149 | +#define REG_UNLOCK_TEST_REG 0x12 | ||
150 | |||
151 | /*I2C1 and I2C4(SR) SDA/SCL pull-up control bits */ | ||
152 | |||
153 | @@ -295,6 +308,8 @@ extern struct twl4030_power_data twl4030_generic_script; | ||
154 | #define SR_I2C_SCL_CTRL_PU BIT(4) | ||
155 | #define SR_I2C_SDA_CTRL_PU BIT(6) | ||
156 | |||
157 | +#define TWL_EEPROM_R_UNLOCK 0x49 | ||
158 | + | ||
159 | /*----------------------------------------------------------------------*/ | ||
160 | |||
161 | /* | ||
162 | -- | ||
163 | 1.6.6.1 | ||
164 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0012-MFD-TWL4030-workaround-changes-for-Erratum-27.patch b/recipes-kernel/linux/linux-omap-2.6.39/mfd/0012-MFD-TWL4030-workaround-changes-for-Erratum-27.patch deleted file mode 100644 index 6fe9dbfb..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0012-MFD-TWL4030-workaround-changes-for-Erratum-27.patch +++ /dev/null | |||
@@ -1,341 +0,0 @@ | |||
1 | From 0bec9f7b20e7c61e0bab93195ec39cf94f1f8e25 Mon Sep 17 00:00:00 2001 | ||
2 | From: Lesly A M <leslyam@ti.com> | ||
3 | Date: Wed, 1 Jun 2011 14:57:01 -0700 | ||
4 | Subject: [PATCH 12/13] MFD: TWL4030: workaround changes for Erratum 27 | ||
5 | |||
6 | Workaround for TWL5030 Silicon Errata 27 & 28: | ||
7 | 27 - VDD1, VDD2, may have glitches when their output value is updated. | ||
8 | 28 - VDD1 and / or VDD2 DCDC clock may stop working when internal clock | ||
9 | is switched from internal to external. | ||
10 | |||
11 | Erratum 27: | ||
12 | If the DCDC regulators is running on their internal oscillator, | ||
13 | negative glitches may occur on VDD1, VDD2 output when voltage is changed. | ||
14 | The OMAP device may reboot if the VDD1 or VDD2 go below the | ||
15 | core minimum operating voltage. | ||
16 | |||
17 | WORKAROUND | ||
18 | Set up the TWL5030 DC-DC power supplies to use the HFCLKIN instead of | ||
19 | the internal oscillator. | ||
20 | |||
21 | Erratum 28: | ||
22 | VDD1/VDD2 clock system may hang during switching the clock source from | ||
23 | internal oscillator to external. VDD1/VDD2 output voltages may collapse | ||
24 | if clock stops. | ||
25 | |||
26 | WORKAROUND | ||
27 | If HFCLK is disabled in OFFMODE, modify the sleep/wakeup sequence and | ||
28 | setuptimes to make sure the switching will happen only when HFCLKIN is stable. | ||
29 | Also use the TWL5030 watchdog to safeguard the first switching from | ||
30 | internal oscillator to HFCLKIN during the TWL5030 init. | ||
31 | |||
32 | IMPACT | ||
33 | power sequence is changed. | ||
34 | sleep/wakeup time values will be changed. | ||
35 | |||
36 | The workaround changes are called from twl4030_power_init(), since we have to | ||
37 | make some i2c_read calls to check the TWL4030 version & the i2c will not be | ||
38 | initialized in the early stage. | ||
39 | |||
40 | This workaround is required for TWL5030 Silicon version less than ES1.2 | ||
41 | The power script & setup time changes are recommended by TI HW team. | ||
42 | |||
43 | For more information please see: | ||
44 | http://omapedia.org/wiki/TWL4030_power_scripts | ||
45 | |||
46 | Changes taken from TWL4030 Erratum 27 workaround patch by Nishanth Menon. | ||
47 | |||
48 | Signed-off-by: Lesly A M <leslyam@ti.com> | ||
49 | Cc: Nishanth Menon <nm@ti.com> | ||
50 | Cc: David Derrick <dderrick@ti.com> | ||
51 | Cc: Samuel Ortiz <sameo@linux.intel.com> | ||
52 | --- | ||
53 | drivers/mfd/twl4030-power.c | 79 +++++++++++++++++++ | ||
54 | drivers/mfd/twl4030-script-omap.c | 150 +++++++++++++++++++++++++++++++++++++ | ||
55 | include/linux/i2c/twl.h | 1 + | ||
56 | 3 files changed, 230 insertions(+), 0 deletions(-) | ||
57 | |||
58 | diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c | ||
59 | index 91d5bc8..8af3fe3 100644 | ||
60 | --- a/drivers/mfd/twl4030-power.c | ||
61 | +++ b/drivers/mfd/twl4030-power.c | ||
62 | @@ -63,6 +63,14 @@ static u8 twl4030_start_script_address = 0x2b; | ||
63 | #define R_MEMORY_ADDRESS PHY_TO_OFF_PM_MASTER(0x59) | ||
64 | #define R_MEMORY_DATA PHY_TO_OFF_PM_MASTER(0x5a) | ||
65 | |||
66 | +#define R_VDD1_OSC 0x5C | ||
67 | +#define R_VDD2_OSC 0x6A | ||
68 | +#define R_VIO_OSC 0x52 | ||
69 | +#define EXT_FS_CLK_EN BIT(6) | ||
70 | + | ||
71 | +#define R_WDT_CFG 0x03 | ||
72 | +#define WDT_WRK_TIMEOUT 0x03 | ||
73 | + | ||
74 | /* resource configuration registers | ||
75 | <RESOURCE>_DEV_GRP at address 'n+0' | ||
76 | <RESOURCE>_TYPE at address 'n+1' | ||
77 | @@ -512,6 +520,67 @@ int twl4030_remove_script(u8 flags) | ||
78 | } | ||
79 | EXPORT_SYMBOL_GPL(twl4030_remove_script); | ||
80 | |||
81 | +/** | ||
82 | + * twl_dcdc_use_hfclk - API to use HFCLK for TWL DCDCs | ||
83 | + * | ||
84 | + * TWL DCDCs switching to HFCLK instead of using internal RC oscillator. | ||
85 | + */ | ||
86 | +static int twl_dcdc_use_hfclk(void) | ||
87 | +{ | ||
88 | + u8 val; | ||
89 | + u8 smps_osc_reg[] = {R_VDD1_OSC, R_VDD2_OSC, R_VIO_OSC}; | ||
90 | + int i; | ||
91 | + int err; | ||
92 | + | ||
93 | + for (i = 0; i < sizeof(smps_osc_reg); i++) { | ||
94 | + err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &val, | ||
95 | + smps_osc_reg[i]); | ||
96 | + val |= EXT_FS_CLK_EN; | ||
97 | + err |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, val, | ||
98 | + smps_osc_reg[i]); | ||
99 | + } | ||
100 | + return err; | ||
101 | +} | ||
102 | + | ||
103 | +/** | ||
104 | + * twl_erratum27_workaround - Workaround for TWL5030 Silicon Erratum 27 | ||
105 | + * 27 - VDD1, VDD2, may have glitches when their output value is updated. | ||
106 | + * 28 - VDD1 and / or VDD2 DCDC clock may stop working when internal clock is | ||
107 | + * switched from internal to external. | ||
108 | + * | ||
109 | + * Workaround requires the TWL DCDCs to use HFCLK instead of | ||
110 | + * internal oscillator. Also enable TWL watchdog before switching the osc | ||
111 | + * to recover if the VDD1/VDD2 stop working. | ||
112 | + */ | ||
113 | +static void twl_erratum27_workaround(void) | ||
114 | +{ | ||
115 | + u8 wdt_counter_val = 0; | ||
116 | + int err; | ||
117 | + | ||
118 | + /* Setup the twl wdt to take care of borderline failure case */ | ||
119 | + err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &wdt_counter_val, | ||
120 | + R_WDT_CFG); | ||
121 | + err |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, WDT_WRK_TIMEOUT, | ||
122 | + R_WDT_CFG); | ||
123 | + | ||
124 | + /* TWL DCDC switching to HFCLK */ | ||
125 | + err |= twl_dcdc_use_hfclk(); | ||
126 | + | ||
127 | + /* restore the original value */ | ||
128 | + err |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, wdt_counter_val, | ||
129 | + R_WDT_CFG); | ||
130 | + if (err) | ||
131 | + pr_warning("TWL4030: workaround setup failed!\n"); | ||
132 | +} | ||
133 | + | ||
134 | +static bool is_twl5030_erratum27wa_required(void) | ||
135 | +{ | ||
136 | + if (twl_get_type() == TWL_SIL_5030) | ||
137 | + return (twl_get_version() < TWL5030_REV_1_2); | ||
138 | + | ||
139 | + return 0; | ||
140 | +} | ||
141 | + | ||
142 | int twl4030_power_init(struct twl4030_power_data *twl4030_scripts) | ||
143 | { | ||
144 | int err = 0; | ||
145 | @@ -530,6 +599,16 @@ int twl4030_power_init(struct twl4030_power_data *twl4030_scripts) | ||
146 | TWL4030_PM_MASTER_PROTECT_KEY); | ||
147 | if (err) | ||
148 | goto unlock; | ||
149 | + | ||
150 | + /* Applying TWL5030 Erratum 27 WA based on Si revision & | ||
151 | + * flag updated from board file*/ | ||
152 | + if (is_twl5030_erratum27wa_required()) { | ||
153 | + pr_info("TWL5030: Enabling workaround for Si Erratum 27\n"); | ||
154 | + twl_erratum27_workaround(); | ||
155 | + if (twl4030_scripts->twl5030_erratum27wa_script) | ||
156 | + twl4030_scripts->twl5030_erratum27wa_script(); | ||
157 | + } | ||
158 | + | ||
159 | for (i = 0; i < twl4030_scripts->num; i++) { | ||
160 | err = load_twl4030_script(twl4030_scripts->scripts[i], address); | ||
161 | if (err) | ||
162 | diff --git a/drivers/mfd/twl4030-script-omap.c b/drivers/mfd/twl4030-script-omap.c | ||
163 | index 867a442..ff93fd2 100644 | ||
164 | --- a/drivers/mfd/twl4030-script-omap.c | ||
165 | +++ b/drivers/mfd/twl4030-script-omap.c | ||
166 | @@ -326,10 +326,160 @@ static struct twl4030_resconfig twl4030_rconfig[] __initdata = { | ||
167 | { 0, 0}, | ||
168 | }; | ||
169 | |||
170 | +/* | ||
171 | + * Sleep and active sequences with changes for TWL5030 Erratum 27 workaround | ||
172 | + * | ||
173 | + * Sysoff (using sys_off signal): | ||
174 | + * When SYS_CLKREQ goes low during retention no resources will be affected | ||
175 | + * since no resources are assigned to P3 only. | ||
176 | + * | ||
177 | + * Since all resources are assigned to P1 and P3 then all resources | ||
178 | + * will be affected on the falling edge of P3 (SYS_CLKREQ). | ||
179 | + * When OMAP lower the SYS_CLKREQ signal PMIC will execute the | ||
180 | + * A2S sequence in which HFCLKOUT is dissabled first and | ||
181 | + * after 488.32 usec(PRM_VOLTOFFSET) resources assigned to P1 and P3 | ||
182 | + * and of TYPE2=1 are put to sleep | ||
183 | + * (VDD1, VDD2, VPLL1, REGEN, NRESPWRON & SYSEN). | ||
184 | + * Again after a 61.04 usec resources assigned to P1 and P3 | ||
185 | + * and of TYPE2=2 are put to sleep | ||
186 | + * (VINTANA1, VINTANA2, VINTDIG, VIO & CLKEN). | ||
187 | + * | ||
188 | + * On wakeup event OMAP goes active and pulls the SYS_CLKREQ high, | ||
189 | + * and will execute the S2A sequence which is same for P1_P2 & P3. | ||
190 | + * This will turn on all resources of TYPE2=2 to go to the active state. | ||
191 | + * Three dummy broadcast messages are added to get a delay of ~10 ms | ||
192 | + * before enabling the HFCLKOUT resource. And after a 30.52 usec | ||
193 | + * all resources of TYPE2=1 are put to the active state. | ||
194 | + * | ||
195 | + * This 10ms delay can be reduced if the oscillator is having less | ||
196 | + * stabilization time. A should be taken care if it needs more time | ||
197 | + * for stabilization. | ||
198 | + * | ||
199 | + */ | ||
200 | + | ||
201 | +/** | ||
202 | + * DOC: Sleep to Active sequence for P1/P2/P3 | ||
203 | + * | ||
204 | + * The wakeup sequence is adjusted to do the VDD1/VDD2 voltage ramp-up | ||
205 | + * only after HFCLKIN is stabilized and the HFCLKOUT is enabled. | ||
206 | + */ | ||
207 | +static struct twl4030_ins wakeup_seq_erratum27[] __initdata = { | ||
208 | + /* | ||
209 | + * Broadcast message to put res(TYPE2 = 2) to active. | ||
210 | + * Wait for ~10 mS (ramp-up time for OSC on the board) | ||
211 | + * after HFCLKIN is enabled | ||
212 | + */ | ||
213 | + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, | ||
214 | + RES_STATE_ACTIVE), 55}, | ||
215 | + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, | ||
216 | + RES_STATE_ACTIVE), 55}, | ||
217 | + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, | ||
218 | + RES_STATE_ACTIVE), 54}, | ||
219 | + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, | ||
220 | + RES_STATE_ACTIVE), 1}, | ||
221 | + /* Singular message to enable HCLKOUT after HFCLKIN is stabilized */ | ||
222 | + {MSG_SINGULAR(DEV_GRP_NULL, RES_HFCLKOUT, RES_STATE_ACTIVE), 1}, | ||
223 | + /* | ||
224 | + * Broadcast message to put res(TYPE2 = 1) to active. | ||
225 | + * VDD1/VDD2 ramp-up after HFCLKIN is stable and HFCLKOUT is enabled. | ||
226 | + */ | ||
227 | + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1, | ||
228 | + RES_STATE_ACTIVE), 2}, | ||
229 | +}; | ||
230 | + | ||
231 | +static struct twl4030_script wakeup_script_erratum27 __initdata = { | ||
232 | + .script = wakeup_seq_erratum27, | ||
233 | + .size = ARRAY_SIZE(wakeup_seq_erratum27), | ||
234 | + .flags = TWL4030_WAKEUP12_SCRIPT | TWL4030_WAKEUP3_SCRIPT, | ||
235 | +}; | ||
236 | + | ||
237 | +/** | ||
238 | + * DOC: Active to Sleep sequence for P1/P2/P3 | ||
239 | + * | ||
240 | + * The sleep sequence is adjusted to do the switching of VDD1/VDD2/VIO OSC from | ||
241 | + * HFCLKIN to internal oscillator when the HFCLKIN is stable. | ||
242 | + */ | ||
243 | +static struct twl4030_ins sleep_on_seq_erratum27[] __initdata = { | ||
244 | + /* | ||
245 | + * Singular message to disable HCLKOUT. | ||
246 | + * Wait for ~488.32 uS to do the switching of VDD1/VDD2/VIO OSC from | ||
247 | + * HFCLKIN to internal oscillator before disabling HFCLKIN. | ||
248 | + */ | ||
249 | + {MSG_SINGULAR(DEV_GRP_NULL, RES_HFCLKOUT, RES_STATE_SLEEP), 20}, | ||
250 | + /* Broadcast message to put res(TYPE2 = 1) to sleep */ | ||
251 | + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1, | ||
252 | + RES_STATE_SLEEP), 2}, | ||
253 | + /* Broadcast message to put res(TYPE2 = 2) to sleep, disable HFCLKIN */ | ||
254 | + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, | ||
255 | + RES_STATE_SLEEP), 2}, | ||
256 | +}; | ||
257 | + | ||
258 | +static struct twl4030_script sleep_on_script_erratum27 __initdata = { | ||
259 | + .script = sleep_on_seq_erratum27, | ||
260 | + .size = ARRAY_SIZE(sleep_on_seq_erratum27), | ||
261 | + .flags = TWL4030_SLEEP_SCRIPT, | ||
262 | +}; | ||
263 | + | ||
264 | +/* TWL4030 script for sleep, wakeup & warm_reset */ | ||
265 | +static struct twl4030_script *twl4030_scripts_erratum27[] __initdata = { | ||
266 | + &wakeup_script_erratum27, | ||
267 | + &sleep_on_script_erratum27, | ||
268 | + &wrst_script, | ||
269 | +}; | ||
270 | + | ||
271 | +/** | ||
272 | + * DOC: TWL4030 resource configuration | ||
273 | + * | ||
274 | + * VDD1/VDD2/VPLL are assigned to P1 and P3, to have better control | ||
275 | + * during OFFMODE. HFCLKOUT is assigned to P1 and P3 (*p2) to turn off | ||
276 | + * only during OFFMODE. | ||
277 | + * (*P2 is included if the platform uses it for modem/some other processor) | ||
278 | + */ | ||
279 | +static struct twl4030_resconfig twl4030_rconfig_erratum27[] __initdata = { | ||
280 | + { .resource = RES_VPLL1, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, | ||
281 | + .type = 3, .type2 = 1, .remap_sleep = RES_STATE_OFF }, | ||
282 | + { .resource = RES_VINTANA1, .devgroup = DEV_GRP_ALL, .type = 1, | ||
283 | + .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, | ||
284 | + { .resource = RES_VINTANA2, .devgroup = DEV_GRP_ALL, .type = 0, | ||
285 | + .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, | ||
286 | + { .resource = RES_VINTDIG, .devgroup = DEV_GRP_ALL, .type = 1, | ||
287 | + .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, | ||
288 | + { .resource = RES_VIO, .devgroup = DEV_GRP_ALL, .type = 2, | ||
289 | + .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, | ||
290 | + { .resource = RES_VDD1, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, | ||
291 | + .type = 4, .type2 = 1, .remap_sleep = RES_STATE_OFF }, | ||
292 | + { .resource = RES_VDD2, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, | ||
293 | + .type = 3, .type2 = 1, .remap_sleep = RES_STATE_OFF }, | ||
294 | + { .resource = RES_REGEN, .devgroup = DEV_GRP_ALL, .type = 2, | ||
295 | + .type2 = 1, .remap_sleep = RES_STATE_SLEEP }, | ||
296 | + { .resource = RES_NRES_PWRON, .devgroup = DEV_GRP_ALL, .type = 0, | ||
297 | + .type2 = 1, .remap_sleep = RES_STATE_SLEEP }, | ||
298 | + { .resource = RES_CLKEN, .devgroup = DEV_GRP_ALL, .type = 3, | ||
299 | + .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, | ||
300 | + { .resource = RES_SYSEN, .devgroup = DEV_GRP_ALL, .type = 6, | ||
301 | + .type2 = 1, .remap_sleep = RES_STATE_SLEEP }, | ||
302 | + { .resource = RES_HFCLKOUT, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, | ||
303 | + .type = 0, .type2 = 1, .remap_sleep = RES_STATE_SLEEP }, | ||
304 | + { 0, 0}, | ||
305 | +}; | ||
306 | + | ||
307 | +/** | ||
308 | + * twl5030_script_erratum27() - API to modify TWL4030 script | ||
309 | + * | ||
310 | + * Updating the TWL4030 script & resource configuration | ||
311 | + */ | ||
312 | +static void __init twl5030_script_erratum27(void) | ||
313 | +{ | ||
314 | + twl4030_generic_script.scripts = twl4030_scripts_erratum27; | ||
315 | + twl4030_generic_script.num = ARRAY_SIZE(twl4030_scripts_erratum27); | ||
316 | + twl4030_generic_script.resource_config = twl4030_rconfig_erratum27; | ||
317 | +} | ||
318 | + | ||
319 | struct twl4030_power_data twl4030_generic_script __initdata = { | ||
320 | .scripts = twl4030_scripts, | ||
321 | .num = ARRAY_SIZE(twl4030_scripts), | ||
322 | .resource_config = twl4030_rconfig, | ||
323 | + .twl5030_erratum27wa_script = twl5030_script_erratum27, | ||
324 | }; | ||
325 | |||
326 | static int __init twl4030_script_probe(struct platform_device *pdev) | ||
327 | diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h | ||
328 | index 23ec058..10cb6e2 100644 | ||
329 | --- a/include/linux/i2c/twl.h | ||
330 | +++ b/include/linux/i2c/twl.h | ||
331 | @@ -681,6 +681,7 @@ struct twl4030_power_data { | ||
332 | struct twl4030_script **scripts; | ||
333 | unsigned num; | ||
334 | struct twl4030_resconfig *resource_config; | ||
335 | + void (*twl5030_erratum27wa_script)(void); | ||
336 | #define TWL4030_RESCONFIG_UNDEF ((u8)-1) | ||
337 | }; | ||
338 | |||
339 | -- | ||
340 | 1.6.6.1 | ||
341 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0013-MFD-TWL4030-optimizing-resource-configuration.patch b/recipes-kernel/linux/linux-omap-2.6.39/mfd/0013-MFD-TWL4030-optimizing-resource-configuration.patch deleted file mode 100644 index 8904f8de..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/mfd/0013-MFD-TWL4030-optimizing-resource-configuration.patch +++ /dev/null | |||
@@ -1,184 +0,0 @@ | |||
1 | From bf171753a162d07753208c6bcfae8ca1e5c94af3 Mon Sep 17 00:00:00 2001 | ||
2 | From: Lesly A M <leslyam@ti.com> | ||
3 | Date: Wed, 1 Jun 2011 14:57:05 -0700 | ||
4 | Subject: [PATCH 13/13] MFD: TWL4030: optimizing resource configuration | ||
5 | |||
6 | Skip the i2c register writes in twl4030_configure_resource() if the new value | ||
7 | is same as the old value, for devgrp/type/remap regs. | ||
8 | |||
9 | Suggested by David Derrick <dderrick@ti.com> | ||
10 | |||
11 | Signed-off-by: Lesly A M <leslyam@ti.com> | ||
12 | Cc: Nishanth Menon <nm@ti.com> | ||
13 | Cc: David Derrick <dderrick@ti.com> | ||
14 | Cc: Samuel Ortiz <sameo@linux.intel.com> | ||
15 | --- | ||
16 | drivers/mfd/twl4030-power.c | 126 ++++++++++++++++++++++++------------------ | ||
17 | 1 files changed, 72 insertions(+), 54 deletions(-) | ||
18 | |||
19 | diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c | ||
20 | index 8af3fe3..d82632f 100644 | ||
21 | --- a/drivers/mfd/twl4030-power.c | ||
22 | +++ b/drivers/mfd/twl4030-power.c | ||
23 | @@ -335,9 +335,9 @@ static int twl4030_configure_resource(struct twl4030_resconfig *rconfig) | ||
24 | { | ||
25 | int rconfig_addr; | ||
26 | int err; | ||
27 | - u8 type; | ||
28 | - u8 grp; | ||
29 | - u8 remap; | ||
30 | + u8 type, type_value; | ||
31 | + u8 grp, grp_value; | ||
32 | + u8 remap, remap_value; | ||
33 | |||
34 | if (rconfig->resource > TOTAL_RESOURCES) { | ||
35 | pr_err("TWL4030 Resource %d does not exist\n", | ||
36 | @@ -348,76 +348,94 @@ static int twl4030_configure_resource(struct twl4030_resconfig *rconfig) | ||
37 | rconfig_addr = res_config_addrs[rconfig->resource]; | ||
38 | |||
39 | /* Set resource group */ | ||
40 | - err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &grp, | ||
41 | + if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) { | ||
42 | + err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &grp, | ||
43 | rconfig_addr + DEV_GRP_OFFSET); | ||
44 | - if (err) { | ||
45 | - pr_err("TWL4030 Resource %d group could not be read\n", | ||
46 | - rconfig->resource); | ||
47 | - return err; | ||
48 | - } | ||
49 | + if (err) { | ||
50 | + pr_err("TWL4030 Resource %d group could not be read\n", | ||
51 | + rconfig->resource); | ||
52 | + return err; | ||
53 | + } | ||
54 | |||
55 | - if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) { | ||
56 | - grp &= ~DEV_GRP_MASK; | ||
57 | - grp |= rconfig->devgroup << DEV_GRP_SHIFT; | ||
58 | - err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, | ||
59 | + grp_value = (grp & DEV_GRP_MASK) >> DEV_GRP_SHIFT; | ||
60 | + | ||
61 | + if (rconfig->devgroup != grp_value) { | ||
62 | + grp &= ~DEV_GRP_MASK; | ||
63 | + grp |= rconfig->devgroup << DEV_GRP_SHIFT; | ||
64 | + err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, | ||
65 | grp, rconfig_addr + DEV_GRP_OFFSET); | ||
66 | - if (err < 0) { | ||
67 | - pr_err("TWL4030 failed to program devgroup\n"); | ||
68 | - return err; | ||
69 | + if (err < 0) { | ||
70 | + pr_err("TWL4030 failed to program devgroup\n"); | ||
71 | + return err; | ||
72 | + } | ||
73 | } | ||
74 | } | ||
75 | |||
76 | /* Set resource types */ | ||
77 | - err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &type, | ||
78 | + if ((rconfig->type != TWL4030_RESCONFIG_UNDEF) || | ||
79 | + (rconfig->type2 != TWL4030_RESCONFIG_UNDEF)) { | ||
80 | + | ||
81 | + err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &type, | ||
82 | rconfig_addr + TYPE_OFFSET); | ||
83 | - if (err < 0) { | ||
84 | - pr_err("TWL4030 Resource %d type could not be read\n", | ||
85 | - rconfig->resource); | ||
86 | - return err; | ||
87 | - } | ||
88 | + if (err < 0) { | ||
89 | + pr_err("TWL4030 Resource %d type could not be read\n", | ||
90 | + rconfig->resource); | ||
91 | + return err; | ||
92 | + } | ||
93 | |||
94 | - if (rconfig->type != TWL4030_RESCONFIG_UNDEF) { | ||
95 | - type &= ~TYPE_MASK; | ||
96 | - type |= rconfig->type << TYPE_SHIFT; | ||
97 | - } | ||
98 | + type_value = type; | ||
99 | |||
100 | - if (rconfig->type2 != TWL4030_RESCONFIG_UNDEF) { | ||
101 | - type &= ~TYPE2_MASK; | ||
102 | - type |= rconfig->type2 << TYPE2_SHIFT; | ||
103 | - } | ||
104 | + if (rconfig->type != TWL4030_RESCONFIG_UNDEF) { | ||
105 | + type &= ~TYPE_MASK; | ||
106 | + type |= rconfig->type << TYPE_SHIFT; | ||
107 | + } | ||
108 | |||
109 | - err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, | ||
110 | + if (rconfig->type2 != TWL4030_RESCONFIG_UNDEF) { | ||
111 | + type &= ~TYPE2_MASK; | ||
112 | + type |= rconfig->type2 << TYPE2_SHIFT; | ||
113 | + } | ||
114 | + | ||
115 | + if (type != type_value) { | ||
116 | + err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, | ||
117 | type, rconfig_addr + TYPE_OFFSET); | ||
118 | - if (err < 0) { | ||
119 | - pr_err("TWL4030 failed to program resource type\n"); | ||
120 | - return err; | ||
121 | + if (err < 0) { | ||
122 | + pr_err("TWL4030 failed to program resource type\n"); | ||
123 | + return err; | ||
124 | + } | ||
125 | + } | ||
126 | } | ||
127 | |||
128 | /* Set remap states */ | ||
129 | - err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &remap, | ||
130 | + if ((rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) || | ||
131 | + (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF)) { | ||
132 | + err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &remap, | ||
133 | rconfig_addr + REMAP_OFFSET); | ||
134 | - if (err < 0) { | ||
135 | - pr_err("TWL4030 Resource %d remap could not be read\n", | ||
136 | - rconfig->resource); | ||
137 | - return err; | ||
138 | - } | ||
139 | + if (err < 0) { | ||
140 | + pr_err("TWL4030 Resource %d remap could not be read\n", | ||
141 | + rconfig->resource); | ||
142 | + return err; | ||
143 | + } | ||
144 | |||
145 | - if (rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) { | ||
146 | - remap &= ~OFF_STATE_MASK; | ||
147 | - remap |= rconfig->remap_off << OFF_STATE_SHIFT; | ||
148 | - } | ||
149 | + remap_value = remap; | ||
150 | |||
151 | - if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) { | ||
152 | - remap &= ~SLEEP_STATE_MASK; | ||
153 | - remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT; | ||
154 | - } | ||
155 | + if (rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) { | ||
156 | + remap &= ~OFF_STATE_MASK; | ||
157 | + remap |= rconfig->remap_off << OFF_STATE_SHIFT; | ||
158 | + } | ||
159 | |||
160 | - err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, | ||
161 | - remap, | ||
162 | - rconfig_addr + REMAP_OFFSET); | ||
163 | - if (err < 0) { | ||
164 | - pr_err("TWL4030 failed to program remap\n"); | ||
165 | - return err; | ||
166 | + if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) { | ||
167 | + remap &= ~SLEEP_STATE_MASK; | ||
168 | + remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT; | ||
169 | + } | ||
170 | + | ||
171 | + if (remap != remap_value) { | ||
172 | + err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, | ||
173 | + remap, rconfig_addr + REMAP_OFFSET); | ||
174 | + if (err < 0) { | ||
175 | + pr_err("TWL4030 failed to program remap\n"); | ||
176 | + return err; | ||
177 | + } | ||
178 | + } | ||
179 | } | ||
180 | |||
181 | return 0; | ||
182 | -- | ||
183 | 1.6.6.1 | ||
184 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/musb/0001-usb-musb-Enable-DMA-mode1-RX-for-USB-Mass-Storage.patch b/recipes-kernel/linux/linux-omap-2.6.39/musb/0001-usb-musb-Enable-DMA-mode1-RX-for-USB-Mass-Storage.patch deleted file mode 100644 index a98a4da9..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/musb/0001-usb-musb-Enable-DMA-mode1-RX-for-USB-Mass-Storage.patch +++ /dev/null | |||
@@ -1,121 +0,0 @@ | |||
1 | From 2adb339e4988632379971febe5696f21d05c71f2 Mon Sep 17 00:00:00 2001 | ||
2 | From: Anand Gadiyar <gadiyar@ti.com> | ||
3 | Date: Tue, 19 Jul 2011 01:52:14 -0700 | ||
4 | Subject: [PATCH] usb: musb: Enable DMA mode1 RX for USB-Mass-Storage | ||
5 | |||
6 | This patch enables the DMA mode1 RX support. | ||
7 | This feature is enabled based on the short_not_ok flag passed from | ||
8 | gadget drivers. | ||
9 | |||
10 | This will result in a thruput performance gain of around | ||
11 | 40% for USB mass-storage/mtp use cases. | ||
12 | |||
13 | Signed-off-by: Anand Gadiyar <gadiyar@ti.com> | ||
14 | Signed-off-by: Moiz Sonasath <m-sonasath@ti.com> | ||
15 | Tested-by: Vikram Pandita <vikram.pandita@ti.com> | ||
16 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
17 | --- | ||
18 | drivers/usb/musb/musb_gadget.c | 68 ++++++++++++++++++++++++--------------- | ||
19 | 1 files changed, 42 insertions(+), 26 deletions(-) | ||
20 | |||
21 | diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c | ||
22 | index f47c201..ca32c63 100644 | ||
23 | --- a/drivers/usb/musb/musb_gadget.c | ||
24 | +++ b/drivers/usb/musb/musb_gadget.c | ||
25 | @@ -630,6 +630,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) | ||
26 | u16 len; | ||
27 | u16 csr = musb_readw(epio, MUSB_RXCSR); | ||
28 | struct musb_hw_ep *hw_ep = &musb->endpoints[epnum]; | ||
29 | + u8 use_mode_1; | ||
30 | |||
31 | if (hw_ep->is_shared_fifo) | ||
32 | musb_ep = &hw_ep->ep_in; | ||
33 | @@ -679,6 +680,18 @@ static void rxstate(struct musb *musb, struct musb_request *req) | ||
34 | |||
35 | if (csr & MUSB_RXCSR_RXPKTRDY) { | ||
36 | len = musb_readw(epio, MUSB_RXCOUNT); | ||
37 | + | ||
38 | + /* | ||
39 | + * Enable Mode 1 for RX transfers only for mass-storage | ||
40 | + * use-case, based on short_not_ok flag which is set only | ||
41 | + * from file_storage and f_mass_storage drivers | ||
42 | + */ | ||
43 | + | ||
44 | + if (request->short_not_ok && len == musb_ep->packet_sz) | ||
45 | + use_mode_1 = 1; | ||
46 | + else | ||
47 | + use_mode_1 = 0; | ||
48 | + | ||
49 | if (request->actual < request->length) { | ||
50 | #ifdef CONFIG_USB_INVENTRA_DMA | ||
51 | if (is_buffer_mapped(req)) { | ||
52 | @@ -710,37 +723,40 @@ static void rxstate(struct musb *musb, struct musb_request *req) | ||
53 | * then becomes usable as a runtime "use mode 1" hint... | ||
54 | */ | ||
55 | |||
56 | - csr |= MUSB_RXCSR_DMAENAB; | ||
57 | -#ifdef USE_MODE1 | ||
58 | - csr |= MUSB_RXCSR_AUTOCLEAR; | ||
59 | - /* csr |= MUSB_RXCSR_DMAMODE; */ | ||
60 | - | ||
61 | - /* this special sequence (enabling and then | ||
62 | - * disabling MUSB_RXCSR_DMAMODE) is required | ||
63 | - * to get DMAReq to activate | ||
64 | - */ | ||
65 | - musb_writew(epio, MUSB_RXCSR, | ||
66 | - csr | MUSB_RXCSR_DMAMODE); | ||
67 | -#else | ||
68 | - if (!musb_ep->hb_mult && | ||
69 | - musb_ep->hw_ep->rx_double_buffered) | ||
70 | + /* Experimental: Mode1 works with mass storage use cases */ | ||
71 | + if (use_mode_1) { | ||
72 | csr |= MUSB_RXCSR_AUTOCLEAR; | ||
73 | -#endif | ||
74 | - musb_writew(epio, MUSB_RXCSR, csr); | ||
75 | + musb_writew(epio, MUSB_RXCSR, csr); | ||
76 | + csr |= MUSB_RXCSR_DMAENAB; | ||
77 | + musb_writew(epio, MUSB_RXCSR, csr); | ||
78 | + | ||
79 | + /* this special sequence (enabling and then | ||
80 | + * disabling MUSB_RXCSR_DMAMODE) is required | ||
81 | + * to get DMAReq to activate | ||
82 | + */ | ||
83 | + musb_writew(epio, MUSB_RXCSR, | ||
84 | + csr | MUSB_RXCSR_DMAMODE); | ||
85 | + musb_writew(epio, MUSB_RXCSR, csr); | ||
86 | + | ||
87 | + } else { | ||
88 | + if (!musb_ep->hb_mult && | ||
89 | + musb_ep->hw_ep->rx_double_buffered) | ||
90 | + csr |= MUSB_RXCSR_AUTOCLEAR; | ||
91 | + csr |= MUSB_RXCSR_DMAENAB; | ||
92 | + musb_writew(epio, MUSB_RXCSR, csr); | ||
93 | + } | ||
94 | |||
95 | if (request->actual < request->length) { | ||
96 | int transfer_size = 0; | ||
97 | -#ifdef USE_MODE1 | ||
98 | - transfer_size = min(request->length - request->actual, | ||
99 | - channel->max_len); | ||
100 | -#else | ||
101 | - transfer_size = min(request->length - request->actual, | ||
102 | - (unsigned)len); | ||
103 | -#endif | ||
104 | - if (transfer_size <= musb_ep->packet_sz) | ||
105 | - musb_ep->dma->desired_mode = 0; | ||
106 | - else | ||
107 | + if (use_mode_1) { | ||
108 | + transfer_size = min(request->length - request->actual, | ||
109 | + channel->max_len); | ||
110 | musb_ep->dma->desired_mode = 1; | ||
111 | + } else { | ||
112 | + transfer_size = min(request->length - request->actual, | ||
113 | + (unsigned)len); | ||
114 | + musb_ep->dma->desired_mode = 0; | ||
115 | + } | ||
116 | |||
117 | use_dma = c->channel_program( | ||
118 | channel, | ||
119 | -- | ||
120 | 1.6.6.1 | ||
121 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/net/0001-NFS-Revert-NFSROOT-default-mount-options.patch b/recipes-kernel/linux/linux-omap-2.6.39/net/0001-NFS-Revert-NFSROOT-default-mount-options.patch deleted file mode 100644 index 617698da..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/net/0001-NFS-Revert-NFSROOT-default-mount-options.patch +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c | ||
2 | index c541093..c4744e1 100644 | ||
3 | --- a/fs/nfs/nfsroot.c | ||
4 | +++ b/fs/nfs/nfsroot.c | ||
5 | @@ -87,7 +87,7 @@ | ||
6 | #define NFS_ROOT "/tftpboot/%s" | ||
7 | |||
8 | /* Default NFSROOT mount options. */ | ||
9 | -#define NFS_DEF_OPTIONS "udp" | ||
10 | +#define NFS_DEF_OPTIONS "vers=2,udp,rsize=4096,wsize=4096" | ||
11 | |||
12 | /* Parameters passed from the kernel command line */ | ||
13 | static char nfs_root_parms[256] __initdata = ""; | ||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0001-OMAP2-cpufreq-free-up-table-on-exit.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0001-OMAP2-cpufreq-free-up-table-on-exit.patch deleted file mode 100644 index 9e9a8a0b..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0001-OMAP2-cpufreq-free-up-table-on-exit.patch +++ /dev/null | |||
@@ -1,38 +0,0 @@ | |||
1 | From 38dd5aadc86725f6018d23679e9daa60ca0a8319 Mon Sep 17 00:00:00 2001 | ||
2 | From: Nishanth Menon <nm@ti.com> | ||
3 | Date: Thu, 12 May 2011 07:59:52 -0500 | ||
4 | Subject: [PATCH 1/6] OMAP2+: cpufreq: free up table on exit | ||
5 | |||
6 | freq_table allocated by opp_init_cpufreq_table in omap_cpu_init | ||
7 | needs to be freed in omap_cpu_exit. | ||
8 | |||
9 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
10 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
11 | --- | ||
12 | arch/arm/mach-omap2/omap2plus-cpufreq.c | 3 +++ | ||
13 | 1 files changed, 3 insertions(+), 0 deletions(-) | ||
14 | |||
15 | diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
16 | index d53ce23..e38ebb8 100644 | ||
17 | --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
18 | +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
19 | @@ -26,6 +26,7 @@ | ||
20 | #include <linux/clk.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/opp.h> | ||
23 | +#include <linux/slab.h> | ||
24 | #include <linux/cpu.h> | ||
25 | |||
26 | #include <asm/system.h> | ||
27 | @@ -216,6 +217,8 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
28 | static int omap_cpu_exit(struct cpufreq_policy *policy) | ||
29 | { | ||
30 | clk_exit_cpufreq_table(&freq_table); | ||
31 | + kfree(freq_table); | ||
32 | + freq_table = NULL; | ||
33 | clk_put(mpu_clk); | ||
34 | return 0; | ||
35 | } | ||
36 | -- | ||
37 | 1.6.6.1 | ||
38 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0002-OMAP2-cpufreq-handle-invalid-cpufreq-table.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0002-OMAP2-cpufreq-handle-invalid-cpufreq-table.patch deleted file mode 100644 index 087724d1..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0002-OMAP2-cpufreq-handle-invalid-cpufreq-table.patch +++ /dev/null | |||
@@ -1,44 +0,0 @@ | |||
1 | From 5febdc0482e545c2a598f035c5e03931e0c3c808 Mon Sep 17 00:00:00 2001 | ||
2 | From: Nishanth Menon <nm@ti.com> | ||
3 | Date: Thu, 12 May 2011 08:14:41 -0500 | ||
4 | Subject: [PATCH 2/6] OMAP2+: cpufreq: handle invalid cpufreq table | ||
5 | |||
6 | Handle the case when cpufreq_frequency_table_cpuinfo fails. freq_table | ||
7 | that we passed failed the internal test of cpufreq generic driver, | ||
8 | so we should'nt be using the freq_table as such. Instead, warn and | ||
9 | fallback to clock functions for validation and operation. | ||
10 | |||
11 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
12 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
13 | --- | ||
14 | arch/arm/mach-omap2/omap2plus-cpufreq.c | 12 ++++++++++-- | ||
15 | 1 files changed, 10 insertions(+), 2 deletions(-) | ||
16 | |||
17 | diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
18 | index e38ebb8..6e3666a 100644 | ||
19 | --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
20 | +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
21 | @@ -182,10 +182,18 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
22 | |||
23 | if (freq_table) { | ||
24 | result = cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
25 | - if (!result) | ||
26 | + if (!result) { | ||
27 | cpufreq_frequency_table_get_attr(freq_table, | ||
28 | policy->cpu); | ||
29 | - } else { | ||
30 | + } else { | ||
31 | + WARN(true, "%s: fallback to clk_round(freq_table=%d)\n", | ||
32 | + __func__, result); | ||
33 | + kfree(freq_table); | ||
34 | + freq_table = NULL; | ||
35 | + } | ||
36 | + } | ||
37 | + | ||
38 | + if (!freq_table) { | ||
39 | policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; | ||
40 | policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, | ||
41 | VERY_HI_RATE) / 1000; | ||
42 | -- | ||
43 | 1.6.6.1 | ||
44 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0003-OMAP2-cpufreq-minor-comment-cleanup.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0003-OMAP2-cpufreq-minor-comment-cleanup.patch deleted file mode 100644 index 4f4cdb14..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0003-OMAP2-cpufreq-minor-comment-cleanup.patch +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | From aef7e862873e6125159a18d22a2e37b1fbab2153 Mon Sep 17 00:00:00 2001 | ||
2 | From: Nishanth Menon <nm@ti.com> | ||
3 | Date: Thu, 12 May 2011 16:27:45 -0700 | ||
4 | Subject: [PATCH 3/6] OMAP2+: cpufreq: minor comment cleanup | ||
5 | |||
6 | this should probably get squashed in.. | ||
7 | |||
8 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
9 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
10 | --- | ||
11 | arch/arm/mach-omap2/omap2plus-cpufreq.c | 6 ++++-- | ||
12 | 1 files changed, 4 insertions(+), 2 deletions(-) | ||
13 | |||
14 | diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
15 | index 6e3666a..45f1e9e 100644 | ||
16 | --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
17 | +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
18 | @@ -84,8 +84,10 @@ static int omap_target(struct cpufreq_policy *policy, | ||
19 | if (is_smp() && (num_online_cpus() < NR_CPUS)) | ||
20 | return ret; | ||
21 | |||
22 | - /* Ensure desired rate is within allowed range. Some govenors | ||
23 | - * (ondemand) will just pass target_freq=0 to get the minimum. */ | ||
24 | + /* | ||
25 | + * Ensure desired rate is within allowed range. Some govenors | ||
26 | + * (ondemand) will just pass target_freq=0 to get the minimum. | ||
27 | + */ | ||
28 | if (target_freq < policy->min) | ||
29 | target_freq = policy->min; | ||
30 | if (target_freq > policy->max) | ||
31 | -- | ||
32 | 1.6.6.1 | ||
33 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0004-OMAP2-cpufreq-use-clk_init_cpufreq_table-if-OPPs-not.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0004-OMAP2-cpufreq-use-clk_init_cpufreq_table-if-OPPs-not.patch deleted file mode 100644 index dd23c082..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0004-OMAP2-cpufreq-use-clk_init_cpufreq_table-if-OPPs-not.patch +++ /dev/null | |||
@@ -1,48 +0,0 @@ | |||
1 | From f231980dbd0f05229f2020e59b7242872576416f Mon Sep 17 00:00:00 2001 | ||
2 | From: Nishanth Menon <nm@ti.com> | ||
3 | Date: Fri, 13 May 2011 05:34:35 -0700 | ||
4 | Subject: [PATCH 4/6] OMAP2: cpufreq: use clk_init_cpufreq_table if OPPs not available | ||
5 | |||
6 | OMAP2 does not use OPP tables at the moment for DVFS. Currently, | ||
7 | we depend on opp table initialization to give us the freq_table, | ||
8 | which makes sense for OMAP3+. for OMAP2, we should be using | ||
9 | clk_init_cpufreq_table - so if the opp based frequency table | ||
10 | initilization fails, fall back to clk_init_cpufreq_table to give | ||
11 | us the table. | ||
12 | |||
13 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
14 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
15 | --- | ||
16 | arch/arm/mach-omap2/omap2plus-cpufreq.c | 9 ++++++++- | ||
17 | 1 files changed, 8 insertions(+), 1 deletions(-) | ||
18 | |||
19 | diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
20 | index 45f1e9e..854f4b3 100644 | ||
21 | --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
22 | +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
23 | @@ -180,7 +180,13 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
24 | pr_warning("%s: unable to get the mpu device\n", __func__); | ||
25 | return -EINVAL; | ||
26 | } | ||
27 | - opp_init_cpufreq_table(mpu_dev, &freq_table); | ||
28 | + | ||
29 | + /* | ||
30 | + * if we dont get cpufreq table using opp, use traditional omap2 lookup | ||
31 | + * as a fallback | ||
32 | + */ | ||
33 | + if (opp_init_cpufreq_table(mpu_dev, &freq_table)) | ||
34 | + clk_init_cpufreq_table(&freq_table); | ||
35 | |||
36 | if (freq_table) { | ||
37 | result = cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
38 | @@ -188,6 +194,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
39 | cpufreq_frequency_table_get_attr(freq_table, | ||
40 | policy->cpu); | ||
41 | } else { | ||
42 | + clk_exit_cpufreq_table(&freq_table); | ||
43 | WARN(true, "%s: fallback to clk_round(freq_table=%d)\n", | ||
44 | __func__, result); | ||
45 | kfree(freq_table); | ||
46 | -- | ||
47 | 1.6.6.1 | ||
48 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0005-OMAP2-cpufreq-use-cpufreq_frequency_table_target.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0005-OMAP2-cpufreq-use-cpufreq_frequency_table_target.patch deleted file mode 100644 index 504d1916..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0005-OMAP2-cpufreq-use-cpufreq_frequency_table_target.patch +++ /dev/null | |||
@@ -1,78 +0,0 @@ | |||
1 | From 272d76bcb22b9509ccc1b59d3a62e3930d902d17 Mon Sep 17 00:00:00 2001 | ||
2 | From: Nishanth Menon <nm@ti.com> | ||
3 | Date: Fri, 13 May 2011 05:43:49 -0700 | ||
4 | Subject: [PATCH 5/6] OMAP2+: cpufreq: use cpufreq_frequency_table_target | ||
5 | |||
6 | Use cpufreq_frequency_table_target for finding the proper target | ||
7 | instead of seeing if the frequency requested is divisible alone. | ||
8 | if we have a frequency table, we should restrict ourselves to | ||
9 | selecting the "approved" frequencies alone and only in the case | ||
10 | where the frequency table is not available should we attempt at | ||
11 | closest roundable clock frequency. | ||
12 | |||
13 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
14 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
15 | --- | ||
16 | arch/arm/mach-omap2/omap2plus-cpufreq.c | 38 ++++++++++++++++++++++-------- | ||
17 | 1 files changed, 28 insertions(+), 10 deletions(-) | ||
18 | |||
19 | diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
20 | index 854f4b3..d0b4f97 100644 | ||
21 | --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
22 | +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
23 | @@ -77,24 +77,42 @@ static int omap_target(struct cpufreq_policy *policy, | ||
24 | unsigned int target_freq, | ||
25 | unsigned int relation) | ||
26 | { | ||
27 | - int i, ret = 0; | ||
28 | + unsigned int i; | ||
29 | + int ret = 0; | ||
30 | struct cpufreq_freqs freqs; | ||
31 | |||
32 | /* Changes not allowed until all CPUs are online */ | ||
33 | if (is_smp() && (num_online_cpus() < NR_CPUS)) | ||
34 | return ret; | ||
35 | |||
36 | - /* | ||
37 | - * Ensure desired rate is within allowed range. Some govenors | ||
38 | - * (ondemand) will just pass target_freq=0 to get the minimum. | ||
39 | - */ | ||
40 | - if (target_freq < policy->min) | ||
41 | - target_freq = policy->min; | ||
42 | - if (target_freq > policy->max) | ||
43 | - target_freq = policy->max; | ||
44 | + if (freq_table) { | ||
45 | + ret = cpufreq_frequency_table_target(policy, freq_table, | ||
46 | + target_freq, relation, &i); | ||
47 | + if (ret) { | ||
48 | + pr_debug("%s: cpu%d: no freq match for %d(ret=%d)\n", | ||
49 | + __func__, policy->cpu, target_freq, ret); | ||
50 | + return ret; | ||
51 | + } | ||
52 | + freqs.new = freq_table[i].frequency; | ||
53 | + } else { | ||
54 | + /* | ||
55 | + * Ensure desired rate is within allowed range. Some govenors | ||
56 | + * (ondemand) will just pass target_freq=0 to get the minimum. | ||
57 | + */ | ||
58 | + if (target_freq < policy->min) | ||
59 | + target_freq = policy->min; | ||
60 | + if (target_freq > policy->max) | ||
61 | + target_freq = policy->max; | ||
62 | + | ||
63 | + freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; | ||
64 | + } | ||
65 | + if (!freqs.new) { | ||
66 | + pr_err("%s: cpu%d: no match for freq %d\n", __func__, | ||
67 | + policy->cpu, target_freq); | ||
68 | + return -EINVAL; | ||
69 | + } | ||
70 | |||
71 | freqs.old = omap_getspeed(policy->cpu); | ||
72 | - freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; | ||
73 | freqs.cpu = policy->cpu; | ||
74 | |||
75 | if (freqs.old == freqs.new) | ||
76 | -- | ||
77 | 1.6.6.1 | ||
78 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0006-OMAP2-cpufreq-fix-freq_table-leak.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0006-OMAP2-cpufreq-fix-freq_table-leak.patch deleted file mode 100644 index 0cb4c91f..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0006-OMAP2-cpufreq-fix-freq_table-leak.patch +++ /dev/null | |||
@@ -1,100 +0,0 @@ | |||
1 | From 42a384af80e07534913d9002ec8d9caf5d4d305c Mon Sep 17 00:00:00 2001 | ||
2 | From: Nishanth Menon <nm@ti.com> | ||
3 | Date: Wed, 18 May 2011 01:48:23 -0500 | ||
4 | Subject: [PATCH 6/6] OMAP2+: cpufreq: fix freq_table leak | ||
5 | |||
6 | Since we have two cpus the cpuinit call for cpu1 causes | ||
7 | freq_table of cpu0 to be overwritten. instead, we maintain | ||
8 | a counter to keep track of cpus who use the cpufreq table | ||
9 | allocate it once(one freq table for all CPUs) and free them | ||
10 | once the last user is done with it. | ||
11 | |||
12 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
13 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
14 | --- | ||
15 | arch/arm/mach-omap2/omap2plus-cpufreq.c | 33 ++++++++++++++++++++++++------ | ||
16 | 1 files changed, 26 insertions(+), 7 deletions(-) | ||
17 | |||
18 | diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
19 | index d0b4f97..fc3d0fb 100644 | ||
20 | --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
21 | +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
22 | @@ -42,6 +42,9 @@ | ||
23 | #define VERY_HI_RATE 900000000 | ||
24 | |||
25 | static struct cpufreq_frequency_table *freq_table; | ||
26 | +static int freq_table_users; | ||
27 | +static DEFINE_MUTEX(freq_table_lock); | ||
28 | + | ||
29 | static struct clk *mpu_clk; | ||
30 | |||
31 | static int omap_verify_speed(struct cpufreq_policy *policy) | ||
32 | @@ -172,6 +175,18 @@ skip_lpj: | ||
33 | return ret; | ||
34 | } | ||
35 | |||
36 | +static void freq_table_free(void) | ||
37 | +{ | ||
38 | + if (!freq_table_users) | ||
39 | + return; | ||
40 | + freq_table_users--; | ||
41 | + if (freq_table_users) | ||
42 | + return; | ||
43 | + clk_exit_cpufreq_table(&freq_table); | ||
44 | + kfree(freq_table); | ||
45 | + freq_table = NULL; | ||
46 | +} | ||
47 | + | ||
48 | static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
49 | { | ||
50 | int result = 0; | ||
51 | @@ -199,14 +214,18 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
52 | return -EINVAL; | ||
53 | } | ||
54 | |||
55 | + mutex_lock(&freq_table_lock); | ||
56 | /* | ||
57 | * if we dont get cpufreq table using opp, use traditional omap2 lookup | ||
58 | * as a fallback | ||
59 | */ | ||
60 | - if (opp_init_cpufreq_table(mpu_dev, &freq_table)) | ||
61 | - clk_init_cpufreq_table(&freq_table); | ||
62 | + if (!freq_table) { | ||
63 | + if (opp_init_cpufreq_table(mpu_dev, &freq_table)) | ||
64 | + clk_init_cpufreq_table(&freq_table); | ||
65 | + } | ||
66 | |||
67 | if (freq_table) { | ||
68 | + freq_table_users++; | ||
69 | result = cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
70 | if (!result) { | ||
71 | cpufreq_frequency_table_get_attr(freq_table, | ||
72 | @@ -215,10 +234,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
73 | clk_exit_cpufreq_table(&freq_table); | ||
74 | WARN(true, "%s: fallback to clk_round(freq_table=%d)\n", | ||
75 | __func__, result); | ||
76 | - kfree(freq_table); | ||
77 | - freq_table = NULL; | ||
78 | + freq_table_free(); | ||
79 | } | ||
80 | } | ||
81 | + mutex_unlock(&freq_table_lock); | ||
82 | |||
83 | if (!freq_table) { | ||
84 | policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; | ||
85 | @@ -251,9 +270,9 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
86 | |||
87 | static int omap_cpu_exit(struct cpufreq_policy *policy) | ||
88 | { | ||
89 | - clk_exit_cpufreq_table(&freq_table); | ||
90 | - kfree(freq_table); | ||
91 | - freq_table = NULL; | ||
92 | + mutex_lock(&freq_table_lock); | ||
93 | + freq_table_free(); | ||
94 | + mutex_unlock(&freq_table_lock); | ||
95 | clk_put(mpu_clk); | ||
96 | return 0; | ||
97 | } | ||
98 | -- | ||
99 | 1.6.6.1 | ||
100 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-hotplug/0001-cpufreq-helpers-for-walking-the-frequency-table.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-hotplug/0001-cpufreq-helpers-for-walking-the-frequency-table.patch deleted file mode 100644 index 576cd08f..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-hotplug/0001-cpufreq-helpers-for-walking-the-frequency-table.patch +++ /dev/null | |||
@@ -1,134 +0,0 @@ | |||
1 | From 8726f3a7218b72a1003904a24bb000b3e4f9b4d1 Mon Sep 17 00:00:00 2001 | ||
2 | From: Mike Turquette <mturquette@ti.com> | ||
3 | Date: Tue, 17 May 2011 09:35:54 -0500 | ||
4 | Subject: [PATCH 1/2] cpufreq: helpers for walking the frequency table | ||
5 | |||
6 | Two new functions for getting the next higher and next lower frequencies | ||
7 | in the cpufreq table, based upon a frequency supplied in kHz. | ||
8 | |||
9 | This is useful for cpufreq governors that do not target frequencies | ||
10 | based upon a percentage or a pre-determined value, but instead access | ||
11 | the cpufreq table directly. | ||
12 | |||
13 | Signed-off-by: Mike Turquette <mturquette@ti.com> | ||
14 | Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
15 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
16 | --- | ||
17 | drivers/cpufreq/freq_table.c | 73 ++++++++++++++++++++++++++++++++++++++++++ | ||
18 | include/linux/cpufreq.h | 9 +++++ | ||
19 | 2 files changed, 82 insertions(+), 0 deletions(-) | ||
20 | |||
21 | diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c | ||
22 | index 0543221..11a307b 100644 | ||
23 | --- a/drivers/cpufreq/freq_table.c | ||
24 | +++ b/drivers/cpufreq/freq_table.c | ||
25 | @@ -13,6 +13,7 @@ | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/cpufreq.h> | ||
29 | +#include <linux/err.h> | ||
30 | |||
31 | #define dprintk(msg...) \ | ||
32 | cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "freq-table", msg) | ||
33 | @@ -174,6 +175,78 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, | ||
34 | } | ||
35 | EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target); | ||
36 | |||
37 | +int cpufreq_frequency_table_next_lowest(struct cpufreq_policy *policy, | ||
38 | + struct cpufreq_frequency_table *table, int *index) | ||
39 | +{ | ||
40 | + unsigned int cur_freq; | ||
41 | + unsigned int next_lowest_freq; | ||
42 | + int optimal_index = -1; | ||
43 | + int i = 0; | ||
44 | + | ||
45 | + if (!policy || IS_ERR(policy) || !table || IS_ERR(table) || | ||
46 | + !index || IS_ERR(index)) | ||
47 | + return -ENOMEM; | ||
48 | + | ||
49 | + cur_freq = policy->cur; | ||
50 | + next_lowest_freq = policy->min; | ||
51 | + | ||
52 | + /* we're at the lowest frequency in the table already, bail out */ | ||
53 | + if (cur_freq == policy->min) | ||
54 | + return -EINVAL; | ||
55 | + | ||
56 | + /* walk the list, find closest freq to cur_freq that is below it */ | ||
57 | + while(table[i].frequency != CPUFREQ_TABLE_END) { | ||
58 | + if (table[i].frequency < cur_freq && | ||
59 | + table[i].frequency >= next_lowest_freq) { | ||
60 | + next_lowest_freq = table[i].frequency; | ||
61 | + optimal_index = table[i].index; | ||
62 | + } | ||
63 | + | ||
64 | + i++; | ||
65 | + } | ||
66 | + | ||
67 | + *index = optimal_index; | ||
68 | + | ||
69 | + return 0; | ||
70 | +} | ||
71 | +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_next_lowest); | ||
72 | + | ||
73 | +int cpufreq_frequency_table_next_highest(struct cpufreq_policy *policy, | ||
74 | + struct cpufreq_frequency_table *table, int *index) | ||
75 | +{ | ||
76 | + unsigned int cur_freq; | ||
77 | + unsigned int next_higher_freq; | ||
78 | + int optimal_index = -1; | ||
79 | + int i = 0; | ||
80 | + | ||
81 | + if (!policy || IS_ERR(policy) || !table || IS_ERR(table) || | ||
82 | + !index || IS_ERR(index)) | ||
83 | + return -ENOMEM; | ||
84 | + | ||
85 | + cur_freq = policy->cur; | ||
86 | + next_higher_freq = policy->max; | ||
87 | + | ||
88 | + /* we're at the highest frequency in the table already, bail out */ | ||
89 | + if (cur_freq == policy->max) | ||
90 | + return -EINVAL; | ||
91 | + | ||
92 | + /* walk the list, find closest freq to cur_freq that is above it */ | ||
93 | + while(table[i].frequency != CPUFREQ_TABLE_END) { | ||
94 | + if (table[i].frequency > cur_freq && | ||
95 | + table[i].frequency <= next_higher_freq) { | ||
96 | + next_higher_freq = table[i].frequency; | ||
97 | + optimal_index = table[i].index; | ||
98 | + } | ||
99 | + | ||
100 | + i++; | ||
101 | + } | ||
102 | + | ||
103 | + *index = optimal_index; | ||
104 | + | ||
105 | + return 0; | ||
106 | +} | ||
107 | +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_next_highest); | ||
108 | + | ||
109 | static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table); | ||
110 | /** | ||
111 | * show_available_freqs - show available frequencies for the specified CPU | ||
112 | diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h | ||
113 | index 9343dd3..a38fca8 100644 | ||
114 | --- a/include/linux/cpufreq.h | ||
115 | +++ b/include/linux/cpufreq.h | ||
116 | @@ -396,6 +396,15 @@ void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, | ||
117 | |||
118 | void cpufreq_frequency_table_put_attr(unsigned int cpu); | ||
119 | |||
120 | +/* the following are for use in governors, or anywhere else */ | ||
121 | +extern int cpufreq_frequency_table_next_lowest(struct cpufreq_policy *policy, | ||
122 | + struct cpufreq_frequency_table *table, | ||
123 | + int *index); | ||
124 | + | ||
125 | +extern int cpufreq_frequency_table_next_highest(struct cpufreq_policy *policy, | ||
126 | + struct cpufreq_frequency_table *table, | ||
127 | + int *index); | ||
128 | + | ||
129 | |||
130 | /********************************************************************* | ||
131 | * UNIFIED DEBUG HELPERS * | ||
132 | -- | ||
133 | 1.6.6.1 | ||
134 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-hotplug/0002-cpufreq-introduce-hotplug-governor.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-hotplug/0002-cpufreq-introduce-hotplug-governor.patch deleted file mode 100644 index 731906cc..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-hotplug/0002-cpufreq-introduce-hotplug-governor.patch +++ /dev/null | |||
@@ -1,879 +0,0 @@ | |||
1 | From e4c777d8314d7925e4895f00b3a7ebd64a4d830b Mon Sep 17 00:00:00 2001 | ||
2 | From: Mike Turquette <mturquette@ti.com> | ||
3 | Date: Tue, 17 May 2011 09:43:09 -0500 | ||
4 | Subject: [PATCH 2/2] cpufreq: introduce hotplug governor | ||
5 | |||
6 | The "hotplug" governor scales CPU frequency based on load, similar to | ||
7 | "ondemand". It scales up to the highest frequency when "up_threshold" | ||
8 | is crossed and scales down one frequency at a time when "down_threshold" | ||
9 | is crossed. Unlike those governors, target frequencies are determined | ||
10 | by directly accessing the CPUfreq frequency table, instead of taking | ||
11 | some percentage of maximum available frequency. | ||
12 | |||
13 | The key difference in the "hotplug" governor is that it will disable | ||
14 | auxillary CPUs when the system is very idle, and enable them again once | ||
15 | the system becomes busy. This is achieved by averaging load over | ||
16 | multiple sampling periods; if CPUs were online or offlined based on a | ||
17 | single sampling period then thrashing will occur. | ||
18 | |||
19 | Sysfs entries exist for "hotplug_in_sampling_periods" and for | ||
20 | "hotplug_out_sampling_periods" which determine how many consecutive | ||
21 | periods get averaged to determine if auxillery CPUs should be onlined or | ||
22 | offlined. Defaults are 5 periods and 20 periods respectively. | ||
23 | Otherwise the standard sysfs entries you might find for "ondemand" and | ||
24 | "conservative" governors are there. | ||
25 | |||
26 | To use this governor it is assumed that your CPUfreq driver has | ||
27 | populated the CPUfreq table, CONFIG_NO_HZ is enabled and | ||
28 | CONFIG_HOTPLUG_CPU is enabled. | ||
29 | |||
30 | Changes in V2: | ||
31 | Corrected default sampling periods | ||
32 | Optimized load history array resizing | ||
33 | Maintain load history when resizing array | ||
34 | Add locking to dbs_check_cpu | ||
35 | Switch from enable_nonboot_cpus to cpu_up | ||
36 | Switch from disable_nonboot_cpus to down_cpu | ||
37 | Fix some printks | ||
38 | Coding style around for-loops | ||
39 | |||
40 | Signed-off-by: Mike Turquette <mturquette@ti.com> | ||
41 | Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
42 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
43 | --- | ||
44 | Documentation/cpu-freq/governors.txt | 28 ++ | ||
45 | drivers/cpufreq/Kconfig | 33 ++ | ||
46 | drivers/cpufreq/Makefile | 1 + | ||
47 | drivers/cpufreq/cpufreq_hotplug.c | 705 ++++++++++++++++++++++++++++++++++ | ||
48 | include/linux/cpufreq.h | 3 + | ||
49 | 5 files changed, 770 insertions(+), 0 deletions(-) | ||
50 | create mode 100644 drivers/cpufreq/cpufreq_hotplug.c | ||
51 | |||
52 | diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt | ||
53 | index e74d0a2..c2e3d3d 100644 | ||
54 | --- a/Documentation/cpu-freq/governors.txt | ||
55 | +++ b/Documentation/cpu-freq/governors.txt | ||
56 | @@ -193,6 +193,34 @@ governor but for the opposite direction. For example when set to its | ||
57 | default value of '20' it means that if the CPU usage needs to be below | ||
58 | 20% between samples to have the frequency decreased. | ||
59 | |||
60 | + | ||
61 | +2.6 Hotplug | ||
62 | +----------- | ||
63 | + | ||
64 | +The CPUfreq governor "hotplug" operates similary to "ondemand" and | ||
65 | +"conservative". It's decisions are based primarily on CPU load. Like | ||
66 | +"ondemand" the "hotplug" governor will ramp up to the highest frequency | ||
67 | +once the run-time tunable "up_threshold" parameter is crossed. Like | ||
68 | +"conservative", the "hotplug" governor exports a "down_threshold" | ||
69 | +parameter that is also tunable at run-time. When the "down_threshold" | ||
70 | +is crossed the CPU transitions to the next lowest frequency in the | ||
71 | +CPUfreq frequency table instead of decrementing the frequency based on a | ||
72 | +percentage of maximum load. | ||
73 | + | ||
74 | +The main reason "hotplug" governor exists is for architectures requiring | ||
75 | +that only the master CPU be online in order to hit low-power states | ||
76 | +(C-states). OMAP4 is one such example of this. The "hotplug" governor | ||
77 | +is also helpful in reducing thermal output in devices with tight thermal | ||
78 | +constraints. | ||
79 | + | ||
80 | +Auxillary CPUs are onlined/offline based on CPU load, but the decision | ||
81 | +to do so is made after averaging several sampling windows. This is to | ||
82 | +reduce CPU hotplug "thrashing", which can be caused by normal system | ||
83 | +entropy and leads to lots of spurious plug-in and plug-out transitions. | ||
84 | +The number of sampling periods averaged together is tunable via the | ||
85 | +"hotplug_in_sampling_periods" and "hotplug_out_sampling_periods" | ||
86 | +run-time tunable parameters. | ||
87 | + | ||
88 | 3. The Governor Interface in the CPUfreq Core | ||
89 | ============================================= | ||
90 | |||
91 | diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig | ||
92 | index ca8ee80..c716a0e 100644 | ||
93 | --- a/drivers/cpufreq/Kconfig | ||
94 | +++ b/drivers/cpufreq/Kconfig | ||
95 | @@ -110,6 +110,19 @@ config CPU_FREQ_DEFAULT_GOV_CONSERVATIVE | ||
96 | Be aware that not all cpufreq drivers support the conservative | ||
97 | governor. If unsure have a look at the help section of the | ||
98 | driver. Fallback governor will be the performance governor. | ||
99 | + | ||
100 | +config CPU_FREQ_DEFAULT_GOV_HOTPLUG | ||
101 | + bool "hotplug" | ||
102 | + select CPU_FREQ_GOV_HOTPLUG | ||
103 | + select CPU_FREQ_GOV_PERFORMANCE | ||
104 | + help | ||
105 | + Use the CPUFreq governor 'hotplug' as default. This allows you | ||
106 | + to get a full dynamic frequency capable system with CPU | ||
107 | + hotplug support by simply loading your cpufreq low-level | ||
108 | + hardware driver. Be aware that not all cpufreq drivers | ||
109 | + support the hotplug governor. If unsure have a look at | ||
110 | + the help section of the driver. Fallback governor will be the | ||
111 | + performance governor. | ||
112 | endchoice | ||
113 | |||
114 | config CPU_FREQ_GOV_PERFORMANCE | ||
115 | @@ -190,4 +203,24 @@ config CPU_FREQ_GOV_CONSERVATIVE | ||
116 | |||
117 | If in doubt, say N. | ||
118 | |||
119 | +config CPU_FREQ_GOV_HOTPLUG | ||
120 | + tristate "'hotplug' cpufreq governor" | ||
121 | + depends on CPU_FREQ && NO_HZ && HOTPLUG_CPU | ||
122 | + help | ||
123 | + 'hotplug' - this driver mimics the frequency scaling behavior | ||
124 | + in 'ondemand', but with several key differences. First is | ||
125 | + that frequency transitions use the CPUFreq table directly, | ||
126 | + instead of incrementing in a percentage of the maximum | ||
127 | + available frequency. Second 'hotplug' will offline auxillary | ||
128 | + CPUs when the system is idle, and online those CPUs once the | ||
129 | + system becomes busy again. This last feature is needed for | ||
130 | + architectures which transition to low power states when only | ||
131 | + the "master" CPU is online, or for thermally constrained | ||
132 | + devices. | ||
133 | + | ||
134 | + If you don't have one of these architectures or devices, use | ||
135 | + 'ondemand' instead. | ||
136 | + | ||
137 | + If in doubt, say N. | ||
138 | + | ||
139 | endif # CPU_FREQ | ||
140 | diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile | ||
141 | index 71fc3b4..05d564c 100644 | ||
142 | --- a/drivers/cpufreq/Makefile | ||
143 | +++ b/drivers/cpufreq/Makefile | ||
144 | @@ -9,6 +9,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o | ||
145 | obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o | ||
146 | obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o | ||
147 | obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o | ||
148 | +obj-$(CONFIG_CPU_FREQ_GOV_HOTPLUG) += cpufreq_hotplug.o | ||
149 | |||
150 | # CPUfreq cross-arch helpers | ||
151 | obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o | ||
152 | diff --git a/drivers/cpufreq/cpufreq_hotplug.c b/drivers/cpufreq/cpufreq_hotplug.c | ||
153 | new file mode 100644 | ||
154 | index 0000000..85aa6d2 | ||
155 | --- /dev/null | ||
156 | +++ b/drivers/cpufreq/cpufreq_hotplug.c | ||
157 | @@ -0,0 +1,705 @@ | ||
158 | +/* | ||
159 | + * CPUFreq hotplug governor | ||
160 | + * | ||
161 | + * Copyright (C) 2010 Texas Instruments, Inc. | ||
162 | + * Mike Turquette <mturquette@ti.com> | ||
163 | + * Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
164 | + * | ||
165 | + * Based on ondemand governor | ||
166 | + * Copyright (C) 2001 Russell King | ||
167 | + * (C) 2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>, | ||
168 | + * Jun Nakajima <jun.nakajima@intel.com> | ||
169 | + * | ||
170 | + * This program is free software; you can redistribute it and/or modify | ||
171 | + * it under the terms of the GNU General Public License version 2 as | ||
172 | + * published by the Free Software Foundation. | ||
173 | + */ | ||
174 | + | ||
175 | +#include <linux/kernel.h> | ||
176 | +#include <linux/module.h> | ||
177 | +#include <linux/init.h> | ||
178 | +#include <linux/cpufreq.h> | ||
179 | +#include <linux/cpu.h> | ||
180 | +#include <linux/jiffies.h> | ||
181 | +#include <linux/kernel_stat.h> | ||
182 | +#include <linux/mutex.h> | ||
183 | +#include <linux/hrtimer.h> | ||
184 | +#include <linux/tick.h> | ||
185 | +#include <linux/ktime.h> | ||
186 | +#include <linux/sched.h> | ||
187 | +#include <linux/err.h> | ||
188 | +#include <linux/slab.h> | ||
189 | + | ||
190 | +/* greater than 80% avg load across online CPUs increases frequency */ | ||
191 | +#define DEFAULT_UP_FREQ_MIN_LOAD (80) | ||
192 | + | ||
193 | +/* less than 20% avg load across online CPUs decreases frequency */ | ||
194 | +#define DEFAULT_DOWN_FREQ_MAX_LOAD (20) | ||
195 | + | ||
196 | +/* default sampling period (uSec) is bogus; 10x ondemand's default for x86 */ | ||
197 | +#define DEFAULT_SAMPLING_PERIOD (100000) | ||
198 | + | ||
199 | +/* default number of sampling periods to average before hotplug-in decision */ | ||
200 | +#define DEFAULT_HOTPLUG_IN_SAMPLING_PERIODS (5) | ||
201 | + | ||
202 | +/* default number of sampling periods to average before hotplug-out decision */ | ||
203 | +#define DEFAULT_HOTPLUG_OUT_SAMPLING_PERIODS (20) | ||
204 | + | ||
205 | +static void do_dbs_timer(struct work_struct *work); | ||
206 | +static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | ||
207 | + unsigned int event); | ||
208 | + | ||
209 | +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_HOTPLUG | ||
210 | +static | ||
211 | +#endif | ||
212 | +struct cpufreq_governor cpufreq_gov_hotplug = { | ||
213 | + .name = "hotplug", | ||
214 | + .governor = cpufreq_governor_dbs, | ||
215 | + .owner = THIS_MODULE, | ||
216 | +}; | ||
217 | + | ||
218 | +struct cpu_dbs_info_s { | ||
219 | + cputime64_t prev_cpu_idle; | ||
220 | + cputime64_t prev_cpu_wall; | ||
221 | + cputime64_t prev_cpu_nice; | ||
222 | + struct cpufreq_policy *cur_policy; | ||
223 | + struct delayed_work work; | ||
224 | + struct cpufreq_frequency_table *freq_table; | ||
225 | + int cpu; | ||
226 | + /* | ||
227 | + * percpu mutex that serializes governor limit change with | ||
228 | + * do_dbs_timer invocation. We do not want do_dbs_timer to run | ||
229 | + * when user is changing the governor or limits. | ||
230 | + */ | ||
231 | + struct mutex timer_mutex; | ||
232 | +}; | ||
233 | +static DEFINE_PER_CPU(struct cpu_dbs_info_s, hp_cpu_dbs_info); | ||
234 | + | ||
235 | +static unsigned int dbs_enable; /* number of CPUs using this policy */ | ||
236 | + | ||
237 | +/* | ||
238 | + * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on | ||
239 | + * different CPUs. It protects dbs_enable in governor start/stop. | ||
240 | + */ | ||
241 | +static DEFINE_MUTEX(dbs_mutex); | ||
242 | + | ||
243 | +static struct workqueue_struct *khotplug_wq; | ||
244 | + | ||
245 | +static struct dbs_tuners { | ||
246 | + unsigned int sampling_rate; | ||
247 | + unsigned int up_threshold; | ||
248 | + unsigned int down_threshold; | ||
249 | + unsigned int hotplug_in_sampling_periods; | ||
250 | + unsigned int hotplug_out_sampling_periods; | ||
251 | + unsigned int hotplug_load_index; | ||
252 | + unsigned int *hotplug_load_history; | ||
253 | + unsigned int ignore_nice; | ||
254 | + unsigned int io_is_busy; | ||
255 | +} dbs_tuners_ins = { | ||
256 | + .sampling_rate = DEFAULT_SAMPLING_PERIOD, | ||
257 | + .up_threshold = DEFAULT_UP_FREQ_MIN_LOAD, | ||
258 | + .down_threshold = DEFAULT_DOWN_FREQ_MAX_LOAD, | ||
259 | + .hotplug_in_sampling_periods = DEFAULT_HOTPLUG_IN_SAMPLING_PERIODS, | ||
260 | + .hotplug_out_sampling_periods = DEFAULT_HOTPLUG_OUT_SAMPLING_PERIODS, | ||
261 | + .hotplug_load_index = 0, | ||
262 | + .ignore_nice = 0, | ||
263 | + .io_is_busy = 0, | ||
264 | +}; | ||
265 | + | ||
266 | +/* | ||
267 | + * A corner case exists when switching io_is_busy at run-time: comparing idle | ||
268 | + * times from a non-io_is_busy period to an io_is_busy period (or vice-versa) | ||
269 | + * will misrepresent the actual change in system idleness. We ignore this | ||
270 | + * corner case: enabling io_is_busy might cause freq increase and disabling | ||
271 | + * might cause freq decrease, which probably matches the original intent. | ||
272 | + */ | ||
273 | +static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall) | ||
274 | +{ | ||
275 | + u64 idle_time; | ||
276 | + u64 iowait_time; | ||
277 | + | ||
278 | + /* cpufreq-hotplug always assumes CONFIG_NO_HZ */ | ||
279 | + idle_time = get_cpu_idle_time_us(cpu, wall); | ||
280 | + | ||
281 | + /* add time spent doing I/O to idle time */ | ||
282 | + if (dbs_tuners_ins.io_is_busy) { | ||
283 | + iowait_time = get_cpu_iowait_time_us(cpu, wall); | ||
284 | + /* cpufreq-hotplug always assumes CONFIG_NO_HZ */ | ||
285 | + if (iowait_time != -1ULL && idle_time >= iowait_time) | ||
286 | + idle_time -= iowait_time; | ||
287 | + } | ||
288 | + | ||
289 | + return idle_time; | ||
290 | +} | ||
291 | + | ||
292 | +/************************** sysfs interface ************************/ | ||
293 | + | ||
294 | +/* XXX look at global sysfs macros in cpufreq.h, can those be used here? */ | ||
295 | + | ||
296 | +/* cpufreq_hotplug Governor Tunables */ | ||
297 | +#define show_one(file_name, object) \ | ||
298 | +static ssize_t show_##file_name \ | ||
299 | +(struct kobject *kobj, struct attribute *attr, char *buf) \ | ||
300 | +{ \ | ||
301 | + return sprintf(buf, "%u\n", dbs_tuners_ins.object); \ | ||
302 | +} | ||
303 | +show_one(sampling_rate, sampling_rate); | ||
304 | +show_one(up_threshold, up_threshold); | ||
305 | +show_one(down_threshold, down_threshold); | ||
306 | +show_one(hotplug_in_sampling_periods, hotplug_in_sampling_periods); | ||
307 | +show_one(hotplug_out_sampling_periods, hotplug_out_sampling_periods); | ||
308 | +show_one(ignore_nice_load, ignore_nice); | ||
309 | +show_one(io_is_busy, io_is_busy); | ||
310 | + | ||
311 | +static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b, | ||
312 | + const char *buf, size_t count) | ||
313 | +{ | ||
314 | + unsigned int input; | ||
315 | + int ret; | ||
316 | + ret = sscanf(buf, "%u", &input); | ||
317 | + if (ret != 1) | ||
318 | + return -EINVAL; | ||
319 | + | ||
320 | + mutex_lock(&dbs_mutex); | ||
321 | + dbs_tuners_ins.sampling_rate = input; | ||
322 | + mutex_unlock(&dbs_mutex); | ||
323 | + | ||
324 | + return count; | ||
325 | +} | ||
326 | + | ||
327 | +static ssize_t store_up_threshold(struct kobject *a, struct attribute *b, | ||
328 | + const char *buf, size_t count) | ||
329 | +{ | ||
330 | + unsigned int input; | ||
331 | + int ret; | ||
332 | + ret = sscanf(buf, "%u", &input); | ||
333 | + | ||
334 | + if (ret != 1 || input <= dbs_tuners_ins.down_threshold) { | ||
335 | + return -EINVAL; | ||
336 | + } | ||
337 | + | ||
338 | + mutex_lock(&dbs_mutex); | ||
339 | + dbs_tuners_ins.up_threshold = input; | ||
340 | + mutex_unlock(&dbs_mutex); | ||
341 | + | ||
342 | + return count; | ||
343 | +} | ||
344 | + | ||
345 | +static ssize_t store_down_threshold(struct kobject *a, struct attribute *b, | ||
346 | + const char *buf, size_t count) | ||
347 | +{ | ||
348 | + unsigned int input; | ||
349 | + int ret; | ||
350 | + ret = sscanf(buf, "%u", &input); | ||
351 | + | ||
352 | + if (ret != 1 || input >= dbs_tuners_ins.up_threshold) { | ||
353 | + return -EINVAL; | ||
354 | + } | ||
355 | + | ||
356 | + mutex_lock(&dbs_mutex); | ||
357 | + dbs_tuners_ins.down_threshold = input; | ||
358 | + mutex_unlock(&dbs_mutex); | ||
359 | + | ||
360 | + return count; | ||
361 | +} | ||
362 | + | ||
363 | +static ssize_t store_hotplug_in_sampling_periods(struct kobject *a, | ||
364 | + struct attribute *b, const char *buf, size_t count) | ||
365 | +{ | ||
366 | + unsigned int input; | ||
367 | + unsigned int *temp; | ||
368 | + unsigned int max_windows; | ||
369 | + int ret; | ||
370 | + ret = sscanf(buf, "%u", &input); | ||
371 | + | ||
372 | + if (ret != 1) | ||
373 | + return -EINVAL; | ||
374 | + | ||
375 | + /* already using this value, bail out */ | ||
376 | + if (input == dbs_tuners_ins.hotplug_in_sampling_periods) | ||
377 | + return count; | ||
378 | + | ||
379 | + mutex_lock(&dbs_mutex); | ||
380 | + ret = count; | ||
381 | + max_windows = max(dbs_tuners_ins.hotplug_in_sampling_periods, | ||
382 | + dbs_tuners_ins.hotplug_out_sampling_periods); | ||
383 | + | ||
384 | + /* no need to resize array */ | ||
385 | + if (input <= max_windows) { | ||
386 | + dbs_tuners_ins.hotplug_in_sampling_periods = input; | ||
387 | + goto out; | ||
388 | + } | ||
389 | + | ||
390 | + /* resize array */ | ||
391 | + temp = kmalloc((sizeof(unsigned int) * input), GFP_KERNEL); | ||
392 | + | ||
393 | + if (!temp || IS_ERR(temp)) { | ||
394 | + ret = -ENOMEM; | ||
395 | + goto out; | ||
396 | + } | ||
397 | + | ||
398 | + memcpy(temp, dbs_tuners_ins.hotplug_load_history, | ||
399 | + (max_windows * sizeof(unsigned int))); | ||
400 | + kfree(dbs_tuners_ins.hotplug_load_history); | ||
401 | + | ||
402 | + /* replace old buffer, old number of sampling periods & old index */ | ||
403 | + dbs_tuners_ins.hotplug_load_history = temp; | ||
404 | + dbs_tuners_ins.hotplug_in_sampling_periods = input; | ||
405 | + dbs_tuners_ins.hotplug_load_index = max_windows; | ||
406 | +out: | ||
407 | + mutex_unlock(&dbs_mutex); | ||
408 | + | ||
409 | + return ret; | ||
410 | +} | ||
411 | + | ||
412 | +static ssize_t store_hotplug_out_sampling_periods(struct kobject *a, | ||
413 | + struct attribute *b, const char *buf, size_t count) | ||
414 | +{ | ||
415 | + unsigned int input; | ||
416 | + unsigned int *temp; | ||
417 | + unsigned int max_windows; | ||
418 | + int ret; | ||
419 | + ret = sscanf(buf, "%u", &input); | ||
420 | + | ||
421 | + if (ret != 1) | ||
422 | + return -EINVAL; | ||
423 | + | ||
424 | + /* already using this value, bail out */ | ||
425 | + if (input == dbs_tuners_ins.hotplug_out_sampling_periods) | ||
426 | + return count; | ||
427 | + | ||
428 | + mutex_lock(&dbs_mutex); | ||
429 | + ret = count; | ||
430 | + max_windows = max(dbs_tuners_ins.hotplug_in_sampling_periods, | ||
431 | + dbs_tuners_ins.hotplug_out_sampling_periods); | ||
432 | + | ||
433 | + /* no need to resize array */ | ||
434 | + if (input <= max_windows) { | ||
435 | + dbs_tuners_ins.hotplug_out_sampling_periods = input; | ||
436 | + goto out; | ||
437 | + } | ||
438 | + | ||
439 | + /* resize array */ | ||
440 | + temp = kmalloc((sizeof(unsigned int) * input), GFP_KERNEL); | ||
441 | + | ||
442 | + if (!temp || IS_ERR(temp)) { | ||
443 | + ret = -ENOMEM; | ||
444 | + goto out; | ||
445 | + } | ||
446 | + | ||
447 | + memcpy(temp, dbs_tuners_ins.hotplug_load_history, | ||
448 | + (max_windows * sizeof(unsigned int))); | ||
449 | + kfree(dbs_tuners_ins.hotplug_load_history); | ||
450 | + | ||
451 | + /* replace old buffer, old number of sampling periods & old index */ | ||
452 | + dbs_tuners_ins.hotplug_load_history = temp; | ||
453 | + dbs_tuners_ins.hotplug_out_sampling_periods = input; | ||
454 | + dbs_tuners_ins.hotplug_load_index = max_windows; | ||
455 | +out: | ||
456 | + mutex_unlock(&dbs_mutex); | ||
457 | + | ||
458 | + return ret; | ||
459 | +} | ||
460 | + | ||
461 | +static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b, | ||
462 | + const char *buf, size_t count) | ||
463 | +{ | ||
464 | + unsigned int input; | ||
465 | + int ret; | ||
466 | + | ||
467 | + unsigned int j; | ||
468 | + | ||
469 | + ret = sscanf(buf, "%u", &input); | ||
470 | + if (ret != 1) | ||
471 | + return -EINVAL; | ||
472 | + | ||
473 | + if (input > 1) | ||
474 | + input = 1; | ||
475 | + | ||
476 | + mutex_lock(&dbs_mutex); | ||
477 | + if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */ | ||
478 | + mutex_unlock(&dbs_mutex); | ||
479 | + return count; | ||
480 | + } | ||
481 | + dbs_tuners_ins.ignore_nice = input; | ||
482 | + | ||
483 | + /* we need to re-evaluate prev_cpu_idle */ | ||
484 | + for_each_online_cpu(j) { | ||
485 | + struct cpu_dbs_info_s *dbs_info; | ||
486 | + dbs_info = &per_cpu(hp_cpu_dbs_info, j); | ||
487 | + dbs_info->prev_cpu_idle = get_cpu_idle_time(j, | ||
488 | + &dbs_info->prev_cpu_wall); | ||
489 | + if (dbs_tuners_ins.ignore_nice) | ||
490 | + dbs_info->prev_cpu_nice = kstat_cpu(j).cpustat.nice; | ||
491 | + | ||
492 | + } | ||
493 | + mutex_unlock(&dbs_mutex); | ||
494 | + | ||
495 | + return count; | ||
496 | +} | ||
497 | + | ||
498 | +static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b, | ||
499 | + const char *buf, size_t count) | ||
500 | +{ | ||
501 | + unsigned int input; | ||
502 | + int ret; | ||
503 | + | ||
504 | + ret = sscanf(buf, "%u", &input); | ||
505 | + if (ret != 1) | ||
506 | + return -EINVAL; | ||
507 | + | ||
508 | + mutex_lock(&dbs_mutex); | ||
509 | + dbs_tuners_ins.io_is_busy = !!input; | ||
510 | + mutex_unlock(&dbs_mutex); | ||
511 | + | ||
512 | + return count; | ||
513 | +} | ||
514 | + | ||
515 | +define_one_global_rw(sampling_rate); | ||
516 | +define_one_global_rw(up_threshold); | ||
517 | +define_one_global_rw(down_threshold); | ||
518 | +define_one_global_rw(hotplug_in_sampling_periods); | ||
519 | +define_one_global_rw(hotplug_out_sampling_periods); | ||
520 | +define_one_global_rw(ignore_nice_load); | ||
521 | +define_one_global_rw(io_is_busy); | ||
522 | + | ||
523 | +static struct attribute *dbs_attributes[] = { | ||
524 | + &sampling_rate.attr, | ||
525 | + &up_threshold.attr, | ||
526 | + &down_threshold.attr, | ||
527 | + &hotplug_in_sampling_periods.attr, | ||
528 | + &hotplug_out_sampling_periods.attr, | ||
529 | + &ignore_nice_load.attr, | ||
530 | + &io_is_busy.attr, | ||
531 | + NULL | ||
532 | +}; | ||
533 | + | ||
534 | +static struct attribute_group dbs_attr_group = { | ||
535 | + .attrs = dbs_attributes, | ||
536 | + .name = "hotplug", | ||
537 | +}; | ||
538 | + | ||
539 | +/************************** sysfs end ************************/ | ||
540 | + | ||
541 | +static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) | ||
542 | +{ | ||
543 | + /* combined load of all enabled CPUs */ | ||
544 | + unsigned int total_load = 0; | ||
545 | + /* single largest CPU load */ | ||
546 | + unsigned int max_load = 0; | ||
547 | + /* average load across all enabled CPUs */ | ||
548 | + unsigned int avg_load = 0; | ||
549 | + /* average load across multiple sampling periods for hotplug events */ | ||
550 | + unsigned int hotplug_in_avg_load = 0; | ||
551 | + unsigned int hotplug_out_avg_load = 0; | ||
552 | + /* number of sampling periods averaged for hotplug decisions */ | ||
553 | + unsigned int periods; | ||
554 | + | ||
555 | + struct cpufreq_policy *policy; | ||
556 | + unsigned int index = 0; | ||
557 | + unsigned int i, j; | ||
558 | + | ||
559 | + policy = this_dbs_info->cur_policy; | ||
560 | + | ||
561 | + /* | ||
562 | + * cpu load accounting | ||
563 | + * get highest load, total load and average load across all CPUs | ||
564 | + */ | ||
565 | + for_each_cpu(j, policy->cpus) { | ||
566 | + unsigned int load; | ||
567 | + unsigned int idle_time, wall_time; | ||
568 | + cputime64_t cur_wall_time, cur_idle_time; | ||
569 | + struct cpu_dbs_info_s *j_dbs_info; | ||
570 | + | ||
571 | + j_dbs_info = &per_cpu(hp_cpu_dbs_info, j); | ||
572 | + | ||
573 | + /* update both cur_idle_time and cur_wall_time */ | ||
574 | + cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); | ||
575 | + | ||
576 | + /* how much wall time has passed since last iteration? */ | ||
577 | + wall_time = (unsigned int) cputime64_sub(cur_wall_time, | ||
578 | + j_dbs_info->prev_cpu_wall); | ||
579 | + j_dbs_info->prev_cpu_wall = cur_wall_time; | ||
580 | + | ||
581 | + /* how much idle time has passed since last iteration? */ | ||
582 | + idle_time = (unsigned int) cputime64_sub(cur_idle_time, | ||
583 | + j_dbs_info->prev_cpu_idle); | ||
584 | + j_dbs_info->prev_cpu_idle = cur_idle_time; | ||
585 | + | ||
586 | + if (unlikely(!wall_time || wall_time < idle_time)) | ||
587 | + continue; | ||
588 | + | ||
589 | + /* load is the percentage of time not spent in idle */ | ||
590 | + load = 100 * (wall_time - idle_time) / wall_time; | ||
591 | + | ||
592 | + /* keep track of combined load across all CPUs */ | ||
593 | + total_load += load; | ||
594 | + | ||
595 | + /* keep track of highest single load across all CPUs */ | ||
596 | + if (load > max_load) | ||
597 | + max_load = load; | ||
598 | + } | ||
599 | + | ||
600 | + /* calculate the average load across all related CPUs */ | ||
601 | + avg_load = total_load / num_online_cpus(); | ||
602 | + | ||
603 | + | ||
604 | + /* | ||
605 | + * hotplug load accounting | ||
606 | + * average load over multiple sampling periods | ||
607 | + */ | ||
608 | + | ||
609 | + /* how many sampling periods do we use for hotplug decisions? */ | ||
610 | + periods = max(dbs_tuners_ins.hotplug_in_sampling_periods, | ||
611 | + dbs_tuners_ins.hotplug_out_sampling_periods); | ||
612 | + | ||
613 | + /* store avg_load in the circular buffer */ | ||
614 | + dbs_tuners_ins.hotplug_load_history[dbs_tuners_ins.hotplug_load_index] | ||
615 | + = avg_load; | ||
616 | + | ||
617 | + /* compute average load across in & out sampling periods */ | ||
618 | + for (i = 0, j = dbs_tuners_ins.hotplug_load_index; | ||
619 | + i < periods; i++, j--) { | ||
620 | + if (i < dbs_tuners_ins.hotplug_in_sampling_periods) | ||
621 | + hotplug_in_avg_load += | ||
622 | + dbs_tuners_ins.hotplug_load_history[j]; | ||
623 | + if (i < dbs_tuners_ins.hotplug_out_sampling_periods) | ||
624 | + hotplug_out_avg_load += | ||
625 | + dbs_tuners_ins.hotplug_load_history[j]; | ||
626 | + | ||
627 | + if (j == 0) | ||
628 | + j = periods; | ||
629 | + } | ||
630 | + | ||
631 | + hotplug_in_avg_load = hotplug_in_avg_load / | ||
632 | + dbs_tuners_ins.hotplug_in_sampling_periods; | ||
633 | + | ||
634 | + hotplug_out_avg_load = hotplug_out_avg_load / | ||
635 | + dbs_tuners_ins.hotplug_out_sampling_periods; | ||
636 | + | ||
637 | + /* return to first element if we're at the circular buffer's end */ | ||
638 | + if (++dbs_tuners_ins.hotplug_load_index == periods) | ||
639 | + dbs_tuners_ins.hotplug_load_index = 0; | ||
640 | + | ||
641 | + /* check for frequency increase */ | ||
642 | + if (avg_load > dbs_tuners_ins.up_threshold) { | ||
643 | + /* should we enable auxillary CPUs? */ | ||
644 | + if (num_online_cpus() < 2 && hotplug_in_avg_load > | ||
645 | + dbs_tuners_ins.up_threshold) { | ||
646 | + /* hotplug with cpufreq is nasty | ||
647 | + * a call to cpufreq_governor_dbs may cause a lockup. | ||
648 | + * wq is not running here so its safe. | ||
649 | + */ | ||
650 | + mutex_unlock(&this_dbs_info->timer_mutex); | ||
651 | + cpu_up(1); | ||
652 | + mutex_lock(&this_dbs_info->timer_mutex); | ||
653 | + goto out; | ||
654 | + } | ||
655 | + | ||
656 | + /* increase to highest frequency supported */ | ||
657 | + if (policy->cur < policy->max) | ||
658 | + __cpufreq_driver_target(policy, policy->max, | ||
659 | + CPUFREQ_RELATION_H); | ||
660 | + | ||
661 | + goto out; | ||
662 | + } | ||
663 | + | ||
664 | + /* check for frequency decrease */ | ||
665 | + if (avg_load < dbs_tuners_ins.down_threshold) { | ||
666 | + /* are we at the minimum frequency already? */ | ||
667 | + if (policy->cur == policy->min) { | ||
668 | + /* should we disable auxillary CPUs? */ | ||
669 | + if (num_online_cpus() > 1 && hotplug_out_avg_load < | ||
670 | + dbs_tuners_ins.down_threshold) { | ||
671 | + mutex_unlock(&this_dbs_info->timer_mutex); | ||
672 | + cpu_down(1); | ||
673 | + mutex_lock(&this_dbs_info->timer_mutex); | ||
674 | + } | ||
675 | + goto out; | ||
676 | + } | ||
677 | + | ||
678 | + /* bump down to the next lowest frequency in the table */ | ||
679 | + if (cpufreq_frequency_table_next_lowest(policy, | ||
680 | + this_dbs_info->freq_table, &index)) { | ||
681 | + pr_err("%s: failed to get next lowest frequency\n", | ||
682 | + __func__); | ||
683 | + goto out; | ||
684 | + } | ||
685 | + | ||
686 | + __cpufreq_driver_target(policy, | ||
687 | + this_dbs_info->freq_table[index].frequency, | ||
688 | + CPUFREQ_RELATION_L); | ||
689 | + } | ||
690 | +out: | ||
691 | + return; | ||
692 | +} | ||
693 | + | ||
694 | +static void do_dbs_timer(struct work_struct *work) | ||
695 | +{ | ||
696 | + struct cpu_dbs_info_s *dbs_info = | ||
697 | + container_of(work, struct cpu_dbs_info_s, work.work); | ||
698 | + unsigned int cpu = dbs_info->cpu; | ||
699 | + | ||
700 | + /* We want all related CPUs to do sampling nearly on same jiffy */ | ||
701 | + int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); | ||
702 | + | ||
703 | + mutex_lock(&dbs_info->timer_mutex); | ||
704 | + dbs_check_cpu(dbs_info); | ||
705 | + queue_delayed_work_on(cpu, khotplug_wq, &dbs_info->work, delay); | ||
706 | + mutex_unlock(&dbs_info->timer_mutex); | ||
707 | +} | ||
708 | + | ||
709 | +static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) | ||
710 | +{ | ||
711 | + /* We want all related CPUs to do sampling nearly on same jiffy */ | ||
712 | + int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); | ||
713 | + delay -= jiffies % delay; | ||
714 | + | ||
715 | + INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer); | ||
716 | + queue_delayed_work_on(dbs_info->cpu, khotplug_wq, &dbs_info->work, | ||
717 | + delay); | ||
718 | +} | ||
719 | + | ||
720 | +static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) | ||
721 | +{ | ||
722 | + cancel_delayed_work_sync(&dbs_info->work); | ||
723 | +} | ||
724 | + | ||
725 | +static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | ||
726 | + unsigned int event) | ||
727 | +{ | ||
728 | + unsigned int cpu = policy->cpu; | ||
729 | + struct cpu_dbs_info_s *this_dbs_info; | ||
730 | + unsigned int i, j, max_periods; | ||
731 | + int rc; | ||
732 | + | ||
733 | + this_dbs_info = &per_cpu(hp_cpu_dbs_info, cpu); | ||
734 | + | ||
735 | + switch (event) { | ||
736 | + case CPUFREQ_GOV_START: | ||
737 | + if ((!cpu_online(cpu)) || (!policy->cur)) | ||
738 | + return -EINVAL; | ||
739 | + | ||
740 | + mutex_lock(&dbs_mutex); | ||
741 | + dbs_enable++; | ||
742 | + for_each_cpu(j, policy->cpus) { | ||
743 | + struct cpu_dbs_info_s *j_dbs_info; | ||
744 | + j_dbs_info = &per_cpu(hp_cpu_dbs_info, j); | ||
745 | + j_dbs_info->cur_policy = policy; | ||
746 | + | ||
747 | + j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j, | ||
748 | + &j_dbs_info->prev_cpu_wall); | ||
749 | + if (dbs_tuners_ins.ignore_nice) { | ||
750 | + j_dbs_info->prev_cpu_nice = | ||
751 | + kstat_cpu(j).cpustat.nice; | ||
752 | + } | ||
753 | + | ||
754 | + max_periods = max(DEFAULT_HOTPLUG_IN_SAMPLING_PERIODS, | ||
755 | + DEFAULT_HOTPLUG_OUT_SAMPLING_PERIODS); | ||
756 | + dbs_tuners_ins.hotplug_load_history = kmalloc( | ||
757 | + (sizeof(unsigned int) * max_periods), | ||
758 | + GFP_KERNEL); | ||
759 | + if (!dbs_tuners_ins.hotplug_load_history) { | ||
760 | + WARN_ON(1); | ||
761 | + return -ENOMEM; | ||
762 | + } | ||
763 | + for (i = 0; i < max_periods; i++) | ||
764 | + dbs_tuners_ins.hotplug_load_history[i] = 50; | ||
765 | + } | ||
766 | + this_dbs_info->cpu = cpu; | ||
767 | + this_dbs_info->freq_table = cpufreq_frequency_get_table(cpu); | ||
768 | + /* | ||
769 | + * Start the timerschedule work, when this governor | ||
770 | + * is used for first time | ||
771 | + */ | ||
772 | + if (dbs_enable == 1) { | ||
773 | + rc = sysfs_create_group(cpufreq_global_kobject, | ||
774 | + &dbs_attr_group); | ||
775 | + if (rc) { | ||
776 | + mutex_unlock(&dbs_mutex); | ||
777 | + return rc; | ||
778 | + } | ||
779 | + } | ||
780 | + mutex_unlock(&dbs_mutex); | ||
781 | + | ||
782 | + mutex_init(&this_dbs_info->timer_mutex); | ||
783 | + dbs_timer_init(this_dbs_info); | ||
784 | + break; | ||
785 | + | ||
786 | + case CPUFREQ_GOV_STOP: | ||
787 | + dbs_timer_exit(this_dbs_info); | ||
788 | + | ||
789 | + mutex_lock(&dbs_mutex); | ||
790 | + mutex_destroy(&this_dbs_info->timer_mutex); | ||
791 | + dbs_enable--; | ||
792 | + mutex_unlock(&dbs_mutex); | ||
793 | + if (!dbs_enable) | ||
794 | + sysfs_remove_group(cpufreq_global_kobject, | ||
795 | + &dbs_attr_group); | ||
796 | + kfree(dbs_tuners_ins.hotplug_load_history); | ||
797 | + /* | ||
798 | + * XXX BIG CAVEAT: Stopping the governor with CPU1 offline | ||
799 | + * will result in it remaining offline until the user onlines | ||
800 | + * it again. It is up to the user to do this (for now). | ||
801 | + */ | ||
802 | + break; | ||
803 | + | ||
804 | + case CPUFREQ_GOV_LIMITS: | ||
805 | + mutex_lock(&this_dbs_info->timer_mutex); | ||
806 | + if (policy->max < this_dbs_info->cur_policy->cur) | ||
807 | + __cpufreq_driver_target(this_dbs_info->cur_policy, | ||
808 | + policy->max, CPUFREQ_RELATION_H); | ||
809 | + else if (policy->min > this_dbs_info->cur_policy->cur) | ||
810 | + __cpufreq_driver_target(this_dbs_info->cur_policy, | ||
811 | + policy->min, CPUFREQ_RELATION_L); | ||
812 | + mutex_unlock(&this_dbs_info->timer_mutex); | ||
813 | + break; | ||
814 | + } | ||
815 | + return 0; | ||
816 | +} | ||
817 | + | ||
818 | +static int __init cpufreq_gov_dbs_init(void) | ||
819 | +{ | ||
820 | + int err; | ||
821 | + cputime64_t wall; | ||
822 | + u64 idle_time; | ||
823 | + int cpu = get_cpu(); | ||
824 | + | ||
825 | + idle_time = get_cpu_idle_time_us(cpu, &wall); | ||
826 | + put_cpu(); | ||
827 | + if (idle_time != -1ULL) { | ||
828 | + dbs_tuners_ins.up_threshold = DEFAULT_UP_FREQ_MIN_LOAD; | ||
829 | + } else { | ||
830 | + pr_err("cpufreq-hotplug: %s: assumes CONFIG_NO_HZ\n", | ||
831 | + __func__); | ||
832 | + return -EINVAL; | ||
833 | + } | ||
834 | + | ||
835 | + khotplug_wq = create_workqueue("khotplug"); | ||
836 | + if (!khotplug_wq) { | ||
837 | + pr_err("Creation of khotplug failed\n"); | ||
838 | + return -EFAULT; | ||
839 | + } | ||
840 | + err = cpufreq_register_governor(&cpufreq_gov_hotplug); | ||
841 | + if (err) | ||
842 | + destroy_workqueue(khotplug_wq); | ||
843 | + | ||
844 | + return err; | ||
845 | +} | ||
846 | + | ||
847 | +static void __exit cpufreq_gov_dbs_exit(void) | ||
848 | +{ | ||
849 | + cpufreq_unregister_governor(&cpufreq_gov_hotplug); | ||
850 | + destroy_workqueue(khotplug_wq); | ||
851 | +} | ||
852 | + | ||
853 | +MODULE_AUTHOR("Mike Turquette <mturquette@ti.com>"); | ||
854 | +MODULE_DESCRIPTION("'cpufreq_hotplug' - cpufreq governor for dynamic frequency scaling and CPU hotplugging"); | ||
855 | +MODULE_LICENSE("GPL"); | ||
856 | + | ||
857 | +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_HOTPLUG | ||
858 | +fs_initcall(cpufreq_gov_dbs_init); | ||
859 | +#else | ||
860 | +module_init(cpufreq_gov_dbs_init); | ||
861 | +#endif | ||
862 | +module_exit(cpufreq_gov_dbs_exit); | ||
863 | diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h | ||
864 | index a38fca8..6cbc3df 100644 | ||
865 | --- a/include/linux/cpufreq.h | ||
866 | +++ b/include/linux/cpufreq.h | ||
867 | @@ -355,6 +355,9 @@ extern struct cpufreq_governor cpufreq_gov_ondemand; | ||
868 | #elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE) | ||
869 | extern struct cpufreq_governor cpufreq_gov_conservative; | ||
870 | #define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_conservative) | ||
871 | +#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_HOTPLUG) | ||
872 | +extern struct cpufreq_governor cpufreq_gov_hotplug; | ||
873 | +#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_hotplug) | ||
874 | #endif | ||
875 | |||
876 | |||
877 | -- | ||
878 | 1.6.6.1 | ||
879 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0001-OMAP-CPUfreq-ensure-driver-initializes-after-cpufreq.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0001-OMAP-CPUfreq-ensure-driver-initializes-after-cpufreq.patch deleted file mode 100644 index d150dfc6..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0001-OMAP-CPUfreq-ensure-driver-initializes-after-cpufreq.patch +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | From 33668b07abd5e66a263cc8b4b88587646f38bed0 Mon Sep 17 00:00:00 2001 | ||
2 | From: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> | ||
3 | Date: Wed, 11 Aug 2010 17:02:43 -0700 | ||
4 | Subject: [PATCH 1/8] OMAP: CPUfreq: ensure driver initializes after cpufreq framework and governors | ||
5 | |||
6 | Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> | ||
7 | Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> | ||
8 | --- | ||
9 | arch/arm/plat-omap/cpu-omap.c | 2 +- | ||
10 | 1 files changed, 1 insertions(+), 1 deletions(-) | ||
11 | |||
12 | diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c | ||
13 | index da4f68d..cd09d4b 100644 | ||
14 | --- a/arch/arm/plat-omap/cpu-omap.c | ||
15 | +++ b/arch/arm/plat-omap/cpu-omap.c | ||
16 | @@ -160,7 +160,7 @@ static int __init omap_cpufreq_init(void) | ||
17 | return cpufreq_register_driver(&omap_driver); | ||
18 | } | ||
19 | |||
20 | -arch_initcall(omap_cpufreq_init); | ||
21 | +late_initcall(omap_cpufreq_init); | ||
22 | |||
23 | /* | ||
24 | * if ever we want to remove this, upon cleanup call: | ||
25 | -- | ||
26 | 1.6.6.1 | ||
27 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0002-OMAP-CPUfreq-ensure-policy-is-fully-initialized.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0002-OMAP-CPUfreq-ensure-policy-is-fully-initialized.patch deleted file mode 100644 index d62e04d1..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0002-OMAP-CPUfreq-ensure-policy-is-fully-initialized.patch +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | From e89b1544450fb8410a44004e48d6b330bc39f0ce Mon Sep 17 00:00:00 2001 | ||
2 | From: Kevin Hilman <khilman@deeprootsystems.com> | ||
3 | Date: Wed, 11 Aug 2010 17:05:38 -0700 | ||
4 | Subject: [PATCH 2/8] OMAP: CPUfreq: ensure policy is fully initialized | ||
5 | |||
6 | Ensure policy min/max/cur values are initialized when OMAP | ||
7 | CPUfreq driver starts. | ||
8 | |||
9 | Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> | ||
10 | --- | ||
11 | arch/arm/plat-omap/cpu-omap.c | 4 ++++ | ||
12 | 1 files changed, 4 insertions(+), 0 deletions(-) | ||
13 | |||
14 | diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c | ||
15 | index cd09d4b..1b36664 100644 | ||
16 | --- a/arch/arm/plat-omap/cpu-omap.c | ||
17 | +++ b/arch/arm/plat-omap/cpu-omap.c | ||
18 | @@ -126,6 +126,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
19 | VERY_HI_RATE) / 1000; | ||
20 | } | ||
21 | |||
22 | + policy->min = policy->cpuinfo.min_freq; | ||
23 | + policy->max = policy->cpuinfo.max_freq; | ||
24 | + policy->cur = omap_getspeed(0); | ||
25 | + | ||
26 | /* FIXME: what's the actual transition time? */ | ||
27 | policy->cpuinfo.transition_latency = 300 * 1000; | ||
28 | |||
29 | -- | ||
30 | 1.6.6.1 | ||
31 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0003-OMAP3-PM-CPUFreq-driver-for-OMAP3.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0003-OMAP3-PM-CPUFreq-driver-for-OMAP3.patch deleted file mode 100644 index fbe16213..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0003-OMAP3-PM-CPUFreq-driver-for-OMAP3.patch +++ /dev/null | |||
@@ -1,263 +0,0 @@ | |||
1 | From 948b868e4a83b054e8a58362238bc6cd61c0aeab Mon Sep 17 00:00:00 2001 | ||
2 | From: Rajendra Nayak <rnayak@ti.com> | ||
3 | Date: Mon, 10 Nov 2008 17:00:25 +0530 | ||
4 | Subject: [PATCH 3/8] OMAP3 PM: CPUFreq driver for OMAP3 | ||
5 | |||
6 | CPUFreq driver for OMAP3 | ||
7 | |||
8 | With additional fixes and cleanups from Tero Kristo: | ||
9 | - Fix rate calculation bug in omap3_select_table_rate | ||
10 | - Refreshed DVFS VDD1 control against latest clock fw | ||
11 | |||
12 | Signed-off-by: Tero Kristo <tero.kristo@nokia.com> | ||
13 | Signed-off-by: Rajendra Nayak <rnayak@ti.com> | ||
14 | |||
15 | OMAP3: PM: CPUFreq: Fix omap_getspeed. | ||
16 | |||
17 | Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> | ||
18 | |||
19 | Make sure omap cpufreq driver initializes after cpufreq framework and governors | ||
20 | |||
21 | Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> | ||
22 | |||
23 | merge: CPUFreq: remove obsolete funcs | ||
24 | |||
25 | OMAP3 clock: Update cpufreq driver | ||
26 | |||
27 | This patch removes all refrences to virtual clock | ||
28 | nodes in CPUFreq driver. | ||
29 | |||
30 | Signed-off-by: Rajendra Nayak <rnayak@ti.com> | ||
31 | Signed-off-by: Tero Kristo <tero.kristo@nokia.com> | ||
32 | Signed-off-by: Jean Pihet <jpihet@mvista.com> | ||
33 | |||
34 | PM: Prevent direct cpufreq scaling during initialization | ||
35 | |||
36 | It is seen that the OMAP specific cpufreq initialization code tries to | ||
37 | scale the MPU frequency to the highest possible without taking care of | ||
38 | the voltage level. On power on reset the power IC does not provide the | ||
39 | necessary voltage for the highest available MPU frequency (that would | ||
40 | satisfy all Si families). This potentially is an window of opportunity | ||
41 | for things to go wrong. | ||
42 | |||
43 | Signed-off-by: Romit Dasgupta <romit@ti.com> | ||
44 | Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> | ||
45 | |||
46 | OMAP3: PM: enable 600MHz (overdrive) OPP | ||
47 | |||
48 | Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> | ||
49 | |||
50 | omap3: introduce cpufreq | ||
51 | |||
52 | OMAP OPP layer functions now have dependencies of CONFIG_CPU_FREQ only. | ||
53 | |||
54 | With this patch, omap opp layer now has its compilation flags | ||
55 | bound to CONFIG_CPU_FREQ. Also its code has been removed from pm34xx.c. | ||
56 | |||
57 | A new file has been created to contain cpu freq code related to | ||
58 | OMAP3: cpufreq34xx.c | ||
59 | |||
60 | OMAP34xx and OMAP36xx family OPPs are made available | ||
61 | |||
62 | Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com> | ||
63 | Signed-off-by: Paul Walmsley <paul@pwsan.com> | ||
64 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
65 | Signed-off-by: Vishwanath BS <vishwanath.bs@ti.com> | ||
66 | Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> | ||
67 | Signed-off-by: Romit Dasgupta <romit@ti.com> | ||
68 | Signed-off-by: Rajendra Nayak <rnayak@ti.com> | ||
69 | |||
70 | omap3: cpufreq: allow default opp table init | ||
71 | |||
72 | For board files which choose to override the defaults, the existing | ||
73 | mechanism will work, for boards that would like to work with defaults, | ||
74 | allow init_common_hw to call init_opp_table to initialize if not | ||
75 | already initialized. this will allow all omap boards which have opp | ||
76 | tables predefined for a silicon to use the same. | ||
77 | |||
78 | Originally reported for overo: | ||
79 | http://marc.info/?t=127265269400004&r=1&w=2 | ||
80 | |||
81 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
82 | Reported-by: Peter Tseng <tsenpet09@gmail.com> | ||
83 | Cc: Cliff Brake <cliff.brake@gmail.com> | ||
84 | Cc: Kevin Hilman <khilman@deeprootsystems.com> | ||
85 | |||
86 | OMAP2: update OPP data to be device based | ||
87 | |||
88 | Cc: Nishanth Menon <nm@ti.com> | ||
89 | Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> | ||
90 | |||
91 | OMAP3: CPUfreq: update to device-based OPP API | ||
92 | |||
93 | Update usage of OPP API to use new device-based API. This requires | ||
94 | getting the 'struct device' for the MPU and using that with the OPP | ||
95 | API. | ||
96 | |||
97 | Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> | ||
98 | |||
99 | omap3: opp: make independent of cpufreq | ||
100 | |||
101 | Make opp3xx data which is registered with the opp layer | ||
102 | dependent purely on CONFIG_PM as opp layer and pm.c users | ||
103 | are CONFIG_PM dependent not cpufreq dependent. | ||
104 | so we rename the data definition to opp3xxx_data.c (inline with what | ||
105 | we have for omap2), also move the build definition to be under | ||
106 | the existing CONFIG_PM build instead of CPUFREQ. | ||
107 | |||
108 | Cc: Eduardo Valentin <eduardo.valentin@nokia.com> | ||
109 | Cc: Kevin Hilman <khilman@deeprootsystems.com> | ||
110 | Cc: Paul Walmsley <paul@pwsan.com> | ||
111 | Cc: Rajendra Nayak <rnayak@ti.com> | ||
112 | Cc: Sanjeev Premi <premi@ti.com> | ||
113 | Cc: Thara Gopinath <thara@ti.com> | ||
114 | Cc: Tony Lindgren <tony@atomide.com> | ||
115 | |||
116 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
117 | --- | ||
118 | arch/arm/mach-omap2/clock.h | 14 +++++++++++++- | ||
119 | arch/arm/mach-omap2/clock34xx.c | 2 ++ | ||
120 | arch/arm/plat-omap/cpu-omap.c | 34 +++++++++++++++++++++++++++++++--- | ||
121 | 3 files changed, 46 insertions(+), 4 deletions(-) | ||
122 | |||
123 | diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h | ||
124 | index e10ff2b..0a07e50 100644 | ||
125 | --- a/arch/arm/mach-omap2/clock.h | ||
126 | +++ b/arch/arm/mach-omap2/clock.h | ||
127 | @@ -141,7 +141,9 @@ extern const struct clksel_rate gpt_sys_rates[]; | ||
128 | extern const struct clksel_rate gfx_l3_rates[]; | ||
129 | extern const struct clksel_rate dsp_ick_rates[]; | ||
130 | |||
131 | -#if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_CPU_FREQ) | ||
132 | +#ifdef CONFIG_CPU_FREQ | ||
133 | + | ||
134 | +#ifdef CONFIG_ARCH_OMAP2 | ||
135 | extern void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table); | ||
136 | extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table); | ||
137 | #else | ||
138 | @@ -149,6 +151,16 @@ extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table) | ||
139 | #define omap2_clk_exit_cpufreq_table 0 | ||
140 | #endif | ||
141 | |||
142 | +#ifdef CONFIG_ARCH_OMAP3 | ||
143 | +extern void omap3_clk_init_cpufreq_table(struct cpufreq_frequency_table **table); | ||
144 | +extern void omap3_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table); | ||
145 | +#else | ||
146 | +#define omap3_clk_init_cpufreq_table 0 | ||
147 | +#define omap3_clk_exit_cpufreq_table 0 | ||
148 | +#endif | ||
149 | + | ||
150 | +#endif /* CONFIG_CPU_FREQ */ | ||
151 | + | ||
152 | extern const struct clkops clkops_omap2_iclk_dflt_wait; | ||
153 | extern const struct clkops clkops_omap2_iclk_dflt; | ||
154 | extern const struct clkops clkops_omap2_iclk_idle_only; | ||
155 | diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c | ||
156 | index 1fc96b9..119e135 100644 | ||
157 | --- a/arch/arm/mach-omap2/clock34xx.c | ||
158 | +++ b/arch/arm/mach-omap2/clock34xx.c | ||
159 | @@ -20,6 +20,8 @@ | ||
160 | #include <linux/kernel.h> | ||
161 | #include <linux/clk.h> | ||
162 | #include <linux/io.h> | ||
163 | +#include <linux/err.h> | ||
164 | +#include <linux/cpufreq.h> | ||
165 | |||
166 | #include <plat/clock.h> | ||
167 | |||
168 | diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c | ||
169 | index 1b36664..f0f9430 100644 | ||
170 | --- a/arch/arm/plat-omap/cpu-omap.c | ||
171 | +++ b/arch/arm/plat-omap/cpu-omap.c | ||
172 | @@ -8,6 +8,10 @@ | ||
173 | * | ||
174 | * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King | ||
175 | * | ||
176 | + * Copyright (C) 2007-2008 Texas Instruments, Inc. | ||
177 | + * Updated to support OMAP3 | ||
178 | + * Rajendra Nayak <rnayak@ti.com> | ||
179 | + * | ||
180 | * This program is free software; you can redistribute it and/or modify | ||
181 | * it under the terms of the GNU General Public License version 2 as | ||
182 | * published by the Free Software Foundation. | ||
183 | @@ -26,12 +30,19 @@ | ||
184 | #include <plat/clock.h> | ||
185 | #include <asm/system.h> | ||
186 | |||
187 | +#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) | ||
188 | +#include <plat/omap-pm.h> | ||
189 | +#include <plat/opp.h> | ||
190 | +#endif | ||
191 | + | ||
192 | #define VERY_HI_RATE 900000000 | ||
193 | |||
194 | static struct cpufreq_frequency_table *freq_table; | ||
195 | |||
196 | #ifdef CONFIG_ARCH_OMAP1 | ||
197 | #define MPU_CLK "mpu" | ||
198 | +#elif CONFIG_ARCH_OMAP3 | ||
199 | +#define MPU_CLK "arm_fck" | ||
200 | #else | ||
201 | #define MPU_CLK "virt_prcm_set" | ||
202 | #endif | ||
203 | @@ -73,7 +84,13 @@ static int omap_target(struct cpufreq_policy *policy, | ||
204 | unsigned int target_freq, | ||
205 | unsigned int relation) | ||
206 | { | ||
207 | +#ifdef CONFIG_ARCH_OMAP1 | ||
208 | struct cpufreq_freqs freqs; | ||
209 | +#endif | ||
210 | +#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) | ||
211 | + unsigned long freq; | ||
212 | + struct device *mpu_dev = omap2_get_mpuss_device(); | ||
213 | +#endif | ||
214 | int ret = 0; | ||
215 | |||
216 | /* Ensure desired rate is within allowed range. Some govenors | ||
217 | @@ -83,13 +100,13 @@ static int omap_target(struct cpufreq_policy *policy, | ||
218 | if (target_freq > policy->max) | ||
219 | target_freq = policy->max; | ||
220 | |||
221 | +#ifdef CONFIG_ARCH_OMAP1 | ||
222 | freqs.old = omap_getspeed(0); | ||
223 | freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; | ||
224 | freqs.cpu = 0; | ||
225 | |||
226 | if (freqs.old == freqs.new) | ||
227 | return ret; | ||
228 | - | ||
229 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
230 | #ifdef CONFIG_CPU_FREQ_DEBUG | ||
231 | printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n", | ||
232 | @@ -97,7 +114,11 @@ static int omap_target(struct cpufreq_policy *policy, | ||
233 | #endif | ||
234 | ret = clk_set_rate(mpu_clk, freqs.new * 1000); | ||
235 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
236 | - | ||
237 | +#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) | ||
238 | + freq = target_freq * 1000; | ||
239 | + if (opp_find_freq_ceil(mpu_dev, &freq)) | ||
240 | + omap_pm_cpu_set_freq(freq); | ||
241 | +#endif | ||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | @@ -114,7 +135,14 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
246 | |||
247 | policy->cur = policy->min = policy->max = omap_getspeed(0); | ||
248 | |||
249 | - clk_init_cpufreq_table(&freq_table); | ||
250 | + if (!cpu_is_omap34xx()) { | ||
251 | + clk_init_cpufreq_table(&freq_table); | ||
252 | + } else { | ||
253 | + struct device *mpu_dev = omap2_get_mpuss_device(); | ||
254 | + | ||
255 | + opp_init_cpufreq_table(mpu_dev, &freq_table); | ||
256 | + } | ||
257 | + | ||
258 | if (freq_table) { | ||
259 | result = cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
260 | if (!result) | ||
261 | -- | ||
262 | 1.6.6.1 | ||
263 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0004-OMAP-PM-CPUFREQ-Fix-conditional-compilation.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0004-OMAP-PM-CPUFREQ-Fix-conditional-compilation.patch deleted file mode 100644 index 36742e43..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0004-OMAP-PM-CPUFREQ-Fix-conditional-compilation.patch +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | From 86227f1eb341e571163464cb0a412ed2179f2541 Mon Sep 17 00:00:00 2001 | ||
2 | From: Silesh C V <silesh@ti.com> | ||
3 | Date: Wed, 29 Sep 2010 14:52:54 +0530 | ||
4 | Subject: [PATCH 4/8] OMAP: PM: CPUFREQ: Fix conditional compilation | ||
5 | |||
6 | Fix conditional compilation. A conditional expresiion | ||
7 | should follow "#elif", in this case #elif clause should | ||
8 | check whether CONFIG_ARCH_OMAP3 is defined or not | ||
9 | (ie. defined(CONFIG_ARCH_OMAP3)) rather than checking for | ||
10 | the value of the macro. | ||
11 | |||
12 | Signed-off-by: Silesh C V <silesh@ti.com> | ||
13 | --- | ||
14 | arch/arm/plat-omap/cpu-omap.c | 2 +- | ||
15 | 1 files changed, 1 insertions(+), 1 deletions(-) | ||
16 | |||
17 | diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c | ||
18 | index f0f9430..c3ac065 100644 | ||
19 | --- a/arch/arm/plat-omap/cpu-omap.c | ||
20 | +++ b/arch/arm/plat-omap/cpu-omap.c | ||
21 | @@ -41,7 +41,7 @@ static struct cpufreq_frequency_table *freq_table; | ||
22 | |||
23 | #ifdef CONFIG_ARCH_OMAP1 | ||
24 | #define MPU_CLK "mpu" | ||
25 | -#elif CONFIG_ARCH_OMAP3 | ||
26 | +#elif defined(CONFIG_ARCH_OMAP3) | ||
27 | #define MPU_CLK "arm_fck" | ||
28 | #else | ||
29 | #define MPU_CLK "virt_prcm_set" | ||
30 | -- | ||
31 | 1.6.6.1 | ||
32 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0005-cpufreq-fixup-after-new-OPP-layer-merged.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0005-cpufreq-fixup-after-new-OPP-layer-merged.patch deleted file mode 100644 index 7cf69325..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0005-cpufreq-fixup-after-new-OPP-layer-merged.patch +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | From 4764137dd613362656726a15cb8184724aeb99bb Mon Sep 17 00:00:00 2001 | ||
2 | From: Kevin Hilman <khilman@deeprootsystems.com> | ||
3 | Date: Tue, 16 Nov 2010 11:48:41 -0800 | ||
4 | Subject: [PATCH 5/8] cpufreq: fixup after new OPP layer merged | ||
5 | |||
6 | --- | ||
7 | arch/arm/plat-omap/cpu-omap.c | 3 ++- | ||
8 | 1 files changed, 2 insertions(+), 1 deletions(-) | ||
9 | |||
10 | diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c | ||
11 | index c3ac065..9cd2709 100644 | ||
12 | --- a/arch/arm/plat-omap/cpu-omap.c | ||
13 | +++ b/arch/arm/plat-omap/cpu-omap.c | ||
14 | @@ -25,6 +25,7 @@ | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/clk.h> | ||
17 | #include <linux/io.h> | ||
18 | +#include <linux/opp.h> | ||
19 | |||
20 | #include <mach/hardware.h> | ||
21 | #include <plat/clock.h> | ||
22 | @@ -32,7 +33,7 @@ | ||
23 | |||
24 | #if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) | ||
25 | #include <plat/omap-pm.h> | ||
26 | -#include <plat/opp.h> | ||
27 | +#include <plat/common.h> | ||
28 | #endif | ||
29 | |||
30 | #define VERY_HI_RATE 900000000 | ||
31 | -- | ||
32 | 1.6.6.1 | ||
33 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0006-OMAP-cpufreq-Split-OMAP1-and-OMAP2PLUS-CPUfreq-drive.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0006-OMAP-cpufreq-Split-OMAP1-and-OMAP2PLUS-CPUfreq-drive.patch deleted file mode 100644 index cfc257e0..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0006-OMAP-cpufreq-Split-OMAP1-and-OMAP2PLUS-CPUfreq-drive.patch +++ /dev/null | |||
@@ -1,669 +0,0 @@ | |||
1 | From e16548716c5cbc3c9885d05f1654d83d5411a3a7 Mon Sep 17 00:00:00 2001 | ||
2 | From: Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
3 | Date: Mon, 14 Mar 2011 17:08:48 +0530 | ||
4 | Subject: [PATCH 6/8] OMAP: cpufreq: Split OMAP1 and OMAP2PLUS CPUfreq drivers. | ||
5 | |||
6 | This patch is an attempt to cleanup the #ifdeferry in the | ||
7 | omap CPUfreq drivers. | ||
8 | |||
9 | The split betwenn OMAP1 and OMAP2PLUS is logical because | ||
10 | - OMAP1 doesn't support opp layer. | ||
11 | - OMAP1 build is seperate from omap2plus. | ||
12 | |||
13 | Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
14 | Cc: Kevin Hilman <khilman@ti.com> | ||
15 | Cc: Vishwanath BS <vishwanath.bs@ti.com> | ||
16 | --- | ||
17 | arch/arm/mach-omap1/Makefile | 3 + | ||
18 | arch/arm/mach-omap1/omap1-cpufreq.c | 176 ++++++++++++++++++++++++++ | ||
19 | arch/arm/mach-omap2/Makefile | 3 + | ||
20 | arch/arm/mach-omap2/omap2plus-cpufreq.c | 201 ++++++++++++++++++++++++++++++ | ||
21 | arch/arm/plat-omap/Makefile | 1 - | ||
22 | arch/arm/plat-omap/cpu-omap.c | 204 ------------------------------- | ||
23 | 6 files changed, 383 insertions(+), 205 deletions(-) | ||
24 | create mode 100644 arch/arm/mach-omap1/omap1-cpufreq.c | ||
25 | create mode 100644 arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
26 | delete mode 100644 arch/arm/plat-omap/cpu-omap.c | ||
27 | |||
28 | diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile | ||
29 | index af98117..e5082b0 100644 | ||
30 | --- a/arch/arm/mach-omap1/Makefile | ||
31 | +++ b/arch/arm/mach-omap1/Makefile | ||
32 | @@ -10,6 +10,9 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o | ||
33 | |||
34 | obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o | ||
35 | |||
36 | +# CPUFREQ driver | ||
37 | +obj-$(CONFIG_CPU_FREQ) += omap1-cpufreq.o | ||
38 | + | ||
39 | # Power Management | ||
40 | obj-$(CONFIG_PM) += pm.o sleep.o pm_bus.o | ||
41 | |||
42 | diff --git a/arch/arm/mach-omap1/omap1-cpufreq.c b/arch/arm/mach-omap1/omap1-cpufreq.c | ||
43 | new file mode 100644 | ||
44 | index 0000000..682cdc8 | ||
45 | --- /dev/null | ||
46 | +++ b/arch/arm/mach-omap1/omap1-cpufreq.c | ||
47 | @@ -0,0 +1,176 @@ | ||
48 | +/* | ||
49 | + * OMAP1 cpufreq driver | ||
50 | + * | ||
51 | + * CPU frequency scaling for OMAP | ||
52 | + * | ||
53 | + * Copyright (C) 2005 Nokia Corporation | ||
54 | + * Written by Tony Lindgren <tony@atomide.com> | ||
55 | + * | ||
56 | + * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King | ||
57 | + * | ||
58 | + * Copyright (C) 2007-2008 Texas Instruments, Inc. | ||
59 | + * Updated to support OMAP3 | ||
60 | + * Rajendra Nayak <rnayak@ti.com> | ||
61 | + * | ||
62 | + * This program is free software; you can redistribute it and/or modify | ||
63 | + * it under the terms of the GNU General Public License version 2 as | ||
64 | + * published by the Free Software Foundation. | ||
65 | + */ | ||
66 | +#include <linux/types.h> | ||
67 | +#include <linux/kernel.h> | ||
68 | +#include <linux/sched.h> | ||
69 | +#include <linux/cpufreq.h> | ||
70 | +#include <linux/delay.h> | ||
71 | +#include <linux/init.h> | ||
72 | +#include <linux/err.h> | ||
73 | +#include <linux/clk.h> | ||
74 | +#include <linux/io.h> | ||
75 | +#include <linux/opp.h> | ||
76 | + | ||
77 | +#include <asm/system.h> | ||
78 | + | ||
79 | +#include <plat/clock.h> | ||
80 | +#include <plat/omap-pm.h> | ||
81 | + | ||
82 | +#include <mach/hardware.h> | ||
83 | + | ||
84 | +#define VERY_HI_RATE 900000000 | ||
85 | + | ||
86 | +static struct cpufreq_frequency_table *freq_table; | ||
87 | +static struct clk *mpu_clk; | ||
88 | + | ||
89 | +static int omap_verify_speed(struct cpufreq_policy *policy) | ||
90 | +{ | ||
91 | + if (freq_table) | ||
92 | + return cpufreq_frequency_table_verify(policy, freq_table); | ||
93 | + | ||
94 | + if (policy->cpu) | ||
95 | + return -EINVAL; | ||
96 | + | ||
97 | + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
98 | + policy->cpuinfo.max_freq); | ||
99 | + | ||
100 | + policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000; | ||
101 | + policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000; | ||
102 | + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
103 | + policy->cpuinfo.max_freq); | ||
104 | + return 0; | ||
105 | +} | ||
106 | + | ||
107 | +static unsigned int omap_getspeed(unsigned int cpu) | ||
108 | +{ | ||
109 | + unsigned long rate; | ||
110 | + | ||
111 | + if (cpu) | ||
112 | + return 0; | ||
113 | + | ||
114 | + rate = clk_get_rate(mpu_clk) / 1000; | ||
115 | + return rate; | ||
116 | +} | ||
117 | + | ||
118 | +static int omap_target(struct cpufreq_policy *policy, | ||
119 | + unsigned int target_freq, | ||
120 | + unsigned int relation) | ||
121 | +{ | ||
122 | + struct cpufreq_freqs freqs; | ||
123 | + int ret = 0; | ||
124 | + | ||
125 | + /* Ensure desired rate is within allowed range. Some govenors | ||
126 | + * (ondemand) will just pass target_freq=0 to get the minimum. */ | ||
127 | + if (target_freq < policy->min) | ||
128 | + target_freq = policy->min; | ||
129 | + if (target_freq > policy->max) | ||
130 | + target_freq = policy->max; | ||
131 | + | ||
132 | + freqs.old = omap_getspeed(0); | ||
133 | + freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; | ||
134 | + freqs.cpu = 0; | ||
135 | + | ||
136 | + if (freqs.old == freqs.new) | ||
137 | + return ret; | ||
138 | + | ||
139 | + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
140 | + | ||
141 | +#ifdef CONFIG_CPU_FREQ_DEBUG | ||
142 | + pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new); | ||
143 | +#endif | ||
144 | + ret = clk_set_rate(mpu_clk, freqs.new * 1000); | ||
145 | + | ||
146 | + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
147 | + | ||
148 | + return ret; | ||
149 | +} | ||
150 | + | ||
151 | +static int __init omap_cpu_init(struct cpufreq_policy *policy) | ||
152 | +{ | ||
153 | + int result = 0; | ||
154 | + | ||
155 | + mpu_clk = clk_get(NULL, "mpu"); | ||
156 | + if (IS_ERR(mpu_clk)) | ||
157 | + return PTR_ERR(mpu_clk); | ||
158 | + | ||
159 | + if (policy->cpu != 0) | ||
160 | + return -EINVAL; | ||
161 | + | ||
162 | + policy->cur = policy->min = policy->max = omap_getspeed(0); | ||
163 | + | ||
164 | + clk_init_cpufreq_table(&freq_table); | ||
165 | + | ||
166 | + if (freq_table) { | ||
167 | + result = cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
168 | + if (!result) | ||
169 | + cpufreq_frequency_table_get_attr(freq_table, | ||
170 | + policy->cpu); | ||
171 | + } else { | ||
172 | + policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; | ||
173 | + policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, | ||
174 | + VERY_HI_RATE) / 1000; | ||
175 | + } | ||
176 | + | ||
177 | + policy->min = policy->cpuinfo.min_freq; | ||
178 | + policy->max = policy->cpuinfo.max_freq; | ||
179 | + policy->cur = omap_getspeed(0); | ||
180 | + | ||
181 | + /* FIXME: what's the actual transition time? */ | ||
182 | + policy->cpuinfo.transition_latency = 300 * 1000; | ||
183 | + | ||
184 | + return 0; | ||
185 | +} | ||
186 | + | ||
187 | +static int omap_cpu_exit(struct cpufreq_policy *policy) | ||
188 | +{ | ||
189 | + clk_exit_cpufreq_table(&freq_table); | ||
190 | + clk_put(mpu_clk); | ||
191 | + return 0; | ||
192 | +} | ||
193 | + | ||
194 | +static struct freq_attr *omap_cpufreq_attr[] = { | ||
195 | + &cpufreq_freq_attr_scaling_available_freqs, | ||
196 | + NULL, | ||
197 | +}; | ||
198 | + | ||
199 | +static struct cpufreq_driver omap_driver = { | ||
200 | + .flags = CPUFREQ_STICKY, | ||
201 | + .verify = omap_verify_speed, | ||
202 | + .target = omap_target, | ||
203 | + .get = omap_getspeed, | ||
204 | + .init = omap_cpu_init, | ||
205 | + .exit = omap_cpu_exit, | ||
206 | + .name = "omap1", | ||
207 | + .attr = omap_cpufreq_attr, | ||
208 | +}; | ||
209 | + | ||
210 | +static int __init omap_cpufreq_init(void) | ||
211 | +{ | ||
212 | + return cpufreq_register_driver(&omap_driver); | ||
213 | +} | ||
214 | + | ||
215 | +static void __exit omap_cpufreq_exit(void) | ||
216 | +{ | ||
217 | + cpufreq_unregister_driver(&omap_driver); | ||
218 | +} | ||
219 | + | ||
220 | +MODULE_DESCRIPTION("cpufreq driver for OMAP1 SOCs"); | ||
221 | +MODULE_LICENSE("GPL"); | ||
222 | +module_init(omap_cpufreq_init); | ||
223 | +module_exit(omap_cpufreq_exit); | ||
224 | diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile | ||
225 | index 05cd983..e9c2445 100644 | ||
226 | --- a/arch/arm/mach-omap2/Makefile | ||
227 | +++ b/arch/arm/mach-omap2/Makefile | ||
228 | @@ -56,6 +56,9 @@ obj-$(CONFIG_ARCH_OMAP3) += opp3xxx_data.o | ||
229 | obj-$(CONFIG_ARCH_OMAP4) += opp4xxx_data.o | ||
230 | endif | ||
231 | |||
232 | +# CPUFREQ driver | ||
233 | +obj-$(CONFIG_CPU_FREQ) += omap2plus-cpufreq.o | ||
234 | + | ||
235 | # Power Management | ||
236 | ifeq ($(CONFIG_PM),y) | ||
237 | obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o | ||
238 | diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
239 | new file mode 100644 | ||
240 | index 0000000..14f84cc | ||
241 | --- /dev/null | ||
242 | +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
243 | @@ -0,0 +1,201 @@ | ||
244 | +/* | ||
245 | + * OMAP2PLUS cpufreq driver | ||
246 | + * | ||
247 | + * CPU frequency scaling for OMAP | ||
248 | + * | ||
249 | + * Copyright (C) 2005 Nokia Corporation | ||
250 | + * Written by Tony Lindgren <tony@atomide.com> | ||
251 | + * | ||
252 | + * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King | ||
253 | + * | ||
254 | + * Copyright (C) 2007-2008 Texas Instruments, Inc. | ||
255 | + * Updated to support OMAP3 | ||
256 | + * Rajendra Nayak <rnayak@ti.com> | ||
257 | + * | ||
258 | + * This program is free software; you can redistribute it and/or modify | ||
259 | + * it under the terms of the GNU General Public License version 2 as | ||
260 | + * published by the Free Software Foundation. | ||
261 | + */ | ||
262 | +#include <linux/types.h> | ||
263 | +#include <linux/kernel.h> | ||
264 | +#include <linux/sched.h> | ||
265 | +#include <linux/cpufreq.h> | ||
266 | +#include <linux/delay.h> | ||
267 | +#include <linux/init.h> | ||
268 | +#include <linux/err.h> | ||
269 | +#include <linux/clk.h> | ||
270 | +#include <linux/io.h> | ||
271 | +#include <linux/opp.h> | ||
272 | + | ||
273 | +#include <asm/system.h> | ||
274 | +#include <asm/smp_plat.h> | ||
275 | + | ||
276 | +#include <plat/clock.h> | ||
277 | +#include <plat/omap-pm.h> | ||
278 | +#include <plat/common.h> | ||
279 | + | ||
280 | +#include <mach/hardware.h> | ||
281 | + | ||
282 | +#define VERY_HI_RATE 900000000 | ||
283 | + | ||
284 | +static struct cpufreq_frequency_table *freq_table; | ||
285 | +static struct clk *mpu_clk; | ||
286 | + | ||
287 | +static int omap_verify_speed(struct cpufreq_policy *policy) | ||
288 | +{ | ||
289 | + if (freq_table) | ||
290 | + return cpufreq_frequency_table_verify(policy, freq_table); | ||
291 | + | ||
292 | + if (policy->cpu) | ||
293 | + return -EINVAL; | ||
294 | + | ||
295 | + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
296 | + policy->cpuinfo.max_freq); | ||
297 | + | ||
298 | + policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000; | ||
299 | + policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000; | ||
300 | + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
301 | + policy->cpuinfo.max_freq); | ||
302 | + return 0; | ||
303 | +} | ||
304 | + | ||
305 | +static unsigned int omap_getspeed(unsigned int cpu) | ||
306 | +{ | ||
307 | + unsigned long rate; | ||
308 | + | ||
309 | + if (cpu) | ||
310 | + return 0; | ||
311 | + | ||
312 | + rate = clk_get_rate(mpu_clk) / 1000; | ||
313 | + return rate; | ||
314 | +} | ||
315 | + | ||
316 | +static int omap_target(struct cpufreq_policy *policy, | ||
317 | + unsigned int target_freq, | ||
318 | + unsigned int relation) | ||
319 | +{ | ||
320 | + int ret = 0; | ||
321 | + struct cpufreq_freqs freqs; | ||
322 | + | ||
323 | + /* Ensure desired rate is within allowed range. Some govenors | ||
324 | + * (ondemand) will just pass target_freq=0 to get the minimum. */ | ||
325 | + if (target_freq < policy->min) | ||
326 | + target_freq = policy->min; | ||
327 | + if (target_freq > policy->max) | ||
328 | + target_freq = policy->max; | ||
329 | + | ||
330 | + freqs.old = omap_getspeed(0); | ||
331 | + freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; | ||
332 | + freqs.cpu = 0; | ||
333 | + | ||
334 | + if (freqs.old == freqs.new) | ||
335 | + return ret; | ||
336 | + | ||
337 | + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
338 | + | ||
339 | +#ifdef CONFIG_CPU_FREQ_DEBUG | ||
340 | + pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new); | ||
341 | +#endif | ||
342 | + | ||
343 | + ret = clk_set_rate(mpu_clk, freqs.new * 1000); | ||
344 | + | ||
345 | + /* | ||
346 | + * Generic CPUFREQ driver jiffy update is under !SMP. So jiffies | ||
347 | + * won't get updated when UP machine cpufreq build with | ||
348 | + * CONFIG_SMP enabled. Below code is added only to manage that | ||
349 | + * scenario | ||
350 | + */ | ||
351 | + if (!is_smp()) | ||
352 | + loops_per_jiffy = | ||
353 | + cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new); | ||
354 | + | ||
355 | + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
356 | + | ||
357 | + return ret; | ||
358 | +} | ||
359 | + | ||
360 | +static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
361 | +{ | ||
362 | + int result = 0; | ||
363 | + struct device *mpu_dev; | ||
364 | + | ||
365 | + if (cpu_is_omap24xx()) | ||
366 | + mpu_clk = clk_get(NULL, "virt_prcm_set"); | ||
367 | + else if (cpu_is_omap34xx()) | ||
368 | + mpu_clk = clk_get(NULL, "dpll1_ck"); | ||
369 | + else if (cpu_is_omap34xx()) | ||
370 | + mpu_clk = clk_get(NULL, "dpll_mpu_ck"); | ||
371 | + | ||
372 | + if (IS_ERR(mpu_clk)) | ||
373 | + return PTR_ERR(mpu_clk); | ||
374 | + | ||
375 | + if (policy->cpu != 0) | ||
376 | + return -EINVAL; | ||
377 | + | ||
378 | + policy->cur = policy->min = policy->max = omap_getspeed(0); | ||
379 | + | ||
380 | + mpu_dev = omap2_get_mpuss_device(); | ||
381 | + if (!mpu_dev) { | ||
382 | + pr_warning("%s: unable to get the mpu device\n", __func__); | ||
383 | + return -EINVAL; | ||
384 | + } | ||
385 | + opp_init_cpufreq_table(mpu_dev, &freq_table); | ||
386 | + | ||
387 | + if (freq_table) { | ||
388 | + result = cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
389 | + if (!result) | ||
390 | + cpufreq_frequency_table_get_attr(freq_table, | ||
391 | + policy->cpu); | ||
392 | + } else { | ||
393 | + policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; | ||
394 | + policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, | ||
395 | + VERY_HI_RATE) / 1000; | ||
396 | + } | ||
397 | + | ||
398 | + policy->min = policy->cpuinfo.min_freq; | ||
399 | + policy->max = policy->cpuinfo.max_freq; | ||
400 | + policy->cur = omap_getspeed(0); | ||
401 | + | ||
402 | + /* FIXME: what's the actual transition time? */ | ||
403 | + policy->cpuinfo.transition_latency = 300 * 1000; | ||
404 | + | ||
405 | + return 0; | ||
406 | +} | ||
407 | + | ||
408 | +static int omap_cpu_exit(struct cpufreq_policy *policy) | ||
409 | +{ | ||
410 | + clk_exit_cpufreq_table(&freq_table); | ||
411 | + clk_put(mpu_clk); | ||
412 | + return 0; | ||
413 | +} | ||
414 | + | ||
415 | +static struct freq_attr *omap_cpufreq_attr[] = { | ||
416 | + &cpufreq_freq_attr_scaling_available_freqs, | ||
417 | + NULL, | ||
418 | +}; | ||
419 | + | ||
420 | +static struct cpufreq_driver omap_driver = { | ||
421 | + .flags = CPUFREQ_STICKY, | ||
422 | + .verify = omap_verify_speed, | ||
423 | + .target = omap_target, | ||
424 | + .get = omap_getspeed, | ||
425 | + .init = omap_cpu_init, | ||
426 | + .exit = omap_cpu_exit, | ||
427 | + .name = "omap2plus", | ||
428 | + .attr = omap_cpufreq_attr, | ||
429 | +}; | ||
430 | + | ||
431 | +static int __init omap_cpufreq_init(void) | ||
432 | +{ | ||
433 | + return cpufreq_register_driver(&omap_driver); | ||
434 | +} | ||
435 | + | ||
436 | +static void __exit omap_cpufreq_exit(void) | ||
437 | +{ | ||
438 | + cpufreq_unregister_driver(&omap_driver); | ||
439 | +} | ||
440 | + | ||
441 | +MODULE_DESCRIPTION("cpufreq driver for OMAP2PLUS SOCs"); | ||
442 | +MODULE_LICENSE("GPL"); | ||
443 | +module_init(omap_cpufreq_init); | ||
444 | +module_exit(omap_cpufreq_exit); | ||
445 | diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile | ||
446 | index a4a1285..ec7862e 100644 | ||
447 | --- a/arch/arm/plat-omap/Makefile | ||
448 | +++ b/arch/arm/plat-omap/Makefile | ||
449 | @@ -21,7 +21,6 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o | ||
450 | obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o | ||
451 | obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu-debug.o | ||
452 | |||
453 | -obj-$(CONFIG_CPU_FREQ) += cpu-omap.o | ||
454 | obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o | ||
455 | obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o | ||
456 | obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o | ||
457 | diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c | ||
458 | deleted file mode 100644 | ||
459 | index 9cd2709..0000000 | ||
460 | --- a/arch/arm/plat-omap/cpu-omap.c | ||
461 | +++ /dev/null | ||
462 | @@ -1,204 +0,0 @@ | ||
463 | -/* | ||
464 | - * linux/arch/arm/plat-omap/cpu-omap.c | ||
465 | - * | ||
466 | - * CPU frequency scaling for OMAP | ||
467 | - * | ||
468 | - * Copyright (C) 2005 Nokia Corporation | ||
469 | - * Written by Tony Lindgren <tony@atomide.com> | ||
470 | - * | ||
471 | - * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King | ||
472 | - * | ||
473 | - * Copyright (C) 2007-2008 Texas Instruments, Inc. | ||
474 | - * Updated to support OMAP3 | ||
475 | - * Rajendra Nayak <rnayak@ti.com> | ||
476 | - * | ||
477 | - * This program is free software; you can redistribute it and/or modify | ||
478 | - * it under the terms of the GNU General Public License version 2 as | ||
479 | - * published by the Free Software Foundation. | ||
480 | - */ | ||
481 | -#include <linux/types.h> | ||
482 | -#include <linux/kernel.h> | ||
483 | -#include <linux/sched.h> | ||
484 | -#include <linux/cpufreq.h> | ||
485 | -#include <linux/delay.h> | ||
486 | -#include <linux/init.h> | ||
487 | -#include <linux/err.h> | ||
488 | -#include <linux/clk.h> | ||
489 | -#include <linux/io.h> | ||
490 | -#include <linux/opp.h> | ||
491 | - | ||
492 | -#include <mach/hardware.h> | ||
493 | -#include <plat/clock.h> | ||
494 | -#include <asm/system.h> | ||
495 | - | ||
496 | -#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) | ||
497 | -#include <plat/omap-pm.h> | ||
498 | -#include <plat/common.h> | ||
499 | -#endif | ||
500 | - | ||
501 | -#define VERY_HI_RATE 900000000 | ||
502 | - | ||
503 | -static struct cpufreq_frequency_table *freq_table; | ||
504 | - | ||
505 | -#ifdef CONFIG_ARCH_OMAP1 | ||
506 | -#define MPU_CLK "mpu" | ||
507 | -#elif defined(CONFIG_ARCH_OMAP3) | ||
508 | -#define MPU_CLK "arm_fck" | ||
509 | -#else | ||
510 | -#define MPU_CLK "virt_prcm_set" | ||
511 | -#endif | ||
512 | - | ||
513 | -static struct clk *mpu_clk; | ||
514 | - | ||
515 | -/* TODO: Add support for SDRAM timing changes */ | ||
516 | - | ||
517 | -static int omap_verify_speed(struct cpufreq_policy *policy) | ||
518 | -{ | ||
519 | - if (freq_table) | ||
520 | - return cpufreq_frequency_table_verify(policy, freq_table); | ||
521 | - | ||
522 | - if (policy->cpu) | ||
523 | - return -EINVAL; | ||
524 | - | ||
525 | - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
526 | - policy->cpuinfo.max_freq); | ||
527 | - | ||
528 | - policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000; | ||
529 | - policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000; | ||
530 | - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
531 | - policy->cpuinfo.max_freq); | ||
532 | - return 0; | ||
533 | -} | ||
534 | - | ||
535 | -static unsigned int omap_getspeed(unsigned int cpu) | ||
536 | -{ | ||
537 | - unsigned long rate; | ||
538 | - | ||
539 | - if (cpu) | ||
540 | - return 0; | ||
541 | - | ||
542 | - rate = clk_get_rate(mpu_clk) / 1000; | ||
543 | - return rate; | ||
544 | -} | ||
545 | - | ||
546 | -static int omap_target(struct cpufreq_policy *policy, | ||
547 | - unsigned int target_freq, | ||
548 | - unsigned int relation) | ||
549 | -{ | ||
550 | -#ifdef CONFIG_ARCH_OMAP1 | ||
551 | - struct cpufreq_freqs freqs; | ||
552 | -#endif | ||
553 | -#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) | ||
554 | - unsigned long freq; | ||
555 | - struct device *mpu_dev = omap2_get_mpuss_device(); | ||
556 | -#endif | ||
557 | - int ret = 0; | ||
558 | - | ||
559 | - /* Ensure desired rate is within allowed range. Some govenors | ||
560 | - * (ondemand) will just pass target_freq=0 to get the minimum. */ | ||
561 | - if (target_freq < policy->min) | ||
562 | - target_freq = policy->min; | ||
563 | - if (target_freq > policy->max) | ||
564 | - target_freq = policy->max; | ||
565 | - | ||
566 | -#ifdef CONFIG_ARCH_OMAP1 | ||
567 | - freqs.old = omap_getspeed(0); | ||
568 | - freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; | ||
569 | - freqs.cpu = 0; | ||
570 | - | ||
571 | - if (freqs.old == freqs.new) | ||
572 | - return ret; | ||
573 | - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
574 | -#ifdef CONFIG_CPU_FREQ_DEBUG | ||
575 | - printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n", | ||
576 | - freqs.old, freqs.new); | ||
577 | -#endif | ||
578 | - ret = clk_set_rate(mpu_clk, freqs.new * 1000); | ||
579 | - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
580 | -#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) | ||
581 | - freq = target_freq * 1000; | ||
582 | - if (opp_find_freq_ceil(mpu_dev, &freq)) | ||
583 | - omap_pm_cpu_set_freq(freq); | ||
584 | -#endif | ||
585 | - return ret; | ||
586 | -} | ||
587 | - | ||
588 | -static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
589 | -{ | ||
590 | - int result = 0; | ||
591 | - | ||
592 | - mpu_clk = clk_get(NULL, MPU_CLK); | ||
593 | - if (IS_ERR(mpu_clk)) | ||
594 | - return PTR_ERR(mpu_clk); | ||
595 | - | ||
596 | - if (policy->cpu != 0) | ||
597 | - return -EINVAL; | ||
598 | - | ||
599 | - policy->cur = policy->min = policy->max = omap_getspeed(0); | ||
600 | - | ||
601 | - if (!cpu_is_omap34xx()) { | ||
602 | - clk_init_cpufreq_table(&freq_table); | ||
603 | - } else { | ||
604 | - struct device *mpu_dev = omap2_get_mpuss_device(); | ||
605 | - | ||
606 | - opp_init_cpufreq_table(mpu_dev, &freq_table); | ||
607 | - } | ||
608 | - | ||
609 | - if (freq_table) { | ||
610 | - result = cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
611 | - if (!result) | ||
612 | - cpufreq_frequency_table_get_attr(freq_table, | ||
613 | - policy->cpu); | ||
614 | - } else { | ||
615 | - policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; | ||
616 | - policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, | ||
617 | - VERY_HI_RATE) / 1000; | ||
618 | - } | ||
619 | - | ||
620 | - policy->min = policy->cpuinfo.min_freq; | ||
621 | - policy->max = policy->cpuinfo.max_freq; | ||
622 | - policy->cur = omap_getspeed(0); | ||
623 | - | ||
624 | - /* FIXME: what's the actual transition time? */ | ||
625 | - policy->cpuinfo.transition_latency = 300 * 1000; | ||
626 | - | ||
627 | - return 0; | ||
628 | -} | ||
629 | - | ||
630 | -static int omap_cpu_exit(struct cpufreq_policy *policy) | ||
631 | -{ | ||
632 | - clk_exit_cpufreq_table(&freq_table); | ||
633 | - clk_put(mpu_clk); | ||
634 | - return 0; | ||
635 | -} | ||
636 | - | ||
637 | -static struct freq_attr *omap_cpufreq_attr[] = { | ||
638 | - &cpufreq_freq_attr_scaling_available_freqs, | ||
639 | - NULL, | ||
640 | -}; | ||
641 | - | ||
642 | -static struct cpufreq_driver omap_driver = { | ||
643 | - .flags = CPUFREQ_STICKY, | ||
644 | - .verify = omap_verify_speed, | ||
645 | - .target = omap_target, | ||
646 | - .get = omap_getspeed, | ||
647 | - .init = omap_cpu_init, | ||
648 | - .exit = omap_cpu_exit, | ||
649 | - .name = "omap", | ||
650 | - .attr = omap_cpufreq_attr, | ||
651 | -}; | ||
652 | - | ||
653 | -static int __init omap_cpufreq_init(void) | ||
654 | -{ | ||
655 | - return cpufreq_register_driver(&omap_driver); | ||
656 | -} | ||
657 | - | ||
658 | -late_initcall(omap_cpufreq_init); | ||
659 | - | ||
660 | -/* | ||
661 | - * if ever we want to remove this, upon cleanup call: | ||
662 | - * | ||
663 | - * cpufreq_unregister_driver() | ||
664 | - * cpufreq_frequency_table_put_attr() | ||
665 | - */ | ||
666 | - | ||
667 | -- | ||
668 | 1.6.6.1 | ||
669 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0007-OMAP2PLUS-cpufreq-Add-SMP-support-to-cater-OMAP4430.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0007-OMAP2PLUS-cpufreq-Add-SMP-support-to-cater-OMAP4430.patch deleted file mode 100644 index 6624d1ec..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0007-OMAP2PLUS-cpufreq-Add-SMP-support-to-cater-OMAP4430.patch +++ /dev/null | |||
@@ -1,170 +0,0 @@ | |||
1 | From f375d3c39d2835929d34c2a046b8c43cea6d1467 Mon Sep 17 00:00:00 2001 | ||
2 | From: Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
3 | Date: Mon, 14 Mar 2011 17:08:49 +0530 | ||
4 | Subject: [PATCH 7/8] OMAP2PLUS: cpufreq: Add SMP support to cater OMAP4430 | ||
5 | |||
6 | On OMAP SMP configuartion, both processors share the voltage | ||
7 | and clock. So both CPUs needs to be scaled together and hence | ||
8 | needs software co-ordination. | ||
9 | |||
10 | Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
11 | Cc: Kevin Hilman <khilman@ti.com> | ||
12 | cc: Vishwanath BS <vishwanath.bs@ti.com> | ||
13 | --- | ||
14 | arch/arm/mach-omap2/omap2plus-cpufreq.c | 73 ++++++++++++++++++++++++++----- | ||
15 | 1 files changed, 62 insertions(+), 11 deletions(-) | ||
16 | |||
17 | diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
18 | index 14f84cc..8d472f6 100644 | ||
19 | --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
20 | +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
21 | @@ -26,9 +26,11 @@ | ||
22 | #include <linux/clk.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <linux/opp.h> | ||
25 | +#include <linux/cpu.h> | ||
26 | |||
27 | #include <asm/system.h> | ||
28 | #include <asm/smp_plat.h> | ||
29 | +#include <asm/cpu.h> | ||
30 | |||
31 | #include <plat/clock.h> | ||
32 | #include <plat/omap-pm.h> | ||
33 | @@ -63,7 +65,7 @@ static unsigned int omap_getspeed(unsigned int cpu) | ||
34 | { | ||
35 | unsigned long rate; | ||
36 | |||
37 | - if (cpu) | ||
38 | + if (cpu >= NR_CPUS) | ||
39 | return 0; | ||
40 | |||
41 | rate = clk_get_rate(mpu_clk) / 1000; | ||
42 | @@ -74,9 +76,13 @@ static int omap_target(struct cpufreq_policy *policy, | ||
43 | unsigned int target_freq, | ||
44 | unsigned int relation) | ||
45 | { | ||
46 | - int ret = 0; | ||
47 | + int i, ret = 0; | ||
48 | struct cpufreq_freqs freqs; | ||
49 | |||
50 | + /* Changes not allowed until all CPUs are online */ | ||
51 | + if (is_smp() && (num_online_cpus() < NR_CPUS)) | ||
52 | + return ret; | ||
53 | + | ||
54 | /* Ensure desired rate is within allowed range. Some govenors | ||
55 | * (ondemand) will just pass target_freq=0 to get the minimum. */ | ||
56 | if (target_freq < policy->min) | ||
57 | @@ -84,15 +90,25 @@ static int omap_target(struct cpufreq_policy *policy, | ||
58 | if (target_freq > policy->max) | ||
59 | target_freq = policy->max; | ||
60 | |||
61 | - freqs.old = omap_getspeed(0); | ||
62 | + freqs.old = omap_getspeed(policy->cpu); | ||
63 | freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; | ||
64 | - freqs.cpu = 0; | ||
65 | + freqs.cpu = policy->cpu; | ||
66 | |||
67 | if (freqs.old == freqs.new) | ||
68 | return ret; | ||
69 | |||
70 | - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
71 | + if (!is_smp()) { | ||
72 | + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
73 | + goto set_freq; | ||
74 | + } | ||
75 | + | ||
76 | + /* notifiers */ | ||
77 | + for_each_cpu(i, policy->cpus) { | ||
78 | + freqs.cpu = i; | ||
79 | + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
80 | + } | ||
81 | |||
82 | +set_freq: | ||
83 | #ifdef CONFIG_CPU_FREQ_DEBUG | ||
84 | pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new); | ||
85 | #endif | ||
86 | @@ -105,12 +121,33 @@ static int omap_target(struct cpufreq_policy *policy, | ||
87 | * CONFIG_SMP enabled. Below code is added only to manage that | ||
88 | * scenario | ||
89 | */ | ||
90 | - if (!is_smp()) | ||
91 | + freqs.new = omap_getspeed(policy->cpu); | ||
92 | + if (!is_smp()) { | ||
93 | loops_per_jiffy = | ||
94 | cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new); | ||
95 | + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
96 | + goto skip_lpj; | ||
97 | + } | ||
98 | |||
99 | - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
100 | +#ifdef CONFIG_SMP | ||
101 | + /* | ||
102 | + * Note that loops_per_jiffy is not updated on SMP systems in | ||
103 | + * cpufreq driver. So, update the per-CPU loops_per_jiffy value | ||
104 | + * on frequency transition. We need to update all dependent CPUs. | ||
105 | + */ | ||
106 | + for_each_cpu(i, policy->cpus) | ||
107 | + per_cpu(cpu_data, i).loops_per_jiffy = | ||
108 | + cpufreq_scale(per_cpu(cpu_data, i).loops_per_jiffy, | ||
109 | + freqs.old, freqs.new); | ||
110 | +#endif | ||
111 | |||
112 | + /* notifiers */ | ||
113 | + for_each_cpu(i, policy->cpus) { | ||
114 | + freqs.cpu = i; | ||
115 | + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
116 | + } | ||
117 | + | ||
118 | +skip_lpj: | ||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | @@ -118,6 +155,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
123 | { | ||
124 | int result = 0; | ||
125 | struct device *mpu_dev; | ||
126 | + static cpumask_var_t cpumask; | ||
127 | |||
128 | if (cpu_is_omap24xx()) | ||
129 | mpu_clk = clk_get(NULL, "virt_prcm_set"); | ||
130 | @@ -129,12 +167,12 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
131 | if (IS_ERR(mpu_clk)) | ||
132 | return PTR_ERR(mpu_clk); | ||
133 | |||
134 | - if (policy->cpu != 0) | ||
135 | + if (policy->cpu >= NR_CPUS) | ||
136 | return -EINVAL; | ||
137 | |||
138 | - policy->cur = policy->min = policy->max = omap_getspeed(0); | ||
139 | - | ||
140 | + policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu); | ||
141 | mpu_dev = omap2_get_mpuss_device(); | ||
142 | + | ||
143 | if (!mpu_dev) { | ||
144 | pr_warning("%s: unable to get the mpu device\n", __func__); | ||
145 | return -EINVAL; | ||
146 | @@ -154,7 +192,20 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
147 | |||
148 | policy->min = policy->cpuinfo.min_freq; | ||
149 | policy->max = policy->cpuinfo.max_freq; | ||
150 | - policy->cur = omap_getspeed(0); | ||
151 | + policy->cur = omap_getspeed(policy->cpu); | ||
152 | + | ||
153 | + /* | ||
154 | + * On OMAP SMP configuartion, both processors share the voltage | ||
155 | + * and clock. So both CPUs needs to be scaled together and hence | ||
156 | + * needs software co-ordination. Use cpufreq affected_cpus | ||
157 | + * interface to handle this scenario. Additional is_smp() check | ||
158 | + * is to keep SMP_ON_UP build working. | ||
159 | + */ | ||
160 | + if (is_smp()) { | ||
161 | + policy->shared_type = CPUFREQ_SHARED_TYPE_ANY; | ||
162 | + cpumask_or(cpumask, cpumask_of(policy->cpu), cpumask); | ||
163 | + cpumask_copy(policy->cpus, cpumask); | ||
164 | + } | ||
165 | |||
166 | /* FIXME: what's the actual transition time? */ | ||
167 | policy->cpuinfo.transition_latency = 300 * 1000; | ||
168 | -- | ||
169 | 1.6.6.1 | ||
170 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0008-OMAP2PLUS-cpufreq-Fix-typo-when-attempting-to-set-mp.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0008-OMAP2PLUS-cpufreq-Fix-typo-when-attempting-to-set-mp.patch deleted file mode 100644 index 3797443c..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0008-OMAP2PLUS-cpufreq-Fix-typo-when-attempting-to-set-mp.patch +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | From 6e101764a47cb6975a555e2237843ad391a542a4 Mon Sep 17 00:00:00 2001 | ||
2 | From: Jarkko Nikula <jhnikula@gmail.com> | ||
3 | Date: Thu, 14 Apr 2011 16:21:58 +0300 | ||
4 | Subject: [PATCH 8/8] OMAP2PLUS: cpufreq: Fix typo when attempting to set mpu_clk for OMAP4 | ||
5 | |||
6 | Fix this typo as there is no dpll_mpu_ck for OMAP3 and code flow is clearly | ||
7 | trying to set mpu_clk for OMAP4 for which this dpll_mpu_ck is available. | ||
8 | |||
9 | Signed-off-by: Jarkko Nikula <jhnikula@gmail.com> | ||
10 | --- | ||
11 | arch/arm/mach-omap2/omap2plus-cpufreq.c | 2 +- | ||
12 | 1 files changed, 1 insertions(+), 1 deletions(-) | ||
13 | |||
14 | diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
15 | index 8d472f6..d53ce23 100644 | ||
16 | --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
17 | +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
18 | @@ -161,7 +161,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
19 | mpu_clk = clk_get(NULL, "virt_prcm_set"); | ||
20 | else if (cpu_is_omap34xx()) | ||
21 | mpu_clk = clk_get(NULL, "dpll1_ck"); | ||
22 | - else if (cpu_is_omap34xx()) | ||
23 | + else if (cpu_is_omap44xx()) | ||
24 | mpu_clk = clk_get(NULL, "dpll_mpu_ck"); | ||
25 | |||
26 | if (IS_ERR(mpu_clk)) | ||
27 | -- | ||
28 | 1.6.6.1 | ||
29 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0001-OMAP2-clockdomain-Add-an-api-to-read-idle-mode.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0001-OMAP2-clockdomain-Add-an-api-to-read-idle-mode.patch deleted file mode 100644 index d9b05173..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0001-OMAP2-clockdomain-Add-an-api-to-read-idle-mode.patch +++ /dev/null | |||
@@ -1,77 +0,0 @@ | |||
1 | From 988f50cb51d18e81ed2f7673a09694d28c9d086a Mon Sep 17 00:00:00 2001 | ||
2 | From: Rajendra Nayak <rnayak@ti.com> | ||
3 | Date: Tue, 5 Apr 2011 15:22:31 +0530 | ||
4 | Subject: [PATCH 1/6] OMAP2+: clockdomain: Add an api to read idle mode | ||
5 | |||
6 | Add a clockdomain api to check if hardware supervised | ||
7 | idle transitions are enabled on a clockdomain. | ||
8 | |||
9 | Signed-off-by: Rajendra Nayak <rnayak@ti.com> | ||
10 | --- | ||
11 | arch/arm/mach-omap2/clockdomain.c | 21 +++++++++++++++++++++ | ||
12 | arch/arm/mach-omap2/clockdomain.h | 3 +++ | ||
13 | 2 files changed, 24 insertions(+), 0 deletions(-) | ||
14 | |||
15 | diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c | ||
16 | index 6cb6c03..2ab3686 100644 | ||
17 | --- a/arch/arm/mach-omap2/clockdomain.c | ||
18 | +++ b/arch/arm/mach-omap2/clockdomain.c | ||
19 | @@ -795,6 +795,27 @@ void clkdm_deny_idle(struct clockdomain *clkdm) | ||
20 | arch_clkdm->clkdm_deny_idle(clkdm); | ||
21 | } | ||
22 | |||
23 | +/** | ||
24 | + * clkdm_is_idle - Check if the clkdm hwsup/autoidle is enabled | ||
25 | + * @clkdm: struct clockdomain * | ||
26 | + * | ||
27 | + * Returns true if the clockdomain is in hardware-supervised | ||
28 | + * idle mode, or 0 otherwise. | ||
29 | + * | ||
30 | + */ | ||
31 | +int clkdm_is_idle(struct clockdomain *clkdm) | ||
32 | +{ | ||
33 | + if (!clkdm) | ||
34 | + return -EINVAL; | ||
35 | + | ||
36 | + if (!arch_clkdm || !arch_clkdm->clkdm_is_idle) | ||
37 | + return -EINVAL; | ||
38 | + | ||
39 | + pr_debug("clockdomain: reading idle state for %s\n", clkdm->name); | ||
40 | + | ||
41 | + return arch_clkdm->clkdm_is_idle(clkdm); | ||
42 | +} | ||
43 | + | ||
44 | |||
45 | /* Clockdomain-to-clock framework interface code */ | ||
46 | |||
47 | diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h | ||
48 | index 5823584..085ed82 100644 | ||
49 | --- a/arch/arm/mach-omap2/clockdomain.h | ||
50 | +++ b/arch/arm/mach-omap2/clockdomain.h | ||
51 | @@ -138,6 +138,7 @@ struct clockdomain { | ||
52 | * @clkdm_wakeup: Force a clockdomain to wakeup | ||
53 | * @clkdm_allow_idle: Enable hw supervised idle transitions for clock domain | ||
54 | * @clkdm_deny_idle: Disable hw supervised idle transitions for clock domain | ||
55 | + * @clkdm_is_idle: Check if hw supervised idle transitions are enabled | ||
56 | * @clkdm_clk_enable: Put the clkdm in right state for a clock enable | ||
57 | * @clkdm_clk_disable: Put the clkdm in right state for a clock disable | ||
58 | */ | ||
59 | @@ -154,6 +155,7 @@ struct clkdm_ops { | ||
60 | int (*clkdm_wakeup)(struct clockdomain *clkdm); | ||
61 | void (*clkdm_allow_idle)(struct clockdomain *clkdm); | ||
62 | void (*clkdm_deny_idle)(struct clockdomain *clkdm); | ||
63 | + int (*clkdm_is_idle)(struct clockdomain *clkdm); | ||
64 | int (*clkdm_clk_enable)(struct clockdomain *clkdm); | ||
65 | int (*clkdm_clk_disable)(struct clockdomain *clkdm); | ||
66 | }; | ||
67 | @@ -177,6 +179,7 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm); | ||
68 | |||
69 | void clkdm_allow_idle(struct clockdomain *clkdm); | ||
70 | void clkdm_deny_idle(struct clockdomain *clkdm); | ||
71 | +int clkdm_is_idle(struct clockdomain *clkdm); | ||
72 | |||
73 | int clkdm_wakeup(struct clockdomain *clkdm); | ||
74 | int clkdm_sleep(struct clockdomain *clkdm); | ||
75 | -- | ||
76 | 1.6.6.1 | ||
77 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0002-OMAP2-clockdomain-Add-SoC-support-for-clkdm_is_idle.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0002-OMAP2-clockdomain-Add-SoC-support-for-clkdm_is_idle.patch deleted file mode 100644 index c7c1ea0b..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0002-OMAP2-clockdomain-Add-SoC-support-for-clkdm_is_idle.patch +++ /dev/null | |||
@@ -1,86 +0,0 @@ | |||
1 | From e3ba8d41bfafd782f3ee7f8930d9bf393986c662 Mon Sep 17 00:00:00 2001 | ||
2 | From: Rajendra Nayak <rnayak@ti.com> | ||
3 | Date: Tue, 5 Apr 2011 15:22:36 +0530 | ||
4 | Subject: [PATCH 2/6] OMAP2+: clockdomain: Add SoC support for clkdm_is_idle | ||
5 | |||
6 | Add the SoC specific implemenation for clkdm_is_idle | ||
7 | for OMAP2/3 and OMAP4. | ||
8 | |||
9 | Signed-off-by: Rajendra Nayak <rnayak@ti.com> | ||
10 | --- | ||
11 | arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | 12 ++++++++++++ | ||
12 | arch/arm/mach-omap2/clockdomain44xx.c | 7 +++++++ | ||
13 | 2 files changed, 19 insertions(+), 0 deletions(-) | ||
14 | |||
15 | diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | ||
16 | index 48d0db7..db49baa 100644 | ||
17 | --- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | ||
18 | +++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | ||
19 | @@ -13,6 +13,7 @@ | ||
20 | */ | ||
21 | |||
22 | #include <linux/types.h> | ||
23 | +#include <linux/errno.h> | ||
24 | #include <plat/prcm.h> | ||
25 | #include "prm.h" | ||
26 | #include "prm2xxx_3xxx.h" | ||
27 | @@ -146,6 +147,15 @@ static void omap2_clkdm_deny_idle(struct clockdomain *clkdm) | ||
28 | _clkdm_del_autodeps(clkdm); | ||
29 | } | ||
30 | |||
31 | +static int omap2_clkdm_is_idle(struct clockdomain *clkdm) | ||
32 | +{ | ||
33 | + if (!clkdm->clktrctrl_mask) | ||
34 | + return -1; | ||
35 | + | ||
36 | + return omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, | ||
37 | + clkdm->clktrctrl_mask); | ||
38 | +} | ||
39 | + | ||
40 | static void _enable_hwsup(struct clockdomain *clkdm) | ||
41 | { | ||
42 | if (cpu_is_omap24xx()) | ||
43 | @@ -252,6 +262,7 @@ struct clkdm_ops omap2_clkdm_operations = { | ||
44 | .clkdm_wakeup = omap2_clkdm_wakeup, | ||
45 | .clkdm_allow_idle = omap2_clkdm_allow_idle, | ||
46 | .clkdm_deny_idle = omap2_clkdm_deny_idle, | ||
47 | + .clkdm_is_idle = omap2_clkdm_is_idle, | ||
48 | .clkdm_clk_enable = omap2_clkdm_clk_enable, | ||
49 | .clkdm_clk_disable = omap2_clkdm_clk_disable, | ||
50 | }; | ||
51 | @@ -269,6 +280,7 @@ struct clkdm_ops omap3_clkdm_operations = { | ||
52 | .clkdm_wakeup = omap3_clkdm_wakeup, | ||
53 | .clkdm_allow_idle = omap3_clkdm_allow_idle, | ||
54 | .clkdm_deny_idle = omap3_clkdm_deny_idle, | ||
55 | + .clkdm_is_idle = omap2_clkdm_is_idle, | ||
56 | .clkdm_clk_enable = omap2_clkdm_clk_enable, | ||
57 | .clkdm_clk_disable = omap2_clkdm_clk_disable, | ||
58 | }; | ||
59 | diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c | ||
60 | index a1a4ecd..4b10727 100644 | ||
61 | --- a/arch/arm/mach-omap2/clockdomain44xx.c | ||
62 | +++ b/arch/arm/mach-omap2/clockdomain44xx.c | ||
63 | @@ -93,6 +93,12 @@ static void omap4_clkdm_deny_idle(struct clockdomain *clkdm) | ||
64 | clkdm->cm_inst, clkdm->clkdm_offs); | ||
65 | } | ||
66 | |||
67 | +static int omap4_clkdm_is_idle(struct clockdomain *clkdm) | ||
68 | +{ | ||
69 | + return omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition, | ||
70 | + clkdm->cm_inst, clkdm->clkdm_offs); | ||
71 | +} | ||
72 | + | ||
73 | static int omap4_clkdm_clk_enable(struct clockdomain *clkdm) | ||
74 | { | ||
75 | bool hwsup = false; | ||
76 | @@ -132,6 +138,7 @@ struct clkdm_ops omap4_clkdm_operations = { | ||
77 | .clkdm_wakeup = omap4_clkdm_wakeup, | ||
78 | .clkdm_allow_idle = omap4_clkdm_allow_idle, | ||
79 | .clkdm_deny_idle = omap4_clkdm_deny_idle, | ||
80 | + .clkdm_is_idle = omap4_clkdm_is_idle, | ||
81 | .clkdm_clk_enable = omap4_clkdm_clk_enable, | ||
82 | .clkdm_clk_disable = omap4_clkdm_clk_disable, | ||
83 | }; | ||
84 | -- | ||
85 | 1.6.6.1 | ||
86 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0003-OMAP2-PM-Initialise-sleep_switch-to-a-non-valid-valu.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0003-OMAP2-PM-Initialise-sleep_switch-to-a-non-valid-valu.patch deleted file mode 100644 index cbe5ca20..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0003-OMAP2-PM-Initialise-sleep_switch-to-a-non-valid-valu.patch +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | From 7cdc87071a4bb390ad5d7ddea210bd2b4d662114 Mon Sep 17 00:00:00 2001 | ||
2 | From: Rajendra Nayak <rnayak@ti.com> | ||
3 | Date: Tue, 5 Apr 2011 15:22:41 +0530 | ||
4 | Subject: [PATCH 3/6] OMAP2+: PM: Initialise sleep_switch to a non-valid value | ||
5 | |||
6 | sleep_switch which is initialised to 0 in omap_set_pwrdm_state | ||
7 | happens to be a valid sleep_switch type (FORCEWAKEUP_SWITCH) | ||
8 | which are defined as | ||
9 | #define FORCEWAKEUP_SWITCH 0 | ||
10 | #define LOWPOWERSTATE_SWITCH 1 | ||
11 | |||
12 | This causes the function to wrongly program some clock domains | ||
13 | even when the Powerdomain is in ON state. | ||
14 | |||
15 | Signed-off-by: Rajendra Nayak <rnayak@ti.com> | ||
16 | --- | ||
17 | arch/arm/mach-omap2/pm.c | 2 +- | ||
18 | 1 files changed, 1 insertions(+), 1 deletions(-) | ||
19 | |||
20 | diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c | ||
21 | index 49486f5..d48813f 100644 | ||
22 | --- a/arch/arm/mach-omap2/pm.c | ||
23 | +++ b/arch/arm/mach-omap2/pm.c | ||
24 | @@ -106,7 +106,7 @@ static void omap2_init_processor_devices(void) | ||
25 | int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) | ||
26 | { | ||
27 | u32 cur_state; | ||
28 | - int sleep_switch = 0; | ||
29 | + int sleep_switch = -1; | ||
30 | int ret = 0; | ||
31 | |||
32 | if (pwrdm == NULL || IS_ERR(pwrdm)) | ||
33 | -- | ||
34 | 1.6.6.1 | ||
35 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0004-OMAP2-PM-idle-clkdms-only-if-already-in-idle.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0004-OMAP2-PM-idle-clkdms-only-if-already-in-idle.patch deleted file mode 100644 index 16eedf9a..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0004-OMAP2-PM-idle-clkdms-only-if-already-in-idle.patch +++ /dev/null | |||
@@ -1,50 +0,0 @@ | |||
1 | From cec133850aa42c03d912c764aaa441677e782eca Mon Sep 17 00:00:00 2001 | ||
2 | From: Rajendra Nayak <rnayak@ti.com> | ||
3 | Date: Tue, 5 Apr 2011 15:22:48 +0530 | ||
4 | Subject: [PATCH 4/6] OMAP2+: PM: idle clkdms only if already in idle | ||
5 | |||
6 | The omap_set_pwrdm_state function forces clockdomains | ||
7 | to idle, without checking the existing idle state | ||
8 | programmed, instead based solely on the HW capability | ||
9 | of the clockdomain to support idle. | ||
10 | This is wrong and the clockdomains should be idled | ||
11 | post a state_switch *only* if idle transitions on the | ||
12 | clockdomain were already enabled. | ||
13 | |||
14 | Signed-off-by: Rajendra Nayak <rnayak@ti.com> | ||
15 | --- | ||
16 | arch/arm/mach-omap2/pm.c | 4 +++- | ||
17 | 1 files changed, 3 insertions(+), 1 deletions(-) | ||
18 | |||
19 | diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c | ||
20 | index d48813f..840b0e1 100644 | ||
21 | --- a/arch/arm/mach-omap2/pm.c | ||
22 | +++ b/arch/arm/mach-omap2/pm.c | ||
23 | @@ -108,6 +108,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) | ||
24 | u32 cur_state; | ||
25 | int sleep_switch = -1; | ||
26 | int ret = 0; | ||
27 | + int hwsup = 0; | ||
28 | |||
29 | if (pwrdm == NULL || IS_ERR(pwrdm)) | ||
30 | return -EINVAL; | ||
31 | @@ -127,6 +128,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) | ||
32 | (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) { | ||
33 | sleep_switch = LOWPOWERSTATE_SWITCH; | ||
34 | } else { | ||
35 | + hwsup = clkdm_is_idle(pwrdm->pwrdm_clkdms[0]); | ||
36 | clkdm_wakeup(pwrdm->pwrdm_clkdms[0]); | ||
37 | pwrdm_wait_transition(pwrdm); | ||
38 | sleep_switch = FORCEWAKEUP_SWITCH; | ||
39 | @@ -142,7 +144,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) | ||
40 | |||
41 | switch (sleep_switch) { | ||
42 | case FORCEWAKEUP_SWITCH: | ||
43 | - if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO) | ||
44 | + if (hwsup) | ||
45 | clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); | ||
46 | else | ||
47 | clkdm_sleep(pwrdm->pwrdm_clkdms[0]); | ||
48 | -- | ||
49 | 1.6.6.1 | ||
50 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0005-OMAP2-hwmod-Follow-the-recomended-PRCM-sequence.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0005-OMAP2-hwmod-Follow-the-recomended-PRCM-sequence.patch deleted file mode 100644 index b0af9e7f..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0005-OMAP2-hwmod-Follow-the-recomended-PRCM-sequence.patch +++ /dev/null | |||
@@ -1,46 +0,0 @@ | |||
1 | From 8fb6b7c488b31fbff5b81bdeea5dbb236342458b Mon Sep 17 00:00:00 2001 | ||
2 | From: Rajendra Nayak <rnayak@ti.com> | ||
3 | Date: Tue, 29 Mar 2011 22:37:43 +0530 | ||
4 | Subject: [PATCH 5/6] OMAP2+: hwmod: Follow the recomended PRCM sequence | ||
5 | |||
6 | Follow the recomended PRCM sequence. | ||
7 | This still does not take care of Optional clocks. | ||
8 | |||
9 | Signed-off-by: Rajendra Nayak <rnayak@ti.com> | ||
10 | --- | ||
11 | arch/arm/mach-omap2/omap_hwmod.c | 9 ++++++++- | ||
12 | 1 files changed, 8 insertions(+), 1 deletions(-) | ||
13 | |||
14 | diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c | ||
15 | index e034294..fc0db0c 100644 | ||
16 | --- a/arch/arm/mach-omap2/omap_hwmod.c | ||
17 | +++ b/arch/arm/mach-omap2/omap_hwmod.c | ||
18 | @@ -1223,6 +1223,7 @@ static int _reset(struct omap_hwmod *oh) | ||
19 | static int _enable(struct omap_hwmod *oh) | ||
20 | { | ||
21 | int r; | ||
22 | + int hwsup = 0; | ||
23 | |||
24 | if (oh->_state != _HWMOD_STATE_INITIALIZED && | ||
25 | oh->_state != _HWMOD_STATE_IDLE && | ||
26 | @@ -1250,10 +1251,16 @@ static int _enable(struct omap_hwmod *oh) | ||
27 | omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED); | ||
28 | |||
29 | _add_initiator_dep(oh, mpu_oh); | ||
30 | + if (oh->_clk && oh->_clk->clkdm) { | ||
31 | + hwsup = clkdm_is_idle(oh->_clk->clkdm); | ||
32 | + clkdm_wakeup(oh->_clk->clkdm); | ||
33 | + } | ||
34 | _enable_clocks(oh); | ||
35 | - | ||
36 | r = _wait_target_ready(oh); | ||
37 | if (!r) { | ||
38 | + if (oh->_clk && oh->_clk->clkdm && hwsup) | ||
39 | + clkdm_allow_idle(oh->_clk->clkdm); | ||
40 | + | ||
41 | oh->_state = _HWMOD_STATE_ENABLED; | ||
42 | |||
43 | /* Access the sysconfig only if the target is ready */ | ||
44 | -- | ||
45 | 1.6.6.1 | ||
46 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0006-OMAP-Serial-Check-wk_st-only-if-present.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0006-OMAP-Serial-Check-wk_st-only-if-present.patch deleted file mode 100644 index a8fc0c07..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0006-OMAP-Serial-Check-wk_st-only-if-present.patch +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | From 7b74888d198c260992349fab214cad3adf853ef9 Mon Sep 17 00:00:00 2001 | ||
2 | From: Rajendra Nayak <rnayak@ti.com> | ||
3 | Date: Tue, 2 Mar 2010 17:25:30 +0530 | ||
4 | Subject: [PATCH 6/6] OMAP: Serial: Check wk_st only if present | ||
5 | |||
6 | Uart on the resume path tries to read wk_st registers, even | ||
7 | on architectures were its not present/populated. | ||
8 | This patch fixes the issue. | ||
9 | |||
10 | Signed-off-by: Rajendra Nayak <rnayak@ti.com> | ||
11 | --- | ||
12 | arch/arm/mach-omap2/serial.c | 5 +++-- | ||
13 | 1 files changed, 3 insertions(+), 2 deletions(-) | ||
14 | |||
15 | diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c | ||
16 | index 1ac361b..a0046ce 100644 | ||
17 | --- a/arch/arm/mach-omap2/serial.c | ||
18 | +++ b/arch/arm/mach-omap2/serial.c | ||
19 | @@ -418,8 +418,9 @@ void omap_uart_resume_idle(int num) | ||
20 | } | ||
21 | |||
22 | /* Check for normal UART wakeup */ | ||
23 | - if (__raw_readl(uart->wk_st) & uart->wk_mask) | ||
24 | - omap_uart_block_sleep(uart); | ||
25 | + if (uart->wk_st && uart->wk_mask) | ||
26 | + if (__raw_readl(uart->wk_st) & uart->wk_mask) | ||
27 | + omap_uart_block_sleep(uart); | ||
28 | return; | ||
29 | } | ||
30 | } | ||
31 | -- | ||
32 | 1.6.6.1 | ||
33 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0001-OMAP3-voltage-remove-spurious-pr_notice-for-debugfs.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0001-OMAP3-voltage-remove-spurious-pr_notice-for-debugfs.patch deleted file mode 100644 index 0d1cbce6..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0001-OMAP3-voltage-remove-spurious-pr_notice-for-debugfs.patch +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | From 4af697edf9d1d85d2735e86e86e1203c3509dcba Mon Sep 17 00:00:00 2001 | ||
2 | From: Nishanth Menon <nm@ti.com> | ||
3 | Date: Sat, 12 Feb 2011 17:27:14 +0530 | ||
4 | Subject: [PATCH 01/12] OMAP3+: voltage: remove spurious pr_notice for debugfs | ||
5 | |||
6 | cat of debugfs entry for vp_volt provides voltage. The additional pr_notice | ||
7 | is just spam on console and provides no additional information. | ||
8 | |||
9 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
10 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
11 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
12 | --- | ||
13 | arch/arm/mach-omap2/voltage.c | 1 - | ||
14 | 1 files changed, 0 insertions(+), 1 deletions(-) | ||
15 | |||
16 | diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c | ||
17 | index 0c1552d..9ef3789 100644 | ||
18 | --- a/arch/arm/mach-omap2/voltage.c | ||
19 | +++ b/arch/arm/mach-omap2/voltage.c | ||
20 | @@ -148,7 +148,6 @@ static int vp_volt_debug_get(void *data, u64 *val) | ||
21 | } | ||
22 | |||
23 | vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage); | ||
24 | - pr_notice("curr_vsel = %x\n", vsel); | ||
25 | |||
26 | if (!vdd->pmic_info->vsel_to_uv) { | ||
27 | pr_warning("PMIC function to convert vsel to voltage" | ||
28 | -- | ||
29 | 1.6.6.1 | ||
30 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0002-OMAP4-PM-remove-redundant-ifdef-CONFIG_PM.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0002-OMAP4-PM-remove-redundant-ifdef-CONFIG_PM.patch deleted file mode 100644 index 7b137925..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0002-OMAP4-PM-remove-redundant-ifdef-CONFIG_PM.patch +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | From 37fb1c8eeecd39542716d3d0c7c5e3ca0eb198f8 Mon Sep 17 00:00:00 2001 | ||
2 | From: Nishanth Menon <nm@ti.com> | ||
3 | Date: Sun, 13 Mar 2011 09:07:23 +0530 | ||
4 | Subject: [PATCH 02/12] OMAP4: PM: remove redundant #ifdef CONFIG_PM | ||
5 | |||
6 | pm44xx.c is built only when CONFIG_PM is setup, | ||
7 | remove redundant CONFIG_PM check. | ||
8 | |||
9 | This also fixes: | ||
10 | https://bugzilla.kernel.org/show_bug.cgi?id=25022 | ||
11 | |||
12 | Reported-by: Martin Etti <ettl.martin@gmx.de> | ||
13 | |||
14 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
15 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
16 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
17 | --- | ||
18 | arch/arm/mach-omap2/pm44xx.c | 2 -- | ||
19 | 1 files changed, 0 insertions(+), 2 deletions(-) | ||
20 | |||
21 | diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c | ||
22 | index 76cfff2..59a870b 100644 | ||
23 | --- a/arch/arm/mach-omap2/pm44xx.c | ||
24 | +++ b/arch/arm/mach-omap2/pm44xx.c | ||
25 | @@ -105,13 +105,11 @@ static int __init omap4_pm_init(void) | ||
26 | |||
27 | pr_err("Power Management for TI OMAP4.\n"); | ||
28 | |||
29 | -#ifdef CONFIG_PM | ||
30 | ret = pwrdm_for_each(pwrdms_setup, NULL); | ||
31 | if (ret) { | ||
32 | pr_err("Failed to setup powerdomains\n"); | ||
33 | goto err2; | ||
34 | } | ||
35 | -#endif | ||
36 | |||
37 | #ifdef CONFIG_SUSPEND | ||
38 | suspend_set_ops(&omap_pm_ops); | ||
39 | -- | ||
40 | 1.6.6.1 | ||
41 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0003-OMAP3-smartreflex-fix-sr_late_init-error-path-in-pro.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0003-OMAP3-smartreflex-fix-sr_late_init-error-path-in-pro.patch deleted file mode 100644 index 6c37b622..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0003-OMAP3-smartreflex-fix-sr_late_init-error-path-in-pro.patch +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | From a22a0dcefe99c8ee260e0c489bc44e6e14bb1ccb Mon Sep 17 00:00:00 2001 | ||
2 | From: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
3 | Date: Thu, 24 Mar 2011 18:35:31 +0200 | ||
4 | Subject: [PATCH 03/12] OMAP3+: smartreflex: fix sr_late_init() error path in probe | ||
5 | |||
6 | sr_late_init() will take care of freeing the resources. | ||
7 | |||
8 | Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
9 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
10 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
11 | --- | ||
12 | arch/arm/mach-omap2/smartreflex.c | 2 +- | ||
13 | 1 files changed, 1 insertions(+), 1 deletions(-) | ||
14 | |||
15 | diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c | ||
16 | index 13e24f9..dbc4b6f 100644 | ||
17 | --- a/arch/arm/mach-omap2/smartreflex.c | ||
18 | +++ b/arch/arm/mach-omap2/smartreflex.c | ||
19 | @@ -883,7 +883,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
20 | ret = sr_late_init(sr_info); | ||
21 | if (ret) { | ||
22 | pr_warning("%s: Error in SR late init\n", __func__); | ||
23 | - goto err_release_region; | ||
24 | + return ret; | ||
25 | } | ||
26 | } | ||
27 | |||
28 | -- | ||
29 | 1.6.6.1 | ||
30 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0004-OMAP3-smartreflex-request-the-memory-region.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0004-OMAP3-smartreflex-request-the-memory-region.patch deleted file mode 100644 index 263094d5..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0004-OMAP3-smartreflex-request-the-memory-region.patch +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | From db9c7da6a78be8584c96c83a3a2d1c8aeb623da8 Mon Sep 17 00:00:00 2001 | ||
2 | From: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
3 | Date: Thu, 24 Mar 2011 18:35:32 +0200 | ||
4 | Subject: [PATCH 04/12] OMAP3+: smartreflex: request the memory region | ||
5 | |||
6 | We are releasing the memory region, but never actually request it. | ||
7 | |||
8 | Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
9 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
10 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
11 | --- | ||
12 | arch/arm/mach-omap2/smartreflex.c | 8 ++++++++ | ||
13 | 1 files changed, 8 insertions(+), 0 deletions(-) | ||
14 | |||
15 | diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c | ||
16 | index dbc4b6f..703143a 100644 | ||
17 | --- a/arch/arm/mach-omap2/smartreflex.c | ||
18 | +++ b/arch/arm/mach-omap2/smartreflex.c | ||
19 | @@ -847,6 +847,14 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
20 | goto err_free_devinfo; | ||
21 | } | ||
22 | |||
23 | + mem = request_mem_region(mem->start, resource_size(mem), | ||
24 | + dev_name(&pdev->dev)); | ||
25 | + if (!mem) { | ||
26 | + dev_err(&pdev->dev, "%s: no mem region\n", __func__); | ||
27 | + ret = -EBUSY; | ||
28 | + goto err_free_devinfo; | ||
29 | + } | ||
30 | + | ||
31 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
32 | |||
33 | pm_runtime_enable(&pdev->dev); | ||
34 | -- | ||
35 | 1.6.6.1 | ||
36 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0005-OMAP3-smartreflex-fix-ioremap-leak-on-probe-error.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0005-OMAP3-smartreflex-fix-ioremap-leak-on-probe-error.patch deleted file mode 100644 index ea1e5673..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0005-OMAP3-smartreflex-fix-ioremap-leak-on-probe-error.patch +++ /dev/null | |||
@@ -1,66 +0,0 @@ | |||
1 | From b3ca51ac09da7c260c28df396d4c830814697ff0 Mon Sep 17 00:00:00 2001 | ||
2 | From: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
3 | Date: Thu, 24 Mar 2011 18:35:33 +0200 | ||
4 | Subject: [PATCH 05/12] OMAP3+: smartreflex: fix ioremap leak on probe error | ||
5 | |||
6 | Add missing iounmap() to error paths. | ||
7 | |||
8 | Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
9 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
10 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
11 | --- | ||
12 | arch/arm/mach-omap2/smartreflex.c | 10 ++++++---- | ||
13 | 1 files changed, 6 insertions(+), 4 deletions(-) | ||
14 | |||
15 | diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c | ||
16 | index 703143a..156807e 100644 | ||
17 | --- a/arch/arm/mach-omap2/smartreflex.c | ||
18 | +++ b/arch/arm/mach-omap2/smartreflex.c | ||
19 | @@ -904,7 +904,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
20 | vdd_dbg_dir = omap_voltage_get_dbgdir(sr_info->voltdm); | ||
21 | if (!vdd_dbg_dir) { | ||
22 | ret = -EINVAL; | ||
23 | - goto err_release_region; | ||
24 | + goto err_iounmap; | ||
25 | } | ||
26 | |||
27 | sr_info->dbg_dir = debugfs_create_dir("smartreflex", vdd_dbg_dir); | ||
28 | @@ -912,7 +912,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
29 | dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n", | ||
30 | __func__); | ||
31 | ret = PTR_ERR(sr_info->dbg_dir); | ||
32 | - goto err_release_region; | ||
33 | + goto err_iounmap; | ||
34 | } | ||
35 | |||
36 | (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR, | ||
37 | @@ -929,7 +929,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
38 | dev_err(&pdev->dev, "%s: Unable to create debugfs directory" | ||
39 | "for n-values\n", __func__); | ||
40 | ret = PTR_ERR(nvalue_dir); | ||
41 | - goto err_release_region; | ||
42 | + goto err_iounmap; | ||
43 | } | ||
44 | |||
45 | omap_voltage_get_volttable(sr_info->voltdm, &volt_data); | ||
46 | @@ -939,7 +939,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
47 | "entries for n-values\n", | ||
48 | __func__, sr_info->voltdm->name); | ||
49 | ret = -ENODATA; | ||
50 | - goto err_release_region; | ||
51 | + goto err_iounmap; | ||
52 | } | ||
53 | |||
54 | for (i = 0; i < sr_info->nvalue_count; i++) { | ||
55 | @@ -953,6 +953,8 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
56 | |||
57 | return ret; | ||
58 | |||
59 | +err_iounmap: | ||
60 | + iounmap(sr_info->base); | ||
61 | err_release_region: | ||
62 | release_mem_region(mem->start, resource_size(mem)); | ||
63 | err_free_devinfo: | ||
64 | -- | ||
65 | 1.6.6.1 | ||
66 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0006-OMAP3-smartreflex-delete-instance-from-sr_list-on-pr.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0006-OMAP3-smartreflex-delete-instance-from-sr_list-on-pr.patch deleted file mode 100644 index cda6da63..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0006-OMAP3-smartreflex-delete-instance-from-sr_list-on-pr.patch +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | From 92e63a2f098ce344cfc51ec9a7420e1a5cf85c3e Mon Sep 17 00:00:00 2001 | ||
2 | From: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
3 | Date: Thu, 24 Mar 2011 18:35:34 +0200 | ||
4 | Subject: [PATCH 06/12] OMAP3+: smartreflex: delete instance from sr_list on probe error | ||
5 | |||
6 | If the probe fails, the node should be deleted from sr_list. | ||
7 | |||
8 | Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
9 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
10 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
11 | --- | ||
12 | arch/arm/mach-omap2/smartreflex.c | 1 + | ||
13 | 1 files changed, 1 insertions(+), 0 deletions(-) | ||
14 | |||
15 | diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c | ||
16 | index 156807e..f0a488a 100644 | ||
17 | --- a/arch/arm/mach-omap2/smartreflex.c | ||
18 | +++ b/arch/arm/mach-omap2/smartreflex.c | ||
19 | @@ -954,6 +954,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
20 | return ret; | ||
21 | |||
22 | err_iounmap: | ||
23 | + list_del(&sr_info->node); | ||
24 | iounmap(sr_info->base); | ||
25 | err_release_region: | ||
26 | release_mem_region(mem->start, resource_size(mem)); | ||
27 | -- | ||
28 | 1.6.6.1 | ||
29 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0007-OMAP3-smartreflex-delete-debugfs-entries-on-probe-er.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0007-OMAP3-smartreflex-delete-debugfs-entries-on-probe-er.patch deleted file mode 100644 index d4543a46..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0007-OMAP3-smartreflex-delete-debugfs-entries-on-probe-er.patch +++ /dev/null | |||
@@ -1,48 +0,0 @@ | |||
1 | From c194377152df812bcb29fff8f217ffbde59089be Mon Sep 17 00:00:00 2001 | ||
2 | From: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
3 | Date: Thu, 24 Mar 2011 18:35:35 +0200 | ||
4 | Subject: [PATCH 07/12] OMAP3+: smartreflex: delete debugfs entries on probe error | ||
5 | |||
6 | Delete created debugfs entries if probe fails. | ||
7 | |||
8 | Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com> | ||
9 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
10 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
11 | --- | ||
12 | arch/arm/mach-omap2/smartreflex.c | 6 ++++-- | ||
13 | 1 files changed, 4 insertions(+), 2 deletions(-) | ||
14 | |||
15 | diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c | ||
16 | index f0a488a..fb7dc52 100644 | ||
17 | --- a/arch/arm/mach-omap2/smartreflex.c | ||
18 | +++ b/arch/arm/mach-omap2/smartreflex.c | ||
19 | @@ -929,7 +929,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
20 | dev_err(&pdev->dev, "%s: Unable to create debugfs directory" | ||
21 | "for n-values\n", __func__); | ||
22 | ret = PTR_ERR(nvalue_dir); | ||
23 | - goto err_iounmap; | ||
24 | + goto err_debugfs; | ||
25 | } | ||
26 | |||
27 | omap_voltage_get_volttable(sr_info->voltdm, &volt_data); | ||
28 | @@ -939,7 +939,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
29 | "entries for n-values\n", | ||
30 | __func__, sr_info->voltdm->name); | ||
31 | ret = -ENODATA; | ||
32 | - goto err_iounmap; | ||
33 | + goto err_debugfs; | ||
34 | } | ||
35 | |||
36 | for (i = 0; i < sr_info->nvalue_count; i++) { | ||
37 | @@ -953,6 +953,8 @@ static int __init omap_sr_probe(struct platform_device *pdev) | ||
38 | |||
39 | return ret; | ||
40 | |||
41 | +err_debugfs: | ||
42 | + debugfs_remove_recursive(sr_info->dbg_dir); | ||
43 | err_iounmap: | ||
44 | list_del(&sr_info->node); | ||
45 | iounmap(sr_info->base); | ||
46 | -- | ||
47 | 1.6.6.1 | ||
48 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0008-OMAP3-cpuidle-remove-useless-SDP-specific-timings.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0008-OMAP3-cpuidle-remove-useless-SDP-specific-timings.patch deleted file mode 100644 index e3ee0412..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0008-OMAP3-cpuidle-remove-useless-SDP-specific-timings.patch +++ /dev/null | |||
@@ -1,57 +0,0 @@ | |||
1 | From 2b9e07516cc3853340b5e06e9ae7244ca5681466 Mon Sep 17 00:00:00 2001 | ||
2 | From: Jean Pihet <j-pihet@ti.com> | ||
3 | Date: Fri, 29 Apr 2011 11:26:22 +0200 | ||
4 | Subject: [PATCH 08/12] OMAP3 cpuidle: remove useless SDP specific timings | ||
5 | |||
6 | The cpuidle states settings can be overriden by some board- | ||
7 | specific settings, by calling omap3_pm_init_cpuidle. | ||
8 | Remove the 3430SDP specific states settings registration | ||
9 | since the figures are identical to the default ones (in cpuidle34xx.c). | ||
10 | |||
11 | Signed-off-by: Jean Pihet <j-pihet@ti.com> | ||
12 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
13 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
14 | --- | ||
15 | arch/arm/mach-omap2/board-3430sdp.c | 19 ------------------- | ||
16 | 1 files changed, 0 insertions(+), 19 deletions(-) | ||
17 | |||
18 | diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c | ||
19 | index 9afd087..7ffad7b 100644 | ||
20 | --- a/arch/arm/mach-omap2/board-3430sdp.c | ||
21 | +++ b/arch/arm/mach-omap2/board-3430sdp.c | ||
22 | @@ -59,24 +59,6 @@ | ||
23 | |||
24 | #define TWL4030_MSECURE_GPIO 22 | ||
25 | |||
26 | -/* FIXME: These values need to be updated based on more profiling on 3430sdp*/ | ||
27 | -static struct cpuidle_params omap3_cpuidle_params_table[] = { | ||
28 | - /* C1 */ | ||
29 | - {1, 2, 2, 5}, | ||
30 | - /* C2 */ | ||
31 | - {1, 10, 10, 30}, | ||
32 | - /* C3 */ | ||
33 | - {1, 50, 50, 300}, | ||
34 | - /* C4 */ | ||
35 | - {1, 1500, 1800, 4000}, | ||
36 | - /* C5 */ | ||
37 | - {1, 2500, 7500, 12000}, | ||
38 | - /* C6 */ | ||
39 | - {1, 3000, 8500, 15000}, | ||
40 | - /* C7 */ | ||
41 | - {1, 10000, 30000, 300000}, | ||
42 | -}; | ||
43 | - | ||
44 | static uint32_t board_keymap[] = { | ||
45 | KEY(0, 0, KEY_LEFT), | ||
46 | KEY(0, 1, KEY_RIGHT), | ||
47 | @@ -883,7 +865,6 @@ static void __init omap_3430sdp_init(void) | ||
48 | omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); | ||
49 | omap_board_config = sdp3430_config; | ||
50 | omap_board_config_size = ARRAY_SIZE(sdp3430_config); | ||
51 | - omap3_pm_init_cpuidle(omap3_cpuidle_params_table); | ||
52 | omap3430_i2c_init(); | ||
53 | omap_display_init(&sdp3430_dss_data); | ||
54 | if (omap_rev() > OMAP3430_REV_ES1_0) | ||
55 | -- | ||
56 | 1.6.6.1 | ||
57 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0009-OMAP3-SR-make-notify-independent-of-class.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0009-OMAP3-SR-make-notify-independent-of-class.patch deleted file mode 100644 index c44371df..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0009-OMAP3-SR-make-notify-independent-of-class.patch +++ /dev/null | |||
@@ -1,48 +0,0 @@ | |||
1 | From a0f28097b944930e479998780863b9e5a39e30b3 Mon Sep 17 00:00:00 2001 | ||
2 | From: Nishanth Menon <nm@ti.com> | ||
3 | Date: Mon, 14 Feb 2011 12:16:36 +0530 | ||
4 | Subject: [PATCH 09/12] OMAP3+: SR: make notify independent of class | ||
5 | |||
6 | Interrupt notification mechanism of SmartReflex can be used by the | ||
7 | choice of implementation of the class driver. For example, Class 2 and | ||
8 | Class 1.5 of SmartReflex can both use the interrupt notification to | ||
9 | identify the transition of voltage or other events. | ||
10 | |||
11 | Hence, the actual class does not matter for notifier. Let the class | ||
12 | driver's handling decide how it should be used. SmartReflex driver | ||
13 | should provide just the primitives. | ||
14 | |||
15 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
16 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
17 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
18 | --- | ||
19 | arch/arm/mach-omap2/smartreflex.c | 6 ++---- | ||
20 | 1 files changed, 2 insertions(+), 4 deletions(-) | ||
21 | |||
22 | diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c | ||
23 | index fb7dc52..3ee7261 100644 | ||
24 | --- a/arch/arm/mach-omap2/smartreflex.c | ||
25 | +++ b/arch/arm/mach-omap2/smartreflex.c | ||
26 | @@ -143,7 +143,7 @@ static irqreturn_t sr_interrupt(int irq, void *data) | ||
27 | sr_write_reg(sr_info, IRQSTATUS, status); | ||
28 | } | ||
29 | |||
30 | - if (sr_class->class_type == SR_CLASS2 && sr_class->notify) | ||
31 | + if (sr_class->notify) | ||
32 | sr_class->notify(sr_info->voltdm, status); | ||
33 | |||
34 | return IRQ_HANDLED; | ||
35 | @@ -258,9 +258,7 @@ static int sr_late_init(struct omap_sr *sr_info) | ||
36 | struct resource *mem; | ||
37 | int ret = 0; | ||
38 | |||
39 | - if (sr_class->class_type == SR_CLASS2 && | ||
40 | - sr_class->notify_flags && sr_info->irq) { | ||
41 | - | ||
42 | + if (sr_class->notify && sr_class->notify_flags && sr_info->irq) { | ||
43 | name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name); | ||
44 | if (name == NULL) { | ||
45 | ret = -ENOMEM; | ||
46 | -- | ||
47 | 1.6.6.1 | ||
48 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0010-OMAP3-SR-disable-interrupt-by-default.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0010-OMAP3-SR-disable-interrupt-by-default.patch deleted file mode 100644 index e25c3e86..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0010-OMAP3-SR-disable-interrupt-by-default.patch +++ /dev/null | |||
@@ -1,37 +0,0 @@ | |||
1 | From ca5dc57538a566681731102e09a9d1865a4a7020 Mon Sep 17 00:00:00 2001 | ||
2 | From: Nishanth Menon <nm@ti.com> | ||
3 | Date: Mon, 14 Feb 2011 12:41:10 +0530 | ||
4 | Subject: [PATCH 10/12] OMAP3+: SR: disable interrupt by default | ||
5 | |||
6 | We will enable and disable interrupt on a need basis in the class | ||
7 | driver. We need to keep the IRQ disabled by default else the | ||
8 | forceupdate or vcbypass events could trigger events that we don't | ||
9 | need/expect to handle. | ||
10 | |||
11 | This is a preparation for SmartReflex AVS class drivers such as | ||
12 | class 2 and class 1.5 which would need to use interrupts. Existing | ||
13 | SmartReflex AVS class 3 driver does not require to use interrupts | ||
14 | and is not impacted by this change. | ||
15 | |||
16 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
17 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
18 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
19 | --- | ||
20 | arch/arm/mach-omap2/smartreflex.c | 1 + | ||
21 | 1 files changed, 1 insertions(+), 0 deletions(-) | ||
22 | |||
23 | diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c | ||
24 | index 3ee7261..616ef62 100644 | ||
25 | --- a/arch/arm/mach-omap2/smartreflex.c | ||
26 | +++ b/arch/arm/mach-omap2/smartreflex.c | ||
27 | @@ -268,6 +268,7 @@ static int sr_late_init(struct omap_sr *sr_info) | ||
28 | 0, name, (void *)sr_info); | ||
29 | if (ret) | ||
30 | goto error; | ||
31 | + disable_irq(sr_info->irq); | ||
32 | } | ||
33 | |||
34 | if (pdata && pdata->enable_on_init) | ||
35 | -- | ||
36 | 1.6.6.1 | ||
37 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0011-OMAP3-SR-enable-disable-SR-only-on-need.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0011-OMAP3-SR-enable-disable-SR-only-on-need.patch deleted file mode 100644 index b96682ea..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0011-OMAP3-SR-enable-disable-SR-only-on-need.patch +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | From 4aa67e94d6b13905abcf3e95cb66ea7be9c2e8dd Mon Sep 17 00:00:00 2001 | ||
2 | From: Nishanth Menon <nm@ti.com> | ||
3 | Date: Mon, 14 Feb 2011 21:14:17 +0530 | ||
4 | Subject: [PATCH 11/12] OMAP3+: SR: enable/disable SR only on need | ||
5 | |||
6 | Since we already know the state of the autocomp enablement, we can | ||
7 | see if the requested state is different from the current state and | ||
8 | enable/disable SR only on the need basis. | ||
9 | |||
10 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
11 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
12 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
13 | --- | ||
14 | arch/arm/mach-omap2/smartreflex.c | 11 +++++++---- | ||
15 | 1 files changed, 7 insertions(+), 4 deletions(-) | ||
16 | |||
17 | diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c | ||
18 | index 616ef62..3bd9fac 100644 | ||
19 | --- a/arch/arm/mach-omap2/smartreflex.c | ||
20 | +++ b/arch/arm/mach-omap2/smartreflex.c | ||
21 | @@ -807,10 +807,13 @@ static int omap_sr_autocomp_store(void *data, u64 val) | ||
22 | return -EINVAL; | ||
23 | } | ||
24 | |||
25 | - if (!val) | ||
26 | - sr_stop_vddautocomp(sr_info); | ||
27 | - else | ||
28 | - sr_start_vddautocomp(sr_info); | ||
29 | + /* control enable/disable only if there is a delta in value */ | ||
30 | + if (sr_info->autocomp_active != val) { | ||
31 | + if (!val) | ||
32 | + sr_stop_vddautocomp(sr_info); | ||
33 | + else | ||
34 | + sr_start_vddautocomp(sr_info); | ||
35 | + } | ||
36 | |||
37 | return 0; | ||
38 | } | ||
39 | -- | ||
40 | 1.6.6.1 | ||
41 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0012-OMAP3-SR-fix-cosmetic-indentation.patch b/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0012-OMAP3-SR-fix-cosmetic-indentation.patch deleted file mode 100644 index eda76a0d..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0012-OMAP3-SR-fix-cosmetic-indentation.patch +++ /dev/null | |||
@@ -1,49 +0,0 @@ | |||
1 | From 0c2089eecdfc3a85a376eddf9c77857f3d575be6 Mon Sep 17 00:00:00 2001 | ||
2 | From: Nishanth Menon <nm@ti.com> | ||
3 | Date: Mon, 14 Feb 2011 12:33:13 +0530 | ||
4 | Subject: [PATCH 12/12] OMAP3+: SR: fix cosmetic indentation | ||
5 | |||
6 | Error label case seems to have a 2 tab indentation when just 1 is | ||
7 | necessary. | ||
8 | |||
9 | Signed-off-by: Nishanth Menon <nm@ti.com> | ||
10 | Signed-off-by: Kevin Hilman <khilman@ti.com> | ||
11 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
12 | --- | ||
13 | arch/arm/mach-omap2/smartreflex.c | 20 ++++++++++---------- | ||
14 | 1 files changed, 10 insertions(+), 10 deletions(-) | ||
15 | |||
16 | diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c | ||
17 | index 3bd9fac..2ce2fb7 100644 | ||
18 | --- a/arch/arm/mach-omap2/smartreflex.c | ||
19 | +++ b/arch/arm/mach-omap2/smartreflex.c | ||
20 | @@ -277,16 +277,16 @@ static int sr_late_init(struct omap_sr *sr_info) | ||
21 | return ret; | ||
22 | |||
23 | error: | ||
24 | - iounmap(sr_info->base); | ||
25 | - mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0); | ||
26 | - release_mem_region(mem->start, resource_size(mem)); | ||
27 | - list_del(&sr_info->node); | ||
28 | - dev_err(&sr_info->pdev->dev, "%s: ERROR in registering" | ||
29 | - "interrupt handler. Smartreflex will" | ||
30 | - "not function as desired\n", __func__); | ||
31 | - kfree(name); | ||
32 | - kfree(sr_info); | ||
33 | - return ret; | ||
34 | + iounmap(sr_info->base); | ||
35 | + mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0); | ||
36 | + release_mem_region(mem->start, resource_size(mem)); | ||
37 | + list_del(&sr_info->node); | ||
38 | + dev_err(&sr_info->pdev->dev, "%s: ERROR in registering" | ||
39 | + "interrupt handler. Smartreflex will" | ||
40 | + "not function as desired\n", __func__); | ||
41 | + kfree(name); | ||
42 | + kfree(sr_info); | ||
43 | + return ret; | ||
44 | } | ||
45 | |||
46 | static void sr_v1_disable(struct omap_sr *sr) | ||
47 | -- | ||
48 | 1.6.6.1 | ||
49 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0001-OMAP-DSS2-DSI-fix-use_sys_clk-highfreq.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0001-OMAP-DSS2-DSI-fix-use_sys_clk-highfreq.patch deleted file mode 100644 index a66407b3..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0001-OMAP-DSS2-DSI-fix-use_sys_clk-highfreq.patch +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | From 6aae34d56ba8fef140b60631536272f6b39c1f61 Mon Sep 17 00:00:00 2001 | ||
2 | From: Tomi Valkeinen <tomi.valkeinen@ti.com> | ||
3 | Date: Thu, 7 Apr 2011 15:28:47 +0300 | ||
4 | Subject: [PATCH 01/32] OMAP: DSS2: DSI: fix use_sys_clk & highfreq | ||
5 | |||
6 | use_sys_clk and highfreq fields in dsi.current_cinfo were never set. | ||
7 | Luckily they weren't used anywhere so it didn't cause any problems. | ||
8 | |||
9 | This patch fixes those fields and they are now set at the same time as | ||
10 | the rest of the fields. | ||
11 | |||
12 | Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> | ||
13 | --- | ||
14 | drivers/video/omap2/dss/dsi.c | 3 +++ | ||
15 | 1 files changed, 3 insertions(+), 0 deletions(-) | ||
16 | |||
17 | diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c | ||
18 | index 0a7f1a4..8604153 100644 | ||
19 | --- a/drivers/video/omap2/dss/dsi.c | ||
20 | +++ b/drivers/video/omap2/dss/dsi.c | ||
21 | @@ -1276,6 +1276,9 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) | ||
22 | |||
23 | DSSDBGF(); | ||
24 | |||
25 | + dsi.current_cinfo.use_sys_clk = cinfo->use_sys_clk; | ||
26 | + dsi.current_cinfo.highfreq = cinfo->highfreq; | ||
27 | + | ||
28 | dsi.current_cinfo.fint = cinfo->fint; | ||
29 | dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr; | ||
30 | dsi.current_cinfo.dsi_pll_hsdiv_dispc_clk = | ||
31 | -- | ||
32 | 1.6.6.1 | ||
33 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0002-OMAP-DSS2-DSI-fix-dsi_dump_clocks.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0002-OMAP-DSS2-DSI-fix-dsi_dump_clocks.patch deleted file mode 100644 index 9d5ab617..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0002-OMAP-DSS2-DSI-fix-dsi_dump_clocks.patch +++ /dev/null | |||
@@ -1,49 +0,0 @@ | |||
1 | From 5275654d2e873ca5bdbbd8be61dbb2d63c0e04cb Mon Sep 17 00:00:00 2001 | ||
2 | From: Tomi Valkeinen <tomi.valkeinen@ti.com> | ||
3 | Date: Mon, 4 Apr 2011 10:02:53 +0300 | ||
4 | Subject: [PATCH 02/32] OMAP: DSS2: DSI: fix dsi_dump_clocks() | ||
5 | |||
6 | On OMAP4, reading DSI_PLL_CONFIGURATION2 register requires the L3 clock | ||
7 | (CIO_CLK_ICG) to PLL. Currently dsi_dump_clocks() tries to read that | ||
8 | register without enabling the L3 clock, leading to crash if DSI is not | ||
9 | in use. | ||
10 | |||
11 | The status of the bit being read from DSI_PLL_CONFIGURATION2 is | ||
12 | available from dsi_clock_info->use_sys_clk, so we can avoid the whole | ||
13 | problem by just using that. | ||
14 | |||
15 | Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> | ||
16 | --- | ||
17 | drivers/video/omap2/dss/dsi.c | 6 +----- | ||
18 | 1 files changed, 1 insertions(+), 5 deletions(-) | ||
19 | |||
20 | diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c | ||
21 | index 8604153..1464ac4 100644 | ||
22 | --- a/drivers/video/omap2/dss/dsi.c | ||
23 | +++ b/drivers/video/omap2/dss/dsi.c | ||
24 | @@ -1491,7 +1491,6 @@ void dsi_pll_uninit(void) | ||
25 | |||
26 | void dsi_dump_clocks(struct seq_file *s) | ||
27 | { | ||
28 | - int clksel; | ||
29 | struct dsi_clock_info *cinfo = &dsi.current_cinfo; | ||
30 | enum dss_clk_source dispc_clk_src, dsi_clk_src; | ||
31 | |||
32 | @@ -1500,13 +1499,10 @@ void dsi_dump_clocks(struct seq_file *s) | ||
33 | |||
34 | enable_clocks(1); | ||
35 | |||
36 | - clksel = REG_GET(DSI_PLL_CONFIGURATION2, 11, 11); | ||
37 | - | ||
38 | seq_printf(s, "- DSI PLL -\n"); | ||
39 | |||
40 | seq_printf(s, "dsi pll source = %s\n", | ||
41 | - clksel == 0 ? | ||
42 | - "dss_sys_clk" : "pclkfree"); | ||
43 | + cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree"); | ||
44 | |||
45 | seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); | ||
46 | |||
47 | -- | ||
48 | 1.6.6.1 | ||
49 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0003-OMAP2PLUS-DSS2-Fix-Return-correct-lcd-clock-source-f.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0003-OMAP2PLUS-DSS2-Fix-Return-correct-lcd-clock-source-f.patch deleted file mode 100644 index 14239fad..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0003-OMAP2PLUS-DSS2-Fix-Return-correct-lcd-clock-source-f.patch +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | From 9ddb3aafff5f7f6b7eaad32f9b1eea249c0dce8b Mon Sep 17 00:00:00 2001 | ||
2 | From: Archit Taneja <archit@ti.com> | ||
3 | Date: Thu, 31 Mar 2011 13:23:35 +0530 | ||
4 | Subject: [PATCH 03/32] OMAP2PLUS: DSS2: Fix: Return correct lcd clock source for OMAP2/3 | ||
5 | |||
6 | dss.lcd_clk_source is set to the default value DSS_CLK_SRC_FCK at dss_init. | ||
7 | For OMAP2 and OMAP3, the dss.lcd_clk_source should always be the same as | ||
8 | dss.dispc_clk_source. The function dss_get_lcd_clk_source() always returns the | ||
9 | default value DSS_CLK_SRC_FCK for OMAP2/3. This leads to wrong clock dumps when | ||
10 | dispc_clk_source is not DSS_CLK_SRC_FCK. | ||
11 | |||
12 | Correct this function to always return dss.dispc_clk_source for OMAP2/3. | ||
13 | |||
14 | Signed-off-by: Archit Taneja <archit@ti.com> | ||
15 | Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> | ||
16 | --- | ||
17 | drivers/video/omap2/dss/dss.c | 10 ++++++++-- | ||
18 | 1 files changed, 8 insertions(+), 2 deletions(-) | ||
19 | |||
20 | diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c | ||
21 | index 3f1fee6..c3b48a0 100644 | ||
22 | --- a/drivers/video/omap2/dss/dss.c | ||
23 | +++ b/drivers/video/omap2/dss/dss.c | ||
24 | @@ -385,8 +385,14 @@ enum dss_clk_source dss_get_dsi_clk_source(void) | ||
25 | |||
26 | enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) | ||
27 | { | ||
28 | - int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1; | ||
29 | - return dss.lcd_clk_source[ix]; | ||
30 | + if (dss_has_feature(FEAT_LCD_CLK_SRC)) { | ||
31 | + int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1; | ||
32 | + return dss.lcd_clk_source[ix]; | ||
33 | + } else { | ||
34 | + /* LCD_CLK source is the same as DISPC_FCLK source for | ||
35 | + * OMAP2 and OMAP3 */ | ||
36 | + return dss.dispc_clk_source; | ||
37 | + } | ||
38 | } | ||
39 | |||
40 | /* calculate clock rates using dividers in cinfo */ | ||
41 | -- | ||
42 | 1.6.6.1 | ||
43 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0004-OMAP-DSS-DSI-Fix-DSI-PLL-power-bug.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0004-OMAP-DSS-DSI-Fix-DSI-PLL-power-bug.patch deleted file mode 100644 index 8c2d6e6c..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0004-OMAP-DSS-DSI-Fix-DSI-PLL-power-bug.patch +++ /dev/null | |||
@@ -1,64 +0,0 @@ | |||
1 | From 4a56fbcabd128dbd07895e5167fd131299a1391c Mon Sep 17 00:00:00 2001 | ||
2 | From: Tomi Valkeinen <tomi.valkeinen@ti.com> | ||
3 | Date: Fri, 15 Apr 2011 10:42:59 +0300 | ||
4 | Subject: [PATCH 04/32] OMAP: DSS: DSI: Fix DSI PLL power bug | ||
5 | |||
6 | OMAP3630 has a HW bug causing DSI PLL power command POWER_ON_DIV (0x3) | ||
7 | to not work properly. The bug prevents us from enabling DSI PLL power | ||
8 | only to HS divider block. | ||
9 | |||
10 | This patch adds a dss feature for the bug and converts POWER_ON_DIV | ||
11 | requests to POWER_ON_ALL (0x2). | ||
12 | |||
13 | Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> | ||
14 | --- | ||
15 | drivers/video/omap2/dss/dsi.c | 5 +++++ | ||
16 | drivers/video/omap2/dss/dss_features.c | 2 +- | ||
17 | drivers/video/omap2/dss/dss_features.h | 2 ++ | ||
18 | 3 files changed, 8 insertions(+), 1 deletions(-) | ||
19 | |||
20 | diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c | ||
21 | index 1464ac4..cbd9ca4 100644 | ||
22 | --- a/drivers/video/omap2/dss/dsi.c | ||
23 | +++ b/drivers/video/omap2/dss/dsi.c | ||
24 | @@ -1059,6 +1059,11 @@ static int dsi_pll_power(enum dsi_pll_power_state state) | ||
25 | { | ||
26 | int t = 0; | ||
27 | |||
28 | + /* DSI-PLL power command 0x3 is not working */ | ||
29 | + if (dss_has_feature(FEAT_DSI_PLL_PWR_BUG) && | ||
30 | + state == DSI_PLL_POWER_ON_DIV) | ||
31 | + state = DSI_PLL_POWER_ON_ALL; | ||
32 | + | ||
33 | REG_FLD_MOD(DSI_CLK_CTRL, state, 31, 30); /* PLL_PWR_CMD */ | ||
34 | |||
35 | /* PLL_PWR_STATUS */ | ||
36 | diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c | ||
37 | index aa16222..8c50e18 100644 | ||
38 | --- a/drivers/video/omap2/dss/dss_features.c | ||
39 | +++ b/drivers/video/omap2/dss/dss_features.c | ||
40 | @@ -271,7 +271,7 @@ static struct omap_dss_features omap3630_dss_features = { | ||
41 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | | ||
42 | FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED | | ||
43 | FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | | ||
44 | - FEAT_RESIZECONF, | ||
45 | + FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG, | ||
46 | |||
47 | .num_mgrs = 2, | ||
48 | .num_ovls = 3, | ||
49 | diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h | ||
50 | index 12e9c4e..37922ce 100644 | ||
51 | --- a/drivers/video/omap2/dss/dss_features.h | ||
52 | +++ b/drivers/video/omap2/dss/dss_features.h | ||
53 | @@ -40,6 +40,8 @@ enum dss_feat_id { | ||
54 | /* Independent core clk divider */ | ||
55 | FEAT_CORE_CLK_DIV = 1 << 11, | ||
56 | FEAT_LCD_CLK_SRC = 1 << 12, | ||
57 | + /* DSI-PLL power command 0x3 is not working */ | ||
58 | + FEAT_DSI_PLL_PWR_BUG = 1 << 13, | ||
59 | }; | ||
60 | |||
61 | /* DSS register field id */ | ||
62 | -- | ||
63 | 1.6.6.1 | ||
64 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0005-OMAP-DSS2-fix-panel-Kconfig-dependencies.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0005-OMAP-DSS2-fix-panel-Kconfig-dependencies.patch deleted file mode 100644 index a8279242..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0005-OMAP-DSS2-fix-panel-Kconfig-dependencies.patch +++ /dev/null | |||
@@ -1,61 +0,0 @@ | |||
1 | From fcb26a06fe1badfaaf7aaa68140c8b3370dd503e Mon Sep 17 00:00:00 2001 | ||
2 | From: Tomi Valkeinen <tomi.valkeinen@ti.com> | ||
3 | Date: Fri, 8 Apr 2011 09:30:27 +0300 | ||
4 | Subject: [PATCH 05/32] OMAP: DSS2: fix panel Kconfig dependencies | ||
5 | |||
6 | All DPI panels were missing dependency to OMAP2_DSS_DPI. Add the | ||
7 | dependency. | ||
8 | |||
9 | Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> | ||
10 | --- | ||
11 | drivers/video/omap2/displays/Kconfig | 9 +++++---- | ||
12 | 1 files changed, 5 insertions(+), 4 deletions(-) | ||
13 | |||
14 | diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig | ||
15 | index d18ad6b..609a280 100644 | ||
16 | --- a/drivers/video/omap2/displays/Kconfig | ||
17 | +++ b/drivers/video/omap2/displays/Kconfig | ||
18 | @@ -3,6 +3,7 @@ menu "OMAP2/3 Display Device Drivers" | ||
19 | |||
20 | config PANEL_GENERIC_DPI | ||
21 | tristate "Generic DPI Panel" | ||
22 | + depends on OMAP2_DSS_DPI | ||
23 | help | ||
24 | Generic DPI panel driver. | ||
25 | Supports DVI output for Beagle and OMAP3 SDP. | ||
26 | @@ -11,20 +12,20 @@ config PANEL_GENERIC_DPI | ||
27 | |||
28 | config PANEL_LGPHILIPS_LB035Q02 | ||
29 | tristate "LG.Philips LB035Q02 LCD Panel" | ||
30 | - depends on OMAP2_DSS && SPI | ||
31 | + depends on OMAP2_DSS_DPI && SPI | ||
32 | help | ||
33 | LCD Panel used on the Gumstix Overo Palo35 | ||
34 | |||
35 | config PANEL_SHARP_LS037V7DW01 | ||
36 | tristate "Sharp LS037V7DW01 LCD Panel" | ||
37 | - depends on OMAP2_DSS | ||
38 | + depends on OMAP2_DSS_DPI | ||
39 | select BACKLIGHT_CLASS_DEVICE | ||
40 | help | ||
41 | LCD Panel used in TI's SDP3430 and EVM boards | ||
42 | |||
43 | config PANEL_NEC_NL8048HL11_01B | ||
44 | tristate "NEC NL8048HL11-01B Panel" | ||
45 | - depends on OMAP2_DSS | ||
46 | + depends on OMAP2_DSS_DPI | ||
47 | help | ||
48 | This NEC NL8048HL11-01B panel is TFT LCD | ||
49 | used in the Zoom2/3/3630 sdp boards. | ||
50 | @@ -37,7 +38,7 @@ config PANEL_TAAL | ||
51 | |||
52 | config PANEL_TPO_TD043MTEA1 | ||
53 | tristate "TPO TD043MTEA1 LCD Panel" | ||
54 | - depends on OMAP2_DSS && SPI | ||
55 | + depends on OMAP2_DSS_DPI && SPI | ||
56 | help | ||
57 | LCD Panel used in OMAP3 Pandora | ||
58 | |||
59 | -- | ||
60 | 1.6.6.1 | ||
61 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0006-OMAP-DSS2-add-bootarg-for-selecting-svideo-or-compos.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0006-OMAP-DSS2-add-bootarg-for-selecting-svideo-or-compos.patch deleted file mode 100644 index d899cb0b..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0006-OMAP-DSS2-add-bootarg-for-selecting-svideo-or-compos.patch +++ /dev/null | |||
@@ -1,75 +0,0 @@ | |||
1 | From 4bd1d52fff974f5a5d0582f4fa4eae6e03e36fc1 Mon Sep 17 00:00:00 2001 | ||
2 | From: Steve Sakoman <steve@sakoman.com> | ||
3 | Date: Tue, 19 Jan 2010 21:19:15 -0800 | ||
4 | Subject: [PATCH 06/32] OMAP: DSS2: add bootarg for selecting svideo or composite for tv output | ||
5 | |||
6 | also add pal-16 and ntsc-16 omapfb.mode settings for 16bpp | ||
7 | --- | ||
8 | drivers/video/omap2/dss/venc.c | 22 ++++++++++++++++++++++ | ||
9 | drivers/video/omap2/omapfb/omapfb-main.c | 10 +++++++++- | ||
10 | 2 files changed, 31 insertions(+), 1 deletions(-) | ||
11 | |||
12 | diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c | ||
13 | index 8e35a5b..827723f 100644 | ||
14 | --- a/drivers/video/omap2/dss/venc.c | ||
15 | +++ b/drivers/video/omap2/dss/venc.c | ||
16 | @@ -85,6 +85,11 @@ | ||
17 | #define VENC_OUTPUT_TEST 0xC8 | ||
18 | #define VENC_DAC_B__DAC_C 0xC8 | ||
19 | |||
20 | +static char *tv_connection; | ||
21 | + | ||
22 | +module_param_named(tvcable, tv_connection, charp, 0); | ||
23 | +MODULE_PARM_DESC(tvcable, "TV connection type (svideo, composite)"); | ||
24 | + | ||
25 | struct venc_config { | ||
26 | u32 f_control; | ||
27 | u32 vidout_ctrl; | ||
28 | @@ -458,6 +463,23 @@ static int venc_panel_probe(struct omap_dss_device *dssdev) | ||
29 | { | ||
30 | dssdev->panel.timings = omap_dss_pal_timings; | ||
31 | |||
32 | + /* Allow the TV output to be overriden */ | ||
33 | + if (tv_connection) { | ||
34 | + if (strcmp(tv_connection, "svideo") == 0) { | ||
35 | + printk(KERN_INFO | ||
36 | + "omapdss: tv output is svideo.\n"); | ||
37 | + dssdev->phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO; | ||
38 | + } else if (strcmp(tv_connection, "composite") == 0) { | ||
39 | + printk(KERN_INFO | ||
40 | + "omapdss: tv output is composite.\n"); | ||
41 | + dssdev->phy.venc.type = OMAP_DSS_VENC_TYPE_COMPOSITE; | ||
42 | + } else { | ||
43 | + printk(KERN_INFO | ||
44 | + "omapdss: unsupported output type'%s'.\n", | ||
45 | + tv_connection); | ||
46 | + } | ||
47 | + } | ||
48 | + | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c | ||
53 | index 505ec66..eaeded5 100644 | ||
54 | --- a/drivers/video/omap2/omapfb/omapfb-main.c | ||
55 | +++ b/drivers/video/omap2/omapfb/omapfb-main.c | ||
56 | @@ -2036,7 +2036,15 @@ static int omapfb_mode_to_timings(const char *mode_str, | ||
57 | int r; | ||
58 | |||
59 | #ifdef CONFIG_OMAP2_DSS_VENC | ||
60 | - if (strcmp(mode_str, "pal") == 0) { | ||
61 | + if (strcmp(mode_str, "pal-16") == 0) { | ||
62 | + *timings = omap_dss_pal_timings; | ||
63 | + *bpp = 16; | ||
64 | + return 0; | ||
65 | + } else if (strcmp(mode_str, "ntsc-16") == 0) { | ||
66 | + *timings = omap_dss_ntsc_timings; | ||
67 | + *bpp = 16; | ||
68 | + return 0; | ||
69 | + } else if (strcmp(mode_str, "pal") == 0) { | ||
70 | *timings = omap_dss_pal_timings; | ||
71 | *bpp = 24; | ||
72 | return 0; | ||
73 | -- | ||
74 | 1.6.6.1 | ||
75 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0007-video-add-timings-for-hd720.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0007-video-add-timings-for-hd720.patch deleted file mode 100644 index b653e6c4..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0007-video-add-timings-for-hd720.patch +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | From 6d87a3f85ac36205111b4fe71ad06976239cdbe7 Mon Sep 17 00:00:00 2001 | ||
2 | From: Steve Sakoman <steve@sakoman.com> | ||
3 | Date: Sat, 19 Dec 2009 06:52:43 -0800 | ||
4 | Subject: [PATCH 07/32] video: add timings for hd720 | ||
5 | |||
6 | --- | ||
7 | drivers/video/modedb.c | 4 ++++ | ||
8 | 1 files changed, 4 insertions(+), 0 deletions(-) | ||
9 | |||
10 | diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c | ||
11 | index 48c3ea8..b320a30 100644 | ||
12 | --- a/drivers/video/modedb.c | ||
13 | +++ b/drivers/video/modedb.c | ||
14 | @@ -103,6 +103,10 @@ static const struct fb_videomode modedb[] = { | ||
15 | { NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6, 0, | ||
16 | FB_VMODE_NONINTERLACED }, | ||
17 | |||
18 | + /* 1280x720 @ 60 Hz, 45 kHz hsync, CEA 681-E Format 4 */ | ||
19 | + { "hd720", 60, 1280, 720, 13468, 220, 110, 20, 5, 40, 5, 0, | ||
20 | + FB_VMODE_NONINTERLACED }, | ||
21 | + | ||
22 | /* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */ | ||
23 | { NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12, 0, | ||
24 | FB_VMODE_INTERLACED }, | ||
25 | -- | ||
26 | 1.6.6.1 | ||
27 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0008-drivers-net-smsc911x-return-ENODEV-if-device-is-not-.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0008-drivers-net-smsc911x-return-ENODEV-if-device-is-not-.patch deleted file mode 100644 index 1e0e0579..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0008-drivers-net-smsc911x-return-ENODEV-if-device-is-not-.patch +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | From 1e3fcfd74686fa8b02f93bb592cca458942058e4 Mon Sep 17 00:00:00 2001 | ||
2 | From: Steve Sakoman <sakoman@gmail.com> | ||
3 | Date: Tue, 15 Dec 2009 15:17:44 -0800 | ||
4 | Subject: [PATCH 08/32] drivers: net: smsc911x: return ENODEV if device is not found | ||
5 | |||
6 | Signed-off-by: Steve Sakoman <sakoman@gmail.com> | ||
7 | --- | ||
8 | drivers/net/smsc911x.c | 4 +++- | ||
9 | 1 files changed, 3 insertions(+), 1 deletions(-) | ||
10 | |||
11 | diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c | ||
12 | index 4b42ecc..5c1202b 100644 | ||
13 | --- a/drivers/net/smsc911x.c | ||
14 | +++ b/drivers/net/smsc911x.c | ||
15 | @@ -2028,8 +2028,10 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) | ||
16 | } | ||
17 | |||
18 | retval = smsc911x_init(dev); | ||
19 | - if (retval < 0) | ||
20 | + if (retval < 0) { | ||
21 | + retval = -ENODEV; | ||
22 | goto out_unmap_io_3; | ||
23 | + } | ||
24 | |||
25 | /* configure irq polarity and type before connecting isr */ | ||
26 | if (pdata->config.irq_polarity == SMSC911X_IRQ_POLARITY_ACTIVE_HIGH) | ||
27 | -- | ||
28 | 1.6.6.1 | ||
29 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0009-drivers-input-touchscreen-ads7846-return-ENODEV-if-d.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0009-drivers-input-touchscreen-ads7846-return-ENODEV-if-d.patch deleted file mode 100644 index f753684a..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0009-drivers-input-touchscreen-ads7846-return-ENODEV-if-d.patch +++ /dev/null | |||
@@ -1,47 +0,0 @@ | |||
1 | From 078005a9c8b5913ed5eb7a7a9508e4b0a5b18c30 Mon Sep 17 00:00:00 2001 | ||
2 | From: Steve Sakoman <sakoman@gmail.com> | ||
3 | Date: Tue, 15 Dec 2009 15:24:10 -0800 | ||
4 | Subject: [PATCH 09/32] drivers: input: touchscreen: ads7846: return ENODEV if device is not found | ||
5 | |||
6 | Signed-off-by: Steve Sakoman <sakoman@gmail.com> | ||
7 | --- | ||
8 | drivers/input/touchscreen/ads7846.c | 13 ++++++++++--- | ||
9 | 1 files changed, 10 insertions(+), 3 deletions(-) | ||
10 | |||
11 | diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c | ||
12 | index 1de1c19..097db10 100644 | ||
13 | --- a/drivers/input/touchscreen/ads7846.c | ||
14 | +++ b/drivers/input/touchscreen/ads7846.c | ||
15 | @@ -1338,11 +1338,18 @@ static int __devinit ads7846_probe(struct spi_device *spi) | ||
16 | * the touchscreen, in case it's not connected. | ||
17 | */ | ||
18 | if (ts->model == 7845) | ||
19 | - ads7845_read12_ser(&spi->dev, PWRDOWN); | ||
20 | + err = ads7845_read12_ser(&spi->dev, PWRDOWN); | ||
21 | else | ||
22 | - (void) ads7846_read12_ser(&spi->dev, | ||
23 | + err = ads7846_read12_ser(&spi->dev, | ||
24 | READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON); | ||
25 | |||
26 | + /* if sample is all 0's or all 1's then there is no device on spi */ | ||
27 | + if ( (err == 0x000) || (err == 0xfff)) { | ||
28 | + dev_info(&spi->dev, "no device detected, test read result was 0x%08X\n", err); | ||
29 | + err = -ENODEV; | ||
30 | + goto err_free_irq; | ||
31 | + } | ||
32 | + | ||
33 | err = sysfs_create_group(&spi->dev.kobj, &ads784x_attr_group); | ||
34 | if (err) | ||
35 | goto err_remove_hwmon; | ||
36 | @@ -1366,7 +1373,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) | ||
37 | err_put_regulator: | ||
38 | regulator_put(ts->reg); | ||
39 | err_free_gpio: | ||
40 | - if (!ts->get_pendown_state) | ||
41 | + if (!ts->get_pendown_state && ts->gpio_pendown != -1) | ||
42 | gpio_free(ts->gpio_pendown); | ||
43 | err_cleanup_filter: | ||
44 | if (ts->filter_cleanup) | ||
45 | -- | ||
46 | 1.6.6.1 | ||
47 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0010-Revert-omap2_mcspi-Flush-posted-writes.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0010-Revert-omap2_mcspi-Flush-posted-writes.patch deleted file mode 100644 index 6c76843d..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0010-Revert-omap2_mcspi-Flush-posted-writes.patch +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | From ae16b19238b8d0609612d0e1f1a419d293f17c80 Mon Sep 17 00:00:00 2001 | ||
2 | From: Steve Sakoman <steve@sakoman.com> | ||
3 | Date: Thu, 3 Mar 2011 13:29:30 -0800 | ||
4 | Subject: [PATCH 10/32] Revert "omap2_mcspi: Flush posted writes" | ||
5 | |||
6 | This reverts commit a330ce2001b290c59fe98c37e981683ef0a75fdf. | ||
7 | --- | ||
8 | drivers/spi/omap2_mcspi.c | 1 - | ||
9 | 1 files changed, 0 insertions(+), 1 deletions(-) | ||
10 | |||
11 | diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c | ||
12 | index 6f86ba0..6094be7 100644 | ||
13 | --- a/drivers/spi/omap2_mcspi.c | ||
14 | +++ b/drivers/spi/omap2_mcspi.c | ||
15 | @@ -195,7 +195,6 @@ static inline void mcspi_write_chconf0(const struct spi_device *spi, u32 val) | ||
16 | |||
17 | cs->chconf0 = val; | ||
18 | mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, val); | ||
19 | - mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0); | ||
20 | } | ||
21 | |||
22 | static void omap2_mcspi_set_dma_req(const struct spi_device *spi, | ||
23 | -- | ||
24 | 1.6.6.1 | ||
25 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0011-Revert-omap_hsmmc-improve-interrupt-synchronisation.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0011-Revert-omap_hsmmc-improve-interrupt-synchronisation.patch deleted file mode 100644 index 78381e9e..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0011-Revert-omap_hsmmc-improve-interrupt-synchronisation.patch +++ /dev/null | |||
@@ -1,482 +0,0 @@ | |||
1 | From 3a66cefdf60033381c623b0425345c41e8c078fe Mon Sep 17 00:00:00 2001 | ||
2 | From: Steve Sakoman <steve@sakoman.com> | ||
3 | Date: Fri, 19 Nov 2010 15:11:19 -0800 | ||
4 | Subject: [PATCH 11/32] Revert "omap_hsmmc: improve interrupt synchronisation" | ||
5 | |||
6 | This reverts commit b417577d3b9bbb06a4ddc9aa955af9bd503f7242. | ||
7 | |||
8 | Conflicts: | ||
9 | |||
10 | drivers/mmc/host/omap_hsmmc.c | ||
11 | --- | ||
12 | drivers/mmc/host/omap_hsmmc.c | 267 ++++++++++++++++++++--------------------- | ||
13 | 1 files changed, 128 insertions(+), 139 deletions(-) | ||
14 | |||
15 | diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c | ||
16 | index 259ece0..15a023b 100644 | ||
17 | --- a/drivers/mmc/host/omap_hsmmc.c | ||
18 | +++ b/drivers/mmc/host/omap_hsmmc.c | ||
19 | @@ -159,10 +159,12 @@ struct omap_hsmmc_host { | ||
20 | */ | ||
21 | struct regulator *vcc; | ||
22 | struct regulator *vcc_aux; | ||
23 | + struct semaphore sem; | ||
24 | struct work_struct mmc_carddetect_work; | ||
25 | void __iomem *base; | ||
26 | resource_size_t mapbase; | ||
27 | spinlock_t irq_lock; /* Prevent races with irq handler */ | ||
28 | + unsigned long flags; | ||
29 | unsigned int id; | ||
30 | unsigned int dma_len; | ||
31 | unsigned int dma_sg_idx; | ||
32 | @@ -183,7 +185,6 @@ struct omap_hsmmc_host { | ||
33 | int protect_card; | ||
34 | int reqs_blocked; | ||
35 | int use_reg; | ||
36 | - int req_in_progress; | ||
37 | |||
38 | struct omap_mmc_platform_data *pdata; | ||
39 | }; | ||
40 | @@ -556,32 +557,6 @@ static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host) | ||
41 | dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stoped\n"); | ||
42 | } | ||
43 | |||
44 | -static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host, | ||
45 | - struct mmc_command *cmd) | ||
46 | -{ | ||
47 | - unsigned int irq_mask; | ||
48 | - | ||
49 | - if (host->use_dma) | ||
50 | - irq_mask = INT_EN_MASK & ~(BRR_ENABLE | BWR_ENABLE); | ||
51 | - else | ||
52 | - irq_mask = INT_EN_MASK; | ||
53 | - | ||
54 | - /* Disable timeout for erases */ | ||
55 | - if (cmd->opcode == MMC_ERASE) | ||
56 | - irq_mask &= ~DTO_ENABLE; | ||
57 | - | ||
58 | - OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); | ||
59 | - OMAP_HSMMC_WRITE(host->base, ISE, irq_mask); | ||
60 | - OMAP_HSMMC_WRITE(host->base, IE, irq_mask); | ||
61 | -} | ||
62 | - | ||
63 | -static void omap_hsmmc_disable_irq(struct omap_hsmmc_host *host) | ||
64 | -{ | ||
65 | - OMAP_HSMMC_WRITE(host->base, ISE, 0); | ||
66 | - OMAP_HSMMC_WRITE(host->base, IE, 0); | ||
67 | - OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); | ||
68 | -} | ||
69 | - | ||
70 | #ifdef CONFIG_PM | ||
71 | |||
72 | /* | ||
73 | @@ -650,7 +625,9 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) | ||
74 | && time_before(jiffies, timeout)) | ||
75 | ; | ||
76 | |||
77 | - omap_hsmmc_disable_irq(host); | ||
78 | + OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); | ||
79 | + OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); | ||
80 | + OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); | ||
81 | |||
82 | /* Do not initialize card-specific things if the power is off */ | ||
83 | if (host->power_mode == MMC_POWER_OFF) | ||
84 | @@ -753,8 +730,6 @@ static void send_init_stream(struct omap_hsmmc_host *host) | ||
85 | return; | ||
86 | |||
87 | disable_irq(host->irq); | ||
88 | - | ||
89 | - OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); | ||
90 | OMAP_HSMMC_WRITE(host->base, CON, | ||
91 | OMAP_HSMMC_READ(host->base, CON) | INIT_STREAM); | ||
92 | OMAP_HSMMC_WRITE(host->base, CMD, INIT_STREAM_CMD); | ||
93 | @@ -820,7 +795,17 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, | ||
94 | mmc_hostname(host->mmc), cmd->opcode, cmd->arg); | ||
95 | host->cmd = cmd; | ||
96 | |||
97 | - omap_hsmmc_enable_irq(host, cmd); | ||
98 | + /* | ||
99 | + * Clear status bits and enable interrupts | ||
100 | + */ | ||
101 | + OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); | ||
102 | + OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); | ||
103 | + | ||
104 | + if (host->use_dma) | ||
105 | + OMAP_HSMMC_WRITE(host->base, IE, | ||
106 | + INT_EN_MASK & ~(BRR_ENABLE | BWR_ENABLE)); | ||
107 | + else | ||
108 | + OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); | ||
109 | |||
110 | host->response_busy = 0; | ||
111 | if (cmd->flags & MMC_RSP_PRESENT) { | ||
112 | @@ -854,7 +839,13 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, | ||
113 | if (host->use_dma) | ||
114 | cmdreg |= DMA_EN; | ||
115 | |||
116 | - host->req_in_progress = 1; | ||
117 | + /* | ||
118 | + * In an interrupt context (i.e. STOP command), the spinlock is unlocked | ||
119 | + * by the interrupt handler, otherwise (i.e. for a new request) it is | ||
120 | + * unlocked here. | ||
121 | + */ | ||
122 | + if (!in_interrupt()) | ||
123 | + spin_unlock_irqrestore(&host->irq_lock, host->flags); | ||
124 | |||
125 | OMAP_HSMMC_WRITE(host->base, ARG, cmd->arg); | ||
126 | OMAP_HSMMC_WRITE(host->base, CMD, cmdreg); | ||
127 | @@ -869,23 +860,6 @@ omap_hsmmc_get_dma_dir(struct omap_hsmmc_host *host, struct mmc_data *data) | ||
128 | return DMA_FROM_DEVICE; | ||
129 | } | ||
130 | |||
131 | -static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_request *mrq) | ||
132 | -{ | ||
133 | - int dma_ch; | ||
134 | - | ||
135 | - spin_lock(&host->irq_lock); | ||
136 | - host->req_in_progress = 0; | ||
137 | - dma_ch = host->dma_ch; | ||
138 | - spin_unlock(&host->irq_lock); | ||
139 | - | ||
140 | - omap_hsmmc_disable_irq(host); | ||
141 | - /* Do not complete the request if DMA is still in progress */ | ||
142 | - if (mrq->data && host->use_dma && dma_ch != -1) | ||
143 | - return; | ||
144 | - host->mrq = NULL; | ||
145 | - mmc_request_done(host->mmc, mrq); | ||
146 | -} | ||
147 | - | ||
148 | /* | ||
149 | * Notify the transfer complete to MMC core | ||
150 | */ | ||
151 | @@ -902,19 +876,25 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data) | ||
152 | return; | ||
153 | } | ||
154 | |||
155 | - omap_hsmmc_request_done(host, mrq); | ||
156 | + host->mrq = NULL; | ||
157 | + mmc_request_done(host->mmc, mrq); | ||
158 | return; | ||
159 | } | ||
160 | |||
161 | host->data = NULL; | ||
162 | |||
163 | + if (host->use_dma && host->dma_ch != -1) | ||
164 | + dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len, | ||
165 | + omap_hsmmc_get_dma_dir(host, data)); | ||
166 | + | ||
167 | if (!data->error) | ||
168 | data->bytes_xfered += data->blocks * (data->blksz); | ||
169 | else | ||
170 | data->bytes_xfered = 0; | ||
171 | |||
172 | if (!data->stop) { | ||
173 | - omap_hsmmc_request_done(host, data->mrq); | ||
174 | + host->mrq = NULL; | ||
175 | + mmc_request_done(host->mmc, data->mrq); | ||
176 | return; | ||
177 | } | ||
178 | omap_hsmmc_start_command(host, data->stop, NULL); | ||
179 | @@ -940,8 +920,10 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) | ||
180 | cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10); | ||
181 | } | ||
182 | } | ||
183 | - if ((host->data == NULL && !host->response_busy) || cmd->error) | ||
184 | - omap_hsmmc_request_done(host, cmd->mrq); | ||
185 | + if ((host->data == NULL && !host->response_busy) || cmd->error) { | ||
186 | + host->mrq = NULL; | ||
187 | + mmc_request_done(host->mmc, cmd->mrq); | ||
188 | + } | ||
189 | } | ||
190 | |||
191 | /* | ||
192 | @@ -949,19 +931,14 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) | ||
193 | */ | ||
194 | static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno) | ||
195 | { | ||
196 | - int dma_ch; | ||
197 | - | ||
198 | host->data->error = errno; | ||
199 | |||
200 | - spin_lock(&host->irq_lock); | ||
201 | - dma_ch = host->dma_ch; | ||
202 | - host->dma_ch = -1; | ||
203 | - spin_unlock(&host->irq_lock); | ||
204 | - | ||
205 | - if (host->use_dma && dma_ch != -1) { | ||
206 | + if (host->use_dma && host->dma_ch != -1) { | ||
207 | dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len, | ||
208 | omap_hsmmc_get_dma_dir(host, host->data)); | ||
209 | - omap_free_dma(dma_ch); | ||
210 | + omap_free_dma(host->dma_ch); | ||
211 | + host->dma_ch = -1; | ||
212 | + up(&host->sem); | ||
213 | } | ||
214 | host->data = NULL; | ||
215 | } | ||
216 | @@ -1034,21 +1011,28 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host, | ||
217 | __func__); | ||
218 | } | ||
219 | |||
220 | -static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) | ||
221 | +/* | ||
222 | + * MMC controller IRQ handler | ||
223 | + */ | ||
224 | +static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id) | ||
225 | { | ||
226 | + struct omap_hsmmc_host *host = dev_id; | ||
227 | struct mmc_data *data; | ||
228 | - int end_cmd = 0, end_trans = 0; | ||
229 | - | ||
230 | - if (!host->req_in_progress) { | ||
231 | - do { | ||
232 | - OMAP_HSMMC_WRITE(host->base, STAT, status); | ||
233 | - /* Flush posted write */ | ||
234 | - status = OMAP_HSMMC_READ(host->base, STAT); | ||
235 | - } while (status & INT_EN_MASK); | ||
236 | - return; | ||
237 | + int end_cmd = 0, end_trans = 0, status; | ||
238 | + | ||
239 | + spin_lock(&host->irq_lock); | ||
240 | + | ||
241 | + if (host->mrq == NULL) { | ||
242 | + OMAP_HSMMC_WRITE(host->base, STAT, | ||
243 | + OMAP_HSMMC_READ(host->base, STAT)); | ||
244 | + /* Flush posted write */ | ||
245 | + OMAP_HSMMC_READ(host->base, STAT); | ||
246 | + spin_unlock(&host->irq_lock); | ||
247 | + return IRQ_HANDLED; | ||
248 | } | ||
249 | |||
250 | data = host->data; | ||
251 | + status = OMAP_HSMMC_READ(host->base, STAT); | ||
252 | dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); | ||
253 | |||
254 | if (status & ERR) { | ||
255 | @@ -1101,27 +1085,15 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) | ||
256 | } | ||
257 | |||
258 | OMAP_HSMMC_WRITE(host->base, STAT, status); | ||
259 | + /* Flush posted write */ | ||
260 | + OMAP_HSMMC_READ(host->base, STAT); | ||
261 | |||
262 | if (end_cmd || ((status & CC) && host->cmd)) | ||
263 | omap_hsmmc_cmd_done(host, host->cmd); | ||
264 | if ((end_trans || (status & TC)) && host->mrq) | ||
265 | omap_hsmmc_xfer_done(host, data); | ||
266 | -} | ||
267 | - | ||
268 | -/* | ||
269 | - * MMC controller IRQ handler | ||
270 | - */ | ||
271 | -static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id) | ||
272 | -{ | ||
273 | - struct omap_hsmmc_host *host = dev_id; | ||
274 | - int status; | ||
275 | |||
276 | - status = OMAP_HSMMC_READ(host->base, STAT); | ||
277 | - do { | ||
278 | - omap_hsmmc_do_irq(host, status); | ||
279 | - /* Flush posted write */ | ||
280 | - status = OMAP_HSMMC_READ(host->base, STAT); | ||
281 | - } while (status & INT_EN_MASK); | ||
282 | + spin_unlock(&host->irq_lock); | ||
283 | |||
284 | return IRQ_HANDLED; | ||
285 | } | ||
286 | @@ -1316,11 +1288,9 @@ static void omap_hsmmc_config_dma_params(struct omap_hsmmc_host *host, | ||
287 | /* | ||
288 | * DMA call back function | ||
289 | */ | ||
290 | -static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data) | ||
291 | +static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *data) | ||
292 | { | ||
293 | - struct omap_hsmmc_host *host = cb_data; | ||
294 | - struct mmc_data *data = host->mrq->data; | ||
295 | - int dma_ch, req_in_progress; | ||
296 | + struct omap_hsmmc_host *host = data; | ||
297 | |||
298 | if (!(ch_status & OMAP_DMA_BLOCK_IRQ)) { | ||
299 | dev_warn(mmc_dev(host->mmc), "unexpected dma status %x\n", | ||
300 | @@ -1328,38 +1298,24 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data) | ||
301 | return; | ||
302 | } | ||
303 | |||
304 | - spin_lock(&host->irq_lock); | ||
305 | - if (host->dma_ch < 0) { | ||
306 | - spin_unlock(&host->irq_lock); | ||
307 | + if (host->dma_ch < 0) | ||
308 | return; | ||
309 | - } | ||
310 | |||
311 | host->dma_sg_idx++; | ||
312 | if (host->dma_sg_idx < host->dma_len) { | ||
313 | /* Fire up the next transfer. */ | ||
314 | - omap_hsmmc_config_dma_params(host, data, | ||
315 | - data->sg + host->dma_sg_idx); | ||
316 | - spin_unlock(&host->irq_lock); | ||
317 | + omap_hsmmc_config_dma_params(host, host->data, | ||
318 | + host->data->sg + host->dma_sg_idx); | ||
319 | return; | ||
320 | } | ||
321 | |||
322 | - dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len, | ||
323 | - omap_hsmmc_get_dma_dir(host, data)); | ||
324 | - | ||
325 | - req_in_progress = host->req_in_progress; | ||
326 | - dma_ch = host->dma_ch; | ||
327 | + omap_free_dma(host->dma_ch); | ||
328 | host->dma_ch = -1; | ||
329 | - spin_unlock(&host->irq_lock); | ||
330 | - | ||
331 | - omap_free_dma(dma_ch); | ||
332 | - | ||
333 | - /* If DMA has finished after TC, complete the request */ | ||
334 | - if (!req_in_progress) { | ||
335 | - struct mmc_request *mrq = host->mrq; | ||
336 | - | ||
337 | - host->mrq = NULL; | ||
338 | - mmc_request_done(host->mmc, mrq); | ||
339 | - } | ||
340 | + /* | ||
341 | + * DMA Callback: run in interrupt context. | ||
342 | + * mutex_unlock will throw a kernel warning if used. | ||
343 | + */ | ||
344 | + up(&host->sem); | ||
345 | } | ||
346 | |||
347 | /* | ||
348 | @@ -1368,7 +1324,7 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data) | ||
349 | static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, | ||
350 | struct mmc_request *req) | ||
351 | { | ||
352 | - int dma_ch = 0, ret = 0, i; | ||
353 | + int dma_ch = 0, ret = 0, err = 1, i; | ||
354 | struct mmc_data *data = req->data; | ||
355 | |||
356 | /* Sanity check: all the SG entries must be aligned by block size. */ | ||
357 | @@ -1385,7 +1341,23 @@ static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, | ||
358 | */ | ||
359 | return -EINVAL; | ||
360 | |||
361 | - BUG_ON(host->dma_ch != -1); | ||
362 | + /* | ||
363 | + * If for some reason the DMA transfer is still active, | ||
364 | + * we wait for timeout period and free the dma | ||
365 | + */ | ||
366 | + if (host->dma_ch != -1) { | ||
367 | + set_current_state(TASK_UNINTERRUPTIBLE); | ||
368 | + schedule_timeout(100); | ||
369 | + if (down_trylock(&host->sem)) { | ||
370 | + omap_free_dma(host->dma_ch); | ||
371 | + host->dma_ch = -1; | ||
372 | + up(&host->sem); | ||
373 | + return err; | ||
374 | + } | ||
375 | + } else { | ||
376 | + if (down_trylock(&host->sem)) | ||
377 | + return err; | ||
378 | + } | ||
379 | |||
380 | ret = omap_request_dma(omap_hsmmc_get_dma_sync_dev(host, data), | ||
381 | "MMC/SD", omap_hsmmc_dma_cb, host, &dma_ch); | ||
382 | @@ -1485,27 +1457,37 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) | ||
383 | struct omap_hsmmc_host *host = mmc_priv(mmc); | ||
384 | int err; | ||
385 | |||
386 | - BUG_ON(host->req_in_progress); | ||
387 | - BUG_ON(host->dma_ch != -1); | ||
388 | - if (host->protect_card) { | ||
389 | - if (host->reqs_blocked < 3) { | ||
390 | - /* | ||
391 | - * Ensure the controller is left in a consistent | ||
392 | - * state by resetting the command and data state | ||
393 | - * machines. | ||
394 | - */ | ||
395 | - omap_hsmmc_reset_controller_fsm(host, SRD); | ||
396 | - omap_hsmmc_reset_controller_fsm(host, SRC); | ||
397 | - host->reqs_blocked += 1; | ||
398 | - } | ||
399 | - req->cmd->error = -EBADF; | ||
400 | - if (req->data) | ||
401 | - req->data->error = -EBADF; | ||
402 | - req->cmd->retries = 0; | ||
403 | - mmc_request_done(mmc, req); | ||
404 | - return; | ||
405 | - } else if (host->reqs_blocked) | ||
406 | - host->reqs_blocked = 0; | ||
407 | + /* | ||
408 | + * Prevent races with the interrupt handler because of unexpected | ||
409 | + * interrupts, but not if we are already in interrupt context i.e. | ||
410 | + * retries. | ||
411 | + */ | ||
412 | + if (!in_interrupt()) { | ||
413 | + spin_lock_irqsave(&host->irq_lock, host->flags); | ||
414 | + /* | ||
415 | + * Protect the card from I/O if there is a possibility | ||
416 | + * it can be removed. | ||
417 | + */ | ||
418 | + if (host->protect_card) { | ||
419 | + if (host->reqs_blocked < 3) { | ||
420 | + /* | ||
421 | + * Ensure the controller is left in a consistent | ||
422 | + * state by resetting the command and data state | ||
423 | + * machines. | ||
424 | + */ | ||
425 | + omap_hsmmc_reset_controller_fsm(host, SRD); | ||
426 | + omap_hsmmc_reset_controller_fsm(host, SRC); | ||
427 | + host->reqs_blocked += 1; | ||
428 | + } | ||
429 | + req->cmd->error = -EBADF; | ||
430 | + if (req->data) | ||
431 | + req->data->error = -EBADF; | ||
432 | + spin_unlock_irqrestore(&host->irq_lock, host->flags); | ||
433 | + mmc_request_done(mmc, req); | ||
434 | + return; | ||
435 | + } else if (host->reqs_blocked) | ||
436 | + host->reqs_blocked = 0; | ||
437 | + } | ||
438 | WARN_ON(host->mrq != NULL); | ||
439 | host->mrq = req; | ||
440 | err = omap_hsmmc_prepare_data(host, req); | ||
441 | @@ -1514,6 +1496,8 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) | ||
442 | if (req->data) | ||
443 | req->data->error = err; | ||
444 | host->mrq = NULL; | ||
445 | + if (!in_interrupt()) | ||
446 | + spin_unlock_irqrestore(&host->irq_lock, host->flags); | ||
447 | mmc_request_done(mmc, req); | ||
448 | return; | ||
449 | } | ||
450 | @@ -2093,6 +2077,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | ||
451 | mmc->f_min = 400000; | ||
452 | mmc->f_max = 52000000; | ||
453 | |||
454 | + sema_init(&host->sem, 1); | ||
455 | spin_lock_init(&host->irq_lock); | ||
456 | |||
457 | host->iclk = clk_get(&pdev->dev, "ick"); | ||
458 | @@ -2235,7 +2220,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | ||
459 | pdata->resume = omap_hsmmc_resume_cdirq; | ||
460 | } | ||
461 | |||
462 | - omap_hsmmc_disable_irq(host); | ||
463 | + OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); | ||
464 | + OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); | ||
465 | |||
466 | mmc_host_lazy_disable(host->mmc); | ||
467 | |||
468 | @@ -2356,7 +2342,10 @@ static int omap_hsmmc_suspend(struct device *dev) | ||
469 | ret = mmc_suspend_host(host->mmc); | ||
470 | mmc_host_enable(host->mmc); | ||
471 | if (ret == 0) { | ||
472 | - omap_hsmmc_disable_irq(host); | ||
473 | + OMAP_HSMMC_WRITE(host->base, ISE, 0); | ||
474 | + OMAP_HSMMC_WRITE(host->base, IE, 0); | ||
475 | + | ||
476 | + | ||
477 | OMAP_HSMMC_WRITE(host->base, HCTL, | ||
478 | OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); | ||
479 | mmc_host_disable(host->mmc); | ||
480 | -- | ||
481 | 1.6.6.1 | ||
482 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0012-Don-t-turn-SDIO-cards-off-to-save-power.-Doing-so-wi.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0012-Don-t-turn-SDIO-cards-off-to-save-power.-Doing-so-wi.patch deleted file mode 100644 index 1c86b22d..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0012-Don-t-turn-SDIO-cards-off-to-save-power.-Doing-so-wi.patch +++ /dev/null | |||
@@ -1,51 +0,0 @@ | |||
1 | From 75d9413d575f724e1f7c006fdef374fb1c200346 Mon Sep 17 00:00:00 2001 | ||
2 | From: David Vrabel <david.vrabel@csr.com> | ||
3 | Date: Fri, 2 Apr 2010 08:41:47 -0700 | ||
4 | Subject: [PATCH 12/32] Don't turn SDIO cards off to save power. Doing so will lose all internal state in the card. | ||
5 | |||
6 | Signed-off-by: David Vrabel <david.vrabel@csr.com> | ||
7 | --- | ||
8 | drivers/mmc/host/omap_hsmmc.c | 12 ++++++++---- | ||
9 | 1 files changed, 8 insertions(+), 4 deletions(-) | ||
10 | |||
11 | diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c | ||
12 | index 15a023b..83f93ab 100644 | ||
13 | --- a/drivers/mmc/host/omap_hsmmc.c | ||
14 | +++ b/drivers/mmc/host/omap_hsmmc.c | ||
15 | @@ -29,6 +29,7 @@ | ||
16 | #include <linux/mmc/host.h> | ||
17 | #include <linux/mmc/core.h> | ||
18 | #include <linux/mmc/mmc.h> | ||
19 | +#include <linux/mmc/card.h> | ||
20 | #include <linux/io.h> | ||
21 | #include <linux/semaphore.h> | ||
22 | #include <linux/gpio.h> | ||
23 | @@ -1760,8 +1761,12 @@ static int omap_hsmmc_sleep_to_off(struct omap_hsmmc_host *host) | ||
24 | mmc_slot(host).card_detect || | ||
25 | (mmc_slot(host).get_cover_state && | ||
26 | mmc_slot(host).get_cover_state(host->dev, host->slot_id)))) { | ||
27 | - mmc_release_host(host->mmc); | ||
28 | - return 0; | ||
29 | + goto out; | ||
30 | + } | ||
31 | + | ||
32 | + /* Don't turn SDIO cards off. */ | ||
33 | + if (host->mmc->card && mmc_card_sdio(host->mmc->card)) { | ||
34 | + goto out; | ||
35 | } | ||
36 | |||
37 | mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); | ||
38 | @@ -1772,9 +1777,8 @@ static int omap_hsmmc_sleep_to_off(struct omap_hsmmc_host *host) | ||
39 | host->dpm_state == CARDSLEEP ? "CARDSLEEP" : "REGSLEEP"); | ||
40 | |||
41 | host->dpm_state = OFF; | ||
42 | - | ||
43 | +out: | ||
44 | mmc_release_host(host->mmc); | ||
45 | - | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | -- | ||
50 | 1.6.6.1 | ||
51 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0013-Enable-the-use-of-SDIO-card-interrupts.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0013-Enable-the-use-of-SDIO-card-interrupts.patch deleted file mode 100644 index 59d5ec47..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0013-Enable-the-use-of-SDIO-card-interrupts.patch +++ /dev/null | |||
@@ -1,288 +0,0 @@ | |||
1 | From 948eeb1f03da5fca0f6734c10efbc35ad63a1d08 Mon Sep 17 00:00:00 2001 | ||
2 | From: David Vrabel <david.vrabel@csr.com> | ||
3 | Date: Fri, 2 Apr 2010 08:42:22 -0700 | ||
4 | Subject: [PATCH 13/32] Enable the use of SDIO card interrupts. | ||
5 | |||
6 | FCLK must be enabled while SDIO interrupts are enabled or the MMC | ||
7 | module won't wake-up (even though ENAWAKEUP in SYSCONFIG and IWE in | ||
8 | HTCL have been set). Enabling the MMC module to wake-up would require | ||
9 | configuring the MMC module (and the mmci_dat[1] GPIO when the CORE | ||
10 | power domain is OFF) as wake-up sources in the PRCM. | ||
11 | |||
12 | The writes to STAT and ISE when starting a command are unnecessary and | ||
13 | have been removed. | ||
14 | |||
15 | Signed-off-by: David Vrabel <david.vrabel@csr.com> | ||
16 | --- | ||
17 | drivers/mmc/host/omap_hsmmc.c | 118 +++++++++++++++++++++++++++++------------ | ||
18 | 1 files changed, 83 insertions(+), 35 deletions(-) | ||
19 | |||
20 | diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c | ||
21 | index 83f93ab..d57686c 100644 | ||
22 | --- a/drivers/mmc/host/omap_hsmmc.c | ||
23 | +++ b/drivers/mmc/host/omap_hsmmc.c | ||
24 | @@ -67,6 +67,7 @@ | ||
25 | #define SDVS_MASK 0x00000E00 | ||
26 | #define SDVSCLR 0xFFFFF1FF | ||
27 | #define SDVSDET 0x00000400 | ||
28 | +#define ENAWAKEUP (1 << 2) | ||
29 | #define AUTOIDLE 0x1 | ||
30 | #define SDBP (1 << 8) | ||
31 | #define DTO 0xe | ||
32 | @@ -77,10 +78,13 @@ | ||
33 | #define CLKD_SHIFT 6 | ||
34 | #define DTO_MASK 0x000F0000 | ||
35 | #define DTO_SHIFT 16 | ||
36 | +#define CIRQ_ENABLE (1 << 8) | ||
37 | #define INT_EN_MASK 0x307F0033 | ||
38 | #define BWR_ENABLE (1 << 4) | ||
39 | #define BRR_ENABLE (1 << 5) | ||
40 | #define DTO_ENABLE (1 << 20) | ||
41 | +#define CTPL (1 << 11) | ||
42 | +#define CLKEXTFREE (1 << 16) | ||
43 | #define INIT_STREAM (1 << 1) | ||
44 | #define DP_SELECT (1 << 21) | ||
45 | #define DDIR (1 << 4) | ||
46 | @@ -88,10 +92,12 @@ | ||
47 | #define MSBS (1 << 5) | ||
48 | #define BCE (1 << 1) | ||
49 | #define FOUR_BIT (1 << 1) | ||
50 | +#define IWE (1 << 24) | ||
51 | #define DW8 (1 << 5) | ||
52 | #define CC 0x1 | ||
53 | #define TC 0x02 | ||
54 | #define OD 0x1 | ||
55 | +#define CIRQ (1 << 8) | ||
56 | #define ERR (1 << 15) | ||
57 | #define CMD_TIMEOUT (1 << 16) | ||
58 | #define DATA_TIMEOUT (1 << 20) | ||
59 | @@ -186,6 +192,7 @@ struct omap_hsmmc_host { | ||
60 | int protect_card; | ||
61 | int reqs_blocked; | ||
62 | int use_reg; | ||
63 | + int sdio_int; | ||
64 | |||
65 | struct omap_mmc_platform_data *pdata; | ||
66 | }; | ||
67 | @@ -598,7 +605,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) | ||
68 | ; | ||
69 | |||
70 | OMAP_HSMMC_WRITE(host->base, SYSCONFIG, | ||
71 | - OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE); | ||
72 | + OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE | ENAWAKEUP); | ||
73 | |||
74 | if (host->id == OMAP_MMC1_DEVID) { | ||
75 | if (host->power_mode != MMC_POWER_OFF && | ||
76 | @@ -613,7 +620,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) | ||
77 | } | ||
78 | |||
79 | OMAP_HSMMC_WRITE(host->base, HCTL, | ||
80 | - OMAP_HSMMC_READ(host->base, HCTL) | hctl); | ||
81 | + OMAP_HSMMC_READ(host->base, HCTL) | hctl | IWE); | ||
82 | |||
83 | OMAP_HSMMC_WRITE(host->base, CAPA, | ||
84 | OMAP_HSMMC_READ(host->base, CAPA) | capa); | ||
85 | @@ -627,7 +634,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) | ||
86 | ; | ||
87 | |||
88 | OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); | ||
89 | - OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); | ||
90 | + OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK | CIRQ); | ||
91 | OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); | ||
92 | |||
93 | /* Do not initialize card-specific things if the power is off */ | ||
94 | @@ -791,22 +798,19 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, | ||
95 | struct mmc_data *data) | ||
96 | { | ||
97 | int cmdreg = 0, resptype = 0, cmdtype = 0; | ||
98 | + int int_en_mask = INT_EN_MASK; | ||
99 | |||
100 | dev_dbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n", | ||
101 | mmc_hostname(host->mmc), cmd->opcode, cmd->arg); | ||
102 | host->cmd = cmd; | ||
103 | |||
104 | - /* | ||
105 | - * Clear status bits and enable interrupts | ||
106 | - */ | ||
107 | - OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); | ||
108 | - OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); | ||
109 | - | ||
110 | if (host->use_dma) | ||
111 | - OMAP_HSMMC_WRITE(host->base, IE, | ||
112 | - INT_EN_MASK & ~(BRR_ENABLE | BWR_ENABLE)); | ||
113 | - else | ||
114 | - OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); | ||
115 | + int_en_mask &= ~(BRR_ENABLE | BWR_ENABLE); | ||
116 | + | ||
117 | + if (host->sdio_int) | ||
118 | + int_en_mask |= CIRQ; | ||
119 | + | ||
120 | + OMAP_HSMMC_WRITE(host->base, IE, int_en_mask); | ||
121 | |||
122 | host->response_busy = 0; | ||
123 | if (cmd->flags & MMC_RSP_PRESENT) { | ||
124 | @@ -1019,23 +1023,26 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id) | ||
125 | { | ||
126 | struct omap_hsmmc_host *host = dev_id; | ||
127 | struct mmc_data *data; | ||
128 | - int end_cmd = 0, end_trans = 0, status; | ||
129 | + u32 status; | ||
130 | + int end_cmd = 0, end_trans = 0; | ||
131 | + bool card_irq = false; | ||
132 | |||
133 | spin_lock(&host->irq_lock); | ||
134 | |||
135 | - if (host->mrq == NULL) { | ||
136 | - OMAP_HSMMC_WRITE(host->base, STAT, | ||
137 | - OMAP_HSMMC_READ(host->base, STAT)); | ||
138 | - /* Flush posted write */ | ||
139 | - OMAP_HSMMC_READ(host->base, STAT); | ||
140 | - spin_unlock(&host->irq_lock); | ||
141 | - return IRQ_HANDLED; | ||
142 | - } | ||
143 | - | ||
144 | - data = host->data; | ||
145 | status = OMAP_HSMMC_READ(host->base, STAT); | ||
146 | + OMAP_HSMMC_WRITE(host->base, STAT, status); | ||
147 | + OMAP_HSMMC_READ(host->base, STAT); /* Flush posted write. */ | ||
148 | + | ||
149 | dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); | ||
150 | |||
151 | + if (status & CIRQ) | ||
152 | + card_irq = true; | ||
153 | + | ||
154 | + if (host->mrq == NULL) | ||
155 | + goto out; | ||
156 | + | ||
157 | + data = host->data; | ||
158 | + | ||
159 | if (status & ERR) { | ||
160 | #ifdef CONFIG_MMC_DEBUG | ||
161 | omap_hsmmc_report_irq(host, status); | ||
162 | @@ -1085,17 +1092,16 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id) | ||
163 | } | ||
164 | } | ||
165 | |||
166 | - OMAP_HSMMC_WRITE(host->base, STAT, status); | ||
167 | - /* Flush posted write */ | ||
168 | - OMAP_HSMMC_READ(host->base, STAT); | ||
169 | - | ||
170 | if (end_cmd || ((status & CC) && host->cmd)) | ||
171 | omap_hsmmc_cmd_done(host, host->cmd); | ||
172 | if ((end_trans || (status & TC)) && host->mrq) | ||
173 | omap_hsmmc_xfer_done(host, data); | ||
174 | - | ||
175 | +out: | ||
176 | spin_unlock(&host->irq_lock); | ||
177 | |||
178 | + if (card_irq) | ||
179 | + mmc_signal_sdio_irq(host->mmc); | ||
180 | + | ||
181 | return IRQ_HANDLED; | ||
182 | } | ||
183 | |||
184 | @@ -1643,6 +1649,47 @@ static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card) | ||
185 | mmc_slot(host).init_card(card); | ||
186 | } | ||
187 | |||
188 | +static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int enable) | ||
189 | +{ | ||
190 | + struct omap_hsmmc_host *host = mmc_priv(mmc); | ||
191 | + u32 ie, con; | ||
192 | + unsigned long flags; | ||
193 | + | ||
194 | + spin_lock_irqsave(&host->irq_lock, flags); | ||
195 | + | ||
196 | + /* | ||
197 | + * When interrupts are enabled, CTPL must be set to enable | ||
198 | + * DAT1 input buffer (or the card interrupt is always | ||
199 | + * asserted) and FCLK must be enabled as wake-up does not | ||
200 | + * work. Take care to disable FCLK after all the register | ||
201 | + * accesses as they might not complete if FCLK is off. | ||
202 | + * | ||
203 | + * FIXME: if the MMC module (and the mmci_dat[1] GPIO when the | ||
204 | + * CORE power domain is OFF) are configured as a wake-up | ||
205 | + * sources in the PRCM, then FCLK could be switched off. This | ||
206 | + * might add too much latency. | ||
207 | + */ | ||
208 | + con = OMAP_HSMMC_READ(host->base, CON); | ||
209 | + ie = OMAP_HSMMC_READ(host->base, IE); | ||
210 | + if (enable) { | ||
211 | + clk_enable(host->fclk); | ||
212 | + ie |= CIRQ_ENABLE; | ||
213 | + con |= CTPL | CLKEXTFREE; | ||
214 | + host->sdio_int = 1; | ||
215 | + } else { | ||
216 | + ie &= ~CIRQ_ENABLE; | ||
217 | + con &= ~(CTPL | CLKEXTFREE); | ||
218 | + host->sdio_int = 0; | ||
219 | + } | ||
220 | + OMAP_HSMMC_WRITE(host->base, CON, con); | ||
221 | + OMAP_HSMMC_WRITE(host->base, IE, ie); | ||
222 | + OMAP_HSMMC_READ(host->base, IE); /* flush posted write */ | ||
223 | + if (!enable) | ||
224 | + clk_disable(host->fclk); | ||
225 | + | ||
226 | + spin_unlock_irqrestore(&host->irq_lock, flags); | ||
227 | +} | ||
228 | + | ||
229 | static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host) | ||
230 | { | ||
231 | u32 hctl, capa, value; | ||
232 | @@ -1657,14 +1704,14 @@ static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host) | ||
233 | } | ||
234 | |||
235 | value = OMAP_HSMMC_READ(host->base, HCTL) & ~SDVS_MASK; | ||
236 | - OMAP_HSMMC_WRITE(host->base, HCTL, value | hctl); | ||
237 | + OMAP_HSMMC_WRITE(host->base, HCTL, value | hctl | IWE); | ||
238 | |||
239 | value = OMAP_HSMMC_READ(host->base, CAPA); | ||
240 | OMAP_HSMMC_WRITE(host->base, CAPA, value | capa); | ||
241 | |||
242 | /* Set the controller to AUTO IDLE mode */ | ||
243 | value = OMAP_HSMMC_READ(host->base, SYSCONFIG); | ||
244 | - OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE); | ||
245 | + OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE | ENAWAKEUP); | ||
246 | |||
247 | /* Set SD bus power bit */ | ||
248 | set_sd_bus_power(host); | ||
249 | @@ -1918,7 +1965,7 @@ static const struct mmc_host_ops omap_hsmmc_ops = { | ||
250 | .get_cd = omap_hsmmc_get_cd, | ||
251 | .get_ro = omap_hsmmc_get_ro, | ||
252 | .init_card = omap_hsmmc_init_card, | ||
253 | - /* NYET -- enable_sdio_irq */ | ||
254 | + .enable_sdio_irq = omap_hsmmc_enable_sdio_irq, | ||
255 | }; | ||
256 | |||
257 | static const struct mmc_host_ops omap_hsmmc_ps_ops = { | ||
258 | @@ -1929,7 +1976,7 @@ static const struct mmc_host_ops omap_hsmmc_ps_ops = { | ||
259 | .get_cd = omap_hsmmc_get_cd, | ||
260 | .get_ro = omap_hsmmc_get_ro, | ||
261 | .init_card = omap_hsmmc_init_card, | ||
262 | - /* NYET -- enable_sdio_irq */ | ||
263 | + .enable_sdio_irq = omap_hsmmc_enable_sdio_irq, | ||
264 | }; | ||
265 | |||
266 | #ifdef CONFIG_DEBUG_FS | ||
267 | @@ -2145,7 +2192,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | ||
268 | mmc->max_seg_size = mmc->max_req_size; | ||
269 | |||
270 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | | ||
271 | - MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE; | ||
272 | + MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE | | ||
273 | + MMC_CAP_SDIO_IRQ; | ||
274 | |||
275 | mmc->caps |= mmc_slot(host).caps; | ||
276 | if (mmc->caps & MMC_CAP_8_BIT_DATA) | ||
277 | @@ -2224,7 +2272,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | ||
278 | pdata->resume = omap_hsmmc_resume_cdirq; | ||
279 | } | ||
280 | |||
281 | - OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); | ||
282 | + OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK | CIRQ); | ||
283 | OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); | ||
284 | |||
285 | mmc_host_lazy_disable(host->mmc); | ||
286 | -- | ||
287 | 1.6.6.1 | ||
288 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0014-soc-codecs-Enable-audio-capture-by-default-for-twl40.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0014-soc-codecs-Enable-audio-capture-by-default-for-twl40.patch deleted file mode 100644 index d6e82879..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0014-soc-codecs-Enable-audio-capture-by-default-for-twl40.patch +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | From f646d3df7a7160fd80f20416c4a0fce55946f527 Mon Sep 17 00:00:00 2001 | ||
2 | From: Steve Sakoman <steve@sakoman.com> | ||
3 | Date: Thu, 17 Dec 2009 12:45:20 -0800 | ||
4 | Subject: [PATCH 14/32] soc: codecs: Enable audio capture by default for twl4030 | ||
5 | |||
6 | --- | ||
7 | sound/soc/codecs/twl4030.c | 4 ++-- | ||
8 | 1 files changed, 2 insertions(+), 2 deletions(-) | ||
9 | |||
10 | diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c | ||
11 | index 575238d..bd51f72 100644 | ||
12 | --- a/sound/soc/codecs/twl4030.c | ||
13 | +++ b/sound/soc/codecs/twl4030.c | ||
14 | @@ -56,8 +56,8 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { | ||
15 | 0x00, /* REG_OPTION (0x2) */ | ||
16 | 0x00, /* REG_UNKNOWN (0x3) */ | ||
17 | 0x00, /* REG_MICBIAS_CTL (0x4) */ | ||
18 | - 0x00, /* REG_ANAMICL (0x5) */ | ||
19 | - 0x00, /* REG_ANAMICR (0x6) */ | ||
20 | + 0x34, /* REG_ANAMICL (0x5) */ | ||
21 | + 0x14, /* REG_ANAMICR (0x6) */ | ||
22 | 0x00, /* REG_AVADC_CTL (0x7) */ | ||
23 | 0x00, /* REG_ADCMICSEL (0x8) */ | ||
24 | 0x00, /* REG_DIGMIXING (0x9) */ | ||
25 | -- | ||
26 | 1.6.6.1 | ||
27 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0015-soc-codecs-twl4030-Turn-on-mic-bias-by-default.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0015-soc-codecs-twl4030-Turn-on-mic-bias-by-default.patch deleted file mode 100644 index 04d91685..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0015-soc-codecs-twl4030-Turn-on-mic-bias-by-default.patch +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | From 00adf70cb5f8706ac5e7b1ec6f5a94f7e490b606 Mon Sep 17 00:00:00 2001 | ||
2 | From: Steve Sakoman <steve@sakoman.com> | ||
3 | Date: Wed, 29 Dec 2010 11:39:16 -0800 | ||
4 | Subject: [PATCH 15/32] soc: codecs: twl4030: Turn on mic bias by default | ||
5 | |||
6 | --- | ||
7 | sound/soc/codecs/twl4030.c | 2 +- | ||
8 | 1 files changed, 1 insertions(+), 1 deletions(-) | ||
9 | |||
10 | diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c | ||
11 | index bd51f72..8949773 100644 | ||
12 | --- a/sound/soc/codecs/twl4030.c | ||
13 | +++ b/sound/soc/codecs/twl4030.c | ||
14 | @@ -55,7 +55,7 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { | ||
15 | 0x00, /* REG_CODEC_MODE (0x1) */ | ||
16 | 0x00, /* REG_OPTION (0x2) */ | ||
17 | 0x00, /* REG_UNKNOWN (0x3) */ | ||
18 | - 0x00, /* REG_MICBIAS_CTL (0x4) */ | ||
19 | + 0x03, /* REG_MICBIAS_CTL (0x4) */ | ||
20 | 0x34, /* REG_ANAMICL (0x5) */ | ||
21 | 0x14, /* REG_ANAMICR (0x6) */ | ||
22 | 0x00, /* REG_AVADC_CTL (0x7) */ | ||
23 | -- | ||
24 | 1.6.6.1 | ||
25 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0016-RTC-add-support-for-backup-battery-recharge.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0016-RTC-add-support-for-backup-battery-recharge.patch deleted file mode 100644 index cb685cc2..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0016-RTC-add-support-for-backup-battery-recharge.patch +++ /dev/null | |||
@@ -1,55 +0,0 @@ | |||
1 | From 6f432e1e39f276a41d600d1cc9cd17fc088877d8 Mon Sep 17 00:00:00 2001 | ||
2 | From: Steve Sakoman <steve@sakoman.com> | ||
3 | Date: Thu, 4 Feb 2010 12:26:22 -0800 | ||
4 | Subject: [PATCH 16/32] RTC: add support for backup battery recharge | ||
5 | |||
6 | --- | ||
7 | drivers/rtc/rtc-twl.c | 25 +++++++++++++++++++++++++ | ||
8 | 1 files changed, 25 insertions(+), 0 deletions(-) | ||
9 | |||
10 | diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c | ||
11 | index f9a2799..713b8ea 100644 | ||
12 | --- a/drivers/rtc/rtc-twl.c | ||
13 | +++ b/drivers/rtc/rtc-twl.c | ||
14 | @@ -30,6 +30,23 @@ | ||
15 | |||
16 | #include <linux/i2c/twl.h> | ||
17 | |||
18 | +/* | ||
19 | + * PM_RECEIVER block register offsets (use TWL4030_MODULE_PM_RECEIVER) | ||
20 | + */ | ||
21 | +#define REG_BB_CFG 0x12 | ||
22 | + | ||
23 | +/* PM_RECEIVER BB_CFG bitfields */ | ||
24 | +#define BIT_PM_RECEIVER_BB_CFG_BBCHEN 0x10 | ||
25 | +#define BIT_PM_RECEIVER_BB_CFG_BBSEL 0x0C | ||
26 | +#define BIT_PM_RECEIVER_BB_CFG_BBSEL_2V5 0x00 | ||
27 | +#define BIT_PM_RECEIVER_BB_CFG_BBSEL_3V0 0x04 | ||
28 | +#define BIT_PM_RECEIVER_BB_CFG_BBSEL_3V1 0x08 | ||
29 | +#define BIT_PM_RECEIVER_BB_CFG_BBSEL_3v2 0x0c | ||
30 | +#define BIT_PM_RECEIVER_BB_CFG_BBISEL 0x03 | ||
31 | +#define BIT_PM_RECEIVER_BB_CFG_BBISEL_25UA 0x00 | ||
32 | +#define BIT_PM_RECEIVER_BB_CFG_BBISEL_150UA 0x01 | ||
33 | +#define BIT_PM_RECEIVER_BB_CFG_BBISEL_500UA 0x02 | ||
34 | +#define BIT_PM_RECEIVER_BB_CFG_BBISEL_1MA 0x03 | ||
35 | |||
36 | /* | ||
37 | * RTC block register offsets (use TWL_MODULE_RTC) | ||
38 | @@ -495,6 +512,14 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev) | ||
39 | if (ret < 0) | ||
40 | goto out2; | ||
41 | |||
42 | + /* enable backup battery charging */ | ||
43 | + /* use a conservative 25uA @ 3.1V */ | ||
44 | + ret = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, | ||
45 | + BIT_PM_RECEIVER_BB_CFG_BBCHEN | | ||
46 | + BIT_PM_RECEIVER_BB_CFG_BBSEL_3V1 | | ||
47 | + BIT_PM_RECEIVER_BB_CFG_BBISEL_25UA, | ||
48 | + REG_BB_CFG); | ||
49 | + | ||
50 | return ret; | ||
51 | |||
52 | out2: | ||
53 | -- | ||
54 | 1.6.6.1 | ||
55 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0017-ARM-OMAP2-mmc-twl4030-move-clock-input-selection-pri.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0017-ARM-OMAP2-mmc-twl4030-move-clock-input-selection-pri.patch deleted file mode 100644 index 1e6ba8db..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0017-ARM-OMAP2-mmc-twl4030-move-clock-input-selection-pri.patch +++ /dev/null | |||
@@ -1,39 +0,0 @@ | |||
1 | From 56dc96df8ff5e3db6afde96d64d74200f85e59c2 Mon Sep 17 00:00:00 2001 | ||
2 | From: Steve Sakoman <steve@sakoman.com> | ||
3 | Date: Sun, 24 Jan 2010 09:33:56 -0800 | ||
4 | Subject: [PATCH 17/32] ARM: OMAP2: mmc-twl4030: move clock input selection prior to vcc test | ||
5 | |||
6 | otherwise it is not executed on systems that use non-twl regulators | ||
7 | --- | ||
8 | arch/arm/mach-omap2/hsmmc.c | 14 ++++++-------- | ||
9 | 1 files changed, 6 insertions(+), 8 deletions(-) | ||
10 | |||
11 | diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c | ||
12 | index b2f30be..84d5ef6 100644 | ||
13 | --- a/arch/arm/mach-omap2/hsmmc.c | ||
14 | +++ b/arch/arm/mach-omap2/hsmmc.c | ||
15 | @@ -185,15 +185,13 @@ static void hsmmc23_before_set_reg(struct device *dev, int slot, | ||
16 | if (mmc->slots[0].remux) | ||
17 | mmc->slots[0].remux(dev, slot, power_on); | ||
18 | |||
19 | - if (power_on) { | ||
20 | - /* Only MMC2 supports a CLKIN */ | ||
21 | - if (mmc->slots[0].internal_clock) { | ||
22 | - u32 reg; | ||
23 | + /* Only MMC2 supports a CLKIN */ | ||
24 | + if (mmc->slots[0].internal_clock) { | ||
25 | + u32 reg; | ||
26 | |||
27 | - reg = omap_ctrl_readl(control_devconf1_offset); | ||
28 | - reg |= OMAP2_MMCSDIO2ADPCLKISEL; | ||
29 | - omap_ctrl_writel(reg, control_devconf1_offset); | ||
30 | - } | ||
31 | + reg = omap_ctrl_readl(control_devconf1_offset); | ||
32 | + reg |= OMAP2_MMCSDIO2ADPCLKISEL; | ||
33 | + omap_ctrl_writel(reg, control_devconf1_offset); | ||
34 | } | ||
35 | } | ||
36 | |||
37 | -- | ||
38 | 1.6.6.1 | ||
39 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0018-Add-power-off-support-for-the-TWL4030-companion.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0018-Add-power-off-support-for-the-TWL4030-companion.patch deleted file mode 100644 index 30860275..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0018-Add-power-off-support-for-the-TWL4030-companion.patch +++ /dev/null | |||
@@ -1,103 +0,0 @@ | |||
1 | From 8c257a6e7460ceb8c899980f7dad701ceb619adc Mon Sep 17 00:00:00 2001 | ||
2 | From: =?UTF-8?q?Bernhard=20W=C3=B6rndl-Aichriedler?= <bwa@xdevelop.at> | ||
3 | Date: Sat, 15 May 2010 16:34:05 +0200 | ||
4 | Subject: [PATCH 18/32] Add power-off support for the TWL4030 companion | ||
5 | |||
6 | This patch adds support for the power-off on shutdown feature of the TWL4030 | ||
7 | --- | ||
8 | drivers/mfd/Kconfig | 6 ++++++ | ||
9 | drivers/mfd/twl-core.c | 40 ++++++++++++++++++++++++++++++++++++++++ | ||
10 | 2 files changed, 46 insertions(+), 0 deletions(-) | ||
11 | |||
12 | diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig | ||
13 | index 3ed3ff0..fe2370a 100644 | ||
14 | --- a/drivers/mfd/Kconfig | ||
15 | +++ b/drivers/mfd/Kconfig | ||
16 | @@ -210,6 +210,12 @@ config TWL4030_CODEC | ||
17 | select MFD_CORE | ||
18 | default n | ||
19 | |||
20 | +config TWL4030_POWEROFF | ||
21 | + bool "TWL4030 Allow power-off on shutdown" | ||
22 | + depends on TWL4030_CORE | ||
23 | + help | ||
24 | + Enables the CPU to power-off the system on shutdown | ||
25 | + | ||
26 | config TWL6030_PWM | ||
27 | tristate "TWL6030 PWM (Pulse Width Modulator) Support" | ||
28 | depends on TWL4030_CORE | ||
29 | diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c | ||
30 | index 960b5be..8804550 100644 | ||
31 | --- a/drivers/mfd/twl-core.c | ||
32 | +++ b/drivers/mfd/twl-core.c | ||
33 | @@ -122,6 +122,12 @@ | ||
34 | #define twl_has_bci() false | ||
35 | #endif | ||
36 | |||
37 | +#if defined (CONFIG_TWL4030_POWEROFF) | ||
38 | +#define twl_has_poweroff() true | ||
39 | +#else | ||
40 | +#define twl_has_poweroff() false | ||
41 | +#endif | ||
42 | + | ||
43 | /* Triton Core internal information (BEGIN) */ | ||
44 | |||
45 | /* Last - for index max*/ | ||
46 | @@ -224,6 +230,10 @@ | ||
47 | #define TWL5031 BIT(2) /* twl5031 has different registers */ | ||
48 | #define TWL6030_CLASS BIT(3) /* TWL6030 class */ | ||
49 | |||
50 | +/* for pm_power_off */ | ||
51 | +#define PWR_P1_SW_EVENTS 0x10 | ||
52 | +#define PWR_DEVOFF (1 << 0) | ||
53 | + | ||
54 | /*----------------------------------------------------------------------*/ | ||
55 | |||
56 | /* is driver active, bound to a chip? */ | ||
57 | @@ -1006,6 +1016,30 @@ static int twl_remove(struct i2c_client *client) | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | +static void twl_poweroff(void) | ||
62 | +{ | ||
63 | + int err; | ||
64 | + u8 val; | ||
65 | + | ||
66 | + err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &val, | ||
67 | + PWR_P1_SW_EVENTS); | ||
68 | + if (err) { | ||
69 | + pr_err("%s: i2c error %d while reading TWL4030" | ||
70 | + "PM_MASTER P1_SW_EVENTS\n", | ||
71 | + DRIVER_NAME, err); | ||
72 | + return; | ||
73 | + } | ||
74 | + | ||
75 | + val |= PWR_DEVOFF; | ||
76 | + | ||
77 | + err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, val, | ||
78 | + PWR_P1_SW_EVENTS); | ||
79 | + if (err) | ||
80 | + pr_err("%s: i2c error %d while writing TWL4030" | ||
81 | + "PM_MASTER P1_SW_EVENTS\n", | ||
82 | + DRIVER_NAME, err); | ||
83 | +} | ||
84 | + | ||
85 | /* NOTE: this driver only handles a single twl4030/tps659x0 chip */ | ||
86 | static int __devinit | ||
87 | twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
88 | @@ -1093,6 +1127,12 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
89 | twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1); | ||
90 | } | ||
91 | |||
92 | + if(twl_has_poweroff()) | ||
93 | + { | ||
94 | + /* initialize pm_power_off routine */ | ||
95 | + pm_power_off = twl_poweroff; | ||
96 | + } | ||
97 | + | ||
98 | status = add_children(pdata, id->driver_data); | ||
99 | fail: | ||
100 | if (status < 0) | ||
101 | -- | ||
102 | 1.6.6.1 | ||
103 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0019-ARM-OMAP-Add-twl4030-madc-support-to-Overo.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0019-ARM-OMAP-Add-twl4030-madc-support-to-Overo.patch deleted file mode 100644 index 1f139f1c..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0019-ARM-OMAP-Add-twl4030-madc-support-to-Overo.patch +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | From 46ea520a3c80914ae5ad3e35be7b8650706da3e6 Mon Sep 17 00:00:00 2001 | ||
2 | From: Steve Sakoman <steve@sakoman.com> | ||
3 | Date: Thu, 17 Dec 2009 14:27:15 -0800 | ||
4 | Subject: [PATCH 19/32] ARM: OMAP: Add twl4030 madc support to Overo | ||
5 | |||
6 | Signed-off-by: Steve Sakoman <steve@sakoman.com> | ||
7 | --- | ||
8 | arch/arm/mach-omap2/board-overo.c | 5 +++++ | ||
9 | 1 files changed, 5 insertions(+), 0 deletions(-) | ||
10 | |||
11 | diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c | ||
12 | index 59ca333..86f76e9 100644 | ||
13 | --- a/arch/arm/mach-omap2/board-overo.c | ||
14 | +++ b/arch/arm/mach-omap2/board-overo.c | ||
15 | @@ -637,10 +637,15 @@ static struct twl4030_codec_data overo_codec_data = { | ||
16 | .audio = &overo_audio_data, | ||
17 | }; | ||
18 | |||
19 | +static struct twl4030_madc_platform_data overo_madc_data = { | ||
20 | + .irq_line = 1, | ||
21 | +}; | ||
22 | + | ||
23 | static struct twl4030_platform_data overo_twldata = { | ||
24 | .irq_base = TWL4030_IRQ_BASE, | ||
25 | .irq_end = TWL4030_IRQ_END, | ||
26 | .gpio = &overo_gpio_data, | ||
27 | + .madc = &overo_madc_data, | ||
28 | .usb = &overo_usb_data, | ||
29 | .codec = &overo_codec_data, | ||
30 | .vmmc1 = &overo_vmmc1, | ||
31 | -- | ||
32 | 1.6.6.1 | ||
33 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0020-Enabling-Hwmon-driver-for-twl4030-madc.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0020-Enabling-Hwmon-driver-for-twl4030-madc.patch deleted file mode 100644 index c80aef9a..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0020-Enabling-Hwmon-driver-for-twl4030-madc.patch +++ /dev/null | |||
@@ -1,46 +0,0 @@ | |||
1 | From 931bd787effbd6f1f00468c89c647c66c0bbc164 Mon Sep 17 00:00:00 2001 | ||
2 | From: Keerthy <j-keerthy@ti.com> | ||
3 | Date: Wed, 4 May 2011 01:14:50 +0530 | ||
4 | Subject: [PATCH 20/32] Enabling Hwmon driver for twl4030-madc | ||
5 | |||
6 | Signed-off-by: Keerthy <j-keerthy@ti.com> | ||
7 | --- | ||
8 | drivers/mfd/twl-core.c | 15 +++++++++++++++ | ||
9 | 1 files changed, 15 insertions(+), 0 deletions(-) | ||
10 | |||
11 | diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c | ||
12 | index 8804550..d9435e4 100644 | ||
13 | --- a/drivers/mfd/twl-core.c | ||
14 | +++ b/drivers/mfd/twl-core.c | ||
15 | @@ -83,6 +83,13 @@ | ||
16 | #define twl_has_madc() false | ||
17 | #endif | ||
18 | |||
19 | +#if defined(CONFIG_SENSORS_TWL4030_MADC) ||\ | ||
20 | + defined(CONFIG_SENSORS_TWL4030_MADC_MODULE) | ||
21 | +#define twl_has_madc_hwmon() true | ||
22 | +#else | ||
23 | +#define twl_has_madc_hwmon() false | ||
24 | +#endif | ||
25 | + | ||
26 | #ifdef CONFIG_TWL4030_POWER | ||
27 | #define twl_has_power() true | ||
28 | #else | ||
29 | @@ -619,6 +626,14 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | ||
30 | return PTR_ERR(child); | ||
31 | } | ||
32 | |||
33 | +if (twl_has_madc_hwmon()) { | ||
34 | + child = add_child(2, "twl4030_madc_hwmon", | ||
35 | + NULL, 0, | ||
36 | + true, pdata->irq_base + MADC_INTR_OFFSET, 0); | ||
37 | + if (IS_ERR(child)) | ||
38 | + return PTR_ERR(child); | ||
39 | + } | ||
40 | + | ||
41 | if (twl_has_rtc()) { | ||
42 | /* | ||
43 | * REVISIT platform_data here currently might expose the | ||
44 | -- | ||
45 | 1.6.6.1 | ||
46 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0021-mfd-twl-core-enable-madc-clock.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0021-mfd-twl-core-enable-madc-clock.patch deleted file mode 100644 index 732d306a..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0021-mfd-twl-core-enable-madc-clock.patch +++ /dev/null | |||
@@ -1,54 +0,0 @@ | |||
1 | From aee147073ad84a7c81fba36dd475c6d2d17ed728 Mon Sep 17 00:00:00 2001 | ||
2 | From: Steve Sakoman <steve@sakoman.com> | ||
3 | Date: Sat, 23 Jan 2010 06:26:54 -0800 | ||
4 | Subject: [PATCH 21/32] mfd: twl-core: enable madc clock | ||
5 | |||
6 | Now that the madc driver has been merged it is also necessary to enable the clock to the madc block | ||
7 | |||
8 | Signed-off-by: Steve Sakoman <steve@sakoman.com> | ||
9 | --- | ||
10 | drivers/mfd/twl-core.c | 8 ++++++++ | ||
11 | include/linux/i2c/twl.h | 1 + | ||
12 | 2 files changed, 9 insertions(+), 0 deletions(-) | ||
13 | |||
14 | diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c | ||
15 | index d9435e4..9096d7d 100644 | ||
16 | --- a/drivers/mfd/twl-core.c | ||
17 | +++ b/drivers/mfd/twl-core.c | ||
18 | @@ -222,6 +222,11 @@ | ||
19 | |||
20 | /* Few power values */ | ||
21 | #define R_CFG_BOOT 0x05 | ||
22 | +#define R_GPBR1 0x0C | ||
23 | + | ||
24 | +/* MADC clock values for R_GPBR1 */ | ||
25 | +#define MADC_HFCLK_EN 0x80 | ||
26 | +#define DEFAULT_MADC_CLK_EN 0x10 | ||
27 | |||
28 | /* some fields in R_CFG_BOOT */ | ||
29 | #define HFCLK_FREQ_19p2_MHZ (1 << 0) | ||
30 | @@ -992,6 +997,9 @@ static void clocks_init(struct device *dev, | ||
31 | |||
32 | e |= unprotect_pm_master(); | ||
33 | /* effect->MADC+USB ck en */ | ||
34 | + if (twl_has_madc()) | ||
35 | + e |= twl_i2c_write_u8(TWL_MODULE_INTBR, | ||
36 | + MADC_HFCLK_EN | DEFAULT_MADC_CLK_EN, R_GPBR1); | ||
37 | e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, ctrl, R_CFG_BOOT); | ||
38 | e |= protect_pm_master(); | ||
39 | |||
40 | diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h | ||
41 | index 0c0d1ae..cbbf3b3 100644 | ||
42 | --- a/include/linux/i2c/twl.h | ||
43 | +++ b/include/linux/i2c/twl.h | ||
44 | @@ -74,6 +74,7 @@ | ||
45 | |||
46 | #define TWL_MODULE_USB TWL4030_MODULE_USB | ||
47 | #define TWL_MODULE_AUDIO_VOICE TWL4030_MODULE_AUDIO_VOICE | ||
48 | +#define TWL_MODULE_INTBR TWL4030_MODULE_INTBR | ||
49 | #define TWL_MODULE_PIH TWL4030_MODULE_PIH | ||
50 | #define TWL_MODULE_MADC TWL4030_MODULE_MADC | ||
51 | #define TWL_MODULE_MAIN_CHARGE TWL4030_MODULE_MAIN_CHARGE | ||
52 | -- | ||
53 | 1.6.6.1 | ||
54 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0022-rtc-twl-Switch-to-using-threaded-irq.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0022-rtc-twl-Switch-to-using-threaded-irq.patch deleted file mode 100644 index 0306d4b4..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0022-rtc-twl-Switch-to-using-threaded-irq.patch +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | From 29dd1b5655f60f97a9cee2f4ff1d27d7da1329a1 Mon Sep 17 00:00:00 2001 | ||
2 | From: Ilkka Koskinen <ilkka.koskinen@nokia.com> | ||
3 | Date: Wed, 16 Mar 2011 16:07:14 +0000 | ||
4 | Subject: [PATCH 22/32] rtc-twl: Switch to using threaded irq | ||
5 | |||
6 | --- | ||
7 | drivers/rtc/rtc-twl.c | 2 +- | ||
8 | 1 files changed, 1 insertions(+), 1 deletions(-) | ||
9 | |||
10 | diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c | ||
11 | index 713b8ea..1fe1bc9 100644 | ||
12 | --- a/drivers/rtc/rtc-twl.c | ||
13 | +++ b/drivers/rtc/rtc-twl.c | ||
14 | @@ -479,7 +479,7 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev) | ||
15 | if (ret < 0) | ||
16 | goto out1; | ||
17 | |||
18 | - ret = request_irq(irq, twl_rtc_interrupt, | ||
19 | + ret = request_threaded_irq(irq, NULL, twl_rtc_interrupt, | ||
20 | IRQF_TRIGGER_RISING, | ||
21 | dev_name(&rtc->dev), rtc); | ||
22 | if (ret < 0) { | ||
23 | -- | ||
24 | 1.6.6.1 | ||
25 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0023-ARM-OMAP-automatically-set-musb-mode-in-platform-dat.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0023-ARM-OMAP-automatically-set-musb-mode-in-platform-dat.patch deleted file mode 100644 index a35d7de5..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0023-ARM-OMAP-automatically-set-musb-mode-in-platform-dat.patch +++ /dev/null | |||
@@ -1,49 +0,0 @@ | |||
1 | From 92c06791d4d6b537a9a83b27d71d7d3dd348f93f Mon Sep 17 00:00:00 2001 | ||
2 | From: Steve Sakoman <steve@sakoman.com> | ||
3 | Date: Wed, 24 Feb 2010 10:37:22 -0800 | ||
4 | Subject: [PATCH 23/32] ARM: OMAP: automatically set musb mode in platform data based on CONFIG options | ||
5 | |||
6 | --- | ||
7 | arch/arm/mach-omap2/board-omap3beagle.c | 6 ++++++ | ||
8 | arch/arm/mach-omap2/board-overo.c | 6 ++++++ | ||
9 | 2 files changed, 12 insertions(+), 0 deletions(-) | ||
10 | |||
11 | diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c | ||
12 | index 33007fd..2de4b02 100644 | ||
13 | --- a/arch/arm/mach-omap2/board-omap3beagle.c | ||
14 | +++ b/arch/arm/mach-omap2/board-omap3beagle.c | ||
15 | @@ -604,7 +604,13 @@ static struct omap_board_mux board_mux[] __initdata = { | ||
16 | |||
17 | static struct omap_musb_board_data musb_board_data = { | ||
18 | .interface_type = MUSB_INTERFACE_ULPI, | ||
19 | +#if defined(CONFIG_USB_MUSB_OTG) | ||
20 | .mode = MUSB_OTG, | ||
21 | +#elif defined(CONFIG_USB_GADGET_MUSB_HDRC) | ||
22 | + .mode = MUSB_PERIPHERAL, | ||
23 | +#else | ||
24 | + .mode = MUSB_HOST, | ||
25 | +#endif | ||
26 | .power = 100, | ||
27 | }; | ||
28 | |||
29 | diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c | ||
30 | index 86f76e9..61c59fc 100644 | ||
31 | --- a/arch/arm/mach-omap2/board-overo.c | ||
32 | +++ b/arch/arm/mach-omap2/board-overo.c | ||
33 | @@ -729,7 +729,13 @@ static struct omap_board_mux board_mux[] __initdata = { | ||
34 | |||
35 | static struct omap_musb_board_data musb_board_data = { | ||
36 | .interface_type = MUSB_INTERFACE_ULPI, | ||
37 | +#if defined(CONFIG_USB_MUSB_OTG) | ||
38 | .mode = MUSB_OTG, | ||
39 | +#elif defined(CONFIG_USB_GADGET_MUSB_HDRC) | ||
40 | + .mode = MUSB_PERIPHERAL, | ||
41 | +#else | ||
42 | + .mode = MUSB_HOST, | ||
43 | +#endif | ||
44 | .power = 100, | ||
45 | }; | ||
46 | |||
47 | -- | ||
48 | 1.6.6.1 | ||
49 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0024-omap-mmc-Adjust-dto-to-eliminate-timeout-errors.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0024-omap-mmc-Adjust-dto-to-eliminate-timeout-errors.patch deleted file mode 100644 index bd1764a5..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0024-omap-mmc-Adjust-dto-to-eliminate-timeout-errors.patch +++ /dev/null | |||
@@ -1,28 +0,0 @@ | |||
1 | From a442a2b9b2f9f51375f8a796ee88784d3754be00 Mon Sep 17 00:00:00 2001 | ||
2 | From: Steve Sakoman <steve@sakoman.com> | ||
3 | Date: Wed, 12 Jan 2011 05:54:55 -0800 | ||
4 | Subject: [PATCH 24/32] omap: mmc: Adjust dto to eliminate timeout errors | ||
5 | |||
6 | A number of SD card types were experiencing timeout errors. This | ||
7 | could also lead to data corruption in some cases. | ||
8 | |||
9 | This fix proposed by Sukumar Ghoral of TI. | ||
10 | --- | ||
11 | drivers/mmc/host/omap_hsmmc.c | 1 + | ||
12 | 1 files changed, 1 insertions(+), 0 deletions(-) | ||
13 | |||
14 | diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c | ||
15 | index d57686c..7fb03e8 100644 | ||
16 | --- a/drivers/mmc/host/omap_hsmmc.c | ||
17 | +++ b/drivers/mmc/host/omap_hsmmc.c | ||
18 | @@ -1400,6 +1400,7 @@ static void set_data_timeout(struct omap_hsmmc_host *host, | ||
19 | cycle_ns = 1000000000 / (clk_get_rate(host->fclk) / clkd); | ||
20 | timeout = timeout_ns / cycle_ns; | ||
21 | timeout += timeout_clks; | ||
22 | + timeout *= 2; | ||
23 | if (timeout) { | ||
24 | while ((timeout & 0x80000000) == 0) { | ||
25 | dto += 1; | ||
26 | -- | ||
27 | 1.6.6.1 | ||
28 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0025-omap-Fix-mtd-subpage-read-alignment.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0025-omap-Fix-mtd-subpage-read-alignment.patch deleted file mode 100644 index 1508da1a..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0025-omap-Fix-mtd-subpage-read-alignment.patch +++ /dev/null | |||
@@ -1,95 +0,0 @@ | |||
1 | From acf75c8b4d0f6775527636bf9d41bb1f74fc2f97 Mon Sep 17 00:00:00 2001 | ||
2 | From: Charles Manning <cdhmanning@gmail.com> | ||
3 | Date: Tue, 18 Jan 2011 11:25:25 +1300 | ||
4 | Subject: [PATCH 25/32] omap: Fix mtd subpage read alignment | ||
5 | |||
6 | This allows the omap2 prefetch engine to work properly for subpage | ||
7 | reads. Without this ECC errors will stop UBIFS from working. | ||
8 | |||
9 | Signed-off-by: Charles Manning <cdhmanning@gmail.com> | ||
10 | --- | ||
11 | drivers/mtd/nand/nand_base.c | 19 +++++++++++++++++++ | ||
12 | drivers/mtd/nand/omap2.c | 1 + | ||
13 | include/linux/mtd/nand.h | 3 +++ | ||
14 | 3 files changed, 23 insertions(+), 0 deletions(-) | ||
15 | |||
16 | diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c | ||
17 | index c54a4cb..6ca7098 100644 | ||
18 | --- a/drivers/mtd/nand/nand_base.c | ||
19 | +++ b/drivers/mtd/nand/nand_base.c | ||
20 | @@ -1157,6 +1157,22 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | ||
21 | } | ||
22 | |||
23 | /** | ||
24 | + * nand_align_subpage32 - function to align subpage read to 32-bits | ||
25 | + * @mtd: mtd info structure | ||
26 | + * @buf: pointer to offset that needs to be aligned | ||
27 | + * @len: pointer to length that needs to be aligned. | ||
28 | + */ | ||
29 | + | ||
30 | +void nand_align_subpage32(int *offs, int *len) | ||
31 | +{ | ||
32 | + int diff = *offs & 3; | ||
33 | + | ||
34 | + *offs = *offs - diff; | ||
35 | + *len = (*len + diff + 3) & ~3; | ||
36 | +} | ||
37 | +EXPORT_SYMBOL(nand_align_subpage32); | ||
38 | + | ||
39 | +/** | ||
40 | * nand_read_subpage - [REPLACABLE] software ecc based sub-page read function | ||
41 | * @mtd: mtd info structure | ||
42 | * @chip: nand chip info structure | ||
43 | @@ -1221,6 +1237,9 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | ||
44 | if (eccpos[index + (num_steps * chip->ecc.bytes)] & (busw - 1)) | ||
45 | aligned_len++; | ||
46 | |||
47 | + if(chip->align_subpage) | ||
48 | + chip->align_subpage(&aligned_pos, &aligned_len); | ||
49 | + | ||
50 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, | ||
51 | mtd->writesize + aligned_pos, -1); | ||
52 | chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len); | ||
53 | diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c | ||
54 | index da9a351..bb89c65 100644 | ||
55 | --- a/drivers/mtd/nand/omap2.c | ||
56 | +++ b/drivers/mtd/nand/omap2.c | ||
57 | @@ -1069,6 +1069,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) | ||
58 | info->nand.ecc.correct = omap_correct_data; | ||
59 | info->nand.ecc.mode = NAND_ECC_HW; | ||
60 | } | ||
61 | + info->nand.align_subpage = nand_align_subpage32; | ||
62 | |||
63 | /* DIP switches on some boards change between 8 and 16 bit | ||
64 | * bus widths for flash. Try the other width if the first try fails. | ||
65 | diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h | ||
66 | index d441927..311f211 100644 | ||
67 | --- a/include/linux/mtd/nand.h | ||
68 | +++ b/include/linux/mtd/nand.h | ||
69 | @@ -479,6 +479,7 @@ struct nand_buffers { | ||
70 | * additional error status checks (determine if errors are | ||
71 | * correctable). | ||
72 | * @write_page: [REPLACEABLE] High-level page write function | ||
73 | + * @align_subpage: [OPTIONAL] Aligns subpage read buffer. | ||
74 | */ | ||
75 | |||
76 | struct nand_chip { | ||
77 | @@ -507,6 +508,7 @@ struct nand_chip { | ||
78 | int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, | ||
79 | const uint8_t *buf, int page, int cached, int raw); | ||
80 | |||
81 | + void (*align_subpage)(int *offs, int *len); | ||
82 | int chip_delay; | ||
83 | unsigned int options; | ||
84 | |||
85 | @@ -602,6 +604,7 @@ extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | ||
86 | int allowbbt); | ||
87 | extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len, | ||
88 | size_t *retlen, uint8_t *buf); | ||
89 | +extern void nand_align_subpage32(int *offs, int *len); | ||
90 | |||
91 | /** | ||
92 | * struct platform_nand_chip - chip level device structure | ||
93 | -- | ||
94 | 1.6.6.1 | ||
95 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0026-mtd-nand-omap2-Force-all-buffer-reads-to-u32-alignme.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0026-mtd-nand-omap2-Force-all-buffer-reads-to-u32-alignme.patch deleted file mode 100644 index 5e060231..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0026-mtd-nand-omap2-Force-all-buffer-reads-to-u32-alignme.patch +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | From 048c2b85c12ac4aa8cd82201e1ade332557e4380 Mon Sep 17 00:00:00 2001 | ||
2 | From: Charles Manning <manningc2@actrix.gen.nz> | ||
3 | Date: Thu, 16 Dec 2010 20:35:56 -0800 | ||
4 | Subject: [PATCH 26/32] mtd: nand: omap2: Force all buffer reads to u32 alignment | ||
5 | |||
6 | --- | ||
7 | drivers/mtd/nand/omap2.c | 12 ++++++++++++ | ||
8 | 1 files changed, 12 insertions(+), 0 deletions(-) | ||
9 | |||
10 | diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c | ||
11 | index bb89c65..832f111 100644 | ||
12 | --- a/drivers/mtd/nand/omap2.c | ||
13 | +++ b/drivers/mtd/nand/omap2.c | ||
14 | @@ -247,6 +247,18 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) | ||
15 | int ret = 0; | ||
16 | u32 *p = (u32 *)buf; | ||
17 | |||
18 | + /* u32 align the buffer and read */ | ||
19 | + /* NB: This assumes the buf ptr can be aligned *down* which is a valid. | ||
20 | + * Assumption when dealing with ecc buffers etc. | ||
21 | + */ | ||
22 | + u32 addr = (u32)p; | ||
23 | + | ||
24 | + int diff = addr & 3; | ||
25 | + addr -= diff; | ||
26 | + len += diff; | ||
27 | + len = (len + 3) & ~3; | ||
28 | + p = (u32 *)addr; | ||
29 | + | ||
30 | /* take care of subpage reads */ | ||
31 | if (len % 4) { | ||
32 | if (info->nand.options & NAND_BUSWIDTH_16) | ||
33 | -- | ||
34 | 1.6.6.1 | ||
35 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0027-omap-nand-fix-subpage-ecc-issue-with-prefetch.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0027-omap-nand-fix-subpage-ecc-issue-with-prefetch.patch deleted file mode 100644 index 21eb1e9f..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0027-omap-nand-fix-subpage-ecc-issue-with-prefetch.patch +++ /dev/null | |||
@@ -1,63 +0,0 @@ | |||
1 | From fb4dfff6a6e107e0e526801e7add4a9aaeab1eab Mon Sep 17 00:00:00 2001 | ||
2 | From: kishore kadiyala <kishore.kadiyala@ti.com> | ||
3 | Date: Mon, 2 May 2011 11:10:38 +0000 | ||
4 | Subject: [PATCH 27/32] omap : nand : fix subpage ecc issue with prefetch | ||
5 | |||
6 | For prefetch engine, read and write got broken in commit '2c01946c'. | ||
7 | We never hit a scenario of not getting 'gpmc_prefetch_enable' | ||
8 | call success. | ||
9 | When reading/writing a subpage with a non divisible by 4 ecc number | ||
10 | of bytes, the mis-aligned bytes gets handled first before enabling | ||
11 | the Prefetch engine, then it reads/writes rest of the bytes. | ||
12 | |||
13 | Signed-off-by: Kishore Kadiyala <kishore.kadiyala@ti.com> | ||
14 | Signed-off-by: Vimal Singh <vimal.newwork@gmail.com> | ||
15 | Reported-by: Bryan DE FARIA <bdefaria@adeneo-embedded.com> | ||
16 | --- | ||
17 | drivers/mtd/nand/omap2.c | 12 +++++------- | ||
18 | 1 files changed, 5 insertions(+), 7 deletions(-) | ||
19 | |||
20 | diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c | ||
21 | index 832f111..471a39b 100644 | ||
22 | --- a/drivers/mtd/nand/omap2.c | ||
23 | +++ b/drivers/mtd/nand/omap2.c | ||
24 | @@ -275,11 +275,10 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) | ||
25 | if (ret) { | ||
26 | /* PFPW engine is busy, use cpu copy method */ | ||
27 | if (info->nand.options & NAND_BUSWIDTH_16) | ||
28 | - omap_read_buf16(mtd, buf, len); | ||
29 | + omap_read_buf16(mtd, (u_char *)p, len); | ||
30 | else | ||
31 | - omap_read_buf8(mtd, buf, len); | ||
32 | + omap_read_buf8(mtd, (u_char *)p, len); | ||
33 | } else { | ||
34 | - p = (u32 *) buf; | ||
35 | do { | ||
36 | r_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT); | ||
37 | r_count = r_count >> 2; | ||
38 | @@ -305,7 +304,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd, | ||
39 | struct omap_nand_info, mtd); | ||
40 | uint32_t w_count = 0; | ||
41 | int i = 0, ret = 0; | ||
42 | - u16 *p; | ||
43 | + u16 *p = (u16 *)buf; | ||
44 | unsigned long tim, limit; | ||
45 | |||
46 | /* take care of subpage writes */ | ||
47 | @@ -321,11 +320,10 @@ static void omap_write_buf_pref(struct mtd_info *mtd, | ||
48 | if (ret) { | ||
49 | /* PFPW engine is busy, use cpu copy method */ | ||
50 | if (info->nand.options & NAND_BUSWIDTH_16) | ||
51 | - omap_write_buf16(mtd, buf, len); | ||
52 | + omap_write_buf16(mtd, (u_char *)p, len); | ||
53 | else | ||
54 | - omap_write_buf8(mtd, buf, len); | ||
55 | + omap_write_buf8(mtd, (u_char *)p, len); | ||
56 | } else { | ||
57 | - p = (u16 *) buf; | ||
58 | while (len) { | ||
59 | w_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT); | ||
60 | w_count = w_count >> 1; | ||
61 | -- | ||
62 | 1.6.6.1 | ||
63 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0028-OMAP-Overo-Add-support-for-spidev.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0028-OMAP-Overo-Add-support-for-spidev.patch deleted file mode 100644 index be1f9630..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0028-OMAP-Overo-Add-support-for-spidev.patch +++ /dev/null | |||
@@ -1,46 +0,0 @@ | |||
1 | From ee2dcb39e9255fc0aa6b4e267e9553bdbd11e82b Mon Sep 17 00:00:00 2001 | ||
2 | From: Scott Ellis <scottellis.developer@gmail.com> | ||
3 | Date: Sun, 23 Jan 2011 20:39:35 -0800 | ||
4 | Subject: [PATCH 28/32] OMAP: Overo: Add support for spidev | ||
5 | |||
6 | --- | ||
7 | arch/arm/mach-omap2/board-overo.c | 16 ++++++++++++++++ | ||
8 | 1 files changed, 16 insertions(+), 0 deletions(-) | ||
9 | |||
10 | diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c | ||
11 | index 61c59fc..05dd3eb 100644 | ||
12 | --- a/arch/arm/mach-omap2/board-overo.c | ||
13 | +++ b/arch/arm/mach-omap2/board-overo.c | ||
14 | @@ -683,6 +683,14 @@ static struct spi_board_info overo_spi_board_info[] __initdata = { | ||
15 | .irq = OMAP_GPIO_IRQ(OVERO_GPIO_PENDOWN), | ||
16 | .platform_data = &ads7846_config, | ||
17 | }, | ||
18 | +#elif defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE) | ||
19 | + { | ||
20 | + .modalias = "spidev", | ||
21 | + .bus_num = 1, | ||
22 | + .chip_select = 0, | ||
23 | + .max_speed_hz = 48000000, | ||
24 | + .mode = SPI_MODE_0, | ||
25 | + }, | ||
26 | #endif | ||
27 | #if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \ | ||
28 | defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE) | ||
29 | @@ -693,6 +701,14 @@ static struct spi_board_info overo_spi_board_info[] __initdata = { | ||
30 | .max_speed_hz = 500000, | ||
31 | .mode = SPI_MODE_3, | ||
32 | }, | ||
33 | +#elif defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE) | ||
34 | + { | ||
35 | + .modalias = "spidev", | ||
36 | + .bus_num = 1, | ||
37 | + .chip_select = 1, | ||
38 | + .max_speed_hz = 48000000, | ||
39 | + .mode = SPI_MODE_0, | ||
40 | + }, | ||
41 | #endif | ||
42 | }; | ||
43 | |||
44 | -- | ||
45 | 1.6.6.1 | ||
46 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0029-unionfs-Add-support-for-unionfs-2.5.9.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0029-unionfs-Add-support-for-unionfs-2.5.9.patch deleted file mode 100644 index c17608b0..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0029-unionfs-Add-support-for-unionfs-2.5.9.patch +++ /dev/null | |||
@@ -1,11494 +0,0 @@ | |||
1 | From 0de368979f94e7c51940979c6149d34aec08f13f Mon Sep 17 00:00:00 2001 | ||
2 | From: Steve Sakoman <steve@sakoman.com> | ||
3 | Date: Mon, 2 May 2011 16:14:34 -0700 | ||
4 | Subject: [PATCH 29/32] unionfs: Add support for unionfs 2.5.9 | ||
5 | |||
6 | --- | ||
7 | Documentation/filesystems/00-INDEX | 2 + | ||
8 | Documentation/filesystems/unionfs/00-INDEX | 10 + | ||
9 | Documentation/filesystems/unionfs/concepts.txt | 287 ++++++ | ||
10 | Documentation/filesystems/unionfs/issues.txt | 28 + | ||
11 | Documentation/filesystems/unionfs/rename.txt | 31 + | ||
12 | Documentation/filesystems/unionfs/usage.txt | 134 +++ | ||
13 | MAINTAINERS | 8 + | ||
14 | fs/Kconfig | 1 + | ||
15 | fs/Makefile | 1 + | ||
16 | fs/namei.c | 38 + | ||
17 | fs/splice.c | 22 +- | ||
18 | fs/stack.c | 14 +- | ||
19 | fs/unionfs/Kconfig | 24 + | ||
20 | fs/unionfs/Makefile | 17 + | ||
21 | fs/unionfs/commonfops.c | 898 +++++++++++++++++++ | ||
22 | fs/unionfs/copyup.c | 896 +++++++++++++++++++ | ||
23 | fs/unionfs/debug.c | 548 ++++++++++++ | ||
24 | fs/unionfs/dentry.c | 406 +++++++++ | ||
25 | fs/unionfs/dirfops.c | 302 +++++++ | ||
26 | fs/unionfs/dirhelper.c | 158 ++++ | ||
27 | fs/unionfs/fanout.h | 407 +++++++++ | ||
28 | fs/unionfs/file.c | 382 ++++++++ | ||
29 | fs/unionfs/inode.c | 1099 ++++++++++++++++++++++++ | ||
30 | fs/unionfs/lookup.c | 569 ++++++++++++ | ||
31 | fs/unionfs/main.c | 763 ++++++++++++++++ | ||
32 | fs/unionfs/mmap.c | 89 ++ | ||
33 | fs/unionfs/rdstate.c | 285 ++++++ | ||
34 | fs/unionfs/rename.c | 522 +++++++++++ | ||
35 | fs/unionfs/sioq.c | 101 +++ | ||
36 | fs/unionfs/sioq.h | 91 ++ | ||
37 | fs/unionfs/subr.c | 95 ++ | ||
38 | fs/unionfs/super.c | 1030 ++++++++++++++++++++++ | ||
39 | fs/unionfs/union.h | 679 +++++++++++++++ | ||
40 | fs/unionfs/unlink.c | 278 ++++++ | ||
41 | fs/unionfs/whiteout.c | 601 +++++++++++++ | ||
42 | fs/unionfs/xattr.c | 173 ++++ | ||
43 | include/linux/fs_stack.h | 14 +- | ||
44 | include/linux/magic.h | 2 + | ||
45 | include/linux/namei.h | 3 + | ||
46 | include/linux/splice.h | 5 + | ||
47 | include/linux/union_fs.h | 22 + | ||
48 | security/security.c | 1 + | ||
49 | 42 files changed, 11024 insertions(+), 12 deletions(-) | ||
50 | create mode 100644 Documentation/filesystems/unionfs/00-INDEX | ||
51 | create mode 100644 Documentation/filesystems/unionfs/concepts.txt | ||
52 | create mode 100644 Documentation/filesystems/unionfs/issues.txt | ||
53 | create mode 100644 Documentation/filesystems/unionfs/rename.txt | ||
54 | create mode 100644 Documentation/filesystems/unionfs/usage.txt | ||
55 | create mode 100644 fs/unionfs/Kconfig | ||
56 | create mode 100644 fs/unionfs/Makefile | ||
57 | create mode 100644 fs/unionfs/commonfops.c | ||
58 | create mode 100644 fs/unionfs/copyup.c | ||
59 | create mode 100644 fs/unionfs/debug.c | ||
60 | create mode 100644 fs/unionfs/dentry.c | ||
61 | create mode 100644 fs/unionfs/dirfops.c | ||
62 | create mode 100644 fs/unionfs/dirhelper.c | ||
63 | create mode 100644 fs/unionfs/fanout.h | ||
64 | create mode 100644 fs/unionfs/file.c | ||
65 | create mode 100644 fs/unionfs/inode.c | ||
66 | create mode 100644 fs/unionfs/lookup.c | ||
67 | create mode 100644 fs/unionfs/main.c | ||
68 | create mode 100644 fs/unionfs/mmap.c | ||
69 | create mode 100644 fs/unionfs/rdstate.c | ||
70 | create mode 100644 fs/unionfs/rename.c | ||
71 | create mode 100644 fs/unionfs/sioq.c | ||
72 | create mode 100644 fs/unionfs/sioq.h | ||
73 | create mode 100644 fs/unionfs/subr.c | ||
74 | create mode 100644 fs/unionfs/super.c | ||
75 | create mode 100644 fs/unionfs/union.h | ||
76 | create mode 100644 fs/unionfs/unlink.c | ||
77 | create mode 100644 fs/unionfs/whiteout.c | ||
78 | create mode 100644 fs/unionfs/xattr.c | ||
79 | create mode 100644 include/linux/union_fs.h | ||
80 | |||
81 | diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX | ||
82 | index 8c624a1..4aa288b 100644 | ||
83 | --- a/Documentation/filesystems/00-INDEX | ||
84 | +++ b/Documentation/filesystems/00-INDEX | ||
85 | @@ -110,6 +110,8 @@ udf.txt | ||
86 | - info and mount options for the UDF filesystem. | ||
87 | ufs.txt | ||
88 | - info on the ufs filesystem. | ||
89 | +unionfs/ | ||
90 | + - info on the unionfs filesystem | ||
91 | vfat.txt | ||
92 | - info on using the VFAT filesystem used in Windows NT and Windows 95 | ||
93 | vfs.txt | ||
94 | diff --git a/Documentation/filesystems/unionfs/00-INDEX b/Documentation/filesystems/unionfs/00-INDEX | ||
95 | new file mode 100644 | ||
96 | index 0000000..96fdf67 | ||
97 | --- /dev/null | ||
98 | +++ b/Documentation/filesystems/unionfs/00-INDEX | ||
99 | @@ -0,0 +1,10 @@ | ||
100 | +00-INDEX | ||
101 | + - this file. | ||
102 | +concepts.txt | ||
103 | + - A brief introduction of concepts. | ||
104 | +issues.txt | ||
105 | + - A summary of known issues with unionfs. | ||
106 | +rename.txt | ||
107 | + - Information regarding rename operations. | ||
108 | +usage.txt | ||
109 | + - Usage information and examples. | ||
110 | diff --git a/Documentation/filesystems/unionfs/concepts.txt b/Documentation/filesystems/unionfs/concepts.txt | ||
111 | new file mode 100644 | ||
112 | index 0000000..b853788 | ||
113 | --- /dev/null | ||
114 | +++ b/Documentation/filesystems/unionfs/concepts.txt | ||
115 | @@ -0,0 +1,287 @@ | ||
116 | +Unionfs 2.x CONCEPTS: | ||
117 | +===================== | ||
118 | + | ||
119 | +This file describes the concepts needed by a namespace unification file | ||
120 | +system. | ||
121 | + | ||
122 | + | ||
123 | +Branch Priority: | ||
124 | +================ | ||
125 | + | ||
126 | +Each branch is assigned a unique priority - starting from 0 (highest | ||
127 | +priority). No two branches can have the same priority. | ||
128 | + | ||
129 | + | ||
130 | +Branch Mode: | ||
131 | +============ | ||
132 | + | ||
133 | +Each branch is assigned a mode - read-write or read-only. This allows | ||
134 | +directories on media mounted read-write to be used in a read-only manner. | ||
135 | + | ||
136 | + | ||
137 | +Whiteouts: | ||
138 | +========== | ||
139 | + | ||
140 | +A whiteout removes a file name from the namespace. Whiteouts are needed when | ||
141 | +one attempts to remove a file on a read-only branch. | ||
142 | + | ||
143 | +Suppose we have a two-branch union, where branch 0 is read-write and branch | ||
144 | +1 is read-only. And a file 'foo' on branch 1: | ||
145 | + | ||
146 | +./b0/ | ||
147 | +./b1/ | ||
148 | +./b1/foo | ||
149 | + | ||
150 | +The unified view would simply be: | ||
151 | + | ||
152 | +./union/ | ||
153 | +./union/foo | ||
154 | + | ||
155 | +Since 'foo' is stored on a read-only branch, it cannot be removed. A | ||
156 | +whiteout is used to remove the name 'foo' from the unified namespace. Again, | ||
157 | +since branch 1 is read-only, the whiteout cannot be created there. So, we | ||
158 | +try on a higher priority (lower numerically) branch and create the whiteout | ||
159 | +there. | ||
160 | + | ||
161 | +./b0/ | ||
162 | +./b0/.wh.foo | ||
163 | +./b1/ | ||
164 | +./b1/foo | ||
165 | + | ||
166 | +Later, when Unionfs traverses branches (due to lookup or readdir), it | ||
167 | +eliminate 'foo' from the namespace (as well as the whiteout itself.) | ||
168 | + | ||
169 | + | ||
170 | +Opaque Directories: | ||
171 | +=================== | ||
172 | + | ||
173 | +Assume we have a unionfs mount comprising of two branches. Branch 0 is | ||
174 | +empty; branch 1 has the directory /a and file /a/f. Let's say we mount a | ||
175 | +union of branch 0 as read-write and branch 1 as read-only. Now, let's say | ||
176 | +we try to perform the following operation in the union: | ||
177 | + | ||
178 | + rm -fr a | ||
179 | + | ||
180 | +Because branch 1 is not writable, we cannot physically remove the file /a/f | ||
181 | +or the directory /a. So instead, we will create a whiteout in branch 0 | ||
182 | +named /.wh.a, masking out the name "a" from branch 1. Next, let's say we | ||
183 | +try to create a directory named "a" as follows: | ||
184 | + | ||
185 | + mkdir a | ||
186 | + | ||
187 | +Because we have a whiteout for "a" already, Unionfs behaves as if "a" | ||
188 | +doesn't exist, and thus will delete the whiteout and replace it with an | ||
189 | +actual directory named "a". | ||
190 | + | ||
191 | +The problem now is that if you try to "ls" in the union, Unionfs will | ||
192 | +perform is normal directory name unification, for *all* directories named | ||
193 | +"a" in all branches. This will cause the file /a/f from branch 1 to | ||
194 | +re-appear in the union's namespace, which violates Unix semantics. | ||
195 | + | ||
196 | +To avoid this problem, we have a different form of whiteouts for | ||
197 | +directories, called "opaque directories" (same as BSD Union Mount does). | ||
198 | +Whenever we replace a whiteout with a directory, that directory is marked as | ||
199 | +opaque. In Unionfs 2.x, it means that we create a file named | ||
200 | +/a/.wh.__dir_opaque in branch 0, after having created directory /a there. | ||
201 | +When unionfs notices that a directory is opaque, it stops all namespace | ||
202 | +operations (including merging readdir contents) at that opaque directory. | ||
203 | +This prevents re-exposing names from masked out directories. | ||
204 | + | ||
205 | + | ||
206 | +Duplicate Elimination: | ||
207 | +====================== | ||
208 | + | ||
209 | +It is possible for files on different branches to have the same name. | ||
210 | +Unionfs then has to select which instance of the file to show to the user. | ||
211 | +Given the fact that each branch has a priority associated with it, the | ||
212 | +simplest solution is to take the instance from the highest priority | ||
213 | +(numerically lowest value) and "hide" the others. | ||
214 | + | ||
215 | + | ||
216 | +Unlinking: | ||
217 | +========= | ||
218 | + | ||
219 | +Unlink operation on non-directory instances is optimized to remove the | ||
220 | +maximum possible objects in case multiple underlying branches have the same | ||
221 | +file name. The unlink operation will first try to delete file instances | ||
222 | +from highest priority branch and then move further to delete from remaining | ||
223 | +branches in order of their decreasing priority. Consider a case (F..D..F), | ||
224 | +where F is a file and D is a directory of the same name; here, some | ||
225 | +intermediate branch could have an empty directory instance with the same | ||
226 | +name, so this operation also tries to delete this directory instance and | ||
227 | +proceed further to delete from next possible lower priority branch. The | ||
228 | +unionfs unlink operation will smoothly delete the files with same name from | ||
229 | +all possible underlying branches. In case if some error occurs, it creates | ||
230 | +whiteout in highest priority branch that will hide file instance in rest of | ||
231 | +the branches. An error could occur either if an unlink operations in any of | ||
232 | +the underlying branch failed or if a branch has no write permission. | ||
233 | + | ||
234 | +This unlinking policy is known as "delete all" and it has the benefit of | ||
235 | +overall reducing the number of inodes used by duplicate files, and further | ||
236 | +reducing the total number of inodes consumed by whiteouts. The cost is of | ||
237 | +extra processing, but testing shows this extra processing is well worth the | ||
238 | +savings. | ||
239 | + | ||
240 | + | ||
241 | +Copyup: | ||
242 | +======= | ||
243 | + | ||
244 | +When a change is made to the contents of a file's data or meta-data, they | ||
245 | +have to be stored somewhere. The best way is to create a copy of the | ||
246 | +original file on a branch that is writable, and then redirect the write | ||
247 | +though to this copy. The copy must be made on a higher priority branch so | ||
248 | +that lookup and readdir return this newer "version" of the file rather than | ||
249 | +the original (see duplicate elimination). | ||
250 | + | ||
251 | +An entire unionfs mount can be read-only or read-write. If it's read-only, | ||
252 | +then none of the branches will be written to, even if some of the branches | ||
253 | +are physically writeable. If the unionfs mount is read-write, then the | ||
254 | +leftmost (highest priority) branch must be writeable (for copyup to take | ||
255 | +place); the remaining branches can be any mix of read-write and read-only. | ||
256 | + | ||
257 | +In a writeable mount, unionfs will create new files/dir in the leftmost | ||
258 | +branch. If one tries to modify a file in a read-only branch/media, unionfs | ||
259 | +will copyup the file to the leftmost branch and modify it there. If you try | ||
260 | +to modify a file from a writeable branch which is not the leftmost branch, | ||
261 | +then unionfs will modify it in that branch; this is useful if you, say, | ||
262 | +unify differnet packages (e.g., apache, sendmail, ftpd, etc.) and you want | ||
263 | +changes to specific package files to remain logically in the directory where | ||
264 | +they came from. | ||
265 | + | ||
266 | +Cache Coherency: | ||
267 | +================ | ||
268 | + | ||
269 | +Unionfs users often want to be able to modify files and directories directly | ||
270 | +on the lower branches, and have those changes be visible at the Unionfs | ||
271 | +level. This means that data (e.g., pages) and meta-data (dentries, inodes, | ||
272 | +open files, etc.) have to be synchronized between the upper and lower | ||
273 | +layers. In other words, the newest changes from a layer below have to be | ||
274 | +propagated to the Unionfs layer above. If the two layers are not in sync, a | ||
275 | +cache incoherency ensues, which could lead to application failures and even | ||
276 | +oopses. The Linux kernel, however, has a rather limited set of mechanisms | ||
277 | +to ensure this inter-layer cache coherency---so Unionfs has to do most of | ||
278 | +the hard work on its own. | ||
279 | + | ||
280 | +Maintaining Invariants: | ||
281 | + | ||
282 | +The way Unionfs ensures cache coherency is as follows. At each entry point | ||
283 | +to a Unionfs file system method, we call a utility function to validate the | ||
284 | +primary objects of this method. Generally, we call unionfs_file_revalidate | ||
285 | +on open files, and __unionfs_d_revalidate_chain on dentries (which also | ||
286 | +validates inodes). These utility functions check to see whether the upper | ||
287 | +Unionfs object is in sync with any of the lower objects that it represents. | ||
288 | +The checks we perform include whether the Unionfs superblock has a newer | ||
289 | +generation number, or if any of the lower objects mtime's or ctime's are | ||
290 | +newer. (Note: generation numbers change when branch-management commands are | ||
291 | +issued, so in a way, maintaining cache coherency is also very important for | ||
292 | +branch-management.) If indeed we determine that any Unionfs object is no | ||
293 | +longer in sync with its lower counterparts, then we rebuild that object | ||
294 | +similarly to how we do so for branch-management. | ||
295 | + | ||
296 | +While rebuilding Unionfs's objects, we also purge any page mappings and | ||
297 | +truncate inode pages (see fs/unionfs/dentry.c:purge_inode_data). This is to | ||
298 | +ensure that Unionfs will re-get the newer data from the lower branches. We | ||
299 | +perform this purging only if the Unionfs operation in question is a reading | ||
300 | +operation; if Unionfs is performing a data writing operation (e.g., ->write, | ||
301 | +->commit_write, etc.) then we do NOT flush the lower mappings/pages: this is | ||
302 | +because (1) a self-deadlock could occur and (2) the upper Unionfs pages are | ||
303 | +considered more authoritative anyway, as they are newer and will overwrite | ||
304 | +any lower pages. | ||
305 | + | ||
306 | +Unionfs maintains the following important invariant regarding mtime's, | ||
307 | +ctime's, and atime's: the upper inode object's times are the max() of all of | ||
308 | +the lower ones. For non-directory objects, there's only one object below, | ||
309 | +so the mapping is simple; for directory objects, there could me multiple | ||
310 | +lower objects and we have to sync up with the newest one of all the lower | ||
311 | +ones. This invariant is important to maintain, especially for directories | ||
312 | +(besides, we need this to be POSIX compliant). A union could comprise | ||
313 | +multiple writable branches, each of which could change. If we don't reflect | ||
314 | +the newest possible mtime/ctime, some applications could fail. For example, | ||
315 | +NFSv2/v3 exports check for newer directory mtimes on the server to determine | ||
316 | +if the client-side attribute cache should be purged. | ||
317 | + | ||
318 | +To maintain these important invariants, of course, Unionfs carefully | ||
319 | +synchronizes upper and lower times in various places. For example, if we | ||
320 | +copy-up a file to a top-level branch, the parent directory where the file | ||
321 | +was copied up to will now have a new mtime: so after a successful copy-up, | ||
322 | +we sync up with the new top-level branch's parent directory mtime. | ||
323 | + | ||
324 | +Implementation: | ||
325 | + | ||
326 | +This cache-coherency implementation is efficient because it defers any | ||
327 | +synchronizing between the upper and lower layers until absolutely needed. | ||
328 | +Consider the example a common situation where users perform a lot of lower | ||
329 | +changes, such as untarring a whole package. While these take place, | ||
330 | +typically the user doesn't access the files via Unionfs; only after the | ||
331 | +lower changes are done, does the user try to access the lower files. With | ||
332 | +our cache-coherency implementation, the entirety of the changes to the lower | ||
333 | +branches will not result in a single CPU cycle spent at the Unionfs level | ||
334 | +until the user invokes a system call that goes through Unionfs. | ||
335 | + | ||
336 | +We have considered two alternate cache-coherency designs. (1) Using the | ||
337 | +dentry/inode notify functionality to register interest in finding out about | ||
338 | +any lower changes. This is a somewhat limited and also a heavy-handed | ||
339 | +approach which could result in many notifications to the Unionfs layer upon | ||
340 | +each small change at the lower layer (imagine a file being modified multiple | ||
341 | +times in rapid succession). (2) Rewriting the VFS to support explicit | ||
342 | +callbacks from lower objects to upper objects. We began exploring such an | ||
343 | +implementation, but found it to be very complicated--it would have resulted | ||
344 | +in massive VFS/MM changes which are unlikely to be accepted by the LKML | ||
345 | +community. We therefore believe that our current cache-coherency design and | ||
346 | +implementation represent the best approach at this time. | ||
347 | + | ||
348 | +Limitations: | ||
349 | + | ||
350 | +Our implementation works in that as long as a user process will have caused | ||
351 | +Unionfs to be called, directly or indirectly, even to just do | ||
352 | +->d_revalidate; then we will have purged the current Unionfs data and the | ||
353 | +process will see the new data. For example, a process that continually | ||
354 | +re-reads the same file's data will see the NEW data as soon as the lower | ||
355 | +file had changed, upon the next read(2) syscall (even if the file is still | ||
356 | +open!) However, this doesn't work when the process re-reads the open file's | ||
357 | +data via mmap(2) (unless the user unmaps/closes the file and remaps/reopens | ||
358 | +it). Once we respond to ->readpage(s), then the kernel maps the page into | ||
359 | +the process's address space and there doesn't appear to be a way to force | ||
360 | +the kernel to invalidate those pages/mappings, and force the process to | ||
361 | +re-issue ->readpage. If there's a way to invalidate active mappings and | ||
362 | +force a ->readpage, let us know please (invalidate_inode_pages2 doesn't do | ||
363 | +the trick). | ||
364 | + | ||
365 | +Our current Unionfs code has to perform many file-revalidation calls. It | ||
366 | +would be really nice if the VFS would export an optional file system hook | ||
367 | +->file_revalidate (similarly to dentry->d_revalidate) that will be called | ||
368 | +before each VFS op that has a "struct file" in it. | ||
369 | + | ||
370 | +Certain file systems have micro-second granularity (or better) for inode | ||
371 | +times, and asynchronous actions could cause those times to change with some | ||
372 | +small delay. In such cases, Unionfs may see a changed inode time that only | ||
373 | +differs by a tiny fraction of a second: such a change may be a false | ||
374 | +positive indication that the lower object has changed, whereas if unionfs | ||
375 | +waits a little longer, that false indication will not be seen. (These false | ||
376 | +positives are harmless, because they would at most cause unionfs to | ||
377 | +re-validate an object that may need no revalidation, and print a debugging | ||
378 | +message that clutters the console/logs.) Therefore, to minimize the chances | ||
379 | +of these situations, we delay the detection of changed times by a small | ||
380 | +factor of a few seconds, called UNIONFS_MIN_CC_TIME (which defaults to 3 | ||
381 | +seconds, as does NFS). This means that we will detect the change, only a | ||
382 | +couple of seconds later, if indeed the time change persists in the lower | ||
383 | +file object. This delayed detection has an added performance benefit: we | ||
384 | +reduce the number of times that unionfs has to revalidate objects, in case | ||
385 | +there's a lot of concurrent activity on both the upper and lower objects, | ||
386 | +for the same file(s). Lastly, this delayed time attribute detection is | ||
387 | +similar to how NFS clients operate (e.g., acregmin). | ||
388 | + | ||
389 | +Finally, there is no way currently in Linux to prevent lower directories | ||
390 | +from being moved around (i.e., topology changes); there's no way to prevent | ||
391 | +modifications to directory sub-trees of whole file systems which are mounted | ||
392 | +read-write. It is therefore possible for in-flight operations in unionfs to | ||
393 | +take place, while a lower directory is being moved around. Therefore, if | ||
394 | +you try to, say, create a new file in a directory through unionfs, while the | ||
395 | +directory is being moved around directly, then the new file may get created | ||
396 | +in the new location where that directory was moved to. This is a somewhat | ||
397 | +similar behaviour in NFS: an NFS client could be creating a new file while | ||
398 | +th NFS server is moving th directory around; the file will get successfully | ||
399 | +created in the new location. (The one exception in unionfs is that if the | ||
400 | +branch is marked read-only by unionfs, then a copyup will take place.) | ||
401 | + | ||
402 | +For more information, see <http://unionfs.filesystems.org/>. | ||
403 | diff --git a/Documentation/filesystems/unionfs/issues.txt b/Documentation/filesystems/unionfs/issues.txt | ||
404 | new file mode 100644 | ||
405 | index 0000000..f4b7e7e | ||
406 | --- /dev/null | ||
407 | +++ b/Documentation/filesystems/unionfs/issues.txt | ||
408 | @@ -0,0 +1,28 @@ | ||
409 | +KNOWN Unionfs 2.x ISSUES: | ||
410 | +========================= | ||
411 | + | ||
412 | +1. Unionfs should not use lookup_one_len() on the underlying f/s as it | ||
413 | + confuses NFSv4. Currently, unionfs_lookup() passes lookup intents to the | ||
414 | + lower file-system, this eliminates part of the problem. The remaining | ||
415 | + calls to lookup_one_len may need to be changed to pass an intent. We are | ||
416 | + currently introducing VFS changes to fs/namei.c's do_path_lookup() to | ||
417 | + allow proper file lookup and opening in stackable file systems. | ||
418 | + | ||
419 | +2. Lockdep (a debugging feature) isn't aware of stacking, and so it | ||
420 | + incorrectly complains about locking problems. The problem boils down to | ||
421 | + this: Lockdep considers all objects of a certain type to be in the same | ||
422 | + class, for example, all inodes. Lockdep doesn't like to see a lock held | ||
423 | + on two inodes within the same task, and warns that it could lead to a | ||
424 | + deadlock. However, stackable file systems do precisely that: they lock | ||
425 | + an upper object, and then a lower object, in a strict order to avoid | ||
426 | + locking problems; in addition, Unionfs, as a fan-out file system, may | ||
427 | + have to lock several lower inodes. We are currently looking into Lockdep | ||
428 | + to see how to make it aware of stackable file systems. For now, we | ||
429 | + temporarily disable lockdep when calling vfs methods on lower objects, | ||
430 | + but only for those places where lockdep complained. While this solution | ||
431 | + may seem unclean, it is not without precedent: other places in the kernel | ||
432 | + also do similar temporary disabling, of course after carefully having | ||
433 | + checked that it is the right thing to do. Anyway, you get any warnings | ||
434 | + from Lockdep, please report them to the Unionfs maintainers. | ||
435 | + | ||
436 | +For more information, see <http://unionfs.filesystems.org/>. | ||
437 | diff --git a/Documentation/filesystems/unionfs/rename.txt b/Documentation/filesystems/unionfs/rename.txt | ||
438 | new file mode 100644 | ||
439 | index 0000000..e20bb82 | ||
440 | --- /dev/null | ||
441 | +++ b/Documentation/filesystems/unionfs/rename.txt | ||
442 | @@ -0,0 +1,31 @@ | ||
443 | +Rename is a complex beast. The following table shows which rename(2) operations | ||
444 | +should succeed and which should fail. | ||
445 | + | ||
446 | +o: success | ||
447 | +E: error (either unionfs or vfs) | ||
448 | +X: EXDEV | ||
449 | + | ||
450 | +none = file does not exist | ||
451 | +file = file is a file | ||
452 | +dir = file is a empty directory | ||
453 | +child= file is a non-empty directory | ||
454 | +wh = file is a directory containing only whiteouts; this makes it logically | ||
455 | + empty | ||
456 | + | ||
457 | + none file dir child wh | ||
458 | +file o o E E E | ||
459 | +dir o E o E o | ||
460 | +child X E X E X | ||
461 | +wh o E o E o | ||
462 | + | ||
463 | + | ||
464 | +Renaming directories: | ||
465 | +===================== | ||
466 | + | ||
467 | +Whenever a empty (either physically or logically) directory is being renamed, | ||
468 | +the following sequence of events should take place: | ||
469 | + | ||
470 | +1) Remove whiteouts from both source and destination directory | ||
471 | +2) Rename source to destination | ||
472 | +3) Make destination opaque to prevent anything under it from showing up | ||
473 | + | ||
474 | diff --git a/Documentation/filesystems/unionfs/usage.txt b/Documentation/filesystems/unionfs/usage.txt | ||
475 | new file mode 100644 | ||
476 | index 0000000..1adde69 | ||
477 | --- /dev/null | ||
478 | +++ b/Documentation/filesystems/unionfs/usage.txt | ||
479 | @@ -0,0 +1,134 @@ | ||
480 | +Unionfs is a stackable unification file system, which can appear to merge | ||
481 | +the contents of several directories (branches), while keeping their physical | ||
482 | +content separate. Unionfs is useful for unified source tree management, | ||
483 | +merged contents of split CD-ROM, merged separate software package | ||
484 | +directories, data grids, and more. Unionfs allows any mix of read-only and | ||
485 | +read-write branches, as well as insertion and deletion of branches anywhere | ||
486 | +in the fan-out. To maintain Unix semantics, Unionfs handles elimination of | ||
487 | +duplicates, partial-error conditions, and more. | ||
488 | + | ||
489 | +GENERAL SYNTAX | ||
490 | +============== | ||
491 | + | ||
492 | +# mount -t unionfs -o <OPTIONS>,<BRANCH-OPTIONS> none MOUNTPOINT | ||
493 | + | ||
494 | +OPTIONS can be any legal combination of: | ||
495 | + | ||
496 | +- ro # mount file system read-only | ||
497 | +- rw # mount file system read-write | ||
498 | +- remount # remount the file system (see Branch Management below) | ||
499 | +- incgen # increment generation no. (see Cache Consistency below) | ||
500 | + | ||
501 | +BRANCH-OPTIONS can be either (1) a list of branches given to the "dirs=" | ||
502 | +option, or (2) a list of individual branch manipulation commands, combined | ||
503 | +with the "remount" option, and is further described in the "Branch | ||
504 | +Management" section below. | ||
505 | + | ||
506 | +The syntax for the "dirs=" mount option is: | ||
507 | + | ||
508 | + dirs=branch[=ro|=rw][:...] | ||
509 | + | ||
510 | +The "dirs=" option takes a colon-delimited list of directories to compose | ||
511 | +the union, with an optional branch mode for each of those directories. | ||
512 | +Directories that come earlier (specified first, on the left) in the list | ||
513 | +have a higher precedence than those which come later. Additionally, | ||
514 | +read-only or read-write permissions of the branch can be specified by | ||
515 | +appending =ro or =rw (default) to each directory. See the Copyup section in | ||
516 | +concepts.txt, for a description of Unionfs's behavior when mixing read-only | ||
517 | +and read-write branches and mounts. | ||
518 | + | ||
519 | +Syntax: | ||
520 | + | ||
521 | + dirs=/branch1[=ro|=rw]:/branch2[=ro|=rw]:...:/branchN[=ro|=rw] | ||
522 | + | ||
523 | +Example: | ||
524 | + | ||
525 | + dirs=/writable_branch=rw:/read-only_branch=ro | ||
526 | + | ||
527 | + | ||
528 | +BRANCH MANAGEMENT | ||
529 | +================= | ||
530 | + | ||
531 | +Once you mount your union for the first time, using the "dirs=" option, you | ||
532 | +can then change the union's overall mode or reconfigure the branches, using | ||
533 | +the remount option, as follows. | ||
534 | + | ||
535 | +To downgrade a union from read-write to read-only: | ||
536 | + | ||
537 | +# mount -t unionfs -o remount,ro none MOUNTPOINT | ||
538 | + | ||
539 | +To upgrade a union from read-only to read-write: | ||
540 | + | ||
541 | +# mount -t unionfs -o remount,rw none MOUNTPOINT | ||
542 | + | ||
543 | +To delete a branch /foo, regardless where it is in the current union: | ||
544 | + | ||
545 | +# mount -t unionfs -o remount,del=/foo none MOUNTPOINT | ||
546 | + | ||
547 | +To insert (add) a branch /foo before /bar: | ||
548 | + | ||
549 | +# mount -t unionfs -o remount,add=/bar:/foo none MOUNTPOINT | ||
550 | + | ||
551 | +To insert (add) a branch /foo (with the "rw" mode flag) before /bar: | ||
552 | + | ||
553 | +# mount -t unionfs -o remount,add=/bar:/foo=rw none MOUNTPOINT | ||
554 | + | ||
555 | +To insert (add) a branch /foo (in "rw" mode) at the very beginning (i.e., a | ||
556 | +new highest-priority branch), you can use the above syntax, or use a short | ||
557 | +hand version as follows: | ||
558 | + | ||
559 | +# mount -t unionfs -o remount,add=/foo none MOUNTPOINT | ||
560 | + | ||
561 | +To append a branch to the very end (new lowest-priority branch): | ||
562 | + | ||
563 | +# mount -t unionfs -o remount,add=:/foo none MOUNTPOINT | ||
564 | + | ||
565 | +To append a branch to the very end (new lowest-priority branch), in | ||
566 | +read-only mode: | ||
567 | + | ||
568 | +# mount -t unionfs -o remount,add=:/foo=ro none MOUNTPOINT | ||
569 | + | ||
570 | +Finally, to change the mode of one existing branch, say /foo, from read-only | ||
571 | +to read-write, and change /bar from read-write to read-only: | ||
572 | + | ||
573 | +# mount -t unionfs -o remount,mode=/foo=rw,mode=/bar=ro none MOUNTPOINT | ||
574 | + | ||
575 | +Note: in Unionfs 2.x, you cannot set the leftmost branch to readonly because | ||
576 | +then Unionfs won't have any writable place for copyups to take place. | ||
577 | +Moreover, the VFS can get confused when it tries to modify something in a | ||
578 | +file system mounted read-write, but isn't permitted to write to it. | ||
579 | +Instead, you should set the whole union as readonly, as described above. | ||
580 | +If, however, you must set the leftmost branch as readonly, perhaps so you | ||
581 | +can get a snapshot of it at a point in time, then you should insert a new | ||
582 | +writable top-level branch, and mark the one you want as readonly. This can | ||
583 | +be accomplished as follows, assuming that /foo is your current leftmost | ||
584 | +branch: | ||
585 | + | ||
586 | +# mount -t tmpfs -o size=NNN /new | ||
587 | +# mount -t unionfs -o remount,add=/new,mode=/foo=ro none MOUNTPOINT | ||
588 | +<do what you want safely in /foo> | ||
589 | +# mount -t unionfs -o remount,del=/new,mode=/foo=rw none MOUNTPOINT | ||
590 | +<check if there's anything in /new you want to preserve> | ||
591 | +# umount /new | ||
592 | + | ||
593 | +CACHE CONSISTENCY | ||
594 | +================= | ||
595 | + | ||
596 | +If you modify any file on any of the lower branches directly, while there is | ||
597 | +a Unionfs 2.x mounted above any of those branches, you should tell Unionfs | ||
598 | +to purge its caches and re-get the objects. To do that, you have to | ||
599 | +increment the generation number of the superblock using the following | ||
600 | +command: | ||
601 | + | ||
602 | +# mount -t unionfs -o remount,incgen none MOUNTPOINT | ||
603 | + | ||
604 | +Note that the older way of incrementing the generation number using an | ||
605 | +ioctl, is no longer supported in Unionfs 2.0 and newer. Ioctls in general | ||
606 | +are not encouraged. Plus, an ioctl is per-file concept, whereas the | ||
607 | +generation number is a per-file-system concept. Worse, such an ioctl | ||
608 | +requires an open file, which then has to be invalidated by the very nature | ||
609 | +of the generation number increase (read: the old generation increase ioctl | ||
610 | +was pretty racy). | ||
611 | + | ||
612 | + | ||
613 | +For more information, see <http://unionfs.filesystems.org/>. | ||
614 | diff --git a/MAINTAINERS b/MAINTAINERS | ||
615 | index 69f19f1..fd88a30 100644 | ||
616 | --- a/MAINTAINERS | ||
617 | +++ b/MAINTAINERS | ||
618 | @@ -6319,6 +6319,14 @@ F: Documentation/cdrom/ | ||
619 | F: drivers/cdrom/cdrom.c | ||
620 | F: include/linux/cdrom.h | ||
621 | |||
622 | +UNIONFS | ||
623 | +P: Erez Zadok | ||
624 | +M: ezk@cs.sunysb.edu | ||
625 | +L: unionfs@filesystems.org | ||
626 | +W: http://unionfs.filesystems.org/ | ||
627 | +T: git git.kernel.org/pub/scm/linux/kernel/git/ezk/unionfs.git | ||
628 | +S: Maintained | ||
629 | + | ||
630 | UNSORTED BLOCK IMAGES (UBI) | ||
631 | M: Artem Bityutskiy <dedekind1@gmail.com> | ||
632 | W: http://www.linux-mtd.infradead.org/ | ||
633 | diff --git a/fs/Kconfig b/fs/Kconfig | ||
634 | index f3aa9b0..0e6182c 100644 | ||
635 | --- a/fs/Kconfig | ||
636 | +++ b/fs/Kconfig | ||
637 | @@ -170,6 +170,7 @@ if MISC_FILESYSTEMS | ||
638 | source "fs/adfs/Kconfig" | ||
639 | source "fs/affs/Kconfig" | ||
640 | source "fs/ecryptfs/Kconfig" | ||
641 | +source "fs/unionfs/Kconfig" | ||
642 | source "fs/hfs/Kconfig" | ||
643 | source "fs/hfsplus/Kconfig" | ||
644 | source "fs/befs/Kconfig" | ||
645 | diff --git a/fs/Makefile b/fs/Makefile | ||
646 | index fb68c2b..8ca9290 100644 | ||
647 | --- a/fs/Makefile | ||
648 | +++ b/fs/Makefile | ||
649 | @@ -83,6 +83,7 @@ obj-$(CONFIG_ISO9660_FS) += isofs/ | ||
650 | obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+ | ||
651 | obj-$(CONFIG_HFS_FS) += hfs/ | ||
652 | obj-$(CONFIG_ECRYPT_FS) += ecryptfs/ | ||
653 | +obj-$(CONFIG_UNION_FS) += unionfs/ | ||
654 | obj-$(CONFIG_VXFS_FS) += freevxfs/ | ||
655 | obj-$(CONFIG_NFS_FS) += nfs/ | ||
656 | obj-$(CONFIG_EXPORTFS) += exportfs/ | ||
657 | diff --git a/fs/namei.c b/fs/namei.c | ||
658 | index e3c4f11..d9f99a4 100644 | ||
659 | --- a/fs/namei.c | ||
660 | +++ b/fs/namei.c | ||
661 | @@ -578,6 +578,7 @@ void release_open_intent(struct nameidata *nd) | ||
662 | fput(file); | ||
663 | } | ||
664 | } | ||
665 | +EXPORT_SYMBOL_GPL(release_open_intent); | ||
666 | |||
667 | static inline int d_revalidate(struct dentry *dentry, struct nameidata *nd) | ||
668 | { | ||
669 | @@ -1819,6 +1820,42 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) | ||
670 | return __lookup_hash(&this, base, NULL); | ||
671 | } | ||
672 | |||
673 | +/* pass nameidata from caller (useful for NFS) */ | ||
674 | +struct dentry *lookup_one_len_nd(const char *name, struct dentry *base, | ||
675 | + int len, struct nameidata *nd) | ||
676 | +{ | ||
677 | + struct qstr this; | ||
678 | + unsigned long hash; | ||
679 | + unsigned int c; | ||
680 | + | ||
681 | + WARN_ON_ONCE(!mutex_is_locked(&base->d_inode->i_mutex)); | ||
682 | + | ||
683 | + this.name = name; | ||
684 | + this.len = len; | ||
685 | + if (!len) | ||
686 | + return ERR_PTR(-EACCES); | ||
687 | + | ||
688 | + hash = init_name_hash(); | ||
689 | + while (len--) { | ||
690 | + c = *(const unsigned char *)name++; | ||
691 | + if (c == '/' || c == '\0') | ||
692 | + return ERR_PTR(-EACCES); | ||
693 | + hash = partial_name_hash(c, hash); | ||
694 | + } | ||
695 | + this.hash = end_name_hash(hash); | ||
696 | + /* | ||
697 | + * See if the low-level filesystem might want | ||
698 | + * to use its own hash.. | ||
699 | + */ | ||
700 | + if (base->d_flags & DCACHE_OP_HASH) { | ||
701 | + int err = base->d_op->d_hash(base, base->d_inode, &this); | ||
702 | + if (err < 0) | ||
703 | + return ERR_PTR(err); | ||
704 | + } | ||
705 | + | ||
706 | + return __lookup_hash(&this, base, nd); | ||
707 | +} | ||
708 | + | ||
709 | int user_path_at(int dfd, const char __user *name, unsigned flags, | ||
710 | struct path *path) | ||
711 | { | ||
712 | @@ -3422,6 +3459,7 @@ EXPORT_SYMBOL(get_write_access); /* binfmt_aout */ | ||
713 | EXPORT_SYMBOL(getname); | ||
714 | EXPORT_SYMBOL(lock_rename); | ||
715 | EXPORT_SYMBOL(lookup_one_len); | ||
716 | +EXPORT_SYMBOL(lookup_one_len_nd); | ||
717 | EXPORT_SYMBOL(page_follow_link_light); | ||
718 | EXPORT_SYMBOL(page_put_link); | ||
719 | EXPORT_SYMBOL(page_readlink); | ||
720 | diff --git a/fs/splice.c b/fs/splice.c | ||
721 | index 50a5d97..a3af841 100644 | ||
722 | --- a/fs/splice.c | ||
723 | +++ b/fs/splice.c | ||
724 | @@ -1081,8 +1081,8 @@ EXPORT_SYMBOL(generic_splice_sendpage); | ||
725 | /* | ||
726 | * Attempt to initiate a splice from pipe to file. | ||
727 | */ | ||
728 | -static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, | ||
729 | - loff_t *ppos, size_t len, unsigned int flags) | ||
730 | +long vfs_splice_from(struct pipe_inode_info *pipe, struct file *out, | ||
731 | + loff_t *ppos, size_t len, unsigned int flags) | ||
732 | { | ||
733 | ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, | ||
734 | loff_t *, size_t, unsigned int); | ||
735 | @@ -1105,13 +1105,14 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, | ||
736 | |||
737 | return splice_write(pipe, out, ppos, len, flags); | ||
738 | } | ||
739 | +EXPORT_SYMBOL_GPL(vfs_splice_from); | ||
740 | |||
741 | /* | ||
742 | * Attempt to initiate a splice from a file to a pipe. | ||
743 | */ | ||
744 | -static long do_splice_to(struct file *in, loff_t *ppos, | ||
745 | - struct pipe_inode_info *pipe, size_t len, | ||
746 | - unsigned int flags) | ||
747 | +long vfs_splice_to(struct file *in, loff_t *ppos, | ||
748 | + struct pipe_inode_info *pipe, size_t len, | ||
749 | + unsigned int flags) | ||
750 | { | ||
751 | ssize_t (*splice_read)(struct file *, loff_t *, | ||
752 | struct pipe_inode_info *, size_t, unsigned int); | ||
753 | @@ -1131,6 +1132,7 @@ static long do_splice_to(struct file *in, loff_t *ppos, | ||
754 | |||
755 | return splice_read(in, ppos, pipe, len, flags); | ||
756 | } | ||
757 | +EXPORT_SYMBOL_GPL(vfs_splice_to); | ||
758 | |||
759 | /** | ||
760 | * splice_direct_to_actor - splices data directly between two non-pipes | ||
761 | @@ -1200,7 +1202,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, | ||
762 | size_t read_len; | ||
763 | loff_t pos = sd->pos, prev_pos = pos; | ||
764 | |||
765 | - ret = do_splice_to(in, &pos, pipe, len, flags); | ||
766 | + ret = vfs_splice_to(in, &pos, pipe, len, flags); | ||
767 | if (unlikely(ret <= 0)) | ||
768 | goto out_release; | ||
769 | |||
770 | @@ -1259,8 +1261,8 @@ static int direct_splice_actor(struct pipe_inode_info *pipe, | ||
771 | { | ||
772 | struct file *file = sd->u.file; | ||
773 | |||
774 | - return do_splice_from(pipe, file, &file->f_pos, sd->total_len, | ||
775 | - sd->flags); | ||
776 | + return vfs_splice_from(pipe, file, &file->f_pos, sd->total_len, | ||
777 | + sd->flags); | ||
778 | } | ||
779 | |||
780 | /** | ||
781 | @@ -1345,7 +1347,7 @@ static long do_splice(struct file *in, loff_t __user *off_in, | ||
782 | } else | ||
783 | off = &out->f_pos; | ||
784 | |||
785 | - ret = do_splice_from(ipipe, out, off, len, flags); | ||
786 | + ret = vfs_splice_from(ipipe, out, off, len, flags); | ||
787 | |||
788 | if (off_out && copy_to_user(off_out, off, sizeof(loff_t))) | ||
789 | ret = -EFAULT; | ||
790 | @@ -1365,7 +1367,7 @@ static long do_splice(struct file *in, loff_t __user *off_in, | ||
791 | } else | ||
792 | off = &in->f_pos; | ||
793 | |||
794 | - ret = do_splice_to(in, off, opipe, len, flags); | ||
795 | + ret = vfs_splice_to(in, off, opipe, len, flags); | ||
796 | |||
797 | if (off_in && copy_to_user(off_in, off, sizeof(loff_t))) | ||
798 | ret = -EFAULT; | ||
799 | diff --git a/fs/stack.c b/fs/stack.c | ||
800 | index 4a6f7f4..7eeef12 100644 | ||
801 | --- a/fs/stack.c | ||
802 | +++ b/fs/stack.c | ||
803 | @@ -1,8 +1,20 @@ | ||
804 | +/* | ||
805 | + * Copyright (c) 2006-2009 Erez Zadok | ||
806 | + * Copyright (c) 2006-2007 Josef 'Jeff' Sipek | ||
807 | + * Copyright (c) 2006-2009 Stony Brook University | ||
808 | + * Copyright (c) 2006-2009 The Research Foundation of SUNY | ||
809 | + * | ||
810 | + * This program is free software; you can redistribute it and/or modify | ||
811 | + * it under the terms of the GNU General Public License version 2 as | ||
812 | + * published by the Free Software Foundation. | ||
813 | + */ | ||
814 | + | ||
815 | #include <linux/module.h> | ||
816 | #include <linux/fs.h> | ||
817 | #include <linux/fs_stack.h> | ||
818 | |||
819 | -/* does _NOT_ require i_mutex to be held. | ||
820 | +/* | ||
821 | + * does _NOT_ require i_mutex to be held. | ||
822 | * | ||
823 | * This function cannot be inlined since i_size_{read,write} is rather | ||
824 | * heavy-weight on 32-bit systems | ||
825 | diff --git a/fs/unionfs/Kconfig b/fs/unionfs/Kconfig | ||
826 | new file mode 100644 | ||
827 | index 0000000..f3c1ac4 | ||
828 | --- /dev/null | ||
829 | +++ b/fs/unionfs/Kconfig | ||
830 | @@ -0,0 +1,24 @@ | ||
831 | +config UNION_FS | ||
832 | + tristate "Union file system (EXPERIMENTAL)" | ||
833 | + depends on EXPERIMENTAL | ||
834 | + help | ||
835 | + Unionfs is a stackable unification file system, which appears to | ||
836 | + merge the contents of several directories (branches), while keeping | ||
837 | + their physical content separate. | ||
838 | + | ||
839 | + See <http://unionfs.filesystems.org> for details | ||
840 | + | ||
841 | +config UNION_FS_XATTR | ||
842 | + bool "Unionfs extended attributes" | ||
843 | + depends on UNION_FS | ||
844 | + help | ||
845 | + Extended attributes are name:value pairs associated with inodes by | ||
846 | + the kernel or by users (see the attr(5) manual page). | ||
847 | + | ||
848 | + If unsure, say N. | ||
849 | + | ||
850 | +config UNION_FS_DEBUG | ||
851 | + bool "Debug Unionfs" | ||
852 | + depends on UNION_FS | ||
853 | + help | ||
854 | + If you say Y here, you can turn on debugging output from Unionfs. | ||
855 | diff --git a/fs/unionfs/Makefile b/fs/unionfs/Makefile | ||
856 | new file mode 100644 | ||
857 | index 0000000..3e31847 | ||
858 | --- /dev/null | ||
859 | +++ b/fs/unionfs/Makefile | ||
860 | @@ -0,0 +1,17 @@ | ||
861 | +UNIONFS_VERSION="2.5.9 (for 2.6.39-rc5)" | ||
862 | + | ||
863 | +EXTRA_CFLAGS += -DUNIONFS_VERSION=\"$(UNIONFS_VERSION)\" | ||
864 | + | ||
865 | +obj-$(CONFIG_UNION_FS) += unionfs.o | ||
866 | + | ||
867 | +unionfs-y := subr.o dentry.o file.o inode.o main.o super.o \ | ||
868 | + rdstate.o copyup.o dirhelper.o rename.o unlink.o \ | ||
869 | + lookup.o commonfops.o dirfops.o sioq.o mmap.o whiteout.o | ||
870 | + | ||
871 | +unionfs-$(CONFIG_UNION_FS_XATTR) += xattr.o | ||
872 | + | ||
873 | +unionfs-$(CONFIG_UNION_FS_DEBUG) += debug.o | ||
874 | + | ||
875 | +ifeq ($(CONFIG_UNION_FS_DEBUG),y) | ||
876 | +EXTRA_CFLAGS += -DDEBUG | ||
877 | +endif | ||
878 | diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c | ||
879 | new file mode 100644 | ||
880 | index 0000000..9f63b1c | ||
881 | --- /dev/null | ||
882 | +++ b/fs/unionfs/commonfops.c | ||
883 | @@ -0,0 +1,898 @@ | ||
884 | +/* | ||
885 | + * Copyright (c) 2003-2011 Erez Zadok | ||
886 | + * Copyright (c) 2003-2006 Charles P. Wright | ||
887 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
888 | + * Copyright (c) 2005-2006 Junjiro Okajima | ||
889 | + * Copyright (c) 2005 Arun M. Krishnakumar | ||
890 | + * Copyright (c) 2004-2006 David P. Quigley | ||
891 | + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair | ||
892 | + * Copyright (c) 2003 Puja Gupta | ||
893 | + * Copyright (c) 2003 Harikesavan Krishnan | ||
894 | + * Copyright (c) 2003-2011 Stony Brook University | ||
895 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
896 | + * | ||
897 | + * This program is free software; you can redistribute it and/or modify | ||
898 | + * it under the terms of the GNU General Public License version 2 as | ||
899 | + * published by the Free Software Foundation. | ||
900 | + */ | ||
901 | + | ||
902 | +#include "union.h" | ||
903 | + | ||
904 | +/* | ||
905 | + * 1) Copyup the file | ||
906 | + * 2) Rename the file to '.unionfs<original inode#><counter>' - obviously | ||
907 | + * stolen from NFS's silly rename | ||
908 | + */ | ||
909 | +static int copyup_deleted_file(struct file *file, struct dentry *dentry, | ||
910 | + struct dentry *parent, int bstart, int bindex) | ||
911 | +{ | ||
912 | + static unsigned int counter; | ||
913 | + const int i_inosize = sizeof(dentry->d_inode->i_ino) * 2; | ||
914 | + const int countersize = sizeof(counter) * 2; | ||
915 | + const int nlen = sizeof(".unionfs") + i_inosize + countersize - 1; | ||
916 | + char name[nlen + 1]; | ||
917 | + int err; | ||
918 | + struct dentry *tmp_dentry = NULL; | ||
919 | + struct dentry *lower_dentry; | ||
920 | + struct dentry *lower_dir_dentry = NULL; | ||
921 | + | ||
922 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bstart); | ||
923 | + | ||
924 | + sprintf(name, ".unionfs%*.*lx", | ||
925 | + i_inosize, i_inosize, lower_dentry->d_inode->i_ino); | ||
926 | + | ||
927 | + /* | ||
928 | + * Loop, looking for an unused temp name to copyup to. | ||
929 | + * | ||
930 | + * It's somewhat silly that we look for a free temp tmp name in the | ||
931 | + * source branch (bstart) instead of the dest branch (bindex), where | ||
932 | + * the final name will be created. We _will_ catch it if somehow | ||
933 | + * the name exists in the dest branch, but it'd be nice to catch it | ||
934 | + * sooner than later. | ||
935 | + */ | ||
936 | +retry: | ||
937 | + tmp_dentry = NULL; | ||
938 | + do { | ||
939 | + char *suffix = name + nlen - countersize; | ||
940 | + | ||
941 | + dput(tmp_dentry); | ||
942 | + counter++; | ||
943 | + sprintf(suffix, "%*.*x", countersize, countersize, counter); | ||
944 | + | ||
945 | + pr_debug("unionfs: trying to rename %s to %s\n", | ||
946 | + dentry->d_name.name, name); | ||
947 | + | ||
948 | + tmp_dentry = lookup_lck_len(name, lower_dentry->d_parent, | ||
949 | + nlen); | ||
950 | + if (IS_ERR(tmp_dentry)) { | ||
951 | + err = PTR_ERR(tmp_dentry); | ||
952 | + goto out; | ||
953 | + } | ||
954 | + } while (tmp_dentry->d_inode != NULL); /* need negative dentry */ | ||
955 | + dput(tmp_dentry); | ||
956 | + | ||
957 | + err = copyup_named_file(parent->d_inode, file, name, bstart, bindex, | ||
958 | + i_size_read(file->f_path.dentry->d_inode)); | ||
959 | + if (err) { | ||
960 | + if (unlikely(err == -EEXIST)) | ||
961 | + goto retry; | ||
962 | + goto out; | ||
963 | + } | ||
964 | + | ||
965 | + /* bring it to the same state as an unlinked file */ | ||
966 | + lower_dentry = unionfs_lower_dentry_idx(dentry, dbstart(dentry)); | ||
967 | + if (!unionfs_lower_inode_idx(dentry->d_inode, bindex)) { | ||
968 | + atomic_inc(&lower_dentry->d_inode->i_count); | ||
969 | + unionfs_set_lower_inode_idx(dentry->d_inode, bindex, | ||
970 | + lower_dentry->d_inode); | ||
971 | + } | ||
972 | + lower_dir_dentry = lock_parent(lower_dentry); | ||
973 | + err = vfs_unlink(lower_dir_dentry->d_inode, lower_dentry); | ||
974 | + unlock_dir(lower_dir_dentry); | ||
975 | + | ||
976 | +out: | ||
977 | + if (!err) | ||
978 | + unionfs_check_dentry(dentry); | ||
979 | + return err; | ||
980 | +} | ||
981 | + | ||
982 | +/* | ||
983 | + * put all references held by upper struct file and free lower file pointer | ||
984 | + * array | ||
985 | + */ | ||
986 | +static void cleanup_file(struct file *file) | ||
987 | +{ | ||
988 | + int bindex, bstart, bend; | ||
989 | + struct file **lower_files; | ||
990 | + struct file *lower_file; | ||
991 | + struct super_block *sb = file->f_path.dentry->d_sb; | ||
992 | + | ||
993 | + lower_files = UNIONFS_F(file)->lower_files; | ||
994 | + bstart = fbstart(file); | ||
995 | + bend = fbend(file); | ||
996 | + | ||
997 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
998 | + int i; /* holds (possibly) updated branch index */ | ||
999 | + int old_bid; | ||
1000 | + | ||
1001 | + lower_file = unionfs_lower_file_idx(file, bindex); | ||
1002 | + if (!lower_file) | ||
1003 | + continue; | ||
1004 | + | ||
1005 | + /* | ||
1006 | + * Find new index of matching branch with an open | ||
1007 | + * file, since branches could have been added or | ||
1008 | + * deleted causing the one with open files to shift. | ||
1009 | + */ | ||
1010 | + old_bid = UNIONFS_F(file)->saved_branch_ids[bindex]; | ||
1011 | + i = branch_id_to_idx(sb, old_bid); | ||
1012 | + if (unlikely(i < 0)) { | ||
1013 | + printk(KERN_ERR "unionfs: no superblock for " | ||
1014 | + "file %p\n", file); | ||
1015 | + continue; | ||
1016 | + } | ||
1017 | + | ||
1018 | + /* decrement count of open files */ | ||
1019 | + branchput(sb, i); | ||
1020 | + /* | ||
1021 | + * fput will perform an mntput for us on the correct branch. | ||
1022 | + * Although we're using the file's old branch configuration, | ||
1023 | + * bindex, which is the old index, correctly points to the | ||
1024 | + * right branch in the file's branch list. In other words, | ||
1025 | + * we're going to mntput the correct branch even if branches | ||
1026 | + * have been added/removed. | ||
1027 | + */ | ||
1028 | + fput(lower_file); | ||
1029 | + UNIONFS_F(file)->lower_files[bindex] = NULL; | ||
1030 | + UNIONFS_F(file)->saved_branch_ids[bindex] = -1; | ||
1031 | + } | ||
1032 | + | ||
1033 | + UNIONFS_F(file)->lower_files = NULL; | ||
1034 | + kfree(lower_files); | ||
1035 | + kfree(UNIONFS_F(file)->saved_branch_ids); | ||
1036 | + /* set to NULL because caller needs to know if to kfree on error */ | ||
1037 | + UNIONFS_F(file)->saved_branch_ids = NULL; | ||
1038 | +} | ||
1039 | + | ||
1040 | +/* open all lower files for a given file */ | ||
1041 | +static int open_all_files(struct file *file) | ||
1042 | +{ | ||
1043 | + int bindex, bstart, bend, err = 0; | ||
1044 | + struct file *lower_file; | ||
1045 | + struct dentry *lower_dentry; | ||
1046 | + struct dentry *dentry = file->f_path.dentry; | ||
1047 | + struct super_block *sb = dentry->d_sb; | ||
1048 | + | ||
1049 | + bstart = dbstart(dentry); | ||
1050 | + bend = dbend(dentry); | ||
1051 | + | ||
1052 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
1053 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
1054 | + if (!lower_dentry) | ||
1055 | + continue; | ||
1056 | + | ||
1057 | + dget(lower_dentry); | ||
1058 | + unionfs_mntget(dentry, bindex); | ||
1059 | + branchget(sb, bindex); | ||
1060 | + | ||
1061 | + lower_file = | ||
1062 | + dentry_open(lower_dentry, | ||
1063 | + unionfs_lower_mnt_idx(dentry, bindex), | ||
1064 | + file->f_flags, current_cred()); | ||
1065 | + if (IS_ERR(lower_file)) { | ||
1066 | + branchput(sb, bindex); | ||
1067 | + err = PTR_ERR(lower_file); | ||
1068 | + goto out; | ||
1069 | + } else { | ||
1070 | + unionfs_set_lower_file_idx(file, bindex, lower_file); | ||
1071 | + } | ||
1072 | + } | ||
1073 | +out: | ||
1074 | + return err; | ||
1075 | +} | ||
1076 | + | ||
1077 | +/* open the highest priority file for a given upper file */ | ||
1078 | +static int open_highest_file(struct file *file, bool willwrite) | ||
1079 | +{ | ||
1080 | + int bindex, bstart, bend, err = 0; | ||
1081 | + struct file *lower_file; | ||
1082 | + struct dentry *lower_dentry; | ||
1083 | + struct dentry *dentry = file->f_path.dentry; | ||
1084 | + struct dentry *parent = dget_parent(dentry); | ||
1085 | + struct inode *parent_inode = parent->d_inode; | ||
1086 | + struct super_block *sb = dentry->d_sb; | ||
1087 | + | ||
1088 | + bstart = dbstart(dentry); | ||
1089 | + bend = dbend(dentry); | ||
1090 | + | ||
1091 | + lower_dentry = unionfs_lower_dentry(dentry); | ||
1092 | + if (willwrite && IS_WRITE_FLAG(file->f_flags) && is_robranch(dentry)) { | ||
1093 | + for (bindex = bstart - 1; bindex >= 0; bindex--) { | ||
1094 | + err = copyup_file(parent_inode, file, bstart, bindex, | ||
1095 | + i_size_read(dentry->d_inode)); | ||
1096 | + if (!err) | ||
1097 | + break; | ||
1098 | + } | ||
1099 | + atomic_set(&UNIONFS_F(file)->generation, | ||
1100 | + atomic_read(&UNIONFS_I(dentry->d_inode)-> | ||
1101 | + generation)); | ||
1102 | + goto out; | ||
1103 | + } | ||
1104 | + | ||
1105 | + dget(lower_dentry); | ||
1106 | + unionfs_mntget(dentry, bstart); | ||
1107 | + lower_file = dentry_open(lower_dentry, | ||
1108 | + unionfs_lower_mnt_idx(dentry, bstart), | ||
1109 | + file->f_flags, current_cred()); | ||
1110 | + if (IS_ERR(lower_file)) { | ||
1111 | + err = PTR_ERR(lower_file); | ||
1112 | + goto out; | ||
1113 | + } | ||
1114 | + branchget(sb, bstart); | ||
1115 | + unionfs_set_lower_file(file, lower_file); | ||
1116 | + /* Fix up the position. */ | ||
1117 | + lower_file->f_pos = file->f_pos; | ||
1118 | + | ||
1119 | + memcpy(&lower_file->f_ra, &file->f_ra, sizeof(struct file_ra_state)); | ||
1120 | +out: | ||
1121 | + dput(parent); | ||
1122 | + return err; | ||
1123 | +} | ||
1124 | + | ||
1125 | +/* perform a delayed copyup of a read-write file on a read-only branch */ | ||
1126 | +static int do_delayed_copyup(struct file *file, struct dentry *parent) | ||
1127 | +{ | ||
1128 | + int bindex, bstart, bend, err = 0; | ||
1129 | + struct dentry *dentry = file->f_path.dentry; | ||
1130 | + struct inode *parent_inode = parent->d_inode; | ||
1131 | + | ||
1132 | + bstart = fbstart(file); | ||
1133 | + bend = fbend(file); | ||
1134 | + | ||
1135 | + BUG_ON(!S_ISREG(dentry->d_inode->i_mode)); | ||
1136 | + | ||
1137 | + unionfs_check_file(file); | ||
1138 | + for (bindex = bstart - 1; bindex >= 0; bindex--) { | ||
1139 | + if (!d_deleted(dentry)) | ||
1140 | + err = copyup_file(parent_inode, file, bstart, | ||
1141 | + bindex, | ||
1142 | + i_size_read(dentry->d_inode)); | ||
1143 | + else | ||
1144 | + err = copyup_deleted_file(file, dentry, parent, | ||
1145 | + bstart, bindex); | ||
1146 | + /* if succeeded, set lower open-file flags and break */ | ||
1147 | + if (!err) { | ||
1148 | + struct file *lower_file; | ||
1149 | + lower_file = unionfs_lower_file_idx(file, bindex); | ||
1150 | + lower_file->f_flags = file->f_flags; | ||
1151 | + break; | ||
1152 | + } | ||
1153 | + } | ||
1154 | + if (err || (bstart <= fbstart(file))) | ||
1155 | + goto out; | ||
1156 | + bend = fbend(file); | ||
1157 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
1158 | + if (unionfs_lower_file_idx(file, bindex)) { | ||
1159 | + branchput(dentry->d_sb, bindex); | ||
1160 | + fput(unionfs_lower_file_idx(file, bindex)); | ||
1161 | + unionfs_set_lower_file_idx(file, bindex, NULL); | ||
1162 | + } | ||
1163 | + } | ||
1164 | + path_put_lowers(dentry, bstart, bend, false); | ||
1165 | + iput_lowers(dentry->d_inode, bstart, bend, false); | ||
1166 | + /* for reg file, we only open it "once" */ | ||
1167 | + fbend(file) = fbstart(file); | ||
1168 | + dbend(dentry) = dbstart(dentry); | ||
1169 | + ibend(dentry->d_inode) = ibstart(dentry->d_inode); | ||
1170 | + | ||
1171 | +out: | ||
1172 | + unionfs_check_file(file); | ||
1173 | + return err; | ||
1174 | +} | ||
1175 | + | ||
1176 | +/* | ||
1177 | + * Helper function for unionfs_file_revalidate/locked. | ||
1178 | + * Expects dentry/parent to be locked already, and revalidated. | ||
1179 | + */ | ||
1180 | +static int __unionfs_file_revalidate(struct file *file, struct dentry *dentry, | ||
1181 | + struct dentry *parent, | ||
1182 | + struct super_block *sb, int sbgen, | ||
1183 | + int dgen, bool willwrite) | ||
1184 | +{ | ||
1185 | + int fgen; | ||
1186 | + int bstart, bend, orig_brid; | ||
1187 | + int size; | ||
1188 | + int err = 0; | ||
1189 | + | ||
1190 | + fgen = atomic_read(&UNIONFS_F(file)->generation); | ||
1191 | + | ||
1192 | + /* | ||
1193 | + * There are two cases we are interested in. The first is if the | ||
1194 | + * generation is lower than the super-block. The second is if | ||
1195 | + * someone has copied up this file from underneath us, we also need | ||
1196 | + * to refresh things. | ||
1197 | + */ | ||
1198 | + if ((d_deleted(dentry) && dbstart(dentry) >= fbstart(file)) || | ||
1199 | + (sbgen <= fgen && | ||
1200 | + dbstart(dentry) == fbstart(file) && | ||
1201 | + unionfs_lower_file(file))) | ||
1202 | + goto out_may_copyup; | ||
1203 | + | ||
1204 | + /* save orig branch ID */ | ||
1205 | + orig_brid = UNIONFS_F(file)->saved_branch_ids[fbstart(file)]; | ||
1206 | + | ||
1207 | + /* First we throw out the existing files. */ | ||
1208 | + cleanup_file(file); | ||
1209 | + | ||
1210 | + /* Now we reopen the file(s) as in unionfs_open. */ | ||
1211 | + bstart = fbstart(file) = dbstart(dentry); | ||
1212 | + bend = fbend(file) = dbend(dentry); | ||
1213 | + | ||
1214 | + size = sizeof(struct file *) * sbmax(sb); | ||
1215 | + UNIONFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL); | ||
1216 | + if (unlikely(!UNIONFS_F(file)->lower_files)) { | ||
1217 | + err = -ENOMEM; | ||
1218 | + goto out; | ||
1219 | + } | ||
1220 | + size = sizeof(int) * sbmax(sb); | ||
1221 | + UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL); | ||
1222 | + if (unlikely(!UNIONFS_F(file)->saved_branch_ids)) { | ||
1223 | + err = -ENOMEM; | ||
1224 | + goto out; | ||
1225 | + } | ||
1226 | + | ||
1227 | + if (S_ISDIR(dentry->d_inode->i_mode)) { | ||
1228 | + /* We need to open all the files. */ | ||
1229 | + err = open_all_files(file); | ||
1230 | + if (err) | ||
1231 | + goto out; | ||
1232 | + } else { | ||
1233 | + int new_brid; | ||
1234 | + /* We only open the highest priority branch. */ | ||
1235 | + err = open_highest_file(file, willwrite); | ||
1236 | + if (err) | ||
1237 | + goto out; | ||
1238 | + new_brid = UNIONFS_F(file)->saved_branch_ids[fbstart(file)]; | ||
1239 | + if (unlikely(new_brid != orig_brid && sbgen > fgen)) { | ||
1240 | + /* | ||
1241 | + * If we re-opened the file on a different branch | ||
1242 | + * than the original one, and this was due to a new | ||
1243 | + * branch inserted, then update the mnt counts of | ||
1244 | + * the old and new branches accordingly. | ||
1245 | + */ | ||
1246 | + unionfs_mntget(dentry, bstart); | ||
1247 | + unionfs_mntput(sb->s_root, | ||
1248 | + branch_id_to_idx(sb, orig_brid)); | ||
1249 | + } | ||
1250 | + /* regular files have only one open lower file */ | ||
1251 | + fbend(file) = fbstart(file); | ||
1252 | + } | ||
1253 | + atomic_set(&UNIONFS_F(file)->generation, | ||
1254 | + atomic_read(&UNIONFS_I(dentry->d_inode)->generation)); | ||
1255 | + | ||
1256 | +out_may_copyup: | ||
1257 | + /* Copyup on the first write to a file on a readonly branch. */ | ||
1258 | + if (willwrite && IS_WRITE_FLAG(file->f_flags) && | ||
1259 | + !IS_WRITE_FLAG(unionfs_lower_file(file)->f_flags) && | ||
1260 | + is_robranch(dentry)) { | ||
1261 | + pr_debug("unionfs: do delay copyup of \"%s\"\n", | ||
1262 | + dentry->d_name.name); | ||
1263 | + err = do_delayed_copyup(file, parent); | ||
1264 | + /* regular files have only one open lower file */ | ||
1265 | + if (!err && !S_ISDIR(dentry->d_inode->i_mode)) | ||
1266 | + fbend(file) = fbstart(file); | ||
1267 | + } | ||
1268 | + | ||
1269 | +out: | ||
1270 | + if (err) { | ||
1271 | + kfree(UNIONFS_F(file)->lower_files); | ||
1272 | + kfree(UNIONFS_F(file)->saved_branch_ids); | ||
1273 | + } | ||
1274 | + return err; | ||
1275 | +} | ||
1276 | + | ||
1277 | +/* | ||
1278 | + * Revalidate the struct file | ||
1279 | + * @file: file to revalidate | ||
1280 | + * @parent: parent dentry (locked by caller) | ||
1281 | + * @willwrite: true if caller may cause changes to the file; false otherwise. | ||
1282 | + * Caller must lock/unlock dentry's branch configuration. | ||
1283 | + */ | ||
1284 | +int unionfs_file_revalidate(struct file *file, struct dentry *parent, | ||
1285 | + bool willwrite) | ||
1286 | +{ | ||
1287 | + struct super_block *sb; | ||
1288 | + struct dentry *dentry; | ||
1289 | + int sbgen, dgen; | ||
1290 | + int err = 0; | ||
1291 | + | ||
1292 | + dentry = file->f_path.dentry; | ||
1293 | + sb = dentry->d_sb; | ||
1294 | + verify_locked(dentry); | ||
1295 | + verify_locked(parent); | ||
1296 | + | ||
1297 | + /* | ||
1298 | + * First revalidate the dentry inside struct file, | ||
1299 | + * but not unhashed dentries. | ||
1300 | + */ | ||
1301 | + if (!d_deleted(dentry) && | ||
1302 | + !__unionfs_d_revalidate(dentry, parent, willwrite)) { | ||
1303 | + err = -ESTALE; | ||
1304 | + goto out; | ||
1305 | + } | ||
1306 | + | ||
1307 | + sbgen = atomic_read(&UNIONFS_SB(sb)->generation); | ||
1308 | + dgen = atomic_read(&UNIONFS_D(dentry)->generation); | ||
1309 | + | ||
1310 | + if (unlikely(sbgen > dgen)) { /* XXX: should never happen */ | ||
1311 | + pr_debug("unionfs: failed to revalidate dentry (%s)\n", | ||
1312 | + dentry->d_name.name); | ||
1313 | + err = -ESTALE; | ||
1314 | + goto out; | ||
1315 | + } | ||
1316 | + | ||
1317 | + err = __unionfs_file_revalidate(file, dentry, parent, sb, | ||
1318 | + sbgen, dgen, willwrite); | ||
1319 | +out: | ||
1320 | + return err; | ||
1321 | +} | ||
1322 | + | ||
1323 | +/* unionfs_open helper function: open a directory */ | ||
1324 | +static int __open_dir(struct inode *inode, struct file *file) | ||
1325 | +{ | ||
1326 | + struct dentry *lower_dentry; | ||
1327 | + struct file *lower_file; | ||
1328 | + int bindex, bstart, bend; | ||
1329 | + struct vfsmount *mnt; | ||
1330 | + | ||
1331 | + bstart = fbstart(file) = dbstart(file->f_path.dentry); | ||
1332 | + bend = fbend(file) = dbend(file->f_path.dentry); | ||
1333 | + | ||
1334 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
1335 | + lower_dentry = | ||
1336 | + unionfs_lower_dentry_idx(file->f_path.dentry, bindex); | ||
1337 | + if (!lower_dentry) | ||
1338 | + continue; | ||
1339 | + | ||
1340 | + dget(lower_dentry); | ||
1341 | + unionfs_mntget(file->f_path.dentry, bindex); | ||
1342 | + mnt = unionfs_lower_mnt_idx(file->f_path.dentry, bindex); | ||
1343 | + lower_file = dentry_open(lower_dentry, mnt, file->f_flags, | ||
1344 | + current_cred()); | ||
1345 | + if (IS_ERR(lower_file)) | ||
1346 | + return PTR_ERR(lower_file); | ||
1347 | + | ||
1348 | + unionfs_set_lower_file_idx(file, bindex, lower_file); | ||
1349 | + | ||
1350 | + /* | ||
1351 | + * The branchget goes after the open, because otherwise | ||
1352 | + * we would miss the reference on release. | ||
1353 | + */ | ||
1354 | + branchget(inode->i_sb, bindex); | ||
1355 | + } | ||
1356 | + | ||
1357 | + return 0; | ||
1358 | +} | ||
1359 | + | ||
1360 | +/* unionfs_open helper function: open a file */ | ||
1361 | +static int __open_file(struct inode *inode, struct file *file, | ||
1362 | + struct dentry *parent) | ||
1363 | +{ | ||
1364 | + struct dentry *lower_dentry; | ||
1365 | + struct file *lower_file; | ||
1366 | + int lower_flags; | ||
1367 | + int bindex, bstart, bend; | ||
1368 | + | ||
1369 | + lower_dentry = unionfs_lower_dentry(file->f_path.dentry); | ||
1370 | + lower_flags = file->f_flags; | ||
1371 | + | ||
1372 | + bstart = fbstart(file) = dbstart(file->f_path.dentry); | ||
1373 | + bend = fbend(file) = dbend(file->f_path.dentry); | ||
1374 | + | ||
1375 | + /* | ||
1376 | + * check for the permission for lower file. If the error is | ||
1377 | + * COPYUP_ERR, copyup the file. | ||
1378 | + */ | ||
1379 | + if (lower_dentry->d_inode && is_robranch(file->f_path.dentry)) { | ||
1380 | + /* | ||
1381 | + * if the open will change the file, copy it up otherwise | ||
1382 | + * defer it. | ||
1383 | + */ | ||
1384 | + if (lower_flags & O_TRUNC) { | ||
1385 | + int size = 0; | ||
1386 | + int err = -EROFS; | ||
1387 | + | ||
1388 | + /* copyup the file */ | ||
1389 | + for (bindex = bstart - 1; bindex >= 0; bindex--) { | ||
1390 | + err = copyup_file(parent->d_inode, file, | ||
1391 | + bstart, bindex, size); | ||
1392 | + if (!err) { | ||
1393 | + /* only one regular file open */ | ||
1394 | + fbend(file) = fbstart(file); | ||
1395 | + break; | ||
1396 | + } | ||
1397 | + } | ||
1398 | + return err; | ||
1399 | + } else { | ||
1400 | + /* | ||
1401 | + * turn off writeable flags, to force delayed copyup | ||
1402 | + * by caller. | ||
1403 | + */ | ||
1404 | + lower_flags &= ~(OPEN_WRITE_FLAGS); | ||
1405 | + } | ||
1406 | + } | ||
1407 | + | ||
1408 | + dget(lower_dentry); | ||
1409 | + | ||
1410 | + /* | ||
1411 | + * dentry_open will decrement mnt refcnt if err. | ||
1412 | + * otherwise fput() will do an mntput() for us upon file close. | ||
1413 | + */ | ||
1414 | + unionfs_mntget(file->f_path.dentry, bstart); | ||
1415 | + lower_file = | ||
1416 | + dentry_open(lower_dentry, | ||
1417 | + unionfs_lower_mnt_idx(file->f_path.dentry, bstart), | ||
1418 | + lower_flags, current_cred()); | ||
1419 | + if (IS_ERR(lower_file)) | ||
1420 | + return PTR_ERR(lower_file); | ||
1421 | + | ||
1422 | + unionfs_set_lower_file(file, lower_file); | ||
1423 | + branchget(inode->i_sb, bstart); | ||
1424 | + | ||
1425 | + return 0; | ||
1426 | +} | ||
1427 | + | ||
1428 | +int unionfs_open(struct inode *inode, struct file *file) | ||
1429 | +{ | ||
1430 | + int err = 0; | ||
1431 | + struct file *lower_file = NULL; | ||
1432 | + struct dentry *dentry = file->f_path.dentry; | ||
1433 | + struct dentry *parent; | ||
1434 | + int bindex = 0, bstart = 0, bend = 0; | ||
1435 | + int size; | ||
1436 | + int valid = 0; | ||
1437 | + | ||
1438 | + unionfs_read_lock(inode->i_sb, UNIONFS_SMUTEX_PARENT); | ||
1439 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
1440 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
1441 | + | ||
1442 | + /* don't open unhashed/deleted files */ | ||
1443 | + if (d_deleted(dentry)) { | ||
1444 | + err = -ENOENT; | ||
1445 | + goto out_nofree; | ||
1446 | + } | ||
1447 | + | ||
1448 | + /* XXX: should I change 'false' below to the 'willwrite' flag? */ | ||
1449 | + valid = __unionfs_d_revalidate(dentry, parent, false); | ||
1450 | + if (unlikely(!valid)) { | ||
1451 | + err = -ESTALE; | ||
1452 | + goto out_nofree; | ||
1453 | + } | ||
1454 | + | ||
1455 | + file->private_data = | ||
1456 | + kzalloc(sizeof(struct unionfs_file_info), GFP_KERNEL); | ||
1457 | + if (unlikely(!UNIONFS_F(file))) { | ||
1458 | + err = -ENOMEM; | ||
1459 | + goto out_nofree; | ||
1460 | + } | ||
1461 | + fbstart(file) = -1; | ||
1462 | + fbend(file) = -1; | ||
1463 | + atomic_set(&UNIONFS_F(file)->generation, | ||
1464 | + atomic_read(&UNIONFS_I(inode)->generation)); | ||
1465 | + | ||
1466 | + size = sizeof(struct file *) * sbmax(inode->i_sb); | ||
1467 | + UNIONFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL); | ||
1468 | + if (unlikely(!UNIONFS_F(file)->lower_files)) { | ||
1469 | + err = -ENOMEM; | ||
1470 | + goto out; | ||
1471 | + } | ||
1472 | + size = sizeof(int) * sbmax(inode->i_sb); | ||
1473 | + UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL); | ||
1474 | + if (unlikely(!UNIONFS_F(file)->saved_branch_ids)) { | ||
1475 | + err = -ENOMEM; | ||
1476 | + goto out; | ||
1477 | + } | ||
1478 | + | ||
1479 | + bstart = fbstart(file) = dbstart(dentry); | ||
1480 | + bend = fbend(file) = dbend(dentry); | ||
1481 | + | ||
1482 | + /* | ||
1483 | + * open all directories and make the unionfs file struct point to | ||
1484 | + * these lower file structs | ||
1485 | + */ | ||
1486 | + if (S_ISDIR(inode->i_mode)) | ||
1487 | + err = __open_dir(inode, file); /* open a dir */ | ||
1488 | + else | ||
1489 | + err = __open_file(inode, file, parent); /* open a file */ | ||
1490 | + | ||
1491 | + /* freeing the allocated resources, and fput the opened files */ | ||
1492 | + if (err) { | ||
1493 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
1494 | + lower_file = unionfs_lower_file_idx(file, bindex); | ||
1495 | + if (!lower_file) | ||
1496 | + continue; | ||
1497 | + | ||
1498 | + branchput(dentry->d_sb, bindex); | ||
1499 | + /* fput calls dput for lower_dentry */ | ||
1500 | + fput(lower_file); | ||
1501 | + } | ||
1502 | + } | ||
1503 | + | ||
1504 | +out: | ||
1505 | + if (err) { | ||
1506 | + kfree(UNIONFS_F(file)->lower_files); | ||
1507 | + kfree(UNIONFS_F(file)->saved_branch_ids); | ||
1508 | + kfree(UNIONFS_F(file)); | ||
1509 | + } | ||
1510 | +out_nofree: | ||
1511 | + if (!err) { | ||
1512 | + unionfs_postcopyup_setmnt(dentry); | ||
1513 | + unionfs_copy_attr_times(inode); | ||
1514 | + unionfs_check_file(file); | ||
1515 | + unionfs_check_inode(inode); | ||
1516 | + } | ||
1517 | + unionfs_unlock_dentry(dentry); | ||
1518 | + unionfs_unlock_parent(dentry, parent); | ||
1519 | + unionfs_read_unlock(inode->i_sb); | ||
1520 | + return err; | ||
1521 | +} | ||
1522 | + | ||
1523 | +/* | ||
1524 | + * release all lower object references & free the file info structure | ||
1525 | + * | ||
1526 | + * No need to grab sb info's rwsem. | ||
1527 | + */ | ||
1528 | +int unionfs_file_release(struct inode *inode, struct file *file) | ||
1529 | +{ | ||
1530 | + struct file *lower_file = NULL; | ||
1531 | + struct unionfs_file_info *fileinfo; | ||
1532 | + struct unionfs_inode_info *inodeinfo; | ||
1533 | + struct super_block *sb = inode->i_sb; | ||
1534 | + struct dentry *dentry = file->f_path.dentry; | ||
1535 | + struct dentry *parent; | ||
1536 | + int bindex, bstart, bend; | ||
1537 | + int err = 0; | ||
1538 | + | ||
1539 | + /* | ||
1540 | + * Since mm/memory.c:might_fault() (under PROVE_LOCKING) was | ||
1541 | + * modified in 2.6.29-rc1 to call might_lock_read on mmap_sem, this | ||
1542 | + * has been causing false positives in file system stacking layers. | ||
1543 | + * In particular, our ->mmap is called after sys_mmap2 already holds | ||
1544 | + * mmap_sem, then we lock our own mutexes; but earlier, it's | ||
1545 | + * possible for lockdep to have locked our mutexes first, and then | ||
1546 | + * we call a lower ->readdir which could call might_fault. The | ||
1547 | + * different ordering of the locks is what lockdep complains about | ||
1548 | + * -- unnecessarily. Therefore, we have no choice but to tell | ||
1549 | + * lockdep to temporarily turn off lockdep here. Note: the comments | ||
1550 | + * inside might_sleep also suggest that it would have been | ||
1551 | + * nicer to only annotate paths that needs that might_lock_read. | ||
1552 | + */ | ||
1553 | + lockdep_off(); | ||
1554 | + unionfs_read_lock(sb, UNIONFS_SMUTEX_PARENT); | ||
1555 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
1556 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
1557 | + | ||
1558 | + /* | ||
1559 | + * We try to revalidate, but the VFS ignores return return values | ||
1560 | + * from file->release, so we must always try to succeed here, | ||
1561 | + * including to do the kfree and dput below. So if revalidation | ||
1562 | + * failed, all we can do is print some message and keep going. | ||
1563 | + */ | ||
1564 | + err = unionfs_file_revalidate(file, parent, | ||
1565 | + UNIONFS_F(file)->wrote_to_file); | ||
1566 | + if (!err) | ||
1567 | + unionfs_check_file(file); | ||
1568 | + fileinfo = UNIONFS_F(file); | ||
1569 | + BUG_ON(file->f_path.dentry->d_inode != inode); | ||
1570 | + inodeinfo = UNIONFS_I(inode); | ||
1571 | + | ||
1572 | + /* fput all the lower files */ | ||
1573 | + bstart = fbstart(file); | ||
1574 | + bend = fbend(file); | ||
1575 | + | ||
1576 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
1577 | + lower_file = unionfs_lower_file_idx(file, bindex); | ||
1578 | + | ||
1579 | + if (lower_file) { | ||
1580 | + unionfs_set_lower_file_idx(file, bindex, NULL); | ||
1581 | + fput(lower_file); | ||
1582 | + branchput(sb, bindex); | ||
1583 | + } | ||
1584 | + | ||
1585 | + /* if there are no more refs to the dentry, dput it */ | ||
1586 | + if (d_deleted(dentry)) { | ||
1587 | + dput(unionfs_lower_dentry_idx(dentry, bindex)); | ||
1588 | + unionfs_set_lower_dentry_idx(dentry, bindex, NULL); | ||
1589 | + } | ||
1590 | + } | ||
1591 | + | ||
1592 | + kfree(fileinfo->lower_files); | ||
1593 | + kfree(fileinfo->saved_branch_ids); | ||
1594 | + | ||
1595 | + if (fileinfo->rdstate) { | ||
1596 | + fileinfo->rdstate->access = jiffies; | ||
1597 | + spin_lock(&inodeinfo->rdlock); | ||
1598 | + inodeinfo->rdcount++; | ||
1599 | + list_add_tail(&fileinfo->rdstate->cache, | ||
1600 | + &inodeinfo->readdircache); | ||
1601 | + mark_inode_dirty(inode); | ||
1602 | + spin_unlock(&inodeinfo->rdlock); | ||
1603 | + fileinfo->rdstate = NULL; | ||
1604 | + } | ||
1605 | + kfree(fileinfo); | ||
1606 | + | ||
1607 | + unionfs_unlock_dentry(dentry); | ||
1608 | + unionfs_unlock_parent(dentry, parent); | ||
1609 | + unionfs_read_unlock(sb); | ||
1610 | + lockdep_on(); | ||
1611 | + return err; | ||
1612 | +} | ||
1613 | + | ||
1614 | +/* pass the ioctl to the lower fs */ | ||
1615 | +static long do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
1616 | +{ | ||
1617 | + struct file *lower_file; | ||
1618 | + int err; | ||
1619 | + | ||
1620 | + lower_file = unionfs_lower_file(file); | ||
1621 | + | ||
1622 | + err = -ENOTTY; | ||
1623 | + if (!lower_file || !lower_file->f_op) | ||
1624 | + goto out; | ||
1625 | + if (lower_file->f_op->unlocked_ioctl) { | ||
1626 | + err = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg); | ||
1627 | +#ifdef CONFIG_COMPAT | ||
1628 | + } else if (lower_file->f_op->ioctl) { | ||
1629 | + err = lower_file->f_op->compat_ioctl( | ||
1630 | + lower_file->f_path.dentry->d_inode, | ||
1631 | + lower_file, cmd, arg); | ||
1632 | +#endif | ||
1633 | + } | ||
1634 | + | ||
1635 | +out: | ||
1636 | + return err; | ||
1637 | +} | ||
1638 | + | ||
1639 | +/* | ||
1640 | + * return to user-space the branch indices containing the file in question | ||
1641 | + * | ||
1642 | + * We use fd_set and therefore we are limited to the number of the branches | ||
1643 | + * to FD_SETSIZE, which is currently 1024 - plenty for most people | ||
1644 | + */ | ||
1645 | +static int unionfs_ioctl_queryfile(struct file *file, struct dentry *parent, | ||
1646 | + unsigned int cmd, unsigned long arg) | ||
1647 | +{ | ||
1648 | + int err = 0; | ||
1649 | + fd_set branchlist; | ||
1650 | + int bstart = 0, bend = 0, bindex = 0; | ||
1651 | + int orig_bstart, orig_bend; | ||
1652 | + struct dentry *dentry, *lower_dentry; | ||
1653 | + struct vfsmount *mnt; | ||
1654 | + | ||
1655 | + dentry = file->f_path.dentry; | ||
1656 | + orig_bstart = dbstart(dentry); | ||
1657 | + orig_bend = dbend(dentry); | ||
1658 | + err = unionfs_partial_lookup(dentry, parent); | ||
1659 | + if (err) | ||
1660 | + goto out; | ||
1661 | + bstart = dbstart(dentry); | ||
1662 | + bend = dbend(dentry); | ||
1663 | + | ||
1664 | + FD_ZERO(&branchlist); | ||
1665 | + | ||
1666 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
1667 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
1668 | + if (!lower_dentry) | ||
1669 | + continue; | ||
1670 | + if (likely(lower_dentry->d_inode)) | ||
1671 | + FD_SET(bindex, &branchlist); | ||
1672 | + /* purge any lower objects after partial_lookup */ | ||
1673 | + if (bindex < orig_bstart || bindex > orig_bend) { | ||
1674 | + dput(lower_dentry); | ||
1675 | + unionfs_set_lower_dentry_idx(dentry, bindex, NULL); | ||
1676 | + iput(unionfs_lower_inode_idx(dentry->d_inode, bindex)); | ||
1677 | + unionfs_set_lower_inode_idx(dentry->d_inode, bindex, | ||
1678 | + NULL); | ||
1679 | + mnt = unionfs_lower_mnt_idx(dentry, bindex); | ||
1680 | + if (!mnt) | ||
1681 | + continue; | ||
1682 | + unionfs_mntput(dentry, bindex); | ||
1683 | + unionfs_set_lower_mnt_idx(dentry, bindex, NULL); | ||
1684 | + } | ||
1685 | + } | ||
1686 | + /* restore original dentry's offsets */ | ||
1687 | + dbstart(dentry) = orig_bstart; | ||
1688 | + dbend(dentry) = orig_bend; | ||
1689 | + ibstart(dentry->d_inode) = orig_bstart; | ||
1690 | + ibend(dentry->d_inode) = orig_bend; | ||
1691 | + | ||
1692 | + err = copy_to_user((void __user *)arg, &branchlist, sizeof(fd_set)); | ||
1693 | + if (unlikely(err)) | ||
1694 | + err = -EFAULT; | ||
1695 | + | ||
1696 | +out: | ||
1697 | + return err < 0 ? err : bend; | ||
1698 | +} | ||
1699 | + | ||
1700 | +long unionfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
1701 | +{ | ||
1702 | + long err; | ||
1703 | + struct dentry *dentry = file->f_path.dentry; | ||
1704 | + struct dentry *parent; | ||
1705 | + | ||
1706 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT); | ||
1707 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
1708 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
1709 | + | ||
1710 | + err = unionfs_file_revalidate(file, parent, true); | ||
1711 | + if (unlikely(err)) | ||
1712 | + goto out; | ||
1713 | + | ||
1714 | + /* check if asked for local commands */ | ||
1715 | + switch (cmd) { | ||
1716 | + case UNIONFS_IOCTL_INCGEN: | ||
1717 | + /* Increment the superblock generation count */ | ||
1718 | + pr_info("unionfs: incgen ioctl deprecated; " | ||
1719 | + "use \"-o remount,incgen\"\n"); | ||
1720 | + err = -ENOSYS; | ||
1721 | + break; | ||
1722 | + | ||
1723 | + case UNIONFS_IOCTL_QUERYFILE: | ||
1724 | + /* Return list of branches containing the given file */ | ||
1725 | + err = unionfs_ioctl_queryfile(file, parent, cmd, arg); | ||
1726 | + break; | ||
1727 | + | ||
1728 | + default: | ||
1729 | + /* pass the ioctl down */ | ||
1730 | + err = do_ioctl(file, cmd, arg); | ||
1731 | + break; | ||
1732 | + } | ||
1733 | + | ||
1734 | +out: | ||
1735 | + unionfs_check_file(file); | ||
1736 | + unionfs_unlock_dentry(dentry); | ||
1737 | + unionfs_unlock_parent(dentry, parent); | ||
1738 | + unionfs_read_unlock(dentry->d_sb); | ||
1739 | + return err; | ||
1740 | +} | ||
1741 | + | ||
1742 | +int unionfs_flush(struct file *file, fl_owner_t id) | ||
1743 | +{ | ||
1744 | + int err = 0; | ||
1745 | + struct file *lower_file = NULL; | ||
1746 | + struct dentry *dentry = file->f_path.dentry; | ||
1747 | + struct dentry *parent; | ||
1748 | + int bindex, bstart, bend; | ||
1749 | + | ||
1750 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT); | ||
1751 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
1752 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
1753 | + | ||
1754 | + err = unionfs_file_revalidate(file, parent, | ||
1755 | + UNIONFS_F(file)->wrote_to_file); | ||
1756 | + if (unlikely(err)) | ||
1757 | + goto out; | ||
1758 | + unionfs_check_file(file); | ||
1759 | + | ||
1760 | + bstart = fbstart(file); | ||
1761 | + bend = fbend(file); | ||
1762 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
1763 | + lower_file = unionfs_lower_file_idx(file, bindex); | ||
1764 | + | ||
1765 | + if (lower_file && lower_file->f_op && | ||
1766 | + lower_file->f_op->flush) { | ||
1767 | + err = lower_file->f_op->flush(lower_file, id); | ||
1768 | + if (err) | ||
1769 | + goto out; | ||
1770 | + } | ||
1771 | + | ||
1772 | + } | ||
1773 | + | ||
1774 | +out: | ||
1775 | + if (!err) | ||
1776 | + unionfs_check_file(file); | ||
1777 | + unionfs_unlock_dentry(dentry); | ||
1778 | + unionfs_unlock_parent(dentry, parent); | ||
1779 | + unionfs_read_unlock(dentry->d_sb); | ||
1780 | + return err; | ||
1781 | +} | ||
1782 | diff --git a/fs/unionfs/copyup.c b/fs/unionfs/copyup.c | ||
1783 | new file mode 100644 | ||
1784 | index 0000000..37c2654 | ||
1785 | --- /dev/null | ||
1786 | +++ b/fs/unionfs/copyup.c | ||
1787 | @@ -0,0 +1,896 @@ | ||
1788 | +/* | ||
1789 | + * Copyright (c) 2003-2011 Erez Zadok | ||
1790 | + * Copyright (c) 2003-2006 Charles P. Wright | ||
1791 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
1792 | + * Copyright (c) 2005-2006 Junjiro Okajima | ||
1793 | + * Copyright (c) 2005 Arun M. Krishnakumar | ||
1794 | + * Copyright (c) 2004-2006 David P. Quigley | ||
1795 | + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair | ||
1796 | + * Copyright (c) 2003 Puja Gupta | ||
1797 | + * Copyright (c) 2003 Harikesavan Krishnan | ||
1798 | + * Copyright (c) 2003-2011 Stony Brook University | ||
1799 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
1800 | + * | ||
1801 | + * This program is free software; you can redistribute it and/or modify | ||
1802 | + * it under the terms of the GNU General Public License version 2 as | ||
1803 | + * published by the Free Software Foundation. | ||
1804 | + */ | ||
1805 | + | ||
1806 | +#include "union.h" | ||
1807 | + | ||
1808 | +/* | ||
1809 | + * For detailed explanation of copyup see: | ||
1810 | + * Documentation/filesystems/unionfs/concepts.txt | ||
1811 | + */ | ||
1812 | + | ||
1813 | +#ifdef CONFIG_UNION_FS_XATTR | ||
1814 | +/* copyup all extended attrs for a given dentry */ | ||
1815 | +static int copyup_xattrs(struct dentry *old_lower_dentry, | ||
1816 | + struct dentry *new_lower_dentry) | ||
1817 | +{ | ||
1818 | + int err = 0; | ||
1819 | + ssize_t list_size = -1; | ||
1820 | + char *name_list = NULL; | ||
1821 | + char *attr_value = NULL; | ||
1822 | + char *name_list_buf = NULL; | ||
1823 | + | ||
1824 | + /* query the actual size of the xattr list */ | ||
1825 | + list_size = vfs_listxattr(old_lower_dentry, NULL, 0); | ||
1826 | + if (list_size <= 0) { | ||
1827 | + err = list_size; | ||
1828 | + goto out; | ||
1829 | + } | ||
1830 | + | ||
1831 | + /* allocate space for the actual list */ | ||
1832 | + name_list = unionfs_xattr_alloc(list_size + 1, XATTR_LIST_MAX); | ||
1833 | + if (unlikely(!name_list || IS_ERR(name_list))) { | ||
1834 | + err = PTR_ERR(name_list); | ||
1835 | + goto out; | ||
1836 | + } | ||
1837 | + | ||
1838 | + name_list_buf = name_list; /* save for kfree at end */ | ||
1839 | + | ||
1840 | + /* now get the actual xattr list of the source file */ | ||
1841 | + list_size = vfs_listxattr(old_lower_dentry, name_list, list_size); | ||
1842 | + if (list_size <= 0) { | ||
1843 | + err = list_size; | ||
1844 | + goto out; | ||
1845 | + } | ||
1846 | + | ||
1847 | + /* allocate space to hold each xattr's value */ | ||
1848 | + attr_value = unionfs_xattr_alloc(XATTR_SIZE_MAX, XATTR_SIZE_MAX); | ||
1849 | + if (unlikely(!attr_value || IS_ERR(attr_value))) { | ||
1850 | + err = PTR_ERR(name_list); | ||
1851 | + goto out; | ||
1852 | + } | ||
1853 | + | ||
1854 | + /* in a loop, get and set each xattr from src to dst file */ | ||
1855 | + while (*name_list) { | ||
1856 | + ssize_t size; | ||
1857 | + | ||
1858 | + /* Lock here since vfs_getxattr doesn't lock for us */ | ||
1859 | + mutex_lock(&old_lower_dentry->d_inode->i_mutex); | ||
1860 | + size = vfs_getxattr(old_lower_dentry, name_list, | ||
1861 | + attr_value, XATTR_SIZE_MAX); | ||
1862 | + mutex_unlock(&old_lower_dentry->d_inode->i_mutex); | ||
1863 | + if (size < 0) { | ||
1864 | + err = size; | ||
1865 | + goto out; | ||
1866 | + } | ||
1867 | + if (size > XATTR_SIZE_MAX) { | ||
1868 | + err = -E2BIG; | ||
1869 | + goto out; | ||
1870 | + } | ||
1871 | + /* Don't lock here since vfs_setxattr does it for us. */ | ||
1872 | + err = vfs_setxattr(new_lower_dentry, name_list, attr_value, | ||
1873 | + size, 0); | ||
1874 | + /* | ||
1875 | + * Selinux depends on "security.*" xattrs, so to maintain | ||
1876 | + * the security of copied-up files, if Selinux is active, | ||
1877 | + * then we must copy these xattrs as well. So we need to | ||
1878 | + * temporarily get FOWNER privileges. | ||
1879 | + * XXX: move entire copyup code to SIOQ. | ||
1880 | + */ | ||
1881 | + if (err == -EPERM && !capable(CAP_FOWNER)) { | ||
1882 | + const struct cred *old_creds; | ||
1883 | + struct cred *new_creds; | ||
1884 | + | ||
1885 | + new_creds = prepare_creds(); | ||
1886 | + if (unlikely(!new_creds)) { | ||
1887 | + err = -ENOMEM; | ||
1888 | + goto out; | ||
1889 | + } | ||
1890 | + cap_raise(new_creds->cap_effective, CAP_FOWNER); | ||
1891 | + old_creds = override_creds(new_creds); | ||
1892 | + err = vfs_setxattr(new_lower_dentry, name_list, | ||
1893 | + attr_value, size, 0); | ||
1894 | + revert_creds(old_creds); | ||
1895 | + } | ||
1896 | + if (err < 0) | ||
1897 | + goto out; | ||
1898 | + name_list += strlen(name_list) + 1; | ||
1899 | + } | ||
1900 | +out: | ||
1901 | + unionfs_xattr_kfree(name_list_buf); | ||
1902 | + unionfs_xattr_kfree(attr_value); | ||
1903 | + /* Ignore if xattr isn't supported */ | ||
1904 | + if (err == -ENOTSUPP || err == -EOPNOTSUPP) | ||
1905 | + err = 0; | ||
1906 | + return err; | ||
1907 | +} | ||
1908 | +#endif /* CONFIG_UNION_FS_XATTR */ | ||
1909 | + | ||
1910 | +/* | ||
1911 | + * Determine the mode based on the copyup flags, and the existing dentry. | ||
1912 | + * | ||
1913 | + * Handle file systems which may not support certain options. For example | ||
1914 | + * jffs2 doesn't allow one to chmod a symlink. So we ignore such harmless | ||
1915 | + * errors, rather than propagating them up, which results in copyup errors | ||
1916 | + * and errors returned back to users. | ||
1917 | + */ | ||
1918 | +static int copyup_permissions(struct super_block *sb, | ||
1919 | + struct dentry *old_lower_dentry, | ||
1920 | + struct dentry *new_lower_dentry) | ||
1921 | +{ | ||
1922 | + struct inode *i = old_lower_dentry->d_inode; | ||
1923 | + struct iattr newattrs; | ||
1924 | + int err; | ||
1925 | + | ||
1926 | + newattrs.ia_atime = i->i_atime; | ||
1927 | + newattrs.ia_mtime = i->i_mtime; | ||
1928 | + newattrs.ia_ctime = i->i_ctime; | ||
1929 | + newattrs.ia_gid = i->i_gid; | ||
1930 | + newattrs.ia_uid = i->i_uid; | ||
1931 | + newattrs.ia_valid = ATTR_CTIME | ATTR_ATIME | ATTR_MTIME | | ||
1932 | + ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_FORCE | | ||
1933 | + ATTR_GID | ATTR_UID; | ||
1934 | + mutex_lock(&new_lower_dentry->d_inode->i_mutex); | ||
1935 | + err = notify_change(new_lower_dentry, &newattrs); | ||
1936 | + if (err) | ||
1937 | + goto out; | ||
1938 | + | ||
1939 | + /* now try to change the mode and ignore EOPNOTSUPP on symlinks */ | ||
1940 | + newattrs.ia_mode = i->i_mode; | ||
1941 | + newattrs.ia_valid = ATTR_MODE | ATTR_FORCE; | ||
1942 | + err = notify_change(new_lower_dentry, &newattrs); | ||
1943 | + if (err == -EOPNOTSUPP && | ||
1944 | + S_ISLNK(new_lower_dentry->d_inode->i_mode)) { | ||
1945 | + printk(KERN_WARNING | ||
1946 | + "unionfs: changing \"%s\" symlink mode unsupported\n", | ||
1947 | + new_lower_dentry->d_name.name); | ||
1948 | + err = 0; | ||
1949 | + } | ||
1950 | + | ||
1951 | +out: | ||
1952 | + mutex_unlock(&new_lower_dentry->d_inode->i_mutex); | ||
1953 | + return err; | ||
1954 | +} | ||
1955 | + | ||
1956 | +/* | ||
1957 | + * create the new device/file/directory - use copyup_permission to copyup | ||
1958 | + * times, and mode | ||
1959 | + * | ||
1960 | + * if the object being copied up is a regular file, the file is only created, | ||
1961 | + * the contents have to be copied up separately | ||
1962 | + */ | ||
1963 | +static int __copyup_ndentry(struct dentry *old_lower_dentry, | ||
1964 | + struct dentry *new_lower_dentry, | ||
1965 | + struct dentry *new_lower_parent_dentry, | ||
1966 | + char *symbuf) | ||
1967 | +{ | ||
1968 | + int err = 0; | ||
1969 | + umode_t old_mode = old_lower_dentry->d_inode->i_mode; | ||
1970 | + struct sioq_args args; | ||
1971 | + | ||
1972 | + if (S_ISDIR(old_mode)) { | ||
1973 | + args.mkdir.parent = new_lower_parent_dentry->d_inode; | ||
1974 | + args.mkdir.dentry = new_lower_dentry; | ||
1975 | + args.mkdir.mode = old_mode; | ||
1976 | + | ||
1977 | + run_sioq(__unionfs_mkdir, &args); | ||
1978 | + err = args.err; | ||
1979 | + } else if (S_ISLNK(old_mode)) { | ||
1980 | + args.symlink.parent = new_lower_parent_dentry->d_inode; | ||
1981 | + args.symlink.dentry = new_lower_dentry; | ||
1982 | + args.symlink.symbuf = symbuf; | ||
1983 | + | ||
1984 | + run_sioq(__unionfs_symlink, &args); | ||
1985 | + err = args.err; | ||
1986 | + } else if (S_ISBLK(old_mode) || S_ISCHR(old_mode) || | ||
1987 | + S_ISFIFO(old_mode) || S_ISSOCK(old_mode)) { | ||
1988 | + args.mknod.parent = new_lower_parent_dentry->d_inode; | ||
1989 | + args.mknod.dentry = new_lower_dentry; | ||
1990 | + args.mknod.mode = old_mode; | ||
1991 | + args.mknod.dev = old_lower_dentry->d_inode->i_rdev; | ||
1992 | + | ||
1993 | + run_sioq(__unionfs_mknod, &args); | ||
1994 | + err = args.err; | ||
1995 | + } else if (S_ISREG(old_mode)) { | ||
1996 | + struct nameidata nd; | ||
1997 | + err = init_lower_nd(&nd, LOOKUP_CREATE); | ||
1998 | + if (unlikely(err < 0)) | ||
1999 | + goto out; | ||
2000 | + args.create.nd = &nd; | ||
2001 | + args.create.parent = new_lower_parent_dentry->d_inode; | ||
2002 | + args.create.dentry = new_lower_dentry; | ||
2003 | + args.create.mode = old_mode; | ||
2004 | + | ||
2005 | + run_sioq(__unionfs_create, &args); | ||
2006 | + err = args.err; | ||
2007 | + release_lower_nd(&nd, err); | ||
2008 | + } else { | ||
2009 | + printk(KERN_CRIT "unionfs: unknown inode type %d\n", | ||
2010 | + old_mode); | ||
2011 | + BUG(); | ||
2012 | + } | ||
2013 | + | ||
2014 | +out: | ||
2015 | + return err; | ||
2016 | +} | ||
2017 | + | ||
2018 | +static int __copyup_reg_data(struct dentry *dentry, | ||
2019 | + struct dentry *new_lower_dentry, int new_bindex, | ||
2020 | + struct dentry *old_lower_dentry, int old_bindex, | ||
2021 | + struct file **copyup_file, loff_t len) | ||
2022 | +{ | ||
2023 | + struct super_block *sb = dentry->d_sb; | ||
2024 | + struct file *input_file; | ||
2025 | + struct file *output_file; | ||
2026 | + struct vfsmount *output_mnt; | ||
2027 | + mm_segment_t old_fs; | ||
2028 | + char *buf = NULL; | ||
2029 | + ssize_t read_bytes, write_bytes; | ||
2030 | + loff_t size; | ||
2031 | + int err = 0; | ||
2032 | + | ||
2033 | + /* open old file */ | ||
2034 | + unionfs_mntget(dentry, old_bindex); | ||
2035 | + branchget(sb, old_bindex); | ||
2036 | + /* dentry_open calls dput and mntput if it returns an error */ | ||
2037 | + input_file = dentry_open(old_lower_dentry, | ||
2038 | + unionfs_lower_mnt_idx(dentry, old_bindex), | ||
2039 | + O_RDONLY | O_LARGEFILE, current_cred()); | ||
2040 | + if (IS_ERR(input_file)) { | ||
2041 | + dput(old_lower_dentry); | ||
2042 | + err = PTR_ERR(input_file); | ||
2043 | + goto out; | ||
2044 | + } | ||
2045 | + if (unlikely(!input_file->f_op || !input_file->f_op->read)) { | ||
2046 | + err = -EINVAL; | ||
2047 | + goto out_close_in; | ||
2048 | + } | ||
2049 | + | ||
2050 | + /* open new file */ | ||
2051 | + dget(new_lower_dentry); | ||
2052 | + output_mnt = unionfs_mntget(sb->s_root, new_bindex); | ||
2053 | + branchget(sb, new_bindex); | ||
2054 | + output_file = dentry_open(new_lower_dentry, output_mnt, | ||
2055 | + O_RDWR | O_LARGEFILE, current_cred()); | ||
2056 | + if (IS_ERR(output_file)) { | ||
2057 | + err = PTR_ERR(output_file); | ||
2058 | + goto out_close_in2; | ||
2059 | + } | ||
2060 | + if (unlikely(!output_file->f_op || !output_file->f_op->write)) { | ||
2061 | + err = -EINVAL; | ||
2062 | + goto out_close_out; | ||
2063 | + } | ||
2064 | + | ||
2065 | + /* allocating a buffer */ | ||
2066 | + buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
2067 | + if (unlikely(!buf)) { | ||
2068 | + err = -ENOMEM; | ||
2069 | + goto out_close_out; | ||
2070 | + } | ||
2071 | + | ||
2072 | + input_file->f_pos = 0; | ||
2073 | + output_file->f_pos = 0; | ||
2074 | + | ||
2075 | + old_fs = get_fs(); | ||
2076 | + set_fs(KERNEL_DS); | ||
2077 | + | ||
2078 | + size = len; | ||
2079 | + err = 0; | ||
2080 | + do { | ||
2081 | + if (len >= PAGE_SIZE) | ||
2082 | + size = PAGE_SIZE; | ||
2083 | + else if ((len < PAGE_SIZE) && (len > 0)) | ||
2084 | + size = len; | ||
2085 | + | ||
2086 | + len -= PAGE_SIZE; | ||
2087 | + | ||
2088 | + read_bytes = | ||
2089 | + input_file->f_op->read(input_file, | ||
2090 | + (char __user *)buf, size, | ||
2091 | + &input_file->f_pos); | ||
2092 | + if (read_bytes <= 0) { | ||
2093 | + err = read_bytes; | ||
2094 | + break; | ||
2095 | + } | ||
2096 | + | ||
2097 | + /* see Documentation/filesystems/unionfs/issues.txt */ | ||
2098 | + lockdep_off(); | ||
2099 | + write_bytes = | ||
2100 | + output_file->f_op->write(output_file, | ||
2101 | + (char __user *)buf, | ||
2102 | + read_bytes, | ||
2103 | + &output_file->f_pos); | ||
2104 | + lockdep_on(); | ||
2105 | + if ((write_bytes < 0) || (write_bytes < read_bytes)) { | ||
2106 | + err = write_bytes; | ||
2107 | + break; | ||
2108 | + } | ||
2109 | + } while ((read_bytes > 0) && (len > 0)); | ||
2110 | + | ||
2111 | + set_fs(old_fs); | ||
2112 | + | ||
2113 | + kfree(buf); | ||
2114 | + | ||
2115 | + if (!err) | ||
2116 | + err = output_file->f_op->fsync(output_file, 0); | ||
2117 | + | ||
2118 | + if (err) | ||
2119 | + goto out_close_out; | ||
2120 | + | ||
2121 | + if (copyup_file) { | ||
2122 | + *copyup_file = output_file; | ||
2123 | + goto out_close_in; | ||
2124 | + } | ||
2125 | + | ||
2126 | +out_close_out: | ||
2127 | + fput(output_file); | ||
2128 | + | ||
2129 | +out_close_in2: | ||
2130 | + branchput(sb, new_bindex); | ||
2131 | + | ||
2132 | +out_close_in: | ||
2133 | + fput(input_file); | ||
2134 | + | ||
2135 | +out: | ||
2136 | + branchput(sb, old_bindex); | ||
2137 | + | ||
2138 | + return err; | ||
2139 | +} | ||
2140 | + | ||
2141 | +/* | ||
2142 | + * dput the lower references for old and new dentry & clear a lower dentry | ||
2143 | + * pointer | ||
2144 | + */ | ||
2145 | +static void __clear(struct dentry *dentry, struct dentry *old_lower_dentry, | ||
2146 | + int old_bstart, int old_bend, | ||
2147 | + struct dentry *new_lower_dentry, int new_bindex) | ||
2148 | +{ | ||
2149 | + /* get rid of the lower dentry and all its traces */ | ||
2150 | + unionfs_set_lower_dentry_idx(dentry, new_bindex, NULL); | ||
2151 | + dbstart(dentry) = old_bstart; | ||
2152 | + dbend(dentry) = old_bend; | ||
2153 | + | ||
2154 | + dput(new_lower_dentry); | ||
2155 | + dput(old_lower_dentry); | ||
2156 | +} | ||
2157 | + | ||
2158 | +/* | ||
2159 | + * Copy up a dentry to a file of specified name. | ||
2160 | + * | ||
2161 | + * @dir: used to pull the ->i_sb to access other branches | ||
2162 | + * @dentry: the non-negative dentry whose lower_inode we should copy | ||
2163 | + * @bstart: the branch of the lower_inode to copy from | ||
2164 | + * @new_bindex: the branch to create the new file in | ||
2165 | + * @name: the name of the file to create | ||
2166 | + * @namelen: length of @name | ||
2167 | + * @copyup_file: the "struct file" to return (optional) | ||
2168 | + * @len: how many bytes to copy-up? | ||
2169 | + */ | ||
2170 | +int copyup_dentry(struct inode *dir, struct dentry *dentry, int bstart, | ||
2171 | + int new_bindex, const char *name, int namelen, | ||
2172 | + struct file **copyup_file, loff_t len) | ||
2173 | +{ | ||
2174 | + struct dentry *new_lower_dentry; | ||
2175 | + struct dentry *old_lower_dentry = NULL; | ||
2176 | + struct super_block *sb; | ||
2177 | + int err = 0; | ||
2178 | + int old_bindex; | ||
2179 | + int old_bstart; | ||
2180 | + int old_bend; | ||
2181 | + struct dentry *new_lower_parent_dentry = NULL; | ||
2182 | + mm_segment_t oldfs; | ||
2183 | + char *symbuf = NULL; | ||
2184 | + | ||
2185 | + verify_locked(dentry); | ||
2186 | + | ||
2187 | + old_bindex = bstart; | ||
2188 | + old_bstart = dbstart(dentry); | ||
2189 | + old_bend = dbend(dentry); | ||
2190 | + | ||
2191 | + BUG_ON(new_bindex < 0); | ||
2192 | + BUG_ON(new_bindex >= old_bindex); | ||
2193 | + | ||
2194 | + sb = dir->i_sb; | ||
2195 | + | ||
2196 | + err = is_robranch_super(sb, new_bindex); | ||
2197 | + if (err) | ||
2198 | + goto out; | ||
2199 | + | ||
2200 | + /* Create the directory structure above this dentry. */ | ||
2201 | + new_lower_dentry = create_parents(dir, dentry, name, new_bindex); | ||
2202 | + if (IS_ERR(new_lower_dentry)) { | ||
2203 | + err = PTR_ERR(new_lower_dentry); | ||
2204 | + goto out; | ||
2205 | + } | ||
2206 | + | ||
2207 | + old_lower_dentry = unionfs_lower_dentry_idx(dentry, old_bindex); | ||
2208 | + /* we conditionally dput this old_lower_dentry at end of function */ | ||
2209 | + dget(old_lower_dentry); | ||
2210 | + | ||
2211 | + /* For symlinks, we must read the link before we lock the directory. */ | ||
2212 | + if (S_ISLNK(old_lower_dentry->d_inode->i_mode)) { | ||
2213 | + | ||
2214 | + symbuf = kmalloc(PATH_MAX, GFP_KERNEL); | ||
2215 | + if (unlikely(!symbuf)) { | ||
2216 | + __clear(dentry, old_lower_dentry, | ||
2217 | + old_bstart, old_bend, | ||
2218 | + new_lower_dentry, new_bindex); | ||
2219 | + err = -ENOMEM; | ||
2220 | + goto out_free; | ||
2221 | + } | ||
2222 | + | ||
2223 | + oldfs = get_fs(); | ||
2224 | + set_fs(KERNEL_DS); | ||
2225 | + err = old_lower_dentry->d_inode->i_op->readlink( | ||
2226 | + old_lower_dentry, | ||
2227 | + (char __user *)symbuf, | ||
2228 | + PATH_MAX); | ||
2229 | + set_fs(oldfs); | ||
2230 | + if (err < 0) { | ||
2231 | + __clear(dentry, old_lower_dentry, | ||
2232 | + old_bstart, old_bend, | ||
2233 | + new_lower_dentry, new_bindex); | ||
2234 | + goto out_free; | ||
2235 | + } | ||
2236 | + symbuf[err] = '\0'; | ||
2237 | + } | ||
2238 | + | ||
2239 | + /* Now we lock the parent, and create the object in the new branch. */ | ||
2240 | + new_lower_parent_dentry = lock_parent(new_lower_dentry); | ||
2241 | + | ||
2242 | + /* create the new inode */ | ||
2243 | + err = __copyup_ndentry(old_lower_dentry, new_lower_dentry, | ||
2244 | + new_lower_parent_dentry, symbuf); | ||
2245 | + | ||
2246 | + if (err) { | ||
2247 | + __clear(dentry, old_lower_dentry, | ||
2248 | + old_bstart, old_bend, | ||
2249 | + new_lower_dentry, new_bindex); | ||
2250 | + goto out_unlock; | ||
2251 | + } | ||
2252 | + | ||
2253 | + /* We actually copyup the file here. */ | ||
2254 | + if (S_ISREG(old_lower_dentry->d_inode->i_mode)) | ||
2255 | + err = __copyup_reg_data(dentry, new_lower_dentry, new_bindex, | ||
2256 | + old_lower_dentry, old_bindex, | ||
2257 | + copyup_file, len); | ||
2258 | + if (err) | ||
2259 | + goto out_unlink; | ||
2260 | + | ||
2261 | + /* Set permissions. */ | ||
2262 | + err = copyup_permissions(sb, old_lower_dentry, new_lower_dentry); | ||
2263 | + if (err) | ||
2264 | + goto out_unlink; | ||
2265 | + | ||
2266 | +#ifdef CONFIG_UNION_FS_XATTR | ||
2267 | + /* Selinux uses extended attributes for permissions. */ | ||
2268 | + err = copyup_xattrs(old_lower_dentry, new_lower_dentry); | ||
2269 | + if (err) | ||
2270 | + goto out_unlink; | ||
2271 | +#endif /* CONFIG_UNION_FS_XATTR */ | ||
2272 | + | ||
2273 | + /* do not allow files getting deleted to be re-interposed */ | ||
2274 | + if (!d_deleted(dentry)) | ||
2275 | + unionfs_reinterpose(dentry); | ||
2276 | + | ||
2277 | + goto out_unlock; | ||
2278 | + | ||
2279 | +out_unlink: | ||
2280 | + /* | ||
2281 | + * copyup failed, because we possibly ran out of space or | ||
2282 | + * quota, or something else happened so let's unlink; we don't | ||
2283 | + * really care about the return value of vfs_unlink | ||
2284 | + */ | ||
2285 | + vfs_unlink(new_lower_parent_dentry->d_inode, new_lower_dentry); | ||
2286 | + | ||
2287 | + if (copyup_file) { | ||
2288 | + /* need to close the file */ | ||
2289 | + | ||
2290 | + fput(*copyup_file); | ||
2291 | + branchput(sb, new_bindex); | ||
2292 | + } | ||
2293 | + | ||
2294 | + /* | ||
2295 | + * TODO: should we reset the error to something like -EIO? | ||
2296 | + * | ||
2297 | + * If we don't reset, the user may get some nonsensical errors, but | ||
2298 | + * on the other hand, if we reset to EIO, we guarantee that the user | ||
2299 | + * will get a "confusing" error message. | ||
2300 | + */ | ||
2301 | + | ||
2302 | +out_unlock: | ||
2303 | + unlock_dir(new_lower_parent_dentry); | ||
2304 | + | ||
2305 | +out_free: | ||
2306 | + /* | ||
2307 | + * If old_lower_dentry was not a file, then we need to dput it. If | ||
2308 | + * it was a file, then it was already dput indirectly by other | ||
2309 | + * functions we call above which operate on regular files. | ||
2310 | + */ | ||
2311 | + if (old_lower_dentry && old_lower_dentry->d_inode && | ||
2312 | + !S_ISREG(old_lower_dentry->d_inode->i_mode)) | ||
2313 | + dput(old_lower_dentry); | ||
2314 | + kfree(symbuf); | ||
2315 | + | ||
2316 | + if (err) { | ||
2317 | + /* | ||
2318 | + * if directory creation succeeded, but inode copyup failed, | ||
2319 | + * then purge new dentries. | ||
2320 | + */ | ||
2321 | + if (dbstart(dentry) < old_bstart && | ||
2322 | + ibstart(dentry->d_inode) > dbstart(dentry)) | ||
2323 | + __clear(dentry, NULL, old_bstart, old_bend, | ||
2324 | + unionfs_lower_dentry(dentry), dbstart(dentry)); | ||
2325 | + goto out; | ||
2326 | + } | ||
2327 | + if (!S_ISDIR(dentry->d_inode->i_mode)) { | ||
2328 | + unionfs_postcopyup_release(dentry); | ||
2329 | + if (!unionfs_lower_inode(dentry->d_inode)) { | ||
2330 | + /* | ||
2331 | + * If we got here, then we copied up to an | ||
2332 | + * unlinked-open file, whose name is .unionfsXXXXX. | ||
2333 | + */ | ||
2334 | + struct inode *inode = new_lower_dentry->d_inode; | ||
2335 | + atomic_inc(&inode->i_count); | ||
2336 | + unionfs_set_lower_inode_idx(dentry->d_inode, | ||
2337 | + ibstart(dentry->d_inode), | ||
2338 | + inode); | ||
2339 | + } | ||
2340 | + } | ||
2341 | + unionfs_postcopyup_setmnt(dentry); | ||
2342 | + /* sync inode times from copied-up inode to our inode */ | ||
2343 | + unionfs_copy_attr_times(dentry->d_inode); | ||
2344 | + unionfs_check_inode(dir); | ||
2345 | + unionfs_check_dentry(dentry); | ||
2346 | +out: | ||
2347 | + return err; | ||
2348 | +} | ||
2349 | + | ||
2350 | +/* | ||
2351 | + * This function creates a copy of a file represented by 'file' which | ||
2352 | + * currently resides in branch 'bstart' to branch 'new_bindex.' The copy | ||
2353 | + * will be named "name". | ||
2354 | + */ | ||
2355 | +int copyup_named_file(struct inode *dir, struct file *file, char *name, | ||
2356 | + int bstart, int new_bindex, loff_t len) | ||
2357 | +{ | ||
2358 | + int err = 0; | ||
2359 | + struct file *output_file = NULL; | ||
2360 | + | ||
2361 | + err = copyup_dentry(dir, file->f_path.dentry, bstart, new_bindex, | ||
2362 | + name, strlen(name), &output_file, len); | ||
2363 | + if (!err) { | ||
2364 | + fbstart(file) = new_bindex; | ||
2365 | + unionfs_set_lower_file_idx(file, new_bindex, output_file); | ||
2366 | + } | ||
2367 | + | ||
2368 | + return err; | ||
2369 | +} | ||
2370 | + | ||
2371 | +/* | ||
2372 | + * This function creates a copy of a file represented by 'file' which | ||
2373 | + * currently resides in branch 'bstart' to branch 'new_bindex'. | ||
2374 | + */ | ||
2375 | +int copyup_file(struct inode *dir, struct file *file, int bstart, | ||
2376 | + int new_bindex, loff_t len) | ||
2377 | +{ | ||
2378 | + int err = 0; | ||
2379 | + struct file *output_file = NULL; | ||
2380 | + struct dentry *dentry = file->f_path.dentry; | ||
2381 | + | ||
2382 | + err = copyup_dentry(dir, dentry, bstart, new_bindex, | ||
2383 | + dentry->d_name.name, dentry->d_name.len, | ||
2384 | + &output_file, len); | ||
2385 | + if (!err) { | ||
2386 | + fbstart(file) = new_bindex; | ||
2387 | + unionfs_set_lower_file_idx(file, new_bindex, output_file); | ||
2388 | + } | ||
2389 | + | ||
2390 | + return err; | ||
2391 | +} | ||
2392 | + | ||
2393 | +/* purge a dentry's lower-branch states (dput/mntput, etc.) */ | ||
2394 | +static void __cleanup_dentry(struct dentry *dentry, int bindex, | ||
2395 | + int old_bstart, int old_bend) | ||
2396 | +{ | ||
2397 | + int loop_start; | ||
2398 | + int loop_end; | ||
2399 | + int new_bstart = -1; | ||
2400 | + int new_bend = -1; | ||
2401 | + int i; | ||
2402 | + | ||
2403 | + loop_start = min(old_bstart, bindex); | ||
2404 | + loop_end = max(old_bend, bindex); | ||
2405 | + | ||
2406 | + /* | ||
2407 | + * This loop sets the bstart and bend for the new dentry by | ||
2408 | + * traversing from left to right. It also dputs all negative | ||
2409 | + * dentries except bindex | ||
2410 | + */ | ||
2411 | + for (i = loop_start; i <= loop_end; i++) { | ||
2412 | + if (!unionfs_lower_dentry_idx(dentry, i)) | ||
2413 | + continue; | ||
2414 | + | ||
2415 | + if (i == bindex) { | ||
2416 | + new_bend = i; | ||
2417 | + if (new_bstart < 0) | ||
2418 | + new_bstart = i; | ||
2419 | + continue; | ||
2420 | + } | ||
2421 | + | ||
2422 | + if (!unionfs_lower_dentry_idx(dentry, i)->d_inode) { | ||
2423 | + dput(unionfs_lower_dentry_idx(dentry, i)); | ||
2424 | + unionfs_set_lower_dentry_idx(dentry, i, NULL); | ||
2425 | + | ||
2426 | + unionfs_mntput(dentry, i); | ||
2427 | + unionfs_set_lower_mnt_idx(dentry, i, NULL); | ||
2428 | + } else { | ||
2429 | + if (new_bstart < 0) | ||
2430 | + new_bstart = i; | ||
2431 | + new_bend = i; | ||
2432 | + } | ||
2433 | + } | ||
2434 | + | ||
2435 | + if (new_bstart < 0) | ||
2436 | + new_bstart = bindex; | ||
2437 | + if (new_bend < 0) | ||
2438 | + new_bend = bindex; | ||
2439 | + dbstart(dentry) = new_bstart; | ||
2440 | + dbend(dentry) = new_bend; | ||
2441 | + | ||
2442 | +} | ||
2443 | + | ||
2444 | +/* set lower inode ptr and update bstart & bend if necessary */ | ||
2445 | +static void __set_inode(struct dentry *upper, struct dentry *lower, | ||
2446 | + int bindex) | ||
2447 | +{ | ||
2448 | + unionfs_set_lower_inode_idx(upper->d_inode, bindex, | ||
2449 | + igrab(lower->d_inode)); | ||
2450 | + if (likely(ibstart(upper->d_inode) > bindex)) | ||
2451 | + ibstart(upper->d_inode) = bindex; | ||
2452 | + if (likely(ibend(upper->d_inode) < bindex)) | ||
2453 | + ibend(upper->d_inode) = bindex; | ||
2454 | + | ||
2455 | +} | ||
2456 | + | ||
2457 | +/* set lower dentry ptr and update bstart & bend if necessary */ | ||
2458 | +static void __set_dentry(struct dentry *upper, struct dentry *lower, | ||
2459 | + int bindex) | ||
2460 | +{ | ||
2461 | + unionfs_set_lower_dentry_idx(upper, bindex, lower); | ||
2462 | + if (likely(dbstart(upper) > bindex)) | ||
2463 | + dbstart(upper) = bindex; | ||
2464 | + if (likely(dbend(upper) < bindex)) | ||
2465 | + dbend(upper) = bindex; | ||
2466 | +} | ||
2467 | + | ||
2468 | +/* | ||
2469 | + * This function replicates the directory structure up-to given dentry | ||
2470 | + * in the bindex branch. | ||
2471 | + */ | ||
2472 | +struct dentry *create_parents(struct inode *dir, struct dentry *dentry, | ||
2473 | + const char *name, int bindex) | ||
2474 | +{ | ||
2475 | + int err; | ||
2476 | + struct dentry *child_dentry; | ||
2477 | + struct dentry *parent_dentry; | ||
2478 | + struct dentry *lower_parent_dentry = NULL; | ||
2479 | + struct dentry *lower_dentry = NULL; | ||
2480 | + const char *childname; | ||
2481 | + unsigned int childnamelen; | ||
2482 | + int nr_dentry; | ||
2483 | + int count = 0; | ||
2484 | + int old_bstart; | ||
2485 | + int old_bend; | ||
2486 | + struct dentry **path = NULL; | ||
2487 | + struct super_block *sb; | ||
2488 | + | ||
2489 | + verify_locked(dentry); | ||
2490 | + | ||
2491 | + err = is_robranch_super(dir->i_sb, bindex); | ||
2492 | + if (err) { | ||
2493 | + lower_dentry = ERR_PTR(err); | ||
2494 | + goto out; | ||
2495 | + } | ||
2496 | + | ||
2497 | + old_bstart = dbstart(dentry); | ||
2498 | + old_bend = dbend(dentry); | ||
2499 | + | ||
2500 | + lower_dentry = ERR_PTR(-ENOMEM); | ||
2501 | + | ||
2502 | + /* There is no sense allocating any less than the minimum. */ | ||
2503 | + nr_dentry = 1; | ||
2504 | + path = kmalloc(nr_dentry * sizeof(struct dentry *), GFP_KERNEL); | ||
2505 | + if (unlikely(!path)) | ||
2506 | + goto out; | ||
2507 | + | ||
2508 | + /* assume the negative dentry of unionfs as the parent dentry */ | ||
2509 | + parent_dentry = dentry; | ||
2510 | + | ||
2511 | + /* | ||
2512 | + * This loop finds the first parent that exists in the given branch. | ||
2513 | + * We start building the directory structure from there. At the end | ||
2514 | + * of the loop, the following should hold: | ||
2515 | + * - child_dentry is the first nonexistent child | ||
2516 | + * - parent_dentry is the first existent parent | ||
2517 | + * - path[0] is the = deepest child | ||
2518 | + * - path[count] is the first child to create | ||
2519 | + */ | ||
2520 | + do { | ||
2521 | + child_dentry = parent_dentry; | ||
2522 | + | ||
2523 | + /* find the parent directory dentry in unionfs */ | ||
2524 | + parent_dentry = dget_parent(child_dentry); | ||
2525 | + | ||
2526 | + /* find out the lower_parent_dentry in the given branch */ | ||
2527 | + lower_parent_dentry = | ||
2528 | + unionfs_lower_dentry_idx(parent_dentry, bindex); | ||
2529 | + | ||
2530 | + /* grow path table */ | ||
2531 | + if (count == nr_dentry) { | ||
2532 | + void *p; | ||
2533 | + | ||
2534 | + nr_dentry *= 2; | ||
2535 | + p = krealloc(path, nr_dentry * sizeof(struct dentry *), | ||
2536 | + GFP_KERNEL); | ||
2537 | + if (unlikely(!p)) { | ||
2538 | + lower_dentry = ERR_PTR(-ENOMEM); | ||
2539 | + goto out; | ||
2540 | + } | ||
2541 | + path = p; | ||
2542 | + } | ||
2543 | + | ||
2544 | + /* store the child dentry */ | ||
2545 | + path[count++] = child_dentry; | ||
2546 | + } while (!lower_parent_dentry); | ||
2547 | + count--; | ||
2548 | + | ||
2549 | + sb = dentry->d_sb; | ||
2550 | + | ||
2551 | + /* | ||
2552 | + * This code goes between the begin/end labels and basically | ||
2553 | + * emulates a while(child_dentry != dentry), only cleaner and | ||
2554 | + * shorter than what would be a much longer while loop. | ||
2555 | + */ | ||
2556 | +begin: | ||
2557 | + /* get lower parent dir in the current branch */ | ||
2558 | + lower_parent_dentry = unionfs_lower_dentry_idx(parent_dentry, bindex); | ||
2559 | + dput(parent_dentry); | ||
2560 | + | ||
2561 | + /* init the values to lookup */ | ||
2562 | + childname = child_dentry->d_name.name; | ||
2563 | + childnamelen = child_dentry->d_name.len; | ||
2564 | + | ||
2565 | + if (child_dentry != dentry) { | ||
2566 | + /* lookup child in the underlying file system */ | ||
2567 | + lower_dentry = lookup_lck_len(childname, lower_parent_dentry, | ||
2568 | + childnamelen); | ||
2569 | + if (IS_ERR(lower_dentry)) | ||
2570 | + goto out; | ||
2571 | + } else { | ||
2572 | + /* | ||
2573 | + * Is the name a whiteout of the child name ? lookup the | ||
2574 | + * whiteout child in the underlying file system | ||
2575 | + */ | ||
2576 | + lower_dentry = lookup_lck_len(name, lower_parent_dentry, | ||
2577 | + strlen(name)); | ||
2578 | + if (IS_ERR(lower_dentry)) | ||
2579 | + goto out; | ||
2580 | + | ||
2581 | + /* Replace the current dentry (if any) with the new one */ | ||
2582 | + dput(unionfs_lower_dentry_idx(dentry, bindex)); | ||
2583 | + unionfs_set_lower_dentry_idx(dentry, bindex, | ||
2584 | + lower_dentry); | ||
2585 | + | ||
2586 | + __cleanup_dentry(dentry, bindex, old_bstart, old_bend); | ||
2587 | + goto out; | ||
2588 | + } | ||
2589 | + | ||
2590 | + if (lower_dentry->d_inode) { | ||
2591 | + /* | ||
2592 | + * since this already exists we dput to avoid | ||
2593 | + * multiple references on the same dentry | ||
2594 | + */ | ||
2595 | + dput(lower_dentry); | ||
2596 | + } else { | ||
2597 | + struct sioq_args args; | ||
2598 | + | ||
2599 | + /* it's a negative dentry, create a new dir */ | ||
2600 | + lower_parent_dentry = lock_parent(lower_dentry); | ||
2601 | + | ||
2602 | + args.mkdir.parent = lower_parent_dentry->d_inode; | ||
2603 | + args.mkdir.dentry = lower_dentry; | ||
2604 | + args.mkdir.mode = child_dentry->d_inode->i_mode; | ||
2605 | + | ||
2606 | + run_sioq(__unionfs_mkdir, &args); | ||
2607 | + err = args.err; | ||
2608 | + | ||
2609 | + if (!err) | ||
2610 | + err = copyup_permissions(dir->i_sb, child_dentry, | ||
2611 | + lower_dentry); | ||
2612 | + unlock_dir(lower_parent_dentry); | ||
2613 | + if (err) { | ||
2614 | + dput(lower_dentry); | ||
2615 | + lower_dentry = ERR_PTR(err); | ||
2616 | + goto out; | ||
2617 | + } | ||
2618 | + | ||
2619 | + } | ||
2620 | + | ||
2621 | + __set_inode(child_dentry, lower_dentry, bindex); | ||
2622 | + __set_dentry(child_dentry, lower_dentry, bindex); | ||
2623 | + /* | ||
2624 | + * update times of this dentry, but also the parent, because if | ||
2625 | + * we changed, the parent may have changed too. | ||
2626 | + */ | ||
2627 | + fsstack_copy_attr_times(parent_dentry->d_inode, | ||
2628 | + lower_parent_dentry->d_inode); | ||
2629 | + unionfs_copy_attr_times(child_dentry->d_inode); | ||
2630 | + | ||
2631 | + parent_dentry = child_dentry; | ||
2632 | + child_dentry = path[--count]; | ||
2633 | + goto begin; | ||
2634 | +out: | ||
2635 | + /* cleanup any leftover locks from the do/while loop above */ | ||
2636 | + if (IS_ERR(lower_dentry)) | ||
2637 | + while (count) | ||
2638 | + dput(path[count--]); | ||
2639 | + kfree(path); | ||
2640 | + return lower_dentry; | ||
2641 | +} | ||
2642 | + | ||
2643 | +/* | ||
2644 | + * Post-copyup helper to ensure we have valid mnts: set lower mnt of | ||
2645 | + * dentry+parents to the first parent node that has an mnt. | ||
2646 | + */ | ||
2647 | +void unionfs_postcopyup_setmnt(struct dentry *dentry) | ||
2648 | +{ | ||
2649 | + struct dentry *parent, *hasone; | ||
2650 | + int bindex = dbstart(dentry); | ||
2651 | + | ||
2652 | + if (unionfs_lower_mnt_idx(dentry, bindex)) | ||
2653 | + return; | ||
2654 | + hasone = dentry->d_parent; | ||
2655 | + /* this loop should stop at root dentry */ | ||
2656 | + while (!unionfs_lower_mnt_idx(hasone, bindex)) | ||
2657 | + hasone = hasone->d_parent; | ||
2658 | + parent = dentry; | ||
2659 | + while (!unionfs_lower_mnt_idx(parent, bindex)) { | ||
2660 | + unionfs_set_lower_mnt_idx(parent, bindex, | ||
2661 | + unionfs_mntget(hasone, bindex)); | ||
2662 | + parent = parent->d_parent; | ||
2663 | + } | ||
2664 | +} | ||
2665 | + | ||
2666 | +/* | ||
2667 | + * Post-copyup helper to release all non-directory source objects of a | ||
2668 | + * copied-up file. Regular files should have only one lower object. | ||
2669 | + */ | ||
2670 | +void unionfs_postcopyup_release(struct dentry *dentry) | ||
2671 | +{ | ||
2672 | + int bstart, bend; | ||
2673 | + | ||
2674 | + BUG_ON(S_ISDIR(dentry->d_inode->i_mode)); | ||
2675 | + bstart = dbstart(dentry); | ||
2676 | + bend = dbend(dentry); | ||
2677 | + | ||
2678 | + path_put_lowers(dentry, bstart + 1, bend, false); | ||
2679 | + iput_lowers(dentry->d_inode, bstart + 1, bend, false); | ||
2680 | + | ||
2681 | + dbend(dentry) = bstart; | ||
2682 | + ibend(dentry->d_inode) = ibstart(dentry->d_inode) = bstart; | ||
2683 | +} | ||
2684 | diff --git a/fs/unionfs/debug.c b/fs/unionfs/debug.c | ||
2685 | new file mode 100644 | ||
2686 | index 0000000..6092e69 | ||
2687 | --- /dev/null | ||
2688 | +++ b/fs/unionfs/debug.c | ||
2689 | @@ -0,0 +1,548 @@ | ||
2690 | +/* | ||
2691 | + * Copyright (c) 2003-2011 Erez Zadok | ||
2692 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
2693 | + * Copyright (c) 2003-2011 Stony Brook University | ||
2694 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
2695 | + * | ||
2696 | + * This program is free software; you can redistribute it and/or modify | ||
2697 | + * it under the terms of the GNU General Public License version 2 as | ||
2698 | + * published by the Free Software Foundation. | ||
2699 | + */ | ||
2700 | + | ||
2701 | +#include "union.h" | ||
2702 | + | ||
2703 | +/* | ||
2704 | + * Helper debugging functions for maintainers (and for users to report back | ||
2705 | + * useful information back to maintainers) | ||
2706 | + */ | ||
2707 | + | ||
2708 | +/* it's always useful to know what part of the code called us */ | ||
2709 | +#define PRINT_CALLER(fname, fxn, line) \ | ||
2710 | + do { \ | ||
2711 | + if (!printed_caller) { \ | ||
2712 | + pr_debug("PC:%s:%s:%d\n", (fname), (fxn), (line)); \ | ||
2713 | + printed_caller = 1; \ | ||
2714 | + } \ | ||
2715 | + } while (0) | ||
2716 | + | ||
2717 | +/* | ||
2718 | + * __unionfs_check_{inode,dentry,file} perform exhaustive sanity checking on | ||
2719 | + * the fan-out of various Unionfs objects. We check that no lower objects | ||
2720 | + * exist outside the start/end branch range; that all objects within are | ||
2721 | + * non-NULL (with some allowed exceptions); that for every lower file | ||
2722 | + * there's a lower dentry+inode; that the start/end ranges match for all | ||
2723 | + * corresponding lower objects; that open files/symlinks have only one lower | ||
2724 | + * objects, but directories can have several; and more. | ||
2725 | + */ | ||
2726 | +void __unionfs_check_inode(const struct inode *inode, | ||
2727 | + const char *fname, const char *fxn, int line) | ||
2728 | +{ | ||
2729 | + int bindex; | ||
2730 | + int istart, iend; | ||
2731 | + struct inode *lower_inode; | ||
2732 | + struct super_block *sb; | ||
2733 | + int printed_caller = 0; | ||
2734 | + void *poison_ptr; | ||
2735 | + | ||
2736 | + /* for inodes now */ | ||
2737 | + BUG_ON(!inode); | ||
2738 | + sb = inode->i_sb; | ||
2739 | + istart = ibstart(inode); | ||
2740 | + iend = ibend(inode); | ||
2741 | + /* don't check inode if no lower branches */ | ||
2742 | + if (istart < 0 && iend < 0) | ||
2743 | + return; | ||
2744 | + if (unlikely(istart > iend)) { | ||
2745 | + PRINT_CALLER(fname, fxn, line); | ||
2746 | + pr_debug(" Ci0: inode=%p istart/end=%d:%d\n", | ||
2747 | + inode, istart, iend); | ||
2748 | + } | ||
2749 | + if (unlikely((istart == -1 && iend != -1) || | ||
2750 | + (istart != -1 && iend == -1))) { | ||
2751 | + PRINT_CALLER(fname, fxn, line); | ||
2752 | + pr_debug(" Ci1: inode=%p istart/end=%d:%d\n", | ||
2753 | + inode, istart, iend); | ||
2754 | + } | ||
2755 | + if (!S_ISDIR(inode->i_mode)) { | ||
2756 | + if (unlikely(iend != istart)) { | ||
2757 | + PRINT_CALLER(fname, fxn, line); | ||
2758 | + pr_debug(" Ci2: inode=%p istart=%d iend=%d\n", | ||
2759 | + inode, istart, iend); | ||
2760 | + } | ||
2761 | + } | ||
2762 | + | ||
2763 | + for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) { | ||
2764 | + if (unlikely(!UNIONFS_I(inode))) { | ||
2765 | + PRINT_CALLER(fname, fxn, line); | ||
2766 | + pr_debug(" Ci3: no inode_info %p\n", inode); | ||
2767 | + return; | ||
2768 | + } | ||
2769 | + if (unlikely(!UNIONFS_I(inode)->lower_inodes)) { | ||
2770 | + PRINT_CALLER(fname, fxn, line); | ||
2771 | + pr_debug(" Ci4: no lower_inodes %p\n", inode); | ||
2772 | + return; | ||
2773 | + } | ||
2774 | + lower_inode = unionfs_lower_inode_idx(inode, bindex); | ||
2775 | + if (lower_inode) { | ||
2776 | + memset(&poison_ptr, POISON_INUSE, sizeof(void *)); | ||
2777 | + if (unlikely(bindex < istart || bindex > iend)) { | ||
2778 | + PRINT_CALLER(fname, fxn, line); | ||
2779 | + pr_debug(" Ci5: inode/linode=%p:%p bindex=%d " | ||
2780 | + "istart/end=%d:%d\n", inode, | ||
2781 | + lower_inode, bindex, istart, iend); | ||
2782 | + } else if (unlikely(lower_inode == poison_ptr)) { | ||
2783 | + /* freed inode! */ | ||
2784 | + PRINT_CALLER(fname, fxn, line); | ||
2785 | + pr_debug(" Ci6: inode/linode=%p:%p bindex=%d " | ||
2786 | + "istart/end=%d:%d\n", inode, | ||
2787 | + lower_inode, bindex, istart, iend); | ||
2788 | + } | ||
2789 | + continue; | ||
2790 | + } | ||
2791 | + /* if we get here, then lower_inode == NULL */ | ||
2792 | + if (bindex < istart || bindex > iend) | ||
2793 | + continue; | ||
2794 | + /* | ||
2795 | + * directories can have NULL lower inodes in b/t start/end, | ||
2796 | + * but NOT if at the start/end range. | ||
2797 | + */ | ||
2798 | + if (unlikely(S_ISDIR(inode->i_mode) && | ||
2799 | + bindex > istart && bindex < iend)) | ||
2800 | + continue; | ||
2801 | + PRINT_CALLER(fname, fxn, line); | ||
2802 | + pr_debug(" Ci7: inode/linode=%p:%p " | ||
2803 | + "bindex=%d istart/end=%d:%d\n", | ||
2804 | + inode, lower_inode, bindex, istart, iend); | ||
2805 | + } | ||
2806 | +} | ||
2807 | + | ||
2808 | +void __unionfs_check_dentry(const struct dentry *dentry, | ||
2809 | + const char *fname, const char *fxn, int line) | ||
2810 | +{ | ||
2811 | + int bindex; | ||
2812 | + int dstart, dend, istart, iend; | ||
2813 | + struct dentry *lower_dentry; | ||
2814 | + struct inode *inode, *lower_inode; | ||
2815 | + struct super_block *sb; | ||
2816 | + struct vfsmount *lower_mnt; | ||
2817 | + int printed_caller = 0; | ||
2818 | + void *poison_ptr; | ||
2819 | + | ||
2820 | + BUG_ON(!dentry); | ||
2821 | + sb = dentry->d_sb; | ||
2822 | + inode = dentry->d_inode; | ||
2823 | + dstart = dbstart(dentry); | ||
2824 | + dend = dbend(dentry); | ||
2825 | + /* don't check dentry/mnt if no lower branches */ | ||
2826 | + if (dstart < 0 && dend < 0) | ||
2827 | + goto check_inode; | ||
2828 | + BUG_ON(dstart > dend); | ||
2829 | + | ||
2830 | + if (unlikely((dstart == -1 && dend != -1) || | ||
2831 | + (dstart != -1 && dend == -1))) { | ||
2832 | + PRINT_CALLER(fname, fxn, line); | ||
2833 | + pr_debug(" CD0: dentry=%p dstart/end=%d:%d\n", | ||
2834 | + dentry, dstart, dend); | ||
2835 | + } | ||
2836 | + /* | ||
2837 | + * check for NULL dentries inside the start/end range, or | ||
2838 | + * non-NULL dentries outside the start/end range. | ||
2839 | + */ | ||
2840 | + for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) { | ||
2841 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
2842 | + if (lower_dentry) { | ||
2843 | + if (unlikely(bindex < dstart || bindex > dend)) { | ||
2844 | + PRINT_CALLER(fname, fxn, line); | ||
2845 | + pr_debug(" CD1: dentry/lower=%p:%p(%p) " | ||
2846 | + "bindex=%d dstart/end=%d:%d\n", | ||
2847 | + dentry, lower_dentry, | ||
2848 | + (lower_dentry ? lower_dentry->d_inode : | ||
2849 | + (void *) -1L), | ||
2850 | + bindex, dstart, dend); | ||
2851 | + } | ||
2852 | + } else { /* lower_dentry == NULL */ | ||
2853 | + if (bindex < dstart || bindex > dend) | ||
2854 | + continue; | ||
2855 | + /* | ||
2856 | + * Directories can have NULL lower inodes in b/t | ||
2857 | + * start/end, but NOT if at the start/end range. | ||
2858 | + * Ignore this rule, however, if this is a NULL | ||
2859 | + * dentry or a deleted dentry. | ||
2860 | + */ | ||
2861 | + if (unlikely(!d_deleted((struct dentry *) dentry) && | ||
2862 | + inode && | ||
2863 | + !(inode && S_ISDIR(inode->i_mode) && | ||
2864 | + bindex > dstart && bindex < dend))) { | ||
2865 | + PRINT_CALLER(fname, fxn, line); | ||
2866 | + pr_debug(" CD2: dentry/lower=%p:%p(%p) " | ||
2867 | + "bindex=%d dstart/end=%d:%d\n", | ||
2868 | + dentry, lower_dentry, | ||
2869 | + (lower_dentry ? | ||
2870 | + lower_dentry->d_inode : | ||
2871 | + (void *) -1L), | ||
2872 | + bindex, dstart, dend); | ||
2873 | + } | ||
2874 | + } | ||
2875 | + } | ||
2876 | + | ||
2877 | + /* check for vfsmounts same as for dentries */ | ||
2878 | + for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) { | ||
2879 | + lower_mnt = unionfs_lower_mnt_idx(dentry, bindex); | ||
2880 | + if (lower_mnt) { | ||
2881 | + if (unlikely(bindex < dstart || bindex > dend)) { | ||
2882 | + PRINT_CALLER(fname, fxn, line); | ||
2883 | + pr_debug(" CM0: dentry/lmnt=%p:%p bindex=%d " | ||
2884 | + "dstart/end=%d:%d\n", dentry, | ||
2885 | + lower_mnt, bindex, dstart, dend); | ||
2886 | + } | ||
2887 | + } else { /* lower_mnt == NULL */ | ||
2888 | + if (bindex < dstart || bindex > dend) | ||
2889 | + continue; | ||
2890 | + /* | ||
2891 | + * Directories can have NULL lower inodes in b/t | ||
2892 | + * start/end, but NOT if at the start/end range. | ||
2893 | + * Ignore this rule, however, if this is a NULL | ||
2894 | + * dentry. | ||
2895 | + */ | ||
2896 | + if (unlikely(inode && | ||
2897 | + !(inode && S_ISDIR(inode->i_mode) && | ||
2898 | + bindex > dstart && bindex < dend))) { | ||
2899 | + PRINT_CALLER(fname, fxn, line); | ||
2900 | + pr_debug(" CM1: dentry/lmnt=%p:%p " | ||
2901 | + "bindex=%d dstart/end=%d:%d\n", | ||
2902 | + dentry, lower_mnt, bindex, | ||
2903 | + dstart, dend); | ||
2904 | + } | ||
2905 | + } | ||
2906 | + } | ||
2907 | + | ||
2908 | +check_inode: | ||
2909 | + /* for inodes now */ | ||
2910 | + if (!inode) | ||
2911 | + return; | ||
2912 | + istart = ibstart(inode); | ||
2913 | + iend = ibend(inode); | ||
2914 | + /* don't check inode if no lower branches */ | ||
2915 | + if (istart < 0 && iend < 0) | ||
2916 | + return; | ||
2917 | + BUG_ON(istart > iend); | ||
2918 | + if (unlikely((istart == -1 && iend != -1) || | ||
2919 | + (istart != -1 && iend == -1))) { | ||
2920 | + PRINT_CALLER(fname, fxn, line); | ||
2921 | + pr_debug(" CI0: dentry/inode=%p:%p istart/end=%d:%d\n", | ||
2922 | + dentry, inode, istart, iend); | ||
2923 | + } | ||
2924 | + if (unlikely(istart != dstart)) { | ||
2925 | + PRINT_CALLER(fname, fxn, line); | ||
2926 | + pr_debug(" CI1: dentry/inode=%p:%p istart=%d dstart=%d\n", | ||
2927 | + dentry, inode, istart, dstart); | ||
2928 | + } | ||
2929 | + if (unlikely(iend != dend)) { | ||
2930 | + PRINT_CALLER(fname, fxn, line); | ||
2931 | + pr_debug(" CI2: dentry/inode=%p:%p iend=%d dend=%d\n", | ||
2932 | + dentry, inode, iend, dend); | ||
2933 | + } | ||
2934 | + | ||
2935 | + if (!S_ISDIR(inode->i_mode)) { | ||
2936 | + if (unlikely(dend != dstart)) { | ||
2937 | + PRINT_CALLER(fname, fxn, line); | ||
2938 | + pr_debug(" CI3: dentry/inode=%p:%p dstart=%d dend=%d\n", | ||
2939 | + dentry, inode, dstart, dend); | ||
2940 | + } | ||
2941 | + if (unlikely(iend != istart)) { | ||
2942 | + PRINT_CALLER(fname, fxn, line); | ||
2943 | + pr_debug(" CI4: dentry/inode=%p:%p istart=%d iend=%d\n", | ||
2944 | + dentry, inode, istart, iend); | ||
2945 | + } | ||
2946 | + } | ||
2947 | + | ||
2948 | + for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) { | ||
2949 | + lower_inode = unionfs_lower_inode_idx(inode, bindex); | ||
2950 | + if (lower_inode) { | ||
2951 | + memset(&poison_ptr, POISON_INUSE, sizeof(void *)); | ||
2952 | + if (unlikely(bindex < istart || bindex > iend)) { | ||
2953 | + PRINT_CALLER(fname, fxn, line); | ||
2954 | + pr_debug(" CI5: dentry/linode=%p:%p bindex=%d " | ||
2955 | + "istart/end=%d:%d\n", dentry, | ||
2956 | + lower_inode, bindex, istart, iend); | ||
2957 | + } else if (unlikely(lower_inode == poison_ptr)) { | ||
2958 | + /* freed inode! */ | ||
2959 | + PRINT_CALLER(fname, fxn, line); | ||
2960 | + pr_debug(" CI6: dentry/linode=%p:%p bindex=%d " | ||
2961 | + "istart/end=%d:%d\n", dentry, | ||
2962 | + lower_inode, bindex, istart, iend); | ||
2963 | + } | ||
2964 | + continue; | ||
2965 | + } | ||
2966 | + /* if we get here, then lower_inode == NULL */ | ||
2967 | + if (bindex < istart || bindex > iend) | ||
2968 | + continue; | ||
2969 | + /* | ||
2970 | + * directories can have NULL lower inodes in b/t start/end, | ||
2971 | + * but NOT if at the start/end range. | ||
2972 | + */ | ||
2973 | + if (unlikely(S_ISDIR(inode->i_mode) && | ||
2974 | + bindex > istart && bindex < iend)) | ||
2975 | + continue; | ||
2976 | + PRINT_CALLER(fname, fxn, line); | ||
2977 | + pr_debug(" CI7: dentry/linode=%p:%p " | ||
2978 | + "bindex=%d istart/end=%d:%d\n", | ||
2979 | + dentry, lower_inode, bindex, istart, iend); | ||
2980 | + } | ||
2981 | + | ||
2982 | + /* | ||
2983 | + * If it's a directory, then intermediate objects b/t start/end can | ||
2984 | + * be NULL. But, check that all three are NULL: lower dentry, mnt, | ||
2985 | + * and inode. | ||
2986 | + */ | ||
2987 | + if (dstart >= 0 && dend >= 0 && S_ISDIR(inode->i_mode)) | ||
2988 | + for (bindex = dstart+1; bindex < dend; bindex++) { | ||
2989 | + lower_inode = unionfs_lower_inode_idx(inode, bindex); | ||
2990 | + lower_dentry = unionfs_lower_dentry_idx(dentry, | ||
2991 | + bindex); | ||
2992 | + lower_mnt = unionfs_lower_mnt_idx(dentry, bindex); | ||
2993 | + if (unlikely(!((lower_inode && lower_dentry && | ||
2994 | + lower_mnt) || | ||
2995 | + (!lower_inode && | ||
2996 | + !lower_dentry && !lower_mnt)))) { | ||
2997 | + PRINT_CALLER(fname, fxn, line); | ||
2998 | + pr_debug(" Cx: lmnt/ldentry/linode=%p:%p:%p " | ||
2999 | + "bindex=%d dstart/end=%d:%d\n", | ||
3000 | + lower_mnt, lower_dentry, lower_inode, | ||
3001 | + bindex, dstart, dend); | ||
3002 | + } | ||
3003 | + } | ||
3004 | + /* check if lower inode is newer than upper one (it shouldn't) */ | ||
3005 | + if (unlikely(is_newer_lower(dentry) && !is_negative_lower(dentry))) { | ||
3006 | + PRINT_CALLER(fname, fxn, line); | ||
3007 | + for (bindex = ibstart(inode); bindex <= ibend(inode); | ||
3008 | + bindex++) { | ||
3009 | + lower_inode = unionfs_lower_inode_idx(inode, bindex); | ||
3010 | + if (unlikely(!lower_inode)) | ||
3011 | + continue; | ||
3012 | + pr_debug(" CI8: bindex=%d mtime/lmtime=%lu.%lu/%lu.%lu " | ||
3013 | + "ctime/lctime=%lu.%lu/%lu.%lu\n", | ||
3014 | + bindex, | ||
3015 | + inode->i_mtime.tv_sec, | ||
3016 | + inode->i_mtime.tv_nsec, | ||
3017 | + lower_inode->i_mtime.tv_sec, | ||
3018 | + lower_inode->i_mtime.tv_nsec, | ||
3019 | + inode->i_ctime.tv_sec, | ||
3020 | + inode->i_ctime.tv_nsec, | ||
3021 | + lower_inode->i_ctime.tv_sec, | ||
3022 | + lower_inode->i_ctime.tv_nsec); | ||
3023 | + } | ||
3024 | + } | ||
3025 | +} | ||
3026 | + | ||
3027 | +void __unionfs_check_file(const struct file *file, | ||
3028 | + const char *fname, const char *fxn, int line) | ||
3029 | +{ | ||
3030 | + int bindex; | ||
3031 | + int dstart, dend, fstart, fend; | ||
3032 | + struct dentry *dentry; | ||
3033 | + struct file *lower_file; | ||
3034 | + struct inode *inode; | ||
3035 | + struct super_block *sb; | ||
3036 | + int printed_caller = 0; | ||
3037 | + | ||
3038 | + BUG_ON(!file); | ||
3039 | + dentry = file->f_path.dentry; | ||
3040 | + sb = dentry->d_sb; | ||
3041 | + dstart = dbstart(dentry); | ||
3042 | + dend = dbend(dentry); | ||
3043 | + BUG_ON(dstart > dend); | ||
3044 | + fstart = fbstart(file); | ||
3045 | + fend = fbend(file); | ||
3046 | + BUG_ON(fstart > fend); | ||
3047 | + | ||
3048 | + if (unlikely((fstart == -1 && fend != -1) || | ||
3049 | + (fstart != -1 && fend == -1))) { | ||
3050 | + PRINT_CALLER(fname, fxn, line); | ||
3051 | + pr_debug(" CF0: file/dentry=%p:%p fstart/end=%d:%d\n", | ||
3052 | + file, dentry, fstart, fend); | ||
3053 | + } | ||
3054 | + if (unlikely(fstart != dstart)) { | ||
3055 | + PRINT_CALLER(fname, fxn, line); | ||
3056 | + pr_debug(" CF1: file/dentry=%p:%p fstart=%d dstart=%d\n", | ||
3057 | + file, dentry, fstart, dstart); | ||
3058 | + } | ||
3059 | + if (unlikely(fend != dend)) { | ||
3060 | + PRINT_CALLER(fname, fxn, line); | ||
3061 | + pr_debug(" CF2: file/dentry=%p:%p fend=%d dend=%d\n", | ||
3062 | + file, dentry, fend, dend); | ||
3063 | + } | ||
3064 | + inode = dentry->d_inode; | ||
3065 | + if (!S_ISDIR(inode->i_mode)) { | ||
3066 | + if (unlikely(fend != fstart)) { | ||
3067 | + PRINT_CALLER(fname, fxn, line); | ||
3068 | + pr_debug(" CF3: file/inode=%p:%p fstart=%d fend=%d\n", | ||
3069 | + file, inode, fstart, fend); | ||
3070 | + } | ||
3071 | + if (unlikely(dend != dstart)) { | ||
3072 | + PRINT_CALLER(fname, fxn, line); | ||
3073 | + pr_debug(" CF4: file/dentry=%p:%p dstart=%d dend=%d\n", | ||
3074 | + file, dentry, dstart, dend); | ||
3075 | + } | ||
3076 | + } | ||
3077 | + | ||
3078 | + /* | ||
3079 | + * check for NULL dentries inside the start/end range, or | ||
3080 | + * non-NULL dentries outside the start/end range. | ||
3081 | + */ | ||
3082 | + for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) { | ||
3083 | + lower_file = unionfs_lower_file_idx(file, bindex); | ||
3084 | + if (lower_file) { | ||
3085 | + if (unlikely(bindex < fstart || bindex > fend)) { | ||
3086 | + PRINT_CALLER(fname, fxn, line); | ||
3087 | + pr_debug(" CF5: file/lower=%p:%p bindex=%d " | ||
3088 | + "fstart/end=%d:%d\n", file, | ||
3089 | + lower_file, bindex, fstart, fend); | ||
3090 | + } | ||
3091 | + } else { /* lower_file == NULL */ | ||
3092 | + if (bindex >= fstart && bindex <= fend) { | ||
3093 | + /* | ||
3094 | + * directories can have NULL lower inodes in | ||
3095 | + * b/t start/end, but NOT if at the | ||
3096 | + * start/end range. | ||
3097 | + */ | ||
3098 | + if (unlikely(!(S_ISDIR(inode->i_mode) && | ||
3099 | + bindex > fstart && | ||
3100 | + bindex < fend))) { | ||
3101 | + PRINT_CALLER(fname, fxn, line); | ||
3102 | + pr_debug(" CF6: file/lower=%p:%p " | ||
3103 | + "bindex=%d fstart/end=%d:%d\n", | ||
3104 | + file, lower_file, bindex, | ||
3105 | + fstart, fend); | ||
3106 | + } | ||
3107 | + } | ||
3108 | + } | ||
3109 | + } | ||
3110 | + | ||
3111 | + __unionfs_check_dentry(dentry, fname, fxn, line); | ||
3112 | +} | ||
3113 | + | ||
3114 | +void __unionfs_check_nd(const struct nameidata *nd, | ||
3115 | + const char *fname, const char *fxn, int line) | ||
3116 | +{ | ||
3117 | + struct file *file; | ||
3118 | + int printed_caller = 0; | ||
3119 | + | ||
3120 | + if (unlikely(!nd)) | ||
3121 | + return; | ||
3122 | + if (nd->flags & LOOKUP_OPEN) { | ||
3123 | + file = nd->intent.open.file; | ||
3124 | + if (unlikely(file->f_path.dentry && | ||
3125 | + strcmp(file->f_path.dentry->d_sb->s_type->name, | ||
3126 | + UNIONFS_NAME))) { | ||
3127 | + PRINT_CALLER(fname, fxn, line); | ||
3128 | + pr_debug(" CND1: lower_file of type %s\n", | ||
3129 | + file->f_path.dentry->d_sb->s_type->name); | ||
3130 | + } | ||
3131 | + } | ||
3132 | +} | ||
3133 | + | ||
3134 | +static unsigned int __mnt_get_count(struct vfsmount *mnt) | ||
3135 | +{ | ||
3136 | +#ifdef CONFIG_SMP | ||
3137 | + unsigned int count = 0; | ||
3138 | + int cpu; | ||
3139 | + | ||
3140 | + for_each_possible_cpu(cpu) { | ||
3141 | + count += per_cpu_ptr(mnt->mnt_pcp, cpu)->mnt_count; | ||
3142 | + } | ||
3143 | + | ||
3144 | + return count; | ||
3145 | +#else | ||
3146 | + return mnt->mnt_count; | ||
3147 | +#endif | ||
3148 | +} | ||
3149 | + | ||
3150 | +/* useful to track vfsmount leaks that could cause EBUSY on unmount */ | ||
3151 | +void __show_branch_counts(const struct super_block *sb, | ||
3152 | + const char *file, const char *fxn, int line) | ||
3153 | +{ | ||
3154 | + int i; | ||
3155 | + struct vfsmount *mnt; | ||
3156 | + | ||
3157 | + pr_debug("BC:"); | ||
3158 | + for (i = 0; i < sbmax(sb); i++) { | ||
3159 | + if (likely(sb->s_root)) | ||
3160 | + mnt = UNIONFS_D(sb->s_root)->lower_paths[i].mnt; | ||
3161 | + else | ||
3162 | + mnt = NULL; | ||
3163 | + printk(KERN_CONT "%d:", | ||
3164 | + (mnt ? __mnt_get_count(mnt) : -99)); | ||
3165 | + } | ||
3166 | + printk(KERN_CONT "%s:%s:%d\n", file, fxn, line); | ||
3167 | +} | ||
3168 | + | ||
3169 | +void __show_inode_times(const struct inode *inode, | ||
3170 | + const char *file, const char *fxn, int line) | ||
3171 | +{ | ||
3172 | + struct inode *lower_inode; | ||
3173 | + int bindex; | ||
3174 | + | ||
3175 | + for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) { | ||
3176 | + lower_inode = unionfs_lower_inode_idx(inode, bindex); | ||
3177 | + if (unlikely(!lower_inode)) | ||
3178 | + continue; | ||
3179 | + pr_debug("IT(%lu:%d): %s:%s:%d " | ||
3180 | + "um=%lu/%lu lm=%lu/%lu uc=%lu/%lu lc=%lu/%lu\n", | ||
3181 | + inode->i_ino, bindex, | ||
3182 | + file, fxn, line, | ||
3183 | + inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec, | ||
3184 | + lower_inode->i_mtime.tv_sec, | ||
3185 | + lower_inode->i_mtime.tv_nsec, | ||
3186 | + inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec, | ||
3187 | + lower_inode->i_ctime.tv_sec, | ||
3188 | + lower_inode->i_ctime.tv_nsec); | ||
3189 | + } | ||
3190 | +} | ||
3191 | + | ||
3192 | +void __show_dinode_times(const struct dentry *dentry, | ||
3193 | + const char *file, const char *fxn, int line) | ||
3194 | +{ | ||
3195 | + struct inode *inode = dentry->d_inode; | ||
3196 | + struct inode *lower_inode; | ||
3197 | + int bindex; | ||
3198 | + | ||
3199 | + for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) { | ||
3200 | + lower_inode = unionfs_lower_inode_idx(inode, bindex); | ||
3201 | + if (!lower_inode) | ||
3202 | + continue; | ||
3203 | + pr_debug("DT(%s:%lu:%d): %s:%s:%d " | ||
3204 | + "um=%lu/%lu lm=%lu/%lu uc=%lu/%lu lc=%lu/%lu\n", | ||
3205 | + dentry->d_name.name, inode->i_ino, bindex, | ||
3206 | + file, fxn, line, | ||
3207 | + inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec, | ||
3208 | + lower_inode->i_mtime.tv_sec, | ||
3209 | + lower_inode->i_mtime.tv_nsec, | ||
3210 | + inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec, | ||
3211 | + lower_inode->i_ctime.tv_sec, | ||
3212 | + lower_inode->i_ctime.tv_nsec); | ||
3213 | + } | ||
3214 | +} | ||
3215 | + | ||
3216 | +void __show_inode_counts(const struct inode *inode, | ||
3217 | + const char *file, const char *fxn, int line) | ||
3218 | +{ | ||
3219 | + struct inode *lower_inode; | ||
3220 | + int bindex; | ||
3221 | + | ||
3222 | + if (unlikely(!inode)) { | ||
3223 | + pr_debug("SiC: Null inode\n"); | ||
3224 | + return; | ||
3225 | + } | ||
3226 | + for (bindex = sbstart(inode->i_sb); bindex <= sbend(inode->i_sb); | ||
3227 | + bindex++) { | ||
3228 | + lower_inode = unionfs_lower_inode_idx(inode, bindex); | ||
3229 | + if (unlikely(!lower_inode)) | ||
3230 | + continue; | ||
3231 | + pr_debug("SIC(%lu:%d:%d): lc=%d %s:%s:%d\n", | ||
3232 | + inode->i_ino, bindex, | ||
3233 | + atomic_read(&(inode)->i_count), | ||
3234 | + atomic_read(&(lower_inode)->i_count), | ||
3235 | + file, fxn, line); | ||
3236 | + } | ||
3237 | +} | ||
3238 | diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c | ||
3239 | new file mode 100644 | ||
3240 | index 0000000..c0205a4 | ||
3241 | --- /dev/null | ||
3242 | +++ b/fs/unionfs/dentry.c | ||
3243 | @@ -0,0 +1,406 @@ | ||
3244 | +/* | ||
3245 | + * Copyright (c) 2003-2011 Erez Zadok | ||
3246 | + * Copyright (c) 2003-2006 Charles P. Wright | ||
3247 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
3248 | + * Copyright (c) 2005-2006 Junjiro Okajima | ||
3249 | + * Copyright (c) 2005 Arun M. Krishnakumar | ||
3250 | + * Copyright (c) 2004-2006 David P. Quigley | ||
3251 | + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair | ||
3252 | + * Copyright (c) 2003 Puja Gupta | ||
3253 | + * Copyright (c) 2003 Harikesavan Krishnan | ||
3254 | + * Copyright (c) 2003-2011 Stony Brook University | ||
3255 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
3256 | + * | ||
3257 | + * This program is free software; you can redistribute it and/or modify | ||
3258 | + * it under the terms of the GNU General Public License version 2 as | ||
3259 | + * published by the Free Software Foundation. | ||
3260 | + */ | ||
3261 | + | ||
3262 | +#include "union.h" | ||
3263 | + | ||
3264 | +bool is_negative_lower(const struct dentry *dentry) | ||
3265 | +{ | ||
3266 | + int bindex; | ||
3267 | + struct dentry *lower_dentry; | ||
3268 | + | ||
3269 | + BUG_ON(!dentry); | ||
3270 | + /* cache coherency: check if file was deleted on lower branch */ | ||
3271 | + if (dbstart(dentry) < 0) | ||
3272 | + return true; | ||
3273 | + for (bindex = dbstart(dentry); bindex <= dbend(dentry); bindex++) { | ||
3274 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
3275 | + /* unhashed (i.e., unlinked) lower dentries don't count */ | ||
3276 | + if (lower_dentry && lower_dentry->d_inode && | ||
3277 | + !d_deleted(lower_dentry) && | ||
3278 | + !(lower_dentry->d_flags & DCACHE_NFSFS_RENAMED)) | ||
3279 | + return false; | ||
3280 | + } | ||
3281 | + return true; | ||
3282 | +} | ||
3283 | + | ||
3284 | +static inline void __dput_lowers(struct dentry *dentry, int start, int end) | ||
3285 | +{ | ||
3286 | + struct dentry *lower_dentry; | ||
3287 | + int bindex; | ||
3288 | + | ||
3289 | + if (start < 0) | ||
3290 | + return; | ||
3291 | + for (bindex = start; bindex <= end; bindex++) { | ||
3292 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
3293 | + if (!lower_dentry) | ||
3294 | + continue; | ||
3295 | + unionfs_set_lower_dentry_idx(dentry, bindex, NULL); | ||
3296 | + dput(lower_dentry); | ||
3297 | + } | ||
3298 | +} | ||
3299 | + | ||
3300 | +/* | ||
3301 | + * Purge and invalidate as many data pages of a unionfs inode. This is | ||
3302 | + * called when the lower inode has changed, and we want to force processes | ||
3303 | + * to re-get the new data. | ||
3304 | + */ | ||
3305 | +static inline void purge_inode_data(struct inode *inode) | ||
3306 | +{ | ||
3307 | + /* remove all non-private mappings */ | ||
3308 | + unmap_mapping_range(inode->i_mapping, 0, 0, 0); | ||
3309 | + /* invalidate as many pages as possible */ | ||
3310 | + invalidate_mapping_pages(inode->i_mapping, 0, -1); | ||
3311 | + /* | ||
3312 | + * Don't try to truncate_inode_pages here, because this could lead | ||
3313 | + * to a deadlock between some of address_space ops and dentry | ||
3314 | + * revalidation: the address space op is invoked with a lock on our | ||
3315 | + * own page, and truncate_inode_pages will block on locked pages. | ||
3316 | + */ | ||
3317 | +} | ||
3318 | + | ||
3319 | +/* | ||
3320 | + * Revalidate a single file/symlink/special dentry. Assume that info nodes | ||
3321 | + * of the @dentry and its @parent are locked. Assume parent is valid, | ||
3322 | + * otherwise return false (and let's hope the VFS will try to re-lookup this | ||
3323 | + * dentry). Returns true if valid, false otherwise. | ||
3324 | + */ | ||
3325 | +bool __unionfs_d_revalidate(struct dentry *dentry, struct dentry *parent, | ||
3326 | + bool willwrite) | ||
3327 | +{ | ||
3328 | + bool valid = true; /* default is valid */ | ||
3329 | + struct dentry *lower_dentry; | ||
3330 | + struct dentry *result; | ||
3331 | + int bindex, bstart, bend; | ||
3332 | + int sbgen, dgen, pdgen; | ||
3333 | + int positive = 0; | ||
3334 | + int interpose_flag; | ||
3335 | + | ||
3336 | + verify_locked(dentry); | ||
3337 | + verify_locked(parent); | ||
3338 | + | ||
3339 | + /* if the dentry is unhashed, do NOT revalidate */ | ||
3340 | + if (d_deleted(dentry)) | ||
3341 | + goto out; | ||
3342 | + | ||
3343 | + dgen = atomic_read(&UNIONFS_D(dentry)->generation); | ||
3344 | + | ||
3345 | + if (is_newer_lower(dentry)) { | ||
3346 | + /* root dentry is always valid */ | ||
3347 | + if (IS_ROOT(dentry)) { | ||
3348 | + unionfs_copy_attr_times(dentry->d_inode); | ||
3349 | + } else { | ||
3350 | + /* | ||
3351 | + * reset generation number to zero, guaranteed to be | ||
3352 | + * "old" | ||
3353 | + */ | ||
3354 | + dgen = 0; | ||
3355 | + atomic_set(&UNIONFS_D(dentry)->generation, dgen); | ||
3356 | + } | ||
3357 | + if (!willwrite) | ||
3358 | + purge_inode_data(dentry->d_inode); | ||
3359 | + } | ||
3360 | + | ||
3361 | + sbgen = atomic_read(&UNIONFS_SB(dentry->d_sb)->generation); | ||
3362 | + | ||
3363 | + BUG_ON(dbstart(dentry) == -1); | ||
3364 | + if (dentry->d_inode) | ||
3365 | + positive = 1; | ||
3366 | + | ||
3367 | + /* if our dentry is valid, then validate all lower ones */ | ||
3368 | + if (sbgen == dgen) | ||
3369 | + goto validate_lowers; | ||
3370 | + | ||
3371 | + /* The root entry should always be valid */ | ||
3372 | + BUG_ON(IS_ROOT(dentry)); | ||
3373 | + | ||
3374 | + /* We can't work correctly if our parent isn't valid. */ | ||
3375 | + pdgen = atomic_read(&UNIONFS_D(parent)->generation); | ||
3376 | + | ||
3377 | + /* Free the pointers for our inodes and this dentry. */ | ||
3378 | + path_put_lowers_all(dentry, false); | ||
3379 | + | ||
3380 | + interpose_flag = INTERPOSE_REVAL_NEG; | ||
3381 | + if (positive) { | ||
3382 | + interpose_flag = INTERPOSE_REVAL; | ||
3383 | + iput_lowers_all(dentry->d_inode, true); | ||
3384 | + } | ||
3385 | + | ||
3386 | + if (realloc_dentry_private_data(dentry) != 0) { | ||
3387 | + valid = false; | ||
3388 | + goto out; | ||
3389 | + } | ||
3390 | + | ||
3391 | + result = unionfs_lookup_full(dentry, parent, interpose_flag); | ||
3392 | + if (result) { | ||
3393 | + if (IS_ERR(result)) { | ||
3394 | + valid = false; | ||
3395 | + goto out; | ||
3396 | + } | ||
3397 | + /* | ||
3398 | + * current unionfs_lookup_backend() doesn't return | ||
3399 | + * a valid dentry | ||
3400 | + */ | ||
3401 | + dput(dentry); | ||
3402 | + dentry = result; | ||
3403 | + } | ||
3404 | + | ||
3405 | + if (unlikely(positive && is_negative_lower(dentry))) { | ||
3406 | + /* call make_bad_inode here ? */ | ||
3407 | + d_drop(dentry); | ||
3408 | + valid = false; | ||
3409 | + goto out; | ||
3410 | + } | ||
3411 | + | ||
3412 | + /* | ||
3413 | + * if we got here then we have revalidated our dentry and all lower | ||
3414 | + * ones, so we can return safely. | ||
3415 | + */ | ||
3416 | + if (!valid) /* lower dentry revalidation failed */ | ||
3417 | + goto out; | ||
3418 | + | ||
3419 | + /* | ||
3420 | + * If the parent's gen no. matches the superblock's gen no., then | ||
3421 | + * we can update our denty's gen no. If they didn't match, then it | ||
3422 | + * was OK to revalidate this dentry with a stale parent, but we'll | ||
3423 | + * purposely not update our dentry's gen no. (so it can be redone); | ||
3424 | + * and, we'll mark our parent dentry as invalid so it'll force it | ||
3425 | + * (and our dentry) to be revalidated. | ||
3426 | + */ | ||
3427 | + if (pdgen == sbgen) | ||
3428 | + atomic_set(&UNIONFS_D(dentry)->generation, sbgen); | ||
3429 | + goto out; | ||
3430 | + | ||
3431 | +validate_lowers: | ||
3432 | + | ||
3433 | + /* The revalidation must occur across all branches */ | ||
3434 | + bstart = dbstart(dentry); | ||
3435 | + bend = dbend(dentry); | ||
3436 | + BUG_ON(bstart == -1); | ||
3437 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
3438 | + int err; | ||
3439 | + struct nameidata lower_nd; | ||
3440 | + | ||
3441 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
3442 | + if (!lower_dentry || !lower_dentry->d_op | ||
3443 | + || !lower_dentry->d_op->d_revalidate) | ||
3444 | + continue; | ||
3445 | + /* | ||
3446 | + * Don't pass nameidata to lower file system, because we | ||
3447 | + * don't want an arbitrary lower file being opened or | ||
3448 | + * returned to us: it may be useless to us because of the | ||
3449 | + * fanout nature of unionfs (cf. file/directory open-file | ||
3450 | + * invariants). We will open lower files as and when needed | ||
3451 | + * later on. | ||
3452 | + */ | ||
3453 | + err = init_lower_nd(&lower_nd, LOOKUP_OPEN); | ||
3454 | + if (unlikely(err < 0)) { | ||
3455 | + valid = false; | ||
3456 | + break; | ||
3457 | + } | ||
3458 | + if (!lower_dentry->d_op->d_revalidate(lower_dentry, &lower_nd)) | ||
3459 | + valid = false; | ||
3460 | + release_lower_nd(&lower_nd, err); | ||
3461 | + } | ||
3462 | + | ||
3463 | + if (!dentry->d_inode || | ||
3464 | + ibstart(dentry->d_inode) < 0 || | ||
3465 | + ibend(dentry->d_inode) < 0) { | ||
3466 | + valid = false; | ||
3467 | + goto out; | ||
3468 | + } | ||
3469 | + | ||
3470 | + if (valid) { | ||
3471 | + /* | ||
3472 | + * If we get here, and we copy the meta-data from the lower | ||
3473 | + * inode to our inode, then it is vital that we have already | ||
3474 | + * purged all unionfs-level file data. We do that in the | ||
3475 | + * caller (__unionfs_d_revalidate) by calling | ||
3476 | + * purge_inode_data. | ||
3477 | + */ | ||
3478 | + unionfs_copy_attr_all(dentry->d_inode, | ||
3479 | + unionfs_lower_inode(dentry->d_inode)); | ||
3480 | + fsstack_copy_inode_size(dentry->d_inode, | ||
3481 | + unionfs_lower_inode(dentry->d_inode)); | ||
3482 | + } | ||
3483 | + | ||
3484 | +out: | ||
3485 | + return valid; | ||
3486 | +} | ||
3487 | + | ||
3488 | +/* | ||
3489 | + * Determine if the lower inode objects have changed from below the unionfs | ||
3490 | + * inode. Return true if changed, false otherwise. | ||
3491 | + * | ||
3492 | + * We check if the mtime or ctime have changed. However, the inode times | ||
3493 | + * can be changed by anyone without much protection, including | ||
3494 | + * asynchronously. This can sometimes cause unionfs to find that the lower | ||
3495 | + * file system doesn't change its inode times quick enough, resulting in a | ||
3496 | + * false positive indication (which is harmless, it just makes unionfs do | ||
3497 | + * extra work in re-validating the objects). To minimize the chances of | ||
3498 | + * these situations, we still consider such small time changes valid, but we | ||
3499 | + * don't print debugging messages unless the time changes are greater than | ||
3500 | + * UNIONFS_MIN_CC_TIME (which defaults to 3 seconds, as with NFS's acregmin) | ||
3501 | + * because significant changes are more likely due to users manually | ||
3502 | + * touching lower files. | ||
3503 | + */ | ||
3504 | +bool is_newer_lower(const struct dentry *dentry) | ||
3505 | +{ | ||
3506 | + int bindex; | ||
3507 | + struct inode *inode; | ||
3508 | + struct inode *lower_inode; | ||
3509 | + | ||
3510 | + /* ignore if we're called on semi-initialized dentries/inodes */ | ||
3511 | + if (!dentry || !UNIONFS_D(dentry)) | ||
3512 | + return false; | ||
3513 | + inode = dentry->d_inode; | ||
3514 | + if (!inode || !UNIONFS_I(inode)->lower_inodes || | ||
3515 | + ibstart(inode) < 0 || ibend(inode) < 0) | ||
3516 | + return false; | ||
3517 | + | ||
3518 | + for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) { | ||
3519 | + lower_inode = unionfs_lower_inode_idx(inode, bindex); | ||
3520 | + if (!lower_inode) | ||
3521 | + continue; | ||
3522 | + | ||
3523 | + /* check if mtime/ctime have changed */ | ||
3524 | + if (unlikely(timespec_compare(&inode->i_mtime, | ||
3525 | + &lower_inode->i_mtime) < 0)) { | ||
3526 | + if ((lower_inode->i_mtime.tv_sec - | ||
3527 | + inode->i_mtime.tv_sec) > UNIONFS_MIN_CC_TIME) { | ||
3528 | + pr_info("unionfs: new lower inode mtime " | ||
3529 | + "(bindex=%d, name=%s)\n", bindex, | ||
3530 | + dentry->d_name.name); | ||
3531 | + show_dinode_times(dentry); | ||
3532 | + } | ||
3533 | + return true; | ||
3534 | + } | ||
3535 | + if (unlikely(timespec_compare(&inode->i_ctime, | ||
3536 | + &lower_inode->i_ctime) < 0)) { | ||
3537 | + if ((lower_inode->i_ctime.tv_sec - | ||
3538 | + inode->i_ctime.tv_sec) > UNIONFS_MIN_CC_TIME) { | ||
3539 | + pr_info("unionfs: new lower inode ctime " | ||
3540 | + "(bindex=%d, name=%s)\n", bindex, | ||
3541 | + dentry->d_name.name); | ||
3542 | + show_dinode_times(dentry); | ||
3543 | + } | ||
3544 | + return true; | ||
3545 | + } | ||
3546 | + } | ||
3547 | + | ||
3548 | + /* | ||
3549 | + * Last check: if this is a positive dentry, but somehow all lower | ||
3550 | + * dentries are negative or unhashed, then this dentry needs to be | ||
3551 | + * revalidated, because someone probably deleted the objects from | ||
3552 | + * the lower branches directly. | ||
3553 | + */ | ||
3554 | + if (is_negative_lower(dentry)) | ||
3555 | + return true; | ||
3556 | + | ||
3557 | + return false; /* default: lower is not newer */ | ||
3558 | +} | ||
3559 | + | ||
3560 | +static int unionfs_d_revalidate(struct dentry *dentry, | ||
3561 | + struct nameidata *nd_unused) | ||
3562 | +{ | ||
3563 | + bool valid = true; | ||
3564 | + int err = 1; /* 1 means valid for the VFS */ | ||
3565 | + struct dentry *parent; | ||
3566 | + | ||
3567 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
3568 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
3569 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
3570 | + | ||
3571 | + valid = __unionfs_d_revalidate(dentry, parent, false); | ||
3572 | + if (valid) { | ||
3573 | + unionfs_postcopyup_setmnt(dentry); | ||
3574 | + unionfs_check_dentry(dentry); | ||
3575 | + } else { | ||
3576 | + d_drop(dentry); | ||
3577 | + err = valid; | ||
3578 | + } | ||
3579 | + unionfs_unlock_dentry(dentry); | ||
3580 | + unionfs_unlock_parent(dentry, parent); | ||
3581 | + unionfs_read_unlock(dentry->d_sb); | ||
3582 | + | ||
3583 | + return err; | ||
3584 | +} | ||
3585 | + | ||
3586 | +static void unionfs_d_release(struct dentry *dentry) | ||
3587 | +{ | ||
3588 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
3589 | + if (unlikely(!UNIONFS_D(dentry))) | ||
3590 | + goto out; /* skip if no lower branches */ | ||
3591 | + /* must lock our branch configuration here */ | ||
3592 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
3593 | + | ||
3594 | + unionfs_check_dentry(dentry); | ||
3595 | + /* this could be a negative dentry, so check first */ | ||
3596 | + if (dbstart(dentry) < 0) { | ||
3597 | + unionfs_unlock_dentry(dentry); | ||
3598 | + goto out; /* due to a (normal) failed lookup */ | ||
3599 | + } | ||
3600 | + | ||
3601 | + /* Release all the lower dentries */ | ||
3602 | + path_put_lowers_all(dentry, true); | ||
3603 | + | ||
3604 | + unionfs_unlock_dentry(dentry); | ||
3605 | + | ||
3606 | +out: | ||
3607 | + free_dentry_private_data(dentry); | ||
3608 | + unionfs_read_unlock(dentry->d_sb); | ||
3609 | + return; | ||
3610 | +} | ||
3611 | + | ||
3612 | +/* | ||
3613 | + * Called when we're removing the last reference to our dentry. So we | ||
3614 | + * should drop all lower references too. | ||
3615 | + */ | ||
3616 | +static void unionfs_d_iput(struct dentry *dentry, struct inode *inode) | ||
3617 | +{ | ||
3618 | + int rc; | ||
3619 | + | ||
3620 | + BUG_ON(!dentry); | ||
3621 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
3622 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
3623 | + | ||
3624 | + if (!UNIONFS_D(dentry) || dbstart(dentry) < 0) | ||
3625 | + goto drop_lower_inodes; | ||
3626 | + path_put_lowers_all(dentry, false); | ||
3627 | + | ||
3628 | +drop_lower_inodes: | ||
3629 | + rc = atomic_read(&inode->i_count); | ||
3630 | + if (rc == 1 && inode->i_nlink == 1 && ibstart(inode) >= 0) { | ||
3631 | + /* see Documentation/filesystems/unionfs/issues.txt */ | ||
3632 | + lockdep_off(); | ||
3633 | + iput(unionfs_lower_inode(inode)); | ||
3634 | + lockdep_on(); | ||
3635 | + unionfs_set_lower_inode(inode, NULL); | ||
3636 | + /* XXX: may need to set start/end to -1? */ | ||
3637 | + } | ||
3638 | + | ||
3639 | + iput(inode); | ||
3640 | + | ||
3641 | + unionfs_unlock_dentry(dentry); | ||
3642 | + unionfs_read_unlock(dentry->d_sb); | ||
3643 | +} | ||
3644 | + | ||
3645 | +struct dentry_operations unionfs_dops = { | ||
3646 | + .d_revalidate = unionfs_d_revalidate, | ||
3647 | + .d_release = unionfs_d_release, | ||
3648 | + .d_iput = unionfs_d_iput, | ||
3649 | +}; | ||
3650 | diff --git a/fs/unionfs/dirfops.c b/fs/unionfs/dirfops.c | ||
3651 | new file mode 100644 | ||
3652 | index 0000000..72a9c1a | ||
3653 | --- /dev/null | ||
3654 | +++ b/fs/unionfs/dirfops.c | ||
3655 | @@ -0,0 +1,302 @@ | ||
3656 | +/* | ||
3657 | + * Copyright (c) 2003-2011 Erez Zadok | ||
3658 | + * Copyright (c) 2003-2006 Charles P. Wright | ||
3659 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
3660 | + * Copyright (c) 2005-2006 Junjiro Okajima | ||
3661 | + * Copyright (c) 2005 Arun M. Krishnakumar | ||
3662 | + * Copyright (c) 2004-2006 David P. Quigley | ||
3663 | + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair | ||
3664 | + * Copyright (c) 2003 Puja Gupta | ||
3665 | + * Copyright (c) 2003 Harikesavan Krishnan | ||
3666 | + * Copyright (c) 2003-2011 Stony Brook University | ||
3667 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
3668 | + * | ||
3669 | + * This program is free software; you can redistribute it and/or modify | ||
3670 | + * it under the terms of the GNU General Public License version 2 as | ||
3671 | + * published by the Free Software Foundation. | ||
3672 | + */ | ||
3673 | + | ||
3674 | +#include "union.h" | ||
3675 | + | ||
3676 | +/* Make sure our rdstate is playing by the rules. */ | ||
3677 | +static void verify_rdstate_offset(struct unionfs_dir_state *rdstate) | ||
3678 | +{ | ||
3679 | + BUG_ON(rdstate->offset >= DIREOF); | ||
3680 | + BUG_ON(rdstate->cookie >= MAXRDCOOKIE); | ||
3681 | +} | ||
3682 | + | ||
3683 | +struct unionfs_getdents_callback { | ||
3684 | + struct unionfs_dir_state *rdstate; | ||
3685 | + void *dirent; | ||
3686 | + int entries_written; | ||
3687 | + int filldir_called; | ||
3688 | + int filldir_error; | ||
3689 | + filldir_t filldir; | ||
3690 | + struct super_block *sb; | ||
3691 | +}; | ||
3692 | + | ||
3693 | +/* based on generic filldir in fs/readir.c */ | ||
3694 | +static int unionfs_filldir(void *dirent, const char *oname, int namelen, | ||
3695 | + loff_t offset, u64 ino, unsigned int d_type) | ||
3696 | +{ | ||
3697 | + struct unionfs_getdents_callback *buf = dirent; | ||
3698 | + struct filldir_node *found = NULL; | ||
3699 | + int err = 0; | ||
3700 | + int is_whiteout; | ||
3701 | + char *name = (char *) oname; | ||
3702 | + | ||
3703 | + buf->filldir_called++; | ||
3704 | + | ||
3705 | + is_whiteout = is_whiteout_name(&name, &namelen); | ||
3706 | + | ||
3707 | + found = find_filldir_node(buf->rdstate, name, namelen, is_whiteout); | ||
3708 | + | ||
3709 | + if (found) { | ||
3710 | + /* | ||
3711 | + * If we had non-whiteout entry in dir cache, then mark it | ||
3712 | + * as a whiteout and but leave it in the dir cache. | ||
3713 | + */ | ||
3714 | + if (is_whiteout && !found->whiteout) | ||
3715 | + found->whiteout = is_whiteout; | ||
3716 | + goto out; | ||
3717 | + } | ||
3718 | + | ||
3719 | + /* if 'name' isn't a whiteout, filldir it. */ | ||
3720 | + if (!is_whiteout) { | ||
3721 | + off_t pos = rdstate2offset(buf->rdstate); | ||
3722 | + u64 unionfs_ino = ino; | ||
3723 | + | ||
3724 | + err = buf->filldir(buf->dirent, name, namelen, pos, | ||
3725 | + unionfs_ino, d_type); | ||
3726 | + buf->rdstate->offset++; | ||
3727 | + verify_rdstate_offset(buf->rdstate); | ||
3728 | + } | ||
3729 | + /* | ||
3730 | + * If we did fill it, stuff it in our hash, otherwise return an | ||
3731 | + * error. | ||
3732 | + */ | ||
3733 | + if (err) { | ||
3734 | + buf->filldir_error = err; | ||
3735 | + goto out; | ||
3736 | + } | ||
3737 | + buf->entries_written++; | ||
3738 | + err = add_filldir_node(buf->rdstate, name, namelen, | ||
3739 | + buf->rdstate->bindex, is_whiteout); | ||
3740 | + if (err) | ||
3741 | + buf->filldir_error = err; | ||
3742 | + | ||
3743 | +out: | ||
3744 | + return err; | ||
3745 | +} | ||
3746 | + | ||
3747 | +static int unionfs_readdir(struct file *file, void *dirent, filldir_t filldir) | ||
3748 | +{ | ||
3749 | + int err = 0; | ||
3750 | + struct file *lower_file = NULL; | ||
3751 | + struct dentry *dentry = file->f_path.dentry; | ||
3752 | + struct dentry *parent; | ||
3753 | + struct inode *inode = NULL; | ||
3754 | + struct unionfs_getdents_callback buf; | ||
3755 | + struct unionfs_dir_state *uds; | ||
3756 | + int bend; | ||
3757 | + loff_t offset; | ||
3758 | + | ||
3759 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT); | ||
3760 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
3761 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
3762 | + | ||
3763 | + err = unionfs_file_revalidate(file, parent, false); | ||
3764 | + if (unlikely(err)) | ||
3765 | + goto out; | ||
3766 | + | ||
3767 | + inode = dentry->d_inode; | ||
3768 | + | ||
3769 | + uds = UNIONFS_F(file)->rdstate; | ||
3770 | + if (!uds) { | ||
3771 | + if (file->f_pos == DIREOF) { | ||
3772 | + goto out; | ||
3773 | + } else if (file->f_pos > 0) { | ||
3774 | + uds = find_rdstate(inode, file->f_pos); | ||
3775 | + if (unlikely(!uds)) { | ||
3776 | + err = -ESTALE; | ||
3777 | + goto out; | ||
3778 | + } | ||
3779 | + UNIONFS_F(file)->rdstate = uds; | ||
3780 | + } else { | ||
3781 | + init_rdstate(file); | ||
3782 | + uds = UNIONFS_F(file)->rdstate; | ||
3783 | + } | ||
3784 | + } | ||
3785 | + bend = fbend(file); | ||
3786 | + | ||
3787 | + while (uds->bindex <= bend) { | ||
3788 | + lower_file = unionfs_lower_file_idx(file, uds->bindex); | ||
3789 | + if (!lower_file) { | ||
3790 | + uds->bindex++; | ||
3791 | + uds->dirpos = 0; | ||
3792 | + continue; | ||
3793 | + } | ||
3794 | + | ||
3795 | + /* prepare callback buffer */ | ||
3796 | + buf.filldir_called = 0; | ||
3797 | + buf.filldir_error = 0; | ||
3798 | + buf.entries_written = 0; | ||
3799 | + buf.dirent = dirent; | ||
3800 | + buf.filldir = filldir; | ||
3801 | + buf.rdstate = uds; | ||
3802 | + buf.sb = inode->i_sb; | ||
3803 | + | ||
3804 | + /* Read starting from where we last left off. */ | ||
3805 | + offset = vfs_llseek(lower_file, uds->dirpos, SEEK_SET); | ||
3806 | + if (offset < 0) { | ||
3807 | + err = offset; | ||
3808 | + goto out; | ||
3809 | + } | ||
3810 | + err = vfs_readdir(lower_file, unionfs_filldir, &buf); | ||
3811 | + | ||
3812 | + /* Save the position for when we continue. */ | ||
3813 | + offset = vfs_llseek(lower_file, 0, SEEK_CUR); | ||
3814 | + if (offset < 0) { | ||
3815 | + err = offset; | ||
3816 | + goto out; | ||
3817 | + } | ||
3818 | + uds->dirpos = offset; | ||
3819 | + | ||
3820 | + /* Copy the atime. */ | ||
3821 | + fsstack_copy_attr_atime(inode, | ||
3822 | + lower_file->f_path.dentry->d_inode); | ||
3823 | + | ||
3824 | + if (err < 0) | ||
3825 | + goto out; | ||
3826 | + | ||
3827 | + if (buf.filldir_error) | ||
3828 | + break; | ||
3829 | + | ||
3830 | + if (!buf.entries_written) { | ||
3831 | + uds->bindex++; | ||
3832 | + uds->dirpos = 0; | ||
3833 | + } | ||
3834 | + } | ||
3835 | + | ||
3836 | + if (!buf.filldir_error && uds->bindex >= bend) { | ||
3837 | + /* Save the number of hash entries for next time. */ | ||
3838 | + UNIONFS_I(inode)->hashsize = uds->hashentries; | ||
3839 | + free_rdstate(uds); | ||
3840 | + UNIONFS_F(file)->rdstate = NULL; | ||
3841 | + file->f_pos = DIREOF; | ||
3842 | + } else { | ||
3843 | + file->f_pos = rdstate2offset(uds); | ||
3844 | + } | ||
3845 | + | ||
3846 | +out: | ||
3847 | + if (!err) | ||
3848 | + unionfs_check_file(file); | ||
3849 | + unionfs_unlock_dentry(dentry); | ||
3850 | + unionfs_unlock_parent(dentry, parent); | ||
3851 | + unionfs_read_unlock(dentry->d_sb); | ||
3852 | + return err; | ||
3853 | +} | ||
3854 | + | ||
3855 | +/* | ||
3856 | + * This is not meant to be a generic repositioning function. If you do | ||
3857 | + * things that aren't supported, then we return EINVAL. | ||
3858 | + * | ||
3859 | + * What is allowed: | ||
3860 | + * (1) seeking to the same position that you are currently at | ||
3861 | + * This really has no effect, but returns where you are. | ||
3862 | + * (2) seeking to the beginning of the file | ||
3863 | + * This throws out all state, and lets you begin again. | ||
3864 | + */ | ||
3865 | +static loff_t unionfs_dir_llseek(struct file *file, loff_t offset, int origin) | ||
3866 | +{ | ||
3867 | + struct unionfs_dir_state *rdstate; | ||
3868 | + struct dentry *dentry = file->f_path.dentry; | ||
3869 | + struct dentry *parent; | ||
3870 | + loff_t err; | ||
3871 | + | ||
3872 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT); | ||
3873 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
3874 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
3875 | + | ||
3876 | + err = unionfs_file_revalidate(file, parent, false); | ||
3877 | + if (unlikely(err)) | ||
3878 | + goto out; | ||
3879 | + | ||
3880 | + rdstate = UNIONFS_F(file)->rdstate; | ||
3881 | + | ||
3882 | + /* | ||
3883 | + * we let users seek to their current position, but not anywhere | ||
3884 | + * else. | ||
3885 | + */ | ||
3886 | + if (!offset) { | ||
3887 | + switch (origin) { | ||
3888 | + case SEEK_SET: | ||
3889 | + if (rdstate) { | ||
3890 | + free_rdstate(rdstate); | ||
3891 | + UNIONFS_F(file)->rdstate = NULL; | ||
3892 | + } | ||
3893 | + init_rdstate(file); | ||
3894 | + err = 0; | ||
3895 | + break; | ||
3896 | + case SEEK_CUR: | ||
3897 | + err = file->f_pos; | ||
3898 | + break; | ||
3899 | + case SEEK_END: | ||
3900 | + /* Unsupported, because we would break everything. */ | ||
3901 | + err = -EINVAL; | ||
3902 | + break; | ||
3903 | + } | ||
3904 | + } else { | ||
3905 | + switch (origin) { | ||
3906 | + case SEEK_SET: | ||
3907 | + if (rdstate) { | ||
3908 | + if (offset == rdstate2offset(rdstate)) | ||
3909 | + err = offset; | ||
3910 | + else if (file->f_pos == DIREOF) | ||
3911 | + err = DIREOF; | ||
3912 | + else | ||
3913 | + err = -EINVAL; | ||
3914 | + } else { | ||
3915 | + struct inode *inode; | ||
3916 | + inode = dentry->d_inode; | ||
3917 | + rdstate = find_rdstate(inode, offset); | ||
3918 | + if (rdstate) { | ||
3919 | + UNIONFS_F(file)->rdstate = rdstate; | ||
3920 | + err = rdstate->offset; | ||
3921 | + } else { | ||
3922 | + err = -EINVAL; | ||
3923 | + } | ||
3924 | + } | ||
3925 | + break; | ||
3926 | + case SEEK_CUR: | ||
3927 | + case SEEK_END: | ||
3928 | + /* Unsupported, because we would break everything. */ | ||
3929 | + err = -EINVAL; | ||
3930 | + break; | ||
3931 | + } | ||
3932 | + } | ||
3933 | + | ||
3934 | +out: | ||
3935 | + if (!err) | ||
3936 | + unionfs_check_file(file); | ||
3937 | + unionfs_unlock_dentry(dentry); | ||
3938 | + unionfs_unlock_parent(dentry, parent); | ||
3939 | + unionfs_read_unlock(dentry->d_sb); | ||
3940 | + return err; | ||
3941 | +} | ||
3942 | + | ||
3943 | +/* | ||
3944 | + * Trimmed directory options, we shouldn't pass everything down since | ||
3945 | + * we don't want to operate on partial directories. | ||
3946 | + */ | ||
3947 | +struct file_operations unionfs_dir_fops = { | ||
3948 | + .llseek = unionfs_dir_llseek, | ||
3949 | + .read = generic_read_dir, | ||
3950 | + .readdir = unionfs_readdir, | ||
3951 | + .unlocked_ioctl = unionfs_ioctl, | ||
3952 | + .open = unionfs_open, | ||
3953 | + .release = unionfs_file_release, | ||
3954 | + .flush = unionfs_flush, | ||
3955 | + .fsync = unionfs_fsync, | ||
3956 | + .fasync = unionfs_fasync, | ||
3957 | +}; | ||
3958 | diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c | ||
3959 | new file mode 100644 | ||
3960 | index 0000000..62ec9af | ||
3961 | --- /dev/null | ||
3962 | +++ b/fs/unionfs/dirhelper.c | ||
3963 | @@ -0,0 +1,158 @@ | ||
3964 | +/* | ||
3965 | + * Copyright (c) 2003-2011 Erez Zadok | ||
3966 | + * Copyright (c) 2003-2006 Charles P. Wright | ||
3967 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
3968 | + * Copyright (c) 2005-2006 Junjiro Okajima | ||
3969 | + * Copyright (c) 2005 Arun M. Krishnakumar | ||
3970 | + * Copyright (c) 2004-2006 David P. Quigley | ||
3971 | + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair | ||
3972 | + * Copyright (c) 2003 Puja Gupta | ||
3973 | + * Copyright (c) 2003 Harikesavan Krishnan | ||
3974 | + * Copyright (c) 2003-2011 Stony Brook University | ||
3975 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
3976 | + * | ||
3977 | + * This program is free software; you can redistribute it and/or modify | ||
3978 | + * it under the terms of the GNU General Public License version 2 as | ||
3979 | + * published by the Free Software Foundation. | ||
3980 | + */ | ||
3981 | + | ||
3982 | +#include "union.h" | ||
3983 | + | ||
3984 | +#define RD_NONE 0 | ||
3985 | +#define RD_CHECK_EMPTY 1 | ||
3986 | +/* The callback structure for check_empty. */ | ||
3987 | +struct unionfs_rdutil_callback { | ||
3988 | + int err; | ||
3989 | + int filldir_called; | ||
3990 | + struct unionfs_dir_state *rdstate; | ||
3991 | + int mode; | ||
3992 | +}; | ||
3993 | + | ||
3994 | +/* This filldir function makes sure only whiteouts exist within a directory. */ | ||
3995 | +static int readdir_util_callback(void *dirent, const char *oname, int namelen, | ||
3996 | + loff_t offset, u64 ino, unsigned int d_type) | ||
3997 | +{ | ||
3998 | + int err = 0; | ||
3999 | + struct unionfs_rdutil_callback *buf = dirent; | ||
4000 | + int is_whiteout; | ||
4001 | + struct filldir_node *found; | ||
4002 | + char *name = (char *) oname; | ||
4003 | + | ||
4004 | + buf->filldir_called = 1; | ||
4005 | + | ||
4006 | + if (name[0] == '.' && (namelen == 1 || | ||
4007 | + (name[1] == '.' && namelen == 2))) | ||
4008 | + goto out; | ||
4009 | + | ||
4010 | + is_whiteout = is_whiteout_name(&name, &namelen); | ||
4011 | + | ||
4012 | + found = find_filldir_node(buf->rdstate, name, namelen, is_whiteout); | ||
4013 | + /* If it was found in the table there was a previous whiteout. */ | ||
4014 | + if (found) | ||
4015 | + goto out; | ||
4016 | + | ||
4017 | + /* | ||
4018 | + * if it wasn't found and isn't a whiteout, the directory isn't | ||
4019 | + * empty. | ||
4020 | + */ | ||
4021 | + err = -ENOTEMPTY; | ||
4022 | + if ((buf->mode == RD_CHECK_EMPTY) && !is_whiteout) | ||
4023 | + goto out; | ||
4024 | + | ||
4025 | + err = add_filldir_node(buf->rdstate, name, namelen, | ||
4026 | + buf->rdstate->bindex, is_whiteout); | ||
4027 | + | ||
4028 | +out: | ||
4029 | + buf->err = err; | ||
4030 | + return err; | ||
4031 | +} | ||
4032 | + | ||
4033 | +/* Is a directory logically empty? */ | ||
4034 | +int check_empty(struct dentry *dentry, struct dentry *parent, | ||
4035 | + struct unionfs_dir_state **namelist) | ||
4036 | +{ | ||
4037 | + int err = 0; | ||
4038 | + struct dentry *lower_dentry = NULL; | ||
4039 | + struct vfsmount *mnt; | ||
4040 | + struct super_block *sb; | ||
4041 | + struct file *lower_file; | ||
4042 | + struct unionfs_rdutil_callback *buf = NULL; | ||
4043 | + int bindex, bstart, bend, bopaque; | ||
4044 | + | ||
4045 | + sb = dentry->d_sb; | ||
4046 | + | ||
4047 | + | ||
4048 | + BUG_ON(!S_ISDIR(dentry->d_inode->i_mode)); | ||
4049 | + | ||
4050 | + err = unionfs_partial_lookup(dentry, parent); | ||
4051 | + if (err) | ||
4052 | + goto out; | ||
4053 | + | ||
4054 | + bstart = dbstart(dentry); | ||
4055 | + bend = dbend(dentry); | ||
4056 | + bopaque = dbopaque(dentry); | ||
4057 | + if (0 <= bopaque && bopaque < bend) | ||
4058 | + bend = bopaque; | ||
4059 | + | ||
4060 | + buf = kmalloc(sizeof(struct unionfs_rdutil_callback), GFP_KERNEL); | ||
4061 | + if (unlikely(!buf)) { | ||
4062 | + err = -ENOMEM; | ||
4063 | + goto out; | ||
4064 | + } | ||
4065 | + buf->err = 0; | ||
4066 | + buf->mode = RD_CHECK_EMPTY; | ||
4067 | + buf->rdstate = alloc_rdstate(dentry->d_inode, bstart); | ||
4068 | + if (unlikely(!buf->rdstate)) { | ||
4069 | + err = -ENOMEM; | ||
4070 | + goto out; | ||
4071 | + } | ||
4072 | + | ||
4073 | + /* Process the lower directories with rdutil_callback as a filldir. */ | ||
4074 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
4075 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
4076 | + if (!lower_dentry) | ||
4077 | + continue; | ||
4078 | + if (!lower_dentry->d_inode) | ||
4079 | + continue; | ||
4080 | + if (!S_ISDIR(lower_dentry->d_inode->i_mode)) | ||
4081 | + continue; | ||
4082 | + | ||
4083 | + dget(lower_dentry); | ||
4084 | + mnt = unionfs_mntget(dentry, bindex); | ||
4085 | + branchget(sb, bindex); | ||
4086 | + lower_file = dentry_open(lower_dentry, mnt, O_RDONLY, current_cred()); | ||
4087 | + if (IS_ERR(lower_file)) { | ||
4088 | + err = PTR_ERR(lower_file); | ||
4089 | + branchput(sb, bindex); | ||
4090 | + goto out; | ||
4091 | + } | ||
4092 | + | ||
4093 | + do { | ||
4094 | + buf->filldir_called = 0; | ||
4095 | + buf->rdstate->bindex = bindex; | ||
4096 | + err = vfs_readdir(lower_file, | ||
4097 | + readdir_util_callback, buf); | ||
4098 | + if (buf->err) | ||
4099 | + err = buf->err; | ||
4100 | + } while ((err >= 0) && buf->filldir_called); | ||
4101 | + | ||
4102 | + /* fput calls dput for lower_dentry */ | ||
4103 | + fput(lower_file); | ||
4104 | + branchput(sb, bindex); | ||
4105 | + | ||
4106 | + if (err < 0) | ||
4107 | + goto out; | ||
4108 | + } | ||
4109 | + | ||
4110 | +out: | ||
4111 | + if (buf) { | ||
4112 | + if (namelist && !err) | ||
4113 | + *namelist = buf->rdstate; | ||
4114 | + else if (buf->rdstate) | ||
4115 | + free_rdstate(buf->rdstate); | ||
4116 | + kfree(buf); | ||
4117 | + } | ||
4118 | + | ||
4119 | + | ||
4120 | + return err; | ||
4121 | +} | ||
4122 | diff --git a/fs/unionfs/fanout.h b/fs/unionfs/fanout.h | ||
4123 | new file mode 100644 | ||
4124 | index 0000000..ae1b86a | ||
4125 | --- /dev/null | ||
4126 | +++ b/fs/unionfs/fanout.h | ||
4127 | @@ -0,0 +1,407 @@ | ||
4128 | +/* | ||
4129 | + * Copyright (c) 2003-2011 Erez Zadok | ||
4130 | + * Copyright (c) 2003-2006 Charles P. Wright | ||
4131 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
4132 | + * Copyright (c) 2005 Arun M. Krishnakumar | ||
4133 | + * Copyright (c) 2004-2006 David P. Quigley | ||
4134 | + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair | ||
4135 | + * Copyright (c) 2003 Puja Gupta | ||
4136 | + * Copyright (c) 2003 Harikesavan Krishnan | ||
4137 | + * Copyright (c) 2003-2011 Stony Brook University | ||
4138 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
4139 | + * | ||
4140 | + * This program is free software; you can redistribute it and/or modify | ||
4141 | + * it under the terms of the GNU General Public License version 2 as | ||
4142 | + * published by the Free Software Foundation. | ||
4143 | + */ | ||
4144 | + | ||
4145 | +#ifndef _FANOUT_H_ | ||
4146 | +#define _FANOUT_H_ | ||
4147 | + | ||
4148 | +/* | ||
4149 | + * Inode to private data | ||
4150 | + * | ||
4151 | + * Since we use containers and the struct inode is _inside_ the | ||
4152 | + * unionfs_inode_info structure, UNIONFS_I will always (given a non-NULL | ||
4153 | + * inode pointer), return a valid non-NULL pointer. | ||
4154 | + */ | ||
4155 | +static inline struct unionfs_inode_info *UNIONFS_I(const struct inode *inode) | ||
4156 | +{ | ||
4157 | + return container_of(inode, struct unionfs_inode_info, vfs_inode); | ||
4158 | +} | ||
4159 | + | ||
4160 | +#define ibstart(ino) (UNIONFS_I(ino)->bstart) | ||
4161 | +#define ibend(ino) (UNIONFS_I(ino)->bend) | ||
4162 | + | ||
4163 | +/* Dentry to private data */ | ||
4164 | +#define UNIONFS_D(dent) ((struct unionfs_dentry_info *)(dent)->d_fsdata) | ||
4165 | +#define dbstart(dent) (UNIONFS_D(dent)->bstart) | ||
4166 | +#define dbend(dent) (UNIONFS_D(dent)->bend) | ||
4167 | +#define dbopaque(dent) (UNIONFS_D(dent)->bopaque) | ||
4168 | + | ||
4169 | +/* Superblock to private data */ | ||
4170 | +#define UNIONFS_SB(super) ((struct unionfs_sb_info *)(super)->s_fs_info) | ||
4171 | +#define sbstart(sb) 0 | ||
4172 | +#define sbend(sb) (UNIONFS_SB(sb)->bend) | ||
4173 | +#define sbmax(sb) (UNIONFS_SB(sb)->bend + 1) | ||
4174 | +#define sbhbid(sb) (UNIONFS_SB(sb)->high_branch_id) | ||
4175 | + | ||
4176 | +/* File to private Data */ | ||
4177 | +#define UNIONFS_F(file) ((struct unionfs_file_info *)((file)->private_data)) | ||
4178 | +#define fbstart(file) (UNIONFS_F(file)->bstart) | ||
4179 | +#define fbend(file) (UNIONFS_F(file)->bend) | ||
4180 | + | ||
4181 | +/* macros to manipulate branch IDs in stored in our superblock */ | ||
4182 | +static inline int branch_id(struct super_block *sb, int index) | ||
4183 | +{ | ||
4184 | + BUG_ON(!sb || index < 0); | ||
4185 | + return UNIONFS_SB(sb)->data[index].branch_id; | ||
4186 | +} | ||
4187 | + | ||
4188 | +static inline void set_branch_id(struct super_block *sb, int index, int val) | ||
4189 | +{ | ||
4190 | + BUG_ON(!sb || index < 0); | ||
4191 | + UNIONFS_SB(sb)->data[index].branch_id = val; | ||
4192 | +} | ||
4193 | + | ||
4194 | +static inline void new_branch_id(struct super_block *sb, int index) | ||
4195 | +{ | ||
4196 | + BUG_ON(!sb || index < 0); | ||
4197 | + set_branch_id(sb, index, ++UNIONFS_SB(sb)->high_branch_id); | ||
4198 | +} | ||
4199 | + | ||
4200 | +/* | ||
4201 | + * Find new index of matching branch with an existing superblock of a known | ||
4202 | + * (possibly old) id. This is needed because branches could have been | ||
4203 | + * added/deleted causing the branches of any open files to shift. | ||
4204 | + * | ||
4205 | + * @sb: the new superblock which may have new/different branch IDs | ||
4206 | + * @id: the old/existing id we're looking for | ||
4207 | + * Returns index of newly found branch (0 or greater), -1 otherwise. | ||
4208 | + */ | ||
4209 | +static inline int branch_id_to_idx(struct super_block *sb, int id) | ||
4210 | +{ | ||
4211 | + int i; | ||
4212 | + for (i = 0; i < sbmax(sb); i++) { | ||
4213 | + if (branch_id(sb, i) == id) | ||
4214 | + return i; | ||
4215 | + } | ||
4216 | + /* in the non-ODF code, this should really never happen */ | ||
4217 | + printk(KERN_WARNING "unionfs: cannot find branch with id %d\n", id); | ||
4218 | + return -1; | ||
4219 | +} | ||
4220 | + | ||
4221 | +/* File to lower file. */ | ||
4222 | +static inline struct file *unionfs_lower_file(const struct file *f) | ||
4223 | +{ | ||
4224 | + BUG_ON(!f); | ||
4225 | + return UNIONFS_F(f)->lower_files[fbstart(f)]; | ||
4226 | +} | ||
4227 | + | ||
4228 | +static inline struct file *unionfs_lower_file_idx(const struct file *f, | ||
4229 | + int index) | ||
4230 | +{ | ||
4231 | + BUG_ON(!f || index < 0); | ||
4232 | + return UNIONFS_F(f)->lower_files[index]; | ||
4233 | +} | ||
4234 | + | ||
4235 | +static inline void unionfs_set_lower_file_idx(struct file *f, int index, | ||
4236 | + struct file *val) | ||
4237 | +{ | ||
4238 | + BUG_ON(!f || index < 0); | ||
4239 | + UNIONFS_F(f)->lower_files[index] = val; | ||
4240 | + /* save branch ID (may be redundant?) */ | ||
4241 | + UNIONFS_F(f)->saved_branch_ids[index] = | ||
4242 | + branch_id((f)->f_path.dentry->d_sb, index); | ||
4243 | +} | ||
4244 | + | ||
4245 | +static inline void unionfs_set_lower_file(struct file *f, struct file *val) | ||
4246 | +{ | ||
4247 | + BUG_ON(!f); | ||
4248 | + unionfs_set_lower_file_idx((f), fbstart(f), (val)); | ||
4249 | +} | ||
4250 | + | ||
4251 | +/* Inode to lower inode. */ | ||
4252 | +static inline struct inode *unionfs_lower_inode(const struct inode *i) | ||
4253 | +{ | ||
4254 | + BUG_ON(!i); | ||
4255 | + return UNIONFS_I(i)->lower_inodes[ibstart(i)]; | ||
4256 | +} | ||
4257 | + | ||
4258 | +static inline struct inode *unionfs_lower_inode_idx(const struct inode *i, | ||
4259 | + int index) | ||
4260 | +{ | ||
4261 | + BUG_ON(!i || index < 0); | ||
4262 | + return UNIONFS_I(i)->lower_inodes[index]; | ||
4263 | +} | ||
4264 | + | ||
4265 | +static inline void unionfs_set_lower_inode_idx(struct inode *i, int index, | ||
4266 | + struct inode *val) | ||
4267 | +{ | ||
4268 | + BUG_ON(!i || index < 0); | ||
4269 | + UNIONFS_I(i)->lower_inodes[index] = val; | ||
4270 | +} | ||
4271 | + | ||
4272 | +static inline void unionfs_set_lower_inode(struct inode *i, struct inode *val) | ||
4273 | +{ | ||
4274 | + BUG_ON(!i); | ||
4275 | + UNIONFS_I(i)->lower_inodes[ibstart(i)] = val; | ||
4276 | +} | ||
4277 | + | ||
4278 | +/* Superblock to lower superblock. */ | ||
4279 | +static inline struct super_block *unionfs_lower_super( | ||
4280 | + const struct super_block *sb) | ||
4281 | +{ | ||
4282 | + BUG_ON(!sb); | ||
4283 | + return UNIONFS_SB(sb)->data[sbstart(sb)].sb; | ||
4284 | +} | ||
4285 | + | ||
4286 | +static inline struct super_block *unionfs_lower_super_idx( | ||
4287 | + const struct super_block *sb, | ||
4288 | + int index) | ||
4289 | +{ | ||
4290 | + BUG_ON(!sb || index < 0); | ||
4291 | + return UNIONFS_SB(sb)->data[index].sb; | ||
4292 | +} | ||
4293 | + | ||
4294 | +static inline void unionfs_set_lower_super_idx(struct super_block *sb, | ||
4295 | + int index, | ||
4296 | + struct super_block *val) | ||
4297 | +{ | ||
4298 | + BUG_ON(!sb || index < 0); | ||
4299 | + UNIONFS_SB(sb)->data[index].sb = val; | ||
4300 | +} | ||
4301 | + | ||
4302 | +static inline void unionfs_set_lower_super(struct super_block *sb, | ||
4303 | + struct super_block *val) | ||
4304 | +{ | ||
4305 | + BUG_ON(!sb); | ||
4306 | + UNIONFS_SB(sb)->data[sbstart(sb)].sb = val; | ||
4307 | +} | ||
4308 | + | ||
4309 | +/* Branch count macros. */ | ||
4310 | +static inline int branch_count(const struct super_block *sb, int index) | ||
4311 | +{ | ||
4312 | + BUG_ON(!sb || index < 0); | ||
4313 | + return atomic_read(&UNIONFS_SB(sb)->data[index].open_files); | ||
4314 | +} | ||
4315 | + | ||
4316 | +static inline void set_branch_count(struct super_block *sb, int index, int val) | ||
4317 | +{ | ||
4318 | + BUG_ON(!sb || index < 0); | ||
4319 | + atomic_set(&UNIONFS_SB(sb)->data[index].open_files, val); | ||
4320 | +} | ||
4321 | + | ||
4322 | +static inline void branchget(struct super_block *sb, int index) | ||
4323 | +{ | ||
4324 | + BUG_ON(!sb || index < 0); | ||
4325 | + atomic_inc(&UNIONFS_SB(sb)->data[index].open_files); | ||
4326 | +} | ||
4327 | + | ||
4328 | +static inline void branchput(struct super_block *sb, int index) | ||
4329 | +{ | ||
4330 | + BUG_ON(!sb || index < 0); | ||
4331 | + atomic_dec(&UNIONFS_SB(sb)->data[index].open_files); | ||
4332 | +} | ||
4333 | + | ||
4334 | +/* Dentry macros */ | ||
4335 | +static inline void unionfs_set_lower_dentry_idx(struct dentry *dent, int index, | ||
4336 | + struct dentry *val) | ||
4337 | +{ | ||
4338 | + BUG_ON(!dent || index < 0); | ||
4339 | + UNIONFS_D(dent)->lower_paths[index].dentry = val; | ||
4340 | +} | ||
4341 | + | ||
4342 | +static inline struct dentry *unionfs_lower_dentry_idx( | ||
4343 | + const struct dentry *dent, | ||
4344 | + int index) | ||
4345 | +{ | ||
4346 | + BUG_ON(!dent || index < 0); | ||
4347 | + return UNIONFS_D(dent)->lower_paths[index].dentry; | ||
4348 | +} | ||
4349 | + | ||
4350 | +static inline struct dentry *unionfs_lower_dentry(const struct dentry *dent) | ||
4351 | +{ | ||
4352 | + BUG_ON(!dent); | ||
4353 | + return unionfs_lower_dentry_idx(dent, dbstart(dent)); | ||
4354 | +} | ||
4355 | + | ||
4356 | +static inline void unionfs_set_lower_mnt_idx(struct dentry *dent, int index, | ||
4357 | + struct vfsmount *mnt) | ||
4358 | +{ | ||
4359 | + BUG_ON(!dent || index < 0); | ||
4360 | + UNIONFS_D(dent)->lower_paths[index].mnt = mnt; | ||
4361 | +} | ||
4362 | + | ||
4363 | +static inline struct vfsmount *unionfs_lower_mnt_idx( | ||
4364 | + const struct dentry *dent, | ||
4365 | + int index) | ||
4366 | +{ | ||
4367 | + BUG_ON(!dent || index < 0); | ||
4368 | + return UNIONFS_D(dent)->lower_paths[index].mnt; | ||
4369 | +} | ||
4370 | + | ||
4371 | +static inline struct vfsmount *unionfs_lower_mnt(const struct dentry *dent) | ||
4372 | +{ | ||
4373 | + BUG_ON(!dent); | ||
4374 | + return unionfs_lower_mnt_idx(dent, dbstart(dent)); | ||
4375 | +} | ||
4376 | + | ||
4377 | +/* Macros for locking a dentry. */ | ||
4378 | +enum unionfs_dentry_lock_class { | ||
4379 | + UNIONFS_DMUTEX_NORMAL, | ||
4380 | + UNIONFS_DMUTEX_ROOT, | ||
4381 | + UNIONFS_DMUTEX_PARENT, | ||
4382 | + UNIONFS_DMUTEX_CHILD, | ||
4383 | + UNIONFS_DMUTEX_WHITEOUT, | ||
4384 | + UNIONFS_DMUTEX_REVAL_PARENT, /* for file/dentry revalidate */ | ||
4385 | + UNIONFS_DMUTEX_REVAL_CHILD, /* for file/dentry revalidate */ | ||
4386 | +}; | ||
4387 | + | ||
4388 | +static inline void unionfs_lock_dentry(struct dentry *d, | ||
4389 | + unsigned int subclass) | ||
4390 | +{ | ||
4391 | + BUG_ON(!d); | ||
4392 | + mutex_lock_nested(&UNIONFS_D(d)->lock, subclass); | ||
4393 | +} | ||
4394 | + | ||
4395 | +static inline void unionfs_unlock_dentry(struct dentry *d) | ||
4396 | +{ | ||
4397 | + BUG_ON(!d); | ||
4398 | + mutex_unlock(&UNIONFS_D(d)->lock); | ||
4399 | +} | ||
4400 | + | ||
4401 | +static inline struct dentry *unionfs_lock_parent(struct dentry *d, | ||
4402 | + unsigned int subclass) | ||
4403 | +{ | ||
4404 | + struct dentry *p; | ||
4405 | + | ||
4406 | + BUG_ON(!d); | ||
4407 | + p = dget_parent(d); | ||
4408 | + if (p != d) | ||
4409 | + mutex_lock_nested(&UNIONFS_D(p)->lock, subclass); | ||
4410 | + return p; | ||
4411 | +} | ||
4412 | + | ||
4413 | +static inline void unionfs_unlock_parent(struct dentry *d, struct dentry *p) | ||
4414 | +{ | ||
4415 | + BUG_ON(!d); | ||
4416 | + BUG_ON(!p); | ||
4417 | + if (p != d) { | ||
4418 | + BUG_ON(!mutex_is_locked(&UNIONFS_D(p)->lock)); | ||
4419 | + mutex_unlock(&UNIONFS_D(p)->lock); | ||
4420 | + } | ||
4421 | + dput(p); | ||
4422 | +} | ||
4423 | + | ||
4424 | +static inline void verify_locked(struct dentry *d) | ||
4425 | +{ | ||
4426 | + BUG_ON(!d); | ||
4427 | + BUG_ON(!mutex_is_locked(&UNIONFS_D(d)->lock)); | ||
4428 | +} | ||
4429 | + | ||
4430 | +/* macros to put lower objects */ | ||
4431 | + | ||
4432 | +/* | ||
4433 | + * iput lower inodes of an unionfs dentry, from bstart to bend. If | ||
4434 | + * @free_lower is true, then also kfree the memory used to hold the lower | ||
4435 | + * object pointers. | ||
4436 | + */ | ||
4437 | +static inline void iput_lowers(struct inode *inode, | ||
4438 | + int bstart, int bend, bool free_lower) | ||
4439 | +{ | ||
4440 | + struct inode *lower_inode; | ||
4441 | + int bindex; | ||
4442 | + | ||
4443 | + BUG_ON(!inode); | ||
4444 | + BUG_ON(!UNIONFS_I(inode)); | ||
4445 | + BUG_ON(bstart < 0); | ||
4446 | + | ||
4447 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
4448 | + lower_inode = unionfs_lower_inode_idx(inode, bindex); | ||
4449 | + if (lower_inode) { | ||
4450 | + unionfs_set_lower_inode_idx(inode, bindex, NULL); | ||
4451 | + /* see Documentation/filesystems/unionfs/issues.txt */ | ||
4452 | + lockdep_off(); | ||
4453 | + iput(lower_inode); | ||
4454 | + lockdep_on(); | ||
4455 | + } | ||
4456 | + } | ||
4457 | + | ||
4458 | + if (free_lower) { | ||
4459 | + kfree(UNIONFS_I(inode)->lower_inodes); | ||
4460 | + UNIONFS_I(inode)->lower_inodes = NULL; | ||
4461 | + } | ||
4462 | +} | ||
4463 | + | ||
4464 | +/* iput all lower inodes, and reset start/end branch indices to -1 */ | ||
4465 | +static inline void iput_lowers_all(struct inode *inode, bool free_lower) | ||
4466 | +{ | ||
4467 | + int bstart, bend; | ||
4468 | + | ||
4469 | + BUG_ON(!inode); | ||
4470 | + BUG_ON(!UNIONFS_I(inode)); | ||
4471 | + bstart = ibstart(inode); | ||
4472 | + bend = ibend(inode); | ||
4473 | + BUG_ON(bstart < 0); | ||
4474 | + | ||
4475 | + iput_lowers(inode, bstart, bend, free_lower); | ||
4476 | + ibstart(inode) = ibend(inode) = -1; | ||
4477 | +} | ||
4478 | + | ||
4479 | +/* | ||
4480 | + * dput/mntput all lower dentries and vfsmounts of an unionfs dentry, from | ||
4481 | + * bstart to bend. If @free_lower is true, then also kfree the memory used | ||
4482 | + * to hold the lower object pointers. | ||
4483 | + * | ||
4484 | + * XXX: implement using path_put VFS macros | ||
4485 | + */ | ||
4486 | +static inline void path_put_lowers(struct dentry *dentry, | ||
4487 | + int bstart, int bend, bool free_lower) | ||
4488 | +{ | ||
4489 | + struct dentry *lower_dentry; | ||
4490 | + struct vfsmount *lower_mnt; | ||
4491 | + int bindex; | ||
4492 | + | ||
4493 | + BUG_ON(!dentry); | ||
4494 | + BUG_ON(!UNIONFS_D(dentry)); | ||
4495 | + BUG_ON(bstart < 0); | ||
4496 | + | ||
4497 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
4498 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
4499 | + if (lower_dentry) { | ||
4500 | + unionfs_set_lower_dentry_idx(dentry, bindex, NULL); | ||
4501 | + dput(lower_dentry); | ||
4502 | + } | ||
4503 | + lower_mnt = unionfs_lower_mnt_idx(dentry, bindex); | ||
4504 | + if (lower_mnt) { | ||
4505 | + unionfs_set_lower_mnt_idx(dentry, bindex, NULL); | ||
4506 | + mntput(lower_mnt); | ||
4507 | + } | ||
4508 | + } | ||
4509 | + | ||
4510 | + if (free_lower) { | ||
4511 | + kfree(UNIONFS_D(dentry)->lower_paths); | ||
4512 | + UNIONFS_D(dentry)->lower_paths = NULL; | ||
4513 | + } | ||
4514 | +} | ||
4515 | + | ||
4516 | +/* | ||
4517 | + * dput/mntput all lower dentries and vfsmounts, and reset start/end branch | ||
4518 | + * indices to -1. | ||
4519 | + */ | ||
4520 | +static inline void path_put_lowers_all(struct dentry *dentry, bool free_lower) | ||
4521 | +{ | ||
4522 | + int bstart, bend; | ||
4523 | + | ||
4524 | + BUG_ON(!dentry); | ||
4525 | + BUG_ON(!UNIONFS_D(dentry)); | ||
4526 | + bstart = dbstart(dentry); | ||
4527 | + bend = dbend(dentry); | ||
4528 | + BUG_ON(bstart < 0); | ||
4529 | + | ||
4530 | + path_put_lowers(dentry, bstart, bend, free_lower); | ||
4531 | + dbstart(dentry) = dbend(dentry) = -1; | ||
4532 | +} | ||
4533 | + | ||
4534 | +#endif /* not _FANOUT_H */ | ||
4535 | diff --git a/fs/unionfs/file.c b/fs/unionfs/file.c | ||
4536 | new file mode 100644 | ||
4537 | index 0000000..416c52f | ||
4538 | --- /dev/null | ||
4539 | +++ b/fs/unionfs/file.c | ||
4540 | @@ -0,0 +1,382 @@ | ||
4541 | +/* | ||
4542 | + * Copyright (c) 2003-2011 Erez Zadok | ||
4543 | + * Copyright (c) 2003-2006 Charles P. Wright | ||
4544 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
4545 | + * Copyright (c) 2005-2006 Junjiro Okajima | ||
4546 | + * Copyright (c) 2005 Arun M. Krishnakumar | ||
4547 | + * Copyright (c) 2004-2006 David P. Quigley | ||
4548 | + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair | ||
4549 | + * Copyright (c) 2003 Puja Gupta | ||
4550 | + * Copyright (c) 2003 Harikesavan Krishnan | ||
4551 | + * Copyright (c) 2003-2011 Stony Brook University | ||
4552 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
4553 | + * | ||
4554 | + * This program is free software; you can redistribute it and/or modify | ||
4555 | + * it under the terms of the GNU General Public License version 2 as | ||
4556 | + * published by the Free Software Foundation. | ||
4557 | + */ | ||
4558 | + | ||
4559 | +#include "union.h" | ||
4560 | + | ||
4561 | +static ssize_t unionfs_read(struct file *file, char __user *buf, | ||
4562 | + size_t count, loff_t *ppos) | ||
4563 | +{ | ||
4564 | + int err; | ||
4565 | + struct file *lower_file; | ||
4566 | + struct dentry *dentry = file->f_path.dentry; | ||
4567 | + struct dentry *parent; | ||
4568 | + | ||
4569 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT); | ||
4570 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
4571 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
4572 | + | ||
4573 | + err = unionfs_file_revalidate(file, parent, false); | ||
4574 | + if (unlikely(err)) | ||
4575 | + goto out; | ||
4576 | + | ||
4577 | + lower_file = unionfs_lower_file(file); | ||
4578 | + err = vfs_read(lower_file, buf, count, ppos); | ||
4579 | + /* update our inode atime upon a successful lower read */ | ||
4580 | + if (err >= 0) { | ||
4581 | + fsstack_copy_attr_atime(dentry->d_inode, | ||
4582 | + lower_file->f_path.dentry->d_inode); | ||
4583 | + unionfs_check_file(file); | ||
4584 | + } | ||
4585 | + | ||
4586 | +out: | ||
4587 | + unionfs_unlock_dentry(dentry); | ||
4588 | + unionfs_unlock_parent(dentry, parent); | ||
4589 | + unionfs_read_unlock(dentry->d_sb); | ||
4590 | + return err; | ||
4591 | +} | ||
4592 | + | ||
4593 | +static ssize_t unionfs_write(struct file *file, const char __user *buf, | ||
4594 | + size_t count, loff_t *ppos) | ||
4595 | +{ | ||
4596 | + int err = 0; | ||
4597 | + struct file *lower_file; | ||
4598 | + struct dentry *dentry = file->f_path.dentry; | ||
4599 | + struct dentry *parent; | ||
4600 | + | ||
4601 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT); | ||
4602 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
4603 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
4604 | + | ||
4605 | + err = unionfs_file_revalidate(file, parent, true); | ||
4606 | + if (unlikely(err)) | ||
4607 | + goto out; | ||
4608 | + | ||
4609 | + lower_file = unionfs_lower_file(file); | ||
4610 | + err = vfs_write(lower_file, buf, count, ppos); | ||
4611 | + /* update our inode times+sizes upon a successful lower write */ | ||
4612 | + if (err >= 0) { | ||
4613 | + fsstack_copy_inode_size(dentry->d_inode, | ||
4614 | + lower_file->f_path.dentry->d_inode); | ||
4615 | + fsstack_copy_attr_times(dentry->d_inode, | ||
4616 | + lower_file->f_path.dentry->d_inode); | ||
4617 | + UNIONFS_F(file)->wrote_to_file = true; /* for delayed copyup */ | ||
4618 | + unionfs_check_file(file); | ||
4619 | + } | ||
4620 | + | ||
4621 | +out: | ||
4622 | + unionfs_unlock_dentry(dentry); | ||
4623 | + unionfs_unlock_parent(dentry, parent); | ||
4624 | + unionfs_read_unlock(dentry->d_sb); | ||
4625 | + return err; | ||
4626 | +} | ||
4627 | + | ||
4628 | +static int unionfs_file_readdir(struct file *file, void *dirent, | ||
4629 | + filldir_t filldir) | ||
4630 | +{ | ||
4631 | + return -ENOTDIR; | ||
4632 | +} | ||
4633 | + | ||
4634 | +static int unionfs_mmap(struct file *file, struct vm_area_struct *vma) | ||
4635 | +{ | ||
4636 | + int err = 0; | ||
4637 | + bool willwrite; | ||
4638 | + struct file *lower_file; | ||
4639 | + struct dentry *dentry = file->f_path.dentry; | ||
4640 | + struct dentry *parent; | ||
4641 | + const struct vm_operations_struct *saved_vm_ops = NULL; | ||
4642 | + | ||
4643 | + /* | ||
4644 | + * Since mm/memory.c:might_fault() (under PROVE_LOCKING) was | ||
4645 | + * modified in 2.6.29-rc1 to call might_lock_read on mmap_sem, this | ||
4646 | + * has been causing false positives in file system stacking layers. | ||
4647 | + * In particular, our ->mmap is called after sys_mmap2 already holds | ||
4648 | + * mmap_sem, then we lock our own mutexes; but earlier, it's | ||
4649 | + * possible for lockdep to have locked our mutexes first, and then | ||
4650 | + * we call a lower ->readdir which could call might_fault. The | ||
4651 | + * different ordering of the locks is what lockdep complains about | ||
4652 | + * -- unnecessarily. Therefore, we have no choice but to tell | ||
4653 | + * lockdep to temporarily turn off lockdep here. Note: the comments | ||
4654 | + * inside might_sleep also suggest that it would have been | ||
4655 | + * nicer to only annotate paths that needs that might_lock_read. | ||
4656 | + */ | ||
4657 | + lockdep_off(); | ||
4658 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT); | ||
4659 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
4660 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
4661 | + | ||
4662 | + /* This might be deferred to mmap's writepage */ | ||
4663 | + willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags); | ||
4664 | + err = unionfs_file_revalidate(file, parent, willwrite); | ||
4665 | + if (unlikely(err)) | ||
4666 | + goto out; | ||
4667 | + unionfs_check_file(file); | ||
4668 | + | ||
4669 | + /* | ||
4670 | + * File systems which do not implement ->writepage may use | ||
4671 | + * generic_file_readonly_mmap as their ->mmap op. If you call | ||
4672 | + * generic_file_readonly_mmap with VM_WRITE, you'd get an -EINVAL. | ||
4673 | + * But we cannot call the lower ->mmap op, so we can't tell that | ||
4674 | + * writeable mappings won't work. Therefore, our only choice is to | ||
4675 | + * check if the lower file system supports the ->writepage, and if | ||
4676 | + * not, return EINVAL (the same error that | ||
4677 | + * generic_file_readonly_mmap returns in that case). | ||
4678 | + */ | ||
4679 | + lower_file = unionfs_lower_file(file); | ||
4680 | + if (willwrite && !lower_file->f_mapping->a_ops->writepage) { | ||
4681 | + err = -EINVAL; | ||
4682 | + printk(KERN_ERR "unionfs: branch %d file system does not " | ||
4683 | + "support writeable mmap\n", fbstart(file)); | ||
4684 | + goto out; | ||
4685 | + } | ||
4686 | + | ||
4687 | + /* | ||
4688 | + * find and save lower vm_ops. | ||
4689 | + * | ||
4690 | + * XXX: the VFS should have a cleaner way of finding the lower vm_ops | ||
4691 | + */ | ||
4692 | + if (!UNIONFS_F(file)->lower_vm_ops) { | ||
4693 | + err = lower_file->f_op->mmap(lower_file, vma); | ||
4694 | + if (err) { | ||
4695 | + printk(KERN_ERR "unionfs: lower mmap failed %d\n", err); | ||
4696 | + goto out; | ||
4697 | + } | ||
4698 | + saved_vm_ops = vma->vm_ops; | ||
4699 | + err = do_munmap(current->mm, vma->vm_start, | ||
4700 | + vma->vm_end - vma->vm_start); | ||
4701 | + if (err) { | ||
4702 | + printk(KERN_ERR "unionfs: do_munmap failed %d\n", err); | ||
4703 | + goto out; | ||
4704 | + } | ||
4705 | + } | ||
4706 | + | ||
4707 | + file->f_mapping->a_ops = &unionfs_dummy_aops; | ||
4708 | + err = generic_file_mmap(file, vma); | ||
4709 | + file->f_mapping->a_ops = &unionfs_aops; | ||
4710 | + if (err) { | ||
4711 | + printk(KERN_ERR "unionfs: generic_file_mmap failed %d\n", err); | ||
4712 | + goto out; | ||
4713 | + } | ||
4714 | + vma->vm_ops = &unionfs_vm_ops; | ||
4715 | + if (!UNIONFS_F(file)->lower_vm_ops) | ||
4716 | + UNIONFS_F(file)->lower_vm_ops = saved_vm_ops; | ||
4717 | + | ||
4718 | +out: | ||
4719 | + if (!err) { | ||
4720 | + /* copyup could cause parent dir times to change */ | ||
4721 | + unionfs_copy_attr_times(parent->d_inode); | ||
4722 | + unionfs_check_file(file); | ||
4723 | + } | ||
4724 | + unionfs_unlock_dentry(dentry); | ||
4725 | + unionfs_unlock_parent(dentry, parent); | ||
4726 | + unionfs_read_unlock(dentry->d_sb); | ||
4727 | + lockdep_on(); | ||
4728 | + return err; | ||
4729 | +} | ||
4730 | + | ||
4731 | +int unionfs_fsync(struct file *file, int datasync) | ||
4732 | +{ | ||
4733 | + int bindex, bstart, bend; | ||
4734 | + struct file *lower_file; | ||
4735 | + struct dentry *dentry = file->f_path.dentry; | ||
4736 | + struct dentry *lower_dentry; | ||
4737 | + struct dentry *parent; | ||
4738 | + struct inode *lower_inode, *inode; | ||
4739 | + int err = -EINVAL; | ||
4740 | + | ||
4741 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT); | ||
4742 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
4743 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
4744 | + | ||
4745 | + err = unionfs_file_revalidate(file, parent, true); | ||
4746 | + if (unlikely(err)) | ||
4747 | + goto out; | ||
4748 | + unionfs_check_file(file); | ||
4749 | + | ||
4750 | + bstart = fbstart(file); | ||
4751 | + bend = fbend(file); | ||
4752 | + if (bstart < 0 || bend < 0) | ||
4753 | + goto out; | ||
4754 | + | ||
4755 | + inode = dentry->d_inode; | ||
4756 | + if (unlikely(!inode)) { | ||
4757 | + printk(KERN_ERR | ||
4758 | + "unionfs: null lower inode in unionfs_fsync\n"); | ||
4759 | + goto out; | ||
4760 | + } | ||
4761 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
4762 | + lower_inode = unionfs_lower_inode_idx(inode, bindex); | ||
4763 | + if (!lower_inode || !lower_inode->i_fop->fsync) | ||
4764 | + continue; | ||
4765 | + lower_file = unionfs_lower_file_idx(file, bindex); | ||
4766 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
4767 | + mutex_lock(&lower_inode->i_mutex); | ||
4768 | + err = lower_inode->i_fop->fsync(lower_file, datasync); | ||
4769 | + if (!err && bindex == bstart) | ||
4770 | + fsstack_copy_attr_times(inode, lower_inode); | ||
4771 | + mutex_unlock(&lower_inode->i_mutex); | ||
4772 | + if (err) | ||
4773 | + goto out; | ||
4774 | + } | ||
4775 | + | ||
4776 | +out: | ||
4777 | + if (!err) | ||
4778 | + unionfs_check_file(file); | ||
4779 | + unionfs_unlock_dentry(dentry); | ||
4780 | + unionfs_unlock_parent(dentry, parent); | ||
4781 | + unionfs_read_unlock(dentry->d_sb); | ||
4782 | + return err; | ||
4783 | +} | ||
4784 | + | ||
4785 | +int unionfs_fasync(int fd, struct file *file, int flag) | ||
4786 | +{ | ||
4787 | + int bindex, bstart, bend; | ||
4788 | + struct file *lower_file; | ||
4789 | + struct dentry *dentry = file->f_path.dentry; | ||
4790 | + struct dentry *parent; | ||
4791 | + struct inode *lower_inode, *inode; | ||
4792 | + int err = 0; | ||
4793 | + | ||
4794 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT); | ||
4795 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
4796 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
4797 | + | ||
4798 | + err = unionfs_file_revalidate(file, parent, true); | ||
4799 | + if (unlikely(err)) | ||
4800 | + goto out; | ||
4801 | + unionfs_check_file(file); | ||
4802 | + | ||
4803 | + bstart = fbstart(file); | ||
4804 | + bend = fbend(file); | ||
4805 | + if (bstart < 0 || bend < 0) | ||
4806 | + goto out; | ||
4807 | + | ||
4808 | + inode = dentry->d_inode; | ||
4809 | + if (unlikely(!inode)) { | ||
4810 | + printk(KERN_ERR | ||
4811 | + "unionfs: null lower inode in unionfs_fasync\n"); | ||
4812 | + goto out; | ||
4813 | + } | ||
4814 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
4815 | + lower_inode = unionfs_lower_inode_idx(inode, bindex); | ||
4816 | + if (!lower_inode || !lower_inode->i_fop->fasync) | ||
4817 | + continue; | ||
4818 | + lower_file = unionfs_lower_file_idx(file, bindex); | ||
4819 | + mutex_lock(&lower_inode->i_mutex); | ||
4820 | + err = lower_inode->i_fop->fasync(fd, lower_file, flag); | ||
4821 | + if (!err && bindex == bstart) | ||
4822 | + fsstack_copy_attr_times(inode, lower_inode); | ||
4823 | + mutex_unlock(&lower_inode->i_mutex); | ||
4824 | + if (err) | ||
4825 | + goto out; | ||
4826 | + } | ||
4827 | + | ||
4828 | +out: | ||
4829 | + if (!err) | ||
4830 | + unionfs_check_file(file); | ||
4831 | + unionfs_unlock_dentry(dentry); | ||
4832 | + unionfs_unlock_parent(dentry, parent); | ||
4833 | + unionfs_read_unlock(dentry->d_sb); | ||
4834 | + return err; | ||
4835 | +} | ||
4836 | + | ||
4837 | +static ssize_t unionfs_splice_read(struct file *file, loff_t *ppos, | ||
4838 | + struct pipe_inode_info *pipe, size_t len, | ||
4839 | + unsigned int flags) | ||
4840 | +{ | ||
4841 | + ssize_t err; | ||
4842 | + struct file *lower_file; | ||
4843 | + struct dentry *dentry = file->f_path.dentry; | ||
4844 | + struct dentry *parent; | ||
4845 | + | ||
4846 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT); | ||
4847 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
4848 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
4849 | + | ||
4850 | + err = unionfs_file_revalidate(file, parent, false); | ||
4851 | + if (unlikely(err)) | ||
4852 | + goto out; | ||
4853 | + | ||
4854 | + lower_file = unionfs_lower_file(file); | ||
4855 | + err = vfs_splice_to(lower_file, ppos, pipe, len, flags); | ||
4856 | + /* update our inode atime upon a successful lower splice-read */ | ||
4857 | + if (err >= 0) { | ||
4858 | + fsstack_copy_attr_atime(dentry->d_inode, | ||
4859 | + lower_file->f_path.dentry->d_inode); | ||
4860 | + unionfs_check_file(file); | ||
4861 | + } | ||
4862 | + | ||
4863 | +out: | ||
4864 | + unionfs_unlock_dentry(dentry); | ||
4865 | + unionfs_unlock_parent(dentry, parent); | ||
4866 | + unionfs_read_unlock(dentry->d_sb); | ||
4867 | + return err; | ||
4868 | +} | ||
4869 | + | ||
4870 | +static ssize_t unionfs_splice_write(struct pipe_inode_info *pipe, | ||
4871 | + struct file *file, loff_t *ppos, | ||
4872 | + size_t len, unsigned int flags) | ||
4873 | +{ | ||
4874 | + ssize_t err = 0; | ||
4875 | + struct file *lower_file; | ||
4876 | + struct dentry *dentry = file->f_path.dentry; | ||
4877 | + struct dentry *parent; | ||
4878 | + | ||
4879 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT); | ||
4880 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
4881 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
4882 | + | ||
4883 | + err = unionfs_file_revalidate(file, parent, true); | ||
4884 | + if (unlikely(err)) | ||
4885 | + goto out; | ||
4886 | + | ||
4887 | + lower_file = unionfs_lower_file(file); | ||
4888 | + err = vfs_splice_from(pipe, lower_file, ppos, len, flags); | ||
4889 | + /* update our inode times+sizes upon a successful lower write */ | ||
4890 | + if (err >= 0) { | ||
4891 | + fsstack_copy_inode_size(dentry->d_inode, | ||
4892 | + lower_file->f_path.dentry->d_inode); | ||
4893 | + fsstack_copy_attr_times(dentry->d_inode, | ||
4894 | + lower_file->f_path.dentry->d_inode); | ||
4895 | + unionfs_check_file(file); | ||
4896 | + } | ||
4897 | + | ||
4898 | +out: | ||
4899 | + unionfs_unlock_dentry(dentry); | ||
4900 | + unionfs_unlock_parent(dentry, parent); | ||
4901 | + unionfs_read_unlock(dentry->d_sb); | ||
4902 | + return err; | ||
4903 | +} | ||
4904 | + | ||
4905 | +struct file_operations unionfs_main_fops = { | ||
4906 | + .llseek = generic_file_llseek, | ||
4907 | + .read = unionfs_read, | ||
4908 | + .write = unionfs_write, | ||
4909 | + .readdir = unionfs_file_readdir, | ||
4910 | + .unlocked_ioctl = unionfs_ioctl, | ||
4911 | +#ifdef CONFIG_COMPAT | ||
4912 | + .compat_ioctl = unionfs_ioctl, | ||
4913 | +#endif | ||
4914 | + .mmap = unionfs_mmap, | ||
4915 | + .open = unionfs_open, | ||
4916 | + .flush = unionfs_flush, | ||
4917 | + .release = unionfs_file_release, | ||
4918 | + .fsync = unionfs_fsync, | ||
4919 | + .fasync = unionfs_fasync, | ||
4920 | + .splice_read = unionfs_splice_read, | ||
4921 | + .splice_write = unionfs_splice_write, | ||
4922 | +}; | ||
4923 | diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c | ||
4924 | new file mode 100644 | ||
4925 | index 0000000..b207c13 | ||
4926 | --- /dev/null | ||
4927 | +++ b/fs/unionfs/inode.c | ||
4928 | @@ -0,0 +1,1099 @@ | ||
4929 | +/* | ||
4930 | + * Copyright (c) 2003-2011 Erez Zadok | ||
4931 | + * Copyright (c) 2003-2006 Charles P. Wright | ||
4932 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
4933 | + * Copyright (c) 2005-2006 Junjiro Okajima | ||
4934 | + * Copyright (c) 2005 Arun M. Krishnakumar | ||
4935 | + * Copyright (c) 2004-2006 David P. Quigley | ||
4936 | + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair | ||
4937 | + * Copyright (c) 2003 Puja Gupta | ||
4938 | + * Copyright (c) 2003 Harikesavan Krishnan | ||
4939 | + * Copyright (c) 2003-2011 Stony Brook University | ||
4940 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
4941 | + * | ||
4942 | + * This program is free software; you can redistribute it and/or modify | ||
4943 | + * it under the terms of the GNU General Public License version 2 as | ||
4944 | + * published by the Free Software Foundation. | ||
4945 | + */ | ||
4946 | + | ||
4947 | +#include "union.h" | ||
4948 | + | ||
4949 | +/* | ||
4950 | + * Find a writeable branch to create new object in. Checks all writeble | ||
4951 | + * branches of the parent inode, from istart to iend order; if none are | ||
4952 | + * suitable, also tries branch 0 (which may require a copyup). | ||
4953 | + * | ||
4954 | + * Return a lower_dentry we can use to create object in, or ERR_PTR. | ||
4955 | + */ | ||
4956 | +static struct dentry *find_writeable_branch(struct inode *parent, | ||
4957 | + struct dentry *dentry) | ||
4958 | +{ | ||
4959 | + int err = -EINVAL; | ||
4960 | + int bindex, istart, iend; | ||
4961 | + struct dentry *lower_dentry = NULL; | ||
4962 | + | ||
4963 | + istart = ibstart(parent); | ||
4964 | + iend = ibend(parent); | ||
4965 | + if (istart < 0) | ||
4966 | + goto out; | ||
4967 | + | ||
4968 | +begin: | ||
4969 | + for (bindex = istart; bindex <= iend; bindex++) { | ||
4970 | + /* skip non-writeable branches */ | ||
4971 | + err = is_robranch_super(dentry->d_sb, bindex); | ||
4972 | + if (err) { | ||
4973 | + err = -EROFS; | ||
4974 | + continue; | ||
4975 | + } | ||
4976 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
4977 | + if (!lower_dentry) | ||
4978 | + continue; | ||
4979 | + /* | ||
4980 | + * check for whiteouts in writeable branch, and remove them | ||
4981 | + * if necessary. | ||
4982 | + */ | ||
4983 | + err = check_unlink_whiteout(dentry, lower_dentry, bindex); | ||
4984 | + if (err > 0) /* ignore if whiteout found and removed */ | ||
4985 | + err = 0; | ||
4986 | + if (err) | ||
4987 | + continue; | ||
4988 | + /* if get here, we can write to the branch */ | ||
4989 | + break; | ||
4990 | + } | ||
4991 | + /* | ||
4992 | + * If istart wasn't already branch 0, and we got any error, then try | ||
4993 | + * branch 0 (which may require copyup) | ||
4994 | + */ | ||
4995 | + if (err && istart > 0) { | ||
4996 | + istart = iend = 0; | ||
4997 | + goto begin; | ||
4998 | + } | ||
4999 | + | ||
5000 | + /* | ||
5001 | + * If we tried even branch 0, and still got an error, abort. But if | ||
5002 | + * the error was an EROFS, then we should try to copyup. | ||
5003 | + */ | ||
5004 | + if (err && err != -EROFS) | ||
5005 | + goto out; | ||
5006 | + | ||
5007 | + /* | ||
5008 | + * If we get here, then check if copyup needed. If lower_dentry is | ||
5009 | + * NULL, create the entire dentry directory structure in branch 0. | ||
5010 | + */ | ||
5011 | + if (!lower_dentry) { | ||
5012 | + bindex = 0; | ||
5013 | + lower_dentry = create_parents(parent, dentry, | ||
5014 | + dentry->d_name.name, bindex); | ||
5015 | + if (IS_ERR(lower_dentry)) { | ||
5016 | + err = PTR_ERR(lower_dentry); | ||
5017 | + goto out; | ||
5018 | + } | ||
5019 | + } | ||
5020 | + err = 0; /* all's well */ | ||
5021 | +out: | ||
5022 | + if (err) | ||
5023 | + return ERR_PTR(err); | ||
5024 | + return lower_dentry; | ||
5025 | +} | ||
5026 | + | ||
5027 | +static int unionfs_create(struct inode *dir, struct dentry *dentry, | ||
5028 | + int mode, struct nameidata *nd_unused) | ||
5029 | +{ | ||
5030 | + int err = 0; | ||
5031 | + struct dentry *lower_dentry = NULL; | ||
5032 | + struct dentry *lower_parent_dentry = NULL; | ||
5033 | + struct dentry *parent; | ||
5034 | + int valid = 0; | ||
5035 | + struct nameidata lower_nd; | ||
5036 | + | ||
5037 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
5038 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
5039 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
5040 | + | ||
5041 | + valid = __unionfs_d_revalidate(dentry, parent, false); | ||
5042 | + if (unlikely(!valid)) { | ||
5043 | + err = -ESTALE; /* same as what real_lookup does */ | ||
5044 | + goto out; | ||
5045 | + } | ||
5046 | + | ||
5047 | + lower_dentry = find_writeable_branch(dir, dentry); | ||
5048 | + if (IS_ERR(lower_dentry)) { | ||
5049 | + err = PTR_ERR(lower_dentry); | ||
5050 | + goto out; | ||
5051 | + } | ||
5052 | + | ||
5053 | + lower_parent_dentry = lock_parent(lower_dentry); | ||
5054 | + if (IS_ERR(lower_parent_dentry)) { | ||
5055 | + err = PTR_ERR(lower_parent_dentry); | ||
5056 | + goto out_unlock; | ||
5057 | + } | ||
5058 | + | ||
5059 | + err = init_lower_nd(&lower_nd, LOOKUP_CREATE); | ||
5060 | + if (unlikely(err < 0)) | ||
5061 | + goto out_unlock; | ||
5062 | + err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode, | ||
5063 | + &lower_nd); | ||
5064 | + release_lower_nd(&lower_nd, err); | ||
5065 | + | ||
5066 | + if (!err) { | ||
5067 | + err = PTR_ERR(unionfs_interpose(dentry, dir->i_sb, 0)); | ||
5068 | + if (!err) { | ||
5069 | + unionfs_copy_attr_times(dir); | ||
5070 | + fsstack_copy_inode_size(dir, | ||
5071 | + lower_parent_dentry->d_inode); | ||
5072 | + /* update no. of links on parent directory */ | ||
5073 | + dir->i_nlink = unionfs_get_nlinks(dir); | ||
5074 | + } | ||
5075 | + } | ||
5076 | + | ||
5077 | +out_unlock: | ||
5078 | + unlock_dir(lower_parent_dentry); | ||
5079 | +out: | ||
5080 | + if (!err) { | ||
5081 | + unionfs_postcopyup_setmnt(dentry); | ||
5082 | + unionfs_check_inode(dir); | ||
5083 | + unionfs_check_dentry(dentry); | ||
5084 | + } | ||
5085 | + unionfs_unlock_dentry(dentry); | ||
5086 | + unionfs_unlock_parent(dentry, parent); | ||
5087 | + unionfs_read_unlock(dentry->d_sb); | ||
5088 | + return err; | ||
5089 | +} | ||
5090 | + | ||
5091 | +/* | ||
5092 | + * unionfs_lookup is the only special function which takes a dentry, yet we | ||
5093 | + * do NOT want to call __unionfs_d_revalidate_chain because by definition, | ||
5094 | + * we don't have a valid dentry here yet. | ||
5095 | + */ | ||
5096 | +static struct dentry *unionfs_lookup(struct inode *dir, | ||
5097 | + struct dentry *dentry, | ||
5098 | + struct nameidata *nd_unused) | ||
5099 | +{ | ||
5100 | + struct dentry *ret, *parent; | ||
5101 | + int err = 0; | ||
5102 | + | ||
5103 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
5104 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
5105 | + | ||
5106 | + /* | ||
5107 | + * As long as we lock/dget the parent, then can skip validating the | ||
5108 | + * parent now; we may have to rebuild this dentry on the next | ||
5109 | + * ->d_revalidate, however. | ||
5110 | + */ | ||
5111 | + | ||
5112 | + /* allocate dentry private data. We free it in ->d_release */ | ||
5113 | + err = new_dentry_private_data(dentry, UNIONFS_DMUTEX_CHILD); | ||
5114 | + if (unlikely(err)) { | ||
5115 | + ret = ERR_PTR(err); | ||
5116 | + goto out; | ||
5117 | + } | ||
5118 | + | ||
5119 | + ret = unionfs_lookup_full(dentry, parent, INTERPOSE_LOOKUP); | ||
5120 | + | ||
5121 | + if (!IS_ERR(ret)) { | ||
5122 | + if (ret) | ||
5123 | + dentry = ret; | ||
5124 | + /* lookup_full can return multiple positive dentries */ | ||
5125 | + if (dentry->d_inode && !S_ISDIR(dentry->d_inode->i_mode)) { | ||
5126 | + BUG_ON(dbstart(dentry) < 0); | ||
5127 | + unionfs_postcopyup_release(dentry); | ||
5128 | + } | ||
5129 | + unionfs_copy_attr_times(dentry->d_inode); | ||
5130 | + } | ||
5131 | + | ||
5132 | + unionfs_check_inode(dir); | ||
5133 | + if (!IS_ERR(ret)) | ||
5134 | + unionfs_check_dentry(dentry); | ||
5135 | + unionfs_check_dentry(parent); | ||
5136 | + unionfs_unlock_dentry(dentry); /* locked in new_dentry_private data */ | ||
5137 | + | ||
5138 | +out: | ||
5139 | + unionfs_unlock_parent(dentry, parent); | ||
5140 | + unionfs_read_unlock(dentry->d_sb); | ||
5141 | + | ||
5142 | + return ret; | ||
5143 | +} | ||
5144 | + | ||
5145 | +static int unionfs_link(struct dentry *old_dentry, struct inode *dir, | ||
5146 | + struct dentry *new_dentry) | ||
5147 | +{ | ||
5148 | + int err = 0; | ||
5149 | + struct dentry *lower_old_dentry = NULL; | ||
5150 | + struct dentry *lower_new_dentry = NULL; | ||
5151 | + struct dentry *lower_dir_dentry = NULL; | ||
5152 | + struct dentry *old_parent, *new_parent; | ||
5153 | + char *name = NULL; | ||
5154 | + bool valid; | ||
5155 | + | ||
5156 | + unionfs_read_lock(old_dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
5157 | + old_parent = dget_parent(old_dentry); | ||
5158 | + new_parent = dget_parent(new_dentry); | ||
5159 | + unionfs_double_lock_parents(old_parent, new_parent); | ||
5160 | + unionfs_double_lock_dentry(old_dentry, new_dentry); | ||
5161 | + | ||
5162 | + valid = __unionfs_d_revalidate(old_dentry, old_parent, false); | ||
5163 | + if (unlikely(!valid)) { | ||
5164 | + err = -ESTALE; | ||
5165 | + goto out; | ||
5166 | + } | ||
5167 | + if (new_dentry->d_inode) { | ||
5168 | + valid = __unionfs_d_revalidate(new_dentry, new_parent, false); | ||
5169 | + if (unlikely(!valid)) { | ||
5170 | + err = -ESTALE; | ||
5171 | + goto out; | ||
5172 | + } | ||
5173 | + } | ||
5174 | + | ||
5175 | + lower_new_dentry = unionfs_lower_dentry(new_dentry); | ||
5176 | + | ||
5177 | + /* check for a whiteout in new dentry branch, and delete it */ | ||
5178 | + err = check_unlink_whiteout(new_dentry, lower_new_dentry, | ||
5179 | + dbstart(new_dentry)); | ||
5180 | + if (err > 0) { /* whiteout found and removed successfully */ | ||
5181 | + lower_dir_dentry = dget_parent(lower_new_dentry); | ||
5182 | + fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); | ||
5183 | + dput(lower_dir_dentry); | ||
5184 | + dir->i_nlink = unionfs_get_nlinks(dir); | ||
5185 | + err = 0; | ||
5186 | + } | ||
5187 | + if (err) | ||
5188 | + goto out; | ||
5189 | + | ||
5190 | + /* check if parent hierachy is needed, then link in same branch */ | ||
5191 | + if (dbstart(old_dentry) != dbstart(new_dentry)) { | ||
5192 | + lower_new_dentry = create_parents(dir, new_dentry, | ||
5193 | + new_dentry->d_name.name, | ||
5194 | + dbstart(old_dentry)); | ||
5195 | + err = PTR_ERR(lower_new_dentry); | ||
5196 | + if (IS_COPYUP_ERR(err)) | ||
5197 | + goto docopyup; | ||
5198 | + if (!lower_new_dentry || IS_ERR(lower_new_dentry)) | ||
5199 | + goto out; | ||
5200 | + } | ||
5201 | + lower_new_dentry = unionfs_lower_dentry(new_dentry); | ||
5202 | + lower_old_dentry = unionfs_lower_dentry(old_dentry); | ||
5203 | + | ||
5204 | + BUG_ON(dbstart(old_dentry) != dbstart(new_dentry)); | ||
5205 | + lower_dir_dentry = lock_parent(lower_new_dentry); | ||
5206 | + err = is_robranch(old_dentry); | ||
5207 | + if (!err) { | ||
5208 | + /* see Documentation/filesystems/unionfs/issues.txt */ | ||
5209 | + lockdep_off(); | ||
5210 | + err = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode, | ||
5211 | + lower_new_dentry); | ||
5212 | + lockdep_on(); | ||
5213 | + } | ||
5214 | + unlock_dir(lower_dir_dentry); | ||
5215 | + | ||
5216 | +docopyup: | ||
5217 | + if (IS_COPYUP_ERR(err)) { | ||
5218 | + int old_bstart = dbstart(old_dentry); | ||
5219 | + int bindex; | ||
5220 | + | ||
5221 | + for (bindex = old_bstart - 1; bindex >= 0; bindex--) { | ||
5222 | + err = copyup_dentry(old_parent->d_inode, | ||
5223 | + old_dentry, old_bstart, | ||
5224 | + bindex, old_dentry->d_name.name, | ||
5225 | + old_dentry->d_name.len, NULL, | ||
5226 | + i_size_read(old_dentry->d_inode)); | ||
5227 | + if (err) | ||
5228 | + continue; | ||
5229 | + lower_new_dentry = | ||
5230 | + create_parents(dir, new_dentry, | ||
5231 | + new_dentry->d_name.name, | ||
5232 | + bindex); | ||
5233 | + lower_old_dentry = unionfs_lower_dentry(old_dentry); | ||
5234 | + lower_dir_dentry = lock_parent(lower_new_dentry); | ||
5235 | + /* see Documentation/filesystems/unionfs/issues.txt */ | ||
5236 | + lockdep_off(); | ||
5237 | + /* do vfs_link */ | ||
5238 | + err = vfs_link(lower_old_dentry, | ||
5239 | + lower_dir_dentry->d_inode, | ||
5240 | + lower_new_dentry); | ||
5241 | + lockdep_on(); | ||
5242 | + unlock_dir(lower_dir_dentry); | ||
5243 | + goto check_link; | ||
5244 | + } | ||
5245 | + goto out; | ||
5246 | + } | ||
5247 | + | ||
5248 | +check_link: | ||
5249 | + if (err || !lower_new_dentry->d_inode) | ||
5250 | + goto out; | ||
5251 | + | ||
5252 | + /* Its a hard link, so use the same inode */ | ||
5253 | + new_dentry->d_inode = igrab(old_dentry->d_inode); | ||
5254 | + d_add(new_dentry, new_dentry->d_inode); | ||
5255 | + unionfs_copy_attr_all(dir, lower_new_dentry->d_parent->d_inode); | ||
5256 | + fsstack_copy_inode_size(dir, lower_new_dentry->d_parent->d_inode); | ||
5257 | + | ||
5258 | + /* propagate number of hard-links */ | ||
5259 | + old_dentry->d_inode->i_nlink = unionfs_get_nlinks(old_dentry->d_inode); | ||
5260 | + /* new dentry's ctime may have changed due to hard-link counts */ | ||
5261 | + unionfs_copy_attr_times(new_dentry->d_inode); | ||
5262 | + | ||
5263 | +out: | ||
5264 | + if (!new_dentry->d_inode) | ||
5265 | + d_drop(new_dentry); | ||
5266 | + | ||
5267 | + kfree(name); | ||
5268 | + if (!err) | ||
5269 | + unionfs_postcopyup_setmnt(new_dentry); | ||
5270 | + | ||
5271 | + unionfs_check_inode(dir); | ||
5272 | + unionfs_check_dentry(new_dentry); | ||
5273 | + unionfs_check_dentry(old_dentry); | ||
5274 | + | ||
5275 | + unionfs_double_unlock_dentry(old_dentry, new_dentry); | ||
5276 | + unionfs_double_unlock_parents(old_parent, new_parent); | ||
5277 | + dput(new_parent); | ||
5278 | + dput(old_parent); | ||
5279 | + unionfs_read_unlock(old_dentry->d_sb); | ||
5280 | + | ||
5281 | + return err; | ||
5282 | +} | ||
5283 | + | ||
5284 | +static int unionfs_symlink(struct inode *dir, struct dentry *dentry, | ||
5285 | + const char *symname) | ||
5286 | +{ | ||
5287 | + int err = 0; | ||
5288 | + struct dentry *lower_dentry = NULL; | ||
5289 | + struct dentry *wh_dentry = NULL; | ||
5290 | + struct dentry *lower_parent_dentry = NULL; | ||
5291 | + struct dentry *parent; | ||
5292 | + char *name = NULL; | ||
5293 | + int valid = 0; | ||
5294 | + umode_t mode; | ||
5295 | + | ||
5296 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
5297 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
5298 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
5299 | + | ||
5300 | + valid = __unionfs_d_revalidate(dentry, parent, false); | ||
5301 | + if (unlikely(!valid)) { | ||
5302 | + err = -ESTALE; | ||
5303 | + goto out; | ||
5304 | + } | ||
5305 | + | ||
5306 | + /* | ||
5307 | + * It's only a bug if this dentry was not negative and couldn't be | ||
5308 | + * revalidated (shouldn't happen). | ||
5309 | + */ | ||
5310 | + BUG_ON(!valid && dentry->d_inode); | ||
5311 | + | ||
5312 | + lower_dentry = find_writeable_branch(dir, dentry); | ||
5313 | + if (IS_ERR(lower_dentry)) { | ||
5314 | + err = PTR_ERR(lower_dentry); | ||
5315 | + goto out; | ||
5316 | + } | ||
5317 | + | ||
5318 | + lower_parent_dentry = lock_parent(lower_dentry); | ||
5319 | + if (IS_ERR(lower_parent_dentry)) { | ||
5320 | + err = PTR_ERR(lower_parent_dentry); | ||
5321 | + goto out_unlock; | ||
5322 | + } | ||
5323 | + | ||
5324 | + mode = S_IALLUGO; | ||
5325 | + err = vfs_symlink(lower_parent_dentry->d_inode, lower_dentry, symname); | ||
5326 | + if (!err) { | ||
5327 | + err = PTR_ERR(unionfs_interpose(dentry, dir->i_sb, 0)); | ||
5328 | + if (!err) { | ||
5329 | + unionfs_copy_attr_times(dir); | ||
5330 | + fsstack_copy_inode_size(dir, | ||
5331 | + lower_parent_dentry->d_inode); | ||
5332 | + /* update no. of links on parent directory */ | ||
5333 | + dir->i_nlink = unionfs_get_nlinks(dir); | ||
5334 | + } | ||
5335 | + } | ||
5336 | + | ||
5337 | +out_unlock: | ||
5338 | + unlock_dir(lower_parent_dentry); | ||
5339 | +out: | ||
5340 | + dput(wh_dentry); | ||
5341 | + kfree(name); | ||
5342 | + | ||
5343 | + if (!err) { | ||
5344 | + unionfs_postcopyup_setmnt(dentry); | ||
5345 | + unionfs_check_inode(dir); | ||
5346 | + unionfs_check_dentry(dentry); | ||
5347 | + } | ||
5348 | + unionfs_unlock_dentry(dentry); | ||
5349 | + unionfs_unlock_parent(dentry, parent); | ||
5350 | + unionfs_read_unlock(dentry->d_sb); | ||
5351 | + return err; | ||
5352 | +} | ||
5353 | + | ||
5354 | +static int unionfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | ||
5355 | +{ | ||
5356 | + int err = 0; | ||
5357 | + struct dentry *lower_dentry = NULL; | ||
5358 | + struct dentry *lower_parent_dentry = NULL; | ||
5359 | + struct dentry *parent; | ||
5360 | + int bindex = 0, bstart; | ||
5361 | + char *name = NULL; | ||
5362 | + int valid; | ||
5363 | + | ||
5364 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
5365 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
5366 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
5367 | + | ||
5368 | + valid = __unionfs_d_revalidate(dentry, parent, false); | ||
5369 | + if (unlikely(!valid)) { | ||
5370 | + err = -ESTALE; /* same as what real_lookup does */ | ||
5371 | + goto out; | ||
5372 | + } | ||
5373 | + | ||
5374 | + bstart = dbstart(dentry); | ||
5375 | + | ||
5376 | + lower_dentry = unionfs_lower_dentry(dentry); | ||
5377 | + | ||
5378 | + /* check for a whiteout in new dentry branch, and delete it */ | ||
5379 | + err = check_unlink_whiteout(dentry, lower_dentry, bstart); | ||
5380 | + if (err > 0) /* whiteout found and removed successfully */ | ||
5381 | + err = 0; | ||
5382 | + if (err) { | ||
5383 | + /* exit if the error returned was NOT -EROFS */ | ||
5384 | + if (!IS_COPYUP_ERR(err)) | ||
5385 | + goto out; | ||
5386 | + bstart--; | ||
5387 | + } | ||
5388 | + | ||
5389 | + /* check if copyup's needed, and mkdir */ | ||
5390 | + for (bindex = bstart; bindex >= 0; bindex--) { | ||
5391 | + int i; | ||
5392 | + int bend = dbend(dentry); | ||
5393 | + | ||
5394 | + if (is_robranch_super(dentry->d_sb, bindex)) | ||
5395 | + continue; | ||
5396 | + | ||
5397 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
5398 | + if (!lower_dentry) { | ||
5399 | + lower_dentry = create_parents(dir, dentry, | ||
5400 | + dentry->d_name.name, | ||
5401 | + bindex); | ||
5402 | + if (!lower_dentry || IS_ERR(lower_dentry)) { | ||
5403 | + printk(KERN_ERR "unionfs: lower dentry " | ||
5404 | + " NULL for bindex = %d\n", bindex); | ||
5405 | + continue; | ||
5406 | + } | ||
5407 | + } | ||
5408 | + | ||
5409 | + lower_parent_dentry = lock_parent(lower_dentry); | ||
5410 | + | ||
5411 | + if (IS_ERR(lower_parent_dentry)) { | ||
5412 | + err = PTR_ERR(lower_parent_dentry); | ||
5413 | + goto out; | ||
5414 | + } | ||
5415 | + | ||
5416 | + err = vfs_mkdir(lower_parent_dentry->d_inode, lower_dentry, | ||
5417 | + mode); | ||
5418 | + | ||
5419 | + unlock_dir(lower_parent_dentry); | ||
5420 | + | ||
5421 | + /* did the mkdir succeed? */ | ||
5422 | + if (err) | ||
5423 | + break; | ||
5424 | + | ||
5425 | + for (i = bindex + 1; i <= bend; i++) { | ||
5426 | + /* XXX: use path_put_lowers? */ | ||
5427 | + if (unionfs_lower_dentry_idx(dentry, i)) { | ||
5428 | + dput(unionfs_lower_dentry_idx(dentry, i)); | ||
5429 | + unionfs_set_lower_dentry_idx(dentry, i, NULL); | ||
5430 | + } | ||
5431 | + } | ||
5432 | + dbend(dentry) = bindex; | ||
5433 | + | ||
5434 | + /* | ||
5435 | + * Only INTERPOSE_LOOKUP can return a value other than 0 on | ||
5436 | + * err. | ||
5437 | + */ | ||
5438 | + err = PTR_ERR(unionfs_interpose(dentry, dir->i_sb, 0)); | ||
5439 | + if (!err) { | ||
5440 | + unionfs_copy_attr_times(dir); | ||
5441 | + fsstack_copy_inode_size(dir, | ||
5442 | + lower_parent_dentry->d_inode); | ||
5443 | + | ||
5444 | + /* update number of links on parent directory */ | ||
5445 | + dir->i_nlink = unionfs_get_nlinks(dir); | ||
5446 | + } | ||
5447 | + | ||
5448 | + err = make_dir_opaque(dentry, dbstart(dentry)); | ||
5449 | + if (err) { | ||
5450 | + printk(KERN_ERR "unionfs: mkdir: error creating " | ||
5451 | + ".wh.__dir_opaque: %d\n", err); | ||
5452 | + goto out; | ||
5453 | + } | ||
5454 | + | ||
5455 | + /* we are done! */ | ||
5456 | + break; | ||
5457 | + } | ||
5458 | + | ||
5459 | +out: | ||
5460 | + if (!dentry->d_inode) | ||
5461 | + d_drop(dentry); | ||
5462 | + | ||
5463 | + kfree(name); | ||
5464 | + | ||
5465 | + if (!err) { | ||
5466 | + unionfs_copy_attr_times(dentry->d_inode); | ||
5467 | + unionfs_postcopyup_setmnt(dentry); | ||
5468 | + } | ||
5469 | + unionfs_check_inode(dir); | ||
5470 | + unionfs_check_dentry(dentry); | ||
5471 | + unionfs_unlock_dentry(dentry); | ||
5472 | + unionfs_unlock_parent(dentry, parent); | ||
5473 | + unionfs_read_unlock(dentry->d_sb); | ||
5474 | + | ||
5475 | + return err; | ||
5476 | +} | ||
5477 | + | ||
5478 | +static int unionfs_mknod(struct inode *dir, struct dentry *dentry, int mode, | ||
5479 | + dev_t dev) | ||
5480 | +{ | ||
5481 | + int err = 0; | ||
5482 | + struct dentry *lower_dentry = NULL; | ||
5483 | + struct dentry *wh_dentry = NULL; | ||
5484 | + struct dentry *lower_parent_dentry = NULL; | ||
5485 | + struct dentry *parent; | ||
5486 | + char *name = NULL; | ||
5487 | + int valid = 0; | ||
5488 | + | ||
5489 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
5490 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
5491 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
5492 | + | ||
5493 | + valid = __unionfs_d_revalidate(dentry, parent, false); | ||
5494 | + if (unlikely(!valid)) { | ||
5495 | + err = -ESTALE; | ||
5496 | + goto out; | ||
5497 | + } | ||
5498 | + | ||
5499 | + /* | ||
5500 | + * It's only a bug if this dentry was not negative and couldn't be | ||
5501 | + * revalidated (shouldn't happen). | ||
5502 | + */ | ||
5503 | + BUG_ON(!valid && dentry->d_inode); | ||
5504 | + | ||
5505 | + lower_dentry = find_writeable_branch(dir, dentry); | ||
5506 | + if (IS_ERR(lower_dentry)) { | ||
5507 | + err = PTR_ERR(lower_dentry); | ||
5508 | + goto out; | ||
5509 | + } | ||
5510 | + | ||
5511 | + lower_parent_dentry = lock_parent(lower_dentry); | ||
5512 | + if (IS_ERR(lower_parent_dentry)) { | ||
5513 | + err = PTR_ERR(lower_parent_dentry); | ||
5514 | + goto out_unlock; | ||
5515 | + } | ||
5516 | + | ||
5517 | + err = vfs_mknod(lower_parent_dentry->d_inode, lower_dentry, mode, dev); | ||
5518 | + if (!err) { | ||
5519 | + err = PTR_ERR(unionfs_interpose(dentry, dir->i_sb, 0)); | ||
5520 | + if (!err) { | ||
5521 | + unionfs_copy_attr_times(dir); | ||
5522 | + fsstack_copy_inode_size(dir, | ||
5523 | + lower_parent_dentry->d_inode); | ||
5524 | + /* update no. of links on parent directory */ | ||
5525 | + dir->i_nlink = unionfs_get_nlinks(dir); | ||
5526 | + } | ||
5527 | + } | ||
5528 | + | ||
5529 | +out_unlock: | ||
5530 | + unlock_dir(lower_parent_dentry); | ||
5531 | +out: | ||
5532 | + dput(wh_dentry); | ||
5533 | + kfree(name); | ||
5534 | + | ||
5535 | + if (!err) { | ||
5536 | + unionfs_postcopyup_setmnt(dentry); | ||
5537 | + unionfs_check_inode(dir); | ||
5538 | + unionfs_check_dentry(dentry); | ||
5539 | + } | ||
5540 | + unionfs_unlock_dentry(dentry); | ||
5541 | + unionfs_unlock_parent(dentry, parent); | ||
5542 | + unionfs_read_unlock(dentry->d_sb); | ||
5543 | + return err; | ||
5544 | +} | ||
5545 | + | ||
5546 | +/* requires sb, dentry, and parent to already be locked */ | ||
5547 | +static int __unionfs_readlink(struct dentry *dentry, char __user *buf, | ||
5548 | + int bufsiz) | ||
5549 | +{ | ||
5550 | + int err; | ||
5551 | + struct dentry *lower_dentry; | ||
5552 | + | ||
5553 | + lower_dentry = unionfs_lower_dentry(dentry); | ||
5554 | + | ||
5555 | + if (!lower_dentry->d_inode->i_op || | ||
5556 | + !lower_dentry->d_inode->i_op->readlink) { | ||
5557 | + err = -EINVAL; | ||
5558 | + goto out; | ||
5559 | + } | ||
5560 | + | ||
5561 | + err = lower_dentry->d_inode->i_op->readlink(lower_dentry, | ||
5562 | + buf, bufsiz); | ||
5563 | + if (err >= 0) | ||
5564 | + fsstack_copy_attr_atime(dentry->d_inode, | ||
5565 | + lower_dentry->d_inode); | ||
5566 | + | ||
5567 | +out: | ||
5568 | + return err; | ||
5569 | +} | ||
5570 | + | ||
5571 | +static int unionfs_readlink(struct dentry *dentry, char __user *buf, | ||
5572 | + int bufsiz) | ||
5573 | +{ | ||
5574 | + int err; | ||
5575 | + struct dentry *parent; | ||
5576 | + | ||
5577 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
5578 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
5579 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
5580 | + | ||
5581 | + if (unlikely(!__unionfs_d_revalidate(dentry, parent, false))) { | ||
5582 | + err = -ESTALE; | ||
5583 | + goto out; | ||
5584 | + } | ||
5585 | + | ||
5586 | + err = __unionfs_readlink(dentry, buf, bufsiz); | ||
5587 | + | ||
5588 | +out: | ||
5589 | + unionfs_check_dentry(dentry); | ||
5590 | + unionfs_unlock_dentry(dentry); | ||
5591 | + unionfs_unlock_parent(dentry, parent); | ||
5592 | + unionfs_read_unlock(dentry->d_sb); | ||
5593 | + | ||
5594 | + return err; | ||
5595 | +} | ||
5596 | + | ||
5597 | +static void *unionfs_follow_link(struct dentry *dentry, struct nameidata *nd) | ||
5598 | +{ | ||
5599 | + char *buf; | ||
5600 | + int len = PAGE_SIZE, err; | ||
5601 | + mm_segment_t old_fs; | ||
5602 | + struct dentry *parent; | ||
5603 | + | ||
5604 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
5605 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
5606 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
5607 | + | ||
5608 | + /* This is freed by the put_link method assuming a successful call. */ | ||
5609 | + buf = kmalloc(len, GFP_KERNEL); | ||
5610 | + if (unlikely(!buf)) { | ||
5611 | + err = -ENOMEM; | ||
5612 | + goto out; | ||
5613 | + } | ||
5614 | + | ||
5615 | + /* read the symlink, and then we will follow it */ | ||
5616 | + old_fs = get_fs(); | ||
5617 | + set_fs(KERNEL_DS); | ||
5618 | + err = __unionfs_readlink(dentry, buf, len); | ||
5619 | + set_fs(old_fs); | ||
5620 | + if (err < 0) { | ||
5621 | + kfree(buf); | ||
5622 | + buf = NULL; | ||
5623 | + goto out; | ||
5624 | + } | ||
5625 | + buf[err] = 0; | ||
5626 | + nd_set_link(nd, buf); | ||
5627 | + err = 0; | ||
5628 | + | ||
5629 | +out: | ||
5630 | + if (err >= 0) { | ||
5631 | + unionfs_check_nd(nd); | ||
5632 | + unionfs_check_dentry(dentry); | ||
5633 | + } | ||
5634 | + | ||
5635 | + unionfs_unlock_dentry(dentry); | ||
5636 | + unionfs_unlock_parent(dentry, parent); | ||
5637 | + unionfs_read_unlock(dentry->d_sb); | ||
5638 | + | ||
5639 | + return ERR_PTR(err); | ||
5640 | +} | ||
5641 | + | ||
5642 | +/* this @nd *IS* still used */ | ||
5643 | +static void unionfs_put_link(struct dentry *dentry, struct nameidata *nd, | ||
5644 | + void *cookie) | ||
5645 | +{ | ||
5646 | + struct dentry *parent; | ||
5647 | + char *buf; | ||
5648 | + | ||
5649 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
5650 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
5651 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
5652 | + | ||
5653 | + if (unlikely(!__unionfs_d_revalidate(dentry, parent, false))) | ||
5654 | + printk(KERN_ERR | ||
5655 | + "unionfs: put_link failed to revalidate dentry\n"); | ||
5656 | + | ||
5657 | + unionfs_check_dentry(dentry); | ||
5658 | +#if 0 | ||
5659 | + /* XXX: can't run this check b/c this fxn can receive a poisoned 'nd' PTR */ | ||
5660 | + unionfs_check_nd(nd); | ||
5661 | +#endif | ||
5662 | + buf = nd_get_link(nd); | ||
5663 | + if (!IS_ERR(buf)) | ||
5664 | + kfree(buf); | ||
5665 | + unionfs_unlock_dentry(dentry); | ||
5666 | + unionfs_unlock_parent(dentry, parent); | ||
5667 | + unionfs_read_unlock(dentry->d_sb); | ||
5668 | +} | ||
5669 | + | ||
5670 | +/* | ||
5671 | + * This is a variant of fs/namei.c:permission() or inode_permission() which | ||
5672 | + * skips over EROFS tests (because we perform copyup on EROFS). | ||
5673 | + */ | ||
5674 | +static int __inode_permission(struct inode *inode, int mask, unsigned int flags) | ||
5675 | +{ | ||
5676 | + int retval; | ||
5677 | + | ||
5678 | + /* nobody gets write access to an immutable file */ | ||
5679 | + if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode)) | ||
5680 | + return -EACCES; | ||
5681 | + | ||
5682 | + /* Ordinary permission routines do not understand MAY_APPEND. */ | ||
5683 | + if (inode->i_op && inode->i_op->permission) { | ||
5684 | + retval = inode->i_op->permission(inode, mask, flags); | ||
5685 | + if (!retval) { | ||
5686 | + /* | ||
5687 | + * Exec permission on a regular file is denied if none | ||
5688 | + * of the execute bits are set. | ||
5689 | + * | ||
5690 | + * This check should be done by the ->permission() | ||
5691 | + * method. | ||
5692 | + */ | ||
5693 | + if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode) && | ||
5694 | + !(inode->i_mode & S_IXUGO)) | ||
5695 | + return -EACCES; | ||
5696 | + } | ||
5697 | + } else { | ||
5698 | + retval = generic_permission(inode, mask, flags, NULL); | ||
5699 | + } | ||
5700 | + if (retval) | ||
5701 | + return retval; | ||
5702 | + | ||
5703 | + return security_inode_permission(inode, | ||
5704 | + mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND)); | ||
5705 | +} | ||
5706 | + | ||
5707 | +/* | ||
5708 | + * Don't grab the superblock read-lock in unionfs_permission, which prevents | ||
5709 | + * a deadlock with the branch-management "add branch" code (which grabbed | ||
5710 | + * the write lock). It is safe to not grab the read lock here, because even | ||
5711 | + * with branch management taking place, there is no chance that | ||
5712 | + * unionfs_permission, or anything it calls, will use stale branch | ||
5713 | + * information. | ||
5714 | + */ | ||
5715 | +static int unionfs_permission(struct inode *inode, int mask, unsigned int flags) | ||
5716 | +{ | ||
5717 | + struct inode *lower_inode = NULL; | ||
5718 | + int err = 0; | ||
5719 | + int bindex, bstart, bend; | ||
5720 | + int is_file; | ||
5721 | + const int write_mask = (mask & MAY_WRITE) && !(mask & MAY_READ); | ||
5722 | + struct inode *inode_grabbed; | ||
5723 | + struct dentry *dentry; | ||
5724 | + | ||
5725 | + if (flags & IPERM_FLAG_RCU) { | ||
5726 | + err = -ECHILD; | ||
5727 | + goto out_nograb; | ||
5728 | + } | ||
5729 | + | ||
5730 | + dentry = d_find_alias(inode); | ||
5731 | + if (dentry) | ||
5732 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
5733 | + | ||
5734 | + inode_grabbed = igrab(inode); | ||
5735 | + is_file = !S_ISDIR(inode->i_mode); | ||
5736 | + | ||
5737 | + if (!UNIONFS_I(inode)->lower_inodes) { | ||
5738 | + if (is_file) /* dirs can be unlinked but chdir'ed to */ | ||
5739 | + err = -ESTALE; /* force revalidate */ | ||
5740 | + goto out; | ||
5741 | + } | ||
5742 | + bstart = ibstart(inode); | ||
5743 | + bend = ibend(inode); | ||
5744 | + if (unlikely(bstart < 0 || bend < 0)) { | ||
5745 | + /* | ||
5746 | + * With branch-management, we can get a stale inode here. | ||
5747 | + * If so, we return ESTALE back to link_path_walk, which | ||
5748 | + * would discard the dcache entry and re-lookup the | ||
5749 | + * dentry+inode. This should be equivalent to issuing | ||
5750 | + * __unionfs_d_revalidate_chain on nd.dentry here. | ||
5751 | + */ | ||
5752 | + if (is_file) /* dirs can be unlinked but chdir'ed to */ | ||
5753 | + err = -ESTALE; /* force revalidate */ | ||
5754 | + goto out; | ||
5755 | + } | ||
5756 | + | ||
5757 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
5758 | + lower_inode = unionfs_lower_inode_idx(inode, bindex); | ||
5759 | + if (!lower_inode) | ||
5760 | + continue; | ||
5761 | + | ||
5762 | + /* | ||
5763 | + * check the condition for D-F-D underlying files/directories, | ||
5764 | + * we don't have to check for files, if we are checking for | ||
5765 | + * directories. | ||
5766 | + */ | ||
5767 | + if (!is_file && !S_ISDIR(lower_inode->i_mode)) | ||
5768 | + continue; | ||
5769 | + | ||
5770 | + /* | ||
5771 | + * We check basic permissions, but we ignore any conditions | ||
5772 | + * such as readonly file systems or branches marked as | ||
5773 | + * readonly, because those conditions should lead to a | ||
5774 | + * copyup taking place later on. However, if user never had | ||
5775 | + * access to the file, then no copyup could ever take place. | ||
5776 | + */ | ||
5777 | + err = __inode_permission(lower_inode, mask, flags); | ||
5778 | + if (err && err != -EACCES && err != EPERM && bindex > 0) { | ||
5779 | + umode_t mode = lower_inode->i_mode; | ||
5780 | + if ((is_robranch_super(inode->i_sb, bindex) || | ||
5781 | + __is_rdonly(lower_inode)) && | ||
5782 | + (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) | ||
5783 | + err = 0; | ||
5784 | + if (IS_COPYUP_ERR(err)) | ||
5785 | + err = 0; | ||
5786 | + } | ||
5787 | + | ||
5788 | + /* | ||
5789 | + * NFS HACK: NFSv2/3 return EACCES on readonly-exported, | ||
5790 | + * locally readonly-mounted file systems, instead of EROFS | ||
5791 | + * like other file systems do. So we have no choice here | ||
5792 | + * but to intercept this and ignore it for NFS branches | ||
5793 | + * marked readonly. Specifically, we avoid using NFS's own | ||
5794 | + * "broken" ->permission method, and rely on | ||
5795 | + * generic_permission() to do basic checking for us. | ||
5796 | + */ | ||
5797 | + if (err && err == -EACCES && | ||
5798 | + is_robranch_super(inode->i_sb, bindex) && | ||
5799 | + lower_inode->i_sb->s_magic == NFS_SUPER_MAGIC) | ||
5800 | + err = generic_permission(lower_inode, mask, flags, NULL); | ||
5801 | + | ||
5802 | + /* | ||
5803 | + * The permissions are an intersection of the overall directory | ||
5804 | + * permissions, so we fail if one fails. | ||
5805 | + */ | ||
5806 | + if (err) | ||
5807 | + goto out; | ||
5808 | + | ||
5809 | + /* only the leftmost file matters. */ | ||
5810 | + if (is_file || write_mask) { | ||
5811 | + if (is_file && write_mask) { | ||
5812 | + err = get_write_access(lower_inode); | ||
5813 | + if (!err) | ||
5814 | + put_write_access(lower_inode); | ||
5815 | + } | ||
5816 | + break; | ||
5817 | + } | ||
5818 | + } | ||
5819 | + /* sync times which may have changed (asynchronously) below */ | ||
5820 | + unionfs_copy_attr_times(inode); | ||
5821 | + | ||
5822 | +out: | ||
5823 | + unionfs_check_inode(inode); | ||
5824 | + if (dentry) { | ||
5825 | + unionfs_unlock_dentry(dentry); | ||
5826 | + dput(dentry); | ||
5827 | + } | ||
5828 | + iput(inode_grabbed); | ||
5829 | +out_nograb: | ||
5830 | + return err; | ||
5831 | +} | ||
5832 | + | ||
5833 | +static int unionfs_setattr(struct dentry *dentry, struct iattr *ia) | ||
5834 | +{ | ||
5835 | + int err = 0; | ||
5836 | + struct dentry *lower_dentry; | ||
5837 | + struct dentry *parent; | ||
5838 | + struct inode *inode; | ||
5839 | + struct inode *lower_inode; | ||
5840 | + int bstart, bend, bindex; | ||
5841 | + loff_t size; | ||
5842 | + struct iattr lower_ia; | ||
5843 | + | ||
5844 | + /* check if user has permission to change inode */ | ||
5845 | + err = inode_change_ok(dentry->d_inode, ia); | ||
5846 | + if (err) | ||
5847 | + goto out_err; | ||
5848 | + | ||
5849 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
5850 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
5851 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
5852 | + | ||
5853 | + if (unlikely(!__unionfs_d_revalidate(dentry, parent, false))) { | ||
5854 | + err = -ESTALE; | ||
5855 | + goto out; | ||
5856 | + } | ||
5857 | + | ||
5858 | + bstart = dbstart(dentry); | ||
5859 | + bend = dbend(dentry); | ||
5860 | + inode = dentry->d_inode; | ||
5861 | + | ||
5862 | + /* | ||
5863 | + * mode change is for clearing setuid/setgid. Allow lower filesystem | ||
5864 | + * to reinterpret it in its own way. | ||
5865 | + */ | ||
5866 | + if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) | ||
5867 | + ia->ia_valid &= ~ATTR_MODE; | ||
5868 | + | ||
5869 | + lower_dentry = unionfs_lower_dentry(dentry); | ||
5870 | + if (!lower_dentry) { /* should never happen after above revalidate */ | ||
5871 | + err = -EINVAL; | ||
5872 | + goto out; | ||
5873 | + } | ||
5874 | + | ||
5875 | + /* | ||
5876 | + * Get the lower inode directly from lower dentry, in case ibstart | ||
5877 | + * is -1 (which happens when the file is open but unlinked. | ||
5878 | + */ | ||
5879 | + lower_inode = lower_dentry->d_inode; | ||
5880 | + | ||
5881 | + /* check if user has permission to change lower inode */ | ||
5882 | + err = inode_change_ok(lower_inode, ia); | ||
5883 | + if (err) | ||
5884 | + goto out; | ||
5885 | + | ||
5886 | + /* copyup if the file is on a read only branch */ | ||
5887 | + if (is_robranch_super(dentry->d_sb, bstart) | ||
5888 | + || __is_rdonly(lower_inode)) { | ||
5889 | + /* check if we have a branch to copy up to */ | ||
5890 | + if (bstart <= 0) { | ||
5891 | + err = -EACCES; | ||
5892 | + goto out; | ||
5893 | + } | ||
5894 | + | ||
5895 | + if (ia->ia_valid & ATTR_SIZE) | ||
5896 | + size = ia->ia_size; | ||
5897 | + else | ||
5898 | + size = i_size_read(inode); | ||
5899 | + /* copyup to next available branch */ | ||
5900 | + for (bindex = bstart - 1; bindex >= 0; bindex--) { | ||
5901 | + err = copyup_dentry(parent->d_inode, | ||
5902 | + dentry, bstart, bindex, | ||
5903 | + dentry->d_name.name, | ||
5904 | + dentry->d_name.len, | ||
5905 | + NULL, size); | ||
5906 | + if (!err) | ||
5907 | + break; | ||
5908 | + } | ||
5909 | + if (err) | ||
5910 | + goto out; | ||
5911 | + /* get updated lower_dentry/inode after copyup */ | ||
5912 | + lower_dentry = unionfs_lower_dentry(dentry); | ||
5913 | + lower_inode = unionfs_lower_inode(inode); | ||
5914 | + /* | ||
5915 | + * check for whiteouts in writeable branch, and remove them | ||
5916 | + * if necessary. | ||
5917 | + */ | ||
5918 | + if (lower_dentry) { | ||
5919 | + err = check_unlink_whiteout(dentry, lower_dentry, | ||
5920 | + bindex); | ||
5921 | + if (err > 0) /* ignore if whiteout found and removed */ | ||
5922 | + err = 0; | ||
5923 | + } | ||
5924 | + } | ||
5925 | + | ||
5926 | + /* | ||
5927 | + * If shrinking, first truncate upper level to cancel writing dirty | ||
5928 | + * pages beyond the new eof; and also if its' maxbytes is more | ||
5929 | + * limiting (fail with -EFBIG before making any change to the lower | ||
5930 | + * level). There is no need to vmtruncate the upper level | ||
5931 | + * afterwards in the other cases: we fsstack_copy_inode_size from | ||
5932 | + * the lower level. | ||
5933 | + */ | ||
5934 | + if (ia->ia_valid & ATTR_SIZE) { | ||
5935 | + size = i_size_read(inode); | ||
5936 | + if (ia->ia_size < size || (ia->ia_size > size && | ||
5937 | + inode->i_sb->s_maxbytes < lower_inode->i_sb->s_maxbytes)) { | ||
5938 | + err = vmtruncate(inode, ia->ia_size); | ||
5939 | + if (err) | ||
5940 | + goto out; | ||
5941 | + } | ||
5942 | + } | ||
5943 | + | ||
5944 | + /* notify the (possibly copied-up) lower inode */ | ||
5945 | + /* | ||
5946 | + * Note: we use lower_dentry->d_inode, because lower_inode may be | ||
5947 | + * unlinked (no inode->i_sb and i_ino==0. This happens if someone | ||
5948 | + * tries to open(), unlink(), then ftruncate() a file. | ||
5949 | + */ | ||
5950 | + /* prepare our own lower struct iattr (with our own lower file) */ | ||
5951 | + memcpy(&lower_ia, ia, sizeof(lower_ia)); | ||
5952 | + if (ia->ia_valid & ATTR_FILE) { | ||
5953 | + lower_ia.ia_file = unionfs_lower_file(ia->ia_file); | ||
5954 | + BUG_ON(!lower_ia.ia_file); // XXX? | ||
5955 | + } | ||
5956 | + | ||
5957 | + mutex_lock(&lower_dentry->d_inode->i_mutex); | ||
5958 | + err = notify_change(lower_dentry, &lower_ia); | ||
5959 | + mutex_unlock(&lower_dentry->d_inode->i_mutex); | ||
5960 | + if (err) | ||
5961 | + goto out; | ||
5962 | + | ||
5963 | + /* get attributes from the first lower inode */ | ||
5964 | + if (ibstart(inode) >= 0) | ||
5965 | + unionfs_copy_attr_all(inode, lower_inode); | ||
5966 | + /* | ||
5967 | + * unionfs_copy_attr_all will copy the lower times to our inode if | ||
5968 | + * the lower ones are newer (useful for cache coherency). However, | ||
5969 | + * ->setattr is the only place in which we may have to copy the | ||
5970 | + * lower inode times absolutely, to support utimes(2). | ||
5971 | + */ | ||
5972 | + if (ia->ia_valid & ATTR_MTIME_SET) | ||
5973 | + inode->i_mtime = lower_inode->i_mtime; | ||
5974 | + if (ia->ia_valid & ATTR_CTIME) | ||
5975 | + inode->i_ctime = lower_inode->i_ctime; | ||
5976 | + if (ia->ia_valid & ATTR_ATIME_SET) | ||
5977 | + inode->i_atime = lower_inode->i_atime; | ||
5978 | + fsstack_copy_inode_size(inode, lower_inode); | ||
5979 | + | ||
5980 | +out: | ||
5981 | + if (!err) | ||
5982 | + unionfs_check_dentry(dentry); | ||
5983 | + unionfs_unlock_dentry(dentry); | ||
5984 | + unionfs_unlock_parent(dentry, parent); | ||
5985 | + unionfs_read_unlock(dentry->d_sb); | ||
5986 | +out_err: | ||
5987 | + return err; | ||
5988 | +} | ||
5989 | + | ||
5990 | +struct inode_operations unionfs_symlink_iops = { | ||
5991 | + .readlink = unionfs_readlink, | ||
5992 | + .permission = unionfs_permission, | ||
5993 | + .follow_link = unionfs_follow_link, | ||
5994 | + .setattr = unionfs_setattr, | ||
5995 | + .put_link = unionfs_put_link, | ||
5996 | +}; | ||
5997 | + | ||
5998 | +struct inode_operations unionfs_dir_iops = { | ||
5999 | + .create = unionfs_create, | ||
6000 | + .lookup = unionfs_lookup, | ||
6001 | + .link = unionfs_link, | ||
6002 | + .unlink = unionfs_unlink, | ||
6003 | + .symlink = unionfs_symlink, | ||
6004 | + .mkdir = unionfs_mkdir, | ||
6005 | + .rmdir = unionfs_rmdir, | ||
6006 | + .mknod = unionfs_mknod, | ||
6007 | + .rename = unionfs_rename, | ||
6008 | + .permission = unionfs_permission, | ||
6009 | + .setattr = unionfs_setattr, | ||
6010 | +#ifdef CONFIG_UNION_FS_XATTR | ||
6011 | + .setxattr = unionfs_setxattr, | ||
6012 | + .getxattr = unionfs_getxattr, | ||
6013 | + .removexattr = unionfs_removexattr, | ||
6014 | + .listxattr = unionfs_listxattr, | ||
6015 | +#endif /* CONFIG_UNION_FS_XATTR */ | ||
6016 | +}; | ||
6017 | + | ||
6018 | +struct inode_operations unionfs_main_iops = { | ||
6019 | + .permission = unionfs_permission, | ||
6020 | + .setattr = unionfs_setattr, | ||
6021 | +#ifdef CONFIG_UNION_FS_XATTR | ||
6022 | + .setxattr = unionfs_setxattr, | ||
6023 | + .getxattr = unionfs_getxattr, | ||
6024 | + .removexattr = unionfs_removexattr, | ||
6025 | + .listxattr = unionfs_listxattr, | ||
6026 | +#endif /* CONFIG_UNION_FS_XATTR */ | ||
6027 | +}; | ||
6028 | diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c | ||
6029 | new file mode 100644 | ||
6030 | index 0000000..3cbde56 | ||
6031 | --- /dev/null | ||
6032 | +++ b/fs/unionfs/lookup.c | ||
6033 | @@ -0,0 +1,569 @@ | ||
6034 | +/* | ||
6035 | + * Copyright (c) 2003-2011 Erez Zadok | ||
6036 | + * Copyright (c) 2003-2006 Charles P. Wright | ||
6037 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
6038 | + * Copyright (c) 2005-2006 Junjiro Okajima | ||
6039 | + * Copyright (c) 2005 Arun M. Krishnakumar | ||
6040 | + * Copyright (c) 2004-2006 David P. Quigley | ||
6041 | + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair | ||
6042 | + * Copyright (c) 2003 Puja Gupta | ||
6043 | + * Copyright (c) 2003 Harikesavan Krishnan | ||
6044 | + * Copyright (c) 2003-2011 Stony Brook University | ||
6045 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
6046 | + * | ||
6047 | + * This program is free software; you can redistribute it and/or modify | ||
6048 | + * it under the terms of the GNU General Public License version 2 as | ||
6049 | + * published by the Free Software Foundation. | ||
6050 | + */ | ||
6051 | + | ||
6052 | +#include "union.h" | ||
6053 | + | ||
6054 | +/* | ||
6055 | + * Lookup one path component @name relative to a <base,mnt> path pair. | ||
6056 | + * Behaves nearly the same as lookup_one_len (i.e., return negative dentry | ||
6057 | + * on ENOENT), but uses the @mnt passed, so it can cross bind mounts and | ||
6058 | + * other lower mounts properly. If @new_mnt is non-null, will fill in the | ||
6059 | + * new mnt there. Caller is responsible to dput/mntput/path_put returned | ||
6060 | + * @dentry and @new_mnt. | ||
6061 | + */ | ||
6062 | +struct dentry *__lookup_one(struct dentry *base, struct vfsmount *mnt, | ||
6063 | + const char *name, struct vfsmount **new_mnt) | ||
6064 | +{ | ||
6065 | + struct dentry *dentry = NULL; | ||
6066 | + struct nameidata lower_nd; | ||
6067 | + int err; | ||
6068 | + | ||
6069 | + /* we use flags=0 to get basic lookup */ | ||
6070 | + err = vfs_path_lookup(base, mnt, name, 0, &lower_nd); | ||
6071 | + | ||
6072 | + switch (err) { | ||
6073 | + case 0: /* no error */ | ||
6074 | + dentry = lower_nd.path.dentry; | ||
6075 | + if (new_mnt) | ||
6076 | + *new_mnt = lower_nd.path.mnt; /* rc already inc'ed */ | ||
6077 | + break; | ||
6078 | + case -ENOENT: | ||
6079 | + /* | ||
6080 | + * We don't consider ENOENT an error, and we want to return | ||
6081 | + * a negative dentry (ala lookup_one_len). As we know | ||
6082 | + * there was no inode for this name before (-ENOENT), then | ||
6083 | + * it's safe to call lookup_one_len (which doesn't take a | ||
6084 | + * vfsmount). | ||
6085 | + */ | ||
6086 | + dentry = lookup_lck_len(name, base, strlen(name)); | ||
6087 | + if (new_mnt) | ||
6088 | + *new_mnt = mntget(lower_nd.path.mnt); | ||
6089 | + break; | ||
6090 | + default: /* all other real errors */ | ||
6091 | + dentry = ERR_PTR(err); | ||
6092 | + break; | ||
6093 | + } | ||
6094 | + | ||
6095 | + return dentry; | ||
6096 | +} | ||
6097 | + | ||
6098 | +/* | ||
6099 | + * This is a utility function that fills in a unionfs dentry. | ||
6100 | + * Caller must lock this dentry with unionfs_lock_dentry. | ||
6101 | + * | ||
6102 | + * Returns: 0 (ok), or -ERRNO if an error occurred. | ||
6103 | + * XXX: get rid of _partial_lookup and make callers call _lookup_full directly | ||
6104 | + */ | ||
6105 | +int unionfs_partial_lookup(struct dentry *dentry, struct dentry *parent) | ||
6106 | +{ | ||
6107 | + struct dentry *tmp; | ||
6108 | + int err = -ENOSYS; | ||
6109 | + | ||
6110 | + tmp = unionfs_lookup_full(dentry, parent, INTERPOSE_PARTIAL); | ||
6111 | + | ||
6112 | + if (!tmp) { | ||
6113 | + err = 0; | ||
6114 | + goto out; | ||
6115 | + } | ||
6116 | + if (IS_ERR(tmp)) { | ||
6117 | + err = PTR_ERR(tmp); | ||
6118 | + goto out; | ||
6119 | + } | ||
6120 | + /* XXX: need to change the interface */ | ||
6121 | + BUG_ON(tmp != dentry); | ||
6122 | +out: | ||
6123 | + return err; | ||
6124 | +} | ||
6125 | + | ||
6126 | +/* The dentry cache is just so we have properly sized dentries. */ | ||
6127 | +static struct kmem_cache *unionfs_dentry_cachep; | ||
6128 | +int unionfs_init_dentry_cache(void) | ||
6129 | +{ | ||
6130 | + unionfs_dentry_cachep = | ||
6131 | + kmem_cache_create("unionfs_dentry", | ||
6132 | + sizeof(struct unionfs_dentry_info), | ||
6133 | + 0, SLAB_RECLAIM_ACCOUNT, NULL); | ||
6134 | + | ||
6135 | + return (unionfs_dentry_cachep ? 0 : -ENOMEM); | ||
6136 | +} | ||
6137 | + | ||
6138 | +void unionfs_destroy_dentry_cache(void) | ||
6139 | +{ | ||
6140 | + if (unionfs_dentry_cachep) | ||
6141 | + kmem_cache_destroy(unionfs_dentry_cachep); | ||
6142 | +} | ||
6143 | + | ||
6144 | +void free_dentry_private_data(struct dentry *dentry) | ||
6145 | +{ | ||
6146 | + if (!dentry || !dentry->d_fsdata) | ||
6147 | + return; | ||
6148 | + kfree(UNIONFS_D(dentry)->lower_paths); | ||
6149 | + UNIONFS_D(dentry)->lower_paths = NULL; | ||
6150 | + kmem_cache_free(unionfs_dentry_cachep, dentry->d_fsdata); | ||
6151 | + dentry->d_fsdata = NULL; | ||
6152 | +} | ||
6153 | + | ||
6154 | +static inline int __realloc_dentry_private_data(struct dentry *dentry) | ||
6155 | +{ | ||
6156 | + struct unionfs_dentry_info *info = UNIONFS_D(dentry); | ||
6157 | + void *p; | ||
6158 | + int size; | ||
6159 | + | ||
6160 | + BUG_ON(!info); | ||
6161 | + | ||
6162 | + size = sizeof(struct path) * sbmax(dentry->d_sb); | ||
6163 | + p = krealloc(info->lower_paths, size, GFP_ATOMIC); | ||
6164 | + if (unlikely(!p)) | ||
6165 | + return -ENOMEM; | ||
6166 | + | ||
6167 | + info->lower_paths = p; | ||
6168 | + | ||
6169 | + info->bstart = -1; | ||
6170 | + info->bend = -1; | ||
6171 | + info->bopaque = -1; | ||
6172 | + info->bcount = sbmax(dentry->d_sb); | ||
6173 | + atomic_set(&info->generation, | ||
6174 | + atomic_read(&UNIONFS_SB(dentry->d_sb)->generation)); | ||
6175 | + | ||
6176 | + memset(info->lower_paths, 0, size); | ||
6177 | + | ||
6178 | + return 0; | ||
6179 | +} | ||
6180 | + | ||
6181 | +/* UNIONFS_D(dentry)->lock must be locked */ | ||
6182 | +int realloc_dentry_private_data(struct dentry *dentry) | ||
6183 | +{ | ||
6184 | + if (!__realloc_dentry_private_data(dentry)) | ||
6185 | + return 0; | ||
6186 | + | ||
6187 | + kfree(UNIONFS_D(dentry)->lower_paths); | ||
6188 | + free_dentry_private_data(dentry); | ||
6189 | + return -ENOMEM; | ||
6190 | +} | ||
6191 | + | ||
6192 | +/* allocate new dentry private data */ | ||
6193 | +int new_dentry_private_data(struct dentry *dentry, int subclass) | ||
6194 | +{ | ||
6195 | + struct unionfs_dentry_info *info = UNIONFS_D(dentry); | ||
6196 | + | ||
6197 | + BUG_ON(info); | ||
6198 | + | ||
6199 | + info = kmem_cache_alloc(unionfs_dentry_cachep, GFP_ATOMIC); | ||
6200 | + if (unlikely(!info)) | ||
6201 | + return -ENOMEM; | ||
6202 | + | ||
6203 | + mutex_init(&info->lock); | ||
6204 | + mutex_lock_nested(&info->lock, subclass); | ||
6205 | + | ||
6206 | + info->lower_paths = NULL; | ||
6207 | + | ||
6208 | + dentry->d_fsdata = info; | ||
6209 | + | ||
6210 | + if (!__realloc_dentry_private_data(dentry)) | ||
6211 | + return 0; | ||
6212 | + | ||
6213 | + mutex_unlock(&info->lock); | ||
6214 | + free_dentry_private_data(dentry); | ||
6215 | + return -ENOMEM; | ||
6216 | +} | ||
6217 | + | ||
6218 | +/* | ||
6219 | + * scan through the lower dentry objects, and set bstart to reflect the | ||
6220 | + * starting branch | ||
6221 | + */ | ||
6222 | +void update_bstart(struct dentry *dentry) | ||
6223 | +{ | ||
6224 | + int bindex; | ||
6225 | + int bstart = dbstart(dentry); | ||
6226 | + int bend = dbend(dentry); | ||
6227 | + struct dentry *lower_dentry; | ||
6228 | + | ||
6229 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
6230 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
6231 | + if (!lower_dentry) | ||
6232 | + continue; | ||
6233 | + if (lower_dentry->d_inode) { | ||
6234 | + dbstart(dentry) = bindex; | ||
6235 | + break; | ||
6236 | + } | ||
6237 | + dput(lower_dentry); | ||
6238 | + unionfs_set_lower_dentry_idx(dentry, bindex, NULL); | ||
6239 | + } | ||
6240 | +} | ||
6241 | + | ||
6242 | + | ||
6243 | +/* | ||
6244 | + * Initialize a nameidata structure (the intent part) we can pass to a lower | ||
6245 | + * file system. Returns 0 on success or -error (only -ENOMEM possible). | ||
6246 | + * Inside that nd structure, this function may also return an allocated | ||
6247 | + * struct file (for open intents). The caller, when done with this nd, must | ||
6248 | + * kfree the intent file (using release_lower_nd). | ||
6249 | + * | ||
6250 | + * XXX: this code, and the callers of this code, should be redone using | ||
6251 | + * vfs_path_lookup() when (1) the nameidata structure is refactored into a | ||
6252 | + * separate intent-structure, and (2) open_namei() is broken into a VFS-only | ||
6253 | + * function and a method that other file systems can call. | ||
6254 | + */ | ||
6255 | +int init_lower_nd(struct nameidata *nd, unsigned int flags) | ||
6256 | +{ | ||
6257 | + int err = 0; | ||
6258 | +#ifdef ALLOC_LOWER_ND_FILE | ||
6259 | + /* | ||
6260 | + * XXX: one day we may need to have the lower return an open file | ||
6261 | + * for us. It is not needed in 2.6.23-rc1 for nfs2/nfs3, but may | ||
6262 | + * very well be needed for nfs4. | ||
6263 | + */ | ||
6264 | + struct file *file; | ||
6265 | +#endif /* ALLOC_LOWER_ND_FILE */ | ||
6266 | + | ||
6267 | + memset(nd, 0, sizeof(struct nameidata)); | ||
6268 | + if (!flags) | ||
6269 | + return err; | ||
6270 | + | ||
6271 | + switch (flags) { | ||
6272 | + case LOOKUP_CREATE: | ||
6273 | + nd->intent.open.flags |= O_CREAT; | ||
6274 | + /* fall through: shared code for create/open cases */ | ||
6275 | + case LOOKUP_OPEN: | ||
6276 | + nd->flags = flags; | ||
6277 | + nd->intent.open.flags |= (FMODE_READ | FMODE_WRITE); | ||
6278 | +#ifdef ALLOC_LOWER_ND_FILE | ||
6279 | + file = kzalloc(sizeof(struct file), GFP_KERNEL); | ||
6280 | + if (unlikely(!file)) { | ||
6281 | + err = -ENOMEM; | ||
6282 | + break; /* exit switch statement and thus return */ | ||
6283 | + } | ||
6284 | + nd->intent.open.file = file; | ||
6285 | +#endif /* ALLOC_LOWER_ND_FILE */ | ||
6286 | + break; | ||
6287 | + default: | ||
6288 | + /* | ||
6289 | + * We should never get here, for now. | ||
6290 | + * We can add new cases here later on. | ||
6291 | + */ | ||
6292 | + pr_debug("unionfs: unknown nameidata flag 0x%x\n", flags); | ||
6293 | + BUG(); | ||
6294 | + break; | ||
6295 | + } | ||
6296 | + | ||
6297 | + return err; | ||
6298 | +} | ||
6299 | + | ||
6300 | +void release_lower_nd(struct nameidata *nd, int err) | ||
6301 | +{ | ||
6302 | + if (!nd->intent.open.file) | ||
6303 | + return; | ||
6304 | + else if (!err) | ||
6305 | + release_open_intent(nd); | ||
6306 | +#ifdef ALLOC_LOWER_ND_FILE | ||
6307 | + kfree(nd->intent.open.file); | ||
6308 | +#endif /* ALLOC_LOWER_ND_FILE */ | ||
6309 | +} | ||
6310 | + | ||
6311 | +/* | ||
6312 | + * Main (and complex) driver function for Unionfs's lookup | ||
6313 | + * | ||
6314 | + * Returns: NULL (ok), ERR_PTR if an error occurred, or a non-null non-error | ||
6315 | + * PTR if d_splice returned a different dentry. | ||
6316 | + * | ||
6317 | + * If lookupmode is INTERPOSE_PARTIAL/REVAL/REVAL_NEG, the passed dentry's | ||
6318 | + * inode info must be locked. If lookupmode is INTERPOSE_LOOKUP (i.e., a | ||
6319 | + * newly looked-up dentry), then unionfs_lookup_backend will return a locked | ||
6320 | + * dentry's info, which the caller must unlock. | ||
6321 | + */ | ||
6322 | +struct dentry *unionfs_lookup_full(struct dentry *dentry, | ||
6323 | + struct dentry *parent, int lookupmode) | ||
6324 | +{ | ||
6325 | + int err = 0; | ||
6326 | + struct dentry *lower_dentry = NULL; | ||
6327 | + struct vfsmount *lower_mnt; | ||
6328 | + struct vfsmount *lower_dir_mnt; | ||
6329 | + struct dentry *wh_lower_dentry = NULL; | ||
6330 | + struct dentry *lower_dir_dentry = NULL; | ||
6331 | + struct dentry *d_interposed = NULL; | ||
6332 | + int bindex, bstart, bend, bopaque; | ||
6333 | + int opaque, num_positive = 0; | ||
6334 | + const char *name; | ||
6335 | + int namelen; | ||
6336 | + int pos_start, pos_end; | ||
6337 | + | ||
6338 | + /* | ||
6339 | + * We should already have a lock on this dentry in the case of a | ||
6340 | + * partial lookup, or a revalidation. Otherwise it is returned from | ||
6341 | + * new_dentry_private_data already locked. | ||
6342 | + */ | ||
6343 | + verify_locked(dentry); | ||
6344 | + verify_locked(parent); | ||
6345 | + | ||
6346 | + /* must initialize dentry operations */ | ||
6347 | + dentry->d_op = &unionfs_dops; | ||
6348 | + | ||
6349 | + /* We never partial lookup the root directory. */ | ||
6350 | + if (IS_ROOT(dentry)) | ||
6351 | + goto out; | ||
6352 | + | ||
6353 | + name = dentry->d_name.name; | ||
6354 | + namelen = dentry->d_name.len; | ||
6355 | + | ||
6356 | + /* No dentries should get created for possible whiteout names. */ | ||
6357 | + if (!is_validname(name)) { | ||
6358 | + err = -EPERM; | ||
6359 | + goto out_free; | ||
6360 | + } | ||
6361 | + | ||
6362 | + /* Now start the actual lookup procedure. */ | ||
6363 | + bstart = dbstart(parent); | ||
6364 | + bend = dbend(parent); | ||
6365 | + bopaque = dbopaque(parent); | ||
6366 | + BUG_ON(bstart < 0); | ||
6367 | + | ||
6368 | + /* adjust bend to bopaque if needed */ | ||
6369 | + if ((bopaque >= 0) && (bopaque < bend)) | ||
6370 | + bend = bopaque; | ||
6371 | + | ||
6372 | + /* lookup all possible dentries */ | ||
6373 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
6374 | + | ||
6375 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
6376 | + lower_mnt = unionfs_lower_mnt_idx(dentry, bindex); | ||
6377 | + | ||
6378 | + /* skip if we already have a positive lower dentry */ | ||
6379 | + if (lower_dentry) { | ||
6380 | + if (dbstart(dentry) < 0) | ||
6381 | + dbstart(dentry) = bindex; | ||
6382 | + if (bindex > dbend(dentry)) | ||
6383 | + dbend(dentry) = bindex; | ||
6384 | + if (lower_dentry->d_inode) | ||
6385 | + num_positive++; | ||
6386 | + continue; | ||
6387 | + } | ||
6388 | + | ||
6389 | + lower_dir_dentry = | ||
6390 | + unionfs_lower_dentry_idx(parent, bindex); | ||
6391 | + /* if the lower dentry's parent does not exist, skip this */ | ||
6392 | + if (!lower_dir_dentry || !lower_dir_dentry->d_inode) | ||
6393 | + continue; | ||
6394 | + | ||
6395 | + /* also skip it if the parent isn't a directory. */ | ||
6396 | + if (!S_ISDIR(lower_dir_dentry->d_inode->i_mode)) | ||
6397 | + continue; /* XXX: should be BUG_ON */ | ||
6398 | + | ||
6399 | + /* check for whiteouts: stop lookup if found */ | ||
6400 | + wh_lower_dentry = lookup_whiteout(name, lower_dir_dentry); | ||
6401 | + if (IS_ERR(wh_lower_dentry)) { | ||
6402 | + err = PTR_ERR(wh_lower_dentry); | ||
6403 | + goto out_free; | ||
6404 | + } | ||
6405 | + if (wh_lower_dentry->d_inode) { | ||
6406 | + dbend(dentry) = dbopaque(dentry) = bindex; | ||
6407 | + if (dbstart(dentry) < 0) | ||
6408 | + dbstart(dentry) = bindex; | ||
6409 | + dput(wh_lower_dentry); | ||
6410 | + break; | ||
6411 | + } | ||
6412 | + dput(wh_lower_dentry); | ||
6413 | + | ||
6414 | + /* Now do regular lookup; lookup @name */ | ||
6415 | + lower_dir_mnt = unionfs_lower_mnt_idx(parent, bindex); | ||
6416 | + lower_mnt = NULL; /* XXX: needed? */ | ||
6417 | + | ||
6418 | + lower_dentry = __lookup_one(lower_dir_dentry, lower_dir_mnt, | ||
6419 | + name, &lower_mnt); | ||
6420 | + | ||
6421 | + if (IS_ERR(lower_dentry)) { | ||
6422 | + err = PTR_ERR(lower_dentry); | ||
6423 | + goto out_free; | ||
6424 | + } | ||
6425 | + unionfs_set_lower_dentry_idx(dentry, bindex, lower_dentry); | ||
6426 | + if (!lower_mnt) | ||
6427 | + lower_mnt = unionfs_mntget(dentry->d_sb->s_root, | ||
6428 | + bindex); | ||
6429 | + unionfs_set_lower_mnt_idx(dentry, bindex, lower_mnt); | ||
6430 | + | ||
6431 | + /* adjust dbstart/end */ | ||
6432 | + if (dbstart(dentry) < 0) | ||
6433 | + dbstart(dentry) = bindex; | ||
6434 | + if (bindex > dbend(dentry)) | ||
6435 | + dbend(dentry) = bindex; | ||
6436 | + /* | ||
6437 | + * We always store the lower dentries above, and update | ||
6438 | + * dbstart/dbend, even if the whole unionfs dentry is | ||
6439 | + * negative (i.e., no lower inodes). | ||
6440 | + */ | ||
6441 | + if (!lower_dentry->d_inode) | ||
6442 | + continue; | ||
6443 | + num_positive++; | ||
6444 | + | ||
6445 | + /* | ||
6446 | + * check if we just found an opaque directory, if so, stop | ||
6447 | + * lookups here. | ||
6448 | + */ | ||
6449 | + if (!S_ISDIR(lower_dentry->d_inode->i_mode)) | ||
6450 | + continue; | ||
6451 | + opaque = is_opaque_dir(dentry, bindex); | ||
6452 | + if (opaque < 0) { | ||
6453 | + err = opaque; | ||
6454 | + goto out_free; | ||
6455 | + } else if (opaque) { | ||
6456 | + dbend(dentry) = dbopaque(dentry) = bindex; | ||
6457 | + break; | ||
6458 | + } | ||
6459 | + dbend(dentry) = bindex; | ||
6460 | + | ||
6461 | + /* update parent directory's atime with the bindex */ | ||
6462 | + fsstack_copy_attr_atime(parent->d_inode, | ||
6463 | + lower_dir_dentry->d_inode); | ||
6464 | + } | ||
6465 | + | ||
6466 | + /* sanity checks, then decide if to process a negative dentry */ | ||
6467 | + BUG_ON(dbstart(dentry) < 0 && dbend(dentry) >= 0); | ||
6468 | + BUG_ON(dbstart(dentry) >= 0 && dbend(dentry) < 0); | ||
6469 | + | ||
6470 | + if (num_positive > 0) | ||
6471 | + goto out_positive; | ||
6472 | + | ||
6473 | + /*** handle NEGATIVE dentries ***/ | ||
6474 | + | ||
6475 | + /* | ||
6476 | + * If negative, keep only first lower negative dentry, to save on | ||
6477 | + * memory. | ||
6478 | + */ | ||
6479 | + if (dbstart(dentry) < dbend(dentry)) { | ||
6480 | + path_put_lowers(dentry, dbstart(dentry) + 1, | ||
6481 | + dbend(dentry), false); | ||
6482 | + dbend(dentry) = dbstart(dentry); | ||
6483 | + } | ||
6484 | + if (lookupmode == INTERPOSE_PARTIAL) | ||
6485 | + goto out; | ||
6486 | + if (lookupmode == INTERPOSE_LOOKUP) { | ||
6487 | + /* | ||
6488 | + * If all we found was a whiteout in the first available | ||
6489 | + * branch, then create a negative dentry for a possibly new | ||
6490 | + * file to be created. | ||
6491 | + */ | ||
6492 | + if (dbopaque(dentry) < 0) | ||
6493 | + goto out; | ||
6494 | + /* XXX: need to get mnt here */ | ||
6495 | + bindex = dbstart(dentry); | ||
6496 | + if (unionfs_lower_dentry_idx(dentry, bindex)) | ||
6497 | + goto out; | ||
6498 | + lower_dir_dentry = | ||
6499 | + unionfs_lower_dentry_idx(parent, bindex); | ||
6500 | + if (!lower_dir_dentry || !lower_dir_dentry->d_inode) | ||
6501 | + goto out; | ||
6502 | + if (!S_ISDIR(lower_dir_dentry->d_inode->i_mode)) | ||
6503 | + goto out; /* XXX: should be BUG_ON */ | ||
6504 | + /* XXX: do we need to cross bind mounts here? */ | ||
6505 | + lower_dentry = lookup_lck_len(name, lower_dir_dentry, namelen); | ||
6506 | + if (IS_ERR(lower_dentry)) { | ||
6507 | + err = PTR_ERR(lower_dentry); | ||
6508 | + goto out; | ||
6509 | + } | ||
6510 | + /* XXX: need to mntget/mntput as needed too! */ | ||
6511 | + unionfs_set_lower_dentry_idx(dentry, bindex, lower_dentry); | ||
6512 | + /* XXX: wrong mnt for crossing bind mounts! */ | ||
6513 | + lower_mnt = unionfs_mntget(dentry->d_sb->s_root, bindex); | ||
6514 | + unionfs_set_lower_mnt_idx(dentry, bindex, lower_mnt); | ||
6515 | + | ||
6516 | + goto out; | ||
6517 | + } | ||
6518 | + | ||
6519 | + /* if we're revalidating a positive dentry, don't make it negative */ | ||
6520 | + if (lookupmode != INTERPOSE_REVAL) | ||
6521 | + d_add(dentry, NULL); | ||
6522 | + | ||
6523 | + goto out; | ||
6524 | + | ||
6525 | +out_positive: | ||
6526 | + /*** handle POSITIVE dentries ***/ | ||
6527 | + | ||
6528 | + /* | ||
6529 | + * This unionfs dentry is positive (at least one lower inode | ||
6530 | + * exists), so scan entire dentry from beginning to end, and remove | ||
6531 | + * any negative lower dentries, if any. Then, update dbstart/dbend | ||
6532 | + * to reflect the start/end of positive dentries. | ||
6533 | + */ | ||
6534 | + pos_start = pos_end = -1; | ||
6535 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
6536 | + lower_dentry = unionfs_lower_dentry_idx(dentry, | ||
6537 | + bindex); | ||
6538 | + if (lower_dentry && lower_dentry->d_inode) { | ||
6539 | + if (pos_start < 0) | ||
6540 | + pos_start = bindex; | ||
6541 | + if (bindex > pos_end) | ||
6542 | + pos_end = bindex; | ||
6543 | + continue; | ||
6544 | + } | ||
6545 | + path_put_lowers(dentry, bindex, bindex, false); | ||
6546 | + } | ||
6547 | + if (pos_start >= 0) | ||
6548 | + dbstart(dentry) = pos_start; | ||
6549 | + if (pos_end >= 0) | ||
6550 | + dbend(dentry) = pos_end; | ||
6551 | + | ||
6552 | + /* Partial lookups need to re-interpose, or throw away older negs. */ | ||
6553 | + if (lookupmode == INTERPOSE_PARTIAL) { | ||
6554 | + if (dentry->d_inode) { | ||
6555 | + unionfs_reinterpose(dentry); | ||
6556 | + goto out; | ||
6557 | + } | ||
6558 | + | ||
6559 | + /* | ||
6560 | + * This dentry was positive, so it is as if we had a | ||
6561 | + * negative revalidation. | ||
6562 | + */ | ||
6563 | + lookupmode = INTERPOSE_REVAL_NEG; | ||
6564 | + update_bstart(dentry); | ||
6565 | + } | ||
6566 | + | ||
6567 | + /* | ||
6568 | + * Interpose can return a dentry if d_splice returned a different | ||
6569 | + * dentry. | ||
6570 | + */ | ||
6571 | + d_interposed = unionfs_interpose(dentry, dentry->d_sb, lookupmode); | ||
6572 | + if (IS_ERR(d_interposed)) | ||
6573 | + err = PTR_ERR(d_interposed); | ||
6574 | + else if (d_interposed) | ||
6575 | + dentry = d_interposed; | ||
6576 | + | ||
6577 | + if (!err) | ||
6578 | + goto out; | ||
6579 | + d_drop(dentry); | ||
6580 | + | ||
6581 | +out_free: | ||
6582 | + /* should dput/mntput all the underlying dentries on error condition */ | ||
6583 | + if (dbstart(dentry) >= 0) | ||
6584 | + path_put_lowers_all(dentry, false); | ||
6585 | + /* free lower_paths unconditionally */ | ||
6586 | + kfree(UNIONFS_D(dentry)->lower_paths); | ||
6587 | + UNIONFS_D(dentry)->lower_paths = NULL; | ||
6588 | + | ||
6589 | +out: | ||
6590 | + if (dentry && UNIONFS_D(dentry)) { | ||
6591 | + BUG_ON(dbstart(dentry) < 0 && dbend(dentry) >= 0); | ||
6592 | + BUG_ON(dbstart(dentry) >= 0 && dbend(dentry) < 0); | ||
6593 | + } | ||
6594 | + if (d_interposed && UNIONFS_D(d_interposed)) { | ||
6595 | + BUG_ON(dbstart(d_interposed) < 0 && dbend(d_interposed) >= 0); | ||
6596 | + BUG_ON(dbstart(d_interposed) >= 0 && dbend(d_interposed) < 0); | ||
6597 | + } | ||
6598 | + | ||
6599 | + if (!err && d_interposed) | ||
6600 | + return d_interposed; | ||
6601 | + return ERR_PTR(err); | ||
6602 | +} | ||
6603 | diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c | ||
6604 | new file mode 100644 | ||
6605 | index 0000000..fa52f61 | ||
6606 | --- /dev/null | ||
6607 | +++ b/fs/unionfs/main.c | ||
6608 | @@ -0,0 +1,763 @@ | ||
6609 | +/* | ||
6610 | + * Copyright (c) 2003-2011 Erez Zadok | ||
6611 | + * Copyright (c) 2003-2006 Charles P. Wright | ||
6612 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
6613 | + * Copyright (c) 2005-2006 Junjiro Okajima | ||
6614 | + * Copyright (c) 2005 Arun M. Krishnakumar | ||
6615 | + * Copyright (c) 2004-2006 David P. Quigley | ||
6616 | + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair | ||
6617 | + * Copyright (c) 2003 Puja Gupta | ||
6618 | + * Copyright (c) 2003 Harikesavan Krishnan | ||
6619 | + * Copyright (c) 2003-2011 Stony Brook University | ||
6620 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
6621 | + * | ||
6622 | + * This program is free software; you can redistribute it and/or modify | ||
6623 | + * it under the terms of the GNU General Public License version 2 as | ||
6624 | + * published by the Free Software Foundation. | ||
6625 | + */ | ||
6626 | + | ||
6627 | +#include "union.h" | ||
6628 | +#include <linux/module.h> | ||
6629 | +#include <linux/moduleparam.h> | ||
6630 | + | ||
6631 | +static void unionfs_fill_inode(struct dentry *dentry, | ||
6632 | + struct inode *inode) | ||
6633 | +{ | ||
6634 | + struct inode *lower_inode; | ||
6635 | + struct dentry *lower_dentry; | ||
6636 | + int bindex, bstart, bend; | ||
6637 | + | ||
6638 | + bstart = dbstart(dentry); | ||
6639 | + bend = dbend(dentry); | ||
6640 | + | ||
6641 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
6642 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
6643 | + if (!lower_dentry) { | ||
6644 | + unionfs_set_lower_inode_idx(inode, bindex, NULL); | ||
6645 | + continue; | ||
6646 | + } | ||
6647 | + | ||
6648 | + /* Initialize the lower inode to the new lower inode. */ | ||
6649 | + if (!lower_dentry->d_inode) | ||
6650 | + continue; | ||
6651 | + | ||
6652 | + unionfs_set_lower_inode_idx(inode, bindex, | ||
6653 | + igrab(lower_dentry->d_inode)); | ||
6654 | + } | ||
6655 | + | ||
6656 | + ibstart(inode) = dbstart(dentry); | ||
6657 | + ibend(inode) = dbend(dentry); | ||
6658 | + | ||
6659 | + /* Use attributes from the first branch. */ | ||
6660 | + lower_inode = unionfs_lower_inode(inode); | ||
6661 | + | ||
6662 | + /* Use different set of inode ops for symlinks & directories */ | ||
6663 | + if (S_ISLNK(lower_inode->i_mode)) | ||
6664 | + inode->i_op = &unionfs_symlink_iops; | ||
6665 | + else if (S_ISDIR(lower_inode->i_mode)) | ||
6666 | + inode->i_op = &unionfs_dir_iops; | ||
6667 | + | ||
6668 | + /* Use different set of file ops for directories */ | ||
6669 | + if (S_ISDIR(lower_inode->i_mode)) | ||
6670 | + inode->i_fop = &unionfs_dir_fops; | ||
6671 | + | ||
6672 | + /* properly initialize special inodes */ | ||
6673 | + if (S_ISBLK(lower_inode->i_mode) || S_ISCHR(lower_inode->i_mode) || | ||
6674 | + S_ISFIFO(lower_inode->i_mode) || S_ISSOCK(lower_inode->i_mode)) | ||
6675 | + init_special_inode(inode, lower_inode->i_mode, | ||
6676 | + lower_inode->i_rdev); | ||
6677 | + | ||
6678 | + /* all well, copy inode attributes */ | ||
6679 | + unionfs_copy_attr_all(inode, lower_inode); | ||
6680 | + fsstack_copy_inode_size(inode, lower_inode); | ||
6681 | +} | ||
6682 | + | ||
6683 | +/* | ||
6684 | + * Connect a unionfs inode dentry/inode with several lower ones. This is | ||
6685 | + * the classic stackable file system "vnode interposition" action. | ||
6686 | + * | ||
6687 | + * @sb: unionfs's super_block | ||
6688 | + */ | ||
6689 | +struct dentry *unionfs_interpose(struct dentry *dentry, struct super_block *sb, | ||
6690 | + int flag) | ||
6691 | +{ | ||
6692 | + int err = 0; | ||
6693 | + struct inode *inode; | ||
6694 | + int need_fill_inode = 1; | ||
6695 | + struct dentry *spliced = NULL; | ||
6696 | + | ||
6697 | + verify_locked(dentry); | ||
6698 | + | ||
6699 | + /* | ||
6700 | + * We allocate our new inode below by calling unionfs_iget, | ||
6701 | + * which will initialize some of the new inode's fields | ||
6702 | + */ | ||
6703 | + | ||
6704 | + /* | ||
6705 | + * On revalidate we've already got our own inode and just need | ||
6706 | + * to fix it up. | ||
6707 | + */ | ||
6708 | + if (flag == INTERPOSE_REVAL) { | ||
6709 | + inode = dentry->d_inode; | ||
6710 | + UNIONFS_I(inode)->bstart = -1; | ||
6711 | + UNIONFS_I(inode)->bend = -1; | ||
6712 | + atomic_set(&UNIONFS_I(inode)->generation, | ||
6713 | + atomic_read(&UNIONFS_SB(sb)->generation)); | ||
6714 | + | ||
6715 | + UNIONFS_I(inode)->lower_inodes = | ||
6716 | + kcalloc(sbmax(sb), sizeof(struct inode *), GFP_KERNEL); | ||
6717 | + if (unlikely(!UNIONFS_I(inode)->lower_inodes)) { | ||
6718 | + err = -ENOMEM; | ||
6719 | + goto out; | ||
6720 | + } | ||
6721 | + } else { | ||
6722 | + /* get unique inode number for unionfs */ | ||
6723 | + inode = unionfs_iget(sb, iunique(sb, UNIONFS_ROOT_INO)); | ||
6724 | + if (IS_ERR(inode)) { | ||
6725 | + err = PTR_ERR(inode); | ||
6726 | + goto out; | ||
6727 | + } | ||
6728 | + if (atomic_read(&inode->i_count) > 1) | ||
6729 | + goto skip; | ||
6730 | + } | ||
6731 | + | ||
6732 | + need_fill_inode = 0; | ||
6733 | + unionfs_fill_inode(dentry, inode); | ||
6734 | + | ||
6735 | +skip: | ||
6736 | + /* only (our) lookup wants to do a d_add */ | ||
6737 | + switch (flag) { | ||
6738 | + case INTERPOSE_DEFAULT: | ||
6739 | + /* for operations which create new inodes */ | ||
6740 | + d_add(dentry, inode); | ||
6741 | + break; | ||
6742 | + case INTERPOSE_REVAL_NEG: | ||
6743 | + d_instantiate(dentry, inode); | ||
6744 | + break; | ||
6745 | + case INTERPOSE_LOOKUP: | ||
6746 | + spliced = d_splice_alias(inode, dentry); | ||
6747 | + if (spliced && spliced != dentry) { | ||
6748 | + /* | ||
6749 | + * d_splice can return a dentry if it was | ||
6750 | + * disconnected and had to be moved. We must ensure | ||
6751 | + * that the private data of the new dentry is | ||
6752 | + * correct and that the inode info was filled | ||
6753 | + * properly. Finally we must return this new | ||
6754 | + * dentry. | ||
6755 | + */ | ||
6756 | + spliced->d_op = &unionfs_dops; | ||
6757 | + spliced->d_fsdata = dentry->d_fsdata; | ||
6758 | + dentry->d_fsdata = NULL; | ||
6759 | + dentry = spliced; | ||
6760 | + if (need_fill_inode) { | ||
6761 | + need_fill_inode = 0; | ||
6762 | + unionfs_fill_inode(dentry, inode); | ||
6763 | + } | ||
6764 | + goto out_spliced; | ||
6765 | + } else if (!spliced) { | ||
6766 | + if (need_fill_inode) { | ||
6767 | + need_fill_inode = 0; | ||
6768 | + unionfs_fill_inode(dentry, inode); | ||
6769 | + goto out_spliced; | ||
6770 | + } | ||
6771 | + } | ||
6772 | + break; | ||
6773 | + case INTERPOSE_REVAL: | ||
6774 | + /* Do nothing. */ | ||
6775 | + break; | ||
6776 | + default: | ||
6777 | + printk(KERN_CRIT "unionfs: invalid interpose flag passed!\n"); | ||
6778 | + BUG(); | ||
6779 | + } | ||
6780 | + goto out; | ||
6781 | + | ||
6782 | +out_spliced: | ||
6783 | + if (!err) | ||
6784 | + return spliced; | ||
6785 | +out: | ||
6786 | + return ERR_PTR(err); | ||
6787 | +} | ||
6788 | + | ||
6789 | +/* like interpose above, but for an already existing dentry */ | ||
6790 | +void unionfs_reinterpose(struct dentry *dentry) | ||
6791 | +{ | ||
6792 | + struct dentry *lower_dentry; | ||
6793 | + struct inode *inode; | ||
6794 | + int bindex, bstart, bend; | ||
6795 | + | ||
6796 | + verify_locked(dentry); | ||
6797 | + | ||
6798 | + /* This is pre-allocated inode */ | ||
6799 | + inode = dentry->d_inode; | ||
6800 | + | ||
6801 | + bstart = dbstart(dentry); | ||
6802 | + bend = dbend(dentry); | ||
6803 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
6804 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
6805 | + if (!lower_dentry) | ||
6806 | + continue; | ||
6807 | + | ||
6808 | + if (!lower_dentry->d_inode) | ||
6809 | + continue; | ||
6810 | + if (unionfs_lower_inode_idx(inode, bindex)) | ||
6811 | + continue; | ||
6812 | + unionfs_set_lower_inode_idx(inode, bindex, | ||
6813 | + igrab(lower_dentry->d_inode)); | ||
6814 | + } | ||
6815 | + ibstart(inode) = dbstart(dentry); | ||
6816 | + ibend(inode) = dbend(dentry); | ||
6817 | +} | ||
6818 | + | ||
6819 | +/* | ||
6820 | + * make sure the branch we just looked up (nd) makes sense: | ||
6821 | + * | ||
6822 | + * 1) we're not trying to stack unionfs on top of unionfs | ||
6823 | + * 2) it exists | ||
6824 | + * 3) is a directory | ||
6825 | + */ | ||
6826 | +int check_branch(const struct path *path) | ||
6827 | +{ | ||
6828 | + /* XXX: remove in ODF code -- stacking unions allowed there */ | ||
6829 | + if (!strcmp(path->dentry->d_sb->s_type->name, UNIONFS_NAME)) | ||
6830 | + return -EINVAL; | ||
6831 | + if (!path->dentry->d_inode) | ||
6832 | + return -ENOENT; | ||
6833 | + if (!S_ISDIR(path->dentry->d_inode->i_mode)) | ||
6834 | + return -ENOTDIR; | ||
6835 | + return 0; | ||
6836 | +} | ||
6837 | + | ||
6838 | +/* checks if two lower_dentries have overlapping branches */ | ||
6839 | +static int is_branch_overlap(struct dentry *dent1, struct dentry *dent2) | ||
6840 | +{ | ||
6841 | + struct dentry *dent = NULL; | ||
6842 | + | ||
6843 | + dent = dent1; | ||
6844 | + while ((dent != dent2) && (dent->d_parent != dent)) | ||
6845 | + dent = dent->d_parent; | ||
6846 | + | ||
6847 | + if (dent == dent2) | ||
6848 | + return 1; | ||
6849 | + | ||
6850 | + dent = dent2; | ||
6851 | + while ((dent != dent1) && (dent->d_parent != dent)) | ||
6852 | + dent = dent->d_parent; | ||
6853 | + | ||
6854 | + return (dent == dent1); | ||
6855 | +} | ||
6856 | + | ||
6857 | +/* | ||
6858 | + * Parse "ro" or "rw" options, but default to "rw" if no mode options was | ||
6859 | + * specified. Fill the mode bits in @perms. If encounter an unknown | ||
6860 | + * string, return -EINVAL. Otherwise return 0. | ||
6861 | + */ | ||
6862 | +int parse_branch_mode(const char *name, int *perms) | ||
6863 | +{ | ||
6864 | + if (!name || !strcmp(name, "rw")) { | ||
6865 | + *perms = MAY_READ | MAY_WRITE; | ||
6866 | + return 0; | ||
6867 | + } | ||
6868 | + if (!strcmp(name, "ro")) { | ||
6869 | + *perms = MAY_READ; | ||
6870 | + return 0; | ||
6871 | + } | ||
6872 | + return -EINVAL; | ||
6873 | +} | ||
6874 | + | ||
6875 | +/* | ||
6876 | + * parse the dirs= mount argument | ||
6877 | + * | ||
6878 | + * We don't need to lock the superblock private data's rwsem, as we get | ||
6879 | + * called only by unionfs_read_super - it is still a long time before anyone | ||
6880 | + * can even get a reference to us. | ||
6881 | + */ | ||
6882 | +static int parse_dirs_option(struct super_block *sb, struct unionfs_dentry_info | ||
6883 | + *lower_root_info, char *options) | ||
6884 | +{ | ||
6885 | + struct path path; | ||
6886 | + char *name; | ||
6887 | + int err = 0; | ||
6888 | + int branches = 1; | ||
6889 | + int bindex = 0; | ||
6890 | + int i = 0; | ||
6891 | + int j = 0; | ||
6892 | + struct dentry *dent1; | ||
6893 | + struct dentry *dent2; | ||
6894 | + | ||
6895 | + if (options[0] == '\0') { | ||
6896 | + printk(KERN_ERR "unionfs: no branches specified\n"); | ||
6897 | + err = -EINVAL; | ||
6898 | + goto out_return; | ||
6899 | + } | ||
6900 | + | ||
6901 | + /* | ||
6902 | + * Each colon means we have a separator, this is really just a rough | ||
6903 | + * guess, since strsep will handle empty fields for us. | ||
6904 | + */ | ||
6905 | + for (i = 0; options[i]; i++) | ||
6906 | + if (options[i] == ':') | ||
6907 | + branches++; | ||
6908 | + | ||
6909 | + /* allocate space for underlying pointers to lower dentry */ | ||
6910 | + UNIONFS_SB(sb)->data = | ||
6911 | + kcalloc(branches, sizeof(struct unionfs_data), GFP_KERNEL); | ||
6912 | + if (unlikely(!UNIONFS_SB(sb)->data)) { | ||
6913 | + err = -ENOMEM; | ||
6914 | + goto out_return; | ||
6915 | + } | ||
6916 | + | ||
6917 | + lower_root_info->lower_paths = | ||
6918 | + kcalloc(branches, sizeof(struct path), GFP_KERNEL); | ||
6919 | + if (unlikely(!lower_root_info->lower_paths)) { | ||
6920 | + err = -ENOMEM; | ||
6921 | + /* free the underlying pointer array */ | ||
6922 | + kfree(UNIONFS_SB(sb)->data); | ||
6923 | + UNIONFS_SB(sb)->data = NULL; | ||
6924 | + goto out_return; | ||
6925 | + } | ||
6926 | + | ||
6927 | + /* now parsing a string such as "b1:b2=rw:b3=ro:b4" */ | ||
6928 | + branches = 0; | ||
6929 | + while ((name = strsep(&options, ":")) != NULL) { | ||
6930 | + int perms; | ||
6931 | + char *mode = strchr(name, '='); | ||
6932 | + | ||
6933 | + if (!name) | ||
6934 | + continue; | ||
6935 | + if (!*name) { /* bad use of ':' (extra colons) */ | ||
6936 | + err = -EINVAL; | ||
6937 | + goto out; | ||
6938 | + } | ||
6939 | + | ||
6940 | + branches++; | ||
6941 | + | ||
6942 | + /* strip off '=' if any */ | ||
6943 | + if (mode) | ||
6944 | + *mode++ = '\0'; | ||
6945 | + | ||
6946 | + err = parse_branch_mode(mode, &perms); | ||
6947 | + if (err) { | ||
6948 | + printk(KERN_ERR "unionfs: invalid mode \"%s\" for " | ||
6949 | + "branch %d\n", mode, bindex); | ||
6950 | + goto out; | ||
6951 | + } | ||
6952 | + /* ensure that leftmost branch is writeable */ | ||
6953 | + if (!bindex && !(perms & MAY_WRITE)) { | ||
6954 | + printk(KERN_ERR "unionfs: leftmost branch cannot be " | ||
6955 | + "read-only (use \"-o ro\" to create a " | ||
6956 | + "read-only union)\n"); | ||
6957 | + err = -EINVAL; | ||
6958 | + goto out; | ||
6959 | + } | ||
6960 | + | ||
6961 | + err = kern_path(name, LOOKUP_FOLLOW, &path); | ||
6962 | + if (err) { | ||
6963 | + printk(KERN_ERR "unionfs: error accessing " | ||
6964 | + "lower directory '%s' (error %d)\n", | ||
6965 | + name, err); | ||
6966 | + goto out; | ||
6967 | + } | ||
6968 | + | ||
6969 | + err = check_branch(&path); | ||
6970 | + if (err) { | ||
6971 | + printk(KERN_ERR "unionfs: lower directory " | ||
6972 | + "'%s' is not a valid branch\n", name); | ||
6973 | + path_put(&path); | ||
6974 | + goto out; | ||
6975 | + } | ||
6976 | + | ||
6977 | + lower_root_info->lower_paths[bindex].dentry = path.dentry; | ||
6978 | + lower_root_info->lower_paths[bindex].mnt = path.mnt; | ||
6979 | + | ||
6980 | + set_branchperms(sb, bindex, perms); | ||
6981 | + set_branch_count(sb, bindex, 0); | ||
6982 | + new_branch_id(sb, bindex); | ||
6983 | + | ||
6984 | + if (lower_root_info->bstart < 0) | ||
6985 | + lower_root_info->bstart = bindex; | ||
6986 | + lower_root_info->bend = bindex; | ||
6987 | + bindex++; | ||
6988 | + } | ||
6989 | + | ||
6990 | + if (branches == 0) { | ||
6991 | + printk(KERN_ERR "unionfs: no branches specified\n"); | ||
6992 | + err = -EINVAL; | ||
6993 | + goto out; | ||
6994 | + } | ||
6995 | + | ||
6996 | + BUG_ON(branches != (lower_root_info->bend + 1)); | ||
6997 | + | ||
6998 | + /* | ||
6999 | + * Ensure that no overlaps exist in the branches. | ||
7000 | + * | ||
7001 | + * This test is required because the Linux kernel has no support | ||
7002 | + * currently for ensuring coherency between stackable layers and | ||
7003 | + * branches. If we were to allow overlapping branches, it would be | ||
7004 | + * possible, for example, to delete a file via one branch, which | ||
7005 | + * would not be reflected in another branch. Such incoherency could | ||
7006 | + * lead to inconsistencies and even kernel oopses. Rather than | ||
7007 | + * implement hacks to work around some of these cache-coherency | ||
7008 | + * problems, we prevent branch overlapping, for now. A complete | ||
7009 | + * solution will involve proper kernel/VFS support for cache | ||
7010 | + * coherency, at which time we could safely remove this | ||
7011 | + * branch-overlapping test. | ||
7012 | + */ | ||
7013 | + for (i = 0; i < branches; i++) { | ||
7014 | + dent1 = lower_root_info->lower_paths[i].dentry; | ||
7015 | + for (j = i + 1; j < branches; j++) { | ||
7016 | + dent2 = lower_root_info->lower_paths[j].dentry; | ||
7017 | + if (is_branch_overlap(dent1, dent2)) { | ||
7018 | + printk(KERN_ERR "unionfs: branches %d and " | ||
7019 | + "%d overlap\n", i, j); | ||
7020 | + err = -EINVAL; | ||
7021 | + goto out; | ||
7022 | + } | ||
7023 | + } | ||
7024 | + } | ||
7025 | + | ||
7026 | +out: | ||
7027 | + if (err) { | ||
7028 | + for (i = 0; i < branches; i++) | ||
7029 | + path_put(&lower_root_info->lower_paths[i]); | ||
7030 | + | ||
7031 | + kfree(lower_root_info->lower_paths); | ||
7032 | + kfree(UNIONFS_SB(sb)->data); | ||
7033 | + | ||
7034 | + /* | ||
7035 | + * MUST clear the pointers to prevent potential double free if | ||
7036 | + * the caller dies later on | ||
7037 | + */ | ||
7038 | + lower_root_info->lower_paths = NULL; | ||
7039 | + UNIONFS_SB(sb)->data = NULL; | ||
7040 | + } | ||
7041 | +out_return: | ||
7042 | + return err; | ||
7043 | +} | ||
7044 | + | ||
7045 | +/* | ||
7046 | + * Parse mount options. See the manual page for usage instructions. | ||
7047 | + * | ||
7048 | + * Returns the dentry object of the lower-level (lower) directory; | ||
7049 | + * We want to mount our stackable file system on top of that lower directory. | ||
7050 | + */ | ||
7051 | +static struct unionfs_dentry_info *unionfs_parse_options( | ||
7052 | + struct super_block *sb, | ||
7053 | + char *options) | ||
7054 | +{ | ||
7055 | + struct unionfs_dentry_info *lower_root_info; | ||
7056 | + char *optname; | ||
7057 | + int err = 0; | ||
7058 | + int bindex; | ||
7059 | + int dirsfound = 0; | ||
7060 | + | ||
7061 | + /* allocate private data area */ | ||
7062 | + err = -ENOMEM; | ||
7063 | + lower_root_info = | ||
7064 | + kzalloc(sizeof(struct unionfs_dentry_info), GFP_KERNEL); | ||
7065 | + if (unlikely(!lower_root_info)) | ||
7066 | + goto out_error; | ||
7067 | + lower_root_info->bstart = -1; | ||
7068 | + lower_root_info->bend = -1; | ||
7069 | + lower_root_info->bopaque = -1; | ||
7070 | + | ||
7071 | + while ((optname = strsep(&options, ",")) != NULL) { | ||
7072 | + char *optarg; | ||
7073 | + | ||
7074 | + if (!optname || !*optname) | ||
7075 | + continue; | ||
7076 | + | ||
7077 | + optarg = strchr(optname, '='); | ||
7078 | + if (optarg) | ||
7079 | + *optarg++ = '\0'; | ||
7080 | + | ||
7081 | + /* | ||
7082 | + * All of our options take an argument now. Insert ones that | ||
7083 | + * don't, above this check. | ||
7084 | + */ | ||
7085 | + if (!optarg) { | ||
7086 | + printk(KERN_ERR "unionfs: %s requires an argument\n", | ||
7087 | + optname); | ||
7088 | + err = -EINVAL; | ||
7089 | + goto out_error; | ||
7090 | + } | ||
7091 | + | ||
7092 | + if (!strcmp("dirs", optname)) { | ||
7093 | + if (++dirsfound > 1) { | ||
7094 | + printk(KERN_ERR | ||
7095 | + "unionfs: multiple dirs specified\n"); | ||
7096 | + err = -EINVAL; | ||
7097 | + goto out_error; | ||
7098 | + } | ||
7099 | + err = parse_dirs_option(sb, lower_root_info, optarg); | ||
7100 | + if (err) | ||
7101 | + goto out_error; | ||
7102 | + continue; | ||
7103 | + } | ||
7104 | + | ||
7105 | + err = -EINVAL; | ||
7106 | + printk(KERN_ERR | ||
7107 | + "unionfs: unrecognized option '%s'\n", optname); | ||
7108 | + goto out_error; | ||
7109 | + } | ||
7110 | + if (dirsfound != 1) { | ||
7111 | + printk(KERN_ERR "unionfs: dirs option required\n"); | ||
7112 | + err = -EINVAL; | ||
7113 | + goto out_error; | ||
7114 | + } | ||
7115 | + goto out; | ||
7116 | + | ||
7117 | +out_error: | ||
7118 | + if (lower_root_info && lower_root_info->lower_paths) { | ||
7119 | + for (bindex = lower_root_info->bstart; | ||
7120 | + bindex >= 0 && bindex <= lower_root_info->bend; | ||
7121 | + bindex++) | ||
7122 | + path_put(&lower_root_info->lower_paths[bindex]); | ||
7123 | + } | ||
7124 | + | ||
7125 | + kfree(lower_root_info->lower_paths); | ||
7126 | + kfree(lower_root_info); | ||
7127 | + | ||
7128 | + kfree(UNIONFS_SB(sb)->data); | ||
7129 | + UNIONFS_SB(sb)->data = NULL; | ||
7130 | + | ||
7131 | + lower_root_info = ERR_PTR(err); | ||
7132 | +out: | ||
7133 | + return lower_root_info; | ||
7134 | +} | ||
7135 | + | ||
7136 | +/* | ||
7137 | + * our custom d_alloc_root work-alike | ||
7138 | + * | ||
7139 | + * we can't use d_alloc_root if we want to use our own interpose function | ||
7140 | + * unchanged, so we simply call our own "fake" d_alloc_root | ||
7141 | + */ | ||
7142 | +static struct dentry *unionfs_d_alloc_root(struct super_block *sb) | ||
7143 | +{ | ||
7144 | + struct dentry *ret = NULL; | ||
7145 | + | ||
7146 | + if (sb) { | ||
7147 | + static const struct qstr name = { | ||
7148 | + .name = "/", | ||
7149 | + .len = 1 | ||
7150 | + }; | ||
7151 | + | ||
7152 | + ret = d_alloc(NULL, &name); | ||
7153 | + if (likely(ret)) { | ||
7154 | + ret->d_op = &unionfs_dops; | ||
7155 | + ret->d_sb = sb; | ||
7156 | + ret->d_parent = ret; | ||
7157 | + } | ||
7158 | + } | ||
7159 | + return ret; | ||
7160 | +} | ||
7161 | + | ||
7162 | +/* | ||
7163 | + * There is no need to lock the unionfs_super_info's rwsem as there is no | ||
7164 | + * way anyone can have a reference to the superblock at this point in time. | ||
7165 | + */ | ||
7166 | +static int unionfs_read_super(struct super_block *sb, void *raw_data, | ||
7167 | + int silent) | ||
7168 | +{ | ||
7169 | + int err = 0; | ||
7170 | + struct unionfs_dentry_info *lower_root_info = NULL; | ||
7171 | + int bindex, bstart, bend; | ||
7172 | + | ||
7173 | + if (!raw_data) { | ||
7174 | + printk(KERN_ERR | ||
7175 | + "unionfs: read_super: missing data argument\n"); | ||
7176 | + err = -EINVAL; | ||
7177 | + goto out; | ||
7178 | + } | ||
7179 | + | ||
7180 | + /* Allocate superblock private data */ | ||
7181 | + sb->s_fs_info = kzalloc(sizeof(struct unionfs_sb_info), GFP_KERNEL); | ||
7182 | + if (unlikely(!UNIONFS_SB(sb))) { | ||
7183 | + printk(KERN_CRIT "unionfs: read_super: out of memory\n"); | ||
7184 | + err = -ENOMEM; | ||
7185 | + goto out; | ||
7186 | + } | ||
7187 | + | ||
7188 | + UNIONFS_SB(sb)->bend = -1; | ||
7189 | + atomic_set(&UNIONFS_SB(sb)->generation, 1); | ||
7190 | + init_rwsem(&UNIONFS_SB(sb)->rwsem); | ||
7191 | + UNIONFS_SB(sb)->high_branch_id = -1; /* -1 == invalid branch ID */ | ||
7192 | + | ||
7193 | + lower_root_info = unionfs_parse_options(sb, raw_data); | ||
7194 | + if (IS_ERR(lower_root_info)) { | ||
7195 | + printk(KERN_ERR | ||
7196 | + "unionfs: read_super: error while parsing options " | ||
7197 | + "(err = %ld)\n", PTR_ERR(lower_root_info)); | ||
7198 | + err = PTR_ERR(lower_root_info); | ||
7199 | + lower_root_info = NULL; | ||
7200 | + goto out_free; | ||
7201 | + } | ||
7202 | + if (lower_root_info->bstart == -1) { | ||
7203 | + err = -ENOENT; | ||
7204 | + goto out_free; | ||
7205 | + } | ||
7206 | + | ||
7207 | + /* set the lower superblock field of upper superblock */ | ||
7208 | + bstart = lower_root_info->bstart; | ||
7209 | + BUG_ON(bstart != 0); | ||
7210 | + sbend(sb) = bend = lower_root_info->bend; | ||
7211 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
7212 | + struct dentry *d = lower_root_info->lower_paths[bindex].dentry; | ||
7213 | + atomic_inc(&d->d_sb->s_active); | ||
7214 | + unionfs_set_lower_super_idx(sb, bindex, d->d_sb); | ||
7215 | + } | ||
7216 | + | ||
7217 | + /* max Bytes is the maximum bytes from highest priority branch */ | ||
7218 | + sb->s_maxbytes = unionfs_lower_super_idx(sb, 0)->s_maxbytes; | ||
7219 | + | ||
7220 | + /* | ||
7221 | + * Our c/m/atime granularity is 1 ns because we may stack on file | ||
7222 | + * systems whose granularity is as good. This is important for our | ||
7223 | + * time-based cache coherency. | ||
7224 | + */ | ||
7225 | + sb->s_time_gran = 1; | ||
7226 | + | ||
7227 | + sb->s_op = &unionfs_sops; | ||
7228 | + | ||
7229 | + /* See comment next to the definition of unionfs_d_alloc_root */ | ||
7230 | + sb->s_root = unionfs_d_alloc_root(sb); | ||
7231 | + if (unlikely(!sb->s_root)) { | ||
7232 | + err = -ENOMEM; | ||
7233 | + goto out_dput; | ||
7234 | + } | ||
7235 | + | ||
7236 | + /* link the upper and lower dentries */ | ||
7237 | + sb->s_root->d_fsdata = NULL; | ||
7238 | + err = new_dentry_private_data(sb->s_root, UNIONFS_DMUTEX_ROOT); | ||
7239 | + if (unlikely(err)) | ||
7240 | + goto out_freedpd; | ||
7241 | + | ||
7242 | + /* Set the lower dentries for s_root */ | ||
7243 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
7244 | + struct dentry *d; | ||
7245 | + struct vfsmount *m; | ||
7246 | + | ||
7247 | + d = lower_root_info->lower_paths[bindex].dentry; | ||
7248 | + m = lower_root_info->lower_paths[bindex].mnt; | ||
7249 | + | ||
7250 | + unionfs_set_lower_dentry_idx(sb->s_root, bindex, d); | ||
7251 | + unionfs_set_lower_mnt_idx(sb->s_root, bindex, m); | ||
7252 | + } | ||
7253 | + dbstart(sb->s_root) = bstart; | ||
7254 | + dbend(sb->s_root) = bend; | ||
7255 | + | ||
7256 | + /* Set the generation number to one, since this is for the mount. */ | ||
7257 | + atomic_set(&UNIONFS_D(sb->s_root)->generation, 1); | ||
7258 | + | ||
7259 | + /* | ||
7260 | + * Call interpose to create the upper level inode. Only | ||
7261 | + * INTERPOSE_LOOKUP can return a value other than 0 on err. | ||
7262 | + */ | ||
7263 | + err = PTR_ERR(unionfs_interpose(sb->s_root, sb, 0)); | ||
7264 | + unionfs_unlock_dentry(sb->s_root); | ||
7265 | + if (!err) | ||
7266 | + goto out; | ||
7267 | + /* else fall through */ | ||
7268 | + | ||
7269 | +out_freedpd: | ||
7270 | + if (UNIONFS_D(sb->s_root)) { | ||
7271 | + kfree(UNIONFS_D(sb->s_root)->lower_paths); | ||
7272 | + free_dentry_private_data(sb->s_root); | ||
7273 | + } | ||
7274 | + dput(sb->s_root); | ||
7275 | + | ||
7276 | +out_dput: | ||
7277 | + if (lower_root_info && !IS_ERR(lower_root_info)) { | ||
7278 | + for (bindex = lower_root_info->bstart; | ||
7279 | + bindex <= lower_root_info->bend; bindex++) { | ||
7280 | + struct dentry *d; | ||
7281 | + d = lower_root_info->lower_paths[bindex].dentry; | ||
7282 | + /* drop refs we took earlier */ | ||
7283 | + atomic_dec(&d->d_sb->s_active); | ||
7284 | + path_put(&lower_root_info->lower_paths[bindex]); | ||
7285 | + } | ||
7286 | + kfree(lower_root_info->lower_paths); | ||
7287 | + kfree(lower_root_info); | ||
7288 | + lower_root_info = NULL; | ||
7289 | + } | ||
7290 | + | ||
7291 | +out_free: | ||
7292 | + kfree(UNIONFS_SB(sb)->data); | ||
7293 | + kfree(UNIONFS_SB(sb)); | ||
7294 | + sb->s_fs_info = NULL; | ||
7295 | + | ||
7296 | +out: | ||
7297 | + if (lower_root_info && !IS_ERR(lower_root_info)) { | ||
7298 | + kfree(lower_root_info->lower_paths); | ||
7299 | + kfree(lower_root_info); | ||
7300 | + } | ||
7301 | + return err; | ||
7302 | +} | ||
7303 | + | ||
7304 | +static struct dentry *unionfs_mount(struct file_system_type *fs_type, | ||
7305 | + int flags, const char *dev_name, | ||
7306 | + void *raw_data) | ||
7307 | +{ | ||
7308 | + struct dentry *dentry; | ||
7309 | + | ||
7310 | + dentry = mount_nodev(fs_type, flags, raw_data, unionfs_read_super); | ||
7311 | + if (!PTR_ERR(dentry)) | ||
7312 | + UNIONFS_SB(dentry->d_sb)->dev_name = | ||
7313 | + kstrdup(dev_name, GFP_KERNEL); | ||
7314 | + return dentry; | ||
7315 | +} | ||
7316 | + | ||
7317 | +static struct file_system_type unionfs_fs_type = { | ||
7318 | + .owner = THIS_MODULE, | ||
7319 | + .name = UNIONFS_NAME, | ||
7320 | + .mount = unionfs_mount, | ||
7321 | + .kill_sb = generic_shutdown_super, | ||
7322 | + .fs_flags = FS_REVAL_DOT, | ||
7323 | +}; | ||
7324 | + | ||
7325 | +static int __init init_unionfs_fs(void) | ||
7326 | +{ | ||
7327 | + int err; | ||
7328 | + | ||
7329 | + pr_info("Registering unionfs " UNIONFS_VERSION "\n"); | ||
7330 | + | ||
7331 | + err = unionfs_init_filldir_cache(); | ||
7332 | + if (unlikely(err)) | ||
7333 | + goto out; | ||
7334 | + err = unionfs_init_inode_cache(); | ||
7335 | + if (unlikely(err)) | ||
7336 | + goto out; | ||
7337 | + err = unionfs_init_dentry_cache(); | ||
7338 | + if (unlikely(err)) | ||
7339 | + goto out; | ||
7340 | + err = init_sioq(); | ||
7341 | + if (unlikely(err)) | ||
7342 | + goto out; | ||
7343 | + err = register_filesystem(&unionfs_fs_type); | ||
7344 | +out: | ||
7345 | + if (unlikely(err)) { | ||
7346 | + stop_sioq(); | ||
7347 | + unionfs_destroy_filldir_cache(); | ||
7348 | + unionfs_destroy_inode_cache(); | ||
7349 | + unionfs_destroy_dentry_cache(); | ||
7350 | + } | ||
7351 | + return err; | ||
7352 | +} | ||
7353 | + | ||
7354 | +static void __exit exit_unionfs_fs(void) | ||
7355 | +{ | ||
7356 | + stop_sioq(); | ||
7357 | + unionfs_destroy_filldir_cache(); | ||
7358 | + unionfs_destroy_inode_cache(); | ||
7359 | + unionfs_destroy_dentry_cache(); | ||
7360 | + unregister_filesystem(&unionfs_fs_type); | ||
7361 | + pr_info("Completed unionfs module unload\n"); | ||
7362 | +} | ||
7363 | + | ||
7364 | +MODULE_AUTHOR("Erez Zadok, Filesystems and Storage Lab, Stony Brook University" | ||
7365 | + " (http://www.fsl.cs.sunysb.edu)"); | ||
7366 | +MODULE_DESCRIPTION("Unionfs " UNIONFS_VERSION | ||
7367 | + " (http://unionfs.filesystems.org)"); | ||
7368 | +MODULE_LICENSE("GPL"); | ||
7369 | + | ||
7370 | +module_init(init_unionfs_fs); | ||
7371 | +module_exit(exit_unionfs_fs); | ||
7372 | diff --git a/fs/unionfs/mmap.c b/fs/unionfs/mmap.c | ||
7373 | new file mode 100644 | ||
7374 | index 0000000..bcc5652 | ||
7375 | --- /dev/null | ||
7376 | +++ b/fs/unionfs/mmap.c | ||
7377 | @@ -0,0 +1,89 @@ | ||
7378 | +/* | ||
7379 | + * Copyright (c) 2003-2011 Erez Zadok | ||
7380 | + * Copyright (c) 2003-2006 Charles P. Wright | ||
7381 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
7382 | + * Copyright (c) 2005-2006 Junjiro Okajima | ||
7383 | + * Copyright (c) 2006 Shaya Potter | ||
7384 | + * Copyright (c) 2005 Arun M. Krishnakumar | ||
7385 | + * Copyright (c) 2004-2006 David P. Quigley | ||
7386 | + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair | ||
7387 | + * Copyright (c) 2003 Puja Gupta | ||
7388 | + * Copyright (c) 2003 Harikesavan Krishnan | ||
7389 | + * Copyright (c) 2003-2011 Stony Brook University | ||
7390 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
7391 | + * | ||
7392 | + * This program is free software; you can redistribute it and/or modify | ||
7393 | + * it under the terms of the GNU General Public License version 2 as | ||
7394 | + * published by the Free Software Foundation. | ||
7395 | + */ | ||
7396 | + | ||
7397 | +#include "union.h" | ||
7398 | + | ||
7399 | + | ||
7400 | +/* | ||
7401 | + * XXX: we need a dummy readpage handler because generic_file_mmap (which we | ||
7402 | + * use in unionfs_mmap) checks for the existence of | ||
7403 | + * mapping->a_ops->readpage, else it returns -ENOEXEC. The VFS will need to | ||
7404 | + * be fixed to allow a file system to define vm_ops->fault without any | ||
7405 | + * address_space_ops whatsoever. | ||
7406 | + * | ||
7407 | + * Otherwise, we don't want to use our readpage method at all. | ||
7408 | + */ | ||
7409 | +static int unionfs_readpage(struct file *file, struct page *page) | ||
7410 | +{ | ||
7411 | + BUG(); | ||
7412 | + return -EINVAL; | ||
7413 | +} | ||
7414 | + | ||
7415 | +static int unionfs_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | ||
7416 | +{ | ||
7417 | + int err; | ||
7418 | + struct file *file, *lower_file; | ||
7419 | + const struct vm_operations_struct *lower_vm_ops; | ||
7420 | + struct vm_area_struct lower_vma; | ||
7421 | + | ||
7422 | + BUG_ON(!vma); | ||
7423 | + memcpy(&lower_vma, vma, sizeof(struct vm_area_struct)); | ||
7424 | + file = lower_vma.vm_file; | ||
7425 | + lower_vm_ops = UNIONFS_F(file)->lower_vm_ops; | ||
7426 | + BUG_ON(!lower_vm_ops); | ||
7427 | + | ||
7428 | + lower_file = unionfs_lower_file(file); | ||
7429 | + BUG_ON(!lower_file); | ||
7430 | + /* | ||
7431 | + * XXX: vm_ops->fault may be called in parallel. Because we have to | ||
7432 | + * resort to temporarily changing the vma->vm_file to point to the | ||
7433 | + * lower file, a concurrent invocation of unionfs_fault could see a | ||
7434 | + * different value. In this workaround, we keep a different copy of | ||
7435 | + * the vma structure in our stack, so we never expose a different | ||
7436 | + * value of the vma->vm_file called to us, even temporarily. A | ||
7437 | + * better fix would be to change the calling semantics of ->fault to | ||
7438 | + * take an explicit file pointer. | ||
7439 | + */ | ||
7440 | + lower_vma.vm_file = lower_file; | ||
7441 | + err = lower_vm_ops->fault(&lower_vma, vmf); | ||
7442 | + return err; | ||
7443 | +} | ||
7444 | + | ||
7445 | +/* | ||
7446 | + * XXX: the default address_space_ops for unionfs is empty. We cannot set | ||
7447 | + * our inode->i_mapping->a_ops to NULL because too many code paths expect | ||
7448 | + * the a_ops vector to be non-NULL. | ||
7449 | + */ | ||
7450 | +struct address_space_operations unionfs_aops = { | ||
7451 | + /* empty on purpose */ | ||
7452 | +}; | ||
7453 | + | ||
7454 | +/* | ||
7455 | + * XXX: we need a second, dummy address_space_ops vector, to be used | ||
7456 | + * temporarily during unionfs_mmap, because the latter calls | ||
7457 | + * generic_file_mmap, which checks if ->readpage exists, else returns | ||
7458 | + * -ENOEXEC. | ||
7459 | + */ | ||
7460 | +struct address_space_operations unionfs_dummy_aops = { | ||
7461 | + .readpage = unionfs_readpage, | ||
7462 | +}; | ||
7463 | + | ||
7464 | +struct vm_operations_struct unionfs_vm_ops = { | ||
7465 | + .fault = unionfs_fault, | ||
7466 | +}; | ||
7467 | diff --git a/fs/unionfs/rdstate.c b/fs/unionfs/rdstate.c | ||
7468 | new file mode 100644 | ||
7469 | index 0000000..59b7333 | ||
7470 | --- /dev/null | ||
7471 | +++ b/fs/unionfs/rdstate.c | ||
7472 | @@ -0,0 +1,285 @@ | ||
7473 | +/* | ||
7474 | + * Copyright (c) 2003-2011 Erez Zadok | ||
7475 | + * Copyright (c) 2003-2006 Charles P. Wright | ||
7476 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
7477 | + * Copyright (c) 2005-2006 Junjiro Okajima | ||
7478 | + * Copyright (c) 2005 Arun M. Krishnakumar | ||
7479 | + * Copyright (c) 2004-2006 David P. Quigley | ||
7480 | + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair | ||
7481 | + * Copyright (c) 2003 Puja Gupta | ||
7482 | + * Copyright (c) 2003 Harikesavan Krishnan | ||
7483 | + * Copyright (c) 2003-2011 Stony Brook University | ||
7484 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
7485 | + * | ||
7486 | + * This program is free software; you can redistribute it and/or modify | ||
7487 | + * it under the terms of the GNU General Public License version 2 as | ||
7488 | + * published by the Free Software Foundation. | ||
7489 | + */ | ||
7490 | + | ||
7491 | +#include "union.h" | ||
7492 | + | ||
7493 | +/* This file contains the routines for maintaining readdir state. */ | ||
7494 | + | ||
7495 | +/* | ||
7496 | + * There are two structures here, rdstate which is a hash table | ||
7497 | + * of the second structure which is a filldir_node. | ||
7498 | + */ | ||
7499 | + | ||
7500 | +/* | ||
7501 | + * This is a struct kmem_cache for filldir nodes, because we allocate a lot | ||
7502 | + * of them and they shouldn't waste memory. If the node has a small name | ||
7503 | + * (as defined by the dentry structure), then we use an inline name to | ||
7504 | + * preserve kmalloc space. | ||
7505 | + */ | ||
7506 | +static struct kmem_cache *unionfs_filldir_cachep; | ||
7507 | + | ||
7508 | +int unionfs_init_filldir_cache(void) | ||
7509 | +{ | ||
7510 | + unionfs_filldir_cachep = | ||
7511 | + kmem_cache_create("unionfs_filldir", | ||
7512 | + sizeof(struct filldir_node), 0, | ||
7513 | + SLAB_RECLAIM_ACCOUNT, NULL); | ||
7514 | + | ||
7515 | + return (unionfs_filldir_cachep ? 0 : -ENOMEM); | ||
7516 | +} | ||
7517 | + | ||
7518 | +void unionfs_destroy_filldir_cache(void) | ||
7519 | +{ | ||
7520 | + if (unionfs_filldir_cachep) | ||
7521 | + kmem_cache_destroy(unionfs_filldir_cachep); | ||
7522 | +} | ||
7523 | + | ||
7524 | +/* | ||
7525 | + * This is a tuning parameter that tells us roughly how big to make the | ||
7526 | + * hash table in directory entries per page. This isn't perfect, but | ||
7527 | + * at least we get a hash table size that shouldn't be too overloaded. | ||
7528 | + * The following averages are based on my home directory. | ||
7529 | + * 14.44693 Overall | ||
7530 | + * 12.29 Single Page Directories | ||
7531 | + * 117.93 Multi-page directories | ||
7532 | + */ | ||
7533 | +#define DENTPAGE 4096 | ||
7534 | +#define DENTPERONEPAGE 12 | ||
7535 | +#define DENTPERPAGE 118 | ||
7536 | +#define MINHASHSIZE 1 | ||
7537 | +static int guesstimate_hash_size(struct inode *inode) | ||
7538 | +{ | ||
7539 | + struct inode *lower_inode; | ||
7540 | + int bindex; | ||
7541 | + int hashsize = MINHASHSIZE; | ||
7542 | + | ||
7543 | + if (UNIONFS_I(inode)->hashsize > 0) | ||
7544 | + return UNIONFS_I(inode)->hashsize; | ||
7545 | + | ||
7546 | + for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) { | ||
7547 | + lower_inode = unionfs_lower_inode_idx(inode, bindex); | ||
7548 | + if (!lower_inode) | ||
7549 | + continue; | ||
7550 | + | ||
7551 | + if (i_size_read(lower_inode) == DENTPAGE) | ||
7552 | + hashsize += DENTPERONEPAGE; | ||
7553 | + else | ||
7554 | + hashsize += (i_size_read(lower_inode) / DENTPAGE) * | ||
7555 | + DENTPERPAGE; | ||
7556 | + } | ||
7557 | + | ||
7558 | + return hashsize; | ||
7559 | +} | ||
7560 | + | ||
7561 | +int init_rdstate(struct file *file) | ||
7562 | +{ | ||
7563 | + BUG_ON(sizeof(loff_t) != | ||
7564 | + (sizeof(unsigned int) + sizeof(unsigned int))); | ||
7565 | + BUG_ON(UNIONFS_F(file)->rdstate != NULL); | ||
7566 | + | ||
7567 | + UNIONFS_F(file)->rdstate = alloc_rdstate(file->f_path.dentry->d_inode, | ||
7568 | + fbstart(file)); | ||
7569 | + | ||
7570 | + return (UNIONFS_F(file)->rdstate ? 0 : -ENOMEM); | ||
7571 | +} | ||
7572 | + | ||
7573 | +struct unionfs_dir_state *find_rdstate(struct inode *inode, loff_t fpos) | ||
7574 | +{ | ||
7575 | + struct unionfs_dir_state *rdstate = NULL; | ||
7576 | + struct list_head *pos; | ||
7577 | + | ||
7578 | + spin_lock(&UNIONFS_I(inode)->rdlock); | ||
7579 | + list_for_each(pos, &UNIONFS_I(inode)->readdircache) { | ||
7580 | + struct unionfs_dir_state *r = | ||
7581 | + list_entry(pos, struct unionfs_dir_state, cache); | ||
7582 | + if (fpos == rdstate2offset(r)) { | ||
7583 | + UNIONFS_I(inode)->rdcount--; | ||
7584 | + list_del(&r->cache); | ||
7585 | + rdstate = r; | ||
7586 | + break; | ||
7587 | + } | ||
7588 | + } | ||
7589 | + spin_unlock(&UNIONFS_I(inode)->rdlock); | ||
7590 | + return rdstate; | ||
7591 | +} | ||
7592 | + | ||
7593 | +struct unionfs_dir_state *alloc_rdstate(struct inode *inode, int bindex) | ||
7594 | +{ | ||
7595 | + int i = 0; | ||
7596 | + int hashsize; | ||
7597 | + unsigned long mallocsize = sizeof(struct unionfs_dir_state); | ||
7598 | + struct unionfs_dir_state *rdstate; | ||
7599 | + | ||
7600 | + hashsize = guesstimate_hash_size(inode); | ||
7601 | + mallocsize += hashsize * sizeof(struct list_head); | ||
7602 | + mallocsize = __roundup_pow_of_two(mallocsize); | ||
7603 | + | ||
7604 | + /* This should give us about 500 entries anyway. */ | ||
7605 | + if (mallocsize > PAGE_SIZE) | ||
7606 | + mallocsize = PAGE_SIZE; | ||
7607 | + | ||
7608 | + hashsize = (mallocsize - sizeof(struct unionfs_dir_state)) / | ||
7609 | + sizeof(struct list_head); | ||
7610 | + | ||
7611 | + rdstate = kmalloc(mallocsize, GFP_KERNEL); | ||
7612 | + if (unlikely(!rdstate)) | ||
7613 | + return NULL; | ||
7614 | + | ||
7615 | + spin_lock(&UNIONFS_I(inode)->rdlock); | ||
7616 | + if (UNIONFS_I(inode)->cookie >= (MAXRDCOOKIE - 1)) | ||
7617 | + UNIONFS_I(inode)->cookie = 1; | ||
7618 | + else | ||
7619 | + UNIONFS_I(inode)->cookie++; | ||
7620 | + | ||
7621 | + rdstate->cookie = UNIONFS_I(inode)->cookie; | ||
7622 | + spin_unlock(&UNIONFS_I(inode)->rdlock); | ||
7623 | + rdstate->offset = 1; | ||
7624 | + rdstate->access = jiffies; | ||
7625 | + rdstate->bindex = bindex; | ||
7626 | + rdstate->dirpos = 0; | ||
7627 | + rdstate->hashentries = 0; | ||
7628 | + rdstate->size = hashsize; | ||
7629 | + for (i = 0; i < rdstate->size; i++) | ||
7630 | + INIT_LIST_HEAD(&rdstate->list[i]); | ||
7631 | + | ||
7632 | + return rdstate; | ||
7633 | +} | ||
7634 | + | ||
7635 | +static void free_filldir_node(struct filldir_node *node) | ||
7636 | +{ | ||
7637 | + if (node->namelen >= DNAME_INLINE_LEN) | ||
7638 | + kfree(node->name); | ||
7639 | + kmem_cache_free(unionfs_filldir_cachep, node); | ||
7640 | +} | ||
7641 | + | ||
7642 | +void free_rdstate(struct unionfs_dir_state *state) | ||
7643 | +{ | ||
7644 | + struct filldir_node *tmp; | ||
7645 | + int i; | ||
7646 | + | ||
7647 | + for (i = 0; i < state->size; i++) { | ||
7648 | + struct list_head *head = &(state->list[i]); | ||
7649 | + struct list_head *pos, *n; | ||
7650 | + | ||
7651 | + /* traverse the list and deallocate space */ | ||
7652 | + list_for_each_safe(pos, n, head) { | ||
7653 | + tmp = list_entry(pos, struct filldir_node, file_list); | ||
7654 | + list_del(&tmp->file_list); | ||
7655 | + free_filldir_node(tmp); | ||
7656 | + } | ||
7657 | + } | ||
7658 | + | ||
7659 | + kfree(state); | ||
7660 | +} | ||
7661 | + | ||
7662 | +struct filldir_node *find_filldir_node(struct unionfs_dir_state *rdstate, | ||
7663 | + const char *name, int namelen, | ||
7664 | + int is_whiteout) | ||
7665 | +{ | ||
7666 | + int index; | ||
7667 | + unsigned int hash; | ||
7668 | + struct list_head *head; | ||
7669 | + struct list_head *pos; | ||
7670 | + struct filldir_node *cursor = NULL; | ||
7671 | + int found = 0; | ||
7672 | + | ||
7673 | + BUG_ON(namelen <= 0); | ||
7674 | + | ||
7675 | + hash = full_name_hash(name, namelen); | ||
7676 | + index = hash % rdstate->size; | ||
7677 | + | ||
7678 | + head = &(rdstate->list[index]); | ||
7679 | + list_for_each(pos, head) { | ||
7680 | + cursor = list_entry(pos, struct filldir_node, file_list); | ||
7681 | + | ||
7682 | + if (cursor->namelen == namelen && cursor->hash == hash && | ||
7683 | + !strncmp(cursor->name, name, namelen)) { | ||
7684 | + /* | ||
7685 | + * a duplicate exists, and hence no need to create | ||
7686 | + * entry to the list | ||
7687 | + */ | ||
7688 | + found = 1; | ||
7689 | + | ||
7690 | + /* | ||
7691 | + * if a duplicate is found in this branch, and is | ||
7692 | + * not due to the caller looking for an entry to | ||
7693 | + * whiteout, then the file system may be corrupted. | ||
7694 | + */ | ||
7695 | + if (unlikely(!is_whiteout && | ||
7696 | + cursor->bindex == rdstate->bindex)) | ||
7697 | + printk(KERN_ERR "unionfs: filldir: possible " | ||
7698 | + "I/O error: a file is duplicated " | ||
7699 | + "in the same branch %d: %s\n", | ||
7700 | + rdstate->bindex, cursor->name); | ||
7701 | + break; | ||
7702 | + } | ||
7703 | + } | ||
7704 | + | ||
7705 | + if (!found) | ||
7706 | + cursor = NULL; | ||
7707 | + | ||
7708 | + return cursor; | ||
7709 | +} | ||
7710 | + | ||
7711 | +int add_filldir_node(struct unionfs_dir_state *rdstate, const char *name, | ||
7712 | + int namelen, int bindex, int whiteout) | ||
7713 | +{ | ||
7714 | + struct filldir_node *new; | ||
7715 | + unsigned int hash; | ||
7716 | + int index; | ||
7717 | + int err = 0; | ||
7718 | + struct list_head *head; | ||
7719 | + | ||
7720 | + BUG_ON(namelen <= 0); | ||
7721 | + | ||
7722 | + hash = full_name_hash(name, namelen); | ||
7723 | + index = hash % rdstate->size; | ||
7724 | + head = &(rdstate->list[index]); | ||
7725 | + | ||
7726 | + new = kmem_cache_alloc(unionfs_filldir_cachep, GFP_KERNEL); | ||
7727 | + if (unlikely(!new)) { | ||
7728 | + err = -ENOMEM; | ||
7729 | + goto out; | ||
7730 | + } | ||
7731 | + | ||
7732 | + INIT_LIST_HEAD(&new->file_list); | ||
7733 | + new->namelen = namelen; | ||
7734 | + new->hash = hash; | ||
7735 | + new->bindex = bindex; | ||
7736 | + new->whiteout = whiteout; | ||
7737 | + | ||
7738 | + if (namelen < DNAME_INLINE_LEN) { | ||
7739 | + new->name = new->iname; | ||
7740 | + } else { | ||
7741 | + new->name = kmalloc(namelen + 1, GFP_KERNEL); | ||
7742 | + if (unlikely(!new->name)) { | ||
7743 | + kmem_cache_free(unionfs_filldir_cachep, new); | ||
7744 | + new = NULL; | ||
7745 | + goto out; | ||
7746 | + } | ||
7747 | + } | ||
7748 | + | ||
7749 | + memcpy(new->name, name, namelen); | ||
7750 | + new->name[namelen] = '\0'; | ||
7751 | + | ||
7752 | + rdstate->hashentries++; | ||
7753 | + | ||
7754 | + list_add(&(new->file_list), head); | ||
7755 | +out: | ||
7756 | + return err; | ||
7757 | +} | ||
7758 | diff --git a/fs/unionfs/rename.c b/fs/unionfs/rename.c | ||
7759 | new file mode 100644 | ||
7760 | index 0000000..c8ab910 | ||
7761 | --- /dev/null | ||
7762 | +++ b/fs/unionfs/rename.c | ||
7763 | @@ -0,0 +1,522 @@ | ||
7764 | +/* | ||
7765 | + * Copyright (c) 2003-2011 Erez Zadok | ||
7766 | + * Copyright (c) 2003-2006 Charles P. Wright | ||
7767 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
7768 | + * Copyright (c) 2005-2006 Junjiro Okajima | ||
7769 | + * Copyright (c) 2005 Arun M. Krishnakumar | ||
7770 | + * Copyright (c) 2004-2006 David P. Quigley | ||
7771 | + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair | ||
7772 | + * Copyright (c) 2003 Puja Gupta | ||
7773 | + * Copyright (c) 2003 Harikesavan Krishnan | ||
7774 | + * Copyright (c) 2003-2011 Stony Brook University | ||
7775 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
7776 | + * | ||
7777 | + * This program is free software; you can redistribute it and/or modify | ||
7778 | + * it under the terms of the GNU General Public License version 2 as | ||
7779 | + * published by the Free Software Foundation. | ||
7780 | + */ | ||
7781 | + | ||
7782 | +#include "union.h" | ||
7783 | + | ||
7784 | +/* | ||
7785 | + * This is a helper function for rename, used when rename ends up with hosed | ||
7786 | + * over dentries and we need to revert. | ||
7787 | + */ | ||
7788 | +static int unionfs_refresh_lower_dentry(struct dentry *dentry, | ||
7789 | + struct dentry *parent, int bindex) | ||
7790 | +{ | ||
7791 | + struct dentry *lower_dentry; | ||
7792 | + struct dentry *lower_parent; | ||
7793 | + int err = 0; | ||
7794 | + struct nameidata lower_nd; | ||
7795 | + | ||
7796 | + verify_locked(dentry); | ||
7797 | + | ||
7798 | + lower_parent = unionfs_lower_dentry_idx(parent, bindex); | ||
7799 | + | ||
7800 | + BUG_ON(!S_ISDIR(lower_parent->d_inode->i_mode)); | ||
7801 | + | ||
7802 | + err = init_lower_nd(&lower_nd, LOOKUP_OPEN); | ||
7803 | + if (unlikely(err < 0)) | ||
7804 | + goto out; | ||
7805 | + lower_dentry = lookup_one_len_nd(dentry->d_name.name, lower_parent, | ||
7806 | + dentry->d_name.len, &lower_nd); | ||
7807 | + release_lower_nd(&lower_nd, err); | ||
7808 | + if (IS_ERR(lower_dentry)) { | ||
7809 | + err = PTR_ERR(lower_dentry); | ||
7810 | + goto out; | ||
7811 | + } | ||
7812 | + | ||
7813 | + dput(unionfs_lower_dentry_idx(dentry, bindex)); | ||
7814 | + iput(unionfs_lower_inode_idx(dentry->d_inode, bindex)); | ||
7815 | + unionfs_set_lower_inode_idx(dentry->d_inode, bindex, NULL); | ||
7816 | + | ||
7817 | + if (!lower_dentry->d_inode) { | ||
7818 | + dput(lower_dentry); | ||
7819 | + unionfs_set_lower_dentry_idx(dentry, bindex, NULL); | ||
7820 | + } else { | ||
7821 | + unionfs_set_lower_dentry_idx(dentry, bindex, lower_dentry); | ||
7822 | + unionfs_set_lower_inode_idx(dentry->d_inode, bindex, | ||
7823 | + igrab(lower_dentry->d_inode)); | ||
7824 | + } | ||
7825 | + | ||
7826 | +out: | ||
7827 | + return err; | ||
7828 | +} | ||
7829 | + | ||
7830 | +static int __unionfs_rename(struct inode *old_dir, struct dentry *old_dentry, | ||
7831 | + struct dentry *old_parent, | ||
7832 | + struct inode *new_dir, struct dentry *new_dentry, | ||
7833 | + struct dentry *new_parent, | ||
7834 | + int bindex) | ||
7835 | +{ | ||
7836 | + int err = 0; | ||
7837 | + struct dentry *lower_old_dentry; | ||
7838 | + struct dentry *lower_new_dentry; | ||
7839 | + struct dentry *lower_old_dir_dentry; | ||
7840 | + struct dentry *lower_new_dir_dentry; | ||
7841 | + struct dentry *trap; | ||
7842 | + | ||
7843 | + lower_new_dentry = unionfs_lower_dentry_idx(new_dentry, bindex); | ||
7844 | + lower_old_dentry = unionfs_lower_dentry_idx(old_dentry, bindex); | ||
7845 | + | ||
7846 | + if (!lower_new_dentry) { | ||
7847 | + lower_new_dentry = | ||
7848 | + create_parents(new_parent->d_inode, | ||
7849 | + new_dentry, new_dentry->d_name.name, | ||
7850 | + bindex); | ||
7851 | + if (IS_ERR(lower_new_dentry)) { | ||
7852 | + err = PTR_ERR(lower_new_dentry); | ||
7853 | + if (IS_COPYUP_ERR(err)) | ||
7854 | + goto out; | ||
7855 | + printk(KERN_ERR "unionfs: error creating directory " | ||
7856 | + "tree for rename, bindex=%d err=%d\n", | ||
7857 | + bindex, err); | ||
7858 | + goto out; | ||
7859 | + } | ||
7860 | + } | ||
7861 | + | ||
7862 | + /* check for and remove whiteout, if any */ | ||
7863 | + err = check_unlink_whiteout(new_dentry, lower_new_dentry, bindex); | ||
7864 | + if (err > 0) /* ignore if whiteout found and successfully removed */ | ||
7865 | + err = 0; | ||
7866 | + if (err) | ||
7867 | + goto out; | ||
7868 | + | ||
7869 | + /* check of old_dentry branch is writable */ | ||
7870 | + err = is_robranch_super(old_dentry->d_sb, bindex); | ||
7871 | + if (err) | ||
7872 | + goto out; | ||
7873 | + | ||
7874 | + dget(lower_old_dentry); | ||
7875 | + dget(lower_new_dentry); | ||
7876 | + lower_old_dir_dentry = dget_parent(lower_old_dentry); | ||
7877 | + lower_new_dir_dentry = dget_parent(lower_new_dentry); | ||
7878 | + | ||
7879 | + trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); | ||
7880 | + /* source should not be ancenstor of target */ | ||
7881 | + if (trap == lower_old_dentry) { | ||
7882 | + err = -EINVAL; | ||
7883 | + goto out_err_unlock; | ||
7884 | + } | ||
7885 | + /* target should not be ancenstor of source */ | ||
7886 | + if (trap == lower_new_dentry) { | ||
7887 | + err = -ENOTEMPTY; | ||
7888 | + goto out_err_unlock; | ||
7889 | + } | ||
7890 | + err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry, | ||
7891 | + lower_new_dir_dentry->d_inode, lower_new_dentry); | ||
7892 | +out_err_unlock: | ||
7893 | + if (!err) { | ||
7894 | + /* update parent dir times */ | ||
7895 | + fsstack_copy_attr_times(old_dir, lower_old_dir_dentry->d_inode); | ||
7896 | + fsstack_copy_attr_times(new_dir, lower_new_dir_dentry->d_inode); | ||
7897 | + } | ||
7898 | + unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); | ||
7899 | + | ||
7900 | + dput(lower_old_dir_dentry); | ||
7901 | + dput(lower_new_dir_dentry); | ||
7902 | + dput(lower_old_dentry); | ||
7903 | + dput(lower_new_dentry); | ||
7904 | + | ||
7905 | +out: | ||
7906 | + if (!err) { | ||
7907 | + /* Fixup the new_dentry. */ | ||
7908 | + if (bindex < dbstart(new_dentry)) | ||
7909 | + dbstart(new_dentry) = bindex; | ||
7910 | + else if (bindex > dbend(new_dentry)) | ||
7911 | + dbend(new_dentry) = bindex; | ||
7912 | + } | ||
7913 | + | ||
7914 | + return err; | ||
7915 | +} | ||
7916 | + | ||
7917 | +/* | ||
7918 | + * Main rename code. This is sufficiently complex, that it's documented in | ||
7919 | + * Documentation/filesystems/unionfs/rename.txt. This routine calls | ||
7920 | + * __unionfs_rename() above to perform some of the work. | ||
7921 | + */ | ||
7922 | +static int do_unionfs_rename(struct inode *old_dir, | ||
7923 | + struct dentry *old_dentry, | ||
7924 | + struct dentry *old_parent, | ||
7925 | + struct inode *new_dir, | ||
7926 | + struct dentry *new_dentry, | ||
7927 | + struct dentry *new_parent) | ||
7928 | +{ | ||
7929 | + int err = 0; | ||
7930 | + int bindex; | ||
7931 | + int old_bstart, old_bend; | ||
7932 | + int new_bstart, new_bend; | ||
7933 | + int do_copyup = -1; | ||
7934 | + int local_err = 0; | ||
7935 | + int eio = 0; | ||
7936 | + int revert = 0; | ||
7937 | + | ||
7938 | + old_bstart = dbstart(old_dentry); | ||
7939 | + old_bend = dbend(old_dentry); | ||
7940 | + | ||
7941 | + new_bstart = dbstart(new_dentry); | ||
7942 | + new_bend = dbend(new_dentry); | ||
7943 | + | ||
7944 | + /* Rename source to destination. */ | ||
7945 | + err = __unionfs_rename(old_dir, old_dentry, old_parent, | ||
7946 | + new_dir, new_dentry, new_parent, | ||
7947 | + old_bstart); | ||
7948 | + if (err) { | ||
7949 | + if (!IS_COPYUP_ERR(err)) | ||
7950 | + goto out; | ||
7951 | + do_copyup = old_bstart - 1; | ||
7952 | + } else { | ||
7953 | + revert = 1; | ||
7954 | + } | ||
7955 | + | ||
7956 | + /* | ||
7957 | + * Unlink all instances of destination that exist to the left of | ||
7958 | + * bstart of source. On error, revert back, goto out. | ||
7959 | + */ | ||
7960 | + for (bindex = old_bstart - 1; bindex >= new_bstart; bindex--) { | ||
7961 | + struct dentry *unlink_dentry; | ||
7962 | + struct dentry *unlink_dir_dentry; | ||
7963 | + | ||
7964 | + BUG_ON(bindex < 0); | ||
7965 | + unlink_dentry = unionfs_lower_dentry_idx(new_dentry, bindex); | ||
7966 | + if (!unlink_dentry) | ||
7967 | + continue; | ||
7968 | + | ||
7969 | + unlink_dir_dentry = lock_parent(unlink_dentry); | ||
7970 | + err = is_robranch_super(old_dir->i_sb, bindex); | ||
7971 | + if (!err) | ||
7972 | + err = vfs_unlink(unlink_dir_dentry->d_inode, | ||
7973 | + unlink_dentry); | ||
7974 | + | ||
7975 | + fsstack_copy_attr_times(new_parent->d_inode, | ||
7976 | + unlink_dir_dentry->d_inode); | ||
7977 | + /* propagate number of hard-links */ | ||
7978 | + new_parent->d_inode->i_nlink = | ||
7979 | + unionfs_get_nlinks(new_parent->d_inode); | ||
7980 | + | ||
7981 | + unlock_dir(unlink_dir_dentry); | ||
7982 | + if (!err) { | ||
7983 | + if (bindex != new_bstart) { | ||
7984 | + dput(unlink_dentry); | ||
7985 | + unionfs_set_lower_dentry_idx(new_dentry, | ||
7986 | + bindex, NULL); | ||
7987 | + } | ||
7988 | + } else if (IS_COPYUP_ERR(err)) { | ||
7989 | + do_copyup = bindex - 1; | ||
7990 | + } else if (revert) { | ||
7991 | + goto revert; | ||
7992 | + } | ||
7993 | + } | ||
7994 | + | ||
7995 | + if (do_copyup != -1) { | ||
7996 | + for (bindex = do_copyup; bindex >= 0; bindex--) { | ||
7997 | + /* | ||
7998 | + * copyup the file into some left directory, so that | ||
7999 | + * you can rename it | ||
8000 | + */ | ||
8001 | + err = copyup_dentry(old_parent->d_inode, | ||
8002 | + old_dentry, old_bstart, bindex, | ||
8003 | + old_dentry->d_name.name, | ||
8004 | + old_dentry->d_name.len, NULL, | ||
8005 | + i_size_read(old_dentry->d_inode)); | ||
8006 | + /* if copyup failed, try next branch to the left */ | ||
8007 | + if (err) | ||
8008 | + continue; | ||
8009 | + /* | ||
8010 | + * create whiteout before calling __unionfs_rename | ||
8011 | + * because the latter will change the old_dentry's | ||
8012 | + * lower name and parent dir, resulting in the | ||
8013 | + * whiteout getting created in the wrong dir. | ||
8014 | + */ | ||
8015 | + err = create_whiteout(old_dentry, bindex); | ||
8016 | + if (err) { | ||
8017 | + printk(KERN_ERR "unionfs: can't create a " | ||
8018 | + "whiteout for %s in rename (err=%d)\n", | ||
8019 | + old_dentry->d_name.name, err); | ||
8020 | + continue; | ||
8021 | + } | ||
8022 | + err = __unionfs_rename(old_dir, old_dentry, old_parent, | ||
8023 | + new_dir, new_dentry, new_parent, | ||
8024 | + bindex); | ||
8025 | + break; | ||
8026 | + } | ||
8027 | + } | ||
8028 | + | ||
8029 | + /* make it opaque */ | ||
8030 | + if (S_ISDIR(old_dentry->d_inode->i_mode)) { | ||
8031 | + err = make_dir_opaque(old_dentry, dbstart(old_dentry)); | ||
8032 | + if (err) | ||
8033 | + goto revert; | ||
8034 | + } | ||
8035 | + | ||
8036 | + /* | ||
8037 | + * Create whiteout for source, only if: | ||
8038 | + * (1) There is more than one underlying instance of source. | ||
8039 | + * (We did a copy_up is taken care of above). | ||
8040 | + */ | ||
8041 | + if ((old_bstart != old_bend) && (do_copyup == -1)) { | ||
8042 | + err = create_whiteout(old_dentry, old_bstart); | ||
8043 | + if (err) { | ||
8044 | + /* can't fix anything now, so we exit with -EIO */ | ||
8045 | + printk(KERN_ERR "unionfs: can't create a whiteout for " | ||
8046 | + "%s in rename!\n", old_dentry->d_name.name); | ||
8047 | + err = -EIO; | ||
8048 | + } | ||
8049 | + } | ||
8050 | + | ||
8051 | +out: | ||
8052 | + return err; | ||
8053 | + | ||
8054 | +revert: | ||
8055 | + /* Do revert here. */ | ||
8056 | + local_err = unionfs_refresh_lower_dentry(new_dentry, new_parent, | ||
8057 | + old_bstart); | ||
8058 | + if (local_err) { | ||
8059 | + printk(KERN_ERR "unionfs: revert failed in rename: " | ||
8060 | + "the new refresh failed\n"); | ||
8061 | + eio = -EIO; | ||
8062 | + } | ||
8063 | + | ||
8064 | + local_err = unionfs_refresh_lower_dentry(old_dentry, old_parent, | ||
8065 | + old_bstart); | ||
8066 | + if (local_err) { | ||
8067 | + printk(KERN_ERR "unionfs: revert failed in rename: " | ||
8068 | + "the old refresh failed\n"); | ||
8069 | + eio = -EIO; | ||
8070 | + goto revert_out; | ||
8071 | + } | ||
8072 | + | ||
8073 | + if (!unionfs_lower_dentry_idx(new_dentry, bindex) || | ||
8074 | + !unionfs_lower_dentry_idx(new_dentry, bindex)->d_inode) { | ||
8075 | + printk(KERN_ERR "unionfs: revert failed in rename: " | ||
8076 | + "the object disappeared from under us!\n"); | ||
8077 | + eio = -EIO; | ||
8078 | + goto revert_out; | ||
8079 | + } | ||
8080 | + | ||
8081 | + if (unionfs_lower_dentry_idx(old_dentry, bindex) && | ||
8082 | + unionfs_lower_dentry_idx(old_dentry, bindex)->d_inode) { | ||
8083 | + printk(KERN_ERR "unionfs: revert failed in rename: " | ||
8084 | + "the object was created underneath us!\n"); | ||
8085 | + eio = -EIO; | ||
8086 | + goto revert_out; | ||
8087 | + } | ||
8088 | + | ||
8089 | + local_err = __unionfs_rename(new_dir, new_dentry, new_parent, | ||
8090 | + old_dir, old_dentry, old_parent, | ||
8091 | + old_bstart); | ||
8092 | + | ||
8093 | + /* If we can't fix it, then we cop-out with -EIO. */ | ||
8094 | + if (local_err) { | ||
8095 | + printk(KERN_ERR "unionfs: revert failed in rename!\n"); | ||
8096 | + eio = -EIO; | ||
8097 | + } | ||
8098 | + | ||
8099 | + local_err = unionfs_refresh_lower_dentry(new_dentry, new_parent, | ||
8100 | + bindex); | ||
8101 | + if (local_err) | ||
8102 | + eio = -EIO; | ||
8103 | + local_err = unionfs_refresh_lower_dentry(old_dentry, old_parent, | ||
8104 | + bindex); | ||
8105 | + if (local_err) | ||
8106 | + eio = -EIO; | ||
8107 | + | ||
8108 | +revert_out: | ||
8109 | + if (eio) | ||
8110 | + err = eio; | ||
8111 | + return err; | ||
8112 | +} | ||
8113 | + | ||
8114 | +/* | ||
8115 | + * We can't copyup a directory, because it may involve huge numbers of | ||
8116 | + * children, etc. Doing that in the kernel would be bad, so instead we | ||
8117 | + * return EXDEV to the user-space utility that caused this, and let the | ||
8118 | + * user-space recurse and ask us to copy up each file separately. | ||
8119 | + */ | ||
8120 | +static int may_rename_dir(struct dentry *dentry, struct dentry *parent) | ||
8121 | +{ | ||
8122 | + int err, bstart; | ||
8123 | + | ||
8124 | + err = check_empty(dentry, parent, NULL); | ||
8125 | + if (err == -ENOTEMPTY) { | ||
8126 | + if (is_robranch(dentry)) | ||
8127 | + return -EXDEV; | ||
8128 | + } else if (err) { | ||
8129 | + return err; | ||
8130 | + } | ||
8131 | + | ||
8132 | + bstart = dbstart(dentry); | ||
8133 | + if (dbend(dentry) == bstart || dbopaque(dentry) == bstart) | ||
8134 | + return 0; | ||
8135 | + | ||
8136 | + dbstart(dentry) = bstart + 1; | ||
8137 | + err = check_empty(dentry, parent, NULL); | ||
8138 | + dbstart(dentry) = bstart; | ||
8139 | + if (err == -ENOTEMPTY) | ||
8140 | + err = -EXDEV; | ||
8141 | + return err; | ||
8142 | +} | ||
8143 | + | ||
8144 | +/* | ||
8145 | + * The locking rules in unionfs_rename are complex. We could use a simpler | ||
8146 | + * superblock-level name-space lock for renames and copy-ups. | ||
8147 | + */ | ||
8148 | +int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry, | ||
8149 | + struct inode *new_dir, struct dentry *new_dentry) | ||
8150 | +{ | ||
8151 | + int err = 0; | ||
8152 | + struct dentry *wh_dentry; | ||
8153 | + struct dentry *old_parent, *new_parent; | ||
8154 | + int valid = true; | ||
8155 | + | ||
8156 | + unionfs_read_lock(old_dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
8157 | + old_parent = dget_parent(old_dentry); | ||
8158 | + new_parent = dget_parent(new_dentry); | ||
8159 | + /* un/lock parent dentries only if they differ from old/new_dentry */ | ||
8160 | + if (old_parent != old_dentry && | ||
8161 | + old_parent != new_dentry) | ||
8162 | + unionfs_lock_dentry(old_parent, UNIONFS_DMUTEX_REVAL_PARENT); | ||
8163 | + if (new_parent != old_dentry && | ||
8164 | + new_parent != new_dentry && | ||
8165 | + new_parent != old_parent) | ||
8166 | + unionfs_lock_dentry(new_parent, UNIONFS_DMUTEX_REVAL_CHILD); | ||
8167 | + unionfs_double_lock_dentry(old_dentry, new_dentry); | ||
8168 | + | ||
8169 | + valid = __unionfs_d_revalidate(old_dentry, old_parent, false); | ||
8170 | + if (!valid) { | ||
8171 | + err = -ESTALE; | ||
8172 | + goto out; | ||
8173 | + } | ||
8174 | + if (!d_deleted(new_dentry) && new_dentry->d_inode) { | ||
8175 | + valid = __unionfs_d_revalidate(new_dentry, new_parent, false); | ||
8176 | + if (!valid) { | ||
8177 | + err = -ESTALE; | ||
8178 | + goto out; | ||
8179 | + } | ||
8180 | + } | ||
8181 | + | ||
8182 | + if (!S_ISDIR(old_dentry->d_inode->i_mode)) | ||
8183 | + err = unionfs_partial_lookup(old_dentry, old_parent); | ||
8184 | + else | ||
8185 | + err = may_rename_dir(old_dentry, old_parent); | ||
8186 | + | ||
8187 | + if (err) | ||
8188 | + goto out; | ||
8189 | + | ||
8190 | + err = unionfs_partial_lookup(new_dentry, new_parent); | ||
8191 | + if (err) | ||
8192 | + goto out; | ||
8193 | + | ||
8194 | + /* | ||
8195 | + * if new_dentry is already lower because of whiteout, | ||
8196 | + * simply override it even if the whited-out dir is not empty. | ||
8197 | + */ | ||
8198 | + wh_dentry = find_first_whiteout(new_dentry); | ||
8199 | + if (!IS_ERR(wh_dentry)) { | ||
8200 | + dput(wh_dentry); | ||
8201 | + } else if (new_dentry->d_inode) { | ||
8202 | + if (S_ISDIR(old_dentry->d_inode->i_mode) != | ||
8203 | + S_ISDIR(new_dentry->d_inode->i_mode)) { | ||
8204 | + err = S_ISDIR(old_dentry->d_inode->i_mode) ? | ||
8205 | + -ENOTDIR : -EISDIR; | ||
8206 | + goto out; | ||
8207 | + } | ||
8208 | + | ||
8209 | + if (S_ISDIR(new_dentry->d_inode->i_mode)) { | ||
8210 | + struct unionfs_dir_state *namelist = NULL; | ||
8211 | + /* check if this unionfs directory is empty or not */ | ||
8212 | + err = check_empty(new_dentry, new_parent, &namelist); | ||
8213 | + if (err) | ||
8214 | + goto out; | ||
8215 | + | ||
8216 | + if (!is_robranch(new_dentry)) | ||
8217 | + err = delete_whiteouts(new_dentry, | ||
8218 | + dbstart(new_dentry), | ||
8219 | + namelist); | ||
8220 | + | ||
8221 | + free_rdstate(namelist); | ||
8222 | + | ||
8223 | + if (err) | ||
8224 | + goto out; | ||
8225 | + } | ||
8226 | + } | ||
8227 | + | ||
8228 | + err = do_unionfs_rename(old_dir, old_dentry, old_parent, | ||
8229 | + new_dir, new_dentry, new_parent); | ||
8230 | + if (err) | ||
8231 | + goto out; | ||
8232 | + | ||
8233 | + /* | ||
8234 | + * force re-lookup since the dir on ro branch is not renamed, and | ||
8235 | + * lower dentries still indicate the un-renamed ones. | ||
8236 | + */ | ||
8237 | + if (S_ISDIR(old_dentry->d_inode->i_mode)) | ||
8238 | + atomic_dec(&UNIONFS_D(old_dentry)->generation); | ||
8239 | + else | ||
8240 | + unionfs_postcopyup_release(old_dentry); | ||
8241 | + if (new_dentry->d_inode && !S_ISDIR(new_dentry->d_inode->i_mode)) { | ||
8242 | + unionfs_postcopyup_release(new_dentry); | ||
8243 | + unionfs_postcopyup_setmnt(new_dentry); | ||
8244 | + if (!unionfs_lower_inode(new_dentry->d_inode)) { | ||
8245 | + /* | ||
8246 | + * If we get here, it means that no copyup was | ||
8247 | + * needed, and that a file by the old name already | ||
8248 | + * existing on the destination branch; that file got | ||
8249 | + * renamed earlier in this function, so all we need | ||
8250 | + * to do here is set the lower inode. | ||
8251 | + */ | ||
8252 | + struct inode *inode; | ||
8253 | + inode = unionfs_lower_inode(old_dentry->d_inode); | ||
8254 | + igrab(inode); | ||
8255 | + unionfs_set_lower_inode_idx(new_dentry->d_inode, | ||
8256 | + dbstart(new_dentry), | ||
8257 | + inode); | ||
8258 | + } | ||
8259 | + } | ||
8260 | + /* if all of this renaming succeeded, update our times */ | ||
8261 | + unionfs_copy_attr_times(old_dentry->d_inode); | ||
8262 | + unionfs_copy_attr_times(new_dentry->d_inode); | ||
8263 | + unionfs_check_inode(old_dir); | ||
8264 | + unionfs_check_inode(new_dir); | ||
8265 | + unionfs_check_dentry(old_dentry); | ||
8266 | + unionfs_check_dentry(new_dentry); | ||
8267 | + | ||
8268 | +out: | ||
8269 | + if (err) /* clear the new_dentry stuff created */ | ||
8270 | + d_drop(new_dentry); | ||
8271 | + | ||
8272 | + unionfs_double_unlock_dentry(old_dentry, new_dentry); | ||
8273 | + if (new_parent != old_dentry && | ||
8274 | + new_parent != new_dentry && | ||
8275 | + new_parent != old_parent) | ||
8276 | + unionfs_unlock_dentry(new_parent); | ||
8277 | + if (old_parent != old_dentry && | ||
8278 | + old_parent != new_dentry) | ||
8279 | + unionfs_unlock_dentry(old_parent); | ||
8280 | + dput(new_parent); | ||
8281 | + dput(old_parent); | ||
8282 | + unionfs_read_unlock(old_dentry->d_sb); | ||
8283 | + | ||
8284 | + return err; | ||
8285 | +} | ||
8286 | diff --git a/fs/unionfs/sioq.c b/fs/unionfs/sioq.c | ||
8287 | new file mode 100644 | ||
8288 | index 0000000..b923742 | ||
8289 | --- /dev/null | ||
8290 | +++ b/fs/unionfs/sioq.c | ||
8291 | @@ -0,0 +1,101 @@ | ||
8292 | +/* | ||
8293 | + * Copyright (c) 2006-2011 Erez Zadok | ||
8294 | + * Copyright (c) 2006 Charles P. Wright | ||
8295 | + * Copyright (c) 2006-2007 Josef 'Jeff' Sipek | ||
8296 | + * Copyright (c) 2006 Junjiro Okajima | ||
8297 | + * Copyright (c) 2006 David P. Quigley | ||
8298 | + * Copyright (c) 2006-2011 Stony Brook University | ||
8299 | + * Copyright (c) 2006-2011 The Research Foundation of SUNY | ||
8300 | + * | ||
8301 | + * This program is free software; you can redistribute it and/or modify | ||
8302 | + * it under the terms of the GNU General Public License version 2 as | ||
8303 | + * published by the Free Software Foundation. | ||
8304 | + */ | ||
8305 | + | ||
8306 | +#include "union.h" | ||
8307 | + | ||
8308 | +/* | ||
8309 | + * Super-user IO work Queue - sometimes we need to perform actions which | ||
8310 | + * would fail due to the unix permissions on the parent directory (e.g., | ||
8311 | + * rmdir a directory which appears empty, but in reality contains | ||
8312 | + * whiteouts). | ||
8313 | + */ | ||
8314 | + | ||
8315 | +static struct workqueue_struct *superio_workqueue; | ||
8316 | + | ||
8317 | +int __init init_sioq(void) | ||
8318 | +{ | ||
8319 | + int err; | ||
8320 | + | ||
8321 | + superio_workqueue = create_workqueue("unionfs_siod"); | ||
8322 | + if (!IS_ERR(superio_workqueue)) | ||
8323 | + return 0; | ||
8324 | + | ||
8325 | + err = PTR_ERR(superio_workqueue); | ||
8326 | + printk(KERN_ERR "unionfs: create_workqueue failed %d\n", err); | ||
8327 | + superio_workqueue = NULL; | ||
8328 | + return err; | ||
8329 | +} | ||
8330 | + | ||
8331 | +void stop_sioq(void) | ||
8332 | +{ | ||
8333 | + if (superio_workqueue) | ||
8334 | + destroy_workqueue(superio_workqueue); | ||
8335 | +} | ||
8336 | + | ||
8337 | +void run_sioq(work_func_t func, struct sioq_args *args) | ||
8338 | +{ | ||
8339 | + INIT_WORK(&args->work, func); | ||
8340 | + | ||
8341 | + init_completion(&args->comp); | ||
8342 | + while (!queue_work(superio_workqueue, &args->work)) { | ||
8343 | + /* TODO: do accounting if needed */ | ||
8344 | + schedule(); | ||
8345 | + } | ||
8346 | + wait_for_completion(&args->comp); | ||
8347 | +} | ||
8348 | + | ||
8349 | +void __unionfs_create(struct work_struct *work) | ||
8350 | +{ | ||
8351 | + struct sioq_args *args = container_of(work, struct sioq_args, work); | ||
8352 | + struct create_args *c = &args->create; | ||
8353 | + | ||
8354 | + args->err = vfs_create(c->parent, c->dentry, c->mode, c->nd); | ||
8355 | + complete(&args->comp); | ||
8356 | +} | ||
8357 | + | ||
8358 | +void __unionfs_mkdir(struct work_struct *work) | ||
8359 | +{ | ||
8360 | + struct sioq_args *args = container_of(work, struct sioq_args, work); | ||
8361 | + struct mkdir_args *m = &args->mkdir; | ||
8362 | + | ||
8363 | + args->err = vfs_mkdir(m->parent, m->dentry, m->mode); | ||
8364 | + complete(&args->comp); | ||
8365 | +} | ||
8366 | + | ||
8367 | +void __unionfs_mknod(struct work_struct *work) | ||
8368 | +{ | ||
8369 | + struct sioq_args *args = container_of(work, struct sioq_args, work); | ||
8370 | + struct mknod_args *m = &args->mknod; | ||
8371 | + | ||
8372 | + args->err = vfs_mknod(m->parent, m->dentry, m->mode, m->dev); | ||
8373 | + complete(&args->comp); | ||
8374 | +} | ||
8375 | + | ||
8376 | +void __unionfs_symlink(struct work_struct *work) | ||
8377 | +{ | ||
8378 | + struct sioq_args *args = container_of(work, struct sioq_args, work); | ||
8379 | + struct symlink_args *s = &args->symlink; | ||
8380 | + | ||
8381 | + args->err = vfs_symlink(s->parent, s->dentry, s->symbuf); | ||
8382 | + complete(&args->comp); | ||
8383 | +} | ||
8384 | + | ||
8385 | +void __unionfs_unlink(struct work_struct *work) | ||
8386 | +{ | ||
8387 | + struct sioq_args *args = container_of(work, struct sioq_args, work); | ||
8388 | + struct unlink_args *u = &args->unlink; | ||
8389 | + | ||
8390 | + args->err = vfs_unlink(u->parent, u->dentry); | ||
8391 | + complete(&args->comp); | ||
8392 | +} | ||
8393 | diff --git a/fs/unionfs/sioq.h b/fs/unionfs/sioq.h | ||
8394 | new file mode 100644 | ||
8395 | index 0000000..c2dfb94 | ||
8396 | --- /dev/null | ||
8397 | +++ b/fs/unionfs/sioq.h | ||
8398 | @@ -0,0 +1,91 @@ | ||
8399 | +/* | ||
8400 | + * Copyright (c) 2006-2011 Erez Zadok | ||
8401 | + * Copyright (c) 2006 Charles P. Wright | ||
8402 | + * Copyright (c) 2006-2007 Josef 'Jeff' Sipek | ||
8403 | + * Copyright (c) 2006 Junjiro Okajima | ||
8404 | + * Copyright (c) 2006 David P. Quigley | ||
8405 | + * Copyright (c) 2006-2011 Stony Brook University | ||
8406 | + * Copyright (c) 2006-2011 The Research Foundation of SUNY | ||
8407 | + * | ||
8408 | + * This program is free software; you can redistribute it and/or modify | ||
8409 | + * it under the terms of the GNU General Public License version 2 as | ||
8410 | + * published by the Free Software Foundation. | ||
8411 | + */ | ||
8412 | + | ||
8413 | +#ifndef _SIOQ_H | ||
8414 | +#define _SIOQ_H | ||
8415 | + | ||
8416 | +struct deletewh_args { | ||
8417 | + struct unionfs_dir_state *namelist; | ||
8418 | + struct dentry *dentry; | ||
8419 | + int bindex; | ||
8420 | +}; | ||
8421 | + | ||
8422 | +struct is_opaque_args { | ||
8423 | + struct dentry *dentry; | ||
8424 | +}; | ||
8425 | + | ||
8426 | +struct create_args { | ||
8427 | + struct inode *parent; | ||
8428 | + struct dentry *dentry; | ||
8429 | + umode_t mode; | ||
8430 | + struct nameidata *nd; | ||
8431 | +}; | ||
8432 | + | ||
8433 | +struct mkdir_args { | ||
8434 | + struct inode *parent; | ||
8435 | + struct dentry *dentry; | ||
8436 | + umode_t mode; | ||
8437 | +}; | ||
8438 | + | ||
8439 | +struct mknod_args { | ||
8440 | + struct inode *parent; | ||
8441 | + struct dentry *dentry; | ||
8442 | + umode_t mode; | ||
8443 | + dev_t dev; | ||
8444 | +}; | ||
8445 | + | ||
8446 | +struct symlink_args { | ||
8447 | + struct inode *parent; | ||
8448 | + struct dentry *dentry; | ||
8449 | + char *symbuf; | ||
8450 | +}; | ||
8451 | + | ||
8452 | +struct unlink_args { | ||
8453 | + struct inode *parent; | ||
8454 | + struct dentry *dentry; | ||
8455 | +}; | ||
8456 | + | ||
8457 | + | ||
8458 | +struct sioq_args { | ||
8459 | + struct completion comp; | ||
8460 | + struct work_struct work; | ||
8461 | + int err; | ||
8462 | + void *ret; | ||
8463 | + | ||
8464 | + union { | ||
8465 | + struct deletewh_args deletewh; | ||
8466 | + struct is_opaque_args is_opaque; | ||
8467 | + struct create_args create; | ||
8468 | + struct mkdir_args mkdir; | ||
8469 | + struct mknod_args mknod; | ||
8470 | + struct symlink_args symlink; | ||
8471 | + struct unlink_args unlink; | ||
8472 | + }; | ||
8473 | +}; | ||
8474 | + | ||
8475 | +/* Extern definitions for SIOQ functions */ | ||
8476 | +extern int __init init_sioq(void); | ||
8477 | +extern void stop_sioq(void); | ||
8478 | +extern void run_sioq(work_func_t func, struct sioq_args *args); | ||
8479 | + | ||
8480 | +/* Extern definitions for our privilege escalation helpers */ | ||
8481 | +extern void __unionfs_create(struct work_struct *work); | ||
8482 | +extern void __unionfs_mkdir(struct work_struct *work); | ||
8483 | +extern void __unionfs_mknod(struct work_struct *work); | ||
8484 | +extern void __unionfs_symlink(struct work_struct *work); | ||
8485 | +extern void __unionfs_unlink(struct work_struct *work); | ||
8486 | +extern void __delete_whiteouts(struct work_struct *work); | ||
8487 | +extern void __is_opaque_dir(struct work_struct *work); | ||
8488 | + | ||
8489 | +#endif /* not _SIOQ_H */ | ||
8490 | diff --git a/fs/unionfs/subr.c b/fs/unionfs/subr.c | ||
8491 | new file mode 100644 | ||
8492 | index 0000000..bdca2f7 | ||
8493 | --- /dev/null | ||
8494 | +++ b/fs/unionfs/subr.c | ||
8495 | @@ -0,0 +1,95 @@ | ||
8496 | +/* | ||
8497 | + * Copyright (c) 2003-2011 Erez Zadok | ||
8498 | + * Copyright (c) 2003-2006 Charles P. Wright | ||
8499 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
8500 | + * Copyright (c) 2005-2006 Junjiro Okajima | ||
8501 | + * Copyright (c) 2005 Arun M. Krishnakumar | ||
8502 | + * Copyright (c) 2004-2006 David P. Quigley | ||
8503 | + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair | ||
8504 | + * Copyright (c) 2003 Puja Gupta | ||
8505 | + * Copyright (c) 2003 Harikesavan Krishnan | ||
8506 | + * Copyright (c) 2003-2011 Stony Brook University | ||
8507 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
8508 | + * | ||
8509 | + * This program is free software; you can redistribute it and/or modify | ||
8510 | + * it under the terms of the GNU General Public License version 2 as | ||
8511 | + * published by the Free Software Foundation. | ||
8512 | + */ | ||
8513 | + | ||
8514 | +#include "union.h" | ||
8515 | + | ||
8516 | +/* | ||
8517 | + * returns the right n_link value based on the inode type | ||
8518 | + */ | ||
8519 | +int unionfs_get_nlinks(const struct inode *inode) | ||
8520 | +{ | ||
8521 | + /* don't bother to do all the work since we're unlinked */ | ||
8522 | + if (inode->i_nlink == 0) | ||
8523 | + return 0; | ||
8524 | + | ||
8525 | + if (!S_ISDIR(inode->i_mode)) | ||
8526 | + return unionfs_lower_inode(inode)->i_nlink; | ||
8527 | + | ||
8528 | + /* | ||
8529 | + * For directories, we return 1. The only place that could cares | ||
8530 | + * about links is readdir, and there's d_type there so even that | ||
8531 | + * doesn't matter. | ||
8532 | + */ | ||
8533 | + return 1; | ||
8534 | +} | ||
8535 | + | ||
8536 | +/* copy a/m/ctime from the lower branch with the newest times */ | ||
8537 | +void unionfs_copy_attr_times(struct inode *upper) | ||
8538 | +{ | ||
8539 | + int bindex; | ||
8540 | + struct inode *lower; | ||
8541 | + | ||
8542 | + if (!upper) | ||
8543 | + return; | ||
8544 | + if (ibstart(upper) < 0) { | ||
8545 | +#ifdef CONFIG_UNION_FS_DEBUG | ||
8546 | + WARN_ON(ibstart(upper) < 0); | ||
8547 | +#endif /* CONFIG_UNION_FS_DEBUG */ | ||
8548 | + return; | ||
8549 | + } | ||
8550 | + for (bindex = ibstart(upper); bindex <= ibend(upper); bindex++) { | ||
8551 | + lower = unionfs_lower_inode_idx(upper, bindex); | ||
8552 | + if (!lower) | ||
8553 | + continue; /* not all lower dir objects may exist */ | ||
8554 | + if (unlikely(timespec_compare(&upper->i_mtime, | ||
8555 | + &lower->i_mtime) < 0)) | ||
8556 | + upper->i_mtime = lower->i_mtime; | ||
8557 | + if (unlikely(timespec_compare(&upper->i_ctime, | ||
8558 | + &lower->i_ctime) < 0)) | ||
8559 | + upper->i_ctime = lower->i_ctime; | ||
8560 | + if (unlikely(timespec_compare(&upper->i_atime, | ||
8561 | + &lower->i_atime) < 0)) | ||
8562 | + upper->i_atime = lower->i_atime; | ||
8563 | + } | ||
8564 | +} | ||
8565 | + | ||
8566 | +/* | ||
8567 | + * A unionfs/fanout version of fsstack_copy_attr_all. Uses a | ||
8568 | + * unionfs_get_nlinks to properly calcluate the number of links to a file. | ||
8569 | + * Also, copies the max() of all a/m/ctimes for all lower inodes (which is | ||
8570 | + * important if the lower inode is a directory type) | ||
8571 | + */ | ||
8572 | +void unionfs_copy_attr_all(struct inode *dest, | ||
8573 | + const struct inode *src) | ||
8574 | +{ | ||
8575 | + dest->i_mode = src->i_mode; | ||
8576 | + dest->i_uid = src->i_uid; | ||
8577 | + dest->i_gid = src->i_gid; | ||
8578 | + dest->i_rdev = src->i_rdev; | ||
8579 | + | ||
8580 | + unionfs_copy_attr_times(dest); | ||
8581 | + | ||
8582 | + dest->i_blkbits = src->i_blkbits; | ||
8583 | + dest->i_flags = src->i_flags; | ||
8584 | + | ||
8585 | + /* | ||
8586 | + * Update the nlinks AFTER updating the above fields, because the | ||
8587 | + * get_links callback may depend on them. | ||
8588 | + */ | ||
8589 | + dest->i_nlink = unionfs_get_nlinks(dest); | ||
8590 | +} | ||
8591 | diff --git a/fs/unionfs/super.c b/fs/unionfs/super.c | ||
8592 | new file mode 100644 | ||
8593 | index 0000000..c3ac814 | ||
8594 | --- /dev/null | ||
8595 | +++ b/fs/unionfs/super.c | ||
8596 | @@ -0,0 +1,1030 @@ | ||
8597 | +/* | ||
8598 | + * Copyright (c) 2003-2011 Erez Zadok | ||
8599 | + * Copyright (c) 2003-2006 Charles P. Wright | ||
8600 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
8601 | + * Copyright (c) 2005-2006 Junjiro Okajima | ||
8602 | + * Copyright (c) 2005 Arun M. Krishnakumar | ||
8603 | + * Copyright (c) 2004-2006 David P. Quigley | ||
8604 | + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair | ||
8605 | + * Copyright (c) 2003 Puja Gupta | ||
8606 | + * Copyright (c) 2003 Harikesavan Krishnan | ||
8607 | + * Copyright (c) 2003-2011 Stony Brook University | ||
8608 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
8609 | + * | ||
8610 | + * This program is free software; you can redistribute it and/or modify | ||
8611 | + * it under the terms of the GNU General Public License version 2 as | ||
8612 | + * published by the Free Software Foundation. | ||
8613 | + */ | ||
8614 | + | ||
8615 | +#include "union.h" | ||
8616 | + | ||
8617 | +/* | ||
8618 | + * The inode cache is used with alloc_inode for both our inode info and the | ||
8619 | + * vfs inode. | ||
8620 | + */ | ||
8621 | +static struct kmem_cache *unionfs_inode_cachep; | ||
8622 | + | ||
8623 | +struct inode *unionfs_iget(struct super_block *sb, unsigned long ino) | ||
8624 | +{ | ||
8625 | + int size; | ||
8626 | + struct unionfs_inode_info *info; | ||
8627 | + struct inode *inode; | ||
8628 | + | ||
8629 | + inode = iget_locked(sb, ino); | ||
8630 | + if (!inode) | ||
8631 | + return ERR_PTR(-ENOMEM); | ||
8632 | + if (!(inode->i_state & I_NEW)) | ||
8633 | + return inode; | ||
8634 | + | ||
8635 | + info = UNIONFS_I(inode); | ||
8636 | + memset(info, 0, offsetof(struct unionfs_inode_info, vfs_inode)); | ||
8637 | + info->bstart = -1; | ||
8638 | + info->bend = -1; | ||
8639 | + atomic_set(&info->generation, | ||
8640 | + atomic_read(&UNIONFS_SB(inode->i_sb)->generation)); | ||
8641 | + spin_lock_init(&info->rdlock); | ||
8642 | + info->rdcount = 1; | ||
8643 | + info->hashsize = -1; | ||
8644 | + INIT_LIST_HEAD(&info->readdircache); | ||
8645 | + | ||
8646 | + size = sbmax(inode->i_sb) * sizeof(struct inode *); | ||
8647 | + info->lower_inodes = kzalloc(size, GFP_KERNEL); | ||
8648 | + if (unlikely(!info->lower_inodes)) { | ||
8649 | + printk(KERN_CRIT "unionfs: no kernel memory when allocating " | ||
8650 | + "lower-pointer array!\n"); | ||
8651 | + iget_failed(inode); | ||
8652 | + return ERR_PTR(-ENOMEM); | ||
8653 | + } | ||
8654 | + | ||
8655 | + inode->i_version++; | ||
8656 | + inode->i_op = &unionfs_main_iops; | ||
8657 | + inode->i_fop = &unionfs_main_fops; | ||
8658 | + | ||
8659 | + inode->i_mapping->a_ops = &unionfs_aops; | ||
8660 | + | ||
8661 | + /* | ||
8662 | + * reset times so unionfs_copy_attr_all can keep out time invariants | ||
8663 | + * right (upper inode time being the max of all lower ones). | ||
8664 | + */ | ||
8665 | + inode->i_atime.tv_sec = inode->i_atime.tv_nsec = 0; | ||
8666 | + inode->i_mtime.tv_sec = inode->i_mtime.tv_nsec = 0; | ||
8667 | + inode->i_ctime.tv_sec = inode->i_ctime.tv_nsec = 0; | ||
8668 | + unlock_new_inode(inode); | ||
8669 | + return inode; | ||
8670 | +} | ||
8671 | + | ||
8672 | +/* | ||
8673 | + * final actions when unmounting a file system | ||
8674 | + * | ||
8675 | + * No need to lock rwsem. | ||
8676 | + */ | ||
8677 | +static void unionfs_put_super(struct super_block *sb) | ||
8678 | +{ | ||
8679 | + int bindex, bstart, bend; | ||
8680 | + struct unionfs_sb_info *spd; | ||
8681 | + int leaks = 0; | ||
8682 | + | ||
8683 | + spd = UNIONFS_SB(sb); | ||
8684 | + if (!spd) | ||
8685 | + return; | ||
8686 | + | ||
8687 | + bstart = sbstart(sb); | ||
8688 | + bend = sbend(sb); | ||
8689 | + | ||
8690 | + /* Make sure we have no leaks of branchget/branchput. */ | ||
8691 | + for (bindex = bstart; bindex <= bend; bindex++) | ||
8692 | + if (unlikely(branch_count(sb, bindex) != 0)) { | ||
8693 | + printk(KERN_CRIT | ||
8694 | + "unionfs: branch %d has %d references left!\n", | ||
8695 | + bindex, branch_count(sb, bindex)); | ||
8696 | + leaks = 1; | ||
8697 | + } | ||
8698 | + WARN_ON(leaks != 0); | ||
8699 | + | ||
8700 | + /* decrement lower super references */ | ||
8701 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
8702 | + struct super_block *s; | ||
8703 | + s = unionfs_lower_super_idx(sb, bindex); | ||
8704 | + unionfs_set_lower_super_idx(sb, bindex, NULL); | ||
8705 | + atomic_dec(&s->s_active); | ||
8706 | + } | ||
8707 | + | ||
8708 | + kfree(spd->dev_name); | ||
8709 | + kfree(spd->data); | ||
8710 | + kfree(spd); | ||
8711 | + sb->s_fs_info = NULL; | ||
8712 | +} | ||
8713 | + | ||
8714 | +/* | ||
8715 | + * Since people use this to answer the "How big of a file can I write?" | ||
8716 | + * question, we report the size of the highest priority branch as the size of | ||
8717 | + * the union. | ||
8718 | + */ | ||
8719 | +static int unionfs_statfs(struct dentry *dentry, struct kstatfs *buf) | ||
8720 | +{ | ||
8721 | + int err = 0; | ||
8722 | + struct super_block *sb; | ||
8723 | + struct dentry *lower_dentry; | ||
8724 | + struct dentry *parent; | ||
8725 | + struct path lower_path; | ||
8726 | + bool valid; | ||
8727 | + | ||
8728 | + sb = dentry->d_sb; | ||
8729 | + | ||
8730 | + unionfs_read_lock(sb, UNIONFS_SMUTEX_CHILD); | ||
8731 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
8732 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
8733 | + | ||
8734 | + valid = __unionfs_d_revalidate(dentry, parent, false); | ||
8735 | + if (unlikely(!valid)) { | ||
8736 | + err = -ESTALE; | ||
8737 | + goto out; | ||
8738 | + } | ||
8739 | + unionfs_check_dentry(dentry); | ||
8740 | + | ||
8741 | + lower_dentry = unionfs_lower_dentry(sb->s_root); | ||
8742 | + lower_path.dentry = lower_dentry; | ||
8743 | + lower_path.mnt = unionfs_mntget(sb->s_root, 0); | ||
8744 | + err = vfs_statfs(&lower_path, buf); | ||
8745 | + mntput(lower_path.mnt); | ||
8746 | + | ||
8747 | + /* set return buf to our f/s to avoid confusing user-level utils */ | ||
8748 | + buf->f_type = UNIONFS_SUPER_MAGIC; | ||
8749 | + /* | ||
8750 | + * Our maximum file name can is shorter by a few bytes because every | ||
8751 | + * file name could potentially be whited-out. | ||
8752 | + * | ||
8753 | + * XXX: this restriction goes away with ODF. | ||
8754 | + */ | ||
8755 | + unionfs_set_max_namelen(&buf->f_namelen); | ||
8756 | + | ||
8757 | + /* | ||
8758 | + * reset two fields to avoid confusing user-land. | ||
8759 | + * XXX: is this still necessary? | ||
8760 | + */ | ||
8761 | + memset(&buf->f_fsid, 0, sizeof(__kernel_fsid_t)); | ||
8762 | + memset(&buf->f_spare, 0, sizeof(buf->f_spare)); | ||
8763 | + | ||
8764 | +out: | ||
8765 | + unionfs_check_dentry(dentry); | ||
8766 | + unionfs_unlock_dentry(dentry); | ||
8767 | + unionfs_unlock_parent(dentry, parent); | ||
8768 | + unionfs_read_unlock(sb); | ||
8769 | + return err; | ||
8770 | +} | ||
8771 | + | ||
8772 | +/* handle mode changing during remount */ | ||
8773 | +static noinline_for_stack int do_remount_mode_option( | ||
8774 | + char *optarg, | ||
8775 | + int cur_branches, | ||
8776 | + struct unionfs_data *new_data, | ||
8777 | + struct path *new_lower_paths) | ||
8778 | +{ | ||
8779 | + int err = -EINVAL; | ||
8780 | + int perms, idx; | ||
8781 | + char *modename = strchr(optarg, '='); | ||
8782 | + struct path path; | ||
8783 | + | ||
8784 | + /* by now, optarg contains the branch name */ | ||
8785 | + if (!*optarg) { | ||
8786 | + printk(KERN_ERR | ||
8787 | + "unionfs: no branch specified for mode change\n"); | ||
8788 | + goto out; | ||
8789 | + } | ||
8790 | + if (!modename) { | ||
8791 | + printk(KERN_ERR "unionfs: branch \"%s\" requires a mode\n", | ||
8792 | + optarg); | ||
8793 | + goto out; | ||
8794 | + } | ||
8795 | + *modename++ = '\0'; | ||
8796 | + err = parse_branch_mode(modename, &perms); | ||
8797 | + if (err) { | ||
8798 | + printk(KERN_ERR "unionfs: invalid mode \"%s\" for \"%s\"\n", | ||
8799 | + modename, optarg); | ||
8800 | + goto out; | ||
8801 | + } | ||
8802 | + | ||
8803 | + /* | ||
8804 | + * Find matching branch index. For now, this assumes that nothing | ||
8805 | + * has been mounted on top of this Unionfs stack. Once we have /odf | ||
8806 | + * and cache-coherency resolved, we'll address the branch-path | ||
8807 | + * uniqueness. | ||
8808 | + */ | ||
8809 | + err = kern_path(optarg, LOOKUP_FOLLOW, &path); | ||
8810 | + if (err) { | ||
8811 | + printk(KERN_ERR "unionfs: error accessing " | ||
8812 | + "lower directory \"%s\" (error %d)\n", | ||
8813 | + optarg, err); | ||
8814 | + goto out; | ||
8815 | + } | ||
8816 | + for (idx = 0; idx < cur_branches; idx++) | ||
8817 | + if (path.mnt == new_lower_paths[idx].mnt && | ||
8818 | + path.dentry == new_lower_paths[idx].dentry) | ||
8819 | + break; | ||
8820 | + path_put(&path); /* no longer needed */ | ||
8821 | + if (idx == cur_branches) { | ||
8822 | + err = -ENOENT; /* err may have been reset above */ | ||
8823 | + printk(KERN_ERR "unionfs: branch \"%s\" " | ||
8824 | + "not found\n", optarg); | ||
8825 | + goto out; | ||
8826 | + } | ||
8827 | + /* check/change mode for existing branch */ | ||
8828 | + /* we don't warn if perms==branchperms */ | ||
8829 | + new_data[idx].branchperms = perms; | ||
8830 | + err = 0; | ||
8831 | +out: | ||
8832 | + return err; | ||
8833 | +} | ||
8834 | + | ||
8835 | +/* handle branch deletion during remount */ | ||
8836 | +static noinline_for_stack int do_remount_del_option( | ||
8837 | + char *optarg, int cur_branches, | ||
8838 | + struct unionfs_data *new_data, | ||
8839 | + struct path *new_lower_paths) | ||
8840 | +{ | ||
8841 | + int err = -EINVAL; | ||
8842 | + int idx; | ||
8843 | + struct path path; | ||
8844 | + | ||
8845 | + /* optarg contains the branch name to delete */ | ||
8846 | + | ||
8847 | + /* | ||
8848 | + * Find matching branch index. For now, this assumes that nothing | ||
8849 | + * has been mounted on top of this Unionfs stack. Once we have /odf | ||
8850 | + * and cache-coherency resolved, we'll address the branch-path | ||
8851 | + * uniqueness. | ||
8852 | + */ | ||
8853 | + err = kern_path(optarg, LOOKUP_FOLLOW, &path); | ||
8854 | + if (err) { | ||
8855 | + printk(KERN_ERR "unionfs: error accessing " | ||
8856 | + "lower directory \"%s\" (error %d)\n", | ||
8857 | + optarg, err); | ||
8858 | + goto out; | ||
8859 | + } | ||
8860 | + for (idx = 0; idx < cur_branches; idx++) | ||
8861 | + if (path.mnt == new_lower_paths[idx].mnt && | ||
8862 | + path.dentry == new_lower_paths[idx].dentry) | ||
8863 | + break; | ||
8864 | + path_put(&path); /* no longer needed */ | ||
8865 | + if (idx == cur_branches) { | ||
8866 | + printk(KERN_ERR "unionfs: branch \"%s\" " | ||
8867 | + "not found\n", optarg); | ||
8868 | + err = -ENOENT; | ||
8869 | + goto out; | ||
8870 | + } | ||
8871 | + /* check if there are any open files on the branch to be deleted */ | ||
8872 | + if (atomic_read(&new_data[idx].open_files) > 0) { | ||
8873 | + err = -EBUSY; | ||
8874 | + goto out; | ||
8875 | + } | ||
8876 | + | ||
8877 | + /* | ||
8878 | + * Now we have to delete the branch. First, release any handles it | ||
8879 | + * has. Then, move the remaining array indexes past "idx" in | ||
8880 | + * new_data and new_lower_paths one to the left. Finally, adjust | ||
8881 | + * cur_branches. | ||
8882 | + */ | ||
8883 | + path_put(&new_lower_paths[idx]); | ||
8884 | + | ||
8885 | + if (idx < cur_branches - 1) { | ||
8886 | + /* if idx==cur_branches-1, we delete last branch: easy */ | ||
8887 | + memmove(&new_data[idx], &new_data[idx+1], | ||
8888 | + (cur_branches - 1 - idx) * | ||
8889 | + sizeof(struct unionfs_data)); | ||
8890 | + memmove(&new_lower_paths[idx], &new_lower_paths[idx+1], | ||
8891 | + (cur_branches - 1 - idx) * sizeof(struct path)); | ||
8892 | + } | ||
8893 | + | ||
8894 | + err = 0; | ||
8895 | +out: | ||
8896 | + return err; | ||
8897 | +} | ||
8898 | + | ||
8899 | +/* handle branch insertion during remount */ | ||
8900 | +static noinline_for_stack int do_remount_add_option( | ||
8901 | + char *optarg, int cur_branches, | ||
8902 | + struct unionfs_data *new_data, | ||
8903 | + struct path *new_lower_paths, | ||
8904 | + int *high_branch_id) | ||
8905 | +{ | ||
8906 | + int err = -EINVAL; | ||
8907 | + int perms; | ||
8908 | + int idx = 0; /* default: insert at beginning */ | ||
8909 | + char *new_branch , *modename = NULL; | ||
8910 | + struct path path; | ||
8911 | + | ||
8912 | + /* | ||
8913 | + * optarg can be of several forms: | ||
8914 | + * | ||
8915 | + * /bar:/foo insert /foo before /bar | ||
8916 | + * /bar:/foo=ro insert /foo in ro mode before /bar | ||
8917 | + * /foo insert /foo in the beginning (prepend) | ||
8918 | + * :/foo insert /foo at the end (append) | ||
8919 | + */ | ||
8920 | + if (*optarg == ':') { /* append? */ | ||
8921 | + new_branch = optarg + 1; /* skip ':' */ | ||
8922 | + idx = cur_branches; | ||
8923 | + goto found_insertion_point; | ||
8924 | + } | ||
8925 | + new_branch = strchr(optarg, ':'); | ||
8926 | + if (!new_branch) { /* prepend? */ | ||
8927 | + new_branch = optarg; | ||
8928 | + goto found_insertion_point; | ||
8929 | + } | ||
8930 | + *new_branch++ = '\0'; /* holds path+mode of new branch */ | ||
8931 | + | ||
8932 | + /* | ||
8933 | + * Find matching branch index. For now, this assumes that nothing | ||
8934 | + * has been mounted on top of this Unionfs stack. Once we have /odf | ||
8935 | + * and cache-coherency resolved, we'll address the branch-path | ||
8936 | + * uniqueness. | ||
8937 | + */ | ||
8938 | + err = kern_path(optarg, LOOKUP_FOLLOW, &path); | ||
8939 | + if (err) { | ||
8940 | + printk(KERN_ERR "unionfs: error accessing " | ||
8941 | + "lower directory \"%s\" (error %d)\n", | ||
8942 | + optarg, err); | ||
8943 | + goto out; | ||
8944 | + } | ||
8945 | + for (idx = 0; idx < cur_branches; idx++) | ||
8946 | + if (path.mnt == new_lower_paths[idx].mnt && | ||
8947 | + path.dentry == new_lower_paths[idx].dentry) | ||
8948 | + break; | ||
8949 | + path_put(&path); /* no longer needed */ | ||
8950 | + if (idx == cur_branches) { | ||
8951 | + printk(KERN_ERR "unionfs: branch \"%s\" " | ||
8952 | + "not found\n", optarg); | ||
8953 | + err = -ENOENT; | ||
8954 | + goto out; | ||
8955 | + } | ||
8956 | + | ||
8957 | + /* | ||
8958 | + * At this point idx will hold the index where the new branch should | ||
8959 | + * be inserted before. | ||
8960 | + */ | ||
8961 | +found_insertion_point: | ||
8962 | + /* find the mode for the new branch */ | ||
8963 | + if (new_branch) | ||
8964 | + modename = strchr(new_branch, '='); | ||
8965 | + if (modename) | ||
8966 | + *modename++ = '\0'; | ||
8967 | + if (!new_branch || !*new_branch) { | ||
8968 | + printk(KERN_ERR "unionfs: null new branch\n"); | ||
8969 | + err = -EINVAL; | ||
8970 | + goto out; | ||
8971 | + } | ||
8972 | + err = parse_branch_mode(modename, &perms); | ||
8973 | + if (err) { | ||
8974 | + printk(KERN_ERR "unionfs: invalid mode \"%s\" for " | ||
8975 | + "branch \"%s\"\n", modename, new_branch); | ||
8976 | + goto out; | ||
8977 | + } | ||
8978 | + err = kern_path(new_branch, LOOKUP_FOLLOW, &path); | ||
8979 | + if (err) { | ||
8980 | + printk(KERN_ERR "unionfs: error accessing " | ||
8981 | + "lower directory \"%s\" (error %d)\n", | ||
8982 | + new_branch, err); | ||
8983 | + goto out; | ||
8984 | + } | ||
8985 | + /* | ||
8986 | + * It's probably safe to check_mode the new branch to insert. Note: | ||
8987 | + * we don't allow inserting branches which are unionfs's by | ||
8988 | + * themselves (check_branch returns EINVAL in that case). This is | ||
8989 | + * because this code base doesn't support stacking unionfs: the ODF | ||
8990 | + * code base supports that correctly. | ||
8991 | + */ | ||
8992 | + err = check_branch(&path); | ||
8993 | + if (err) { | ||
8994 | + printk(KERN_ERR "unionfs: lower directory " | ||
8995 | + "\"%s\" is not a valid branch\n", optarg); | ||
8996 | + path_put(&path); | ||
8997 | + goto out; | ||
8998 | + } | ||
8999 | + | ||
9000 | + /* | ||
9001 | + * Now we have to insert the new branch. But first, move the bits | ||
9002 | + * to make space for the new branch, if needed. Finally, adjust | ||
9003 | + * cur_branches. | ||
9004 | + * We don't release nd here; it's kept until umount/remount. | ||
9005 | + */ | ||
9006 | + if (idx < cur_branches) { | ||
9007 | + /* if idx==cur_branches, we append: easy */ | ||
9008 | + memmove(&new_data[idx+1], &new_data[idx], | ||
9009 | + (cur_branches - idx) * sizeof(struct unionfs_data)); | ||
9010 | + memmove(&new_lower_paths[idx+1], &new_lower_paths[idx], | ||
9011 | + (cur_branches - idx) * sizeof(struct path)); | ||
9012 | + } | ||
9013 | + new_lower_paths[idx].dentry = path.dentry; | ||
9014 | + new_lower_paths[idx].mnt = path.mnt; | ||
9015 | + | ||
9016 | + new_data[idx].sb = path.dentry->d_sb; | ||
9017 | + atomic_set(&new_data[idx].open_files, 0); | ||
9018 | + new_data[idx].branchperms = perms; | ||
9019 | + new_data[idx].branch_id = ++*high_branch_id; /* assign new branch ID */ | ||
9020 | + | ||
9021 | + err = 0; | ||
9022 | +out: | ||
9023 | + return err; | ||
9024 | +} | ||
9025 | + | ||
9026 | + | ||
9027 | +/* | ||
9028 | + * Support branch management options on remount. | ||
9029 | + * | ||
9030 | + * See Documentation/filesystems/unionfs/ for details. | ||
9031 | + * | ||
9032 | + * @flags: numeric mount options | ||
9033 | + * @options: mount options string | ||
9034 | + * | ||
9035 | + * This function can rearrange a mounted union dynamically, adding and | ||
9036 | + * removing branches, including changing branch modes. Clearly this has to | ||
9037 | + * be done safely and atomically. Luckily, the VFS already calls this | ||
9038 | + * function with lock_super(sb) and lock_kernel() held, preventing | ||
9039 | + * concurrent mixing of new mounts, remounts, and unmounts. Moreover, | ||
9040 | + * do_remount_sb(), our caller function, already called shrink_dcache_sb(sb) | ||
9041 | + * to purge dentries/inodes from our superblock, and also called | ||
9042 | + * fsync_super(sb) to purge any dirty pages. So we're good. | ||
9043 | + * | ||
9044 | + * XXX: however, our remount code may also need to invalidate mapped pages | ||
9045 | + * so as to force them to be re-gotten from the (newly reconfigured) lower | ||
9046 | + * branches. This has to wait for proper mmap and cache coherency support | ||
9047 | + * in the VFS. | ||
9048 | + * | ||
9049 | + */ | ||
9050 | +static int unionfs_remount_fs(struct super_block *sb, int *flags, | ||
9051 | + char *options) | ||
9052 | +{ | ||
9053 | + int err = 0; | ||
9054 | + int i; | ||
9055 | + char *optionstmp, *tmp_to_free; /* kstrdup'ed of "options" */ | ||
9056 | + char *optname; | ||
9057 | + int cur_branches = 0; /* no. of current branches */ | ||
9058 | + int new_branches = 0; /* no. of branches actually left in the end */ | ||
9059 | + int add_branches; /* est. no. of branches to add */ | ||
9060 | + int del_branches; /* est. no. of branches to del */ | ||
9061 | + int max_branches; /* max possible no. of branches */ | ||
9062 | + struct unionfs_data *new_data = NULL, *tmp_data = NULL; | ||
9063 | + struct path *new_lower_paths = NULL, *tmp_lower_paths = NULL; | ||
9064 | + struct inode **new_lower_inodes = NULL; | ||
9065 | + int new_high_branch_id; /* new high branch ID */ | ||
9066 | + int size; /* memory allocation size, temp var */ | ||
9067 | + int old_ibstart, old_ibend; | ||
9068 | + | ||
9069 | + unionfs_write_lock(sb); | ||
9070 | + | ||
9071 | + /* | ||
9072 | + * The VFS will take care of "ro" and "rw" flags, and we can safely | ||
9073 | + * ignore MS_SILENT, but anything else left over is an error. So we | ||
9074 | + * need to check if any other flags may have been passed (none are | ||
9075 | + * allowed/supported as of now). | ||
9076 | + */ | ||
9077 | + if ((*flags & ~(MS_RDONLY | MS_SILENT)) != 0) { | ||
9078 | + printk(KERN_ERR | ||
9079 | + "unionfs: remount flags 0x%x unsupported\n", *flags); | ||
9080 | + err = -EINVAL; | ||
9081 | + goto out_error; | ||
9082 | + } | ||
9083 | + | ||
9084 | + /* | ||
9085 | + * If 'options' is NULL, it's probably because the user just changed | ||
9086 | + * the union to a "ro" or "rw" and the VFS took care of it. So | ||
9087 | + * nothing to do and we're done. | ||
9088 | + */ | ||
9089 | + if (!options || options[0] == '\0') | ||
9090 | + goto out_error; | ||
9091 | + | ||
9092 | + /* | ||
9093 | + * Find out how many branches we will have in the end, counting | ||
9094 | + * "add" and "del" commands. Copy the "options" string because | ||
9095 | + * strsep modifies the string and we need it later. | ||
9096 | + */ | ||
9097 | + tmp_to_free = kstrdup(options, GFP_KERNEL); | ||
9098 | + optionstmp = tmp_to_free; | ||
9099 | + if (unlikely(!optionstmp)) { | ||
9100 | + err = -ENOMEM; | ||
9101 | + goto out_free; | ||
9102 | + } | ||
9103 | + cur_branches = sbmax(sb); /* current no. branches */ | ||
9104 | + new_branches = sbmax(sb); | ||
9105 | + del_branches = 0; | ||
9106 | + add_branches = 0; | ||
9107 | + new_high_branch_id = sbhbid(sb); /* save current high_branch_id */ | ||
9108 | + while ((optname = strsep(&optionstmp, ",")) != NULL) { | ||
9109 | + char *optarg; | ||
9110 | + | ||
9111 | + if (!optname || !*optname) | ||
9112 | + continue; | ||
9113 | + | ||
9114 | + optarg = strchr(optname, '='); | ||
9115 | + if (optarg) | ||
9116 | + *optarg++ = '\0'; | ||
9117 | + | ||
9118 | + if (!strcmp("add", optname)) | ||
9119 | + add_branches++; | ||
9120 | + else if (!strcmp("del", optname)) | ||
9121 | + del_branches++; | ||
9122 | + } | ||
9123 | + kfree(tmp_to_free); | ||
9124 | + /* after all changes, will we have at least one branch left? */ | ||
9125 | + if ((new_branches + add_branches - del_branches) < 1) { | ||
9126 | + printk(KERN_ERR | ||
9127 | + "unionfs: no branches left after remount\n"); | ||
9128 | + err = -EINVAL; | ||
9129 | + goto out_free; | ||
9130 | + } | ||
9131 | + | ||
9132 | + /* | ||
9133 | + * Since we haven't actually parsed all the add/del options, nor | ||
9134 | + * have we checked them for errors, we don't know for sure how many | ||
9135 | + * branches we will have after all changes have taken place. In | ||
9136 | + * fact, the total number of branches left could be less than what | ||
9137 | + * we have now. So we need to allocate space for a temporary | ||
9138 | + * placeholder that is at least as large as the maximum number of | ||
9139 | + * branches we *could* have, which is the current number plus all | ||
9140 | + * the additions. Once we're done with these temp placeholders, we | ||
9141 | + * may have to re-allocate the final size, copy over from the temp, | ||
9142 | + * and then free the temps (done near the end of this function). | ||
9143 | + */ | ||
9144 | + max_branches = cur_branches + add_branches; | ||
9145 | + /* allocate space for new pointers to lower dentry */ | ||
9146 | + tmp_data = kcalloc(max_branches, | ||
9147 | + sizeof(struct unionfs_data), GFP_KERNEL); | ||
9148 | + if (unlikely(!tmp_data)) { | ||
9149 | + err = -ENOMEM; | ||
9150 | + goto out_free; | ||
9151 | + } | ||
9152 | + /* allocate space for new pointers to lower paths */ | ||
9153 | + tmp_lower_paths = kcalloc(max_branches, | ||
9154 | + sizeof(struct path), GFP_KERNEL); | ||
9155 | + if (unlikely(!tmp_lower_paths)) { | ||
9156 | + err = -ENOMEM; | ||
9157 | + goto out_free; | ||
9158 | + } | ||
9159 | + /* copy current info into new placeholders, incrementing refcnts */ | ||
9160 | + memcpy(tmp_data, UNIONFS_SB(sb)->data, | ||
9161 | + cur_branches * sizeof(struct unionfs_data)); | ||
9162 | + memcpy(tmp_lower_paths, UNIONFS_D(sb->s_root)->lower_paths, | ||
9163 | + cur_branches * sizeof(struct path)); | ||
9164 | + for (i = 0; i < cur_branches; i++) | ||
9165 | + path_get(&tmp_lower_paths[i]); /* drop refs at end of fxn */ | ||
9166 | + | ||
9167 | + /******************************************************************* | ||
9168 | + * For each branch command, do kern_path on the requested branch, | ||
9169 | + * and apply the change to a temp branch list. To handle errors, we | ||
9170 | + * already dup'ed the old arrays (above), and increased the refcnts | ||
9171 | + * on various f/s objects. So now we can do all the kern_path'ss | ||
9172 | + * and branch-management commands on the new arrays. If it fail mid | ||
9173 | + * way, we free the tmp arrays and *put all objects. If we succeed, | ||
9174 | + * then we free old arrays and *put its objects, and then replace | ||
9175 | + * the arrays with the new tmp list (we may have to re-allocate the | ||
9176 | + * memory because the temp lists could have been larger than what we | ||
9177 | + * actually needed). | ||
9178 | + *******************************************************************/ | ||
9179 | + | ||
9180 | + while ((optname = strsep(&options, ",")) != NULL) { | ||
9181 | + char *optarg; | ||
9182 | + | ||
9183 | + if (!optname || !*optname) | ||
9184 | + continue; | ||
9185 | + /* | ||
9186 | + * At this stage optname holds a comma-delimited option, but | ||
9187 | + * without the commas. Next, we need to break the string on | ||
9188 | + * the '=' symbol to separate CMD=ARG, where ARG itself can | ||
9189 | + * be KEY=VAL. For example, in mode=/foo=rw, CMD is "mode", | ||
9190 | + * KEY is "/foo", and VAL is "rw". | ||
9191 | + */ | ||
9192 | + optarg = strchr(optname, '='); | ||
9193 | + if (optarg) | ||
9194 | + *optarg++ = '\0'; | ||
9195 | + /* incgen remount option (instead of old ioctl) */ | ||
9196 | + if (!strcmp("incgen", optname)) { | ||
9197 | + err = 0; | ||
9198 | + goto out_no_change; | ||
9199 | + } | ||
9200 | + | ||
9201 | + /* | ||
9202 | + * All of our options take an argument now. (Insert ones | ||
9203 | + * that don't above this check.) So at this stage optname | ||
9204 | + * contains the CMD part and optarg contains the ARG part. | ||
9205 | + */ | ||
9206 | + if (!optarg || !*optarg) { | ||
9207 | + printk(KERN_ERR "unionfs: all remount options require " | ||
9208 | + "an argument (%s)\n", optname); | ||
9209 | + err = -EINVAL; | ||
9210 | + goto out_release; | ||
9211 | + } | ||
9212 | + | ||
9213 | + if (!strcmp("add", optname)) { | ||
9214 | + err = do_remount_add_option(optarg, new_branches, | ||
9215 | + tmp_data, | ||
9216 | + tmp_lower_paths, | ||
9217 | + &new_high_branch_id); | ||
9218 | + if (err) | ||
9219 | + goto out_release; | ||
9220 | + new_branches++; | ||
9221 | + if (new_branches > UNIONFS_MAX_BRANCHES) { | ||
9222 | + printk(KERN_ERR "unionfs: command exceeds " | ||
9223 | + "%d branches\n", UNIONFS_MAX_BRANCHES); | ||
9224 | + err = -E2BIG; | ||
9225 | + goto out_release; | ||
9226 | + } | ||
9227 | + continue; | ||
9228 | + } | ||
9229 | + if (!strcmp("del", optname)) { | ||
9230 | + err = do_remount_del_option(optarg, new_branches, | ||
9231 | + tmp_data, | ||
9232 | + tmp_lower_paths); | ||
9233 | + if (err) | ||
9234 | + goto out_release; | ||
9235 | + new_branches--; | ||
9236 | + continue; | ||
9237 | + } | ||
9238 | + if (!strcmp("mode", optname)) { | ||
9239 | + err = do_remount_mode_option(optarg, new_branches, | ||
9240 | + tmp_data, | ||
9241 | + tmp_lower_paths); | ||
9242 | + if (err) | ||
9243 | + goto out_release; | ||
9244 | + continue; | ||
9245 | + } | ||
9246 | + | ||
9247 | + /* | ||
9248 | + * When you use "mount -o remount,ro", mount(8) will | ||
9249 | + * reportedly pass the original dirs= string from | ||
9250 | + * /proc/mounts. So for now, we have to ignore dirs= and | ||
9251 | + * not consider it an error, unless we want to allow users | ||
9252 | + * to pass dirs= in remount. Note that to allow the VFS to | ||
9253 | + * actually process the ro/rw remount options, we have to | ||
9254 | + * return 0 from this function. | ||
9255 | + */ | ||
9256 | + if (!strcmp("dirs", optname)) { | ||
9257 | + printk(KERN_WARNING | ||
9258 | + "unionfs: remount ignoring option \"%s\"\n", | ||
9259 | + optname); | ||
9260 | + continue; | ||
9261 | + } | ||
9262 | + | ||
9263 | + err = -EINVAL; | ||
9264 | + printk(KERN_ERR | ||
9265 | + "unionfs: unrecognized option \"%s\"\n", optname); | ||
9266 | + goto out_release; | ||
9267 | + } | ||
9268 | + | ||
9269 | +out_no_change: | ||
9270 | + | ||
9271 | + /****************************************************************** | ||
9272 | + * WE'RE ALMOST DONE: check if leftmost branch might be read-only, | ||
9273 | + * see if we need to allocate a small-sized new vector, copy the | ||
9274 | + * vectors to their correct place, release the refcnt of the older | ||
9275 | + * ones, and return. Also handle invalidating any pages that will | ||
9276 | + * have to be re-read. | ||
9277 | + *******************************************************************/ | ||
9278 | + | ||
9279 | + if (!(tmp_data[0].branchperms & MAY_WRITE)) { | ||
9280 | + printk(KERN_ERR "unionfs: leftmost branch cannot be read-only " | ||
9281 | + "(use \"remount,ro\" to create a read-only union)\n"); | ||
9282 | + err = -EINVAL; | ||
9283 | + goto out_release; | ||
9284 | + } | ||
9285 | + | ||
9286 | + /* (re)allocate space for new pointers to lower dentry */ | ||
9287 | + size = new_branches * sizeof(struct unionfs_data); | ||
9288 | + new_data = krealloc(tmp_data, size, GFP_KERNEL); | ||
9289 | + if (unlikely(!new_data)) { | ||
9290 | + err = -ENOMEM; | ||
9291 | + goto out_release; | ||
9292 | + } | ||
9293 | + | ||
9294 | + /* allocate space for new pointers to lower paths */ | ||
9295 | + size = new_branches * sizeof(struct path); | ||
9296 | + new_lower_paths = krealloc(tmp_lower_paths, size, GFP_KERNEL); | ||
9297 | + if (unlikely(!new_lower_paths)) { | ||
9298 | + err = -ENOMEM; | ||
9299 | + goto out_release; | ||
9300 | + } | ||
9301 | + | ||
9302 | + /* allocate space for new pointers to lower inodes */ | ||
9303 | + new_lower_inodes = kcalloc(new_branches, | ||
9304 | + sizeof(struct inode *), GFP_KERNEL); | ||
9305 | + if (unlikely(!new_lower_inodes)) { | ||
9306 | + err = -ENOMEM; | ||
9307 | + goto out_release; | ||
9308 | + } | ||
9309 | + | ||
9310 | + /* | ||
9311 | + * OK, just before we actually put the new set of branches in place, | ||
9312 | + * we need to ensure that our own f/s has no dirty objects left. | ||
9313 | + * Luckily, do_remount_sb() already calls shrink_dcache_sb(sb) and | ||
9314 | + * fsync_super(sb), taking care of dentries, inodes, and dirty | ||
9315 | + * pages. So all that's left is for us to invalidate any leftover | ||
9316 | + * (non-dirty) pages to ensure that they will be re-read from the | ||
9317 | + * new lower branches (and to support mmap). | ||
9318 | + */ | ||
9319 | + | ||
9320 | + /* | ||
9321 | + * Once we finish the remounting successfully, our superblock | ||
9322 | + * generation number will have increased. This will be detected by | ||
9323 | + * our dentry-revalidation code upon subsequent f/s operations | ||
9324 | + * through unionfs. The revalidation code will rebuild the union of | ||
9325 | + * lower inodes for a given unionfs inode and invalidate any pages | ||
9326 | + * of such "stale" inodes (by calling our purge_inode_data | ||
9327 | + * function). This revalidation will happen lazily and | ||
9328 | + * incrementally, as users perform operations on cached inodes. We | ||
9329 | + * would like to encourage this revalidation to happen sooner if | ||
9330 | + * possible, so we like to try to invalidate as many other pages in | ||
9331 | + * our superblock as we can. We used to call drop_pagecache_sb() or | ||
9332 | + * a variant thereof, but either method was racy (drop_caches alone | ||
9333 | + * is known to be racy). So now we let the revalidation happen on a | ||
9334 | + * per file basis in ->d_revalidate. | ||
9335 | + */ | ||
9336 | + | ||
9337 | + /* grab new lower super references; release old ones */ | ||
9338 | + for (i = 0; i < new_branches; i++) | ||
9339 | + atomic_inc(&new_data[i].sb->s_active); | ||
9340 | + for (i = 0; i < sbmax(sb); i++) | ||
9341 | + atomic_dec(&UNIONFS_SB(sb)->data[i].sb->s_active); | ||
9342 | + | ||
9343 | + /* copy new vectors into their correct place */ | ||
9344 | + tmp_data = UNIONFS_SB(sb)->data; | ||
9345 | + UNIONFS_SB(sb)->data = new_data; | ||
9346 | + new_data = NULL; /* so don't free good pointers below */ | ||
9347 | + tmp_lower_paths = UNIONFS_D(sb->s_root)->lower_paths; | ||
9348 | + UNIONFS_D(sb->s_root)->lower_paths = new_lower_paths; | ||
9349 | + new_lower_paths = NULL; /* so don't free good pointers below */ | ||
9350 | + | ||
9351 | + /* update our unionfs_sb_info and root dentry index of last branch */ | ||
9352 | + i = sbmax(sb); /* save no. of branches to release at end */ | ||
9353 | + sbend(sb) = new_branches - 1; | ||
9354 | + dbend(sb->s_root) = new_branches - 1; | ||
9355 | + old_ibstart = ibstart(sb->s_root->d_inode); | ||
9356 | + old_ibend = ibend(sb->s_root->d_inode); | ||
9357 | + ibend(sb->s_root->d_inode) = new_branches - 1; | ||
9358 | + UNIONFS_D(sb->s_root)->bcount = new_branches; | ||
9359 | + new_branches = i; /* no. of branches to release below */ | ||
9360 | + | ||
9361 | + /* | ||
9362 | + * Update lower inodes: 3 steps | ||
9363 | + * 1. grab ref on all new lower inodes | ||
9364 | + */ | ||
9365 | + for (i = dbstart(sb->s_root); i <= dbend(sb->s_root); i++) { | ||
9366 | + struct dentry *lower_dentry = | ||
9367 | + unionfs_lower_dentry_idx(sb->s_root, i); | ||
9368 | + igrab(lower_dentry->d_inode); | ||
9369 | + new_lower_inodes[i] = lower_dentry->d_inode; | ||
9370 | + } | ||
9371 | + /* 2. release reference on all older lower inodes */ | ||
9372 | + iput_lowers(sb->s_root->d_inode, old_ibstart, old_ibend, true); | ||
9373 | + /* 3. update root dentry's inode to new lower_inodes array */ | ||
9374 | + UNIONFS_I(sb->s_root->d_inode)->lower_inodes = new_lower_inodes; | ||
9375 | + new_lower_inodes = NULL; | ||
9376 | + | ||
9377 | + /* maxbytes may have changed */ | ||
9378 | + sb->s_maxbytes = unionfs_lower_super_idx(sb, 0)->s_maxbytes; | ||
9379 | + /* update high branch ID */ | ||
9380 | + sbhbid(sb) = new_high_branch_id; | ||
9381 | + | ||
9382 | + /* update our sb->generation for revalidating objects */ | ||
9383 | + i = atomic_inc_return(&UNIONFS_SB(sb)->generation); | ||
9384 | + atomic_set(&UNIONFS_D(sb->s_root)->generation, i); | ||
9385 | + atomic_set(&UNIONFS_I(sb->s_root->d_inode)->generation, i); | ||
9386 | + if (!(*flags & MS_SILENT)) | ||
9387 | + pr_info("unionfs: %s: new generation number %d\n", | ||
9388 | + UNIONFS_SB(sb)->dev_name, i); | ||
9389 | + /* finally, update the root dentry's times */ | ||
9390 | + unionfs_copy_attr_times(sb->s_root->d_inode); | ||
9391 | + err = 0; /* reset to success */ | ||
9392 | + | ||
9393 | + /* | ||
9394 | + * The code above falls through to the next label, and releases the | ||
9395 | + * refcnts of the older ones (stored in tmp_*): if we fell through | ||
9396 | + * here, it means success. However, if we jump directly to this | ||
9397 | + * label from any error above, then an error occurred after we | ||
9398 | + * grabbed various refcnts, and so we have to release the | ||
9399 | + * temporarily constructed structures. | ||
9400 | + */ | ||
9401 | +out_release: | ||
9402 | + /* no need to cleanup/release anything in tmp_data */ | ||
9403 | + if (tmp_lower_paths) | ||
9404 | + for (i = 0; i < new_branches; i++) | ||
9405 | + path_put(&tmp_lower_paths[i]); | ||
9406 | +out_free: | ||
9407 | + kfree(tmp_lower_paths); | ||
9408 | + kfree(tmp_data); | ||
9409 | + kfree(new_lower_paths); | ||
9410 | + kfree(new_data); | ||
9411 | + kfree(new_lower_inodes); | ||
9412 | +out_error: | ||
9413 | + unionfs_check_dentry(sb->s_root); | ||
9414 | + unionfs_write_unlock(sb); | ||
9415 | + return err; | ||
9416 | +} | ||
9417 | + | ||
9418 | +/* | ||
9419 | + * Called by iput() when the inode reference count reached zero | ||
9420 | + * and the inode is not hashed anywhere. Used to clear anything | ||
9421 | + * that needs to be, before the inode is completely destroyed and put | ||
9422 | + * on the inode free list. | ||
9423 | + * | ||
9424 | + * No need to lock sb info's rwsem. | ||
9425 | + */ | ||
9426 | +static void unionfs_evict_inode(struct inode *inode) | ||
9427 | +{ | ||
9428 | + int bindex, bstart, bend; | ||
9429 | + struct inode *lower_inode; | ||
9430 | + struct list_head *pos, *n; | ||
9431 | + struct unionfs_dir_state *rdstate; | ||
9432 | + | ||
9433 | + truncate_inode_pages(&inode->i_data, 0); | ||
9434 | + end_writeback(inode); | ||
9435 | + | ||
9436 | + list_for_each_safe(pos, n, &UNIONFS_I(inode)->readdircache) { | ||
9437 | + rdstate = list_entry(pos, struct unionfs_dir_state, cache); | ||
9438 | + list_del(&rdstate->cache); | ||
9439 | + free_rdstate(rdstate); | ||
9440 | + } | ||
9441 | + | ||
9442 | + /* | ||
9443 | + * Decrement a reference to a lower_inode, which was incremented | ||
9444 | + * by our read_inode when it was created initially. | ||
9445 | + */ | ||
9446 | + bstart = ibstart(inode); | ||
9447 | + bend = ibend(inode); | ||
9448 | + if (bstart >= 0) { | ||
9449 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
9450 | + lower_inode = unionfs_lower_inode_idx(inode, bindex); | ||
9451 | + if (!lower_inode) | ||
9452 | + continue; | ||
9453 | + unionfs_set_lower_inode_idx(inode, bindex, NULL); | ||
9454 | + /* see Documentation/filesystems/unionfs/issues.txt */ | ||
9455 | + lockdep_off(); | ||
9456 | + iput(lower_inode); | ||
9457 | + lockdep_on(); | ||
9458 | + } | ||
9459 | + } | ||
9460 | + | ||
9461 | + kfree(UNIONFS_I(inode)->lower_inodes); | ||
9462 | + UNIONFS_I(inode)->lower_inodes = NULL; | ||
9463 | +} | ||
9464 | + | ||
9465 | +static struct inode *unionfs_alloc_inode(struct super_block *sb) | ||
9466 | +{ | ||
9467 | + struct unionfs_inode_info *i; | ||
9468 | + | ||
9469 | + i = kmem_cache_alloc(unionfs_inode_cachep, GFP_KERNEL); | ||
9470 | + if (unlikely(!i)) | ||
9471 | + return NULL; | ||
9472 | + | ||
9473 | + /* memset everything up to the inode to 0 */ | ||
9474 | + memset(i, 0, offsetof(struct unionfs_inode_info, vfs_inode)); | ||
9475 | + | ||
9476 | + i->vfs_inode.i_version = 1; | ||
9477 | + return &i->vfs_inode; | ||
9478 | +} | ||
9479 | + | ||
9480 | +static void unionfs_destroy_inode(struct inode *inode) | ||
9481 | +{ | ||
9482 | + kmem_cache_free(unionfs_inode_cachep, UNIONFS_I(inode)); | ||
9483 | +} | ||
9484 | + | ||
9485 | +/* unionfs inode cache constructor */ | ||
9486 | +static void init_once(void *obj) | ||
9487 | +{ | ||
9488 | + struct unionfs_inode_info *i = obj; | ||
9489 | + | ||
9490 | + inode_init_once(&i->vfs_inode); | ||
9491 | +} | ||
9492 | + | ||
9493 | +int unionfs_init_inode_cache(void) | ||
9494 | +{ | ||
9495 | + int err = 0; | ||
9496 | + | ||
9497 | + unionfs_inode_cachep = | ||
9498 | + kmem_cache_create("unionfs_inode_cache", | ||
9499 | + sizeof(struct unionfs_inode_info), 0, | ||
9500 | + SLAB_RECLAIM_ACCOUNT, init_once); | ||
9501 | + if (unlikely(!unionfs_inode_cachep)) | ||
9502 | + err = -ENOMEM; | ||
9503 | + return err; | ||
9504 | +} | ||
9505 | + | ||
9506 | +/* unionfs inode cache destructor */ | ||
9507 | +void unionfs_destroy_inode_cache(void) | ||
9508 | +{ | ||
9509 | + if (unionfs_inode_cachep) | ||
9510 | + kmem_cache_destroy(unionfs_inode_cachep); | ||
9511 | +} | ||
9512 | + | ||
9513 | +/* | ||
9514 | + * Called when we have a dirty inode, right here we only throw out | ||
9515 | + * parts of our readdir list that are too old. | ||
9516 | + * | ||
9517 | + * No need to grab sb info's rwsem. | ||
9518 | + */ | ||
9519 | +static int unionfs_write_inode(struct inode *inode, | ||
9520 | + struct writeback_control *wbc) | ||
9521 | +{ | ||
9522 | + struct list_head *pos, *n; | ||
9523 | + struct unionfs_dir_state *rdstate; | ||
9524 | + | ||
9525 | + spin_lock(&UNIONFS_I(inode)->rdlock); | ||
9526 | + list_for_each_safe(pos, n, &UNIONFS_I(inode)->readdircache) { | ||
9527 | + rdstate = list_entry(pos, struct unionfs_dir_state, cache); | ||
9528 | + /* We keep this list in LRU order. */ | ||
9529 | + if ((rdstate->access + RDCACHE_JIFFIES) > jiffies) | ||
9530 | + break; | ||
9531 | + UNIONFS_I(inode)->rdcount--; | ||
9532 | + list_del(&rdstate->cache); | ||
9533 | + free_rdstate(rdstate); | ||
9534 | + } | ||
9535 | + spin_unlock(&UNIONFS_I(inode)->rdlock); | ||
9536 | + | ||
9537 | + return 0; | ||
9538 | +} | ||
9539 | + | ||
9540 | +/* | ||
9541 | + * Used only in nfs, to kill any pending RPC tasks, so that subsequent | ||
9542 | + * code can actually succeed and won't leave tasks that need handling. | ||
9543 | + */ | ||
9544 | +static void unionfs_umount_begin(struct super_block *sb) | ||
9545 | +{ | ||
9546 | + struct super_block *lower_sb; | ||
9547 | + int bindex, bstart, bend; | ||
9548 | + | ||
9549 | + unionfs_read_lock(sb, UNIONFS_SMUTEX_CHILD); | ||
9550 | + | ||
9551 | + bstart = sbstart(sb); | ||
9552 | + bend = sbend(sb); | ||
9553 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
9554 | + lower_sb = unionfs_lower_super_idx(sb, bindex); | ||
9555 | + | ||
9556 | + if (lower_sb && lower_sb->s_op && | ||
9557 | + lower_sb->s_op->umount_begin) | ||
9558 | + lower_sb->s_op->umount_begin(lower_sb); | ||
9559 | + } | ||
9560 | + | ||
9561 | + unionfs_read_unlock(sb); | ||
9562 | +} | ||
9563 | + | ||
9564 | +static int unionfs_show_options(struct seq_file *m, struct vfsmount *mnt) | ||
9565 | +{ | ||
9566 | + struct super_block *sb = mnt->mnt_sb; | ||
9567 | + int ret = 0; | ||
9568 | + char *tmp_page; | ||
9569 | + char *path; | ||
9570 | + int bindex, bstart, bend; | ||
9571 | + int perms; | ||
9572 | + | ||
9573 | + /* to prevent a silly lockdep warning with namespace_sem */ | ||
9574 | + lockdep_off(); | ||
9575 | + unionfs_read_lock(sb, UNIONFS_SMUTEX_CHILD); | ||
9576 | + unionfs_lock_dentry(sb->s_root, UNIONFS_DMUTEX_CHILD); | ||
9577 | + | ||
9578 | + tmp_page = (char *) __get_free_page(GFP_KERNEL); | ||
9579 | + if (unlikely(!tmp_page)) { | ||
9580 | + ret = -ENOMEM; | ||
9581 | + goto out; | ||
9582 | + } | ||
9583 | + | ||
9584 | + bstart = sbstart(sb); | ||
9585 | + bend = sbend(sb); | ||
9586 | + | ||
9587 | + seq_printf(m, ",dirs="); | ||
9588 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
9589 | + struct path p; | ||
9590 | + p.dentry = unionfs_lower_dentry_idx(sb->s_root, bindex); | ||
9591 | + p.mnt = unionfs_lower_mnt_idx(sb->s_root, bindex); | ||
9592 | + path = d_path(&p, tmp_page, PAGE_SIZE); | ||
9593 | + if (IS_ERR(path)) { | ||
9594 | + ret = PTR_ERR(path); | ||
9595 | + goto out; | ||
9596 | + } | ||
9597 | + | ||
9598 | + perms = branchperms(sb, bindex); | ||
9599 | + | ||
9600 | + seq_printf(m, "%s=%s", path, | ||
9601 | + perms & MAY_WRITE ? "rw" : "ro"); | ||
9602 | + if (bindex != bend) | ||
9603 | + seq_printf(m, ":"); | ||
9604 | + } | ||
9605 | + | ||
9606 | +out: | ||
9607 | + free_page((unsigned long) tmp_page); | ||
9608 | + | ||
9609 | + unionfs_unlock_dentry(sb->s_root); | ||
9610 | + unionfs_read_unlock(sb); | ||
9611 | + lockdep_on(); | ||
9612 | + | ||
9613 | + return ret; | ||
9614 | +} | ||
9615 | + | ||
9616 | +struct super_operations unionfs_sops = { | ||
9617 | + .put_super = unionfs_put_super, | ||
9618 | + .statfs = unionfs_statfs, | ||
9619 | + .remount_fs = unionfs_remount_fs, | ||
9620 | + .evict_inode = unionfs_evict_inode, | ||
9621 | + .umount_begin = unionfs_umount_begin, | ||
9622 | + .show_options = unionfs_show_options, | ||
9623 | + .write_inode = unionfs_write_inode, | ||
9624 | + .alloc_inode = unionfs_alloc_inode, | ||
9625 | + .destroy_inode = unionfs_destroy_inode, | ||
9626 | +}; | ||
9627 | diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h | ||
9628 | new file mode 100644 | ||
9629 | index 0000000..1821705 | ||
9630 | --- /dev/null | ||
9631 | +++ b/fs/unionfs/union.h | ||
9632 | @@ -0,0 +1,679 @@ | ||
9633 | +/* | ||
9634 | + * Copyright (c) 2003-2011 Erez Zadok | ||
9635 | + * Copyright (c) 2003-2006 Charles P. Wright | ||
9636 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
9637 | + * Copyright (c) 2005 Arun M. Krishnakumar | ||
9638 | + * Copyright (c) 2004-2006 David P. Quigley | ||
9639 | + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair | ||
9640 | + * Copyright (c) 2003 Puja Gupta | ||
9641 | + * Copyright (c) 2003 Harikesavan Krishnan | ||
9642 | + * Copyright (c) 2003-2011 Stony Brook University | ||
9643 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
9644 | + * | ||
9645 | + * This program is free software; you can redistribute it and/or modify | ||
9646 | + * it under the terms of the GNU General Public License version 2 as | ||
9647 | + * published by the Free Software Foundation. | ||
9648 | + */ | ||
9649 | + | ||
9650 | +#ifndef _UNION_H_ | ||
9651 | +#define _UNION_H_ | ||
9652 | + | ||
9653 | +#include <linux/dcache.h> | ||
9654 | +#include <linux/file.h> | ||
9655 | +#include <linux/list.h> | ||
9656 | +#include <linux/fs.h> | ||
9657 | +#include <linux/mm.h> | ||
9658 | +#include <linux/module.h> | ||
9659 | +#include <linux/mount.h> | ||
9660 | +#include <linux/namei.h> | ||
9661 | +#include <linux/page-flags.h> | ||
9662 | +#include <linux/pagemap.h> | ||
9663 | +#include <linux/poll.h> | ||
9664 | +#include <linux/security.h> | ||
9665 | +#include <linux/seq_file.h> | ||
9666 | +#include <linux/slab.h> | ||
9667 | +#include <linux/spinlock.h> | ||
9668 | +#include <linux/statfs.h> | ||
9669 | +#include <linux/string.h> | ||
9670 | +#include <linux/vmalloc.h> | ||
9671 | +#include <linux/writeback.h> | ||
9672 | +#include <linux/buffer_head.h> | ||
9673 | +#include <linux/xattr.h> | ||
9674 | +#include <linux/fs_stack.h> | ||
9675 | +#include <linux/magic.h> | ||
9676 | +#include <linux/log2.h> | ||
9677 | +#include <linux/poison.h> | ||
9678 | +#include <linux/mman.h> | ||
9679 | +#include <linux/backing-dev.h> | ||
9680 | +#include <linux/splice.h> | ||
9681 | +#include <linux/sched.h> | ||
9682 | + | ||
9683 | +#include <asm/system.h> | ||
9684 | + | ||
9685 | +#include <linux/union_fs.h> | ||
9686 | + | ||
9687 | +/* the file system name */ | ||
9688 | +#define UNIONFS_NAME "unionfs" | ||
9689 | + | ||
9690 | +/* unionfs root inode number */ | ||
9691 | +#define UNIONFS_ROOT_INO 1 | ||
9692 | + | ||
9693 | +/* number of times we try to get a unique temporary file name */ | ||
9694 | +#define GET_TMPNAM_MAX_RETRY 5 | ||
9695 | + | ||
9696 | +/* maximum number of branches we support, to avoid memory blowup */ | ||
9697 | +#define UNIONFS_MAX_BRANCHES 128 | ||
9698 | + | ||
9699 | +/* minimum time (seconds) required for time-based cache-coherency */ | ||
9700 | +#define UNIONFS_MIN_CC_TIME 3 | ||
9701 | + | ||
9702 | +/* Operations vectors defined in specific files. */ | ||
9703 | +extern struct file_operations unionfs_main_fops; | ||
9704 | +extern struct file_operations unionfs_dir_fops; | ||
9705 | +extern struct inode_operations unionfs_main_iops; | ||
9706 | +extern struct inode_operations unionfs_dir_iops; | ||
9707 | +extern struct inode_operations unionfs_symlink_iops; | ||
9708 | +extern struct super_operations unionfs_sops; | ||
9709 | +extern struct dentry_operations unionfs_dops; | ||
9710 | +extern struct address_space_operations unionfs_aops, unionfs_dummy_aops; | ||
9711 | +extern struct vm_operations_struct unionfs_vm_ops; | ||
9712 | + | ||
9713 | +/* How long should an entry be allowed to persist */ | ||
9714 | +#define RDCACHE_JIFFIES (5*HZ) | ||
9715 | + | ||
9716 | +/* compatibility with Real-Time patches */ | ||
9717 | +#ifdef CONFIG_PREEMPT_RT | ||
9718 | +# define unionfs_rw_semaphore compat_rw_semaphore | ||
9719 | +#else /* not CONFIG_PREEMPT_RT */ | ||
9720 | +# define unionfs_rw_semaphore rw_semaphore | ||
9721 | +#endif /* not CONFIG_PREEMPT_RT */ | ||
9722 | + | ||
9723 | +/* file private data. */ | ||
9724 | +struct unionfs_file_info { | ||
9725 | + int bstart; | ||
9726 | + int bend; | ||
9727 | + atomic_t generation; | ||
9728 | + | ||
9729 | + struct unionfs_dir_state *rdstate; | ||
9730 | + struct file **lower_files; | ||
9731 | + int *saved_branch_ids; /* IDs of branches when file was opened */ | ||
9732 | + const struct vm_operations_struct *lower_vm_ops; | ||
9733 | + bool wrote_to_file; /* for delayed copyup */ | ||
9734 | +}; | ||
9735 | + | ||
9736 | +/* unionfs inode data in memory */ | ||
9737 | +struct unionfs_inode_info { | ||
9738 | + int bstart; | ||
9739 | + int bend; | ||
9740 | + atomic_t generation; | ||
9741 | + /* Stuff for readdir over NFS. */ | ||
9742 | + spinlock_t rdlock; | ||
9743 | + struct list_head readdircache; | ||
9744 | + int rdcount; | ||
9745 | + int hashsize; | ||
9746 | + int cookie; | ||
9747 | + | ||
9748 | + /* The lower inodes */ | ||
9749 | + struct inode **lower_inodes; | ||
9750 | + | ||
9751 | + struct inode vfs_inode; | ||
9752 | +}; | ||
9753 | + | ||
9754 | +/* unionfs dentry data in memory */ | ||
9755 | +struct unionfs_dentry_info { | ||
9756 | + /* | ||
9757 | + * The semaphore is used to lock the dentry as soon as we get into a | ||
9758 | + * unionfs function from the VFS. Our lock ordering is that children | ||
9759 | + * go before their parents. | ||
9760 | + */ | ||
9761 | + struct mutex lock; | ||
9762 | + int bstart; | ||
9763 | + int bend; | ||
9764 | + int bopaque; | ||
9765 | + int bcount; | ||
9766 | + atomic_t generation; | ||
9767 | + struct path *lower_paths; | ||
9768 | +}; | ||
9769 | + | ||
9770 | +/* These are the pointers to our various objects. */ | ||
9771 | +struct unionfs_data { | ||
9772 | + struct super_block *sb; /* lower super_block */ | ||
9773 | + atomic_t open_files; /* number of open files on branch */ | ||
9774 | + int branchperms; | ||
9775 | + int branch_id; /* unique branch ID at re/mount time */ | ||
9776 | +}; | ||
9777 | + | ||
9778 | +/* unionfs super-block data in memory */ | ||
9779 | +struct unionfs_sb_info { | ||
9780 | + int bend; | ||
9781 | + | ||
9782 | + atomic_t generation; | ||
9783 | + | ||
9784 | + /* | ||
9785 | + * This rwsem is used to make sure that a branch management | ||
9786 | + * operation... | ||
9787 | + * 1) will not begin before all currently in-flight operations | ||
9788 | + * complete. | ||
9789 | + * 2) any new operations do not execute until the currently | ||
9790 | + * running branch management operation completes. | ||
9791 | + * | ||
9792 | + * The write_lock_owner records the PID of the task which grabbed | ||
9793 | + * the rw_sem for writing. If the same task also tries to grab the | ||
9794 | + * read lock, we allow it. This prevents a self-deadlock when | ||
9795 | + * branch-management is used on a pivot_root'ed union, because we | ||
9796 | + * have to ->lookup paths which belong to the same union. | ||
9797 | + */ | ||
9798 | + struct unionfs_rw_semaphore rwsem; | ||
9799 | + pid_t write_lock_owner; /* PID of rw_sem owner (write lock) */ | ||
9800 | + int high_branch_id; /* last unique branch ID given */ | ||
9801 | + char *dev_name; /* to identify different unions in pr_debug */ | ||
9802 | + struct unionfs_data *data; | ||
9803 | +}; | ||
9804 | + | ||
9805 | +/* | ||
9806 | + * structure for making the linked list of entries by readdir on left branch | ||
9807 | + * to compare with entries on right branch | ||
9808 | + */ | ||
9809 | +struct filldir_node { | ||
9810 | + struct list_head file_list; /* list for directory entries */ | ||
9811 | + char *name; /* name entry */ | ||
9812 | + int hash; /* name hash */ | ||
9813 | + int namelen; /* name len since name is not 0 terminated */ | ||
9814 | + | ||
9815 | + /* | ||
9816 | + * we can check for duplicate whiteouts and files in the same branch | ||
9817 | + * in order to return -EIO. | ||
9818 | + */ | ||
9819 | + int bindex; | ||
9820 | + | ||
9821 | + /* is this a whiteout entry? */ | ||
9822 | + int whiteout; | ||
9823 | + | ||
9824 | + /* Inline name, so we don't need to separately kmalloc small ones */ | ||
9825 | + char iname[DNAME_INLINE_LEN]; | ||
9826 | +}; | ||
9827 | + | ||
9828 | +/* Directory hash table. */ | ||
9829 | +struct unionfs_dir_state { | ||
9830 | + unsigned int cookie; /* the cookie, based off of rdversion */ | ||
9831 | + unsigned int offset; /* The entry we have returned. */ | ||
9832 | + int bindex; | ||
9833 | + loff_t dirpos; /* offset within the lower level directory */ | ||
9834 | + int size; /* How big is the hash table? */ | ||
9835 | + int hashentries; /* How many entries have been inserted? */ | ||
9836 | + unsigned long access; | ||
9837 | + | ||
9838 | + /* This cache list is used when the inode keeps us around. */ | ||
9839 | + struct list_head cache; | ||
9840 | + struct list_head list[0]; | ||
9841 | +}; | ||
9842 | + | ||
9843 | +/* externs needed for fanout.h or sioq.h */ | ||
9844 | +extern int unionfs_get_nlinks(const struct inode *inode); | ||
9845 | +extern void unionfs_copy_attr_times(struct inode *upper); | ||
9846 | +extern void unionfs_copy_attr_all(struct inode *dest, const struct inode *src); | ||
9847 | + | ||
9848 | +/* include miscellaneous macros */ | ||
9849 | +#include "fanout.h" | ||
9850 | +#include "sioq.h" | ||
9851 | + | ||
9852 | +/* externs for cache creation/deletion routines */ | ||
9853 | +extern void unionfs_destroy_filldir_cache(void); | ||
9854 | +extern int unionfs_init_filldir_cache(void); | ||
9855 | +extern int unionfs_init_inode_cache(void); | ||
9856 | +extern void unionfs_destroy_inode_cache(void); | ||
9857 | +extern int unionfs_init_dentry_cache(void); | ||
9858 | +extern void unionfs_destroy_dentry_cache(void); | ||
9859 | + | ||
9860 | +/* Initialize and free readdir-specific state. */ | ||
9861 | +extern int init_rdstate(struct file *file); | ||
9862 | +extern struct unionfs_dir_state *alloc_rdstate(struct inode *inode, | ||
9863 | + int bindex); | ||
9864 | +extern struct unionfs_dir_state *find_rdstate(struct inode *inode, | ||
9865 | + loff_t fpos); | ||
9866 | +extern void free_rdstate(struct unionfs_dir_state *state); | ||
9867 | +extern int add_filldir_node(struct unionfs_dir_state *rdstate, | ||
9868 | + const char *name, int namelen, int bindex, | ||
9869 | + int whiteout); | ||
9870 | +extern struct filldir_node *find_filldir_node(struct unionfs_dir_state *rdstate, | ||
9871 | + const char *name, int namelen, | ||
9872 | + int is_whiteout); | ||
9873 | + | ||
9874 | +extern struct dentry **alloc_new_dentries(int objs); | ||
9875 | +extern struct unionfs_data *alloc_new_data(int objs); | ||
9876 | + | ||
9877 | +/* We can only use 32-bits of offset for rdstate --- blech! */ | ||
9878 | +#define DIREOF (0xfffff) | ||
9879 | +#define RDOFFBITS 20 /* This is the number of bits in DIREOF. */ | ||
9880 | +#define MAXRDCOOKIE (0xfff) | ||
9881 | +/* Turn an rdstate into an offset. */ | ||
9882 | +static inline off_t rdstate2offset(struct unionfs_dir_state *buf) | ||
9883 | +{ | ||
9884 | + off_t tmp; | ||
9885 | + | ||
9886 | + tmp = ((buf->cookie & MAXRDCOOKIE) << RDOFFBITS) | ||
9887 | + | (buf->offset & DIREOF); | ||
9888 | + return tmp; | ||
9889 | +} | ||
9890 | + | ||
9891 | +/* Macros for locking a super_block. */ | ||
9892 | +enum unionfs_super_lock_class { | ||
9893 | + UNIONFS_SMUTEX_NORMAL, | ||
9894 | + UNIONFS_SMUTEX_PARENT, /* when locking on behalf of file */ | ||
9895 | + UNIONFS_SMUTEX_CHILD, /* when locking on behalf of dentry */ | ||
9896 | +}; | ||
9897 | +static inline void unionfs_read_lock(struct super_block *sb, int subclass) | ||
9898 | +{ | ||
9899 | + if (UNIONFS_SB(sb)->write_lock_owner && | ||
9900 | + UNIONFS_SB(sb)->write_lock_owner == current->pid) | ||
9901 | + return; | ||
9902 | + down_read_nested(&UNIONFS_SB(sb)->rwsem, subclass); | ||
9903 | +} | ||
9904 | +static inline void unionfs_read_unlock(struct super_block *sb) | ||
9905 | +{ | ||
9906 | + if (UNIONFS_SB(sb)->write_lock_owner && | ||
9907 | + UNIONFS_SB(sb)->write_lock_owner == current->pid) | ||
9908 | + return; | ||
9909 | + up_read(&UNIONFS_SB(sb)->rwsem); | ||
9910 | +} | ||
9911 | +static inline void unionfs_write_lock(struct super_block *sb) | ||
9912 | +{ | ||
9913 | + down_write(&UNIONFS_SB(sb)->rwsem); | ||
9914 | + UNIONFS_SB(sb)->write_lock_owner = current->pid; | ||
9915 | +} | ||
9916 | +static inline void unionfs_write_unlock(struct super_block *sb) | ||
9917 | +{ | ||
9918 | + up_write(&UNIONFS_SB(sb)->rwsem); | ||
9919 | + UNIONFS_SB(sb)->write_lock_owner = 0; | ||
9920 | +} | ||
9921 | + | ||
9922 | +static inline void unionfs_double_lock_dentry(struct dentry *d1, | ||
9923 | + struct dentry *d2) | ||
9924 | +{ | ||
9925 | + BUG_ON(d1 == d2); | ||
9926 | + if (d1 < d2) { | ||
9927 | + unionfs_lock_dentry(d1, UNIONFS_DMUTEX_PARENT); | ||
9928 | + unionfs_lock_dentry(d2, UNIONFS_DMUTEX_CHILD); | ||
9929 | + } else { | ||
9930 | + unionfs_lock_dentry(d2, UNIONFS_DMUTEX_PARENT); | ||
9931 | + unionfs_lock_dentry(d1, UNIONFS_DMUTEX_CHILD); | ||
9932 | + } | ||
9933 | +} | ||
9934 | + | ||
9935 | +static inline void unionfs_double_unlock_dentry(struct dentry *d1, | ||
9936 | + struct dentry *d2) | ||
9937 | +{ | ||
9938 | + BUG_ON(d1 == d2); | ||
9939 | + if (d1 < d2) { /* unlock in reverse order than double_lock_dentry */ | ||
9940 | + unionfs_unlock_dentry(d1); | ||
9941 | + unionfs_unlock_dentry(d2); | ||
9942 | + } else { | ||
9943 | + unionfs_unlock_dentry(d2); | ||
9944 | + unionfs_unlock_dentry(d1); | ||
9945 | + } | ||
9946 | +} | ||
9947 | + | ||
9948 | +static inline void unionfs_double_lock_parents(struct dentry *p1, | ||
9949 | + struct dentry *p2) | ||
9950 | +{ | ||
9951 | + if (p1 == p2) { | ||
9952 | + unionfs_lock_dentry(p1, UNIONFS_DMUTEX_REVAL_PARENT); | ||
9953 | + return; | ||
9954 | + } | ||
9955 | + if (p1 < p2) { | ||
9956 | + unionfs_lock_dentry(p1, UNIONFS_DMUTEX_REVAL_PARENT); | ||
9957 | + unionfs_lock_dentry(p2, UNIONFS_DMUTEX_REVAL_CHILD); | ||
9958 | + } else { | ||
9959 | + unionfs_lock_dentry(p2, UNIONFS_DMUTEX_REVAL_PARENT); | ||
9960 | + unionfs_lock_dentry(p1, UNIONFS_DMUTEX_REVAL_CHILD); | ||
9961 | + } | ||
9962 | +} | ||
9963 | + | ||
9964 | +static inline void unionfs_double_unlock_parents(struct dentry *p1, | ||
9965 | + struct dentry *p2) | ||
9966 | +{ | ||
9967 | + if (p1 == p2) { | ||
9968 | + unionfs_unlock_dentry(p1); | ||
9969 | + return; | ||
9970 | + } | ||
9971 | + if (p1 < p2) { /* unlock in reverse order of double_lock_parents */ | ||
9972 | + unionfs_unlock_dentry(p1); | ||
9973 | + unionfs_unlock_dentry(p2); | ||
9974 | + } else { | ||
9975 | + unionfs_unlock_dentry(p2); | ||
9976 | + unionfs_unlock_dentry(p1); | ||
9977 | + } | ||
9978 | +} | ||
9979 | + | ||
9980 | +extern int new_dentry_private_data(struct dentry *dentry, int subclass); | ||
9981 | +extern int realloc_dentry_private_data(struct dentry *dentry); | ||
9982 | +extern void free_dentry_private_data(struct dentry *dentry); | ||
9983 | +extern void update_bstart(struct dentry *dentry); | ||
9984 | +extern int init_lower_nd(struct nameidata *nd, unsigned int flags); | ||
9985 | +extern void release_lower_nd(struct nameidata *nd, int err); | ||
9986 | + | ||
9987 | +/* | ||
9988 | + * EXTERNALS: | ||
9989 | + */ | ||
9990 | + | ||
9991 | +/* replicates the directory structure up to given dentry in given branch */ | ||
9992 | +extern struct dentry *create_parents(struct inode *dir, struct dentry *dentry, | ||
9993 | + const char *name, int bindex); | ||
9994 | + | ||
9995 | +/* partial lookup */ | ||
9996 | +extern int unionfs_partial_lookup(struct dentry *dentry, | ||
9997 | + struct dentry *parent); | ||
9998 | +extern struct dentry *unionfs_lookup_full(struct dentry *dentry, | ||
9999 | + struct dentry *parent, | ||
10000 | + int lookupmode); | ||
10001 | + | ||
10002 | +/* copies a file from dbstart to newbindex branch */ | ||
10003 | +extern int copyup_file(struct inode *dir, struct file *file, int bstart, | ||
10004 | + int newbindex, loff_t size); | ||
10005 | +extern int copyup_named_file(struct inode *dir, struct file *file, | ||
10006 | + char *name, int bstart, int new_bindex, | ||
10007 | + loff_t len); | ||
10008 | +/* copies a dentry from dbstart to newbindex branch */ | ||
10009 | +extern int copyup_dentry(struct inode *dir, struct dentry *dentry, | ||
10010 | + int bstart, int new_bindex, const char *name, | ||
10011 | + int namelen, struct file **copyup_file, loff_t len); | ||
10012 | +/* helper functions for post-copyup actions */ | ||
10013 | +extern void unionfs_postcopyup_setmnt(struct dentry *dentry); | ||
10014 | +extern void unionfs_postcopyup_release(struct dentry *dentry); | ||
10015 | + | ||
10016 | +/* Is this directory empty: 0 if it is empty, -ENOTEMPTY if not. */ | ||
10017 | +extern int check_empty(struct dentry *dentry, struct dentry *parent, | ||
10018 | + struct unionfs_dir_state **namelist); | ||
10019 | +/* whiteout and opaque directory helpers */ | ||
10020 | +extern char *alloc_whname(const char *name, int len); | ||
10021 | +extern bool is_whiteout_name(char **namep, int *namelenp); | ||
10022 | +extern bool is_validname(const char *name); | ||
10023 | +extern struct dentry *lookup_whiteout(const char *name, | ||
10024 | + struct dentry *lower_parent); | ||
10025 | +extern struct dentry *find_first_whiteout(struct dentry *dentry); | ||
10026 | +extern int unlink_whiteout(struct dentry *wh_dentry); | ||
10027 | +extern int check_unlink_whiteout(struct dentry *dentry, | ||
10028 | + struct dentry *lower_dentry, int bindex); | ||
10029 | +extern int create_whiteout(struct dentry *dentry, int start); | ||
10030 | +extern int delete_whiteouts(struct dentry *dentry, int bindex, | ||
10031 | + struct unionfs_dir_state *namelist); | ||
10032 | +extern int is_opaque_dir(struct dentry *dentry, int bindex); | ||
10033 | +extern int make_dir_opaque(struct dentry *dir, int bindex); | ||
10034 | +extern void unionfs_set_max_namelen(long *namelen); | ||
10035 | + | ||
10036 | +extern void unionfs_reinterpose(struct dentry *this_dentry); | ||
10037 | +extern struct super_block *unionfs_duplicate_super(struct super_block *sb); | ||
10038 | + | ||
10039 | +/* Locking functions. */ | ||
10040 | +extern int unionfs_setlk(struct file *file, int cmd, struct file_lock *fl); | ||
10041 | +extern int unionfs_getlk(struct file *file, struct file_lock *fl); | ||
10042 | + | ||
10043 | +/* Common file operations. */ | ||
10044 | +extern int unionfs_file_revalidate(struct file *file, struct dentry *parent, | ||
10045 | + bool willwrite); | ||
10046 | +extern int unionfs_open(struct inode *inode, struct file *file); | ||
10047 | +extern int unionfs_file_release(struct inode *inode, struct file *file); | ||
10048 | +extern int unionfs_flush(struct file *file, fl_owner_t id); | ||
10049 | +extern long unionfs_ioctl(struct file *file, unsigned int cmd, | ||
10050 | + unsigned long arg); | ||
10051 | +extern int unionfs_fsync(struct file *file, int datasync); | ||
10052 | +extern int unionfs_fasync(int fd, struct file *file, int flag); | ||
10053 | + | ||
10054 | +/* Inode operations */ | ||
10055 | +extern struct inode *unionfs_iget(struct super_block *sb, unsigned long ino); | ||
10056 | +extern int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry, | ||
10057 | + struct inode *new_dir, struct dentry *new_dentry); | ||
10058 | +extern int unionfs_unlink(struct inode *dir, struct dentry *dentry); | ||
10059 | +extern int unionfs_rmdir(struct inode *dir, struct dentry *dentry); | ||
10060 | + | ||
10061 | +extern bool __unionfs_d_revalidate(struct dentry *dentry, | ||
10062 | + struct dentry *parent, bool willwrite); | ||
10063 | +extern bool is_negative_lower(const struct dentry *dentry); | ||
10064 | +extern bool is_newer_lower(const struct dentry *dentry); | ||
10065 | +extern void purge_sb_data(struct super_block *sb); | ||
10066 | + | ||
10067 | +/* The values for unionfs_interpose's flag. */ | ||
10068 | +#define INTERPOSE_DEFAULT 0 | ||
10069 | +#define INTERPOSE_LOOKUP 1 | ||
10070 | +#define INTERPOSE_REVAL 2 | ||
10071 | +#define INTERPOSE_REVAL_NEG 3 | ||
10072 | +#define INTERPOSE_PARTIAL 4 | ||
10073 | + | ||
10074 | +extern struct dentry *unionfs_interpose(struct dentry *this_dentry, | ||
10075 | + struct super_block *sb, int flag); | ||
10076 | + | ||
10077 | +#ifdef CONFIG_UNION_FS_XATTR | ||
10078 | +/* Extended attribute functions. */ | ||
10079 | +extern void *unionfs_xattr_alloc(size_t size, size_t limit); | ||
10080 | +static inline void unionfs_xattr_kfree(const void *p) | ||
10081 | +{ | ||
10082 | + kfree(p); | ||
10083 | +} | ||
10084 | +extern ssize_t unionfs_getxattr(struct dentry *dentry, const char *name, | ||
10085 | + void *value, size_t size); | ||
10086 | +extern int unionfs_removexattr(struct dentry *dentry, const char *name); | ||
10087 | +extern ssize_t unionfs_listxattr(struct dentry *dentry, char *list, | ||
10088 | + size_t size); | ||
10089 | +extern int unionfs_setxattr(struct dentry *dentry, const char *name, | ||
10090 | + const void *value, size_t size, int flags); | ||
10091 | +#endif /* CONFIG_UNION_FS_XATTR */ | ||
10092 | + | ||
10093 | +/* The root directory is unhashed, but isn't deleted. */ | ||
10094 | +static inline int d_deleted(struct dentry *d) | ||
10095 | +{ | ||
10096 | + return d_unhashed(d) && (d != d->d_sb->s_root); | ||
10097 | +} | ||
10098 | + | ||
10099 | +/* unionfs_permission, check if we should bypass error to facilitate copyup */ | ||
10100 | +#define IS_COPYUP_ERR(err) ((err) == -EROFS) | ||
10101 | + | ||
10102 | +/* unionfs_open, check if we need to copyup the file */ | ||
10103 | +#define OPEN_WRITE_FLAGS (O_WRONLY | O_RDWR | O_APPEND) | ||
10104 | +#define IS_WRITE_FLAG(flag) ((flag) & OPEN_WRITE_FLAGS) | ||
10105 | + | ||
10106 | +static inline int branchperms(const struct super_block *sb, int index) | ||
10107 | +{ | ||
10108 | + BUG_ON(index < 0); | ||
10109 | + return UNIONFS_SB(sb)->data[index].branchperms; | ||
10110 | +} | ||
10111 | + | ||
10112 | +static inline int set_branchperms(struct super_block *sb, int index, int perms) | ||
10113 | +{ | ||
10114 | + BUG_ON(index < 0); | ||
10115 | + UNIONFS_SB(sb)->data[index].branchperms = perms; | ||
10116 | + return perms; | ||
10117 | +} | ||
10118 | + | ||
10119 | +/* check if readonly lower inode, but possibly unlinked (no inode->i_sb) */ | ||
10120 | +static inline int __is_rdonly(const struct inode *inode) | ||
10121 | +{ | ||
10122 | + /* if unlinked, can't be readonly (?) */ | ||
10123 | + if (!inode->i_sb) | ||
10124 | + return 0; | ||
10125 | + return IS_RDONLY(inode); | ||
10126 | + | ||
10127 | +} | ||
10128 | +/* Is this file on a read-only branch? */ | ||
10129 | +static inline int is_robranch_super(const struct super_block *sb, int index) | ||
10130 | +{ | ||
10131 | + int ret; | ||
10132 | + | ||
10133 | + ret = (!(branchperms(sb, index) & MAY_WRITE)) ? -EROFS : 0; | ||
10134 | + return ret; | ||
10135 | +} | ||
10136 | + | ||
10137 | +/* Is this file on a read-only branch? */ | ||
10138 | +static inline int is_robranch_idx(const struct dentry *dentry, int index) | ||
10139 | +{ | ||
10140 | + struct super_block *lower_sb; | ||
10141 | + | ||
10142 | + BUG_ON(index < 0); | ||
10143 | + | ||
10144 | + if (!(branchperms(dentry->d_sb, index) & MAY_WRITE)) | ||
10145 | + return -EROFS; | ||
10146 | + | ||
10147 | + lower_sb = unionfs_lower_super_idx(dentry->d_sb, index); | ||
10148 | + BUG_ON(lower_sb == NULL); | ||
10149 | + /* | ||
10150 | + * test sb flags directly, not IS_RDONLY(lower_inode) because the | ||
10151 | + * lower_dentry could be a negative. | ||
10152 | + */ | ||
10153 | + if (lower_sb->s_flags & MS_RDONLY) | ||
10154 | + return -EROFS; | ||
10155 | + | ||
10156 | + return 0; | ||
10157 | +} | ||
10158 | + | ||
10159 | +static inline int is_robranch(const struct dentry *dentry) | ||
10160 | +{ | ||
10161 | + int index; | ||
10162 | + | ||
10163 | + index = UNIONFS_D(dentry)->bstart; | ||
10164 | + BUG_ON(index < 0); | ||
10165 | + | ||
10166 | + return is_robranch_idx(dentry, index); | ||
10167 | +} | ||
10168 | + | ||
10169 | +/* | ||
10170 | + * EXTERNALS: | ||
10171 | + */ | ||
10172 | +extern int check_branch(const struct path *path); | ||
10173 | +extern int parse_branch_mode(const char *name, int *perms); | ||
10174 | + | ||
10175 | +/* locking helpers */ | ||
10176 | +static inline struct dentry *lock_parent(struct dentry *dentry) | ||
10177 | +{ | ||
10178 | + struct dentry *dir = dget_parent(dentry); | ||
10179 | + mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); | ||
10180 | + return dir; | ||
10181 | +} | ||
10182 | +static inline struct dentry *lock_parent_wh(struct dentry *dentry) | ||
10183 | +{ | ||
10184 | + struct dentry *dir = dget_parent(dentry); | ||
10185 | + | ||
10186 | + mutex_lock_nested(&dir->d_inode->i_mutex, UNIONFS_DMUTEX_WHITEOUT); | ||
10187 | + return dir; | ||
10188 | +} | ||
10189 | + | ||
10190 | +static inline void unlock_dir(struct dentry *dir) | ||
10191 | +{ | ||
10192 | + mutex_unlock(&dir->d_inode->i_mutex); | ||
10193 | + dput(dir); | ||
10194 | +} | ||
10195 | + | ||
10196 | +/* lock base inode mutex before calling lookup_one_len */ | ||
10197 | +static inline struct dentry *lookup_lck_len(const char *name, | ||
10198 | + struct dentry *base, int len) | ||
10199 | +{ | ||
10200 | + struct dentry *d; | ||
10201 | + struct nameidata lower_nd; | ||
10202 | + int err; | ||
10203 | + | ||
10204 | + err = init_lower_nd(&lower_nd, LOOKUP_OPEN); | ||
10205 | + if (unlikely(err < 0)) { | ||
10206 | + d = ERR_PTR(err); | ||
10207 | + goto out; | ||
10208 | + } | ||
10209 | + mutex_lock(&base->d_inode->i_mutex); | ||
10210 | + d = lookup_one_len_nd(name, base, len, &lower_nd); | ||
10211 | + release_lower_nd(&lower_nd, err); | ||
10212 | + mutex_unlock(&base->d_inode->i_mutex); | ||
10213 | +out: | ||
10214 | + return d; | ||
10215 | +} | ||
10216 | + | ||
10217 | +static inline struct vfsmount *unionfs_mntget(struct dentry *dentry, | ||
10218 | + int bindex) | ||
10219 | +{ | ||
10220 | + struct vfsmount *mnt; | ||
10221 | + | ||
10222 | + BUG_ON(!dentry || bindex < 0); | ||
10223 | + | ||
10224 | + mnt = mntget(unionfs_lower_mnt_idx(dentry, bindex)); | ||
10225 | +#ifdef CONFIG_UNION_FS_DEBUG | ||
10226 | + if (!mnt) | ||
10227 | + pr_debug("unionfs: mntget: mnt=%p bindex=%d\n", | ||
10228 | + mnt, bindex); | ||
10229 | +#endif /* CONFIG_UNION_FS_DEBUG */ | ||
10230 | + | ||
10231 | + return mnt; | ||
10232 | +} | ||
10233 | + | ||
10234 | +static inline void unionfs_mntput(struct dentry *dentry, int bindex) | ||
10235 | +{ | ||
10236 | + struct vfsmount *mnt; | ||
10237 | + | ||
10238 | + if (!dentry && bindex < 0) | ||
10239 | + return; | ||
10240 | + BUG_ON(!dentry || bindex < 0); | ||
10241 | + | ||
10242 | + mnt = unionfs_lower_mnt_idx(dentry, bindex); | ||
10243 | +#ifdef CONFIG_UNION_FS_DEBUG | ||
10244 | + /* | ||
10245 | + * Directories can have NULL lower objects in between start/end, but | ||
10246 | + * NOT if at the start/end range. We cannot verify that this dentry | ||
10247 | + * is a type=DIR, because it may already be a negative dentry. But | ||
10248 | + * if dbstart is greater than dbend, we know that this couldn't have | ||
10249 | + * been a regular file: it had to have been a directory. | ||
10250 | + */ | ||
10251 | + if (!mnt && !(bindex > dbstart(dentry) && bindex < dbend(dentry))) | ||
10252 | + pr_debug("unionfs: mntput: mnt=%p bindex=%d\n", mnt, bindex); | ||
10253 | +#endif /* CONFIG_UNION_FS_DEBUG */ | ||
10254 | + mntput(mnt); | ||
10255 | +} | ||
10256 | + | ||
10257 | +#ifdef CONFIG_UNION_FS_DEBUG | ||
10258 | + | ||
10259 | +/* useful for tracking code reachability */ | ||
10260 | +#define UDBG pr_debug("DBG:%s:%s:%d\n", __FILE__, __func__, __LINE__) | ||
10261 | + | ||
10262 | +#define unionfs_check_inode(i) __unionfs_check_inode((i), \ | ||
10263 | + __FILE__, __func__, __LINE__) | ||
10264 | +#define unionfs_check_dentry(d) __unionfs_check_dentry((d), \ | ||
10265 | + __FILE__, __func__, __LINE__) | ||
10266 | +#define unionfs_check_file(f) __unionfs_check_file((f), \ | ||
10267 | + __FILE__, __func__, __LINE__) | ||
10268 | +#define unionfs_check_nd(n) __unionfs_check_nd((n), \ | ||
10269 | + __FILE__, __func__, __LINE__) | ||
10270 | +#define show_branch_counts(sb) __show_branch_counts((sb), \ | ||
10271 | + __FILE__, __func__, __LINE__) | ||
10272 | +#define show_inode_times(i) __show_inode_times((i), \ | ||
10273 | + __FILE__, __func__, __LINE__) | ||
10274 | +#define show_dinode_times(d) __show_dinode_times((d), \ | ||
10275 | + __FILE__, __func__, __LINE__) | ||
10276 | +#define show_inode_counts(i) __show_inode_counts((i), \ | ||
10277 | + __FILE__, __func__, __LINE__) | ||
10278 | + | ||
10279 | +extern void __unionfs_check_inode(const struct inode *inode, const char *fname, | ||
10280 | + const char *fxn, int line); | ||
10281 | +extern void __unionfs_check_dentry(const struct dentry *dentry, | ||
10282 | + const char *fname, const char *fxn, | ||
10283 | + int line); | ||
10284 | +extern void __unionfs_check_file(const struct file *file, | ||
10285 | + const char *fname, const char *fxn, int line); | ||
10286 | +extern void __unionfs_check_nd(const struct nameidata *nd, | ||
10287 | + const char *fname, const char *fxn, int line); | ||
10288 | +extern void __show_branch_counts(const struct super_block *sb, | ||
10289 | + const char *file, const char *fxn, int line); | ||
10290 | +extern void __show_inode_times(const struct inode *inode, | ||
10291 | + const char *file, const char *fxn, int line); | ||
10292 | +extern void __show_dinode_times(const struct dentry *dentry, | ||
10293 | + const char *file, const char *fxn, int line); | ||
10294 | +extern void __show_inode_counts(const struct inode *inode, | ||
10295 | + const char *file, const char *fxn, int line); | ||
10296 | + | ||
10297 | +#else /* not CONFIG_UNION_FS_DEBUG */ | ||
10298 | + | ||
10299 | +/* we leave useful hooks for these check functions throughout the code */ | ||
10300 | +#define unionfs_check_inode(i) do { } while (0) | ||
10301 | +#define unionfs_check_dentry(d) do { } while (0) | ||
10302 | +#define unionfs_check_file(f) do { } while (0) | ||
10303 | +#define unionfs_check_nd(n) do { } while (0) | ||
10304 | +#define show_branch_counts(sb) do { } while (0) | ||
10305 | +#define show_inode_times(i) do { } while (0) | ||
10306 | +#define show_dinode_times(d) do { } while (0) | ||
10307 | +#define show_inode_counts(i) do { } while (0) | ||
10308 | + | ||
10309 | +#endif /* not CONFIG_UNION_FS_DEBUG */ | ||
10310 | + | ||
10311 | +#endif /* not _UNION_H_ */ | ||
10312 | diff --git a/fs/unionfs/unlink.c b/fs/unionfs/unlink.c | ||
10313 | new file mode 100644 | ||
10314 | index 0000000..bf447bb | ||
10315 | --- /dev/null | ||
10316 | +++ b/fs/unionfs/unlink.c | ||
10317 | @@ -0,0 +1,278 @@ | ||
10318 | +/* | ||
10319 | + * Copyright (c) 2003-2011 Erez Zadok | ||
10320 | + * Copyright (c) 2003-2006 Charles P. Wright | ||
10321 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
10322 | + * Copyright (c) 2005-2006 Junjiro Okajima | ||
10323 | + * Copyright (c) 2005 Arun M. Krishnakumar | ||
10324 | + * Copyright (c) 2004-2006 David P. Quigley | ||
10325 | + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair | ||
10326 | + * Copyright (c) 2003 Puja Gupta | ||
10327 | + * Copyright (c) 2003 Harikesavan Krishnan | ||
10328 | + * Copyright (c) 2003-2011 Stony Brook University | ||
10329 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
10330 | + * | ||
10331 | + * This program is free software; you can redistribute it and/or modify | ||
10332 | + * it under the terms of the GNU General Public License version 2 as | ||
10333 | + * published by the Free Software Foundation. | ||
10334 | + */ | ||
10335 | + | ||
10336 | +#include "union.h" | ||
10337 | + | ||
10338 | +/* | ||
10339 | + * Helper function for Unionfs's unlink operation. | ||
10340 | + * | ||
10341 | + * The main goal of this function is to optimize the unlinking of non-dir | ||
10342 | + * objects in unionfs by deleting all possible lower inode objects from the | ||
10343 | + * underlying branches having same dentry name as the non-dir dentry on | ||
10344 | + * which this unlink operation is called. This way we delete as many lower | ||
10345 | + * inodes as possible, and save space. Whiteouts need to be created in | ||
10346 | + * branch0 only if unlinking fails on any of the lower branch other than | ||
10347 | + * branch0, or if a lower branch is marked read-only. | ||
10348 | + * | ||
10349 | + * Also, while unlinking a file, if we encounter any dir type entry in any | ||
10350 | + * intermediate branch, then we remove the directory by calling vfs_rmdir. | ||
10351 | + * The following special cases are also handled: | ||
10352 | + | ||
10353 | + * (1) If an error occurs in branch0 during vfs_unlink, then we return | ||
10354 | + * appropriate error. | ||
10355 | + * | ||
10356 | + * (2) If we get an error during unlink in any of other lower branch other | ||
10357 | + * than branch0, then we create a whiteout in branch0. | ||
10358 | + * | ||
10359 | + * (3) If a whiteout already exists in any intermediate branch, we delete | ||
10360 | + * all possible inodes only up to that branch (this is an "opaqueness" | ||
10361 | + * as as per Documentation/filesystems/unionfs/concepts.txt). | ||
10362 | + * | ||
10363 | + */ | ||
10364 | +static int unionfs_unlink_whiteout(struct inode *dir, struct dentry *dentry, | ||
10365 | + struct dentry *parent) | ||
10366 | +{ | ||
10367 | + struct dentry *lower_dentry; | ||
10368 | + struct dentry *lower_dir_dentry; | ||
10369 | + int bindex; | ||
10370 | + int err = 0; | ||
10371 | + | ||
10372 | + err = unionfs_partial_lookup(dentry, parent); | ||
10373 | + if (err) | ||
10374 | + goto out; | ||
10375 | + | ||
10376 | + /* trying to unlink all possible valid instances */ | ||
10377 | + for (bindex = dbstart(dentry); bindex <= dbend(dentry); bindex++) { | ||
10378 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
10379 | + if (!lower_dentry || !lower_dentry->d_inode) | ||
10380 | + continue; | ||
10381 | + | ||
10382 | + lower_dir_dentry = lock_parent(lower_dentry); | ||
10383 | + | ||
10384 | + /* avoid destroying the lower inode if the object is in use */ | ||
10385 | + dget(lower_dentry); | ||
10386 | + err = is_robranch_super(dentry->d_sb, bindex); | ||
10387 | + if (!err) { | ||
10388 | + /* see Documentation/filesystems/unionfs/issues.txt */ | ||
10389 | + lockdep_off(); | ||
10390 | + if (!S_ISDIR(lower_dentry->d_inode->i_mode)) | ||
10391 | + err = vfs_unlink(lower_dir_dentry->d_inode, | ||
10392 | + lower_dentry); | ||
10393 | + else | ||
10394 | + err = vfs_rmdir(lower_dir_dentry->d_inode, | ||
10395 | + lower_dentry); | ||
10396 | + lockdep_on(); | ||
10397 | + } | ||
10398 | + | ||
10399 | + /* if lower object deletion succeeds, update inode's times */ | ||
10400 | + if (!err) | ||
10401 | + unionfs_copy_attr_times(dentry->d_inode); | ||
10402 | + dput(lower_dentry); | ||
10403 | + fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); | ||
10404 | + unlock_dir(lower_dir_dentry); | ||
10405 | + | ||
10406 | + if (err) | ||
10407 | + break; | ||
10408 | + } | ||
10409 | + | ||
10410 | + /* | ||
10411 | + * Create the whiteout in branch 0 (highest priority) only if (a) | ||
10412 | + * there was an error in any intermediate branch other than branch 0 | ||
10413 | + * due to failure of vfs_unlink/vfs_rmdir or (b) a branch marked or | ||
10414 | + * mounted read-only. | ||
10415 | + */ | ||
10416 | + if (err) { | ||
10417 | + if ((bindex == 0) || | ||
10418 | + ((bindex == dbstart(dentry)) && | ||
10419 | + (!IS_COPYUP_ERR(err)))) | ||
10420 | + goto out; | ||
10421 | + else { | ||
10422 | + if (!IS_COPYUP_ERR(err)) | ||
10423 | + pr_debug("unionfs: lower object deletion " | ||
10424 | + "failed in branch:%d\n", bindex); | ||
10425 | + err = create_whiteout(dentry, sbstart(dentry->d_sb)); | ||
10426 | + } | ||
10427 | + } | ||
10428 | + | ||
10429 | +out: | ||
10430 | + if (!err) | ||
10431 | + inode_dec_link_count(dentry->d_inode); | ||
10432 | + | ||
10433 | + /* We don't want to leave negative leftover dentries for revalidate. */ | ||
10434 | + if (!err && (dbopaque(dentry) != -1)) | ||
10435 | + update_bstart(dentry); | ||
10436 | + | ||
10437 | + return err; | ||
10438 | +} | ||
10439 | + | ||
10440 | +int unionfs_unlink(struct inode *dir, struct dentry *dentry) | ||
10441 | +{ | ||
10442 | + int err = 0; | ||
10443 | + struct inode *inode = dentry->d_inode; | ||
10444 | + struct dentry *parent; | ||
10445 | + int valid; | ||
10446 | + | ||
10447 | + BUG_ON(S_ISDIR(inode->i_mode)); | ||
10448 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
10449 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
10450 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
10451 | + | ||
10452 | + valid = __unionfs_d_revalidate(dentry, parent, false); | ||
10453 | + if (unlikely(!valid)) { | ||
10454 | + err = -ESTALE; | ||
10455 | + goto out; | ||
10456 | + } | ||
10457 | + unionfs_check_dentry(dentry); | ||
10458 | + | ||
10459 | + err = unionfs_unlink_whiteout(dir, dentry, parent); | ||
10460 | + /* call d_drop so the system "forgets" about us */ | ||
10461 | + if (!err) { | ||
10462 | + unionfs_postcopyup_release(dentry); | ||
10463 | + unionfs_postcopyup_setmnt(parent); | ||
10464 | + if (inode->i_nlink == 0) /* drop lower inodes */ | ||
10465 | + iput_lowers_all(inode, false); | ||
10466 | + d_drop(dentry); | ||
10467 | + /* | ||
10468 | + * if unlink/whiteout succeeded, parent dir mtime has | ||
10469 | + * changed | ||
10470 | + */ | ||
10471 | + unionfs_copy_attr_times(dir); | ||
10472 | + } | ||
10473 | + | ||
10474 | +out: | ||
10475 | + if (!err) { | ||
10476 | + unionfs_check_dentry(dentry); | ||
10477 | + unionfs_check_inode(dir); | ||
10478 | + } | ||
10479 | + unionfs_unlock_dentry(dentry); | ||
10480 | + unionfs_unlock_parent(dentry, parent); | ||
10481 | + unionfs_read_unlock(dentry->d_sb); | ||
10482 | + return err; | ||
10483 | +} | ||
10484 | + | ||
10485 | +static int unionfs_rmdir_first(struct inode *dir, struct dentry *dentry, | ||
10486 | + struct unionfs_dir_state *namelist) | ||
10487 | +{ | ||
10488 | + int err; | ||
10489 | + struct dentry *lower_dentry; | ||
10490 | + struct dentry *lower_dir_dentry = NULL; | ||
10491 | + | ||
10492 | + /* Here we need to remove whiteout entries. */ | ||
10493 | + err = delete_whiteouts(dentry, dbstart(dentry), namelist); | ||
10494 | + if (err) | ||
10495 | + goto out; | ||
10496 | + | ||
10497 | + lower_dentry = unionfs_lower_dentry(dentry); | ||
10498 | + | ||
10499 | + lower_dir_dentry = lock_parent(lower_dentry); | ||
10500 | + | ||
10501 | + /* avoid destroying the lower inode if the file is in use */ | ||
10502 | + dget(lower_dentry); | ||
10503 | + err = is_robranch(dentry); | ||
10504 | + if (!err) | ||
10505 | + err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); | ||
10506 | + dput(lower_dentry); | ||
10507 | + | ||
10508 | + fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); | ||
10509 | + /* propagate number of hard-links */ | ||
10510 | + dentry->d_inode->i_nlink = unionfs_get_nlinks(dentry->d_inode); | ||
10511 | + | ||
10512 | +out: | ||
10513 | + if (lower_dir_dentry) | ||
10514 | + unlock_dir(lower_dir_dentry); | ||
10515 | + return err; | ||
10516 | +} | ||
10517 | + | ||
10518 | +int unionfs_rmdir(struct inode *dir, struct dentry *dentry) | ||
10519 | +{ | ||
10520 | + int err = 0; | ||
10521 | + struct unionfs_dir_state *namelist = NULL; | ||
10522 | + struct dentry *parent; | ||
10523 | + int dstart, dend; | ||
10524 | + bool valid; | ||
10525 | + | ||
10526 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
10527 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
10528 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
10529 | + | ||
10530 | + valid = __unionfs_d_revalidate(dentry, parent, false); | ||
10531 | + if (unlikely(!valid)) { | ||
10532 | + err = -ESTALE; | ||
10533 | + goto out; | ||
10534 | + } | ||
10535 | + unionfs_check_dentry(dentry); | ||
10536 | + | ||
10537 | + /* check if this unionfs directory is empty or not */ | ||
10538 | + err = check_empty(dentry, parent, &namelist); | ||
10539 | + if (err) | ||
10540 | + goto out; | ||
10541 | + | ||
10542 | + err = unionfs_rmdir_first(dir, dentry, namelist); | ||
10543 | + dstart = dbstart(dentry); | ||
10544 | + dend = dbend(dentry); | ||
10545 | + /* | ||
10546 | + * We create a whiteout for the directory if there was an error to | ||
10547 | + * rmdir the first directory entry in the union. Otherwise, we | ||
10548 | + * create a whiteout only if there is no chance that a lower | ||
10549 | + * priority branch might also have the same named directory. IOW, | ||
10550 | + * if there is not another same-named directory at a lower priority | ||
10551 | + * branch, then we don't need to create a whiteout for it. | ||
10552 | + */ | ||
10553 | + if (!err) { | ||
10554 | + if (dstart < dend) | ||
10555 | + err = create_whiteout(dentry, dstart); | ||
10556 | + } else { | ||
10557 | + int new_err; | ||
10558 | + | ||
10559 | + if (dstart == 0) | ||
10560 | + goto out; | ||
10561 | + | ||
10562 | + /* exit if the error returned was NOT -EROFS */ | ||
10563 | + if (!IS_COPYUP_ERR(err)) | ||
10564 | + goto out; | ||
10565 | + | ||
10566 | + new_err = create_whiteout(dentry, dstart - 1); | ||
10567 | + if (new_err != -EEXIST) | ||
10568 | + err = new_err; | ||
10569 | + } | ||
10570 | + | ||
10571 | +out: | ||
10572 | + /* | ||
10573 | + * Drop references to lower dentry/inode so storage space for them | ||
10574 | + * can be reclaimed. Then, call d_drop so the system "forgets" | ||
10575 | + * about us. | ||
10576 | + */ | ||
10577 | + if (!err) { | ||
10578 | + iput_lowers_all(dentry->d_inode, false); | ||
10579 | + dput(unionfs_lower_dentry_idx(dentry, dstart)); | ||
10580 | + unionfs_set_lower_dentry_idx(dentry, dstart, NULL); | ||
10581 | + d_drop(dentry); | ||
10582 | + /* update our lower vfsmnts, in case a copyup took place */ | ||
10583 | + unionfs_postcopyup_setmnt(dentry); | ||
10584 | + unionfs_check_dentry(dentry); | ||
10585 | + unionfs_check_inode(dir); | ||
10586 | + } | ||
10587 | + | ||
10588 | + if (namelist) | ||
10589 | + free_rdstate(namelist); | ||
10590 | + | ||
10591 | + unionfs_unlock_dentry(dentry); | ||
10592 | + unionfs_unlock_parent(dentry, parent); | ||
10593 | + unionfs_read_unlock(dentry->d_sb); | ||
10594 | + return err; | ||
10595 | +} | ||
10596 | diff --git a/fs/unionfs/whiteout.c b/fs/unionfs/whiteout.c | ||
10597 | new file mode 100644 | ||
10598 | index 0000000..582cef2 | ||
10599 | --- /dev/null | ||
10600 | +++ b/fs/unionfs/whiteout.c | ||
10601 | @@ -0,0 +1,601 @@ | ||
10602 | +/* | ||
10603 | + * Copyright (c) 2003-2011 Erez Zadok | ||
10604 | + * Copyright (c) 2003-2006 Charles P. Wright | ||
10605 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
10606 | + * Copyright (c) 2005-2006 Junjiro Okajima | ||
10607 | + * Copyright (c) 2005 Arun M. Krishnakumar | ||
10608 | + * Copyright (c) 2004-2006 David P. Quigley | ||
10609 | + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair | ||
10610 | + * Copyright (c) 2003 Puja Gupta | ||
10611 | + * Copyright (c) 2003 Harikesavan Krishnan | ||
10612 | + * Copyright (c) 2003-2011 Stony Brook University | ||
10613 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
10614 | + * | ||
10615 | + * This program is free software; you can redistribute it and/or modify | ||
10616 | + * it under the terms of the GNU General Public License version 2 as | ||
10617 | + * published by the Free Software Foundation. | ||
10618 | + */ | ||
10619 | + | ||
10620 | +#include "union.h" | ||
10621 | + | ||
10622 | +/* | ||
10623 | + * whiteout and opaque directory helpers | ||
10624 | + */ | ||
10625 | + | ||
10626 | +/* What do we use for whiteouts. */ | ||
10627 | +#define UNIONFS_WHPFX ".wh." | ||
10628 | +#define UNIONFS_WHLEN 4 | ||
10629 | +/* | ||
10630 | + * If a directory contains this file, then it is opaque. We start with the | ||
10631 | + * .wh. flag so that it is blocked by lookup. | ||
10632 | + */ | ||
10633 | +#define UNIONFS_DIR_OPAQUE_NAME "__dir_opaque" | ||
10634 | +#define UNIONFS_DIR_OPAQUE UNIONFS_WHPFX UNIONFS_DIR_OPAQUE_NAME | ||
10635 | + | ||
10636 | +/* construct whiteout filename */ | ||
10637 | +char *alloc_whname(const char *name, int len) | ||
10638 | +{ | ||
10639 | + char *buf; | ||
10640 | + | ||
10641 | + buf = kmalloc(len + UNIONFS_WHLEN + 1, GFP_KERNEL); | ||
10642 | + if (unlikely(!buf)) | ||
10643 | + return ERR_PTR(-ENOMEM); | ||
10644 | + | ||
10645 | + strcpy(buf, UNIONFS_WHPFX); | ||
10646 | + strlcat(buf, name, len + UNIONFS_WHLEN + 1); | ||
10647 | + | ||
10648 | + return buf; | ||
10649 | +} | ||
10650 | + | ||
10651 | +/* | ||
10652 | + * XXX: this can be inline or CPP macro, but is here to keep all whiteout | ||
10653 | + * code in one place. | ||
10654 | + */ | ||
10655 | +void unionfs_set_max_namelen(long *namelen) | ||
10656 | +{ | ||
10657 | + *namelen -= UNIONFS_WHLEN; | ||
10658 | +} | ||
10659 | + | ||
10660 | +/* check if @namep is a whiteout, update @namep and @namelenp accordingly */ | ||
10661 | +bool is_whiteout_name(char **namep, int *namelenp) | ||
10662 | +{ | ||
10663 | + if (*namelenp > UNIONFS_WHLEN && | ||
10664 | + !strncmp(*namep, UNIONFS_WHPFX, UNIONFS_WHLEN)) { | ||
10665 | + *namep += UNIONFS_WHLEN; | ||
10666 | + *namelenp -= UNIONFS_WHLEN; | ||
10667 | + return true; | ||
10668 | + } | ||
10669 | + return false; | ||
10670 | +} | ||
10671 | + | ||
10672 | +/* is the filename valid == !(whiteout for a file or opaque dir marker) */ | ||
10673 | +bool is_validname(const char *name) | ||
10674 | +{ | ||
10675 | + if (!strncmp(name, UNIONFS_WHPFX, UNIONFS_WHLEN)) | ||
10676 | + return false; | ||
10677 | + if (!strncmp(name, UNIONFS_DIR_OPAQUE_NAME, | ||
10678 | + sizeof(UNIONFS_DIR_OPAQUE_NAME) - 1)) | ||
10679 | + return false; | ||
10680 | + return true; | ||
10681 | +} | ||
10682 | + | ||
10683 | +/* | ||
10684 | + * Look for a whiteout @name in @lower_parent directory. If error, return | ||
10685 | + * ERR_PTR. Caller must dput() the returned dentry if not an error. | ||
10686 | + * | ||
10687 | + * XXX: some callers can reuse the whname allocated buffer to avoid repeated | ||
10688 | + * free then re-malloc calls. Need to provide a different API for those | ||
10689 | + * callers. | ||
10690 | + */ | ||
10691 | +struct dentry *lookup_whiteout(const char *name, struct dentry *lower_parent) | ||
10692 | +{ | ||
10693 | + char *whname = NULL; | ||
10694 | + int err = 0, namelen; | ||
10695 | + struct dentry *wh_dentry = NULL; | ||
10696 | + | ||
10697 | + namelen = strlen(name); | ||
10698 | + whname = alloc_whname(name, namelen); | ||
10699 | + if (unlikely(IS_ERR(whname))) { | ||
10700 | + err = PTR_ERR(whname); | ||
10701 | + goto out; | ||
10702 | + } | ||
10703 | + | ||
10704 | + /* check if whiteout exists in this branch: lookup .wh.foo */ | ||
10705 | + wh_dentry = lookup_lck_len(whname, lower_parent, strlen(whname)); | ||
10706 | + if (IS_ERR(wh_dentry)) { | ||
10707 | + err = PTR_ERR(wh_dentry); | ||
10708 | + goto out; | ||
10709 | + } | ||
10710 | + | ||
10711 | + /* check if negative dentry (ENOENT) */ | ||
10712 | + if (!wh_dentry->d_inode) | ||
10713 | + goto out; | ||
10714 | + | ||
10715 | + /* whiteout found: check if valid type */ | ||
10716 | + if (!S_ISREG(wh_dentry->d_inode->i_mode)) { | ||
10717 | + printk(KERN_ERR "unionfs: invalid whiteout %s entry type %d\n", | ||
10718 | + whname, wh_dentry->d_inode->i_mode); | ||
10719 | + dput(wh_dentry); | ||
10720 | + err = -EIO; | ||
10721 | + goto out; | ||
10722 | + } | ||
10723 | + | ||
10724 | +out: | ||
10725 | + kfree(whname); | ||
10726 | + if (err) | ||
10727 | + wh_dentry = ERR_PTR(err); | ||
10728 | + return wh_dentry; | ||
10729 | +} | ||
10730 | + | ||
10731 | +/* find and return first whiteout in parent directory, else ENOENT */ | ||
10732 | +struct dentry *find_first_whiteout(struct dentry *dentry) | ||
10733 | +{ | ||
10734 | + int bindex, bstart, bend; | ||
10735 | + struct dentry *parent, *lower_parent, *wh_dentry; | ||
10736 | + | ||
10737 | + parent = dget_parent(dentry); | ||
10738 | + | ||
10739 | + bstart = dbstart(parent); | ||
10740 | + bend = dbend(parent); | ||
10741 | + wh_dentry = ERR_PTR(-ENOENT); | ||
10742 | + | ||
10743 | + for (bindex = bstart; bindex <= bend; bindex++) { | ||
10744 | + lower_parent = unionfs_lower_dentry_idx(parent, bindex); | ||
10745 | + if (!lower_parent) | ||
10746 | + continue; | ||
10747 | + wh_dentry = lookup_whiteout(dentry->d_name.name, lower_parent); | ||
10748 | + if (IS_ERR(wh_dentry)) | ||
10749 | + continue; | ||
10750 | + if (wh_dentry->d_inode) | ||
10751 | + break; | ||
10752 | + dput(wh_dentry); | ||
10753 | + wh_dentry = ERR_PTR(-ENOENT); | ||
10754 | + } | ||
10755 | + | ||
10756 | + dput(parent); | ||
10757 | + | ||
10758 | + return wh_dentry; | ||
10759 | +} | ||
10760 | + | ||
10761 | +/* | ||
10762 | + * Unlink a whiteout dentry. Returns 0 or -errno. Caller must hold and | ||
10763 | + * release dentry reference. | ||
10764 | + */ | ||
10765 | +int unlink_whiteout(struct dentry *wh_dentry) | ||
10766 | +{ | ||
10767 | + int err; | ||
10768 | + struct dentry *lower_dir_dentry; | ||
10769 | + | ||
10770 | + /* dget and lock parent dentry */ | ||
10771 | + lower_dir_dentry = lock_parent_wh(wh_dentry); | ||
10772 | + | ||
10773 | + /* see Documentation/filesystems/unionfs/issues.txt */ | ||
10774 | + lockdep_off(); | ||
10775 | + err = vfs_unlink(lower_dir_dentry->d_inode, wh_dentry); | ||
10776 | + lockdep_on(); | ||
10777 | + unlock_dir(lower_dir_dentry); | ||
10778 | + | ||
10779 | + /* | ||
10780 | + * Whiteouts are special files and should be deleted no matter what | ||
10781 | + * (as if they never existed), in order to allow this create | ||
10782 | + * operation to succeed. This is especially important in sticky | ||
10783 | + * directories: a whiteout may have been created by one user, but | ||
10784 | + * the newly created file may be created by another user. | ||
10785 | + * Therefore, in order to maintain Unix semantics, if the vfs_unlink | ||
10786 | + * above failed, then we have to try to directly unlink the | ||
10787 | + * whiteout. Note: in the ODF version of unionfs, whiteout are | ||
10788 | + * handled much more cleanly. | ||
10789 | + */ | ||
10790 | + if (err == -EPERM) { | ||
10791 | + struct inode *inode = lower_dir_dentry->d_inode; | ||
10792 | + err = inode->i_op->unlink(inode, wh_dentry); | ||
10793 | + } | ||
10794 | + if (err) | ||
10795 | + printk(KERN_ERR "unionfs: could not unlink whiteout %s, " | ||
10796 | + "err = %d\n", wh_dentry->d_name.name, err); | ||
10797 | + | ||
10798 | + return err; | ||
10799 | + | ||
10800 | +} | ||
10801 | + | ||
10802 | +/* | ||
10803 | + * Helper function when creating new objects (create, symlink, mknod, etc.). | ||
10804 | + * Checks to see if there's a whiteout in @lower_dentry's parent directory, | ||
10805 | + * whose name is taken from @dentry. Then tries to remove that whiteout, if | ||
10806 | + * found. If <dentry,bindex> is a branch marked readonly, return -EROFS. | ||
10807 | + * If it finds both a regular file and a whiteout, delete whiteout (this | ||
10808 | + * should never happen). | ||
10809 | + * | ||
10810 | + * Return 0 if no whiteout was found. Return 1 if one was found and | ||
10811 | + * successfully removed. Therefore a value >= 0 tells the caller that | ||
10812 | + * @lower_dentry belongs to a good branch to create the new object in). | ||
10813 | + * Return -ERRNO if an error occurred during whiteout lookup or in trying to | ||
10814 | + * unlink the whiteout. | ||
10815 | + */ | ||
10816 | +int check_unlink_whiteout(struct dentry *dentry, struct dentry *lower_dentry, | ||
10817 | + int bindex) | ||
10818 | +{ | ||
10819 | + int err; | ||
10820 | + struct dentry *wh_dentry = NULL; | ||
10821 | + struct dentry *lower_dir_dentry = NULL; | ||
10822 | + | ||
10823 | + /* look for whiteout dentry first */ | ||
10824 | + lower_dir_dentry = dget_parent(lower_dentry); | ||
10825 | + wh_dentry = lookup_whiteout(dentry->d_name.name, lower_dir_dentry); | ||
10826 | + dput(lower_dir_dentry); | ||
10827 | + if (IS_ERR(wh_dentry)) { | ||
10828 | + err = PTR_ERR(wh_dentry); | ||
10829 | + goto out; | ||
10830 | + } | ||
10831 | + | ||
10832 | + if (!wh_dentry->d_inode) { /* no whiteout exists*/ | ||
10833 | + err = 0; | ||
10834 | + goto out_dput; | ||
10835 | + } | ||
10836 | + | ||
10837 | + /* check if regular file and whiteout were both found */ | ||
10838 | + if (unlikely(lower_dentry->d_inode)) | ||
10839 | + printk(KERN_WARNING "unionfs: removing whiteout; regular " | ||
10840 | + "file exists in directory %s (branch %d)\n", | ||
10841 | + lower_dir_dentry->d_name.name, bindex); | ||
10842 | + | ||
10843 | + /* check if branch is writeable */ | ||
10844 | + err = is_robranch_super(dentry->d_sb, bindex); | ||
10845 | + if (err) | ||
10846 | + goto out_dput; | ||
10847 | + | ||
10848 | + /* .wh.foo has been found, so let's unlink it */ | ||
10849 | + err = unlink_whiteout(wh_dentry); | ||
10850 | + if (!err) | ||
10851 | + err = 1; /* a whiteout was found and successfully removed */ | ||
10852 | +out_dput: | ||
10853 | + dput(wh_dentry); | ||
10854 | +out: | ||
10855 | + return err; | ||
10856 | +} | ||
10857 | + | ||
10858 | +/* | ||
10859 | + * Pass an unionfs dentry and an index. It will try to create a whiteout | ||
10860 | + * for the filename in dentry, and will try in branch 'index'. On error, | ||
10861 | + * it will proceed to a branch to the left. | ||
10862 | + */ | ||
10863 | +int create_whiteout(struct dentry *dentry, int start) | ||
10864 | +{ | ||
10865 | + int bstart, bend, bindex; | ||
10866 | + struct dentry *lower_dir_dentry; | ||
10867 | + struct dentry *lower_dentry; | ||
10868 | + struct dentry *lower_wh_dentry; | ||
10869 | + struct nameidata nd; | ||
10870 | + char *name = NULL; | ||
10871 | + int err = -EINVAL; | ||
10872 | + | ||
10873 | + verify_locked(dentry); | ||
10874 | + | ||
10875 | + bstart = dbstart(dentry); | ||
10876 | + bend = dbend(dentry); | ||
10877 | + | ||
10878 | + /* create dentry's whiteout equivalent */ | ||
10879 | + name = alloc_whname(dentry->d_name.name, dentry->d_name.len); | ||
10880 | + if (unlikely(IS_ERR(name))) { | ||
10881 | + err = PTR_ERR(name); | ||
10882 | + goto out; | ||
10883 | + } | ||
10884 | + | ||
10885 | + for (bindex = start; bindex >= 0; bindex--) { | ||
10886 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
10887 | + | ||
10888 | + if (!lower_dentry) { | ||
10889 | + /* | ||
10890 | + * if lower dentry is not present, create the | ||
10891 | + * entire lower dentry directory structure and go | ||
10892 | + * ahead. Since we want to just create whiteout, we | ||
10893 | + * only want the parent dentry, and hence get rid of | ||
10894 | + * this dentry. | ||
10895 | + */ | ||
10896 | + lower_dentry = create_parents(dentry->d_inode, | ||
10897 | + dentry, | ||
10898 | + dentry->d_name.name, | ||
10899 | + bindex); | ||
10900 | + if (!lower_dentry || IS_ERR(lower_dentry)) { | ||
10901 | + int ret = PTR_ERR(lower_dentry); | ||
10902 | + if (!IS_COPYUP_ERR(ret)) | ||
10903 | + printk(KERN_ERR | ||
10904 | + "unionfs: create_parents for " | ||
10905 | + "whiteout failed: bindex=%d " | ||
10906 | + "err=%d\n", bindex, ret); | ||
10907 | + continue; | ||
10908 | + } | ||
10909 | + } | ||
10910 | + | ||
10911 | + lower_wh_dentry = | ||
10912 | + lookup_lck_len(name, lower_dentry->d_parent, | ||
10913 | + dentry->d_name.len + UNIONFS_WHLEN); | ||
10914 | + if (IS_ERR(lower_wh_dentry)) | ||
10915 | + continue; | ||
10916 | + | ||
10917 | + /* | ||
10918 | + * The whiteout already exists. This used to be impossible, | ||
10919 | + * but now is possible because of opaqueness. | ||
10920 | + */ | ||
10921 | + if (lower_wh_dentry->d_inode) { | ||
10922 | + dput(lower_wh_dentry); | ||
10923 | + err = 0; | ||
10924 | + goto out; | ||
10925 | + } | ||
10926 | + | ||
10927 | + err = init_lower_nd(&nd, LOOKUP_CREATE); | ||
10928 | + if (unlikely(err < 0)) | ||
10929 | + goto out; | ||
10930 | + lower_dir_dentry = lock_parent_wh(lower_wh_dentry); | ||
10931 | + err = is_robranch_super(dentry->d_sb, bindex); | ||
10932 | + if (!err) | ||
10933 | + err = vfs_create(lower_dir_dentry->d_inode, | ||
10934 | + lower_wh_dentry, | ||
10935 | + current_umask() & S_IRUGO, | ||
10936 | + &nd); | ||
10937 | + unlock_dir(lower_dir_dentry); | ||
10938 | + dput(lower_wh_dentry); | ||
10939 | + release_lower_nd(&nd, err); | ||
10940 | + | ||
10941 | + if (!err || !IS_COPYUP_ERR(err)) | ||
10942 | + break; | ||
10943 | + } | ||
10944 | + | ||
10945 | + /* set dbopaque so that lookup will not proceed after this branch */ | ||
10946 | + if (!err) | ||
10947 | + dbopaque(dentry) = bindex; | ||
10948 | + | ||
10949 | +out: | ||
10950 | + kfree(name); | ||
10951 | + return err; | ||
10952 | +} | ||
10953 | + | ||
10954 | +/* | ||
10955 | + * Delete all of the whiteouts in a given directory for rmdir. | ||
10956 | + * | ||
10957 | + * lower directory inode should be locked | ||
10958 | + */ | ||
10959 | +static int do_delete_whiteouts(struct dentry *dentry, int bindex, | ||
10960 | + struct unionfs_dir_state *namelist) | ||
10961 | +{ | ||
10962 | + int err = 0; | ||
10963 | + struct dentry *lower_dir_dentry = NULL; | ||
10964 | + struct dentry *lower_dentry; | ||
10965 | + char *name = NULL, *p; | ||
10966 | + struct inode *lower_dir; | ||
10967 | + int i; | ||
10968 | + struct list_head *pos; | ||
10969 | + struct filldir_node *cursor; | ||
10970 | + | ||
10971 | + /* Find out lower parent dentry */ | ||
10972 | + lower_dir_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
10973 | + BUG_ON(!S_ISDIR(lower_dir_dentry->d_inode->i_mode)); | ||
10974 | + lower_dir = lower_dir_dentry->d_inode; | ||
10975 | + BUG_ON(!S_ISDIR(lower_dir->i_mode)); | ||
10976 | + | ||
10977 | + err = -ENOMEM; | ||
10978 | + name = __getname(); | ||
10979 | + if (unlikely(!name)) | ||
10980 | + goto out; | ||
10981 | + strcpy(name, UNIONFS_WHPFX); | ||
10982 | + p = name + UNIONFS_WHLEN; | ||
10983 | + | ||
10984 | + err = 0; | ||
10985 | + for (i = 0; !err && i < namelist->size; i++) { | ||
10986 | + list_for_each(pos, &namelist->list[i]) { | ||
10987 | + cursor = | ||
10988 | + list_entry(pos, struct filldir_node, | ||
10989 | + file_list); | ||
10990 | + /* Only operate on whiteouts in this branch. */ | ||
10991 | + if (cursor->bindex != bindex) | ||
10992 | + continue; | ||
10993 | + if (!cursor->whiteout) | ||
10994 | + continue; | ||
10995 | + | ||
10996 | + strlcpy(p, cursor->name, PATH_MAX - UNIONFS_WHLEN); | ||
10997 | + lower_dentry = | ||
10998 | + lookup_lck_len(name, lower_dir_dentry, | ||
10999 | + cursor->namelen + | ||
11000 | + UNIONFS_WHLEN); | ||
11001 | + if (IS_ERR(lower_dentry)) { | ||
11002 | + err = PTR_ERR(lower_dentry); | ||
11003 | + break; | ||
11004 | + } | ||
11005 | + if (lower_dentry->d_inode) | ||
11006 | + err = vfs_unlink(lower_dir, lower_dentry); | ||
11007 | + dput(lower_dentry); | ||
11008 | + if (err) | ||
11009 | + break; | ||
11010 | + } | ||
11011 | + } | ||
11012 | + | ||
11013 | + __putname(name); | ||
11014 | + | ||
11015 | + /* After all of the removals, we should copy the attributes once. */ | ||
11016 | + fsstack_copy_attr_times(dentry->d_inode, lower_dir_dentry->d_inode); | ||
11017 | + | ||
11018 | +out: | ||
11019 | + return err; | ||
11020 | +} | ||
11021 | + | ||
11022 | + | ||
11023 | +void __delete_whiteouts(struct work_struct *work) | ||
11024 | +{ | ||
11025 | + struct sioq_args *args = container_of(work, struct sioq_args, work); | ||
11026 | + struct deletewh_args *d = &args->deletewh; | ||
11027 | + | ||
11028 | + args->err = do_delete_whiteouts(d->dentry, d->bindex, d->namelist); | ||
11029 | + complete(&args->comp); | ||
11030 | +} | ||
11031 | + | ||
11032 | +/* delete whiteouts in a dir (for rmdir operation) using sioq if necessary */ | ||
11033 | +int delete_whiteouts(struct dentry *dentry, int bindex, | ||
11034 | + struct unionfs_dir_state *namelist) | ||
11035 | +{ | ||
11036 | + int err; | ||
11037 | + struct super_block *sb; | ||
11038 | + struct dentry *lower_dir_dentry; | ||
11039 | + struct inode *lower_dir; | ||
11040 | + struct sioq_args args; | ||
11041 | + | ||
11042 | + sb = dentry->d_sb; | ||
11043 | + | ||
11044 | + BUG_ON(!S_ISDIR(dentry->d_inode->i_mode)); | ||
11045 | + BUG_ON(bindex < dbstart(dentry)); | ||
11046 | + BUG_ON(bindex > dbend(dentry)); | ||
11047 | + err = is_robranch_super(sb, bindex); | ||
11048 | + if (err) | ||
11049 | + goto out; | ||
11050 | + | ||
11051 | + lower_dir_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
11052 | + BUG_ON(!S_ISDIR(lower_dir_dentry->d_inode->i_mode)); | ||
11053 | + lower_dir = lower_dir_dentry->d_inode; | ||
11054 | + BUG_ON(!S_ISDIR(lower_dir->i_mode)); | ||
11055 | + | ||
11056 | + if (!inode_permission(lower_dir, MAY_WRITE | MAY_EXEC)) { | ||
11057 | + err = do_delete_whiteouts(dentry, bindex, namelist); | ||
11058 | + } else { | ||
11059 | + args.deletewh.namelist = namelist; | ||
11060 | + args.deletewh.dentry = dentry; | ||
11061 | + args.deletewh.bindex = bindex; | ||
11062 | + run_sioq(__delete_whiteouts, &args); | ||
11063 | + err = args.err; | ||
11064 | + } | ||
11065 | + | ||
11066 | +out: | ||
11067 | + return err; | ||
11068 | +} | ||
11069 | + | ||
11070 | +/**************************************************************************** | ||
11071 | + * Opaque directory helpers * | ||
11072 | + ****************************************************************************/ | ||
11073 | + | ||
11074 | +/* | ||
11075 | + * is_opaque_dir: returns 0 if it is NOT an opaque dir, 1 if it is, and | ||
11076 | + * -errno if an error occurred trying to figure this out. | ||
11077 | + */ | ||
11078 | +int is_opaque_dir(struct dentry *dentry, int bindex) | ||
11079 | +{ | ||
11080 | + int err = 0; | ||
11081 | + struct dentry *lower_dentry; | ||
11082 | + struct dentry *wh_lower_dentry; | ||
11083 | + struct inode *lower_inode; | ||
11084 | + struct sioq_args args; | ||
11085 | + struct nameidata lower_nd; | ||
11086 | + | ||
11087 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
11088 | + lower_inode = lower_dentry->d_inode; | ||
11089 | + | ||
11090 | + BUG_ON(!S_ISDIR(lower_inode->i_mode)); | ||
11091 | + | ||
11092 | + mutex_lock(&lower_inode->i_mutex); | ||
11093 | + | ||
11094 | + if (!inode_permission(lower_inode, MAY_EXEC)) { | ||
11095 | + err = init_lower_nd(&lower_nd, LOOKUP_OPEN); | ||
11096 | + if (unlikely(err < 0)) { | ||
11097 | + mutex_unlock(&lower_inode->i_mutex); | ||
11098 | + goto out; | ||
11099 | + } | ||
11100 | + wh_lower_dentry = | ||
11101 | + lookup_one_len_nd(UNIONFS_DIR_OPAQUE, lower_dentry, | ||
11102 | + sizeof(UNIONFS_DIR_OPAQUE) - 1, | ||
11103 | + &lower_nd); | ||
11104 | + release_lower_nd(&lower_nd, err); | ||
11105 | + } else { | ||
11106 | + args.is_opaque.dentry = lower_dentry; | ||
11107 | + run_sioq(__is_opaque_dir, &args); | ||
11108 | + wh_lower_dentry = args.ret; | ||
11109 | + } | ||
11110 | + | ||
11111 | + mutex_unlock(&lower_inode->i_mutex); | ||
11112 | + | ||
11113 | + if (IS_ERR(wh_lower_dentry)) { | ||
11114 | + err = PTR_ERR(wh_lower_dentry); | ||
11115 | + goto out; | ||
11116 | + } | ||
11117 | + | ||
11118 | + /* This is an opaque dir iff wh_lower_dentry is positive */ | ||
11119 | + err = !!wh_lower_dentry->d_inode; | ||
11120 | + | ||
11121 | + dput(wh_lower_dentry); | ||
11122 | +out: | ||
11123 | + return err; | ||
11124 | +} | ||
11125 | + | ||
11126 | +void __is_opaque_dir(struct work_struct *work) | ||
11127 | +{ | ||
11128 | + struct sioq_args *args = container_of(work, struct sioq_args, work); | ||
11129 | + struct nameidata lower_nd; | ||
11130 | + int err; | ||
11131 | + | ||
11132 | + err = init_lower_nd(&lower_nd, LOOKUP_OPEN); | ||
11133 | + if (unlikely(err < 0)) | ||
11134 | + return; | ||
11135 | + args->ret = lookup_one_len_nd(UNIONFS_DIR_OPAQUE, | ||
11136 | + args->is_opaque.dentry, | ||
11137 | + sizeof(UNIONFS_DIR_OPAQUE) - 1, | ||
11138 | + &lower_nd); | ||
11139 | + release_lower_nd(&lower_nd, err); | ||
11140 | + complete(&args->comp); | ||
11141 | +} | ||
11142 | + | ||
11143 | +int make_dir_opaque(struct dentry *dentry, int bindex) | ||
11144 | +{ | ||
11145 | + int err = 0; | ||
11146 | + struct dentry *lower_dentry, *diropq; | ||
11147 | + struct inode *lower_dir; | ||
11148 | + struct nameidata nd; | ||
11149 | + const struct cred *old_creds; | ||
11150 | + struct cred *new_creds; | ||
11151 | + | ||
11152 | + /* | ||
11153 | + * Opaque directory whiteout markers are special files (like regular | ||
11154 | + * whiteouts), and should appear to the users as if they don't | ||
11155 | + * exist. They should be created/deleted regardless of directory | ||
11156 | + * search/create permissions, but only for the duration of this | ||
11157 | + * creation of the .wh.__dir_opaque: file. Note, this does not | ||
11158 | + * circumvent normal ->permission). | ||
11159 | + */ | ||
11160 | + new_creds = prepare_creds(); | ||
11161 | + if (unlikely(!new_creds)) { | ||
11162 | + err = -ENOMEM; | ||
11163 | + goto out_err; | ||
11164 | + } | ||
11165 | + cap_raise(new_creds->cap_effective, CAP_DAC_READ_SEARCH); | ||
11166 | + cap_raise(new_creds->cap_effective, CAP_DAC_OVERRIDE); | ||
11167 | + old_creds = override_creds(new_creds); | ||
11168 | + | ||
11169 | + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); | ||
11170 | + lower_dir = lower_dentry->d_inode; | ||
11171 | + BUG_ON(!S_ISDIR(dentry->d_inode->i_mode) || | ||
11172 | + !S_ISDIR(lower_dir->i_mode)); | ||
11173 | + | ||
11174 | + mutex_lock(&lower_dir->i_mutex); | ||
11175 | + err = init_lower_nd(&nd, LOOKUP_OPEN); | ||
11176 | + if (unlikely(err < 0)) | ||
11177 | + goto out; | ||
11178 | + diropq = lookup_one_len_nd(UNIONFS_DIR_OPAQUE, lower_dentry, | ||
11179 | + sizeof(UNIONFS_DIR_OPAQUE) - 1, &nd); | ||
11180 | + release_lower_nd(&nd, err); | ||
11181 | + if (IS_ERR(diropq)) { | ||
11182 | + err = PTR_ERR(diropq); | ||
11183 | + goto out; | ||
11184 | + } | ||
11185 | + | ||
11186 | + err = init_lower_nd(&nd, LOOKUP_CREATE); | ||
11187 | + if (unlikely(err < 0)) | ||
11188 | + goto out; | ||
11189 | + if (!diropq->d_inode) | ||
11190 | + err = vfs_create(lower_dir, diropq, S_IRUGO, &nd); | ||
11191 | + if (!err) | ||
11192 | + dbopaque(dentry) = bindex; | ||
11193 | + release_lower_nd(&nd, err); | ||
11194 | + | ||
11195 | + dput(diropq); | ||
11196 | + | ||
11197 | +out: | ||
11198 | + mutex_unlock(&lower_dir->i_mutex); | ||
11199 | + revert_creds(old_creds); | ||
11200 | +out_err: | ||
11201 | + return err; | ||
11202 | +} | ||
11203 | diff --git a/fs/unionfs/xattr.c b/fs/unionfs/xattr.c | ||
11204 | new file mode 100644 | ||
11205 | index 0000000..a93d803 | ||
11206 | --- /dev/null | ||
11207 | +++ b/fs/unionfs/xattr.c | ||
11208 | @@ -0,0 +1,173 @@ | ||
11209 | +/* | ||
11210 | + * Copyright (c) 2003-2011 Erez Zadok | ||
11211 | + * Copyright (c) 2003-2006 Charles P. Wright | ||
11212 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
11213 | + * Copyright (c) 2005-2006 Junjiro Okajima | ||
11214 | + * Copyright (c) 2005 Arun M. Krishnakumar | ||
11215 | + * Copyright (c) 2004-2006 David P. Quigley | ||
11216 | + * Copyright (c) 2003-2004 Mohammad Nayyer Zubair | ||
11217 | + * Copyright (c) 2003 Puja Gupta | ||
11218 | + * Copyright (c) 2003 Harikesavan Krishnan | ||
11219 | + * Copyright (c) 2003-2011 Stony Brook University | ||
11220 | + * Copyright (c) 2003-2011 The Research Foundation of SUNY | ||
11221 | + * | ||
11222 | + * This program is free software; you can redistribute it and/or modify | ||
11223 | + * it under the terms of the GNU General Public License version 2 as | ||
11224 | + * published by the Free Software Foundation. | ||
11225 | + */ | ||
11226 | + | ||
11227 | +#include "union.h" | ||
11228 | + | ||
11229 | +/* This is lifted from fs/xattr.c */ | ||
11230 | +void *unionfs_xattr_alloc(size_t size, size_t limit) | ||
11231 | +{ | ||
11232 | + void *ptr; | ||
11233 | + | ||
11234 | + if (size > limit) | ||
11235 | + return ERR_PTR(-E2BIG); | ||
11236 | + | ||
11237 | + if (!size) /* size request, no buffer is needed */ | ||
11238 | + return NULL; | ||
11239 | + | ||
11240 | + ptr = kmalloc(size, GFP_KERNEL); | ||
11241 | + if (unlikely(!ptr)) | ||
11242 | + return ERR_PTR(-ENOMEM); | ||
11243 | + return ptr; | ||
11244 | +} | ||
11245 | + | ||
11246 | +/* | ||
11247 | + * BKL held by caller. | ||
11248 | + * dentry->d_inode->i_mutex locked | ||
11249 | + */ | ||
11250 | +ssize_t unionfs_getxattr(struct dentry *dentry, const char *name, void *value, | ||
11251 | + size_t size) | ||
11252 | +{ | ||
11253 | + struct dentry *lower_dentry = NULL; | ||
11254 | + struct dentry *parent; | ||
11255 | + int err = -EOPNOTSUPP; | ||
11256 | + bool valid; | ||
11257 | + | ||
11258 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
11259 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
11260 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
11261 | + | ||
11262 | + valid = __unionfs_d_revalidate(dentry, parent, false); | ||
11263 | + if (unlikely(!valid)) { | ||
11264 | + err = -ESTALE; | ||
11265 | + goto out; | ||
11266 | + } | ||
11267 | + | ||
11268 | + lower_dentry = unionfs_lower_dentry(dentry); | ||
11269 | + | ||
11270 | + err = vfs_getxattr(lower_dentry, (char *) name, value, size); | ||
11271 | + | ||
11272 | +out: | ||
11273 | + unionfs_check_dentry(dentry); | ||
11274 | + unionfs_unlock_dentry(dentry); | ||
11275 | + unionfs_unlock_parent(dentry, parent); | ||
11276 | + unionfs_read_unlock(dentry->d_sb); | ||
11277 | + return err; | ||
11278 | +} | ||
11279 | + | ||
11280 | +/* | ||
11281 | + * BKL held by caller. | ||
11282 | + * dentry->d_inode->i_mutex locked | ||
11283 | + */ | ||
11284 | +int unionfs_setxattr(struct dentry *dentry, const char *name, | ||
11285 | + const void *value, size_t size, int flags) | ||
11286 | +{ | ||
11287 | + struct dentry *lower_dentry = NULL; | ||
11288 | + struct dentry *parent; | ||
11289 | + int err = -EOPNOTSUPP; | ||
11290 | + bool valid; | ||
11291 | + | ||
11292 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
11293 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
11294 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
11295 | + | ||
11296 | + valid = __unionfs_d_revalidate(dentry, parent, false); | ||
11297 | + if (unlikely(!valid)) { | ||
11298 | + err = -ESTALE; | ||
11299 | + goto out; | ||
11300 | + } | ||
11301 | + | ||
11302 | + lower_dentry = unionfs_lower_dentry(dentry); | ||
11303 | + | ||
11304 | + err = vfs_setxattr(lower_dentry, (char *) name, (void *) value, | ||
11305 | + size, flags); | ||
11306 | + | ||
11307 | +out: | ||
11308 | + unionfs_check_dentry(dentry); | ||
11309 | + unionfs_unlock_dentry(dentry); | ||
11310 | + unionfs_unlock_parent(dentry, parent); | ||
11311 | + unionfs_read_unlock(dentry->d_sb); | ||
11312 | + return err; | ||
11313 | +} | ||
11314 | + | ||
11315 | +/* | ||
11316 | + * BKL held by caller. | ||
11317 | + * dentry->d_inode->i_mutex locked | ||
11318 | + */ | ||
11319 | +int unionfs_removexattr(struct dentry *dentry, const char *name) | ||
11320 | +{ | ||
11321 | + struct dentry *lower_dentry = NULL; | ||
11322 | + struct dentry *parent; | ||
11323 | + int err = -EOPNOTSUPP; | ||
11324 | + bool valid; | ||
11325 | + | ||
11326 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
11327 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
11328 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
11329 | + | ||
11330 | + valid = __unionfs_d_revalidate(dentry, parent, false); | ||
11331 | + if (unlikely(!valid)) { | ||
11332 | + err = -ESTALE; | ||
11333 | + goto out; | ||
11334 | + } | ||
11335 | + | ||
11336 | + lower_dentry = unionfs_lower_dentry(dentry); | ||
11337 | + | ||
11338 | + err = vfs_removexattr(lower_dentry, (char *) name); | ||
11339 | + | ||
11340 | +out: | ||
11341 | + unionfs_check_dentry(dentry); | ||
11342 | + unionfs_unlock_dentry(dentry); | ||
11343 | + unionfs_unlock_parent(dentry, parent); | ||
11344 | + unionfs_read_unlock(dentry->d_sb); | ||
11345 | + return err; | ||
11346 | +} | ||
11347 | + | ||
11348 | +/* | ||
11349 | + * BKL held by caller. | ||
11350 | + * dentry->d_inode->i_mutex locked | ||
11351 | + */ | ||
11352 | +ssize_t unionfs_listxattr(struct dentry *dentry, char *list, size_t size) | ||
11353 | +{ | ||
11354 | + struct dentry *lower_dentry = NULL; | ||
11355 | + struct dentry *parent; | ||
11356 | + int err = -EOPNOTSUPP; | ||
11357 | + char *encoded_list = NULL; | ||
11358 | + bool valid; | ||
11359 | + | ||
11360 | + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD); | ||
11361 | + parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); | ||
11362 | + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); | ||
11363 | + | ||
11364 | + valid = __unionfs_d_revalidate(dentry, parent, false); | ||
11365 | + if (unlikely(!valid)) { | ||
11366 | + err = -ESTALE; | ||
11367 | + goto out; | ||
11368 | + } | ||
11369 | + | ||
11370 | + lower_dentry = unionfs_lower_dentry(dentry); | ||
11371 | + | ||
11372 | + encoded_list = list; | ||
11373 | + err = vfs_listxattr(lower_dentry, encoded_list, size); | ||
11374 | + | ||
11375 | +out: | ||
11376 | + unionfs_check_dentry(dentry); | ||
11377 | + unionfs_unlock_dentry(dentry); | ||
11378 | + unionfs_unlock_parent(dentry, parent); | ||
11379 | + unionfs_read_unlock(dentry->d_sb); | ||
11380 | + return err; | ||
11381 | +} | ||
11382 | diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h | ||
11383 | index da317c7..64f1ced 100644 | ||
11384 | --- a/include/linux/fs_stack.h | ||
11385 | +++ b/include/linux/fs_stack.h | ||
11386 | @@ -1,7 +1,19 @@ | ||
11387 | +/* | ||
11388 | + * Copyright (c) 2006-2009 Erez Zadok | ||
11389 | + * Copyright (c) 2006-2007 Josef 'Jeff' Sipek | ||
11390 | + * Copyright (c) 2006-2009 Stony Brook University | ||
11391 | + * Copyright (c) 2006-2009 The Research Foundation of SUNY | ||
11392 | + * | ||
11393 | + * This program is free software; you can redistribute it and/or modify | ||
11394 | + * it under the terms of the GNU General Public License version 2 as | ||
11395 | + * published by the Free Software Foundation. | ||
11396 | + */ | ||
11397 | + | ||
11398 | #ifndef _LINUX_FS_STACK_H | ||
11399 | #define _LINUX_FS_STACK_H | ||
11400 | |||
11401 | -/* This file defines generic functions used primarily by stackable | ||
11402 | +/* | ||
11403 | + * This file defines generic functions used primarily by stackable | ||
11404 | * filesystems; none of these functions require i_mutex to be held. | ||
11405 | */ | ||
11406 | |||
11407 | diff --git a/include/linux/magic.h b/include/linux/magic.h | ||
11408 | index 1e5df2a..01ee54d 100644 | ||
11409 | --- a/include/linux/magic.h | ||
11410 | +++ b/include/linux/magic.h | ||
11411 | @@ -50,6 +50,8 @@ | ||
11412 | #define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs" | ||
11413 | #define REISER2FS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs" | ||
11414 | |||
11415 | +#define UNIONFS_SUPER_MAGIC 0xf15f083d | ||
11416 | + | ||
11417 | #define SMB_SUPER_MAGIC 0x517B | ||
11418 | #define USBDEVICE_SUPER_MAGIC 0x9fa2 | ||
11419 | #define CGROUP_SUPER_MAGIC 0x27e0eb | ||
11420 | diff --git a/include/linux/namei.h b/include/linux/namei.h | ||
11421 | index eba45ea..8e19e9c 100644 | ||
11422 | --- a/include/linux/namei.h | ||
11423 | +++ b/include/linux/namei.h | ||
11424 | @@ -81,8 +81,11 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *, | ||
11425 | |||
11426 | extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry, | ||
11427 | int (*open)(struct inode *, struct file *)); | ||
11428 | +extern void release_open_intent(struct nameidata *); | ||
11429 | |||
11430 | extern struct dentry *lookup_one_len(const char *, struct dentry *, int); | ||
11431 | +extern struct dentry *lookup_one_len_nd(const char *, struct dentry *, int, | ||
11432 | + struct nameidata *nd); | ||
11433 | |||
11434 | extern int follow_down_one(struct path *); | ||
11435 | extern int follow_down(struct path *); | ||
11436 | diff --git a/include/linux/splice.h b/include/linux/splice.h | ||
11437 | index 997c3b4..54f5501 100644 | ||
11438 | --- a/include/linux/splice.h | ||
11439 | +++ b/include/linux/splice.h | ||
11440 | @@ -81,6 +81,11 @@ extern ssize_t splice_to_pipe(struct pipe_inode_info *, | ||
11441 | struct splice_pipe_desc *); | ||
11442 | extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *, | ||
11443 | splice_direct_actor *); | ||
11444 | +extern long vfs_splice_from(struct pipe_inode_info *pipe, struct file *out, | ||
11445 | + loff_t *ppos, size_t len, unsigned int flags); | ||
11446 | +extern long vfs_splice_to(struct file *in, loff_t *ppos, | ||
11447 | + struct pipe_inode_info *pipe, size_t len, | ||
11448 | + unsigned int flags); | ||
11449 | |||
11450 | /* | ||
11451 | * for dynamic pipe sizing | ||
11452 | diff --git a/include/linux/union_fs.h b/include/linux/union_fs.h | ||
11453 | new file mode 100644 | ||
11454 | index 0000000..c84d97e | ||
11455 | --- /dev/null | ||
11456 | +++ b/include/linux/union_fs.h | ||
11457 | @@ -0,0 +1,22 @@ | ||
11458 | +/* | ||
11459 | + * Copyright (c) 2003-2009 Erez Zadok | ||
11460 | + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek | ||
11461 | + * Copyright (c) 2003-2009 Stony Brook University | ||
11462 | + * Copyright (c) 2003-2009 The Research Foundation of SUNY | ||
11463 | + * | ||
11464 | + * This program is free software; you can redistribute it and/or modify | ||
11465 | + * it under the terms of the GNU General Public License version 2 as | ||
11466 | + * published by the Free Software Foundation. | ||
11467 | + */ | ||
11468 | + | ||
11469 | +#ifndef _LINUX_UNION_FS_H | ||
11470 | +#define _LINUX_UNION_FS_H | ||
11471 | + | ||
11472 | +/* | ||
11473 | + * DEFINITIONS FOR USER AND KERNEL CODE: | ||
11474 | + */ | ||
11475 | +# define UNIONFS_IOCTL_INCGEN _IOR(0x15, 11, int) | ||
11476 | +# define UNIONFS_IOCTL_QUERYFILE _IOR(0x15, 15, int) | ||
11477 | + | ||
11478 | +#endif /* _LINUX_UNIONFS_H */ | ||
11479 | + | ||
11480 | diff --git a/security/security.c b/security/security.c | ||
11481 | index 4ba6d4c..093d8b4 100644 | ||
11482 | --- a/security/security.c | ||
11483 | +++ b/security/security.c | ||
11484 | @@ -520,6 +520,7 @@ int security_inode_permission(struct inode *inode, int mask) | ||
11485 | return 0; | ||
11486 | return security_ops->inode_permission(inode, mask, 0); | ||
11487 | } | ||
11488 | +EXPORT_SYMBOL(security_inode_permission); | ||
11489 | |||
11490 | int security_inode_exec_permission(struct inode *inode, unsigned int flags) | ||
11491 | { | ||
11492 | -- | ||
11493 | 1.6.6.1 | ||
11494 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0030-omap-Change-omap_device-activate-latency-messages-fr.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0030-omap-Change-omap_device-activate-latency-messages-fr.patch deleted file mode 100644 index 7dc80905..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0030-omap-Change-omap_device-activate-latency-messages-fr.patch +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | From 728b784863056a2b2e35134f71082271ebab0892 Mon Sep 17 00:00:00 2001 | ||
2 | From: Steve Sakoman <steve@sakoman.com> | ||
3 | Date: Mon, 23 May 2011 12:16:50 -0700 | ||
4 | Subject: [PATCH 30/32] omap: Change omap_device activate latency messages from pr_warning to pr_debug | ||
5 | |||
6 | Messages can be safely ignored, so reduce console noise | ||
7 | |||
8 | Signed-off-by: Steve Sakoman <steve@sakoman.com> | ||
9 | --- | ||
10 | arch/arm/plat-omap/omap_device.c | 4 ++-- | ||
11 | 1 files changed, 2 insertions(+), 2 deletions(-) | ||
12 | |||
13 | diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c | ||
14 | index 9bbda9a..ca8a479 100644 | ||
15 | --- a/arch/arm/plat-omap/omap_device.c | ||
16 | +++ b/arch/arm/plat-omap/omap_device.c | ||
17 | @@ -145,12 +145,12 @@ static int _omap_device_activate(struct omap_device *od, u8 ignore_lat) | ||
18 | odpl->activate_lat_worst = act_lat; | ||
19 | if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) { | ||
20 | odpl->activate_lat = act_lat; | ||
21 | - pr_warning("omap_device: %s.%d: new worst case " | ||
22 | + pr_debug("omap_device: %s.%d: new worst case " | ||
23 | "activate latency %d: %llu\n", | ||
24 | od->pdev.name, od->pdev.id, | ||
25 | od->pm_lat_level, act_lat); | ||
26 | } else | ||
27 | - pr_warning("omap_device: %s.%d: activate " | ||
28 | + pr_debug("omap_device: %s.%d: activate " | ||
29 | "latency %d higher than exptected. " | ||
30 | "(%llu > %d)\n", | ||
31 | od->pdev.name, od->pdev.id, | ||
32 | -- | ||
33 | 1.6.6.1 | ||
34 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0031-omap-overo-Add-opp-init.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0031-omap-overo-Add-opp-init.patch deleted file mode 100644 index 07df7634..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0031-omap-overo-Add-opp-init.patch +++ /dev/null | |||
@@ -1,105 +0,0 @@ | |||
1 | From 530abfee962141f263344b4de3ca48b57e5e514c Mon Sep 17 00:00:00 2001 | ||
2 | From: Steve Sakoman <steve@sakoman.com> | ||
3 | Date: Tue, 24 May 2011 20:36:07 -0700 | ||
4 | Subject: [PATCH 31/32] omap: overo: Add opp init | ||
5 | |||
6 | omap: overo: Add opp init | ||
7 | |||
8 | Work in progress | ||
9 | |||
10 | Signed-off-by: Steve Sakoman <steve@sakoman.com> | ||
11 | --- | ||
12 | arch/arm/mach-omap2/board-overo.c | 49 +++++++++++++++++++++++++++++++++++++ | ||
13 | 1 files changed, 49 insertions(+), 0 deletions(-) | ||
14 | |||
15 | diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c | ||
16 | index 05dd3eb..8c2d21f 100644 | ||
17 | --- a/arch/arm/mach-omap2/board-overo.c | ||
18 | +++ b/arch/arm/mach-omap2/board-overo.c | ||
19 | @@ -25,6 +25,7 @@ | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/kernel.h> | ||
23 | +#include <linux/opp.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/i2c/twl.h> | ||
26 | #include <linux/regulator/machine.h> | ||
27 | @@ -43,6 +44,7 @@ | ||
28 | |||
29 | #include <plat/board.h> | ||
30 | #include <plat/common.h> | ||
31 | +#include <plat/omap_device.h> | ||
32 | #include <plat/display.h> | ||
33 | #include <plat/panel-generic-dpi.h> | ||
34 | #include <mach/gpio.h> | ||
35 | @@ -54,6 +56,7 @@ | ||
36 | #include <plat/usb.h> | ||
37 | |||
38 | #include "mux.h" | ||
39 | +#include "pm.h" | ||
40 | #include "sdram-micron-mt46h32m32lf-6.h" | ||
41 | #include "hsmmc.h" | ||
42 | |||
43 | @@ -755,6 +758,51 @@ static struct omap_musb_board_data musb_board_data = { | ||
44 | .power = 100, | ||
45 | }; | ||
46 | |||
47 | +static void __init overo_opp_init(void) | ||
48 | +{ | ||
49 | + int r = 0; | ||
50 | + | ||
51 | + /* Initialize the omap3 opp table */ | ||
52 | + if (omap3_opp_init()) { | ||
53 | + pr_err("%s: opp default init failed\n", __func__); | ||
54 | + return; | ||
55 | + } | ||
56 | + | ||
57 | + /* Custom OPP enabled for 36/3730 */ | ||
58 | + if (cpu_is_omap3630()) { | ||
59 | + struct omap_hwmod *mh = omap_hwmod_lookup("mpu"); | ||
60 | + struct omap_hwmod *dh = omap_hwmod_lookup("iva"); | ||
61 | + struct device *dev; | ||
62 | + | ||
63 | + if (!mh || !dh) { | ||
64 | + pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n", | ||
65 | + __func__, mh, dh); | ||
66 | + return; | ||
67 | + } | ||
68 | + /* Enable MPU 1GHz and lower opps */ | ||
69 | + dev = &mh->od->pdev.dev; | ||
70 | + r = opp_enable(dev, 1000000000); | ||
71 | + | ||
72 | + /* Enable IVA 800MHz and lower opps */ | ||
73 | + dev = &dh->od->pdev.dev; | ||
74 | + r |= opp_enable(dev, 800000000); | ||
75 | + | ||
76 | + if (r) { | ||
77 | + pr_err("%s: failed to enable higher opp %d\n", | ||
78 | + __func__, r); | ||
79 | + /* | ||
80 | + * Cleanup - disable the higher freqs - we dont care | ||
81 | + * about the results | ||
82 | + */ | ||
83 | + dev = &mh->od->pdev.dev; | ||
84 | + opp_disable(dev, 1000000000); | ||
85 | + dev = &dh->od->pdev.dev; | ||
86 | + opp_disable(dev, 800000000); | ||
87 | + } | ||
88 | + } | ||
89 | + return; | ||
90 | +} | ||
91 | + | ||
92 | static void __init overo_init(void) | ||
93 | { | ||
94 | omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); | ||
95 | @@ -770,6 +818,7 @@ static void __init overo_init(void) | ||
96 | overo_display_init(); | ||
97 | overo_init_led(); | ||
98 | overo_init_keys(); | ||
99 | + overo_opp_init(); | ||
100 | |||
101 | /* Ensure SDRC pins are mux'd for self-refresh */ | ||
102 | omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); | ||
103 | -- | ||
104 | 1.6.6.1 | ||
105 | |||
diff --git a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0032-omap3-Add-basic-support-for-720MHz-part.patch b/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0032-omap3-Add-basic-support-for-720MHz-part.patch deleted file mode 100644 index 9a9320d7..00000000 --- a/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0032-omap3-Add-basic-support-for-720MHz-part.patch +++ /dev/null | |||
@@ -1,202 +0,0 @@ | |||
1 | From cd9682b39f41675c4e551c607425226b38fab17d Mon Sep 17 00:00:00 2001 | ||
2 | From: Sanjeev Premi <premi@ti.com> | ||
3 | Date: Tue, 18 Jan 2011 13:19:55 +0530 | ||
4 | Subject: [PATCH 32/32] omap3: Add basic support for 720MHz part | ||
5 | |||
6 | This patch adds support for new speed enhanced parts with ARM | ||
7 | and IVA running at 720MHz and 520MHz respectively. These parts | ||
8 | can be probed at run-time by reading PRODID.SKUID[3:0] at | ||
9 | 0x4830A20C [1]. | ||
10 | |||
11 | This patch specifically does following: | ||
12 | * Detect devices capable of 720MHz. | ||
13 | * Add new OPP | ||
14 | * Ensure that OPP is conditionally enabled. | ||
15 | * Check for presence of IVA before attempting to enable | ||
16 | the corresponding OPP. | ||
17 | |||
18 | [1] http://focus.ti.com/lit/ug/spruff1d/spruff1d.pdf | ||
19 | |||
20 | Signed-off-by: Sanjeev Premi <premi@ti.com> | ||
21 | --- | ||
22 | arch/arm/mach-omap2/control.h | 7 ++++ | ||
23 | arch/arm/mach-omap2/id.c | 10 +++++ | ||
24 | arch/arm/mach-omap2/opp3xxx_data.c | 63 ++++++++++++++++++++++++++++++++- | ||
25 | arch/arm/plat-omap/include/plat/cpu.h | 2 + | ||
26 | 4 files changed, 81 insertions(+), 1 deletions(-) | ||
27 | |||
28 | diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h | ||
29 | index c2804c1..6edd7cc 100644 | ||
30 | --- a/arch/arm/mach-omap2/control.h | ||
31 | +++ b/arch/arm/mach-omap2/control.h | ||
32 | @@ -371,6 +371,13 @@ | ||
33 | #define FEAT_NEON 0 | ||
34 | #define FEAT_NEON_NONE 1 | ||
35 | |||
36 | +/* | ||
37 | + * Product ID register | ||
38 | + */ | ||
39 | +#define OMAP3_PRODID 0x020C | ||
40 | + | ||
41 | +#define OMAP3_SKUID_MASK 0x0f | ||
42 | +#define OMAP3_SKUID_720MHZ 0x08 | ||
43 | |||
44 | #ifndef __ASSEMBLY__ | ||
45 | #ifdef CONFIG_ARCH_OMAP2PLUS | ||
46 | diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c | ||
47 | index 2537090..b6ed78a 100644 | ||
48 | --- a/arch/arm/mach-omap2/id.c | ||
49 | +++ b/arch/arm/mach-omap2/id.c | ||
50 | @@ -210,6 +210,15 @@ static void __init omap3_check_features(void) | ||
51 | * TODO: Get additional info (where applicable) | ||
52 | * e.g. Size of L2 cache. | ||
53 | */ | ||
54 | + | ||
55 | + /* | ||
56 | + * Does it support 720MHz? | ||
57 | + */ | ||
58 | + status = (OMAP3_SKUID_MASK & read_tap_reg(OMAP3_PRODID)); | ||
59 | + | ||
60 | + if (status & OMAP3_SKUID_720MHZ) { | ||
61 | + omap3_features |= OMAP3_HAS_720MHZ; | ||
62 | + } | ||
63 | } | ||
64 | |||
65 | static void __init ti816x_check_features(void) | ||
66 | @@ -490,6 +499,7 @@ static void __init omap3_cpuinfo(void) | ||
67 | OMAP3_SHOW_FEATURE(neon); | ||
68 | OMAP3_SHOW_FEATURE(isp); | ||
69 | OMAP3_SHOW_FEATURE(192mhz_clk); | ||
70 | + OMAP3_SHOW_FEATURE(720mhz); | ||
71 | |||
72 | printk(")\n"); | ||
73 | } | ||
74 | diff --git a/arch/arm/mach-omap2/opp3xxx_data.c b/arch/arm/mach-omap2/opp3xxx_data.c | ||
75 | index d95f3f9..44fbc84 100644 | ||
76 | --- a/arch/arm/mach-omap2/opp3xxx_data.c | ||
77 | +++ b/arch/arm/mach-omap2/opp3xxx_data.c | ||
78 | @@ -18,8 +18,10 @@ | ||
79 | * GNU General Public License for more details. | ||
80 | */ | ||
81 | #include <linux/module.h> | ||
82 | +#include <linux/opp.h> | ||
83 | |||
84 | #include <plat/cpu.h> | ||
85 | +#include <plat/omap_device.h> | ||
86 | |||
87 | #include "control.h" | ||
88 | #include "omap_opp_data.h" | ||
89 | @@ -98,6 +100,8 @@ static struct omap_opp_def __initdata omap34xx_opp_def_list[] = { | ||
90 | OPP_INITIALIZER("mpu", true, 550000000, OMAP3430_VDD_MPU_OPP4_UV), | ||
91 | /* MPU OPP5 */ | ||
92 | OPP_INITIALIZER("mpu", true, 600000000, OMAP3430_VDD_MPU_OPP5_UV), | ||
93 | + /* MPU OPP6 */ | ||
94 | + OPP_INITIALIZER("mpu", false, 720000000, 1350000), | ||
95 | |||
96 | /* | ||
97 | * L3 OPP1 - 41.5 MHz is disabled because: The voltage for that OPP is | ||
98 | @@ -123,6 +127,8 @@ static struct omap_opp_def __initdata omap34xx_opp_def_list[] = { | ||
99 | OPP_INITIALIZER("iva", true, 400000000, OMAP3430_VDD_MPU_OPP4_UV), | ||
100 | /* DSP OPP5 */ | ||
101 | OPP_INITIALIZER("iva", true, 430000000, OMAP3430_VDD_MPU_OPP5_UV), | ||
102 | + /* DSP OPP6 */ | ||
103 | + OPP_INITIALIZER("iva", false, 520000000, 1350000), | ||
104 | }; | ||
105 | |||
106 | static struct omap_opp_def __initdata omap36xx_opp_def_list[] = { | ||
107 | @@ -150,6 +156,57 @@ static struct omap_opp_def __initdata omap36xx_opp_def_list[] = { | ||
108 | OPP_INITIALIZER("iva", false, 800000000, OMAP3630_VDD_MPU_OPP1G_UV), | ||
109 | }; | ||
110 | |||
111 | + | ||
112 | +/** | ||
113 | + * omap3_opp_enable_720Mhz() - Enable the OPP corresponding to 720MHz | ||
114 | + * | ||
115 | + * This function would be executed only if the silicon is capable of | ||
116 | + * running at the 720MHz. | ||
117 | + */ | ||
118 | +static int __init omap3_opp_enable_720Mhz(void) | ||
119 | +{ | ||
120 | + int r = -ENODEV; | ||
121 | + struct omap_hwmod *oh_mpu = omap_hwmod_lookup("mpu"); | ||
122 | + struct omap_hwmod *oh_iva; | ||
123 | + struct platform_device *pdev; | ||
124 | + | ||
125 | + if (!oh_mpu || !oh_mpu->od) { | ||
126 | + goto err; | ||
127 | + } else { | ||
128 | + pdev = &oh_mpu->od->pdev; | ||
129 | + | ||
130 | + r = opp_enable(&pdev->dev, 720000000); | ||
131 | + if (r < 0) { | ||
132 | + dev_err(&pdev->dev, | ||
133 | + "opp_enable() failed for mpu@720MHz"); | ||
134 | + goto err; | ||
135 | + } | ||
136 | + } | ||
137 | + | ||
138 | + if (omap3_has_iva()) { | ||
139 | + oh_iva = omap_hwmod_lookup("iva"); | ||
140 | + | ||
141 | + if (!oh_iva || !oh_iva->od) { | ||
142 | + r = -ENODEV; | ||
143 | + goto err; | ||
144 | + } else { | ||
145 | + pdev = &oh_iva->od->pdev; | ||
146 | + | ||
147 | + r = opp_enable(&pdev->dev, 520000000); | ||
148 | + if (r < 0) { | ||
149 | + dev_err(&pdev->dev, | ||
150 | + "opp_enable() failed for iva@520MHz"); | ||
151 | + goto err; | ||
152 | + } | ||
153 | + } | ||
154 | + } | ||
155 | + | ||
156 | + dev_info(&pdev->dev, "Enabled OPP corresponding to 720MHz\n"); | ||
157 | + | ||
158 | +err: | ||
159 | + return r; | ||
160 | +} | ||
161 | + | ||
162 | /** | ||
163 | * omap3_opp_init() - initialize omap3 opp table | ||
164 | */ | ||
165 | @@ -163,10 +220,14 @@ int __init omap3_opp_init(void) | ||
166 | if (cpu_is_omap3630()) | ||
167 | r = omap_init_opp_table(omap36xx_opp_def_list, | ||
168 | ARRAY_SIZE(omap36xx_opp_def_list)); | ||
169 | - else | ||
170 | + else { | ||
171 | r = omap_init_opp_table(omap34xx_opp_def_list, | ||
172 | ARRAY_SIZE(omap34xx_opp_def_list)); | ||
173 | |||
174 | + if (omap3_has_720mhz()) | ||
175 | + r = omap3_opp_enable_720Mhz(); | ||
176 | + } | ||
177 | + | ||
178 | return r; | ||
179 | } | ||
180 | device_initcall(omap3_opp_init); | ||
181 | diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h | ||
182 | index 8198bb6..5204c1e 100644 | ||
183 | --- a/arch/arm/plat-omap/include/plat/cpu.h | ||
184 | +++ b/arch/arm/plat-omap/include/plat/cpu.h | ||
185 | @@ -478,6 +478,7 @@ extern u32 omap3_features; | ||
186 | #define OMAP3_HAS_192MHZ_CLK BIT(5) | ||
187 | #define OMAP3_HAS_IO_WAKEUP BIT(6) | ||
188 | #define OMAP3_HAS_SDRC BIT(7) | ||
189 | +#define OMAP3_HAS_720MHZ BIT(8) | ||
190 | |||
191 | #define OMAP3_HAS_FEATURE(feat,flag) \ | ||
192 | static inline unsigned int omap3_has_ ##feat(void) \ | ||
193 | @@ -493,5 +494,6 @@ OMAP3_HAS_FEATURE(isp, ISP) | ||
194 | OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK) | ||
195 | OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP) | ||
196 | OMAP3_HAS_FEATURE(sdrc, SDRC) | ||
197 | +OMAP3_HAS_FEATURE(720mhz, 720MHZ) | ||
198 | |||
199 | #endif | ||
200 | -- | ||
201 | 1.6.6.1 | ||
202 | |||
diff --git a/recipes-kernel/linux/linux-omap_2.6.39.bb b/recipes-kernel/linux/linux-omap_2.6.39.bb deleted file mode 100644 index 430fa09b..00000000 --- a/recipes-kernel/linux/linux-omap_2.6.39.bb +++ /dev/null | |||
@@ -1,123 +0,0 @@ | |||
1 | require linux.inc | ||
2 | |||
3 | DESCRIPTION = "Linux kernel for OMAP processors" | ||
4 | |||
5 | COMPATIBLE_MACHINE = "(beagleboard)" | ||
6 | |||
7 | # The main PR is now using MACHINE_KERNEL_PR, for omap3 see conf/machine/include/omap3.inc | ||
8 | SRCREV_pn-${PN} = "v2.6.39" | ||
9 | MACHINE_KERNEL_PR_append = "o" | ||
10 | |||
11 | FILESEXTRAPATHS_prepend := "{THISDIR}/${PN}-${PV}:" | ||
12 | |||
13 | SRC_URI += "git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git;protocol=git \ | ||
14 | file://defconfig" | ||
15 | |||
16 | SRC_URI_append = " \ | ||
17 | file://sakoman/0001-OMAP-DSS2-DSI-fix-use_sys_clk-highfreq.patch \ | ||
18 | file://sakoman/0002-OMAP-DSS2-DSI-fix-dsi_dump_clocks.patch \ | ||
19 | file://sakoman/0003-OMAP2PLUS-DSS2-Fix-Return-correct-lcd-clock-source-f.patch \ | ||
20 | file://sakoman/0004-OMAP-DSS-DSI-Fix-DSI-PLL-power-bug.patch \ | ||
21 | file://sakoman/0005-OMAP-DSS2-fix-panel-Kconfig-dependencies.patch \ | ||
22 | file://sakoman/0006-OMAP-DSS2-add-bootarg-for-selecting-svideo-or-compos.patch \ | ||
23 | file://sakoman/0007-video-add-timings-for-hd720.patch \ | ||
24 | file://sakoman/0008-drivers-net-smsc911x-return-ENODEV-if-device-is-not-.patch \ | ||
25 | file://sakoman/0009-drivers-input-touchscreen-ads7846-return-ENODEV-if-d.patch \ | ||
26 | file://sakoman/0010-Revert-omap2_mcspi-Flush-posted-writes.patch \ | ||
27 | file://sakoman/0011-Revert-omap_hsmmc-improve-interrupt-synchronisation.patch \ | ||
28 | file://sakoman/0012-Don-t-turn-SDIO-cards-off-to-save-power.-Doing-so-wi.patch \ | ||
29 | file://sakoman/0014-soc-codecs-Enable-audio-capture-by-default-for-twl40.patch \ | ||
30 | file://sakoman/0015-soc-codecs-twl4030-Turn-on-mic-bias-by-default.patch \ | ||
31 | file://sakoman/0016-RTC-add-support-for-backup-battery-recharge.patch \ | ||
32 | file://sakoman/0017-ARM-OMAP2-mmc-twl4030-move-clock-input-selection-pri.patch \ | ||
33 | file://sakoman/0018-Add-power-off-support-for-the-TWL4030-companion.patch \ | ||
34 | file://sakoman/0019-ARM-OMAP-Add-twl4030-madc-support-to-Overo.patch \ | ||
35 | file://sakoman/0020-Enabling-Hwmon-driver-for-twl4030-madc.patch \ | ||
36 | file://sakoman/0021-mfd-twl-core-enable-madc-clock.patch \ | ||
37 | file://sakoman/0022-rtc-twl-Switch-to-using-threaded-irq.patch \ | ||
38 | file://sakoman/0023-ARM-OMAP-automatically-set-musb-mode-in-platform-dat.patch \ | ||
39 | file://sakoman/0024-omap-mmc-Adjust-dto-to-eliminate-timeout-errors.patch \ | ||
40 | file://sakoman/0025-omap-Fix-mtd-subpage-read-alignment.patch \ | ||
41 | file://sakoman/0026-mtd-nand-omap2-Force-all-buffer-reads-to-u32-alignme.patch \ | ||
42 | file://sakoman/0027-omap-nand-fix-subpage-ecc-issue-with-prefetch.patch \ | ||
43 | file://sakoman/0028-OMAP-Overo-Add-support-for-spidev.patch \ | ||
44 | file://sakoman/0029-unionfs-Add-support-for-unionfs-2.5.9.patch \ | ||
45 | file://sakoman/0030-omap-Change-omap_device-activate-latency-messages-fr.patch \ | ||
46 | file://sakoman/0031-omap-overo-Add-opp-init.patch \ | ||
47 | file://sakoman/0032-omap3-Add-basic-support-for-720MHz-part.patch \ | ||
48 | \ | ||
49 | file://beagle/0001-OMAP3-beagle-add-support-for-beagleboard-xM-revision.patch \ | ||
50 | file://beagle/0002-OMAP3-beagle-add-support-for-expansionboards.patch \ | ||
51 | file://beagle/0003-OMAP3-beagle-add-MADC-support.patch \ | ||
52 | file://beagle/0004-OMAP3-beagle-add-regulators-for-camera-interface.patch \ | ||
53 | file://beagle/0005-OMAP3-beagle-HACK-add-in-1GHz-OPP.patch \ | ||
54 | file://beagle/0006-OMAP3-BEAGLE-fix-RTC.patch \ | ||
55 | file://beagle/0007-omap-mmc-Adjust-dto-to-eliminate-timeout-errors.patch \ | ||
56 | \ | ||
57 | file://camera/0001-Add-driver-for-Aptina-Micron-mt9p031-sensor.patch \ | ||
58 | file://camera/0002-v4l-Add-mt9v032-sensor-driver.patch \ | ||
59 | file://camera/0003-Add-support-for-mt9p031-LI-5M03-module-in-Beagleboar.patch \ | ||
60 | \ | ||
61 | file://pm/linux-omap-2.6.39-ti-pm/0001-OMAP3-voltage-remove-spurious-pr_notice-for-debugfs.patch \ | ||
62 | file://pm/linux-omap-2.6.39-ti-pm/0002-OMAP4-PM-remove-redundant-ifdef-CONFIG_PM.patch \ | ||
63 | file://pm/linux-omap-2.6.39-ti-pm/0003-OMAP3-smartreflex-fix-sr_late_init-error-path-in-pro.patch \ | ||
64 | file://pm/linux-omap-2.6.39-ti-pm/0004-OMAP3-smartreflex-request-the-memory-region.patch \ | ||
65 | file://pm/linux-omap-2.6.39-ti-pm/0005-OMAP3-smartreflex-fix-ioremap-leak-on-probe-error.patch \ | ||
66 | file://pm/linux-omap-2.6.39-ti-pm/0006-OMAP3-smartreflex-delete-instance-from-sr_list-on-pr.patch \ | ||
67 | file://pm/linux-omap-2.6.39-ti-pm/0007-OMAP3-smartreflex-delete-debugfs-entries-on-probe-er.patch \ | ||
68 | file://pm/linux-omap-2.6.39-ti-pm/0008-OMAP3-cpuidle-remove-useless-SDP-specific-timings.patch \ | ||
69 | file://pm/linux-omap-2.6.39-ti-pm/0009-OMAP3-SR-make-notify-independent-of-class.patch \ | ||
70 | file://pm/linux-omap-2.6.39-ti-pm/0010-OMAP3-SR-disable-interrupt-by-default.patch \ | ||
71 | file://pm/linux-omap-2.6.39-ti-pm/0011-OMAP3-SR-enable-disable-SR-only-on-need.patch \ | ||
72 | file://pm/linux-omap-2.6.39-ti-pm/0012-OMAP3-SR-fix-cosmetic-indentation.patch \ | ||
73 | \ | ||
74 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0001-OMAP-CPUfreq-ensure-driver-initializes-after-cpufreq.patch \ | ||
75 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0002-OMAP-CPUfreq-ensure-policy-is-fully-initialized.patch \ | ||
76 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0003-OMAP3-PM-CPUFreq-driver-for-OMAP3.patch \ | ||
77 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0004-OMAP-PM-CPUFREQ-Fix-conditional-compilation.patch \ | ||
78 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0005-cpufreq-fixup-after-new-OPP-layer-merged.patch \ | ||
79 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0006-OMAP-cpufreq-Split-OMAP1-and-OMAP2PLUS-CPUfreq-drive.patch \ | ||
80 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0007-OMAP2PLUS-cpufreq-Add-SMP-support-to-cater-OMAP4430.patch \ | ||
81 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0008-OMAP2PLUS-cpufreq-Fix-typo-when-attempting-to-set-mp.patch \ | ||
82 | \ | ||
83 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-hotplug/0001-cpufreq-helpers-for-walking-the-frequency-table.patch \ | ||
84 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-hotplug/0002-cpufreq-introduce-hotplug-governor.patch \ | ||
85 | \ | ||
86 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0001-OMAP2-cpufreq-free-up-table-on-exit.patch \ | ||
87 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0002-OMAP2-cpufreq-handle-invalid-cpufreq-table.patch \ | ||
88 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0003-OMAP2-cpufreq-minor-comment-cleanup.patch \ | ||
89 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0004-OMAP2-cpufreq-use-clk_init_cpufreq_table-if-OPPs-not.patch \ | ||
90 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0005-OMAP2-cpufreq-use-cpufreq_frequency_table_target.patch \ | ||
91 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0006-OMAP2-cpufreq-fix-freq_table-leak.patch \ | ||
92 | \ | ||
93 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0001-OMAP2-clockdomain-Add-an-api-to-read-idle-mode.patch \ | ||
94 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0002-OMAP2-clockdomain-Add-SoC-support-for-clkdm_is_idle.patch \ | ||
95 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0003-OMAP2-PM-Initialise-sleep_switch-to-a-non-valid-valu.patch \ | ||
96 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0004-OMAP2-PM-idle-clkdms-only-if-already-in-idle.patch \ | ||
97 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0005-OMAP2-hwmod-Follow-the-recomended-PRCM-sequence.patch \ | ||
98 | file://pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0006-OMAP-Serial-Check-wk_st-only-if-present.patch \ | ||
99 | \ | ||
100 | file://mfd/0001-mfd-Fix-omap-usbhs-crash-when-rmmoding-ehci-or-ohci.patch \ | ||
101 | file://mfd/0002-mfd-Fix-omap_usbhs_alloc_children-error-handling.patch \ | ||
102 | file://mfd/0003-mfd-Add-omap-usbhs-runtime-PM-support.patch \ | ||
103 | file://mfd/0004-arm-omap-usb-ehci-and-ohci-hwmod-structures-for-omap.patch \ | ||
104 | file://mfd/0005-arm-omap-usb-register-hwmods-of-usbhs.patch \ | ||
105 | file://mfd/0006-arm-omap-usb-device-name-change-for-the-clk-names-of.patch \ | ||
106 | file://mfd/0007-mfd-global-Suspend-and-resume-support-of-ehci-and-oh.patch \ | ||
107 | file://mfd/0008-MFD-TWL4030-Correct-the-warning-print-during-script-.patch \ | ||
108 | file://mfd/0009-MFD-TWL4030-Modifying-the-macro-name-Main_Ref-to-all.patch \ | ||
109 | file://mfd/0010-MFD-TWL4030-power-scripts-for-OMAP3-boards.patch \ | ||
110 | file://mfd/0011-MFD-TWL4030-TWL-version-checking.patch \ | ||
111 | file://mfd/0012-MFD-TWL4030-workaround-changes-for-Erratum-27.patch \ | ||
112 | file://mfd/0013-MFD-TWL4030-optimizing-resource-configuration.patch \ | ||
113 | \ | ||
114 | file://musb/0001-usb-musb-Enable-DMA-mode1-RX-for-USB-Mass-Storage.patch \ | ||
115 | \ | ||
116 | file://net/0001-NFS-Revert-NFSROOT-default-mount-options.patch \ | ||
117 | " | ||
118 | |||
119 | SRC_URI_append_beagleboard = " file://logo_linux_clut224.ppm \ | ||
120 | " | ||
121 | |||
122 | S = "${WORKDIR}/git" | ||
123 | |||