summaryrefslogtreecommitdiffstats
path: root/extras/recipes-kernel/linux/linux-omap-2.6.39
diff options
context:
space:
mode:
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap-2.6.39')
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0001-OMAP3-beagle-add-support-for-beagleboard-xM-revision.patch117
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0002-OMAP3-beagle-add-support-for-expansionboards.patch359
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0003-OMAP3-beagle-add-MADC-support.patch36
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0004-OMAP3-beagle-add-regulators-for-camera-interface.patch88
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0005-OMAP3-beagle-HACK-add-in-1GHz-OPP.patch31
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0006-OMAP3-BEAGLE-fix-RTC.patch27
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0007-omap-mmc-Adjust-dto-to-eliminate-timeout-errors.patch33
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0007-omap3-beagle-Use-GPTIMERi-1-for-clockevents.patch42
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/beagleboard/configs/stock3490
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/beagleboard/defconfig3517
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/camera/0001-Add-driver-for-Aptina-Micron-mt9p031-sensor.patch859
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/camera/0002-v4l-Add-mt9v032-sensor-driver.patch853
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/camera/0003-Add-support-for-mt9p031-LI-5M03-module-in-Beagleboar.patch162
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0001-mfd-Fix-omap-usbhs-crash-when-rmmoding-ehci-or-ohci.patch67
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0002-mfd-Fix-omap_usbhs_alloc_children-error-handling.patch50
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0003-mfd-Add-omap-usbhs-runtime-PM-support.patch245
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0004-arm-omap-usb-ehci-and-ohci-hwmod-structures-for-omap.patch406
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0005-arm-omap-usb-register-hwmods-of-usbhs.patch160
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0006-arm-omap-usb-device-name-change-for-the-clk-names-of.patch123
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0007-mfd-global-Suspend-and-resume-support-of-ehci-and-oh.patch165
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0008-MFD-TWL4030-Correct-the-warning-print-during-script-.patch36
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0009-MFD-TWL4030-Modifying-the-macro-name-Main_Ref-to-all.patch61
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0010-MFD-TWL4030-power-scripts-for-OMAP3-boards.patch705
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0011-MFD-TWL4030-TWL-version-checking.patch164
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0012-MFD-TWL4030-workaround-changes-for-Erratum-27.patch341
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0013-MFD-TWL4030-optimizing-resource-configuration.patch184
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/musb/0001-usb-musb-Enable-DMA-mode1-RX-for-USB-Mass-Storage.patch121
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/net/0001-NFS-Revert-NFSROOT-default-mount-options.patch13
-rw-r--r--extras/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.patch38
-rw-r--r--extras/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.patch44
-rw-r--r--extras/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.patch33
-rw-r--r--extras/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.patch48
-rw-r--r--extras/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.patch78
-rw-r--r--extras/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.patch100
-rw-r--r--extras/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.patch134
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-hotplug/0002-cpufreq-introduce-hotplug-governor.patch879
-rw-r--r--extras/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.patch27
-rw-r--r--extras/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.patch31
-rw-r--r--extras/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.patch263
-rw-r--r--extras/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.patch32
-rw-r--r--extras/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.patch33
-rw-r--r--extras/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.patch669
-rw-r--r--extras/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.patch170
-rw-r--r--extras/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.patch29
-rw-r--r--extras/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.patch77
-rw-r--r--extras/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.patch86
-rw-r--r--extras/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.patch35
-rw-r--r--extras/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.patch50
-rw-r--r--extras/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.patch46
-rw-r--r--extras/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.patch33
-rw-r--r--extras/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.patch30
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0002-OMAP4-PM-remove-redundant-ifdef-CONFIG_PM.patch41
-rw-r--r--extras/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.patch30
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0004-OMAP3-smartreflex-request-the-memory-region.patch36
-rw-r--r--extras/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.patch66
-rw-r--r--extras/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.patch29
-rw-r--r--extras/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.patch48
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0008-OMAP3-cpuidle-remove-useless-SDP-specific-timings.patch57
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0009-OMAP3-SR-make-notify-independent-of-class.patch48
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0010-OMAP3-SR-disable-interrupt-by-default.patch37
-rw-r--r--extras/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.patch41
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0012-OMAP3-SR-fix-cosmetic-indentation.patch49
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0001-OMAP-DSS2-DSI-fix-use_sys_clk-highfreq.patch33
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0002-OMAP-DSS2-DSI-fix-dsi_dump_clocks.patch49
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0003-OMAP2PLUS-DSS2-Fix-Return-correct-lcd-clock-source-f.patch43
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0004-OMAP-DSS-DSI-Fix-DSI-PLL-power-bug.patch64
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0005-OMAP-DSS2-fix-panel-Kconfig-dependencies.patch61
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0006-OMAP-DSS2-add-bootarg-for-selecting-svideo-or-compos.patch75
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0007-video-add-timings-for-hd720.patch27
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0008-drivers-net-smsc911x-return-ENODEV-if-device-is-not-.patch29
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0009-drivers-input-touchscreen-ads7846-return-ENODEV-if-d.patch47
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0010-Revert-omap2_mcspi-Flush-posted-writes.patch25
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0011-Revert-omap_hsmmc-improve-interrupt-synchronisation.patch482
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0012-Don-t-turn-SDIO-cards-off-to-save-power.-Doing-so-wi.patch51
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0013-Enable-the-use-of-SDIO-card-interrupts.patch288
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0014-soc-codecs-Enable-audio-capture-by-default-for-twl40.patch27
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0015-soc-codecs-twl4030-Turn-on-mic-bias-by-default.patch25
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0016-RTC-add-support-for-backup-battery-recharge.patch55
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0017-ARM-OMAP2-mmc-twl4030-move-clock-input-selection-pri.patch39
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0018-Add-power-off-support-for-the-TWL4030-companion.patch103
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0019-ARM-OMAP-Add-twl4030-madc-support-to-Overo.patch33
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0020-Enabling-Hwmon-driver-for-twl4030-madc.patch46
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0021-mfd-twl-core-enable-madc-clock.patch54
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0022-rtc-twl-Switch-to-using-threaded-irq.patch25
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0023-ARM-OMAP-automatically-set-musb-mode-in-platform-dat.patch49
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0024-omap-mmc-Adjust-dto-to-eliminate-timeout-errors.patch28
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0025-omap-Fix-mtd-subpage-read-alignment.patch95
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0026-mtd-nand-omap2-Force-all-buffer-reads-to-u32-alignme.patch35
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0027-omap-nand-fix-subpage-ecc-issue-with-prefetch.patch63
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0028-OMAP-Overo-Add-support-for-spidev.patch46
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0029-unionfs-Add-support-for-unionfs-2.5.9.patch11494
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0030-omap-Change-omap_device-activate-latency-messages-fr.patch34
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0031-omap-overo-Add-opp-init.patch105
-rw-r--r--extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0032-omap3-Add-basic-support-for-720MHz-part.patch202
94 files changed, 29734 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0001-OMAP3-beagle-add-support-for-beagleboard-xM-revision.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0001-OMAP3-beagle-add-support-for-beagleboard-xM-revision.patch
new file mode 100644
index 00000000..7522d6c1
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0001-OMAP3-beagle-add-support-for-beagleboard-xM-revision.patch
@@ -0,0 +1,117 @@
1From 16c1bdb30f1bcd750b29dffd2ef3003be2d30610 Mon Sep 17 00:00:00 2001
2From: Koen Kooi <koen@dominion.thruhere.net>
3Date: Fri, 20 May 2011 12:48:37 +0200
4Subject: [PATCH 1/7] OMAP3: beagle: add support for beagleboard xM revision C
5
6The USB enable GPIO has been inverted and the USER button moved.
7
8Signed-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
13diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
14index 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--
1161.6.6.1
117
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0002-OMAP3-beagle-add-support-for-expansionboards.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0002-OMAP3-beagle-add-support-for-expansionboards.patch
new file mode 100644
index 00000000..2e95c763
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0002-OMAP3-beagle-add-support-for-expansionboards.patch
@@ -0,0 +1,359 @@
1From 27494059a5d005b8cad4e0e8640ff031b86220dc Mon Sep 17 00:00:00 2001
2From: Koen Kooi <koen@dominion.thruhere.net>
3Date: Fri, 20 May 2011 13:06:24 +0200
4Subject: [PATCH 2/7] OMAP3: beagle: add support for expansionboards
5
6Signed-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
11diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
12index 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--
3581.6.6.1
359
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0003-OMAP3-beagle-add-MADC-support.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0003-OMAP3-beagle-add-MADC-support.patch
new file mode 100644
index 00000000..79097dbf
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0003-OMAP3-beagle-add-MADC-support.patch
@@ -0,0 +1,36 @@
1From 91e701f3287923d11dd295b6a62186909e362503 Mon Sep 17 00:00:00 2001
2From: Koen Kooi <koen@dominion.thruhere.net>
3Date: Sat, 21 May 2011 16:18:30 +0200
4Subject: [PATCH 3/7] OMAP3: beagle: add MADC support
5
6Signed-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
11diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
12index 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--
351.6.6.1
36
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0004-OMAP3-beagle-add-regulators-for-camera-interface.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0004-OMAP3-beagle-add-regulators-for-camera-interface.patch
new file mode 100644
index 00000000..29e99569
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0004-OMAP3-beagle-add-regulators-for-camera-interface.patch
@@ -0,0 +1,88 @@
1From 9d7f46abab88c74e674461a2f4e9ab35b524a6ef Mon Sep 17 00:00:00 2001
2From: Koen Kooi <koen@dominion.thruhere.net>
3Date: Wed, 25 May 2011 08:56:06 +0200
4Subject: [PATCH 4/7] OMAP3: beagle: add regulators for camera interface
5
6Signed-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
11diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
12index 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--
871.6.6.1
88
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0005-OMAP3-beagle-HACK-add-in-1GHz-OPP.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0005-OMAP3-beagle-HACK-add-in-1GHz-OPP.patch
new file mode 100644
index 00000000..8b65b76e
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0005-OMAP3-beagle-HACK-add-in-1GHz-OPP.patch
@@ -0,0 +1,31 @@
1From aa93263ed7827e33148396656b7e7ab4579509a5 Mon Sep 17 00:00:00 2001
2From: Koen Kooi <koen@dominion.thruhere.net>
3Date: Wed, 25 May 2011 08:57:40 +0200
4Subject: [PATCH 5/7] OMAP3: beagle: HACK! add in 1GHz OPP
5
6Signed-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
11diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
12index 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--
301.6.6.1
31
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0006-OMAP3-BEAGLE-fix-RTC.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0006-OMAP3-BEAGLE-fix-RTC.patch
new file mode 100644
index 00000000..76443d94
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0006-OMAP3-BEAGLE-fix-RTC.patch
@@ -0,0 +1,27 @@
1From dd2c7ba245ec1b17e3d323a6c4a1cad9697dbbbe Mon Sep 17 00:00:00 2001
2From: Koen Kooi <koen@dominion.thruhere.net>
3Date: Wed, 15 Jun 2011 16:25:50 +0200
4Subject: [PATCH 6/7] OMAP3: BEAGLE: fix RTC
5
6Signed-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
11diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
12index 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--
261.6.6.1
27
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0007-omap-mmc-Adjust-dto-to-eliminate-timeout-errors.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0007-omap-mmc-Adjust-dto-to-eliminate-timeout-errors.patch
new file mode 100644
index 00000000..8cd314c6
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0007-omap-mmc-Adjust-dto-to-eliminate-timeout-errors.patch
@@ -0,0 +1,33 @@
1From bd0b2f97c48aa6aac0c6a494f1c6ba5af5de486b Mon Sep 17 00:00:00 2001
2From: Steve Sakoman <steve@sakoman.com>
3Date: Mon, 18 Jul 2011 23:13:41 -0500
4Subject: [PATCH] omap_hsmmc: Set dto to max value of 14 to avoid SD Card timeouts
5
6This fixes MMC errors due to timeouts on certain SD Cards following suggestions
7to set dto to 14 by Jason Kridner and Steven Kipisz
8
9Details of the issue:
10http://talk.maemo.org/showthread.php?p=1000707#post1000707
11
12This 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
17diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
18index 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--
321.7.0.4
33
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0007-omap3-beagle-Use-GPTIMERi-1-for-clockevents.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0007-omap3-beagle-Use-GPTIMERi-1-for-clockevents.patch
new file mode 100644
index 00000000..d5a4cf67
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagle/0007-omap3-beagle-Use-GPTIMERi-1-for-clockevents.patch
@@ -0,0 +1,42 @@
1From 101b0aedf8152711847e2f9f347d267a3ac7f287 Mon Sep 17 00:00:00 2001
2From: Sanjeev Premi <premi@ti.com>
3Date: Fri, 24 Jun 2011 16:23:45 +0000
4Subject: [PATCH 7/7] omap3: beagle: Use GPTIMERi 1 for clockevents
5
6The current selection of the GPTIMER on was result of
7a hardware issue in early versions of the Beagleboards
8(Ax and B1 thru B4). [1] [2]
9
10Its been long since the hardware issue has been fixed.
11This patch uses GPTIMER 1 for all newer board revisions
12incl. 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
17Signed-off-by: Sanjeev Premi <premi@ti.com>
18Cc: Paul Walmsley <paul@pwsan.com>
19Reviewed-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
24diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
25index 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--
411.6.6.1
42
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/beagleboard/configs/stock b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagleboard/configs/stock
new file mode 100644
index 00000000..dd288e24
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagleboard/configs/stock
@@ -0,0 +1,3490 @@
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#
6CONFIG_ARM=y
7CONFIG_HAVE_PWM=y
8CONFIG_SYS_SUPPORTS_APM_EMULATION=y
9CONFIG_HAVE_SCHED_CLOCK=y
10CONFIG_GENERIC_GPIO=y
11# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
12CONFIG_GENERIC_CLOCKEVENTS=y
13CONFIG_KTIME_SCALAR=y
14CONFIG_HAVE_PROC_CPU=y
15CONFIG_STACKTRACE_SUPPORT=y
16CONFIG_HAVE_LATENCYTOP_SUPPORT=y
17CONFIG_LOCKDEP_SUPPORT=y
18CONFIG_TRACE_IRQFLAGS_SUPPORT=y
19CONFIG_HARDIRQS_SW_RESEND=y
20CONFIG_GENERIC_IRQ_PROBE=y
21CONFIG_RWSEM_GENERIC_SPINLOCK=y
22CONFIG_ARCH_HAS_CPUFREQ=y
23CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
24CONFIG_GENERIC_HWEIGHT=y
25CONFIG_GENERIC_CALIBRATE_DELAY=y
26CONFIG_NEED_DMA_MAP_STATE=y
27CONFIG_VECTORS_BASE=0xffff0000
28# CONFIG_ARM_PATCH_PHYS_VIRT is not set
29CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
30CONFIG_CONSTRUCTORS=y
31CONFIG_HAVE_IRQ_WORK=y
32CONFIG_IRQ_WORK=y
33
34#
35# General setup
36#
37CONFIG_EXPERIMENTAL=y
38CONFIG_BROKEN_ON_SMP=y
39CONFIG_INIT_ENV_ARG_LIMIT=32
40CONFIG_CROSS_COMPILE=""
41CONFIG_LOCALVERSION=""
42# CONFIG_LOCALVERSION_AUTO is not set
43CONFIG_HAVE_KERNEL_GZIP=y
44CONFIG_HAVE_KERNEL_LZMA=y
45CONFIG_HAVE_KERNEL_LZO=y
46CONFIG_KERNEL_GZIP=y
47# CONFIG_KERNEL_LZMA is not set
48# CONFIG_KERNEL_LZO is not set
49CONFIG_SWAP=y
50CONFIG_SYSVIPC=y
51CONFIG_SYSVIPC_SYSCTL=y
52# CONFIG_POSIX_MQUEUE is not set
53CONFIG_BSD_PROCESS_ACCT=y
54# CONFIG_BSD_PROCESS_ACCT_V3 is not set
55CONFIG_FHANDLE=y
56CONFIG_TASKSTATS=y
57CONFIG_TASK_DELAY_ACCT=y
58CONFIG_TASK_XACCT=y
59CONFIG_TASK_IO_ACCOUNTING=y
60# CONFIG_AUDIT is not set
61CONFIG_HAVE_GENERIC_HARDIRQS=y
62
63#
64# IRQ subsystem
65#
66CONFIG_GENERIC_HARDIRQS=y
67CONFIG_HAVE_SPARSE_IRQ=y
68CONFIG_GENERIC_IRQ_SHOW=y
69# CONFIG_SPARSE_IRQ is not set
70
71#
72# RCU Subsystem
73#
74CONFIG_TREE_PREEMPT_RCU=y
75# CONFIG_TINY_RCU is not set
76# CONFIG_TINY_PREEMPT_RCU is not set
77CONFIG_PREEMPT_RCU=y
78# CONFIG_RCU_TRACE is not set
79CONFIG_RCU_FANOUT=32
80# CONFIG_RCU_FANOUT_EXACT is not set
81# CONFIG_TREE_RCU_TRACE is not set
82CONFIG_IKCONFIG=y
83CONFIG_IKCONFIG_PROC=y
84CONFIG_LOG_BUF_SHIFT=16
85CONFIG_CGROUPS=y
86# CONFIG_CGROUP_DEBUG is not set
87CONFIG_CGROUP_NS=y
88CONFIG_CGROUP_FREEZER=y
89CONFIG_CGROUP_DEVICE=y
90CONFIG_CPUSETS=y
91CONFIG_PROC_PID_CPUSET=y
92CONFIG_CGROUP_CPUACCT=y
93CONFIG_RESOURCE_COUNTERS=y
94CONFIG_CGROUP_MEM_RES_CTLR=y
95CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y
96CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED=y
97CONFIG_CGROUP_PERF=y
98CONFIG_CGROUP_SCHED=y
99CONFIG_FAIR_GROUP_SCHED=y
100CONFIG_RT_GROUP_SCHED=y
101# CONFIG_BLK_CGROUP is not set
102# CONFIG_NAMESPACES is not set
103CONFIG_SCHED_AUTOGROUP=y
104CONFIG_MM_OWNER=y
105# CONFIG_SYSFS_DEPRECATED is not set
106# CONFIG_RELAY is not set
107CONFIG_BLK_DEV_INITRD=y
108CONFIG_INITRAMFS_SOURCE=""
109CONFIG_RD_GZIP=y
110# CONFIG_RD_BZIP2 is not set
111# CONFIG_RD_LZMA is not set
112CONFIG_RD_XZ=y
113CONFIG_RD_LZO=y
114CONFIG_CC_OPTIMIZE_FOR_SIZE=y
115CONFIG_SYSCTL=y
116CONFIG_ANON_INODES=y
117CONFIG_EXPERT=y
118CONFIG_UID16=y
119# CONFIG_SYSCTL_SYSCALL is not set
120CONFIG_KALLSYMS=y
121# CONFIG_KALLSYMS_ALL is not set
122# CONFIG_KALLSYMS_EXTRA_PASS is not set
123CONFIG_HOTPLUG=y
124CONFIG_PRINTK=y
125CONFIG_BUG=y
126CONFIG_ELF_CORE=y
127CONFIG_BASE_FULL=y
128CONFIG_FUTEX=y
129CONFIG_EPOLL=y
130CONFIG_SIGNALFD=y
131CONFIG_TIMERFD=y
132CONFIG_EVENTFD=y
133CONFIG_SHMEM=y
134CONFIG_AIO=y
135CONFIG_EMBEDDED=y
136CONFIG_HAVE_PERF_EVENTS=y
137CONFIG_PERF_USE_VMALLOC=y
138
139#
140# Kernel Performance Events And Counters
141#
142CONFIG_PERF_EVENTS=y
143# CONFIG_PERF_COUNTERS is not set
144# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
145CONFIG_VM_EVENT_COUNTERS=y
146# CONFIG_COMPAT_BRK is not set
147CONFIG_SLAB=y
148# CONFIG_SLUB is not set
149# CONFIG_SLOB is not set
150CONFIG_PROFILING=y
151CONFIG_OPROFILE=y
152CONFIG_HAVE_OPROFILE=y
153# CONFIG_KPROBES is not set
154CONFIG_HAVE_KPROBES=y
155CONFIG_HAVE_KRETPROBES=y
156CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
157CONFIG_HAVE_CLK=y
158CONFIG_HAVE_DMA_API_DEBUG=y
159CONFIG_HAVE_HW_BREAKPOINT=y
160
161#
162# GCOV-based kernel profiling
163#
164# CONFIG_GCOV_KERNEL is not set
165CONFIG_HAVE_GENERIC_DMA_COHERENT=y
166CONFIG_SLABINFO=y
167CONFIG_RT_MUTEXES=y
168CONFIG_BASE_SMALL=0
169CONFIG_MODULES=y
170CONFIG_MODULE_FORCE_LOAD=y
171CONFIG_MODULE_UNLOAD=y
172CONFIG_MODULE_FORCE_UNLOAD=y
173CONFIG_MODVERSIONS=y
174CONFIG_MODULE_SRCVERSION_ALL=y
175CONFIG_BLOCK=y
176CONFIG_LBDAF=y
177CONFIG_BLK_DEV_BSG=y
178# CONFIG_BLK_DEV_INTEGRITY is not set
179
180#
181# IO Schedulers
182#
183CONFIG_IOSCHED_NOOP=y
184CONFIG_IOSCHED_DEADLINE=y
185CONFIG_IOSCHED_CFQ=y
186# CONFIG_DEFAULT_DEADLINE is not set
187CONFIG_DEFAULT_CFQ=y
188# CONFIG_DEFAULT_NOOP is not set
189CONFIG_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
219CONFIG_FREEZER=y
220
221#
222# System Type
223#
224CONFIG_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
279CONFIG_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#
288CONFIG_ARCH_OMAP_OTG=y
289# CONFIG_ARCH_OMAP1 is not set
290CONFIG_ARCH_OMAP2PLUS=y
291
292#
293# OMAP Feature Selections
294#
295CONFIG_OMAP_SMARTREFLEX=y
296CONFIG_OMAP_SMARTREFLEX_CLASS3=y
297CONFIG_OMAP_RESET_CLOCKS=y
298# CONFIG_OMAP_MUX is not set
299CONFIG_OMAP_MCBSP=y
300CONFIG_OMAP_MBOX_FWK=m
301CONFIG_OMAP_MBOX_KFIFO_SIZE=256
302CONFIG_OMAP_IOMMU=y
303CONFIG_OMAP_IOMMU_DEBUG=m
304CONFIG_OMAP_32K_TIMER=y
305# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set
306CONFIG_OMAP_32K_TIMER_HZ=128
307CONFIG_OMAP_DM_TIMER=y
308# CONFIG_OMAP_PM_NONE is not set
309CONFIG_OMAP_PM_NOOP=y
310
311#
312# TI OMAP2/3/4 Specific Features
313#
314CONFIG_ARCH_OMAP2PLUS_TYPICAL=y
315# CONFIG_ARCH_OMAP2 is not set
316CONFIG_ARCH_OMAP3=y
317# CONFIG_ARCH_OMAP4 is not set
318CONFIG_SOC_OMAP3430=y
319# CONFIG_SOC_OMAPTI816X is not set
320CONFIG_OMAP_PACKAGE_CBB=y
321
322#
323# OMAP Board Type
324#
325CONFIG_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
330CONFIG_MACH_OVERO=y
331CONFIG_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
335CONFIG_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
339CONFIG_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#
357CONFIG_CPU_V7=y
358CONFIG_CPU_32v6K=y
359CONFIG_CPU_32v7=y
360CONFIG_CPU_ABRT_EV7=y
361CONFIG_CPU_PABRT_V7=y
362CONFIG_CPU_CACHE_V7=y
363CONFIG_CPU_CACHE_VIPT=y
364CONFIG_CPU_COPY_V6=y
365CONFIG_CPU_TLB_V7=y
366CONFIG_CPU_HAS_ASID=y
367CONFIG_CPU_CP15=y
368CONFIG_CPU_CP15_MMU=y
369
370#
371# Processor Features
372#
373CONFIG_ARM_THUMB=y
374CONFIG_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
379CONFIG_ARM_L1_CACHE_SHIFT_6=y
380CONFIG_ARM_L1_CACHE_SHIFT=6
381CONFIG_ARM_DMA_MEM_BUFFERABLE=y
382CONFIG_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#
398CONFIG_TICK_ONESHOT=y
399CONFIG_NO_HZ=y
400CONFIG_HIGH_RES_TIMERS=y
401CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
402CONFIG_VMSPLIT_3G=y
403# CONFIG_VMSPLIT_2G is not set
404# CONFIG_VMSPLIT_1G is not set
405CONFIG_PAGE_OFFSET=0xC0000000
406# CONFIG_PREEMPT_NONE is not set
407# CONFIG_PREEMPT_VOLUNTARY is not set
408CONFIG_PREEMPT=y
409CONFIG_HZ=128
410# CONFIG_THUMB2_KERNEL is not set
411CONFIG_AEABI=y
412# CONFIG_OABI_COMPAT is not set
413CONFIG_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
417CONFIG_SELECT_MEMORY_MODEL=y
418CONFIG_FLATMEM_MANUAL=y
419CONFIG_FLATMEM=y
420CONFIG_FLAT_NODE_MEM_MAP=y
421CONFIG_HAVE_MEMBLOCK=y
422CONFIG_PAGEFLAGS_EXTENDED=y
423CONFIG_SPLIT_PTLOCK_CPUS=4
424CONFIG_COMPACTION=y
425CONFIG_MIGRATION=y
426# CONFIG_PHYS_ADDR_T_64BIT is not set
427CONFIG_ZONE_DMA_FLAG=0
428CONFIG_VIRT_TO_BUS=y
429# CONFIG_KSM is not set
430CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
431CONFIG_NEED_PER_CPU_KM=y
432CONFIG_FORCE_MAX_ZONEORDER=11
433CONFIG_LEDS=y
434CONFIG_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#
443CONFIG_ZBOOT_ROM_TEXT=0x0
444CONFIG_ZBOOT_ROM_BSS=0x0
445CONFIG_CMDLINE=" debug "
446# CONFIG_CMDLINE_FORCE is not set
447# CONFIG_XIP_KERNEL is not set
448CONFIG_KEXEC=y
449CONFIG_ATAGS_PROC=y
450# CONFIG_CRASH_DUMP is not set
451# CONFIG_AUTO_ZRELADDR is not set
452
453#
454# CPU Power Management
455#
456CONFIG_CPU_FREQ=y
457CONFIG_CPU_FREQ_TABLE=y
458CONFIG_CPU_FREQ_DEBUG=y
459CONFIG_CPU_FREQ_STAT=y
460CONFIG_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
463CONFIG_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
466CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
467CONFIG_CPU_FREQ_GOV_POWERSAVE=y
468CONFIG_CPU_FREQ_GOV_USERSPACE=y
469CONFIG_CPU_FREQ_GOV_ONDEMAND=y
470CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
471CONFIG_CPU_IDLE=y
472CONFIG_CPU_IDLE_GOV_LADDER=y
473CONFIG_CPU_IDLE_GOV_MENU=y
474
475#
476# Floating point emulation
477#
478
479#
480# At least one emulation must be selected
481#
482CONFIG_VFP=y
483CONFIG_VFPv3=y
484CONFIG_NEON=y
485
486#
487# Userspace binary formats
488#
489CONFIG_BINFMT_ELF=y
490# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
491CONFIG_HAVE_AOUT=y
492CONFIG_BINFMT_AOUT=m
493CONFIG_BINFMT_MISC=y
494
495#
496# Power management options
497#
498CONFIG_SUSPEND=y
499CONFIG_SUSPEND_FREEZER=y
500CONFIG_PM_SLEEP=y
501CONFIG_PM_RUNTIME=y
502CONFIG_PM=y
503CONFIG_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
507CONFIG_CAN_PM_TRACE=y
508# CONFIG_APM_EMULATION is not set
509CONFIG_ARCH_HAS_OPP=y
510CONFIG_PM_OPP=y
511CONFIG_ARCH_SUSPEND_POSSIBLE=y
512CONFIG_NET=y
513
514#
515# Networking options
516#
517CONFIG_PACKET=y
518CONFIG_UNIX=y
519CONFIG_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
524CONFIG_XFRM_IPCOMP=m
525CONFIG_NET_KEY=y
526# CONFIG_NET_KEY_MIGRATE is not set
527CONFIG_INET=y
528# CONFIG_IP_MULTICAST is not set
529# CONFIG_IP_ADVANCED_ROUTER is not set
530CONFIG_IP_ROUTE_CLASSID=y
531CONFIG_IP_PNP=y
532CONFIG_IP_PNP_DHCP=y
533CONFIG_IP_PNP_BOOTP=y
534CONFIG_IP_PNP_RARP=y
535CONFIG_NET_IPIP=m
536CONFIG_NET_IPGRE_DEMUX=m
537CONFIG_NET_IPGRE=m
538# CONFIG_ARPD is not set
539# CONFIG_SYN_COOKIES is not set
540CONFIG_INET_AH=m
541CONFIG_INET_ESP=m
542CONFIG_INET_IPCOMP=m
543CONFIG_INET_XFRM_TUNNEL=m
544CONFIG_INET_TUNNEL=m
545CONFIG_INET_XFRM_MODE_TRANSPORT=y
546CONFIG_INET_XFRM_MODE_TUNNEL=y
547CONFIG_INET_XFRM_MODE_BEET=y
548CONFIG_INET_LRO=y
549CONFIG_INET_DIAG=m
550CONFIG_INET_TCP_DIAG=m
551CONFIG_TCP_CONG_ADVANCED=y
552CONFIG_TCP_CONG_BIC=m
553CONFIG_TCP_CONG_CUBIC=y
554CONFIG_TCP_CONG_WESTWOOD=m
555CONFIG_TCP_CONG_HTCP=m
556CONFIG_TCP_CONG_HSTCP=m
557CONFIG_TCP_CONG_HYBLA=m
558CONFIG_TCP_CONG_VEGAS=m
559CONFIG_TCP_CONG_SCALABLE=m
560CONFIG_TCP_CONG_LP=m
561CONFIG_TCP_CONG_VENO=m
562CONFIG_TCP_CONG_YEAH=m
563CONFIG_TCP_CONG_ILLINOIS=m
564CONFIG_DEFAULT_CUBIC=y
565# CONFIG_DEFAULT_RENO is not set
566CONFIG_DEFAULT_TCP_CONG="cubic"
567# CONFIG_TCP_MD5SIG is not set
568CONFIG_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
572CONFIG_INET6_AH=m
573CONFIG_INET6_ESP=m
574CONFIG_INET6_IPCOMP=m
575CONFIG_IPV6_MIP6=m
576CONFIG_INET6_XFRM_TUNNEL=m
577CONFIG_INET6_TUNNEL=m
578CONFIG_INET6_XFRM_MODE_TRANSPORT=m
579CONFIG_INET6_XFRM_MODE_TUNNEL=m
580CONFIG_INET6_XFRM_MODE_BEET=m
581CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
582CONFIG_IPV6_SIT=m
583# CONFIG_IPV6_SIT_6RD is not set
584CONFIG_IPV6_NDISC_NODETYPE=y
585CONFIG_IPV6_TUNNEL=m
586CONFIG_IPV6_MULTIPLE_TABLES=y
587CONFIG_IPV6_SUBTREES=y
588CONFIG_IPV6_MROUTE=y
589CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
590# CONFIG_IPV6_PIMSM_V2 is not set
591# CONFIG_NETWORK_SECMARK is not set
592CONFIG_NETWORK_PHY_TIMESTAMPING=y
593CONFIG_NETFILTER=y
594# CONFIG_NETFILTER_DEBUG is not set
595CONFIG_NETFILTER_ADVANCED=y
596CONFIG_BRIDGE_NETFILTER=y
597
598#
599# Core Netfilter Configuration
600#
601CONFIG_NETFILTER_NETLINK=m
602CONFIG_NETFILTER_NETLINK_QUEUE=m
603CONFIG_NETFILTER_NETLINK_LOG=m
604CONFIG_NF_CONNTRACK=m
605CONFIG_NF_CONNTRACK_MARK=y
606CONFIG_NF_CONNTRACK_ZONES=y
607CONFIG_NF_CONNTRACK_EVENTS=y
608CONFIG_NF_CONNTRACK_TIMESTAMP=y
609CONFIG_NF_CT_PROTO_DCCP=m
610CONFIG_NF_CT_PROTO_GRE=m
611CONFIG_NF_CT_PROTO_SCTP=m
612CONFIG_NF_CT_PROTO_UDPLITE=m
613CONFIG_NF_CONNTRACK_AMANDA=m
614CONFIG_NF_CONNTRACK_FTP=m
615CONFIG_NF_CONNTRACK_H323=m
616CONFIG_NF_CONNTRACK_IRC=m
617CONFIG_NF_CONNTRACK_BROADCAST=m
618CONFIG_NF_CONNTRACK_NETBIOS_NS=m
619CONFIG_NF_CONNTRACK_SNMP=m
620CONFIG_NF_CONNTRACK_PPTP=m
621CONFIG_NF_CONNTRACK_SANE=m
622CONFIG_NF_CONNTRACK_SIP=m
623CONFIG_NF_CONNTRACK_TFTP=m
624CONFIG_NF_CT_NETLINK=m
625# CONFIG_NETFILTER_TPROXY is not set
626CONFIG_NETFILTER_XTABLES=m
627
628#
629# Xtables combined modules
630#
631CONFIG_NETFILTER_XT_MARK=m
632CONFIG_NETFILTER_XT_CONNMARK=m
633CONFIG_NETFILTER_XT_SET=m
634
635#
636# Xtables targets
637#
638CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
639CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
640CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
641CONFIG_NETFILTER_XT_TARGET_CT=m
642# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
643CONFIG_NETFILTER_XT_TARGET_HL=m
644CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
645# CONFIG_NETFILTER_XT_TARGET_LED is not set
646CONFIG_NETFILTER_XT_TARGET_MARK=m
647CONFIG_NETFILTER_XT_TARGET_NFLOG=m
648CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
649# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
650CONFIG_NETFILTER_XT_TARGET_RATEEST=m
651CONFIG_NETFILTER_XT_TARGET_TEE=m
652# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
653CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
654# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
655
656#
657# Xtables matches
658#
659CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
660# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
661CONFIG_NETFILTER_XT_MATCH_COMMENT=m
662CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
663CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
664CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
665CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
666CONFIG_NETFILTER_XT_MATCH_CPU=m
667CONFIG_NETFILTER_XT_MATCH_DCCP=m
668CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
669CONFIG_NETFILTER_XT_MATCH_DSCP=m
670CONFIG_NETFILTER_XT_MATCH_ESP=m
671CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
672CONFIG_NETFILTER_XT_MATCH_HELPER=m
673CONFIG_NETFILTER_XT_MATCH_HL=m
674CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
675CONFIG_NETFILTER_XT_MATCH_IPVS=m
676CONFIG_NETFILTER_XT_MATCH_LENGTH=m
677CONFIG_NETFILTER_XT_MATCH_LIMIT=m
678CONFIG_NETFILTER_XT_MATCH_MAC=m
679CONFIG_NETFILTER_XT_MATCH_MARK=m
680CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
681# CONFIG_NETFILTER_XT_MATCH_OSF is not set
682CONFIG_NETFILTER_XT_MATCH_OWNER=m
683CONFIG_NETFILTER_XT_MATCH_POLICY=m
684# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
685CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
686CONFIG_NETFILTER_XT_MATCH_QUOTA=m
687CONFIG_NETFILTER_XT_MATCH_RATEEST=m
688CONFIG_NETFILTER_XT_MATCH_REALM=m
689CONFIG_NETFILTER_XT_MATCH_RECENT=m
690CONFIG_NETFILTER_XT_MATCH_SCTP=m
691CONFIG_NETFILTER_XT_MATCH_STATE=m
692CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
693CONFIG_NETFILTER_XT_MATCH_STRING=m
694CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
695CONFIG_NETFILTER_XT_MATCH_TIME=m
696CONFIG_NETFILTER_XT_MATCH_U32=m
697CONFIG_IP_SET=m
698CONFIG_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
709CONFIG_IP_VS=m
710CONFIG_IP_VS_IPV6=y
711CONFIG_IP_VS_DEBUG=y
712CONFIG_IP_VS_TAB_BITS=12
713
714#
715# IPVS transport protocol load balancing support
716#
717CONFIG_IP_VS_PROTO_TCP=y
718CONFIG_IP_VS_PROTO_UDP=y
719CONFIG_IP_VS_PROTO_AH_ESP=y
720CONFIG_IP_VS_PROTO_ESP=y
721CONFIG_IP_VS_PROTO_AH=y
722# CONFIG_IP_VS_PROTO_SCTP is not set
723
724#
725# IPVS scheduler
726#
727CONFIG_IP_VS_RR=m
728CONFIG_IP_VS_WRR=m
729CONFIG_IP_VS_LC=m
730CONFIG_IP_VS_WLC=m
731CONFIG_IP_VS_LBLC=m
732CONFIG_IP_VS_LBLCR=m
733CONFIG_IP_VS_DH=m
734CONFIG_IP_VS_SH=m
735CONFIG_IP_VS_SED=m
736CONFIG_IP_VS_NQ=m
737
738#
739# IPVS application helper
740#
741CONFIG_IP_VS_FTP=m
742CONFIG_IP_VS_NFCT=y
743CONFIG_IP_VS_PE_SIP=m
744
745#
746# IP: Netfilter Configuration
747#
748CONFIG_NF_DEFRAG_IPV4=m
749CONFIG_NF_CONNTRACK_IPV4=m
750CONFIG_NF_CONNTRACK_PROC_COMPAT=y
751CONFIG_IP_NF_QUEUE=m
752CONFIG_IP_NF_IPTABLES=m
753CONFIG_IP_NF_MATCH_AH=m
754CONFIG_IP_NF_MATCH_ECN=m
755CONFIG_IP_NF_MATCH_TTL=m
756CONFIG_IP_NF_FILTER=m
757CONFIG_IP_NF_TARGET_REJECT=m
758CONFIG_IP_NF_TARGET_LOG=m
759CONFIG_IP_NF_TARGET_ULOG=m
760CONFIG_NF_NAT=m
761CONFIG_NF_NAT_NEEDED=y
762CONFIG_IP_NF_TARGET_MASQUERADE=m
763CONFIG_IP_NF_TARGET_NETMAP=m
764CONFIG_IP_NF_TARGET_REDIRECT=m
765CONFIG_NF_NAT_SNMP_BASIC=m
766CONFIG_NF_NAT_PROTO_DCCP=m
767CONFIG_NF_NAT_PROTO_GRE=m
768CONFIG_NF_NAT_PROTO_UDPLITE=m
769CONFIG_NF_NAT_PROTO_SCTP=m
770CONFIG_NF_NAT_FTP=m
771CONFIG_NF_NAT_IRC=m
772CONFIG_NF_NAT_TFTP=m
773CONFIG_NF_NAT_AMANDA=m
774CONFIG_NF_NAT_PPTP=m
775CONFIG_NF_NAT_H323=m
776CONFIG_NF_NAT_SIP=m
777CONFIG_IP_NF_MANGLE=m
778CONFIG_IP_NF_TARGET_CLUSTERIP=m
779CONFIG_IP_NF_TARGET_ECN=m
780CONFIG_IP_NF_TARGET_TTL=m
781CONFIG_IP_NF_RAW=m
782CONFIG_IP_NF_ARPTABLES=m
783CONFIG_IP_NF_ARPFILTER=m
784CONFIG_IP_NF_ARP_MANGLE=m
785
786#
787# IPv6: Netfilter Configuration
788#
789CONFIG_NF_DEFRAG_IPV6=m
790CONFIG_NF_CONNTRACK_IPV6=m
791CONFIG_IP6_NF_QUEUE=m
792CONFIG_IP6_NF_IPTABLES=m
793CONFIG_IP6_NF_MATCH_AH=m
794CONFIG_IP6_NF_MATCH_EUI64=m
795CONFIG_IP6_NF_MATCH_FRAG=m
796CONFIG_IP6_NF_MATCH_OPTS=m
797CONFIG_IP6_NF_MATCH_HL=m
798CONFIG_IP6_NF_MATCH_IPV6HEADER=m
799CONFIG_IP6_NF_MATCH_MH=m
800CONFIG_IP6_NF_MATCH_RT=m
801CONFIG_IP6_NF_TARGET_HL=m
802CONFIG_IP6_NF_TARGET_LOG=m
803CONFIG_IP6_NF_FILTER=m
804CONFIG_IP6_NF_TARGET_REJECT=m
805CONFIG_IP6_NF_MANGLE=m
806CONFIG_IP6_NF_RAW=m
807# CONFIG_BRIDGE_NF_EBTABLES is not set
808CONFIG_IP_DCCP=m
809CONFIG_INET_DCCP_DIAG=m
810
811#
812# DCCP CCIDs Configuration (EXPERIMENTAL)
813#
814# CONFIG_IP_DCCP_CCID2_DEBUG is not set
815CONFIG_IP_DCCP_CCID3=y
816# CONFIG_IP_DCCP_CCID3_DEBUG is not set
817CONFIG_IP_DCCP_TFRC_LIB=y
818
819#
820# DCCP Kernel Hacking
821#
822# CONFIG_IP_DCCP_DEBUG is not set
823CONFIG_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
828CONFIG_SCTP_HMAC_MD5=y
829# CONFIG_RDS is not set
830CONFIG_TIPC=m
831# CONFIG_TIPC_ADVANCED is not set
832# CONFIG_TIPC_DEBUG is not set
833CONFIG_ATM=m
834CONFIG_ATM_CLIP=m
835# CONFIG_ATM_CLIP_NO_ICMP is not set
836CONFIG_ATM_LANE=m
837CONFIG_ATM_MPOA=m
838CONFIG_ATM_BR2684=m
839# CONFIG_ATM_BR2684_IPFILTER is not set
840CONFIG_L2TP=m
841CONFIG_L2TP_DEBUGFS=m
842CONFIG_L2TP_V3=y
843CONFIG_L2TP_IP=m
844CONFIG_L2TP_ETH=m
845CONFIG_STP=m
846CONFIG_GARP=m
847CONFIG_BRIDGE=m
848CONFIG_BRIDGE_IGMP_SNOOPING=y
849# CONFIG_NET_DSA is not set
850CONFIG_VLAN_8021Q=m
851CONFIG_VLAN_8021Q_GVRP=y
852# CONFIG_DECNET is not set
853CONFIG_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
860CONFIG_WAN_ROUTER=m
861# CONFIG_PHONET is not set
862# CONFIG_IEEE802154 is not set
863CONFIG_NET_SCHED=y
864
865#
866# Queueing/Scheduling
867#
868CONFIG_NET_SCH_CBQ=m
869CONFIG_NET_SCH_HTB=m
870CONFIG_NET_SCH_HFSC=m
871CONFIG_NET_SCH_ATM=m
872CONFIG_NET_SCH_PRIO=m
873CONFIG_NET_SCH_MULTIQ=m
874CONFIG_NET_SCH_RED=m
875# CONFIG_NET_SCH_SFB is not set
876CONFIG_NET_SCH_SFQ=m
877CONFIG_NET_SCH_TEQL=m
878CONFIG_NET_SCH_TBF=m
879CONFIG_NET_SCH_GRED=m
880CONFIG_NET_SCH_DSMARK=m
881CONFIG_NET_SCH_NETEM=m
882CONFIG_NET_SCH_DRR=m
883CONFIG_NET_SCH_MQPRIO=m
884CONFIG_NET_SCH_CHOKE=m
885
886#
887# Classification
888#
889CONFIG_NET_CLS=y
890CONFIG_NET_CLS_BASIC=m
891CONFIG_NET_CLS_TCINDEX=m
892CONFIG_NET_CLS_ROUTE4=m
893CONFIG_NET_CLS_FW=m
894CONFIG_NET_CLS_U32=m
895CONFIG_CLS_U32_PERF=y
896CONFIG_CLS_U32_MARK=y
897CONFIG_NET_CLS_RSVP=m
898CONFIG_NET_CLS_RSVP6=m
899CONFIG_NET_CLS_FLOW=m
900CONFIG_NET_CLS_CGROUP=m
901# CONFIG_NET_EMATCH is not set
902# CONFIG_NET_CLS_ACT is not set
903CONFIG_NET_CLS_IND=y
904CONFIG_NET_SCH_FIFO=y
905# CONFIG_DCB is not set
906CONFIG_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
914CONFIG_CAN=m
915CONFIG_CAN_RAW=m
916CONFIG_CAN_BCM=m
917
918#
919# CAN Device Drivers
920#
921CONFIG_CAN_VCAN=m
922CONFIG_CAN_SLCAN=m
923# CONFIG_CAN_DEV is not set
924# CONFIG_CAN_DEBUG_DEVICES is not set
925CONFIG_IRDA=m
926
927#
928# IrDA protocols
929#
930CONFIG_IRLAN=m
931CONFIG_IRNET=m
932CONFIG_IRCOMM=m
933CONFIG_IRDA_ULTRA=y
934
935#
936# IrDA options
937#
938CONFIG_IRDA_CACHE_LAST_LSAP=y
939CONFIG_IRDA_FAST_RR=y
940CONFIG_IRDA_DEBUG=y
941
942#
943# Infrared-port device drivers
944#
945
946#
947# SIR device drivers
948#
949CONFIG_IRTTY_SIR=m
950
951#
952# Dongle support
953#
954CONFIG_DONGLE=y
955CONFIG_ESI_DONGLE=m
956CONFIG_ACTISYS_DONGLE=m
957CONFIG_TEKRAM_DONGLE=m
958CONFIG_TOIM3232_DONGLE=m
959CONFIG_LITELINK_DONGLE=m
960CONFIG_MA600_DONGLE=m
961CONFIG_GIRBIL_DONGLE=m
962CONFIG_MCP2120_DONGLE=m
963CONFIG_OLD_BELKIN_DONGLE=m
964# CONFIG_ACT200L_DONGLE is not set
965CONFIG_KINGSUN_DONGLE=m
966CONFIG_KSDAZZLE_DONGLE=m
967CONFIG_KS959_DONGLE=m
968
969#
970# FIR device drivers
971#
972CONFIG_USB_IRDA=m
973CONFIG_SIGMATEL_FIR=m
974CONFIG_MCS_FIR=m
975CONFIG_BT=m
976CONFIG_BT_L2CAP=y
977CONFIG_BT_SCO=y
978CONFIG_BT_RFCOMM=m
979CONFIG_BT_RFCOMM_TTY=y
980CONFIG_BT_BNEP=m
981CONFIG_BT_BNEP_MC_FILTER=y
982CONFIG_BT_BNEP_PROTO_FILTER=y
983CONFIG_BT_HIDP=m
984
985#
986# Bluetooth device drivers
987#
988CONFIG_BT_HCIBTUSB=m
989CONFIG_BT_HCIBTSDIO=m
990CONFIG_BT_HCIUART=m
991CONFIG_BT_HCIUART_H4=y
992CONFIG_BT_HCIUART_BCSP=y
993CONFIG_BT_HCIUART_ATH3K=y
994CONFIG_BT_HCIUART_LL=y
995CONFIG_BT_HCIBCM203X=m
996CONFIG_BT_HCIBPA10X=m
997CONFIG_BT_HCIBFUSB=m
998# CONFIG_BT_HCIVHCI is not set
999# CONFIG_BT_MRVL is not set
1000CONFIG_BT_ATH3K=m
1001CONFIG_BT_WILINK=m
1002CONFIG_AF_RXRPC=m
1003# CONFIG_AF_RXRPC_DEBUG is not set
1004# CONFIG_RXKAD is not set
1005CONFIG_FIB_RULES=y
1006CONFIG_WIRELESS=y
1007CONFIG_WIRELESS_EXT=y
1008CONFIG_WEXT_CORE=y
1009CONFIG_WEXT_PROC=y
1010CONFIG_WEXT_SPY=y
1011CONFIG_WEXT_PRIV=y
1012CONFIG_CFG80211=m
1013CONFIG_NL80211_TESTMODE=y
1014# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
1015# CONFIG_CFG80211_REG_DEBUG is not set
1016CONFIG_CFG80211_DEFAULT_PS=y
1017# CONFIG_CFG80211_DEBUGFS is not set
1018# CONFIG_CFG80211_INTERNAL_REGDB is not set
1019CONFIG_CFG80211_WEXT=y
1020CONFIG_WIRELESS_EXT_SYSFS=y
1021CONFIG_LIB80211=y
1022CONFIG_LIB80211_CRYPT_WEP=m
1023CONFIG_LIB80211_CRYPT_CCMP=m
1024CONFIG_LIB80211_CRYPT_TKIP=m
1025# CONFIG_LIB80211_DEBUG is not set
1026CONFIG_MAC80211=m
1027CONFIG_MAC80211_HAS_RC=y
1028CONFIG_MAC80211_RC_PID=y
1029# CONFIG_MAC80211_RC_MINSTREL is not set
1030CONFIG_MAC80211_RC_DEFAULT_PID=y
1031CONFIG_MAC80211_RC_DEFAULT="pid"
1032# CONFIG_MAC80211_MESH is not set
1033CONFIG_MAC80211_LEDS=y
1034# CONFIG_MAC80211_DEBUGFS is not set
1035# CONFIG_MAC80211_DEBUG_MENU is not set
1036CONFIG_WIMAX=m
1037CONFIG_WIMAX_DEBUG_LEVEL=8
1038CONFIG_RFKILL=m
1039CONFIG_RFKILL_LEDS=y
1040CONFIG_RFKILL_INPUT=y
1041CONFIG_NET_9P=m
1042# CONFIG_NET_9P_DEBUG is not set
1043# CONFIG_CAIF is not set
1044CONFIG_CEPH_LIB=m
1045# CONFIG_CEPH_LIB_PRETTYDEBUG is not set
1046
1047#
1048# Device Drivers
1049#
1050
1051#
1052# Generic Driver Options
1053#
1054CONFIG_UEVENT_HELPER_PATH=""
1055CONFIG_DEVTMPFS=y
1056CONFIG_DEVTMPFS_MOUNT=y
1057CONFIG_STANDALONE=y
1058CONFIG_PREVENT_FIRMWARE_BUILD=y
1059CONFIG_FW_LOADER=y
1060CONFIG_FIRMWARE_IN_KERNEL=y
1061CONFIG_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
1066CONFIG_MTD=y
1067# CONFIG_MTD_DEBUG is not set
1068# CONFIG_MTD_TESTS is not set
1069CONFIG_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#
1078CONFIG_MTD_CHAR=y
1079CONFIG_MTD_BLKDEVS=y
1080CONFIG_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
1086CONFIG_SM_FTL=m
1087# CONFIG_MTD_OOPS is not set
1088CONFIG_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
1095CONFIG_MTD_MAP_BANK_WIDTH_1=y
1096CONFIG_MTD_MAP_BANK_WIDTH_2=y
1097CONFIG_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
1101CONFIG_MTD_CFI_I1=y
1102CONFIG_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
1132CONFIG_MTD_NAND_ECC=y
1133# CONFIG_MTD_NAND_ECC_SMC is not set
1134CONFIG_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
1140CONFIG_MTD_NAND_OMAP2=y
1141CONFIG_MTD_NAND_IDS=y
1142# CONFIG_MTD_NAND_DISKONCHIP is not set
1143# CONFIG_MTD_NAND_NANDSIM is not set
1144CONFIG_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
1152CONFIG_MTD_UBI=y
1153CONFIG_MTD_UBI_WL_THRESHOLD=4096
1154CONFIG_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
1158CONFIG_BLK_DEV=y
1159# CONFIG_BLK_DEV_COW_COMMON is not set
1160CONFIG_BLK_DEV_LOOP=y
1161CONFIG_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
1168CONFIG_BLK_DEV_RAM=y
1169CONFIG_BLK_DEV_RAM_COUNT=16
1170CONFIG_BLK_DEV_RAM_SIZE=16384
1171# CONFIG_BLK_DEV_XIP is not set
1172CONFIG_CDROM_PKTCDVD=m
1173CONFIG_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
1179CONFIG_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
1187CONFIG_SENSORS_BH1780=m
1188# CONFIG_SENSORS_BH1770 is not set
1189# CONFIG_SENSORS_APDS990X is not set
1190CONFIG_HMC6352=m
1191# CONFIG_DS1682 is not set
1192# CONFIG_TI_DAC7512 is not set
1193CONFIG_BMP085=m
1194# CONFIG_C2PORT is not set
1195
1196#
1197# EEPROM support
1198#
1199CONFIG_EEPROM_AT24=m
1200# CONFIG_EEPROM_AT25 is not set
1201# CONFIG_EEPROM_LEGACY is not set
1202# CONFIG_EEPROM_MAX6875 is not set
1203CONFIG_EEPROM_93CX6=y
1204CONFIG_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#
1211CONFIG_TI_ST=m
1212# CONFIG_SENSORS_LIS3_SPI is not set
1213# CONFIG_SENSORS_LIS3_I2C is not set
1214CONFIG_HAVE_IDE=y
1215# CONFIG_IDE is not set
1216
1217#
1218# SCSI device support
1219#
1220CONFIG_SCSI_MOD=y
1221CONFIG_RAID_ATTRS=m
1222CONFIG_SCSI=y
1223CONFIG_SCSI_DMA=y
1224# CONFIG_SCSI_TGT is not set
1225# CONFIG_SCSI_NETLINK is not set
1226CONFIG_SCSI_PROC_FS=y
1227
1228#
1229# SCSI support type (disk, tape, CD-ROM)
1230#
1231CONFIG_BLK_DEV_SD=y
1232# CONFIG_CHR_DEV_ST is not set
1233# CONFIG_CHR_DEV_OSST is not set
1234CONFIG_BLK_DEV_SR=y
1235CONFIG_BLK_DEV_SR_VENDOR=y
1236CONFIG_CHR_DEV_SG=y
1237CONFIG_CHR_DEV_SCH=m
1238CONFIG_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
1242CONFIG_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
1249CONFIG_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
1253CONFIG_SCSI_LOWLEVEL=y
1254CONFIG_ISCSI_TCP=m
1255CONFIG_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
1262CONFIG_MD=y
1263CONFIG_BLK_DEV_MD=m
1264CONFIG_MD_LINEAR=m
1265CONFIG_MD_RAID0=m
1266CONFIG_MD_RAID1=m
1267CONFIG_MD_RAID10=m
1268CONFIG_MD_RAID456=m
1269CONFIG_MD_MULTIPATH=m
1270CONFIG_MD_FAULTY=m
1271CONFIG_BLK_DEV_DM=m
1272# CONFIG_DM_DEBUG is not set
1273CONFIG_DM_CRYPT=m
1274CONFIG_DM_SNAPSHOT=m
1275CONFIG_DM_MIRROR=m
1276CONFIG_DM_RAID=m
1277# CONFIG_DM_LOG_USERSPACE is not set
1278CONFIG_DM_ZERO=m
1279CONFIG_DM_MULTIPATH=m
1280# CONFIG_DM_MULTIPATH_QL is not set
1281# CONFIG_DM_MULTIPATH_ST is not set
1282CONFIG_DM_DELAY=m
1283# CONFIG_DM_UEVENT is not set
1284CONFIG_DM_FLAKEY=m
1285CONFIG_TARGET_CORE=m
1286CONFIG_TCM_IBLOCK=m
1287CONFIG_TCM_FILEIO=m
1288CONFIG_TCM_PSCSI=m
1289CONFIG_LOOPBACK_TARGET=m
1290# CONFIG_LOOPBACK_TARGET_CDB_DEBUG is not set
1291CONFIG_NETDEVICES=y
1292CONFIG_DUMMY=m
1293CONFIG_BONDING=m
1294CONFIG_MACVLAN=m
1295CONFIG_MACVTAP=m
1296CONFIG_EQUALIZER=m
1297CONFIG_TUN=m
1298CONFIG_VETH=m
1299CONFIG_MII=y
1300CONFIG_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
1313CONFIG_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
1319CONFIG_MICREL_PHY=m
1320# CONFIG_FIXED_PHY is not set
1321# CONFIG_MDIO_BITBANG is not set
1322CONFIG_NET_ETHERNET=y
1323# CONFIG_AX88796 is not set
1324CONFIG_SMC91X=y
1325# CONFIG_TI_DAVINCI_EMAC is not set
1326CONFIG_TI_DAVINCI_MDIO=m
1327CONFIG_TI_DAVINCI_CPDMA=m
1328# CONFIG_DM9000 is not set
1329CONFIG_ENC28J60=y
1330# CONFIG_ENC28J60_WRITEVERIFY is not set
1331# CONFIG_ETHOC is not set
1332CONFIG_SMC911X=y
1333CONFIG_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
1344CONFIG_KS8842=m
1345CONFIG_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
1350CONFIG_WLAN=y
1351# CONFIG_LIBERTAS_THINFIRM is not set
1352CONFIG_AT76C50X_USB=m
1353CONFIG_USB_ZD1201=m
1354CONFIG_USB_NET_RNDIS_WLAN=m
1355CONFIG_RTL8187=m
1356CONFIG_RTL8187_LEDS=y
1357# CONFIG_MAC80211_HWSIM is not set
1358# CONFIG_ATH_COMMON is not set
1359CONFIG_B43=m
1360# CONFIG_B43_SDIO is not set
1361CONFIG_B43_PIO=y
1362CONFIG_B43_PHY_N=y
1363CONFIG_B43_PHY_LP=y
1364CONFIG_B43_LEDS=y
1365CONFIG_B43_HWRNG=y
1366# CONFIG_B43_DEBUG is not set
1367# CONFIG_B43LEGACY is not set
1368CONFIG_HOSTAP=m
1369CONFIG_HOSTAP_FIRMWARE=y
1370CONFIG_HOSTAP_FIRMWARE_NVRAM=y
1371# CONFIG_IWM is not set
1372CONFIG_LIBERTAS=m
1373CONFIG_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
1378CONFIG_P54_COMMON=m
1379CONFIG_P54_USB=m
1380# CONFIG_P54_SPI is not set
1381CONFIG_P54_LEDS=y
1382CONFIG_RT2X00=m
1383CONFIG_RT2500USB=m
1384CONFIG_RT73USB=m
1385# CONFIG_RT2800USB is not set
1386CONFIG_RT2X00_LIB_USB=m
1387CONFIG_RT2X00_LIB=m
1388CONFIG_RT2X00_LIB_FIRMWARE=y
1389CONFIG_RT2X00_LIB_CRYPTO=y
1390CONFIG_RT2X00_LIB_LEDS=y
1391# CONFIG_RT2X00_DEBUG is not set
1392CONFIG_RTL8192CU=m
1393CONFIG_RTLWIFI=m
1394CONFIG_RTL8192C_COMMON=m
1395CONFIG_WL1251=m
1396CONFIG_WL1251_SPI=m
1397CONFIG_WL1251_SDIO=m
1398CONFIG_WL12XX_MENU=m
1399CONFIG_WL12XX=m
1400CONFIG_WL12XX_HT=y
1401CONFIG_WL12XX_SPI=m
1402CONFIG_WL12XX_SDIO=m
1403# CONFIG_WL12XX_SDIO_TEST is not set
1404CONFIG_WL12XX_PLATFORM_DATA=y
1405CONFIG_ZD1211RW=m
1406# CONFIG_ZD1211RW_DEBUG is not set
1407
1408#
1409# WiMAX Wireless Broadband devices
1410#
1411CONFIG_WIMAX_I2400M=m
1412CONFIG_WIMAX_I2400M_USB=m
1413CONFIG_WIMAX_I2400M_SDIO=m
1414CONFIG_WIMAX_IWMC3200_SDIO=y
1415CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8
1416
1417#
1418# USB Network Adapters
1419#
1420CONFIG_USB_CATC=y
1421CONFIG_USB_KAWETH=y
1422CONFIG_USB_PEGASUS=y
1423CONFIG_USB_RTL8150=y
1424CONFIG_USB_USBNET=y
1425CONFIG_USB_NET_AX8817X=y
1426CONFIG_USB_NET_CDCETHER=y
1427# CONFIG_USB_NET_CDC_EEM is not set
1428CONFIG_USB_NET_CDC_NCM=m
1429CONFIG_USB_NET_DM9601=y
1430CONFIG_USB_NET_SMSC75XX=m
1431CONFIG_USB_NET_SMSC95XX=y
1432CONFIG_USB_NET_GL620A=y
1433CONFIG_USB_NET_NET1080=y
1434CONFIG_USB_NET_PLUSB=y
1435CONFIG_USB_NET_MCS7830=y
1436CONFIG_USB_NET_RNDIS_HOST=y
1437CONFIG_USB_NET_CDC_SUBSET=y
1438CONFIG_USB_ALI_M5632=y
1439CONFIG_USB_AN2720=y
1440CONFIG_USB_BELKIN=y
1441CONFIG_USB_ARMLINUX=y
1442CONFIG_USB_EPSON2888=y
1443CONFIG_USB_KC2190=y
1444CONFIG_USB_NET_ZAURUS=y
1445CONFIG_USB_NET_CX82310_ETH=m
1446CONFIG_USB_HSO=m
1447CONFIG_USB_NET_INT51X1=m
1448CONFIG_USB_IPHETH=m
1449CONFIG_USB_SIERRA_NET=m
1450CONFIG_USB_VL600=m
1451# CONFIG_WAN is not set
1452CONFIG_ATM_DRIVERS=y
1453# CONFIG_ATM_DUMMY is not set
1454# CONFIG_ATM_TCP is not set
1455
1456#
1457# CAIF transport drivers
1458#
1459CONFIG_PPP=m
1460CONFIG_PPP_MULTILINK=y
1461CONFIG_PPP_FILTER=y
1462CONFIG_PPP_ASYNC=m
1463CONFIG_PPP_SYNC_TTY=m
1464CONFIG_PPP_DEFLATE=m
1465CONFIG_PPP_BSDCOMP=m
1466CONFIG_PPP_MPPE=m
1467CONFIG_PPPOE=m
1468CONFIG_PPTP=m
1469# CONFIG_PPPOATM is not set
1470CONFIG_PPPOL2TP=m
1471# CONFIG_SLIP is not set
1472CONFIG_SLHC=m
1473CONFIG_NETCONSOLE=m
1474CONFIG_NETCONSOLE_DYNAMIC=y
1475CONFIG_NETPOLL=y
1476CONFIG_NETPOLL_TRAP=y
1477CONFIG_NET_POLL_CONTROLLER=y
1478# CONFIG_ISDN is not set
1479# CONFIG_PHONE is not set
1480
1481#
1482# Input device support
1483#
1484CONFIG_INPUT=y
1485CONFIG_INPUT_FF_MEMLESS=y
1486CONFIG_INPUT_POLLDEV=y
1487# CONFIG_INPUT_SPARSEKMAP is not set
1488
1489#
1490# Userland interfaces
1491#
1492CONFIG_INPUT_MOUSEDEV=y
1493CONFIG_INPUT_MOUSEDEV_PSAUX=y
1494CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
1495CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
1496# CONFIG_INPUT_JOYDEV is not set
1497CONFIG_INPUT_EVDEV=y
1498# CONFIG_INPUT_EVBUG is not set
1499
1500#
1501# Input Device Drivers
1502#
1503CONFIG_INPUT_KEYBOARD=y
1504# CONFIG_KEYBOARD_ADP5588 is not set
1505# CONFIG_KEYBOARD_ATKBD is not set
1506CONFIG_KEYBOARD_QT1070=m
1507CONFIG_KEYBOARD_QT2160=m
1508# CONFIG_KEYBOARD_LKKBD is not set
1509CONFIG_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
1514CONFIG_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
1521CONFIG_INPUT_MOUSE=y
1522CONFIG_MOUSE_PS2=y
1523CONFIG_MOUSE_PS2_ALPS=y
1524CONFIG_MOUSE_PS2_LOGIPS2PP=y
1525CONFIG_MOUSE_PS2_SYNAPTICS=y
1526CONFIG_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
1539CONFIG_INPUT_MISC=y
1540CONFIG_INPUT_AD714X=m
1541CONFIG_INPUT_AD714X_I2C=m
1542CONFIG_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
1549CONFIG_INPUT_TWL4030_PWRBUTTON=y
1550CONFIG_INPUT_TWL4030_VIBRA=m
1551CONFIG_INPUT_UINPUT=y
1552CONFIG_INPUT_PCF8574=m
1553CONFIG_INPUT_PWM_BEEPER=m
1554# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
1555CONFIG_INPUT_ADXL34X=m
1556CONFIG_INPUT_ADXL34X_I2C=m
1557CONFIG_INPUT_ADXL34X_SPI=m
1558CONFIG_INPUT_CMA3000=m
1559CONFIG_INPUT_CMA3000_I2C=m
1560
1561#
1562# Hardware I/O ports
1563#
1564CONFIG_SERIO=y
1565CONFIG_SERIO_SERPORT=y
1566CONFIG_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#
1575CONFIG_VT=y
1576CONFIG_CONSOLE_TRANSLATIONS=y
1577CONFIG_VT_CONSOLE=y
1578CONFIG_HW_CONSOLE=y
1579CONFIG_VT_HW_CONSOLE_BINDING=y
1580CONFIG_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
1584CONFIG_N_GSM=m
1585CONFIG_DEVKMEM=y
1586
1587#
1588# Serial drivers
1589#
1590CONFIG_SERIAL_8250=y
1591CONFIG_SERIAL_8250_CONSOLE=y
1592CONFIG_SERIAL_8250_NR_UARTS=32
1593CONFIG_SERIAL_8250_RUNTIME_UARTS=4
1594CONFIG_SERIAL_8250_EXTENDED=y
1595CONFIG_SERIAL_8250_MANY_PORTS=y
1596CONFIG_SERIAL_8250_SHARE_IRQ=y
1597CONFIG_SERIAL_8250_DETECT_IRQ=y
1598CONFIG_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
1605CONFIG_SERIAL_CORE=y
1606CONFIG_SERIAL_CORE_CONSOLE=y
1607CONFIG_SERIAL_OMAP=y
1608CONFIG_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
1612CONFIG_SERIAL_IFX6X60=m
1613CONFIG_TTY_PRINTK=y
1614# CONFIG_HVC_DCC is not set
1615# CONFIG_IPMI_HANDLER is not set
1616CONFIG_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
1622CONFIG_I2C=y
1623CONFIG_I2C_BOARDINFO=y
1624CONFIG_I2C_COMPAT=y
1625CONFIG_I2C_CHARDEV=y
1626CONFIG_I2C_MUX=m
1627
1628#
1629# Multiplexer I2C Chip support
1630#
1631CONFIG_I2C_MUX_GPIO=m
1632# CONFIG_I2C_MUX_PCA9541 is not set
1633# CONFIG_I2C_MUX_PCA954x is not set
1634CONFIG_I2C_HELPER_AUTO=y
1635CONFIG_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
1647CONFIG_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#
1656CONFIG_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
1668CONFIG_SPI=y
1669# CONFIG_SPI_DEBUG is not set
1670CONFIG_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
1679CONFIG_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#
1687CONFIG_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#
1698CONFIG_ARCH_REQUIRE_GPIOLIB=y
1699CONFIG_GPIOLIB=y
1700# CONFIG_DEBUG_GPIO is not set
1701CONFIG_GPIO_SYSFS=y
1702CONFIG_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#
1713CONFIG_GPIO_MAX7300=m
1714# CONFIG_GPIO_MAX732X is not set
1715# CONFIG_GPIO_PCF857X is not set
1716# CONFIG_GPIO_SX150X is not set
1717CONFIG_GPIO_TWL4030=y
1718CONFIG_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
1740CONFIG_POWER_SUPPLY=m
1741# CONFIG_POWER_SUPPLY_DEBUG is not set
1742# CONFIG_PDA_POWER is not set
1743CONFIG_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
1748CONFIG_BATTERY_MAX17042=m
1749CONFIG_CHARGER_ISP1704=m
1750CONFIG_CHARGER_TWL4030=m
1751CONFIG_CHARGER_GPIO=m
1752CONFIG_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
1768CONFIG_SENSORS_ADT7411=m
1769# CONFIG_SENSORS_ADT7462 is not set
1770# CONFIG_SENSORS_ADT7470 is not set
1771# CONFIG_SENSORS_ADT7475 is not set
1772CONFIG_SENSORS_ASC7621=m
1773# CONFIG_SENSORS_ATXP1 is not set
1774CONFIG_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
1782CONFIG_SENSORS_GPIO_FAN=m
1783# CONFIG_SENSORS_IT87 is not set
1784CONFIG_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
1814CONFIG_SENSORS_SMM665=m
1815# CONFIG_SENSORS_DME1737 is not set
1816CONFIG_SENSORS_EMC1403=m
1817CONFIG_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
1824CONFIG_SENSORS_ADS7871=m
1825CONFIG_SENSORS_AMC6821=m
1826# CONFIG_SENSORS_THMC50 is not set
1827CONFIG_SENSORS_TMP102=m
1828# CONFIG_SENSORS_TMP401 is not set
1829# CONFIG_SENSORS_TMP421 is not set
1830CONFIG_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
1841CONFIG_THERMAL=y
1842CONFIG_THERMAL_HWMON=y
1843CONFIG_WATCHDOG=y
1844CONFIG_WATCHDOG_NOWAYOUT=y
1845
1846#
1847# Watchdog Device Drivers
1848#
1849# CONFIG_SOFT_WATCHDOG is not set
1850CONFIG_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
1858CONFIG_SSB_POSSIBLE=y
1859
1860#
1861# Sonics Silicon Backplane
1862#
1863CONFIG_SSB=y
1864CONFIG_SSB_BLOCKIO=y
1865CONFIG_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
1869CONFIG_MFD_SUPPORT=y
1870CONFIG_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
1877CONFIG_TPS6105X=m
1878# CONFIG_TPS65010 is not set
1879CONFIG_TPS6507X=m
1880CONFIG_TWL4030_CORE=y
1881CONFIG_TWL4030_MADC=m
1882CONFIG_TWL4030_POWER=y
1883CONFIG_TWL4030_CODEC=y
1884CONFIG_TWL4030_POWEROFF=y
1885CONFIG_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
1906CONFIG_MFD_TPS6586X=y
1907CONFIG_MFD_WL1273_CORE=m
1908CONFIG_MFD_OMAP_USB_HOST=y
1909CONFIG_REGULATOR=y
1910# CONFIG_REGULATOR_DEBUG is not set
1911CONFIG_REGULATOR_DUMMY=y
1912CONFIG_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
1920CONFIG_REGULATOR_TWL4030=y
1921# CONFIG_REGULATOR_LP3971 is not set
1922# CONFIG_REGULATOR_LP3972 is not set
1923CONFIG_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
1928CONFIG_REGULATOR_TPS6586X=m
1929CONFIG_REGULATOR_TPS6524X=m
1930CONFIG_MEDIA_SUPPORT=y
1931
1932#
1933# Multimedia core support
1934#
1935CONFIG_MEDIA_CONTROLLER=y
1936CONFIG_VIDEO_DEV=y
1937CONFIG_VIDEO_V4L2_COMMON=y
1938CONFIG_VIDEO_V4L2_SUBDEV_API=y
1939CONFIG_DVB_CORE=m
1940CONFIG_VIDEO_MEDIA=m
1941
1942#
1943# Multimedia drivers
1944#
1945CONFIG_RC_CORE=m
1946CONFIG_LIRC=m
1947CONFIG_RC_MAP=m
1948CONFIG_IR_NEC_DECODER=m
1949CONFIG_IR_RC5_DECODER=m
1950CONFIG_IR_RC6_DECODER=m
1951CONFIG_IR_JVC_DECODER=m
1952CONFIG_IR_SONY_DECODER=m
1953CONFIG_IR_RC5_SZ_DECODER=m
1954CONFIG_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
1958CONFIG_RC_LOOPBACK=m
1959CONFIG_MEDIA_ATTACH=y
1960CONFIG_MEDIA_TUNER=m
1961CONFIG_MEDIA_TUNER_CUSTOMISE=y
1962
1963#
1964# Customize TV tuners
1965#
1966CONFIG_MEDIA_TUNER_SIMPLE=m
1967CONFIG_MEDIA_TUNER_TDA8290=m
1968CONFIG_MEDIA_TUNER_TDA827X=m
1969CONFIG_MEDIA_TUNER_TDA18271=m
1970CONFIG_MEDIA_TUNER_TDA9887=m
1971CONFIG_MEDIA_TUNER_TEA5761=m
1972CONFIG_MEDIA_TUNER_TEA5767=m
1973CONFIG_MEDIA_TUNER_MT20XX=m
1974CONFIG_MEDIA_TUNER_MT2060=m
1975CONFIG_MEDIA_TUNER_MT2266=m
1976CONFIG_MEDIA_TUNER_MT2131=m
1977CONFIG_MEDIA_TUNER_QT1010=m
1978CONFIG_MEDIA_TUNER_XC2028=m
1979CONFIG_MEDIA_TUNER_XC5000=m
1980CONFIG_MEDIA_TUNER_MXL5005S=m
1981CONFIG_MEDIA_TUNER_MXL5007T=m
1982CONFIG_MEDIA_TUNER_MC44S803=m
1983CONFIG_MEDIA_TUNER_MAX2165=m
1984CONFIG_MEDIA_TUNER_TDA18218=m
1985CONFIG_VIDEO_V4L2=y
1986CONFIG_VIDEOBUF_GEN=y
1987CONFIG_VIDEOBUF_VMALLOC=m
1988CONFIG_VIDEOBUF_DMA_CONTIG=y
1989CONFIG_VIDEOBUF_DVB=m
1990CONFIG_VIDEO_TVEEPROM=m
1991CONFIG_VIDEO_TUNER=m
1992CONFIG_V4L2_MEM2MEM_DEV=m
1993CONFIG_VIDEOBUF2_CORE=m
1994CONFIG_VIDEOBUF2_MEMOPS=m
1995CONFIG_VIDEOBUF2_VMALLOC=m
1996CONFIG_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
2000CONFIG_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
2014CONFIG_VIDEO_MSP3400=m
2015# CONFIG_VIDEO_CS5345 is not set
2016CONFIG_VIDEO_CS53L32A=m
2017# CONFIG_VIDEO_M52790 is not set
2018# CONFIG_VIDEO_TLV320AIC23B is not set
2019CONFIG_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#
2031CONFIG_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
2037CONFIG_VIDEO_MT9V011=m
2038# CONFIG_VIDEO_TCM825X is not set
2039# CONFIG_VIDEO_SAA7110 is not set
2040CONFIG_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#
2051CONFIG_VIDEO_CX25840=m
2052
2053#
2054# MPEG video encoders
2055#
2056CONFIG_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
2074CONFIG_VIDEO_VIVI=m
2075CONFIG_VIDEO_VPFE_CAPTURE=y
2076# CONFIG_VIDEO_DM6446_CCDC is not set
2077CONFIG_VIDEO_OMAP2_VOUT=y
2078# CONFIG_VIDEO_CPIA2 is not set
2079CONFIG_VIDEO_TIMBERDALE=m
2080# CONFIG_VIDEO_AU0828 is not set
2081CONFIG_VIDEO_SR030PC30=m
2082CONFIG_VIDEO_NOON010PC30=m
2083CONFIG_VIDEO_OMAP3=y
2084# CONFIG_VIDEO_OMAP3_DEBUG is not set
2085# CONFIG_SOC_CAMERA is not set
2086CONFIG_V4L_USB_DRIVERS=y
2087CONFIG_USB_VIDEO_CLASS=m
2088CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
2089CONFIG_USB_GSPCA=m
2090CONFIG_USB_M5602=m
2091CONFIG_USB_STV06XX=m
2092# CONFIG_USB_GL860 is not set
2093CONFIG_USB_GSPCA_BENQ=m
2094CONFIG_USB_GSPCA_CONEX=m
2095CONFIG_USB_GSPCA_CPIA1=m
2096CONFIG_USB_GSPCA_ETOMS=m
2097CONFIG_USB_GSPCA_FINEPIX=m
2098# CONFIG_USB_GSPCA_JEILINJ is not set
2099CONFIG_USB_GSPCA_KONICA=m
2100CONFIG_USB_GSPCA_MARS=m
2101# CONFIG_USB_GSPCA_MR97310A is not set
2102CONFIG_USB_GSPCA_NW80X=m
2103CONFIG_USB_GSPCA_OV519=m
2104CONFIG_USB_GSPCA_OV534=m
2105CONFIG_USB_GSPCA_OV534_9=m
2106CONFIG_USB_GSPCA_PAC207=m
2107# CONFIG_USB_GSPCA_PAC7302 is not set
2108CONFIG_USB_GSPCA_PAC7311=m
2109CONFIG_USB_GSPCA_SN9C2028=m
2110# CONFIG_USB_GSPCA_SN9C20X is not set
2111CONFIG_USB_GSPCA_SONIXB=m
2112CONFIG_USB_GSPCA_SONIXJ=m
2113CONFIG_USB_GSPCA_SPCA500=m
2114CONFIG_USB_GSPCA_SPCA501=m
2115CONFIG_USB_GSPCA_SPCA505=m
2116CONFIG_USB_GSPCA_SPCA506=m
2117CONFIG_USB_GSPCA_SPCA508=m
2118CONFIG_USB_GSPCA_SPCA561=m
2119CONFIG_USB_GSPCA_SPCA1528=m
2120# CONFIG_USB_GSPCA_SQ905 is not set
2121# CONFIG_USB_GSPCA_SQ905C is not set
2122CONFIG_USB_GSPCA_SQ930X=m
2123CONFIG_USB_GSPCA_STK014=m
2124# CONFIG_USB_GSPCA_STV0680 is not set
2125CONFIG_USB_GSPCA_SUNPLUS=m
2126CONFIG_USB_GSPCA_T613=m
2127CONFIG_USB_GSPCA_TV8532=m
2128CONFIG_USB_GSPCA_VC032X=m
2129CONFIG_USB_GSPCA_VICAM=m
2130CONFIG_USB_GSPCA_XIRLINK_CIT=m
2131CONFIG_USB_GSPCA_ZC3XX=m
2132CONFIG_VIDEO_PVRUSB2=m
2133CONFIG_VIDEO_PVRUSB2_SYSFS=y
2134CONFIG_VIDEO_PVRUSB2_DVB=y
2135# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
2136CONFIG_VIDEO_HDPVR=m
2137CONFIG_VIDEO_EM28XX=m
2138CONFIG_VIDEO_EM28XX_ALSA=m
2139CONFIG_VIDEO_EM28XX_DVB=m
2140CONFIG_VIDEO_TLG2300=m
2141CONFIG_VIDEO_CX231XX=m
2142CONFIG_VIDEO_CX231XX_RC=y
2143# CONFIG_VIDEO_CX231XX_ALSA is not set
2144CONFIG_VIDEO_CX231XX_DVB=m
2145CONFIG_VIDEO_USBVISION=m
2146CONFIG_USB_ET61X251=m
2147CONFIG_USB_SN9C102=m
2148CONFIG_USB_PWC=m
2149# CONFIG_USB_PWC_DEBUG is not set
2150CONFIG_USB_PWC_INPUT_EVDEV=y
2151CONFIG_USB_ZR364XX=m
2152CONFIG_USB_STKWEBCAM=m
2153CONFIG_USB_S2255=m
2154CONFIG_V4L_MEM2MEM_DRIVERS=y
2155CONFIG_VIDEO_MEM2MEM_TESTDEV=m
2156CONFIG_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
2163CONFIG_RADIO_SAA7706H=m
2164# CONFIG_RADIO_TEF6862 is not set
2165CONFIG_RADIO_WL1273=m
2166
2167#
2168# Texas Instruments WL128x FM driver (ST based)
2169#
2170CONFIG_RADIO_WL128X=m
2171CONFIG_DVB_MAX_ADAPTERS=8
2172CONFIG_DVB_DYNAMIC_MINORS=y
2173CONFIG_DVB_CAPTURE_DRIVERS=y
2174# CONFIG_TTPCI_EEPROM is not set
2175
2176#
2177# Supported USB Adapters
2178#
2179CONFIG_DVB_USB=m
2180# CONFIG_DVB_USB_DEBUG is not set
2181CONFIG_DVB_USB_A800=m
2182CONFIG_DVB_USB_DIBUSB_MB=m
2183# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
2184CONFIG_DVB_USB_DIBUSB_MC=m
2185CONFIG_DVB_USB_DIB0700=m
2186CONFIG_DVB_USB_UMT_010=m
2187CONFIG_DVB_USB_CXUSB=m
2188CONFIG_DVB_USB_M920X=m
2189CONFIG_DVB_USB_GL861=m
2190CONFIG_DVB_USB_AU6610=m
2191CONFIG_DVB_USB_DIGITV=m
2192CONFIG_DVB_USB_VP7045=m
2193CONFIG_DVB_USB_VP702X=m
2194CONFIG_DVB_USB_GP8PSK=m
2195CONFIG_DVB_USB_NOVA_T_USB2=m
2196CONFIG_DVB_USB_TTUSB2=m
2197CONFIG_DVB_USB_DTT200U=m
2198CONFIG_DVB_USB_OPERA1=m
2199CONFIG_DVB_USB_AF9005=m
2200CONFIG_DVB_USB_AF9005_REMOTE=m
2201CONFIG_DVB_USB_DW2102=m
2202CONFIG_DVB_USB_CINERGY_T2=m
2203CONFIG_DVB_USB_ANYSEE=m
2204CONFIG_DVB_USB_DTV5100=m
2205CONFIG_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
2209CONFIG_DVB_USB_AZ6027=m
2210CONFIG_DVB_USB_LME2510=m
2211CONFIG_DVB_USB_TECHNISAT_USB2=m
2212# CONFIG_SMS_SIANO_MDTV is not set
2213
2214#
2215# Supported FlexCopII (B2C2) Adapters
2216#
2217CONFIG_DVB_B2C2_FLEXCOP=m
2218CONFIG_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#
2229CONFIG_DVB_STB0899=m
2230CONFIG_DVB_STB6100=m
2231CONFIG_DVB_STV090x=m
2232CONFIG_DVB_STV6110x=m
2233
2234#
2235# DVB-S (satellite) frontends
2236#
2237CONFIG_DVB_CX24123=m
2238CONFIG_DVB_MT312=m
2239CONFIG_DVB_ZL10039=m
2240CONFIG_DVB_S5H1420=m
2241CONFIG_DVB_STV0288=m
2242CONFIG_DVB_STB6000=m
2243CONFIG_DVB_STV0299=m
2244CONFIG_DVB_STV6110=m
2245CONFIG_DVB_STV0900=m
2246CONFIG_DVB_TDA10086=m
2247CONFIG_DVB_TUNER_ITD1000=m
2248CONFIG_DVB_TUNER_CX24113=m
2249CONFIG_DVB_TDA826X=m
2250CONFIG_DVB_CX24116=m
2251CONFIG_DVB_SI21XX=m
2252CONFIG_DVB_DS3000=m
2253
2254#
2255# DVB-T (terrestrial) frontends
2256#
2257CONFIG_DVB_CX22702=m
2258CONFIG_DVB_TDA1004X=m
2259CONFIG_DVB_NXT6000=m
2260CONFIG_DVB_MT352=m
2261CONFIG_DVB_ZL10353=m
2262CONFIG_DVB_DIB3000MB=m
2263CONFIG_DVB_DIB3000MC=m
2264CONFIG_DVB_DIB7000M=m
2265CONFIG_DVB_DIB7000P=m
2266CONFIG_DVB_TDA10048=m
2267CONFIG_DVB_AF9013=m
2268
2269#
2270# DVB-C (cable) frontends
2271#
2272CONFIG_DVB_TDA10023=m
2273CONFIG_DVB_STV0297=m
2274
2275#
2276# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
2277#
2278CONFIG_DVB_NXT200X=m
2279CONFIG_DVB_BCM3510=m
2280CONFIG_DVB_LGDT330X=m
2281CONFIG_DVB_LGDT3305=m
2282CONFIG_DVB_S5H1409=m
2283CONFIG_DVB_S5H1411=m
2284
2285#
2286# ISDB-T (terrestrial) frontends
2287#
2288CONFIG_DVB_S921=m
2289CONFIG_DVB_DIB8000=m
2290CONFIG_DVB_MB86A20S=m
2291
2292#
2293# Digital terrestrial only tuners/PLL
2294#
2295CONFIG_DVB_PLL=m
2296CONFIG_DVB_TUNER_DIB0070=m
2297CONFIG_DVB_TUNER_DIB0090=m
2298
2299#
2300# SEC control devices for DVB-S
2301#
2302CONFIG_DVB_LNBP21=m
2303CONFIG_DVB_ISL6421=m
2304CONFIG_DVB_LGS8GXX=m
2305CONFIG_DVB_ATBM8830=m
2306CONFIG_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#
2316CONFIG_DRM=m
2317# CONFIG_VGASTATE is not set
2318# CONFIG_VIDEO_OUTPUT_CONTROL is not set
2319CONFIG_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
2323CONFIG_FB_CFB_FILLRECT=y
2324CONFIG_FB_CFB_COPYAREA=y
2325CONFIG_FB_CFB_IMAGEBLIT=y
2326# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
2327CONFIG_FB_SYS_FILLRECT=m
2328CONFIG_FB_SYS_COPYAREA=m
2329CONFIG_FB_SYS_IMAGEBLIT=m
2330# CONFIG_FB_FOREIGN_ENDIAN is not set
2331CONFIG_FB_SYS_FOPS=m
2332# CONFIG_FB_WMT_GE_ROPS is not set
2333CONFIG_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
2337CONFIG_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
2345CONFIG_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
2351CONFIG_OMAP2_VRAM=y
2352CONFIG_OMAP2_VRFB=y
2353CONFIG_OMAP2_DSS=y
2354CONFIG_OMAP2_VRAM_SIZE=14
2355CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
2356# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set
2357CONFIG_OMAP2_DSS_DPI=y
2358# CONFIG_OMAP2_DSS_RFBI is not set
2359CONFIG_OMAP2_DSS_VENC=y
2360# CONFIG_OMAP2_DSS_SDI is not set
2361CONFIG_OMAP2_DSS_DSI=y
2362CONFIG_OMAP2_DSS_USE_DSI_PLL=y
2363# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
2364CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
2365CONFIG_FB_OMAP2=y
2366CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
2367CONFIG_FB_OMAP2_NUM_FBS=2
2368
2369#
2370# OMAP2/3 Display Device Drivers
2371#
2372CONFIG_PANEL_GENERIC_DPI=y
2373# CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set
2374CONFIG_PANEL_SHARP_LS037V7DW01=y
2375CONFIG_PANEL_NEC_NL8048HL11_01B=y
2376# CONFIG_PANEL_TAAL is not set
2377CONFIG_PANEL_TPO_TD043MTEA1=m
2378# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
2379CONFIG_BACKLIGHT_CLASS_DEVICE=y
2380
2381#
2382# Display device support
2383#
2384CONFIG_DISPLAY_SUPPORT=y
2385
2386#
2387# Display hardware drivers
2388#
2389
2390#
2391# Console display driver support
2392#
2393CONFIG_DUMMY_CONSOLE=y
2394CONFIG_FRAMEBUFFER_CONSOLE=y
2395# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
2396CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
2397# CONFIG_FONTS is not set
2398CONFIG_FONT_8x8=y
2399CONFIG_FONT_8x16=y
2400CONFIG_LOGO=y
2401# CONFIG_LOGO_LINUX_MONO is not set
2402# CONFIG_LOGO_LINUX_VGA16 is not set
2403CONFIG_LOGO_LINUX_CLUT224=y
2404CONFIG_SOUND=y
2405CONFIG_SOUND_OSS_CORE=y
2406CONFIG_SOUND_OSS_CORE_PRECLAIM=y
2407CONFIG_SND=y
2408CONFIG_SND_TIMER=y
2409CONFIG_SND_PCM=y
2410CONFIG_SND_HWDEP=y
2411CONFIG_SND_RAWMIDI=y
2412CONFIG_SND_JACK=y
2413CONFIG_SND_SEQUENCER=m
2414# CONFIG_SND_SEQ_DUMMY is not set
2415CONFIG_SND_OSSEMUL=y
2416CONFIG_SND_MIXER_OSS=y
2417CONFIG_SND_PCM_OSS=y
2418CONFIG_SND_PCM_OSS_PLUGINS=y
2419CONFIG_SND_SEQUENCER_OSS=y
2420CONFIG_SND_HRTIMER=m
2421CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
2422CONFIG_SND_DYNAMIC_MINORS=y
2423CONFIG_SND_SUPPORT_OLD_API=y
2424CONFIG_SND_VERBOSE_PROCFS=y
2425# CONFIG_SND_VERBOSE_PRINTK is not set
2426# CONFIG_SND_DEBUG is not set
2427CONFIG_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
2432CONFIG_SND_DRIVERS=y
2433# CONFIG_SND_DUMMY is not set
2434CONFIG_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
2440CONFIG_SND_SPI=y
2441CONFIG_SND_USB=y
2442CONFIG_SND_USB_AUDIO=y
2443CONFIG_SND_USB_UA101=m
2444CONFIG_SND_USB_CAIAQ=m
2445CONFIG_SND_USB_CAIAQ_INPUT=y
2446CONFIG_SND_USB_6FIRE=m
2447CONFIG_SND_SOC=y
2448CONFIG_SND_SOC_CACHE_LZO=y
2449CONFIG_SND_OMAP_SOC=y
2450CONFIG_SND_OMAP_SOC_MCBSP=y
2451CONFIG_SND_OMAP_SOC_OVERO=y
2452CONFIG_SND_OMAP_SOC_OMAP3EVM=y
2453CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y
2454CONFIG_SND_OMAP_SOC_ZOOM2=y
2455CONFIG_SND_SOC_I2C_AND_SPI=y
2456# CONFIG_SND_SOC_ALL_CODECS is not set
2457CONFIG_SND_SOC_TWL4030=y
2458# CONFIG_SOUND_PRIME is not set
2459CONFIG_HID_SUPPORT=y
2460CONFIG_HID=y
2461# CONFIG_HIDRAW is not set
2462
2463#
2464# USB Input Devices
2465#
2466CONFIG_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
2474CONFIG_HID_A4TECH=y
2475CONFIG_HID_ACRUX=m
2476# CONFIG_HID_ACRUX_FF is not set
2477CONFIG_HID_APPLE=y
2478CONFIG_HID_BELKIN=y
2479# CONFIG_HID_CANDO is not set
2480CONFIG_HID_CHERRY=y
2481CONFIG_HID_CHICONY=y
2482# CONFIG_HID_PRODIKEYS is not set
2483CONFIG_HID_CYPRESS=y
2484# CONFIG_HID_DRAGONRISE is not set
2485CONFIG_HID_EMS_FF=m
2486# CONFIG_HID_ELECOM is not set
2487CONFIG_HID_EZKEY=y
2488CONFIG_HID_KEYTOUCH=m
2489# CONFIG_HID_KYE is not set
2490CONFIG_HID_UCLOGIC=m
2491CONFIG_HID_WALTOP=m
2492CONFIG_HID_GYRATION=y
2493# CONFIG_HID_TWINHAN is not set
2494# CONFIG_HID_KENSINGTON is not set
2495CONFIG_HID_LCPOWER=m
2496CONFIG_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
2501CONFIG_HID_MAGICMOUSE=m
2502CONFIG_HID_MICROSOFT=y
2503# CONFIG_HID_MOSART is not set
2504CONFIG_HID_MONTEREY=y
2505CONFIG_HID_MULTITOUCH=m
2506CONFIG_HID_NTRIG=y
2507# CONFIG_HID_ORTEK is not set
2508CONFIG_HID_PANTHERLORD=y
2509# CONFIG_PANTHERLORD_FF is not set
2510CONFIG_HID_PETALYNX=y
2511CONFIG_HID_PICOLCD=m
2512CONFIG_HID_PICOLCD_FB=y
2513CONFIG_HID_PICOLCD_BACKLIGHT=y
2514CONFIG_HID_PICOLCD_LEDS=y
2515CONFIG_HID_QUANTA=m
2516CONFIG_HID_ROCCAT=m
2517CONFIG_HID_ROCCAT_COMMON=m
2518CONFIG_HID_ROCCAT_ARVO=m
2519CONFIG_HID_ROCCAT_KONE=m
2520CONFIG_HID_ROCCAT_KONEPLUS=m
2521CONFIG_HID_ROCCAT_KOVAPLUS=m
2522# CONFIG_HID_ROCCAT_PYRA is not set
2523CONFIG_HID_SAMSUNG=y
2524CONFIG_HID_SONY=y
2525CONFIG_HID_STANTUM=m
2526CONFIG_HID_SUNPLUS=y
2527# CONFIG_HID_GREENASIA is not set
2528# CONFIG_HID_SMARTJOYPLUS is not set
2529CONFIG_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
2534CONFIG_USB_SUPPORT=y
2535CONFIG_USB_ARCH_HAS_HCD=y
2536CONFIG_USB_ARCH_HAS_OHCI=y
2537CONFIG_USB_ARCH_HAS_EHCI=y
2538CONFIG_USB=y
2539# CONFIG_USB_DEBUG is not set
2540CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
2541
2542#
2543# Miscellaneous USB options
2544#
2545CONFIG_USB_DEVICEFS=y
2546CONFIG_USB_DEVICE_CLASS=y
2547# CONFIG_USB_DYNAMIC_MINORS is not set
2548CONFIG_USB_SUSPEND=y
2549CONFIG_USB_OTG=y
2550# CONFIG_USB_OTG_WHITELIST is not set
2551# CONFIG_USB_OTG_BLACKLIST_HUB is not set
2552CONFIG_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
2560CONFIG_USB_EHCI_HCD=y
2561# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
2562CONFIG_USB_EHCI_TT_NEWSCHED=y
2563CONFIG_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
2573CONFIG_USB_MUSB_HDRC=y
2574# CONFIG_USB_MUSB_TUSB6010 is not set
2575CONFIG_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
2579CONFIG_USB_MUSB_OTG=y
2580CONFIG_USB_GADGET_MUSB_HDRC=y
2581CONFIG_USB_MUSB_HDRC_HCD=y
2582# CONFIG_MUSB_PIO_ONLY is not set
2583CONFIG_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#
2590CONFIG_USB_ACM=m
2591CONFIG_USB_PRINTER=m
2592CONFIG_USB_WDM=m
2593CONFIG_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#
2602CONFIG_USB_STORAGE=y
2603# CONFIG_USB_STORAGE_DEBUG is not set
2604CONFIG_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
2616CONFIG_USB_STORAGE_ENE_UB6250=m
2617CONFIG_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#
2629CONFIG_USB_SERIAL=m
2630CONFIG_USB_EZUSB=y
2631CONFIG_USB_SERIAL_GENERIC=y
2632CONFIG_USB_SERIAL_AIRCABLE=m
2633CONFIG_USB_SERIAL_ARK3116=m
2634CONFIG_USB_SERIAL_BELKIN=m
2635CONFIG_USB_SERIAL_CH341=m
2636CONFIG_USB_SERIAL_WHITEHEAT=n
2637CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
2638# CONFIG_USB_SERIAL_CP210X is not set
2639CONFIG_USB_SERIAL_CYPRESS_M8=m
2640CONFIG_USB_SERIAL_EMPEG=m
2641CONFIG_USB_SERIAL_FTDI_SIO=m
2642CONFIG_USB_SERIAL_FUNSOFT=m
2643CONFIG_USB_SERIAL_VISOR=m
2644CONFIG_USB_SERIAL_IPAQ=m
2645CONFIG_USB_SERIAL_IR=m
2646CONFIG_USB_SERIAL_EDGEPORT=m
2647CONFIG_USB_SERIAL_EDGEPORT_TI=m
2648CONFIG_USB_SERIAL_GARMIN=m
2649CONFIG_USB_SERIAL_IPW=m
2650CONFIG_USB_SERIAL_IUU=m
2651CONFIG_USB_SERIAL_KEYSPAN_PDA=m
2652CONFIG_USB_SERIAL_KEYSPAN=m
2653CONFIG_USB_SERIAL_KEYSPAN_MPR=y
2654CONFIG_USB_SERIAL_KEYSPAN_USA28=y
2655CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
2656CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
2657CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
2658CONFIG_USB_SERIAL_KEYSPAN_USA19=y
2659CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
2660CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
2661CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
2662CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
2663CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
2664CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
2665CONFIG_USB_SERIAL_KLSI=m
2666CONFIG_USB_SERIAL_KOBIL_SCT=m
2667CONFIG_USB_SERIAL_MCT_U232=m
2668CONFIG_USB_SERIAL_MOS7720=m
2669CONFIG_USB_SERIAL_MOS7840=m
2670CONFIG_USB_SERIAL_MOTOROLA=m
2671CONFIG_USB_SERIAL_NAVMAN=m
2672CONFIG_USB_SERIAL_PL2303=m
2673CONFIG_USB_SERIAL_OTI6858=m
2674CONFIG_USB_SERIAL_QCAUX=m
2675# CONFIG_USB_SERIAL_QUALCOMM is not set
2676CONFIG_USB_SERIAL_SPCP8X5=m
2677CONFIG_USB_SERIAL_HP4X=m
2678CONFIG_USB_SERIAL_SAFE=m
2679# CONFIG_USB_SERIAL_SAFE_PADDED is not set
2680CONFIG_USB_SERIAL_SAMBA=m
2681CONFIG_USB_SERIAL_SIEMENS_MPI=m
2682CONFIG_USB_SERIAL_SIERRAWIRELESS=m
2683# CONFIG_USB_SERIAL_SYMBOL is not set
2684CONFIG_USB_SERIAL_TI=n
2685CONFIG_USB_SERIAL_CYBERJACK=m
2686CONFIG_USB_SERIAL_XIRCOM=n
2687# CONFIG_USB_SERIAL_OPTION is not set
2688CONFIG_USB_SERIAL_OMNINET=m
2689CONFIG_USB_SERIAL_OPTICON=m
2690CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
2691CONFIG_USB_SERIAL_ZIO=m
2692CONFIG_USB_SERIAL_SSU100=m
2693CONFIG_USB_SERIAL_DEBUG=m
2694
2695#
2696# USB Miscellaneous drivers
2697#
2698CONFIG_USB_EMI62=m
2699CONFIG_USB_EMI26=m
2700# CONFIG_USB_ADUTUX is not set
2701# CONFIG_USB_SEVSEG is not set
2702# CONFIG_USB_RIO500 is not set
2703CONFIG_USB_LEGOTOWER=m
2704CONFIG_USB_LCD=m
2705CONFIG_USB_LED=m
2706CONFIG_USB_CYPRESS_CY7C63=m
2707CONFIG_USB_CYTHERM=m
2708CONFIG_USB_IDMOUSE=m
2709CONFIG_USB_FTDI_ELAN=m
2710# CONFIG_USB_APPLEDISPLAY is not set
2711CONFIG_USB_SISUSBVGA=m
2712CONFIG_USB_SISUSBVGA_CON=y
2713CONFIG_USB_LD=m
2714CONFIG_USB_TRANCEVIBRATOR=m
2715# CONFIG_USB_IOWARRIOR is not set
2716CONFIG_USB_TEST=m
2717# CONFIG_USB_ISIGHTFW is not set
2718CONFIG_USB_YUREX=m
2719CONFIG_USB_ATM=m
2720CONFIG_USB_SPEEDTOUCH=m
2721CONFIG_USB_CXACRU=m
2722CONFIG_USB_UEAGLEATM=m
2723CONFIG_USB_XUSBATM=m
2724CONFIG_USB_GADGET=y
2725# CONFIG_USB_GADGET_DEBUG is not set
2726# CONFIG_USB_GADGET_DEBUG_FILES is not set
2727CONFIG_USB_GADGET_DEBUG_FS=y
2728CONFIG_USB_GADGET_VBUS_DRAW=480
2729CONFIG_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
2736CONFIG_USB_GADGET_DUALSPEED=y
2737# CONFIG_USB_ZERO is not set
2738# CONFIG_USB_AUDIO is not set
2739CONFIG_USB_ETH=m
2740CONFIG_USB_ETH_RNDIS=y
2741# CONFIG_USB_ETH_EEM is not set
2742CONFIG_USB_G_NCM=m
2743# CONFIG_USB_GADGETFS is not set
2744CONFIG_USB_FUNCTIONFS=m
2745# CONFIG_USB_FUNCTIONFS_ETH is not set
2746CONFIG_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
2755CONFIG_USB_G_HID=m
2756CONFIG_USB_G_DBGP=m
2757# CONFIG_USB_G_DBGP_PRINTK is not set
2758CONFIG_USB_G_DBGP_SERIAL=y
2759CONFIG_USB_G_WEBCAM=m
2760
2761#
2762# OTG and related infrastructure
2763#
2764CONFIG_USB_OTG_UTILS=y
2765CONFIG_USB_GPIO_VBUS=y
2766# CONFIG_ISP1301_OMAP is not set
2767# CONFIG_USB_ULPI is not set
2768CONFIG_TWL4030_USB=y
2769CONFIG_TWL6030_USB=m
2770CONFIG_NOP_USB_XCEIV=y
2771CONFIG_MMC=y
2772# CONFIG_MMC_DEBUG is not set
2773CONFIG_MMC_UNSAFE_RESUME=y
2774# CONFIG_MMC_CLKGATE is not set
2775
2776#
2777# MMC/SD/SDIO Card Drivers
2778#
2779CONFIG_MMC_BLOCK=y
2780CONFIG_MMC_BLOCK_MINORS=8
2781CONFIG_MMC_BLOCK_BOUNCE=y
2782CONFIG_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
2790CONFIG_MMC_OMAP_HS=y
2791CONFIG_MMC_SPI=m
2792# CONFIG_MMC_DW is not set
2793CONFIG_MMC_USHC=m
2794# CONFIG_MEMSTICK is not set
2795CONFIG_NEW_LEDS=y
2796CONFIG_LEDS_CLASS=y
2797
2798#
2799# LED drivers
2800#
2801# CONFIG_LEDS_LM3530 is not set
2802# CONFIG_LEDS_PCA9532 is not set
2803CONFIG_LEDS_GPIO=y
2804CONFIG_LEDS_GPIO_PLATFORM=y
2805# CONFIG_LEDS_LP3944 is not set
2806CONFIG_LEDS_LP5521=m
2807CONFIG_LEDS_LP5523=m
2808# CONFIG_LEDS_PCA955X is not set
2809# CONFIG_LEDS_DAC124S085 is not set
2810CONFIG_LEDS_PWM=m
2811CONFIG_LEDS_REGULATOR=m
2812# CONFIG_LEDS_BD2802 is not set
2813# CONFIG_LEDS_LT3593 is not set
2814CONFIG_LEDS_TRIGGERS=y
2815
2816#
2817# LED Triggers
2818#
2819CONFIG_LEDS_TRIGGER_TIMER=m
2820CONFIG_LEDS_TRIGGER_HEARTBEAT=y
2821CONFIG_LEDS_TRIGGER_BACKLIGHT=m
2822CONFIG_LEDS_TRIGGER_GPIO=m
2823CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
2824
2825#
2826# iptables trigger is under Netfilter config (LED target)
2827#
2828CONFIG_NFC_DEVICES=y
2829CONFIG_PN544_NFC=m
2830# CONFIG_ACCESSIBILITY is not set
2831CONFIG_RTC_LIB=y
2832CONFIG_RTC_CLASS=y
2833CONFIG_RTC_HCTOSYS=y
2834CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
2835# CONFIG_RTC_DEBUG is not set
2836
2837#
2838# RTC interfaces
2839#
2840CONFIG_RTC_INTF_SYSFS=y
2841CONFIG_RTC_INTF_PROC=y
2842CONFIG_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#
2849CONFIG_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
2861CONFIG_RTC_DRV_BQ32K=m
2862CONFIG_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
2901CONFIG_TIMB_DMA=m
2902CONFIG_DMA_ENGINE=y
2903# CONFIG_AUXDISPLAY is not set
2904CONFIG_UIO=m
2905CONFIG_UIO_PDRV=m
2906CONFIG_UIO_PDRV_GENIRQ=m
2907CONFIG_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
2911CONFIG_W35UND=m
2912CONFIG_PRISM2_USB=m
2913CONFIG_ECHO=m
2914CONFIG_BRCM80211=m
2915CONFIG_BRCMFMAC=y
2916# CONFIG_BRCMDBG is not set
2917CONFIG_RT2870=m
2918# CONFIG_COMEDI is not set
2919# CONFIG_ASUS_OLED is not set
2920CONFIG_R8712U=m
2921CONFIG_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
2929CONFIG_XVMALLOC=y
2930CONFIG_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
2937CONFIG_MACH_NO_WESTBRIDGE=y
2938# CONFIG_ATH6K_LEGACY is not set
2939CONFIG_USB_ENESTORAGE=m
2940CONFIG_BCM_WIMAX=m
2941CONFIG_FT1000=m
2942CONFIG_FT1000_USB=m
2943
2944#
2945# Speakup console speech
2946#
2947# CONFIG_SPEAKUP is not set
2948CONFIG_TOUCHSCREEN_CLEARPAD_TM1217=m
2949CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=m
2950
2951#
2952# Altera FPGA firmware download module
2953#
2954# CONFIG_ALTERA_STAPL is not set
2955CONFIG_CLKDEV_LOOKUP=y
2956
2957#
2958# File systems
2959#
2960CONFIG_EXT2_FS=y
2961# CONFIG_EXT2_FS_XATTR is not set
2962# CONFIG_EXT2_FS_XIP is not set
2963CONFIG_EXT3_FS=y
2964# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
2965# CONFIG_EXT3_FS_XATTR is not set
2966CONFIG_EXT4_FS=y
2967CONFIG_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
2971CONFIG_JBD=y
2972# CONFIG_JBD_DEBUG is not set
2973CONFIG_JBD2=y
2974# CONFIG_JBD2_DEBUG is not set
2975CONFIG_FS_MBCACHE=y
2976CONFIG_REISERFS_FS=m
2977# CONFIG_REISERFS_CHECK is not set
2978CONFIG_REISERFS_PROC_INFO=y
2979CONFIG_REISERFS_FS_XATTR=y
2980# CONFIG_REISERFS_FS_POSIX_ACL is not set
2981# CONFIG_REISERFS_FS_SECURITY is not set
2982CONFIG_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
2987CONFIG_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
2992CONFIG_GFS2_FS=m
2993# CONFIG_GFS2_FS_LOCKING_DLM is not set
2994CONFIG_OCFS2_FS=m
2995CONFIG_OCFS2_FS_O2CB=m
2996CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
2997CONFIG_OCFS2_FS_STATS=y
2998CONFIG_OCFS2_DEBUG_MASKLOG=y
2999# CONFIG_OCFS2_DEBUG_FS is not set
3000CONFIG_BTRFS_FS=m
3001# CONFIG_BTRFS_FS_POSIX_ACL is not set
3002# CONFIG_NILFS2_FS is not set
3003CONFIG_FS_POSIX_ACL=y
3004CONFIG_EXPORTFS=y
3005CONFIG_FILE_LOCKING=y
3006CONFIG_FSNOTIFY=y
3007CONFIG_DNOTIFY=y
3008CONFIG_INOTIFY_USER=y
3009CONFIG_FANOTIFY=y
3010CONFIG_QUOTA=y
3011# CONFIG_QUOTA_NETLINK_INTERFACE is not set
3012CONFIG_PRINT_QUOTA_WARNING=y
3013# CONFIG_QUOTA_DEBUG is not set
3014CONFIG_QUOTA_TREE=y
3015# CONFIG_QFMT_V1 is not set
3016CONFIG_QFMT_V2=y
3017CONFIG_QUOTACTL=y
3018CONFIG_AUTOFS4_FS=m
3019CONFIG_FUSE_FS=m
3020# CONFIG_CUSE is not set
3021CONFIG_GENERIC_ACL=y
3022
3023#
3024# Caches
3025#
3026# CONFIG_FSCACHE is not set
3027
3028#
3029# CD-ROM/DVD Filesystems
3030#
3031CONFIG_ISO9660_FS=m
3032CONFIG_JOLIET=y
3033CONFIG_ZISOFS=y
3034CONFIG_UDF_FS=m
3035CONFIG_UDF_NLS=y
3036
3037#
3038# DOS/FAT/NT Filesystems
3039#
3040CONFIG_FAT_FS=y
3041CONFIG_MSDOS_FS=y
3042CONFIG_VFAT_FS=y
3043CONFIG_FAT_DEFAULT_CODEPAGE=437
3044CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
3045CONFIG_NTFS_FS=m
3046# CONFIG_NTFS_DEBUG is not set
3047CONFIG_NTFS_RW=y
3048
3049#
3050# Pseudo filesystems
3051#
3052CONFIG_PROC_FS=y
3053CONFIG_PROC_SYSCTL=y
3054CONFIG_PROC_PAGE_MONITOR=y
3055CONFIG_SYSFS=y
3056CONFIG_TMPFS=y
3057CONFIG_TMPFS_POSIX_ACL=y
3058# CONFIG_HUGETLB_PAGE is not set
3059CONFIG_CONFIGFS_FS=m
3060CONFIG_MISC_FILESYSTEMS=y
3061CONFIG_ADFS_FS=m
3062# CONFIG_ADFS_FS_RW is not set
3063CONFIG_AFFS_FS=m
3064# CONFIG_ECRYPT_FS is not set
3065CONFIG_UNION_FS=m
3066CONFIG_UNION_FS_XATTR=y
3067# CONFIG_UNION_FS_DEBUG is not set
3068CONFIG_HFS_FS=m
3069CONFIG_HFSPLUS_FS=m
3070CONFIG_BEFS_FS=m
3071# CONFIG_BEFS_DEBUG is not set
3072CONFIG_BFS_FS=m
3073CONFIG_EFS_FS=m
3074CONFIG_JFFS2_FS=y
3075CONFIG_JFFS2_FS_DEBUG=0
3076CONFIG_JFFS2_FS_WRITEBUFFER=y
3077# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
3078CONFIG_JFFS2_SUMMARY=y
3079CONFIG_JFFS2_FS_XATTR=y
3080CONFIG_JFFS2_FS_POSIX_ACL=y
3081CONFIG_JFFS2_FS_SECURITY=y
3082CONFIG_JFFS2_COMPRESSION_OPTIONS=y
3083CONFIG_JFFS2_ZLIB=y
3084CONFIG_JFFS2_LZO=y
3085CONFIG_JFFS2_RTIME=y
3086CONFIG_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
3090CONFIG_JFFS2_CMODE_FAVOURLZO=y
3091CONFIG_UBIFS_FS=y
3092CONFIG_UBIFS_FS_XATTR=y
3093CONFIG_UBIFS_FS_ADVANCED_COMPR=y
3094CONFIG_UBIFS_FS_LZO=y
3095CONFIG_UBIFS_FS_ZLIB=y
3096# CONFIG_UBIFS_FS_DEBUG is not set
3097CONFIG_LOGFS=m
3098CONFIG_CRAMFS=m
3099CONFIG_SQUASHFS=y
3100# CONFIG_SQUASHFS_XATTR is not set
3101CONFIG_SQUASHFS_LZO=y
3102CONFIG_SQUASHFS_XZ=y
3103# CONFIG_SQUASHFS_EMBEDDED is not set
3104CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
3105CONFIG_VXFS_FS=m
3106CONFIG_MINIX_FS=m
3107CONFIG_OMFS_FS=m
3108CONFIG_HPFS_FS=m
3109CONFIG_QNX4FS_FS=m
3110CONFIG_ROMFS_FS=m
3111CONFIG_ROMFS_BACKED_BY_BLOCK=y
3112# CONFIG_ROMFS_BACKED_BY_MTD is not set
3113# CONFIG_ROMFS_BACKED_BY_BOTH is not set
3114CONFIG_ROMFS_ON_BLOCK=y
3115CONFIG_PSTORE=y
3116CONFIG_SYSV_FS=m
3117CONFIG_UFS_FS=m
3118# CONFIG_UFS_FS_WRITE is not set
3119# CONFIG_UFS_DEBUG is not set
3120CONFIG_NETWORK_FILESYSTEMS=y
3121CONFIG_NFS_FS=y
3122CONFIG_NFS_V3=y
3123# CONFIG_NFS_V3_ACL is not set
3124CONFIG_NFS_V4=y
3125# CONFIG_NFS_V4_1 is not set
3126CONFIG_ROOT_NFS=y
3127# CONFIG_NFS_USE_LEGACY_DNS is not set
3128CONFIG_NFS_USE_KERNEL_DNS=y
3129# CONFIG_NFS_USE_NEW_IDMAPPER is not set
3130CONFIG_NFSD=m
3131CONFIG_NFSD_DEPRECATED=y
3132CONFIG_NFSD_V2_ACL=y
3133CONFIG_NFSD_V3=y
3134CONFIG_NFSD_V3_ACL=y
3135CONFIG_NFSD_V4=y
3136CONFIG_LOCKD=y
3137CONFIG_LOCKD_V4=y
3138CONFIG_NFS_ACL_SUPPORT=m
3139CONFIG_NFS_COMMON=y
3140CONFIG_SUNRPC=y
3141CONFIG_SUNRPC_GSS=y
3142CONFIG_RPCSEC_GSS_KRB5=m
3143CONFIG_CEPH_FS=m
3144CONFIG_CIFS=m
3145CONFIG_CIFS_STATS=y
3146CONFIG_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
3152CONFIG_CIFS_EXPERIMENTAL=y
3153CONFIG_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
3162CONFIG_CODA_FS=m
3163CONFIG_AFS_FS=m
3164# CONFIG_AFS_DEBUG is not set
3165CONFIG_9P_FS=m
3166# CONFIG_9P_FS_POSIX_ACL is not set
3167
3168#
3169# Partition Types
3170#
3171CONFIG_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
3176CONFIG_MAC_PARTITION=y
3177CONFIG_MSDOS_PARTITION=y
3178CONFIG_BSD_DISKLABEL=y
3179CONFIG_MINIX_SUBPARTITION=y
3180CONFIG_SOLARIS_X86_PARTITION=y
3181# CONFIG_UNIXWARE_DISKLABEL is not set
3182CONFIG_LDM_PARTITION=y
3183CONFIG_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
3188CONFIG_EFI_PARTITION=y
3189# CONFIG_SYSV68_PARTITION is not set
3190CONFIG_NLS=y
3191CONFIG_NLS_DEFAULT="iso8859-1"
3192CONFIG_NLS_CODEPAGE_437=y
3193CONFIG_NLS_CODEPAGE_737=m
3194CONFIG_NLS_CODEPAGE_775=m
3195CONFIG_NLS_CODEPAGE_850=m
3196CONFIG_NLS_CODEPAGE_852=m
3197CONFIG_NLS_CODEPAGE_855=m
3198CONFIG_NLS_CODEPAGE_857=m
3199CONFIG_NLS_CODEPAGE_860=m
3200CONFIG_NLS_CODEPAGE_861=m
3201CONFIG_NLS_CODEPAGE_862=m
3202CONFIG_NLS_CODEPAGE_863=m
3203CONFIG_NLS_CODEPAGE_864=m
3204CONFIG_NLS_CODEPAGE_865=m
3205CONFIG_NLS_CODEPAGE_866=m
3206CONFIG_NLS_CODEPAGE_869=m
3207CONFIG_NLS_CODEPAGE_936=m
3208CONFIG_NLS_CODEPAGE_950=m
3209CONFIG_NLS_CODEPAGE_932=m
3210CONFIG_NLS_CODEPAGE_949=m
3211CONFIG_NLS_CODEPAGE_874=m
3212CONFIG_NLS_ISO8859_8=m
3213CONFIG_NLS_CODEPAGE_1250=m
3214CONFIG_NLS_CODEPAGE_1251=m
3215CONFIG_NLS_ASCII=m
3216CONFIG_NLS_ISO8859_1=y
3217CONFIG_NLS_ISO8859_2=m
3218CONFIG_NLS_ISO8859_3=m
3219CONFIG_NLS_ISO8859_4=m
3220CONFIG_NLS_ISO8859_5=m
3221CONFIG_NLS_ISO8859_6=m
3222CONFIG_NLS_ISO8859_7=m
3223CONFIG_NLS_ISO8859_9=m
3224CONFIG_NLS_ISO8859_13=m
3225CONFIG_NLS_ISO8859_14=m
3226CONFIG_NLS_ISO8859_15=m
3227CONFIG_NLS_KOI8_R=m
3228CONFIG_NLS_KOI8_U=m
3229CONFIG_NLS_UTF8=y
3230CONFIG_DLM=m
3231# CONFIG_DLM_DEBUG is not set
3232
3233#
3234# Kernel hacking
3235#
3236CONFIG_PRINTK_TIME=y
3237CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
3238CONFIG_ENABLE_WARN_DEPRECATED=y
3239CONFIG_ENABLE_MUST_CHECK=y
3240CONFIG_FRAME_WARN=1024
3241CONFIG_MAGIC_SYSRQ=y
3242# CONFIG_STRIP_ASM_SYMS is not set
3243# CONFIG_UNUSED_SYMBOLS is not set
3244CONFIG_DEBUG_FS=y
3245# CONFIG_HEADERS_CHECK is not set
3246# CONFIG_DEBUG_SECTION_MISMATCH is not set
3247CONFIG_DEBUG_KERNEL=y
3248# CONFIG_DEBUG_SHIRQ is not set
3249# CONFIG_LOCKUP_DETECTOR is not set
3250# CONFIG_HARDLOCKUP_DETECTOR is not set
3251CONFIG_DETECT_HUNG_TASK=y
3252# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
3253CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
3254CONFIG_SCHED_DEBUG=y
3255CONFIG_SCHEDSTATS=y
3256CONFIG_TIMER_STATS=y
3257# CONFIG_DEBUG_OBJECTS is not set
3258# CONFIG_DEBUG_SLAB is not set
3259# CONFIG_DEBUG_KMEMLEAK is not set
3260CONFIG_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
3264CONFIG_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
3293CONFIG_HAVE_FUNCTION_TRACER=y
3294CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
3295CONFIG_HAVE_DYNAMIC_FTRACE=y
3296CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
3297CONFIG_HAVE_C_RECORDMCOUNT=y
3298CONFIG_RING_BUFFER=y
3299CONFIG_RING_BUFFER_ALLOW_SWAP=y
3300CONFIG_TRACING_SUPPORT=y
3301CONFIG_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
3307CONFIG_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
3318CONFIG_HAVE_ARCH_KGDB=y
3319# CONFIG_KGDB is not set
3320# CONFIG_TEST_KSTRTOX is not set
3321# CONFIG_STRICT_DEVMEM is not set
3322CONFIG_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#
3331CONFIG_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
3336CONFIG_DEFAULT_SECURITY_DAC=y
3337CONFIG_DEFAULT_SECURITY=""
3338CONFIG_XOR_BLOCKS=m
3339CONFIG_ASYNC_CORE=m
3340CONFIG_ASYNC_MEMCPY=m
3341CONFIG_ASYNC_XOR=m
3342CONFIG_ASYNC_PQ=m
3343CONFIG_ASYNC_RAID6_RECOV=m
3344CONFIG_CRYPTO=y
3345
3346#
3347# Crypto core or helper
3348#
3349CONFIG_CRYPTO_ALGAPI=y
3350CONFIG_CRYPTO_ALGAPI2=y
3351CONFIG_CRYPTO_AEAD=m
3352CONFIG_CRYPTO_AEAD2=y
3353CONFIG_CRYPTO_BLKCIPHER=y
3354CONFIG_CRYPTO_BLKCIPHER2=y
3355CONFIG_CRYPTO_HASH=y
3356CONFIG_CRYPTO_HASH2=y
3357CONFIG_CRYPTO_RNG=m
3358CONFIG_CRYPTO_RNG2=y
3359CONFIG_CRYPTO_PCOMP2=y
3360CONFIG_CRYPTO_MANAGER=y
3361CONFIG_CRYPTO_MANAGER2=y
3362CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
3363CONFIG_CRYPTO_GF128MUL=m
3364CONFIG_CRYPTO_NULL=m
3365CONFIG_CRYPTO_WORKQUEUE=y
3366CONFIG_CRYPTO_CRYPTD=m
3367CONFIG_CRYPTO_AUTHENC=m
3368CONFIG_CRYPTO_TEST=m
3369
3370#
3371# Authenticated Encryption with Associated Data
3372#
3373CONFIG_CRYPTO_CCM=m
3374CONFIG_CRYPTO_GCM=m
3375CONFIG_CRYPTO_SEQIV=m
3376
3377#
3378# Block modes
3379#
3380CONFIG_CRYPTO_CBC=y
3381CONFIG_CRYPTO_CTR=m
3382CONFIG_CRYPTO_CTS=m
3383CONFIG_CRYPTO_ECB=y
3384CONFIG_CRYPTO_LRW=m
3385CONFIG_CRYPTO_PCBC=m
3386CONFIG_CRYPTO_XTS=m
3387
3388#
3389# Hash modes
3390#
3391CONFIG_CRYPTO_HMAC=m
3392CONFIG_CRYPTO_XCBC=m
3393# CONFIG_CRYPTO_VMAC is not set
3394
3395#
3396# Digest
3397#
3398CONFIG_CRYPTO_CRC32C=y
3399CONFIG_CRYPTO_GHASH=m
3400CONFIG_CRYPTO_MD4=m
3401CONFIG_CRYPTO_MD5=y
3402CONFIG_CRYPTO_MICHAEL_MIC=y
3403CONFIG_CRYPTO_RMD128=m
3404CONFIG_CRYPTO_RMD160=m
3405CONFIG_CRYPTO_RMD256=m
3406CONFIG_CRYPTO_RMD320=m
3407CONFIG_CRYPTO_SHA1=m
3408CONFIG_CRYPTO_SHA256=m
3409CONFIG_CRYPTO_SHA512=m
3410CONFIG_CRYPTO_TGR192=m
3411CONFIG_CRYPTO_WP512=m
3412
3413#
3414# Ciphers
3415#
3416CONFIG_CRYPTO_AES=y
3417CONFIG_CRYPTO_ANUBIS=m
3418CONFIG_CRYPTO_ARC4=y
3419CONFIG_CRYPTO_BLOWFISH=m
3420CONFIG_CRYPTO_CAMELLIA=m
3421CONFIG_CRYPTO_CAST5=m
3422CONFIG_CRYPTO_CAST6=m
3423CONFIG_CRYPTO_DES=y
3424CONFIG_CRYPTO_FCRYPT=m
3425CONFIG_CRYPTO_KHAZAD=m
3426CONFIG_CRYPTO_SALSA20=m
3427CONFIG_CRYPTO_SEED=m
3428CONFIG_CRYPTO_SERPENT=m
3429CONFIG_CRYPTO_TEA=m
3430CONFIG_CRYPTO_TWOFISH=m
3431CONFIG_CRYPTO_TWOFISH_COMMON=m
3432
3433#
3434# Compression
3435#
3436CONFIG_CRYPTO_DEFLATE=y
3437# CONFIG_CRYPTO_ZLIB is not set
3438CONFIG_CRYPTO_LZO=y
3439
3440#
3441# Random Number Generation
3442#
3443CONFIG_CRYPTO_ANSI_CPRNG=m
3444CONFIG_CRYPTO_USER_API=m
3445CONFIG_CRYPTO_USER_API_HASH=m
3446CONFIG_CRYPTO_USER_API_SKCIPHER=m
3447CONFIG_CRYPTO_HW=y
3448CONFIG_CRYPTO_DEV_OMAP_SHAM=m
3449CONFIG_CRYPTO_DEV_OMAP_AES=m
3450# CONFIG_BINARY_PRINTF is not set
3451
3452#
3453# Library routines
3454#
3455CONFIG_RAID6_PQ=m
3456CONFIG_BITREVERSE=y
3457CONFIG_GENERIC_FIND_LAST_BIT=y
3458CONFIG_CRC_CCITT=y
3459CONFIG_CRC16=y
3460CONFIG_CRC_T10DIF=y
3461CONFIG_CRC_ITU_T=y
3462CONFIG_CRC32=y
3463CONFIG_CRC7=y
3464CONFIG_LIBCRC32C=y
3465CONFIG_ZLIB_INFLATE=y
3466CONFIG_ZLIB_DEFLATE=y
3467CONFIG_LZO_COMPRESS=y
3468CONFIG_LZO_DECOMPRESS=y
3469CONFIG_XZ_DEC=y
3470CONFIG_XZ_DEC_X86=y
3471CONFIG_XZ_DEC_POWERPC=y
3472CONFIG_XZ_DEC_IA64=y
3473CONFIG_XZ_DEC_ARM=y
3474CONFIG_XZ_DEC_ARMTHUMB=y
3475CONFIG_XZ_DEC_SPARC=y
3476CONFIG_XZ_DEC_BCJ=y
3477CONFIG_XZ_DEC_TEST=m
3478CONFIG_DECOMPRESS_GZIP=y
3479CONFIG_DECOMPRESS_XZ=y
3480CONFIG_DECOMPRESS_LZO=y
3481CONFIG_TEXTSEARCH=y
3482CONFIG_TEXTSEARCH_KMP=m
3483CONFIG_TEXTSEARCH_BM=m
3484CONFIG_TEXTSEARCH_FSM=m
3485CONFIG_BTREE=y
3486CONFIG_HAS_IOMEM=y
3487CONFIG_HAS_IOPORT=y
3488CONFIG_HAS_DMA=y
3489CONFIG_NLATTR=y
3490CONFIG_AVERAGE=y
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/beagleboard/defconfig b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagleboard/defconfig
new file mode 100644
index 00000000..6f97d93b
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/beagleboard/defconfig
@@ -0,0 +1,3517 @@
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#
6CONFIG_ARM=y
7CONFIG_HAVE_PWM=y
8CONFIG_SYS_SUPPORTS_APM_EMULATION=y
9CONFIG_HAVE_SCHED_CLOCK=y
10CONFIG_GENERIC_GPIO=y
11# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
12CONFIG_GENERIC_CLOCKEVENTS=y
13CONFIG_KTIME_SCALAR=y
14CONFIG_HAVE_PROC_CPU=y
15CONFIG_STACKTRACE_SUPPORT=y
16CONFIG_HAVE_LATENCYTOP_SUPPORT=y
17CONFIG_LOCKDEP_SUPPORT=y
18CONFIG_TRACE_IRQFLAGS_SUPPORT=y
19CONFIG_HARDIRQS_SW_RESEND=y
20CONFIG_GENERIC_IRQ_PROBE=y
21CONFIG_RWSEM_GENERIC_SPINLOCK=y
22CONFIG_ARCH_HAS_CPUFREQ=y
23CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
24CONFIG_GENERIC_HWEIGHT=y
25CONFIG_GENERIC_CALIBRATE_DELAY=y
26CONFIG_NEED_DMA_MAP_STATE=y
27CONFIG_VECTORS_BASE=0xffff0000
28# CONFIG_ARM_PATCH_PHYS_VIRT is not set
29CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
30CONFIG_CONSTRUCTORS=y
31CONFIG_HAVE_IRQ_WORK=y
32CONFIG_IRQ_WORK=y
33
34#
35# General setup
36#
37CONFIG_EXPERIMENTAL=y
38CONFIG_BROKEN_ON_SMP=y
39CONFIG_INIT_ENV_ARG_LIMIT=32
40CONFIG_CROSS_COMPILE=""
41CONFIG_LOCALVERSION=""
42# CONFIG_LOCALVERSION_AUTO is not set
43CONFIG_HAVE_KERNEL_GZIP=y
44CONFIG_HAVE_KERNEL_LZMA=y
45CONFIG_HAVE_KERNEL_LZO=y
46CONFIG_KERNEL_GZIP=y
47# CONFIG_KERNEL_LZMA is not set
48# CONFIG_KERNEL_LZO is not set
49CONFIG_SWAP=y
50CONFIG_SYSVIPC=y
51CONFIG_SYSVIPC_SYSCTL=y
52CONFIG_POSIX_MQUEUE=y
53CONFIG_POSIX_MQUEUE_SYSCTL=y
54CONFIG_BSD_PROCESS_ACCT=y
55# CONFIG_BSD_PROCESS_ACCT_V3 is not set
56CONFIG_FHANDLE=y
57CONFIG_TASKSTATS=y
58CONFIG_TASK_DELAY_ACCT=y
59CONFIG_TASK_XACCT=y
60CONFIG_TASK_IO_ACCOUNTING=y
61# CONFIG_AUDIT is not set
62CONFIG_HAVE_GENERIC_HARDIRQS=y
63
64#
65# IRQ subsystem
66#
67CONFIG_GENERIC_HARDIRQS=y
68CONFIG_HAVE_SPARSE_IRQ=y
69CONFIG_GENERIC_IRQ_SHOW=y
70# CONFIG_SPARSE_IRQ is not set
71
72#
73# RCU Subsystem
74#
75CONFIG_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
79CONFIG_IKCONFIG=y
80CONFIG_IKCONFIG_PROC=y
81CONFIG_LOG_BUF_SHIFT=16
82CONFIG_CGROUPS=y
83# CONFIG_CGROUP_DEBUG is not set
84CONFIG_CGROUP_NS=y
85CONFIG_CGROUP_FREEZER=y
86CONFIG_CGROUP_DEVICE=y
87CONFIG_CPUSETS=y
88CONFIG_PROC_PID_CPUSET=y
89CONFIG_CGROUP_CPUACCT=y
90CONFIG_RESOURCE_COUNTERS=y
91CONFIG_CGROUP_MEM_RES_CTLR=y
92CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y
93CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED=y
94CONFIG_CGROUP_PERF=y
95CONFIG_CGROUP_SCHED=y
96CONFIG_FAIR_GROUP_SCHED=y
97CONFIG_RT_GROUP_SCHED=y
98CONFIG_BLK_CGROUP=y
99# CONFIG_DEBUG_BLK_CGROUP is not set
100CONFIG_NAMESPACES=y
101CONFIG_UTS_NS=y
102CONFIG_IPC_NS=y
103CONFIG_USER_NS=y
104CONFIG_PID_NS=y
105CONFIG_NET_NS=y
106CONFIG_SCHED_AUTOGROUP=y
107CONFIG_MM_OWNER=y
108# CONFIG_SYSFS_DEPRECATED is not set
109# CONFIG_RELAY is not set
110CONFIG_BLK_DEV_INITRD=y
111CONFIG_INITRAMFS_SOURCE=""
112CONFIG_RD_GZIP=y
113CONFIG_RD_BZIP2=y
114CONFIG_RD_LZMA=y
115CONFIG_RD_XZ=y
116CONFIG_RD_LZO=y
117CONFIG_CC_OPTIMIZE_FOR_SIZE=y
118CONFIG_SYSCTL=y
119CONFIG_ANON_INODES=y
120CONFIG_EXPERT=y
121CONFIG_UID16=y
122# CONFIG_SYSCTL_SYSCALL is not set
123CONFIG_KALLSYMS=y
124# CONFIG_KALLSYMS_ALL is not set
125# CONFIG_KALLSYMS_EXTRA_PASS is not set
126CONFIG_HOTPLUG=y
127CONFIG_PRINTK=y
128CONFIG_BUG=y
129CONFIG_ELF_CORE=y
130CONFIG_BASE_FULL=y
131CONFIG_FUTEX=y
132CONFIG_EPOLL=y
133CONFIG_SIGNALFD=y
134CONFIG_TIMERFD=y
135CONFIG_EVENTFD=y
136CONFIG_SHMEM=y
137CONFIG_AIO=y
138CONFIG_EMBEDDED=y
139CONFIG_HAVE_PERF_EVENTS=y
140CONFIG_PERF_USE_VMALLOC=y
141
142#
143# Kernel Performance Events And Counters
144#
145CONFIG_PERF_EVENTS=y
146# CONFIG_PERF_COUNTERS is not set
147# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
148CONFIG_VM_EVENT_COUNTERS=y
149# CONFIG_COMPAT_BRK is not set
150CONFIG_SLAB=y
151# CONFIG_SLUB is not set
152# CONFIG_SLOB is not set
153CONFIG_PROFILING=y
154CONFIG_OPROFILE=y
155CONFIG_HAVE_OPROFILE=y
156# CONFIG_KPROBES is not set
157CONFIG_HAVE_KPROBES=y
158CONFIG_HAVE_KRETPROBES=y
159CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
160CONFIG_HAVE_CLK=y
161CONFIG_HAVE_DMA_API_DEBUG=y
162CONFIG_HAVE_HW_BREAKPOINT=y
163
164#
165# GCOV-based kernel profiling
166#
167# CONFIG_GCOV_KERNEL is not set
168CONFIG_HAVE_GENERIC_DMA_COHERENT=y
169CONFIG_SLABINFO=y
170CONFIG_RT_MUTEXES=y
171CONFIG_BASE_SMALL=0
172CONFIG_MODULES=y
173CONFIG_MODULE_FORCE_LOAD=y
174CONFIG_MODULE_UNLOAD=y
175CONFIG_MODULE_FORCE_UNLOAD=y
176CONFIG_MODVERSIONS=y
177CONFIG_MODULE_SRCVERSION_ALL=y
178CONFIG_BLOCK=y
179CONFIG_LBDAF=y
180CONFIG_BLK_DEV_BSG=y
181CONFIG_BLK_DEV_INTEGRITY=y
182CONFIG_BLK_DEV_THROTTLING=y
183
184#
185# IO Schedulers
186#
187CONFIG_IOSCHED_NOOP=y
188CONFIG_IOSCHED_DEADLINE=y
189CONFIG_IOSCHED_CFQ=y
190CONFIG_CFQ_GROUP_IOSCHED=y
191# CONFIG_DEFAULT_DEADLINE is not set
192CONFIG_DEFAULT_CFQ=y
193# CONFIG_DEFAULT_NOOP is not set
194CONFIG_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
201CONFIG_INLINE_SPIN_UNLOCK=y
202# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
203CONFIG_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
210CONFIG_INLINE_READ_UNLOCK=y
211# CONFIG_INLINE_READ_UNLOCK_BH is not set
212CONFIG_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
219CONFIG_INLINE_WRITE_UNLOCK=y
220# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
221CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
222# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
223# CONFIG_MUTEX_SPIN_ON_OWNER is not set
224CONFIG_FREEZER=y
225
226#
227# System Type
228#
229CONFIG_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
284CONFIG_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#
293CONFIG_ARCH_OMAP_OTG=y
294# CONFIG_ARCH_OMAP1 is not set
295CONFIG_ARCH_OMAP2PLUS=y
296
297#
298# OMAP Feature Selections
299#
300CONFIG_OMAP_SMARTREFLEX=y
301CONFIG_OMAP_SMARTREFLEX_CLASS3=y
302CONFIG_OMAP_RESET_CLOCKS=y
303# CONFIG_OMAP_MUX is not set
304CONFIG_OMAP_MCBSP=y
305CONFIG_OMAP_MBOX_FWK=m
306CONFIG_OMAP_MBOX_KFIFO_SIZE=256
307CONFIG_OMAP_IOMMU=y
308CONFIG_OMAP_IOMMU_DEBUG=m
309CONFIG_OMAP_32K_TIMER=y
310# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set
311CONFIG_OMAP_32K_TIMER_HZ=128
312CONFIG_OMAP_DM_TIMER=y
313# CONFIG_OMAP_PM_NONE is not set
314CONFIG_OMAP_PM_NOOP=y
315
316#
317# TI OMAP2/3/4 Specific Features
318#
319CONFIG_ARCH_OMAP2PLUS_TYPICAL=y
320# CONFIG_ARCH_OMAP2 is not set
321CONFIG_ARCH_OMAP3=y
322# CONFIG_ARCH_OMAP4 is not set
323CONFIG_SOC_OMAP3430=y
324# CONFIG_SOC_OMAPTI816X is not set
325CONFIG_OMAP_PACKAGE_CBB=y
326
327#
328# OMAP Board Type
329#
330CONFIG_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
335CONFIG_MACH_OVERO=y
336CONFIG_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
340CONFIG_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
344CONFIG_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#
362CONFIG_CPU_V7=y
363CONFIG_CPU_32v6K=y
364CONFIG_CPU_32v7=y
365CONFIG_CPU_ABRT_EV7=y
366CONFIG_CPU_PABRT_V7=y
367CONFIG_CPU_CACHE_V7=y
368CONFIG_CPU_CACHE_VIPT=y
369CONFIG_CPU_COPY_V6=y
370CONFIG_CPU_TLB_V7=y
371CONFIG_CPU_HAS_ASID=y
372CONFIG_CPU_CP15=y
373CONFIG_CPU_CP15_MMU=y
374
375#
376# Processor Features
377#
378CONFIG_ARM_THUMB=y
379CONFIG_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
384CONFIG_ARM_L1_CACHE_SHIFT_6=y
385CONFIG_ARM_L1_CACHE_SHIFT=6
386CONFIG_ARM_DMA_MEM_BUFFERABLE=y
387CONFIG_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#
403CONFIG_TICK_ONESHOT=y
404CONFIG_NO_HZ=y
405CONFIG_HIGH_RES_TIMERS=y
406CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
407CONFIG_VMSPLIT_3G=y
408# CONFIG_VMSPLIT_2G is not set
409# CONFIG_VMSPLIT_1G is not set
410CONFIG_PAGE_OFFSET=0xC0000000
411# CONFIG_PREEMPT_NONE is not set
412CONFIG_PREEMPT_VOLUNTARY=y
413# CONFIG_PREEMPT is not set
414CONFIG_HZ=128
415# CONFIG_THUMB2_KERNEL is not set
416CONFIG_AEABI=y
417# CONFIG_OABI_COMPAT is not set
418CONFIG_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
422CONFIG_SELECT_MEMORY_MODEL=y
423CONFIG_FLATMEM_MANUAL=y
424CONFIG_FLATMEM=y
425CONFIG_FLAT_NODE_MEM_MAP=y
426CONFIG_HAVE_MEMBLOCK=y
427CONFIG_PAGEFLAGS_EXTENDED=y
428CONFIG_SPLIT_PTLOCK_CPUS=4
429CONFIG_COMPACTION=y
430CONFIG_MIGRATION=y
431# CONFIG_PHYS_ADDR_T_64BIT is not set
432CONFIG_ZONE_DMA_FLAG=0
433CONFIG_VIRT_TO_BUS=y
434# CONFIG_KSM is not set
435CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
436CONFIG_NEED_PER_CPU_KM=y
437CONFIG_FORCE_MAX_ZONEORDER=11
438CONFIG_LEDS=y
439CONFIG_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#
448CONFIG_ZBOOT_ROM_TEXT=0x0
449CONFIG_ZBOOT_ROM_BSS=0x0
450CONFIG_CMDLINE=" debug "
451# CONFIG_CMDLINE_FORCE is not set
452# CONFIG_XIP_KERNEL is not set
453CONFIG_KEXEC=y
454CONFIG_ATAGS_PROC=y
455# CONFIG_CRASH_DUMP is not set
456CONFIG_AUTO_ZRELADDR=y
457
458#
459# CPU Power Management
460#
461CONFIG_CPU_FREQ=y
462CONFIG_CPU_FREQ_TABLE=y
463# CONFIG_CPU_FREQ_DEBUG is not set
464CONFIG_CPU_FREQ_STAT=y
465CONFIG_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
468CONFIG_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
472CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
473CONFIG_CPU_FREQ_GOV_POWERSAVE=y
474CONFIG_CPU_FREQ_GOV_USERSPACE=y
475CONFIG_CPU_FREQ_GOV_ONDEMAND=y
476CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
477CONFIG_CPU_IDLE=y
478CONFIG_CPU_IDLE_GOV_LADDER=y
479CONFIG_CPU_IDLE_GOV_MENU=y
480
481#
482# Floating point emulation
483#
484
485#
486# At least one emulation must be selected
487#
488CONFIG_VFP=y
489CONFIG_VFPv3=y
490CONFIG_NEON=y
491
492#
493# Userspace binary formats
494#
495CONFIG_BINFMT_ELF=y
496# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
497CONFIG_HAVE_AOUT=y
498CONFIG_BINFMT_AOUT=m
499CONFIG_BINFMT_MISC=y
500
501#
502# Power management options
503#
504CONFIG_SUSPEND=y
505CONFIG_SUSPEND_FREEZER=y
506CONFIG_PM_SLEEP=y
507CONFIG_PM_RUNTIME=y
508CONFIG_PM=y
509CONFIG_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
513CONFIG_CAN_PM_TRACE=y
514# CONFIG_APM_EMULATION is not set
515CONFIG_ARCH_HAS_OPP=y
516CONFIG_PM_OPP=y
517CONFIG_ARCH_SUSPEND_POSSIBLE=y
518CONFIG_NET=y
519
520#
521# Networking options
522#
523CONFIG_PACKET=y
524CONFIG_UNIX=y
525CONFIG_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
530CONFIG_XFRM_IPCOMP=m
531CONFIG_NET_KEY=y
532# CONFIG_NET_KEY_MIGRATE is not set
533CONFIG_INET=y
534# CONFIG_IP_MULTICAST is not set
535# CONFIG_IP_ADVANCED_ROUTER is not set
536CONFIG_IP_ROUTE_CLASSID=y
537CONFIG_IP_PNP=y
538CONFIG_IP_PNP_DHCP=y
539CONFIG_IP_PNP_BOOTP=y
540CONFIG_IP_PNP_RARP=y
541CONFIG_NET_IPIP=m
542CONFIG_NET_IPGRE_DEMUX=m
543CONFIG_NET_IPGRE=m
544# CONFIG_ARPD is not set
545# CONFIG_SYN_COOKIES is not set
546CONFIG_INET_AH=m
547CONFIG_INET_ESP=m
548CONFIG_INET_IPCOMP=m
549CONFIG_INET_XFRM_TUNNEL=m
550CONFIG_INET_TUNNEL=m
551CONFIG_INET_XFRM_MODE_TRANSPORT=y
552CONFIG_INET_XFRM_MODE_TUNNEL=y
553CONFIG_INET_XFRM_MODE_BEET=y
554CONFIG_INET_LRO=y
555CONFIG_INET_DIAG=m
556CONFIG_INET_TCP_DIAG=m
557CONFIG_TCP_CONG_ADVANCED=y
558CONFIG_TCP_CONG_BIC=m
559CONFIG_TCP_CONG_CUBIC=y
560CONFIG_TCP_CONG_WESTWOOD=m
561CONFIG_TCP_CONG_HTCP=m
562CONFIG_TCP_CONG_HSTCP=m
563CONFIG_TCP_CONG_HYBLA=m
564CONFIG_TCP_CONG_VEGAS=m
565CONFIG_TCP_CONG_SCALABLE=m
566CONFIG_TCP_CONG_LP=m
567CONFIG_TCP_CONG_VENO=m
568CONFIG_TCP_CONG_YEAH=m
569CONFIG_TCP_CONG_ILLINOIS=m
570CONFIG_DEFAULT_CUBIC=y
571# CONFIG_DEFAULT_RENO is not set
572CONFIG_DEFAULT_TCP_CONG="cubic"
573# CONFIG_TCP_MD5SIG is not set
574CONFIG_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
578CONFIG_INET6_AH=m
579CONFIG_INET6_ESP=m
580CONFIG_INET6_IPCOMP=m
581CONFIG_IPV6_MIP6=m
582CONFIG_INET6_XFRM_TUNNEL=m
583CONFIG_INET6_TUNNEL=m
584CONFIG_INET6_XFRM_MODE_TRANSPORT=m
585CONFIG_INET6_XFRM_MODE_TUNNEL=m
586CONFIG_INET6_XFRM_MODE_BEET=m
587CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
588CONFIG_IPV6_SIT=m
589# CONFIG_IPV6_SIT_6RD is not set
590CONFIG_IPV6_NDISC_NODETYPE=y
591CONFIG_IPV6_TUNNEL=m
592CONFIG_IPV6_MULTIPLE_TABLES=y
593CONFIG_IPV6_SUBTREES=y
594CONFIG_IPV6_MROUTE=y
595CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
596# CONFIG_IPV6_PIMSM_V2 is not set
597# CONFIG_NETWORK_SECMARK is not set
598CONFIG_NETWORK_PHY_TIMESTAMPING=y
599CONFIG_NETFILTER=y
600# CONFIG_NETFILTER_DEBUG is not set
601CONFIG_NETFILTER_ADVANCED=y
602CONFIG_BRIDGE_NETFILTER=y
603
604#
605# Core Netfilter Configuration
606#
607CONFIG_NETFILTER_NETLINK=m
608CONFIG_NETFILTER_NETLINK_QUEUE=m
609CONFIG_NETFILTER_NETLINK_LOG=m
610CONFIG_NF_CONNTRACK=m
611CONFIG_NF_CONNTRACK_MARK=y
612CONFIG_NF_CONNTRACK_ZONES=y
613CONFIG_NF_CONNTRACK_EVENTS=y
614CONFIG_NF_CONNTRACK_TIMESTAMP=y
615CONFIG_NF_CT_PROTO_DCCP=m
616CONFIG_NF_CT_PROTO_GRE=m
617CONFIG_NF_CT_PROTO_SCTP=m
618CONFIG_NF_CT_PROTO_UDPLITE=m
619CONFIG_NF_CONNTRACK_AMANDA=m
620CONFIG_NF_CONNTRACK_FTP=m
621CONFIG_NF_CONNTRACK_H323=m
622CONFIG_NF_CONNTRACK_IRC=m
623CONFIG_NF_CONNTRACK_BROADCAST=m
624CONFIG_NF_CONNTRACK_NETBIOS_NS=m
625CONFIG_NF_CONNTRACK_SNMP=m
626CONFIG_NF_CONNTRACK_PPTP=m
627CONFIG_NF_CONNTRACK_SANE=m
628CONFIG_NF_CONNTRACK_SIP=m
629CONFIG_NF_CONNTRACK_TFTP=m
630CONFIG_NF_CT_NETLINK=m
631# CONFIG_NETFILTER_TPROXY is not set
632CONFIG_NETFILTER_XTABLES=m
633
634#
635# Xtables combined modules
636#
637CONFIG_NETFILTER_XT_MARK=m
638CONFIG_NETFILTER_XT_CONNMARK=m
639CONFIG_NETFILTER_XT_SET=m
640
641#
642# Xtables targets
643#
644CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
645CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
646CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
647CONFIG_NETFILTER_XT_TARGET_CT=m
648# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
649CONFIG_NETFILTER_XT_TARGET_HL=m
650CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
651# CONFIG_NETFILTER_XT_TARGET_LED is not set
652CONFIG_NETFILTER_XT_TARGET_MARK=m
653CONFIG_NETFILTER_XT_TARGET_NFLOG=m
654CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
655# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
656CONFIG_NETFILTER_XT_TARGET_RATEEST=m
657CONFIG_NETFILTER_XT_TARGET_TEE=m
658# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
659CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
660# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
661
662#
663# Xtables matches
664#
665CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
666# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
667CONFIG_NETFILTER_XT_MATCH_COMMENT=m
668CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
669CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
670CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
671CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
672CONFIG_NETFILTER_XT_MATCH_CPU=m
673CONFIG_NETFILTER_XT_MATCH_DCCP=m
674CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
675CONFIG_NETFILTER_XT_MATCH_DSCP=m
676CONFIG_NETFILTER_XT_MATCH_ESP=m
677CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
678CONFIG_NETFILTER_XT_MATCH_HELPER=m
679CONFIG_NETFILTER_XT_MATCH_HL=m
680CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
681CONFIG_NETFILTER_XT_MATCH_IPVS=m
682CONFIG_NETFILTER_XT_MATCH_LENGTH=m
683CONFIG_NETFILTER_XT_MATCH_LIMIT=m
684CONFIG_NETFILTER_XT_MATCH_MAC=m
685CONFIG_NETFILTER_XT_MATCH_MARK=m
686CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
687# CONFIG_NETFILTER_XT_MATCH_OSF is not set
688CONFIG_NETFILTER_XT_MATCH_OWNER=m
689CONFIG_NETFILTER_XT_MATCH_POLICY=m
690# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
691CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
692CONFIG_NETFILTER_XT_MATCH_QUOTA=m
693CONFIG_NETFILTER_XT_MATCH_RATEEST=m
694CONFIG_NETFILTER_XT_MATCH_REALM=m
695CONFIG_NETFILTER_XT_MATCH_RECENT=m
696CONFIG_NETFILTER_XT_MATCH_SCTP=m
697CONFIG_NETFILTER_XT_MATCH_STATE=m
698CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
699CONFIG_NETFILTER_XT_MATCH_STRING=m
700CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
701CONFIG_NETFILTER_XT_MATCH_TIME=m
702CONFIG_NETFILTER_XT_MATCH_U32=m
703CONFIG_IP_SET=m
704CONFIG_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
715CONFIG_IP_VS=m
716CONFIG_IP_VS_IPV6=y
717CONFIG_IP_VS_DEBUG=y
718CONFIG_IP_VS_TAB_BITS=12
719
720#
721# IPVS transport protocol load balancing support
722#
723CONFIG_IP_VS_PROTO_TCP=y
724CONFIG_IP_VS_PROTO_UDP=y
725CONFIG_IP_VS_PROTO_AH_ESP=y
726CONFIG_IP_VS_PROTO_ESP=y
727CONFIG_IP_VS_PROTO_AH=y
728# CONFIG_IP_VS_PROTO_SCTP is not set
729
730#
731# IPVS scheduler
732#
733CONFIG_IP_VS_RR=m
734CONFIG_IP_VS_WRR=m
735CONFIG_IP_VS_LC=m
736CONFIG_IP_VS_WLC=m
737CONFIG_IP_VS_LBLC=m
738CONFIG_IP_VS_LBLCR=m
739CONFIG_IP_VS_DH=m
740CONFIG_IP_VS_SH=m
741CONFIG_IP_VS_SED=m
742CONFIG_IP_VS_NQ=m
743
744#
745# IPVS application helper
746#
747CONFIG_IP_VS_FTP=m
748CONFIG_IP_VS_NFCT=y
749CONFIG_IP_VS_PE_SIP=m
750
751#
752# IP: Netfilter Configuration
753#
754CONFIG_NF_DEFRAG_IPV4=m
755CONFIG_NF_CONNTRACK_IPV4=m
756CONFIG_NF_CONNTRACK_PROC_COMPAT=y
757CONFIG_IP_NF_QUEUE=m
758CONFIG_IP_NF_IPTABLES=m
759CONFIG_IP_NF_MATCH_AH=m
760CONFIG_IP_NF_MATCH_ECN=m
761CONFIG_IP_NF_MATCH_TTL=m
762CONFIG_IP_NF_FILTER=m
763CONFIG_IP_NF_TARGET_REJECT=m
764CONFIG_IP_NF_TARGET_LOG=m
765CONFIG_IP_NF_TARGET_ULOG=m
766CONFIG_NF_NAT=m
767CONFIG_NF_NAT_NEEDED=y
768CONFIG_IP_NF_TARGET_MASQUERADE=m
769CONFIG_IP_NF_TARGET_NETMAP=m
770CONFIG_IP_NF_TARGET_REDIRECT=m
771CONFIG_NF_NAT_SNMP_BASIC=m
772CONFIG_NF_NAT_PROTO_DCCP=m
773CONFIG_NF_NAT_PROTO_GRE=m
774CONFIG_NF_NAT_PROTO_UDPLITE=m
775CONFIG_NF_NAT_PROTO_SCTP=m
776CONFIG_NF_NAT_FTP=m
777CONFIG_NF_NAT_IRC=m
778CONFIG_NF_NAT_TFTP=m
779CONFIG_NF_NAT_AMANDA=m
780CONFIG_NF_NAT_PPTP=m
781CONFIG_NF_NAT_H323=m
782CONFIG_NF_NAT_SIP=m
783CONFIG_IP_NF_MANGLE=m
784CONFIG_IP_NF_TARGET_CLUSTERIP=m
785CONFIG_IP_NF_TARGET_ECN=m
786CONFIG_IP_NF_TARGET_TTL=m
787CONFIG_IP_NF_RAW=m
788CONFIG_IP_NF_ARPTABLES=m
789CONFIG_IP_NF_ARPFILTER=m
790CONFIG_IP_NF_ARP_MANGLE=m
791
792#
793# IPv6: Netfilter Configuration
794#
795CONFIG_NF_DEFRAG_IPV6=m
796CONFIG_NF_CONNTRACK_IPV6=m
797CONFIG_IP6_NF_QUEUE=m
798CONFIG_IP6_NF_IPTABLES=m
799CONFIG_IP6_NF_MATCH_AH=m
800CONFIG_IP6_NF_MATCH_EUI64=m
801CONFIG_IP6_NF_MATCH_FRAG=m
802CONFIG_IP6_NF_MATCH_OPTS=m
803CONFIG_IP6_NF_MATCH_HL=m
804CONFIG_IP6_NF_MATCH_IPV6HEADER=m
805CONFIG_IP6_NF_MATCH_MH=m
806CONFIG_IP6_NF_MATCH_RT=m
807CONFIG_IP6_NF_TARGET_HL=m
808CONFIG_IP6_NF_TARGET_LOG=m
809CONFIG_IP6_NF_FILTER=m
810CONFIG_IP6_NF_TARGET_REJECT=m
811CONFIG_IP6_NF_MANGLE=m
812CONFIG_IP6_NF_RAW=m
813# CONFIG_BRIDGE_NF_EBTABLES is not set
814CONFIG_IP_DCCP=m
815CONFIG_INET_DCCP_DIAG=m
816
817#
818# DCCP CCIDs Configuration (EXPERIMENTAL)
819#
820# CONFIG_IP_DCCP_CCID2_DEBUG is not set
821CONFIG_IP_DCCP_CCID3=y
822# CONFIG_IP_DCCP_CCID3_DEBUG is not set
823CONFIG_IP_DCCP_TFRC_LIB=y
824
825#
826# DCCP Kernel Hacking
827#
828# CONFIG_IP_DCCP_DEBUG is not set
829CONFIG_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
834CONFIG_SCTP_HMAC_MD5=y
835# CONFIG_RDS is not set
836CONFIG_TIPC=m
837# CONFIG_TIPC_ADVANCED is not set
838# CONFIG_TIPC_DEBUG is not set
839CONFIG_ATM=m
840CONFIG_ATM_CLIP=m
841# CONFIG_ATM_CLIP_NO_ICMP is not set
842CONFIG_ATM_LANE=m
843CONFIG_ATM_MPOA=m
844CONFIG_ATM_BR2684=m
845# CONFIG_ATM_BR2684_IPFILTER is not set
846CONFIG_L2TP=m
847CONFIG_L2TP_DEBUGFS=m
848CONFIG_L2TP_V3=y
849CONFIG_L2TP_IP=m
850CONFIG_L2TP_ETH=m
851CONFIG_STP=m
852CONFIG_GARP=m
853CONFIG_BRIDGE=m
854CONFIG_BRIDGE_IGMP_SNOOPING=y
855# CONFIG_NET_DSA is not set
856CONFIG_VLAN_8021Q=m
857CONFIG_VLAN_8021Q_GVRP=y
858# CONFIG_DECNET is not set
859CONFIG_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
866CONFIG_WAN_ROUTER=m
867# CONFIG_PHONET is not set
868# CONFIG_IEEE802154 is not set
869CONFIG_NET_SCHED=y
870
871#
872# Queueing/Scheduling
873#
874CONFIG_NET_SCH_CBQ=m
875CONFIG_NET_SCH_HTB=m
876CONFIG_NET_SCH_HFSC=m
877CONFIG_NET_SCH_ATM=m
878CONFIG_NET_SCH_PRIO=m
879CONFIG_NET_SCH_MULTIQ=m
880CONFIG_NET_SCH_RED=m
881# CONFIG_NET_SCH_SFB is not set
882CONFIG_NET_SCH_SFQ=m
883CONFIG_NET_SCH_TEQL=m
884CONFIG_NET_SCH_TBF=m
885CONFIG_NET_SCH_GRED=m
886CONFIG_NET_SCH_DSMARK=m
887CONFIG_NET_SCH_NETEM=m
888CONFIG_NET_SCH_DRR=m
889CONFIG_NET_SCH_MQPRIO=m
890CONFIG_NET_SCH_CHOKE=m
891
892#
893# Classification
894#
895CONFIG_NET_CLS=y
896CONFIG_NET_CLS_BASIC=m
897CONFIG_NET_CLS_TCINDEX=m
898CONFIG_NET_CLS_ROUTE4=m
899CONFIG_NET_CLS_FW=m
900CONFIG_NET_CLS_U32=m
901CONFIG_CLS_U32_PERF=y
902CONFIG_CLS_U32_MARK=y
903CONFIG_NET_CLS_RSVP=m
904CONFIG_NET_CLS_RSVP6=m
905CONFIG_NET_CLS_FLOW=m
906CONFIG_NET_CLS_CGROUP=m
907# CONFIG_NET_EMATCH is not set
908# CONFIG_NET_CLS_ACT is not set
909CONFIG_NET_CLS_IND=y
910CONFIG_NET_SCH_FIFO=y
911# CONFIG_DCB is not set
912CONFIG_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
920CONFIG_CAN=m
921CONFIG_CAN_RAW=m
922CONFIG_CAN_BCM=m
923
924#
925# CAN Device Drivers
926#
927CONFIG_CAN_VCAN=m
928CONFIG_CAN_SLCAN=m
929# CONFIG_CAN_DEV is not set
930# CONFIG_CAN_DEBUG_DEVICES is not set
931CONFIG_IRDA=m
932
933#
934# IrDA protocols
935#
936CONFIG_IRLAN=m
937CONFIG_IRNET=m
938CONFIG_IRCOMM=m
939CONFIG_IRDA_ULTRA=y
940
941#
942# IrDA options
943#
944CONFIG_IRDA_CACHE_LAST_LSAP=y
945CONFIG_IRDA_FAST_RR=y
946CONFIG_IRDA_DEBUG=y
947
948#
949# Infrared-port device drivers
950#
951
952#
953# SIR device drivers
954#
955CONFIG_IRTTY_SIR=m
956
957#
958# Dongle support
959#
960CONFIG_DONGLE=y
961CONFIG_ESI_DONGLE=m
962CONFIG_ACTISYS_DONGLE=m
963CONFIG_TEKRAM_DONGLE=m
964CONFIG_TOIM3232_DONGLE=m
965CONFIG_LITELINK_DONGLE=m
966CONFIG_MA600_DONGLE=m
967CONFIG_GIRBIL_DONGLE=m
968CONFIG_MCP2120_DONGLE=m
969CONFIG_OLD_BELKIN_DONGLE=m
970# CONFIG_ACT200L_DONGLE is not set
971CONFIG_KINGSUN_DONGLE=m
972CONFIG_KSDAZZLE_DONGLE=m
973CONFIG_KS959_DONGLE=m
974
975#
976# FIR device drivers
977#
978CONFIG_USB_IRDA=m
979CONFIG_SIGMATEL_FIR=m
980CONFIG_MCS_FIR=m
981CONFIG_BT=y
982CONFIG_BT_L2CAP=y
983CONFIG_BT_SCO=y
984CONFIG_BT_RFCOMM=m
985CONFIG_BT_RFCOMM_TTY=y
986CONFIG_BT_BNEP=m
987CONFIG_BT_BNEP_MC_FILTER=y
988CONFIG_BT_BNEP_PROTO_FILTER=y
989CONFIG_BT_HIDP=m
990
991#
992# Bluetooth device drivers
993#
994CONFIG_BT_HCIBTUSB=y
995CONFIG_BT_HCIBTSDIO=m
996CONFIG_BT_HCIUART=y
997CONFIG_BT_HCIUART_H4=y
998CONFIG_BT_HCIUART_BCSP=y
999CONFIG_BT_HCIUART_ATH3K=y
1000CONFIG_BT_HCIUART_LL=y
1001CONFIG_BT_HCIBCM203X=m
1002CONFIG_BT_HCIBPA10X=m
1003CONFIG_BT_HCIBFUSB=m
1004# CONFIG_BT_HCIVHCI is not set
1005CONFIG_BT_MRVL=m
1006# CONFIG_BT_MRVL_SDIO is not set
1007CONFIG_BT_ATH3K=m
1008CONFIG_BT_WILINK=m
1009CONFIG_AF_RXRPC=m
1010# CONFIG_AF_RXRPC_DEBUG is not set
1011# CONFIG_RXKAD is not set
1012CONFIG_FIB_RULES=y
1013CONFIG_WIRELESS=y
1014CONFIG_WIRELESS_EXT=y
1015CONFIG_WEXT_CORE=y
1016CONFIG_WEXT_PROC=y
1017CONFIG_WEXT_SPY=y
1018CONFIG_WEXT_PRIV=y
1019CONFIG_CFG80211=m
1020CONFIG_NL80211_TESTMODE=y
1021# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
1022# CONFIG_CFG80211_REG_DEBUG is not set
1023CONFIG_CFG80211_DEFAULT_PS=y
1024# CONFIG_CFG80211_DEBUGFS is not set
1025# CONFIG_CFG80211_INTERNAL_REGDB is not set
1026CONFIG_CFG80211_WEXT=y
1027CONFIG_WIRELESS_EXT_SYSFS=y
1028CONFIG_LIB80211=y
1029CONFIG_LIB80211_CRYPT_WEP=m
1030CONFIG_LIB80211_CRYPT_CCMP=m
1031CONFIG_LIB80211_CRYPT_TKIP=m
1032# CONFIG_LIB80211_DEBUG is not set
1033CONFIG_MAC80211=m
1034CONFIG_MAC80211_HAS_RC=y
1035CONFIG_MAC80211_RC_PID=y
1036# CONFIG_MAC80211_RC_MINSTREL is not set
1037CONFIG_MAC80211_RC_DEFAULT_PID=y
1038CONFIG_MAC80211_RC_DEFAULT="pid"
1039# CONFIG_MAC80211_MESH is not set
1040CONFIG_MAC80211_LEDS=y
1041# CONFIG_MAC80211_DEBUGFS is not set
1042# CONFIG_MAC80211_DEBUG_MENU is not set
1043CONFIG_WIMAX=m
1044CONFIG_WIMAX_DEBUG_LEVEL=8
1045CONFIG_RFKILL=y
1046CONFIG_RFKILL_LEDS=y
1047CONFIG_RFKILL_INPUT=y
1048CONFIG_NET_9P=m
1049# CONFIG_NET_9P_DEBUG is not set
1050# CONFIG_CAIF is not set
1051CONFIG_CEPH_LIB=m
1052# CONFIG_CEPH_LIB_PRETTYDEBUG is not set
1053
1054#
1055# Device Drivers
1056#
1057
1058#
1059# Generic Driver Options
1060#
1061CONFIG_UEVENT_HELPER_PATH=""
1062CONFIG_DEVTMPFS=y
1063CONFIG_DEVTMPFS_MOUNT=y
1064CONFIG_STANDALONE=y
1065CONFIG_PREVENT_FIRMWARE_BUILD=y
1066CONFIG_FW_LOADER=y
1067CONFIG_FIRMWARE_IN_KERNEL=y
1068CONFIG_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
1073CONFIG_MTD=y
1074# CONFIG_MTD_DEBUG is not set
1075# CONFIG_MTD_TESTS is not set
1076CONFIG_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#
1085CONFIG_MTD_CHAR=y
1086CONFIG_MTD_BLKDEVS=y
1087CONFIG_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
1093CONFIG_SM_FTL=m
1094# CONFIG_MTD_OOPS is not set
1095CONFIG_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
1102CONFIG_MTD_MAP_BANK_WIDTH_1=y
1103CONFIG_MTD_MAP_BANK_WIDTH_2=y
1104CONFIG_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
1108CONFIG_MTD_CFI_I1=y
1109CONFIG_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
1139CONFIG_MTD_NAND_ECC=y
1140# CONFIG_MTD_NAND_ECC_SMC is not set
1141CONFIG_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
1147CONFIG_MTD_NAND_OMAP2=y
1148CONFIG_MTD_NAND_IDS=y
1149# CONFIG_MTD_NAND_DISKONCHIP is not set
1150# CONFIG_MTD_NAND_NANDSIM is not set
1151CONFIG_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
1159CONFIG_MTD_UBI=y
1160CONFIG_MTD_UBI_WL_THRESHOLD=4096
1161CONFIG_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
1165CONFIG_BLK_DEV=y
1166# CONFIG_BLK_DEV_COW_COMMON is not set
1167CONFIG_BLK_DEV_LOOP=y
1168CONFIG_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
1175CONFIG_BLK_DEV_RAM=y
1176CONFIG_BLK_DEV_RAM_COUNT=16
1177CONFIG_BLK_DEV_RAM_SIZE=16384
1178# CONFIG_BLK_DEV_XIP is not set
1179CONFIG_CDROM_PKTCDVD=m
1180CONFIG_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
1186CONFIG_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
1194CONFIG_SENSORS_BH1780=m
1195# CONFIG_SENSORS_BH1770 is not set
1196# CONFIG_SENSORS_APDS990X is not set
1197CONFIG_HMC6352=m
1198# CONFIG_DS1682 is not set
1199# CONFIG_TI_DAC7512 is not set
1200CONFIG_BMP085=m
1201# CONFIG_C2PORT is not set
1202
1203#
1204# EEPROM support
1205#
1206CONFIG_EEPROM_AT24=m
1207# CONFIG_EEPROM_AT25 is not set
1208# CONFIG_EEPROM_LEGACY is not set
1209# CONFIG_EEPROM_MAX6875 is not set
1210CONFIG_EEPROM_93CX6=y
1211CONFIG_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#
1218CONFIG_TI_ST=m
1219# CONFIG_SENSORS_LIS3_SPI is not set
1220# CONFIG_SENSORS_LIS3_I2C is not set
1221CONFIG_HAVE_IDE=y
1222# CONFIG_IDE is not set
1223
1224#
1225# SCSI device support
1226#
1227CONFIG_SCSI_MOD=y
1228CONFIG_RAID_ATTRS=m
1229CONFIG_SCSI=y
1230CONFIG_SCSI_DMA=y
1231# CONFIG_SCSI_TGT is not set
1232# CONFIG_SCSI_NETLINK is not set
1233CONFIG_SCSI_PROC_FS=y
1234
1235#
1236# SCSI support type (disk, tape, CD-ROM)
1237#
1238CONFIG_BLK_DEV_SD=y
1239# CONFIG_CHR_DEV_ST is not set
1240# CONFIG_CHR_DEV_OSST is not set
1241CONFIG_BLK_DEV_SR=y
1242CONFIG_BLK_DEV_SR_VENDOR=y
1243CONFIG_CHR_DEV_SG=y
1244CONFIG_CHR_DEV_SCH=m
1245CONFIG_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
1249CONFIG_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
1256CONFIG_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
1260CONFIG_SCSI_LOWLEVEL=y
1261CONFIG_ISCSI_TCP=m
1262CONFIG_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
1269CONFIG_MD=y
1270CONFIG_BLK_DEV_MD=m
1271CONFIG_MD_LINEAR=m
1272CONFIG_MD_RAID0=m
1273CONFIG_MD_RAID1=m
1274CONFIG_MD_RAID10=m
1275CONFIG_MD_RAID456=m
1276CONFIG_MD_MULTIPATH=m
1277CONFIG_MD_FAULTY=m
1278CONFIG_BLK_DEV_DM=m
1279# CONFIG_DM_DEBUG is not set
1280CONFIG_DM_CRYPT=m
1281CONFIG_DM_SNAPSHOT=m
1282CONFIG_DM_MIRROR=m
1283CONFIG_DM_RAID=m
1284# CONFIG_DM_LOG_USERSPACE is not set
1285CONFIG_DM_ZERO=m
1286CONFIG_DM_MULTIPATH=m
1287# CONFIG_DM_MULTIPATH_QL is not set
1288# CONFIG_DM_MULTIPATH_ST is not set
1289CONFIG_DM_DELAY=m
1290# CONFIG_DM_UEVENT is not set
1291CONFIG_DM_FLAKEY=m
1292CONFIG_TARGET_CORE=m
1293CONFIG_TCM_IBLOCK=m
1294CONFIG_TCM_FILEIO=m
1295CONFIG_TCM_PSCSI=m
1296CONFIG_LOOPBACK_TARGET=m
1297# CONFIG_LOOPBACK_TARGET_CDB_DEBUG is not set
1298CONFIG_NETDEVICES=y
1299CONFIG_DUMMY=m
1300CONFIG_BONDING=m
1301CONFIG_MACVLAN=m
1302CONFIG_MACVTAP=m
1303CONFIG_EQUALIZER=m
1304CONFIG_TUN=m
1305CONFIG_VETH=m
1306CONFIG_MII=y
1307CONFIG_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
1320CONFIG_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
1326CONFIG_MICREL_PHY=m
1327# CONFIG_FIXED_PHY is not set
1328# CONFIG_MDIO_BITBANG is not set
1329CONFIG_NET_ETHERNET=y
1330# CONFIG_AX88796 is not set
1331CONFIG_SMC91X=y
1332# CONFIG_TI_DAVINCI_EMAC is not set
1333CONFIG_TI_DAVINCI_MDIO=m
1334CONFIG_TI_DAVINCI_CPDMA=m
1335# CONFIG_DM9000 is not set
1336CONFIG_ENC28J60=y
1337# CONFIG_ENC28J60_WRITEVERIFY is not set
1338# CONFIG_ETHOC is not set
1339CONFIG_SMC911X=y
1340CONFIG_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
1351CONFIG_KS8842=m
1352CONFIG_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
1357CONFIG_WLAN=y
1358# CONFIG_LIBERTAS_THINFIRM is not set
1359CONFIG_AT76C50X_USB=m
1360CONFIG_USB_ZD1201=m
1361CONFIG_USB_NET_RNDIS_WLAN=m
1362CONFIG_RTL8187=m
1363CONFIG_RTL8187_LEDS=y
1364# CONFIG_MAC80211_HWSIM is not set
1365# CONFIG_ATH_COMMON is not set
1366CONFIG_B43=m
1367# CONFIG_B43_SDIO is not set
1368CONFIG_B43_PIO=y
1369CONFIG_B43_PHY_N=y
1370CONFIG_B43_PHY_LP=y
1371CONFIG_B43_LEDS=y
1372CONFIG_B43_HWRNG=y
1373# CONFIG_B43_DEBUG is not set
1374# CONFIG_B43LEGACY is not set
1375CONFIG_HOSTAP=m
1376CONFIG_HOSTAP_FIRMWARE=y
1377CONFIG_HOSTAP_FIRMWARE_NVRAM=y
1378# CONFIG_IWM is not set
1379CONFIG_LIBERTAS=m
1380CONFIG_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
1385CONFIG_P54_COMMON=m
1386CONFIG_P54_USB=m
1387# CONFIG_P54_SPI is not set
1388CONFIG_P54_LEDS=y
1389CONFIG_RT2X00=m
1390CONFIG_RT2500USB=m
1391CONFIG_RT73USB=m
1392# CONFIG_RT2800USB is not set
1393CONFIG_RT2X00_LIB_USB=m
1394CONFIG_RT2X00_LIB=m
1395CONFIG_RT2X00_LIB_FIRMWARE=y
1396CONFIG_RT2X00_LIB_CRYPTO=y
1397CONFIG_RT2X00_LIB_LEDS=y
1398# CONFIG_RT2X00_DEBUG is not set
1399CONFIG_RTL8192CU=m
1400CONFIG_RTLWIFI=m
1401CONFIG_RTL8192C_COMMON=m
1402CONFIG_WL1251=m
1403CONFIG_WL1251_SPI=m
1404CONFIG_WL1251_SDIO=m
1405CONFIG_WL12XX_MENU=m
1406CONFIG_WL12XX=m
1407CONFIG_WL12XX_HT=y
1408CONFIG_WL12XX_SPI=m
1409CONFIG_WL12XX_SDIO=m
1410# CONFIG_WL12XX_SDIO_TEST is not set
1411CONFIG_WL12XX_PLATFORM_DATA=y
1412CONFIG_ZD1211RW=m
1413# CONFIG_ZD1211RW_DEBUG is not set
1414
1415#
1416# WiMAX Wireless Broadband devices
1417#
1418CONFIG_WIMAX_I2400M=m
1419CONFIG_WIMAX_I2400M_USB=m
1420CONFIG_WIMAX_I2400M_SDIO=m
1421CONFIG_WIMAX_IWMC3200_SDIO=y
1422CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8
1423
1424#
1425# USB Network Adapters
1426#
1427CONFIG_USB_CATC=y
1428CONFIG_USB_KAWETH=y
1429CONFIG_USB_PEGASUS=y
1430CONFIG_USB_RTL8150=y
1431CONFIG_USB_USBNET=y
1432CONFIG_USB_NET_AX8817X=y
1433CONFIG_USB_NET_CDCETHER=y
1434# CONFIG_USB_NET_CDC_EEM is not set
1435CONFIG_USB_NET_CDC_NCM=m
1436CONFIG_USB_NET_DM9601=y
1437CONFIG_USB_NET_SMSC75XX=m
1438CONFIG_USB_NET_SMSC95XX=y
1439CONFIG_USB_NET_GL620A=y
1440CONFIG_USB_NET_NET1080=y
1441CONFIG_USB_NET_PLUSB=y
1442CONFIG_USB_NET_MCS7830=y
1443CONFIG_USB_NET_RNDIS_HOST=y
1444CONFIG_USB_NET_CDC_SUBSET=y
1445CONFIG_USB_ALI_M5632=y
1446CONFIG_USB_AN2720=y
1447CONFIG_USB_BELKIN=y
1448CONFIG_USB_ARMLINUX=y
1449CONFIG_USB_EPSON2888=y
1450CONFIG_USB_KC2190=y
1451CONFIG_USB_NET_ZAURUS=y
1452CONFIG_USB_NET_CX82310_ETH=m
1453CONFIG_USB_HSO=m
1454CONFIG_USB_NET_INT51X1=m
1455CONFIG_USB_IPHETH=m
1456CONFIG_USB_SIERRA_NET=m
1457CONFIG_USB_VL600=m
1458# CONFIG_WAN is not set
1459CONFIG_ATM_DRIVERS=y
1460# CONFIG_ATM_DUMMY is not set
1461# CONFIG_ATM_TCP is not set
1462
1463#
1464# CAIF transport drivers
1465#
1466CONFIG_PPP=m
1467CONFIG_PPP_MULTILINK=y
1468CONFIG_PPP_FILTER=y
1469CONFIG_PPP_ASYNC=m
1470CONFIG_PPP_SYNC_TTY=m
1471CONFIG_PPP_DEFLATE=m
1472CONFIG_PPP_BSDCOMP=m
1473CONFIG_PPP_MPPE=m
1474CONFIG_PPPOE=m
1475CONFIG_PPTP=m
1476# CONFIG_PPPOATM is not set
1477CONFIG_PPPOL2TP=m
1478# CONFIG_SLIP is not set
1479CONFIG_SLHC=m
1480CONFIG_NETCONSOLE=m
1481CONFIG_NETCONSOLE_DYNAMIC=y
1482CONFIG_NETPOLL=y
1483CONFIG_NETPOLL_TRAP=y
1484CONFIG_NET_POLL_CONTROLLER=y
1485# CONFIG_ISDN is not set
1486# CONFIG_PHONE is not set
1487
1488#
1489# Input device support
1490#
1491CONFIG_INPUT=y
1492CONFIG_INPUT_FF_MEMLESS=y
1493CONFIG_INPUT_POLLDEV=y
1494# CONFIG_INPUT_SPARSEKMAP is not set
1495
1496#
1497# Userland interfaces
1498#
1499CONFIG_INPUT_MOUSEDEV=y
1500CONFIG_INPUT_MOUSEDEV_PSAUX=y
1501CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
1502CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
1503# CONFIG_INPUT_JOYDEV is not set
1504CONFIG_INPUT_EVDEV=y
1505# CONFIG_INPUT_EVBUG is not set
1506
1507#
1508# Input Device Drivers
1509#
1510CONFIG_INPUT_KEYBOARD=y
1511# CONFIG_KEYBOARD_ADP5588 is not set
1512# CONFIG_KEYBOARD_ATKBD is not set
1513CONFIG_KEYBOARD_QT1070=m
1514CONFIG_KEYBOARD_QT2160=m
1515# CONFIG_KEYBOARD_LKKBD is not set
1516CONFIG_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
1521CONFIG_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
1528CONFIG_INPUT_MOUSE=y
1529CONFIG_MOUSE_PS2=y
1530CONFIG_MOUSE_PS2_ALPS=y
1531CONFIG_MOUSE_PS2_LOGIPS2PP=y
1532CONFIG_MOUSE_PS2_SYNAPTICS=y
1533CONFIG_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
1546CONFIG_INPUT_MISC=y
1547CONFIG_INPUT_AD714X=m
1548CONFIG_INPUT_AD714X_I2C=m
1549CONFIG_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
1556CONFIG_INPUT_TWL4030_PWRBUTTON=y
1557CONFIG_INPUT_TWL4030_VIBRA=m
1558CONFIG_INPUT_UINPUT=y
1559CONFIG_INPUT_PCF8574=m
1560CONFIG_INPUT_PWM_BEEPER=m
1561# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
1562CONFIG_INPUT_ADXL34X=m
1563CONFIG_INPUT_ADXL34X_I2C=m
1564CONFIG_INPUT_ADXL34X_SPI=m
1565CONFIG_INPUT_CMA3000=m
1566CONFIG_INPUT_CMA3000_I2C=m
1567
1568#
1569# Hardware I/O ports
1570#
1571CONFIG_SERIO=y
1572CONFIG_SERIO_SERPORT=y
1573CONFIG_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#
1582CONFIG_VT=y
1583CONFIG_CONSOLE_TRANSLATIONS=y
1584CONFIG_VT_CONSOLE=y
1585CONFIG_HW_CONSOLE=y
1586CONFIG_VT_HW_CONSOLE_BINDING=y
1587CONFIG_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
1591CONFIG_N_GSM=m
1592CONFIG_DEVKMEM=y
1593
1594#
1595# Serial drivers
1596#
1597CONFIG_SERIAL_8250=y
1598CONFIG_SERIAL_8250_CONSOLE=y
1599CONFIG_SERIAL_8250_NR_UARTS=32
1600CONFIG_SERIAL_8250_RUNTIME_UARTS=4
1601CONFIG_SERIAL_8250_EXTENDED=y
1602CONFIG_SERIAL_8250_MANY_PORTS=y
1603CONFIG_SERIAL_8250_SHARE_IRQ=y
1604CONFIG_SERIAL_8250_DETECT_IRQ=y
1605CONFIG_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
1612CONFIG_SERIAL_CORE=y
1613CONFIG_SERIAL_CORE_CONSOLE=y
1614CONFIG_SERIAL_OMAP=y
1615CONFIG_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
1619CONFIG_SERIAL_IFX6X60=m
1620CONFIG_TTY_PRINTK=y
1621# CONFIG_HVC_DCC is not set
1622# CONFIG_IPMI_HANDLER is not set
1623CONFIG_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
1629CONFIG_I2C=y
1630CONFIG_I2C_BOARDINFO=y
1631CONFIG_I2C_COMPAT=y
1632CONFIG_I2C_CHARDEV=y
1633CONFIG_I2C_MUX=m
1634
1635#
1636# Multiplexer I2C Chip support
1637#
1638CONFIG_I2C_MUX_GPIO=m
1639# CONFIG_I2C_MUX_PCA9541 is not set
1640# CONFIG_I2C_MUX_PCA954x is not set
1641CONFIG_I2C_HELPER_AUTO=y
1642CONFIG_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
1654CONFIG_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#
1663CONFIG_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
1675CONFIG_SPI=y
1676# CONFIG_SPI_DEBUG is not set
1677CONFIG_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
1686CONFIG_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#
1694CONFIG_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#
1705CONFIG_ARCH_REQUIRE_GPIOLIB=y
1706CONFIG_GPIOLIB=y
1707# CONFIG_DEBUG_GPIO is not set
1708CONFIG_GPIO_SYSFS=y
1709CONFIG_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#
1720CONFIG_GPIO_MAX7300=m
1721# CONFIG_GPIO_MAX732X is not set
1722# CONFIG_GPIO_PCF857X is not set
1723# CONFIG_GPIO_SX150X is not set
1724CONFIG_GPIO_TWL4030=y
1725CONFIG_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
1747CONFIG_POWER_SUPPLY=m
1748# CONFIG_POWER_SUPPLY_DEBUG is not set
1749# CONFIG_PDA_POWER is not set
1750CONFIG_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
1755CONFIG_BATTERY_MAX17042=m
1756CONFIG_CHARGER_ISP1704=m
1757CONFIG_CHARGER_TWL4030=m
1758CONFIG_CHARGER_GPIO=m
1759CONFIG_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
1775CONFIG_SENSORS_ADT7411=m
1776# CONFIG_SENSORS_ADT7462 is not set
1777# CONFIG_SENSORS_ADT7470 is not set
1778# CONFIG_SENSORS_ADT7475 is not set
1779CONFIG_SENSORS_ASC7621=m
1780# CONFIG_SENSORS_ATXP1 is not set
1781CONFIG_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
1789CONFIG_SENSORS_GPIO_FAN=m
1790# CONFIG_SENSORS_IT87 is not set
1791CONFIG_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
1821CONFIG_SENSORS_SMM665=m
1822# CONFIG_SENSORS_DME1737 is not set
1823CONFIG_SENSORS_EMC1403=m
1824CONFIG_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
1831CONFIG_SENSORS_ADS7871=m
1832CONFIG_SENSORS_AMC6821=m
1833# CONFIG_SENSORS_THMC50 is not set
1834CONFIG_SENSORS_TMP102=m
1835# CONFIG_SENSORS_TMP401 is not set
1836# CONFIG_SENSORS_TMP421 is not set
1837CONFIG_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
1848CONFIG_THERMAL=y
1849CONFIG_THERMAL_HWMON=y
1850CONFIG_WATCHDOG=y
1851CONFIG_WATCHDOG_NOWAYOUT=y
1852
1853#
1854# Watchdog Device Drivers
1855#
1856# CONFIG_SOFT_WATCHDOG is not set
1857CONFIG_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
1865CONFIG_SSB_POSSIBLE=y
1866
1867#
1868# Sonics Silicon Backplane
1869#
1870CONFIG_SSB=y
1871CONFIG_SSB_BLOCKIO=y
1872CONFIG_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
1876CONFIG_MFD_SUPPORT=y
1877CONFIG_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
1884CONFIG_TPS6105X=m
1885# CONFIG_TPS65010 is not set
1886CONFIG_TPS6507X=m
1887CONFIG_TWL4030_CORE=y
1888CONFIG_TWL4030_MADC=m
1889CONFIG_TWL4030_POWER=y
1890CONFIG_TWL4030_SCRIPT=y
1891CONFIG_TWL4030_CODEC=y
1892CONFIG_TWL4030_POWEROFF=y
1893CONFIG_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
1914CONFIG_MFD_TPS6586X=y
1915CONFIG_MFD_WL1273_CORE=m
1916CONFIG_MFD_OMAP_USB_HOST=y
1917CONFIG_REGULATOR=y
1918# CONFIG_REGULATOR_DEBUG is not set
1919CONFIG_REGULATOR_DUMMY=y
1920CONFIG_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
1928CONFIG_REGULATOR_TWL4030=y
1929# CONFIG_REGULATOR_LP3971 is not set
1930# CONFIG_REGULATOR_LP3972 is not set
1931CONFIG_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
1936CONFIG_REGULATOR_TPS6586X=m
1937CONFIG_REGULATOR_TPS6524X=m
1938CONFIG_MEDIA_SUPPORT=y
1939
1940#
1941# Multimedia core support
1942#
1943CONFIG_MEDIA_CONTROLLER=y
1944CONFIG_VIDEO_DEV=y
1945CONFIG_VIDEO_V4L2_COMMON=y
1946CONFIG_VIDEO_V4L2_SUBDEV_API=y
1947CONFIG_DVB_CORE=m
1948CONFIG_VIDEO_MEDIA=m
1949
1950#
1951# Multimedia drivers
1952#
1953CONFIG_RC_CORE=m
1954CONFIG_LIRC=m
1955CONFIG_RC_MAP=m
1956CONFIG_IR_NEC_DECODER=m
1957CONFIG_IR_RC5_DECODER=m
1958CONFIG_IR_RC6_DECODER=m
1959CONFIG_IR_JVC_DECODER=m
1960CONFIG_IR_SONY_DECODER=m
1961CONFIG_IR_RC5_SZ_DECODER=m
1962CONFIG_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
1966CONFIG_RC_LOOPBACK=m
1967CONFIG_MEDIA_ATTACH=y
1968CONFIG_MEDIA_TUNER=m
1969CONFIG_MEDIA_TUNER_CUSTOMISE=y
1970
1971#
1972# Customize TV tuners
1973#
1974CONFIG_MEDIA_TUNER_SIMPLE=m
1975CONFIG_MEDIA_TUNER_TDA8290=m
1976CONFIG_MEDIA_TUNER_TDA827X=m
1977CONFIG_MEDIA_TUNER_TDA18271=m
1978CONFIG_MEDIA_TUNER_TDA9887=m
1979CONFIG_MEDIA_TUNER_TEA5761=m
1980CONFIG_MEDIA_TUNER_TEA5767=m
1981CONFIG_MEDIA_TUNER_MT20XX=m
1982CONFIG_MEDIA_TUNER_MT2060=m
1983CONFIG_MEDIA_TUNER_MT2266=m
1984CONFIG_MEDIA_TUNER_MT2131=m
1985CONFIG_MEDIA_TUNER_QT1010=m
1986CONFIG_MEDIA_TUNER_XC2028=m
1987CONFIG_MEDIA_TUNER_XC5000=m
1988CONFIG_MEDIA_TUNER_MXL5005S=m
1989CONFIG_MEDIA_TUNER_MXL5007T=m
1990CONFIG_MEDIA_TUNER_MC44S803=m
1991CONFIG_MEDIA_TUNER_MAX2165=m
1992CONFIG_MEDIA_TUNER_TDA18218=m
1993CONFIG_VIDEO_V4L2=y
1994CONFIG_VIDEOBUF_GEN=y
1995CONFIG_VIDEOBUF_VMALLOC=m
1996CONFIG_VIDEOBUF_DMA_CONTIG=y
1997CONFIG_VIDEOBUF_DVB=m
1998CONFIG_VIDEO_TVEEPROM=m
1999CONFIG_VIDEO_TUNER=m
2000CONFIG_V4L2_MEM2MEM_DEV=m
2001CONFIG_VIDEOBUF2_CORE=m
2002CONFIG_VIDEOBUF2_MEMOPS=m
2003CONFIG_VIDEOBUF2_VMALLOC=m
2004CONFIG_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
2008CONFIG_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
2022CONFIG_VIDEO_MSP3400=m
2023# CONFIG_VIDEO_CS5345 is not set
2024CONFIG_VIDEO_CS53L32A=m
2025# CONFIG_VIDEO_M52790 is not set
2026# CONFIG_VIDEO_TLV320AIC23B is not set
2027CONFIG_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#
2039CONFIG_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
2044CONFIG_VIDEO_OV7670=m
2045CONFIG_VIDEO_MT9P031=y
2046CONFIG_VIDEO_MT9V011=m
2047CONFIG_VIDEO_MT9V032=y
2048# CONFIG_VIDEO_TCM825X is not set
2049# CONFIG_VIDEO_SAA7110 is not set
2050CONFIG_VIDEO_SAA711X=m
2051# CONFIG_VIDEO_SAA717X is not set
2052# CONFIG_VIDEO_SAA7191 is not set
2053CONFIG_VIDEO_TVP514X=m
2054CONFIG_VIDEO_TVP5150=m
2055CONFIG_VIDEO_TVP7002=m
2056# CONFIG_VIDEO_VPX3220 is not set
2057
2058#
2059# Video and audio decoders
2060#
2061CONFIG_VIDEO_CX25840=m
2062
2063#
2064# MPEG video encoders
2065#
2066CONFIG_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
2084CONFIG_VIDEO_VIVI=m
2085CONFIG_VIDEO_VPSS_SYSTEM=m
2086CONFIG_VIDEO_VPFE_CAPTURE=y
2087CONFIG_VIDEO_DM6446_CCDC=m
2088CONFIG_VIDEO_OMAP2_VOUT=y
2089# CONFIG_VIDEO_CPIA2 is not set
2090CONFIG_VIDEO_TIMBERDALE=m
2091# CONFIG_VIDEO_AU0828 is not set
2092CONFIG_VIDEO_SR030PC30=m
2093CONFIG_VIDEO_NOON010PC30=m
2094CONFIG_VIDEO_OMAP3=y
2095CONFIG_VIDEO_OMAP3_DEBUG=y
2096# CONFIG_SOC_CAMERA is not set
2097CONFIG_V4L_USB_DRIVERS=y
2098CONFIG_USB_VIDEO_CLASS=m
2099CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
2100CONFIG_USB_GSPCA=m
2101CONFIG_USB_M5602=m
2102CONFIG_USB_STV06XX=m
2103# CONFIG_USB_GL860 is not set
2104CONFIG_USB_GSPCA_BENQ=m
2105CONFIG_USB_GSPCA_CONEX=m
2106CONFIG_USB_GSPCA_CPIA1=m
2107CONFIG_USB_GSPCA_ETOMS=m
2108CONFIG_USB_GSPCA_FINEPIX=m
2109# CONFIG_USB_GSPCA_JEILINJ is not set
2110CONFIG_USB_GSPCA_KONICA=m
2111CONFIG_USB_GSPCA_MARS=m
2112# CONFIG_USB_GSPCA_MR97310A is not set
2113CONFIG_USB_GSPCA_NW80X=m
2114CONFIG_USB_GSPCA_OV519=m
2115CONFIG_USB_GSPCA_OV534=m
2116CONFIG_USB_GSPCA_OV534_9=m
2117CONFIG_USB_GSPCA_PAC207=m
2118# CONFIG_USB_GSPCA_PAC7302 is not set
2119CONFIG_USB_GSPCA_PAC7311=m
2120CONFIG_USB_GSPCA_SN9C2028=m
2121# CONFIG_USB_GSPCA_SN9C20X is not set
2122CONFIG_USB_GSPCA_SONIXB=m
2123CONFIG_USB_GSPCA_SONIXJ=m
2124CONFIG_USB_GSPCA_SPCA500=m
2125CONFIG_USB_GSPCA_SPCA501=m
2126CONFIG_USB_GSPCA_SPCA505=m
2127CONFIG_USB_GSPCA_SPCA506=m
2128CONFIG_USB_GSPCA_SPCA508=m
2129CONFIG_USB_GSPCA_SPCA561=m
2130CONFIG_USB_GSPCA_SPCA1528=m
2131# CONFIG_USB_GSPCA_SQ905 is not set
2132# CONFIG_USB_GSPCA_SQ905C is not set
2133CONFIG_USB_GSPCA_SQ930X=m
2134CONFIG_USB_GSPCA_STK014=m
2135# CONFIG_USB_GSPCA_STV0680 is not set
2136CONFIG_USB_GSPCA_SUNPLUS=m
2137CONFIG_USB_GSPCA_T613=m
2138CONFIG_USB_GSPCA_TV8532=m
2139CONFIG_USB_GSPCA_VC032X=m
2140CONFIG_USB_GSPCA_VICAM=m
2141CONFIG_USB_GSPCA_XIRLINK_CIT=m
2142CONFIG_USB_GSPCA_ZC3XX=m
2143CONFIG_VIDEO_PVRUSB2=m
2144CONFIG_VIDEO_PVRUSB2_SYSFS=y
2145CONFIG_VIDEO_PVRUSB2_DVB=y
2146# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
2147CONFIG_VIDEO_HDPVR=m
2148CONFIG_VIDEO_EM28XX=m
2149CONFIG_VIDEO_EM28XX_ALSA=m
2150CONFIG_VIDEO_EM28XX_DVB=m
2151CONFIG_VIDEO_TLG2300=m
2152CONFIG_VIDEO_CX231XX=m
2153CONFIG_VIDEO_CX231XX_RC=y
2154# CONFIG_VIDEO_CX231XX_ALSA is not set
2155CONFIG_VIDEO_CX231XX_DVB=m
2156CONFIG_VIDEO_USBVISION=m
2157CONFIG_USB_ET61X251=m
2158CONFIG_USB_SN9C102=m
2159CONFIG_USB_PWC=m
2160# CONFIG_USB_PWC_DEBUG is not set
2161CONFIG_USB_PWC_INPUT_EVDEV=y
2162CONFIG_USB_ZR364XX=m
2163CONFIG_USB_STKWEBCAM=m
2164CONFIG_USB_S2255=m
2165CONFIG_V4L_MEM2MEM_DRIVERS=y
2166CONFIG_VIDEO_MEM2MEM_TESTDEV=m
2167CONFIG_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
2174CONFIG_RADIO_SAA7706H=m
2175# CONFIG_RADIO_TEF6862 is not set
2176CONFIG_RADIO_WL1273=m
2177
2178#
2179# Texas Instruments WL128x FM driver (ST based)
2180#
2181CONFIG_RADIO_WL128X=m
2182CONFIG_DVB_MAX_ADAPTERS=8
2183CONFIG_DVB_DYNAMIC_MINORS=y
2184CONFIG_DVB_CAPTURE_DRIVERS=y
2185# CONFIG_TTPCI_EEPROM is not set
2186
2187#
2188# Supported USB Adapters
2189#
2190CONFIG_DVB_USB=m
2191# CONFIG_DVB_USB_DEBUG is not set
2192CONFIG_DVB_USB_A800=m
2193CONFIG_DVB_USB_DIBUSB_MB=m
2194# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
2195CONFIG_DVB_USB_DIBUSB_MC=m
2196CONFIG_DVB_USB_DIB0700=m
2197CONFIG_DVB_USB_UMT_010=m
2198CONFIG_DVB_USB_CXUSB=m
2199CONFIG_DVB_USB_M920X=m
2200CONFIG_DVB_USB_GL861=m
2201CONFIG_DVB_USB_AU6610=m
2202CONFIG_DVB_USB_DIGITV=m
2203CONFIG_DVB_USB_VP7045=m
2204CONFIG_DVB_USB_VP702X=m
2205CONFIG_DVB_USB_GP8PSK=m
2206CONFIG_DVB_USB_NOVA_T_USB2=m
2207CONFIG_DVB_USB_TTUSB2=m
2208CONFIG_DVB_USB_DTT200U=m
2209CONFIG_DVB_USB_OPERA1=m
2210CONFIG_DVB_USB_AF9005=m
2211CONFIG_DVB_USB_AF9005_REMOTE=m
2212CONFIG_DVB_USB_DW2102=m
2213CONFIG_DVB_USB_CINERGY_T2=m
2214CONFIG_DVB_USB_ANYSEE=m
2215CONFIG_DVB_USB_DTV5100=m
2216CONFIG_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
2220CONFIG_DVB_USB_AZ6027=m
2221CONFIG_DVB_USB_LME2510=m
2222CONFIG_DVB_USB_TECHNISAT_USB2=m
2223# CONFIG_SMS_SIANO_MDTV is not set
2224
2225#
2226# Supported FlexCopII (B2C2) Adapters
2227#
2228CONFIG_DVB_B2C2_FLEXCOP=m
2229CONFIG_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#
2240CONFIG_DVB_STB0899=m
2241CONFIG_DVB_STB6100=m
2242CONFIG_DVB_STV090x=m
2243CONFIG_DVB_STV6110x=m
2244
2245#
2246# DVB-S (satellite) frontends
2247#
2248CONFIG_DVB_CX24123=m
2249CONFIG_DVB_MT312=m
2250CONFIG_DVB_ZL10039=m
2251CONFIG_DVB_S5H1420=m
2252CONFIG_DVB_STV0288=m
2253CONFIG_DVB_STB6000=m
2254CONFIG_DVB_STV0299=m
2255CONFIG_DVB_STV6110=m
2256CONFIG_DVB_STV0900=m
2257CONFIG_DVB_TDA10086=m
2258CONFIG_DVB_TUNER_ITD1000=m
2259CONFIG_DVB_TUNER_CX24113=m
2260CONFIG_DVB_TDA826X=m
2261CONFIG_DVB_CX24116=m
2262CONFIG_DVB_SI21XX=m
2263CONFIG_DVB_DS3000=m
2264
2265#
2266# DVB-T (terrestrial) frontends
2267#
2268CONFIG_DVB_CX22702=m
2269CONFIG_DVB_TDA1004X=m
2270CONFIG_DVB_NXT6000=m
2271CONFIG_DVB_MT352=m
2272CONFIG_DVB_ZL10353=m
2273CONFIG_DVB_DIB3000MB=m
2274CONFIG_DVB_DIB3000MC=m
2275CONFIG_DVB_DIB7000M=m
2276CONFIG_DVB_DIB7000P=m
2277CONFIG_DVB_TDA10048=m
2278CONFIG_DVB_AF9013=m
2279
2280#
2281# DVB-C (cable) frontends
2282#
2283CONFIG_DVB_TDA10023=m
2284CONFIG_DVB_STV0297=m
2285
2286#
2287# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
2288#
2289CONFIG_DVB_NXT200X=m
2290CONFIG_DVB_BCM3510=m
2291CONFIG_DVB_LGDT330X=m
2292CONFIG_DVB_LGDT3305=m
2293CONFIG_DVB_S5H1409=m
2294CONFIG_DVB_S5H1411=m
2295
2296#
2297# ISDB-T (terrestrial) frontends
2298#
2299CONFIG_DVB_S921=m
2300CONFIG_DVB_DIB8000=m
2301CONFIG_DVB_MB86A20S=m
2302
2303#
2304# Digital terrestrial only tuners/PLL
2305#
2306CONFIG_DVB_PLL=m
2307CONFIG_DVB_TUNER_DIB0070=m
2308CONFIG_DVB_TUNER_DIB0090=m
2309
2310#
2311# SEC control devices for DVB-S
2312#
2313CONFIG_DVB_LNBP21=m
2314CONFIG_DVB_ISL6421=m
2315CONFIG_DVB_LGS8GXX=m
2316CONFIG_DVB_ATBM8830=m
2317CONFIG_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#
2327CONFIG_DRM=m
2328# CONFIG_VGASTATE is not set
2329# CONFIG_VIDEO_OUTPUT_CONTROL is not set
2330CONFIG_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
2334CONFIG_FB_CFB_FILLRECT=y
2335CONFIG_FB_CFB_COPYAREA=y
2336CONFIG_FB_CFB_IMAGEBLIT=y
2337# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
2338CONFIG_FB_SYS_FILLRECT=m
2339CONFIG_FB_SYS_COPYAREA=m
2340CONFIG_FB_SYS_IMAGEBLIT=m
2341# CONFIG_FB_FOREIGN_ENDIAN is not set
2342CONFIG_FB_SYS_FOPS=m
2343# CONFIG_FB_WMT_GE_ROPS is not set
2344CONFIG_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
2348CONFIG_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
2356CONFIG_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
2362CONFIG_OMAP2_VRAM=y
2363CONFIG_OMAP2_VRFB=y
2364CONFIG_OMAP2_DSS=y
2365CONFIG_OMAP2_VRAM_SIZE=14
2366CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
2367# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set
2368CONFIG_OMAP2_DSS_DPI=y
2369# CONFIG_OMAP2_DSS_RFBI is not set
2370CONFIG_OMAP2_DSS_VENC=y
2371# CONFIG_OMAP2_DSS_SDI is not set
2372CONFIG_OMAP2_DSS_DSI=y
2373CONFIG_OMAP2_DSS_USE_DSI_PLL=y
2374# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
2375CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
2376CONFIG_FB_OMAP2=y
2377CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
2378CONFIG_FB_OMAP2_NUM_FBS=2
2379
2380#
2381# OMAP2/3 Display Device Drivers
2382#
2383CONFIG_PANEL_GENERIC_DPI=y
2384# CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set
2385CONFIG_PANEL_SHARP_LS037V7DW01=y
2386CONFIG_PANEL_NEC_NL8048HL11_01B=y
2387# CONFIG_PANEL_TAAL is not set
2388CONFIG_PANEL_TPO_TD043MTEA1=m
2389# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
2390CONFIG_BACKLIGHT_CLASS_DEVICE=y
2391
2392#
2393# Display device support
2394#
2395CONFIG_DISPLAY_SUPPORT=y
2396
2397#
2398# Display hardware drivers
2399#
2400
2401#
2402# Console display driver support
2403#
2404CONFIG_DUMMY_CONSOLE=y
2405CONFIG_FRAMEBUFFER_CONSOLE=y
2406# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
2407CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
2408# CONFIG_FONTS is not set
2409CONFIG_FONT_8x8=y
2410CONFIG_FONT_8x16=y
2411CONFIG_LOGO=y
2412# CONFIG_LOGO_LINUX_MONO is not set
2413# CONFIG_LOGO_LINUX_VGA16 is not set
2414CONFIG_LOGO_LINUX_CLUT224=y
2415CONFIG_SOUND=y
2416CONFIG_SOUND_OSS_CORE=y
2417CONFIG_SOUND_OSS_CORE_PRECLAIM=y
2418CONFIG_SND=y
2419CONFIG_SND_TIMER=y
2420CONFIG_SND_PCM=y
2421CONFIG_SND_HWDEP=y
2422CONFIG_SND_RAWMIDI=y
2423CONFIG_SND_JACK=y
2424CONFIG_SND_SEQUENCER=m
2425# CONFIG_SND_SEQ_DUMMY is not set
2426CONFIG_SND_OSSEMUL=y
2427CONFIG_SND_MIXER_OSS=y
2428CONFIG_SND_PCM_OSS=y
2429CONFIG_SND_PCM_OSS_PLUGINS=y
2430CONFIG_SND_SEQUENCER_OSS=y
2431CONFIG_SND_HRTIMER=m
2432CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
2433CONFIG_SND_DYNAMIC_MINORS=y
2434CONFIG_SND_SUPPORT_OLD_API=y
2435CONFIG_SND_VERBOSE_PROCFS=y
2436# CONFIG_SND_VERBOSE_PRINTK is not set
2437# CONFIG_SND_DEBUG is not set
2438CONFIG_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
2443CONFIG_SND_DRIVERS=y
2444# CONFIG_SND_DUMMY is not set
2445CONFIG_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
2451CONFIG_SND_SPI=y
2452CONFIG_SND_USB=y
2453CONFIG_SND_USB_AUDIO=y
2454CONFIG_SND_USB_UA101=m
2455CONFIG_SND_USB_CAIAQ=m
2456CONFIG_SND_USB_CAIAQ_INPUT=y
2457CONFIG_SND_USB_6FIRE=m
2458CONFIG_SND_SOC=y
2459CONFIG_SND_SOC_CACHE_LZO=y
2460CONFIG_SND_OMAP_SOC=y
2461CONFIG_SND_OMAP_SOC_MCBSP=y
2462CONFIG_SND_OMAP_SOC_OVERO=y
2463CONFIG_SND_OMAP_SOC_OMAP3EVM=y
2464CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y
2465CONFIG_SND_OMAP_SOC_ZOOM2=y
2466CONFIG_SND_SOC_I2C_AND_SPI=y
2467# CONFIG_SND_SOC_ALL_CODECS is not set
2468CONFIG_SND_SOC_TWL4030=y
2469# CONFIG_SOUND_PRIME is not set
2470CONFIG_HID_SUPPORT=y
2471CONFIG_HID=y
2472# CONFIG_HIDRAW is not set
2473
2474#
2475# USB Input Devices
2476#
2477CONFIG_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
2485CONFIG_HID_A4TECH=y
2486CONFIG_HID_ACRUX=m
2487# CONFIG_HID_ACRUX_FF is not set
2488CONFIG_HID_APPLE=y
2489CONFIG_HID_BELKIN=y
2490# CONFIG_HID_CANDO is not set
2491CONFIG_HID_CHERRY=y
2492CONFIG_HID_CHICONY=y
2493# CONFIG_HID_PRODIKEYS is not set
2494CONFIG_HID_CYPRESS=y
2495# CONFIG_HID_DRAGONRISE is not set
2496CONFIG_HID_EMS_FF=m
2497# CONFIG_HID_ELECOM is not set
2498CONFIG_HID_EZKEY=y
2499CONFIG_HID_KEYTOUCH=m
2500# CONFIG_HID_KYE is not set
2501CONFIG_HID_UCLOGIC=m
2502CONFIG_HID_WALTOP=m
2503CONFIG_HID_GYRATION=y
2504# CONFIG_HID_TWINHAN is not set
2505# CONFIG_HID_KENSINGTON is not set
2506CONFIG_HID_LCPOWER=m
2507CONFIG_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
2512CONFIG_HID_MAGICMOUSE=m
2513CONFIG_HID_MICROSOFT=y
2514# CONFIG_HID_MOSART is not set
2515CONFIG_HID_MONTEREY=y
2516CONFIG_HID_MULTITOUCH=m
2517CONFIG_HID_NTRIG=y
2518# CONFIG_HID_ORTEK is not set
2519CONFIG_HID_PANTHERLORD=y
2520# CONFIG_PANTHERLORD_FF is not set
2521CONFIG_HID_PETALYNX=y
2522CONFIG_HID_PICOLCD=m
2523CONFIG_HID_PICOLCD_FB=y
2524CONFIG_HID_PICOLCD_BACKLIGHT=y
2525CONFIG_HID_PICOLCD_LEDS=y
2526CONFIG_HID_QUANTA=m
2527CONFIG_HID_ROCCAT=m
2528CONFIG_HID_ROCCAT_COMMON=m
2529CONFIG_HID_ROCCAT_ARVO=m
2530CONFIG_HID_ROCCAT_KONE=m
2531CONFIG_HID_ROCCAT_KONEPLUS=m
2532CONFIG_HID_ROCCAT_KOVAPLUS=m
2533# CONFIG_HID_ROCCAT_PYRA is not set
2534CONFIG_HID_SAMSUNG=y
2535CONFIG_HID_SONY=y
2536CONFIG_HID_STANTUM=m
2537CONFIG_HID_SUNPLUS=y
2538# CONFIG_HID_GREENASIA is not set
2539# CONFIG_HID_SMARTJOYPLUS is not set
2540CONFIG_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
2545CONFIG_USB_SUPPORT=y
2546CONFIG_USB_ARCH_HAS_HCD=y
2547CONFIG_USB_ARCH_HAS_OHCI=y
2548CONFIG_USB_ARCH_HAS_EHCI=y
2549CONFIG_USB=y
2550# CONFIG_USB_DEBUG is not set
2551CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
2552
2553#
2554# Miscellaneous USB options
2555#
2556CONFIG_USB_DEVICEFS=y
2557CONFIG_USB_DEVICE_CLASS=y
2558# CONFIG_USB_DYNAMIC_MINORS is not set
2559CONFIG_USB_SUSPEND=y
2560CONFIG_USB_OTG=y
2561# CONFIG_USB_OTG_WHITELIST is not set
2562# CONFIG_USB_OTG_BLACKLIST_HUB is not set
2563CONFIG_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
2571CONFIG_USB_EHCI_HCD=y
2572# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
2573CONFIG_USB_EHCI_TT_NEWSCHED=y
2574CONFIG_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
2584CONFIG_USB_MUSB_HDRC=y
2585# CONFIG_USB_MUSB_TUSB6010 is not set
2586CONFIG_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
2590CONFIG_USB_MUSB_OTG=y
2591CONFIG_USB_GADGET_MUSB_HDRC=y
2592CONFIG_USB_MUSB_HDRC_HCD=y
2593# CONFIG_MUSB_PIO_ONLY is not set
2594CONFIG_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#
2601CONFIG_USB_ACM=m
2602CONFIG_USB_PRINTER=m
2603CONFIG_USB_WDM=m
2604CONFIG_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#
2613CONFIG_USB_STORAGE=y
2614# CONFIG_USB_STORAGE_DEBUG is not set
2615CONFIG_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
2627CONFIG_USB_STORAGE_ENE_UB6250=m
2628CONFIG_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#
2640CONFIG_USB_SERIAL=m
2641CONFIG_USB_EZUSB=y
2642CONFIG_USB_SERIAL_GENERIC=y
2643CONFIG_USB_SERIAL_AIRCABLE=m
2644CONFIG_USB_SERIAL_ARK3116=m
2645CONFIG_USB_SERIAL_BELKIN=m
2646CONFIG_USB_SERIAL_CH341=m
2647# CONFIG_USB_SERIAL_WHITEHEAT is not set
2648CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
2649# CONFIG_USB_SERIAL_CP210X is not set
2650CONFIG_USB_SERIAL_CYPRESS_M8=m
2651CONFIG_USB_SERIAL_EMPEG=m
2652CONFIG_USB_SERIAL_FTDI_SIO=m
2653CONFIG_USB_SERIAL_FUNSOFT=m
2654CONFIG_USB_SERIAL_VISOR=m
2655CONFIG_USB_SERIAL_IPAQ=m
2656CONFIG_USB_SERIAL_IR=m
2657CONFIG_USB_SERIAL_EDGEPORT=m
2658CONFIG_USB_SERIAL_EDGEPORT_TI=m
2659CONFIG_USB_SERIAL_GARMIN=m
2660CONFIG_USB_SERIAL_IPW=m
2661CONFIG_USB_SERIAL_IUU=m
2662CONFIG_USB_SERIAL_KEYSPAN_PDA=m
2663CONFIG_USB_SERIAL_KEYSPAN=m
2664CONFIG_USB_SERIAL_KEYSPAN_MPR=y
2665CONFIG_USB_SERIAL_KEYSPAN_USA28=y
2666CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
2667CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
2668CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
2669CONFIG_USB_SERIAL_KEYSPAN_USA19=y
2670CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
2671CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
2672CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
2673CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
2674CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
2675CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
2676CONFIG_USB_SERIAL_KLSI=m
2677CONFIG_USB_SERIAL_KOBIL_SCT=m
2678CONFIG_USB_SERIAL_MCT_U232=m
2679CONFIG_USB_SERIAL_MOS7720=m
2680CONFIG_USB_SERIAL_MOS7840=m
2681CONFIG_USB_SERIAL_MOTOROLA=m
2682CONFIG_USB_SERIAL_NAVMAN=m
2683CONFIG_USB_SERIAL_PL2303=m
2684CONFIG_USB_SERIAL_OTI6858=m
2685CONFIG_USB_SERIAL_QCAUX=m
2686# CONFIG_USB_SERIAL_QUALCOMM is not set
2687CONFIG_USB_SERIAL_SPCP8X5=m
2688CONFIG_USB_SERIAL_HP4X=m
2689CONFIG_USB_SERIAL_SAFE=m
2690# CONFIG_USB_SERIAL_SAFE_PADDED is not set
2691CONFIG_USB_SERIAL_SAMBA=m
2692CONFIG_USB_SERIAL_SIEMENS_MPI=m
2693CONFIG_USB_SERIAL_SIERRAWIRELESS=m
2694# CONFIG_USB_SERIAL_SYMBOL is not set
2695# CONFIG_USB_SERIAL_TI is not set
2696CONFIG_USB_SERIAL_CYBERJACK=m
2697# CONFIG_USB_SERIAL_XIRCOM is not set
2698# CONFIG_USB_SERIAL_OPTION is not set
2699CONFIG_USB_SERIAL_OMNINET=m
2700CONFIG_USB_SERIAL_OPTICON=m
2701CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
2702CONFIG_USB_SERIAL_ZIO=m
2703CONFIG_USB_SERIAL_SSU100=m
2704CONFIG_USB_SERIAL_DEBUG=m
2705
2706#
2707# USB Miscellaneous drivers
2708#
2709CONFIG_USB_EMI62=m
2710CONFIG_USB_EMI26=m
2711# CONFIG_USB_ADUTUX is not set
2712# CONFIG_USB_SEVSEG is not set
2713# CONFIG_USB_RIO500 is not set
2714CONFIG_USB_LEGOTOWER=m
2715CONFIG_USB_LCD=m
2716CONFIG_USB_LED=m
2717CONFIG_USB_CYPRESS_CY7C63=m
2718CONFIG_USB_CYTHERM=m
2719CONFIG_USB_IDMOUSE=m
2720CONFIG_USB_FTDI_ELAN=m
2721# CONFIG_USB_APPLEDISPLAY is not set
2722CONFIG_USB_SISUSBVGA=m
2723CONFIG_USB_SISUSBVGA_CON=y
2724CONFIG_USB_LD=m
2725CONFIG_USB_TRANCEVIBRATOR=m
2726# CONFIG_USB_IOWARRIOR is not set
2727CONFIG_USB_TEST=m
2728# CONFIG_USB_ISIGHTFW is not set
2729CONFIG_USB_YUREX=m
2730CONFIG_USB_ATM=m
2731CONFIG_USB_SPEEDTOUCH=m
2732CONFIG_USB_CXACRU=m
2733CONFIG_USB_UEAGLEATM=m
2734CONFIG_USB_XUSBATM=m
2735CONFIG_USB_GADGET=y
2736# CONFIG_USB_GADGET_DEBUG is not set
2737# CONFIG_USB_GADGET_DEBUG_FILES is not set
2738CONFIG_USB_GADGET_DEBUG_FS=y
2739CONFIG_USB_GADGET_VBUS_DRAW=480
2740CONFIG_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
2747CONFIG_USB_GADGET_DUALSPEED=y
2748# CONFIG_USB_ZERO is not set
2749# CONFIG_USB_AUDIO is not set
2750CONFIG_USB_ETH=m
2751CONFIG_USB_ETH_RNDIS=y
2752# CONFIG_USB_ETH_EEM is not set
2753CONFIG_USB_G_NCM=m
2754# CONFIG_USB_GADGETFS is not set
2755CONFIG_USB_FUNCTIONFS=m
2756# CONFIG_USB_FUNCTIONFS_ETH is not set
2757CONFIG_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
2766CONFIG_USB_G_HID=m
2767CONFIG_USB_G_DBGP=m
2768# CONFIG_USB_G_DBGP_PRINTK is not set
2769CONFIG_USB_G_DBGP_SERIAL=y
2770CONFIG_USB_G_WEBCAM=m
2771
2772#
2773# OTG and related infrastructure
2774#
2775CONFIG_USB_OTG_UTILS=y
2776CONFIG_USB_GPIO_VBUS=y
2777# CONFIG_ISP1301_OMAP is not set
2778# CONFIG_USB_ULPI is not set
2779CONFIG_TWL4030_USB=y
2780CONFIG_TWL6030_USB=m
2781CONFIG_NOP_USB_XCEIV=y
2782CONFIG_MMC=y
2783# CONFIG_MMC_DEBUG is not set
2784CONFIG_MMC_UNSAFE_RESUME=y
2785# CONFIG_MMC_CLKGATE is not set
2786
2787#
2788# MMC/SD/SDIO Card Drivers
2789#
2790CONFIG_MMC_BLOCK=y
2791CONFIG_MMC_BLOCK_MINORS=8
2792CONFIG_MMC_BLOCK_BOUNCE=y
2793CONFIG_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
2801CONFIG_MMC_OMAP_HS=y
2802CONFIG_MMC_SPI=m
2803# CONFIG_MMC_DW is not set
2804CONFIG_MMC_USHC=m
2805# CONFIG_MEMSTICK is not set
2806CONFIG_NEW_LEDS=y
2807CONFIG_LEDS_CLASS=y
2808
2809#
2810# LED drivers
2811#
2812# CONFIG_LEDS_LM3530 is not set
2813# CONFIG_LEDS_PCA9532 is not set
2814CONFIG_LEDS_GPIO=y
2815CONFIG_LEDS_GPIO_PLATFORM=y
2816# CONFIG_LEDS_LP3944 is not set
2817CONFIG_LEDS_LP5521=m
2818CONFIG_LEDS_LP5523=m
2819# CONFIG_LEDS_PCA955X is not set
2820# CONFIG_LEDS_DAC124S085 is not set
2821CONFIG_LEDS_PWM=m
2822CONFIG_LEDS_REGULATOR=m
2823# CONFIG_LEDS_BD2802 is not set
2824# CONFIG_LEDS_LT3593 is not set
2825CONFIG_LEDS_TRIGGERS=y
2826
2827#
2828# LED Triggers
2829#
2830CONFIG_LEDS_TRIGGER_TIMER=m
2831CONFIG_LEDS_TRIGGER_HEARTBEAT=y
2832CONFIG_LEDS_TRIGGER_BACKLIGHT=m
2833CONFIG_LEDS_TRIGGER_GPIO=m
2834CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
2835
2836#
2837# iptables trigger is under Netfilter config (LED target)
2838#
2839CONFIG_NFC_DEVICES=y
2840CONFIG_PN544_NFC=m
2841# CONFIG_ACCESSIBILITY is not set
2842CONFIG_RTC_LIB=y
2843CONFIG_RTC_CLASS=y
2844CONFIG_RTC_HCTOSYS=y
2845CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
2846# CONFIG_RTC_DEBUG is not set
2847
2848#
2849# RTC interfaces
2850#
2851CONFIG_RTC_INTF_SYSFS=y
2852CONFIG_RTC_INTF_PROC=y
2853CONFIG_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#
2860CONFIG_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
2872CONFIG_RTC_DRV_BQ32K=m
2873CONFIG_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
2912CONFIG_TIMB_DMA=m
2913CONFIG_DMA_ENGINE=y
2914# CONFIG_AUXDISPLAY is not set
2915CONFIG_UIO=m
2916CONFIG_UIO_PDRV=m
2917CONFIG_UIO_PDRV_GENIRQ=m
2918CONFIG_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
2922CONFIG_W35UND=m
2923CONFIG_PRISM2_USB=m
2924CONFIG_ECHO=m
2925CONFIG_BRCM80211=m
2926CONFIG_BRCMFMAC=y
2927# CONFIG_BRCMDBG is not set
2928CONFIG_RT2870=m
2929# CONFIG_COMEDI is not set
2930# CONFIG_ASUS_OLED is not set
2931CONFIG_R8712U=m
2932CONFIG_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
2940CONFIG_XVMALLOC=y
2941CONFIG_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
2948CONFIG_MACH_NO_WESTBRIDGE=y
2949# CONFIG_ATH6K_LEGACY is not set
2950CONFIG_USB_ENESTORAGE=m
2951CONFIG_BCM_WIMAX=m
2952CONFIG_FT1000=m
2953CONFIG_FT1000_USB=m
2954
2955#
2956# Speakup console speech
2957#
2958# CONFIG_SPEAKUP is not set
2959CONFIG_TOUCHSCREEN_CLEARPAD_TM1217=m
2960CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=m
2961
2962#
2963# Altera FPGA firmware download module
2964#
2965# CONFIG_ALTERA_STAPL is not set
2966CONFIG_CLKDEV_LOOKUP=y
2967
2968#
2969# File systems
2970#
2971CONFIG_EXT2_FS=y
2972CONFIG_EXT2_FS_XATTR=y
2973CONFIG_EXT2_FS_POSIX_ACL=y
2974CONFIG_EXT2_FS_SECURITY=y
2975# CONFIG_EXT2_FS_XIP is not set
2976CONFIG_EXT3_FS=y
2977# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
2978CONFIG_EXT3_FS_XATTR=y
2979CONFIG_EXT3_FS_POSIX_ACL=y
2980# CONFIG_EXT3_FS_SECURITY is not set
2981CONFIG_EXT4_FS=y
2982CONFIG_EXT4_FS_XATTR=y
2983CONFIG_EXT4_FS_POSIX_ACL=y
2984CONFIG_EXT4_FS_SECURITY=y
2985# CONFIG_EXT4_DEBUG is not set
2986CONFIG_JBD=y
2987# CONFIG_JBD_DEBUG is not set
2988CONFIG_JBD2=y
2989# CONFIG_JBD2_DEBUG is not set
2990CONFIG_FS_MBCACHE=y
2991CONFIG_REISERFS_FS=m
2992# CONFIG_REISERFS_CHECK is not set
2993CONFIG_REISERFS_PROC_INFO=y
2994CONFIG_REISERFS_FS_XATTR=y
2995# CONFIG_REISERFS_FS_POSIX_ACL is not set
2996# CONFIG_REISERFS_FS_SECURITY is not set
2997CONFIG_JFS_FS=m
2998CONFIG_JFS_POSIX_ACL=y
2999# CONFIG_JFS_SECURITY is not set
3000# CONFIG_JFS_DEBUG is not set
3001CONFIG_JFS_STATISTICS=y
3002CONFIG_XFS_FS=m
3003CONFIG_XFS_QUOTA=y
3004CONFIG_XFS_POSIX_ACL=y
3005CONFIG_XFS_RT=y
3006# CONFIG_XFS_DEBUG is not set
3007CONFIG_GFS2_FS=m
3008CONFIG_GFS2_FS_LOCKING_DLM=y
3009CONFIG_OCFS2_FS=m
3010CONFIG_OCFS2_FS_O2CB=m
3011CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
3012CONFIG_OCFS2_FS_STATS=y
3013CONFIG_OCFS2_DEBUG_MASKLOG=y
3014# CONFIG_OCFS2_DEBUG_FS is not set
3015CONFIG_BTRFS_FS=m
3016CONFIG_BTRFS_FS_POSIX_ACL=y
3017CONFIG_NILFS2_FS=m
3018CONFIG_FS_POSIX_ACL=y
3019CONFIG_EXPORTFS=y
3020CONFIG_FILE_LOCKING=y
3021CONFIG_FSNOTIFY=y
3022CONFIG_DNOTIFY=y
3023CONFIG_INOTIFY_USER=y
3024CONFIG_FANOTIFY=y
3025CONFIG_QUOTA=y
3026# CONFIG_QUOTA_NETLINK_INTERFACE is not set
3027CONFIG_PRINT_QUOTA_WARNING=y
3028# CONFIG_QUOTA_DEBUG is not set
3029CONFIG_QUOTA_TREE=y
3030# CONFIG_QFMT_V1 is not set
3031CONFIG_QFMT_V2=y
3032CONFIG_QUOTACTL=y
3033CONFIG_AUTOFS4_FS=y
3034CONFIG_FUSE_FS=m
3035CONFIG_CUSE=m
3036CONFIG_GENERIC_ACL=y
3037
3038#
3039# Caches
3040#
3041CONFIG_FSCACHE=m
3042CONFIG_FSCACHE_STATS=y
3043CONFIG_FSCACHE_HISTOGRAM=y
3044# CONFIG_FSCACHE_DEBUG is not set
3045# CONFIG_FSCACHE_OBJECT_LIST is not set
3046CONFIG_CACHEFILES=m
3047# CONFIG_CACHEFILES_DEBUG is not set
3048CONFIG_CACHEFILES_HISTOGRAM=y
3049
3050#
3051# CD-ROM/DVD Filesystems
3052#
3053CONFIG_ISO9660_FS=m
3054CONFIG_JOLIET=y
3055CONFIG_ZISOFS=y
3056CONFIG_UDF_FS=m
3057CONFIG_UDF_NLS=y
3058
3059#
3060# DOS/FAT/NT Filesystems
3061#
3062CONFIG_FAT_FS=y
3063CONFIG_MSDOS_FS=y
3064CONFIG_VFAT_FS=y
3065CONFIG_FAT_DEFAULT_CODEPAGE=437
3066CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
3067CONFIG_NTFS_FS=m
3068# CONFIG_NTFS_DEBUG is not set
3069# CONFIG_NTFS_RW is not set
3070
3071#
3072# Pseudo filesystems
3073#
3074CONFIG_PROC_FS=y
3075CONFIG_PROC_SYSCTL=y
3076CONFIG_PROC_PAGE_MONITOR=y
3077CONFIG_SYSFS=y
3078CONFIG_TMPFS=y
3079CONFIG_TMPFS_POSIX_ACL=y
3080# CONFIG_HUGETLB_PAGE is not set
3081CONFIG_CONFIGFS_FS=m
3082CONFIG_MISC_FILESYSTEMS=y
3083CONFIG_ADFS_FS=m
3084# CONFIG_ADFS_FS_RW is not set
3085CONFIG_AFFS_FS=m
3086# CONFIG_ECRYPT_FS is not set
3087CONFIG_UNION_FS=m
3088CONFIG_UNION_FS_XATTR=y
3089# CONFIG_UNION_FS_DEBUG is not set
3090CONFIG_HFS_FS=m
3091CONFIG_HFSPLUS_FS=m
3092CONFIG_BEFS_FS=m
3093# CONFIG_BEFS_DEBUG is not set
3094CONFIG_BFS_FS=m
3095CONFIG_EFS_FS=m
3096CONFIG_JFFS2_FS=y
3097CONFIG_JFFS2_FS_DEBUG=0
3098CONFIG_JFFS2_FS_WRITEBUFFER=y
3099# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
3100CONFIG_JFFS2_SUMMARY=y
3101CONFIG_JFFS2_FS_XATTR=y
3102CONFIG_JFFS2_FS_POSIX_ACL=y
3103CONFIG_JFFS2_FS_SECURITY=y
3104CONFIG_JFFS2_COMPRESSION_OPTIONS=y
3105CONFIG_JFFS2_ZLIB=y
3106CONFIG_JFFS2_LZO=y
3107CONFIG_JFFS2_RTIME=y
3108CONFIG_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
3112CONFIG_JFFS2_CMODE_FAVOURLZO=y
3113CONFIG_UBIFS_FS=y
3114CONFIG_UBIFS_FS_XATTR=y
3115CONFIG_UBIFS_FS_ADVANCED_COMPR=y
3116CONFIG_UBIFS_FS_LZO=y
3117CONFIG_UBIFS_FS_ZLIB=y
3118# CONFIG_UBIFS_FS_DEBUG is not set
3119CONFIG_LOGFS=m
3120CONFIG_CRAMFS=m
3121CONFIG_SQUASHFS=y
3122# CONFIG_SQUASHFS_XATTR is not set
3123CONFIG_SQUASHFS_LZO=y
3124CONFIG_SQUASHFS_XZ=y
3125# CONFIG_SQUASHFS_EMBEDDED is not set
3126CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
3127CONFIG_VXFS_FS=m
3128CONFIG_MINIX_FS=m
3129CONFIG_OMFS_FS=m
3130CONFIG_HPFS_FS=m
3131CONFIG_QNX4FS_FS=m
3132CONFIG_ROMFS_FS=m
3133CONFIG_ROMFS_BACKED_BY_BLOCK=y
3134# CONFIG_ROMFS_BACKED_BY_MTD is not set
3135# CONFIG_ROMFS_BACKED_BY_BOTH is not set
3136CONFIG_ROMFS_ON_BLOCK=y
3137CONFIG_PSTORE=y
3138CONFIG_SYSV_FS=m
3139CONFIG_UFS_FS=m
3140# CONFIG_UFS_FS_WRITE is not set
3141# CONFIG_UFS_DEBUG is not set
3142CONFIG_NETWORK_FILESYSTEMS=y
3143CONFIG_NFS_FS=y
3144CONFIG_NFS_V3=y
3145CONFIG_NFS_V3_ACL=y
3146CONFIG_NFS_V4=y
3147CONFIG_NFS_V4_1=y
3148CONFIG_PNFS_FILE_LAYOUT=y
3149CONFIG_ROOT_NFS=y
3150# CONFIG_NFS_USE_LEGACY_DNS is not set
3151CONFIG_NFS_USE_KERNEL_DNS=y
3152# CONFIG_NFS_USE_NEW_IDMAPPER is not set
3153CONFIG_NFSD=m
3154CONFIG_NFSD_DEPRECATED=y
3155CONFIG_NFSD_V2_ACL=y
3156CONFIG_NFSD_V3=y
3157CONFIG_NFSD_V3_ACL=y
3158CONFIG_NFSD_V4=y
3159CONFIG_LOCKD=y
3160CONFIG_LOCKD_V4=y
3161CONFIG_NFS_ACL_SUPPORT=y
3162CONFIG_NFS_COMMON=y
3163CONFIG_SUNRPC=y
3164CONFIG_SUNRPC_GSS=y
3165CONFIG_RPCSEC_GSS_KRB5=m
3166CONFIG_CEPH_FS=m
3167CONFIG_CIFS=m
3168CONFIG_CIFS_STATS=y
3169CONFIG_CIFS_STATS2=y
3170# CONFIG_CIFS_WEAK_PW_HASH is not set
3171# CONFIG_CIFS_UPCALL is not set
3172CONFIG_CIFS_XATTR=y
3173CONFIG_CIFS_POSIX=y
3174# CONFIG_CIFS_DEBUG2 is not set
3175CONFIG_CIFS_DFS_UPCALL=y
3176CONFIG_CIFS_FSCACHE=y
3177CONFIG_CIFS_ACL=y
3178CONFIG_CIFS_EXPERIMENTAL=y
3179CONFIG_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
3188CONFIG_CODA_FS=m
3189CONFIG_AFS_FS=m
3190# CONFIG_AFS_DEBUG is not set
3191# CONFIG_AFS_FSCACHE is not set
3192CONFIG_9P_FS=m
3193CONFIG_9P_FSCACHE=y
3194CONFIG_9P_FS_POSIX_ACL=y
3195
3196#
3197# Partition Types
3198#
3199CONFIG_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
3204CONFIG_MAC_PARTITION=y
3205CONFIG_MSDOS_PARTITION=y
3206CONFIG_BSD_DISKLABEL=y
3207CONFIG_MINIX_SUBPARTITION=y
3208CONFIG_SOLARIS_X86_PARTITION=y
3209# CONFIG_UNIXWARE_DISKLABEL is not set
3210CONFIG_LDM_PARTITION=y
3211CONFIG_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
3216CONFIG_EFI_PARTITION=y
3217# CONFIG_SYSV68_PARTITION is not set
3218CONFIG_NLS=y
3219CONFIG_NLS_DEFAULT="iso8859-1"
3220CONFIG_NLS_CODEPAGE_437=y
3221CONFIG_NLS_CODEPAGE_737=m
3222CONFIG_NLS_CODEPAGE_775=m
3223CONFIG_NLS_CODEPAGE_850=m
3224CONFIG_NLS_CODEPAGE_852=m
3225CONFIG_NLS_CODEPAGE_855=m
3226CONFIG_NLS_CODEPAGE_857=m
3227CONFIG_NLS_CODEPAGE_860=m
3228CONFIG_NLS_CODEPAGE_861=m
3229CONFIG_NLS_CODEPAGE_862=m
3230CONFIG_NLS_CODEPAGE_863=m
3231CONFIG_NLS_CODEPAGE_864=m
3232CONFIG_NLS_CODEPAGE_865=m
3233CONFIG_NLS_CODEPAGE_866=m
3234CONFIG_NLS_CODEPAGE_869=m
3235CONFIG_NLS_CODEPAGE_936=m
3236CONFIG_NLS_CODEPAGE_950=m
3237CONFIG_NLS_CODEPAGE_932=m
3238CONFIG_NLS_CODEPAGE_949=m
3239CONFIG_NLS_CODEPAGE_874=m
3240CONFIG_NLS_ISO8859_8=m
3241CONFIG_NLS_CODEPAGE_1250=m
3242CONFIG_NLS_CODEPAGE_1251=m
3243CONFIG_NLS_ASCII=m
3244CONFIG_NLS_ISO8859_1=y
3245CONFIG_NLS_ISO8859_2=m
3246CONFIG_NLS_ISO8859_3=m
3247CONFIG_NLS_ISO8859_4=m
3248CONFIG_NLS_ISO8859_5=m
3249CONFIG_NLS_ISO8859_6=m
3250CONFIG_NLS_ISO8859_7=m
3251CONFIG_NLS_ISO8859_9=m
3252CONFIG_NLS_ISO8859_13=m
3253CONFIG_NLS_ISO8859_14=m
3254CONFIG_NLS_ISO8859_15=m
3255CONFIG_NLS_KOI8_R=m
3256CONFIG_NLS_KOI8_U=m
3257CONFIG_NLS_UTF8=y
3258CONFIG_DLM=m
3259# CONFIG_DLM_DEBUG is not set
3260
3261#
3262# Kernel hacking
3263#
3264CONFIG_PRINTK_TIME=y
3265CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
3266CONFIG_ENABLE_WARN_DEPRECATED=y
3267CONFIG_ENABLE_MUST_CHECK=y
3268CONFIG_FRAME_WARN=1024
3269CONFIG_MAGIC_SYSRQ=y
3270# CONFIG_STRIP_ASM_SYMS is not set
3271# CONFIG_UNUSED_SYMBOLS is not set
3272CONFIG_DEBUG_FS=y
3273# CONFIG_HEADERS_CHECK is not set
3274# CONFIG_DEBUG_SECTION_MISMATCH is not set
3275CONFIG_DEBUG_KERNEL=y
3276# CONFIG_DEBUG_SHIRQ is not set
3277# CONFIG_LOCKUP_DETECTOR is not set
3278# CONFIG_HARDLOCKUP_DETECTOR is not set
3279CONFIG_DETECT_HUNG_TASK=y
3280# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
3281CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
3282CONFIG_SCHED_DEBUG=y
3283CONFIG_SCHEDSTATS=y
3284CONFIG_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
3291CONFIG_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
3319CONFIG_HAVE_FUNCTION_TRACER=y
3320CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
3321CONFIG_HAVE_DYNAMIC_FTRACE=y
3322CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
3323CONFIG_HAVE_C_RECORDMCOUNT=y
3324CONFIG_RING_BUFFER=y
3325CONFIG_RING_BUFFER_ALLOW_SWAP=y
3326CONFIG_TRACING_SUPPORT=y
3327CONFIG_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
3332CONFIG_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
3343CONFIG_HAVE_ARCH_KGDB=y
3344# CONFIG_KGDB is not set
3345# CONFIG_TEST_KSTRTOX is not set
3346# CONFIG_STRICT_DEVMEM is not set
3347CONFIG_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#
3356CONFIG_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
3361CONFIG_DEFAULT_SECURITY_DAC=y
3362CONFIG_DEFAULT_SECURITY=""
3363CONFIG_XOR_BLOCKS=m
3364CONFIG_ASYNC_CORE=m
3365CONFIG_ASYNC_MEMCPY=m
3366CONFIG_ASYNC_XOR=m
3367CONFIG_ASYNC_PQ=m
3368CONFIG_ASYNC_RAID6_RECOV=m
3369CONFIG_CRYPTO=y
3370
3371#
3372# Crypto core or helper
3373#
3374CONFIG_CRYPTO_ALGAPI=y
3375CONFIG_CRYPTO_ALGAPI2=y
3376CONFIG_CRYPTO_AEAD=m
3377CONFIG_CRYPTO_AEAD2=y
3378CONFIG_CRYPTO_BLKCIPHER=y
3379CONFIG_CRYPTO_BLKCIPHER2=y
3380CONFIG_CRYPTO_HASH=y
3381CONFIG_CRYPTO_HASH2=y
3382CONFIG_CRYPTO_RNG=m
3383CONFIG_CRYPTO_RNG2=y
3384CONFIG_CRYPTO_PCOMP2=y
3385CONFIG_CRYPTO_MANAGER=y
3386CONFIG_CRYPTO_MANAGER2=y
3387CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
3388CONFIG_CRYPTO_GF128MUL=m
3389CONFIG_CRYPTO_NULL=m
3390CONFIG_CRYPTO_WORKQUEUE=y
3391CONFIG_CRYPTO_CRYPTD=m
3392CONFIG_CRYPTO_AUTHENC=m
3393CONFIG_CRYPTO_TEST=m
3394
3395#
3396# Authenticated Encryption with Associated Data
3397#
3398CONFIG_CRYPTO_CCM=m
3399CONFIG_CRYPTO_GCM=m
3400CONFIG_CRYPTO_SEQIV=m
3401
3402#
3403# Block modes
3404#
3405CONFIG_CRYPTO_CBC=y
3406CONFIG_CRYPTO_CTR=m
3407CONFIG_CRYPTO_CTS=m
3408CONFIG_CRYPTO_ECB=y
3409CONFIG_CRYPTO_LRW=m
3410CONFIG_CRYPTO_PCBC=m
3411CONFIG_CRYPTO_XTS=m
3412
3413#
3414# Hash modes
3415#
3416CONFIG_CRYPTO_HMAC=m
3417CONFIG_CRYPTO_XCBC=m
3418# CONFIG_CRYPTO_VMAC is not set
3419
3420#
3421# Digest
3422#
3423CONFIG_CRYPTO_CRC32C=y
3424CONFIG_CRYPTO_GHASH=m
3425CONFIG_CRYPTO_MD4=m
3426CONFIG_CRYPTO_MD5=y
3427CONFIG_CRYPTO_MICHAEL_MIC=y
3428CONFIG_CRYPTO_RMD128=m
3429CONFIG_CRYPTO_RMD160=m
3430CONFIG_CRYPTO_RMD256=m
3431CONFIG_CRYPTO_RMD320=m
3432CONFIG_CRYPTO_SHA1=m
3433CONFIG_CRYPTO_SHA256=m
3434CONFIG_CRYPTO_SHA512=m
3435CONFIG_CRYPTO_TGR192=m
3436CONFIG_CRYPTO_WP512=m
3437
3438#
3439# Ciphers
3440#
3441CONFIG_CRYPTO_AES=y
3442CONFIG_CRYPTO_ANUBIS=m
3443CONFIG_CRYPTO_ARC4=y
3444CONFIG_CRYPTO_BLOWFISH=m
3445CONFIG_CRYPTO_CAMELLIA=m
3446CONFIG_CRYPTO_CAST5=m
3447CONFIG_CRYPTO_CAST6=m
3448CONFIG_CRYPTO_DES=y
3449CONFIG_CRYPTO_FCRYPT=m
3450CONFIG_CRYPTO_KHAZAD=m
3451CONFIG_CRYPTO_SALSA20=m
3452CONFIG_CRYPTO_SEED=m
3453CONFIG_CRYPTO_SERPENT=m
3454CONFIG_CRYPTO_TEA=m
3455CONFIG_CRYPTO_TWOFISH=m
3456CONFIG_CRYPTO_TWOFISH_COMMON=m
3457
3458#
3459# Compression
3460#
3461CONFIG_CRYPTO_DEFLATE=y
3462# CONFIG_CRYPTO_ZLIB is not set
3463CONFIG_CRYPTO_LZO=y
3464
3465#
3466# Random Number Generation
3467#
3468CONFIG_CRYPTO_ANSI_CPRNG=m
3469CONFIG_CRYPTO_USER_API=m
3470CONFIG_CRYPTO_USER_API_HASH=m
3471CONFIG_CRYPTO_USER_API_SKCIPHER=m
3472CONFIG_CRYPTO_HW=y
3473CONFIG_CRYPTO_DEV_OMAP_SHAM=m
3474CONFIG_CRYPTO_DEV_OMAP_AES=m
3475# CONFIG_BINARY_PRINTF is not set
3476
3477#
3478# Library routines
3479#
3480CONFIG_RAID6_PQ=m
3481CONFIG_BITREVERSE=y
3482CONFIG_GENERIC_FIND_LAST_BIT=y
3483CONFIG_CRC_CCITT=y
3484CONFIG_CRC16=y
3485CONFIG_CRC_T10DIF=y
3486CONFIG_CRC_ITU_T=y
3487CONFIG_CRC32=y
3488CONFIG_CRC7=y
3489CONFIG_LIBCRC32C=y
3490CONFIG_ZLIB_INFLATE=y
3491CONFIG_ZLIB_DEFLATE=y
3492CONFIG_LZO_COMPRESS=y
3493CONFIG_LZO_DECOMPRESS=y
3494CONFIG_XZ_DEC=y
3495CONFIG_XZ_DEC_X86=y
3496CONFIG_XZ_DEC_POWERPC=y
3497CONFIG_XZ_DEC_IA64=y
3498CONFIG_XZ_DEC_ARM=y
3499CONFIG_XZ_DEC_ARMTHUMB=y
3500CONFIG_XZ_DEC_SPARC=y
3501CONFIG_XZ_DEC_BCJ=y
3502CONFIG_XZ_DEC_TEST=m
3503CONFIG_DECOMPRESS_GZIP=y
3504CONFIG_DECOMPRESS_BZIP2=y
3505CONFIG_DECOMPRESS_LZMA=y
3506CONFIG_DECOMPRESS_XZ=y
3507CONFIG_DECOMPRESS_LZO=y
3508CONFIG_TEXTSEARCH=y
3509CONFIG_TEXTSEARCH_KMP=m
3510CONFIG_TEXTSEARCH_BM=m
3511CONFIG_TEXTSEARCH_FSM=m
3512CONFIG_BTREE=y
3513CONFIG_HAS_IOMEM=y
3514CONFIG_HAS_IOPORT=y
3515CONFIG_HAS_DMA=y
3516CONFIG_NLATTR=y
3517CONFIG_AVERAGE=y
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/camera/0001-Add-driver-for-Aptina-Micron-mt9p031-sensor.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/camera/0001-Add-driver-for-Aptina-Micron-mt9p031-sensor.patch
new file mode 100644
index 00000000..cf9e116d
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/camera/0001-Add-driver-for-Aptina-Micron-mt9p031-sensor.patch
@@ -0,0 +1,859 @@
1From e630a914bf14bf190feaf4a2cc57f6b27c4024e1 Mon Sep 17 00:00:00 2001
2From: Javier Martin <javier.martin@vista-silicon.com>
3Date: Wed, 1 Jun 2011 17:36:48 +0200
4Subject: [PATCH 1/3] Add driver for Aptina (Micron) mt9p031 sensor.
5
6Clock frequency of 57MHz used in previous version was wrong since
7when VDD_IO is 1.8V it can only support 48MHz.
8
9Two new platform flags have been added:
10
11- vdd_io: indicates whether the chip is powered with 1.8 or 2.8 VDD_IO.
12So that it can use the maximum allowed frequency.
13- version: monochrome and color versions of the chip have exactly
14the same ID, so the only way to select one of them is through
15platform data.
16
17Internal PLL is now used to generate PIXCLK depending on VDD_IO.
18
19Signed-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
29diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
30index 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
47diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
48index 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
59diff --git a/drivers/media/video/mt9p031.c b/drivers/media/video/mt9p031.c
60new file mode 100644
61index 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");
828diff --git a/include/media/mt9p031.h b/include/media/mt9p031.h
829new file mode 100644
830index 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--
8581.6.6.1
859
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/camera/0002-v4l-Add-mt9v032-sensor-driver.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/camera/0002-v4l-Add-mt9v032-sensor-driver.patch
new file mode 100644
index 00000000..fb7cd205
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/camera/0002-v4l-Add-mt9v032-sensor-driver.patch
@@ -0,0 +1,853 @@
1From ba65e798c98e9c4d331deb2b51337964336d3f78 Mon Sep 17 00:00:00 2001
2From: Detlev Casanova <detlev.casanova@gmail.com>
3Date: Sun, 28 Nov 2010 19:07:20 +0100
4Subject: [PATCH 2/3] v4l: Add mt9v032 sensor driver
5
6The MT9V032 is a parallel wide VGA sensor from Aptina (formerly Micron)
7controlled through I2C.
8
9The driver creates a V4L2 subdevice. It currently supports binning and
10cropping, and the gain, auto gain, exposure, auto exposure and test
11pattern controls.
12
13Signed-off-by: Detlev Casanova <detlev.casanova@gmail.com>
14Signed-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
24diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
25index 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
42diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
43index 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
54diff --git a/drivers/media/video/mt9v032.c b/drivers/media/video/mt9v032.c
55new file mode 100644
56index 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");
833diff --git a/include/media/mt9v032.h b/include/media/mt9v032.h
834new file mode 100644
835index 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--
8521.6.6.1
853
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/camera/0003-Add-support-for-mt9p031-LI-5M03-module-in-Beagleboar.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/camera/0003-Add-support-for-mt9p031-LI-5M03-module-in-Beagleboar.patch
new file mode 100644
index 00000000..a1807e73
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/camera/0003-Add-support-for-mt9p031-LI-5M03-module-in-Beagleboar.patch
@@ -0,0 +1,162 @@
1From f662a8a2b9794121568903f5cc969e50eb151892 Mon Sep 17 00:00:00 2001
2From: Javier Martin <javier.martin@vista-silicon.com>
3Date: Mon, 30 May 2011 10:37:17 +0200
4Subject: [PATCH 3/3] Add support for mt9p031 (LI-5M03 module) in Beagleboard xM.
5
6Since isp clocks have not been exposed yet, this patch
7includes a temporal solution for testing mt9p031 driver
8in Beagleboard xM.
9
10Signed-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
18diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
19index 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
30diff --git a/arch/arm/mach-omap2/board-omap3beagle-camera.c b/arch/arm/mach-omap2/board-omap3beagle-camera.c
31new file mode 100644
32index 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);
131diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
132index 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--
1611.6.6.1
162
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0001-mfd-Fix-omap-usbhs-crash-when-rmmoding-ehci-or-ohci.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0001-mfd-Fix-omap-usbhs-crash-when-rmmoding-ehci-or-ohci.patch
new file mode 100644
index 00000000..c9f1e6a9
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0001-mfd-Fix-omap-usbhs-crash-when-rmmoding-ehci-or-ohci.patch
@@ -0,0 +1,67 @@
1From 46be90d202c36db19e27c2991cbff401c6c3ee81 Mon Sep 17 00:00:00 2001
2From: Keshava Munegowda <Keshava_mgowda@ti.com>
3Date: Mon, 16 May 2011 14:24:58 +0530
4Subject: [PATCH 01/13] mfd: Fix omap usbhs crash when rmmoding ehci or ohci
5
6The disabling of clocks and freeing GPIO are changed
7to fix the occurrence of the crash of rmmod of ehci and ohci
8drivers. The GPIOs should be freed after the spin locks are
9unlocked.
10
11Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com>
12Acked-by: Felipe Balbi <balbi@ti.com>
13Cc: stable@kernel.org
14Signed-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
19diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
20index 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--
661.6.6.1
67
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0002-mfd-Fix-omap_usbhs_alloc_children-error-handling.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0002-mfd-Fix-omap_usbhs_alloc_children-error-handling.patch
new file mode 100644
index 00000000..380dd82a
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0002-mfd-Fix-omap_usbhs_alloc_children-error-handling.patch
@@ -0,0 +1,50 @@
1From 89a903aca8fda3dcf1a6f9a424247e772afdd44e Mon Sep 17 00:00:00 2001
2From: Axel Lin <axel.lin@gmail.com>
3Date: Sat, 14 May 2011 14:15:36 +0800
4Subject: [PATCH 02/13] mfd: Fix omap_usbhs_alloc_children error handling
5
61. Return proper error if omap_usbhs_alloc_child fails
72. 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
11Signed-off-by: Axel Lin <axel.lin@gmail.com>
12Signed-off-by: Axel Lin <axel.lin@gmail.com>
13Tested-by: Keshava Munegowda <keshava_mgowda@ti.com>
14Acked-by: Felipe Balbi <balbi@ti.com>
15Signed-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
20diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
21index 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--
491.6.6.1
50
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0003-mfd-Add-omap-usbhs-runtime-PM-support.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0003-mfd-Add-omap-usbhs-runtime-PM-support.patch
new file mode 100644
index 00000000..b47deb2c
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0003-mfd-Add-omap-usbhs-runtime-PM-support.patch
@@ -0,0 +1,245 @@
1From edc881f9c4897fab11542cd5c36a33b288f702be Mon Sep 17 00:00:00 2001
2From: Keshava Munegowda <Keshava_mgowda@ti.com>
3Date: Sun, 22 May 2011 22:51:26 +0200
4Subject: [PATCH 03/13] mfd: Add omap-usbhs runtime PM support
5
6The usbhs core driver does not enable/disable the interface and
7functional clocks; These clocks are handled by hwmod and runtime pm,
8hence insted of the clock enable/disable, the runtime pm APIS are
9used. however,the port clocks and tll clocks are handled
10by the usbhs core.
11
12Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com>
13Signed-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
18diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
19index 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--
2441.6.6.1
245
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0004-arm-omap-usb-ehci-and-ohci-hwmod-structures-for-omap.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0004-arm-omap-usb-ehci-and-ohci-hwmod-structures-for-omap.patch
new file mode 100644
index 00000000..3d4d8a2d
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0004-arm-omap-usb-ehci-and-ohci-hwmod-structures-for-omap.patch
@@ -0,0 +1,406 @@
1From 339b167f6f76707a2d6ae3a7c0b921b8278564af Mon Sep 17 00:00:00 2001
2From: Keshava Munegowda <Keshava_mgowda@ti.com>
3Date: Wed, 1 Jun 2011 11:02:49 -0700
4Subject: [PATCH 04/13] arm: omap: usb: ehci and ohci hwmod structures for omap3 and omap4
5
6Following 2 hwmod strcuture are added:
7UHH hwmod of usbhs with uhh base address and
8EHCI , OHCI irq and base addresses.
9TLL hwmod of usbhs with the TLL base address and irq.
10
11Signed-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
17diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
18index 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
226diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
227index 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--
4051.6.6.1
406
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0005-arm-omap-usb-register-hwmods-of-usbhs.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0005-arm-omap-usb-register-hwmods-of-usbhs.patch
new file mode 100644
index 00000000..8e9a4ba4
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0005-arm-omap-usb-register-hwmods-of-usbhs.patch
@@ -0,0 +1,160 @@
1From 70f5e1a0e6639710503a9ffb9008ddcd2bb3f06e Mon Sep 17 00:00:00 2001
2From: Keshava Munegowda <Keshava_mgowda@ti.com>
3Date: Wed, 1 Jun 2011 11:02:54 -0700
4Subject: [PATCH 05/13] arm: omap: usb: register hwmods of usbhs
5
6The hwmod structure of uhh and tll are retrived
7and registered with omap device
8
9Signed-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
14diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c
15index 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--
1591.6.6.1
160
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0006-arm-omap-usb-device-name-change-for-the-clk-names-of.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0006-arm-omap-usb-device-name-change-for-the-clk-names-of.patch
new file mode 100644
index 00000000..c0ac58bf
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0006-arm-omap-usb-device-name-change-for-the-clk-names-of.patch
@@ -0,0 +1,123 @@
1From 64bc651bb56435e4cd86d2ebfa4f301abdbac6e5 Mon Sep 17 00:00:00 2001
2From: Keshava Munegowda <Keshava_mgowda@ti.com>
3Date: Wed, 1 Jun 2011 11:02:58 -0700
4Subject: [PATCH 06/13] arm: omap: usb: device name change for the clk names of usbhs
5
6device name usbhs clocks are changed from
7usbhs-omap.0 to usbhs_omap; this is because
8in the hwmod registration the device name is set
9as usbhs_omap
10
11Signed-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
18diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
19index 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),
73diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
74index 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),
108diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
109index 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--
1221.6.6.1
123
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0007-mfd-global-Suspend-and-resume-support-of-ehci-and-oh.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0007-mfd-global-Suspend-and-resume-support-of-ehci-and-oh.patch
new file mode 100644
index 00000000..94d5f591
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0007-mfd-global-Suspend-and-resume-support-of-ehci-and-oh.patch
@@ -0,0 +1,165 @@
1From bf583f2924fd9b2f0356cbd0bbfd58c48d98ef15 Mon Sep 17 00:00:00 2001
2From: Keshava Munegowda <Keshava_mgowda@ti.com>
3Date: Wed, 1 Jun 2011 11:03:03 -0700
4Subject: [PATCH 07/13] mfd: global Suspend and resume support of ehci and ohci
5
6The global suspend and resume functions for usbhs core driver
7are implemented.These routine are called when the global suspend
8and resume occurs. Before calling these functions, the
9bus suspend and resume of ehci and ohci drivers are called
10from runtime pm.
11
12Signed-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
17diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
18index 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--
1641.6.6.1
165
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0008-MFD-TWL4030-Correct-the-warning-print-during-script-.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0008-MFD-TWL4030-Correct-the-warning-print-during-script-.patch
new file mode 100644
index 00000000..e3de4672
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0008-MFD-TWL4030-Correct-the-warning-print-during-script-.patch
@@ -0,0 +1,36 @@
1From 1f2e639755b920398d6592775e0e31f7fb1ca955 Mon Sep 17 00:00:00 2001
2From: Lesly A M <leslyam@ti.com>
3Date: Wed, 1 Jun 2011 14:56:38 -0700
4Subject: [PATCH 08/13] MFD: TWL4030: Correct the warning print during script loading
5
6Correcting the if condition check for printing the warning,
7if wakeup script is not updated before updating the sleep script.
8
9Since the flag 'order' is set to '1' while updating the wakeup script for P1P2,
10the 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
13Signed-off-by: Lesly A M <leslyam@ti.com>
14Cc: Nishanth Menon <nm@ti.com>
15Cc: David Derrick <dderrick@ti.com>
16Cc: Samuel Ortiz <sameo@linux.intel.com>
17---
18 drivers/mfd/twl4030-power.c | 2 +-
19 1 files changed, 1 insertions(+), 1 deletions(-)
20
21diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
22index 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--
351.6.6.1
36
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0009-MFD-TWL4030-Modifying-the-macro-name-Main_Ref-to-all.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0009-MFD-TWL4030-Modifying-the-macro-name-Main_Ref-to-all.patch
new file mode 100644
index 00000000..6be454aa
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0009-MFD-TWL4030-Modifying-the-macro-name-Main_Ref-to-all.patch
@@ -0,0 +1,61 @@
1From ea9acebfe2d3ca8fb3969eaf327665632142b85d Mon Sep 17 00:00:00 2001
2From: Lesly A M <leslyam@ti.com>
3Date: Wed, 1 Jun 2011 14:56:45 -0700
4Subject: [PATCH 09/13] MFD: TWL4030: Modifying the macro name Main_Ref to all caps
5
6Modifying the macro name Main_Ref to all caps(MAIN_REF).
7
8Suggested by Nishanth Menon <nm@ti.com>
9
10Signed-off-by: Lesly A M <leslyam@ti.com>
11Cc: Nishanth Menon <nm@ti.com>
12Cc: David Derrick <dderrick@ti.com>
13Cc: 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
20diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
21index 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},
33diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
34index 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)
46diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
47index 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--
601.6.6.1
61
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0010-MFD-TWL4030-power-scripts-for-OMAP3-boards.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0010-MFD-TWL4030-power-scripts-for-OMAP3-boards.patch
new file mode 100644
index 00000000..84e1ae7e
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0010-MFD-TWL4030-power-scripts-for-OMAP3-boards.patch
@@ -0,0 +1,705 @@
1From 0b29e1f61b85dd2d04f035088b70dc287d15b9f0 Mon Sep 17 00:00:00 2001
2From: Lesly A M <leslyam@ti.com>
3Date: Wed, 1 Jun 2011 14:56:49 -0700
4Subject: [PATCH 10/13] MFD: TWL4030: power scripts for OMAP3 boards
5
6Power bus message sequence for TWL4030 to enter sleep/wakeup/warm_reset.
7
8TWL4030 power scripts which can be used by different OMAP3 boards
9with the power companion chip (TWL4030 series).
10
11The twl4030 generic script can be used by any board file to update
12the power data in twl4030_platform_data.
13
14Since the TWL4030 power script has dependency with APIs in twl4030-power.c
15removing the __init for these APIs.
16
17For more information please see:
18 http://omapedia.org/wiki/TWL4030_power_scripts
19
20Signed-off-by: Lesly A M <leslyam@ti.com>
21Cc: Nishanth Menon <nm@ti.com>
22Cc: David Derrick <dderrick@ti.com>
23Cc: 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
35diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
36index 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
47diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
48index 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 }
80diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
81index 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
102diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
103index 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
114diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
115index 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);
242diff --git a/drivers/mfd/twl4030-script-omap.c b/drivers/mfd/twl4030-script-omap.c
243new file mode 100644
244index 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");
621diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
622index 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--
7041.6.6.1
705
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0011-MFD-TWL4030-TWL-version-checking.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0011-MFD-TWL4030-TWL-version-checking.patch
new file mode 100644
index 00000000..6de2193d
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0011-MFD-TWL4030-TWL-version-checking.patch
@@ -0,0 +1,164 @@
1From 3ceb224732230934aba7d082f3e2ca96c14a9ca0 Mon Sep 17 00:00:00 2001
2From: Lesly A M <leslyam@ti.com>
3Date: Wed, 1 Jun 2011 14:56:56 -0700
4Subject: [PATCH 11/13] MFD: TWL4030: TWL version checking
5
6Added API to get the TWL5030 Si version from the IDCODE register.
7It is used for enabling the workaround for TWL erratum 27.
8
9Signed-off-by: Lesly A M <leslyam@ti.com>
10Cc: Nishanth Menon <nm@ti.com>
11Cc: David Derrick <dderrick@ti.com>
12Cc: 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
18diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
19index 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);
112diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
113index 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--
1631.6.6.1
164
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0012-MFD-TWL4030-workaround-changes-for-Erratum-27.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0012-MFD-TWL4030-workaround-changes-for-Erratum-27.patch
new file mode 100644
index 00000000..6fe9dbfb
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0012-MFD-TWL4030-workaround-changes-for-Erratum-27.patch
@@ -0,0 +1,341 @@
1From 0bec9f7b20e7c61e0bab93195ec39cf94f1f8e25 Mon Sep 17 00:00:00 2001
2From: Lesly A M <leslyam@ti.com>
3Date: Wed, 1 Jun 2011 14:57:01 -0700
4Subject: [PATCH 12/13] MFD: TWL4030: workaround changes for Erratum 27
5
6Workaround 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
11Erratum 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
21Erratum 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
36The workaround changes are called from twl4030_power_init(), since we have to
37make some i2c_read calls to check the TWL4030 version & the i2c will not be
38initialized in the early stage.
39
40This workaround is required for TWL5030 Silicon version less than ES1.2
41The power script & setup time changes are recommended by TI HW team.
42
43For more information please see:
44 http://omapedia.org/wiki/TWL4030_power_scripts
45
46Changes taken from TWL4030 Erratum 27 workaround patch by Nishanth Menon.
47
48Signed-off-by: Lesly A M <leslyam@ti.com>
49Cc: Nishanth Menon <nm@ti.com>
50Cc: David Derrick <dderrick@ti.com>
51Cc: 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
58diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
59index 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)
162diff --git a/drivers/mfd/twl4030-script-omap.c b/drivers/mfd/twl4030-script-omap.c
163index 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)
327diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
328index 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--
3401.6.6.1
341
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0013-MFD-TWL4030-optimizing-resource-configuration.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0013-MFD-TWL4030-optimizing-resource-configuration.patch
new file mode 100644
index 00000000..8904f8de
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/mfd/0013-MFD-TWL4030-optimizing-resource-configuration.patch
@@ -0,0 +1,184 @@
1From bf171753a162d07753208c6bcfae8ca1e5c94af3 Mon Sep 17 00:00:00 2001
2From: Lesly A M <leslyam@ti.com>
3Date: Wed, 1 Jun 2011 14:57:05 -0700
4Subject: [PATCH 13/13] MFD: TWL4030: optimizing resource configuration
5
6Skip the i2c register writes in twl4030_configure_resource() if the new value
7is same as the old value, for devgrp/type/remap regs.
8
9Suggested by David Derrick <dderrick@ti.com>
10
11Signed-off-by: Lesly A M <leslyam@ti.com>
12Cc: Nishanth Menon <nm@ti.com>
13Cc: David Derrick <dderrick@ti.com>
14Cc: Samuel Ortiz <sameo@linux.intel.com>
15---
16 drivers/mfd/twl4030-power.c | 126 ++++++++++++++++++++++++------------------
17 1 files changed, 72 insertions(+), 54 deletions(-)
18
19diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
20index 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--
1831.6.6.1
184
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/musb/0001-usb-musb-Enable-DMA-mode1-RX-for-USB-Mass-Storage.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/musb/0001-usb-musb-Enable-DMA-mode1-RX-for-USB-Mass-Storage.patch
new file mode 100644
index 00000000..a98a4da9
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/musb/0001-usb-musb-Enable-DMA-mode1-RX-for-USB-Mass-Storage.patch
@@ -0,0 +1,121 @@
1From 2adb339e4988632379971febe5696f21d05c71f2 Mon Sep 17 00:00:00 2001
2From: Anand Gadiyar <gadiyar@ti.com>
3Date: Tue, 19 Jul 2011 01:52:14 -0700
4Subject: [PATCH] usb: musb: Enable DMA mode1 RX for USB-Mass-Storage
5
6This patch enables the DMA mode1 RX support.
7This feature is enabled based on the short_not_ok flag passed from
8gadget drivers.
9
10This will result in a thruput performance gain of around
1140% for USB mass-storage/mtp use cases.
12
13Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
14Signed-off-by: Moiz Sonasath <m-sonasath@ti.com>
15Tested-by: Vikram Pandita <vikram.pandita@ti.com>
16Signed-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
21diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
22index 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--
1201.6.6.1
121
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/net/0001-NFS-Revert-NFSROOT-default-mount-options.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/net/0001-NFS-Revert-NFSROOT-default-mount-options.patch
new file mode 100644
index 00000000..617698da
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/net/0001-NFS-Revert-NFSROOT-default-mount-options.patch
@@ -0,0 +1,13 @@
1diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
2index 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/extras/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/extras/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
new file mode 100644
index 00000000..9e9a8a0b
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,38 @@
1From 38dd5aadc86725f6018d23679e9daa60ca0a8319 Mon Sep 17 00:00:00 2001
2From: Nishanth Menon <nm@ti.com>
3Date: Thu, 12 May 2011 07:59:52 -0500
4Subject: [PATCH 1/6] OMAP2+: cpufreq: free up table on exit
5
6freq_table allocated by opp_init_cpufreq_table in omap_cpu_init
7needs to be freed in omap_cpu_exit.
8
9Signed-off-by: Nishanth Menon <nm@ti.com>
10Signed-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
15diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
16index 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--
371.6.6.1
38
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..087724d1
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,44 @@
1From 5febdc0482e545c2a598f035c5e03931e0c3c808 Mon Sep 17 00:00:00 2001
2From: Nishanth Menon <nm@ti.com>
3Date: Thu, 12 May 2011 08:14:41 -0500
4Subject: [PATCH 2/6] OMAP2+: cpufreq: handle invalid cpufreq table
5
6Handle the case when cpufreq_frequency_table_cpuinfo fails. freq_table
7that we passed failed the internal test of cpufreq generic driver,
8so we should'nt be using the freq_table as such. Instead, warn and
9fallback to clock functions for validation and operation.
10
11Signed-off-by: Nishanth Menon <nm@ti.com>
12Signed-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
17diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
18index 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--
431.6.6.1
44
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..4f4cdb14
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,33 @@
1From aef7e862873e6125159a18d22a2e37b1fbab2153 Mon Sep 17 00:00:00 2001
2From: Nishanth Menon <nm@ti.com>
3Date: Thu, 12 May 2011 16:27:45 -0700
4Subject: [PATCH 3/6] OMAP2+: cpufreq: minor comment cleanup
5
6this should probably get squashed in..
7
8Signed-off-by: Nishanth Menon <nm@ti.com>
9Signed-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
14diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
15index 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--
321.6.6.1
33
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..dd23c082
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,48 @@
1From f231980dbd0f05229f2020e59b7242872576416f Mon Sep 17 00:00:00 2001
2From: Nishanth Menon <nm@ti.com>
3Date: Fri, 13 May 2011 05:34:35 -0700
4Subject: [PATCH 4/6] OMAP2: cpufreq: use clk_init_cpufreq_table if OPPs not available
5
6OMAP2 does not use OPP tables at the moment for DVFS. Currently,
7we depend on opp table initialization to give us the freq_table,
8which makes sense for OMAP3+. for OMAP2, we should be using
9clk_init_cpufreq_table - so if the opp based frequency table
10initilization fails, fall back to clk_init_cpufreq_table to give
11us the table.
12
13Signed-off-by: Nishanth Menon <nm@ti.com>
14Signed-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
19diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
20index 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--
471.6.6.1
48
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..504d1916
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,78 @@
1From 272d76bcb22b9509ccc1b59d3a62e3930d902d17 Mon Sep 17 00:00:00 2001
2From: Nishanth Menon <nm@ti.com>
3Date: Fri, 13 May 2011 05:43:49 -0700
4Subject: [PATCH 5/6] OMAP2+: cpufreq: use cpufreq_frequency_table_target
5
6Use cpufreq_frequency_table_target for finding the proper target
7instead of seeing if the frequency requested is divisible alone.
8if we have a frequency table, we should restrict ourselves to
9selecting the "approved" frequencies alone and only in the case
10where the frequency table is not available should we attempt at
11closest roundable clock frequency.
12
13Signed-off-by: Nishanth Menon <nm@ti.com>
14Signed-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
19diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
20index 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--
771.6.6.1
78
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..0cb4c91f
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,100 @@
1From 42a384af80e07534913d9002ec8d9caf5d4d305c Mon Sep 17 00:00:00 2001
2From: Nishanth Menon <nm@ti.com>
3Date: Wed, 18 May 2011 01:48:23 -0500
4Subject: [PATCH 6/6] OMAP2+: cpufreq: fix freq_table leak
5
6Since we have two cpus the cpuinit call for cpu1 causes
7freq_table of cpu0 to be overwritten. instead, we maintain
8a counter to keep track of cpus who use the cpufreq table
9allocate it once(one freq table for all CPUs) and free them
10once the last user is done with it.
11
12Signed-off-by: Nishanth Menon <nm@ti.com>
13Signed-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
18diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
19index 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--
991.6.6.1
100
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..576cd08f
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,134 @@
1From 8726f3a7218b72a1003904a24bb000b3e4f9b4d1 Mon Sep 17 00:00:00 2001
2From: Mike Turquette <mturquette@ti.com>
3Date: Tue, 17 May 2011 09:35:54 -0500
4Subject: [PATCH 1/2] cpufreq: helpers for walking the frequency table
5
6Two new functions for getting the next higher and next lower frequencies
7in the cpufreq table, based upon a frequency supplied in kHz.
8
9This is useful for cpufreq governors that do not target frequencies
10based upon a percentage or a pre-determined value, but instead access
11the cpufreq table directly.
12
13Signed-off-by: Mike Turquette <mturquette@ti.com>
14Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
15Signed-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
21diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
22index 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
112diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
113index 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--
1331.6.6.1
134
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..731906cc
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,879 @@
1From e4c777d8314d7925e4895f00b3a7ebd64a4d830b Mon Sep 17 00:00:00 2001
2From: Mike Turquette <mturquette@ti.com>
3Date: Tue, 17 May 2011 09:43:09 -0500
4Subject: [PATCH 2/2] cpufreq: introduce hotplug governor
5
6The "hotplug" governor scales CPU frequency based on load, similar to
7"ondemand". It scales up to the highest frequency when "up_threshold"
8is crossed and scales down one frequency at a time when "down_threshold"
9is crossed. Unlike those governors, target frequencies are determined
10by directly accessing the CPUfreq frequency table, instead of taking
11some percentage of maximum available frequency.
12
13The key difference in the "hotplug" governor is that it will disable
14auxillary CPUs when the system is very idle, and enable them again once
15the system becomes busy. This is achieved by averaging load over
16multiple sampling periods; if CPUs were online or offlined based on a
17single sampling period then thrashing will occur.
18
19Sysfs entries exist for "hotplug_in_sampling_periods" and for
20"hotplug_out_sampling_periods" which determine how many consecutive
21periods get averaged to determine if auxillery CPUs should be onlined or
22offlined. Defaults are 5 periods and 20 periods respectively.
23Otherwise the standard sysfs entries you might find for "ondemand" and
24"conservative" governors are there.
25
26To use this governor it is assumed that your CPUfreq driver has
27populated the CPUfreq table, CONFIG_NO_HZ is enabled and
28CONFIG_HOTPLUG_CPU is enabled.
29
30Changes 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
40Signed-off-by: Mike Turquette <mturquette@ti.com>
41Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
42Signed-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
52diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
53index 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
91diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
92index 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
140diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
141index 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
152diff --git a/drivers/cpufreq/cpufreq_hotplug.c b/drivers/cpufreq/cpufreq_hotplug.c
153new file mode 100644
154index 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);
863diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
864index 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--
8781.6.6.1
879
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..d150dfc6
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,27 @@
1From 33668b07abd5e66a263cc8b4b88587646f38bed0 Mon Sep 17 00:00:00 2001
2From: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
3Date: Wed, 11 Aug 2010 17:02:43 -0700
4Subject: [PATCH 1/8] OMAP: CPUfreq: ensure driver initializes after cpufreq framework and governors
5
6Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
7Signed-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
12diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
13index 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--
261.6.6.1
27
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..d62e04d1
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,31 @@
1From e89b1544450fb8410a44004e48d6b330bc39f0ce Mon Sep 17 00:00:00 2001
2From: Kevin Hilman <khilman@deeprootsystems.com>
3Date: Wed, 11 Aug 2010 17:05:38 -0700
4Subject: [PATCH 2/8] OMAP: CPUfreq: ensure policy is fully initialized
5
6Ensure policy min/max/cur values are initialized when OMAP
7CPUfreq driver starts.
8
9Signed-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
14diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
15index 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--
301.6.6.1
31
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..fbe16213
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,263 @@
1From 948b868e4a83b054e8a58362238bc6cd61c0aeab Mon Sep 17 00:00:00 2001
2From: Rajendra Nayak <rnayak@ti.com>
3Date: Mon, 10 Nov 2008 17:00:25 +0530
4Subject: [PATCH 3/8] OMAP3 PM: CPUFreq driver for OMAP3
5
6CPUFreq driver for OMAP3
7
8With 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
12Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
13Signed-off-by: Rajendra Nayak <rnayak@ti.com>
14
15OMAP3: PM: CPUFreq: Fix omap_getspeed.
16
17Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
18
19Make sure omap cpufreq driver initializes after cpufreq framework and governors
20
21Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
22
23merge: CPUFreq: remove obsolete funcs
24
25OMAP3 clock: Update cpufreq driver
26
27This patch removes all refrences to virtual clock
28nodes in CPUFreq driver.
29
30Signed-off-by: Rajendra Nayak <rnayak@ti.com>
31Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
32Signed-off-by: Jean Pihet <jpihet@mvista.com>
33
34PM: Prevent direct cpufreq scaling during initialization
35
36It is seen that the OMAP specific cpufreq initialization code tries to
37scale the MPU frequency to the highest possible without taking care of
38the voltage level. On power on reset the power IC does not provide the
39necessary voltage for the highest available MPU frequency (that would
40satisfy all Si families). This potentially is an window of opportunity
41for things to go wrong.
42
43Signed-off-by: Romit Dasgupta <romit@ti.com>
44Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
45
46OMAP3: PM: enable 600MHz (overdrive) OPP
47
48Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
49
50omap3: introduce cpufreq
51
52OMAP OPP layer functions now have dependencies of CONFIG_CPU_FREQ only.
53
54With this patch, omap opp layer now has its compilation flags
55bound to CONFIG_CPU_FREQ. Also its code has been removed from pm34xx.c.
56
57A new file has been created to contain cpu freq code related to
58OMAP3: cpufreq34xx.c
59
60OMAP34xx and OMAP36xx family OPPs are made available
61
62Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
63Signed-off-by: Paul Walmsley <paul@pwsan.com>
64Signed-off-by: Nishanth Menon <nm@ti.com>
65Signed-off-by: Vishwanath BS <vishwanath.bs@ti.com>
66Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
67Signed-off-by: Romit Dasgupta <romit@ti.com>
68Signed-off-by: Rajendra Nayak <rnayak@ti.com>
69
70omap3: cpufreq: allow default opp table init
71
72For board files which choose to override the defaults, the existing
73mechanism will work, for boards that would like to work with defaults,
74allow init_common_hw to call init_opp_table to initialize if not
75already initialized. this will allow all omap boards which have opp
76tables predefined for a silicon to use the same.
77
78Originally reported for overo:
79http://marc.info/?t=127265269400004&r=1&w=2
80
81Signed-off-by: Nishanth Menon <nm@ti.com>
82Reported-by: Peter Tseng <tsenpet09@gmail.com>
83Cc: Cliff Brake <cliff.brake@gmail.com>
84Cc: Kevin Hilman <khilman@deeprootsystems.com>
85
86OMAP2: update OPP data to be device based
87
88Cc: Nishanth Menon <nm@ti.com>
89Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
90
91OMAP3: CPUfreq: update to device-based OPP API
92
93Update usage of OPP API to use new device-based API. This requires
94getting the 'struct device' for the MPU and using that with the OPP
95API.
96
97Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
98
99omap3: opp: make independent of cpufreq
100
101Make opp3xx data which is registered with the opp layer
102dependent purely on CONFIG_PM as opp layer and pm.c users
103are CONFIG_PM dependent not cpufreq dependent.
104so we rename the data definition to opp3xxx_data.c (inline with what
105we have for omap2), also move the build definition to be under
106the existing CONFIG_PM build instead of CPUFREQ.
107
108Cc: Eduardo Valentin <eduardo.valentin@nokia.com>
109Cc: Kevin Hilman <khilman@deeprootsystems.com>
110Cc: Paul Walmsley <paul@pwsan.com>
111Cc: Rajendra Nayak <rnayak@ti.com>
112Cc: Sanjeev Premi <premi@ti.com>
113Cc: Thara Gopinath <thara@ti.com>
114Cc: Tony Lindgren <tony@atomide.com>
115
116Signed-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
123diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
124index 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;
155diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
156index 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
168diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
169index 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--
2621.6.6.1
263
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..36742e43
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,32 @@
1From 86227f1eb341e571163464cb0a412ed2179f2541 Mon Sep 17 00:00:00 2001
2From: Silesh C V <silesh@ti.com>
3Date: Wed, 29 Sep 2010 14:52:54 +0530
4Subject: [PATCH 4/8] OMAP: PM: CPUFREQ: Fix conditional compilation
5
6Fix conditional compilation. A conditional expresiion
7should follow "#elif", in this case #elif clause should
8check whether CONFIG_ARCH_OMAP3 is defined or not
9(ie. defined(CONFIG_ARCH_OMAP3)) rather than checking for
10the value of the macro.
11
12Signed-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
17diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
18index 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--
311.6.6.1
32
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..7cf69325
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,33 @@
1From 4764137dd613362656726a15cb8184724aeb99bb Mon Sep 17 00:00:00 2001
2From: Kevin Hilman <khilman@deeprootsystems.com>
3Date: Tue, 16 Nov 2010 11:48:41 -0800
4Subject: [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
10diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
11index 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--
321.6.6.1
33
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..cfc257e0
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,669 @@
1From e16548716c5cbc3c9885d05f1654d83d5411a3a7 Mon Sep 17 00:00:00 2001
2From: Santosh Shilimkar <santosh.shilimkar@ti.com>
3Date: Mon, 14 Mar 2011 17:08:48 +0530
4Subject: [PATCH 6/8] OMAP: cpufreq: Split OMAP1 and OMAP2PLUS CPUfreq drivers.
5
6This patch is an attempt to cleanup the #ifdeferry in the
7omap CPUfreq drivers.
8
9The split betwenn OMAP1 and OMAP2PLUS is logical because
10 - OMAP1 doesn't support opp layer.
11 - OMAP1 build is seperate from omap2plus.
12
13Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
14Cc: Kevin Hilman <khilman@ti.com>
15Cc: 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
28diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
29index 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
42diff --git a/arch/arm/mach-omap1/omap1-cpufreq.c b/arch/arm/mach-omap1/omap1-cpufreq.c
43new file mode 100644
44index 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);
224diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
225index 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
238diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
239new file mode 100644
240index 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);
445diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
446index 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
457diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
458deleted file mode 100644
459index 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--
6681.6.6.1
669
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..6624d1ec
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,170 @@
1From f375d3c39d2835929d34c2a046b8c43cea6d1467 Mon Sep 17 00:00:00 2001
2From: Santosh Shilimkar <santosh.shilimkar@ti.com>
3Date: Mon, 14 Mar 2011 17:08:49 +0530
4Subject: [PATCH 7/8] OMAP2PLUS: cpufreq: Add SMP support to cater OMAP4430
5
6On OMAP SMP configuartion, both processors share the voltage
7and clock. So both CPUs needs to be scaled together and hence
8needs software co-ordination.
9
10Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
11Cc: Kevin Hilman <khilman@ti.com>
12cc: 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
17diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
18index 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--
1691.6.6.1
170
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..3797443c
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,29 @@
1From 6e101764a47cb6975a555e2237843ad391a542a4 Mon Sep 17 00:00:00 2001
2From: Jarkko Nikula <jhnikula@gmail.com>
3Date: Thu, 14 Apr 2011 16:21:58 +0300
4Subject: [PATCH 8/8] OMAP2PLUS: cpufreq: Fix typo when attempting to set mpu_clk for OMAP4
5
6Fix this typo as there is no dpll_mpu_ck for OMAP3 and code flow is clearly
7trying to set mpu_clk for OMAP4 for which this dpll_mpu_ck is available.
8
9Signed-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
14diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
15index 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--
281.6.6.1
29
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..d9b05173
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,77 @@
1From 988f50cb51d18e81ed2f7673a09694d28c9d086a Mon Sep 17 00:00:00 2001
2From: Rajendra Nayak <rnayak@ti.com>
3Date: Tue, 5 Apr 2011 15:22:31 +0530
4Subject: [PATCH 1/6] OMAP2+: clockdomain: Add an api to read idle mode
5
6Add a clockdomain api to check if hardware supervised
7idle transitions are enabled on a clockdomain.
8
9Signed-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
15diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
16index 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
47diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
48index 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--
761.6.6.1
77
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..c7c1ea0b
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,86 @@
1From e3ba8d41bfafd782f3ee7f8930d9bf393986c662 Mon Sep 17 00:00:00 2001
2From: Rajendra Nayak <rnayak@ti.com>
3Date: Tue, 5 Apr 2011 15:22:36 +0530
4Subject: [PATCH 2/6] OMAP2+: clockdomain: Add SoC support for clkdm_is_idle
5
6Add the SoC specific implemenation for clkdm_is_idle
7for OMAP2/3 and OMAP4.
8
9Signed-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
15diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
16index 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 };
59diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c
60index 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--
851.6.6.1
86
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..cbe5ca20
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,35 @@
1From 7cdc87071a4bb390ad5d7ddea210bd2b4d662114 Mon Sep 17 00:00:00 2001
2From: Rajendra Nayak <rnayak@ti.com>
3Date: Tue, 5 Apr 2011 15:22:41 +0530
4Subject: [PATCH 3/6] OMAP2+: PM: Initialise sleep_switch to a non-valid value
5
6sleep_switch which is initialised to 0 in omap_set_pwrdm_state
7happens to be a valid sleep_switch type (FORCEWAKEUP_SWITCH)
8which are defined as
9#define FORCEWAKEUP_SWITCH 0
10#define LOWPOWERSTATE_SWITCH 1
11
12This causes the function to wrongly program some clock domains
13even when the Powerdomain is in ON state.
14
15Signed-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
20diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
21index 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--
341.6.6.1
35
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..16eedf9a
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,50 @@
1From cec133850aa42c03d912c764aaa441677e782eca Mon Sep 17 00:00:00 2001
2From: Rajendra Nayak <rnayak@ti.com>
3Date: Tue, 5 Apr 2011 15:22:48 +0530
4Subject: [PATCH 4/6] OMAP2+: PM: idle clkdms only if already in idle
5
6The omap_set_pwrdm_state function forces clockdomains
7to idle, without checking the existing idle state
8programmed, instead based solely on the HW capability
9of the clockdomain to support idle.
10This is wrong and the clockdomains should be idled
11post a state_switch *only* if idle transitions on the
12clockdomain were already enabled.
13
14Signed-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
19diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
20index 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--
491.6.6.1
50
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..b0af9e7f
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,46 @@
1From 8fb6b7c488b31fbff5b81bdeea5dbb236342458b Mon Sep 17 00:00:00 2001
2From: Rajendra Nayak <rnayak@ti.com>
3Date: Tue, 29 Mar 2011 22:37:43 +0530
4Subject: [PATCH 5/6] OMAP2+: hwmod: Follow the recomended PRCM sequence
5
6Follow the recomended PRCM sequence.
7This still does not take care of Optional clocks.
8
9Signed-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
14diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
15index 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--
451.6.6.1
46
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..a8fc0c07
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,33 @@
1From 7b74888d198c260992349fab214cad3adf853ef9 Mon Sep 17 00:00:00 2001
2From: Rajendra Nayak <rnayak@ti.com>
3Date: Tue, 2 Mar 2010 17:25:30 +0530
4Subject: [PATCH 6/6] OMAP: Serial: Check wk_st only if present
5
6Uart on the resume path tries to read wk_st registers, even
7on architectures were its not present/populated.
8This patch fixes the issue.
9
10Signed-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
15diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
16index 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--
321.6.6.1
33
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..0d1cbce6
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,30 @@
1From 4af697edf9d1d85d2735e86e86e1203c3509dcba Mon Sep 17 00:00:00 2001
2From: Nishanth Menon <nm@ti.com>
3Date: Sat, 12 Feb 2011 17:27:14 +0530
4Subject: [PATCH 01/12] OMAP3+: voltage: remove spurious pr_notice for debugfs
5
6cat of debugfs entry for vp_volt provides voltage. The additional pr_notice
7is just spam on console and provides no additional information.
8
9Signed-off-by: Nishanth Menon <nm@ti.com>
10Signed-off-by: Kevin Hilman <khilman@ti.com>
11Signed-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
16diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
17index 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--
291.6.6.1
30
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..7b137925
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,41 @@
1From 37fb1c8eeecd39542716d3d0c7c5e3ca0eb198f8 Mon Sep 17 00:00:00 2001
2From: Nishanth Menon <nm@ti.com>
3Date: Sun, 13 Mar 2011 09:07:23 +0530
4Subject: [PATCH 02/12] OMAP4: PM: remove redundant #ifdef CONFIG_PM
5
6pm44xx.c is built only when CONFIG_PM is setup,
7remove redundant CONFIG_PM check.
8
9This also fixes:
10https://bugzilla.kernel.org/show_bug.cgi?id=25022
11
12Reported-by: Martin Etti <ettl.martin@gmx.de>
13
14Signed-off-by: Nishanth Menon <nm@ti.com>
15Signed-off-by: Kevin Hilman <khilman@ti.com>
16Signed-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
21diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
22index 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--
401.6.6.1
41
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..6c37b622
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,30 @@
1From a22a0dcefe99c8ee260e0c489bc44e6e14bb1ccb Mon Sep 17 00:00:00 2001
2From: Aaro Koskinen <aaro.koskinen@nokia.com>
3Date: Thu, 24 Mar 2011 18:35:31 +0200
4Subject: [PATCH 03/12] OMAP3+: smartreflex: fix sr_late_init() error path in probe
5
6sr_late_init() will take care of freeing the resources.
7
8Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
9Signed-off-by: Kevin Hilman <khilman@ti.com>
10Signed-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
15diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
16index 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--
291.6.6.1
30
diff --git a/extras/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/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0004-OMAP3-smartreflex-request-the-memory-region.patch
new file mode 100644
index 00000000..263094d5
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0004-OMAP3-smartreflex-request-the-memory-region.patch
@@ -0,0 +1,36 @@
1From db9c7da6a78be8584c96c83a3a2d1c8aeb623da8 Mon Sep 17 00:00:00 2001
2From: Aaro Koskinen <aaro.koskinen@nokia.com>
3Date: Thu, 24 Mar 2011 18:35:32 +0200
4Subject: [PATCH 04/12] OMAP3+: smartreflex: request the memory region
5
6We are releasing the memory region, but never actually request it.
7
8Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
9Signed-off-by: Kevin Hilman <khilman@ti.com>
10Signed-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
15diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
16index 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--
351.6.6.1
36
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..ea1e5673
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,66 @@
1From b3ca51ac09da7c260c28df396d4c830814697ff0 Mon Sep 17 00:00:00 2001
2From: Aaro Koskinen <aaro.koskinen@nokia.com>
3Date: Thu, 24 Mar 2011 18:35:33 +0200
4Subject: [PATCH 05/12] OMAP3+: smartreflex: fix ioremap leak on probe error
5
6Add missing iounmap() to error paths.
7
8Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
9Signed-off-by: Kevin Hilman <khilman@ti.com>
10Signed-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
15diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
16index 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--
651.6.6.1
66
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..cda6da63
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,29 @@
1From 92e63a2f098ce344cfc51ec9a7420e1a5cf85c3e Mon Sep 17 00:00:00 2001
2From: Aaro Koskinen <aaro.koskinen@nokia.com>
3Date: Thu, 24 Mar 2011 18:35:34 +0200
4Subject: [PATCH 06/12] OMAP3+: smartreflex: delete instance from sr_list on probe error
5
6If the probe fails, the node should be deleted from sr_list.
7
8Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
9Signed-off-by: Kevin Hilman <khilman@ti.com>
10Signed-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
15diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
16index 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--
281.6.6.1
29
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..d4543a46
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,48 @@
1From c194377152df812bcb29fff8f217ffbde59089be Mon Sep 17 00:00:00 2001
2From: Aaro Koskinen <aaro.koskinen@nokia.com>
3Date: Thu, 24 Mar 2011 18:35:35 +0200
4Subject: [PATCH 07/12] OMAP3+: smartreflex: delete debugfs entries on probe error
5
6Delete created debugfs entries if probe fails.
7
8Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
9Signed-off-by: Kevin Hilman <khilman@ti.com>
10Signed-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
15diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
16index 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--
471.6.6.1
48
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..e3ee0412
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,57 @@
1From 2b9e07516cc3853340b5e06e9ae7244ca5681466 Mon Sep 17 00:00:00 2001
2From: Jean Pihet <j-pihet@ti.com>
3Date: Fri, 29 Apr 2011 11:26:22 +0200
4Subject: [PATCH 08/12] OMAP3 cpuidle: remove useless SDP specific timings
5
6The cpuidle states settings can be overriden by some board-
7specific settings, by calling omap3_pm_init_cpuidle.
8Remove the 3430SDP specific states settings registration
9since the figures are identical to the default ones (in cpuidle34xx.c).
10
11Signed-off-by: Jean Pihet <j-pihet@ti.com>
12Signed-off-by: Kevin Hilman <khilman@ti.com>
13Signed-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
18diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
19index 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--
561.6.6.1
57
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..c44371df
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,48 @@
1From a0f28097b944930e479998780863b9e5a39e30b3 Mon Sep 17 00:00:00 2001
2From: Nishanth Menon <nm@ti.com>
3Date: Mon, 14 Feb 2011 12:16:36 +0530
4Subject: [PATCH 09/12] OMAP3+: SR: make notify independent of class
5
6Interrupt notification mechanism of SmartReflex can be used by the
7choice of implementation of the class driver. For example, Class 2 and
8Class 1.5 of SmartReflex can both use the interrupt notification to
9identify the transition of voltage or other events.
10
11Hence, the actual class does not matter for notifier. Let the class
12driver's handling decide how it should be used. SmartReflex driver
13should provide just the primitives.
14
15Signed-off-by: Nishanth Menon <nm@ti.com>
16Signed-off-by: Kevin Hilman <khilman@ti.com>
17Signed-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
22diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
23index 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--
471.6.6.1
48
diff --git a/extras/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/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0010-OMAP3-SR-disable-interrupt-by-default.patch
new file mode 100644
index 00000000..e25c3e86
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0010-OMAP3-SR-disable-interrupt-by-default.patch
@@ -0,0 +1,37 @@
1From ca5dc57538a566681731102e09a9d1865a4a7020 Mon Sep 17 00:00:00 2001
2From: Nishanth Menon <nm@ti.com>
3Date: Mon, 14 Feb 2011 12:41:10 +0530
4Subject: [PATCH 10/12] OMAP3+: SR: disable interrupt by default
5
6We will enable and disable interrupt on a need basis in the class
7driver. We need to keep the IRQ disabled by default else the
8forceupdate or vcbypass events could trigger events that we don't
9need/expect to handle.
10
11This is a preparation for SmartReflex AVS class drivers such as
12class 2 and class 1.5 which would need to use interrupts. Existing
13SmartReflex AVS class 3 driver does not require to use interrupts
14and is not impacted by this change.
15
16Signed-off-by: Nishanth Menon <nm@ti.com>
17Signed-off-by: Kevin Hilman <khilman@ti.com>
18Signed-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
23diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
24index 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--
361.6.6.1
37
diff --git a/extras/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/extras/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
new file mode 100644
index 00000000..b96682ea
--- /dev/null
+++ b/extras/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
@@ -0,0 +1,41 @@
1From 4aa67e94d6b13905abcf3e95cb66ea7be9c2e8dd Mon Sep 17 00:00:00 2001
2From: Nishanth Menon <nm@ti.com>
3Date: Mon, 14 Feb 2011 21:14:17 +0530
4Subject: [PATCH 11/12] OMAP3+: SR: enable/disable SR only on need
5
6Since we already know the state of the autocomp enablement, we can
7see if the requested state is different from the current state and
8enable/disable SR only on the need basis.
9
10Signed-off-by: Nishanth Menon <nm@ti.com>
11Signed-off-by: Kevin Hilman <khilman@ti.com>
12Signed-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
17diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
18index 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--
401.6.6.1
41
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0012-OMAP3-SR-fix-cosmetic-indentation.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0012-OMAP3-SR-fix-cosmetic-indentation.patch
new file mode 100644
index 00000000..eda76a0d
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm/0012-OMAP3-SR-fix-cosmetic-indentation.patch
@@ -0,0 +1,49 @@
1From 0c2089eecdfc3a85a376eddf9c77857f3d575be6 Mon Sep 17 00:00:00 2001
2From: Nishanth Menon <nm@ti.com>
3Date: Mon, 14 Feb 2011 12:33:13 +0530
4Subject: [PATCH 12/12] OMAP3+: SR: fix cosmetic indentation
5
6Error label case seems to have a 2 tab indentation when just 1 is
7necessary.
8
9Signed-off-by: Nishanth Menon <nm@ti.com>
10Signed-off-by: Kevin Hilman <khilman@ti.com>
11Signed-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
16diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
17index 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--
481.6.6.1
49
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0001-OMAP-DSS2-DSI-fix-use_sys_clk-highfreq.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0001-OMAP-DSS2-DSI-fix-use_sys_clk-highfreq.patch
new file mode 100644
index 00000000..a66407b3
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0001-OMAP-DSS2-DSI-fix-use_sys_clk-highfreq.patch
@@ -0,0 +1,33 @@
1From 6aae34d56ba8fef140b60631536272f6b39c1f61 Mon Sep 17 00:00:00 2001
2From: Tomi Valkeinen <tomi.valkeinen@ti.com>
3Date: Thu, 7 Apr 2011 15:28:47 +0300
4Subject: [PATCH 01/32] OMAP: DSS2: DSI: fix use_sys_clk & highfreq
5
6use_sys_clk and highfreq fields in dsi.current_cinfo were never set.
7Luckily they weren't used anywhere so it didn't cause any problems.
8
9This patch fixes those fields and they are now set at the same time as
10the rest of the fields.
11
12Signed-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
17diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
18index 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--
321.6.6.1
33
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0002-OMAP-DSS2-DSI-fix-dsi_dump_clocks.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0002-OMAP-DSS2-DSI-fix-dsi_dump_clocks.patch
new file mode 100644
index 00000000..9d5ab617
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0002-OMAP-DSS2-DSI-fix-dsi_dump_clocks.patch
@@ -0,0 +1,49 @@
1From 5275654d2e873ca5bdbbd8be61dbb2d63c0e04cb Mon Sep 17 00:00:00 2001
2From: Tomi Valkeinen <tomi.valkeinen@ti.com>
3Date: Mon, 4 Apr 2011 10:02:53 +0300
4Subject: [PATCH 02/32] OMAP: DSS2: DSI: fix dsi_dump_clocks()
5
6On OMAP4, reading DSI_PLL_CONFIGURATION2 register requires the L3 clock
7(CIO_CLK_ICG) to PLL. Currently dsi_dump_clocks() tries to read that
8register without enabling the L3 clock, leading to crash if DSI is not
9in use.
10
11The status of the bit being read from DSI_PLL_CONFIGURATION2 is
12available from dsi_clock_info->use_sys_clk, so we can avoid the whole
13problem by just using that.
14
15Signed-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
20diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
21index 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--
481.6.6.1
49
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0003-OMAP2PLUS-DSS2-Fix-Return-correct-lcd-clock-source-f.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0003-OMAP2PLUS-DSS2-Fix-Return-correct-lcd-clock-source-f.patch
new file mode 100644
index 00000000..14239fad
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0003-OMAP2PLUS-DSS2-Fix-Return-correct-lcd-clock-source-f.patch
@@ -0,0 +1,43 @@
1From 9ddb3aafff5f7f6b7eaad32f9b1eea249c0dce8b Mon Sep 17 00:00:00 2001
2From: Archit Taneja <archit@ti.com>
3Date: Thu, 31 Mar 2011 13:23:35 +0530
4Subject: [PATCH 03/32] OMAP2PLUS: DSS2: Fix: Return correct lcd clock source for OMAP2/3
5
6dss.lcd_clk_source is set to the default value DSS_CLK_SRC_FCK at dss_init.
7For OMAP2 and OMAP3, the dss.lcd_clk_source should always be the same as
8dss.dispc_clk_source. The function dss_get_lcd_clk_source() always returns the
9default value DSS_CLK_SRC_FCK for OMAP2/3. This leads to wrong clock dumps when
10dispc_clk_source is not DSS_CLK_SRC_FCK.
11
12Correct this function to always return dss.dispc_clk_source for OMAP2/3.
13
14Signed-off-by: Archit Taneja <archit@ti.com>
15Signed-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
20diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
21index 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--
421.6.6.1
43
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0004-OMAP-DSS-DSI-Fix-DSI-PLL-power-bug.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0004-OMAP-DSS-DSI-Fix-DSI-PLL-power-bug.patch
new file mode 100644
index 00000000..8c2d6e6c
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0004-OMAP-DSS-DSI-Fix-DSI-PLL-power-bug.patch
@@ -0,0 +1,64 @@
1From 4a56fbcabd128dbd07895e5167fd131299a1391c Mon Sep 17 00:00:00 2001
2From: Tomi Valkeinen <tomi.valkeinen@ti.com>
3Date: Fri, 15 Apr 2011 10:42:59 +0300
4Subject: [PATCH 04/32] OMAP: DSS: DSI: Fix DSI PLL power bug
5
6OMAP3630 has a HW bug causing DSI PLL power command POWER_ON_DIV (0x3)
7to not work properly. The bug prevents us from enabling DSI PLL power
8only to HS divider block.
9
10This patch adds a dss feature for the bug and converts POWER_ON_DIV
11requests to POWER_ON_ALL (0x2).
12
13Signed-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
20diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
21index 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 */
36diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
37index 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,
49diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
50index 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--
631.6.6.1
64
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0005-OMAP-DSS2-fix-panel-Kconfig-dependencies.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0005-OMAP-DSS2-fix-panel-Kconfig-dependencies.patch
new file mode 100644
index 00000000..a8279242
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0005-OMAP-DSS2-fix-panel-Kconfig-dependencies.patch
@@ -0,0 +1,61 @@
1From fcb26a06fe1badfaaf7aaa68140c8b3370dd503e Mon Sep 17 00:00:00 2001
2From: Tomi Valkeinen <tomi.valkeinen@ti.com>
3Date: Fri, 8 Apr 2011 09:30:27 +0300
4Subject: [PATCH 05/32] OMAP: DSS2: fix panel Kconfig dependencies
5
6All DPI panels were missing dependency to OMAP2_DSS_DPI. Add the
7dependency.
8
9Signed-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
14diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
15index 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--
601.6.6.1
61
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0006-OMAP-DSS2-add-bootarg-for-selecting-svideo-or-compos.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0006-OMAP-DSS2-add-bootarg-for-selecting-svideo-or-compos.patch
new file mode 100644
index 00000000..d899cb0b
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0006-OMAP-DSS2-add-bootarg-for-selecting-svideo-or-compos.patch
@@ -0,0 +1,75 @@
1From 4bd1d52fff974f5a5d0582f4fa4eae6e03e36fc1 Mon Sep 17 00:00:00 2001
2From: Steve Sakoman <steve@sakoman.com>
3Date: Tue, 19 Jan 2010 21:19:15 -0800
4Subject: [PATCH 06/32] OMAP: DSS2: add bootarg for selecting svideo or composite for tv output
5
6also 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
12diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
13index 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
52diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
53index 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--
741.6.6.1
75
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0007-video-add-timings-for-hd720.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0007-video-add-timings-for-hd720.patch
new file mode 100644
index 00000000..b653e6c4
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0007-video-add-timings-for-hd720.patch
@@ -0,0 +1,27 @@
1From 6d87a3f85ac36205111b4fe71ad06976239cdbe7 Mon Sep 17 00:00:00 2001
2From: Steve Sakoman <steve@sakoman.com>
3Date: Sat, 19 Dec 2009 06:52:43 -0800
4Subject: [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
10diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
11index 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--
261.6.6.1
27
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0008-drivers-net-smsc911x-return-ENODEV-if-device-is-not-.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0008-drivers-net-smsc911x-return-ENODEV-if-device-is-not-.patch
new file mode 100644
index 00000000..1e0e0579
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0008-drivers-net-smsc911x-return-ENODEV-if-device-is-not-.patch
@@ -0,0 +1,29 @@
1From 1e3fcfd74686fa8b02f93bb592cca458942058e4 Mon Sep 17 00:00:00 2001
2From: Steve Sakoman <sakoman@gmail.com>
3Date: Tue, 15 Dec 2009 15:17:44 -0800
4Subject: [PATCH 08/32] drivers: net: smsc911x: return ENODEV if device is not found
5
6Signed-off-by: Steve Sakoman <sakoman@gmail.com>
7---
8 drivers/net/smsc911x.c | 4 +++-
9 1 files changed, 3 insertions(+), 1 deletions(-)
10
11diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
12index 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--
281.6.6.1
29
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0009-drivers-input-touchscreen-ads7846-return-ENODEV-if-d.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0009-drivers-input-touchscreen-ads7846-return-ENODEV-if-d.patch
new file mode 100644
index 00000000..f753684a
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0009-drivers-input-touchscreen-ads7846-return-ENODEV-if-d.patch
@@ -0,0 +1,47 @@
1From 078005a9c8b5913ed5eb7a7a9508e4b0a5b18c30 Mon Sep 17 00:00:00 2001
2From: Steve Sakoman <sakoman@gmail.com>
3Date: Tue, 15 Dec 2009 15:24:10 -0800
4Subject: [PATCH 09/32] drivers: input: touchscreen: ads7846: return ENODEV if device is not found
5
6Signed-off-by: Steve Sakoman <sakoman@gmail.com>
7---
8 drivers/input/touchscreen/ads7846.c | 13 ++++++++++---
9 1 files changed, 10 insertions(+), 3 deletions(-)
10
11diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
12index 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--
461.6.6.1
47
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0010-Revert-omap2_mcspi-Flush-posted-writes.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0010-Revert-omap2_mcspi-Flush-posted-writes.patch
new file mode 100644
index 00000000..6c76843d
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0010-Revert-omap2_mcspi-Flush-posted-writes.patch
@@ -0,0 +1,25 @@
1From ae16b19238b8d0609612d0e1f1a419d293f17c80 Mon Sep 17 00:00:00 2001
2From: Steve Sakoman <steve@sakoman.com>
3Date: Thu, 3 Mar 2011 13:29:30 -0800
4Subject: [PATCH 10/32] Revert "omap2_mcspi: Flush posted writes"
5
6This reverts commit a330ce2001b290c59fe98c37e981683ef0a75fdf.
7---
8 drivers/spi/omap2_mcspi.c | 1 -
9 1 files changed, 0 insertions(+), 1 deletions(-)
10
11diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
12index 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--
241.6.6.1
25
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0011-Revert-omap_hsmmc-improve-interrupt-synchronisation.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0011-Revert-omap_hsmmc-improve-interrupt-synchronisation.patch
new file mode 100644
index 00000000..78381e9e
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0011-Revert-omap_hsmmc-improve-interrupt-synchronisation.patch
@@ -0,0 +1,482 @@
1From 3a66cefdf60033381c623b0425345c41e8c078fe Mon Sep 17 00:00:00 2001
2From: Steve Sakoman <steve@sakoman.com>
3Date: Fri, 19 Nov 2010 15:11:19 -0800
4Subject: [PATCH 11/32] Revert "omap_hsmmc: improve interrupt synchronisation"
5
6This reverts commit b417577d3b9bbb06a4ddc9aa955af9bd503f7242.
7
8Conflicts:
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
15diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
16index 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--
4811.6.6.1
482
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0012-Don-t-turn-SDIO-cards-off-to-save-power.-Doing-so-wi.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0012-Don-t-turn-SDIO-cards-off-to-save-power.-Doing-so-wi.patch
new file mode 100644
index 00000000..1c86b22d
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0012-Don-t-turn-SDIO-cards-off-to-save-power.-Doing-so-wi.patch
@@ -0,0 +1,51 @@
1From 75d9413d575f724e1f7c006fdef374fb1c200346 Mon Sep 17 00:00:00 2001
2From: David Vrabel <david.vrabel@csr.com>
3Date: Fri, 2 Apr 2010 08:41:47 -0700
4Subject: [PATCH 12/32] Don't turn SDIO cards off to save power. Doing so will lose all internal state in the card.
5
6Signed-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
11diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
12index 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--
501.6.6.1
51
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0013-Enable-the-use-of-SDIO-card-interrupts.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0013-Enable-the-use-of-SDIO-card-interrupts.patch
new file mode 100644
index 00000000..59d5ec47
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0013-Enable-the-use-of-SDIO-card-interrupts.patch
@@ -0,0 +1,288 @@
1From 948eeb1f03da5fca0f6734c10efbc35ad63a1d08 Mon Sep 17 00:00:00 2001
2From: David Vrabel <david.vrabel@csr.com>
3Date: Fri, 2 Apr 2010 08:42:22 -0700
4Subject: [PATCH 13/32] Enable the use of SDIO card interrupts.
5
6FCLK must be enabled while SDIO interrupts are enabled or the MMC
7module won't wake-up (even though ENAWAKEUP in SYSCONFIG and IWE in
8HTCL have been set). Enabling the MMC module to wake-up would require
9configuring the MMC module (and the mmci_dat[1] GPIO when the CORE
10power domain is OFF) as wake-up sources in the PRCM.
11
12The writes to STAT and ISE when starting a command are unnecessary and
13have been removed.
14
15Signed-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
20diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
21index 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--
2871.6.6.1
288
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0014-soc-codecs-Enable-audio-capture-by-default-for-twl40.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0014-soc-codecs-Enable-audio-capture-by-default-for-twl40.patch
new file mode 100644
index 00000000..d6e82879
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0014-soc-codecs-Enable-audio-capture-by-default-for-twl40.patch
@@ -0,0 +1,27 @@
1From f646d3df7a7160fd80f20416c4a0fce55946f527 Mon Sep 17 00:00:00 2001
2From: Steve Sakoman <steve@sakoman.com>
3Date: Thu, 17 Dec 2009 12:45:20 -0800
4Subject: [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
10diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
11index 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--
261.6.6.1
27
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0015-soc-codecs-twl4030-Turn-on-mic-bias-by-default.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0015-soc-codecs-twl4030-Turn-on-mic-bias-by-default.patch
new file mode 100644
index 00000000..04d91685
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0015-soc-codecs-twl4030-Turn-on-mic-bias-by-default.patch
@@ -0,0 +1,25 @@
1From 00adf70cb5f8706ac5e7b1ec6f5a94f7e490b606 Mon Sep 17 00:00:00 2001
2From: Steve Sakoman <steve@sakoman.com>
3Date: Wed, 29 Dec 2010 11:39:16 -0800
4Subject: [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
10diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
11index 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--
241.6.6.1
25
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0016-RTC-add-support-for-backup-battery-recharge.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0016-RTC-add-support-for-backup-battery-recharge.patch
new file mode 100644
index 00000000..cb685cc2
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0016-RTC-add-support-for-backup-battery-recharge.patch
@@ -0,0 +1,55 @@
1From 6f432e1e39f276a41d600d1cc9cd17fc088877d8 Mon Sep 17 00:00:00 2001
2From: Steve Sakoman <steve@sakoman.com>
3Date: Thu, 4 Feb 2010 12:26:22 -0800
4Subject: [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
10diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
11index 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--
541.6.6.1
55
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0017-ARM-OMAP2-mmc-twl4030-move-clock-input-selection-pri.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0017-ARM-OMAP2-mmc-twl4030-move-clock-input-selection-pri.patch
new file mode 100644
index 00000000..1e6ba8db
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0017-ARM-OMAP2-mmc-twl4030-move-clock-input-selection-pri.patch
@@ -0,0 +1,39 @@
1From 56dc96df8ff5e3db6afde96d64d74200f85e59c2 Mon Sep 17 00:00:00 2001
2From: Steve Sakoman <steve@sakoman.com>
3Date: Sun, 24 Jan 2010 09:33:56 -0800
4Subject: [PATCH 17/32] ARM: OMAP2: mmc-twl4030: move clock input selection prior to vcc test
5
6otherwise 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
11diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
12index 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--
381.6.6.1
39
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0018-Add-power-off-support-for-the-TWL4030-companion.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0018-Add-power-off-support-for-the-TWL4030-companion.patch
new file mode 100644
index 00000000..30860275
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0018-Add-power-off-support-for-the-TWL4030-companion.patch
@@ -0,0 +1,103 @@
1From 8c257a6e7460ceb8c899980f7dad701ceb619adc Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Bernhard=20W=C3=B6rndl-Aichriedler?= <bwa@xdevelop.at>
3Date: Sat, 15 May 2010 16:34:05 +0200
4Subject: [PATCH 18/32] Add power-off support for the TWL4030 companion
5
6This 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
12diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
13index 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
29diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
30index 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--
1021.6.6.1
103
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0019-ARM-OMAP-Add-twl4030-madc-support-to-Overo.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0019-ARM-OMAP-Add-twl4030-madc-support-to-Overo.patch
new file mode 100644
index 00000000..1f139f1c
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0019-ARM-OMAP-Add-twl4030-madc-support-to-Overo.patch
@@ -0,0 +1,33 @@
1From 46ea520a3c80914ae5ad3e35be7b8650706da3e6 Mon Sep 17 00:00:00 2001
2From: Steve Sakoman <steve@sakoman.com>
3Date: Thu, 17 Dec 2009 14:27:15 -0800
4Subject: [PATCH 19/32] ARM: OMAP: Add twl4030 madc support to Overo
5
6Signed-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
11diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
12index 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--
321.6.6.1
33
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0020-Enabling-Hwmon-driver-for-twl4030-madc.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0020-Enabling-Hwmon-driver-for-twl4030-madc.patch
new file mode 100644
index 00000000..c80aef9a
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0020-Enabling-Hwmon-driver-for-twl4030-madc.patch
@@ -0,0 +1,46 @@
1From 931bd787effbd6f1f00468c89c647c66c0bbc164 Mon Sep 17 00:00:00 2001
2From: Keerthy <j-keerthy@ti.com>
3Date: Wed, 4 May 2011 01:14:50 +0530
4Subject: [PATCH 20/32] Enabling Hwmon driver for twl4030-madc
5
6Signed-off-by: Keerthy <j-keerthy@ti.com>
7---
8 drivers/mfd/twl-core.c | 15 +++++++++++++++
9 1 files changed, 15 insertions(+), 0 deletions(-)
10
11diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
12index 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--
451.6.6.1
46
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0021-mfd-twl-core-enable-madc-clock.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0021-mfd-twl-core-enable-madc-clock.patch
new file mode 100644
index 00000000..732d306a
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0021-mfd-twl-core-enable-madc-clock.patch
@@ -0,0 +1,54 @@
1From aee147073ad84a7c81fba36dd475c6d2d17ed728 Mon Sep 17 00:00:00 2001
2From: Steve Sakoman <steve@sakoman.com>
3Date: Sat, 23 Jan 2010 06:26:54 -0800
4Subject: [PATCH 21/32] mfd: twl-core: enable madc clock
5
6Now that the madc driver has been merged it is also necessary to enable the clock to the madc block
7
8Signed-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
14diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
15index 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
40diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
41index 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--
531.6.6.1
54
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0022-rtc-twl-Switch-to-using-threaded-irq.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0022-rtc-twl-Switch-to-using-threaded-irq.patch
new file mode 100644
index 00000000..0306d4b4
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0022-rtc-twl-Switch-to-using-threaded-irq.patch
@@ -0,0 +1,25 @@
1From 29dd1b5655f60f97a9cee2f4ff1d27d7da1329a1 Mon Sep 17 00:00:00 2001
2From: Ilkka Koskinen <ilkka.koskinen@nokia.com>
3Date: Wed, 16 Mar 2011 16:07:14 +0000
4Subject: [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
10diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
11index 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--
241.6.6.1
25
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0023-ARM-OMAP-automatically-set-musb-mode-in-platform-dat.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0023-ARM-OMAP-automatically-set-musb-mode-in-platform-dat.patch
new file mode 100644
index 00000000..a35d7de5
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0023-ARM-OMAP-automatically-set-musb-mode-in-platform-dat.patch
@@ -0,0 +1,49 @@
1From 92c06791d4d6b537a9a83b27d71d7d3dd348f93f Mon Sep 17 00:00:00 2001
2From: Steve Sakoman <steve@sakoman.com>
3Date: Wed, 24 Feb 2010 10:37:22 -0800
4Subject: [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
11diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
12index 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
29diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
30index 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--
481.6.6.1
49
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0024-omap-mmc-Adjust-dto-to-eliminate-timeout-errors.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0024-omap-mmc-Adjust-dto-to-eliminate-timeout-errors.patch
new file mode 100644
index 00000000..bd1764a5
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0024-omap-mmc-Adjust-dto-to-eliminate-timeout-errors.patch
@@ -0,0 +1,28 @@
1From a442a2b9b2f9f51375f8a796ee88784d3754be00 Mon Sep 17 00:00:00 2001
2From: Steve Sakoman <steve@sakoman.com>
3Date: Wed, 12 Jan 2011 05:54:55 -0800
4Subject: [PATCH 24/32] omap: mmc: Adjust dto to eliminate timeout errors
5
6A number of SD card types were experiencing timeout errors. This
7could also lead to data corruption in some cases.
8
9This 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
14diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
15index 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--
271.6.6.1
28
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0025-omap-Fix-mtd-subpage-read-alignment.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0025-omap-Fix-mtd-subpage-read-alignment.patch
new file mode 100644
index 00000000..1508da1a
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0025-omap-Fix-mtd-subpage-read-alignment.patch
@@ -0,0 +1,95 @@
1From acf75c8b4d0f6775527636bf9d41bb1f74fc2f97 Mon Sep 17 00:00:00 2001
2From: Charles Manning <cdhmanning@gmail.com>
3Date: Tue, 18 Jan 2011 11:25:25 +1300
4Subject: [PATCH 25/32] omap: Fix mtd subpage read alignment
5
6This allows the omap2 prefetch engine to work properly for subpage
7reads. Without this ECC errors will stop UBIFS from working.
8
9Signed-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
16diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
17index 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);
53diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
54index 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.
65diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
66index 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--
941.6.6.1
95
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0026-mtd-nand-omap2-Force-all-buffer-reads-to-u32-alignme.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0026-mtd-nand-omap2-Force-all-buffer-reads-to-u32-alignme.patch
new file mode 100644
index 00000000..5e060231
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0026-mtd-nand-omap2-Force-all-buffer-reads-to-u32-alignme.patch
@@ -0,0 +1,35 @@
1From 048c2b85c12ac4aa8cd82201e1ade332557e4380 Mon Sep 17 00:00:00 2001
2From: Charles Manning <manningc2@actrix.gen.nz>
3Date: Thu, 16 Dec 2010 20:35:56 -0800
4Subject: [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
10diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
11index 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--
341.6.6.1
35
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0027-omap-nand-fix-subpage-ecc-issue-with-prefetch.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0027-omap-nand-fix-subpage-ecc-issue-with-prefetch.patch
new file mode 100644
index 00000000..21eb1e9f
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0027-omap-nand-fix-subpage-ecc-issue-with-prefetch.patch
@@ -0,0 +1,63 @@
1From fb4dfff6a6e107e0e526801e7add4a9aaeab1eab Mon Sep 17 00:00:00 2001
2From: kishore kadiyala <kishore.kadiyala@ti.com>
3Date: Mon, 2 May 2011 11:10:38 +0000
4Subject: [PATCH 27/32] omap : nand : fix subpage ecc issue with prefetch
5
6For prefetch engine, read and write got broken in commit '2c01946c'.
7We never hit a scenario of not getting 'gpmc_prefetch_enable'
8call success.
9When reading/writing a subpage with a non divisible by 4 ecc number
10of bytes, the mis-aligned bytes gets handled first before enabling
11the Prefetch engine, then it reads/writes rest of the bytes.
12
13Signed-off-by: Kishore Kadiyala <kishore.kadiyala@ti.com>
14Signed-off-by: Vimal Singh <vimal.newwork@gmail.com>
15Reported-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
20diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
21index 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--
621.6.6.1
63
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0028-OMAP-Overo-Add-support-for-spidev.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0028-OMAP-Overo-Add-support-for-spidev.patch
new file mode 100644
index 00000000..be1f9630
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0028-OMAP-Overo-Add-support-for-spidev.patch
@@ -0,0 +1,46 @@
1From ee2dcb39e9255fc0aa6b4e267e9553bdbd11e82b Mon Sep 17 00:00:00 2001
2From: Scott Ellis <scottellis.developer@gmail.com>
3Date: Sun, 23 Jan 2011 20:39:35 -0800
4Subject: [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
10diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
11index 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--
451.6.6.1
46
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0029-unionfs-Add-support-for-unionfs-2.5.9.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0029-unionfs-Add-support-for-unionfs-2.5.9.patch
new file mode 100644
index 00000000..c17608b0
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0029-unionfs-Add-support-for-unionfs-2.5.9.patch
@@ -0,0 +1,11494 @@
1From 0de368979f94e7c51940979c6149d34aec08f13f Mon Sep 17 00:00:00 2001
2From: Steve Sakoman <steve@sakoman.com>
3Date: Mon, 2 May 2011 16:14:34 -0700
4Subject: [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
81diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
82index 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
94diff --git a/Documentation/filesystems/unionfs/00-INDEX b/Documentation/filesystems/unionfs/00-INDEX
95new file mode 100644
96index 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.
110diff --git a/Documentation/filesystems/unionfs/concepts.txt b/Documentation/filesystems/unionfs/concepts.txt
111new file mode 100644
112index 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/>.
403diff --git a/Documentation/filesystems/unionfs/issues.txt b/Documentation/filesystems/unionfs/issues.txt
404new file mode 100644
405index 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/>.
437diff --git a/Documentation/filesystems/unionfs/rename.txt b/Documentation/filesystems/unionfs/rename.txt
438new file mode 100644
439index 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+
474diff --git a/Documentation/filesystems/unionfs/usage.txt b/Documentation/filesystems/unionfs/usage.txt
475new file mode 100644
476index 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/>.
614diff --git a/MAINTAINERS b/MAINTAINERS
615index 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/
633diff --git a/fs/Kconfig b/fs/Kconfig
634index 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"
645diff --git a/fs/Makefile b/fs/Makefile
646index 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/
657diff --git a/fs/namei.c b/fs/namei.c
658index 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);
720diff --git a/fs/splice.c b/fs/splice.c
721index 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;
799diff --git a/fs/stack.c b/fs/stack.c
800index 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
825diff --git a/fs/unionfs/Kconfig b/fs/unionfs/Kconfig
826new file mode 100644
827index 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.
855diff --git a/fs/unionfs/Makefile b/fs/unionfs/Makefile
856new file mode 100644
857index 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
878diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
879new file mode 100644
880index 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+}
1782diff --git a/fs/unionfs/copyup.c b/fs/unionfs/copyup.c
1783new file mode 100644
1784index 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+}
2684diff --git a/fs/unionfs/debug.c b/fs/unionfs/debug.c
2685new file mode 100644
2686index 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+}
3238diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c
3239new file mode 100644
3240index 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+};
3650diff --git a/fs/unionfs/dirfops.c b/fs/unionfs/dirfops.c
3651new file mode 100644
3652index 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+};
3958diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
3959new file mode 100644
3960index 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+}
4122diff --git a/fs/unionfs/fanout.h b/fs/unionfs/fanout.h
4123new file mode 100644
4124index 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 */
4535diff --git a/fs/unionfs/file.c b/fs/unionfs/file.c
4536new file mode 100644
4537index 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+};
4923diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
4924new file mode 100644
4925index 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+};
6028diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
6029new file mode 100644
6030index 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+}
6603diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c
6604new file mode 100644
6605index 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);
7372diff --git a/fs/unionfs/mmap.c b/fs/unionfs/mmap.c
7373new file mode 100644
7374index 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+};
7467diff --git a/fs/unionfs/rdstate.c b/fs/unionfs/rdstate.c
7468new file mode 100644
7469index 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+}
7758diff --git a/fs/unionfs/rename.c b/fs/unionfs/rename.c
7759new file mode 100644
7760index 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+}
8286diff --git a/fs/unionfs/sioq.c b/fs/unionfs/sioq.c
8287new file mode 100644
8288index 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+}
8393diff --git a/fs/unionfs/sioq.h b/fs/unionfs/sioq.h
8394new file mode 100644
8395index 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 */
8490diff --git a/fs/unionfs/subr.c b/fs/unionfs/subr.c
8491new file mode 100644
8492index 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+}
8591diff --git a/fs/unionfs/super.c b/fs/unionfs/super.c
8592new file mode 100644
8593index 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+};
9627diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
9628new file mode 100644
9629index 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_ */
10312diff --git a/fs/unionfs/unlink.c b/fs/unionfs/unlink.c
10313new file mode 100644
10314index 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+}
10596diff --git a/fs/unionfs/whiteout.c b/fs/unionfs/whiteout.c
10597new file mode 100644
10598index 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+}
11203diff --git a/fs/unionfs/xattr.c b/fs/unionfs/xattr.c
11204new file mode 100644
11205index 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+}
11382diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h
11383index 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
11407diff --git a/include/linux/magic.h b/include/linux/magic.h
11408index 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
11420diff --git a/include/linux/namei.h b/include/linux/namei.h
11421index 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 *);
11436diff --git a/include/linux/splice.h b/include/linux/splice.h
11437index 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
11452diff --git a/include/linux/union_fs.h b/include/linux/union_fs.h
11453new file mode 100644
11454index 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+
11480diff --git a/security/security.c b/security/security.c
11481index 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--
114931.6.6.1
11494
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0030-omap-Change-omap_device-activate-latency-messages-fr.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0030-omap-Change-omap_device-activate-latency-messages-fr.patch
new file mode 100644
index 00000000..7dc80905
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0030-omap-Change-omap_device-activate-latency-messages-fr.patch
@@ -0,0 +1,34 @@
1From 728b784863056a2b2e35134f71082271ebab0892 Mon Sep 17 00:00:00 2001
2From: Steve Sakoman <steve@sakoman.com>
3Date: Mon, 23 May 2011 12:16:50 -0700
4Subject: [PATCH 30/32] omap: Change omap_device activate latency messages from pr_warning to pr_debug
5
6Messages can be safely ignored, so reduce console noise
7
8Signed-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
13diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
14index 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--
331.6.6.1
34
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0031-omap-overo-Add-opp-init.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0031-omap-overo-Add-opp-init.patch
new file mode 100644
index 00000000..07df7634
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0031-omap-overo-Add-opp-init.patch
@@ -0,0 +1,105 @@
1From 530abfee962141f263344b4de3ca48b57e5e514c Mon Sep 17 00:00:00 2001
2From: Steve Sakoman <steve@sakoman.com>
3Date: Tue, 24 May 2011 20:36:07 -0700
4Subject: [PATCH 31/32] omap: overo: Add opp init
5
6omap: overo: Add opp init
7
8Work in progress
9
10Signed-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
15diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
16index 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--
1041.6.6.1
105
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0032-omap3-Add-basic-support-for-720MHz-part.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0032-omap3-Add-basic-support-for-720MHz-part.patch
new file mode 100644
index 00000000..9a9320d7
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/sakoman/0032-omap3-Add-basic-support-for-720MHz-part.patch
@@ -0,0 +1,202 @@
1From cd9682b39f41675c4e551c607425226b38fab17d Mon Sep 17 00:00:00 2001
2From: Sanjeev Premi <premi@ti.com>
3Date: Tue, 18 Jan 2011 13:19:55 +0530
4Subject: [PATCH 32/32] omap3: Add basic support for 720MHz part
5
6This patch adds support for new speed enhanced parts with ARM
7and IVA running at 720MHz and 520MHz respectively. These parts
8can be probed at run-time by reading PRODID.SKUID[3:0] at
90x4830A20C [1].
10
11This 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
20Signed-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
28diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
29index 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
46diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
47index 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 }
74diff --git a/arch/arm/mach-omap2/opp3xxx_data.c b/arch/arm/mach-omap2/opp3xxx_data.c
75index 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);
181diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
182index 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--
2011.6.6.1
202