diff options
508 files changed, 17107 insertions, 3556 deletions
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index 9e642c5bf526..8dfc6708a257 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX | |||
@@ -232,6 +232,8 @@ memory.txt | |||
232 | - info on typical Linux memory problems. | 232 | - info on typical Linux memory problems. |
233 | mips/ | 233 | mips/ |
234 | - directory with info about Linux on MIPS architecture. | 234 | - directory with info about Linux on MIPS architecture. |
235 | mmc/ | ||
236 | - directory with info about the MMC subsystem | ||
235 | mono.txt | 237 | mono.txt |
236 | - how to execute Mono-based .NET binaries with the help of BINFMT_MISC. | 238 | - how to execute Mono-based .NET binaries with the help of BINFMT_MISC. |
237 | mutex-design.txt | 239 | mutex-design.txt |
diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt index a99d7031cdf9..45d5a217484f 100644 --- a/Documentation/cpu-hotplug.txt +++ b/Documentation/cpu-hotplug.txt | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | Maintainers: | 3 | Maintainers: |
4 | CPU Hotplug Core: | 4 | CPU Hotplug Core: |
5 | Rusty Russell <rusty@rustycorp.com.au> | 5 | Rusty Russell <rusty@rustcorp.com.au> |
6 | Srivatsa Vaddagiri <vatsa@in.ibm.com> | 6 | Srivatsa Vaddagiri <vatsa@in.ibm.com> |
7 | i386: | 7 | i386: |
8 | Zwane Mwaikambo <zwane@arm.linux.org.uk> | 8 | Zwane Mwaikambo <zwane@arm.linux.org.uk> |
diff --git a/Documentation/devices.txt b/Documentation/devices.txt index f2da781705b2..d0d1df6cb5de 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt | |||
@@ -445,6 +445,7 @@ Your cooperation is appreciated. | |||
445 | 233 = /dev/kmview View-OS A process with a view | 445 | 233 = /dev/kmview View-OS A process with a view |
446 | 234 = /dev/btrfs-control Btrfs control device | 446 | 234 = /dev/btrfs-control Btrfs control device |
447 | 235 = /dev/autofs Autofs control device | 447 | 235 = /dev/autofs Autofs control device |
448 | 236 = /dev/mapper/control Device-Mapper control device | ||
448 | 240-254 Reserved for local use | 449 | 240-254 Reserved for local use |
449 | 255 Reserved for MISC_DYNAMIC_MINOR | 450 | 255 Reserved for MISC_DYNAMIC_MINOR |
450 | 451 | ||
diff --git a/Documentation/i2c/instantiating-devices b/Documentation/i2c/instantiating-devices index e89490270aba..87da405a8597 100644 --- a/Documentation/i2c/instantiating-devices +++ b/Documentation/i2c/instantiating-devices | |||
@@ -102,7 +102,7 @@ static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev) | |||
102 | memset(&i2c_info, 0, sizeof(struct i2c_board_info)); | 102 | memset(&i2c_info, 0, sizeof(struct i2c_board_info)); |
103 | strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE); | 103 | strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE); |
104 | isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info, | 104 | isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info, |
105 | normal_i2c); | 105 | normal_i2c, NULL); |
106 | i2c_put_adapter(i2c_adap); | 106 | i2c_put_adapter(i2c_adap); |
107 | (...) | 107 | (...) |
108 | } | 108 | } |
diff --git a/Documentation/mmc/00-INDEX b/Documentation/mmc/00-INDEX new file mode 100644 index 000000000000..fca586f5b853 --- /dev/null +++ b/Documentation/mmc/00-INDEX | |||
@@ -0,0 +1,4 @@ | |||
1 | 00-INDEX | ||
2 | - this file | ||
3 | mmc-dev-attrs.txt | ||
4 | - info on SD and MMC device attributes | ||
diff --git a/Documentation/mmc/mmc-dev-attrs.txt b/Documentation/mmc/mmc-dev-attrs.txt new file mode 100644 index 000000000000..ff2bd685bced --- /dev/null +++ b/Documentation/mmc/mmc-dev-attrs.txt | |||
@@ -0,0 +1,56 @@ | |||
1 | SD and MMC Device Attributes | ||
2 | ============================ | ||
3 | |||
4 | All attributes are read-only. | ||
5 | |||
6 | cid Card Identifaction Register | ||
7 | csd Card Specific Data Register | ||
8 | scr SD Card Configuration Register (SD only) | ||
9 | date Manufacturing Date (from CID Register) | ||
10 | fwrev Firmware/Product Revision (from CID Register) (SD and MMCv1 only) | ||
11 | hwrev Hardware/Product Revision (from CID Register) (SD and MMCv1 only) | ||
12 | manfid Manufacturer ID (from CID Register) | ||
13 | name Product Name (from CID Register) | ||
14 | oemid OEM/Application ID (from CID Register) | ||
15 | serial Product Serial Number (from CID Register) | ||
16 | erase_size Erase group size | ||
17 | preferred_erase_size Preferred erase size | ||
18 | |||
19 | Note on Erase Size and Preferred Erase Size: | ||
20 | |||
21 | "erase_size" is the minimum size, in bytes, of an erase | ||
22 | operation. For MMC, "erase_size" is the erase group size | ||
23 | reported by the card. Note that "erase_size" does not apply | ||
24 | to trim or secure trim operations where the minimum size is | ||
25 | always one 512 byte sector. For SD, "erase_size" is 512 | ||
26 | if the card is block-addressed, 0 otherwise. | ||
27 | |||
28 | SD/MMC cards can erase an arbitrarily large area up to and | ||
29 | including the whole card. When erasing a large area it may | ||
30 | be desirable to do it in smaller chunks for three reasons: | ||
31 | 1. A single erase command will make all other I/O on | ||
32 | the card wait. This is not a problem if the whole card | ||
33 | is being erased, but erasing one partition will make | ||
34 | I/O for another partition on the same card wait for the | ||
35 | duration of the erase - which could be a several | ||
36 | minutes. | ||
37 | 2. To be able to inform the user of erase progress. | ||
38 | 3. The erase timeout becomes too large to be very | ||
39 | useful. Because the erase timeout contains a margin | ||
40 | which is multiplied by the size of the erase area, | ||
41 | the value can end up being several minutes for large | ||
42 | areas. | ||
43 | |||
44 | "erase_size" is not the most efficient unit to erase | ||
45 | (especially for SD where it is just one sector), | ||
46 | hence "preferred_erase_size" provides a good chunk | ||
47 | size for erasing large areas. | ||
48 | |||
49 | For MMC, "preferred_erase_size" is the high-capacity | ||
50 | erase size if a card specifies one, otherwise it is | ||
51 | based on the capacity of the card. | ||
52 | |||
53 | For SD, "preferred_erase_size" is the allocation unit | ||
54 | size specified by the card. | ||
55 | |||
56 | "preferred_erase_size" is in bytes. | ||
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 03771d7c5dd7..ce46fa1e643e 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt | |||
@@ -83,8 +83,8 @@ ALC269 | |||
83 | ====== | 83 | ====== |
84 | basic Basic preset | 84 | basic Basic preset |
85 | quanta Quanta FL1 | 85 | quanta Quanta FL1 |
86 | eeepc-p703 ASUS Eeepc P703 P900A | 86 | laptop-amic Laptops with analog-mic input |
87 | eeepc-p901 ASUS Eeepc P901 S101 | 87 | laptop-dmic Laptops with digital-mic input |
88 | fujitsu FSC Amilo | 88 | fujitsu FSC Amilo |
89 | lifebook Fujitsu Lifebook S6420 | 89 | lifebook Fujitsu Lifebook S6420 |
90 | auto auto-config reading BIOS (default) | 90 | auto auto-config reading BIOS (default) |
@@ -109,6 +109,8 @@ ALC662/663/272 | |||
109 | asus-mode4 ASUS | 109 | asus-mode4 ASUS |
110 | asus-mode5 ASUS | 110 | asus-mode5 ASUS |
111 | asus-mode6 ASUS | 111 | asus-mode6 ASUS |
112 | asus-mode7 ASUS | ||
113 | asus-mode8 ASUS | ||
112 | dell Dell with ALC272 | 114 | dell Dell with ALC272 |
113 | dell-zm1 Dell ZM1 with ALC272 | 115 | dell-zm1 Dell ZM1 with ALC272 |
114 | samsung-nc10 Samsung NC10 mini notebook | 116 | samsung-nc10 Samsung NC10 mini notebook |
@@ -295,8 +297,10 @@ Conexant 5066 | |||
295 | ============= | 297 | ============= |
296 | laptop Basic Laptop config (default) | 298 | laptop Basic Laptop config (default) |
297 | dell-laptop Dell laptops | 299 | dell-laptop Dell laptops |
300 | dell-vostro Dell Vostro | ||
298 | olpc-xo-1_5 OLPC XO 1.5 | 301 | olpc-xo-1_5 OLPC XO 1.5 |
299 | ideapad Lenovo IdeaPad U150 | 302 | ideapad Lenovo IdeaPad U150 |
303 | thinkpad Lenovo Thinkpad | ||
300 | 304 | ||
301 | STAC9200 | 305 | STAC9200 |
302 | ======== | 306 | ======== |
@@ -404,6 +408,7 @@ STAC92HD83* | |||
404 | mic-ref Reference board with power management for ports | 408 | mic-ref Reference board with power management for ports |
405 | dell-s14 Dell laptop | 409 | dell-s14 Dell laptop |
406 | hp HP laptops with (inverted) mute-LED | 410 | hp HP laptops with (inverted) mute-LED |
411 | hp-dv7-4000 HP dv-7 4000 | ||
407 | auto BIOS setup (default) | 412 | auto BIOS setup (default) |
408 | 413 | ||
409 | STAC9872 | 414 | STAC9872 |
@@ -416,3 +421,7 @@ Cirrus Logic CS4206/4207 | |||
416 | mbp55 MacBook Pro 5,5 | 421 | mbp55 MacBook Pro 5,5 |
417 | imac27 IMac 27 Inch | 422 | imac27 IMac 27 Inch |
418 | auto BIOS setup (default) | 423 | auto BIOS setup (default) |
424 | |||
425 | VIA VT17xx/VT18xx/VT20xx | ||
426 | ======================== | ||
427 | auto BIOS setup (default) | ||
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile index 7ff8020d4d24..704610648a25 100644 --- a/arch/arm/mach-msm/Makefile +++ b/arch/arm/mach-msm/Makefile | |||
@@ -15,7 +15,7 @@ obj-$(CONFIG_ARCH_QSD8X50) += sirc.o | |||
15 | obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o | 15 | obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o |
16 | obj-$(CONFIG_MSM_SMD) += last_radio_log.o | 16 | obj-$(CONFIG_MSM_SMD) += last_radio_log.o |
17 | 17 | ||
18 | obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o devices-msm7x00.o | 18 | obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o devices-msm7x00.o |
19 | obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o | 19 | obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o |
20 | obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o | 20 | obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o |
21 | obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o | 21 | obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o |
diff --git a/arch/arm/mach-msm/acpuclock-arm11.c b/arch/arm/mach-msm/acpuclock-arm11.c index f060a3959a75..7ffbd987eb5d 100644 --- a/arch/arm/mach-msm/acpuclock-arm11.c +++ b/arch/arm/mach-msm/acpuclock-arm11.c | |||
@@ -17,7 +17,6 @@ | |||
17 | * | 17 | * |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/version.h> | ||
21 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
22 | #include <linux/init.h> | 21 | #include <linux/init.h> |
23 | #include <linux/list.h> | 22 | #include <linux/list.h> |
diff --git a/arch/arm/mach-msm/board-trout-gpio.c b/arch/arm/mach-msm/board-trout-gpio.c index 523d213bf79e..c50f3afc3134 100644 --- a/arch/arm/mach-msm/board-trout-gpio.c +++ b/arch/arm/mach-msm/board-trout-gpio.c | |||
@@ -15,10 +15,20 @@ | |||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/irq.h> | 17 | #include <linux/irq.h> |
18 | #include <linux/interrupt.h> | ||
18 | #include <linux/gpio.h> | 19 | #include <linux/gpio.h> |
19 | 20 | ||
20 | #include "board-trout.h" | 21 | #include "board-trout.h" |
21 | 22 | ||
23 | static uint8_t trout_int_mask[2] = { | ||
24 | [0] = 0xff, /* mask all interrupts */ | ||
25 | [1] = 0xff, | ||
26 | }; | ||
27 | static uint8_t trout_sleep_int_mask[] = { | ||
28 | [0] = 0xff, | ||
29 | [1] = 0xff, | ||
30 | }; | ||
31 | |||
22 | struct msm_gpio_chip { | 32 | struct msm_gpio_chip { |
23 | struct gpio_chip chip; | 33 | struct gpio_chip chip; |
24 | void __iomem *reg; /* Base of register bank */ | 34 | void __iomem *reg; /* Base of register bank */ |
@@ -95,16 +105,121 @@ static struct msm_gpio_chip msm_gpio_banks[] = { | |||
95 | TROUT_GPIO_BANK("VIRTUAL", 0x12, TROUT_GPIO_VIRTUAL_BASE, 0), | 105 | TROUT_GPIO_BANK("VIRTUAL", 0x12, TROUT_GPIO_VIRTUAL_BASE, 0), |
96 | }; | 106 | }; |
97 | 107 | ||
108 | static void trout_gpio_irq_ack(unsigned int irq) | ||
109 | { | ||
110 | int bank = TROUT_INT_TO_BANK(irq); | ||
111 | uint8_t mask = TROUT_INT_TO_MASK(irq); | ||
112 | int reg = TROUT_BANK_TO_STAT_REG(bank); | ||
113 | /*printk(KERN_INFO "trout_gpio_irq_ack irq %d\n", irq);*/ | ||
114 | writeb(mask, TROUT_CPLD_BASE + reg); | ||
115 | } | ||
116 | |||
117 | static void trout_gpio_irq_mask(unsigned int irq) | ||
118 | { | ||
119 | unsigned long flags; | ||
120 | uint8_t reg_val; | ||
121 | int bank = TROUT_INT_TO_BANK(irq); | ||
122 | uint8_t mask = TROUT_INT_TO_MASK(irq); | ||
123 | int reg = TROUT_BANK_TO_MASK_REG(bank); | ||
124 | |||
125 | local_irq_save(flags); | ||
126 | reg_val = trout_int_mask[bank] |= mask; | ||
127 | /*printk(KERN_INFO "trout_gpio_irq_mask irq %d => %d:%02x\n", | ||
128 | irq, bank, reg_val);*/ | ||
129 | writeb(reg_val, TROUT_CPLD_BASE + reg); | ||
130 | local_irq_restore(flags); | ||
131 | } | ||
132 | |||
133 | static void trout_gpio_irq_unmask(unsigned int irq) | ||
134 | { | ||
135 | unsigned long flags; | ||
136 | uint8_t reg_val; | ||
137 | int bank = TROUT_INT_TO_BANK(irq); | ||
138 | uint8_t mask = TROUT_INT_TO_MASK(irq); | ||
139 | int reg = TROUT_BANK_TO_MASK_REG(bank); | ||
140 | |||
141 | local_irq_save(flags); | ||
142 | reg_val = trout_int_mask[bank] &= ~mask; | ||
143 | /*printk(KERN_INFO "trout_gpio_irq_unmask irq %d => %d:%02x\n", | ||
144 | irq, bank, reg_val);*/ | ||
145 | writeb(reg_val, TROUT_CPLD_BASE + reg); | ||
146 | local_irq_restore(flags); | ||
147 | } | ||
148 | |||
149 | int trout_gpio_irq_set_wake(unsigned int irq, unsigned int on) | ||
150 | { | ||
151 | unsigned long flags; | ||
152 | int bank = TROUT_INT_TO_BANK(irq); | ||
153 | uint8_t mask = TROUT_INT_TO_MASK(irq); | ||
154 | |||
155 | local_irq_save(flags); | ||
156 | if(on) | ||
157 | trout_sleep_int_mask[bank] &= ~mask; | ||
158 | else | ||
159 | trout_sleep_int_mask[bank] |= mask; | ||
160 | local_irq_restore(flags); | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static void trout_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | ||
165 | { | ||
166 | int j, m; | ||
167 | unsigned v; | ||
168 | int bank; | ||
169 | int stat_reg; | ||
170 | int int_base = TROUT_INT_START; | ||
171 | uint8_t int_mask; | ||
172 | |||
173 | for (bank = 0; bank < 2; bank++) { | ||
174 | stat_reg = TROUT_BANK_TO_STAT_REG(bank); | ||
175 | v = readb(TROUT_CPLD_BASE + stat_reg); | ||
176 | int_mask = trout_int_mask[bank]; | ||
177 | if (v & int_mask) { | ||
178 | writeb(v & int_mask, TROUT_CPLD_BASE + stat_reg); | ||
179 | printk(KERN_ERR "trout_gpio_irq_handler: got masked " | ||
180 | "interrupt: %d:%02x\n", bank, v & int_mask); | ||
181 | } | ||
182 | v &= ~int_mask; | ||
183 | while (v) { | ||
184 | m = v & -v; | ||
185 | j = fls(m) - 1; | ||
186 | /*printk(KERN_INFO "msm_gpio_irq_handler %d:%02x %02x b" | ||
187 | "it %d irq %d\n", bank, v, m, j, int_base + j);*/ | ||
188 | v &= ~m; | ||
189 | generic_handle_irq(int_base + j); | ||
190 | } | ||
191 | int_base += TROUT_INT_BANK0_COUNT; | ||
192 | } | ||
193 | desc->chip->ack(irq); | ||
194 | } | ||
195 | |||
196 | static struct irq_chip trout_gpio_irq_chip = { | ||
197 | .name = "troutgpio", | ||
198 | .ack = trout_gpio_irq_ack, | ||
199 | .mask = trout_gpio_irq_mask, | ||
200 | .unmask = trout_gpio_irq_unmask, | ||
201 | .set_wake = trout_gpio_irq_set_wake, | ||
202 | }; | ||
203 | |||
98 | /* | 204 | /* |
99 | * Called from the processor-specific init to enable GPIO pin support. | 205 | * Called from the processor-specific init to enable GPIO pin support. |
100 | */ | 206 | */ |
101 | int __init trout_init_gpio(void) | 207 | int __init trout_init_gpio(void) |
102 | { | 208 | { |
103 | int i; | 209 | int i; |
210 | for(i = TROUT_INT_START; i <= TROUT_INT_END; i++) { | ||
211 | set_irq_chip(i, &trout_gpio_irq_chip); | ||
212 | set_irq_handler(i, handle_edge_irq); | ||
213 | set_irq_flags(i, IRQF_VALID); | ||
214 | } | ||
104 | 215 | ||
105 | for (i = 0; i < ARRAY_SIZE(msm_gpio_banks); i++) | 216 | for (i = 0; i < ARRAY_SIZE(msm_gpio_banks); i++) |
106 | gpiochip_add(&msm_gpio_banks[i].chip); | 217 | gpiochip_add(&msm_gpio_banks[i].chip); |
107 | 218 | ||
219 | set_irq_type(MSM_GPIO_TO_INT(17), IRQF_TRIGGER_HIGH); | ||
220 | set_irq_chained_handler(MSM_GPIO_TO_INT(17), trout_gpio_irq_handler); | ||
221 | set_irq_wake(MSM_GPIO_TO_INT(17), 1); | ||
222 | |||
108 | return 0; | 223 | return 0; |
109 | } | 224 | } |
110 | 225 | ||
diff --git a/arch/arm/mach-msm/board-trout-mmc.c b/arch/arm/mach-msm/board-trout-mmc.c new file mode 100644 index 000000000000..44be8464657b --- /dev/null +++ b/arch/arm/mach-msm/board-trout-mmc.c | |||
@@ -0,0 +1,186 @@ | |||
1 | /* linux/arch/arm/mach-msm/board-trout-mmc.c | ||
2 | ** Author: Brian Swetland <swetland@google.com> | ||
3 | */ | ||
4 | |||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/init.h> | ||
7 | #include <linux/platform_device.h> | ||
8 | #include <linux/delay.h> | ||
9 | #include <linux/mmc/host.h> | ||
10 | #include <linux/mmc/sdio_ids.h> | ||
11 | #include <linux/err.h> | ||
12 | #include <linux/debugfs.h> | ||
13 | |||
14 | #include <asm/gpio.h> | ||
15 | #include <asm/io.h> | ||
16 | |||
17 | #include <mach/vreg.h> | ||
18 | |||
19 | #include <mach/mmc.h> | ||
20 | |||
21 | #include "devices.h" | ||
22 | |||
23 | #include "board-trout.h" | ||
24 | |||
25 | #include "proc_comm.h" | ||
26 | |||
27 | #define DEBUG_SDSLOT_VDD 1 | ||
28 | |||
29 | /* ---- COMMON ---- */ | ||
30 | static void config_gpio_table(uint32_t *table, int len) | ||
31 | { | ||
32 | int n; | ||
33 | unsigned id; | ||
34 | for(n = 0; n < len; n++) { | ||
35 | id = table[n]; | ||
36 | msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &id, 0); | ||
37 | } | ||
38 | } | ||
39 | |||
40 | /* ---- SDCARD ---- */ | ||
41 | |||
42 | static uint32_t sdcard_on_gpio_table[] = { | ||
43 | PCOM_GPIO_CFG(62, 2, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_8MA), /* CLK */ | ||
44 | PCOM_GPIO_CFG(63, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_8MA), /* CMD */ | ||
45 | PCOM_GPIO_CFG(64, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_8MA), /* DAT3 */ | ||
46 | PCOM_GPIO_CFG(65, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_8MA), /* DAT2 */ | ||
47 | PCOM_GPIO_CFG(66, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_4MA), /* DAT1 */ | ||
48 | PCOM_GPIO_CFG(67, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_4MA), /* DAT0 */ | ||
49 | }; | ||
50 | |||
51 | static uint32_t sdcard_off_gpio_table[] = { | ||
52 | PCOM_GPIO_CFG(62, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* CLK */ | ||
53 | PCOM_GPIO_CFG(63, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* CMD */ | ||
54 | PCOM_GPIO_CFG(64, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* DAT3 */ | ||
55 | PCOM_GPIO_CFG(65, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* DAT2 */ | ||
56 | PCOM_GPIO_CFG(66, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* DAT1 */ | ||
57 | PCOM_GPIO_CFG(67, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* DAT0 */ | ||
58 | }; | ||
59 | |||
60 | static uint opt_disable_sdcard; | ||
61 | |||
62 | static int __init trout_disablesdcard_setup(char *str) | ||
63 | { | ||
64 | int cal = simple_strtol(str, NULL, 0); | ||
65 | |||
66 | opt_disable_sdcard = cal; | ||
67 | return 1; | ||
68 | } | ||
69 | |||
70 | __setup("board_trout.disable_sdcard=", trout_disablesdcard_setup); | ||
71 | |||
72 | static struct vreg *vreg_sdslot; /* SD slot power */ | ||
73 | |||
74 | struct mmc_vdd_xlat { | ||
75 | int mask; | ||
76 | int level; | ||
77 | }; | ||
78 | |||
79 | static struct mmc_vdd_xlat mmc_vdd_table[] = { | ||
80 | { MMC_VDD_165_195, 1800 }, | ||
81 | { MMC_VDD_20_21, 2050 }, | ||
82 | { MMC_VDD_21_22, 2150 }, | ||
83 | { MMC_VDD_22_23, 2250 }, | ||
84 | { MMC_VDD_23_24, 2350 }, | ||
85 | { MMC_VDD_24_25, 2450 }, | ||
86 | { MMC_VDD_25_26, 2550 }, | ||
87 | { MMC_VDD_26_27, 2650 }, | ||
88 | { MMC_VDD_27_28, 2750 }, | ||
89 | { MMC_VDD_28_29, 2850 }, | ||
90 | { MMC_VDD_29_30, 2950 }, | ||
91 | }; | ||
92 | |||
93 | static unsigned int sdslot_vdd = 0xffffffff; | ||
94 | static unsigned int sdslot_vreg_enabled; | ||
95 | |||
96 | static uint32_t trout_sdslot_switchvdd(struct device *dev, unsigned int vdd) | ||
97 | { | ||
98 | int i, rc; | ||
99 | |||
100 | BUG_ON(!vreg_sdslot); | ||
101 | |||
102 | if (vdd == sdslot_vdd) | ||
103 | return 0; | ||
104 | |||
105 | sdslot_vdd = vdd; | ||
106 | |||
107 | if (vdd == 0) { | ||
108 | #if DEBUG_SDSLOT_VDD | ||
109 | printk("%s: Disabling SD slot power\n", __func__); | ||
110 | #endif | ||
111 | config_gpio_table(sdcard_off_gpio_table, | ||
112 | ARRAY_SIZE(sdcard_off_gpio_table)); | ||
113 | vreg_disable(vreg_sdslot); | ||
114 | sdslot_vreg_enabled = 0; | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | if (!sdslot_vreg_enabled) { | ||
119 | rc = vreg_enable(vreg_sdslot); | ||
120 | if (rc) { | ||
121 | printk(KERN_ERR "%s: Error enabling vreg (%d)\n", | ||
122 | __func__, rc); | ||
123 | } | ||
124 | config_gpio_table(sdcard_on_gpio_table, | ||
125 | ARRAY_SIZE(sdcard_on_gpio_table)); | ||
126 | sdslot_vreg_enabled = 1; | ||
127 | } | ||
128 | |||
129 | for (i = 0; i < ARRAY_SIZE(mmc_vdd_table); i++) { | ||
130 | if (mmc_vdd_table[i].mask == (1 << vdd)) { | ||
131 | #if DEBUG_SDSLOT_VDD | ||
132 | printk("%s: Setting level to %u\n", | ||
133 | __func__, mmc_vdd_table[i].level); | ||
134 | #endif | ||
135 | rc = vreg_set_level(vreg_sdslot, | ||
136 | mmc_vdd_table[i].level); | ||
137 | if (rc) { | ||
138 | printk(KERN_ERR | ||
139 | "%s: Error setting vreg level (%d)\n", | ||
140 | __func__, rc); | ||
141 | } | ||
142 | return 0; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | printk(KERN_ERR "%s: Invalid VDD %d specified\n", __func__, vdd); | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static unsigned int trout_sdslot_status(struct device *dev) | ||
151 | { | ||
152 | unsigned int status; | ||
153 | |||
154 | status = (unsigned int) gpio_get_value(TROUT_GPIO_SDMC_CD_N); | ||
155 | return (!status); | ||
156 | } | ||
157 | |||
158 | #define TROUT_MMC_VDD MMC_VDD_165_195 | MMC_VDD_20_21 | MMC_VDD_21_22 \ | ||
159 | | MMC_VDD_22_23 | MMC_VDD_23_24 | MMC_VDD_24_25 \ | ||
160 | | MMC_VDD_25_26 | MMC_VDD_26_27 | MMC_VDD_27_28 \ | ||
161 | | MMC_VDD_28_29 | MMC_VDD_29_30 | ||
162 | |||
163 | static struct msm_mmc_platform_data trout_sdslot_data = { | ||
164 | .ocr_mask = TROUT_MMC_VDD, | ||
165 | .status = trout_sdslot_status, | ||
166 | .translate_vdd = trout_sdslot_switchvdd, | ||
167 | }; | ||
168 | |||
169 | int __init trout_init_mmc(unsigned int sys_rev) | ||
170 | { | ||
171 | sdslot_vreg_enabled = 0; | ||
172 | |||
173 | vreg_sdslot = vreg_get(0, "gp6"); | ||
174 | if (IS_ERR(vreg_sdslot)) | ||
175 | return PTR_ERR(vreg_sdslot); | ||
176 | |||
177 | set_irq_wake(TROUT_GPIO_TO_INT(TROUT_GPIO_SDMC_CD_N), 1); | ||
178 | |||
179 | if (!opt_disable_sdcard) | ||
180 | msm_add_sdcc(2, &trout_sdslot_data, | ||
181 | TROUT_GPIO_TO_INT(TROUT_GPIO_SDMC_CD_N), 0); | ||
182 | else | ||
183 | printk(KERN_INFO "trout: SD-Card interface disabled\n"); | ||
184 | return 0; | ||
185 | } | ||
186 | |||
diff --git a/arch/arm/mach-msm/board-trout.c b/arch/arm/mach-msm/board-trout.c index e69a1502e4e8..469e0be3499d 100644 --- a/arch/arm/mach-msm/board-trout.c +++ b/arch/arm/mach-msm/board-trout.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include "devices.h" | 30 | #include "devices.h" |
31 | #include "board-trout.h" | 31 | #include "board-trout.h" |
32 | 32 | ||
33 | extern int trout_init_mmc(unsigned int); | ||
34 | |||
33 | static struct platform_device *devices[] __initdata = { | 35 | static struct platform_device *devices[] __initdata = { |
34 | &msm_device_uart3, | 36 | &msm_device_uart3, |
35 | &msm_device_smd, | 37 | &msm_device_smd, |
@@ -55,7 +57,16 @@ static void __init trout_fixup(struct machine_desc *desc, struct tag *tags, | |||
55 | 57 | ||
56 | static void __init trout_init(void) | 58 | static void __init trout_init(void) |
57 | { | 59 | { |
60 | int rc; | ||
61 | |||
58 | platform_add_devices(devices, ARRAY_SIZE(devices)); | 62 | platform_add_devices(devices, ARRAY_SIZE(devices)); |
63 | |||
64 | #ifdef CONFIG_MMC | ||
65 | rc = trout_init_mmc(system_rev); | ||
66 | if (rc) | ||
67 | printk(KERN_CRIT "%s: MMC init failure (%d)\n", __func__, rc); | ||
68 | #endif | ||
69 | |||
59 | } | 70 | } |
60 | 71 | ||
61 | static struct map_desc trout_io_desc[] __initdata = { | 72 | static struct map_desc trout_io_desc[] __initdata = { |
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c index 9cb1276ab749..c57210f4f06a 100644 --- a/arch/arm/mach-msm/clock.c +++ b/arch/arm/mach-msm/clock.c | |||
@@ -14,7 +14,6 @@ | |||
14 | * | 14 | * |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/version.h> | ||
18 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
19 | #include <linux/init.h> | 18 | #include <linux/init.h> |
20 | #include <linux/module.h> | 19 | #include <linux/module.h> |
diff --git a/arch/arm/mach-msm/devices-msm7x00.c b/arch/arm/mach-msm/devices-msm7x00.c index fde9d8f69f10..4e8c0bcdc92d 100644 --- a/arch/arm/mach-msm/devices-msm7x00.c +++ b/arch/arm/mach-msm/devices-msm7x00.c | |||
@@ -322,7 +322,8 @@ static struct platform_device *msm_sdcc_devices[] __initdata = { | |||
322 | &msm_device_sdc4, | 322 | &msm_device_sdc4, |
323 | }; | 323 | }; |
324 | 324 | ||
325 | int __init msm_add_sdcc(unsigned int controller, struct mmc_platform_data *plat, | 325 | int __init msm_add_sdcc(unsigned int controller, |
326 | struct msm_mmc_platform_data *plat, | ||
326 | unsigned int stat_irq, unsigned long stat_irq_flags) | 327 | unsigned int stat_irq, unsigned long stat_irq_flags) |
327 | { | 328 | { |
328 | struct platform_device *pdev; | 329 | struct platform_device *pdev; |
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h index e302fbdc439b..5a79bcf50413 100644 --- a/arch/arm/mach-msm/include/mach/board.h +++ b/arch/arm/mach-msm/include/mach/board.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #define __ASM_ARCH_MSM_BOARD_H | 18 | #define __ASM_ARCH_MSM_BOARD_H |
19 | 19 | ||
20 | #include <linux/types.h> | 20 | #include <linux/types.h> |
21 | #include <mach/mmc.h> | ||
21 | 22 | ||
22 | /* platform device data structures */ | 23 | /* platform device data structures */ |
23 | 24 | ||
@@ -40,5 +41,8 @@ void __init msm_init_irq(void); | |||
40 | void __init msm_init_gpio(void); | 41 | void __init msm_init_gpio(void); |
41 | void __init msm_clock_init(struct clk *clock_tbl, unsigned num_clocks); | 42 | void __init msm_clock_init(struct clk *clock_tbl, unsigned num_clocks); |
42 | void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *); | 43 | void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *); |
44 | int __init msm_add_sdcc(unsigned int controller, | ||
45 | struct msm_mmc_platform_data *plat, | ||
46 | unsigned int stat_irq, unsigned long stat_irq_flags); | ||
43 | 47 | ||
44 | #endif | 48 | #endif |
diff --git a/arch/arm/mach-msm/include/mach/mmc.h b/arch/arm/mach-msm/include/mach/mmc.h index 0ecf25426284..d54b6b086cff 100644 --- a/arch/arm/mach-msm/include/mach/mmc.h +++ b/arch/arm/mach-msm/include/mach/mmc.h | |||
@@ -15,7 +15,7 @@ struct embedded_sdio_data { | |||
15 | int num_funcs; | 15 | int num_funcs; |
16 | }; | 16 | }; |
17 | 17 | ||
18 | struct mmc_platform_data { | 18 | struct msm_mmc_platform_data { |
19 | unsigned int ocr_mask; /* available voltages */ | 19 | unsigned int ocr_mask; /* available voltages */ |
20 | u32 (*translate_vdd)(struct device *, unsigned int); | 20 | u32 (*translate_vdd)(struct device *, unsigned int); |
21 | unsigned int (*status)(struct device *); | 21 | unsigned int (*status)(struct device *); |
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c index cf11d414b425..f07dc7c738f0 100644 --- a/arch/arm/mach-msm/smd.c +++ b/arch/arm/mach-msm/smd.c | |||
@@ -997,7 +997,7 @@ int smd_core_init(void) | |||
997 | return 0; | 997 | return 0; |
998 | } | 998 | } |
999 | 999 | ||
1000 | static int __init msm_smd_probe(struct platform_device *pdev) | 1000 | static int __devinit msm_smd_probe(struct platform_device *pdev) |
1001 | { | 1001 | { |
1002 | pr_info("smd_init()\n"); | 1002 | pr_info("smd_init()\n"); |
1003 | 1003 | ||
diff --git a/arch/cris/include/asm/pgtable.h b/arch/cris/include/asm/pgtable.h index 99ea6cd1b143..f63d6fccbc6c 100644 --- a/arch/cris/include/asm/pgtable.h +++ b/arch/cris/include/asm/pgtable.h | |||
@@ -260,6 +260,9 @@ static inline pgd_t * pgd_offset(const struct mm_struct *mm, unsigned long addre | |||
260 | #define pgd_ERROR(e) \ | 260 | #define pgd_ERROR(e) \ |
261 | printk("%s:%d: bad pgd %p(%08lx).\n", __FILE__, __LINE__, &(e), pgd_val(e)) | 261 | printk("%s:%d: bad pgd %p(%08lx).\n", __FILE__, __LINE__, &(e), pgd_val(e)) |
262 | 262 | ||
263 | #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ | ||
264 | remap_pfn_range(vma, vaddr, pfn, size, prot) | ||
265 | |||
263 | 266 | ||
264 | extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* defined in head.S */ | 267 | extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* defined in head.S */ |
265 | 268 | ||
diff --git a/arch/ia64/include/asm/rwsem.h b/arch/ia64/include/asm/rwsem.h index e8762688e8e3..215d5454c7d3 100644 --- a/arch/ia64/include/asm/rwsem.h +++ b/arch/ia64/include/asm/rwsem.h | |||
@@ -40,9 +40,9 @@ struct rw_semaphore { | |||
40 | }; | 40 | }; |
41 | 41 | ||
42 | #define RWSEM_UNLOCKED_VALUE __IA64_UL_CONST(0x0000000000000000) | 42 | #define RWSEM_UNLOCKED_VALUE __IA64_UL_CONST(0x0000000000000000) |
43 | #define RWSEM_ACTIVE_BIAS __IA64_UL_CONST(0x0000000000000001) | 43 | #define RWSEM_ACTIVE_BIAS (1L) |
44 | #define RWSEM_ACTIVE_MASK __IA64_UL_CONST(0x00000000ffffffff) | 44 | #define RWSEM_ACTIVE_MASK (0xffffffffL) |
45 | #define RWSEM_WAITING_BIAS -__IA64_UL_CONST(0x0000000100000000) | 45 | #define RWSEM_WAITING_BIAS (-0x100000000L) |
46 | #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS | 46 | #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS |
47 | #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) | 47 | #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) |
48 | 48 | ||
diff --git a/arch/mn10300/boot/compressed/misc.c b/arch/mn10300/boot/compressed/misc.c index f673383518e4..42cbd77bd439 100644 --- a/arch/mn10300/boot/compressed/misc.c +++ b/arch/mn10300/boot/compressed/misc.c | |||
@@ -167,6 +167,7 @@ static uch *high_buffer_start /* = (uch *)(((ulg)&end) + HEAP_SIZE)*/; | |||
167 | static char *vidmem = (char *)0xb8000; | 167 | static char *vidmem = (char *)0xb8000; |
168 | static int lines, cols; | 168 | static int lines, cols; |
169 | 169 | ||
170 | #define BOOTLOADER_INFLATE | ||
170 | #include "../../../../lib/inflate.c" | 171 | #include "../../../../lib/inflate.c" |
171 | 172 | ||
172 | static inline void scroll(void) | 173 | static inline void scroll(void) |
diff --git a/arch/mn10300/include/asm/gdb-stub.h b/arch/mn10300/include/asm/gdb-stub.h index 556cce992548..41ed26763964 100644 --- a/arch/mn10300/include/asm/gdb-stub.h +++ b/arch/mn10300/include/asm/gdb-stub.h | |||
@@ -157,25 +157,25 @@ void gdbstub_printk(const char *fmt, ...) | |||
157 | #ifdef CONFIG_GDBSTUB_DEBUG_ENTRY | 157 | #ifdef CONFIG_GDBSTUB_DEBUG_ENTRY |
158 | #define gdbstub_entry(FMT, ...) gdbstub_printk(FMT, ##__VA_ARGS__) | 158 | #define gdbstub_entry(FMT, ...) gdbstub_printk(FMT, ##__VA_ARGS__) |
159 | #else | 159 | #else |
160 | #define gdbstub_entry(FMT, ...) ({ 0; }) | 160 | #define gdbstub_entry(FMT, ...) no_printk(FMT, ##__VA_ARGS__) |
161 | #endif | 161 | #endif |
162 | 162 | ||
163 | #ifdef CONFIG_GDBSTUB_DEBUG_PROTOCOL | 163 | #ifdef CONFIG_GDBSTUB_DEBUG_PROTOCOL |
164 | #define gdbstub_proto(FMT, ...) gdbstub_printk(FMT, ##__VA_ARGS__) | 164 | #define gdbstub_proto(FMT, ...) gdbstub_printk(FMT, ##__VA_ARGS__) |
165 | #else | 165 | #else |
166 | #define gdbstub_proto(FMT, ...) ({ 0; }) | 166 | #define gdbstub_proto(FMT, ...) no_printk(FMT, ##__VA_ARGS__) |
167 | #endif | 167 | #endif |
168 | 168 | ||
169 | #ifdef CONFIG_GDBSTUB_DEBUG_IO | 169 | #ifdef CONFIG_GDBSTUB_DEBUG_IO |
170 | #define gdbstub_io(FMT, ...) gdbstub_printk(FMT, ##__VA_ARGS__) | 170 | #define gdbstub_io(FMT, ...) gdbstub_printk(FMT, ##__VA_ARGS__) |
171 | #else | 171 | #else |
172 | #define gdbstub_io(FMT, ...) ({ 0; }) | 172 | #define gdbstub_io(FMT, ...) no_printk(FMT, ##__VA_ARGS__) |
173 | #endif | 173 | #endif |
174 | 174 | ||
175 | #ifdef CONFIG_GDBSTUB_DEBUG_BREAKPOINT | 175 | #ifdef CONFIG_GDBSTUB_DEBUG_BREAKPOINT |
176 | #define gdbstub_bkpt(FMT, ...) gdbstub_printk(FMT, ##__VA_ARGS__) | 176 | #define gdbstub_bkpt(FMT, ...) gdbstub_printk(FMT, ##__VA_ARGS__) |
177 | #else | 177 | #else |
178 | #define gdbstub_bkpt(FMT, ...) ({ 0; }) | 178 | #define gdbstub_bkpt(FMT, ...) no_printk(FMT, ##__VA_ARGS__) |
179 | #endif | 179 | #endif |
180 | 180 | ||
181 | #endif /* !__ASSEMBLY__ */ | 181 | #endif /* !__ASSEMBLY__ */ |
diff --git a/arch/mn10300/include/asm/posix_types.h b/arch/mn10300/include/asm/posix_types.h index 077567c37798..56ffbc158798 100644 --- a/arch/mn10300/include/asm/posix_types.h +++ b/arch/mn10300/include/asm/posix_types.h | |||
@@ -25,8 +25,13 @@ typedef int __kernel_pid_t; | |||
25 | typedef unsigned short __kernel_ipc_pid_t; | 25 | typedef unsigned short __kernel_ipc_pid_t; |
26 | typedef unsigned short __kernel_uid_t; | 26 | typedef unsigned short __kernel_uid_t; |
27 | typedef unsigned short __kernel_gid_t; | 27 | typedef unsigned short __kernel_gid_t; |
28 | #if __GNUC__ == 4 | ||
29 | typedef unsigned int __kernel_size_t; | ||
30 | typedef signed int __kernel_ssize_t; | ||
31 | #else | ||
28 | typedef unsigned long __kernel_size_t; | 32 | typedef unsigned long __kernel_size_t; |
29 | typedef long __kernel_ssize_t; | 33 | typedef signed long __kernel_ssize_t; |
34 | #endif | ||
30 | typedef int __kernel_ptrdiff_t; | 35 | typedef int __kernel_ptrdiff_t; |
31 | typedef long __kernel_time_t; | 36 | typedef long __kernel_time_t; |
32 | typedef long __kernel_suseconds_t; | 37 | typedef long __kernel_suseconds_t; |
diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c index ef34d5a0f8bd..9d49073e827a 100644 --- a/arch/mn10300/kernel/mn10300-serial.c +++ b/arch/mn10300/kernel/mn10300-serial.c | |||
@@ -44,11 +44,6 @@ static const char serial_revdate[] = "2007-11-06"; | |||
44 | #include <unit/timex.h> | 44 | #include <unit/timex.h> |
45 | #include "mn10300-serial.h" | 45 | #include "mn10300-serial.h" |
46 | 46 | ||
47 | static inline __attribute__((format(printf, 1, 2))) | ||
48 | void no_printk(const char *fmt, ...) | ||
49 | { | ||
50 | } | ||
51 | |||
52 | #define kenter(FMT, ...) \ | 47 | #define kenter(FMT, ...) \ |
53 | printk(KERN_DEBUG "-->%s(" FMT ")\n", __func__, ##__VA_ARGS__) | 48 | printk(KERN_DEBUG "-->%s(" FMT ")\n", __func__, ##__VA_ARGS__) |
54 | #define _enter(FMT, ...) \ | 49 | #define _enter(FMT, ...) \ |
diff --git a/arch/mn10300/kernel/rtc.c b/arch/mn10300/kernel/rtc.c index 815a933aafa8..4eef0e7224f6 100644 --- a/arch/mn10300/kernel/rtc.c +++ b/arch/mn10300/kernel/rtc.c | |||
@@ -20,9 +20,6 @@ | |||
20 | DEFINE_SPINLOCK(rtc_lock); | 20 | DEFINE_SPINLOCK(rtc_lock); |
21 | EXPORT_SYMBOL(rtc_lock); | 21 | EXPORT_SYMBOL(rtc_lock); |
22 | 22 | ||
23 | /* last time the RTC got updated */ | ||
24 | static long last_rtc_update; | ||
25 | |||
26 | /* time for RTC to update itself in ioclks */ | 23 | /* time for RTC to update itself in ioclks */ |
27 | static unsigned long mn10300_rtc_update_period; | 24 | static unsigned long mn10300_rtc_update_period; |
28 | 25 | ||
@@ -110,7 +107,7 @@ static int set_rtc_mmss(unsigned long nowtime) | |||
110 | 107 | ||
111 | int update_persistent_clock(struct timespec now) | 108 | int update_persistent_clock(struct timespec now) |
112 | { | 109 | { |
113 | return set_rtc_mms(now.tv_sec); | 110 | return set_rtc_mmss(now.tv_sec); |
114 | } | 111 | } |
115 | 112 | ||
116 | /* | 113 | /* |
diff --git a/arch/parisc/mm/ioremap.c b/arch/parisc/mm/ioremap.c index 92d496ad07c9..838d0259cd27 100644 --- a/arch/parisc/mm/ioremap.c +++ b/arch/parisc/mm/ioremap.c | |||
@@ -71,7 +71,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l | |||
71 | */ | 71 | */ |
72 | offset = phys_addr & ~PAGE_MASK; | 72 | offset = phys_addr & ~PAGE_MASK; |
73 | phys_addr &= PAGE_MASK; | 73 | phys_addr &= PAGE_MASK; |
74 | size = PAGE_ALIGN(last_addr) - phys_addr; | 74 | size = PAGE_ALIGN(last_addr + 1) - phys_addr; |
75 | 75 | ||
76 | /* | 76 | /* |
77 | * Ok, go for it.. | 77 | * Ok, go for it.. |
diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c index 51df7e754698..f9751c8905be 100644 --- a/arch/powerpc/platforms/83xx/mpc837x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c | |||
@@ -102,7 +102,7 @@ static struct of_device_id mpc837x_ids[] = { | |||
102 | 102 | ||
103 | static int __init mpc837x_declare_of_platform_devices(void) | 103 | static int __init mpc837x_declare_of_platform_devices(void) |
104 | { | 104 | { |
105 | /* Publish of_device */ | 105 | /* Publish platform_device */ |
106 | of_platform_bus_probe(NULL, mpc837x_ids, NULL); | 106 | of_platform_bus_probe(NULL, mpc837x_ids, NULL); |
107 | 107 | ||
108 | return 0; | 108 | return 0; |
diff --git a/arch/powerpc/platforms/83xx/mpc837x_rdb.c b/arch/powerpc/platforms/83xx/mpc837x_rdb.c index e00801c42540..910caa6b5810 100644 --- a/arch/powerpc/platforms/83xx/mpc837x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc837x_rdb.c | |||
@@ -78,7 +78,7 @@ static struct of_device_id mpc837x_ids[] = { | |||
78 | 78 | ||
79 | static int __init mpc837x_declare_of_platform_devices(void) | 79 | static int __init mpc837x_declare_of_platform_devices(void) |
80 | { | 80 | { |
81 | /* Publish of_device */ | 81 | /* Publish platform_device */ |
82 | of_platform_bus_probe(NULL, mpc837x_ids, NULL); | 82 | of_platform_bus_probe(NULL, mpc837x_ids, NULL); |
83 | 83 | ||
84 | return 0; | 84 | return 0; |
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 8bd86530ee25..6425abe5b7db 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c | |||
@@ -1332,7 +1332,7 @@ static inline void fsl_rio_info(struct device *dev, u32 ccsr) | |||
1332 | 1332 | ||
1333 | /** | 1333 | /** |
1334 | * fsl_rio_setup - Setup Freescale PowerPC RapidIO interface | 1334 | * fsl_rio_setup - Setup Freescale PowerPC RapidIO interface |
1335 | * @dev: of_device pointer | 1335 | * @dev: platform_device pointer |
1336 | * | 1336 | * |
1337 | * Initializes MPC85xx RapidIO hardware interface, configures | 1337 | * Initializes MPC85xx RapidIO hardware interface, configures |
1338 | * master port with system-specific info, and registers the | 1338 | * master port with system-specific info, and registers the |
diff --git a/arch/score/mm/tlb-score.c b/arch/score/mm/tlb-score.c index 4fa5aa5afecc..6fdb100244c8 100644 --- a/arch/score/mm/tlb-score.c +++ b/arch/score/mm/tlb-score.c | |||
@@ -158,7 +158,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) | |||
158 | 158 | ||
159 | void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) | 159 | void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) |
160 | { | 160 | { |
161 | if (!vma || vma->vm_mm->context != 0) { | 161 | if (vma && vma->vm_mm->context != 0) { |
162 | unsigned long flags; | 162 | unsigned long flags; |
163 | int oldpid, newpid, idx; | 163 | int oldpid, newpid, idx; |
164 | unsigned long vma_ASID = vma->vm_mm->context; | 164 | unsigned long vma_ASID = vma->vm_mm->context; |
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index 68142df76608..0c46e398cd8f 100644 --- a/arch/um/drivers/hostaudio_kern.c +++ b/arch/um/drivers/hostaudio_kern.c | |||
@@ -187,7 +187,9 @@ static int hostaudio_open(struct inode *inode, struct file *file) | |||
187 | int ret; | 187 | int ret; |
188 | 188 | ||
189 | #ifdef DEBUG | 189 | #ifdef DEBUG |
190 | kparam_block_sysfs_write(dsp); | ||
190 | printk(KERN_DEBUG "hostaudio: open called (host: %s)\n", dsp); | 191 | printk(KERN_DEBUG "hostaudio: open called (host: %s)\n", dsp); |
192 | kparam_unblock_sysfs_write(dsp); | ||
191 | #endif | 193 | #endif |
192 | 194 | ||
193 | state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL); | 195 | state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL); |
@@ -199,9 +201,11 @@ static int hostaudio_open(struct inode *inode, struct file *file) | |||
199 | if (file->f_mode & FMODE_WRITE) | 201 | if (file->f_mode & FMODE_WRITE) |
200 | w = 1; | 202 | w = 1; |
201 | 203 | ||
204 | kparam_block_sysfs_write(dsp); | ||
202 | lock_kernel(); | 205 | lock_kernel(); |
203 | ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); | 206 | ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); |
204 | unlock_kernel(); | 207 | unlock_kernel(); |
208 | kparam_unblock_sysfs_write(dsp); | ||
205 | 209 | ||
206 | if (ret < 0) { | 210 | if (ret < 0) { |
207 | kfree(state); | 211 | kfree(state); |
@@ -258,13 +262,17 @@ static int hostmixer_open_mixdev(struct inode *inode, struct file *file) | |||
258 | if (file->f_mode & FMODE_WRITE) | 262 | if (file->f_mode & FMODE_WRITE) |
259 | w = 1; | 263 | w = 1; |
260 | 264 | ||
265 | kparam_block_sysfs_write(mixer); | ||
261 | lock_kernel(); | 266 | lock_kernel(); |
262 | ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); | 267 | ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); |
263 | unlock_kernel(); | 268 | unlock_kernel(); |
269 | kparam_unblock_sysfs_write(mixer); | ||
264 | 270 | ||
265 | if (ret < 0) { | 271 | if (ret < 0) { |
272 | kparam_block_sysfs_write(dsp); | ||
266 | printk(KERN_ERR "hostaudio_open_mixdev failed to open '%s', " | 273 | printk(KERN_ERR "hostaudio_open_mixdev failed to open '%s', " |
267 | "err = %d\n", dsp, -ret); | 274 | "err = %d\n", dsp, -ret); |
275 | kparam_unblock_sysfs_write(dsp); | ||
268 | kfree(state); | 276 | kfree(state); |
269 | return ret; | 277 | return ret; |
270 | } | 278 | } |
@@ -320,8 +328,10 @@ MODULE_LICENSE("GPL"); | |||
320 | 328 | ||
321 | static int __init hostaudio_init_module(void) | 329 | static int __init hostaudio_init_module(void) |
322 | { | 330 | { |
331 | __kernel_param_lock(); | ||
323 | printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n", | 332 | printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n", |
324 | dsp, mixer); | 333 | dsp, mixer); |
334 | __kernel_param_unlock(); | ||
325 | 335 | ||
326 | module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1); | 336 | module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1); |
327 | if (module_data.dev_audio < 0) { | 337 | if (module_data.dev_audio < 0) { |
diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h index 625c3f0e741a..8ca82839288a 100644 --- a/arch/x86/include/asm/page.h +++ b/arch/x86/include/asm/page.h | |||
@@ -37,6 +37,13 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr, | |||
37 | #define __pa_nodebug(x) __phys_addr_nodebug((unsigned long)(x)) | 37 | #define __pa_nodebug(x) __phys_addr_nodebug((unsigned long)(x)) |
38 | /* __pa_symbol should be used for C visible symbols. | 38 | /* __pa_symbol should be used for C visible symbols. |
39 | This seems to be the official gcc blessed way to do such arithmetic. */ | 39 | This seems to be the official gcc blessed way to do such arithmetic. */ |
40 | /* | ||
41 | * We need __phys_reloc_hide() here because gcc may assume that there is no | ||
42 | * overflow during __pa() calculation and can optimize it unexpectedly. | ||
43 | * Newer versions of gcc provide -fno-strict-overflow switch to handle this | ||
44 | * case properly. Once all supported versions of gcc understand it, we can | ||
45 | * remove this Voodoo magic stuff. (i.e. once gcc3.x is deprecated) | ||
46 | */ | ||
40 | #define __pa_symbol(x) __pa(__phys_reloc_hide((unsigned long)(x))) | 47 | #define __pa_symbol(x) __pa(__phys_reloc_hide((unsigned long)(x))) |
41 | 48 | ||
42 | #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) | 49 | #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) |
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h index 018a0a400799..bf5f7d32bd08 100644 --- a/arch/x86/include/asm/xen/page.h +++ b/arch/x86/include/asm/xen/page.h | |||
@@ -112,13 +112,9 @@ static inline xpaddr_t machine_to_phys(xmaddr_t machine) | |||
112 | */ | 112 | */ |
113 | static inline unsigned long mfn_to_local_pfn(unsigned long mfn) | 113 | static inline unsigned long mfn_to_local_pfn(unsigned long mfn) |
114 | { | 114 | { |
115 | extern unsigned long max_mapnr; | ||
116 | unsigned long pfn = mfn_to_pfn(mfn); | 115 | unsigned long pfn = mfn_to_pfn(mfn); |
117 | if ((pfn < max_mapnr) | 116 | if (get_phys_to_machine(pfn) != mfn) |
118 | && !xen_feature(XENFEAT_auto_translated_physmap) | 117 | return -1; /* force !pfn_valid() */ |
119 | && (get_phys_to_machine(pfn) != mfn)) | ||
120 | return max_mapnr; /* force !pfn_valid() */ | ||
121 | /* XXX fixme; not true with sparsemem */ | ||
122 | return pfn; | 118 | return pfn; |
123 | } | 119 | } |
124 | 120 | ||
diff --git a/arch/x86/include/asm/xen/swiotlb-xen.h b/arch/x86/include/asm/xen/swiotlb-xen.h new file mode 100644 index 000000000000..1be1ab7d6a41 --- /dev/null +++ b/arch/x86/include/asm/xen/swiotlb-xen.h | |||
@@ -0,0 +1,14 @@ | |||
1 | #ifndef _ASM_X86_SWIOTLB_XEN_H | ||
2 | #define _ASM_X86_SWIOTLB_XEN_H | ||
3 | |||
4 | #ifdef CONFIG_SWIOTLB_XEN | ||
5 | extern int xen_swiotlb; | ||
6 | extern int __init pci_xen_swiotlb_detect(void); | ||
7 | extern void __init pci_xen_swiotlb_init(void); | ||
8 | #else | ||
9 | #define xen_swiotlb (0) | ||
10 | static inline int __init pci_xen_swiotlb_detect(void) { return 0; } | ||
11 | static inline void __init pci_xen_swiotlb_init(void) { } | ||
12 | #endif | ||
13 | |||
14 | #endif /* _ASM_X86_SWIOTLB_XEN_H */ | ||
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 980508c79082..e3b534cda49a 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -1606,7 +1606,7 @@ void __init init_apic_mappings(void) | |||
1606 | * acpi lapic path already maps that address in | 1606 | * acpi lapic path already maps that address in |
1607 | * acpi_register_lapic_address() | 1607 | * acpi_register_lapic_address() |
1608 | */ | 1608 | */ |
1609 | if (!acpi_lapic) | 1609 | if (!acpi_lapic && !smp_found_config) |
1610 | set_fixmap_nocache(FIX_APIC_BASE, apic_phys); | 1610 | set_fixmap_nocache(FIX_APIC_BASE, apic_phys); |
1611 | 1611 | ||
1612 | apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n", | 1612 | apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n", |
diff --git a/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c index a36de5bbb622..994230d4dc4e 100644 --- a/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c | |||
@@ -110,7 +110,7 @@ struct pcc_cpu { | |||
110 | u32 output_offset; | 110 | u32 output_offset; |
111 | }; | 111 | }; |
112 | 112 | ||
113 | static struct pcc_cpu *pcc_cpu_info; | 113 | static struct pcc_cpu __percpu *pcc_cpu_info; |
114 | 114 | ||
115 | static int pcc_cpufreq_verify(struct cpufreq_policy *policy) | 115 | static int pcc_cpufreq_verify(struct cpufreq_policy *policy) |
116 | { | 116 | { |
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 33dbcc4ec5ff..351f9c0fea1f 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c | |||
@@ -582,7 +582,7 @@ static void init_one_hpet_msi_clockevent(struct hpet_dev *hdev, int cpu) | |||
582 | * scaled math multiplication factor for nanosecond to hpet tick | 582 | * scaled math multiplication factor for nanosecond to hpet tick |
583 | * conversion. | 583 | * conversion. |
584 | */ | 584 | */ |
585 | hpet_freq = 1000000000000000ULL; | 585 | hpet_freq = FSEC_PER_SEC; |
586 | do_div(hpet_freq, hpet_period); | 586 | do_div(hpet_freq, hpet_period); |
587 | evt->mult = div_sc((unsigned long) hpet_freq, | 587 | evt->mult = div_sc((unsigned long) hpet_freq, |
588 | NSEC_PER_SEC, evt->shift); | 588 | NSEC_PER_SEC, evt->shift); |
@@ -837,7 +837,7 @@ static int hpet_clocksource_register(void) | |||
837 | * cyc/sec = FSEC_PER_SEC/hpet_period(fsec/cyc) | 837 | * cyc/sec = FSEC_PER_SEC/hpet_period(fsec/cyc) |
838 | * cyc/sec = (FSEC_PER_NSEC * NSEC_PER_SEC)/hpet_period | 838 | * cyc/sec = (FSEC_PER_NSEC * NSEC_PER_SEC)/hpet_period |
839 | */ | 839 | */ |
840 | hpet_freq = FSEC_PER_NSEC * NSEC_PER_SEC; | 840 | hpet_freq = FSEC_PER_SEC; |
841 | do_div(hpet_freq, hpet_period); | 841 | do_div(hpet_freq, hpet_period); |
842 | clocksource_register_hz(&clocksource_hpet, (u32)hpet_freq); | 842 | clocksource_register_hz(&clocksource_hpet, (u32)hpet_freq); |
843 | 843 | ||
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index d86dbf7e54be..d7b6f7fb4fec 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c | |||
@@ -274,6 +274,18 @@ static void __init smp_dump_mptable(struct mpc_table *mpc, unsigned char *mpt) | |||
274 | 274 | ||
275 | void __init default_smp_read_mpc_oem(struct mpc_table *mpc) { } | 275 | void __init default_smp_read_mpc_oem(struct mpc_table *mpc) { } |
276 | 276 | ||
277 | static void __init smp_register_lapic_address(unsigned long address) | ||
278 | { | ||
279 | mp_lapic_addr = address; | ||
280 | |||
281 | set_fixmap_nocache(FIX_APIC_BASE, address); | ||
282 | if (boot_cpu_physical_apicid == -1U) { | ||
283 | boot_cpu_physical_apicid = read_apic_id(); | ||
284 | apic_version[boot_cpu_physical_apicid] = | ||
285 | GET_APIC_VERSION(apic_read(APIC_LVR)); | ||
286 | } | ||
287 | } | ||
288 | |||
277 | static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) | 289 | static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) |
278 | { | 290 | { |
279 | char str[16]; | 291 | char str[16]; |
@@ -295,6 +307,10 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) | |||
295 | if (early) | 307 | if (early) |
296 | return 1; | 308 | return 1; |
297 | 309 | ||
310 | /* Initialize the lapic mapping */ | ||
311 | if (!acpi_lapic) | ||
312 | smp_register_lapic_address(mpc->lapic); | ||
313 | |||
298 | if (mpc->oemptr) | 314 | if (mpc->oemptr) |
299 | x86_init.mpparse.smp_read_mpc_oem(mpc); | 315 | x86_init.mpparse.smp_read_mpc_oem(mpc); |
300 | 316 | ||
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 4b7e3d8b01dd..9f07cfcbd3a5 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <asm/calgary.h> | 13 | #include <asm/calgary.h> |
14 | #include <asm/amd_iommu.h> | 14 | #include <asm/amd_iommu.h> |
15 | #include <asm/x86_init.h> | 15 | #include <asm/x86_init.h> |
16 | #include <asm/xen/swiotlb-xen.h> | ||
16 | 17 | ||
17 | static int forbid_dac __read_mostly; | 18 | static int forbid_dac __read_mostly; |
18 | 19 | ||
@@ -132,7 +133,7 @@ void __init pci_iommu_alloc(void) | |||
132 | /* free the range so iommu could get some range less than 4G */ | 133 | /* free the range so iommu could get some range less than 4G */ |
133 | dma32_free_bootmem(); | 134 | dma32_free_bootmem(); |
134 | 135 | ||
135 | if (pci_swiotlb_detect()) | 136 | if (pci_xen_swiotlb_detect() || pci_swiotlb_detect()) |
136 | goto out; | 137 | goto out; |
137 | 138 | ||
138 | gart_iommu_hole_init(); | 139 | gart_iommu_hole_init(); |
@@ -144,6 +145,8 @@ void __init pci_iommu_alloc(void) | |||
144 | /* needs to be called after gart_iommu_hole_init */ | 145 | /* needs to be called after gart_iommu_hole_init */ |
145 | amd_iommu_detect(); | 146 | amd_iommu_detect(); |
146 | out: | 147 | out: |
148 | pci_xen_swiotlb_init(); | ||
149 | |||
147 | pci_swiotlb_init(); | 150 | pci_swiotlb_init(); |
148 | } | 151 | } |
149 | 152 | ||
@@ -296,7 +299,7 @@ static int __init pci_iommu_init(void) | |||
296 | #endif | 299 | #endif |
297 | x86_init.iommu.iommu_init(); | 300 | x86_init.iommu.iommu_init(); |
298 | 301 | ||
299 | if (swiotlb) { | 302 | if (swiotlb || xen_swiotlb) { |
300 | printk(KERN_INFO "PCI-DMA: " | 303 | printk(KERN_INFO "PCI-DMA: " |
301 | "Using software bounce buffering for IO (SWIOTLB)\n"); | 304 | "Using software bounce buffering for IO (SWIOTLB)\n"); |
302 | swiotlb_print_info(); | 305 | swiotlb_print_info(); |
diff --git a/arch/x86/lib/atomic64_386_32.S b/arch/x86/lib/atomic64_386_32.S index 4a5979aa6883..2cda60a06e65 100644 --- a/arch/x86/lib/atomic64_386_32.S +++ b/arch/x86/lib/atomic64_386_32.S | |||
@@ -25,150 +25,172 @@ | |||
25 | CFI_ADJUST_CFA_OFFSET -4 | 25 | CFI_ADJUST_CFA_OFFSET -4 |
26 | .endm | 26 | .endm |
27 | 27 | ||
28 | .macro BEGIN func reg | 28 | #define BEGIN(op) \ |
29 | $v = \reg | 29 | .macro endp; \ |
30 | 30 | CFI_ENDPROC; \ | |
31 | ENTRY(atomic64_\func\()_386) | 31 | ENDPROC(atomic64_##op##_386); \ |
32 | CFI_STARTPROC | 32 | .purgem endp; \ |
33 | LOCK $v | 33 | .endm; \ |
34 | 34 | ENTRY(atomic64_##op##_386); \ | |
35 | .macro RETURN | 35 | CFI_STARTPROC; \ |
36 | UNLOCK $v | 36 | LOCK v; |
37 | |||
38 | #define ENDP endp | ||
39 | |||
40 | #define RET \ | ||
41 | UNLOCK v; \ | ||
37 | ret | 42 | ret |
38 | .endm | ||
39 | |||
40 | .macro END_ | ||
41 | CFI_ENDPROC | ||
42 | ENDPROC(atomic64_\func\()_386) | ||
43 | .purgem RETURN | ||
44 | .purgem END_ | ||
45 | .purgem END | ||
46 | .endm | ||
47 | |||
48 | .macro END | ||
49 | RETURN | ||
50 | END_ | ||
51 | .endm | ||
52 | .endm | ||
53 | 43 | ||
54 | BEGIN read %ecx | 44 | #define RET_ENDP \ |
55 | movl ($v), %eax | 45 | RET; \ |
56 | movl 4($v), %edx | 46 | ENDP |
57 | END | 47 | |
58 | 48 | #define v %ecx | |
59 | BEGIN set %esi | 49 | BEGIN(read) |
60 | movl %ebx, ($v) | 50 | movl (v), %eax |
61 | movl %ecx, 4($v) | 51 | movl 4(v), %edx |
62 | END | 52 | RET_ENDP |
63 | 53 | #undef v | |
64 | BEGIN xchg %esi | 54 | |
65 | movl ($v), %eax | 55 | #define v %esi |
66 | movl 4($v), %edx | 56 | BEGIN(set) |
67 | movl %ebx, ($v) | 57 | movl %ebx, (v) |
68 | movl %ecx, 4($v) | 58 | movl %ecx, 4(v) |
69 | END | 59 | RET_ENDP |
70 | 60 | #undef v | |
71 | BEGIN add %ecx | 61 | |
72 | addl %eax, ($v) | 62 | #define v %esi |
73 | adcl %edx, 4($v) | 63 | BEGIN(xchg) |
74 | END | 64 | movl (v), %eax |
75 | 65 | movl 4(v), %edx | |
76 | BEGIN add_return %ecx | 66 | movl %ebx, (v) |
77 | addl ($v), %eax | 67 | movl %ecx, 4(v) |
78 | adcl 4($v), %edx | 68 | RET_ENDP |
79 | movl %eax, ($v) | 69 | #undef v |
80 | movl %edx, 4($v) | 70 | |
81 | END | 71 | #define v %ecx |
82 | 72 | BEGIN(add) | |
83 | BEGIN sub %ecx | 73 | addl %eax, (v) |
84 | subl %eax, ($v) | 74 | adcl %edx, 4(v) |
85 | sbbl %edx, 4($v) | 75 | RET_ENDP |
86 | END | 76 | #undef v |
87 | 77 | ||
88 | BEGIN sub_return %ecx | 78 | #define v %ecx |
79 | BEGIN(add_return) | ||
80 | addl (v), %eax | ||
81 | adcl 4(v), %edx | ||
82 | movl %eax, (v) | ||
83 | movl %edx, 4(v) | ||
84 | RET_ENDP | ||
85 | #undef v | ||
86 | |||
87 | #define v %ecx | ||
88 | BEGIN(sub) | ||
89 | subl %eax, (v) | ||
90 | sbbl %edx, 4(v) | ||
91 | RET_ENDP | ||
92 | #undef v | ||
93 | |||
94 | #define v %ecx | ||
95 | BEGIN(sub_return) | ||
89 | negl %edx | 96 | negl %edx |
90 | negl %eax | 97 | negl %eax |
91 | sbbl $0, %edx | 98 | sbbl $0, %edx |
92 | addl ($v), %eax | 99 | addl (v), %eax |
93 | adcl 4($v), %edx | 100 | adcl 4(v), %edx |
94 | movl %eax, ($v) | 101 | movl %eax, (v) |
95 | movl %edx, 4($v) | 102 | movl %edx, 4(v) |
96 | END | 103 | RET_ENDP |
97 | 104 | #undef v | |
98 | BEGIN inc %esi | 105 | |
99 | addl $1, ($v) | 106 | #define v %esi |
100 | adcl $0, 4($v) | 107 | BEGIN(inc) |
101 | END | 108 | addl $1, (v) |
102 | 109 | adcl $0, 4(v) | |
103 | BEGIN inc_return %esi | 110 | RET_ENDP |
104 | movl ($v), %eax | 111 | #undef v |
105 | movl 4($v), %edx | 112 | |
113 | #define v %esi | ||
114 | BEGIN(inc_return) | ||
115 | movl (v), %eax | ||
116 | movl 4(v), %edx | ||
106 | addl $1, %eax | 117 | addl $1, %eax |
107 | adcl $0, %edx | 118 | adcl $0, %edx |
108 | movl %eax, ($v) | 119 | movl %eax, (v) |
109 | movl %edx, 4($v) | 120 | movl %edx, 4(v) |
110 | END | 121 | RET_ENDP |
111 | 122 | #undef v | |
112 | BEGIN dec %esi | 123 | |
113 | subl $1, ($v) | 124 | #define v %esi |
114 | sbbl $0, 4($v) | 125 | BEGIN(dec) |
115 | END | 126 | subl $1, (v) |
116 | 127 | sbbl $0, 4(v) | |
117 | BEGIN dec_return %esi | 128 | RET_ENDP |
118 | movl ($v), %eax | 129 | #undef v |
119 | movl 4($v), %edx | 130 | |
131 | #define v %esi | ||
132 | BEGIN(dec_return) | ||
133 | movl (v), %eax | ||
134 | movl 4(v), %edx | ||
120 | subl $1, %eax | 135 | subl $1, %eax |
121 | sbbl $0, %edx | 136 | sbbl $0, %edx |
122 | movl %eax, ($v) | 137 | movl %eax, (v) |
123 | movl %edx, 4($v) | 138 | movl %edx, 4(v) |
124 | END | 139 | RET_ENDP |
140 | #undef v | ||
125 | 141 | ||
126 | BEGIN add_unless %ecx | 142 | #define v %ecx |
143 | BEGIN(add_unless) | ||
127 | addl %eax, %esi | 144 | addl %eax, %esi |
128 | adcl %edx, %edi | 145 | adcl %edx, %edi |
129 | addl ($v), %eax | 146 | addl (v), %eax |
130 | adcl 4($v), %edx | 147 | adcl 4(v), %edx |
131 | cmpl %eax, %esi | 148 | cmpl %eax, %esi |
132 | je 3f | 149 | je 3f |
133 | 1: | 150 | 1: |
134 | movl %eax, ($v) | 151 | movl %eax, (v) |
135 | movl %edx, 4($v) | 152 | movl %edx, 4(v) |
136 | movl $1, %eax | 153 | movl $1, %eax |
137 | 2: | 154 | 2: |
138 | RETURN | 155 | RET |
139 | 3: | 156 | 3: |
140 | cmpl %edx, %edi | 157 | cmpl %edx, %edi |
141 | jne 1b | 158 | jne 1b |
142 | xorl %eax, %eax | 159 | xorl %eax, %eax |
143 | jmp 2b | 160 | jmp 2b |
144 | END_ | 161 | ENDP |
162 | #undef v | ||
145 | 163 | ||
146 | BEGIN inc_not_zero %esi | 164 | #define v %esi |
147 | movl ($v), %eax | 165 | BEGIN(inc_not_zero) |
148 | movl 4($v), %edx | 166 | movl (v), %eax |
167 | movl 4(v), %edx | ||
149 | testl %eax, %eax | 168 | testl %eax, %eax |
150 | je 3f | 169 | je 3f |
151 | 1: | 170 | 1: |
152 | addl $1, %eax | 171 | addl $1, %eax |
153 | adcl $0, %edx | 172 | adcl $0, %edx |
154 | movl %eax, ($v) | 173 | movl %eax, (v) |
155 | movl %edx, 4($v) | 174 | movl %edx, 4(v) |
156 | movl $1, %eax | 175 | movl $1, %eax |
157 | 2: | 176 | 2: |
158 | RETURN | 177 | RET |
159 | 3: | 178 | 3: |
160 | testl %edx, %edx | 179 | testl %edx, %edx |
161 | jne 1b | 180 | jne 1b |
162 | jmp 2b | 181 | jmp 2b |
163 | END_ | 182 | ENDP |
183 | #undef v | ||
164 | 184 | ||
165 | BEGIN dec_if_positive %esi | 185 | #define v %esi |
166 | movl ($v), %eax | 186 | BEGIN(dec_if_positive) |
167 | movl 4($v), %edx | 187 | movl (v), %eax |
188 | movl 4(v), %edx | ||
168 | subl $1, %eax | 189 | subl $1, %eax |
169 | sbbl $0, %edx | 190 | sbbl $0, %edx |
170 | js 1f | 191 | js 1f |
171 | movl %eax, ($v) | 192 | movl %eax, (v) |
172 | movl %edx, 4($v) | 193 | movl %edx, 4(v) |
173 | 1: | 194 | 1: |
174 | END | 195 | RET_ENDP |
196 | #undef v | ||
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index f62777940dfb..4c4508e8a204 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
@@ -802,8 +802,10 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address, | |||
802 | up_read(&mm->mmap_sem); | 802 | up_read(&mm->mmap_sem); |
803 | 803 | ||
804 | /* Kernel mode? Handle exceptions or die: */ | 804 | /* Kernel mode? Handle exceptions or die: */ |
805 | if (!(error_code & PF_USER)) | 805 | if (!(error_code & PF_USER)) { |
806 | no_context(regs, error_code, address); | 806 | no_context(regs, error_code, address); |
807 | return; | ||
808 | } | ||
807 | 809 | ||
808 | /* User-space => ok to do another page fault: */ | 810 | /* User-space => ok to do another page fault: */ |
809 | if (is_prefetch(regs, error_code, address)) | 811 | if (is_prefetch(regs, error_code, address)) |
diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile index 930954685980..779385158915 100644 --- a/arch/x86/xen/Makefile +++ b/arch/x86/xen/Makefile | |||
@@ -18,3 +18,4 @@ obj-$(CONFIG_SMP) += smp.o | |||
18 | obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o | 18 | obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o |
19 | obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o | 19 | obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o |
20 | 20 | ||
21 | obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o | ||
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index d4ff5e83621d..7d46c8441418 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -1172,6 +1172,10 @@ asmlinkage void __init xen_start_kernel(void) | |||
1172 | 1172 | ||
1173 | pgd = (pgd_t *)xen_start_info->pt_base; | 1173 | pgd = (pgd_t *)xen_start_info->pt_base; |
1174 | 1174 | ||
1175 | if (!xen_initial_domain()) | ||
1176 | __supported_pte_mask &= ~(_PAGE_PWT | _PAGE_PCD); | ||
1177 | |||
1178 | __supported_pte_mask |= _PAGE_IOMAP; | ||
1175 | /* Don't do the full vcpu_info placement stuff until we have a | 1179 | /* Don't do the full vcpu_info placement stuff until we have a |
1176 | possible map and a non-dummy shared_info. */ | 1180 | possible map and a non-dummy shared_info. */ |
1177 | per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0]; | 1181 | per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0]; |
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 413b19b3d0fe..42086ac406af 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/highmem.h> | 42 | #include <linux/highmem.h> |
43 | #include <linux/debugfs.h> | 43 | #include <linux/debugfs.h> |
44 | #include <linux/bug.h> | 44 | #include <linux/bug.h> |
45 | #include <linux/vmalloc.h> | ||
45 | #include <linux/module.h> | 46 | #include <linux/module.h> |
46 | #include <linux/gfp.h> | 47 | #include <linux/gfp.h> |
47 | 48 | ||
@@ -51,15 +52,19 @@ | |||
51 | #include <asm/mmu_context.h> | 52 | #include <asm/mmu_context.h> |
52 | #include <asm/setup.h> | 53 | #include <asm/setup.h> |
53 | #include <asm/paravirt.h> | 54 | #include <asm/paravirt.h> |
55 | #include <asm/e820.h> | ||
54 | #include <asm/linkage.h> | 56 | #include <asm/linkage.h> |
57 | #include <asm/page.h> | ||
55 | 58 | ||
56 | #include <asm/xen/hypercall.h> | 59 | #include <asm/xen/hypercall.h> |
57 | #include <asm/xen/hypervisor.h> | 60 | #include <asm/xen/hypervisor.h> |
58 | 61 | ||
62 | #include <xen/xen.h> | ||
59 | #include <xen/page.h> | 63 | #include <xen/page.h> |
60 | #include <xen/interface/xen.h> | 64 | #include <xen/interface/xen.h> |
61 | #include <xen/interface/hvm/hvm_op.h> | 65 | #include <xen/interface/hvm/hvm_op.h> |
62 | #include <xen/interface/version.h> | 66 | #include <xen/interface/version.h> |
67 | #include <xen/interface/memory.h> | ||
63 | #include <xen/hvc-console.h> | 68 | #include <xen/hvc-console.h> |
64 | 69 | ||
65 | #include "multicalls.h" | 70 | #include "multicalls.h" |
@@ -68,6 +73,13 @@ | |||
68 | 73 | ||
69 | #define MMU_UPDATE_HISTO 30 | 74 | #define MMU_UPDATE_HISTO 30 |
70 | 75 | ||
76 | /* | ||
77 | * Protects atomic reservation decrease/increase against concurrent increases. | ||
78 | * Also protects non-atomic updates of current_pages and driver_pages, and | ||
79 | * balloon lists. | ||
80 | */ | ||
81 | DEFINE_SPINLOCK(xen_reservation_lock); | ||
82 | |||
71 | #ifdef CONFIG_XEN_DEBUG_FS | 83 | #ifdef CONFIG_XEN_DEBUG_FS |
72 | 84 | ||
73 | static struct { | 85 | static struct { |
@@ -378,6 +390,28 @@ static bool xen_page_pinned(void *ptr) | |||
378 | return PagePinned(page); | 390 | return PagePinned(page); |
379 | } | 391 | } |
380 | 392 | ||
393 | static bool xen_iomap_pte(pte_t pte) | ||
394 | { | ||
395 | return pte_flags(pte) & _PAGE_IOMAP; | ||
396 | } | ||
397 | |||
398 | static void xen_set_iomap_pte(pte_t *ptep, pte_t pteval) | ||
399 | { | ||
400 | struct multicall_space mcs; | ||
401 | struct mmu_update *u; | ||
402 | |||
403 | mcs = xen_mc_entry(sizeof(*u)); | ||
404 | u = mcs.args; | ||
405 | |||
406 | /* ptep might be kmapped when using 32-bit HIGHPTE */ | ||
407 | u->ptr = arbitrary_virt_to_machine(ptep).maddr; | ||
408 | u->val = pte_val_ma(pteval); | ||
409 | |||
410 | MULTI_mmu_update(mcs.mc, mcs.args, 1, NULL, DOMID_IO); | ||
411 | |||
412 | xen_mc_issue(PARAVIRT_LAZY_MMU); | ||
413 | } | ||
414 | |||
381 | static void xen_extend_mmu_update(const struct mmu_update *update) | 415 | static void xen_extend_mmu_update(const struct mmu_update *update) |
382 | { | 416 | { |
383 | struct multicall_space mcs; | 417 | struct multicall_space mcs; |
@@ -454,6 +488,11 @@ void set_pte_mfn(unsigned long vaddr, unsigned long mfn, pgprot_t flags) | |||
454 | void xen_set_pte_at(struct mm_struct *mm, unsigned long addr, | 488 | void xen_set_pte_at(struct mm_struct *mm, unsigned long addr, |
455 | pte_t *ptep, pte_t pteval) | 489 | pte_t *ptep, pte_t pteval) |
456 | { | 490 | { |
491 | if (xen_iomap_pte(pteval)) { | ||
492 | xen_set_iomap_pte(ptep, pteval); | ||
493 | goto out; | ||
494 | } | ||
495 | |||
457 | ADD_STATS(set_pte_at, 1); | 496 | ADD_STATS(set_pte_at, 1); |
458 | // ADD_STATS(set_pte_at_pinned, xen_page_pinned(ptep)); | 497 | // ADD_STATS(set_pte_at_pinned, xen_page_pinned(ptep)); |
459 | ADD_STATS(set_pte_at_current, mm == current->mm); | 498 | ADD_STATS(set_pte_at_current, mm == current->mm); |
@@ -524,8 +563,25 @@ static pteval_t pte_pfn_to_mfn(pteval_t val) | |||
524 | return val; | 563 | return val; |
525 | } | 564 | } |
526 | 565 | ||
566 | static pteval_t iomap_pte(pteval_t val) | ||
567 | { | ||
568 | if (val & _PAGE_PRESENT) { | ||
569 | unsigned long pfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT; | ||
570 | pteval_t flags = val & PTE_FLAGS_MASK; | ||
571 | |||
572 | /* We assume the pte frame number is a MFN, so | ||
573 | just use it as-is. */ | ||
574 | val = ((pteval_t)pfn << PAGE_SHIFT) | flags; | ||
575 | } | ||
576 | |||
577 | return val; | ||
578 | } | ||
579 | |||
527 | pteval_t xen_pte_val(pte_t pte) | 580 | pteval_t xen_pte_val(pte_t pte) |
528 | { | 581 | { |
582 | if (xen_initial_domain() && (pte.pte & _PAGE_IOMAP)) | ||
583 | return pte.pte; | ||
584 | |||
529 | return pte_mfn_to_pfn(pte.pte); | 585 | return pte_mfn_to_pfn(pte.pte); |
530 | } | 586 | } |
531 | PV_CALLEE_SAVE_REGS_THUNK(xen_pte_val); | 587 | PV_CALLEE_SAVE_REGS_THUNK(xen_pte_val); |
@@ -538,7 +594,22 @@ PV_CALLEE_SAVE_REGS_THUNK(xen_pgd_val); | |||
538 | 594 | ||
539 | pte_t xen_make_pte(pteval_t pte) | 595 | pte_t xen_make_pte(pteval_t pte) |
540 | { | 596 | { |
541 | pte = pte_pfn_to_mfn(pte); | 597 | phys_addr_t addr = (pte & PTE_PFN_MASK); |
598 | |||
599 | /* | ||
600 | * Unprivileged domains are allowed to do IOMAPpings for | ||
601 | * PCI passthrough, but not map ISA space. The ISA | ||
602 | * mappings are just dummy local mappings to keep other | ||
603 | * parts of the kernel happy. | ||
604 | */ | ||
605 | if (unlikely(pte & _PAGE_IOMAP) && | ||
606 | (xen_initial_domain() || addr >= ISA_END_ADDRESS)) { | ||
607 | pte = iomap_pte(pte); | ||
608 | } else { | ||
609 | pte &= ~_PAGE_IOMAP; | ||
610 | pte = pte_pfn_to_mfn(pte); | ||
611 | } | ||
612 | |||
542 | return native_make_pte(pte); | 613 | return native_make_pte(pte); |
543 | } | 614 | } |
544 | PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte); | 615 | PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte); |
@@ -594,6 +665,11 @@ void xen_set_pud(pud_t *ptr, pud_t val) | |||
594 | 665 | ||
595 | void xen_set_pte(pte_t *ptep, pte_t pte) | 666 | void xen_set_pte(pte_t *ptep, pte_t pte) |
596 | { | 667 | { |
668 | if (xen_iomap_pte(pte)) { | ||
669 | xen_set_iomap_pte(ptep, pte); | ||
670 | return; | ||
671 | } | ||
672 | |||
597 | ADD_STATS(pte_update, 1); | 673 | ADD_STATS(pte_update, 1); |
598 | // ADD_STATS(pte_update_pinned, xen_page_pinned(ptep)); | 674 | // ADD_STATS(pte_update_pinned, xen_page_pinned(ptep)); |
599 | ADD_STATS(pte_update_batched, paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU); | 675 | ADD_STATS(pte_update_batched, paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU); |
@@ -610,6 +686,11 @@ void xen_set_pte(pte_t *ptep, pte_t pte) | |||
610 | #ifdef CONFIG_X86_PAE | 686 | #ifdef CONFIG_X86_PAE |
611 | void xen_set_pte_atomic(pte_t *ptep, pte_t pte) | 687 | void xen_set_pte_atomic(pte_t *ptep, pte_t pte) |
612 | { | 688 | { |
689 | if (xen_iomap_pte(pte)) { | ||
690 | xen_set_iomap_pte(ptep, pte); | ||
691 | return; | ||
692 | } | ||
693 | |||
613 | set_64bit((u64 *)ptep, native_pte_val(pte)); | 694 | set_64bit((u64 *)ptep, native_pte_val(pte)); |
614 | } | 695 | } |
615 | 696 | ||
@@ -936,8 +1017,6 @@ static int xen_pin_page(struct mm_struct *mm, struct page *page, | |||
936 | read-only, and can be pinned. */ | 1017 | read-only, and can be pinned. */ |
937 | static void __xen_pgd_pin(struct mm_struct *mm, pgd_t *pgd) | 1018 | static void __xen_pgd_pin(struct mm_struct *mm, pgd_t *pgd) |
938 | { | 1019 | { |
939 | vm_unmap_aliases(); | ||
940 | |||
941 | xen_mc_batch(); | 1020 | xen_mc_batch(); |
942 | 1021 | ||
943 | if (__xen_pgd_walk(mm, pgd, xen_pin_page, USER_LIMIT)) { | 1022 | if (__xen_pgd_walk(mm, pgd, xen_pin_page, USER_LIMIT)) { |
@@ -1501,7 +1580,6 @@ static void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn, unsigned l | |||
1501 | if (PagePinned(virt_to_page(mm->pgd))) { | 1580 | if (PagePinned(virt_to_page(mm->pgd))) { |
1502 | SetPagePinned(page); | 1581 | SetPagePinned(page); |
1503 | 1582 | ||
1504 | vm_unmap_aliases(); | ||
1505 | if (!PageHighMem(page)) { | 1583 | if (!PageHighMem(page)) { |
1506 | make_lowmem_page_readonly(__va(PFN_PHYS((unsigned long)pfn))); | 1584 | make_lowmem_page_readonly(__va(PFN_PHYS((unsigned long)pfn))); |
1507 | if (level == PT_PTE && USE_SPLIT_PTLOCKS) | 1585 | if (level == PT_PTE && USE_SPLIT_PTLOCKS) |
@@ -1812,9 +1890,16 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot) | |||
1812 | pte = pfn_pte(phys, prot); | 1890 | pte = pfn_pte(phys, prot); |
1813 | break; | 1891 | break; |
1814 | 1892 | ||
1815 | default: | 1893 | case FIX_PARAVIRT_BOOTMAP: |
1894 | /* This is an MFN, but it isn't an IO mapping from the | ||
1895 | IO domain */ | ||
1816 | pte = mfn_pte(phys, prot); | 1896 | pte = mfn_pte(phys, prot); |
1817 | break; | 1897 | break; |
1898 | |||
1899 | default: | ||
1900 | /* By default, set_fixmap is used for hardware mappings */ | ||
1901 | pte = mfn_pte(phys, __pgprot(pgprot_val(prot) | _PAGE_IOMAP)); | ||
1902 | break; | ||
1818 | } | 1903 | } |
1819 | 1904 | ||
1820 | __native_set_fixmap(idx, pte); | 1905 | __native_set_fixmap(idx, pte); |
@@ -1940,7 +2025,205 @@ void __init xen_init_mmu_ops(void) | |||
1940 | x86_init.paging.pagetable_setup_start = xen_pagetable_setup_start; | 2025 | x86_init.paging.pagetable_setup_start = xen_pagetable_setup_start; |
1941 | x86_init.paging.pagetable_setup_done = xen_pagetable_setup_done; | 2026 | x86_init.paging.pagetable_setup_done = xen_pagetable_setup_done; |
1942 | pv_mmu_ops = xen_mmu_ops; | 2027 | pv_mmu_ops = xen_mmu_ops; |
2028 | |||
2029 | vmap_lazy_unmap = false; | ||
2030 | } | ||
2031 | |||
2032 | /* Protected by xen_reservation_lock. */ | ||
2033 | #define MAX_CONTIG_ORDER 9 /* 2MB */ | ||
2034 | static unsigned long discontig_frames[1<<MAX_CONTIG_ORDER]; | ||
2035 | |||
2036 | #define VOID_PTE (mfn_pte(0, __pgprot(0))) | ||
2037 | static void xen_zap_pfn_range(unsigned long vaddr, unsigned int order, | ||
2038 | unsigned long *in_frames, | ||
2039 | unsigned long *out_frames) | ||
2040 | { | ||
2041 | int i; | ||
2042 | struct multicall_space mcs; | ||
2043 | |||
2044 | xen_mc_batch(); | ||
2045 | for (i = 0; i < (1UL<<order); i++, vaddr += PAGE_SIZE) { | ||
2046 | mcs = __xen_mc_entry(0); | ||
2047 | |||
2048 | if (in_frames) | ||
2049 | in_frames[i] = virt_to_mfn(vaddr); | ||
2050 | |||
2051 | MULTI_update_va_mapping(mcs.mc, vaddr, VOID_PTE, 0); | ||
2052 | set_phys_to_machine(virt_to_pfn(vaddr), INVALID_P2M_ENTRY); | ||
2053 | |||
2054 | if (out_frames) | ||
2055 | out_frames[i] = virt_to_pfn(vaddr); | ||
2056 | } | ||
2057 | xen_mc_issue(0); | ||
2058 | } | ||
2059 | |||
2060 | /* | ||
2061 | * Update the pfn-to-mfn mappings for a virtual address range, either to | ||
2062 | * point to an array of mfns, or contiguously from a single starting | ||
2063 | * mfn. | ||
2064 | */ | ||
2065 | static void xen_remap_exchanged_ptes(unsigned long vaddr, int order, | ||
2066 | unsigned long *mfns, | ||
2067 | unsigned long first_mfn) | ||
2068 | { | ||
2069 | unsigned i, limit; | ||
2070 | unsigned long mfn; | ||
2071 | |||
2072 | xen_mc_batch(); | ||
2073 | |||
2074 | limit = 1u << order; | ||
2075 | for (i = 0; i < limit; i++, vaddr += PAGE_SIZE) { | ||
2076 | struct multicall_space mcs; | ||
2077 | unsigned flags; | ||
2078 | |||
2079 | mcs = __xen_mc_entry(0); | ||
2080 | if (mfns) | ||
2081 | mfn = mfns[i]; | ||
2082 | else | ||
2083 | mfn = first_mfn + i; | ||
2084 | |||
2085 | if (i < (limit - 1)) | ||
2086 | flags = 0; | ||
2087 | else { | ||
2088 | if (order == 0) | ||
2089 | flags = UVMF_INVLPG | UVMF_ALL; | ||
2090 | else | ||
2091 | flags = UVMF_TLB_FLUSH | UVMF_ALL; | ||
2092 | } | ||
2093 | |||
2094 | MULTI_update_va_mapping(mcs.mc, vaddr, | ||
2095 | mfn_pte(mfn, PAGE_KERNEL), flags); | ||
2096 | |||
2097 | set_phys_to_machine(virt_to_pfn(vaddr), mfn); | ||
2098 | } | ||
2099 | |||
2100 | xen_mc_issue(0); | ||
2101 | } | ||
2102 | |||
2103 | /* | ||
2104 | * Perform the hypercall to exchange a region of our pfns to point to | ||
2105 | * memory with the required contiguous alignment. Takes the pfns as | ||
2106 | * input, and populates mfns as output. | ||
2107 | * | ||
2108 | * Returns a success code indicating whether the hypervisor was able to | ||
2109 | * satisfy the request or not. | ||
2110 | */ | ||
2111 | static int xen_exchange_memory(unsigned long extents_in, unsigned int order_in, | ||
2112 | unsigned long *pfns_in, | ||
2113 | unsigned long extents_out, | ||
2114 | unsigned int order_out, | ||
2115 | unsigned long *mfns_out, | ||
2116 | unsigned int address_bits) | ||
2117 | { | ||
2118 | long rc; | ||
2119 | int success; | ||
2120 | |||
2121 | struct xen_memory_exchange exchange = { | ||
2122 | .in = { | ||
2123 | .nr_extents = extents_in, | ||
2124 | .extent_order = order_in, | ||
2125 | .extent_start = pfns_in, | ||
2126 | .domid = DOMID_SELF | ||
2127 | }, | ||
2128 | .out = { | ||
2129 | .nr_extents = extents_out, | ||
2130 | .extent_order = order_out, | ||
2131 | .extent_start = mfns_out, | ||
2132 | .address_bits = address_bits, | ||
2133 | .domid = DOMID_SELF | ||
2134 | } | ||
2135 | }; | ||
2136 | |||
2137 | BUG_ON(extents_in << order_in != extents_out << order_out); | ||
2138 | |||
2139 | rc = HYPERVISOR_memory_op(XENMEM_exchange, &exchange); | ||
2140 | success = (exchange.nr_exchanged == extents_in); | ||
2141 | |||
2142 | BUG_ON(!success && ((exchange.nr_exchanged != 0) || (rc == 0))); | ||
2143 | BUG_ON(success && (rc != 0)); | ||
2144 | |||
2145 | return success; | ||
2146 | } | ||
2147 | |||
2148 | int xen_create_contiguous_region(unsigned long vstart, unsigned int order, | ||
2149 | unsigned int address_bits) | ||
2150 | { | ||
2151 | unsigned long *in_frames = discontig_frames, out_frame; | ||
2152 | unsigned long flags; | ||
2153 | int success; | ||
2154 | |||
2155 | /* | ||
2156 | * Currently an auto-translated guest will not perform I/O, nor will | ||
2157 | * it require PAE page directories below 4GB. Therefore any calls to | ||
2158 | * this function are redundant and can be ignored. | ||
2159 | */ | ||
2160 | |||
2161 | if (xen_feature(XENFEAT_auto_translated_physmap)) | ||
2162 | return 0; | ||
2163 | |||
2164 | if (unlikely(order > MAX_CONTIG_ORDER)) | ||
2165 | return -ENOMEM; | ||
2166 | |||
2167 | memset((void *) vstart, 0, PAGE_SIZE << order); | ||
2168 | |||
2169 | spin_lock_irqsave(&xen_reservation_lock, flags); | ||
2170 | |||
2171 | /* 1. Zap current PTEs, remembering MFNs. */ | ||
2172 | xen_zap_pfn_range(vstart, order, in_frames, NULL); | ||
2173 | |||
2174 | /* 2. Get a new contiguous memory extent. */ | ||
2175 | out_frame = virt_to_pfn(vstart); | ||
2176 | success = xen_exchange_memory(1UL << order, 0, in_frames, | ||
2177 | 1, order, &out_frame, | ||
2178 | address_bits); | ||
2179 | |||
2180 | /* 3. Map the new extent in place of old pages. */ | ||
2181 | if (success) | ||
2182 | xen_remap_exchanged_ptes(vstart, order, NULL, out_frame); | ||
2183 | else | ||
2184 | xen_remap_exchanged_ptes(vstart, order, in_frames, 0); | ||
2185 | |||
2186 | spin_unlock_irqrestore(&xen_reservation_lock, flags); | ||
2187 | |||
2188 | return success ? 0 : -ENOMEM; | ||
2189 | } | ||
2190 | EXPORT_SYMBOL_GPL(xen_create_contiguous_region); | ||
2191 | |||
2192 | void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order) | ||
2193 | { | ||
2194 | unsigned long *out_frames = discontig_frames, in_frame; | ||
2195 | unsigned long flags; | ||
2196 | int success; | ||
2197 | |||
2198 | if (xen_feature(XENFEAT_auto_translated_physmap)) | ||
2199 | return; | ||
2200 | |||
2201 | if (unlikely(order > MAX_CONTIG_ORDER)) | ||
2202 | return; | ||
2203 | |||
2204 | memset((void *) vstart, 0, PAGE_SIZE << order); | ||
2205 | |||
2206 | spin_lock_irqsave(&xen_reservation_lock, flags); | ||
2207 | |||
2208 | /* 1. Find start MFN of contiguous extent. */ | ||
2209 | in_frame = virt_to_mfn(vstart); | ||
2210 | |||
2211 | /* 2. Zap current PTEs. */ | ||
2212 | xen_zap_pfn_range(vstart, order, NULL, out_frames); | ||
2213 | |||
2214 | /* 3. Do the exchange for non-contiguous MFNs. */ | ||
2215 | success = xen_exchange_memory(1, order, &in_frame, 1UL << order, | ||
2216 | 0, out_frames, 0); | ||
2217 | |||
2218 | /* 4. Map new pages in place of old pages. */ | ||
2219 | if (success) | ||
2220 | xen_remap_exchanged_ptes(vstart, order, out_frames, 0); | ||
2221 | else | ||
2222 | xen_remap_exchanged_ptes(vstart, order, NULL, in_frame); | ||
2223 | |||
2224 | spin_unlock_irqrestore(&xen_reservation_lock, flags); | ||
1943 | } | 2225 | } |
2226 | EXPORT_SYMBOL_GPL(xen_destroy_contiguous_region); | ||
1944 | 2227 | ||
1945 | #ifdef CONFIG_XEN_PVHVM | 2228 | #ifdef CONFIG_XEN_PVHVM |
1946 | static void xen_hvm_exit_mmap(struct mm_struct *mm) | 2229 | static void xen_hvm_exit_mmap(struct mm_struct *mm) |
diff --git a/arch/x86/xen/pci-swiotlb-xen.c b/arch/x86/xen/pci-swiotlb-xen.c new file mode 100644 index 000000000000..a013ec9d0c54 --- /dev/null +++ b/arch/x86/xen/pci-swiotlb-xen.c | |||
@@ -0,0 +1,58 @@ | |||
1 | /* Glue code to lib/swiotlb-xen.c */ | ||
2 | |||
3 | #include <linux/dma-mapping.h> | ||
4 | #include <xen/swiotlb-xen.h> | ||
5 | |||
6 | #include <asm/xen/hypervisor.h> | ||
7 | #include <xen/xen.h> | ||
8 | |||
9 | int xen_swiotlb __read_mostly; | ||
10 | |||
11 | static struct dma_map_ops xen_swiotlb_dma_ops = { | ||
12 | .mapping_error = xen_swiotlb_dma_mapping_error, | ||
13 | .alloc_coherent = xen_swiotlb_alloc_coherent, | ||
14 | .free_coherent = xen_swiotlb_free_coherent, | ||
15 | .sync_single_for_cpu = xen_swiotlb_sync_single_for_cpu, | ||
16 | .sync_single_for_device = xen_swiotlb_sync_single_for_device, | ||
17 | .sync_sg_for_cpu = xen_swiotlb_sync_sg_for_cpu, | ||
18 | .sync_sg_for_device = xen_swiotlb_sync_sg_for_device, | ||
19 | .map_sg = xen_swiotlb_map_sg_attrs, | ||
20 | .unmap_sg = xen_swiotlb_unmap_sg_attrs, | ||
21 | .map_page = xen_swiotlb_map_page, | ||
22 | .unmap_page = xen_swiotlb_unmap_page, | ||
23 | .dma_supported = xen_swiotlb_dma_supported, | ||
24 | }; | ||
25 | |||
26 | /* | ||
27 | * pci_xen_swiotlb_detect - set xen_swiotlb to 1 if necessary | ||
28 | * | ||
29 | * This returns non-zero if we are forced to use xen_swiotlb (by the boot | ||
30 | * option). | ||
31 | */ | ||
32 | int __init pci_xen_swiotlb_detect(void) | ||
33 | { | ||
34 | |||
35 | /* If running as PV guest, either iommu=soft, or swiotlb=force will | ||
36 | * activate this IOMMU. If running as PV privileged, activate it | ||
37 | * irregardlesss. | ||
38 | */ | ||
39 | if ((xen_initial_domain() || swiotlb || swiotlb_force) && | ||
40 | (xen_pv_domain())) | ||
41 | xen_swiotlb = 1; | ||
42 | |||
43 | /* If we are running under Xen, we MUST disable the native SWIOTLB. | ||
44 | * Don't worry about swiotlb_force flag activating the native, as | ||
45 | * the 'swiotlb' flag is the only one turning it on. */ | ||
46 | if (xen_pv_domain()) | ||
47 | swiotlb = 0; | ||
48 | |||
49 | return xen_swiotlb; | ||
50 | } | ||
51 | |||
52 | void __init pci_xen_swiotlb_init(void) | ||
53 | { | ||
54 | if (xen_swiotlb) { | ||
55 | xen_swiotlb_init(1); | ||
56 | dma_ops = &xen_swiotlb_dma_ops; | ||
57 | } | ||
58 | } | ||
diff --git a/block/blk-core.c b/block/blk-core.c index 7da630e25ae7..ee1a1e7e63cc 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -1514,7 +1514,10 @@ static inline void __generic_make_request(struct bio *bio) | |||
1514 | if (bio_check_eod(bio, nr_sectors)) | 1514 | if (bio_check_eod(bio, nr_sectors)) |
1515 | goto end_io; | 1515 | goto end_io; |
1516 | 1516 | ||
1517 | if ((bio->bi_rw & REQ_DISCARD) && !blk_queue_discard(q)) { | 1517 | if ((bio->bi_rw & REQ_DISCARD) && |
1518 | (!blk_queue_discard(q) || | ||
1519 | ((bio->bi_rw & REQ_SECURE) && | ||
1520 | !blk_queue_secdiscard(q)))) { | ||
1518 | err = -EOPNOTSUPP; | 1521 | err = -EOPNOTSUPP; |
1519 | goto end_io; | 1522 | goto end_io; |
1520 | } | 1523 | } |
diff --git a/block/blk-lib.c b/block/blk-lib.c index c1fc55a83ba1..c392029a104e 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c | |||
@@ -62,6 +62,12 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, | |||
62 | max_discard_sectors &= ~(disc_sects - 1); | 62 | max_discard_sectors &= ~(disc_sects - 1); |
63 | } | 63 | } |
64 | 64 | ||
65 | if (flags & BLKDEV_IFL_SECURE) { | ||
66 | if (!blk_queue_secdiscard(q)) | ||
67 | return -EOPNOTSUPP; | ||
68 | type |= DISCARD_SECURE; | ||
69 | } | ||
70 | |||
65 | while (nr_sects && !ret) { | 71 | while (nr_sects && !ret) { |
66 | bio = bio_alloc(gfp_mask, 1); | 72 | bio = bio_alloc(gfp_mask, 1); |
67 | if (!bio) { | 73 | if (!bio) { |
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index d53085637731..119f07b74dc0 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c | |||
@@ -703,6 +703,7 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
703 | case BLKFLSBUF: | 703 | case BLKFLSBUF: |
704 | case BLKROSET: | 704 | case BLKROSET: |
705 | case BLKDISCARD: | 705 | case BLKDISCARD: |
706 | case BLKSECDISCARD: | ||
706 | /* | 707 | /* |
707 | * the ones below are implemented in blkdev_locked_ioctl, | 708 | * the ones below are implemented in blkdev_locked_ioctl, |
708 | * but we call blkdev_ioctl, which gets the lock for us | 709 | * but we call blkdev_ioctl, which gets the lock for us |
diff --git a/block/elevator.c b/block/elevator.c index 816a7c8d6394..ec585c9554d3 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
@@ -83,6 +83,12 @@ int elv_rq_merge_ok(struct request *rq, struct bio *bio) | |||
83 | return 0; | 83 | return 0; |
84 | 84 | ||
85 | /* | 85 | /* |
86 | * Don't merge discard requests and secure discard requests | ||
87 | */ | ||
88 | if ((bio->bi_rw & REQ_SECURE) != (rq->bio->bi_rw & REQ_SECURE)) | ||
89 | return 0; | ||
90 | |||
91 | /* | ||
86 | * different data direction or already started, don't merge | 92 | * different data direction or already started, don't merge |
87 | */ | 93 | */ |
88 | if (bio_data_dir(bio) != rq_data_dir(rq)) | 94 | if (bio_data_dir(bio) != rq_data_dir(rq)) |
diff --git a/block/ioctl.c b/block/ioctl.c index 09fd7f1ef23a..d8052f0dabd3 100644 --- a/block/ioctl.c +++ b/block/ioctl.c | |||
@@ -114,8 +114,10 @@ static int blkdev_reread_part(struct block_device *bdev) | |||
114 | } | 114 | } |
115 | 115 | ||
116 | static int blk_ioctl_discard(struct block_device *bdev, uint64_t start, | 116 | static int blk_ioctl_discard(struct block_device *bdev, uint64_t start, |
117 | uint64_t len) | 117 | uint64_t len, int secure) |
118 | { | 118 | { |
119 | unsigned long flags = BLKDEV_IFL_WAIT; | ||
120 | |||
119 | if (start & 511) | 121 | if (start & 511) |
120 | return -EINVAL; | 122 | return -EINVAL; |
121 | if (len & 511) | 123 | if (len & 511) |
@@ -125,8 +127,9 @@ static int blk_ioctl_discard(struct block_device *bdev, uint64_t start, | |||
125 | 127 | ||
126 | if (start + len > (bdev->bd_inode->i_size >> 9)) | 128 | if (start + len > (bdev->bd_inode->i_size >> 9)) |
127 | return -EINVAL; | 129 | return -EINVAL; |
128 | return blkdev_issue_discard(bdev, start, len, GFP_KERNEL, | 130 | if (secure) |
129 | BLKDEV_IFL_WAIT); | 131 | flags |= BLKDEV_IFL_SECURE; |
132 | return blkdev_issue_discard(bdev, start, len, GFP_KERNEL, flags); | ||
130 | } | 133 | } |
131 | 134 | ||
132 | static int put_ushort(unsigned long arg, unsigned short val) | 135 | static int put_ushort(unsigned long arg, unsigned short val) |
@@ -213,7 +216,8 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, | |||
213 | set_device_ro(bdev, n); | 216 | set_device_ro(bdev, n); |
214 | return 0; | 217 | return 0; |
215 | 218 | ||
216 | case BLKDISCARD: { | 219 | case BLKDISCARD: |
220 | case BLKSECDISCARD: { | ||
217 | uint64_t range[2]; | 221 | uint64_t range[2]; |
218 | 222 | ||
219 | if (!(mode & FMODE_WRITE)) | 223 | if (!(mode & FMODE_WRITE)) |
@@ -222,7 +226,8 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, | |||
222 | if (copy_from_user(range, (void __user *)arg, sizeof(range))) | 226 | if (copy_from_user(range, (void __user *)arg, sizeof(range))) |
223 | return -EFAULT; | 227 | return -EFAULT; |
224 | 228 | ||
225 | return blk_ioctl_discard(bdev, range[0], range[1]); | 229 | return blk_ioctl_discard(bdev, range[0], range[1], |
230 | cmd == BLKSECDISCARD); | ||
226 | } | 231 | } |
227 | 232 | ||
228 | case HDIO_GETGEO: { | 233 | case HDIO_GETGEO: { |
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index 864dd46c346f..18645f4e83cd 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/uaccess.h> | 33 | #include <linux/uaccess.h> |
34 | #include <linux/cper.h> | 34 | #include <linux/cper.h> |
35 | #include <linux/nmi.h> | 35 | #include <linux/nmi.h> |
36 | #include <linux/hardirq.h> | ||
36 | #include <acpi/apei.h> | 37 | #include <acpi/apei.h> |
37 | 38 | ||
38 | #include "apei-internal.h" | 39 | #include "apei-internal.h" |
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index 146135e7a6a1..295dbfa2db9c 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c | |||
@@ -96,7 +96,8 @@ static const struct acpi_dlevel acpi_debug_levels[] = { | |||
96 | /* -------------------------------------------------------------------------- | 96 | /* -------------------------------------------------------------------------- |
97 | FS Interface (/sys) | 97 | FS Interface (/sys) |
98 | -------------------------------------------------------------------------- */ | 98 | -------------------------------------------------------------------------- */ |
99 | static int param_get_debug_layer(char *buffer, struct kernel_param *kp) { | 99 | static int param_get_debug_layer(char *buffer, const struct kernel_param *kp) |
100 | { | ||
100 | int result = 0; | 101 | int result = 0; |
101 | int i; | 102 | int i; |
102 | 103 | ||
@@ -118,7 +119,8 @@ static int param_get_debug_layer(char *buffer, struct kernel_param *kp) { | |||
118 | return result; | 119 | return result; |
119 | } | 120 | } |
120 | 121 | ||
121 | static int param_get_debug_level(char *buffer, struct kernel_param *kp) { | 122 | static int param_get_debug_level(char *buffer, const struct kernel_param *kp) |
123 | { | ||
122 | int result = 0; | 124 | int result = 0; |
123 | int i; | 125 | int i; |
124 | 126 | ||
@@ -137,8 +139,18 @@ static int param_get_debug_level(char *buffer, struct kernel_param *kp) { | |||
137 | return result; | 139 | return result; |
138 | } | 140 | } |
139 | 141 | ||
140 | module_param_call(debug_layer, param_set_uint, param_get_debug_layer, &acpi_dbg_layer, 0644); | 142 | static struct kernel_param_ops acpi_debug_layer_ops = { |
141 | module_param_call(debug_level, param_set_uint, param_get_debug_level, &acpi_dbg_level, 0644); | 143 | .set = param_set_uint, |
144 | .get = param_get_debug_layer, | ||
145 | }; | ||
146 | |||
147 | static struct kernel_param_ops acpi_debug_level_ops = { | ||
148 | .set = param_set_uint, | ||
149 | .get = param_get_debug_level, | ||
150 | }; | ||
151 | |||
152 | module_param_cb(debug_layer, &acpi_debug_layer_ops, &acpi_dbg_layer, 0644); | ||
153 | module_param_cb(debug_level, &acpi_debug_level_ops, &acpi_dbg_level, 0644); | ||
142 | 154 | ||
143 | static char trace_method_name[6]; | 155 | static char trace_method_name[6]; |
144 | module_param_string(trace_method_name, trace_method_name, 6, 0644); | 156 | module_param_string(trace_method_name, trace_method_name, 6, 0644); |
@@ -147,7 +159,7 @@ module_param(trace_debug_layer, uint, 0644); | |||
147 | static unsigned int trace_debug_level; | 159 | static unsigned int trace_debug_level; |
148 | module_param(trace_debug_level, uint, 0644); | 160 | module_param(trace_debug_level, uint, 0644); |
149 | 161 | ||
150 | static int param_set_trace_state(const char *val, struct kernel_param *kp) | 162 | static int param_set_trace_state(const char *val, const struct kernel_param *kp) |
151 | { | 163 | { |
152 | int result = 0; | 164 | int result = 0; |
153 | 165 | ||
@@ -181,7 +193,7 @@ exit: | |||
181 | return result; | 193 | return result; |
182 | } | 194 | } |
183 | 195 | ||
184 | static int param_get_trace_state(char *buffer, struct kernel_param *kp) | 196 | static int param_get_trace_state(char *buffer, const struct kernel_param *kp) |
185 | { | 197 | { |
186 | if (!acpi_gbl_trace_method_name) | 198 | if (!acpi_gbl_trace_method_name) |
187 | return sprintf(buffer, "disable"); | 199 | return sprintf(buffer, "disable"); |
@@ -194,8 +206,12 @@ static int param_get_trace_state(char *buffer, struct kernel_param *kp) | |||
194 | return 0; | 206 | return 0; |
195 | } | 207 | } |
196 | 208 | ||
197 | module_param_call(trace_state, param_set_trace_state, param_get_trace_state, | 209 | static struct kernel_param_ops param_ops_trace_state = { |
198 | NULL, 0644); | 210 | .set = param_set_trace_state, |
211 | .get = param_get_trace_state, | ||
212 | }; | ||
213 | |||
214 | module_param_cb(trace_state, ¶m_ops_trace_state, NULL, 0644); | ||
199 | 215 | ||
200 | /* -------------------------------------------------------------------------- | 216 | /* -------------------------------------------------------------------------- |
201 | DebugFS Interface | 217 | DebugFS Interface |
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c index f087ab55b1df..8cc536e49a0a 100644 --- a/drivers/ata/pata_mpc52xx.c +++ b/drivers/ata/pata_mpc52xx.c | |||
@@ -680,7 +680,7 @@ mpc52xx_ata_remove_one(struct device *dev) | |||
680 | /* ======================================================================== */ | 680 | /* ======================================================================== */ |
681 | 681 | ||
682 | static int __devinit | 682 | static int __devinit |
683 | mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match) | 683 | mpc52xx_ata_probe(struct platform_device *op, const struct of_device_id *match) |
684 | { | 684 | { |
685 | unsigned int ipb_freq; | 685 | unsigned int ipb_freq; |
686 | struct resource res_mem; | 686 | struct resource res_mem; |
@@ -821,7 +821,7 @@ mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match) | |||
821 | } | 821 | } |
822 | 822 | ||
823 | static int | 823 | static int |
824 | mpc52xx_ata_remove(struct of_device *op) | 824 | mpc52xx_ata_remove(struct platform_device *op) |
825 | { | 825 | { |
826 | struct mpc52xx_ata_priv *priv; | 826 | struct mpc52xx_ata_priv *priv; |
827 | int task_irq; | 827 | int task_irq; |
@@ -848,7 +848,7 @@ mpc52xx_ata_remove(struct of_device *op) | |||
848 | #ifdef CONFIG_PM | 848 | #ifdef CONFIG_PM |
849 | 849 | ||
850 | static int | 850 | static int |
851 | mpc52xx_ata_suspend(struct of_device *op, pm_message_t state) | 851 | mpc52xx_ata_suspend(struct platform_device *op, pm_message_t state) |
852 | { | 852 | { |
853 | struct ata_host *host = dev_get_drvdata(&op->dev); | 853 | struct ata_host *host = dev_get_drvdata(&op->dev); |
854 | 854 | ||
@@ -856,7 +856,7 @@ mpc52xx_ata_suspend(struct of_device *op, pm_message_t state) | |||
856 | } | 856 | } |
857 | 857 | ||
858 | static int | 858 | static int |
859 | mpc52xx_ata_resume(struct of_device *op) | 859 | mpc52xx_ata_resume(struct platform_device *op) |
860 | { | 860 | { |
861 | struct ata_host *host = dev_get_drvdata(&op->dev); | 861 | struct ata_host *host = dev_get_drvdata(&op->dev); |
862 | struct mpc52xx_ata_priv *priv = host->private_data; | 862 | struct mpc52xx_ata_priv *priv = host->private_data; |
diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c index 5a1b82c08be9..480e043ce6b8 100644 --- a/drivers/ata/pata_of_platform.c +++ b/drivers/ata/pata_of_platform.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <linux/of_platform.h> | 14 | #include <linux/of_platform.h> |
15 | #include <linux/ata_platform.h> | 15 | #include <linux/ata_platform.h> |
16 | 16 | ||
17 | static int __devinit pata_of_platform_probe(struct of_device *ofdev, | 17 | static int __devinit pata_of_platform_probe(struct platform_device *ofdev, |
18 | const struct of_device_id *match) | 18 | const struct of_device_id *match) |
19 | { | 19 | { |
20 | int ret; | 20 | int ret; |
@@ -78,7 +78,7 @@ static int __devinit pata_of_platform_probe(struct of_device *ofdev, | |||
78 | reg_shift, pio_mask); | 78 | reg_shift, pio_mask); |
79 | } | 79 | } |
80 | 80 | ||
81 | static int __devexit pata_of_platform_remove(struct of_device *ofdev) | 81 | static int __devexit pata_of_platform_remove(struct platform_device *ofdev) |
82 | { | 82 | { |
83 | return __pata_platform_remove(&ofdev->dev); | 83 | return __pata_platform_remove(&ofdev->dev); |
84 | } | 84 | } |
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index 18c986dbb7f1..7325f77480dc 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c | |||
@@ -1296,7 +1296,7 @@ static const struct ata_port_info sata_fsl_port_info[] = { | |||
1296 | }, | 1296 | }, |
1297 | }; | 1297 | }; |
1298 | 1298 | ||
1299 | static int sata_fsl_probe(struct of_device *ofdev, | 1299 | static int sata_fsl_probe(struct platform_device *ofdev, |
1300 | const struct of_device_id *match) | 1300 | const struct of_device_id *match) |
1301 | { | 1301 | { |
1302 | int retval = -ENXIO; | 1302 | int retval = -ENXIO; |
@@ -1370,7 +1370,7 @@ error_exit_with_cleanup: | |||
1370 | return retval; | 1370 | return retval; |
1371 | } | 1371 | } |
1372 | 1372 | ||
1373 | static int sata_fsl_remove(struct of_device *ofdev) | 1373 | static int sata_fsl_remove(struct platform_device *ofdev) |
1374 | { | 1374 | { |
1375 | struct ata_host *host = dev_get_drvdata(&ofdev->dev); | 1375 | struct ata_host *host = dev_get_drvdata(&ofdev->dev); |
1376 | struct sata_fsl_host_priv *host_priv = host->private_data; | 1376 | struct sata_fsl_host_priv *host_priv = host->private_data; |
@@ -1387,13 +1387,13 @@ static int sata_fsl_remove(struct of_device *ofdev) | |||
1387 | } | 1387 | } |
1388 | 1388 | ||
1389 | #ifdef CONFIG_PM | 1389 | #ifdef CONFIG_PM |
1390 | static int sata_fsl_suspend(struct of_device *op, pm_message_t state) | 1390 | static int sata_fsl_suspend(struct platform_device *op, pm_message_t state) |
1391 | { | 1391 | { |
1392 | struct ata_host *host = dev_get_drvdata(&op->dev); | 1392 | struct ata_host *host = dev_get_drvdata(&op->dev); |
1393 | return ata_host_suspend(host, state); | 1393 | return ata_host_suspend(host, state); |
1394 | } | 1394 | } |
1395 | 1395 | ||
1396 | static int sata_fsl_resume(struct of_device *op) | 1396 | static int sata_fsl_resume(struct platform_device *op) |
1397 | { | 1397 | { |
1398 | struct ata_host *host = dev_get_drvdata(&op->dev); | 1398 | struct ata_host *host = dev_get_drvdata(&op->dev); |
1399 | struct sata_fsl_host_priv *host_priv = host->private_data; | 1399 | struct sata_fsl_host_priv *host_priv = host->private_data; |
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index b7385e077717..c8fc69c85a06 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c | |||
@@ -674,7 +674,7 @@ static void fore200e_sba_write(u32 val, volatile u32 __iomem *addr) | |||
674 | 674 | ||
675 | static u32 fore200e_sba_dma_map(struct fore200e *fore200e, void* virt_addr, int size, int direction) | 675 | static u32 fore200e_sba_dma_map(struct fore200e *fore200e, void* virt_addr, int size, int direction) |
676 | { | 676 | { |
677 | struct of_device *op = fore200e->bus_dev; | 677 | struct platform_device *op = fore200e->bus_dev; |
678 | u32 dma_addr; | 678 | u32 dma_addr; |
679 | 679 | ||
680 | dma_addr = dma_map_single(&op->dev, virt_addr, size, direction); | 680 | dma_addr = dma_map_single(&op->dev, virt_addr, size, direction); |
@@ -687,7 +687,7 @@ static u32 fore200e_sba_dma_map(struct fore200e *fore200e, void* virt_addr, int | |||
687 | 687 | ||
688 | static void fore200e_sba_dma_unmap(struct fore200e *fore200e, u32 dma_addr, int size, int direction) | 688 | static void fore200e_sba_dma_unmap(struct fore200e *fore200e, u32 dma_addr, int size, int direction) |
689 | { | 689 | { |
690 | struct of_device *op = fore200e->bus_dev; | 690 | struct platform_device *op = fore200e->bus_dev; |
691 | 691 | ||
692 | DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n", | 692 | DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n", |
693 | dma_addr, size, direction); | 693 | dma_addr, size, direction); |
@@ -697,7 +697,7 @@ static void fore200e_sba_dma_unmap(struct fore200e *fore200e, u32 dma_addr, int | |||
697 | 697 | ||
698 | static void fore200e_sba_dma_sync_for_cpu(struct fore200e *fore200e, u32 dma_addr, int size, int direction) | 698 | static void fore200e_sba_dma_sync_for_cpu(struct fore200e *fore200e, u32 dma_addr, int size, int direction) |
699 | { | 699 | { |
700 | struct of_device *op = fore200e->bus_dev; | 700 | struct platform_device *op = fore200e->bus_dev; |
701 | 701 | ||
702 | DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); | 702 | DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); |
703 | 703 | ||
@@ -706,7 +706,7 @@ static void fore200e_sba_dma_sync_for_cpu(struct fore200e *fore200e, u32 dma_add | |||
706 | 706 | ||
707 | static void fore200e_sba_dma_sync_for_device(struct fore200e *fore200e, u32 dma_addr, int size, int direction) | 707 | static void fore200e_sba_dma_sync_for_device(struct fore200e *fore200e, u32 dma_addr, int size, int direction) |
708 | { | 708 | { |
709 | struct of_device *op = fore200e->bus_dev; | 709 | struct platform_device *op = fore200e->bus_dev; |
710 | 710 | ||
711 | DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); | 711 | DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); |
712 | 712 | ||
@@ -719,7 +719,7 @@ static void fore200e_sba_dma_sync_for_device(struct fore200e *fore200e, u32 dma_ | |||
719 | static int fore200e_sba_dma_chunk_alloc(struct fore200e *fore200e, struct chunk *chunk, | 719 | static int fore200e_sba_dma_chunk_alloc(struct fore200e *fore200e, struct chunk *chunk, |
720 | int size, int nbr, int alignment) | 720 | int size, int nbr, int alignment) |
721 | { | 721 | { |
722 | struct of_device *op = fore200e->bus_dev; | 722 | struct platform_device *op = fore200e->bus_dev; |
723 | 723 | ||
724 | chunk->alloc_size = chunk->align_size = size * nbr; | 724 | chunk->alloc_size = chunk->align_size = size * nbr; |
725 | 725 | ||
@@ -738,7 +738,7 @@ static int fore200e_sba_dma_chunk_alloc(struct fore200e *fore200e, struct chunk | |||
738 | /* free a DVMA consistent chunk of memory */ | 738 | /* free a DVMA consistent chunk of memory */ |
739 | static void fore200e_sba_dma_chunk_free(struct fore200e *fore200e, struct chunk *chunk) | 739 | static void fore200e_sba_dma_chunk_free(struct fore200e *fore200e, struct chunk *chunk) |
740 | { | 740 | { |
741 | struct of_device *op = fore200e->bus_dev; | 741 | struct platform_device *op = fore200e->bus_dev; |
742 | 742 | ||
743 | dma_free_coherent(&op->dev, chunk->alloc_size, | 743 | dma_free_coherent(&op->dev, chunk->alloc_size, |
744 | chunk->alloc_addr, chunk->dma_addr); | 744 | chunk->alloc_addr, chunk->dma_addr); |
@@ -770,7 +770,7 @@ static void fore200e_sba_reset(struct fore200e *fore200e) | |||
770 | 770 | ||
771 | static int __init fore200e_sba_map(struct fore200e *fore200e) | 771 | static int __init fore200e_sba_map(struct fore200e *fore200e) |
772 | { | 772 | { |
773 | struct of_device *op = fore200e->bus_dev; | 773 | struct platform_device *op = fore200e->bus_dev; |
774 | unsigned int bursts; | 774 | unsigned int bursts; |
775 | 775 | ||
776 | /* gain access to the SBA specific registers */ | 776 | /* gain access to the SBA specific registers */ |
@@ -800,7 +800,7 @@ static int __init fore200e_sba_map(struct fore200e *fore200e) | |||
800 | 800 | ||
801 | static void fore200e_sba_unmap(struct fore200e *fore200e) | 801 | static void fore200e_sba_unmap(struct fore200e *fore200e) |
802 | { | 802 | { |
803 | struct of_device *op = fore200e->bus_dev; | 803 | struct platform_device *op = fore200e->bus_dev; |
804 | 804 | ||
805 | of_iounmap(&op->resource[0], fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH); | 805 | of_iounmap(&op->resource[0], fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH); |
806 | of_iounmap(&op->resource[1], fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH); | 806 | of_iounmap(&op->resource[1], fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH); |
@@ -816,7 +816,7 @@ static int __init fore200e_sba_configure(struct fore200e *fore200e) | |||
816 | 816 | ||
817 | static int __init fore200e_sba_prom_read(struct fore200e *fore200e, struct prom_data *prom) | 817 | static int __init fore200e_sba_prom_read(struct fore200e *fore200e, struct prom_data *prom) |
818 | { | 818 | { |
819 | struct of_device *op = fore200e->bus_dev; | 819 | struct platform_device *op = fore200e->bus_dev; |
820 | const u8 *prop; | 820 | const u8 *prop; |
821 | int len; | 821 | int len; |
822 | 822 | ||
@@ -840,7 +840,7 @@ static int __init fore200e_sba_prom_read(struct fore200e *fore200e, struct prom_ | |||
840 | 840 | ||
841 | static int fore200e_sba_proc_read(struct fore200e *fore200e, char *page) | 841 | static int fore200e_sba_proc_read(struct fore200e *fore200e, char *page) |
842 | { | 842 | { |
843 | struct of_device *op = fore200e->bus_dev; | 843 | struct platform_device *op = fore200e->bus_dev; |
844 | const struct linux_prom_registers *regs; | 844 | const struct linux_prom_registers *regs; |
845 | 845 | ||
846 | regs = of_get_property(op->dev.of_node, "reg", NULL); | 846 | regs = of_get_property(op->dev.of_node, "reg", NULL); |
@@ -2513,7 +2513,7 @@ fore200e_load_and_start_fw(struct fore200e* fore200e) | |||
2513 | device = &((struct pci_dev *) fore200e->bus_dev)->dev; | 2513 | device = &((struct pci_dev *) fore200e->bus_dev)->dev; |
2514 | #ifdef CONFIG_SBUS | 2514 | #ifdef CONFIG_SBUS |
2515 | else if (strcmp(fore200e->bus->model_name, "SBA-200E") == 0) | 2515 | else if (strcmp(fore200e->bus->model_name, "SBA-200E") == 0) |
2516 | device = &((struct of_device *) fore200e->bus_dev)->dev; | 2516 | device = &((struct platform_device *) fore200e->bus_dev)->dev; |
2517 | #endif | 2517 | #endif |
2518 | else | 2518 | else |
2519 | return err; | 2519 | return err; |
@@ -2643,7 +2643,7 @@ fore200e_init(struct fore200e* fore200e) | |||
2643 | } | 2643 | } |
2644 | 2644 | ||
2645 | #ifdef CONFIG_SBUS | 2645 | #ifdef CONFIG_SBUS |
2646 | static int __devinit fore200e_sba_probe(struct of_device *op, | 2646 | static int __devinit fore200e_sba_probe(struct platform_device *op, |
2647 | const struct of_device_id *match) | 2647 | const struct of_device_id *match) |
2648 | { | 2648 | { |
2649 | const struct fore200e_bus *bus = match->data; | 2649 | const struct fore200e_bus *bus = match->data; |
@@ -2675,7 +2675,7 @@ static int __devinit fore200e_sba_probe(struct of_device *op, | |||
2675 | return 0; | 2675 | return 0; |
2676 | } | 2676 | } |
2677 | 2677 | ||
2678 | static int __devexit fore200e_sba_remove(struct of_device *op) | 2678 | static int __devexit fore200e_sba_remove(struct platform_device *op) |
2679 | { | 2679 | { |
2680 | struct fore200e *fore200e = dev_get_drvdata(&op->dev); | 2680 | struct fore200e *fore200e = dev_get_drvdata(&op->dev); |
2681 | 2681 | ||
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index b71888b909a0..2982b3ee9465 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c | |||
@@ -1194,7 +1194,7 @@ static struct platform_driver ace_platform_driver = { | |||
1194 | 1194 | ||
1195 | #if defined(CONFIG_OF) | 1195 | #if defined(CONFIG_OF) |
1196 | static int __devinit | 1196 | static int __devinit |
1197 | ace_of_probe(struct of_device *op, const struct of_device_id *match) | 1197 | ace_of_probe(struct platform_device *op, const struct of_device_id *match) |
1198 | { | 1198 | { |
1199 | struct resource res; | 1199 | struct resource res; |
1200 | resource_size_t physaddr; | 1200 | resource_size_t physaddr; |
@@ -1226,7 +1226,7 @@ ace_of_probe(struct of_device *op, const struct of_device_id *match) | |||
1226 | return ace_alloc(&op->dev, id ? *id : 0, physaddr, irq, bus_width); | 1226 | return ace_alloc(&op->dev, id ? *id : 0, physaddr, irq, bus_width); |
1227 | } | 1227 | } |
1228 | 1228 | ||
1229 | static int __devexit ace_of_remove(struct of_device *op) | 1229 | static int __devexit ace_of_remove(struct platform_device *op) |
1230 | { | 1230 | { |
1231 | ace_free(&op->dev); | 1231 | ace_free(&op->dev); |
1232 | return 0; | 1232 | return 0; |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 7cfcc629a7fd..3d44ec724c17 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -1002,7 +1002,7 @@ config SCx200_GPIO | |||
1002 | 1002 | ||
1003 | config PC8736x_GPIO | 1003 | config PC8736x_GPIO |
1004 | tristate "NatSemi PC8736x GPIO Support" | 1004 | tristate "NatSemi PC8736x GPIO Support" |
1005 | depends on X86 | 1005 | depends on X86_32 |
1006 | default SCx200_GPIO # mostly N | 1006 | default SCx200_GPIO # mostly N |
1007 | select NSC_GPIO # needed for support routines | 1007 | select NSC_GPIO # needed for support routines |
1008 | help | 1008 | help |
diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c index 5a80ad68ef22..7b01bc609de3 100644 --- a/drivers/char/hvc_iucv.c +++ b/drivers/char/hvc_iucv.c | |||
@@ -1149,7 +1149,7 @@ out_err: | |||
1149 | * Note: If it is called early in the boot process, @val is stored and | 1149 | * Note: If it is called early in the boot process, @val is stored and |
1150 | * parsed later in hvc_iucv_init(). | 1150 | * parsed later in hvc_iucv_init(). |
1151 | */ | 1151 | */ |
1152 | static int param_set_vmidfilter(const char *val, struct kernel_param *kp) | 1152 | static int param_set_vmidfilter(const char *val, const struct kernel_param *kp) |
1153 | { | 1153 | { |
1154 | int rc; | 1154 | int rc; |
1155 | 1155 | ||
@@ -1176,7 +1176,7 @@ static int param_set_vmidfilter(const char *val, struct kernel_param *kp) | |||
1176 | * The function stores the filter as a comma-separated list of z/VM user IDs | 1176 | * The function stores the filter as a comma-separated list of z/VM user IDs |
1177 | * in @buffer. Typically, sysfs routines call this function for attr show. | 1177 | * in @buffer. Typically, sysfs routines call this function for attr show. |
1178 | */ | 1178 | */ |
1179 | static int param_get_vmidfilter(char *buffer, struct kernel_param *kp) | 1179 | static int param_get_vmidfilter(char *buffer, const struct kernel_param *kp) |
1180 | { | 1180 | { |
1181 | int rc; | 1181 | int rc; |
1182 | size_t index, len; | 1182 | size_t index, len; |
@@ -1203,6 +1203,11 @@ static int param_get_vmidfilter(char *buffer, struct kernel_param *kp) | |||
1203 | 1203 | ||
1204 | #define param_check_vmidfilter(name, p) __param_check(name, p, void) | 1204 | #define param_check_vmidfilter(name, p) __param_check(name, p, void) |
1205 | 1205 | ||
1206 | static struct kernel_param_ops param_ops_vmidfilter = { | ||
1207 | .set = param_set_vmidfilter, | ||
1208 | .get = param_get_vmidfilter, | ||
1209 | }; | ||
1210 | |||
1206 | /** | 1211 | /** |
1207 | * hvc_iucv_init() - z/VM IUCV HVC device driver initialization | 1212 | * hvc_iucv_init() - z/VM IUCV HVC device driver initialization |
1208 | */ | 1213 | */ |
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index 7a4f080f8356..1acdb2509511 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c | |||
@@ -619,7 +619,7 @@ static void __devinit n2rng_driver_version(void) | |||
619 | pr_info("%s", version); | 619 | pr_info("%s", version); |
620 | } | 620 | } |
621 | 621 | ||
622 | static int __devinit n2rng_probe(struct of_device *op, | 622 | static int __devinit n2rng_probe(struct platform_device *op, |
623 | const struct of_device_id *match) | 623 | const struct of_device_id *match) |
624 | { | 624 | { |
625 | int victoria_falls = (match->data != NULL); | 625 | int victoria_falls = (match->data != NULL); |
@@ -714,7 +714,7 @@ out: | |||
714 | return err; | 714 | return err; |
715 | } | 715 | } |
716 | 716 | ||
717 | static int __devexit n2rng_remove(struct of_device *op) | 717 | static int __devexit n2rng_remove(struct platform_device *op) |
718 | { | 718 | { |
719 | struct n2rng *np = dev_get_drvdata(&op->dev); | 719 | struct n2rng *np = dev_get_drvdata(&op->dev); |
720 | 720 | ||
diff --git a/drivers/char/hw_random/n2rng.h b/drivers/char/hw_random/n2rng.h index a2b81e7bfc18..4bea07f30978 100644 --- a/drivers/char/hw_random/n2rng.h +++ b/drivers/char/hw_random/n2rng.h | |||
@@ -65,7 +65,7 @@ struct n2rng_unit { | |||
65 | }; | 65 | }; |
66 | 66 | ||
67 | struct n2rng { | 67 | struct n2rng { |
68 | struct of_device *op; | 68 | struct platform_device *op; |
69 | 69 | ||
70 | unsigned long flags; | 70 | unsigned long flags; |
71 | #define N2RNG_FLAG_VF 0x00000001 /* Victoria Falls RNG, else N2 */ | 71 | #define N2RNG_FLAG_VF 0x00000001 /* Victoria Falls RNG, else N2 */ |
diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c index 261ba8f22b8b..a31c830ca8cd 100644 --- a/drivers/char/hw_random/pasemi-rng.c +++ b/drivers/char/hw_random/pasemi-rng.c | |||
@@ -94,7 +94,7 @@ static struct hwrng pasemi_rng = { | |||
94 | .data_read = pasemi_rng_data_read, | 94 | .data_read = pasemi_rng_data_read, |
95 | }; | 95 | }; |
96 | 96 | ||
97 | static int __devinit rng_probe(struct of_device *ofdev, | 97 | static int __devinit rng_probe(struct platform_device *ofdev, |
98 | const struct of_device_id *match) | 98 | const struct of_device_id *match) |
99 | { | 99 | { |
100 | void __iomem *rng_regs; | 100 | void __iomem *rng_regs; |
@@ -123,7 +123,7 @@ static int __devinit rng_probe(struct of_device *ofdev, | |||
123 | return err; | 123 | return err; |
124 | } | 124 | } |
125 | 125 | ||
126 | static int __devexit rng_remove(struct of_device *dev) | 126 | static int __devexit rng_remove(struct platform_device *dev) |
127 | { | 127 | { |
128 | void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv; | 128 | void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv; |
129 | 129 | ||
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 48330e0fd488..3822b4f49c84 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -2528,7 +2528,7 @@ static struct pci_driver ipmi_pci_driver = { | |||
2528 | 2528 | ||
2529 | 2529 | ||
2530 | #ifdef CONFIG_PPC_OF | 2530 | #ifdef CONFIG_PPC_OF |
2531 | static int __devinit ipmi_of_probe(struct of_device *dev, | 2531 | static int __devinit ipmi_of_probe(struct platform_device *dev, |
2532 | const struct of_device_id *match) | 2532 | const struct of_device_id *match) |
2533 | { | 2533 | { |
2534 | struct smi_info *info; | 2534 | struct smi_info *info; |
@@ -2607,7 +2607,7 @@ static int __devinit ipmi_of_probe(struct of_device *dev, | |||
2607 | return 0; | 2607 | return 0; |
2608 | } | 2608 | } |
2609 | 2609 | ||
2610 | static int __devexit ipmi_of_remove(struct of_device *dev) | 2610 | static int __devexit ipmi_of_remove(struct platform_device *dev) |
2611 | { | 2611 | { |
2612 | cleanup_one_si(dev_get_drvdata(&dev->dev)); | 2612 | cleanup_one_si(dev_get_drvdata(&dev->dev)); |
2613 | return 0; | 2613 | return 0; |
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 82bcdb262a3a..654d566ca57c 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c | |||
@@ -196,7 +196,7 @@ static void ipmi_unregister_watchdog(int ipmi_intf); | |||
196 | */ | 196 | */ |
197 | static int start_now; | 197 | static int start_now; |
198 | 198 | ||
199 | static int set_param_int(const char *val, struct kernel_param *kp) | 199 | static int set_param_timeout(const char *val, const struct kernel_param *kp) |
200 | { | 200 | { |
201 | char *endp; | 201 | char *endp; |
202 | int l; | 202 | int l; |
@@ -215,10 +215,11 @@ static int set_param_int(const char *val, struct kernel_param *kp) | |||
215 | return rv; | 215 | return rv; |
216 | } | 216 | } |
217 | 217 | ||
218 | static int get_param_int(char *buffer, struct kernel_param *kp) | 218 | static struct kernel_param_ops param_ops_timeout = { |
219 | { | 219 | .set = set_param_timeout, |
220 | return sprintf(buffer, "%i", *((int *)kp->arg)); | 220 | .get = param_get_int, |
221 | } | 221 | }; |
222 | #define param_check_timeout param_check_int | ||
222 | 223 | ||
223 | typedef int (*action_fn)(const char *intval, char *outval); | 224 | typedef int (*action_fn)(const char *intval, char *outval); |
224 | 225 | ||
@@ -227,7 +228,7 @@ static int preaction_op(const char *inval, char *outval); | |||
227 | static int preop_op(const char *inval, char *outval); | 228 | static int preop_op(const char *inval, char *outval); |
228 | static void check_parms(void); | 229 | static void check_parms(void); |
229 | 230 | ||
230 | static int set_param_str(const char *val, struct kernel_param *kp) | 231 | static int set_param_str(const char *val, const struct kernel_param *kp) |
231 | { | 232 | { |
232 | action_fn fn = (action_fn) kp->arg; | 233 | action_fn fn = (action_fn) kp->arg; |
233 | int rv = 0; | 234 | int rv = 0; |
@@ -251,7 +252,7 @@ static int set_param_str(const char *val, struct kernel_param *kp) | |||
251 | return rv; | 252 | return rv; |
252 | } | 253 | } |
253 | 254 | ||
254 | static int get_param_str(char *buffer, struct kernel_param *kp) | 255 | static int get_param_str(char *buffer, const struct kernel_param *kp) |
255 | { | 256 | { |
256 | action_fn fn = (action_fn) kp->arg; | 257 | action_fn fn = (action_fn) kp->arg; |
257 | int rv; | 258 | int rv; |
@@ -263,7 +264,7 @@ static int get_param_str(char *buffer, struct kernel_param *kp) | |||
263 | } | 264 | } |
264 | 265 | ||
265 | 266 | ||
266 | static int set_param_wdog_ifnum(const char *val, struct kernel_param *kp) | 267 | static int set_param_wdog_ifnum(const char *val, const struct kernel_param *kp) |
267 | { | 268 | { |
268 | int rv = param_set_int(val, kp); | 269 | int rv = param_set_int(val, kp); |
269 | if (rv) | 270 | if (rv) |
@@ -276,27 +277,38 @@ static int set_param_wdog_ifnum(const char *val, struct kernel_param *kp) | |||
276 | return 0; | 277 | return 0; |
277 | } | 278 | } |
278 | 279 | ||
279 | module_param_call(ifnum_to_use, set_param_wdog_ifnum, get_param_int, | 280 | static struct kernel_param_ops param_ops_wdog_ifnum = { |
280 | &ifnum_to_use, 0644); | 281 | .set = set_param_wdog_ifnum, |
282 | .get = param_get_int, | ||
283 | }; | ||
284 | |||
285 | #define param_check_wdog_ifnum param_check_int | ||
286 | |||
287 | static struct kernel_param_ops param_ops_str = { | ||
288 | .set = set_param_str, | ||
289 | .get = get_param_str, | ||
290 | }; | ||
291 | |||
292 | module_param(ifnum_to_use, wdog_ifnum, 0644); | ||
281 | MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog " | 293 | MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog " |
282 | "timer. Setting to -1 defaults to the first registered " | 294 | "timer. Setting to -1 defaults to the first registered " |
283 | "interface"); | 295 | "interface"); |
284 | 296 | ||
285 | module_param_call(timeout, set_param_int, get_param_int, &timeout, 0644); | 297 | module_param(timeout, timeout, 0644); |
286 | MODULE_PARM_DESC(timeout, "Timeout value in seconds."); | 298 | MODULE_PARM_DESC(timeout, "Timeout value in seconds."); |
287 | 299 | ||
288 | module_param_call(pretimeout, set_param_int, get_param_int, &pretimeout, 0644); | 300 | module_param(pretimeout, timeout, 0644); |
289 | MODULE_PARM_DESC(pretimeout, "Pretimeout value in seconds."); | 301 | MODULE_PARM_DESC(pretimeout, "Pretimeout value in seconds."); |
290 | 302 | ||
291 | module_param_call(action, set_param_str, get_param_str, action_op, 0644); | 303 | module_param_cb(action, ¶m_ops_str, action_op, 0644); |
292 | MODULE_PARM_DESC(action, "Timeout action. One of: " | 304 | MODULE_PARM_DESC(action, "Timeout action. One of: " |
293 | "reset, none, power_cycle, power_off."); | 305 | "reset, none, power_cycle, power_off."); |
294 | 306 | ||
295 | module_param_call(preaction, set_param_str, get_param_str, preaction_op, 0644); | 307 | module_param_cb(preaction, ¶m_ops_str, preaction_op, 0644); |
296 | MODULE_PARM_DESC(preaction, "Pretimeout action. One of: " | 308 | MODULE_PARM_DESC(preaction, "Pretimeout action. One of: " |
297 | "pre_none, pre_smi, pre_nmi, pre_int."); | 309 | "pre_none, pre_smi, pre_nmi, pre_int."); |
298 | 310 | ||
299 | module_param_call(preop, set_param_str, get_param_str, preop_op, 0644); | 311 | module_param_cb(preop, ¶m_ops_str, preop_op, 0644); |
300 | MODULE_PARM_DESC(preop, "Pretimeout driver operation. One of: " | 312 | MODULE_PARM_DESC(preop, "Pretimeout driver operation. One of: " |
301 | "preop_none, preop_panic, preop_give_data."); | 313 | "preop_none, preop_panic, preop_give_data."); |
302 | 314 | ||
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 95acb8c880f4..dfa8b3062fda 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
@@ -961,7 +961,7 @@ static int __init rtc_init(void) | |||
961 | #endif | 961 | #endif |
962 | #ifdef CONFIG_SPARC32 | 962 | #ifdef CONFIG_SPARC32 |
963 | struct device_node *ebus_dp; | 963 | struct device_node *ebus_dp; |
964 | struct of_device *op; | 964 | struct platform_device *op; |
965 | #else | 965 | #else |
966 | void *r; | 966 | void *r; |
967 | #ifdef RTC_IRQ | 967 | #ifdef RTC_IRQ |
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index ed8a9cec2a05..0ed763cd2e77 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c | |||
@@ -761,7 +761,7 @@ static struct platform_driver hwicap_platform_driver = { | |||
761 | 761 | ||
762 | #if defined(CONFIG_OF) | 762 | #if defined(CONFIG_OF) |
763 | static int __devinit | 763 | static int __devinit |
764 | hwicap_of_probe(struct of_device *op, const struct of_device_id *match) | 764 | hwicap_of_probe(struct platform_device *op, const struct of_device_id *match) |
765 | { | 765 | { |
766 | struct resource res; | 766 | struct resource res; |
767 | const unsigned int *id; | 767 | const unsigned int *id; |
@@ -798,7 +798,7 @@ hwicap_of_probe(struct of_device *op, const struct of_device_id *match) | |||
798 | regs); | 798 | regs); |
799 | } | 799 | } |
800 | 800 | ||
801 | static int __devexit hwicap_of_remove(struct of_device *op) | 801 | static int __devexit hwicap_of_remove(struct platform_device *op) |
802 | { | 802 | { |
803 | return hwicap_remove(&op->dev); | 803 | return hwicap_remove(&op->dev); |
804 | } | 804 | } |
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c index 983530ba04a7..2b1baee525bc 100644 --- a/drivers/crypto/amcc/crypto4xx_core.c +++ b/drivers/crypto/amcc/crypto4xx_core.c | |||
@@ -1150,7 +1150,7 @@ struct crypto4xx_alg_common crypto4xx_alg[] = { | |||
1150 | /** | 1150 | /** |
1151 | * Module Initialization Routine | 1151 | * Module Initialization Routine |
1152 | */ | 1152 | */ |
1153 | static int __init crypto4xx_probe(struct of_device *ofdev, | 1153 | static int __init crypto4xx_probe(struct platform_device *ofdev, |
1154 | const struct of_device_id *match) | 1154 | const struct of_device_id *match) |
1155 | { | 1155 | { |
1156 | int rc; | 1156 | int rc; |
@@ -1258,7 +1258,7 @@ err_alloc_dev: | |||
1258 | return rc; | 1258 | return rc; |
1259 | } | 1259 | } |
1260 | 1260 | ||
1261 | static int __exit crypto4xx_remove(struct of_device *ofdev) | 1261 | static int __exit crypto4xx_remove(struct platform_device *ofdev) |
1262 | { | 1262 | { |
1263 | struct device *dev = &ofdev->dev; | 1263 | struct device *dev = &ofdev->dev; |
1264 | struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev); | 1264 | struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev); |
diff --git a/drivers/crypto/amcc/crypto4xx_core.h b/drivers/crypto/amcc/crypto4xx_core.h index da9cbe3b9fc3..bac0bdeb4b5f 100644 --- a/drivers/crypto/amcc/crypto4xx_core.h +++ b/drivers/crypto/amcc/crypto4xx_core.h | |||
@@ -104,7 +104,7 @@ struct crypto4xx_device { | |||
104 | 104 | ||
105 | struct crypto4xx_core_device { | 105 | struct crypto4xx_core_device { |
106 | struct device *device; | 106 | struct device *device; |
107 | struct of_device *ofdev; | 107 | struct platform_device *ofdev; |
108 | struct crypto4xx_device *dev; | 108 | struct crypto4xx_device *dev; |
109 | u32 int_status; | 109 | u32 int_status; |
110 | u32 irq; | 110 | u32 irq; |
diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c index 26af2dd5d831..88ee01510ec0 100644 --- a/drivers/crypto/n2_core.c +++ b/drivers/crypto/n2_core.c | |||
@@ -1552,7 +1552,7 @@ static void __exit n2_unregister_algs(void) | |||
1552 | 1552 | ||
1553 | /* To map CWQ queues to interrupt sources, the hypervisor API provides | 1553 | /* To map CWQ queues to interrupt sources, the hypervisor API provides |
1554 | * a devino. This isn't very useful to us because all of the | 1554 | * a devino. This isn't very useful to us because all of the |
1555 | * interrupts listed in the of_device node have been translated to | 1555 | * interrupts listed in the device_node have been translated to |
1556 | * Linux virtual IRQ cookie numbers. | 1556 | * Linux virtual IRQ cookie numbers. |
1557 | * | 1557 | * |
1558 | * So we have to back-translate, going through the 'intr' and 'ino' | 1558 | * So we have to back-translate, going through the 'intr' and 'ino' |
@@ -1560,7 +1560,7 @@ static void __exit n2_unregister_algs(void) | |||
1560 | * 'interrupts' property entries, in order to to figure out which | 1560 | * 'interrupts' property entries, in order to to figure out which |
1561 | * devino goes to which already-translated IRQ. | 1561 | * devino goes to which already-translated IRQ. |
1562 | */ | 1562 | */ |
1563 | static int find_devino_index(struct of_device *dev, struct spu_mdesc_info *ip, | 1563 | static int find_devino_index(struct platform_device *dev, struct spu_mdesc_info *ip, |
1564 | unsigned long dev_ino) | 1564 | unsigned long dev_ino) |
1565 | { | 1565 | { |
1566 | const unsigned int *dev_intrs; | 1566 | const unsigned int *dev_intrs; |
@@ -1580,7 +1580,7 @@ static int find_devino_index(struct of_device *dev, struct spu_mdesc_info *ip, | |||
1580 | if (!dev_intrs) | 1580 | if (!dev_intrs) |
1581 | return -ENODEV; | 1581 | return -ENODEV; |
1582 | 1582 | ||
1583 | for (i = 0; i < dev->num_irqs; i++) { | 1583 | for (i = 0; i < dev->archdata.num_irqs; i++) { |
1584 | if (dev_intrs[i] == intr) | 1584 | if (dev_intrs[i] == intr) |
1585 | return i; | 1585 | return i; |
1586 | } | 1586 | } |
@@ -1588,7 +1588,7 @@ static int find_devino_index(struct of_device *dev, struct spu_mdesc_info *ip, | |||
1588 | return -ENODEV; | 1588 | return -ENODEV; |
1589 | } | 1589 | } |
1590 | 1590 | ||
1591 | static int spu_map_ino(struct of_device *dev, struct spu_mdesc_info *ip, | 1591 | static int spu_map_ino(struct platform_device *dev, struct spu_mdesc_info *ip, |
1592 | const char *irq_name, struct spu_queue *p, | 1592 | const char *irq_name, struct spu_queue *p, |
1593 | irq_handler_t handler) | 1593 | irq_handler_t handler) |
1594 | { | 1594 | { |
@@ -1603,7 +1603,7 @@ static int spu_map_ino(struct of_device *dev, struct spu_mdesc_info *ip, | |||
1603 | if (index < 0) | 1603 | if (index < 0) |
1604 | return index; | 1604 | return index; |
1605 | 1605 | ||
1606 | p->irq = dev->irqs[index]; | 1606 | p->irq = dev->archdata.irqs[index]; |
1607 | 1607 | ||
1608 | sprintf(p->irq_name, "%s-%d", irq_name, index); | 1608 | sprintf(p->irq_name, "%s-%d", irq_name, index); |
1609 | 1609 | ||
@@ -1736,7 +1736,7 @@ static void spu_list_destroy(struct list_head *list) | |||
1736 | * gathering cpu membership information. | 1736 | * gathering cpu membership information. |
1737 | */ | 1737 | */ |
1738 | static int spu_mdesc_walk_arcs(struct mdesc_handle *mdesc, | 1738 | static int spu_mdesc_walk_arcs(struct mdesc_handle *mdesc, |
1739 | struct of_device *dev, | 1739 | struct platform_device *dev, |
1740 | u64 node, struct spu_queue *p, | 1740 | u64 node, struct spu_queue *p, |
1741 | struct spu_queue **table) | 1741 | struct spu_queue **table) |
1742 | { | 1742 | { |
@@ -1763,7 +1763,7 @@ static int spu_mdesc_walk_arcs(struct mdesc_handle *mdesc, | |||
1763 | 1763 | ||
1764 | /* Process an 'exec-unit' MDESC node of type 'cwq'. */ | 1764 | /* Process an 'exec-unit' MDESC node of type 'cwq'. */ |
1765 | static int handle_exec_unit(struct spu_mdesc_info *ip, struct list_head *list, | 1765 | static int handle_exec_unit(struct spu_mdesc_info *ip, struct list_head *list, |
1766 | struct of_device *dev, struct mdesc_handle *mdesc, | 1766 | struct platform_device *dev, struct mdesc_handle *mdesc, |
1767 | u64 node, const char *iname, unsigned long q_type, | 1767 | u64 node, const char *iname, unsigned long q_type, |
1768 | irq_handler_t handler, struct spu_queue **table) | 1768 | irq_handler_t handler, struct spu_queue **table) |
1769 | { | 1769 | { |
@@ -1794,7 +1794,7 @@ static int handle_exec_unit(struct spu_mdesc_info *ip, struct list_head *list, | |||
1794 | return spu_map_ino(dev, ip, iname, p, handler); | 1794 | return spu_map_ino(dev, ip, iname, p, handler); |
1795 | } | 1795 | } |
1796 | 1796 | ||
1797 | static int spu_mdesc_scan(struct mdesc_handle *mdesc, struct of_device *dev, | 1797 | static int spu_mdesc_scan(struct mdesc_handle *mdesc, struct platform_device *dev, |
1798 | struct spu_mdesc_info *ip, struct list_head *list, | 1798 | struct spu_mdesc_info *ip, struct list_head *list, |
1799 | const char *exec_name, unsigned long q_type, | 1799 | const char *exec_name, unsigned long q_type, |
1800 | irq_handler_t handler, struct spu_queue **table) | 1800 | irq_handler_t handler, struct spu_queue **table) |
@@ -1855,7 +1855,7 @@ static int __devinit get_irq_props(struct mdesc_handle *mdesc, u64 node, | |||
1855 | } | 1855 | } |
1856 | 1856 | ||
1857 | static int __devinit grab_mdesc_irq_props(struct mdesc_handle *mdesc, | 1857 | static int __devinit grab_mdesc_irq_props(struct mdesc_handle *mdesc, |
1858 | struct of_device *dev, | 1858 | struct platform_device *dev, |
1859 | struct spu_mdesc_info *ip, | 1859 | struct spu_mdesc_info *ip, |
1860 | const char *node_name) | 1860 | const char *node_name) |
1861 | { | 1861 | { |
@@ -2004,7 +2004,7 @@ static void __devinit n2_spu_driver_version(void) | |||
2004 | pr_info("%s", version); | 2004 | pr_info("%s", version); |
2005 | } | 2005 | } |
2006 | 2006 | ||
2007 | static int __devinit n2_crypto_probe(struct of_device *dev, | 2007 | static int __devinit n2_crypto_probe(struct platform_device *dev, |
2008 | const struct of_device_id *match) | 2008 | const struct of_device_id *match) |
2009 | { | 2009 | { |
2010 | struct mdesc_handle *mdesc; | 2010 | struct mdesc_handle *mdesc; |
@@ -2081,7 +2081,7 @@ out_free_n2cp: | |||
2081 | return err; | 2081 | return err; |
2082 | } | 2082 | } |
2083 | 2083 | ||
2084 | static int __devexit n2_crypto_remove(struct of_device *dev) | 2084 | static int __devexit n2_crypto_remove(struct platform_device *dev) |
2085 | { | 2085 | { |
2086 | struct n2_crypto *np = dev_get_drvdata(&dev->dev); | 2086 | struct n2_crypto *np = dev_get_drvdata(&dev->dev); |
2087 | 2087 | ||
@@ -2116,7 +2116,7 @@ static void free_ncp(struct n2_mau *mp) | |||
2116 | kfree(mp); | 2116 | kfree(mp); |
2117 | } | 2117 | } |
2118 | 2118 | ||
2119 | static int __devinit n2_mau_probe(struct of_device *dev, | 2119 | static int __devinit n2_mau_probe(struct platform_device *dev, |
2120 | const struct of_device_id *match) | 2120 | const struct of_device_id *match) |
2121 | { | 2121 | { |
2122 | struct mdesc_handle *mdesc; | 2122 | struct mdesc_handle *mdesc; |
@@ -2184,7 +2184,7 @@ out_free_ncp: | |||
2184 | return err; | 2184 | return err; |
2185 | } | 2185 | } |
2186 | 2186 | ||
2187 | static int __devexit n2_mau_remove(struct of_device *dev) | 2187 | static int __devexit n2_mau_remove(struct platform_device *dev) |
2188 | { | 2188 | { |
2189 | struct n2_mau *mp = dev_get_drvdata(&dev->dev); | 2189 | struct n2_mau *mp = dev_get_drvdata(&dev->dev); |
2190 | 2190 | ||
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 97f4af1d8a64..4bcd825b5739 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c | |||
@@ -118,7 +118,7 @@ struct talitos_channel { | |||
118 | 118 | ||
119 | struct talitos_private { | 119 | struct talitos_private { |
120 | struct device *dev; | 120 | struct device *dev; |
121 | struct of_device *ofdev; | 121 | struct platform_device *ofdev; |
122 | void __iomem *reg; | 122 | void __iomem *reg; |
123 | int irq; | 123 | int irq; |
124 | 124 | ||
@@ -2308,7 +2308,7 @@ static int hw_supports(struct device *dev, __be32 desc_hdr_template) | |||
2308 | return ret; | 2308 | return ret; |
2309 | } | 2309 | } |
2310 | 2310 | ||
2311 | static int talitos_remove(struct of_device *ofdev) | 2311 | static int talitos_remove(struct platform_device *ofdev) |
2312 | { | 2312 | { |
2313 | struct device *dev = &ofdev->dev; | 2313 | struct device *dev = &ofdev->dev; |
2314 | struct talitos_private *priv = dev_get_drvdata(dev); | 2314 | struct talitos_private *priv = dev_get_drvdata(dev); |
@@ -2401,7 +2401,7 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev, | |||
2401 | return t_alg; | 2401 | return t_alg; |
2402 | } | 2402 | } |
2403 | 2403 | ||
2404 | static int talitos_probe(struct of_device *ofdev, | 2404 | static int talitos_probe(struct platform_device *ofdev, |
2405 | const struct of_device_id *match) | 2405 | const struct of_device_id *match) |
2406 | { | 2406 | { |
2407 | struct device *dev = &ofdev->dev; | 2407 | struct device *dev = &ofdev->dev; |
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index f0fd6db6063c..cea08bed9cf9 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c | |||
@@ -1297,7 +1297,7 @@ static void fsl_dma_chan_remove(struct fsldma_chan *chan) | |||
1297 | kfree(chan); | 1297 | kfree(chan); |
1298 | } | 1298 | } |
1299 | 1299 | ||
1300 | static int __devinit fsldma_of_probe(struct of_device *op, | 1300 | static int __devinit fsldma_of_probe(struct platform_device *op, |
1301 | const struct of_device_id *match) | 1301 | const struct of_device_id *match) |
1302 | { | 1302 | { |
1303 | struct fsldma_device *fdev; | 1303 | struct fsldma_device *fdev; |
@@ -1382,7 +1382,7 @@ out_return: | |||
1382 | return err; | 1382 | return err; |
1383 | } | 1383 | } |
1384 | 1384 | ||
1385 | static int fsldma_of_remove(struct of_device *op) | 1385 | static int fsldma_of_remove(struct platform_device *op) |
1386 | { | 1386 | { |
1387 | struct fsldma_device *fdev; | 1387 | struct fsldma_device *fdev; |
1388 | unsigned int i; | 1388 | unsigned int i; |
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c index 14a8c0f1698e..4e9cbf300594 100644 --- a/drivers/dma/mpc512x_dma.c +++ b/drivers/dma/mpc512x_dma.c | |||
@@ -627,7 +627,7 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, | |||
627 | return &mdesc->desc; | 627 | return &mdesc->desc; |
628 | } | 628 | } |
629 | 629 | ||
630 | static int __devinit mpc_dma_probe(struct of_device *op, | 630 | static int __devinit mpc_dma_probe(struct platform_device *op, |
631 | const struct of_device_id *match) | 631 | const struct of_device_id *match) |
632 | { | 632 | { |
633 | struct device_node *dn = op->dev.of_node; | 633 | struct device_node *dn = op->dev.of_node; |
@@ -753,7 +753,7 @@ static int __devinit mpc_dma_probe(struct of_device *op, | |||
753 | return retval; | 753 | return retval; |
754 | } | 754 | } |
755 | 755 | ||
756 | static int __devexit mpc_dma_remove(struct of_device *op) | 756 | static int __devexit mpc_dma_remove(struct platform_device *op) |
757 | { | 757 | { |
758 | struct device *dev = &op->dev; | 758 | struct device *dev = &op->dev; |
759 | struct mpc_dma *mdma = dev_get_drvdata(dev); | 759 | struct mpc_dma *mdma = dev_get_drvdata(dev); |
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c index 7c3747902a37..0d58a4a4487f 100644 --- a/drivers/dma/ppc4xx/adma.c +++ b/drivers/dma/ppc4xx/adma.c | |||
@@ -4257,11 +4257,11 @@ static int ppc440spe_adma_setup_irqs(struct ppc440spe_adma_device *adev, | |||
4257 | struct ppc440spe_adma_chan *chan, | 4257 | struct ppc440spe_adma_chan *chan, |
4258 | int *initcode) | 4258 | int *initcode) |
4259 | { | 4259 | { |
4260 | struct of_device *ofdev; | 4260 | struct platform_device *ofdev; |
4261 | struct device_node *np; | 4261 | struct device_node *np; |
4262 | int ret; | 4262 | int ret; |
4263 | 4263 | ||
4264 | ofdev = container_of(adev->dev, struct of_device, dev); | 4264 | ofdev = container_of(adev->dev, struct platform_device, dev); |
4265 | np = ofdev->dev.of_node; | 4265 | np = ofdev->dev.of_node; |
4266 | if (adev->id != PPC440SPE_XOR_ID) { | 4266 | if (adev->id != PPC440SPE_XOR_ID) { |
4267 | adev->err_irq = irq_of_parse_and_map(np, 1); | 4267 | adev->err_irq = irq_of_parse_and_map(np, 1); |
@@ -4393,7 +4393,7 @@ static void ppc440spe_adma_release_irqs(struct ppc440spe_adma_device *adev, | |||
4393 | /** | 4393 | /** |
4394 | * ppc440spe_adma_probe - probe the asynch device | 4394 | * ppc440spe_adma_probe - probe the asynch device |
4395 | */ | 4395 | */ |
4396 | static int __devinit ppc440spe_adma_probe(struct of_device *ofdev, | 4396 | static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev, |
4397 | const struct of_device_id *match) | 4397 | const struct of_device_id *match) |
4398 | { | 4398 | { |
4399 | struct device_node *np = ofdev->dev.of_node; | 4399 | struct device_node *np = ofdev->dev.of_node; |
@@ -4625,7 +4625,7 @@ out: | |||
4625 | /** | 4625 | /** |
4626 | * ppc440spe_adma_remove - remove the asynch device | 4626 | * ppc440spe_adma_remove - remove the asynch device |
4627 | */ | 4627 | */ |
4628 | static int __devexit ppc440spe_adma_remove(struct of_device *ofdev) | 4628 | static int __devexit ppc440spe_adma_remove(struct platform_device *ofdev) |
4629 | { | 4629 | { |
4630 | struct ppc440spe_adma_device *adev = dev_get_drvdata(&ofdev->dev); | 4630 | struct ppc440spe_adma_device *adev = dev_get_drvdata(&ofdev->dev); |
4631 | struct device_node *np = ofdev->dev.of_node; | 4631 | struct device_node *np = ofdev->dev.of_node; |
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index af75e27f5224..b123bb308a4a 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c | |||
@@ -200,7 +200,7 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id) | |||
200 | return IRQ_HANDLED; | 200 | return IRQ_HANDLED; |
201 | } | 201 | } |
202 | 202 | ||
203 | static int __devinit mpc85xx_pci_err_probe(struct of_device *op, | 203 | static int __devinit mpc85xx_pci_err_probe(struct platform_device *op, |
204 | const struct of_device_id *match) | 204 | const struct of_device_id *match) |
205 | { | 205 | { |
206 | struct edac_pci_ctl_info *pci; | 206 | struct edac_pci_ctl_info *pci; |
@@ -305,7 +305,7 @@ err: | |||
305 | return res; | 305 | return res; |
306 | } | 306 | } |
307 | 307 | ||
308 | static int mpc85xx_pci_err_remove(struct of_device *op) | 308 | static int mpc85xx_pci_err_remove(struct platform_device *op) |
309 | { | 309 | { |
310 | struct edac_pci_ctl_info *pci = dev_get_drvdata(&op->dev); | 310 | struct edac_pci_ctl_info *pci = dev_get_drvdata(&op->dev); |
311 | struct mpc85xx_pci_pdata *pdata = pci->pvt_info; | 311 | struct mpc85xx_pci_pdata *pdata = pci->pvt_info; |
@@ -503,7 +503,7 @@ static irqreturn_t mpc85xx_l2_isr(int irq, void *dev_id) | |||
503 | return IRQ_HANDLED; | 503 | return IRQ_HANDLED; |
504 | } | 504 | } |
505 | 505 | ||
506 | static int __devinit mpc85xx_l2_err_probe(struct of_device *op, | 506 | static int __devinit mpc85xx_l2_err_probe(struct platform_device *op, |
507 | const struct of_device_id *match) | 507 | const struct of_device_id *match) |
508 | { | 508 | { |
509 | struct edac_device_ctl_info *edac_dev; | 509 | struct edac_device_ctl_info *edac_dev; |
@@ -613,7 +613,7 @@ err: | |||
613 | return res; | 613 | return res; |
614 | } | 614 | } |
615 | 615 | ||
616 | static int mpc85xx_l2_err_remove(struct of_device *op) | 616 | static int mpc85xx_l2_err_remove(struct platform_device *op) |
617 | { | 617 | { |
618 | struct edac_device_ctl_info *edac_dev = dev_get_drvdata(&op->dev); | 618 | struct edac_device_ctl_info *edac_dev = dev_get_drvdata(&op->dev); |
619 | struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info; | 619 | struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info; |
@@ -956,7 +956,7 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci) | |||
956 | } | 956 | } |
957 | } | 957 | } |
958 | 958 | ||
959 | static int __devinit mpc85xx_mc_err_probe(struct of_device *op, | 959 | static int __devinit mpc85xx_mc_err_probe(struct platform_device *op, |
960 | const struct of_device_id *match) | 960 | const struct of_device_id *match) |
961 | { | 961 | { |
962 | struct mem_ctl_info *mci; | 962 | struct mem_ctl_info *mci; |
@@ -1088,7 +1088,7 @@ err: | |||
1088 | return res; | 1088 | return res; |
1089 | } | 1089 | } |
1090 | 1090 | ||
1091 | static int mpc85xx_mc_err_remove(struct of_device *op) | 1091 | static int mpc85xx_mc_err_remove(struct platform_device *op) |
1092 | { | 1092 | { |
1093 | struct mem_ctl_info *mci = dev_get_drvdata(&op->dev); | 1093 | struct mem_ctl_info *mci = dev_get_drvdata(&op->dev); |
1094 | struct mpc85xx_mc_pdata *pdata = mci->pvt_info; | 1094 | struct mpc85xx_mc_pdata *pdata = mci->pvt_info; |
diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c index e78839e89a06..070cea41b661 100644 --- a/drivers/edac/ppc4xx_edac.c +++ b/drivers/edac/ppc4xx_edac.c | |||
@@ -184,9 +184,9 @@ struct ppc4xx_ecc_status { | |||
184 | 184 | ||
185 | /* Function Prototypes */ | 185 | /* Function Prototypes */ |
186 | 186 | ||
187 | static int ppc4xx_edac_probe(struct of_device *device, | 187 | static int ppc4xx_edac_probe(struct platform_device *device, |
188 | const struct of_device_id *device_id); | 188 | const struct of_device_id *device_id); |
189 | static int ppc4xx_edac_remove(struct of_device *device); | 189 | static int ppc4xx_edac_remove(struct platform_device *device); |
190 | 190 | ||
191 | /* Global Variables */ | 191 | /* Global Variables */ |
192 | 192 | ||
@@ -1014,7 +1014,7 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) | |||
1014 | */ | 1014 | */ |
1015 | static int __devinit | 1015 | static int __devinit |
1016 | ppc4xx_edac_mc_init(struct mem_ctl_info *mci, | 1016 | ppc4xx_edac_mc_init(struct mem_ctl_info *mci, |
1017 | struct of_device *op, | 1017 | struct platform_device *op, |
1018 | const struct of_device_id *match, | 1018 | const struct of_device_id *match, |
1019 | const dcr_host_t *dcr_host, | 1019 | const dcr_host_t *dcr_host, |
1020 | u32 mcopt1) | 1020 | u32 mcopt1) |
@@ -1108,7 +1108,7 @@ ppc4xx_edac_mc_init(struct mem_ctl_info *mci, | |||
1108 | * mapped and assigned. | 1108 | * mapped and assigned. |
1109 | */ | 1109 | */ |
1110 | static int __devinit | 1110 | static int __devinit |
1111 | ppc4xx_edac_register_irq(struct of_device *op, struct mem_ctl_info *mci) | 1111 | ppc4xx_edac_register_irq(struct platform_device *op, struct mem_ctl_info *mci) |
1112 | { | 1112 | { |
1113 | int status = 0; | 1113 | int status = 0; |
1114 | int ded_irq, sec_irq; | 1114 | int ded_irq, sec_irq; |
@@ -1238,7 +1238,7 @@ ppc4xx_edac_map_dcrs(const struct device_node *np, dcr_host_t *dcr_host) | |||
1238 | * driver; otherwise, < 0 on error. | 1238 | * driver; otherwise, < 0 on error. |
1239 | */ | 1239 | */ |
1240 | static int __devinit | 1240 | static int __devinit |
1241 | ppc4xx_edac_probe(struct of_device *op, const struct of_device_id *match) | 1241 | ppc4xx_edac_probe(struct platform_device *op, const struct of_device_id *match) |
1242 | { | 1242 | { |
1243 | int status = 0; | 1243 | int status = 0; |
1244 | u32 mcopt1, memcheck; | 1244 | u32 mcopt1, memcheck; |
@@ -1359,7 +1359,7 @@ ppc4xx_edac_probe(struct of_device *op, const struct of_device_id *match) | |||
1359 | * Unconditionally returns 0. | 1359 | * Unconditionally returns 0. |
1360 | */ | 1360 | */ |
1361 | static int | 1361 | static int |
1362 | ppc4xx_edac_remove(struct of_device *op) | 1362 | ppc4xx_edac_remove(struct platform_device *op) |
1363 | { | 1363 | { |
1364 | struct mem_ctl_info *mci = dev_get_drvdata(&op->dev); | 1364 | struct mem_ctl_info *mci = dev_get_drvdata(&op->dev); |
1365 | struct ppc4xx_edac_pdata *pdata = mci->pvt_info; | 1365 | struct ppc4xx_edac_pdata *pdata = mci->pvt_info; |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f623953b5797..510aa2054544 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -206,6 +206,13 @@ config GPIO_SX150X | |||
206 | 8 bits: sx1508q | 206 | 8 bits: sx1508q |
207 | 16 bits: sx1509q | 207 | 16 bits: sx1509q |
208 | 208 | ||
209 | config GPIO_STMPE | ||
210 | bool "STMPE GPIOs" | ||
211 | depends on MFD_STMPE | ||
212 | help | ||
213 | This enables support for the GPIOs found on the STMPE I/O | ||
214 | Expanders. | ||
215 | |||
209 | config GPIO_TC35892 | 216 | config GPIO_TC35892 |
210 | bool "TC35892 GPIOs" | 217 | bool "TC35892 GPIOs" |
211 | depends on MFD_TC35892 | 218 | depends on MFD_TC35892 |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index a69e0609ff7f..fc6019d93720 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -20,6 +20,7 @@ obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o | |||
20 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o | 20 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o |
21 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o | 21 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o |
22 | obj-$(CONFIG_GPIO_PL061) += pl061.o | 22 | obj-$(CONFIG_GPIO_PL061) += pl061.o |
23 | obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o | ||
23 | obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o | 24 | obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o |
24 | obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o | 25 | obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o |
25 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o | 26 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o |
diff --git a/drivers/gpio/stmpe-gpio.c b/drivers/gpio/stmpe-gpio.c new file mode 100644 index 000000000000..4e1f1b9d5e67 --- /dev/null +++ b/drivers/gpio/stmpe-gpio.c | |||
@@ -0,0 +1,399 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/platform_device.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/gpio.h> | ||
13 | #include <linux/irq.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/mfd/stmpe.h> | ||
16 | |||
17 | /* | ||
18 | * These registers are modified under the irq bus lock and cached to avoid | ||
19 | * unnecessary writes in bus_sync_unlock. | ||
20 | */ | ||
21 | enum { REG_RE, REG_FE, REG_IE }; | ||
22 | |||
23 | #define CACHE_NR_REGS 3 | ||
24 | #define CACHE_NR_BANKS (STMPE_NR_GPIOS / 8) | ||
25 | |||
26 | struct stmpe_gpio { | ||
27 | struct gpio_chip chip; | ||
28 | struct stmpe *stmpe; | ||
29 | struct device *dev; | ||
30 | struct mutex irq_lock; | ||
31 | |||
32 | int irq_base; | ||
33 | |||
34 | /* Caches of interrupt control registers for bus_lock */ | ||
35 | u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS]; | ||
36 | u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS]; | ||
37 | }; | ||
38 | |||
39 | static inline struct stmpe_gpio *to_stmpe_gpio(struct gpio_chip *chip) | ||
40 | { | ||
41 | return container_of(chip, struct stmpe_gpio, chip); | ||
42 | } | ||
43 | |||
44 | static int stmpe_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
45 | { | ||
46 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
47 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
48 | u8 reg = stmpe->regs[STMPE_IDX_GPMR_LSB] - (offset / 8); | ||
49 | u8 mask = 1 << (offset % 8); | ||
50 | int ret; | ||
51 | |||
52 | ret = stmpe_reg_read(stmpe, reg); | ||
53 | if (ret < 0) | ||
54 | return ret; | ||
55 | |||
56 | return ret & mask; | ||
57 | } | ||
58 | |||
59 | static void stmpe_gpio_set(struct gpio_chip *chip, unsigned offset, int val) | ||
60 | { | ||
61 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
62 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
63 | int which = val ? STMPE_IDX_GPSR_LSB : STMPE_IDX_GPCR_LSB; | ||
64 | u8 reg = stmpe->regs[which] - (offset / 8); | ||
65 | u8 mask = 1 << (offset % 8); | ||
66 | |||
67 | stmpe_reg_write(stmpe, reg, mask); | ||
68 | } | ||
69 | |||
70 | static int stmpe_gpio_direction_output(struct gpio_chip *chip, | ||
71 | unsigned offset, int val) | ||
72 | { | ||
73 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
74 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
75 | u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8); | ||
76 | u8 mask = 1 << (offset % 8); | ||
77 | |||
78 | stmpe_gpio_set(chip, offset, val); | ||
79 | |||
80 | return stmpe_set_bits(stmpe, reg, mask, mask); | ||
81 | } | ||
82 | |||
83 | static int stmpe_gpio_direction_input(struct gpio_chip *chip, | ||
84 | unsigned offset) | ||
85 | { | ||
86 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
87 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
88 | u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8); | ||
89 | u8 mask = 1 << (offset % 8); | ||
90 | |||
91 | return stmpe_set_bits(stmpe, reg, mask, 0); | ||
92 | } | ||
93 | |||
94 | static int stmpe_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
95 | { | ||
96 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
97 | |||
98 | return stmpe_gpio->irq_base + offset; | ||
99 | } | ||
100 | |||
101 | static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset) | ||
102 | { | ||
103 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
104 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
105 | |||
106 | return stmpe_set_altfunc(stmpe, 1 << offset, STMPE_BLOCK_GPIO); | ||
107 | } | ||
108 | |||
109 | static struct gpio_chip template_chip = { | ||
110 | .label = "stmpe", | ||
111 | .owner = THIS_MODULE, | ||
112 | .direction_input = stmpe_gpio_direction_input, | ||
113 | .get = stmpe_gpio_get, | ||
114 | .direction_output = stmpe_gpio_direction_output, | ||
115 | .set = stmpe_gpio_set, | ||
116 | .to_irq = stmpe_gpio_to_irq, | ||
117 | .request = stmpe_gpio_request, | ||
118 | .can_sleep = 1, | ||
119 | }; | ||
120 | |||
121 | static int stmpe_gpio_irq_set_type(unsigned int irq, unsigned int type) | ||
122 | { | ||
123 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
124 | int offset = irq - stmpe_gpio->irq_base; | ||
125 | int regoffset = offset / 8; | ||
126 | int mask = 1 << (offset % 8); | ||
127 | |||
128 | if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH) | ||
129 | return -EINVAL; | ||
130 | |||
131 | if (type == IRQ_TYPE_EDGE_RISING) | ||
132 | stmpe_gpio->regs[REG_RE][regoffset] |= mask; | ||
133 | else | ||
134 | stmpe_gpio->regs[REG_RE][regoffset] &= ~mask; | ||
135 | |||
136 | if (type == IRQ_TYPE_EDGE_FALLING) | ||
137 | stmpe_gpio->regs[REG_FE][regoffset] |= mask; | ||
138 | else | ||
139 | stmpe_gpio->regs[REG_FE][regoffset] &= ~mask; | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static void stmpe_gpio_irq_lock(unsigned int irq) | ||
145 | { | ||
146 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
147 | |||
148 | mutex_lock(&stmpe_gpio->irq_lock); | ||
149 | } | ||
150 | |||
151 | static void stmpe_gpio_irq_sync_unlock(unsigned int irq) | ||
152 | { | ||
153 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
154 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
155 | int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8); | ||
156 | static const u8 regmap[] = { | ||
157 | [REG_RE] = STMPE_IDX_GPRER_LSB, | ||
158 | [REG_FE] = STMPE_IDX_GPFER_LSB, | ||
159 | [REG_IE] = STMPE_IDX_IEGPIOR_LSB, | ||
160 | }; | ||
161 | int i, j; | ||
162 | |||
163 | for (i = 0; i < CACHE_NR_REGS; i++) { | ||
164 | for (j = 0; j < num_banks; j++) { | ||
165 | u8 old = stmpe_gpio->oldregs[i][j]; | ||
166 | u8 new = stmpe_gpio->regs[i][j]; | ||
167 | |||
168 | if (new == old) | ||
169 | continue; | ||
170 | |||
171 | stmpe_gpio->oldregs[i][j] = new; | ||
172 | stmpe_reg_write(stmpe, stmpe->regs[regmap[i]] - j, new); | ||
173 | } | ||
174 | } | ||
175 | |||
176 | mutex_unlock(&stmpe_gpio->irq_lock); | ||
177 | } | ||
178 | |||
179 | static void stmpe_gpio_irq_mask(unsigned int irq) | ||
180 | { | ||
181 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
182 | int offset = irq - stmpe_gpio->irq_base; | ||
183 | int regoffset = offset / 8; | ||
184 | int mask = 1 << (offset % 8); | ||
185 | |||
186 | stmpe_gpio->regs[REG_IE][regoffset] &= ~mask; | ||
187 | } | ||
188 | |||
189 | static void stmpe_gpio_irq_unmask(unsigned int irq) | ||
190 | { | ||
191 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
192 | int offset = irq - stmpe_gpio->irq_base; | ||
193 | int regoffset = offset / 8; | ||
194 | int mask = 1 << (offset % 8); | ||
195 | |||
196 | stmpe_gpio->regs[REG_IE][regoffset] |= mask; | ||
197 | } | ||
198 | |||
199 | static struct irq_chip stmpe_gpio_irq_chip = { | ||
200 | .name = "stmpe-gpio", | ||
201 | .bus_lock = stmpe_gpio_irq_lock, | ||
202 | .bus_sync_unlock = stmpe_gpio_irq_sync_unlock, | ||
203 | .mask = stmpe_gpio_irq_mask, | ||
204 | .unmask = stmpe_gpio_irq_unmask, | ||
205 | .set_type = stmpe_gpio_irq_set_type, | ||
206 | }; | ||
207 | |||
208 | static irqreturn_t stmpe_gpio_irq(int irq, void *dev) | ||
209 | { | ||
210 | struct stmpe_gpio *stmpe_gpio = dev; | ||
211 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
212 | u8 statmsbreg = stmpe->regs[STMPE_IDX_ISGPIOR_MSB]; | ||
213 | int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8); | ||
214 | u8 status[num_banks]; | ||
215 | int ret; | ||
216 | int i; | ||
217 | |||
218 | ret = stmpe_block_read(stmpe, statmsbreg, num_banks, status); | ||
219 | if (ret < 0) | ||
220 | return IRQ_NONE; | ||
221 | |||
222 | for (i = 0; i < num_banks; i++) { | ||
223 | int bank = num_banks - i - 1; | ||
224 | unsigned int enabled = stmpe_gpio->regs[REG_IE][bank]; | ||
225 | unsigned int stat = status[i]; | ||
226 | |||
227 | stat &= enabled; | ||
228 | if (!stat) | ||
229 | continue; | ||
230 | |||
231 | while (stat) { | ||
232 | int bit = __ffs(stat); | ||
233 | int line = bank * 8 + bit; | ||
234 | |||
235 | handle_nested_irq(stmpe_gpio->irq_base + line); | ||
236 | stat &= ~(1 << bit); | ||
237 | } | ||
238 | |||
239 | stmpe_reg_write(stmpe, statmsbreg + i, status[i]); | ||
240 | stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_GPEDR_MSB] + i, | ||
241 | status[i]); | ||
242 | } | ||
243 | |||
244 | return IRQ_HANDLED; | ||
245 | } | ||
246 | |||
247 | static int __devinit stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio) | ||
248 | { | ||
249 | int base = stmpe_gpio->irq_base; | ||
250 | int irq; | ||
251 | |||
252 | for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) { | ||
253 | set_irq_chip_data(irq, stmpe_gpio); | ||
254 | set_irq_chip_and_handler(irq, &stmpe_gpio_irq_chip, | ||
255 | handle_simple_irq); | ||
256 | set_irq_nested_thread(irq, 1); | ||
257 | #ifdef CONFIG_ARM | ||
258 | set_irq_flags(irq, IRQF_VALID); | ||
259 | #else | ||
260 | set_irq_noprobe(irq); | ||
261 | #endif | ||
262 | } | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static void stmpe_gpio_irq_remove(struct stmpe_gpio *stmpe_gpio) | ||
268 | { | ||
269 | int base = stmpe_gpio->irq_base; | ||
270 | int irq; | ||
271 | |||
272 | for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) { | ||
273 | #ifdef CONFIG_ARM | ||
274 | set_irq_flags(irq, 0); | ||
275 | #endif | ||
276 | set_irq_chip_and_handler(irq, NULL, NULL); | ||
277 | set_irq_chip_data(irq, NULL); | ||
278 | } | ||
279 | } | ||
280 | |||
281 | static int __devinit stmpe_gpio_probe(struct platform_device *pdev) | ||
282 | { | ||
283 | struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); | ||
284 | struct stmpe_gpio_platform_data *pdata; | ||
285 | struct stmpe_gpio *stmpe_gpio; | ||
286 | int ret; | ||
287 | int irq; | ||
288 | |||
289 | pdata = stmpe->pdata->gpio; | ||
290 | if (!pdata) | ||
291 | return -ENODEV; | ||
292 | |||
293 | irq = platform_get_irq(pdev, 0); | ||
294 | if (irq < 0) | ||
295 | return irq; | ||
296 | |||
297 | stmpe_gpio = kzalloc(sizeof(struct stmpe_gpio), GFP_KERNEL); | ||
298 | if (!stmpe_gpio) | ||
299 | return -ENOMEM; | ||
300 | |||
301 | mutex_init(&stmpe_gpio->irq_lock); | ||
302 | |||
303 | stmpe_gpio->dev = &pdev->dev; | ||
304 | stmpe_gpio->stmpe = stmpe; | ||
305 | |||
306 | stmpe_gpio->chip = template_chip; | ||
307 | stmpe_gpio->chip.ngpio = stmpe->num_gpios; | ||
308 | stmpe_gpio->chip.dev = &pdev->dev; | ||
309 | stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1; | ||
310 | |||
311 | stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0); | ||
312 | |||
313 | ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO); | ||
314 | if (ret) | ||
315 | return ret; | ||
316 | |||
317 | ret = stmpe_gpio_irq_init(stmpe_gpio); | ||
318 | if (ret) | ||
319 | goto out_free; | ||
320 | |||
321 | ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq, IRQF_ONESHOT, | ||
322 | "stmpe-gpio", stmpe_gpio); | ||
323 | if (ret) { | ||
324 | dev_err(&pdev->dev, "unable to get irq: %d\n", ret); | ||
325 | goto out_removeirq; | ||
326 | } | ||
327 | |||
328 | ret = gpiochip_add(&stmpe_gpio->chip); | ||
329 | if (ret) { | ||
330 | dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); | ||
331 | goto out_freeirq; | ||
332 | } | ||
333 | |||
334 | if (pdata && pdata->setup) | ||
335 | pdata->setup(stmpe, stmpe_gpio->chip.base); | ||
336 | |||
337 | platform_set_drvdata(pdev, stmpe_gpio); | ||
338 | |||
339 | return 0; | ||
340 | |||
341 | out_freeirq: | ||
342 | free_irq(irq, stmpe_gpio); | ||
343 | out_removeirq: | ||
344 | stmpe_gpio_irq_remove(stmpe_gpio); | ||
345 | out_free: | ||
346 | kfree(stmpe_gpio); | ||
347 | return ret; | ||
348 | } | ||
349 | |||
350 | static int __devexit stmpe_gpio_remove(struct platform_device *pdev) | ||
351 | { | ||
352 | struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev); | ||
353 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
354 | struct stmpe_gpio_platform_data *pdata = stmpe->pdata->gpio; | ||
355 | int irq = platform_get_irq(pdev, 0); | ||
356 | int ret; | ||
357 | |||
358 | if (pdata && pdata->remove) | ||
359 | pdata->remove(stmpe, stmpe_gpio->chip.base); | ||
360 | |||
361 | ret = gpiochip_remove(&stmpe_gpio->chip); | ||
362 | if (ret < 0) { | ||
363 | dev_err(stmpe_gpio->dev, | ||
364 | "unable to remove gpiochip: %d\n", ret); | ||
365 | return ret; | ||
366 | } | ||
367 | |||
368 | stmpe_disable(stmpe, STMPE_BLOCK_GPIO); | ||
369 | |||
370 | free_irq(irq, stmpe_gpio); | ||
371 | stmpe_gpio_irq_remove(stmpe_gpio); | ||
372 | platform_set_drvdata(pdev, NULL); | ||
373 | kfree(stmpe_gpio); | ||
374 | |||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | static struct platform_driver stmpe_gpio_driver = { | ||
379 | .driver.name = "stmpe-gpio", | ||
380 | .driver.owner = THIS_MODULE, | ||
381 | .probe = stmpe_gpio_probe, | ||
382 | .remove = __devexit_p(stmpe_gpio_remove), | ||
383 | }; | ||
384 | |||
385 | static int __init stmpe_gpio_init(void) | ||
386 | { | ||
387 | return platform_driver_register(&stmpe_gpio_driver); | ||
388 | } | ||
389 | subsys_initcall(stmpe_gpio_init); | ||
390 | |||
391 | static void __exit stmpe_gpio_exit(void) | ||
392 | { | ||
393 | platform_driver_unregister(&stmpe_gpio_driver); | ||
394 | } | ||
395 | module_exit(stmpe_gpio_exit); | ||
396 | |||
397 | MODULE_LICENSE("GPL v2"); | ||
398 | MODULE_DESCRIPTION("STMPExxxx GPIO driver"); | ||
399 | MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>"); | ||
diff --git a/drivers/gpio/wm831x-gpio.c b/drivers/gpio/wm831x-gpio.c index 1fa449a1a4cb..309644cf4d9b 100644 --- a/drivers/gpio/wm831x-gpio.c +++ b/drivers/gpio/wm831x-gpio.c | |||
@@ -108,6 +108,37 @@ static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | |||
108 | return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset; | 108 | return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset; |
109 | } | 109 | } |
110 | 110 | ||
111 | static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, | ||
112 | unsigned debounce) | ||
113 | { | ||
114 | struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); | ||
115 | struct wm831x *wm831x = wm831x_gpio->wm831x; | ||
116 | int reg = WM831X_GPIO1_CONTROL + offset; | ||
117 | int ret, fn; | ||
118 | |||
119 | ret = wm831x_reg_read(wm831x, reg); | ||
120 | if (ret < 0) | ||
121 | return ret; | ||
122 | |||
123 | switch (ret & WM831X_GPN_FN_MASK) { | ||
124 | case 0: | ||
125 | case 1: | ||
126 | break; | ||
127 | default: | ||
128 | /* Not in GPIO mode */ | ||
129 | return -EBUSY; | ||
130 | } | ||
131 | |||
132 | if (debounce >= 32 && debounce <= 64) | ||
133 | fn = 0; | ||
134 | else if (debounce >= 4000 && debounce <= 8000) | ||
135 | fn = 1; | ||
136 | else | ||
137 | return -EINVAL; | ||
138 | |||
139 | return wm831x_set_bits(wm831x, reg, WM831X_GPN_FN_MASK, fn); | ||
140 | } | ||
141 | |||
111 | #ifdef CONFIG_DEBUG_FS | 142 | #ifdef CONFIG_DEBUG_FS |
112 | static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | 143 | static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) |
113 | { | 144 | { |
@@ -208,6 +239,7 @@ static struct gpio_chip template_chip = { | |||
208 | .direction_output = wm831x_gpio_direction_out, | 239 | .direction_output = wm831x_gpio_direction_out, |
209 | .set = wm831x_gpio_set, | 240 | .set = wm831x_gpio_set, |
210 | .to_irq = wm831x_gpio_to_irq, | 241 | .to_irq = wm831x_gpio_to_irq, |
242 | .set_debounce = wm831x_gpio_set_debounce, | ||
211 | .dbg_show = wm831x_gpio_dbg_show, | 243 | .dbg_show = wm831x_gpio_dbg_show, |
212 | .can_sleep = 1, | 244 | .can_sleep = 1, |
213 | }; | 245 | }; |
diff --git a/drivers/gpu/drm/ati_pcigart.c b/drivers/gpu/drm/ati_pcigart.c index 17be051b7aa3..1c3649242208 100644 --- a/drivers/gpu/drm/ati_pcigart.c +++ b/drivers/gpu/drm/ati_pcigart.c | |||
@@ -152,7 +152,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga | |||
152 | /* we need to support large memory configurations */ | 152 | /* we need to support large memory configurations */ |
153 | entry->busaddr[i] = pci_map_page(dev->pdev, entry->pagelist[i], | 153 | entry->busaddr[i] = pci_map_page(dev->pdev, entry->pagelist[i], |
154 | 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | 154 | 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); |
155 | if (entry->busaddr[i] == 0) { | 155 | if (pci_dma_mapping_error(dev->pdev, entry->busaddr[i])) { |
156 | DRM_ERROR("unable to map PCIGART pages!\n"); | 156 | DRM_ERROR("unable to map PCIGART pages!\n"); |
157 | drm_ati_pcigart_cleanup(dev, gart_info); | 157 | drm_ati_pcigart_cleanup(dev, gart_info); |
158 | address = NULL; | 158 | address = NULL; |
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index a5c9ce93bbcb..3e257a50bf56 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c | |||
@@ -328,14 +328,13 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset, | |||
328 | return -EINVAL; | 328 | return -EINVAL; |
329 | } | 329 | } |
330 | 330 | ||
331 | list = kmalloc(sizeof(*list), GFP_KERNEL); | 331 | list = kzalloc(sizeof(*list), GFP_KERNEL); |
332 | if (!list) { | 332 | if (!list) { |
333 | if (map->type == _DRM_REGISTERS) | 333 | if (map->type == _DRM_REGISTERS) |
334 | iounmap(map->handle); | 334 | iounmap(map->handle); |
335 | kfree(map); | 335 | kfree(map); |
336 | return -EINVAL; | 336 | return -EINVAL; |
337 | } | 337 | } |
338 | memset(list, 0, sizeof(*list)); | ||
339 | list->map = map; | 338 | list->map = map; |
340 | 339 | ||
341 | mutex_lock(&dev->struct_mutex); | 340 | mutex_lock(&dev->struct_mutex); |
@@ -678,13 +677,12 @@ int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request) | |||
678 | return -EINVAL; | 677 | return -EINVAL; |
679 | } | 678 | } |
680 | 679 | ||
681 | entry->buflist = kmalloc(count * sizeof(*entry->buflist), GFP_KERNEL); | 680 | entry->buflist = kzalloc(count * sizeof(*entry->buflist), GFP_KERNEL); |
682 | if (!entry->buflist) { | 681 | if (!entry->buflist) { |
683 | mutex_unlock(&dev->struct_mutex); | 682 | mutex_unlock(&dev->struct_mutex); |
684 | atomic_dec(&dev->buf_alloc); | 683 | atomic_dec(&dev->buf_alloc); |
685 | return -ENOMEM; | 684 | return -ENOMEM; |
686 | } | 685 | } |
687 | memset(entry->buflist, 0, count * sizeof(*entry->buflist)); | ||
688 | 686 | ||
689 | entry->buf_size = size; | 687 | entry->buf_size = size; |
690 | entry->page_order = page_order; | 688 | entry->page_order = page_order; |
@@ -708,7 +706,7 @@ int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request) | |||
708 | buf->file_priv = NULL; | 706 | buf->file_priv = NULL; |
709 | 707 | ||
710 | buf->dev_priv_size = dev->driver->dev_priv_size; | 708 | buf->dev_priv_size = dev->driver->dev_priv_size; |
711 | buf->dev_private = kmalloc(buf->dev_priv_size, GFP_KERNEL); | 709 | buf->dev_private = kzalloc(buf->dev_priv_size, GFP_KERNEL); |
712 | if (!buf->dev_private) { | 710 | if (!buf->dev_private) { |
713 | /* Set count correctly so we free the proper amount. */ | 711 | /* Set count correctly so we free the proper amount. */ |
714 | entry->buf_count = count; | 712 | entry->buf_count = count; |
@@ -717,7 +715,6 @@ int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request) | |||
717 | atomic_dec(&dev->buf_alloc); | 715 | atomic_dec(&dev->buf_alloc); |
718 | return -ENOMEM; | 716 | return -ENOMEM; |
719 | } | 717 | } |
720 | memset(buf->dev_private, 0, buf->dev_priv_size); | ||
721 | 718 | ||
722 | DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address); | 719 | DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address); |
723 | 720 | ||
@@ -832,22 +829,20 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request) | |||
832 | return -EINVAL; | 829 | return -EINVAL; |
833 | } | 830 | } |
834 | 831 | ||
835 | entry->buflist = kmalloc(count * sizeof(*entry->buflist), GFP_KERNEL); | 832 | entry->buflist = kzalloc(count * sizeof(*entry->buflist), GFP_KERNEL); |
836 | if (!entry->buflist) { | 833 | if (!entry->buflist) { |
837 | mutex_unlock(&dev->struct_mutex); | 834 | mutex_unlock(&dev->struct_mutex); |
838 | atomic_dec(&dev->buf_alloc); | 835 | atomic_dec(&dev->buf_alloc); |
839 | return -ENOMEM; | 836 | return -ENOMEM; |
840 | } | 837 | } |
841 | memset(entry->buflist, 0, count * sizeof(*entry->buflist)); | ||
842 | 838 | ||
843 | entry->seglist = kmalloc(count * sizeof(*entry->seglist), GFP_KERNEL); | 839 | entry->seglist = kzalloc(count * sizeof(*entry->seglist), GFP_KERNEL); |
844 | if (!entry->seglist) { | 840 | if (!entry->seglist) { |
845 | kfree(entry->buflist); | 841 | kfree(entry->buflist); |
846 | mutex_unlock(&dev->struct_mutex); | 842 | mutex_unlock(&dev->struct_mutex); |
847 | atomic_dec(&dev->buf_alloc); | 843 | atomic_dec(&dev->buf_alloc); |
848 | return -ENOMEM; | 844 | return -ENOMEM; |
849 | } | 845 | } |
850 | memset(entry->seglist, 0, count * sizeof(*entry->seglist)); | ||
851 | 846 | ||
852 | /* Keep the original pagelist until we know all the allocations | 847 | /* Keep the original pagelist until we know all the allocations |
853 | * have succeeded | 848 | * have succeeded |
@@ -911,8 +906,8 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request) | |||
911 | buf->file_priv = NULL; | 906 | buf->file_priv = NULL; |
912 | 907 | ||
913 | buf->dev_priv_size = dev->driver->dev_priv_size; | 908 | buf->dev_priv_size = dev->driver->dev_priv_size; |
914 | buf->dev_private = kmalloc(buf->dev_priv_size, | 909 | buf->dev_private = kzalloc(buf->dev_priv_size, |
915 | GFP_KERNEL); | 910 | GFP_KERNEL); |
916 | if (!buf->dev_private) { | 911 | if (!buf->dev_private) { |
917 | /* Set count correctly so we free the proper amount. */ | 912 | /* Set count correctly so we free the proper amount. */ |
918 | entry->buf_count = count; | 913 | entry->buf_count = count; |
@@ -923,7 +918,6 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request) | |||
923 | atomic_dec(&dev->buf_alloc); | 918 | atomic_dec(&dev->buf_alloc); |
924 | return -ENOMEM; | 919 | return -ENOMEM; |
925 | } | 920 | } |
926 | memset(buf->dev_private, 0, buf->dev_priv_size); | ||
927 | 921 | ||
928 | DRM_DEBUG("buffer %d @ %p\n", | 922 | DRM_DEBUG("buffer %d @ %p\n", |
929 | entry->buf_count, buf->address); | 923 | entry->buf_count, buf->address); |
@@ -1048,14 +1042,13 @@ static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request | |||
1048 | return -EINVAL; | 1042 | return -EINVAL; |
1049 | } | 1043 | } |
1050 | 1044 | ||
1051 | entry->buflist = kmalloc(count * sizeof(*entry->buflist), | 1045 | entry->buflist = kzalloc(count * sizeof(*entry->buflist), |
1052 | GFP_KERNEL); | 1046 | GFP_KERNEL); |
1053 | if (!entry->buflist) { | 1047 | if (!entry->buflist) { |
1054 | mutex_unlock(&dev->struct_mutex); | 1048 | mutex_unlock(&dev->struct_mutex); |
1055 | atomic_dec(&dev->buf_alloc); | 1049 | atomic_dec(&dev->buf_alloc); |
1056 | return -ENOMEM; | 1050 | return -ENOMEM; |
1057 | } | 1051 | } |
1058 | memset(entry->buflist, 0, count * sizeof(*entry->buflist)); | ||
1059 | 1052 | ||
1060 | entry->buf_size = size; | 1053 | entry->buf_size = size; |
1061 | entry->page_order = page_order; | 1054 | entry->page_order = page_order; |
@@ -1080,7 +1073,7 @@ static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request | |||
1080 | buf->file_priv = NULL; | 1073 | buf->file_priv = NULL; |
1081 | 1074 | ||
1082 | buf->dev_priv_size = dev->driver->dev_priv_size; | 1075 | buf->dev_priv_size = dev->driver->dev_priv_size; |
1083 | buf->dev_private = kmalloc(buf->dev_priv_size, GFP_KERNEL); | 1076 | buf->dev_private = kzalloc(buf->dev_priv_size, GFP_KERNEL); |
1084 | if (!buf->dev_private) { | 1077 | if (!buf->dev_private) { |
1085 | /* Set count correctly so we free the proper amount. */ | 1078 | /* Set count correctly so we free the proper amount. */ |
1086 | entry->buf_count = count; | 1079 | entry->buf_count = count; |
@@ -1090,8 +1083,6 @@ static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request | |||
1090 | return -ENOMEM; | 1083 | return -ENOMEM; |
1091 | } | 1084 | } |
1092 | 1085 | ||
1093 | memset(buf->dev_private, 0, buf->dev_priv_size); | ||
1094 | |||
1095 | DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address); | 1086 | DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address); |
1096 | 1087 | ||
1097 | offset += alignment; | 1088 | offset += alignment; |
@@ -1209,14 +1200,13 @@ static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request | |||
1209 | return -EINVAL; | 1200 | return -EINVAL; |
1210 | } | 1201 | } |
1211 | 1202 | ||
1212 | entry->buflist = kmalloc(count * sizeof(*entry->buflist), | 1203 | entry->buflist = kzalloc(count * sizeof(*entry->buflist), |
1213 | GFP_KERNEL); | 1204 | GFP_KERNEL); |
1214 | if (!entry->buflist) { | 1205 | if (!entry->buflist) { |
1215 | mutex_unlock(&dev->struct_mutex); | 1206 | mutex_unlock(&dev->struct_mutex); |
1216 | atomic_dec(&dev->buf_alloc); | 1207 | atomic_dec(&dev->buf_alloc); |
1217 | return -ENOMEM; | 1208 | return -ENOMEM; |
1218 | } | 1209 | } |
1219 | memset(entry->buflist, 0, count * sizeof(*entry->buflist)); | ||
1220 | 1210 | ||
1221 | entry->buf_size = size; | 1211 | entry->buf_size = size; |
1222 | entry->page_order = page_order; | 1212 | entry->page_order = page_order; |
@@ -1240,7 +1230,7 @@ static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request | |||
1240 | buf->file_priv = NULL; | 1230 | buf->file_priv = NULL; |
1241 | 1231 | ||
1242 | buf->dev_priv_size = dev->driver->dev_priv_size; | 1232 | buf->dev_priv_size = dev->driver->dev_priv_size; |
1243 | buf->dev_private = kmalloc(buf->dev_priv_size, GFP_KERNEL); | 1233 | buf->dev_private = kzalloc(buf->dev_priv_size, GFP_KERNEL); |
1244 | if (!buf->dev_private) { | 1234 | if (!buf->dev_private) { |
1245 | /* Set count correctly so we free the proper amount. */ | 1235 | /* Set count correctly so we free the proper amount. */ |
1246 | entry->buf_count = count; | 1236 | entry->buf_count = count; |
@@ -1249,7 +1239,6 @@ static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request | |||
1249 | atomic_dec(&dev->buf_alloc); | 1239 | atomic_dec(&dev->buf_alloc); |
1250 | return -ENOMEM; | 1240 | return -ENOMEM; |
1251 | } | 1241 | } |
1252 | memset(buf->dev_private, 0, buf->dev_priv_size); | ||
1253 | 1242 | ||
1254 | DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address); | 1243 | DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address); |
1255 | 1244 | ||
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 4c68f76993d8..37e0b4fa482a 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -1682,9 +1682,9 @@ int drm_mode_addfb(struct drm_device *dev, | |||
1682 | /* TODO setup destructor callback */ | 1682 | /* TODO setup destructor callback */ |
1683 | 1683 | ||
1684 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); | 1684 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); |
1685 | if (!fb) { | 1685 | if (IS_ERR(fb)) { |
1686 | DRM_ERROR("could not create framebuffer\n"); | 1686 | DRM_ERROR("could not create framebuffer\n"); |
1687 | ret = -EINVAL; | 1687 | ret = PTR_ERR(fb); |
1688 | goto out; | 1688 | goto out; |
1689 | } | 1689 | } |
1690 | 1690 | ||
@@ -2541,7 +2541,7 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev, | |||
2541 | goto out; | 2541 | goto out; |
2542 | } | 2542 | } |
2543 | 2543 | ||
2544 | crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, crtc->gamma_size); | 2544 | crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size); |
2545 | 2545 | ||
2546 | out: | 2546 | out: |
2547 | mutex_unlock(&dev->mode_config.mutex); | 2547 | mutex_unlock(&dev->mode_config.mutex); |
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index b9e4dbfa0533..7e31d4348340 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
@@ -817,12 +817,12 @@ int drm_helper_resume_force_mode(struct drm_device *dev) | |||
817 | if (encoder_funcs->dpms) | 817 | if (encoder_funcs->dpms) |
818 | (*encoder_funcs->dpms) (encoder, | 818 | (*encoder_funcs->dpms) (encoder, |
819 | drm_helper_choose_encoder_dpms(encoder)); | 819 | drm_helper_choose_encoder_dpms(encoder)); |
820 | |||
821 | crtc_funcs = crtc->helper_private; | ||
822 | if (crtc_funcs->dpms) | ||
823 | (*crtc_funcs->dpms) (crtc, | ||
824 | drm_helper_choose_crtc_dpms(crtc)); | ||
825 | } | 820 | } |
821 | |||
822 | crtc_funcs = crtc->helper_private; | ||
823 | if (crtc_funcs->dpms) | ||
824 | (*crtc_funcs->dpms) (crtc, | ||
825 | drm_helper_choose_crtc_dpms(crtc)); | ||
826 | } | 826 | } |
827 | } | 827 | } |
828 | /* disable the unused connectors while restoring the modesetting */ | 828 | /* disable the unused connectors while restoring the modesetting */ |
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index dce5c4a97f8d..96e963108225 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
@@ -33,6 +33,11 @@ | |||
33 | #include <linux/i2c-algo-bit.h> | 33 | #include <linux/i2c-algo-bit.h> |
34 | #include "drmP.h" | 34 | #include "drmP.h" |
35 | #include "drm_edid.h" | 35 | #include "drm_edid.h" |
36 | #include "drm_edid_modes.h" | ||
37 | |||
38 | #define version_greater(edid, maj, min) \ | ||
39 | (((edid)->version > (maj)) || \ | ||
40 | ((edid)->version == (maj) && (edid)->revision > (min))) | ||
36 | 41 | ||
37 | #define EDID_EST_TIMINGS 16 | 42 | #define EDID_EST_TIMINGS 16 |
38 | #define EDID_STD_TIMINGS 8 | 43 | #define EDID_STD_TIMINGS 8 |
@@ -62,6 +67,13 @@ | |||
62 | /* use +hsync +vsync for detailed mode */ | 67 | /* use +hsync +vsync for detailed mode */ |
63 | #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) | 68 | #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) |
64 | 69 | ||
70 | struct detailed_mode_closure { | ||
71 | struct drm_connector *connector; | ||
72 | struct edid *edid; | ||
73 | bool preferred; | ||
74 | u32 quirks; | ||
75 | int modes; | ||
76 | }; | ||
65 | 77 | ||
66 | #define LEVEL_DMT 0 | 78 | #define LEVEL_DMT 0 |
67 | #define LEVEL_GTF 1 | 79 | #define LEVEL_GTF 1 |
@@ -375,7 +387,6 @@ static u32 edid_get_quirks(struct edid *edid) | |||
375 | #define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay) | 387 | #define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay) |
376 | #define MODE_REFRESH_DIFF(m,r) (abs((m)->vrefresh - target_refresh)) | 388 | #define MODE_REFRESH_DIFF(m,r) (abs((m)->vrefresh - target_refresh)) |
377 | 389 | ||
378 | |||
379 | /** | 390 | /** |
380 | * edid_fixup_preferred - set preferred modes based on quirk list | 391 | * edid_fixup_preferred - set preferred modes based on quirk list |
381 | * @connector: has mode list to fix up | 392 | * @connector: has mode list to fix up |
@@ -422,245 +433,6 @@ static void edid_fixup_preferred(struct drm_connector *connector, | |||
422 | preferred_mode->type |= DRM_MODE_TYPE_PREFERRED; | 433 | preferred_mode->type |= DRM_MODE_TYPE_PREFERRED; |
423 | } | 434 | } |
424 | 435 | ||
425 | /* | ||
426 | * Add the Autogenerated from the DMT spec. | ||
427 | * This table is copied from xfree86/modes/xf86EdidModes.c. | ||
428 | * But the mode with Reduced blank feature is deleted. | ||
429 | */ | ||
430 | static struct drm_display_mode drm_dmt_modes[] = { | ||
431 | /* 640x350@85Hz */ | ||
432 | { DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 31500, 640, 672, | ||
433 | 736, 832, 0, 350, 382, 385, 445, 0, | ||
434 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
435 | /* 640x400@85Hz */ | ||
436 | { DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 31500, 640, 672, | ||
437 | 736, 832, 0, 400, 401, 404, 445, 0, | ||
438 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
439 | /* 720x400@85Hz */ | ||
440 | { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 756, | ||
441 | 828, 936, 0, 400, 401, 404, 446, 0, | ||
442 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
443 | /* 640x480@60Hz */ | ||
444 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656, | ||
445 | 752, 800, 0, 480, 489, 492, 525, 0, | ||
446 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
447 | /* 640x480@72Hz */ | ||
448 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664, | ||
449 | 704, 832, 0, 480, 489, 492, 520, 0, | ||
450 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
451 | /* 640x480@75Hz */ | ||
452 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656, | ||
453 | 720, 840, 0, 480, 481, 484, 500, 0, | ||
454 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
455 | /* 640x480@85Hz */ | ||
456 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 36000, 640, 696, | ||
457 | 752, 832, 0, 480, 481, 484, 509, 0, | ||
458 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
459 | /* 800x600@56Hz */ | ||
460 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824, | ||
461 | 896, 1024, 0, 600, 601, 603, 625, 0, | ||
462 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
463 | /* 800x600@60Hz */ | ||
464 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, | ||
465 | 968, 1056, 0, 600, 601, 605, 628, 0, | ||
466 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
467 | /* 800x600@72Hz */ | ||
468 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856, | ||
469 | 976, 1040, 0, 600, 637, 643, 666, 0, | ||
470 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
471 | /* 800x600@75Hz */ | ||
472 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816, | ||
473 | 896, 1056, 0, 600, 601, 604, 625, 0, | ||
474 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
475 | /* 800x600@85Hz */ | ||
476 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 56250, 800, 832, | ||
477 | 896, 1048, 0, 600, 601, 604, 631, 0, | ||
478 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
479 | /* 848x480@60Hz */ | ||
480 | { DRM_MODE("848x480", DRM_MODE_TYPE_DRIVER, 33750, 848, 864, | ||
481 | 976, 1088, 0, 480, 486, 494, 517, 0, | ||
482 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
483 | /* 1024x768@43Hz, interlace */ | ||
484 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 44900, 1024, 1032, | ||
485 | 1208, 1264, 0, 768, 768, 772, 817, 0, | ||
486 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | | ||
487 | DRM_MODE_FLAG_INTERLACE) }, | ||
488 | /* 1024x768@60Hz */ | ||
489 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, | ||
490 | 1184, 1344, 0, 768, 771, 777, 806, 0, | ||
491 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
492 | /* 1024x768@70Hz */ | ||
493 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048, | ||
494 | 1184, 1328, 0, 768, 771, 777, 806, 0, | ||
495 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
496 | /* 1024x768@75Hz */ | ||
497 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78750, 1024, 1040, | ||
498 | 1136, 1312, 0, 768, 769, 772, 800, 0, | ||
499 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
500 | /* 1024x768@85Hz */ | ||
501 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 94500, 1024, 1072, | ||
502 | 1168, 1376, 0, 768, 769, 772, 808, 0, | ||
503 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
504 | /* 1152x864@75Hz */ | ||
505 | { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216, | ||
506 | 1344, 1600, 0, 864, 865, 868, 900, 0, | ||
507 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
508 | /* 1280x768@60Hz */ | ||
509 | { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344, | ||
510 | 1472, 1664, 0, 768, 771, 778, 798, 0, | ||
511 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
512 | /* 1280x768@75Hz */ | ||
513 | { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 102250, 1280, 1360, | ||
514 | 1488, 1696, 0, 768, 771, 778, 805, 0, | ||
515 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
516 | /* 1280x768@85Hz */ | ||
517 | { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 117500, 1280, 1360, | ||
518 | 1496, 1712, 0, 768, 771, 778, 809, 0, | ||
519 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
520 | /* 1280x800@60Hz */ | ||
521 | { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352, | ||
522 | 1480, 1680, 0, 800, 803, 809, 831, 0, | ||
523 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
524 | /* 1280x800@75Hz */ | ||
525 | { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 106500, 1280, 1360, | ||
526 | 1488, 1696, 0, 800, 803, 809, 838, 0, | ||
527 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
528 | /* 1280x800@85Hz */ | ||
529 | { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 122500, 1280, 1360, | ||
530 | 1496, 1712, 0, 800, 803, 809, 843, 0, | ||
531 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
532 | /* 1280x960@60Hz */ | ||
533 | { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376, | ||
534 | 1488, 1800, 0, 960, 961, 964, 1000, 0, | ||
535 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
536 | /* 1280x960@85Hz */ | ||
537 | { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1344, | ||
538 | 1504, 1728, 0, 960, 961, 964, 1011, 0, | ||
539 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
540 | /* 1280x1024@60Hz */ | ||
541 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328, | ||
542 | 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, | ||
543 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
544 | /* 1280x1024@75Hz */ | ||
545 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296, | ||
546 | 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, | ||
547 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
548 | /* 1280x1024@85Hz */ | ||
549 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 157500, 1280, 1344, | ||
550 | 1504, 1728, 0, 1024, 1025, 1028, 1072, 0, | ||
551 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
552 | /* 1360x768@60Hz */ | ||
553 | { DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424, | ||
554 | 1536, 1792, 0, 768, 771, 777, 795, 0, | ||
555 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
556 | /* 1440x1050@60Hz */ | ||
557 | { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488, | ||
558 | 1632, 1864, 0, 1050, 1053, 1057, 1089, 0, | ||
559 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
560 | /* 1440x1050@75Hz */ | ||
561 | { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 156000, 1400, 1504, | ||
562 | 1648, 1896, 0, 1050, 1053, 1057, 1099, 0, | ||
563 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
564 | /* 1440x1050@85Hz */ | ||
565 | { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 179500, 1400, 1504, | ||
566 | 1656, 1912, 0, 1050, 1053, 1057, 1105, 0, | ||
567 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
568 | /* 1440x900@60Hz */ | ||
569 | { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520, | ||
570 | 1672, 1904, 0, 900, 903, 909, 934, 0, | ||
571 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
572 | /* 1440x900@75Hz */ | ||
573 | { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 136750, 1440, 1536, | ||
574 | 1688, 1936, 0, 900, 903, 909, 942, 0, | ||
575 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
576 | /* 1440x900@85Hz */ | ||
577 | { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 157000, 1440, 1544, | ||
578 | 1696, 1952, 0, 900, 903, 909, 948, 0, | ||
579 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
580 | /* 1600x1200@60Hz */ | ||
581 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664, | ||
582 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
583 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
584 | /* 1600x1200@65Hz */ | ||
585 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 175500, 1600, 1664, | ||
586 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
587 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
588 | /* 1600x1200@70Hz */ | ||
589 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 189000, 1600, 1664, | ||
590 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
591 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
592 | /* 1600x1200@75Hz */ | ||
593 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 202500, 1600, 1664, | ||
594 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
595 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
596 | /* 1600x1200@85Hz */ | ||
597 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 229500, 1600, 1664, | ||
598 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
599 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
600 | /* 1680x1050@60Hz */ | ||
601 | { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784, | ||
602 | 1960, 2240, 0, 1050, 1053, 1059, 1089, 0, | ||
603 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
604 | /* 1680x1050@75Hz */ | ||
605 | { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 187000, 1680, 1800, | ||
606 | 1976, 2272, 0, 1050, 1053, 1059, 1099, 0, | ||
607 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
608 | /* 1680x1050@85Hz */ | ||
609 | { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 214750, 1680, 1808, | ||
610 | 1984, 2288, 0, 1050, 1053, 1059, 1105, 0, | ||
611 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
612 | /* 1792x1344@60Hz */ | ||
613 | { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920, | ||
614 | 2120, 2448, 0, 1344, 1345, 1348, 1394, 0, | ||
615 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
616 | /* 1729x1344@75Hz */ | ||
617 | { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 261000, 1792, 1888, | ||
618 | 2104, 2456, 0, 1344, 1345, 1348, 1417, 0, | ||
619 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
620 | /* 1853x1392@60Hz */ | ||
621 | { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952, | ||
622 | 2176, 2528, 0, 1392, 1393, 1396, 1439, 0, | ||
623 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
624 | /* 1856x1392@75Hz */ | ||
625 | { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 288000, 1856, 1984, | ||
626 | 2208, 2560, 0, 1392, 1395, 1399, 1500, 0, | ||
627 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
628 | /* 1920x1200@60Hz */ | ||
629 | { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056, | ||
630 | 2256, 2592, 0, 1200, 1203, 1209, 1245, 0, | ||
631 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
632 | /* 1920x1200@75Hz */ | ||
633 | { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 245250, 1920, 2056, | ||
634 | 2264, 2608, 0, 1200, 1203, 1209, 1255, 0, | ||
635 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
636 | /* 1920x1200@85Hz */ | ||
637 | { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 281250, 1920, 2064, | ||
638 | 2272, 2624, 0, 1200, 1203, 1209, 1262, 0, | ||
639 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
640 | /* 1920x1440@60Hz */ | ||
641 | { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048, | ||
642 | 2256, 2600, 0, 1440, 1441, 1444, 1500, 0, | ||
643 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
644 | /* 1920x1440@75Hz */ | ||
645 | { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2064, | ||
646 | 2288, 2640, 0, 1440, 1441, 1444, 1500, 0, | ||
647 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
648 | /* 2560x1600@60Hz */ | ||
649 | { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752, | ||
650 | 3032, 3504, 0, 1600, 1603, 1609, 1658, 0, | ||
651 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
652 | /* 2560x1600@75HZ */ | ||
653 | { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 443250, 2560, 2768, | ||
654 | 3048, 3536, 0, 1600, 1603, 1609, 1672, 0, | ||
655 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
656 | /* 2560x1600@85HZ */ | ||
657 | { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 505250, 2560, 2768, | ||
658 | 3048, 3536, 0, 1600, 1603, 1609, 1682, 0, | ||
659 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
660 | }; | ||
661 | static const int drm_num_dmt_modes = | ||
662 | sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); | ||
663 | |||
664 | struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, | 436 | struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, |
665 | int hsize, int vsize, int fresh) | 437 | int hsize, int vsize, int fresh) |
666 | { | 438 | { |
@@ -685,6 +457,46 @@ EXPORT_SYMBOL(drm_mode_find_dmt); | |||
685 | typedef void detailed_cb(struct detailed_timing *timing, void *closure); | 457 | typedef void detailed_cb(struct detailed_timing *timing, void *closure); |
686 | 458 | ||
687 | static void | 459 | static void |
460 | cea_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure) | ||
461 | { | ||
462 | int i, n = 0; | ||
463 | u8 rev = ext[0x01], d = ext[0x02]; | ||
464 | u8 *det_base = ext + d; | ||
465 | |||
466 | switch (rev) { | ||
467 | case 0: | ||
468 | /* can't happen */ | ||
469 | return; | ||
470 | case 1: | ||
471 | /* have to infer how many blocks we have, check pixel clock */ | ||
472 | for (i = 0; i < 6; i++) | ||
473 | if (det_base[18*i] || det_base[18*i+1]) | ||
474 | n++; | ||
475 | break; | ||
476 | default: | ||
477 | /* explicit count */ | ||
478 | n = min(ext[0x03] & 0x0f, 6); | ||
479 | break; | ||
480 | } | ||
481 | |||
482 | for (i = 0; i < n; i++) | ||
483 | cb((struct detailed_timing *)(det_base + 18 * i), closure); | ||
484 | } | ||
485 | |||
486 | static void | ||
487 | vtb_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure) | ||
488 | { | ||
489 | unsigned int i, n = min((int)ext[0x02], 6); | ||
490 | u8 *det_base = ext + 5; | ||
491 | |||
492 | if (ext[0x01] != 1) | ||
493 | return; /* unknown version */ | ||
494 | |||
495 | for (i = 0; i < n; i++) | ||
496 | cb((struct detailed_timing *)(det_base + 18 * i), closure); | ||
497 | } | ||
498 | |||
499 | static void | ||
688 | drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure) | 500 | drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure) |
689 | { | 501 | { |
690 | int i; | 502 | int i; |
@@ -696,7 +508,19 @@ drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure) | |||
696 | for (i = 0; i < EDID_DETAILED_TIMINGS; i++) | 508 | for (i = 0; i < EDID_DETAILED_TIMINGS; i++) |
697 | cb(&(edid->detailed_timings[i]), closure); | 509 | cb(&(edid->detailed_timings[i]), closure); |
698 | 510 | ||
699 | /* XXX extension block walk */ | 511 | for (i = 1; i <= raw_edid[0x7e]; i++) { |
512 | u8 *ext = raw_edid + (i * EDID_LENGTH); | ||
513 | switch (*ext) { | ||
514 | case CEA_EXT: | ||
515 | cea_for_each_detailed_block(ext, cb, closure); | ||
516 | break; | ||
517 | case VTB_EXT: | ||
518 | vtb_for_each_detailed_block(ext, cb, closure); | ||
519 | break; | ||
520 | default: | ||
521 | break; | ||
522 | } | ||
523 | } | ||
700 | } | 524 | } |
701 | 525 | ||
702 | static void | 526 | static void |
@@ -1047,117 +871,6 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, | |||
1047 | return mode; | 871 | return mode; |
1048 | } | 872 | } |
1049 | 873 | ||
1050 | /* | ||
1051 | * Detailed mode info for the EDID "established modes" data to use. | ||
1052 | */ | ||
1053 | static struct drm_display_mode edid_est_modes[] = { | ||
1054 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, | ||
1055 | 968, 1056, 0, 600, 601, 605, 628, 0, | ||
1056 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@60Hz */ | ||
1057 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824, | ||
1058 | 896, 1024, 0, 600, 601, 603, 625, 0, | ||
1059 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@56Hz */ | ||
1060 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656, | ||
1061 | 720, 840, 0, 480, 481, 484, 500, 0, | ||
1062 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@75Hz */ | ||
1063 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664, | ||
1064 | 704, 832, 0, 480, 489, 491, 520, 0, | ||
1065 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@72Hz */ | ||
1066 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 30240, 640, 704, | ||
1067 | 768, 864, 0, 480, 483, 486, 525, 0, | ||
1068 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@67Hz */ | ||
1069 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25200, 640, 656, | ||
1070 | 752, 800, 0, 480, 490, 492, 525, 0, | ||
1071 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@60Hz */ | ||
1072 | { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 738, | ||
1073 | 846, 900, 0, 400, 421, 423, 449, 0, | ||
1074 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 720x400@88Hz */ | ||
1075 | { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 28320, 720, 738, | ||
1076 | 846, 900, 0, 400, 412, 414, 449, 0, | ||
1077 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 720x400@70Hz */ | ||
1078 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296, | ||
1079 | 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, | ||
1080 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1280x1024@75Hz */ | ||
1081 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78800, 1024, 1040, | ||
1082 | 1136, 1312, 0, 768, 769, 772, 800, 0, | ||
1083 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1024x768@75Hz */ | ||
1084 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048, | ||
1085 | 1184, 1328, 0, 768, 771, 777, 806, 0, | ||
1086 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@70Hz */ | ||
1087 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, | ||
1088 | 1184, 1344, 0, 768, 771, 777, 806, 0, | ||
1089 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@60Hz */ | ||
1090 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER,44900, 1024, 1032, | ||
1091 | 1208, 1264, 0, 768, 768, 776, 817, 0, | ||
1092 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_INTERLACE) }, /* 1024x768@43Hz */ | ||
1093 | { DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 57284, 832, 864, | ||
1094 | 928, 1152, 0, 624, 625, 628, 667, 0, | ||
1095 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 832x624@75Hz */ | ||
1096 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816, | ||
1097 | 896, 1056, 0, 600, 601, 604, 625, 0, | ||
1098 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@75Hz */ | ||
1099 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856, | ||
1100 | 976, 1040, 0, 600, 637, 643, 666, 0, | ||
1101 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@72Hz */ | ||
1102 | { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216, | ||
1103 | 1344, 1600, 0, 864, 865, 868, 900, 0, | ||
1104 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1152x864@75Hz */ | ||
1105 | }; | ||
1106 | |||
1107 | /** | ||
1108 | * add_established_modes - get est. modes from EDID and add them | ||
1109 | * @edid: EDID block to scan | ||
1110 | * | ||
1111 | * Each EDID block contains a bitmap of the supported "established modes" list | ||
1112 | * (defined above). Tease them out and add them to the global modes list. | ||
1113 | */ | ||
1114 | static int add_established_modes(struct drm_connector *connector, struct edid *edid) | ||
1115 | { | ||
1116 | struct drm_device *dev = connector->dev; | ||
1117 | unsigned long est_bits = edid->established_timings.t1 | | ||
1118 | (edid->established_timings.t2 << 8) | | ||
1119 | ((edid->established_timings.mfg_rsvd & 0x80) << 9); | ||
1120 | int i, modes = 0; | ||
1121 | |||
1122 | for (i = 0; i <= EDID_EST_TIMINGS; i++) | ||
1123 | if (est_bits & (1<<i)) { | ||
1124 | struct drm_display_mode *newmode; | ||
1125 | newmode = drm_mode_duplicate(dev, &edid_est_modes[i]); | ||
1126 | if (newmode) { | ||
1127 | drm_mode_probed_add(connector, newmode); | ||
1128 | modes++; | ||
1129 | } | ||
1130 | } | ||
1131 | |||
1132 | return modes; | ||
1133 | } | ||
1134 | |||
1135 | /** | ||
1136 | * add_standard_modes - get std. modes from EDID and add them | ||
1137 | * @edid: EDID block to scan | ||
1138 | * | ||
1139 | * Standard modes can be calculated using the CVT standard. Grab them from | ||
1140 | * @edid, calculate them, and add them to the list. | ||
1141 | */ | ||
1142 | static int add_standard_modes(struct drm_connector *connector, struct edid *edid) | ||
1143 | { | ||
1144 | int i, modes = 0; | ||
1145 | |||
1146 | for (i = 0; i < EDID_STD_TIMINGS; i++) { | ||
1147 | struct drm_display_mode *newmode; | ||
1148 | |||
1149 | newmode = drm_mode_std(connector, edid, | ||
1150 | &edid->standard_timings[i], | ||
1151 | edid->revision); | ||
1152 | if (newmode) { | ||
1153 | drm_mode_probed_add(connector, newmode); | ||
1154 | modes++; | ||
1155 | } | ||
1156 | } | ||
1157 | |||
1158 | return modes; | ||
1159 | } | ||
1160 | |||
1161 | static bool | 874 | static bool |
1162 | mode_is_rb(struct drm_display_mode *mode) | 875 | mode_is_rb(struct drm_display_mode *mode) |
1163 | { | 876 | { |
@@ -1267,113 +980,33 @@ drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid, | |||
1267 | return modes; | 980 | return modes; |
1268 | } | 981 | } |
1269 | 982 | ||
1270 | static int drm_cvt_modes(struct drm_connector *connector, | 983 | static void |
1271 | struct detailed_timing *timing) | 984 | do_inferred_modes(struct detailed_timing *timing, void *c) |
1272 | { | 985 | { |
1273 | int i, j, modes = 0; | 986 | struct detailed_mode_closure *closure = c; |
1274 | struct drm_display_mode *newmode; | 987 | struct detailed_non_pixel *data = &timing->data.other_data; |
1275 | struct drm_device *dev = connector->dev; | 988 | int gtf = (closure->edid->features & DRM_EDID_FEATURE_DEFAULT_GTF); |
1276 | struct cvt_timing *cvt; | ||
1277 | const int rates[] = { 60, 85, 75, 60, 50 }; | ||
1278 | const u8 empty[3] = { 0, 0, 0 }; | ||
1279 | |||
1280 | for (i = 0; i < 4; i++) { | ||
1281 | int uninitialized_var(width), height; | ||
1282 | cvt = &(timing->data.other_data.data.cvt[i]); | ||
1283 | 989 | ||
1284 | if (!memcmp(cvt->code, empty, 3)) | 990 | if (gtf && data->type == EDID_DETAIL_MONITOR_RANGE) |
1285 | continue; | 991 | closure->modes += drm_gtf_modes_for_range(closure->connector, |
992 | closure->edid, | ||
993 | timing); | ||
994 | } | ||
1286 | 995 | ||
1287 | height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 4) + 1) * 2; | 996 | static int |
1288 | switch (cvt->code[1] & 0x0c) { | 997 | add_inferred_modes(struct drm_connector *connector, struct edid *edid) |
1289 | case 0x00: | 998 | { |
1290 | width = height * 4 / 3; | 999 | struct detailed_mode_closure closure = { |
1291 | break; | 1000 | connector, edid, 0, 0, 0 |
1292 | case 0x04: | 1001 | }; |
1293 | width = height * 16 / 9; | ||
1294 | break; | ||
1295 | case 0x08: | ||
1296 | width = height * 16 / 10; | ||
1297 | break; | ||
1298 | case 0x0c: | ||
1299 | width = height * 15 / 9; | ||
1300 | break; | ||
1301 | } | ||
1302 | 1002 | ||
1303 | for (j = 1; j < 5; j++) { | 1003 | if (version_greater(edid, 1, 0)) |
1304 | if (cvt->code[2] & (1 << j)) { | 1004 | drm_for_each_detailed_block((u8 *)edid, do_inferred_modes, |
1305 | newmode = drm_cvt_mode(dev, width, height, | 1005 | &closure); |
1306 | rates[j], j == 0, | ||
1307 | false, false); | ||
1308 | if (newmode) { | ||
1309 | drm_mode_probed_add(connector, newmode); | ||
1310 | modes++; | ||
1311 | } | ||
1312 | } | ||
1313 | } | ||
1314 | } | ||
1315 | 1006 | ||
1316 | return modes; | 1007 | return closure.modes; |
1317 | } | 1008 | } |
1318 | 1009 | ||
1319 | static const struct { | ||
1320 | short w; | ||
1321 | short h; | ||
1322 | short r; | ||
1323 | short rb; | ||
1324 | } est3_modes[] = { | ||
1325 | /* byte 6 */ | ||
1326 | { 640, 350, 85, 0 }, | ||
1327 | { 640, 400, 85, 0 }, | ||
1328 | { 720, 400, 85, 0 }, | ||
1329 | { 640, 480, 85, 0 }, | ||
1330 | { 848, 480, 60, 0 }, | ||
1331 | { 800, 600, 85, 0 }, | ||
1332 | { 1024, 768, 85, 0 }, | ||
1333 | { 1152, 864, 75, 0 }, | ||
1334 | /* byte 7 */ | ||
1335 | { 1280, 768, 60, 1 }, | ||
1336 | { 1280, 768, 60, 0 }, | ||
1337 | { 1280, 768, 75, 0 }, | ||
1338 | { 1280, 768, 85, 0 }, | ||
1339 | { 1280, 960, 60, 0 }, | ||
1340 | { 1280, 960, 85, 0 }, | ||
1341 | { 1280, 1024, 60, 0 }, | ||
1342 | { 1280, 1024, 85, 0 }, | ||
1343 | /* byte 8 */ | ||
1344 | { 1360, 768, 60, 0 }, | ||
1345 | { 1440, 900, 60, 1 }, | ||
1346 | { 1440, 900, 60, 0 }, | ||
1347 | { 1440, 900, 75, 0 }, | ||
1348 | { 1440, 900, 85, 0 }, | ||
1349 | { 1400, 1050, 60, 1 }, | ||
1350 | { 1400, 1050, 60, 0 }, | ||
1351 | { 1400, 1050, 75, 0 }, | ||
1352 | /* byte 9 */ | ||
1353 | { 1400, 1050, 85, 0 }, | ||
1354 | { 1680, 1050, 60, 1 }, | ||
1355 | { 1680, 1050, 60, 0 }, | ||
1356 | { 1680, 1050, 75, 0 }, | ||
1357 | { 1680, 1050, 85, 0 }, | ||
1358 | { 1600, 1200, 60, 0 }, | ||
1359 | { 1600, 1200, 65, 0 }, | ||
1360 | { 1600, 1200, 70, 0 }, | ||
1361 | /* byte 10 */ | ||
1362 | { 1600, 1200, 75, 0 }, | ||
1363 | { 1600, 1200, 85, 0 }, | ||
1364 | { 1792, 1344, 60, 0 }, | ||
1365 | { 1792, 1344, 85, 0 }, | ||
1366 | { 1856, 1392, 60, 0 }, | ||
1367 | { 1856, 1392, 75, 0 }, | ||
1368 | { 1920, 1200, 60, 1 }, | ||
1369 | { 1920, 1200, 60, 0 }, | ||
1370 | /* byte 11 */ | ||
1371 | { 1920, 1200, 75, 0 }, | ||
1372 | { 1920, 1200, 85, 0 }, | ||
1373 | { 1920, 1440, 60, 0 }, | ||
1374 | { 1920, 1440, 75, 0 }, | ||
1375 | }; | ||
1376 | |||
1377 | static int | 1010 | static int |
1378 | drm_est3_modes(struct drm_connector *connector, struct detailed_timing *timing) | 1011 | drm_est3_modes(struct drm_connector *connector, struct detailed_timing *timing) |
1379 | { | 1012 | { |
@@ -1403,37 +1036,63 @@ drm_est3_modes(struct drm_connector *connector, struct detailed_timing *timing) | |||
1403 | return modes; | 1036 | return modes; |
1404 | } | 1037 | } |
1405 | 1038 | ||
1406 | static int add_detailed_modes(struct drm_connector *connector, | 1039 | static void |
1407 | struct detailed_timing *timing, | 1040 | do_established_modes(struct detailed_timing *timing, void *c) |
1408 | struct edid *edid, u32 quirks, int preferred) | ||
1409 | { | 1041 | { |
1410 | int i, modes = 0; | 1042 | struct detailed_mode_closure *closure = c; |
1411 | struct detailed_non_pixel *data = &timing->data.other_data; | 1043 | struct detailed_non_pixel *data = &timing->data.other_data; |
1412 | int gtf = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF); | ||
1413 | struct drm_display_mode *newmode; | ||
1414 | struct drm_device *dev = connector->dev; | ||
1415 | 1044 | ||
1416 | if (timing->pixel_clock) { | 1045 | if (data->type == EDID_DETAIL_EST_TIMINGS) |
1417 | newmode = drm_mode_detailed(dev, edid, timing, quirks); | 1046 | closure->modes += drm_est3_modes(closure->connector, timing); |
1418 | if (!newmode) | 1047 | } |
1419 | return 0; | ||
1420 | 1048 | ||
1421 | if (preferred) | 1049 | /** |
1422 | newmode->type |= DRM_MODE_TYPE_PREFERRED; | 1050 | * add_established_modes - get est. modes from EDID and add them |
1051 | * @edid: EDID block to scan | ||
1052 | * | ||
1053 | * Each EDID block contains a bitmap of the supported "established modes" list | ||
1054 | * (defined above). Tease them out and add them to the global modes list. | ||
1055 | */ | ||
1056 | static int | ||
1057 | add_established_modes(struct drm_connector *connector, struct edid *edid) | ||
1058 | { | ||
1059 | struct drm_device *dev = connector->dev; | ||
1060 | unsigned long est_bits = edid->established_timings.t1 | | ||
1061 | (edid->established_timings.t2 << 8) | | ||
1062 | ((edid->established_timings.mfg_rsvd & 0x80) << 9); | ||
1063 | int i, modes = 0; | ||
1064 | struct detailed_mode_closure closure = { | ||
1065 | connector, edid, 0, 0, 0 | ||
1066 | }; | ||
1423 | 1067 | ||
1424 | drm_mode_probed_add(connector, newmode); | 1068 | for (i = 0; i <= EDID_EST_TIMINGS; i++) { |
1425 | return 1; | 1069 | if (est_bits & (1<<i)) { |
1070 | struct drm_display_mode *newmode; | ||
1071 | newmode = drm_mode_duplicate(dev, &edid_est_modes[i]); | ||
1072 | if (newmode) { | ||
1073 | drm_mode_probed_add(connector, newmode); | ||
1074 | modes++; | ||
1075 | } | ||
1076 | } | ||
1426 | } | 1077 | } |
1427 | 1078 | ||
1428 | /* other timing types */ | 1079 | if (version_greater(edid, 1, 0)) |
1429 | switch (data->type) { | 1080 | drm_for_each_detailed_block((u8 *)edid, |
1430 | case EDID_DETAIL_MONITOR_RANGE: | 1081 | do_established_modes, &closure); |
1431 | if (gtf) | 1082 | |
1432 | modes += drm_gtf_modes_for_range(connector, edid, | 1083 | return modes + closure.modes; |
1433 | timing); | 1084 | } |
1434 | break; | 1085 | |
1435 | case EDID_DETAIL_STD_MODES: | 1086 | static void |
1436 | /* Six modes per detailed section */ | 1087 | do_standard_modes(struct detailed_timing *timing, void *c) |
1088 | { | ||
1089 | struct detailed_mode_closure *closure = c; | ||
1090 | struct detailed_non_pixel *data = &timing->data.other_data; | ||
1091 | struct drm_connector *connector = closure->connector; | ||
1092 | struct edid *edid = closure->edid; | ||
1093 | |||
1094 | if (data->type == EDID_DETAIL_STD_MODES) { | ||
1095 | int i; | ||
1437 | for (i = 0; i < 6; i++) { | 1096 | for (i = 0; i < 6; i++) { |
1438 | struct std_timing *std; | 1097 | struct std_timing *std; |
1439 | struct drm_display_mode *newmode; | 1098 | struct drm_display_mode *newmode; |
@@ -1443,108 +1102,169 @@ static int add_detailed_modes(struct drm_connector *connector, | |||
1443 | edid->revision); | 1102 | edid->revision); |
1444 | if (newmode) { | 1103 | if (newmode) { |
1445 | drm_mode_probed_add(connector, newmode); | 1104 | drm_mode_probed_add(connector, newmode); |
1446 | modes++; | 1105 | closure->modes++; |
1447 | } | 1106 | } |
1448 | } | 1107 | } |
1449 | break; | ||
1450 | case EDID_DETAIL_CVT_3BYTE: | ||
1451 | modes += drm_cvt_modes(connector, timing); | ||
1452 | break; | ||
1453 | case EDID_DETAIL_EST_TIMINGS: | ||
1454 | modes += drm_est3_modes(connector, timing); | ||
1455 | break; | ||
1456 | default: | ||
1457 | break; | ||
1458 | } | 1108 | } |
1459 | |||
1460 | return modes; | ||
1461 | } | 1109 | } |
1462 | 1110 | ||
1463 | /** | 1111 | /** |
1464 | * add_detailed_info - get detailed mode info from EDID data | 1112 | * add_standard_modes - get std. modes from EDID and add them |
1465 | * @connector: attached connector | ||
1466 | * @edid: EDID block to scan | 1113 | * @edid: EDID block to scan |
1467 | * @quirks: quirks to apply | ||
1468 | * | 1114 | * |
1469 | * Some of the detailed timing sections may contain mode information. Grab | 1115 | * Standard modes can be calculated using the appropriate standard (DMT, |
1470 | * it and add it to the list. | 1116 | * GTF or CVT. Grab them from @edid and add them to the list. |
1471 | */ | 1117 | */ |
1472 | static int add_detailed_info(struct drm_connector *connector, | 1118 | static int |
1473 | struct edid *edid, u32 quirks) | 1119 | add_standard_modes(struct drm_connector *connector, struct edid *edid) |
1474 | { | 1120 | { |
1475 | int i, modes = 0; | 1121 | int i, modes = 0; |
1122 | struct detailed_mode_closure closure = { | ||
1123 | connector, edid, 0, 0, 0 | ||
1124 | }; | ||
1125 | |||
1126 | for (i = 0; i < EDID_STD_TIMINGS; i++) { | ||
1127 | struct drm_display_mode *newmode; | ||
1128 | |||
1129 | newmode = drm_mode_std(connector, edid, | ||
1130 | &edid->standard_timings[i], | ||
1131 | edid->revision); | ||
1132 | if (newmode) { | ||
1133 | drm_mode_probed_add(connector, newmode); | ||
1134 | modes++; | ||
1135 | } | ||
1136 | } | ||
1137 | |||
1138 | if (version_greater(edid, 1, 0)) | ||
1139 | drm_for_each_detailed_block((u8 *)edid, do_standard_modes, | ||
1140 | &closure); | ||
1141 | |||
1142 | /* XXX should also look for standard codes in VTB blocks */ | ||
1143 | |||
1144 | return modes + closure.modes; | ||
1145 | } | ||
1476 | 1146 | ||
1477 | for (i = 0; i < EDID_DETAILED_TIMINGS; i++) { | 1147 | static int drm_cvt_modes(struct drm_connector *connector, |
1478 | struct detailed_timing *timing = &edid->detailed_timings[i]; | 1148 | struct detailed_timing *timing) |
1479 | int preferred = (i == 0); | 1149 | { |
1150 | int i, j, modes = 0; | ||
1151 | struct drm_display_mode *newmode; | ||
1152 | struct drm_device *dev = connector->dev; | ||
1153 | struct cvt_timing *cvt; | ||
1154 | const int rates[] = { 60, 85, 75, 60, 50 }; | ||
1155 | const u8 empty[3] = { 0, 0, 0 }; | ||
1480 | 1156 | ||
1481 | if (preferred && edid->version == 1 && edid->revision < 4) | 1157 | for (i = 0; i < 4; i++) { |
1482 | preferred = (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING); | 1158 | int uninitialized_var(width), height; |
1159 | cvt = &(timing->data.other_data.data.cvt[i]); | ||
1483 | 1160 | ||
1484 | /* In 1.0, only timings are allowed */ | 1161 | if (!memcmp(cvt->code, empty, 3)) |
1485 | if (!timing->pixel_clock && edid->version == 1 && | ||
1486 | edid->revision == 0) | ||
1487 | continue; | 1162 | continue; |
1488 | 1163 | ||
1489 | modes += add_detailed_modes(connector, timing, edid, quirks, | 1164 | height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 4) + 1) * 2; |
1490 | preferred); | 1165 | switch (cvt->code[1] & 0x0c) { |
1166 | case 0x00: | ||
1167 | width = height * 4 / 3; | ||
1168 | break; | ||
1169 | case 0x04: | ||
1170 | width = height * 16 / 9; | ||
1171 | break; | ||
1172 | case 0x08: | ||
1173 | width = height * 16 / 10; | ||
1174 | break; | ||
1175 | case 0x0c: | ||
1176 | width = height * 15 / 9; | ||
1177 | break; | ||
1178 | } | ||
1179 | |||
1180 | for (j = 1; j < 5; j++) { | ||
1181 | if (cvt->code[2] & (1 << j)) { | ||
1182 | newmode = drm_cvt_mode(dev, width, height, | ||
1183 | rates[j], j == 0, | ||
1184 | false, false); | ||
1185 | if (newmode) { | ||
1186 | drm_mode_probed_add(connector, newmode); | ||
1187 | modes++; | ||
1188 | } | ||
1189 | } | ||
1190 | } | ||
1491 | } | 1191 | } |
1492 | 1192 | ||
1493 | return modes; | 1193 | return modes; |
1494 | } | 1194 | } |
1495 | 1195 | ||
1496 | /** | 1196 | static void |
1497 | * add_detailed_mode_eedid - get detailed mode info from addtional timing | 1197 | do_cvt_mode(struct detailed_timing *timing, void *c) |
1498 | * EDID block | ||
1499 | * @connector: attached connector | ||
1500 | * @edid: EDID block to scan(It is only to get addtional timing EDID block) | ||
1501 | * @quirks: quirks to apply | ||
1502 | * | ||
1503 | * Some of the detailed timing sections may contain mode information. Grab | ||
1504 | * it and add it to the list. | ||
1505 | */ | ||
1506 | static int add_detailed_info_eedid(struct drm_connector *connector, | ||
1507 | struct edid *edid, u32 quirks) | ||
1508 | { | 1198 | { |
1509 | int i, modes = 0; | 1199 | struct detailed_mode_closure *closure = c; |
1510 | char *edid_ext = NULL; | 1200 | struct detailed_non_pixel *data = &timing->data.other_data; |
1511 | struct detailed_timing *timing; | ||
1512 | int start_offset, end_offset; | ||
1513 | 1201 | ||
1514 | if (edid->version == 1 && edid->revision < 3) | 1202 | if (data->type == EDID_DETAIL_CVT_3BYTE) |
1515 | return 0; | 1203 | closure->modes += drm_cvt_modes(closure->connector, timing); |
1516 | if (!edid->extensions) | 1204 | } |
1517 | return 0; | ||
1518 | 1205 | ||
1519 | /* Find CEA extension */ | 1206 | static int |
1520 | for (i = 0; i < edid->extensions; i++) { | 1207 | add_cvt_modes(struct drm_connector *connector, struct edid *edid) |
1521 | edid_ext = (char *)edid + EDID_LENGTH * (i + 1); | 1208 | { |
1522 | if (edid_ext[0] == 0x02) | 1209 | struct detailed_mode_closure closure = { |
1523 | break; | 1210 | connector, edid, 0, 0, 0 |
1524 | } | 1211 | }; |
1525 | 1212 | ||
1526 | if (i == edid->extensions) | 1213 | if (version_greater(edid, 1, 2)) |
1527 | return 0; | 1214 | drm_for_each_detailed_block((u8 *)edid, do_cvt_mode, &closure); |
1528 | 1215 | ||
1529 | /* Get the start offset of detailed timing block */ | 1216 | /* XXX should also look for CVT codes in VTB blocks */ |
1530 | start_offset = edid_ext[2]; | ||
1531 | if (start_offset == 0) { | ||
1532 | /* If the start_offset is zero, it means that neither detailed | ||
1533 | * info nor data block exist. In such case it is also | ||
1534 | * unnecessary to parse the detailed timing info. | ||
1535 | */ | ||
1536 | return 0; | ||
1537 | } | ||
1538 | 1217 | ||
1539 | end_offset = EDID_LENGTH; | 1218 | return closure.modes; |
1540 | end_offset -= sizeof(struct detailed_timing); | 1219 | } |
1541 | for (i = start_offset; i < end_offset; | 1220 | |
1542 | i += sizeof(struct detailed_timing)) { | 1221 | static void |
1543 | timing = (struct detailed_timing *)(edid_ext + i); | 1222 | do_detailed_mode(struct detailed_timing *timing, void *c) |
1544 | modes += add_detailed_modes(connector, timing, edid, quirks, 0); | 1223 | { |
1224 | struct detailed_mode_closure *closure = c; | ||
1225 | struct drm_display_mode *newmode; | ||
1226 | |||
1227 | if (timing->pixel_clock) { | ||
1228 | newmode = drm_mode_detailed(closure->connector->dev, | ||
1229 | closure->edid, timing, | ||
1230 | closure->quirks); | ||
1231 | if (!newmode) | ||
1232 | return; | ||
1233 | |||
1234 | if (closure->preferred) | ||
1235 | newmode->type |= DRM_MODE_TYPE_PREFERRED; | ||
1236 | |||
1237 | drm_mode_probed_add(closure->connector, newmode); | ||
1238 | closure->modes++; | ||
1239 | closure->preferred = 0; | ||
1545 | } | 1240 | } |
1241 | } | ||
1546 | 1242 | ||
1547 | return modes; | 1243 | /* |
1244 | * add_detailed_modes - Add modes from detailed timings | ||
1245 | * @connector: attached connector | ||
1246 | * @edid: EDID block to scan | ||
1247 | * @quirks: quirks to apply | ||
1248 | */ | ||
1249 | static int | ||
1250 | add_detailed_modes(struct drm_connector *connector, struct edid *edid, | ||
1251 | u32 quirks) | ||
1252 | { | ||
1253 | struct detailed_mode_closure closure = { | ||
1254 | connector, | ||
1255 | edid, | ||
1256 | 1, | ||
1257 | quirks, | ||
1258 | 0 | ||
1259 | }; | ||
1260 | |||
1261 | if (closure.preferred && !version_greater(edid, 1, 3)) | ||
1262 | closure.preferred = | ||
1263 | (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING); | ||
1264 | |||
1265 | drm_for_each_detailed_block((u8 *)edid, do_detailed_mode, &closure); | ||
1266 | |||
1267 | return closure.modes; | ||
1548 | } | 1268 | } |
1549 | 1269 | ||
1550 | #define HDMI_IDENTIFIER 0x000C03 | 1270 | #define HDMI_IDENTIFIER 0x000C03 |
@@ -1640,35 +1360,21 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) | |||
1640 | * - established timing codes | 1360 | * - established timing codes |
1641 | * - modes inferred from GTF or CVT range information | 1361 | * - modes inferred from GTF or CVT range information |
1642 | * | 1362 | * |
1643 | * We don't quite implement this yet, but we're close. | 1363 | * We get this pretty much right. |
1644 | * | 1364 | * |
1645 | * XXX order for additional mode types in extension blocks? | 1365 | * XXX order for additional mode types in extension blocks? |
1646 | */ | 1366 | */ |
1647 | num_modes += add_detailed_info(connector, edid, quirks); | 1367 | num_modes += add_detailed_modes(connector, edid, quirks); |
1648 | num_modes += add_detailed_info_eedid(connector, edid, quirks); | 1368 | num_modes += add_cvt_modes(connector, edid); |
1649 | num_modes += add_standard_modes(connector, edid); | 1369 | num_modes += add_standard_modes(connector, edid); |
1650 | num_modes += add_established_modes(connector, edid); | 1370 | num_modes += add_established_modes(connector, edid); |
1371 | num_modes += add_inferred_modes(connector, edid); | ||
1651 | 1372 | ||
1652 | if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) | 1373 | if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) |
1653 | edid_fixup_preferred(connector, quirks); | 1374 | edid_fixup_preferred(connector, quirks); |
1654 | 1375 | ||
1655 | connector->display_info.serration_vsync = (edid->input & DRM_EDID_INPUT_SERRATION_VSYNC) ? 1 : 0; | ||
1656 | connector->display_info.sync_on_green = (edid->input & DRM_EDID_INPUT_SYNC_ON_GREEN) ? 1 : 0; | ||
1657 | connector->display_info.composite_sync = (edid->input & DRM_EDID_INPUT_COMPOSITE_SYNC) ? 1 : 0; | ||
1658 | connector->display_info.separate_syncs = (edid->input & DRM_EDID_INPUT_SEPARATE_SYNCS) ? 1 : 0; | ||
1659 | connector->display_info.blank_to_black = (edid->input & DRM_EDID_INPUT_BLANK_TO_BLACK) ? 1 : 0; | ||
1660 | connector->display_info.video_level = (edid->input & DRM_EDID_INPUT_VIDEO_LEVEL) >> 5; | ||
1661 | connector->display_info.digital = (edid->input & DRM_EDID_INPUT_DIGITAL) ? 1 : 0; | ||
1662 | connector->display_info.width_mm = edid->width_cm * 10; | 1376 | connector->display_info.width_mm = edid->width_cm * 10; |
1663 | connector->display_info.height_mm = edid->height_cm * 10; | 1377 | connector->display_info.height_mm = edid->height_cm * 10; |
1664 | connector->display_info.gamma = edid->gamma; | ||
1665 | connector->display_info.gtf_supported = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF) ? 1 : 0; | ||
1666 | connector->display_info.standard_color = (edid->features & DRM_EDID_FEATURE_STANDARD_COLOR) ? 1 : 0; | ||
1667 | connector->display_info.display_type = (edid->features & DRM_EDID_FEATURE_DISPLAY_TYPE) >> 3; | ||
1668 | connector->display_info.active_off_supported = (edid->features & DRM_EDID_FEATURE_PM_ACTIVE_OFF) ? 1 : 0; | ||
1669 | connector->display_info.suspend_supported = (edid->features & DRM_EDID_FEATURE_PM_SUSPEND) ? 1 : 0; | ||
1670 | connector->display_info.standby_supported = (edid->features & DRM_EDID_FEATURE_PM_STANDBY) ? 1 : 0; | ||
1671 | connector->display_info.gamma = edid->gamma; | ||
1672 | 1378 | ||
1673 | return num_modes; | 1379 | return num_modes; |
1674 | } | 1380 | } |
diff --git a/drivers/gpu/drm/drm_edid_modes.h b/drivers/gpu/drm/drm_edid_modes.h new file mode 100644 index 000000000000..6eb7592e152f --- /dev/null +++ b/drivers/gpu/drm/drm_edid_modes.h | |||
@@ -0,0 +1,380 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2007-2008 Intel Corporation | ||
3 | * Jesse Barnes <jesse.barnes@intel.com> | ||
4 | * Copyright 2010 Red Hat, Inc. | ||
5 | * | ||
6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
7 | * copy of this software and associated documentation files (the "Software"), | ||
8 | * to deal in the Software without restriction, including without limitation | ||
9 | * the rights to use, copy, modify, merge, publish, distribute, sub license, | ||
10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
11 | * Software is furnished to do so, subject to the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice (including the | ||
14 | * next paragraph) shall be included in all copies or substantial portions | ||
15 | * of the Software. | ||
16 | * | ||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
23 | * DEALINGS IN THE SOFTWARE. | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include "drmP.h" | ||
28 | #include "drm_edid.h" | ||
29 | |||
30 | /* | ||
31 | * Autogenerated from the DMT spec. | ||
32 | * This table is copied from xfree86/modes/xf86EdidModes.c. | ||
33 | * But the mode with Reduced blank feature is deleted. | ||
34 | */ | ||
35 | static struct drm_display_mode drm_dmt_modes[] = { | ||
36 | /* 640x350@85Hz */ | ||
37 | { DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 31500, 640, 672, | ||
38 | 736, 832, 0, 350, 382, 385, 445, 0, | ||
39 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
40 | /* 640x400@85Hz */ | ||
41 | { DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 31500, 640, 672, | ||
42 | 736, 832, 0, 400, 401, 404, 445, 0, | ||
43 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
44 | /* 720x400@85Hz */ | ||
45 | { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 756, | ||
46 | 828, 936, 0, 400, 401, 404, 446, 0, | ||
47 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
48 | /* 640x480@60Hz */ | ||
49 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656, | ||
50 | 752, 800, 0, 480, 489, 492, 525, 0, | ||
51 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
52 | /* 640x480@72Hz */ | ||
53 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664, | ||
54 | 704, 832, 0, 480, 489, 492, 520, 0, | ||
55 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
56 | /* 640x480@75Hz */ | ||
57 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656, | ||
58 | 720, 840, 0, 480, 481, 484, 500, 0, | ||
59 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
60 | /* 640x480@85Hz */ | ||
61 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 36000, 640, 696, | ||
62 | 752, 832, 0, 480, 481, 484, 509, 0, | ||
63 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
64 | /* 800x600@56Hz */ | ||
65 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824, | ||
66 | 896, 1024, 0, 600, 601, 603, 625, 0, | ||
67 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
68 | /* 800x600@60Hz */ | ||
69 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, | ||
70 | 968, 1056, 0, 600, 601, 605, 628, 0, | ||
71 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
72 | /* 800x600@72Hz */ | ||
73 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856, | ||
74 | 976, 1040, 0, 600, 637, 643, 666, 0, | ||
75 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
76 | /* 800x600@75Hz */ | ||
77 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816, | ||
78 | 896, 1056, 0, 600, 601, 604, 625, 0, | ||
79 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
80 | /* 800x600@85Hz */ | ||
81 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 56250, 800, 832, | ||
82 | 896, 1048, 0, 600, 601, 604, 631, 0, | ||
83 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
84 | /* 848x480@60Hz */ | ||
85 | { DRM_MODE("848x480", DRM_MODE_TYPE_DRIVER, 33750, 848, 864, | ||
86 | 976, 1088, 0, 480, 486, 494, 517, 0, | ||
87 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
88 | /* 1024x768@43Hz, interlace */ | ||
89 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 44900, 1024, 1032, | ||
90 | 1208, 1264, 0, 768, 768, 772, 817, 0, | ||
91 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | | ||
92 | DRM_MODE_FLAG_INTERLACE) }, | ||
93 | /* 1024x768@60Hz */ | ||
94 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, | ||
95 | 1184, 1344, 0, 768, 771, 777, 806, 0, | ||
96 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
97 | /* 1024x768@70Hz */ | ||
98 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048, | ||
99 | 1184, 1328, 0, 768, 771, 777, 806, 0, | ||
100 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
101 | /* 1024x768@75Hz */ | ||
102 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78750, 1024, 1040, | ||
103 | 1136, 1312, 0, 768, 769, 772, 800, 0, | ||
104 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
105 | /* 1024x768@85Hz */ | ||
106 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 94500, 1024, 1072, | ||
107 | 1168, 1376, 0, 768, 769, 772, 808, 0, | ||
108 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
109 | /* 1152x864@75Hz */ | ||
110 | { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216, | ||
111 | 1344, 1600, 0, 864, 865, 868, 900, 0, | ||
112 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
113 | /* 1280x768@60Hz */ | ||
114 | { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344, | ||
115 | 1472, 1664, 0, 768, 771, 778, 798, 0, | ||
116 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
117 | /* 1280x768@75Hz */ | ||
118 | { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 102250, 1280, 1360, | ||
119 | 1488, 1696, 0, 768, 771, 778, 805, 0, | ||
120 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
121 | /* 1280x768@85Hz */ | ||
122 | { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 117500, 1280, 1360, | ||
123 | 1496, 1712, 0, 768, 771, 778, 809, 0, | ||
124 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
125 | /* 1280x800@60Hz */ | ||
126 | { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352, | ||
127 | 1480, 1680, 0, 800, 803, 809, 831, 0, | ||
128 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
129 | /* 1280x800@75Hz */ | ||
130 | { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 106500, 1280, 1360, | ||
131 | 1488, 1696, 0, 800, 803, 809, 838, 0, | ||
132 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
133 | /* 1280x800@85Hz */ | ||
134 | { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 122500, 1280, 1360, | ||
135 | 1496, 1712, 0, 800, 803, 809, 843, 0, | ||
136 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
137 | /* 1280x960@60Hz */ | ||
138 | { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376, | ||
139 | 1488, 1800, 0, 960, 961, 964, 1000, 0, | ||
140 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
141 | /* 1280x960@85Hz */ | ||
142 | { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1344, | ||
143 | 1504, 1728, 0, 960, 961, 964, 1011, 0, | ||
144 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
145 | /* 1280x1024@60Hz */ | ||
146 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328, | ||
147 | 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, | ||
148 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
149 | /* 1280x1024@75Hz */ | ||
150 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296, | ||
151 | 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, | ||
152 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
153 | /* 1280x1024@85Hz */ | ||
154 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 157500, 1280, 1344, | ||
155 | 1504, 1728, 0, 1024, 1025, 1028, 1072, 0, | ||
156 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
157 | /* 1360x768@60Hz */ | ||
158 | { DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424, | ||
159 | 1536, 1792, 0, 768, 771, 777, 795, 0, | ||
160 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
161 | /* 1440x1050@60Hz */ | ||
162 | { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488, | ||
163 | 1632, 1864, 0, 1050, 1053, 1057, 1089, 0, | ||
164 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
165 | /* 1440x1050@75Hz */ | ||
166 | { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 156000, 1400, 1504, | ||
167 | 1648, 1896, 0, 1050, 1053, 1057, 1099, 0, | ||
168 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
169 | /* 1440x1050@85Hz */ | ||
170 | { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 179500, 1400, 1504, | ||
171 | 1656, 1912, 0, 1050, 1053, 1057, 1105, 0, | ||
172 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
173 | /* 1440x900@60Hz */ | ||
174 | { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520, | ||
175 | 1672, 1904, 0, 900, 903, 909, 934, 0, | ||
176 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
177 | /* 1440x900@75Hz */ | ||
178 | { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 136750, 1440, 1536, | ||
179 | 1688, 1936, 0, 900, 903, 909, 942, 0, | ||
180 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
181 | /* 1440x900@85Hz */ | ||
182 | { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 157000, 1440, 1544, | ||
183 | 1696, 1952, 0, 900, 903, 909, 948, 0, | ||
184 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
185 | /* 1600x1200@60Hz */ | ||
186 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664, | ||
187 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
188 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
189 | /* 1600x1200@65Hz */ | ||
190 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 175500, 1600, 1664, | ||
191 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
192 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
193 | /* 1600x1200@70Hz */ | ||
194 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 189000, 1600, 1664, | ||
195 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
196 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
197 | /* 1600x1200@75Hz */ | ||
198 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 202500, 1600, 1664, | ||
199 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
200 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
201 | /* 1600x1200@85Hz */ | ||
202 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 229500, 1600, 1664, | ||
203 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
204 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
205 | /* 1680x1050@60Hz */ | ||
206 | { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784, | ||
207 | 1960, 2240, 0, 1050, 1053, 1059, 1089, 0, | ||
208 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
209 | /* 1680x1050@75Hz */ | ||
210 | { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 187000, 1680, 1800, | ||
211 | 1976, 2272, 0, 1050, 1053, 1059, 1099, 0, | ||
212 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
213 | /* 1680x1050@85Hz */ | ||
214 | { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 214750, 1680, 1808, | ||
215 | 1984, 2288, 0, 1050, 1053, 1059, 1105, 0, | ||
216 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
217 | /* 1792x1344@60Hz */ | ||
218 | { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920, | ||
219 | 2120, 2448, 0, 1344, 1345, 1348, 1394, 0, | ||
220 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
221 | /* 1729x1344@75Hz */ | ||
222 | { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 261000, 1792, 1888, | ||
223 | 2104, 2456, 0, 1344, 1345, 1348, 1417, 0, | ||
224 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
225 | /* 1853x1392@60Hz */ | ||
226 | { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952, | ||
227 | 2176, 2528, 0, 1392, 1393, 1396, 1439, 0, | ||
228 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
229 | /* 1856x1392@75Hz */ | ||
230 | { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 288000, 1856, 1984, | ||
231 | 2208, 2560, 0, 1392, 1395, 1399, 1500, 0, | ||
232 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
233 | /* 1920x1200@60Hz */ | ||
234 | { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056, | ||
235 | 2256, 2592, 0, 1200, 1203, 1209, 1245, 0, | ||
236 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
237 | /* 1920x1200@75Hz */ | ||
238 | { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 245250, 1920, 2056, | ||
239 | 2264, 2608, 0, 1200, 1203, 1209, 1255, 0, | ||
240 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
241 | /* 1920x1200@85Hz */ | ||
242 | { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 281250, 1920, 2064, | ||
243 | 2272, 2624, 0, 1200, 1203, 1209, 1262, 0, | ||
244 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
245 | /* 1920x1440@60Hz */ | ||
246 | { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048, | ||
247 | 2256, 2600, 0, 1440, 1441, 1444, 1500, 0, | ||
248 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
249 | /* 1920x1440@75Hz */ | ||
250 | { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2064, | ||
251 | 2288, 2640, 0, 1440, 1441, 1444, 1500, 0, | ||
252 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
253 | /* 2560x1600@60Hz */ | ||
254 | { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752, | ||
255 | 3032, 3504, 0, 1600, 1603, 1609, 1658, 0, | ||
256 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
257 | /* 2560x1600@75HZ */ | ||
258 | { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 443250, 2560, 2768, | ||
259 | 3048, 3536, 0, 1600, 1603, 1609, 1672, 0, | ||
260 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
261 | /* 2560x1600@85HZ */ | ||
262 | { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 505250, 2560, 2768, | ||
263 | 3048, 3536, 0, 1600, 1603, 1609, 1682, 0, | ||
264 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
265 | }; | ||
266 | static const int drm_num_dmt_modes = | ||
267 | sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); | ||
268 | |||
269 | static struct drm_display_mode edid_est_modes[] = { | ||
270 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, | ||
271 | 968, 1056, 0, 600, 601, 605, 628, 0, | ||
272 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@60Hz */ | ||
273 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824, | ||
274 | 896, 1024, 0, 600, 601, 603, 625, 0, | ||
275 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@56Hz */ | ||
276 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656, | ||
277 | 720, 840, 0, 480, 481, 484, 500, 0, | ||
278 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@75Hz */ | ||
279 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664, | ||
280 | 704, 832, 0, 480, 489, 491, 520, 0, | ||
281 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@72Hz */ | ||
282 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 30240, 640, 704, | ||
283 | 768, 864, 0, 480, 483, 486, 525, 0, | ||
284 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@67Hz */ | ||
285 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25200, 640, 656, | ||
286 | 752, 800, 0, 480, 490, 492, 525, 0, | ||
287 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@60Hz */ | ||
288 | { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 738, | ||
289 | 846, 900, 0, 400, 421, 423, 449, 0, | ||
290 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 720x400@88Hz */ | ||
291 | { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 28320, 720, 738, | ||
292 | 846, 900, 0, 400, 412, 414, 449, 0, | ||
293 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 720x400@70Hz */ | ||
294 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296, | ||
295 | 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, | ||
296 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1280x1024@75Hz */ | ||
297 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78800, 1024, 1040, | ||
298 | 1136, 1312, 0, 768, 769, 772, 800, 0, | ||
299 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1024x768@75Hz */ | ||
300 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048, | ||
301 | 1184, 1328, 0, 768, 771, 777, 806, 0, | ||
302 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@70Hz */ | ||
303 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, | ||
304 | 1184, 1344, 0, 768, 771, 777, 806, 0, | ||
305 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@60Hz */ | ||
306 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER,44900, 1024, 1032, | ||
307 | 1208, 1264, 0, 768, 768, 776, 817, 0, | ||
308 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_INTERLACE) }, /* 1024x768@43Hz */ | ||
309 | { DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 57284, 832, 864, | ||
310 | 928, 1152, 0, 624, 625, 628, 667, 0, | ||
311 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 832x624@75Hz */ | ||
312 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816, | ||
313 | 896, 1056, 0, 600, 601, 604, 625, 0, | ||
314 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@75Hz */ | ||
315 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856, | ||
316 | 976, 1040, 0, 600, 637, 643, 666, 0, | ||
317 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@72Hz */ | ||
318 | { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216, | ||
319 | 1344, 1600, 0, 864, 865, 868, 900, 0, | ||
320 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1152x864@75Hz */ | ||
321 | }; | ||
322 | |||
323 | static const struct { | ||
324 | short w; | ||
325 | short h; | ||
326 | short r; | ||
327 | short rb; | ||
328 | } est3_modes[] = { | ||
329 | /* byte 6 */ | ||
330 | { 640, 350, 85, 0 }, | ||
331 | { 640, 400, 85, 0 }, | ||
332 | { 720, 400, 85, 0 }, | ||
333 | { 640, 480, 85, 0 }, | ||
334 | { 848, 480, 60, 0 }, | ||
335 | { 800, 600, 85, 0 }, | ||
336 | { 1024, 768, 85, 0 }, | ||
337 | { 1152, 864, 75, 0 }, | ||
338 | /* byte 7 */ | ||
339 | { 1280, 768, 60, 1 }, | ||
340 | { 1280, 768, 60, 0 }, | ||
341 | { 1280, 768, 75, 0 }, | ||
342 | { 1280, 768, 85, 0 }, | ||
343 | { 1280, 960, 60, 0 }, | ||
344 | { 1280, 960, 85, 0 }, | ||
345 | { 1280, 1024, 60, 0 }, | ||
346 | { 1280, 1024, 85, 0 }, | ||
347 | /* byte 8 */ | ||
348 | { 1360, 768, 60, 0 }, | ||
349 | { 1440, 900, 60, 1 }, | ||
350 | { 1440, 900, 60, 0 }, | ||
351 | { 1440, 900, 75, 0 }, | ||
352 | { 1440, 900, 85, 0 }, | ||
353 | { 1400, 1050, 60, 1 }, | ||
354 | { 1400, 1050, 60, 0 }, | ||
355 | { 1400, 1050, 75, 0 }, | ||
356 | /* byte 9 */ | ||
357 | { 1400, 1050, 85, 0 }, | ||
358 | { 1680, 1050, 60, 1 }, | ||
359 | { 1680, 1050, 60, 0 }, | ||
360 | { 1680, 1050, 75, 0 }, | ||
361 | { 1680, 1050, 85, 0 }, | ||
362 | { 1600, 1200, 60, 0 }, | ||
363 | { 1600, 1200, 65, 0 }, | ||
364 | { 1600, 1200, 70, 0 }, | ||
365 | /* byte 10 */ | ||
366 | { 1600, 1200, 75, 0 }, | ||
367 | { 1600, 1200, 85, 0 }, | ||
368 | { 1792, 1344, 60, 0 }, | ||
369 | { 1792, 1344, 85, 0 }, | ||
370 | { 1856, 1392, 60, 0 }, | ||
371 | { 1856, 1392, 75, 0 }, | ||
372 | { 1920, 1200, 60, 1 }, | ||
373 | { 1920, 1200, 60, 0 }, | ||
374 | /* byte 11 */ | ||
375 | { 1920, 1200, 75, 0 }, | ||
376 | { 1920, 1200, 85, 0 }, | ||
377 | { 1920, 1440, 60, 0 }, | ||
378 | { 1920, 1440, 75, 0 }, | ||
379 | }; | ||
380 | static const int num_est3_modes = sizeof(est3_modes) / sizeof(est3_modes[0]); | ||
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 2ca8df8b6102..3a652a65546f 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c | |||
@@ -135,15 +135,9 @@ int drm_open(struct inode *inode, struct file *filp) | |||
135 | retcode = drm_open_helper(inode, filp, dev); | 135 | retcode = drm_open_helper(inode, filp, dev); |
136 | if (!retcode) { | 136 | if (!retcode) { |
137 | atomic_inc(&dev->counts[_DRM_STAT_OPENS]); | 137 | atomic_inc(&dev->counts[_DRM_STAT_OPENS]); |
138 | spin_lock(&dev->count_lock); | 138 | if (!dev->open_count++) |
139 | if (!dev->open_count++) { | ||
140 | spin_unlock(&dev->count_lock); | ||
141 | retcode = drm_setup(dev); | 139 | retcode = drm_setup(dev); |
142 | goto out; | ||
143 | } | ||
144 | spin_unlock(&dev->count_lock); | ||
145 | } | 140 | } |
146 | out: | ||
147 | if (!retcode) { | 141 | if (!retcode) { |
148 | mutex_lock(&dev->struct_mutex); | 142 | mutex_lock(&dev->struct_mutex); |
149 | if (minor->type == DRM_MINOR_LEGACY) { | 143 | if (minor->type == DRM_MINOR_LEGACY) { |
@@ -570,18 +564,14 @@ int drm_release(struct inode *inode, struct file *filp) | |||
570 | */ | 564 | */ |
571 | 565 | ||
572 | atomic_inc(&dev->counts[_DRM_STAT_CLOSES]); | 566 | atomic_inc(&dev->counts[_DRM_STAT_CLOSES]); |
573 | spin_lock(&dev->count_lock); | ||
574 | if (!--dev->open_count) { | 567 | if (!--dev->open_count) { |
575 | if (atomic_read(&dev->ioctl_count)) { | 568 | if (atomic_read(&dev->ioctl_count)) { |
576 | DRM_ERROR("Device busy: %d\n", | 569 | DRM_ERROR("Device busy: %d\n", |
577 | atomic_read(&dev->ioctl_count)); | 570 | atomic_read(&dev->ioctl_count)); |
578 | retcode = -EBUSY; | 571 | retcode = -EBUSY; |
579 | goto out; | 572 | } else |
580 | } | 573 | retcode = drm_lastclose(dev); |
581 | retcode = drm_lastclose(dev); | ||
582 | } | 574 | } |
583 | out: | ||
584 | spin_unlock(&dev->count_lock); | ||
585 | mutex_unlock(&drm_global_mutex); | 575 | mutex_unlock(&drm_global_mutex); |
586 | 576 | ||
587 | return retcode; | 577 | return retcode; |
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 4f1b86714489..bf92d07510df 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c | |||
@@ -322,7 +322,7 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data, | |||
322 | 322 | ||
323 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 323 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
324 | if (obj == NULL) | 324 | if (obj == NULL) |
325 | return -EBADF; | 325 | return -ENOENT; |
326 | 326 | ||
327 | again: | 327 | again: |
328 | if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0) { | 328 | if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0) { |
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 7b03b197fc00..47db4df37a69 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c | |||
@@ -392,6 +392,7 @@ int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_pri | |||
392 | if (sv->drm_di_minor >= 1) { | 392 | if (sv->drm_di_minor >= 1) { |
393 | /* | 393 | /* |
394 | * Version 1.1 includes tying of DRM to specific device | 394 | * Version 1.1 includes tying of DRM to specific device |
395 | * Version 1.4 has proper PCI domain support | ||
395 | */ | 396 | */ |
396 | retcode = drm_set_busid(dev, file_priv); | 397 | retcode = drm_set_busid(dev, file_priv); |
397 | if (retcode) | 398 | if (retcode) |
diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c index 833b35f44a77..08792a740f18 100644 --- a/drivers/gpu/drm/i2c/ch7006_drv.c +++ b/drivers/gpu/drm/i2c/ch7006_drv.c | |||
@@ -470,6 +470,7 @@ static int ch7006_encoder_init(struct i2c_client *client, | |||
470 | priv->hmargin = 50; | 470 | priv->hmargin = 50; |
471 | priv->vmargin = 50; | 471 | priv->vmargin = 50; |
472 | priv->last_dpms = -1; | 472 | priv->last_dpms = -1; |
473 | priv->chip_version = ch7006_read(client, CH7006_VERSION_ID); | ||
473 | 474 | ||
474 | if (ch7006_tv_norm) { | 475 | if (ch7006_tv_norm) { |
475 | for (i = 0; i < NUM_TV_NORMS; i++) { | 476 | for (i = 0; i < NUM_TV_NORMS; i++) { |
diff --git a/drivers/gpu/drm/i2c/ch7006_mode.c b/drivers/gpu/drm/i2c/ch7006_mode.c index e447dfb63890..c860f24a5afc 100644 --- a/drivers/gpu/drm/i2c/ch7006_mode.c +++ b/drivers/gpu/drm/i2c/ch7006_mode.c | |||
@@ -316,7 +316,10 @@ void ch7006_setup_power_state(struct drm_encoder *encoder) | |||
316 | } | 316 | } |
317 | 317 | ||
318 | } else { | 318 | } else { |
319 | *power |= bitfs(CH7006_POWER_LEVEL, FULL_POWER_OFF); | 319 | if (priv->chip_version >= 0x20) |
320 | *power |= bitfs(CH7006_POWER_LEVEL, FULL_POWER_OFF); | ||
321 | else | ||
322 | *power |= bitfs(CH7006_POWER_LEVEL, POWER_OFF); | ||
320 | } | 323 | } |
321 | } | 324 | } |
322 | 325 | ||
diff --git a/drivers/gpu/drm/i2c/ch7006_priv.h b/drivers/gpu/drm/i2c/ch7006_priv.h index 1c6d2e3bd96f..17667b7d57e7 100644 --- a/drivers/gpu/drm/i2c/ch7006_priv.h +++ b/drivers/gpu/drm/i2c/ch7006_priv.h | |||
@@ -95,6 +95,7 @@ struct ch7006_priv { | |||
95 | int flicker; | 95 | int flicker; |
96 | int scale; | 96 | int scale; |
97 | 97 | ||
98 | int chip_version; | ||
98 | int last_dpms; | 99 | int last_dpms; |
99 | }; | 100 | }; |
100 | 101 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2a4ed7ca8b4e..0758c7802e6b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -456,7 +456,7 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, | |||
456 | 456 | ||
457 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 457 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
458 | if (obj == NULL) | 458 | if (obj == NULL) |
459 | return -EBADF; | 459 | return -ENOENT; |
460 | obj_priv = to_intel_bo(obj); | 460 | obj_priv = to_intel_bo(obj); |
461 | 461 | ||
462 | /* Bounds check source. | 462 | /* Bounds check source. |
@@ -919,7 +919,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | |||
919 | 919 | ||
920 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 920 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
921 | if (obj == NULL) | 921 | if (obj == NULL) |
922 | return -EBADF; | 922 | return -ENOENT; |
923 | obj_priv = to_intel_bo(obj); | 923 | obj_priv = to_intel_bo(obj); |
924 | 924 | ||
925 | /* Bounds check destination. | 925 | /* Bounds check destination. |
@@ -1002,7 +1002,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
1002 | 1002 | ||
1003 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 1003 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
1004 | if (obj == NULL) | 1004 | if (obj == NULL) |
1005 | return -EBADF; | 1005 | return -ENOENT; |
1006 | obj_priv = to_intel_bo(obj); | 1006 | obj_priv = to_intel_bo(obj); |
1007 | 1007 | ||
1008 | mutex_lock(&dev->struct_mutex); | 1008 | mutex_lock(&dev->struct_mutex); |
@@ -1060,7 +1060,7 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, | |||
1060 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 1060 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
1061 | if (obj == NULL) { | 1061 | if (obj == NULL) { |
1062 | mutex_unlock(&dev->struct_mutex); | 1062 | mutex_unlock(&dev->struct_mutex); |
1063 | return -EBADF; | 1063 | return -ENOENT; |
1064 | } | 1064 | } |
1065 | 1065 | ||
1066 | #if WATCH_BUF | 1066 | #if WATCH_BUF |
@@ -1099,7 +1099,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, | |||
1099 | 1099 | ||
1100 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 1100 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
1101 | if (obj == NULL) | 1101 | if (obj == NULL) |
1102 | return -EBADF; | 1102 | return -ENOENT; |
1103 | 1103 | ||
1104 | offset = args->offset; | 1104 | offset = args->offset; |
1105 | 1105 | ||
@@ -1373,7 +1373,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, | |||
1373 | 1373 | ||
1374 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 1374 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
1375 | if (obj == NULL) | 1375 | if (obj == NULL) |
1376 | return -EBADF; | 1376 | return -ENOENT; |
1377 | 1377 | ||
1378 | mutex_lock(&dev->struct_mutex); | 1378 | mutex_lock(&dev->struct_mutex); |
1379 | 1379 | ||
@@ -3364,7 +3364,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
3364 | reloc->target_handle); | 3364 | reloc->target_handle); |
3365 | if (target_obj == NULL) { | 3365 | if (target_obj == NULL) { |
3366 | i915_gem_object_unpin(obj); | 3366 | i915_gem_object_unpin(obj); |
3367 | return -EBADF; | 3367 | return -ENOENT; |
3368 | } | 3368 | } |
3369 | target_obj_priv = to_intel_bo(target_obj); | 3369 | target_obj_priv = to_intel_bo(target_obj); |
3370 | 3370 | ||
@@ -3781,7 +3781,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3781 | exec_list[i].handle, i); | 3781 | exec_list[i].handle, i); |
3782 | /* prevent error path from reading uninitialized data */ | 3782 | /* prevent error path from reading uninitialized data */ |
3783 | args->buffer_count = i + 1; | 3783 | args->buffer_count = i + 1; |
3784 | ret = -EBADF; | 3784 | ret = -ENOENT; |
3785 | goto err; | 3785 | goto err; |
3786 | } | 3786 | } |
3787 | 3787 | ||
@@ -3791,7 +3791,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3791 | object_list[i]); | 3791 | object_list[i]); |
3792 | /* prevent error path from reading uninitialized data */ | 3792 | /* prevent error path from reading uninitialized data */ |
3793 | args->buffer_count = i + 1; | 3793 | args->buffer_count = i + 1; |
3794 | ret = -EBADF; | 3794 | ret = -EINVAL; |
3795 | goto err; | 3795 | goto err; |
3796 | } | 3796 | } |
3797 | obj_priv->in_execbuffer = true; | 3797 | obj_priv->in_execbuffer = true; |
@@ -4265,7 +4265,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, | |||
4265 | DRM_ERROR("Bad handle in i915_gem_pin_ioctl(): %d\n", | 4265 | DRM_ERROR("Bad handle in i915_gem_pin_ioctl(): %d\n", |
4266 | args->handle); | 4266 | args->handle); |
4267 | mutex_unlock(&dev->struct_mutex); | 4267 | mutex_unlock(&dev->struct_mutex); |
4268 | return -EBADF; | 4268 | return -ENOENT; |
4269 | } | 4269 | } |
4270 | obj_priv = to_intel_bo(obj); | 4270 | obj_priv = to_intel_bo(obj); |
4271 | 4271 | ||
@@ -4321,7 +4321,7 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data, | |||
4321 | DRM_ERROR("Bad handle in i915_gem_unpin_ioctl(): %d\n", | 4321 | DRM_ERROR("Bad handle in i915_gem_unpin_ioctl(): %d\n", |
4322 | args->handle); | 4322 | args->handle); |
4323 | mutex_unlock(&dev->struct_mutex); | 4323 | mutex_unlock(&dev->struct_mutex); |
4324 | return -EBADF; | 4324 | return -ENOENT; |
4325 | } | 4325 | } |
4326 | 4326 | ||
4327 | obj_priv = to_intel_bo(obj); | 4327 | obj_priv = to_intel_bo(obj); |
@@ -4355,7 +4355,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
4355 | if (obj == NULL) { | 4355 | if (obj == NULL) { |
4356 | DRM_ERROR("Bad handle in i915_gem_busy_ioctl(): %d\n", | 4356 | DRM_ERROR("Bad handle in i915_gem_busy_ioctl(): %d\n", |
4357 | args->handle); | 4357 | args->handle); |
4358 | return -EBADF; | 4358 | return -ENOENT; |
4359 | } | 4359 | } |
4360 | 4360 | ||
4361 | mutex_lock(&dev->struct_mutex); | 4361 | mutex_lock(&dev->struct_mutex); |
@@ -4408,7 +4408,7 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, | |||
4408 | if (obj == NULL) { | 4408 | if (obj == NULL) { |
4409 | DRM_ERROR("Bad handle in i915_gem_madvise_ioctl(): %d\n", | 4409 | DRM_ERROR("Bad handle in i915_gem_madvise_ioctl(): %d\n", |
4410 | args->handle); | 4410 | args->handle); |
4411 | return -EBADF; | 4411 | return -ENOENT; |
4412 | } | 4412 | } |
4413 | 4413 | ||
4414 | mutex_lock(&dev->struct_mutex); | 4414 | mutex_lock(&dev->struct_mutex); |
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 155719e4d16f..710eca70b323 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c | |||
@@ -275,7 +275,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, | |||
275 | 275 | ||
276 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 276 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
277 | if (obj == NULL) | 277 | if (obj == NULL) |
278 | return -EINVAL; | 278 | return -ENOENT; |
279 | obj_priv = to_intel_bo(obj); | 279 | obj_priv = to_intel_bo(obj); |
280 | 280 | ||
281 | if (!i915_tiling_ok(dev, args->stride, obj->size, args->tiling_mode)) { | 281 | if (!i915_tiling_ok(dev, args->stride, obj->size, args->tiling_mode)) { |
@@ -362,7 +362,7 @@ i915_gem_get_tiling(struct drm_device *dev, void *data, | |||
362 | 362 | ||
363 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 363 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
364 | if (obj == NULL) | 364 | if (obj == NULL) |
365 | return -EINVAL; | 365 | return -ENOENT; |
366 | obj_priv = to_intel_bo(obj); | 366 | obj_priv = to_intel_bo(obj); |
367 | 367 | ||
368 | mutex_lock(&dev->struct_mutex); | 368 | mutex_lock(&dev->struct_mutex); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1e5e0d379fa9..5ec10e02341b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -4429,15 +4429,12 @@ void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, | |||
4429 | } | 4429 | } |
4430 | 4430 | ||
4431 | static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, | 4431 | static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, |
4432 | u16 *blue, uint32_t size) | 4432 | u16 *blue, uint32_t start, uint32_t size) |
4433 | { | 4433 | { |
4434 | int end = (start + size > 256) ? 256 : start + size, i; | ||
4434 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 4435 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
4435 | int i; | ||
4436 | |||
4437 | if (size != 256) | ||
4438 | return; | ||
4439 | 4436 | ||
4440 | for (i = 0; i < 256; i++) { | 4437 | for (i = start; i < end; i++) { |
4441 | intel_crtc->lut_r[i] = red[i] >> 8; | 4438 | intel_crtc->lut_r[i] = red[i] >> 8; |
4442 | intel_crtc->lut_g[i] = green[i] >> 8; | 4439 | intel_crtc->lut_g[i] = green[i] >> 8; |
4443 | intel_crtc->lut_b[i] = blue[i] >> 8; | 4440 | intel_crtc->lut_b[i] = blue[i] >> 8; |
@@ -5412,18 +5409,18 @@ intel_user_framebuffer_create(struct drm_device *dev, | |||
5412 | 5409 | ||
5413 | obj = drm_gem_object_lookup(dev, filp, mode_cmd->handle); | 5410 | obj = drm_gem_object_lookup(dev, filp, mode_cmd->handle); |
5414 | if (!obj) | 5411 | if (!obj) |
5415 | return NULL; | 5412 | return ERR_PTR(-ENOENT); |
5416 | 5413 | ||
5417 | intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); | 5414 | intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); |
5418 | if (!intel_fb) | 5415 | if (!intel_fb) |
5419 | return NULL; | 5416 | return ERR_PTR(-ENOMEM); |
5420 | 5417 | ||
5421 | ret = intel_framebuffer_init(dev, intel_fb, | 5418 | ret = intel_framebuffer_init(dev, intel_fb, |
5422 | mode_cmd, obj); | 5419 | mode_cmd, obj); |
5423 | if (ret) { | 5420 | if (ret) { |
5424 | drm_gem_object_unreference_unlocked(obj); | 5421 | drm_gem_object_unreference_unlocked(obj); |
5425 | kfree(intel_fb); | 5422 | kfree(intel_fb); |
5426 | return NULL; | 5423 | return ERR_PTR(ret); |
5427 | } | 5424 | } |
5428 | 5425 | ||
5429 | return &intel_fb->base; | 5426 | return &intel_fb->base; |
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index a79525f434a8..7bdc96256bf5 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c | |||
@@ -121,7 +121,9 @@ static int intelfb_create(struct intel_fbdev *ifbdev, | |||
121 | 121 | ||
122 | info->par = ifbdev; | 122 | info->par = ifbdev; |
123 | 123 | ||
124 | intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, fbo); | 124 | ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, fbo); |
125 | if (ret) | ||
126 | goto out_unpin; | ||
125 | 127 | ||
126 | fb = &ifbdev->ifb.base; | 128 | fb = &ifbdev->ifb.base; |
127 | 129 | ||
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 2405d5ef0ca7..e9b06e4ef2a2 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile | |||
@@ -12,12 +12,12 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ | |||
12 | nouveau_dp.o \ | 12 | nouveau_dp.o \ |
13 | nv04_timer.o \ | 13 | nv04_timer.o \ |
14 | nv04_mc.o nv40_mc.o nv50_mc.o \ | 14 | nv04_mc.o nv40_mc.o nv50_mc.o \ |
15 | nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o \ | 15 | nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \ |
16 | nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \ | 16 | nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o nvc0_fifo.o \ |
17 | nv04_graph.o nv10_graph.o nv20_graph.o \ | 17 | nv04_graph.o nv10_graph.o nv20_graph.o \ |
18 | nv40_graph.o nv50_graph.o \ | 18 | nv40_graph.o nv50_graph.o nvc0_graph.o \ |
19 | nv40_grctx.o nv50_grctx.o \ | 19 | nv40_grctx.o nv50_grctx.o \ |
20 | nv04_instmem.o nv50_instmem.o \ | 20 | nv04_instmem.o nv50_instmem.o nvc0_instmem.o \ |
21 | nv50_crtc.o nv50_dac.o nv50_sor.o \ | 21 | nv50_crtc.o nv50_dac.o nv50_sor.o \ |
22 | nv50_cursor.o nv50_display.o nv50_fbcon.o \ | 22 | nv50_cursor.o nv50_display.o nv50_fbcon.o \ |
23 | nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ | 23 | nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 7369b5e73649..0b69a9628c95 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
@@ -1928,6 +1928,31 @@ init_condition_time(struct nvbios *bios, uint16_t offset, | |||
1928 | } | 1928 | } |
1929 | 1929 | ||
1930 | static int | 1930 | static int |
1931 | init_ltime(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | ||
1932 | { | ||
1933 | /* | ||
1934 | * INIT_LTIME opcode: 0x57 ('V') | ||
1935 | * | ||
1936 | * offset (8 bit): opcode | ||
1937 | * offset + 1 (16 bit): time | ||
1938 | * | ||
1939 | * Sleep for "time" miliseconds. | ||
1940 | */ | ||
1941 | |||
1942 | unsigned time = ROM16(bios->data[offset + 1]); | ||
1943 | |||
1944 | if (!iexec->execute) | ||
1945 | return 3; | ||
1946 | |||
1947 | BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X miliseconds\n", | ||
1948 | offset, time); | ||
1949 | |||
1950 | msleep(time); | ||
1951 | |||
1952 | return 3; | ||
1953 | } | ||
1954 | |||
1955 | static int | ||
1931 | init_zm_reg_sequence(struct nvbios *bios, uint16_t offset, | 1956 | init_zm_reg_sequence(struct nvbios *bios, uint16_t offset, |
1932 | struct init_exec *iexec) | 1957 | struct init_exec *iexec) |
1933 | { | 1958 | { |
@@ -1995,6 +2020,64 @@ init_sub_direct(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
1995 | } | 2020 | } |
1996 | 2021 | ||
1997 | static int | 2022 | static int |
2023 | init_i2c_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | ||
2024 | { | ||
2025 | /* | ||
2026 | * INIT_I2C_IF opcode: 0x5E ('^') | ||
2027 | * | ||
2028 | * offset (8 bit): opcode | ||
2029 | * offset + 1 (8 bit): DCB I2C table entry index | ||
2030 | * offset + 2 (8 bit): I2C slave address | ||
2031 | * offset + 3 (8 bit): I2C register | ||
2032 | * offset + 4 (8 bit): mask | ||
2033 | * offset + 5 (8 bit): data | ||
2034 | * | ||
2035 | * Read the register given by "I2C register" on the device addressed | ||
2036 | * by "I2C slave address" on the I2C bus given by "DCB I2C table | ||
2037 | * entry index". Compare the result AND "mask" to "data". | ||
2038 | * If they're not equal, skip subsequent opcodes until condition is | ||
2039 | * inverted (INIT_NOT), or we hit INIT_RESUME | ||
2040 | */ | ||
2041 | |||
2042 | uint8_t i2c_index = bios->data[offset + 1]; | ||
2043 | uint8_t i2c_address = bios->data[offset + 2] >> 1; | ||
2044 | uint8_t reg = bios->data[offset + 3]; | ||
2045 | uint8_t mask = bios->data[offset + 4]; | ||
2046 | uint8_t data = bios->data[offset + 5]; | ||
2047 | struct nouveau_i2c_chan *chan; | ||
2048 | union i2c_smbus_data val; | ||
2049 | int ret; | ||
2050 | |||
2051 | /* no execute check by design */ | ||
2052 | |||
2053 | BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X\n", | ||
2054 | offset, i2c_index, i2c_address); | ||
2055 | |||
2056 | chan = init_i2c_device_find(bios->dev, i2c_index); | ||
2057 | if (!chan) | ||
2058 | return -ENODEV; | ||
2059 | |||
2060 | ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0, | ||
2061 | I2C_SMBUS_READ, reg, | ||
2062 | I2C_SMBUS_BYTE_DATA, &val); | ||
2063 | if (ret < 0) { | ||
2064 | BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: [no device], " | ||
2065 | "Mask: 0x%02X, Data: 0x%02X\n", | ||
2066 | offset, reg, mask, data); | ||
2067 | iexec->execute = 0; | ||
2068 | return 6; | ||
2069 | } | ||
2070 | |||
2071 | BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: 0x%02X, " | ||
2072 | "Mask: 0x%02X, Data: 0x%02X\n", | ||
2073 | offset, reg, val.byte, mask, data); | ||
2074 | |||
2075 | iexec->execute = ((val.byte & mask) == data); | ||
2076 | |||
2077 | return 6; | ||
2078 | } | ||
2079 | |||
2080 | static int | ||
1998 | init_copy_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | 2081 | init_copy_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) |
1999 | { | 2082 | { |
2000 | /* | 2083 | /* |
@@ -2083,9 +2166,10 @@ peek_fb(struct drm_device *dev, struct io_mapping *fb, | |||
2083 | uint32_t val = 0; | 2166 | uint32_t val = 0; |
2084 | 2167 | ||
2085 | if (off < pci_resource_len(dev->pdev, 1)) { | 2168 | if (off < pci_resource_len(dev->pdev, 1)) { |
2086 | uint32_t __iomem *p = io_mapping_map_atomic_wc(fb, off, KM_USER0); | 2169 | uint32_t __iomem *p = |
2170 | io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0); | ||
2087 | 2171 | ||
2088 | val = ioread32(p); | 2172 | val = ioread32(p + (off & ~PAGE_MASK)); |
2089 | 2173 | ||
2090 | io_mapping_unmap_atomic(p, KM_USER0); | 2174 | io_mapping_unmap_atomic(p, KM_USER0); |
2091 | } | 2175 | } |
@@ -2098,9 +2182,10 @@ poke_fb(struct drm_device *dev, struct io_mapping *fb, | |||
2098 | uint32_t off, uint32_t val) | 2182 | uint32_t off, uint32_t val) |
2099 | { | 2183 | { |
2100 | if (off < pci_resource_len(dev->pdev, 1)) { | 2184 | if (off < pci_resource_len(dev->pdev, 1)) { |
2101 | uint32_t __iomem *p = io_mapping_map_atomic_wc(fb, off, KM_USER0); | 2185 | uint32_t __iomem *p = |
2186 | io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0); | ||
2102 | 2187 | ||
2103 | iowrite32(val, p); | 2188 | iowrite32(val, p + (off & ~PAGE_MASK)); |
2104 | wmb(); | 2189 | wmb(); |
2105 | 2190 | ||
2106 | io_mapping_unmap_atomic(p, KM_USER0); | 2191 | io_mapping_unmap_atomic(p, KM_USER0); |
@@ -2165,7 +2250,7 @@ nv04_init_compute_mem(struct nvbios *bios) | |||
2165 | NV04_PFB_BOOT_0_RAM_AMOUNT, | 2250 | NV04_PFB_BOOT_0_RAM_AMOUNT, |
2166 | NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); | 2251 | NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); |
2167 | 2252 | ||
2168 | } else if (peek_fb(dev, fb, 0) == patt) { | 2253 | } else if (peek_fb(dev, fb, 0) != patt) { |
2169 | if (read_back_fb(dev, fb, 0x800000, patt)) | 2254 | if (read_back_fb(dev, fb, 0x800000, patt)) |
2170 | bios_md32(bios, NV04_PFB_BOOT_0, | 2255 | bios_md32(bios, NV04_PFB_BOOT_0, |
2171 | NV04_PFB_BOOT_0_RAM_AMOUNT, | 2256 | NV04_PFB_BOOT_0_RAM_AMOUNT, |
@@ -2593,7 +2678,7 @@ init_configure_preinit(struct nvbios *bios, uint16_t offset, | |||
2593 | /* no iexec->execute check by design */ | 2678 | /* no iexec->execute check by design */ |
2594 | 2679 | ||
2595 | uint32_t straps = bios_rd32(bios, NV_PEXTDEV_BOOT_0); | 2680 | uint32_t straps = bios_rd32(bios, NV_PEXTDEV_BOOT_0); |
2596 | uint8_t cr3c = ((straps << 2) & 0xf0) | (straps & (1 << 6)); | 2681 | uint8_t cr3c = ((straps << 2) & 0xf0) | (straps & 0x40) >> 6; |
2597 | 2682 | ||
2598 | if (bios->major_version > 2) | 2683 | if (bios->major_version > 2) |
2599 | return 0; | 2684 | return 0; |
@@ -3140,7 +3225,7 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
3140 | const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; | 3225 | const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; |
3141 | int i; | 3226 | int i; |
3142 | 3227 | ||
3143 | if (dev_priv->card_type != NV_50) { | 3228 | if (dev_priv->card_type < NV_50) { |
3144 | NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n"); | 3229 | NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n"); |
3145 | return 1; | 3230 | return 1; |
3146 | } | 3231 | } |
@@ -3490,6 +3575,69 @@ init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
3490 | return len; | 3575 | return len; |
3491 | } | 3576 | } |
3492 | 3577 | ||
3578 | static int | ||
3579 | init_i2c_long_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | ||
3580 | { | ||
3581 | /* | ||
3582 | * INIT_I2C_LONG_IF opcode: 0x9A ('') | ||
3583 | * | ||
3584 | * offset (8 bit): opcode | ||
3585 | * offset + 1 (8 bit): DCB I2C table entry index | ||
3586 | * offset + 2 (8 bit): I2C slave address | ||
3587 | * offset + 3 (16 bit): I2C register | ||
3588 | * offset + 5 (8 bit): mask | ||
3589 | * offset + 6 (8 bit): data | ||
3590 | * | ||
3591 | * Read the register given by "I2C register" on the device addressed | ||
3592 | * by "I2C slave address" on the I2C bus given by "DCB I2C table | ||
3593 | * entry index". Compare the result AND "mask" to "data". | ||
3594 | * If they're not equal, skip subsequent opcodes until condition is | ||
3595 | * inverted (INIT_NOT), or we hit INIT_RESUME | ||
3596 | */ | ||
3597 | |||
3598 | uint8_t i2c_index = bios->data[offset + 1]; | ||
3599 | uint8_t i2c_address = bios->data[offset + 2] >> 1; | ||
3600 | uint8_t reglo = bios->data[offset + 3]; | ||
3601 | uint8_t reghi = bios->data[offset + 4]; | ||
3602 | uint8_t mask = bios->data[offset + 5]; | ||
3603 | uint8_t data = bios->data[offset + 6]; | ||
3604 | struct nouveau_i2c_chan *chan; | ||
3605 | uint8_t buf0[2] = { reghi, reglo }; | ||
3606 | uint8_t buf1[1]; | ||
3607 | struct i2c_msg msg[2] = { | ||
3608 | { i2c_address, 0, 1, buf0 }, | ||
3609 | { i2c_address, I2C_M_RD, 1, buf1 }, | ||
3610 | }; | ||
3611 | int ret; | ||
3612 | |||
3613 | /* no execute check by design */ | ||
3614 | |||
3615 | BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X\n", | ||
3616 | offset, i2c_index, i2c_address); | ||
3617 | |||
3618 | chan = init_i2c_device_find(bios->dev, i2c_index); | ||
3619 | if (!chan) | ||
3620 | return -ENODEV; | ||
3621 | |||
3622 | |||
3623 | ret = i2c_transfer(&chan->adapter, msg, 2); | ||
3624 | if (ret < 0) { | ||
3625 | BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X:0x%02X, Value: [no device], " | ||
3626 | "Mask: 0x%02X, Data: 0x%02X\n", | ||
3627 | offset, reghi, reglo, mask, data); | ||
3628 | iexec->execute = 0; | ||
3629 | return 7; | ||
3630 | } | ||
3631 | |||
3632 | BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X:0x%02X, Value: 0x%02X, " | ||
3633 | "Mask: 0x%02X, Data: 0x%02X\n", | ||
3634 | offset, reghi, reglo, buf1[0], mask, data); | ||
3635 | |||
3636 | iexec->execute = ((buf1[0] & mask) == data); | ||
3637 | |||
3638 | return 7; | ||
3639 | } | ||
3640 | |||
3493 | static struct init_tbl_entry itbl_entry[] = { | 3641 | static struct init_tbl_entry itbl_entry[] = { |
3494 | /* command name , id , length , offset , mult , command handler */ | 3642 | /* command name , id , length , offset , mult , command handler */ |
3495 | /* INIT_PROG (0x31, 15, 10, 4) removed due to no example of use */ | 3643 | /* INIT_PROG (0x31, 15, 10, 4) removed due to no example of use */ |
@@ -3516,9 +3664,11 @@ static struct init_tbl_entry itbl_entry[] = { | |||
3516 | { "INIT_ZM_CR" , 0x53, init_zm_cr }, | 3664 | { "INIT_ZM_CR" , 0x53, init_zm_cr }, |
3517 | { "INIT_ZM_CR_GROUP" , 0x54, init_zm_cr_group }, | 3665 | { "INIT_ZM_CR_GROUP" , 0x54, init_zm_cr_group }, |
3518 | { "INIT_CONDITION_TIME" , 0x56, init_condition_time }, | 3666 | { "INIT_CONDITION_TIME" , 0x56, init_condition_time }, |
3667 | { "INIT_LTIME" , 0x57, init_ltime }, | ||
3519 | { "INIT_ZM_REG_SEQUENCE" , 0x58, init_zm_reg_sequence }, | 3668 | { "INIT_ZM_REG_SEQUENCE" , 0x58, init_zm_reg_sequence }, |
3520 | /* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */ | 3669 | /* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */ |
3521 | { "INIT_SUB_DIRECT" , 0x5B, init_sub_direct }, | 3670 | { "INIT_SUB_DIRECT" , 0x5B, init_sub_direct }, |
3671 | { "INIT_I2C_IF" , 0x5E, init_i2c_if }, | ||
3522 | { "INIT_COPY_NV_REG" , 0x5F, init_copy_nv_reg }, | 3672 | { "INIT_COPY_NV_REG" , 0x5F, init_copy_nv_reg }, |
3523 | { "INIT_ZM_INDEX_IO" , 0x62, init_zm_index_io }, | 3673 | { "INIT_ZM_INDEX_IO" , 0x62, init_zm_index_io }, |
3524 | { "INIT_COMPUTE_MEM" , 0x63, init_compute_mem }, | 3674 | { "INIT_COMPUTE_MEM" , 0x63, init_compute_mem }, |
@@ -3552,6 +3702,7 @@ static struct init_tbl_entry itbl_entry[] = { | |||
3552 | { "INIT_97" , 0x97, init_97 }, | 3702 | { "INIT_97" , 0x97, init_97 }, |
3553 | { "INIT_AUXCH" , 0x98, init_auxch }, | 3703 | { "INIT_AUXCH" , 0x98, init_auxch }, |
3554 | { "INIT_ZM_AUXCH" , 0x99, init_zm_auxch }, | 3704 | { "INIT_ZM_AUXCH" , 0x99, init_zm_auxch }, |
3705 | { "INIT_I2C_LONG_IF" , 0x9A, init_i2c_long_if }, | ||
3555 | { NULL , 0 , NULL } | 3706 | { NULL , 0 , NULL } |
3556 | }; | 3707 | }; |
3557 | 3708 | ||
@@ -4410,7 +4561,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, | |||
4410 | bios->display.script_table_ptr, | 4561 | bios->display.script_table_ptr, |
4411 | table[2], table[3], table[0] >= 0x21); | 4562 | table[2], table[3], table[0] >= 0x21); |
4412 | if (!otable) { | 4563 | if (!otable) { |
4413 | NV_ERROR(dev, "Couldn't find matching output script table\n"); | 4564 | NV_DEBUG_KMS(dev, "failed to match any output table\n"); |
4414 | return 1; | 4565 | return 1; |
4415 | } | 4566 | } |
4416 | 4567 | ||
@@ -4467,7 +4618,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, | |||
4467 | if (script) | 4618 | if (script) |
4468 | script = clkcmptable(bios, script, pxclk); | 4619 | script = clkcmptable(bios, script, pxclk); |
4469 | if (!script) { | 4620 | if (!script) { |
4470 | NV_ERROR(dev, "clock script 0 not found\n"); | 4621 | NV_DEBUG_KMS(dev, "clock script 0 not found\n"); |
4471 | return 1; | 4622 | return 1; |
4472 | } | 4623 | } |
4473 | 4624 | ||
@@ -4826,7 +4977,7 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4826 | pll_lim->min_p = record[12]; | 4977 | pll_lim->min_p = record[12]; |
4827 | pll_lim->max_p = record[13]; | 4978 | pll_lim->max_p = record[13]; |
4828 | /* where did this go to?? */ | 4979 | /* where did this go to?? */ |
4829 | if (limit_match == 0x00614100 || limit_match == 0x00614900) | 4980 | if ((entry[0] & 0xf0) == 0x80) |
4830 | pll_lim->refclk = 27000; | 4981 | pll_lim->refclk = 27000; |
4831 | else | 4982 | else |
4832 | pll_lim->refclk = 100000; | 4983 | pll_lim->refclk = 100000; |
@@ -5852,7 +6003,7 @@ static void fabricate_vga_output(struct dcb_table *dcb, int i2c, int heads) | |||
5852 | entry->i2c_index = i2c; | 6003 | entry->i2c_index = i2c; |
5853 | entry->heads = heads; | 6004 | entry->heads = heads; |
5854 | entry->location = DCB_LOC_ON_CHIP; | 6005 | entry->location = DCB_LOC_ON_CHIP; |
5855 | /* "or" mostly unused in early gen crt modesetting, 0 is fine */ | 6006 | entry->or = 1; |
5856 | } | 6007 | } |
5857 | 6008 | ||
5858 | static void fabricate_dvi_i_output(struct dcb_table *dcb, bool twoHeads) | 6009 | static void fabricate_dvi_i_output(struct dcb_table *dcb, bool twoHeads) |
@@ -5980,7 +6131,13 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, | |||
5980 | } | 6131 | } |
5981 | break; | 6132 | break; |
5982 | case OUTPUT_TMDS: | 6133 | case OUTPUT_TMDS: |
5983 | entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4; | 6134 | if (dcb->version >= 0x40) |
6135 | entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4; | ||
6136 | else if (dcb->version >= 0x30) | ||
6137 | entry->tmdsconf.slave_addr = (conf & 0x00000700) >> 8; | ||
6138 | else if (dcb->version >= 0x22) | ||
6139 | entry->tmdsconf.slave_addr = (conf & 0x00000070) >> 4; | ||
6140 | |||
5984 | break; | 6141 | break; |
5985 | case 0xe: | 6142 | case 0xe: |
5986 | /* weird g80 mobile type that "nv" treats as a terminator */ | 6143 | /* weird g80 mobile type that "nv" treats as a terminator */ |
@@ -6270,6 +6427,19 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) | |||
6270 | dcb->i2c_table = &bios->data[i2ctabptr]; | 6427 | dcb->i2c_table = &bios->data[i2ctabptr]; |
6271 | if (dcb->version >= 0x30) | 6428 | if (dcb->version >= 0x30) |
6272 | dcb->i2c_default_indices = dcb->i2c_table[4]; | 6429 | dcb->i2c_default_indices = dcb->i2c_table[4]; |
6430 | |||
6431 | /* | ||
6432 | * Parse the "management" I2C bus, used for hardware | ||
6433 | * monitoring and some external TMDS transmitters. | ||
6434 | */ | ||
6435 | if (dcb->version >= 0x22) { | ||
6436 | int idx = (dcb->version >= 0x40 ? | ||
6437 | dcb->i2c_default_indices & 0xf : | ||
6438 | 2); | ||
6439 | |||
6440 | read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table, | ||
6441 | idx, &dcb->i2c[idx]); | ||
6442 | } | ||
6273 | } | 6443 | } |
6274 | 6444 | ||
6275 | if (entries > DCB_MAX_NUM_ENTRIES) | 6445 | if (entries > DCB_MAX_NUM_ENTRIES) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index 024458a8d060..fd14dfd3d780 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h | |||
@@ -131,6 +131,7 @@ struct dcb_entry { | |||
131 | } dpconf; | 131 | } dpconf; |
132 | struct { | 132 | struct { |
133 | struct sor_conf sor; | 133 | struct sor_conf sor; |
134 | int slave_addr; | ||
134 | } tmdsconf; | 135 | } tmdsconf; |
135 | }; | 136 | }; |
136 | bool i2c_upper_default; | 137 | bool i2c_upper_default; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 3ca8343c15df..84f85183d041 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
@@ -51,9 +51,6 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo) | |||
51 | if (nvbo->tile) | 51 | if (nvbo->tile) |
52 | nv10_mem_expire_tiling(dev, nvbo->tile, NULL); | 52 | nv10_mem_expire_tiling(dev, nvbo->tile, NULL); |
53 | 53 | ||
54 | spin_lock(&dev_priv->ttm.bo_list_lock); | ||
55 | list_del(&nvbo->head); | ||
56 | spin_unlock(&dev_priv->ttm.bo_list_lock); | ||
57 | kfree(nvbo); | 54 | kfree(nvbo); |
58 | } | 55 | } |
59 | 56 | ||
@@ -166,9 +163,6 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, | |||
166 | } | 163 | } |
167 | nvbo->channel = NULL; | 164 | nvbo->channel = NULL; |
168 | 165 | ||
169 | spin_lock(&dev_priv->ttm.bo_list_lock); | ||
170 | list_add_tail(&nvbo->head, &dev_priv->ttm.bo_list); | ||
171 | spin_unlock(&dev_priv->ttm.bo_list_lock); | ||
172 | *pnvbo = nvbo; | 166 | *pnvbo = nvbo; |
173 | return 0; | 167 | return 0; |
174 | } | 168 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 734e92635e83..b1b22baf1428 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -37,12 +37,6 @@ | |||
37 | #include "nouveau_connector.h" | 37 | #include "nouveau_connector.h" |
38 | #include "nouveau_hw.h" | 38 | #include "nouveau_hw.h" |
39 | 39 | ||
40 | static inline struct drm_encoder_slave_funcs * | ||
41 | get_slave_funcs(struct nouveau_encoder *enc) | ||
42 | { | ||
43 | return to_encoder_slave(to_drm_encoder(enc))->slave_funcs; | ||
44 | } | ||
45 | |||
46 | static struct nouveau_encoder * | 40 | static struct nouveau_encoder * |
47 | find_encoder_by_type(struct drm_connector *connector, int type) | 41 | find_encoder_by_type(struct drm_connector *connector, int type) |
48 | { | 42 | { |
@@ -360,6 +354,7 @@ nouveau_connector_set_property(struct drm_connector *connector, | |||
360 | { | 354 | { |
361 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 355 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
362 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; | 356 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; |
357 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); | ||
363 | struct drm_device *dev = connector->dev; | 358 | struct drm_device *dev = connector->dev; |
364 | int ret; | 359 | int ret; |
365 | 360 | ||
@@ -432,8 +427,8 @@ nouveau_connector_set_property(struct drm_connector *connector, | |||
432 | } | 427 | } |
433 | 428 | ||
434 | if (nv_encoder && nv_encoder->dcb->type == OUTPUT_TV) | 429 | if (nv_encoder && nv_encoder->dcb->type == OUTPUT_TV) |
435 | return get_slave_funcs(nv_encoder)-> | 430 | return get_slave_funcs(encoder)->set_property( |
436 | set_property(to_drm_encoder(nv_encoder), connector, property, value); | 431 | encoder, connector, property, value); |
437 | 432 | ||
438 | return -EINVAL; | 433 | return -EINVAL; |
439 | } | 434 | } |
@@ -545,6 +540,7 @@ nouveau_connector_get_modes(struct drm_connector *connector) | |||
545 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 540 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
546 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 541 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
547 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; | 542 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; |
543 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); | ||
548 | int ret = 0; | 544 | int ret = 0; |
549 | 545 | ||
550 | /* destroy the native mode, the attached monitor could have changed. | 546 | /* destroy the native mode, the attached monitor could have changed. |
@@ -580,8 +576,7 @@ nouveau_connector_get_modes(struct drm_connector *connector) | |||
580 | } | 576 | } |
581 | 577 | ||
582 | if (nv_encoder->dcb->type == OUTPUT_TV) | 578 | if (nv_encoder->dcb->type == OUTPUT_TV) |
583 | ret = get_slave_funcs(nv_encoder)-> | 579 | ret = get_slave_funcs(encoder)->get_modes(encoder, connector); |
584 | get_modes(to_drm_encoder(nv_encoder), connector); | ||
585 | 580 | ||
586 | if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS || | 581 | if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS || |
587 | nv_connector->dcb->type == DCB_CONNECTOR_eDP) | 582 | nv_connector->dcb->type == DCB_CONNECTOR_eDP) |
@@ -597,6 +592,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector, | |||
597 | struct drm_nouveau_private *dev_priv = connector->dev->dev_private; | 592 | struct drm_nouveau_private *dev_priv = connector->dev->dev_private; |
598 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 593 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
599 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; | 594 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; |
595 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); | ||
600 | unsigned min_clock = 25000, max_clock = min_clock; | 596 | unsigned min_clock = 25000, max_clock = min_clock; |
601 | unsigned clock = mode->clock; | 597 | unsigned clock = mode->clock; |
602 | 598 | ||
@@ -623,8 +619,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector, | |||
623 | max_clock = 350000; | 619 | max_clock = 350000; |
624 | break; | 620 | break; |
625 | case OUTPUT_TV: | 621 | case OUTPUT_TV: |
626 | return get_slave_funcs(nv_encoder)-> | 622 | return get_slave_funcs(encoder)->mode_valid(encoder, mode); |
627 | mode_valid(to_drm_encoder(nv_encoder), mode); | ||
628 | case OUTPUT_DP: | 623 | case OUTPUT_DP: |
629 | if (nv_encoder->dp.link_bw == DP_LINK_BW_2_7) | 624 | if (nv_encoder->dp.link_bw == DP_LINK_BW_2_7) |
630 | max_clock = nv_encoder->dp.link_nr * 270000; | 625 | max_clock = nv_encoder->dp.link_nr * 270000; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 74e6b4ed12c0..2e11fd65b4dd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
@@ -84,16 +84,16 @@ nouveau_user_framebuffer_create(struct drm_device *dev, | |||
84 | 84 | ||
85 | gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); | 85 | gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); |
86 | if (!gem) | 86 | if (!gem) |
87 | return NULL; | 87 | return ERR_PTR(-ENOENT); |
88 | 88 | ||
89 | nouveau_fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL); | 89 | nouveau_fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL); |
90 | if (!nouveau_fb) | 90 | if (!nouveau_fb) |
91 | return NULL; | 91 | return ERR_PTR(-ENOMEM); |
92 | 92 | ||
93 | ret = nouveau_framebuffer_init(dev, nouveau_fb, mode_cmd, nouveau_gem_object(gem)); | 93 | ret = nouveau_framebuffer_init(dev, nouveau_fb, mode_cmd, nouveau_gem_object(gem)); |
94 | if (ret) { | 94 | if (ret) { |
95 | drm_gem_object_unreference(gem); | 95 | drm_gem_object_unreference(gem); |
96 | return NULL; | 96 | return ERR_PTR(ret); |
97 | } | 97 | } |
98 | 98 | ||
99 | return &nouveau_fb->base; | 99 | return &nouveau_fb->base; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 33742b11188b..8a1b188b4cd1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c | |||
@@ -572,47 +572,64 @@ out: | |||
572 | return ret ? ret : (stat & NV50_AUXCH_STAT_REPLY); | 572 | return ret ? ret : (stat & NV50_AUXCH_STAT_REPLY); |
573 | } | 573 | } |
574 | 574 | ||
575 | int | 575 | static int |
576 | nouveau_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, | 576 | nouveau_dp_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) |
577 | uint8_t write_byte, uint8_t *read_byte) | ||
578 | { | 577 | { |
579 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | 578 | struct nouveau_i2c_chan *auxch = (struct nouveau_i2c_chan *)adap; |
580 | struct nouveau_i2c_chan *auxch = (struct nouveau_i2c_chan *)adapter; | ||
581 | struct drm_device *dev = auxch->dev; | 579 | struct drm_device *dev = auxch->dev; |
582 | int ret = 0, cmd, addr = algo_data->address; | 580 | struct i2c_msg *msg = msgs; |
583 | uint8_t *buf; | 581 | int ret, mcnt = num; |
584 | |||
585 | if (mode == MODE_I2C_READ) { | ||
586 | cmd = AUX_I2C_READ; | ||
587 | buf = read_byte; | ||
588 | } else { | ||
589 | cmd = (mode & MODE_I2C_READ) ? AUX_I2C_READ : AUX_I2C_WRITE; | ||
590 | buf = &write_byte; | ||
591 | } | ||
592 | 582 | ||
593 | if (!(mode & MODE_I2C_STOP)) | 583 | while (mcnt--) { |
594 | cmd |= AUX_I2C_MOT; | 584 | u8 remaining = msg->len; |
585 | u8 *ptr = msg->buf; | ||
595 | 586 | ||
596 | if (mode & MODE_I2C_START) | 587 | while (remaining) { |
597 | return 1; | 588 | u8 cnt = (remaining > 16) ? 16 : remaining; |
589 | u8 cmd; | ||
598 | 590 | ||
599 | for (;;) { | 591 | if (msg->flags & I2C_M_RD) |
600 | ret = nouveau_dp_auxch(auxch, cmd, addr, buf, 1); | 592 | cmd = AUX_I2C_READ; |
601 | if (ret < 0) | 593 | else |
602 | return ret; | 594 | cmd = AUX_I2C_WRITE; |
603 | 595 | ||
604 | switch (ret & NV50_AUXCH_STAT_REPLY_I2C) { | 596 | if (mcnt || remaining > 16) |
605 | case NV50_AUXCH_STAT_REPLY_I2C_ACK: | 597 | cmd |= AUX_I2C_MOT; |
606 | return 1; | 598 | |
607 | case NV50_AUXCH_STAT_REPLY_I2C_NACK: | 599 | ret = nouveau_dp_auxch(auxch, cmd, msg->addr, ptr, cnt); |
608 | return -EREMOTEIO; | 600 | if (ret < 0) |
609 | case NV50_AUXCH_STAT_REPLY_I2C_DEFER: | 601 | return ret; |
610 | udelay(100); | 602 | |
611 | break; | 603 | switch (ret & NV50_AUXCH_STAT_REPLY_I2C) { |
612 | default: | 604 | case NV50_AUXCH_STAT_REPLY_I2C_ACK: |
613 | NV_ERROR(dev, "invalid auxch status: 0x%08x\n", ret); | 605 | break; |
614 | return -EREMOTEIO; | 606 | case NV50_AUXCH_STAT_REPLY_I2C_NACK: |
607 | return -EREMOTEIO; | ||
608 | case NV50_AUXCH_STAT_REPLY_I2C_DEFER: | ||
609 | udelay(100); | ||
610 | continue; | ||
611 | default: | ||
612 | NV_ERROR(dev, "bad auxch reply: 0x%08x\n", ret); | ||
613 | return -EREMOTEIO; | ||
614 | } | ||
615 | |||
616 | ptr += cnt; | ||
617 | remaining -= cnt; | ||
615 | } | 618 | } |
619 | |||
620 | msg++; | ||
616 | } | 621 | } |
622 | |||
623 | return num; | ||
624 | } | ||
625 | |||
626 | static u32 | ||
627 | nouveau_dp_i2c_func(struct i2c_adapter *adap) | ||
628 | { | ||
629 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||
617 | } | 630 | } |
618 | 631 | ||
632 | const struct i2c_algorithm nouveau_dp_i2c_algo = { | ||
633 | .master_xfer = nouveau_dp_i2c_xfer, | ||
634 | .functionality = nouveau_dp_i2c_func | ||
635 | }; | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index e15db15dca77..e424bf74d706 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
@@ -410,7 +410,7 @@ enum nv04_fp_display_regs { | |||
410 | 410 | ||
411 | struct nv04_crtc_reg { | 411 | struct nv04_crtc_reg { |
412 | unsigned char MiscOutReg; /* */ | 412 | unsigned char MiscOutReg; /* */ |
413 | uint8_t CRTC[0x9f]; | 413 | uint8_t CRTC[0xa0]; |
414 | uint8_t CR58[0x10]; | 414 | uint8_t CR58[0x10]; |
415 | uint8_t Sequencer[5]; | 415 | uint8_t Sequencer[5]; |
416 | uint8_t Graphics[9]; | 416 | uint8_t Graphics[9]; |
@@ -509,6 +509,7 @@ enum nouveau_card_type { | |||
509 | NV_30 = 0x30, | 509 | NV_30 = 0x30, |
510 | NV_40 = 0x40, | 510 | NV_40 = 0x40, |
511 | NV_50 = 0x50, | 511 | NV_50 = 0x50, |
512 | NV_C0 = 0xc0, | ||
512 | }; | 513 | }; |
513 | 514 | ||
514 | struct drm_nouveau_private { | 515 | struct drm_nouveau_private { |
@@ -536,8 +537,6 @@ struct drm_nouveau_private { | |||
536 | struct drm_global_reference mem_global_ref; | 537 | struct drm_global_reference mem_global_ref; |
537 | struct ttm_bo_global_ref bo_global_ref; | 538 | struct ttm_bo_global_ref bo_global_ref; |
538 | struct ttm_bo_device bdev; | 539 | struct ttm_bo_device bdev; |
539 | spinlock_t bo_list_lock; | ||
540 | struct list_head bo_list; | ||
541 | atomic_t validate_sequence; | 540 | atomic_t validate_sequence; |
542 | } ttm; | 541 | } ttm; |
543 | 542 | ||
@@ -931,6 +930,10 @@ extern void nv40_fb_set_region_tiling(struct drm_device *, int, uint32_t, | |||
931 | extern int nv50_fb_init(struct drm_device *); | 930 | extern int nv50_fb_init(struct drm_device *); |
932 | extern void nv50_fb_takedown(struct drm_device *); | 931 | extern void nv50_fb_takedown(struct drm_device *); |
933 | 932 | ||
933 | /* nvc0_fb.c */ | ||
934 | extern int nvc0_fb_init(struct drm_device *); | ||
935 | extern void nvc0_fb_takedown(struct drm_device *); | ||
936 | |||
934 | /* nv04_fifo.c */ | 937 | /* nv04_fifo.c */ |
935 | extern int nv04_fifo_init(struct drm_device *); | 938 | extern int nv04_fifo_init(struct drm_device *); |
936 | extern void nv04_fifo_disable(struct drm_device *); | 939 | extern void nv04_fifo_disable(struct drm_device *); |
@@ -968,6 +971,20 @@ extern void nv50_fifo_destroy_context(struct nouveau_channel *); | |||
968 | extern int nv50_fifo_load_context(struct nouveau_channel *); | 971 | extern int nv50_fifo_load_context(struct nouveau_channel *); |
969 | extern int nv50_fifo_unload_context(struct drm_device *); | 972 | extern int nv50_fifo_unload_context(struct drm_device *); |
970 | 973 | ||
974 | /* nvc0_fifo.c */ | ||
975 | extern int nvc0_fifo_init(struct drm_device *); | ||
976 | extern void nvc0_fifo_takedown(struct drm_device *); | ||
977 | extern void nvc0_fifo_disable(struct drm_device *); | ||
978 | extern void nvc0_fifo_enable(struct drm_device *); | ||
979 | extern bool nvc0_fifo_reassign(struct drm_device *, bool); | ||
980 | extern bool nvc0_fifo_cache_flush(struct drm_device *); | ||
981 | extern bool nvc0_fifo_cache_pull(struct drm_device *, bool); | ||
982 | extern int nvc0_fifo_channel_id(struct drm_device *); | ||
983 | extern int nvc0_fifo_create_context(struct nouveau_channel *); | ||
984 | extern void nvc0_fifo_destroy_context(struct nouveau_channel *); | ||
985 | extern int nvc0_fifo_load_context(struct nouveau_channel *); | ||
986 | extern int nvc0_fifo_unload_context(struct drm_device *); | ||
987 | |||
971 | /* nv04_graph.c */ | 988 | /* nv04_graph.c */ |
972 | extern struct nouveau_pgraph_object_class nv04_graph_grclass[]; | 989 | extern struct nouveau_pgraph_object_class nv04_graph_grclass[]; |
973 | extern int nv04_graph_init(struct drm_device *); | 990 | extern int nv04_graph_init(struct drm_device *); |
@@ -1032,6 +1049,16 @@ extern int nv50_graph_unload_context(struct drm_device *); | |||
1032 | extern void nv50_graph_context_switch(struct drm_device *); | 1049 | extern void nv50_graph_context_switch(struct drm_device *); |
1033 | extern int nv50_grctx_init(struct nouveau_grctx *); | 1050 | extern int nv50_grctx_init(struct nouveau_grctx *); |
1034 | 1051 | ||
1052 | /* nvc0_graph.c */ | ||
1053 | extern int nvc0_graph_init(struct drm_device *); | ||
1054 | extern void nvc0_graph_takedown(struct drm_device *); | ||
1055 | extern void nvc0_graph_fifo_access(struct drm_device *, bool); | ||
1056 | extern struct nouveau_channel *nvc0_graph_channel(struct drm_device *); | ||
1057 | extern int nvc0_graph_create_context(struct nouveau_channel *); | ||
1058 | extern void nvc0_graph_destroy_context(struct nouveau_channel *); | ||
1059 | extern int nvc0_graph_load_context(struct nouveau_channel *); | ||
1060 | extern int nvc0_graph_unload_context(struct drm_device *); | ||
1061 | |||
1035 | /* nv04_instmem.c */ | 1062 | /* nv04_instmem.c */ |
1036 | extern int nv04_instmem_init(struct drm_device *); | 1063 | extern int nv04_instmem_init(struct drm_device *); |
1037 | extern void nv04_instmem_takedown(struct drm_device *); | 1064 | extern void nv04_instmem_takedown(struct drm_device *); |
@@ -1058,6 +1085,18 @@ extern void nv50_instmem_flush(struct drm_device *); | |||
1058 | extern void nv84_instmem_flush(struct drm_device *); | 1085 | extern void nv84_instmem_flush(struct drm_device *); |
1059 | extern void nv50_vm_flush(struct drm_device *, int engine); | 1086 | extern void nv50_vm_flush(struct drm_device *, int engine); |
1060 | 1087 | ||
1088 | /* nvc0_instmem.c */ | ||
1089 | extern int nvc0_instmem_init(struct drm_device *); | ||
1090 | extern void nvc0_instmem_takedown(struct drm_device *); | ||
1091 | extern int nvc0_instmem_suspend(struct drm_device *); | ||
1092 | extern void nvc0_instmem_resume(struct drm_device *); | ||
1093 | extern int nvc0_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, | ||
1094 | uint32_t *size); | ||
1095 | extern void nvc0_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); | ||
1096 | extern int nvc0_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); | ||
1097 | extern int nvc0_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); | ||
1098 | extern void nvc0_instmem_flush(struct drm_device *); | ||
1099 | |||
1061 | /* nv04_mc.c */ | 1100 | /* nv04_mc.c */ |
1062 | extern int nv04_mc_init(struct drm_device *); | 1101 | extern int nv04_mc_init(struct drm_device *); |
1063 | extern void nv04_mc_takedown(struct drm_device *); | 1102 | extern void nv04_mc_takedown(struct drm_device *); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index a1a0d48ae70c..7c82d68bc155 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h | |||
@@ -71,6 +71,12 @@ static inline struct drm_encoder *to_drm_encoder(struct nouveau_encoder *enc) | |||
71 | return &enc->base.base; | 71 | return &enc->base.base; |
72 | } | 72 | } |
73 | 73 | ||
74 | static inline struct drm_encoder_slave_funcs * | ||
75 | get_slave_funcs(struct drm_encoder *enc) | ||
76 | { | ||
77 | return to_encoder_slave(enc)->slave_funcs; | ||
78 | } | ||
79 | |||
74 | struct nouveau_connector * | 80 | struct nouveau_connector * |
75 | nouveau_encoder_connector_get(struct nouveau_encoder *encoder); | 81 | nouveau_encoder_connector_get(struct nouveau_encoder *encoder); |
76 | int nv50_sor_create(struct drm_connector *, struct dcb_entry *); | 82 | int nv50_sor_create(struct drm_connector *, struct dcb_entry *); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 099f637264aa..dbd30b2e43fd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c | |||
@@ -281,6 +281,8 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, | |||
281 | 281 | ||
282 | if (dev_priv->channel && !nouveau_nofbaccel) { | 282 | if (dev_priv->channel && !nouveau_nofbaccel) { |
283 | switch (dev_priv->card_type) { | 283 | switch (dev_priv->card_type) { |
284 | case NV_C0: | ||
285 | break; | ||
284 | case NV_50: | 286 | case NV_50: |
285 | nv50_fbcon_accel_init(info); | 287 | nv50_fbcon_accel_init(info); |
286 | info->fbops = &nv50_fbcon_ops; | 288 | info->fbops = &nv50_fbcon_ops; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 547f2c24c1e7..0f417ac1b696 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
@@ -284,7 +284,7 @@ retry: | |||
284 | if (!gem) { | 284 | if (!gem) { |
285 | NV_ERROR(dev, "Unknown handle 0x%08x\n", b->handle); | 285 | NV_ERROR(dev, "Unknown handle 0x%08x\n", b->handle); |
286 | validate_fini(op, NULL); | 286 | validate_fini(op, NULL); |
287 | return -EINVAL; | 287 | return -ENOENT; |
288 | } | 288 | } |
289 | nvbo = gem->driver_private; | 289 | nvbo = gem->driver_private; |
290 | 290 | ||
@@ -759,7 +759,7 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, | |||
759 | 759 | ||
760 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); | 760 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); |
761 | if (!gem) | 761 | if (!gem) |
762 | return ret; | 762 | return -ENOENT; |
763 | nvbo = nouveau_gem_object(gem); | 763 | nvbo = nouveau_gem_object(gem); |
764 | 764 | ||
765 | if (nvbo->cpu_filp) { | 765 | if (nvbo->cpu_filp) { |
@@ -797,7 +797,7 @@ nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data, | |||
797 | 797 | ||
798 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); | 798 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); |
799 | if (!gem) | 799 | if (!gem) |
800 | return ret; | 800 | return -ENOENT; |
801 | nvbo = nouveau_gem_object(gem); | 801 | nvbo = nouveau_gem_object(gem); |
802 | 802 | ||
803 | if (nvbo->cpu_filp != file_priv) | 803 | if (nvbo->cpu_filp != file_priv) |
@@ -822,7 +822,7 @@ nouveau_gem_ioctl_info(struct drm_device *dev, void *data, | |||
822 | 822 | ||
823 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); | 823 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); |
824 | if (!gem) | 824 | if (!gem) |
825 | return -EINVAL; | 825 | return -ENOENT; |
826 | 826 | ||
827 | ret = nouveau_gem_info(gem, req); | 827 | ret = nouveau_gem_info(gem, req); |
828 | drm_gem_object_unreference_unlocked(gem); | 828 | drm_gem_object_unreference_unlocked(gem); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.c b/drivers/gpu/drm/nouveau/nouveau_hw.c index 7855b35effc3..7b613682e400 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hw.c +++ b/drivers/gpu/drm/nouveau/nouveau_hw.c | |||
@@ -865,8 +865,12 @@ nv_save_state_ext(struct drm_device *dev, int head, | |||
865 | rd_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); | 865 | rd_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); |
866 | rd_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); | 866 | rd_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); |
867 | rd_cio_state(dev, head, regp, NV_CIO_CRE_21); | 867 | rd_cio_state(dev, head, regp, NV_CIO_CRE_21); |
868 | if (dev_priv->card_type >= NV_30) | 868 | |
869 | if (dev_priv->card_type >= NV_30) { | ||
869 | rd_cio_state(dev, head, regp, NV_CIO_CRE_47); | 870 | rd_cio_state(dev, head, regp, NV_CIO_CRE_47); |
871 | rd_cio_state(dev, head, regp, 0x9f); | ||
872 | } | ||
873 | |||
870 | rd_cio_state(dev, head, regp, NV_CIO_CRE_49); | 874 | rd_cio_state(dev, head, regp, NV_CIO_CRE_49); |
871 | rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); | 875 | rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); |
872 | rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX); | 876 | rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX); |
@@ -971,8 +975,11 @@ nv_load_state_ext(struct drm_device *dev, int head, | |||
971 | wr_cio_state(dev, head, regp, NV_CIO_CRE_ENH_INDEX); | 975 | wr_cio_state(dev, head, regp, NV_CIO_CRE_ENH_INDEX); |
972 | wr_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); | 976 | wr_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); |
973 | wr_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); | 977 | wr_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); |
974 | if (dev_priv->card_type >= NV_30) | 978 | |
979 | if (dev_priv->card_type >= NV_30) { | ||
975 | wr_cio_state(dev, head, regp, NV_CIO_CRE_47); | 980 | wr_cio_state(dev, head, regp, NV_CIO_CRE_47); |
981 | wr_cio_state(dev, head, regp, 0x9f); | ||
982 | } | ||
976 | 983 | ||
977 | wr_cio_state(dev, head, regp, NV_CIO_CRE_49); | 984 | wr_cio_state(dev, head, regp, NV_CIO_CRE_49); |
978 | wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); | 985 | wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c index cb0cb34440c6..0bd407ca3d42 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.c +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c | |||
@@ -163,7 +163,7 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) | |||
163 | if (entry->chan) | 163 | if (entry->chan) |
164 | return -EEXIST; | 164 | return -EEXIST; |
165 | 165 | ||
166 | if (dev_priv->card_type == NV_50 && entry->read >= NV50_I2C_PORTS) { | 166 | if (dev_priv->card_type == NV_C0 && entry->read >= NV50_I2C_PORTS) { |
167 | NV_ERROR(dev, "unknown i2c port %d\n", entry->read); | 167 | NV_ERROR(dev, "unknown i2c port %d\n", entry->read); |
168 | return -EINVAL; | 168 | return -EINVAL; |
169 | } | 169 | } |
@@ -174,26 +174,26 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) | |||
174 | 174 | ||
175 | switch (entry->port_type) { | 175 | switch (entry->port_type) { |
176 | case 0: | 176 | case 0: |
177 | i2c->algo.bit.setsda = nv04_i2c_setsda; | 177 | i2c->bit.setsda = nv04_i2c_setsda; |
178 | i2c->algo.bit.setscl = nv04_i2c_setscl; | 178 | i2c->bit.setscl = nv04_i2c_setscl; |
179 | i2c->algo.bit.getsda = nv04_i2c_getsda; | 179 | i2c->bit.getsda = nv04_i2c_getsda; |
180 | i2c->algo.bit.getscl = nv04_i2c_getscl; | 180 | i2c->bit.getscl = nv04_i2c_getscl; |
181 | i2c->rd = entry->read; | 181 | i2c->rd = entry->read; |
182 | i2c->wr = entry->write; | 182 | i2c->wr = entry->write; |
183 | break; | 183 | break; |
184 | case 4: | 184 | case 4: |
185 | i2c->algo.bit.setsda = nv4e_i2c_setsda; | 185 | i2c->bit.setsda = nv4e_i2c_setsda; |
186 | i2c->algo.bit.setscl = nv4e_i2c_setscl; | 186 | i2c->bit.setscl = nv4e_i2c_setscl; |
187 | i2c->algo.bit.getsda = nv4e_i2c_getsda; | 187 | i2c->bit.getsda = nv4e_i2c_getsda; |
188 | i2c->algo.bit.getscl = nv4e_i2c_getscl; | 188 | i2c->bit.getscl = nv4e_i2c_getscl; |
189 | i2c->rd = 0x600800 + entry->read; | 189 | i2c->rd = 0x600800 + entry->read; |
190 | i2c->wr = 0x600800 + entry->write; | 190 | i2c->wr = 0x600800 + entry->write; |
191 | break; | 191 | break; |
192 | case 5: | 192 | case 5: |
193 | i2c->algo.bit.setsda = nv50_i2c_setsda; | 193 | i2c->bit.setsda = nv50_i2c_setsda; |
194 | i2c->algo.bit.setscl = nv50_i2c_setscl; | 194 | i2c->bit.setscl = nv50_i2c_setscl; |
195 | i2c->algo.bit.getsda = nv50_i2c_getsda; | 195 | i2c->bit.getsda = nv50_i2c_getsda; |
196 | i2c->algo.bit.getscl = nv50_i2c_getscl; | 196 | i2c->bit.getscl = nv50_i2c_getscl; |
197 | i2c->rd = nv50_i2c_port[entry->read]; | 197 | i2c->rd = nv50_i2c_port[entry->read]; |
198 | i2c->wr = i2c->rd; | 198 | i2c->wr = i2c->rd; |
199 | break; | 199 | break; |
@@ -216,17 +216,14 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) | |||
216 | i2c_set_adapdata(&i2c->adapter, i2c); | 216 | i2c_set_adapdata(&i2c->adapter, i2c); |
217 | 217 | ||
218 | if (entry->port_type < 6) { | 218 | if (entry->port_type < 6) { |
219 | i2c->adapter.algo_data = &i2c->algo.bit; | 219 | i2c->adapter.algo_data = &i2c->bit; |
220 | i2c->algo.bit.udelay = 40; | 220 | i2c->bit.udelay = 40; |
221 | i2c->algo.bit.timeout = usecs_to_jiffies(5000); | 221 | i2c->bit.timeout = usecs_to_jiffies(5000); |
222 | i2c->algo.bit.data = i2c; | 222 | i2c->bit.data = i2c; |
223 | ret = i2c_bit_add_bus(&i2c->adapter); | 223 | ret = i2c_bit_add_bus(&i2c->adapter); |
224 | } else { | 224 | } else { |
225 | i2c->adapter.algo_data = &i2c->algo.dp; | 225 | i2c->adapter.algo = &nouveau_dp_i2c_algo; |
226 | i2c->algo.dp.running = false; | 226 | ret = i2c_add_adapter(&i2c->adapter); |
227 | i2c->algo.dp.address = 0; | ||
228 | i2c->algo.dp.aux_ch = nouveau_dp_i2c_aux_ch; | ||
229 | ret = i2c_dp_aux_add_bus(&i2c->adapter); | ||
230 | } | 227 | } |
231 | 228 | ||
232 | if (ret) { | 229 | if (ret) { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.h b/drivers/gpu/drm/nouveau/nouveau_i2c.h index 6dd2f8713cd1..f71cb32f7571 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.h +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.h | |||
@@ -33,10 +33,7 @@ struct dcb_i2c_entry; | |||
33 | struct nouveau_i2c_chan { | 33 | struct nouveau_i2c_chan { |
34 | struct i2c_adapter adapter; | 34 | struct i2c_adapter adapter; |
35 | struct drm_device *dev; | 35 | struct drm_device *dev; |
36 | union { | 36 | struct i2c_algo_bit_data bit; |
37 | struct i2c_algo_bit_data bit; | ||
38 | struct i2c_algo_dp_aux_data dp; | ||
39 | } algo; | ||
40 | unsigned rd; | 37 | unsigned rd; |
41 | unsigned wr; | 38 | unsigned wr; |
42 | unsigned data; | 39 | unsigned data; |
@@ -49,7 +46,6 @@ bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr); | |||
49 | int nouveau_i2c_identify(struct drm_device *dev, const char *what, | 46 | int nouveau_i2c_identify(struct drm_device *dev, const char *what, |
50 | struct i2c_board_info *info, int index); | 47 | struct i2c_board_info *info, int index); |
51 | 48 | ||
52 | int nouveau_dp_i2c_aux_ch(struct i2c_adapter *, int mode, uint8_t write_byte, | 49 | extern const struct i2c_algorithm nouveau_dp_i2c_algo; |
53 | uint8_t *read_byte); | ||
54 | 50 | ||
55 | #endif /* __NOUVEAU_I2C_H__ */ | 51 | #endif /* __NOUVEAU_I2C_H__ */ |
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 53360f156063..794b0ee30cf6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c | |||
@@ -49,7 +49,7 @@ nouveau_irq_preinstall(struct drm_device *dev) | |||
49 | /* Master disable */ | 49 | /* Master disable */ |
50 | nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); | 50 | nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); |
51 | 51 | ||
52 | if (dev_priv->card_type == NV_50) { | 52 | if (dev_priv->card_type >= NV_50) { |
53 | INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); | 53 | INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); |
54 | INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh); | 54 | INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh); |
55 | INIT_LIST_HEAD(&dev_priv->vbl_waiting); | 55 | INIT_LIST_HEAD(&dev_priv->vbl_waiting); |
@@ -586,11 +586,11 @@ nouveau_pgraph_irq_handler(struct drm_device *dev) | |||
586 | } | 586 | } |
587 | 587 | ||
588 | if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) { | 588 | if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) { |
589 | nouveau_pgraph_intr_context_switch(dev); | ||
590 | |||
591 | status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; | 589 | status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; |
592 | nv_wr32(dev, NV03_PGRAPH_INTR, | 590 | nv_wr32(dev, NV03_PGRAPH_INTR, |
593 | NV_PGRAPH_INTR_CONTEXT_SWITCH); | 591 | NV_PGRAPH_INTR_CONTEXT_SWITCH); |
592 | |||
593 | nouveau_pgraph_intr_context_switch(dev); | ||
594 | } | 594 | } |
595 | 595 | ||
596 | if (status) { | 596 | if (status) { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index a9f36ab256b7..9689d4147686 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c | |||
@@ -320,7 +320,8 @@ nouveau_mem_detect(struct drm_device *dev) | |||
320 | if (dev_priv->card_type < NV_50) { | 320 | if (dev_priv->card_type < NV_50) { |
321 | dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); | 321 | dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); |
322 | dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; | 322 | dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; |
323 | } else { | 323 | } else |
324 | if (dev_priv->card_type < NV_C0) { | ||
324 | dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); | 325 | dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); |
325 | dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; | 326 | dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; |
326 | dev_priv->vram_size &= 0xffffffff00ll; | 327 | dev_priv->vram_size &= 0xffffffff00ll; |
@@ -328,6 +329,9 @@ nouveau_mem_detect(struct drm_device *dev) | |||
328 | dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10); | 329 | dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10); |
329 | dev_priv->vram_sys_base <<= 12; | 330 | dev_priv->vram_sys_base <<= 12; |
330 | } | 331 | } |
332 | } else { | ||
333 | dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20; | ||
334 | dev_priv->vram_size *= nv_rd32(dev, 0x121c74); | ||
331 | } | 335 | } |
332 | 336 | ||
333 | NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20)); | 337 | NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20)); |
@@ -351,7 +355,7 @@ nouveau_mem_reset_agp(struct drm_device *dev) | |||
351 | /* First of all, disable fast writes, otherwise if it's | 355 | /* First of all, disable fast writes, otherwise if it's |
352 | * already enabled in the AGP bridge and we disable the card's | 356 | * already enabled in the AGP bridge and we disable the card's |
353 | * AGP controller we might be locking ourselves out of it. */ | 357 | * AGP controller we might be locking ourselves out of it. */ |
354 | if (dev->agp->acquired) { | 358 | if (nv_rd32(dev, NV04_PBUS_PCI_NV_19) & PCI_AGP_COMMAND_FW) { |
355 | struct drm_agp_info info; | 359 | struct drm_agp_info info; |
356 | struct drm_agp_mode mode; | 360 | struct drm_agp_mode mode; |
357 | 361 | ||
@@ -359,7 +363,7 @@ nouveau_mem_reset_agp(struct drm_device *dev) | |||
359 | if (ret) | 363 | if (ret) |
360 | return ret; | 364 | return ret; |
361 | 365 | ||
362 | mode.mode = info.mode & ~0x10; | 366 | mode.mode = info.mode & ~PCI_AGP_COMMAND_FW; |
363 | ret = drm_agp_enable(dev, mode); | 367 | ret = drm_agp_enable(dev, mode); |
364 | if (ret) | 368 | if (ret) |
365 | return ret; | 369 | return ret; |
@@ -405,6 +409,8 @@ nouveau_mem_init_agp(struct drm_device *dev) | |||
405 | } | 409 | } |
406 | } | 410 | } |
407 | 411 | ||
412 | nouveau_mem_reset_agp(dev); | ||
413 | |||
408 | ret = drm_agp_info(dev, &info); | 414 | ret = drm_agp_info(dev, &info); |
409 | if (ret) { | 415 | if (ret) { |
410 | NV_ERROR(dev, "Unable to get AGP info: %d\n", ret); | 416 | NV_ERROR(dev, "Unable to get AGP info: %d\n", ret); |
@@ -459,8 +465,6 @@ nouveau_mem_init(struct drm_device *dev) | |||
459 | return ret; | 465 | return ret; |
460 | } | 466 | } |
461 | 467 | ||
462 | INIT_LIST_HEAD(&dev_priv->ttm.bo_list); | ||
463 | spin_lock_init(&dev_priv->ttm.bo_list_lock); | ||
464 | spin_lock_init(&dev_priv->tile.lock); | 468 | spin_lock_init(&dev_priv->tile.lock); |
465 | 469 | ||
466 | dev_priv->fb_available_size = dev_priv->vram_size; | 470 | dev_priv->fb_available_size = dev_priv->vram_size; |
@@ -494,7 +498,6 @@ nouveau_mem_init(struct drm_device *dev) | |||
494 | /* GART */ | 498 | /* GART */ |
495 | #if !defined(__powerpc__) && !defined(__ia64__) | 499 | #if !defined(__powerpc__) && !defined(__ia64__) |
496 | if (drm_device_is_agp(dev) && dev->agp && !nouveau_noagp) { | 500 | if (drm_device_is_agp(dev) && dev->agp && !nouveau_noagp) { |
497 | nouveau_mem_reset_agp(dev); | ||
498 | ret = nouveau_mem_init_agp(dev); | 501 | ret = nouveau_mem_init_agp(dev); |
499 | if (ret) | 502 | if (ret) |
500 | NV_ERROR(dev, "Error initialising AGP: %d\n", ret); | 503 | NV_ERROR(dev, "Error initialising AGP: %d\n", ret); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h index 9c1056cb8a90..21a6e453b975 100644 --- a/drivers/gpu/drm/nouveau/nouveau_reg.h +++ b/drivers/gpu/drm/nouveau/nouveau_reg.h | |||
@@ -220,28 +220,21 @@ | |||
220 | # define NV_PGRAPH_INTR_ERROR (1<<20) | 220 | # define NV_PGRAPH_INTR_ERROR (1<<20) |
221 | #define NV10_PGRAPH_CTX_CONTROL 0x00400144 | 221 | #define NV10_PGRAPH_CTX_CONTROL 0x00400144 |
222 | #define NV10_PGRAPH_CTX_USER 0x00400148 | 222 | #define NV10_PGRAPH_CTX_USER 0x00400148 |
223 | #define NV10_PGRAPH_CTX_SWITCH1 0x0040014C | 223 | #define NV10_PGRAPH_CTX_SWITCH(i) (0x0040014C + 0x4*(i)) |
224 | #define NV10_PGRAPH_CTX_SWITCH2 0x00400150 | ||
225 | #define NV10_PGRAPH_CTX_SWITCH3 0x00400154 | ||
226 | #define NV10_PGRAPH_CTX_SWITCH4 0x00400158 | ||
227 | #define NV10_PGRAPH_CTX_SWITCH5 0x0040015C | ||
228 | #define NV04_PGRAPH_CTX_SWITCH1 0x00400160 | 224 | #define NV04_PGRAPH_CTX_SWITCH1 0x00400160 |
229 | #define NV10_PGRAPH_CTX_CACHE1 0x00400160 | 225 | #define NV10_PGRAPH_CTX_CACHE(i, j) (0x00400160 \ |
226 | + 0x4*(i) + 0x20*(j)) | ||
230 | #define NV04_PGRAPH_CTX_SWITCH2 0x00400164 | 227 | #define NV04_PGRAPH_CTX_SWITCH2 0x00400164 |
231 | #define NV04_PGRAPH_CTX_SWITCH3 0x00400168 | 228 | #define NV04_PGRAPH_CTX_SWITCH3 0x00400168 |
232 | #define NV04_PGRAPH_CTX_SWITCH4 0x0040016C | 229 | #define NV04_PGRAPH_CTX_SWITCH4 0x0040016C |
233 | #define NV04_PGRAPH_CTX_CONTROL 0x00400170 | 230 | #define NV04_PGRAPH_CTX_CONTROL 0x00400170 |
234 | #define NV04_PGRAPH_CTX_USER 0x00400174 | 231 | #define NV04_PGRAPH_CTX_USER 0x00400174 |
235 | #define NV04_PGRAPH_CTX_CACHE1 0x00400180 | 232 | #define NV04_PGRAPH_CTX_CACHE1 0x00400180 |
236 | #define NV10_PGRAPH_CTX_CACHE2 0x00400180 | ||
237 | #define NV03_PGRAPH_CTX_CONTROL 0x00400190 | 233 | #define NV03_PGRAPH_CTX_CONTROL 0x00400190 |
238 | #define NV03_PGRAPH_CTX_USER 0x00400194 | 234 | #define NV03_PGRAPH_CTX_USER 0x00400194 |
239 | #define NV04_PGRAPH_CTX_CACHE2 0x004001A0 | 235 | #define NV04_PGRAPH_CTX_CACHE2 0x004001A0 |
240 | #define NV10_PGRAPH_CTX_CACHE3 0x004001A0 | ||
241 | #define NV04_PGRAPH_CTX_CACHE3 0x004001C0 | 236 | #define NV04_PGRAPH_CTX_CACHE3 0x004001C0 |
242 | #define NV10_PGRAPH_CTX_CACHE4 0x004001C0 | ||
243 | #define NV04_PGRAPH_CTX_CACHE4 0x004001E0 | 237 | #define NV04_PGRAPH_CTX_CACHE4 0x004001E0 |
244 | #define NV10_PGRAPH_CTX_CACHE5 0x004001E0 | ||
245 | #define NV40_PGRAPH_CTXCTL_0304 0x00400304 | 238 | #define NV40_PGRAPH_CTXCTL_0304 0x00400304 |
246 | #define NV40_PGRAPH_CTXCTL_0304_XFER_CTX 0x00000001 | 239 | #define NV40_PGRAPH_CTXCTL_0304_XFER_CTX 0x00000001 |
247 | #define NV40_PGRAPH_CTXCTL_UCODE_STAT 0x00400308 | 240 | #define NV40_PGRAPH_CTXCTL_UCODE_STAT 0x00400308 |
@@ -356,9 +349,12 @@ | |||
356 | #define NV04_PGRAPH_FFINTFC_ST2 0x00400754 | 349 | #define NV04_PGRAPH_FFINTFC_ST2 0x00400754 |
357 | #define NV10_PGRAPH_RDI_DATA 0x00400754 | 350 | #define NV10_PGRAPH_RDI_DATA 0x00400754 |
358 | #define NV04_PGRAPH_DMA_PITCH 0x00400760 | 351 | #define NV04_PGRAPH_DMA_PITCH 0x00400760 |
359 | #define NV10_PGRAPH_FFINTFC_ST2 0x00400764 | 352 | #define NV10_PGRAPH_FFINTFC_FIFO_PTR 0x00400760 |
360 | #define NV04_PGRAPH_DVD_COLORFMT 0x00400764 | 353 | #define NV04_PGRAPH_DVD_COLORFMT 0x00400764 |
354 | #define NV10_PGRAPH_FFINTFC_ST2 0x00400764 | ||
361 | #define NV04_PGRAPH_SCALED_FORMAT 0x00400768 | 355 | #define NV04_PGRAPH_SCALED_FORMAT 0x00400768 |
356 | #define NV10_PGRAPH_FFINTFC_ST2_DL 0x00400768 | ||
357 | #define NV10_PGRAPH_FFINTFC_ST2_DH 0x0040076c | ||
362 | #define NV10_PGRAPH_DMA_PITCH 0x00400770 | 358 | #define NV10_PGRAPH_DMA_PITCH 0x00400770 |
363 | #define NV10_PGRAPH_DVD_COLORFMT 0x00400774 | 359 | #define NV10_PGRAPH_DVD_COLORFMT 0x00400774 |
364 | #define NV10_PGRAPH_SCALED_FORMAT 0x00400778 | 360 | #define NV10_PGRAPH_SCALED_FORMAT 0x00400778 |
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index ee3729e7823b..989322be3728 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c | |||
@@ -359,6 +359,54 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
359 | engine->gpio.set = nv50_gpio_set; | 359 | engine->gpio.set = nv50_gpio_set; |
360 | engine->gpio.irq_enable = nv50_gpio_irq_enable; | 360 | engine->gpio.irq_enable = nv50_gpio_irq_enable; |
361 | break; | 361 | break; |
362 | case 0xC0: | ||
363 | engine->instmem.init = nvc0_instmem_init; | ||
364 | engine->instmem.takedown = nvc0_instmem_takedown; | ||
365 | engine->instmem.suspend = nvc0_instmem_suspend; | ||
366 | engine->instmem.resume = nvc0_instmem_resume; | ||
367 | engine->instmem.populate = nvc0_instmem_populate; | ||
368 | engine->instmem.clear = nvc0_instmem_clear; | ||
369 | engine->instmem.bind = nvc0_instmem_bind; | ||
370 | engine->instmem.unbind = nvc0_instmem_unbind; | ||
371 | engine->instmem.flush = nvc0_instmem_flush; | ||
372 | engine->mc.init = nv50_mc_init; | ||
373 | engine->mc.takedown = nv50_mc_takedown; | ||
374 | engine->timer.init = nv04_timer_init; | ||
375 | engine->timer.read = nv04_timer_read; | ||
376 | engine->timer.takedown = nv04_timer_takedown; | ||
377 | engine->fb.init = nvc0_fb_init; | ||
378 | engine->fb.takedown = nvc0_fb_takedown; | ||
379 | engine->graph.grclass = NULL; //nvc0_graph_grclass; | ||
380 | engine->graph.init = nvc0_graph_init; | ||
381 | engine->graph.takedown = nvc0_graph_takedown; | ||
382 | engine->graph.fifo_access = nvc0_graph_fifo_access; | ||
383 | engine->graph.channel = nvc0_graph_channel; | ||
384 | engine->graph.create_context = nvc0_graph_create_context; | ||
385 | engine->graph.destroy_context = nvc0_graph_destroy_context; | ||
386 | engine->graph.load_context = nvc0_graph_load_context; | ||
387 | engine->graph.unload_context = nvc0_graph_unload_context; | ||
388 | engine->fifo.channels = 128; | ||
389 | engine->fifo.init = nvc0_fifo_init; | ||
390 | engine->fifo.takedown = nvc0_fifo_takedown; | ||
391 | engine->fifo.disable = nvc0_fifo_disable; | ||
392 | engine->fifo.enable = nvc0_fifo_enable; | ||
393 | engine->fifo.reassign = nvc0_fifo_reassign; | ||
394 | engine->fifo.channel_id = nvc0_fifo_channel_id; | ||
395 | engine->fifo.create_context = nvc0_fifo_create_context; | ||
396 | engine->fifo.destroy_context = nvc0_fifo_destroy_context; | ||
397 | engine->fifo.load_context = nvc0_fifo_load_context; | ||
398 | engine->fifo.unload_context = nvc0_fifo_unload_context; | ||
399 | engine->display.early_init = nv50_display_early_init; | ||
400 | engine->display.late_takedown = nv50_display_late_takedown; | ||
401 | engine->display.create = nv50_display_create; | ||
402 | engine->display.init = nv50_display_init; | ||
403 | engine->display.destroy = nv50_display_destroy; | ||
404 | engine->gpio.init = nv50_gpio_init; | ||
405 | engine->gpio.takedown = nouveau_stub_takedown; | ||
406 | engine->gpio.get = nv50_gpio_get; | ||
407 | engine->gpio.set = nv50_gpio_set; | ||
408 | engine->gpio.irq_enable = nv50_gpio_irq_enable; | ||
409 | break; | ||
362 | default: | 410 | default: |
363 | NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); | 411 | NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); |
364 | return 1; | 412 | return 1; |
@@ -739,8 +787,10 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
739 | int ret; | 787 | int ret; |
740 | 788 | ||
741 | dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); | 789 | dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); |
742 | if (!dev_priv) | 790 | if (!dev_priv) { |
743 | return -ENOMEM; | 791 | ret = -ENOMEM; |
792 | goto err_out; | ||
793 | } | ||
744 | dev->dev_private = dev_priv; | 794 | dev->dev_private = dev_priv; |
745 | dev_priv->dev = dev; | 795 | dev_priv->dev = dev; |
746 | 796 | ||
@@ -750,8 +800,10 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
750 | dev->pci_vendor, dev->pci_device, dev->pdev->class); | 800 | dev->pci_vendor, dev->pci_device, dev->pdev->class); |
751 | 801 | ||
752 | dev_priv->wq = create_workqueue("nouveau"); | 802 | dev_priv->wq = create_workqueue("nouveau"); |
753 | if (!dev_priv->wq) | 803 | if (!dev_priv->wq) { |
754 | return -EINVAL; | 804 | ret = -EINVAL; |
805 | goto err_priv; | ||
806 | } | ||
755 | 807 | ||
756 | /* resource 0 is mmio regs */ | 808 | /* resource 0 is mmio regs */ |
757 | /* resource 1 is linear FB */ | 809 | /* resource 1 is linear FB */ |
@@ -764,7 +816,8 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
764 | if (!dev_priv->mmio) { | 816 | if (!dev_priv->mmio) { |
765 | NV_ERROR(dev, "Unable to initialize the mmio mapping. " | 817 | NV_ERROR(dev, "Unable to initialize the mmio mapping. " |
766 | "Please report your setup to " DRIVER_EMAIL "\n"); | 818 | "Please report your setup to " DRIVER_EMAIL "\n"); |
767 | return -EINVAL; | 819 | ret = -EINVAL; |
820 | goto err_wq; | ||
768 | } | 821 | } |
769 | NV_DEBUG(dev, "regs mapped ok at 0x%llx\n", | 822 | NV_DEBUG(dev, "regs mapped ok at 0x%llx\n", |
770 | (unsigned long long)mmio_start_offs); | 823 | (unsigned long long)mmio_start_offs); |
@@ -810,9 +863,13 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
810 | case 0xa0: | 863 | case 0xa0: |
811 | dev_priv->card_type = NV_50; | 864 | dev_priv->card_type = NV_50; |
812 | break; | 865 | break; |
866 | case 0xc0: | ||
867 | dev_priv->card_type = NV_C0; | ||
868 | break; | ||
813 | default: | 869 | default: |
814 | NV_INFO(dev, "Unsupported chipset 0x%08x\n", reg0); | 870 | NV_INFO(dev, "Unsupported chipset 0x%08x\n", reg0); |
815 | return -EINVAL; | 871 | ret = -EINVAL; |
872 | goto err_mmio; | ||
816 | } | 873 | } |
817 | 874 | ||
818 | NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n", | 875 | NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n", |
@@ -820,7 +877,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
820 | 877 | ||
821 | ret = nouveau_remove_conflicting_drivers(dev); | 878 | ret = nouveau_remove_conflicting_drivers(dev); |
822 | if (ret) | 879 | if (ret) |
823 | return ret; | 880 | goto err_mmio; |
824 | 881 | ||
825 | /* Map PRAMIN BAR, or on older cards, the aperture withing BAR0 */ | 882 | /* Map PRAMIN BAR, or on older cards, the aperture withing BAR0 */ |
826 | if (dev_priv->card_type >= NV_40) { | 883 | if (dev_priv->card_type >= NV_40) { |
@@ -834,7 +891,8 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
834 | dev_priv->ramin_size); | 891 | dev_priv->ramin_size); |
835 | if (!dev_priv->ramin) { | 892 | if (!dev_priv->ramin) { |
836 | NV_ERROR(dev, "Failed to PRAMIN BAR"); | 893 | NV_ERROR(dev, "Failed to PRAMIN BAR"); |
837 | return -ENOMEM; | 894 | ret = -ENOMEM; |
895 | goto err_mmio; | ||
838 | } | 896 | } |
839 | } else { | 897 | } else { |
840 | dev_priv->ramin_size = 1 * 1024 * 1024; | 898 | dev_priv->ramin_size = 1 * 1024 * 1024; |
@@ -842,7 +900,8 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
842 | dev_priv->ramin_size); | 900 | dev_priv->ramin_size); |
843 | if (!dev_priv->ramin) { | 901 | if (!dev_priv->ramin) { |
844 | NV_ERROR(dev, "Failed to map BAR0 PRAMIN.\n"); | 902 | NV_ERROR(dev, "Failed to map BAR0 PRAMIN.\n"); |
845 | return -ENOMEM; | 903 | ret = -ENOMEM; |
904 | goto err_mmio; | ||
846 | } | 905 | } |
847 | } | 906 | } |
848 | 907 | ||
@@ -857,9 +916,21 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
857 | /* For kernel modesetting, init card now and bring up fbcon */ | 916 | /* For kernel modesetting, init card now and bring up fbcon */ |
858 | ret = nouveau_card_init(dev); | 917 | ret = nouveau_card_init(dev); |
859 | if (ret) | 918 | if (ret) |
860 | return ret; | 919 | goto err_ramin; |
861 | 920 | ||
862 | return 0; | 921 | return 0; |
922 | |||
923 | err_ramin: | ||
924 | iounmap(dev_priv->ramin); | ||
925 | err_mmio: | ||
926 | iounmap(dev_priv->mmio); | ||
927 | err_wq: | ||
928 | destroy_workqueue(dev_priv->wq); | ||
929 | err_priv: | ||
930 | kfree(dev_priv); | ||
931 | dev->dev_private = NULL; | ||
932 | err_out: | ||
933 | return ret; | ||
863 | } | 934 | } |
864 | 935 | ||
865 | void nouveau_lastclose(struct drm_device *dev) | 936 | void nouveau_lastclose(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c index 1c20c08ce67c..497df8765f28 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c | |||
@@ -542,6 +542,9 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) | |||
542 | * 1 << 30 on 0x60.830), for no apparent reason */ | 542 | * 1 << 30 on 0x60.830), for no apparent reason */ |
543 | regp->CRTC[NV_CIO_CRE_59] = off_chip_digital; | 543 | regp->CRTC[NV_CIO_CRE_59] = off_chip_digital; |
544 | 544 | ||
545 | if (dev_priv->card_type >= NV_30) | ||
546 | regp->CRTC[0x9f] = off_chip_digital ? 0x11 : 0x1; | ||
547 | |||
545 | regp->crtc_830 = mode->crtc_vdisplay - 3; | 548 | regp->crtc_830 = mode->crtc_vdisplay - 3; |
546 | regp->crtc_834 = mode->crtc_vdisplay - 1; | 549 | regp->crtc_834 = mode->crtc_vdisplay - 1; |
547 | 550 | ||
@@ -739,15 +742,13 @@ nv_crtc_gamma_load(struct drm_crtc *crtc) | |||
739 | } | 742 | } |
740 | 743 | ||
741 | static void | 744 | static void |
742 | nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t size) | 745 | nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start, |
746 | uint32_t size) | ||
743 | { | 747 | { |
748 | int end = (start + size > 256) ? 256 : start + size, i; | ||
744 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 749 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
745 | int i; | ||
746 | 750 | ||
747 | if (size != 256) | 751 | for (i = start; i < end; i++) { |
748 | return; | ||
749 | |||
750 | for (i = 0; i < 256; i++) { | ||
751 | nv_crtc->lut.r[i] = r[i]; | 752 | nv_crtc->lut.r[i] = r[i]; |
752 | nv_crtc->lut.g[i] = g[i]; | 753 | nv_crtc->lut.g[i] = g[i]; |
753 | nv_crtc->lut.b[i] = b[i]; | 754 | nv_crtc->lut.b[i] = b[i]; |
@@ -914,7 +915,7 @@ nv04_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, | |||
914 | 915 | ||
915 | gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); | 916 | gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); |
916 | if (!gem) | 917 | if (!gem) |
917 | return -EINVAL; | 918 | return -ENOENT; |
918 | cursor = nouveau_gem_object(gem); | 919 | cursor = nouveau_gem_object(gem); |
919 | 920 | ||
920 | ret = nouveau_bo_map(cursor); | 921 | ret = nouveau_bo_map(cursor); |
diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index 3311f3a8c818..a5dcf7685800 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include "nouveau_hw.h" | 34 | #include "nouveau_hw.h" |
35 | #include "nvreg.h" | 35 | #include "nvreg.h" |
36 | 36 | ||
37 | #include "i2c/sil164.h" | ||
38 | |||
37 | #define FP_TG_CONTROL_ON (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS | \ | 39 | #define FP_TG_CONTROL_ON (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS | \ |
38 | NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS | \ | 40 | NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS | \ |
39 | NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS) | 41 | NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS) |
@@ -144,6 +146,36 @@ void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode) | |||
144 | } | 146 | } |
145 | } | 147 | } |
146 | 148 | ||
149 | static struct drm_encoder *get_tmds_slave(struct drm_encoder *encoder) | ||
150 | { | ||
151 | struct drm_device *dev = encoder->dev; | ||
152 | struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; | ||
153 | struct drm_encoder *slave; | ||
154 | |||
155 | if (dcb->type != OUTPUT_TMDS || dcb->location == DCB_LOC_ON_CHIP) | ||
156 | return NULL; | ||
157 | |||
158 | /* Some BIOSes (e.g. the one in a Quadro FX1000) report several | ||
159 | * TMDS transmitters at the same I2C address, in the same I2C | ||
160 | * bus. This can still work because in that case one of them is | ||
161 | * always hard-wired to a reasonable configuration using straps, | ||
162 | * and the other one needs to be programmed. | ||
163 | * | ||
164 | * I don't think there's a way to know which is which, even the | ||
165 | * blob programs the one exposed via I2C for *both* heads, so | ||
166 | * let's do the same. | ||
167 | */ | ||
168 | list_for_each_entry(slave, &dev->mode_config.encoder_list, head) { | ||
169 | struct dcb_entry *slave_dcb = nouveau_encoder(slave)->dcb; | ||
170 | |||
171 | if (slave_dcb->type == OUTPUT_TMDS && get_slave_funcs(slave) && | ||
172 | slave_dcb->tmdsconf.slave_addr == dcb->tmdsconf.slave_addr) | ||
173 | return slave; | ||
174 | } | ||
175 | |||
176 | return NULL; | ||
177 | } | ||
178 | |||
147 | static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder, | 179 | static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder, |
148 | struct drm_display_mode *mode, | 180 | struct drm_display_mode *mode, |
149 | struct drm_display_mode *adjusted_mode) | 181 | struct drm_display_mode *adjusted_mode) |
@@ -429,6 +461,11 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) | |||
429 | else | 461 | else |
430 | NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000); | 462 | NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000); |
431 | 463 | ||
464 | /* Init external transmitters */ | ||
465 | if (get_tmds_slave(encoder)) | ||
466 | get_slave_funcs(get_tmds_slave(encoder))->mode_set( | ||
467 | encoder, &nv_encoder->mode, &nv_encoder->mode); | ||
468 | |||
432 | helper->dpms(encoder, DRM_MODE_DPMS_ON); | 469 | helper->dpms(encoder, DRM_MODE_DPMS_ON); |
433 | 470 | ||
434 | NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", | 471 | NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", |
@@ -550,10 +587,42 @@ static void nv04_dfp_destroy(struct drm_encoder *encoder) | |||
550 | 587 | ||
551 | NV_DEBUG_KMS(encoder->dev, "\n"); | 588 | NV_DEBUG_KMS(encoder->dev, "\n"); |
552 | 589 | ||
590 | if (get_slave_funcs(encoder)) | ||
591 | get_slave_funcs(encoder)->destroy(encoder); | ||
592 | |||
553 | drm_encoder_cleanup(encoder); | 593 | drm_encoder_cleanup(encoder); |
554 | kfree(nv_encoder); | 594 | kfree(nv_encoder); |
555 | } | 595 | } |
556 | 596 | ||
597 | static void nv04_tmds_slave_init(struct drm_encoder *encoder) | ||
598 | { | ||
599 | struct drm_device *dev = encoder->dev; | ||
600 | struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; | ||
601 | struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, 2); | ||
602 | struct i2c_board_info info[] = { | ||
603 | { | ||
604 | .type = "sil164", | ||
605 | .addr = (dcb->tmdsconf.slave_addr == 0x7 ? 0x3a : 0x38), | ||
606 | .platform_data = &(struct sil164_encoder_params) { | ||
607 | SIL164_INPUT_EDGE_RISING | ||
608 | } | ||
609 | }, | ||
610 | { } | ||
611 | }; | ||
612 | int type; | ||
613 | |||
614 | if (!nv_gf4_disp_arch(dev) || !i2c || | ||
615 | get_tmds_slave(encoder)) | ||
616 | return; | ||
617 | |||
618 | type = nouveau_i2c_identify(dev, "TMDS transmitter", info, 2); | ||
619 | if (type < 0) | ||
620 | return; | ||
621 | |||
622 | drm_i2c_encoder_init(dev, to_encoder_slave(encoder), | ||
623 | &i2c->adapter, &info[type]); | ||
624 | } | ||
625 | |||
557 | static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = { | 626 | static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = { |
558 | .dpms = nv04_lvds_dpms, | 627 | .dpms = nv04_lvds_dpms, |
559 | .save = nv04_dfp_save, | 628 | .save = nv04_dfp_save, |
@@ -616,6 +685,10 @@ nv04_dfp_create(struct drm_connector *connector, struct dcb_entry *entry) | |||
616 | encoder->possible_crtcs = entry->heads; | 685 | encoder->possible_crtcs = entry->heads; |
617 | encoder->possible_clones = 0; | 686 | encoder->possible_clones = 0; |
618 | 687 | ||
688 | if (entry->type == OUTPUT_TMDS && | ||
689 | entry->location != DCB_LOC_ON_CHIP) | ||
690 | nv04_tmds_slave_init(encoder); | ||
691 | |||
619 | drm_mode_connector_attach_encoder(connector, encoder); | 692 | drm_mode_connector_attach_encoder(connector, encoder); |
620 | return 0; | 693 | return 0; |
621 | } | 694 | } |
diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c index 94e299cef0b2..0b5d012d7c28 100644 --- a/drivers/gpu/drm/nouveau/nv04_tv.c +++ b/drivers/gpu/drm/nouveau/nv04_tv.c | |||
@@ -89,7 +89,7 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode) | |||
89 | 89 | ||
90 | NVWriteRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel); | 90 | NVWriteRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel); |
91 | 91 | ||
92 | to_encoder_slave(encoder)->slave_funcs->dpms(encoder, mode); | 92 | get_slave_funcs(encoder)->dpms(encoder, mode); |
93 | } | 93 | } |
94 | 94 | ||
95 | static void nv04_tv_bind(struct drm_device *dev, int head, bool bind) | 95 | static void nv04_tv_bind(struct drm_device *dev, int head, bool bind) |
@@ -152,7 +152,7 @@ static void nv04_tv_mode_set(struct drm_encoder *encoder, | |||
152 | regp->tv_vskew = 1; | 152 | regp->tv_vskew = 1; |
153 | regp->tv_vsync_delay = 1; | 153 | regp->tv_vsync_delay = 1; |
154 | 154 | ||
155 | to_encoder_slave(encoder)->slave_funcs->mode_set(encoder, mode, adjusted_mode); | 155 | get_slave_funcs(encoder)->mode_set(encoder, mode, adjusted_mode); |
156 | } | 156 | } |
157 | 157 | ||
158 | static void nv04_tv_commit(struct drm_encoder *encoder) | 158 | static void nv04_tv_commit(struct drm_encoder *encoder) |
@@ -171,8 +171,7 @@ static void nv04_tv_commit(struct drm_encoder *encoder) | |||
171 | 171 | ||
172 | static void nv04_tv_destroy(struct drm_encoder *encoder) | 172 | static void nv04_tv_destroy(struct drm_encoder *encoder) |
173 | { | 173 | { |
174 | to_encoder_slave(encoder)->slave_funcs->destroy(encoder); | 174 | get_slave_funcs(encoder)->destroy(encoder); |
175 | |||
176 | drm_encoder_cleanup(encoder); | 175 | drm_encoder_cleanup(encoder); |
177 | 176 | ||
178 | kfree(encoder->helper_private); | 177 | kfree(encoder->helper_private); |
@@ -229,7 +228,7 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_entry *entry) | |||
229 | goto fail_cleanup; | 228 | goto fail_cleanup; |
230 | 229 | ||
231 | /* Fill the function pointers */ | 230 | /* Fill the function pointers */ |
232 | sfuncs = to_encoder_slave(encoder)->slave_funcs; | 231 | sfuncs = get_slave_funcs(encoder); |
233 | 232 | ||
234 | *hfuncs = (struct drm_encoder_helper_funcs) { | 233 | *hfuncs = (struct drm_encoder_helper_funcs) { |
235 | .dpms = nv04_tv_dpms, | 234 | .dpms = nv04_tv_dpms, |
@@ -243,7 +242,6 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_entry *entry) | |||
243 | }; | 242 | }; |
244 | 243 | ||
245 | /* Attach it to the specified connector. */ | 244 | /* Attach it to the specified connector. */ |
246 | sfuncs->set_config(encoder, nv04_tv_encoder_info[type].platform_data); | ||
247 | sfuncs->create_resources(encoder, connector); | 245 | sfuncs->create_resources(encoder, connector); |
248 | drm_mode_connector_attach_encoder(connector, encoder); | 246 | drm_mode_connector_attach_encoder(connector, encoder); |
249 | 247 | ||
diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c index fcf2cdd19493..b2f6a57c0cc5 100644 --- a/drivers/gpu/drm/nouveau/nv10_graph.c +++ b/drivers/gpu/drm/nouveau/nv10_graph.c | |||
@@ -43,51 +43,51 @@ struct pipe_state { | |||
43 | }; | 43 | }; |
44 | 44 | ||
45 | static int nv10_graph_ctx_regs[] = { | 45 | static int nv10_graph_ctx_regs[] = { |
46 | NV10_PGRAPH_CTX_SWITCH1, | 46 | NV10_PGRAPH_CTX_SWITCH(0), |
47 | NV10_PGRAPH_CTX_SWITCH2, | 47 | NV10_PGRAPH_CTX_SWITCH(1), |
48 | NV10_PGRAPH_CTX_SWITCH3, | 48 | NV10_PGRAPH_CTX_SWITCH(2), |
49 | NV10_PGRAPH_CTX_SWITCH4, | 49 | NV10_PGRAPH_CTX_SWITCH(3), |
50 | NV10_PGRAPH_CTX_SWITCH5, | 50 | NV10_PGRAPH_CTX_SWITCH(4), |
51 | NV10_PGRAPH_CTX_CACHE1, /* 8 values from 0x400160 to 0x40017c */ | 51 | NV10_PGRAPH_CTX_CACHE(0, 0), |
52 | NV10_PGRAPH_CTX_CACHE2, /* 8 values from 0x400180 to 0x40019c */ | 52 | NV10_PGRAPH_CTX_CACHE(0, 1), |
53 | NV10_PGRAPH_CTX_CACHE3, /* 8 values from 0x4001a0 to 0x4001bc */ | 53 | NV10_PGRAPH_CTX_CACHE(0, 2), |
54 | NV10_PGRAPH_CTX_CACHE4, /* 8 values from 0x4001c0 to 0x4001dc */ | 54 | NV10_PGRAPH_CTX_CACHE(0, 3), |
55 | NV10_PGRAPH_CTX_CACHE5, /* 8 values from 0x4001e0 to 0x4001fc */ | 55 | NV10_PGRAPH_CTX_CACHE(0, 4), |
56 | 0x00400164, | 56 | NV10_PGRAPH_CTX_CACHE(1, 0), |
57 | 0x00400184, | 57 | NV10_PGRAPH_CTX_CACHE(1, 1), |
58 | 0x004001a4, | 58 | NV10_PGRAPH_CTX_CACHE(1, 2), |
59 | 0x004001c4, | 59 | NV10_PGRAPH_CTX_CACHE(1, 3), |
60 | 0x004001e4, | 60 | NV10_PGRAPH_CTX_CACHE(1, 4), |
61 | 0x00400168, | 61 | NV10_PGRAPH_CTX_CACHE(2, 0), |
62 | 0x00400188, | 62 | NV10_PGRAPH_CTX_CACHE(2, 1), |
63 | 0x004001a8, | 63 | NV10_PGRAPH_CTX_CACHE(2, 2), |
64 | 0x004001c8, | 64 | NV10_PGRAPH_CTX_CACHE(2, 3), |
65 | 0x004001e8, | 65 | NV10_PGRAPH_CTX_CACHE(2, 4), |
66 | 0x0040016c, | 66 | NV10_PGRAPH_CTX_CACHE(3, 0), |
67 | 0x0040018c, | 67 | NV10_PGRAPH_CTX_CACHE(3, 1), |
68 | 0x004001ac, | 68 | NV10_PGRAPH_CTX_CACHE(3, 2), |
69 | 0x004001cc, | 69 | NV10_PGRAPH_CTX_CACHE(3, 3), |
70 | 0x004001ec, | 70 | NV10_PGRAPH_CTX_CACHE(3, 4), |
71 | 0x00400170, | 71 | NV10_PGRAPH_CTX_CACHE(4, 0), |
72 | 0x00400190, | 72 | NV10_PGRAPH_CTX_CACHE(4, 1), |
73 | 0x004001b0, | 73 | NV10_PGRAPH_CTX_CACHE(4, 2), |
74 | 0x004001d0, | 74 | NV10_PGRAPH_CTX_CACHE(4, 3), |
75 | 0x004001f0, | 75 | NV10_PGRAPH_CTX_CACHE(4, 4), |
76 | 0x00400174, | 76 | NV10_PGRAPH_CTX_CACHE(5, 0), |
77 | 0x00400194, | 77 | NV10_PGRAPH_CTX_CACHE(5, 1), |
78 | 0x004001b4, | 78 | NV10_PGRAPH_CTX_CACHE(5, 2), |
79 | 0x004001d4, | 79 | NV10_PGRAPH_CTX_CACHE(5, 3), |
80 | 0x004001f4, | 80 | NV10_PGRAPH_CTX_CACHE(5, 4), |
81 | 0x00400178, | 81 | NV10_PGRAPH_CTX_CACHE(6, 0), |
82 | 0x00400198, | 82 | NV10_PGRAPH_CTX_CACHE(6, 1), |
83 | 0x004001b8, | 83 | NV10_PGRAPH_CTX_CACHE(6, 2), |
84 | 0x004001d8, | 84 | NV10_PGRAPH_CTX_CACHE(6, 3), |
85 | 0x004001f8, | 85 | NV10_PGRAPH_CTX_CACHE(6, 4), |
86 | 0x0040017c, | 86 | NV10_PGRAPH_CTX_CACHE(7, 0), |
87 | 0x0040019c, | 87 | NV10_PGRAPH_CTX_CACHE(7, 1), |
88 | 0x004001bc, | 88 | NV10_PGRAPH_CTX_CACHE(7, 2), |
89 | 0x004001dc, | 89 | NV10_PGRAPH_CTX_CACHE(7, 3), |
90 | 0x004001fc, | 90 | NV10_PGRAPH_CTX_CACHE(7, 4), |
91 | NV10_PGRAPH_CTX_USER, | 91 | NV10_PGRAPH_CTX_USER, |
92 | NV04_PGRAPH_DMA_START_0, | 92 | NV04_PGRAPH_DMA_START_0, |
93 | NV04_PGRAPH_DMA_START_1, | 93 | NV04_PGRAPH_DMA_START_1, |
@@ -653,6 +653,78 @@ static int nv17_graph_ctx_regs_find_offset(struct drm_device *dev, int reg) | |||
653 | return -1; | 653 | return -1; |
654 | } | 654 | } |
655 | 655 | ||
656 | static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan, | ||
657 | uint32_t inst) | ||
658 | { | ||
659 | struct drm_device *dev = chan->dev; | ||
660 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
661 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | ||
662 | uint32_t st2, st2_dl, st2_dh, fifo_ptr, fifo[0x60/4]; | ||
663 | uint32_t ctx_user, ctx_switch[5]; | ||
664 | int i, subchan = -1; | ||
665 | |||
666 | /* NV10TCL_DMA_VTXBUF (method 0x18c) modifies hidden state | ||
667 | * that cannot be restored via MMIO. Do it through the FIFO | ||
668 | * instead. | ||
669 | */ | ||
670 | |||
671 | /* Look for a celsius object */ | ||
672 | for (i = 0; i < 8; i++) { | ||
673 | int class = nv_rd32(dev, NV10_PGRAPH_CTX_CACHE(i, 0)) & 0xfff; | ||
674 | |||
675 | if (class == 0x56 || class == 0x96 || class == 0x99) { | ||
676 | subchan = i; | ||
677 | break; | ||
678 | } | ||
679 | } | ||
680 | |||
681 | if (subchan < 0 || !inst) | ||
682 | return; | ||
683 | |||
684 | /* Save the current ctx object */ | ||
685 | ctx_user = nv_rd32(dev, NV10_PGRAPH_CTX_USER); | ||
686 | for (i = 0; i < 5; i++) | ||
687 | ctx_switch[i] = nv_rd32(dev, NV10_PGRAPH_CTX_SWITCH(i)); | ||
688 | |||
689 | /* Save the FIFO state */ | ||
690 | st2 = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2); | ||
691 | st2_dl = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2_DL); | ||
692 | st2_dh = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2_DH); | ||
693 | fifo_ptr = nv_rd32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR); | ||
694 | |||
695 | for (i = 0; i < ARRAY_SIZE(fifo); i++) | ||
696 | fifo[i] = nv_rd32(dev, 0x4007a0 + 4 * i); | ||
697 | |||
698 | /* Switch to the celsius subchannel */ | ||
699 | for (i = 0; i < 5; i++) | ||
700 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(i), | ||
701 | nv_rd32(dev, NV10_PGRAPH_CTX_CACHE(subchan, i))); | ||
702 | nv_mask(dev, NV10_PGRAPH_CTX_USER, 0xe000, subchan << 13); | ||
703 | |||
704 | /* Inject NV10TCL_DMA_VTXBUF */ | ||
705 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR, 0); | ||
706 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, | ||
707 | 0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c); | ||
708 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst); | ||
709 | nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000); | ||
710 | pgraph->fifo_access(dev, true); | ||
711 | pgraph->fifo_access(dev, false); | ||
712 | |||
713 | /* Restore the FIFO state */ | ||
714 | for (i = 0; i < ARRAY_SIZE(fifo); i++) | ||
715 | nv_wr32(dev, 0x4007a0 + 4 * i, fifo[i]); | ||
716 | |||
717 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR, fifo_ptr); | ||
718 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, st2); | ||
719 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, st2_dl); | ||
720 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DH, st2_dh); | ||
721 | |||
722 | /* Restore the current ctx object */ | ||
723 | for (i = 0; i < 5; i++) | ||
724 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(i), ctx_switch[i]); | ||
725 | nv_wr32(dev, NV10_PGRAPH_CTX_USER, ctx_user); | ||
726 | } | ||
727 | |||
656 | int nv10_graph_load_context(struct nouveau_channel *chan) | 728 | int nv10_graph_load_context(struct nouveau_channel *chan) |
657 | { | 729 | { |
658 | struct drm_device *dev = chan->dev; | 730 | struct drm_device *dev = chan->dev; |
@@ -670,6 +742,8 @@ int nv10_graph_load_context(struct nouveau_channel *chan) | |||
670 | } | 742 | } |
671 | 743 | ||
672 | nv10_graph_load_pipe(chan); | 744 | nv10_graph_load_pipe(chan); |
745 | nv10_graph_load_dma_vtxbuf(chan, (nv_rd32(dev, NV10_PGRAPH_GLOBALSTATE1) | ||
746 | & 0xffff)); | ||
673 | 747 | ||
674 | nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100); | 748 | nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100); |
675 | tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER); | 749 | tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER); |
@@ -856,11 +930,12 @@ int nv10_graph_init(struct drm_device *dev) | |||
856 | for (i = 0; i < NV10_PFB_TILE__SIZE; i++) | 930 | for (i = 0; i < NV10_PFB_TILE__SIZE; i++) |
857 | nv10_graph_set_region_tiling(dev, i, 0, 0, 0); | 931 | nv10_graph_set_region_tiling(dev, i, 0, 0, 0); |
858 | 932 | ||
859 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH1, 0x00000000); | 933 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(0), 0x00000000); |
860 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH2, 0x00000000); | 934 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(1), 0x00000000); |
861 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH3, 0x00000000); | 935 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(2), 0x00000000); |
862 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH4, 0x00000000); | 936 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(3), 0x00000000); |
863 | nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); | 937 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(4), 0x00000000); |
938 | nv_wr32(dev, NV10_PGRAPH_STATE, 0xFFFFFFFF); | ||
864 | 939 | ||
865 | tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff; | 940 | tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff; |
866 | tmp |= (dev_priv->engine.fifo.channels - 1) << 24; | 941 | tmp |= (dev_priv->engine.fifo.channels - 1) << 24; |
diff --git a/drivers/gpu/drm/nouveau/nv30_fb.c b/drivers/gpu/drm/nouveau/nv30_fb.c index 9d35c8b3b839..4a3f2f095128 100644 --- a/drivers/gpu/drm/nouveau/nv30_fb.c +++ b/drivers/gpu/drm/nouveau/nv30_fb.c | |||
@@ -30,15 +30,25 @@ | |||
30 | #include "nouveau_drm.h" | 30 | #include "nouveau_drm.h" |
31 | 31 | ||
32 | static int | 32 | static int |
33 | calc_ref(int b, int l, int i) | 33 | calc_bias(struct drm_device *dev, int k, int i, int j) |
34 | { | ||
35 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
36 | int b = (dev_priv->chipset > 0x30 ? | ||
37 | nv_rd32(dev, 0x122c + 0x10 * k + 0x4 * j) >> (4 * (i ^ 1)) : | ||
38 | 0) & 0xf; | ||
39 | |||
40 | return 2 * (b & 0x8 ? b - 0x10 : b); | ||
41 | } | ||
42 | |||
43 | static int | ||
44 | calc_ref(struct drm_device *dev, int l, int k, int i) | ||
34 | { | 45 | { |
35 | int j, x = 0; | 46 | int j, x = 0; |
36 | 47 | ||
37 | for (j = 0; j < 4; j++) { | 48 | for (j = 0; j < 4; j++) { |
38 | int n = (b >> (8 * j) & 0xf); | 49 | int m = (l >> (8 * i) & 0xff) + calc_bias(dev, k, i, j); |
39 | int m = (l >> (8 * i) & 0xff) + 2 * (n & 0x8 ? n - 0x10 : n); | ||
40 | 50 | ||
41 | x |= (0x80 | (m & 0x1f)) << (8 * j); | 51 | x |= (0x80 | clamp(m, 0, 0x1f)) << (8 * j); |
42 | } | 52 | } |
43 | 53 | ||
44 | return x; | 54 | return x; |
@@ -63,18 +73,16 @@ nv30_fb_init(struct drm_device *dev) | |||
63 | dev_priv->chipset == 0x35) { | 73 | dev_priv->chipset == 0x35) { |
64 | /* Related to ROP count */ | 74 | /* Related to ROP count */ |
65 | int n = (dev_priv->chipset == 0x31 ? 2 : 4); | 75 | int n = (dev_priv->chipset == 0x31 ? 2 : 4); |
66 | int b = (dev_priv->chipset > 0x30 ? | ||
67 | nv_rd32(dev, 0x122c) & 0xf : 0); | ||
68 | int l = nv_rd32(dev, 0x1003d0); | 76 | int l = nv_rd32(dev, 0x1003d0); |
69 | 77 | ||
70 | for (i = 0; i < n; i++) { | 78 | for (i = 0; i < n; i++) { |
71 | for (j = 0; j < 3; j++) | 79 | for (j = 0; j < 3; j++) |
72 | nv_wr32(dev, 0x10037c + 0xc * i + 0x4 * j, | 80 | nv_wr32(dev, 0x10037c + 0xc * i + 0x4 * j, |
73 | calc_ref(b, l, j)); | 81 | calc_ref(dev, l, 0, j)); |
74 | 82 | ||
75 | for (j = 0; j < 2; j++) | 83 | for (j = 0; j < 2; j++) |
76 | nv_wr32(dev, 0x1003ac + 0x8 * i + 0x4 * j, | 84 | nv_wr32(dev, 0x1003ac + 0x8 * i + 0x4 * j, |
77 | calc_ref(b, l, j)); | 85 | calc_ref(dev, l, 1, j)); |
78 | } | 86 | } |
79 | } | 87 | } |
80 | 88 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c index 5d11ea101666..bfd4ca2fe7ef 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c | |||
@@ -264,11 +264,16 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, int scaling_mode, bool update) | |||
264 | int | 264 | int |
265 | nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) | 265 | nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) |
266 | { | 266 | { |
267 | uint32_t reg = NV50_PDISPLAY_CRTC_CLK_CTRL1(head); | 267 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
268 | struct pll_lims pll; | 268 | struct pll_lims pll; |
269 | uint32_t reg1, reg2; | 269 | uint32_t reg, reg1, reg2; |
270 | int ret, N1, M1, N2, M2, P; | 270 | int ret, N1, M1, N2, M2, P; |
271 | 271 | ||
272 | if (dev_priv->chipset < NV_C0) | ||
273 | reg = NV50_PDISPLAY_CRTC_CLK_CTRL1(head); | ||
274 | else | ||
275 | reg = 0x614140 + (head * 0x800); | ||
276 | |||
272 | ret = get_pll_limits(dev, reg, &pll); | 277 | ret = get_pll_limits(dev, reg, &pll); |
273 | if (ret) | 278 | if (ret) |
274 | return ret; | 279 | return ret; |
@@ -286,7 +291,8 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) | |||
286 | nv_wr32(dev, reg, 0x10000611); | 291 | nv_wr32(dev, reg, 0x10000611); |
287 | nv_wr32(dev, reg + 4, reg1 | (M1 << 16) | N1); | 292 | nv_wr32(dev, reg + 4, reg1 | (M1 << 16) | N1); |
288 | nv_wr32(dev, reg + 8, reg2 | (P << 28) | (M2 << 16) | N2); | 293 | nv_wr32(dev, reg + 8, reg2 | (P << 28) | (M2 << 16) | N2); |
289 | } else { | 294 | } else |
295 | if (dev_priv->chipset < NV_C0) { | ||
290 | ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); | 296 | ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); |
291 | if (ret <= 0) | 297 | if (ret <= 0) |
292 | return 0; | 298 | return 0; |
@@ -298,6 +304,17 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) | |||
298 | nv_wr32(dev, reg, 0x50000610); | 304 | nv_wr32(dev, reg, 0x50000610); |
299 | nv_wr32(dev, reg + 4, reg1 | (P << 16) | (M1 << 8) | N1); | 305 | nv_wr32(dev, reg + 4, reg1 | (P << 16) | (M1 << 8) | N1); |
300 | nv_wr32(dev, reg + 8, N2); | 306 | nv_wr32(dev, reg + 8, N2); |
307 | } else { | ||
308 | ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); | ||
309 | if (ret <= 0) | ||
310 | return 0; | ||
311 | |||
312 | NV_DEBUG(dev, "pclk %d out %d N %d fN 0x%04x M %d P %d\n", | ||
313 | pclk, ret, N1, N2, M1, P); | ||
314 | |||
315 | nv_mask(dev, reg + 0x0c, 0x00000000, 0x00000100); | ||
316 | nv_wr32(dev, reg + 0x04, (P << 16) | (N1 << 8) | M1); | ||
317 | nv_wr32(dev, reg + 0x10, N2 << 16); | ||
301 | } | 318 | } |
302 | 319 | ||
303 | return 0; | 320 | return 0; |
@@ -348,7 +365,7 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, | |||
348 | 365 | ||
349 | gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); | 366 | gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); |
350 | if (!gem) | 367 | if (!gem) |
351 | return -EINVAL; | 368 | return -ENOENT; |
352 | cursor = nouveau_gem_object(gem); | 369 | cursor = nouveau_gem_object(gem); |
353 | 370 | ||
354 | ret = nouveau_bo_map(cursor); | 371 | ret = nouveau_bo_map(cursor); |
@@ -381,15 +398,12 @@ nv50_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) | |||
381 | 398 | ||
382 | static void | 399 | static void |
383 | nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, | 400 | nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, |
384 | uint32_t size) | 401 | uint32_t start, uint32_t size) |
385 | { | 402 | { |
403 | int end = (start + size > 256) ? 256 : start + size, i; | ||
386 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 404 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
387 | int i; | ||
388 | |||
389 | if (size != 256) | ||
390 | return; | ||
391 | 405 | ||
392 | for (i = 0; i < 256; i++) { | 406 | for (i = start; i < end; i++) { |
393 | nv_crtc->lut.r[i] = r[i]; | 407 | nv_crtc->lut.r[i] = r[i]; |
394 | nv_crtc->lut.g[i] = g[i]; | 408 | nv_crtc->lut.g[i] = g[i]; |
395 | nv_crtc->lut.b[i] = b[i]; | 409 | nv_crtc->lut.b[i] = b[i]; |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index f13ad0de9c8f..612fa6d6a0cb 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
@@ -76,7 +76,10 @@ nv50_evo_dmaobj_new(struct nouveau_channel *evo, uint32_t class, uint32_t name, | |||
76 | nv_wo32(dev, obj, 2, offset); | 76 | nv_wo32(dev, obj, 2, offset); |
77 | nv_wo32(dev, obj, 3, 0x00000000); | 77 | nv_wo32(dev, obj, 3, 0x00000000); |
78 | nv_wo32(dev, obj, 4, 0x00000000); | 78 | nv_wo32(dev, obj, 4, 0x00000000); |
79 | nv_wo32(dev, obj, 5, 0x00010000); | 79 | if (dev_priv->card_type < NV_C0) |
80 | nv_wo32(dev, obj, 5, 0x00010000); | ||
81 | else | ||
82 | nv_wo32(dev, obj, 5, 0x00020000); | ||
80 | dev_priv->engine.instmem.flush(dev); | 83 | dev_priv->engine.instmem.flush(dev); |
81 | 84 | ||
82 | return 0; | 85 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/nvc0_fb.c b/drivers/gpu/drm/nouveau/nvc0_fb.c new file mode 100644 index 000000000000..26a996025dd2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvc0_fb.c | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | |||
27 | #include "nouveau_drv.h" | ||
28 | |||
29 | int | ||
30 | nvc0_fb_init(struct drm_device *dev) | ||
31 | { | ||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | void | ||
36 | nvc0_fb_takedown(struct drm_device *dev) | ||
37 | { | ||
38 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c new file mode 100644 index 000000000000..d64375871979 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | |||
27 | #include "nouveau_drv.h" | ||
28 | |||
29 | void | ||
30 | nvc0_fifo_disable(struct drm_device *dev) | ||
31 | { | ||
32 | } | ||
33 | |||
34 | void | ||
35 | nvc0_fifo_enable(struct drm_device *dev) | ||
36 | { | ||
37 | } | ||
38 | |||
39 | bool | ||
40 | nvc0_fifo_reassign(struct drm_device *dev, bool enable) | ||
41 | { | ||
42 | return false; | ||
43 | } | ||
44 | |||
45 | bool | ||
46 | nvc0_fifo_cache_flush(struct drm_device *dev) | ||
47 | { | ||
48 | return true; | ||
49 | } | ||
50 | |||
51 | bool | ||
52 | nvc0_fifo_cache_pull(struct drm_device *dev, bool enable) | ||
53 | { | ||
54 | return false; | ||
55 | } | ||
56 | |||
57 | int | ||
58 | nvc0_fifo_channel_id(struct drm_device *dev) | ||
59 | { | ||
60 | return 127; | ||
61 | } | ||
62 | |||
63 | int | ||
64 | nvc0_fifo_create_context(struct nouveau_channel *chan) | ||
65 | { | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | void | ||
70 | nvc0_fifo_destroy_context(struct nouveau_channel *chan) | ||
71 | { | ||
72 | } | ||
73 | |||
74 | int | ||
75 | nvc0_fifo_load_context(struct nouveau_channel *chan) | ||
76 | { | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | int | ||
81 | nvc0_fifo_unload_context(struct drm_device *dev) | ||
82 | { | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | void | ||
87 | nvc0_fifo_takedown(struct drm_device *dev) | ||
88 | { | ||
89 | } | ||
90 | |||
91 | int | ||
92 | nvc0_fifo_init(struct drm_device *dev) | ||
93 | { | ||
94 | return 0; | ||
95 | } | ||
96 | |||
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c new file mode 100644 index 000000000000..717a5177a8d8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvc0_graph.c | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | |||
27 | #include "nouveau_drv.h" | ||
28 | |||
29 | void | ||
30 | nvc0_graph_fifo_access(struct drm_device *dev, bool enabled) | ||
31 | { | ||
32 | } | ||
33 | |||
34 | struct nouveau_channel * | ||
35 | nvc0_graph_channel(struct drm_device *dev) | ||
36 | { | ||
37 | return NULL; | ||
38 | } | ||
39 | |||
40 | int | ||
41 | nvc0_graph_create_context(struct nouveau_channel *chan) | ||
42 | { | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | void | ||
47 | nvc0_graph_destroy_context(struct nouveau_channel *chan) | ||
48 | { | ||
49 | } | ||
50 | |||
51 | int | ||
52 | nvc0_graph_load_context(struct nouveau_channel *chan) | ||
53 | { | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | int | ||
58 | nvc0_graph_unload_context(struct drm_device *dev) | ||
59 | { | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | void | ||
64 | nvc0_graph_takedown(struct drm_device *dev) | ||
65 | { | ||
66 | } | ||
67 | |||
68 | int | ||
69 | nvc0_graph_init(struct drm_device *dev) | ||
70 | { | ||
71 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
72 | dev_priv->engine.graph.accel_blocked = true; | ||
73 | return 0; | ||
74 | } | ||
75 | |||
diff --git a/drivers/gpu/drm/nouveau/nvc0_instmem.c b/drivers/gpu/drm/nouveau/nvc0_instmem.c new file mode 100644 index 000000000000..3ab3cdc42173 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvc0_instmem.c | |||
@@ -0,0 +1,232 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | |||
27 | #include "nouveau_drv.h" | ||
28 | |||
29 | int | ||
30 | nvc0_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, | ||
31 | uint32_t *size) | ||
32 | { | ||
33 | int ret; | ||
34 | |||
35 | *size = ALIGN(*size, 4096); | ||
36 | if (*size == 0) | ||
37 | return -EINVAL; | ||
38 | |||
39 | ret = nouveau_bo_new(dev, NULL, *size, 0, TTM_PL_FLAG_VRAM, 0, 0x0000, | ||
40 | true, false, &gpuobj->im_backing); | ||
41 | if (ret) { | ||
42 | NV_ERROR(dev, "error getting PRAMIN backing pages: %d\n", ret); | ||
43 | return ret; | ||
44 | } | ||
45 | |||
46 | ret = nouveau_bo_pin(gpuobj->im_backing, TTM_PL_FLAG_VRAM); | ||
47 | if (ret) { | ||
48 | NV_ERROR(dev, "error pinning PRAMIN backing VRAM: %d\n", ret); | ||
49 | nouveau_bo_ref(NULL, &gpuobj->im_backing); | ||
50 | return ret; | ||
51 | } | ||
52 | |||
53 | gpuobj->im_backing_start = gpuobj->im_backing->bo.mem.mm_node->start; | ||
54 | gpuobj->im_backing_start <<= PAGE_SHIFT; | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | void | ||
59 | nvc0_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | ||
60 | { | ||
61 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
62 | |||
63 | if (gpuobj && gpuobj->im_backing) { | ||
64 | if (gpuobj->im_bound) | ||
65 | dev_priv->engine.instmem.unbind(dev, gpuobj); | ||
66 | nouveau_bo_unpin(gpuobj->im_backing); | ||
67 | nouveau_bo_ref(NULL, &gpuobj->im_backing); | ||
68 | gpuobj->im_backing = NULL; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | int | ||
73 | nvc0_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | ||
74 | { | ||
75 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
76 | uint32_t pte, pte_end; | ||
77 | uint64_t vram; | ||
78 | |||
79 | if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) | ||
80 | return -EINVAL; | ||
81 | |||
82 | NV_DEBUG(dev, "st=0x%lx sz=0x%lx\n", | ||
83 | gpuobj->im_pramin->start, gpuobj->im_pramin->size); | ||
84 | |||
85 | pte = gpuobj->im_pramin->start >> 12; | ||
86 | pte_end = (gpuobj->im_pramin->size >> 12) + pte; | ||
87 | vram = gpuobj->im_backing_start; | ||
88 | |||
89 | NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n", | ||
90 | gpuobj->im_pramin->start, pte, pte_end); | ||
91 | NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start); | ||
92 | |||
93 | while (pte < pte_end) { | ||
94 | nv_wr32(dev, 0x702000 + (pte * 8), (vram >> 8) | 1); | ||
95 | nv_wr32(dev, 0x702004 + (pte * 8), 0); | ||
96 | vram += 4096; | ||
97 | pte++; | ||
98 | } | ||
99 | dev_priv->engine.instmem.flush(dev); | ||
100 | |||
101 | if (1) { | ||
102 | u32 chan = nv_rd32(dev, 0x1700) << 16; | ||
103 | nv_wr32(dev, 0x100cb8, (chan + 0x1000) >> 8); | ||
104 | nv_wr32(dev, 0x100cbc, 0x80000005); | ||
105 | } | ||
106 | |||
107 | gpuobj->im_bound = 1; | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | int | ||
112 | nvc0_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | ||
113 | { | ||
114 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
115 | uint32_t pte, pte_end; | ||
116 | |||
117 | if (gpuobj->im_bound == 0) | ||
118 | return -EINVAL; | ||
119 | |||
120 | pte = gpuobj->im_pramin->start >> 12; | ||
121 | pte_end = (gpuobj->im_pramin->size >> 12) + pte; | ||
122 | while (pte < pte_end) { | ||
123 | nv_wr32(dev, 0x702000 + (pte * 8), 0); | ||
124 | nv_wr32(dev, 0x702004 + (pte * 8), 0); | ||
125 | pte++; | ||
126 | } | ||
127 | dev_priv->engine.instmem.flush(dev); | ||
128 | |||
129 | gpuobj->im_bound = 0; | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | void | ||
134 | nvc0_instmem_flush(struct drm_device *dev) | ||
135 | { | ||
136 | nv_wr32(dev, 0x070000, 1); | ||
137 | if (!nv_wait(0x070000, 0x00000002, 0x00000000)) | ||
138 | NV_ERROR(dev, "PRAMIN flush timeout\n"); | ||
139 | } | ||
140 | |||
141 | int | ||
142 | nvc0_instmem_suspend(struct drm_device *dev) | ||
143 | { | ||
144 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
145 | int i; | ||
146 | |||
147 | dev_priv->susres.ramin_copy = vmalloc(65536); | ||
148 | if (!dev_priv->susres.ramin_copy) | ||
149 | return -ENOMEM; | ||
150 | |||
151 | for (i = 0x700000; i < 0x710000; i += 4) | ||
152 | dev_priv->susres.ramin_copy[i/4] = nv_rd32(dev, i); | ||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | void | ||
157 | nvc0_instmem_resume(struct drm_device *dev) | ||
158 | { | ||
159 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
160 | u64 chan; | ||
161 | int i; | ||
162 | |||
163 | chan = dev_priv->vram_size - dev_priv->ramin_rsvd_vram; | ||
164 | nv_wr32(dev, 0x001700, chan >> 16); | ||
165 | |||
166 | for (i = 0x700000; i < 0x710000; i += 4) | ||
167 | nv_wr32(dev, i, dev_priv->susres.ramin_copy[i/4]); | ||
168 | vfree(dev_priv->susres.ramin_copy); | ||
169 | dev_priv->susres.ramin_copy = NULL; | ||
170 | |||
171 | nv_wr32(dev, 0x001714, 0xc0000000 | (chan >> 12)); | ||
172 | } | ||
173 | |||
174 | int | ||
175 | nvc0_instmem_init(struct drm_device *dev) | ||
176 | { | ||
177 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
178 | u64 chan, pgt3, imem, lim3 = dev_priv->ramin_size - 1; | ||
179 | int ret, i; | ||
180 | |||
181 | dev_priv->ramin_rsvd_vram = 1 * 1024 * 1024; | ||
182 | chan = dev_priv->vram_size - dev_priv->ramin_rsvd_vram; | ||
183 | imem = 4096 + 4096 + 32768; | ||
184 | |||
185 | nv_wr32(dev, 0x001700, chan >> 16); | ||
186 | |||
187 | /* channel setup */ | ||
188 | nv_wr32(dev, 0x700200, lower_32_bits(chan + 0x1000)); | ||
189 | nv_wr32(dev, 0x700204, upper_32_bits(chan + 0x1000)); | ||
190 | nv_wr32(dev, 0x700208, lower_32_bits(lim3)); | ||
191 | nv_wr32(dev, 0x70020c, upper_32_bits(lim3)); | ||
192 | |||
193 | /* point pgd -> pgt */ | ||
194 | nv_wr32(dev, 0x701000, 0); | ||
195 | nv_wr32(dev, 0x701004, ((chan + 0x2000) >> 8) | 1); | ||
196 | |||
197 | /* point pgt -> physical vram for channel */ | ||
198 | pgt3 = 0x2000; | ||
199 | for (i = 0; i < dev_priv->ramin_rsvd_vram; i += 4096, pgt3 += 8) { | ||
200 | nv_wr32(dev, 0x700000 + pgt3, ((chan + i) >> 8) | 1); | ||
201 | nv_wr32(dev, 0x700004 + pgt3, 0); | ||
202 | } | ||
203 | |||
204 | /* clear rest of pgt */ | ||
205 | for (; i < dev_priv->ramin_size; i += 4096, pgt3 += 8) { | ||
206 | nv_wr32(dev, 0x700000 + pgt3, 0); | ||
207 | nv_wr32(dev, 0x700004 + pgt3, 0); | ||
208 | } | ||
209 | |||
210 | /* point bar3 at the channel */ | ||
211 | nv_wr32(dev, 0x001714, 0xc0000000 | (chan >> 12)); | ||
212 | |||
213 | /* Global PRAMIN heap */ | ||
214 | ret = drm_mm_init(&dev_priv->ramin_heap, imem, | ||
215 | dev_priv->ramin_size - imem); | ||
216 | if (ret) { | ||
217 | NV_ERROR(dev, "Failed to init RAMIN heap\n"); | ||
218 | return -ENOMEM; | ||
219 | } | ||
220 | |||
221 | /*XXX: incorrect, but needed to make hash func "work" */ | ||
222 | dev_priv->ramht_offset = 0x10000; | ||
223 | dev_priv->ramht_bits = 9; | ||
224 | dev_priv->ramht_size = (1 << dev_priv->ramht_bits); | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | void | ||
229 | nvc0_instmem_takedown(struct drm_device *dev) | ||
230 | { | ||
231 | } | ||
232 | |||
diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c index 68e6f4349309..4f4cd8b286d5 100644 --- a/drivers/gpu/drm/radeon/r600_cp.c +++ b/drivers/gpu/drm/radeon/r600_cp.c | |||
@@ -200,7 +200,7 @@ int r600_page_table_init(struct drm_device *dev) | |||
200 | entry->pagelist[i], 0, | 200 | entry->pagelist[i], 0, |
201 | PAGE_SIZE, | 201 | PAGE_SIZE, |
202 | PCI_DMA_BIDIRECTIONAL); | 202 | PCI_DMA_BIDIRECTIONAL); |
203 | if (entry->busaddr[i] == 0) { | 203 | if (pci_dma_mapping_error(dev->pdev, entry->busaddr[i])) { |
204 | DRM_ERROR("unable to map PCIGART pages!\n"); | 204 | DRM_ERROR("unable to map PCIGART pages!\n"); |
205 | r600_page_table_cleanup(dev, gart_info); | 205 | r600_page_table_cleanup(dev, gart_info); |
206 | goto done; | 206 | goto done; |
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index c3ea212e0c3c..d8864949e387 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c | |||
@@ -133,6 +133,7 @@ static inline int r600_bpe_from_format(u32 *bpe, u32 format) | |||
133 | case V_038004_FMT_GB_GR: | 133 | case V_038004_FMT_GB_GR: |
134 | case V_038004_FMT_BG_RG: | 134 | case V_038004_FMT_BG_RG: |
135 | case V_038004_COLOR_INVALID: | 135 | case V_038004_COLOR_INVALID: |
136 | default: | ||
136 | *bpe = 16; | 137 | *bpe = 16; |
137 | return -EINVAL; | 138 | return -EINVAL; |
138 | } | 139 | } |
@@ -174,7 +175,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) | |||
174 | dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n"); | 175 | dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n"); |
175 | return -EINVAL; | 176 | return -EINVAL; |
176 | } | 177 | } |
177 | size = radeon_bo_size(track->cb_color_bo[i]); | 178 | size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i]; |
178 | if (r600_bpe_from_format(&bpe, G_0280A0_FORMAT(track->cb_color_info[i]))) { | 179 | if (r600_bpe_from_format(&bpe, G_0280A0_FORMAT(track->cb_color_info[i]))) { |
179 | dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n", | 180 | dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n", |
180 | __func__, __LINE__, G_0280A0_FORMAT(track->cb_color_info[i]), | 181 | __func__, __LINE__, G_0280A0_FORMAT(track->cb_color_info[i]), |
@@ -327,7 +328,6 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) | |||
327 | dev_warn(p->dev, "z/stencil buffer size not set\n"); | 328 | dev_warn(p->dev, "z/stencil buffer size not set\n"); |
328 | return -EINVAL; | 329 | return -EINVAL; |
329 | } | 330 | } |
330 | printk_once(KERN_WARNING "You have old & broken userspace please consider updating mesa\n"); | ||
331 | tmp = radeon_bo_size(track->db_bo) - track->db_offset; | 331 | tmp = radeon_bo_size(track->db_bo) - track->db_offset; |
332 | tmp = (tmp / bpe) >> 6; | 332 | tmp = (tmp / bpe) >> 6; |
333 | if (!tmp) { | 333 | if (!tmp) { |
@@ -882,8 +882,6 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx | |||
882 | return -EINVAL; | 882 | return -EINVAL; |
883 | } | 883 | } |
884 | ib[idx] = track->cb_color_base_last[tmp]; | 884 | ib[idx] = track->cb_color_base_last[tmp]; |
885 | printk_once(KERN_WARNING "You have old & broken userspace " | ||
886 | "please consider updating mesa & xf86-video-ati\n"); | ||
887 | track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp]; | 885 | track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp]; |
888 | } else { | 886 | } else { |
889 | r = r600_cs_packet_next_reloc(p, &reloc); | 887 | r = r600_cs_packet_next_reloc(p, &reloc); |
@@ -910,8 +908,6 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx | |||
910 | return -EINVAL; | 908 | return -EINVAL; |
911 | } | 909 | } |
912 | ib[idx] = track->cb_color_base_last[tmp]; | 910 | ib[idx] = track->cb_color_base_last[tmp]; |
913 | printk_once(KERN_WARNING "You have old & broken userspace " | ||
914 | "please consider updating mesa & xf86-video-ati\n"); | ||
915 | track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp]; | 911 | track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp]; |
916 | } else { | 912 | } else { |
917 | r = r600_cs_packet_next_reloc(p, &reloc); | 913 | r = r600_cs_packet_next_reloc(p, &reloc); |
@@ -938,7 +934,7 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx | |||
938 | return -EINVAL; | 934 | return -EINVAL; |
939 | } | 935 | } |
940 | tmp = (reg - CB_COLOR0_BASE) / 4; | 936 | tmp = (reg - CB_COLOR0_BASE) / 4; |
941 | track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx); | 937 | track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; |
942 | ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); | 938 | ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); |
943 | track->cb_color_base_last[tmp] = ib[idx]; | 939 | track->cb_color_base_last[tmp] = ib[idx]; |
944 | track->cb_color_bo[tmp] = reloc->robj; | 940 | track->cb_color_bo[tmp] = reloc->robj; |
@@ -950,7 +946,7 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx | |||
950 | "0x%04X\n", reg); | 946 | "0x%04X\n", reg); |
951 | return -EINVAL; | 947 | return -EINVAL; |
952 | } | 948 | } |
953 | track->db_offset = radeon_get_ib_value(p, idx); | 949 | track->db_offset = radeon_get_ib_value(p, idx) << 8; |
954 | ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); | 950 | ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); |
955 | track->db_bo = reloc->robj; | 951 | track->db_bo = reloc->robj; |
956 | break; | 952 | break; |
@@ -1055,10 +1051,10 @@ static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels | |||
1055 | } | 1051 | } |
1056 | *l0_size = ALIGN((w0 * bpe), pitch_align) * h0 * d0; | 1052 | *l0_size = ALIGN((w0 * bpe), pitch_align) * h0 * d0; |
1057 | *mipmap_size = offset; | 1053 | *mipmap_size = offset; |
1058 | if (!blevel) | ||
1059 | *mipmap_size -= *l0_size; | ||
1060 | if (!nlevels) | 1054 | if (!nlevels) |
1061 | *mipmap_size = *l0_size; | 1055 | *mipmap_size = *l0_size; |
1056 | if (!blevel) | ||
1057 | *mipmap_size -= *l0_size; | ||
1062 | } | 1058 | } |
1063 | 1059 | ||
1064 | /** | 1060 | /** |
@@ -1165,14 +1161,14 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i | |||
1165 | (pitch_align * bpe), | 1161 | (pitch_align * bpe), |
1166 | &l0_size, &mipmap_size); | 1162 | &l0_size, &mipmap_size); |
1167 | /* using get ib will give us the offset into the texture bo */ | 1163 | /* using get ib will give us the offset into the texture bo */ |
1168 | word0 = radeon_get_ib_value(p, idx + 2); | 1164 | word0 = radeon_get_ib_value(p, idx + 2) << 8; |
1169 | if ((l0_size + word0) > radeon_bo_size(texture)) { | 1165 | if ((l0_size + word0) > radeon_bo_size(texture)) { |
1170 | dev_warn(p->dev, "texture bo too small (%d %d %d %d -> %d have %ld)\n", | 1166 | dev_warn(p->dev, "texture bo too small (%d %d %d %d -> %d have %ld)\n", |
1171 | w0, h0, bpe, word0, l0_size, radeon_bo_size(texture)); | 1167 | w0, h0, bpe, word0, l0_size, radeon_bo_size(texture)); |
1172 | return -EINVAL; | 1168 | return -EINVAL; |
1173 | } | 1169 | } |
1174 | /* using get ib will give us the offset into the mipmap bo */ | 1170 | /* using get ib will give us the offset into the mipmap bo */ |
1175 | word0 = radeon_get_ib_value(p, idx + 3); | 1171 | word0 = radeon_get_ib_value(p, idx + 3) << 8; |
1176 | if ((mipmap_size + word0) > radeon_bo_size(mipmap)) { | 1172 | if ((mipmap_size + word0) > radeon_bo_size(mipmap)) { |
1177 | dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", | 1173 | dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", |
1178 | w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture)); | 1174 | w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture)); |
@@ -1366,7 +1362,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, | |||
1366 | } | 1362 | } |
1367 | for (i = 0; i < (pkt->count / 7); i++) { | 1363 | for (i = 0; i < (pkt->count / 7); i++) { |
1368 | struct radeon_bo *texture, *mipmap; | 1364 | struct radeon_bo *texture, *mipmap; |
1369 | u32 size, offset; | 1365 | u32 size, offset, base_offset, mip_offset; |
1370 | 1366 | ||
1371 | switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) { | 1367 | switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) { |
1372 | case SQ_TEX_VTX_VALID_TEXTURE: | 1368 | case SQ_TEX_VTX_VALID_TEXTURE: |
@@ -1376,7 +1372,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, | |||
1376 | DRM_ERROR("bad SET_RESOURCE\n"); | 1372 | DRM_ERROR("bad SET_RESOURCE\n"); |
1377 | return -EINVAL; | 1373 | return -EINVAL; |
1378 | } | 1374 | } |
1379 | ib[idx+1+(i*7)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); | 1375 | base_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); |
1380 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) | 1376 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) |
1381 | ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1); | 1377 | ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1); |
1382 | else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) | 1378 | else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) |
@@ -1388,12 +1384,14 @@ static int r600_packet3_check(struct radeon_cs_parser *p, | |||
1388 | DRM_ERROR("bad SET_RESOURCE\n"); | 1384 | DRM_ERROR("bad SET_RESOURCE\n"); |
1389 | return -EINVAL; | 1385 | return -EINVAL; |
1390 | } | 1386 | } |
1391 | ib[idx+1+(i*7)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); | 1387 | mip_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); |
1392 | mipmap = reloc->robj; | 1388 | mipmap = reloc->robj; |
1393 | r = r600_check_texture_resource(p, idx+(i*7)+1, | 1389 | r = r600_check_texture_resource(p, idx+(i*7)+1, |
1394 | texture, mipmap, reloc->lobj.tiling_flags); | 1390 | texture, mipmap, reloc->lobj.tiling_flags); |
1395 | if (r) | 1391 | if (r) |
1396 | return r; | 1392 | return r; |
1393 | ib[idx+1+(i*7)+2] += base_offset; | ||
1394 | ib[idx+1+(i*7)+3] += mip_offset; | ||
1397 | break; | 1395 | break; |
1398 | case SQ_TEX_VTX_VALID_BUFFER: | 1396 | case SQ_TEX_VTX_VALID_BUFFER: |
1399 | /* vtx base */ | 1397 | /* vtx base */ |
@@ -1403,10 +1401,11 @@ static int r600_packet3_check(struct radeon_cs_parser *p, | |||
1403 | return -EINVAL; | 1401 | return -EINVAL; |
1404 | } | 1402 | } |
1405 | offset = radeon_get_ib_value(p, idx+1+(i*7)+0); | 1403 | offset = radeon_get_ib_value(p, idx+1+(i*7)+0); |
1406 | size = radeon_get_ib_value(p, idx+1+(i*7)+1); | 1404 | size = radeon_get_ib_value(p, idx+1+(i*7)+1) + 1; |
1407 | if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) { | 1405 | if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) { |
1408 | /* force size to size of the buffer */ | 1406 | /* force size to size of the buffer */ |
1409 | dev_warn(p->dev, "vbo resource seems too big for the bo\n"); | 1407 | dev_warn(p->dev, "vbo resource seems too big (%d) for the bo (%ld)\n", |
1408 | size + offset, radeon_bo_size(reloc->robj)); | ||
1410 | ib[idx+1+(i*7)+1] = radeon_bo_size(reloc->robj); | 1409 | ib[idx+1+(i*7)+1] = radeon_bo_size(reloc->robj); |
1411 | } | 1410 | } |
1412 | ib[idx+1+(i*7)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff); | 1411 | ib[idx+1+(i*7)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff); |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 3cd1c470b777..3dfcfa3ca425 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -1100,6 +1100,8 @@ struct radeon_device { | |||
1100 | struct notifier_block acpi_nb; | 1100 | struct notifier_block acpi_nb; |
1101 | /* only one userspace can use Hyperz features at a time */ | 1101 | /* only one userspace can use Hyperz features at a time */ |
1102 | struct drm_file *hyperz_filp; | 1102 | struct drm_file *hyperz_filp; |
1103 | /* i2c buses */ | ||
1104 | struct radeon_i2c_chan *i2c_bus[RADEON_MAX_I2C_BUS]; | ||
1103 | }; | 1105 | }; |
1104 | 1106 | ||
1105 | int radeon_device_init(struct radeon_device *rdev, | 1107 | int radeon_device_init(struct radeon_device *rdev, |
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 3bc2bcdf5308..6d30868744ee 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c | |||
@@ -48,7 +48,8 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
48 | struct radeon_i2c_bus_rec *i2c_bus, | 48 | struct radeon_i2c_bus_rec *i2c_bus, |
49 | bool linkb, uint32_t igp_lane_info, | 49 | bool linkb, uint32_t igp_lane_info, |
50 | uint16_t connector_object_id, | 50 | uint16_t connector_object_id, |
51 | struct radeon_hpd *hpd); | 51 | struct radeon_hpd *hpd, |
52 | struct radeon_router *router); | ||
52 | 53 | ||
53 | /* from radeon_legacy_encoder.c */ | 54 | /* from radeon_legacy_encoder.c */ |
54 | extern void | 55 | extern void |
@@ -114,7 +115,8 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev | |||
114 | 115 | ||
115 | i2c.i2c_id = gpio->sucI2cId.ucAccess; | 116 | i2c.i2c_id = gpio->sucI2cId.ucAccess; |
116 | 117 | ||
117 | i2c.valid = true; | 118 | if (i2c.mask_clk_reg) |
119 | i2c.valid = true; | ||
118 | break; | 120 | break; |
119 | } | 121 | } |
120 | } | 122 | } |
@@ -123,6 +125,66 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev | |||
123 | return i2c; | 125 | return i2c; |
124 | } | 126 | } |
125 | 127 | ||
128 | void radeon_atombios_i2c_init(struct radeon_device *rdev) | ||
129 | { | ||
130 | struct atom_context *ctx = rdev->mode_info.atom_context; | ||
131 | ATOM_GPIO_I2C_ASSIGMENT *gpio; | ||
132 | struct radeon_i2c_bus_rec i2c; | ||
133 | int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info); | ||
134 | struct _ATOM_GPIO_I2C_INFO *i2c_info; | ||
135 | uint16_t data_offset, size; | ||
136 | int i, num_indices; | ||
137 | char stmp[32]; | ||
138 | |||
139 | memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec)); | ||
140 | |||
141 | if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) { | ||
142 | i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset); | ||
143 | |||
144 | num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / | ||
145 | sizeof(ATOM_GPIO_I2C_ASSIGMENT); | ||
146 | |||
147 | for (i = 0; i < num_indices; i++) { | ||
148 | gpio = &i2c_info->asGPIO_Info[i]; | ||
149 | i2c.valid = false; | ||
150 | i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; | ||
151 | i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; | ||
152 | i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; | ||
153 | i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4; | ||
154 | i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4; | ||
155 | i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4; | ||
156 | i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4; | ||
157 | i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4; | ||
158 | i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift); | ||
159 | i2c.mask_data_mask = (1 << gpio->ucDataMaskShift); | ||
160 | i2c.en_clk_mask = (1 << gpio->ucClkEnShift); | ||
161 | i2c.en_data_mask = (1 << gpio->ucDataEnShift); | ||
162 | i2c.y_clk_mask = (1 << gpio->ucClkY_Shift); | ||
163 | i2c.y_data_mask = (1 << gpio->ucDataY_Shift); | ||
164 | i2c.a_clk_mask = (1 << gpio->ucClkA_Shift); | ||
165 | i2c.a_data_mask = (1 << gpio->ucDataA_Shift); | ||
166 | |||
167 | if (gpio->sucI2cId.sbfAccess.bfHW_Capable) | ||
168 | i2c.hw_capable = true; | ||
169 | else | ||
170 | i2c.hw_capable = false; | ||
171 | |||
172 | if (gpio->sucI2cId.ucAccess == 0xa0) | ||
173 | i2c.mm_i2c = true; | ||
174 | else | ||
175 | i2c.mm_i2c = false; | ||
176 | |||
177 | i2c.i2c_id = gpio->sucI2cId.ucAccess; | ||
178 | |||
179 | if (i2c.mask_clk_reg) { | ||
180 | i2c.valid = true; | ||
181 | sprintf(stmp, "0x%x", i2c.i2c_id); | ||
182 | rdev->i2c_bus[i] = radeon_i2c_create(rdev->ddev, &i2c, stmp); | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | } | ||
187 | |||
126 | static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev, | 188 | static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev, |
127 | u8 id) | 189 | u8 id) |
128 | { | 190 | { |
@@ -206,6 +268,7 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, | |||
206 | uint16_t *line_mux, | 268 | uint16_t *line_mux, |
207 | struct radeon_hpd *hpd) | 269 | struct radeon_hpd *hpd) |
208 | { | 270 | { |
271 | struct radeon_device *rdev = dev->dev_private; | ||
209 | 272 | ||
210 | /* Asus M2A-VM HDMI board lists the DVI port as HDMI */ | 273 | /* Asus M2A-VM HDMI board lists the DVI port as HDMI */ |
211 | if ((dev->pdev->device == 0x791e) && | 274 | if ((dev->pdev->device == 0x791e) && |
@@ -308,13 +371,22 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, | |||
308 | } | 371 | } |
309 | } | 372 | } |
310 | 373 | ||
311 | /* Acer laptop reports DVI-D as DVI-I */ | 374 | /* Acer laptop reports DVI-D as DVI-I and hpd pins reversed */ |
312 | if ((dev->pdev->device == 0x95c4) && | 375 | if ((dev->pdev->device == 0x95c4) && |
313 | (dev->pdev->subsystem_vendor == 0x1025) && | 376 | (dev->pdev->subsystem_vendor == 0x1025) && |
314 | (dev->pdev->subsystem_device == 0x013c)) { | 377 | (dev->pdev->subsystem_device == 0x013c)) { |
378 | struct radeon_gpio_rec gpio; | ||
379 | |||
315 | if ((*connector_type == DRM_MODE_CONNECTOR_DVII) && | 380 | if ((*connector_type == DRM_MODE_CONNECTOR_DVII) && |
316 | (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) | 381 | (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) { |
382 | gpio = radeon_lookup_gpio(rdev, 6); | ||
383 | *hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio); | ||
317 | *connector_type = DRM_MODE_CONNECTOR_DVID; | 384 | *connector_type = DRM_MODE_CONNECTOR_DVID; |
385 | } else if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) && | ||
386 | (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) { | ||
387 | gpio = radeon_lookup_gpio(rdev, 7); | ||
388 | *hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio); | ||
389 | } | ||
318 | } | 390 | } |
319 | 391 | ||
320 | /* XFX Pine Group device rv730 reports no VGA DDC lines | 392 | /* XFX Pine Group device rv730 reports no VGA DDC lines |
@@ -399,13 +471,15 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
399 | u16 size, data_offset; | 471 | u16 size, data_offset; |
400 | u8 frev, crev; | 472 | u8 frev, crev; |
401 | ATOM_CONNECTOR_OBJECT_TABLE *con_obj; | 473 | ATOM_CONNECTOR_OBJECT_TABLE *con_obj; |
474 | ATOM_OBJECT_TABLE *router_obj; | ||
402 | ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj; | 475 | ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj; |
403 | ATOM_OBJECT_HEADER *obj_header; | 476 | ATOM_OBJECT_HEADER *obj_header; |
404 | int i, j, path_size, device_support; | 477 | int i, j, k, path_size, device_support; |
405 | int connector_type; | 478 | int connector_type; |
406 | u16 igp_lane_info, conn_id, connector_object_id; | 479 | u16 igp_lane_info, conn_id, connector_object_id; |
407 | bool linkb; | 480 | bool linkb; |
408 | struct radeon_i2c_bus_rec ddc_bus; | 481 | struct radeon_i2c_bus_rec ddc_bus; |
482 | struct radeon_router router; | ||
409 | struct radeon_gpio_rec gpio; | 483 | struct radeon_gpio_rec gpio; |
410 | struct radeon_hpd hpd; | 484 | struct radeon_hpd hpd; |
411 | 485 | ||
@@ -415,6 +489,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
415 | if (crev < 2) | 489 | if (crev < 2) |
416 | return false; | 490 | return false; |
417 | 491 | ||
492 | router.valid = false; | ||
493 | |||
418 | obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset); | 494 | obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset); |
419 | path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *) | 495 | path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *) |
420 | (ctx->bios + data_offset + | 496 | (ctx->bios + data_offset + |
@@ -422,6 +498,9 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
422 | con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *) | 498 | con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *) |
423 | (ctx->bios + data_offset + | 499 | (ctx->bios + data_offset + |
424 | le16_to_cpu(obj_header->usConnectorObjectTableOffset)); | 500 | le16_to_cpu(obj_header->usConnectorObjectTableOffset)); |
501 | router_obj = (ATOM_OBJECT_TABLE *) | ||
502 | (ctx->bios + data_offset + | ||
503 | le16_to_cpu(obj_header->usRouterObjectTableOffset)); | ||
425 | device_support = le16_to_cpu(obj_header->usDeviceSupport); | 504 | device_support = le16_to_cpu(obj_header->usDeviceSupport); |
426 | 505 | ||
427 | path_size = 0; | 506 | path_size = 0; |
@@ -508,33 +587,86 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
508 | if (connector_type == DRM_MODE_CONNECTOR_Unknown) | 587 | if (connector_type == DRM_MODE_CONNECTOR_Unknown) |
509 | continue; | 588 | continue; |
510 | 589 | ||
511 | for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); | 590 | for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) { |
512 | j++) { | 591 | uint8_t grph_obj_id, grph_obj_num, grph_obj_type; |
513 | uint8_t enc_obj_id, enc_obj_num, enc_obj_type; | ||
514 | 592 | ||
515 | enc_obj_id = | 593 | grph_obj_id = |
516 | (le16_to_cpu(path->usGraphicObjIds[j]) & | 594 | (le16_to_cpu(path->usGraphicObjIds[j]) & |
517 | OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; | 595 | OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; |
518 | enc_obj_num = | 596 | grph_obj_num = |
519 | (le16_to_cpu(path->usGraphicObjIds[j]) & | 597 | (le16_to_cpu(path->usGraphicObjIds[j]) & |
520 | ENUM_ID_MASK) >> ENUM_ID_SHIFT; | 598 | ENUM_ID_MASK) >> ENUM_ID_SHIFT; |
521 | enc_obj_type = | 599 | grph_obj_type = |
522 | (le16_to_cpu(path->usGraphicObjIds[j]) & | 600 | (le16_to_cpu(path->usGraphicObjIds[j]) & |
523 | OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; | 601 | OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; |
524 | 602 | ||
525 | /* FIXME: add support for router objects */ | 603 | if (grph_obj_type == GRAPH_OBJECT_TYPE_ENCODER) { |
526 | if (enc_obj_type == GRAPH_OBJECT_TYPE_ENCODER) { | 604 | if (grph_obj_num == 2) |
527 | if (enc_obj_num == 2) | ||
528 | linkb = true; | 605 | linkb = true; |
529 | else | 606 | else |
530 | linkb = false; | 607 | linkb = false; |
531 | 608 | ||
532 | radeon_add_atom_encoder(dev, | 609 | radeon_add_atom_encoder(dev, |
533 | enc_obj_id, | 610 | grph_obj_id, |
534 | le16_to_cpu | 611 | le16_to_cpu |
535 | (path-> | 612 | (path-> |
536 | usDeviceTag)); | 613 | usDeviceTag)); |
537 | 614 | ||
615 | } else if (grph_obj_type == GRAPH_OBJECT_TYPE_ROUTER) { | ||
616 | router.valid = false; | ||
617 | for (k = 0; k < router_obj->ucNumberOfObjects; k++) { | ||
618 | u16 router_obj_id = le16_to_cpu(router_obj->asObjects[j].usObjectID); | ||
619 | if (le16_to_cpu(path->usGraphicObjIds[j]) == router_obj_id) { | ||
620 | ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *) | ||
621 | (ctx->bios + data_offset + | ||
622 | le16_to_cpu(router_obj->asObjects[k].usRecordOffset)); | ||
623 | ATOM_I2C_RECORD *i2c_record; | ||
624 | ATOM_I2C_ID_CONFIG_ACCESS *i2c_config; | ||
625 | ATOM_ROUTER_DDC_PATH_SELECT_RECORD *ddc_path; | ||
626 | ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *router_src_dst_table = | ||
627 | (ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *) | ||
628 | (ctx->bios + data_offset + | ||
629 | le16_to_cpu(router_obj->asObjects[k].usSrcDstTableOffset)); | ||
630 | int enum_id; | ||
631 | |||
632 | router.router_id = router_obj_id; | ||
633 | for (enum_id = 0; enum_id < router_src_dst_table->ucNumberOfDst; | ||
634 | enum_id++) { | ||
635 | if (le16_to_cpu(path->usConnObjectId) == | ||
636 | le16_to_cpu(router_src_dst_table->usDstObjectID[enum_id])) | ||
637 | break; | ||
638 | } | ||
639 | |||
640 | while (record->ucRecordType > 0 && | ||
641 | record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) { | ||
642 | switch (record->ucRecordType) { | ||
643 | case ATOM_I2C_RECORD_TYPE: | ||
644 | i2c_record = | ||
645 | (ATOM_I2C_RECORD *) | ||
646 | record; | ||
647 | i2c_config = | ||
648 | (ATOM_I2C_ID_CONFIG_ACCESS *) | ||
649 | &i2c_record->sucI2cId; | ||
650 | router.i2c_info = | ||
651 | radeon_lookup_i2c_gpio(rdev, | ||
652 | i2c_config-> | ||
653 | ucAccess); | ||
654 | router.i2c_addr = i2c_record->ucI2CAddr >> 1; | ||
655 | break; | ||
656 | case ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE: | ||
657 | ddc_path = (ATOM_ROUTER_DDC_PATH_SELECT_RECORD *) | ||
658 | record; | ||
659 | router.valid = true; | ||
660 | router.mux_type = ddc_path->ucMuxType; | ||
661 | router.mux_control_pin = ddc_path->ucMuxControlPin; | ||
662 | router.mux_state = ddc_path->ucMuxState[enum_id]; | ||
663 | break; | ||
664 | } | ||
665 | record = (ATOM_COMMON_RECORD_HEADER *) | ||
666 | ((char *)record + record->ucRecordSize); | ||
667 | } | ||
668 | } | ||
669 | } | ||
538 | } | 670 | } |
539 | } | 671 | } |
540 | 672 | ||
@@ -614,7 +746,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
614 | connector_type, &ddc_bus, | 746 | connector_type, &ddc_bus, |
615 | linkb, igp_lane_info, | 747 | linkb, igp_lane_info, |
616 | connector_object_id, | 748 | connector_object_id, |
617 | &hpd); | 749 | &hpd, |
750 | &router); | ||
618 | 751 | ||
619 | } | 752 | } |
620 | } | 753 | } |
@@ -691,6 +824,9 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct | |||
691 | int i, j, max_device; | 824 | int i, j, max_device; |
692 | struct bios_connector *bios_connectors; | 825 | struct bios_connector *bios_connectors; |
693 | size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE; | 826 | size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE; |
827 | struct radeon_router router; | ||
828 | |||
829 | router.valid = false; | ||
694 | 830 | ||
695 | bios_connectors = kzalloc(bc_size, GFP_KERNEL); | 831 | bios_connectors = kzalloc(bc_size, GFP_KERNEL); |
696 | if (!bios_connectors) | 832 | if (!bios_connectors) |
@@ -862,7 +998,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct | |||
862 | &bios_connectors[i].ddc_bus, | 998 | &bios_connectors[i].ddc_bus, |
863 | false, 0, | 999 | false, 0, |
864 | connector_object_id, | 1000 | connector_object_id, |
865 | &bios_connectors[i].hpd); | 1001 | &bios_connectors[i].hpd, |
1002 | &router); | ||
866 | } | 1003 | } |
867 | } | 1004 | } |
868 | 1005 | ||
@@ -1521,7 +1658,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) | |||
1521 | thermal_controller_names[power_info->info.ucOverdriveThermalController], | 1658 | thermal_controller_names[power_info->info.ucOverdriveThermalController], |
1522 | power_info->info.ucOverdriveControllerAddress >> 1); | 1659 | power_info->info.ucOverdriveControllerAddress >> 1); |
1523 | i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine); | 1660 | i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine); |
1524 | rdev->pm.i2c_bus = radeon_i2c_create(rdev->ddev, &i2c_bus, "Thermal"); | 1661 | rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); |
1525 | if (rdev->pm.i2c_bus) { | 1662 | if (rdev->pm.i2c_bus) { |
1526 | struct i2c_board_info info = { }; | 1663 | struct i2c_board_info info = { }; |
1527 | const char *name = thermal_controller_names[power_info->info. | 1664 | const char *name = thermal_controller_names[power_info->info. |
@@ -1814,7 +1951,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) | |||
1814 | (controller->ucFanParameters & | 1951 | (controller->ucFanParameters & |
1815 | ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); | 1952 | ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); |
1816 | i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine); | 1953 | i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine); |
1817 | rdev->pm.i2c_bus = radeon_i2c_create(rdev->ddev, &i2c_bus, "Thermal"); | 1954 | rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); |
1818 | if (rdev->pm.i2c_bus) { | 1955 | if (rdev->pm.i2c_bus) { |
1819 | struct i2c_board_info info = { }; | 1956 | struct i2c_board_info info = { }; |
1820 | const char *name = pp_lib_thermal_controller_names[controller->ucType]; | 1957 | const char *name = pp_lib_thermal_controller_names[controller->ucType]; |
@@ -1927,6 +2064,11 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) | |||
1927 | rdev->pm.power_state[state_index].type = | 2064 | rdev->pm.power_state[state_index].type = |
1928 | POWER_STATE_TYPE_PERFORMANCE; | 2065 | POWER_STATE_TYPE_PERFORMANCE; |
1929 | break; | 2066 | break; |
2067 | case ATOM_PPLIB_CLASSIFICATION_UI_NONE: | ||
2068 | if (misc2 & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) | ||
2069 | rdev->pm.power_state[state_index].type = | ||
2070 | POWER_STATE_TYPE_PERFORMANCE; | ||
2071 | break; | ||
1930 | } | 2072 | } |
1931 | rdev->pm.power_state[state_index].flags = 0; | 2073 | rdev->pm.power_state[state_index].flags = 0; |
1932 | if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) | 2074 | if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) |
diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c index f64936cc4dd9..14448a740ba6 100644 --- a/drivers/gpu/drm/radeon/radeon_clocks.c +++ b/drivers/gpu/drm/radeon/radeon_clocks.c | |||
@@ -91,6 +91,85 @@ uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev) | |||
91 | return mclk; | 91 | return mclk; |
92 | } | 92 | } |
93 | 93 | ||
94 | #ifdef CONFIG_OF | ||
95 | /* | ||
96 | * Read XTAL (ref clock), SCLK and MCLK from Open Firmware device | ||
97 | * tree. Hopefully, ATI OF driver is kind enough to fill these | ||
98 | */ | ||
99 | static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) | ||
100 | { | ||
101 | struct radeon_device *rdev = dev->dev_private; | ||
102 | struct device_node *dp = rdev->pdev->dev.of_node; | ||
103 | const u32 *val; | ||
104 | struct radeon_pll *p1pll = &rdev->clock.p1pll; | ||
105 | struct radeon_pll *p2pll = &rdev->clock.p2pll; | ||
106 | struct radeon_pll *spll = &rdev->clock.spll; | ||
107 | struct radeon_pll *mpll = &rdev->clock.mpll; | ||
108 | |||
109 | if (dp == NULL) | ||
110 | return false; | ||
111 | val = of_get_property(dp, "ATY,RefCLK", NULL); | ||
112 | if (!val || !*val) { | ||
113 | printk(KERN_WARNING "radeonfb: No ATY,RefCLK property !\n"); | ||
114 | return false; | ||
115 | } | ||
116 | p1pll->reference_freq = p2pll->reference_freq = (*val) / 10; | ||
117 | p1pll->reference_div = RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff; | ||
118 | if (p1pll->reference_div < 2) | ||
119 | p1pll->reference_div = 12; | ||
120 | p2pll->reference_div = p1pll->reference_div; | ||
121 | |||
122 | /* These aren't in the device-tree */ | ||
123 | if (rdev->family >= CHIP_R420) { | ||
124 | p1pll->pll_in_min = 100; | ||
125 | p1pll->pll_in_max = 1350; | ||
126 | p1pll->pll_out_min = 20000; | ||
127 | p1pll->pll_out_max = 50000; | ||
128 | p2pll->pll_in_min = 100; | ||
129 | p2pll->pll_in_max = 1350; | ||
130 | p2pll->pll_out_min = 20000; | ||
131 | p2pll->pll_out_max = 50000; | ||
132 | } else { | ||
133 | p1pll->pll_in_min = 40; | ||
134 | p1pll->pll_in_max = 500; | ||
135 | p1pll->pll_out_min = 12500; | ||
136 | p1pll->pll_out_max = 35000; | ||
137 | p2pll->pll_in_min = 40; | ||
138 | p2pll->pll_in_max = 500; | ||
139 | p2pll->pll_out_min = 12500; | ||
140 | p2pll->pll_out_max = 35000; | ||
141 | } | ||
142 | |||
143 | spll->reference_freq = mpll->reference_freq = p1pll->reference_freq; | ||
144 | spll->reference_div = mpll->reference_div = | ||
145 | RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & | ||
146 | RADEON_M_SPLL_REF_DIV_MASK; | ||
147 | |||
148 | val = of_get_property(dp, "ATY,SCLK", NULL); | ||
149 | if (val && *val) | ||
150 | rdev->clock.default_sclk = (*val) / 10; | ||
151 | else | ||
152 | rdev->clock.default_sclk = | ||
153 | radeon_legacy_get_engine_clock(rdev); | ||
154 | |||
155 | val = of_get_property(dp, "ATY,MCLK", NULL); | ||
156 | if (val && *val) | ||
157 | rdev->clock.default_mclk = (*val) / 10; | ||
158 | else | ||
159 | rdev->clock.default_mclk = | ||
160 | radeon_legacy_get_memory_clock(rdev); | ||
161 | |||
162 | DRM_INFO("Using device-tree clock info\n"); | ||
163 | |||
164 | return true; | ||
165 | } | ||
166 | #else | ||
167 | static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) | ||
168 | { | ||
169 | return false; | ||
170 | } | ||
171 | #endif /* CONFIG_OF */ | ||
172 | |||
94 | void radeon_get_clock_info(struct drm_device *dev) | 173 | void radeon_get_clock_info(struct drm_device *dev) |
95 | { | 174 | { |
96 | struct radeon_device *rdev = dev->dev_private; | 175 | struct radeon_device *rdev = dev->dev_private; |
@@ -105,6 +184,8 @@ void radeon_get_clock_info(struct drm_device *dev) | |||
105 | ret = radeon_atom_get_clock_info(dev); | 184 | ret = radeon_atom_get_clock_info(dev); |
106 | else | 185 | else |
107 | ret = radeon_combios_get_clock_info(dev); | 186 | ret = radeon_combios_get_clock_info(dev); |
187 | if (!ret) | ||
188 | ret = radeon_read_clocks_OF(dev); | ||
108 | 189 | ||
109 | if (ret) { | 190 | if (ret) { |
110 | if (p1pll->reference_div < 2) { | 191 | if (p1pll->reference_div < 2) { |
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 5e1474cde4b4..885dcfac1838 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c | |||
@@ -480,9 +480,66 @@ radeon_combios_get_hardcoded_edid(struct radeon_device *rdev) | |||
480 | } | 480 | } |
481 | 481 | ||
482 | static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rdev, | 482 | static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rdev, |
483 | int ddc_line) | 483 | enum radeon_combios_ddc ddc, |
484 | u32 clk_mask, | ||
485 | u32 data_mask) | ||
484 | { | 486 | { |
485 | struct radeon_i2c_bus_rec i2c; | 487 | struct radeon_i2c_bus_rec i2c; |
488 | int ddc_line = 0; | ||
489 | |||
490 | /* ddc id = mask reg | ||
491 | * DDC_NONE_DETECTED = none | ||
492 | * DDC_DVI = RADEON_GPIO_DVI_DDC | ||
493 | * DDC_VGA = RADEON_GPIO_VGA_DDC | ||
494 | * DDC_LCD = RADEON_GPIOPAD_MASK | ||
495 | * DDC_GPIO = RADEON_MDGPIO_MASK | ||
496 | * r1xx/r2xx | ||
497 | * DDC_MONID = RADEON_GPIO_MONID | ||
498 | * DDC_CRT2 = RADEON_GPIO_CRT2_DDC | ||
499 | * r3xx | ||
500 | * DDC_MONID = RADEON_GPIO_MONID | ||
501 | * DDC_CRT2 = RADEON_GPIO_DVI_DDC | ||
502 | * rs3xx/rs4xx | ||
503 | * DDC_MONID = RADEON_GPIOPAD_MASK | ||
504 | * DDC_CRT2 = RADEON_GPIO_MONID | ||
505 | */ | ||
506 | switch (ddc) { | ||
507 | case DDC_NONE_DETECTED: | ||
508 | default: | ||
509 | ddc_line = 0; | ||
510 | break; | ||
511 | case DDC_DVI: | ||
512 | ddc_line = RADEON_GPIO_DVI_DDC; | ||
513 | break; | ||
514 | case DDC_VGA: | ||
515 | ddc_line = RADEON_GPIO_VGA_DDC; | ||
516 | break; | ||
517 | case DDC_LCD: | ||
518 | ddc_line = RADEON_GPIOPAD_MASK; | ||
519 | break; | ||
520 | case DDC_GPIO: | ||
521 | ddc_line = RADEON_MDGPIO_MASK; | ||
522 | break; | ||
523 | case DDC_MONID: | ||
524 | if (rdev->family == CHIP_RS300 || | ||
525 | rdev->family == CHIP_RS400 || | ||
526 | rdev->family == CHIP_RS480) | ||
527 | ddc_line = RADEON_GPIOPAD_MASK; | ||
528 | else | ||
529 | ddc_line = RADEON_GPIO_MONID; | ||
530 | break; | ||
531 | case DDC_CRT2: | ||
532 | if (rdev->family == CHIP_RS300 || | ||
533 | rdev->family == CHIP_RS400 || | ||
534 | rdev->family == CHIP_RS480) | ||
535 | ddc_line = RADEON_GPIO_MONID; | ||
536 | else if (rdev->family >= CHIP_R300) { | ||
537 | ddc_line = RADEON_GPIO_DVI_DDC; | ||
538 | ddc = DDC_DVI; | ||
539 | } else | ||
540 | ddc_line = RADEON_GPIO_CRT2_DDC; | ||
541 | break; | ||
542 | } | ||
486 | 543 | ||
487 | if (ddc_line == RADEON_GPIOPAD_MASK) { | 544 | if (ddc_line == RADEON_GPIOPAD_MASK) { |
488 | i2c.mask_clk_reg = RADEON_GPIOPAD_MASK; | 545 | i2c.mask_clk_reg = RADEON_GPIOPAD_MASK; |
@@ -503,15 +560,6 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde | |||
503 | i2c.y_clk_reg = RADEON_MDGPIO_Y; | 560 | i2c.y_clk_reg = RADEON_MDGPIO_Y; |
504 | i2c.y_data_reg = RADEON_MDGPIO_Y; | 561 | i2c.y_data_reg = RADEON_MDGPIO_Y; |
505 | } else { | 562 | } else { |
506 | i2c.mask_clk_mask = RADEON_GPIO_EN_1; | ||
507 | i2c.mask_data_mask = RADEON_GPIO_EN_0; | ||
508 | i2c.a_clk_mask = RADEON_GPIO_A_1; | ||
509 | i2c.a_data_mask = RADEON_GPIO_A_0; | ||
510 | i2c.en_clk_mask = RADEON_GPIO_EN_1; | ||
511 | i2c.en_data_mask = RADEON_GPIO_EN_0; | ||
512 | i2c.y_clk_mask = RADEON_GPIO_Y_1; | ||
513 | i2c.y_data_mask = RADEON_GPIO_Y_0; | ||
514 | |||
515 | i2c.mask_clk_reg = ddc_line; | 563 | i2c.mask_clk_reg = ddc_line; |
516 | i2c.mask_data_reg = ddc_line; | 564 | i2c.mask_data_reg = ddc_line; |
517 | i2c.a_clk_reg = ddc_line; | 565 | i2c.a_clk_reg = ddc_line; |
@@ -522,6 +570,26 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde | |||
522 | i2c.y_data_reg = ddc_line; | 570 | i2c.y_data_reg = ddc_line; |
523 | } | 571 | } |
524 | 572 | ||
573 | if (clk_mask && data_mask) { | ||
574 | i2c.mask_clk_mask = clk_mask; | ||
575 | i2c.mask_data_mask = data_mask; | ||
576 | i2c.a_clk_mask = clk_mask; | ||
577 | i2c.a_data_mask = data_mask; | ||
578 | i2c.en_clk_mask = clk_mask; | ||
579 | i2c.en_data_mask = data_mask; | ||
580 | i2c.y_clk_mask = clk_mask; | ||
581 | i2c.y_data_mask = data_mask; | ||
582 | } else { | ||
583 | i2c.mask_clk_mask = RADEON_GPIO_EN_1; | ||
584 | i2c.mask_data_mask = RADEON_GPIO_EN_0; | ||
585 | i2c.a_clk_mask = RADEON_GPIO_A_1; | ||
586 | i2c.a_data_mask = RADEON_GPIO_A_0; | ||
587 | i2c.en_clk_mask = RADEON_GPIO_EN_1; | ||
588 | i2c.en_data_mask = RADEON_GPIO_EN_0; | ||
589 | i2c.y_clk_mask = RADEON_GPIO_Y_1; | ||
590 | i2c.y_data_mask = RADEON_GPIO_Y_0; | ||
591 | } | ||
592 | |||
525 | switch (rdev->family) { | 593 | switch (rdev->family) { |
526 | case CHIP_R100: | 594 | case CHIP_R100: |
527 | case CHIP_RV100: | 595 | case CHIP_RV100: |
@@ -599,7 +667,8 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde | |||
599 | break; | 667 | break; |
600 | } | 668 | } |
601 | i2c.mm_i2c = false; | 669 | i2c.mm_i2c = false; |
602 | i2c.i2c_id = 0; | 670 | |
671 | i2c.i2c_id = ddc; | ||
603 | i2c.hpd = RADEON_HPD_NONE; | 672 | i2c.hpd = RADEON_HPD_NONE; |
604 | 673 | ||
605 | if (ddc_line) | 674 | if (ddc_line) |
@@ -610,6 +679,62 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde | |||
610 | return i2c; | 679 | return i2c; |
611 | } | 680 | } |
612 | 681 | ||
682 | void radeon_combios_i2c_init(struct radeon_device *rdev) | ||
683 | { | ||
684 | struct drm_device *dev = rdev->ddev; | ||
685 | struct radeon_i2c_bus_rec i2c; | ||
686 | |||
687 | |||
688 | i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); | ||
689 | rdev->i2c_bus[0] = radeon_i2c_create(dev, &i2c, "DVI_DDC"); | ||
690 | |||
691 | i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); | ||
692 | rdev->i2c_bus[1] = radeon_i2c_create(dev, &i2c, "VGA_DDC"); | ||
693 | |||
694 | i2c.valid = true; | ||
695 | i2c.hw_capable = true; | ||
696 | i2c.mm_i2c = true; | ||
697 | i2c.i2c_id = 0xa0; | ||
698 | rdev->i2c_bus[2] = radeon_i2c_create(dev, &i2c, "MM_I2C"); | ||
699 | |||
700 | if (rdev->family == CHIP_RS300 || | ||
701 | rdev->family == CHIP_RS400 || | ||
702 | rdev->family == CHIP_RS480) { | ||
703 | u16 offset; | ||
704 | u8 id, blocks, clk, data; | ||
705 | int i; | ||
706 | |||
707 | i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); | ||
708 | rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID"); | ||
709 | |||
710 | offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE); | ||
711 | if (offset) { | ||
712 | blocks = RBIOS8(offset + 2); | ||
713 | for (i = 0; i < blocks; i++) { | ||
714 | id = RBIOS8(offset + 3 + (i * 5) + 0); | ||
715 | if (id == 136) { | ||
716 | clk = RBIOS8(offset + 3 + (i * 5) + 3); | ||
717 | data = RBIOS8(offset + 3 + (i * 5) + 4); | ||
718 | i2c = combios_setup_i2c_bus(rdev, DDC_MONID, | ||
719 | clk, data); | ||
720 | rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "GPIOPAD_MASK"); | ||
721 | break; | ||
722 | } | ||
723 | } | ||
724 | } | ||
725 | |||
726 | } else if (rdev->family >= CHIP_R300) { | ||
727 | i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); | ||
728 | rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID"); | ||
729 | } else { | ||
730 | i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); | ||
731 | rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID"); | ||
732 | |||
733 | i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); | ||
734 | rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "CRT2_DDC"); | ||
735 | } | ||
736 | } | ||
737 | |||
613 | bool radeon_combios_get_clock_info(struct drm_device *dev) | 738 | bool radeon_combios_get_clock_info(struct drm_device *dev) |
614 | { | 739 | { |
615 | struct radeon_device *rdev = dev->dev_private; | 740 | struct radeon_device *rdev = dev->dev_private; |
@@ -1247,8 +1372,8 @@ bool radeon_legacy_get_ext_tmds_info_from_table(struct radeon_encoder *encoder, | |||
1247 | struct radeon_i2c_bus_rec i2c_bus; | 1372 | struct radeon_i2c_bus_rec i2c_bus; |
1248 | 1373 | ||
1249 | /* default for macs */ | 1374 | /* default for macs */ |
1250 | i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); | 1375 | i2c_bus = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); |
1251 | tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); | 1376 | tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); |
1252 | 1377 | ||
1253 | /* XXX some macs have duallink chips */ | 1378 | /* XXX some macs have duallink chips */ |
1254 | switch (rdev->mode_info.connector_table) { | 1379 | switch (rdev->mode_info.connector_table) { |
@@ -1269,47 +1394,16 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder | |||
1269 | struct drm_device *dev = encoder->base.dev; | 1394 | struct drm_device *dev = encoder->base.dev; |
1270 | struct radeon_device *rdev = dev->dev_private; | 1395 | struct radeon_device *rdev = dev->dev_private; |
1271 | uint16_t offset; | 1396 | uint16_t offset; |
1272 | uint8_t ver, id, blocks, clk, data; | 1397 | uint8_t ver; |
1273 | int i; | ||
1274 | enum radeon_combios_ddc gpio; | 1398 | enum radeon_combios_ddc gpio; |
1275 | struct radeon_i2c_bus_rec i2c_bus; | 1399 | struct radeon_i2c_bus_rec i2c_bus; |
1276 | 1400 | ||
1277 | tmds->i2c_bus = NULL; | 1401 | tmds->i2c_bus = NULL; |
1278 | if (rdev->flags & RADEON_IS_IGP) { | 1402 | if (rdev->flags & RADEON_IS_IGP) { |
1279 | offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE); | 1403 | i2c_bus = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); |
1280 | if (offset) { | 1404 | tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); |
1281 | ver = RBIOS8(offset); | 1405 | tmds->dvo_chip = DVO_SIL164; |
1282 | DRM_INFO("GPIO Table revision: %d\n", ver); | 1406 | tmds->slave_addr = 0x70 >> 1; /* 7 bit addressing */ |
1283 | blocks = RBIOS8(offset + 2); | ||
1284 | for (i = 0; i < blocks; i++) { | ||
1285 | id = RBIOS8(offset + 3 + (i * 5) + 0); | ||
1286 | if (id == 136) { | ||
1287 | clk = RBIOS8(offset + 3 + (i * 5) + 3); | ||
1288 | data = RBIOS8(offset + 3 + (i * 5) + 4); | ||
1289 | i2c_bus.valid = true; | ||
1290 | i2c_bus.mask_clk_mask = (1 << clk); | ||
1291 | i2c_bus.mask_data_mask = (1 << data); | ||
1292 | i2c_bus.a_clk_mask = (1 << clk); | ||
1293 | i2c_bus.a_data_mask = (1 << data); | ||
1294 | i2c_bus.en_clk_mask = (1 << clk); | ||
1295 | i2c_bus.en_data_mask = (1 << data); | ||
1296 | i2c_bus.y_clk_mask = (1 << clk); | ||
1297 | i2c_bus.y_data_mask = (1 << data); | ||
1298 | i2c_bus.mask_clk_reg = RADEON_GPIOPAD_MASK; | ||
1299 | i2c_bus.mask_data_reg = RADEON_GPIOPAD_MASK; | ||
1300 | i2c_bus.a_clk_reg = RADEON_GPIOPAD_A; | ||
1301 | i2c_bus.a_data_reg = RADEON_GPIOPAD_A; | ||
1302 | i2c_bus.en_clk_reg = RADEON_GPIOPAD_EN; | ||
1303 | i2c_bus.en_data_reg = RADEON_GPIOPAD_EN; | ||
1304 | i2c_bus.y_clk_reg = RADEON_GPIOPAD_Y; | ||
1305 | i2c_bus.y_data_reg = RADEON_GPIOPAD_Y; | ||
1306 | tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); | ||
1307 | tmds->dvo_chip = DVO_SIL164; | ||
1308 | tmds->slave_addr = 0x70 >> 1; /* 7 bit addressing */ | ||
1309 | break; | ||
1310 | } | ||
1311 | } | ||
1312 | } | ||
1313 | } else { | 1407 | } else { |
1314 | offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE); | 1408 | offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE); |
1315 | if (offset) { | 1409 | if (offset) { |
@@ -1318,37 +1412,15 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder | |||
1318 | tmds->slave_addr = RBIOS8(offset + 4 + 2); | 1412 | tmds->slave_addr = RBIOS8(offset + 4 + 2); |
1319 | tmds->slave_addr >>= 1; /* 7 bit addressing */ | 1413 | tmds->slave_addr >>= 1; /* 7 bit addressing */ |
1320 | gpio = RBIOS8(offset + 4 + 3); | 1414 | gpio = RBIOS8(offset + 4 + 3); |
1321 | switch (gpio) { | 1415 | if (gpio == DDC_LCD) { |
1322 | case DDC_MONID: | 1416 | /* MM i2c */ |
1323 | i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); | ||
1324 | tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); | ||
1325 | break; | ||
1326 | case DDC_DVI: | ||
1327 | i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | ||
1328 | tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); | ||
1329 | break; | ||
1330 | case DDC_VGA: | ||
1331 | i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | ||
1332 | tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); | ||
1333 | break; | ||
1334 | case DDC_CRT2: | ||
1335 | /* R3xx+ chips don't have GPIO_CRT2_DDC gpio pad */ | ||
1336 | if (rdev->family >= CHIP_R300) | ||
1337 | i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); | ||
1338 | else | ||
1339 | i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); | ||
1340 | tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); | ||
1341 | break; | ||
1342 | case DDC_LCD: /* MM i2c */ | ||
1343 | i2c_bus.valid = true; | 1417 | i2c_bus.valid = true; |
1344 | i2c_bus.hw_capable = true; | 1418 | i2c_bus.hw_capable = true; |
1345 | i2c_bus.mm_i2c = true; | 1419 | i2c_bus.mm_i2c = true; |
1346 | tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); | 1420 | i2c_bus.i2c_id = 0xa0; |
1347 | break; | 1421 | } else |
1348 | default: | 1422 | i2c_bus = combios_setup_i2c_bus(rdev, gpio, 0, 0); |
1349 | DRM_ERROR("Unsupported gpio %d\n", gpio); | 1423 | tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); |
1350 | break; | ||
1351 | } | ||
1352 | } | 1424 | } |
1353 | } | 1425 | } |
1354 | 1426 | ||
@@ -1430,7 +1502,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1430 | /* these are the most common settings */ | 1502 | /* these are the most common settings */ |
1431 | if (rdev->flags & RADEON_SINGLE_CRTC) { | 1503 | if (rdev->flags & RADEON_SINGLE_CRTC) { |
1432 | /* VGA - primary dac */ | 1504 | /* VGA - primary dac */ |
1433 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 1505 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
1434 | hpd.hpd = RADEON_HPD_NONE; | 1506 | hpd.hpd = RADEON_HPD_NONE; |
1435 | radeon_add_legacy_encoder(dev, | 1507 | radeon_add_legacy_encoder(dev, |
1436 | radeon_get_encoder_id(dev, | 1508 | radeon_get_encoder_id(dev, |
@@ -1445,7 +1517,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1445 | &hpd); | 1517 | &hpd); |
1446 | } else if (rdev->flags & RADEON_IS_MOBILITY) { | 1518 | } else if (rdev->flags & RADEON_IS_MOBILITY) { |
1447 | /* LVDS */ | 1519 | /* LVDS */ |
1448 | ddc_i2c = combios_setup_i2c_bus(rdev, 0); | 1520 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_NONE_DETECTED, 0, 0); |
1449 | hpd.hpd = RADEON_HPD_NONE; | 1521 | hpd.hpd = RADEON_HPD_NONE; |
1450 | radeon_add_legacy_encoder(dev, | 1522 | radeon_add_legacy_encoder(dev, |
1451 | radeon_get_encoder_id(dev, | 1523 | radeon_get_encoder_id(dev, |
@@ -1460,7 +1532,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1460 | &hpd); | 1532 | &hpd); |
1461 | 1533 | ||
1462 | /* VGA - primary dac */ | 1534 | /* VGA - primary dac */ |
1463 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 1535 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
1464 | hpd.hpd = RADEON_HPD_NONE; | 1536 | hpd.hpd = RADEON_HPD_NONE; |
1465 | radeon_add_legacy_encoder(dev, | 1537 | radeon_add_legacy_encoder(dev, |
1466 | radeon_get_encoder_id(dev, | 1538 | radeon_get_encoder_id(dev, |
@@ -1475,7 +1547,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1475 | &hpd); | 1547 | &hpd); |
1476 | } else { | 1548 | } else { |
1477 | /* DVI-I - tv dac, int tmds */ | 1549 | /* DVI-I - tv dac, int tmds */ |
1478 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | 1550 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); |
1479 | hpd.hpd = RADEON_HPD_1; | 1551 | hpd.hpd = RADEON_HPD_1; |
1480 | radeon_add_legacy_encoder(dev, | 1552 | radeon_add_legacy_encoder(dev, |
1481 | radeon_get_encoder_id(dev, | 1553 | radeon_get_encoder_id(dev, |
@@ -1496,7 +1568,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1496 | &hpd); | 1568 | &hpd); |
1497 | 1569 | ||
1498 | /* VGA - primary dac */ | 1570 | /* VGA - primary dac */ |
1499 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 1571 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
1500 | hpd.hpd = RADEON_HPD_NONE; | 1572 | hpd.hpd = RADEON_HPD_NONE; |
1501 | radeon_add_legacy_encoder(dev, | 1573 | radeon_add_legacy_encoder(dev, |
1502 | radeon_get_encoder_id(dev, | 1574 | radeon_get_encoder_id(dev, |
@@ -1532,7 +1604,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1532 | DRM_INFO("Connector Table: %d (ibook)\n", | 1604 | DRM_INFO("Connector Table: %d (ibook)\n", |
1533 | rdev->mode_info.connector_table); | 1605 | rdev->mode_info.connector_table); |
1534 | /* LVDS */ | 1606 | /* LVDS */ |
1535 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | 1607 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); |
1536 | hpd.hpd = RADEON_HPD_NONE; | 1608 | hpd.hpd = RADEON_HPD_NONE; |
1537 | radeon_add_legacy_encoder(dev, | 1609 | radeon_add_legacy_encoder(dev, |
1538 | radeon_get_encoder_id(dev, | 1610 | radeon_get_encoder_id(dev, |
@@ -1544,7 +1616,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1544 | CONNECTOR_OBJECT_ID_LVDS, | 1616 | CONNECTOR_OBJECT_ID_LVDS, |
1545 | &hpd); | 1617 | &hpd); |
1546 | /* VGA - TV DAC */ | 1618 | /* VGA - TV DAC */ |
1547 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 1619 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
1548 | hpd.hpd = RADEON_HPD_NONE; | 1620 | hpd.hpd = RADEON_HPD_NONE; |
1549 | radeon_add_legacy_encoder(dev, | 1621 | radeon_add_legacy_encoder(dev, |
1550 | radeon_get_encoder_id(dev, | 1622 | radeon_get_encoder_id(dev, |
@@ -1573,7 +1645,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1573 | DRM_INFO("Connector Table: %d (powerbook external tmds)\n", | 1645 | DRM_INFO("Connector Table: %d (powerbook external tmds)\n", |
1574 | rdev->mode_info.connector_table); | 1646 | rdev->mode_info.connector_table); |
1575 | /* LVDS */ | 1647 | /* LVDS */ |
1576 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | 1648 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); |
1577 | hpd.hpd = RADEON_HPD_NONE; | 1649 | hpd.hpd = RADEON_HPD_NONE; |
1578 | radeon_add_legacy_encoder(dev, | 1650 | radeon_add_legacy_encoder(dev, |
1579 | radeon_get_encoder_id(dev, | 1651 | radeon_get_encoder_id(dev, |
@@ -1585,7 +1657,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1585 | CONNECTOR_OBJECT_ID_LVDS, | 1657 | CONNECTOR_OBJECT_ID_LVDS, |
1586 | &hpd); | 1658 | &hpd); |
1587 | /* DVI-I - primary dac, ext tmds */ | 1659 | /* DVI-I - primary dac, ext tmds */ |
1588 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 1660 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
1589 | hpd.hpd = RADEON_HPD_2; /* ??? */ | 1661 | hpd.hpd = RADEON_HPD_2; /* ??? */ |
1590 | radeon_add_legacy_encoder(dev, | 1662 | radeon_add_legacy_encoder(dev, |
1591 | radeon_get_encoder_id(dev, | 1663 | radeon_get_encoder_id(dev, |
@@ -1622,7 +1694,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1622 | DRM_INFO("Connector Table: %d (powerbook internal tmds)\n", | 1694 | DRM_INFO("Connector Table: %d (powerbook internal tmds)\n", |
1623 | rdev->mode_info.connector_table); | 1695 | rdev->mode_info.connector_table); |
1624 | /* LVDS */ | 1696 | /* LVDS */ |
1625 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | 1697 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); |
1626 | hpd.hpd = RADEON_HPD_NONE; | 1698 | hpd.hpd = RADEON_HPD_NONE; |
1627 | radeon_add_legacy_encoder(dev, | 1699 | radeon_add_legacy_encoder(dev, |
1628 | radeon_get_encoder_id(dev, | 1700 | radeon_get_encoder_id(dev, |
@@ -1634,7 +1706,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1634 | CONNECTOR_OBJECT_ID_LVDS, | 1706 | CONNECTOR_OBJECT_ID_LVDS, |
1635 | &hpd); | 1707 | &hpd); |
1636 | /* DVI-I - primary dac, int tmds */ | 1708 | /* DVI-I - primary dac, int tmds */ |
1637 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 1709 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
1638 | hpd.hpd = RADEON_HPD_1; /* ??? */ | 1710 | hpd.hpd = RADEON_HPD_1; /* ??? */ |
1639 | radeon_add_legacy_encoder(dev, | 1711 | radeon_add_legacy_encoder(dev, |
1640 | radeon_get_encoder_id(dev, | 1712 | radeon_get_encoder_id(dev, |
@@ -1670,7 +1742,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1670 | DRM_INFO("Connector Table: %d (powerbook vga)\n", | 1742 | DRM_INFO("Connector Table: %d (powerbook vga)\n", |
1671 | rdev->mode_info.connector_table); | 1743 | rdev->mode_info.connector_table); |
1672 | /* LVDS */ | 1744 | /* LVDS */ |
1673 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | 1745 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); |
1674 | hpd.hpd = RADEON_HPD_NONE; | 1746 | hpd.hpd = RADEON_HPD_NONE; |
1675 | radeon_add_legacy_encoder(dev, | 1747 | radeon_add_legacy_encoder(dev, |
1676 | radeon_get_encoder_id(dev, | 1748 | radeon_get_encoder_id(dev, |
@@ -1682,7 +1754,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1682 | CONNECTOR_OBJECT_ID_LVDS, | 1754 | CONNECTOR_OBJECT_ID_LVDS, |
1683 | &hpd); | 1755 | &hpd); |
1684 | /* VGA - primary dac */ | 1756 | /* VGA - primary dac */ |
1685 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 1757 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
1686 | hpd.hpd = RADEON_HPD_NONE; | 1758 | hpd.hpd = RADEON_HPD_NONE; |
1687 | radeon_add_legacy_encoder(dev, | 1759 | radeon_add_legacy_encoder(dev, |
1688 | radeon_get_encoder_id(dev, | 1760 | radeon_get_encoder_id(dev, |
@@ -1711,7 +1783,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1711 | DRM_INFO("Connector Table: %d (mini external tmds)\n", | 1783 | DRM_INFO("Connector Table: %d (mini external tmds)\n", |
1712 | rdev->mode_info.connector_table); | 1784 | rdev->mode_info.connector_table); |
1713 | /* DVI-I - tv dac, ext tmds */ | 1785 | /* DVI-I - tv dac, ext tmds */ |
1714 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); | 1786 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); |
1715 | hpd.hpd = RADEON_HPD_2; /* ??? */ | 1787 | hpd.hpd = RADEON_HPD_2; /* ??? */ |
1716 | radeon_add_legacy_encoder(dev, | 1788 | radeon_add_legacy_encoder(dev, |
1717 | radeon_get_encoder_id(dev, | 1789 | radeon_get_encoder_id(dev, |
@@ -1748,7 +1820,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1748 | DRM_INFO("Connector Table: %d (mini internal tmds)\n", | 1820 | DRM_INFO("Connector Table: %d (mini internal tmds)\n", |
1749 | rdev->mode_info.connector_table); | 1821 | rdev->mode_info.connector_table); |
1750 | /* DVI-I - tv dac, int tmds */ | 1822 | /* DVI-I - tv dac, int tmds */ |
1751 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); | 1823 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); |
1752 | hpd.hpd = RADEON_HPD_1; /* ??? */ | 1824 | hpd.hpd = RADEON_HPD_1; /* ??? */ |
1753 | radeon_add_legacy_encoder(dev, | 1825 | radeon_add_legacy_encoder(dev, |
1754 | radeon_get_encoder_id(dev, | 1826 | radeon_get_encoder_id(dev, |
@@ -1784,7 +1856,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1784 | DRM_INFO("Connector Table: %d (imac g5 isight)\n", | 1856 | DRM_INFO("Connector Table: %d (imac g5 isight)\n", |
1785 | rdev->mode_info.connector_table); | 1857 | rdev->mode_info.connector_table); |
1786 | /* DVI-D - int tmds */ | 1858 | /* DVI-D - int tmds */ |
1787 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); | 1859 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); |
1788 | hpd.hpd = RADEON_HPD_1; /* ??? */ | 1860 | hpd.hpd = RADEON_HPD_1; /* ??? */ |
1789 | radeon_add_legacy_encoder(dev, | 1861 | radeon_add_legacy_encoder(dev, |
1790 | radeon_get_encoder_id(dev, | 1862 | radeon_get_encoder_id(dev, |
@@ -1796,7 +1868,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1796 | CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D, | 1868 | CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D, |
1797 | &hpd); | 1869 | &hpd); |
1798 | /* VGA - tv dac */ | 1870 | /* VGA - tv dac */ |
1799 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | 1871 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); |
1800 | hpd.hpd = RADEON_HPD_NONE; | 1872 | hpd.hpd = RADEON_HPD_NONE; |
1801 | radeon_add_legacy_encoder(dev, | 1873 | radeon_add_legacy_encoder(dev, |
1802 | radeon_get_encoder_id(dev, | 1874 | radeon_get_encoder_id(dev, |
@@ -1825,7 +1897,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1825 | DRM_INFO("Connector Table: %d (emac)\n", | 1897 | DRM_INFO("Connector Table: %d (emac)\n", |
1826 | rdev->mode_info.connector_table); | 1898 | rdev->mode_info.connector_table); |
1827 | /* VGA - primary dac */ | 1899 | /* VGA - primary dac */ |
1828 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 1900 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
1829 | hpd.hpd = RADEON_HPD_NONE; | 1901 | hpd.hpd = RADEON_HPD_NONE; |
1830 | radeon_add_legacy_encoder(dev, | 1902 | radeon_add_legacy_encoder(dev, |
1831 | radeon_get_encoder_id(dev, | 1903 | radeon_get_encoder_id(dev, |
@@ -1837,7 +1909,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1837 | CONNECTOR_OBJECT_ID_VGA, | 1909 | CONNECTOR_OBJECT_ID_VGA, |
1838 | &hpd); | 1910 | &hpd); |
1839 | /* VGA - tv dac */ | 1911 | /* VGA - tv dac */ |
1840 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); | 1912 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); |
1841 | hpd.hpd = RADEON_HPD_NONE; | 1913 | hpd.hpd = RADEON_HPD_NONE; |
1842 | radeon_add_legacy_encoder(dev, | 1914 | radeon_add_legacy_encoder(dev, |
1843 | radeon_get_encoder_id(dev, | 1915 | radeon_get_encoder_id(dev, |
@@ -1866,7 +1938,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1866 | DRM_INFO("Connector Table: %d (rn50-power)\n", | 1938 | DRM_INFO("Connector Table: %d (rn50-power)\n", |
1867 | rdev->mode_info.connector_table); | 1939 | rdev->mode_info.connector_table); |
1868 | /* VGA - primary dac */ | 1940 | /* VGA - primary dac */ |
1869 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 1941 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
1870 | hpd.hpd = RADEON_HPD_NONE; | 1942 | hpd.hpd = RADEON_HPD_NONE; |
1871 | radeon_add_legacy_encoder(dev, | 1943 | radeon_add_legacy_encoder(dev, |
1872 | radeon_get_encoder_id(dev, | 1944 | radeon_get_encoder_id(dev, |
@@ -1877,7 +1949,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1877 | DRM_MODE_CONNECTOR_VGA, &ddc_i2c, | 1949 | DRM_MODE_CONNECTOR_VGA, &ddc_i2c, |
1878 | CONNECTOR_OBJECT_ID_VGA, | 1950 | CONNECTOR_OBJECT_ID_VGA, |
1879 | &hpd); | 1951 | &hpd); |
1880 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); | 1952 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); |
1881 | hpd.hpd = RADEON_HPD_NONE; | 1953 | hpd.hpd = RADEON_HPD_NONE; |
1882 | radeon_add_legacy_encoder(dev, | 1954 | radeon_add_legacy_encoder(dev, |
1883 | radeon_get_encoder_id(dev, | 1955 | radeon_get_encoder_id(dev, |
@@ -1907,31 +1979,6 @@ static bool radeon_apply_legacy_quirks(struct drm_device *dev, | |||
1907 | struct radeon_i2c_bus_rec *ddc_i2c, | 1979 | struct radeon_i2c_bus_rec *ddc_i2c, |
1908 | struct radeon_hpd *hpd) | 1980 | struct radeon_hpd *hpd) |
1909 | { | 1981 | { |
1910 | struct radeon_device *rdev = dev->dev_private; | ||
1911 | |||
1912 | /* XPRESS DDC quirks */ | ||
1913 | if ((rdev->family == CHIP_RS400 || | ||
1914 | rdev->family == CHIP_RS480) && | ||
1915 | ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC) | ||
1916 | *ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); | ||
1917 | else if ((rdev->family == CHIP_RS400 || | ||
1918 | rdev->family == CHIP_RS480) && | ||
1919 | ddc_i2c->mask_clk_reg == RADEON_GPIO_MONID) { | ||
1920 | *ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIOPAD_MASK); | ||
1921 | ddc_i2c->mask_clk_mask = (0x20 << 8); | ||
1922 | ddc_i2c->mask_data_mask = 0x80; | ||
1923 | ddc_i2c->a_clk_mask = (0x20 << 8); | ||
1924 | ddc_i2c->a_data_mask = 0x80; | ||
1925 | ddc_i2c->en_clk_mask = (0x20 << 8); | ||
1926 | ddc_i2c->en_data_mask = 0x80; | ||
1927 | ddc_i2c->y_clk_mask = (0x20 << 8); | ||
1928 | ddc_i2c->y_data_mask = 0x80; | ||
1929 | } | ||
1930 | |||
1931 | /* R3xx+ chips don't have GPIO_CRT2_DDC gpio pad */ | ||
1932 | if ((rdev->family >= CHIP_R300) && | ||
1933 | ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC) | ||
1934 | *ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | ||
1935 | 1982 | ||
1936 | /* Certain IBM chipset RN50s have a BIOS reporting two VGAs, | 1983 | /* Certain IBM chipset RN50s have a BIOS reporting two VGAs, |
1937 | one with VGA DDC and one with CRT2 DDC. - kill the CRT2 DDC one */ | 1984 | one with VGA DDC and one with CRT2 DDC. - kill the CRT2 DDC one */ |
@@ -2035,27 +2082,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) | |||
2035 | connector = (tmp >> 12) & 0xf; | 2082 | connector = (tmp >> 12) & 0xf; |
2036 | 2083 | ||
2037 | ddc_type = (tmp >> 8) & 0xf; | 2084 | ddc_type = (tmp >> 8) & 0xf; |
2038 | switch (ddc_type) { | 2085 | ddc_i2c = combios_setup_i2c_bus(rdev, ddc_type, 0, 0); |
2039 | case DDC_MONID: | ||
2040 | ddc_i2c = | ||
2041 | combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); | ||
2042 | break; | ||
2043 | case DDC_DVI: | ||
2044 | ddc_i2c = | ||
2045 | combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | ||
2046 | break; | ||
2047 | case DDC_VGA: | ||
2048 | ddc_i2c = | ||
2049 | combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | ||
2050 | break; | ||
2051 | case DDC_CRT2: | ||
2052 | ddc_i2c = | ||
2053 | combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); | ||
2054 | break; | ||
2055 | default: | ||
2056 | ddc_i2c.valid = false; | ||
2057 | break; | ||
2058 | } | ||
2059 | 2086 | ||
2060 | switch (connector) { | 2087 | switch (connector) { |
2061 | case CONNECTOR_PROPRIETARY_LEGACY: | 2088 | case CONNECTOR_PROPRIETARY_LEGACY: |
@@ -2225,7 +2252,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) | |||
2225 | 0), | 2252 | 0), |
2226 | ATOM_DEVICE_DFP1_SUPPORT); | 2253 | ATOM_DEVICE_DFP1_SUPPORT); |
2227 | 2254 | ||
2228 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | 2255 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); |
2229 | hpd.hpd = RADEON_HPD_1; | 2256 | hpd.hpd = RADEON_HPD_1; |
2230 | radeon_add_legacy_connector(dev, | 2257 | radeon_add_legacy_connector(dev, |
2231 | 0, | 2258 | 0, |
@@ -2245,7 +2272,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) | |||
2245 | ATOM_DEVICE_CRT1_SUPPORT, | 2272 | ATOM_DEVICE_CRT1_SUPPORT, |
2246 | 1), | 2273 | 1), |
2247 | ATOM_DEVICE_CRT1_SUPPORT); | 2274 | ATOM_DEVICE_CRT1_SUPPORT); |
2248 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 2275 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
2249 | hpd.hpd = RADEON_HPD_NONE; | 2276 | hpd.hpd = RADEON_HPD_NONE; |
2250 | radeon_add_legacy_connector(dev, | 2277 | radeon_add_legacy_connector(dev, |
2251 | 0, | 2278 | 0, |
@@ -2278,70 +2305,25 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) | |||
2278 | if (lcd_ddc_info) { | 2305 | if (lcd_ddc_info) { |
2279 | ddc_type = RBIOS8(lcd_ddc_info + 2); | 2306 | ddc_type = RBIOS8(lcd_ddc_info + 2); |
2280 | switch (ddc_type) { | 2307 | switch (ddc_type) { |
2281 | case DDC_MONID: | ||
2282 | ddc_i2c = | ||
2283 | combios_setup_i2c_bus | ||
2284 | (rdev, RADEON_GPIO_MONID); | ||
2285 | break; | ||
2286 | case DDC_DVI: | ||
2287 | ddc_i2c = | ||
2288 | combios_setup_i2c_bus | ||
2289 | (rdev, RADEON_GPIO_DVI_DDC); | ||
2290 | break; | ||
2291 | case DDC_VGA: | ||
2292 | ddc_i2c = | ||
2293 | combios_setup_i2c_bus | ||
2294 | (rdev, RADEON_GPIO_VGA_DDC); | ||
2295 | break; | ||
2296 | case DDC_CRT2: | ||
2297 | ddc_i2c = | ||
2298 | combios_setup_i2c_bus | ||
2299 | (rdev, RADEON_GPIO_CRT2_DDC); | ||
2300 | break; | ||
2301 | case DDC_LCD: | 2308 | case DDC_LCD: |
2302 | ddc_i2c = | 2309 | ddc_i2c = |
2303 | combios_setup_i2c_bus | 2310 | combios_setup_i2c_bus(rdev, |
2304 | (rdev, RADEON_GPIOPAD_MASK); | 2311 | DDC_LCD, |
2305 | ddc_i2c.mask_clk_mask = | 2312 | RBIOS32(lcd_ddc_info + 3), |
2306 | RBIOS32(lcd_ddc_info + 3); | 2313 | RBIOS32(lcd_ddc_info + 7)); |
2307 | ddc_i2c.mask_data_mask = | 2314 | radeon_i2c_add(rdev, &ddc_i2c, "LCD"); |
2308 | RBIOS32(lcd_ddc_info + 7); | ||
2309 | ddc_i2c.a_clk_mask = | ||
2310 | RBIOS32(lcd_ddc_info + 3); | ||
2311 | ddc_i2c.a_data_mask = | ||
2312 | RBIOS32(lcd_ddc_info + 7); | ||
2313 | ddc_i2c.en_clk_mask = | ||
2314 | RBIOS32(lcd_ddc_info + 3); | ||
2315 | ddc_i2c.en_data_mask = | ||
2316 | RBIOS32(lcd_ddc_info + 7); | ||
2317 | ddc_i2c.y_clk_mask = | ||
2318 | RBIOS32(lcd_ddc_info + 3); | ||
2319 | ddc_i2c.y_data_mask = | ||
2320 | RBIOS32(lcd_ddc_info + 7); | ||
2321 | break; | 2315 | break; |
2322 | case DDC_GPIO: | 2316 | case DDC_GPIO: |
2323 | ddc_i2c = | 2317 | ddc_i2c = |
2324 | combios_setup_i2c_bus | 2318 | combios_setup_i2c_bus(rdev, |
2325 | (rdev, RADEON_MDGPIO_MASK); | 2319 | DDC_GPIO, |
2326 | ddc_i2c.mask_clk_mask = | 2320 | RBIOS32(lcd_ddc_info + 3), |
2327 | RBIOS32(lcd_ddc_info + 3); | 2321 | RBIOS32(lcd_ddc_info + 7)); |
2328 | ddc_i2c.mask_data_mask = | 2322 | radeon_i2c_add(rdev, &ddc_i2c, "LCD"); |
2329 | RBIOS32(lcd_ddc_info + 7); | ||
2330 | ddc_i2c.a_clk_mask = | ||
2331 | RBIOS32(lcd_ddc_info + 3); | ||
2332 | ddc_i2c.a_data_mask = | ||
2333 | RBIOS32(lcd_ddc_info + 7); | ||
2334 | ddc_i2c.en_clk_mask = | ||
2335 | RBIOS32(lcd_ddc_info + 3); | ||
2336 | ddc_i2c.en_data_mask = | ||
2337 | RBIOS32(lcd_ddc_info + 7); | ||
2338 | ddc_i2c.y_clk_mask = | ||
2339 | RBIOS32(lcd_ddc_info + 3); | ||
2340 | ddc_i2c.y_data_mask = | ||
2341 | RBIOS32(lcd_ddc_info + 7); | ||
2342 | break; | 2323 | break; |
2343 | default: | 2324 | default: |
2344 | ddc_i2c.valid = false; | 2325 | ddc_i2c = |
2326 | combios_setup_i2c_bus(rdev, ddc_type, 0, 0); | ||
2345 | break; | 2327 | break; |
2346 | } | 2328 | } |
2347 | DRM_DEBUG_KMS("LCD DDC Info Table found!\n"); | 2329 | DRM_DEBUG_KMS("LCD DDC Info Table found!\n"); |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 2395c8600cf4..47c4b276d30c 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
@@ -518,8 +518,6 @@ static void radeon_connector_destroy(struct drm_connector *connector) | |||
518 | { | 518 | { |
519 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 519 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
520 | 520 | ||
521 | if (radeon_connector->ddc_bus) | ||
522 | radeon_i2c_destroy(radeon_connector->ddc_bus); | ||
523 | if (radeon_connector->edid) | 521 | if (radeon_connector->edid) |
524 | kfree(radeon_connector->edid); | 522 | kfree(radeon_connector->edid); |
525 | kfree(radeon_connector->con_priv); | 523 | kfree(radeon_connector->con_priv); |
@@ -955,8 +953,6 @@ static void radeon_dp_connector_destroy(struct drm_connector *connector) | |||
955 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 953 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
956 | struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; | 954 | struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; |
957 | 955 | ||
958 | if (radeon_connector->ddc_bus) | ||
959 | radeon_i2c_destroy(radeon_connector->ddc_bus); | ||
960 | if (radeon_connector->edid) | 956 | if (radeon_connector->edid) |
961 | kfree(radeon_connector->edid); | 957 | kfree(radeon_connector->edid); |
962 | if (radeon_dig_connector->dp_i2c_bus) | 958 | if (radeon_dig_connector->dp_i2c_bus) |
@@ -1044,7 +1040,8 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1044 | bool linkb, | 1040 | bool linkb, |
1045 | uint32_t igp_lane_info, | 1041 | uint32_t igp_lane_info, |
1046 | uint16_t connector_object_id, | 1042 | uint16_t connector_object_id, |
1047 | struct radeon_hpd *hpd) | 1043 | struct radeon_hpd *hpd, |
1044 | struct radeon_router *router) | ||
1048 | { | 1045 | { |
1049 | struct radeon_device *rdev = dev->dev_private; | 1046 | struct radeon_device *rdev = dev->dev_private; |
1050 | struct drm_connector *connector; | 1047 | struct drm_connector *connector; |
@@ -1069,6 +1066,11 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1069 | radeon_connector->shared_ddc = true; | 1066 | radeon_connector->shared_ddc = true; |
1070 | shared_ddc = true; | 1067 | shared_ddc = true; |
1071 | } | 1068 | } |
1069 | if (radeon_connector->router_bus && router->valid && | ||
1070 | (radeon_connector->router.router_id == router->router_id)) { | ||
1071 | radeon_connector->shared_ddc = false; | ||
1072 | shared_ddc = false; | ||
1073 | } | ||
1072 | } | 1074 | } |
1073 | } | 1075 | } |
1074 | 1076 | ||
@@ -1083,12 +1085,18 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1083 | radeon_connector->shared_ddc = shared_ddc; | 1085 | radeon_connector->shared_ddc = shared_ddc; |
1084 | radeon_connector->connector_object_id = connector_object_id; | 1086 | radeon_connector->connector_object_id = connector_object_id; |
1085 | radeon_connector->hpd = *hpd; | 1087 | radeon_connector->hpd = *hpd; |
1088 | radeon_connector->router = *router; | ||
1089 | if (router->valid) { | ||
1090 | radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info); | ||
1091 | if (!radeon_connector->router_bus) | ||
1092 | goto failed; | ||
1093 | } | ||
1086 | switch (connector_type) { | 1094 | switch (connector_type) { |
1087 | case DRM_MODE_CONNECTOR_VGA: | 1095 | case DRM_MODE_CONNECTOR_VGA: |
1088 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); | 1096 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
1089 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); | 1097 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
1090 | if (i2c_bus->valid) { | 1098 | if (i2c_bus->valid) { |
1091 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); | 1099 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1092 | if (!radeon_connector->ddc_bus) | 1100 | if (!radeon_connector->ddc_bus) |
1093 | goto failed; | 1101 | goto failed; |
1094 | } | 1102 | } |
@@ -1104,7 +1112,7 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1104 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); | 1112 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
1105 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); | 1113 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
1106 | if (i2c_bus->valid) { | 1114 | if (i2c_bus->valid) { |
1107 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); | 1115 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1108 | if (!radeon_connector->ddc_bus) | 1116 | if (!radeon_connector->ddc_bus) |
1109 | goto failed; | 1117 | goto failed; |
1110 | } | 1118 | } |
@@ -1126,7 +1134,7 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1126 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); | 1134 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
1127 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); | 1135 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
1128 | if (i2c_bus->valid) { | 1136 | if (i2c_bus->valid) { |
1129 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); | 1137 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1130 | if (!radeon_connector->ddc_bus) | 1138 | if (!radeon_connector->ddc_bus) |
1131 | goto failed; | 1139 | goto failed; |
1132 | } | 1140 | } |
@@ -1156,7 +1164,7 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1156 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); | 1164 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
1157 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); | 1165 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
1158 | if (i2c_bus->valid) { | 1166 | if (i2c_bus->valid) { |
1159 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "HDMI"); | 1167 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1160 | if (!radeon_connector->ddc_bus) | 1168 | if (!radeon_connector->ddc_bus) |
1161 | goto failed; | 1169 | goto failed; |
1162 | } | 1170 | } |
@@ -1187,10 +1195,7 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1187 | radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); | 1195 | radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); |
1188 | if (!radeon_dig_connector->dp_i2c_bus) | 1196 | if (!radeon_dig_connector->dp_i2c_bus) |
1189 | goto failed; | 1197 | goto failed; |
1190 | if (connector_type == DRM_MODE_CONNECTOR_eDP) | 1198 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1191 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "eDP"); | ||
1192 | else | ||
1193 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP"); | ||
1194 | if (!radeon_connector->ddc_bus) | 1199 | if (!radeon_connector->ddc_bus) |
1195 | goto failed; | 1200 | goto failed; |
1196 | } | 1201 | } |
@@ -1230,7 +1235,7 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1230 | drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); | 1235 | drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); |
1231 | drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); | 1236 | drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); |
1232 | if (i2c_bus->valid) { | 1237 | if (i2c_bus->valid) { |
1233 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); | 1238 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1234 | if (!radeon_connector->ddc_bus) | 1239 | if (!radeon_connector->ddc_bus) |
1235 | goto failed; | 1240 | goto failed; |
1236 | } | 1241 | } |
@@ -1252,8 +1257,6 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1252 | return; | 1257 | return; |
1253 | 1258 | ||
1254 | failed: | 1259 | failed: |
1255 | if (radeon_connector->ddc_bus) | ||
1256 | radeon_i2c_destroy(radeon_connector->ddc_bus); | ||
1257 | drm_connector_cleanup(connector); | 1260 | drm_connector_cleanup(connector); |
1258 | kfree(connector); | 1261 | kfree(connector); |
1259 | } | 1262 | } |
@@ -1300,7 +1303,7 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
1300 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); | 1303 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
1301 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); | 1304 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
1302 | if (i2c_bus->valid) { | 1305 | if (i2c_bus->valid) { |
1303 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); | 1306 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1304 | if (!radeon_connector->ddc_bus) | 1307 | if (!radeon_connector->ddc_bus) |
1305 | goto failed; | 1308 | goto failed; |
1306 | } | 1309 | } |
@@ -1316,7 +1319,7 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
1316 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); | 1319 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
1317 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); | 1320 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
1318 | if (i2c_bus->valid) { | 1321 | if (i2c_bus->valid) { |
1319 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); | 1322 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1320 | if (!radeon_connector->ddc_bus) | 1323 | if (!radeon_connector->ddc_bus) |
1321 | goto failed; | 1324 | goto failed; |
1322 | } | 1325 | } |
@@ -1332,7 +1335,7 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
1332 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); | 1335 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
1333 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); | 1336 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
1334 | if (i2c_bus->valid) { | 1337 | if (i2c_bus->valid) { |
1335 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); | 1338 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1336 | if (!radeon_connector->ddc_bus) | 1339 | if (!radeon_connector->ddc_bus) |
1337 | goto failed; | 1340 | goto failed; |
1338 | } | 1341 | } |
@@ -1372,7 +1375,7 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
1372 | drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); | 1375 | drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); |
1373 | drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); | 1376 | drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); |
1374 | if (i2c_bus->valid) { | 1377 | if (i2c_bus->valid) { |
1375 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); | 1378 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1376 | if (!radeon_connector->ddc_bus) | 1379 | if (!radeon_connector->ddc_bus) |
1377 | goto failed; | 1380 | goto failed; |
1378 | } | 1381 | } |
@@ -1393,8 +1396,6 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
1393 | return; | 1396 | return; |
1394 | 1397 | ||
1395 | failed: | 1398 | failed: |
1396 | if (radeon_connector->ddc_bus) | ||
1397 | radeon_i2c_destroy(radeon_connector->ddc_bus); | ||
1398 | drm_connector_cleanup(connector); | 1399 | drm_connector_cleanup(connector); |
1399 | kfree(connector); | 1400 | kfree(connector); |
1400 | } | 1401 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index ae0fb7356e62..fcc79b5d22d1 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c | |||
@@ -72,7 +72,7 @@ int radeon_cs_parser_relocs(struct radeon_cs_parser *p) | |||
72 | if (p->relocs[i].gobj == NULL) { | 72 | if (p->relocs[i].gobj == NULL) { |
73 | DRM_ERROR("gem object lookup failed 0x%x\n", | 73 | DRM_ERROR("gem object lookup failed 0x%x\n", |
74 | r->handle); | 74 | r->handle); |
75 | return -EINVAL; | 75 | return -ENOENT; |
76 | } | 76 | } |
77 | p->relocs_ptr[i] = &p->relocs[i]; | 77 | p->relocs_ptr[i] = &p->relocs[i]; |
78 | p->relocs[i].robj = p->relocs[i].gobj->driver_private; | 78 | p->relocs[i].robj = p->relocs[i].gobj->driver_private; |
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 4eb67c0e0996..5731fc9b1ae3 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c | |||
@@ -170,7 +170,7 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc, | |||
170 | obj = drm_gem_object_lookup(crtc->dev, file_priv, handle); | 170 | obj = drm_gem_object_lookup(crtc->dev, file_priv, handle); |
171 | if (!obj) { | 171 | if (!obj) { |
172 | DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id); | 172 | DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id); |
173 | return -EINVAL; | 173 | return -ENOENT; |
174 | } | 174 | } |
175 | 175 | ||
176 | ret = radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &gpu_addr); | 176 | ret = radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &gpu_addr); |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index a64811a94519..4f7a170d1566 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
@@ -347,7 +347,8 @@ int radeon_dummy_page_init(struct radeon_device *rdev) | |||
347 | return -ENOMEM; | 347 | return -ENOMEM; |
348 | rdev->dummy_page.addr = pci_map_page(rdev->pdev, rdev->dummy_page.page, | 348 | rdev->dummy_page.addr = pci_map_page(rdev->pdev, rdev->dummy_page.page, |
349 | 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | 349 | 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); |
350 | if (!rdev->dummy_page.addr) { | 350 | if (pci_dma_mapping_error(rdev->pdev, rdev->dummy_page.addr)) { |
351 | dev_err(&rdev->pdev->dev, "Failed to DMA MAP the dummy page\n"); | ||
351 | __free_page(rdev->dummy_page.page); | 352 | __free_page(rdev->dummy_page.page); |
352 | rdev->dummy_page.page = NULL; | 353 | rdev->dummy_page.page = NULL; |
353 | return -ENOMEM; | 354 | return -ENOMEM; |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 74dac9635d70..5764f4d3b4f1 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -161,17 +161,13 @@ void radeon_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, | |||
161 | } | 161 | } |
162 | 162 | ||
163 | static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, | 163 | static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, |
164 | u16 *blue, uint32_t size) | 164 | u16 *blue, uint32_t start, uint32_t size) |
165 | { | 165 | { |
166 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 166 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
167 | int i; | 167 | int end = (start + size > 256) ? 256 : start + size, i; |
168 | |||
169 | if (size != 256) { | ||
170 | return; | ||
171 | } | ||
172 | 168 | ||
173 | /* userspace palettes are always correct as is */ | 169 | /* userspace palettes are always correct as is */ |
174 | for (i = 0; i < 256; i++) { | 170 | for (i = start; i < end; i++) { |
175 | radeon_crtc->lut_r[i] = red[i] >> 6; | 171 | radeon_crtc->lut_r[i] = red[i] >> 6; |
176 | radeon_crtc->lut_g[i] = green[i] >> 6; | 172 | radeon_crtc->lut_g[i] = green[i] >> 6; |
177 | radeon_crtc->lut_b[i] = blue[i] >> 6; | 173 | radeon_crtc->lut_b[i] = blue[i] >> 6; |
@@ -319,6 +315,10 @@ static void radeon_print_display_setup(struct drm_device *dev) | |||
319 | radeon_connector->ddc_bus->rec.en_data_reg, | 315 | radeon_connector->ddc_bus->rec.en_data_reg, |
320 | radeon_connector->ddc_bus->rec.y_clk_reg, | 316 | radeon_connector->ddc_bus->rec.y_clk_reg, |
321 | radeon_connector->ddc_bus->rec.y_data_reg); | 317 | radeon_connector->ddc_bus->rec.y_data_reg); |
318 | if (radeon_connector->router_bus) | ||
319 | DRM_INFO(" DDC Router 0x%x/0x%x\n", | ||
320 | radeon_connector->router.mux_control_pin, | ||
321 | radeon_connector->router.mux_state); | ||
322 | } else { | 322 | } else { |
323 | if (connector->connector_type == DRM_MODE_CONNECTOR_VGA || | 323 | if (connector->connector_type == DRM_MODE_CONNECTOR_VGA || |
324 | connector->connector_type == DRM_MODE_CONNECTOR_DVII || | 324 | connector->connector_type == DRM_MODE_CONNECTOR_DVII || |
@@ -395,6 +395,10 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) | |||
395 | struct radeon_device *rdev = dev->dev_private; | 395 | struct radeon_device *rdev = dev->dev_private; |
396 | int ret = 0; | 396 | int ret = 0; |
397 | 397 | ||
398 | /* on hw with routers, select right port */ | ||
399 | if (radeon_connector->router.valid) | ||
400 | radeon_router_select_port(radeon_connector); | ||
401 | |||
398 | if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || | 402 | if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || |
399 | (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { | 403 | (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { |
400 | struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; | 404 | struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; |
@@ -425,6 +429,10 @@ static int radeon_ddc_dump(struct drm_connector *connector) | |||
425 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 429 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
426 | int ret = 0; | 430 | int ret = 0; |
427 | 431 | ||
432 | /* on hw with routers, select right port */ | ||
433 | if (radeon_connector->router.valid) | ||
434 | radeon_router_select_port(radeon_connector); | ||
435 | |||
428 | if (!radeon_connector->ddc_bus) | 436 | if (!radeon_connector->ddc_bus) |
429 | return -1; | 437 | return -1; |
430 | edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter); | 438 | edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter); |
@@ -876,13 +884,12 @@ radeon_user_framebuffer_create(struct drm_device *dev, | |||
876 | if (obj == NULL) { | 884 | if (obj == NULL) { |
877 | dev_err(&dev->pdev->dev, "No GEM object associated to handle 0x%08X, " | 885 | dev_err(&dev->pdev->dev, "No GEM object associated to handle 0x%08X, " |
878 | "can't create framebuffer\n", mode_cmd->handle); | 886 | "can't create framebuffer\n", mode_cmd->handle); |
879 | return NULL; | 887 | return ERR_PTR(-ENOENT); |
880 | } | 888 | } |
881 | 889 | ||
882 | radeon_fb = kzalloc(sizeof(*radeon_fb), GFP_KERNEL); | 890 | radeon_fb = kzalloc(sizeof(*radeon_fb), GFP_KERNEL); |
883 | if (radeon_fb == NULL) { | 891 | if (radeon_fb == NULL) |
884 | return NULL; | 892 | return ERR_PTR(-ENOMEM); |
885 | } | ||
886 | 893 | ||
887 | radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj); | 894 | radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj); |
888 | 895 | ||
@@ -1040,6 +1047,9 @@ int radeon_modeset_init(struct radeon_device *rdev) | |||
1040 | return ret; | 1047 | return ret; |
1041 | } | 1048 | } |
1042 | 1049 | ||
1050 | /* init i2c buses */ | ||
1051 | radeon_i2c_init(rdev); | ||
1052 | |||
1043 | /* check combios for a valid hardcoded EDID - Sun servers */ | 1053 | /* check combios for a valid hardcoded EDID - Sun servers */ |
1044 | if (!rdev->is_atom_bios) { | 1054 | if (!rdev->is_atom_bios) { |
1045 | /* check for hardcoded EDID in BIOS */ | 1055 | /* check for hardcoded EDID in BIOS */ |
@@ -1080,6 +1090,8 @@ void radeon_modeset_fini(struct radeon_device *rdev) | |||
1080 | drm_mode_config_cleanup(rdev->ddev); | 1090 | drm_mode_config_cleanup(rdev->ddev); |
1081 | rdev->mode_info.mode_config_initialized = false; | 1091 | rdev->mode_info.mode_config_initialized = false; |
1082 | } | 1092 | } |
1093 | /* free i2c buses */ | ||
1094 | radeon_i2c_fini(rdev); | ||
1083 | } | 1095 | } |
1084 | 1096 | ||
1085 | bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | 1097 | bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, |
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index a72a3ee5d69b..c578f265b24c 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c | |||
@@ -226,7 +226,7 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
226 | /* just do a BO wait for now */ | 226 | /* just do a BO wait for now */ |
227 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | 227 | gobj = drm_gem_object_lookup(dev, filp, args->handle); |
228 | if (gobj == NULL) { | 228 | if (gobj == NULL) { |
229 | return -EINVAL; | 229 | return -ENOENT; |
230 | } | 230 | } |
231 | robj = gobj->driver_private; | 231 | robj = gobj->driver_private; |
232 | 232 | ||
@@ -245,7 +245,7 @@ int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, | |||
245 | 245 | ||
246 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | 246 | gobj = drm_gem_object_lookup(dev, filp, args->handle); |
247 | if (gobj == NULL) { | 247 | if (gobj == NULL) { |
248 | return -EINVAL; | 248 | return -ENOENT; |
249 | } | 249 | } |
250 | robj = gobj->driver_private; | 250 | robj = gobj->driver_private; |
251 | args->addr_ptr = radeon_bo_mmap_offset(robj); | 251 | args->addr_ptr = radeon_bo_mmap_offset(robj); |
@@ -264,7 +264,7 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
264 | 264 | ||
265 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | 265 | gobj = drm_gem_object_lookup(dev, filp, args->handle); |
266 | if (gobj == NULL) { | 266 | if (gobj == NULL) { |
267 | return -EINVAL; | 267 | return -ENOENT; |
268 | } | 268 | } |
269 | robj = gobj->driver_private; | 269 | robj = gobj->driver_private; |
270 | r = radeon_bo_wait(robj, &cur_placement, true); | 270 | r = radeon_bo_wait(robj, &cur_placement, true); |
@@ -294,7 +294,7 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, | |||
294 | 294 | ||
295 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | 295 | gobj = drm_gem_object_lookup(dev, filp, args->handle); |
296 | if (gobj == NULL) { | 296 | if (gobj == NULL) { |
297 | return -EINVAL; | 297 | return -ENOENT; |
298 | } | 298 | } |
299 | robj = gobj->driver_private; | 299 | robj = gobj->driver_private; |
300 | r = radeon_bo_wait(robj, NULL, false); | 300 | r = radeon_bo_wait(robj, NULL, false); |
@@ -316,7 +316,7 @@ int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data, | |||
316 | DRM_DEBUG("%d \n", args->handle); | 316 | DRM_DEBUG("%d \n", args->handle); |
317 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | 317 | gobj = drm_gem_object_lookup(dev, filp, args->handle); |
318 | if (gobj == NULL) | 318 | if (gobj == NULL) |
319 | return -EINVAL; | 319 | return -ENOENT; |
320 | robj = gobj->driver_private; | 320 | robj = gobj->driver_private; |
321 | r = radeon_bo_set_tiling_flags(robj, args->tiling_flags, args->pitch); | 321 | r = radeon_bo_set_tiling_flags(robj, args->tiling_flags, args->pitch); |
322 | drm_gem_object_unreference_unlocked(gobj); | 322 | drm_gem_object_unreference_unlocked(gobj); |
@@ -334,7 +334,7 @@ int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data, | |||
334 | DRM_DEBUG("\n"); | 334 | DRM_DEBUG("\n"); |
335 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | 335 | gobj = drm_gem_object_lookup(dev, filp, args->handle); |
336 | if (gobj == NULL) | 336 | if (gobj == NULL) |
337 | return -EINVAL; | 337 | return -ENOENT; |
338 | rbo = gobj->driver_private; | 338 | rbo = gobj->driver_private; |
339 | r = radeon_bo_reserve(rbo, false); | 339 | r = radeon_bo_reserve(rbo, false); |
340 | if (unlikely(r != 0)) | 340 | if (unlikely(r != 0)) |
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 5def6f5dff38..bfd2ce5f5372 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c | |||
@@ -52,6 +52,10 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector) | |||
52 | } | 52 | } |
53 | }; | 53 | }; |
54 | 54 | ||
55 | /* on hw with routers, select right port */ | ||
56 | if (radeon_connector->router.valid) | ||
57 | radeon_router_select_port(radeon_connector); | ||
58 | |||
55 | ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); | 59 | ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); |
56 | if (ret == 2) | 60 | if (ret == 2) |
57 | return true; | 61 | return true; |
@@ -960,6 +964,59 @@ void radeon_i2c_destroy(struct radeon_i2c_chan *i2c) | |||
960 | kfree(i2c); | 964 | kfree(i2c); |
961 | } | 965 | } |
962 | 966 | ||
967 | /* Add the default buses */ | ||
968 | void radeon_i2c_init(struct radeon_device *rdev) | ||
969 | { | ||
970 | if (rdev->is_atom_bios) | ||
971 | radeon_atombios_i2c_init(rdev); | ||
972 | else | ||
973 | radeon_combios_i2c_init(rdev); | ||
974 | } | ||
975 | |||
976 | /* remove all the buses */ | ||
977 | void radeon_i2c_fini(struct radeon_device *rdev) | ||
978 | { | ||
979 | int i; | ||
980 | |||
981 | for (i = 0; i < RADEON_MAX_I2C_BUS; i++) { | ||
982 | if (rdev->i2c_bus[i]) { | ||
983 | radeon_i2c_destroy(rdev->i2c_bus[i]); | ||
984 | rdev->i2c_bus[i] = NULL; | ||
985 | } | ||
986 | } | ||
987 | } | ||
988 | |||
989 | /* Add additional buses */ | ||
990 | void radeon_i2c_add(struct radeon_device *rdev, | ||
991 | struct radeon_i2c_bus_rec *rec, | ||
992 | const char *name) | ||
993 | { | ||
994 | struct drm_device *dev = rdev->ddev; | ||
995 | int i; | ||
996 | |||
997 | for (i = 0; i < RADEON_MAX_I2C_BUS; i++) { | ||
998 | if (!rdev->i2c_bus[i]) { | ||
999 | rdev->i2c_bus[i] = radeon_i2c_create(dev, rec, name); | ||
1000 | return; | ||
1001 | } | ||
1002 | } | ||
1003 | } | ||
1004 | |||
1005 | /* looks up bus based on id */ | ||
1006 | struct radeon_i2c_chan *radeon_i2c_lookup(struct radeon_device *rdev, | ||
1007 | struct radeon_i2c_bus_rec *i2c_bus) | ||
1008 | { | ||
1009 | int i; | ||
1010 | |||
1011 | for (i = 0; i < RADEON_MAX_I2C_BUS; i++) { | ||
1012 | if (rdev->i2c_bus[i] && | ||
1013 | (rdev->i2c_bus[i]->rec.i2c_id == i2c_bus->i2c_id)) { | ||
1014 | return rdev->i2c_bus[i]; | ||
1015 | } | ||
1016 | } | ||
1017 | return NULL; | ||
1018 | } | ||
1019 | |||
963 | struct drm_encoder *radeon_best_encoder(struct drm_connector *connector) | 1020 | struct drm_encoder *radeon_best_encoder(struct drm_connector *connector) |
964 | { | 1021 | { |
965 | return NULL; | 1022 | return NULL; |
@@ -1020,3 +1077,28 @@ void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c_bus, | |||
1020 | addr, val); | 1077 | addr, val); |
1021 | } | 1078 | } |
1022 | 1079 | ||
1080 | /* router switching */ | ||
1081 | void radeon_router_select_port(struct radeon_connector *radeon_connector) | ||
1082 | { | ||
1083 | u8 val; | ||
1084 | |||
1085 | if (!radeon_connector->router.valid) | ||
1086 | return; | ||
1087 | |||
1088 | radeon_i2c_get_byte(radeon_connector->router_bus, | ||
1089 | radeon_connector->router.i2c_addr, | ||
1090 | 0x3, &val); | ||
1091 | val &= radeon_connector->router.mux_control_pin; | ||
1092 | radeon_i2c_put_byte(radeon_connector->router_bus, | ||
1093 | radeon_connector->router.i2c_addr, | ||
1094 | 0x3, val); | ||
1095 | radeon_i2c_get_byte(radeon_connector->router_bus, | ||
1096 | radeon_connector->router.i2c_addr, | ||
1097 | 0x1, &val); | ||
1098 | val &= radeon_connector->router.mux_control_pin; | ||
1099 | val |= radeon_connector->router.mux_state; | ||
1100 | radeon_i2c_put_byte(radeon_connector->router_bus, | ||
1101 | radeon_connector->router.i2c_addr, | ||
1102 | 0x1, val); | ||
1103 | } | ||
1104 | |||
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index ddcd3b13f151..b1c8ace5f080 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c | |||
@@ -112,7 +112,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
112 | 112 | ||
113 | info = data; | 113 | info = data; |
114 | value_ptr = (uint32_t *)((unsigned long)info->value); | 114 | value_ptr = (uint32_t *)((unsigned long)info->value); |
115 | value = *value_ptr; | 115 | if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) |
116 | return -EFAULT; | ||
117 | |||
116 | switch (info->request) { | 118 | switch (info->request) { |
117 | case RADEON_INFO_DEVICE_ID: | 119 | case RADEON_INFO_DEVICE_ID: |
118 | value = dev->pci_device; | 120 | value = dev->pci_device; |
@@ -160,13 +162,27 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
160 | return -EINVAL; | 162 | return -EINVAL; |
161 | } | 163 | } |
162 | case RADEON_INFO_WANT_HYPERZ: | 164 | case RADEON_INFO_WANT_HYPERZ: |
165 | /* The "value" here is both an input and output parameter. | ||
166 | * If the input value is 1, filp requests hyper-z access. | ||
167 | * If the input value is 0, filp revokes its hyper-z access. | ||
168 | * | ||
169 | * When returning, the value is 1 if filp owns hyper-z access, | ||
170 | * 0 otherwise. */ | ||
171 | if (value >= 2) { | ||
172 | DRM_DEBUG_KMS("WANT_HYPERZ: invalid value %d\n", value); | ||
173 | return -EINVAL; | ||
174 | } | ||
163 | mutex_lock(&dev->struct_mutex); | 175 | mutex_lock(&dev->struct_mutex); |
164 | if (rdev->hyperz_filp) | 176 | if (value == 1) { |
165 | value = 0; | 177 | /* wants hyper-z */ |
166 | else { | 178 | if (!rdev->hyperz_filp) |
167 | rdev->hyperz_filp = filp; | 179 | rdev->hyperz_filp = filp; |
168 | value = 1; | 180 | } else if (value == 0) { |
181 | /* revokes hyper-z */ | ||
182 | if (rdev->hyperz_filp == filp) | ||
183 | rdev->hyperz_filp = NULL; | ||
169 | } | 184 | } |
185 | value = rdev->hyperz_filp == filp ? 1 : 0; | ||
170 | mutex_unlock(&dev->struct_mutex); | 186 | mutex_unlock(&dev->struct_mutex); |
171 | break; | 187 | break; |
172 | default: | 188 | default: |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 71aea4037e90..5bbc086b9267 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
@@ -82,6 +82,8 @@ enum radeon_hpd_id { | |||
82 | RADEON_HPD_NONE = 0xff, | 82 | RADEON_HPD_NONE = 0xff, |
83 | }; | 83 | }; |
84 | 84 | ||
85 | #define RADEON_MAX_I2C_BUS 16 | ||
86 | |||
85 | /* radeon gpio-based i2c | 87 | /* radeon gpio-based i2c |
86 | * 1. "mask" reg and bits | 88 | * 1. "mask" reg and bits |
87 | * grabs the gpio pins for software use | 89 | * grabs the gpio pins for software use |
@@ -398,6 +400,16 @@ struct radeon_hpd { | |||
398 | struct radeon_gpio_rec gpio; | 400 | struct radeon_gpio_rec gpio; |
399 | }; | 401 | }; |
400 | 402 | ||
403 | struct radeon_router { | ||
404 | bool valid; | ||
405 | u32 router_id; | ||
406 | struct radeon_i2c_bus_rec i2c_info; | ||
407 | u8 i2c_addr; | ||
408 | u8 mux_type; | ||
409 | u8 mux_control_pin; | ||
410 | u8 mux_state; | ||
411 | }; | ||
412 | |||
401 | struct radeon_connector { | 413 | struct radeon_connector { |
402 | struct drm_connector base; | 414 | struct drm_connector base; |
403 | uint32_t connector_id; | 415 | uint32_t connector_id; |
@@ -413,6 +425,8 @@ struct radeon_connector { | |||
413 | bool dac_load_detect; | 425 | bool dac_load_detect; |
414 | uint16_t connector_object_id; | 426 | uint16_t connector_object_id; |
415 | struct radeon_hpd hpd; | 427 | struct radeon_hpd hpd; |
428 | struct radeon_router router; | ||
429 | struct radeon_i2c_chan *router_bus; | ||
416 | }; | 430 | }; |
417 | 431 | ||
418 | struct radeon_framebuffer { | 432 | struct radeon_framebuffer { |
@@ -445,6 +459,15 @@ extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, | |||
445 | extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, | 459 | extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, |
446 | uint8_t write_byte, uint8_t *read_byte); | 460 | uint8_t write_byte, uint8_t *read_byte); |
447 | 461 | ||
462 | extern void radeon_i2c_init(struct radeon_device *rdev); | ||
463 | extern void radeon_i2c_fini(struct radeon_device *rdev); | ||
464 | extern void radeon_combios_i2c_init(struct radeon_device *rdev); | ||
465 | extern void radeon_atombios_i2c_init(struct radeon_device *rdev); | ||
466 | extern void radeon_i2c_add(struct radeon_device *rdev, | ||
467 | struct radeon_i2c_bus_rec *rec, | ||
468 | const char *name); | ||
469 | extern struct radeon_i2c_chan *radeon_i2c_lookup(struct radeon_device *rdev, | ||
470 | struct radeon_i2c_bus_rec *i2c_bus); | ||
448 | extern struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, | 471 | extern struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, |
449 | struct radeon_i2c_bus_rec *rec, | 472 | struct radeon_i2c_bus_rec *rec, |
450 | const char *name); | 473 | const char *name); |
@@ -460,6 +483,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c, | |||
460 | u8 slave_addr, | 483 | u8 slave_addr, |
461 | u8 addr, | 484 | u8 addr, |
462 | u8 val); | 485 | u8 val); |
486 | extern void radeon_router_select_port(struct radeon_connector *radeon_connector); | ||
463 | extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector); | 487 | extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector); |
464 | extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); | 488 | extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); |
465 | 489 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 95f8b3a3c43d..58038f5cab38 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
@@ -472,9 +472,9 @@ static const struct attribute_group hwmon_attrgroup = { | |||
472 | .attrs = hwmon_attributes, | 472 | .attrs = hwmon_attributes, |
473 | }; | 473 | }; |
474 | 474 | ||
475 | static void radeon_hwmon_init(struct radeon_device *rdev) | 475 | static int radeon_hwmon_init(struct radeon_device *rdev) |
476 | { | 476 | { |
477 | int err; | 477 | int err = 0; |
478 | 478 | ||
479 | rdev->pm.int_hwmon_dev = NULL; | 479 | rdev->pm.int_hwmon_dev = NULL; |
480 | 480 | ||
@@ -483,15 +483,26 @@ static void radeon_hwmon_init(struct radeon_device *rdev) | |||
483 | case THERMAL_TYPE_RV770: | 483 | case THERMAL_TYPE_RV770: |
484 | case THERMAL_TYPE_EVERGREEN: | 484 | case THERMAL_TYPE_EVERGREEN: |
485 | rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev); | 485 | rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev); |
486 | if (IS_ERR(rdev->pm.int_hwmon_dev)) { | ||
487 | err = PTR_ERR(rdev->pm.int_hwmon_dev); | ||
488 | dev_err(rdev->dev, | ||
489 | "Unable to register hwmon device: %d\n", err); | ||
490 | break; | ||
491 | } | ||
486 | dev_set_drvdata(rdev->pm.int_hwmon_dev, rdev->ddev); | 492 | dev_set_drvdata(rdev->pm.int_hwmon_dev, rdev->ddev); |
487 | err = sysfs_create_group(&rdev->pm.int_hwmon_dev->kobj, | 493 | err = sysfs_create_group(&rdev->pm.int_hwmon_dev->kobj, |
488 | &hwmon_attrgroup); | 494 | &hwmon_attrgroup); |
489 | if (err) | 495 | if (err) { |
490 | DRM_ERROR("Unable to create hwmon sysfs file: %d\n", err); | 496 | dev_err(rdev->dev, |
497 | "Unable to create hwmon sysfs file: %d\n", err); | ||
498 | hwmon_device_unregister(rdev->dev); | ||
499 | } | ||
491 | break; | 500 | break; |
492 | default: | 501 | default: |
493 | break; | 502 | break; |
494 | } | 503 | } |
504 | |||
505 | return err; | ||
495 | } | 506 | } |
496 | 507 | ||
497 | static void radeon_hwmon_fini(struct radeon_device *rdev) | 508 | static void radeon_hwmon_fini(struct radeon_device *rdev) |
@@ -540,6 +551,7 @@ void radeon_pm_resume(struct radeon_device *rdev) | |||
540 | int radeon_pm_init(struct radeon_device *rdev) | 551 | int radeon_pm_init(struct radeon_device *rdev) |
541 | { | 552 | { |
542 | int ret; | 553 | int ret; |
554 | |||
543 | /* default to profile method */ | 555 | /* default to profile method */ |
544 | rdev->pm.pm_method = PM_METHOD_PROFILE; | 556 | rdev->pm.pm_method = PM_METHOD_PROFILE; |
545 | rdev->pm.profile = PM_PROFILE_DEFAULT; | 557 | rdev->pm.profile = PM_PROFILE_DEFAULT; |
@@ -561,7 +573,9 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
561 | } | 573 | } |
562 | 574 | ||
563 | /* set up the internal thermal sensor if applicable */ | 575 | /* set up the internal thermal sensor if applicable */ |
564 | radeon_hwmon_init(rdev); | 576 | ret = radeon_hwmon_init(rdev); |
577 | if (ret) | ||
578 | return ret; | ||
565 | if (rdev->pm.num_power_states > 1) { | 579 | if (rdev->pm.num_power_states > 1) { |
566 | /* where's the best place to put these? */ | 580 | /* where's the best place to put these? */ |
567 | ret = device_create_file(rdev->dev, &dev_attr_power_profile); | 581 | ret = device_create_file(rdev->dev, &dev_attr_power_profile); |
diff --git a/drivers/gpu/drm/radeon/reg_srcs/rv515 b/drivers/gpu/drm/radeon/reg_srcs/rv515 index 8293855f5f0d..b3f9f1d92005 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/rv515 +++ b/drivers/gpu/drm/radeon/reg_srcs/rv515 | |||
@@ -316,6 +316,7 @@ rv515 0x6d40 | |||
316 | 0x4BD0 FG_FOG_COLOR_B | 316 | 0x4BD0 FG_FOG_COLOR_B |
317 | 0x4BD4 FG_ALPHA_FUNC | 317 | 0x4BD4 FG_ALPHA_FUNC |
318 | 0x4BD8 FG_DEPTH_SRC | 318 | 0x4BD8 FG_DEPTH_SRC |
319 | 0x4BE0 FG_ALPHA_VALUE | ||
319 | 0x4C00 US_ALU_CONST_R_0 | 320 | 0x4C00 US_ALU_CONST_R_0 |
320 | 0x4C04 US_ALU_CONST_G_0 | 321 | 0x4C04 US_ALU_CONST_G_0 |
321 | 0x4C08 US_ALU_CONST_B_0 | 322 | 0x4C08 US_ALU_CONST_B_0 |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 437ac786277a..64d7f47df868 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | |||
@@ -737,7 +737,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, | |||
737 | 737 | ||
738 | if (ret) { | 738 | if (ret) { |
739 | DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret); | 739 | DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret); |
740 | return NULL; | 740 | return ERR_PTR(ret); |
741 | } | 741 | } |
742 | return &vfb->base; | 742 | return &vfb->base; |
743 | 743 | ||
@@ -747,7 +747,7 @@ try_dmabuf: | |||
747 | ret = vmw_user_dmabuf_lookup(tfile, mode_cmd->handle, &bo); | 747 | ret = vmw_user_dmabuf_lookup(tfile, mode_cmd->handle, &bo); |
748 | if (ret) { | 748 | if (ret) { |
749 | DRM_ERROR("failed to find buffer: %i\n", ret); | 749 | DRM_ERROR("failed to find buffer: %i\n", ret); |
750 | return NULL; | 750 | return ERR_PTR(-ENOENT); |
751 | } | 751 | } |
752 | 752 | ||
753 | ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb, | 753 | ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb, |
@@ -758,7 +758,7 @@ try_dmabuf: | |||
758 | 758 | ||
759 | if (ret) { | 759 | if (ret) { |
760 | DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret); | 760 | DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret); |
761 | return NULL; | 761 | return ERR_PTR(ret); |
762 | } | 762 | } |
763 | 763 | ||
764 | return &vfb->base; | 764 | return &vfb->base; |
@@ -768,7 +768,7 @@ err_not_scanout: | |||
768 | /* vmw_user_surface_lookup takes one ref */ | 768 | /* vmw_user_surface_lookup takes one ref */ |
769 | vmw_surface_unreference(&surface); | 769 | vmw_surface_unreference(&surface); |
770 | 770 | ||
771 | return NULL; | 771 | return ERR_PTR(-EINVAL); |
772 | } | 772 | } |
773 | 773 | ||
774 | static struct drm_mode_config_funcs vmw_kms_funcs = { | 774 | static struct drm_mode_config_funcs vmw_kms_funcs = { |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index cfaf690a5b2f..2ff5cf78235f 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | |||
@@ -79,7 +79,7 @@ static void vmw_ldu_crtc_restore(struct drm_crtc *crtc) | |||
79 | 79 | ||
80 | static void vmw_ldu_crtc_gamma_set(struct drm_crtc *crtc, | 80 | static void vmw_ldu_crtc_gamma_set(struct drm_crtc *crtc, |
81 | u16 *r, u16 *g, u16 *b, | 81 | u16 *r, u16 *g, u16 *b, |
82 | uint32_t size) | 82 | uint32_t start, uint32_t size) |
83 | { | 83 | { |
84 | } | 84 | } |
85 | 85 | ||
diff --git a/drivers/hwmon/ams/ams.h b/drivers/hwmon/ams/ams.h index b28d7e27a031..90f094d45450 100644 --- a/drivers/hwmon/ams/ams.h +++ b/drivers/hwmon/ams/ams.h | |||
@@ -23,7 +23,7 @@ struct ams { | |||
23 | 23 | ||
24 | /* General properties */ | 24 | /* General properties */ |
25 | struct device_node *of_node; | 25 | struct device_node *of_node; |
26 | struct of_device *of_dev; | 26 | struct platform_device *of_dev; |
27 | char has_device; | 27 | char has_device; |
28 | char vflag; | 28 | char vflag; |
29 | u32 orient1; | 29 | u32 orient1; |
diff --git a/drivers/hwmon/mc13783-adc.c b/drivers/hwmon/mc13783-adc.c index ce3c7bc81814..d5226c9e1201 100644 --- a/drivers/hwmon/mc13783-adc.c +++ b/drivers/hwmon/mc13783-adc.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 18 | * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/mfd/mc13783-private.h> | 21 | #include <linux/mfd/mc13783.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/hwmon-sysfs.h> | 23 | #include <linux/hwmon-sysfs.h> |
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
@@ -144,6 +144,14 @@ static const struct attribute_group mc13783_group_ts = { | |||
144 | .attrs = mc13783_attr_ts, | 144 | .attrs = mc13783_attr_ts, |
145 | }; | 145 | }; |
146 | 146 | ||
147 | static int mc13783_adc_use_touchscreen(struct platform_device *pdev) | ||
148 | { | ||
149 | struct mc13783_adc_priv *priv = platform_get_drvdata(pdev); | ||
150 | unsigned flags = mc13783_get_flags(priv->mc13783); | ||
151 | |||
152 | return flags & MC13783_USE_TOUCHSCREEN; | ||
153 | } | ||
154 | |||
147 | static int __init mc13783_adc_probe(struct platform_device *pdev) | 155 | static int __init mc13783_adc_probe(struct platform_device *pdev) |
148 | { | 156 | { |
149 | struct mc13783_adc_priv *priv; | 157 | struct mc13783_adc_priv *priv; |
@@ -162,10 +170,11 @@ static int __init mc13783_adc_probe(struct platform_device *pdev) | |||
162 | if (ret) | 170 | if (ret) |
163 | goto out_err_create1; | 171 | goto out_err_create1; |
164 | 172 | ||
165 | if (!(priv->mc13783->flags & MC13783_USE_TOUCHSCREEN)) | 173 | if (!mc13783_adc_use_touchscreen(pdev)) { |
166 | ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group_ts); | 174 | ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group_ts); |
167 | if (ret) | 175 | if (ret) |
168 | goto out_err_create2; | 176 | goto out_err_create2; |
177 | } | ||
169 | 178 | ||
170 | priv->hwmon_dev = hwmon_device_register(&pdev->dev); | 179 | priv->hwmon_dev = hwmon_device_register(&pdev->dev); |
171 | if (IS_ERR(priv->hwmon_dev)) { | 180 | if (IS_ERR(priv->hwmon_dev)) { |
@@ -180,7 +189,7 @@ static int __init mc13783_adc_probe(struct platform_device *pdev) | |||
180 | 189 | ||
181 | out_err_register: | 190 | out_err_register: |
182 | 191 | ||
183 | if (!(priv->mc13783->flags & MC13783_USE_TOUCHSCREEN)) | 192 | if (!mc13783_adc_use_touchscreen(pdev)) |
184 | sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts); | 193 | sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts); |
185 | out_err_create2: | 194 | out_err_create2: |
186 | 195 | ||
@@ -199,7 +208,7 @@ static int __devexit mc13783_adc_remove(struct platform_device *pdev) | |||
199 | 208 | ||
200 | hwmon_device_unregister(priv->hwmon_dev); | 209 | hwmon_device_unregister(priv->hwmon_dev); |
201 | 210 | ||
202 | if (!(priv->mc13783->flags & MC13783_USE_TOUCHSCREEN)) | 211 | if (!mc13783_adc_use_touchscreen(pdev)) |
203 | sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts); | 212 | sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts); |
204 | 213 | ||
205 | sysfs_remove_group(&pdev->dev.kobj, &mc13783_group); | 214 | sysfs_remove_group(&pdev->dev.kobj, &mc13783_group); |
diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c index 89643261ccdb..d863e13a50b8 100644 --- a/drivers/hwmon/ultra45_env.c +++ b/drivers/hwmon/ultra45_env.c | |||
@@ -234,7 +234,7 @@ static const struct attribute_group env_group = { | |||
234 | .attrs = env_attributes, | 234 | .attrs = env_attributes, |
235 | }; | 235 | }; |
236 | 236 | ||
237 | static int __devinit env_probe(struct of_device *op, | 237 | static int __devinit env_probe(struct platform_device *op, |
238 | const struct of_device_id *match) | 238 | const struct of_device_id *match) |
239 | { | 239 | { |
240 | struct env *p = kzalloc(sizeof(*p), GFP_KERNEL); | 240 | struct env *p = kzalloc(sizeof(*p), GFP_KERNEL); |
@@ -276,7 +276,7 @@ out_free: | |||
276 | goto out; | 276 | goto out; |
277 | } | 277 | } |
278 | 278 | ||
279 | static int __devexit env_remove(struct of_device *op) | 279 | static int __devexit env_remove(struct platform_device *op) |
280 | { | 280 | { |
281 | struct env *p = dev_get_drvdata(&op->dev); | 281 | struct env *p = dev_get_drvdata(&op->dev); |
282 | 282 | ||
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index d06083fdffbb..30f06e956bfb 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig | |||
@@ -47,6 +47,19 @@ config I2C_CHARDEV | |||
47 | This support is also available as a module. If so, the module | 47 | This support is also available as a module. If so, the module |
48 | will be called i2c-dev. | 48 | will be called i2c-dev. |
49 | 49 | ||
50 | config I2C_MUX | ||
51 | tristate "I2C bus multiplexing support" | ||
52 | depends on EXPERIMENTAL | ||
53 | help | ||
54 | Say Y here if you want the I2C core to support the ability to | ||
55 | handle multiplexed I2C bus topologies, by presenting each | ||
56 | multiplexed segment as a I2C adapter. | ||
57 | |||
58 | This support is also available as a module. If so, the module | ||
59 | will be called i2c-mux. | ||
60 | |||
61 | source drivers/i2c/muxes/Kconfig | ||
62 | |||
50 | config I2C_HELPER_AUTO | 63 | config I2C_HELPER_AUTO |
51 | bool "Autoselect pertinent helper modules" | 64 | bool "Autoselect pertinent helper modules" |
52 | default y | 65 | default y |
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index a7d9b4be9bb3..c00fd66388f5 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile | |||
@@ -6,7 +6,8 @@ obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o | |||
6 | obj-$(CONFIG_I2C) += i2c-core.o | 6 | obj-$(CONFIG_I2C) += i2c-core.o |
7 | obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o | 7 | obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o |
8 | obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o | 8 | obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o |
9 | obj-y += algos/ busses/ | 9 | obj-$(CONFIG_I2C_MUX) += i2c-mux.o |
10 | obj-y += algos/ busses/ muxes/ | ||
10 | 11 | ||
11 | ifeq ($(CONFIG_I2C_DEBUG_CORE),y) | 12 | ifeq ($(CONFIG_I2C_DEBUG_CORE),y) |
12 | EXTRA_CFLAGS += -DDEBUG | 13 | EXTRA_CFLAGS += -DDEBUG |
diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index e591de1bc704..f7bd2613cecc 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c | |||
@@ -105,7 +105,7 @@ struct i2c_reg { | |||
105 | 105 | ||
106 | struct cpm_i2c { | 106 | struct cpm_i2c { |
107 | char *base; | 107 | char *base; |
108 | struct of_device *ofdev; | 108 | struct platform_device *ofdev; |
109 | struct i2c_adapter adap; | 109 | struct i2c_adapter adap; |
110 | uint dp_addr; | 110 | uint dp_addr; |
111 | int version; /* CPM1=1, CPM2=2 */ | 111 | int version; /* CPM1=1, CPM2=2 */ |
@@ -428,7 +428,7 @@ static const struct i2c_adapter cpm_ops = { | |||
428 | 428 | ||
429 | static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm) | 429 | static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm) |
430 | { | 430 | { |
431 | struct of_device *ofdev = cpm->ofdev; | 431 | struct platform_device *ofdev = cpm->ofdev; |
432 | const u32 *data; | 432 | const u32 *data; |
433 | int len, ret, i; | 433 | int len, ret, i; |
434 | void __iomem *i2c_base; | 434 | void __iomem *i2c_base; |
@@ -634,7 +634,7 @@ static void cpm_i2c_shutdown(struct cpm_i2c *cpm) | |||
634 | cpm_muram_free(cpm->i2c_addr); | 634 | cpm_muram_free(cpm->i2c_addr); |
635 | } | 635 | } |
636 | 636 | ||
637 | static int __devinit cpm_i2c_probe(struct of_device *ofdev, | 637 | static int __devinit cpm_i2c_probe(struct platform_device *ofdev, |
638 | const struct of_device_id *match) | 638 | const struct of_device_id *match) |
639 | { | 639 | { |
640 | int result, len; | 640 | int result, len; |
@@ -687,7 +687,7 @@ out_free: | |||
687 | return result; | 687 | return result; |
688 | } | 688 | } |
689 | 689 | ||
690 | static int __devexit cpm_i2c_remove(struct of_device *ofdev) | 690 | static int __devexit cpm_i2c_remove(struct platform_device *ofdev) |
691 | { | 691 | { |
692 | struct cpm_i2c *cpm = dev_get_drvdata(&ofdev->dev); | 692 | struct cpm_i2c *cpm = dev_get_drvdata(&ofdev->dev); |
693 | 693 | ||
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 1168d61418c9..43ca32fddde2 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c | |||
@@ -661,7 +661,7 @@ static inline u8 iic_clckdiv(unsigned int opb) | |||
661 | return (u8)((opb + 9) / 10 - 1); | 661 | return (u8)((opb + 9) / 10 - 1); |
662 | } | 662 | } |
663 | 663 | ||
664 | static int __devinit iic_request_irq(struct of_device *ofdev, | 664 | static int __devinit iic_request_irq(struct platform_device *ofdev, |
665 | struct ibm_iic_private *dev) | 665 | struct ibm_iic_private *dev) |
666 | { | 666 | { |
667 | struct device_node *np = ofdev->dev.of_node; | 667 | struct device_node *np = ofdev->dev.of_node; |
@@ -692,7 +692,7 @@ static int __devinit iic_request_irq(struct of_device *ofdev, | |||
692 | /* | 692 | /* |
693 | * Register single IIC interface | 693 | * Register single IIC interface |
694 | */ | 694 | */ |
695 | static int __devinit iic_probe(struct of_device *ofdev, | 695 | static int __devinit iic_probe(struct platform_device *ofdev, |
696 | const struct of_device_id *match) | 696 | const struct of_device_id *match) |
697 | { | 697 | { |
698 | struct device_node *np = ofdev->dev.of_node; | 698 | struct device_node *np = ofdev->dev.of_node; |
@@ -780,7 +780,7 @@ error_cleanup: | |||
780 | /* | 780 | /* |
781 | * Cleanup initialized IIC interface | 781 | * Cleanup initialized IIC interface |
782 | */ | 782 | */ |
783 | static int __devexit iic_remove(struct of_device *ofdev) | 783 | static int __devexit iic_remove(struct platform_device *ofdev) |
784 | { | 784 | { |
785 | struct ibm_iic_private *dev = dev_get_drvdata(&ofdev->dev); | 785 | struct ibm_iic_private *dev = dev_get_drvdata(&ofdev->dev); |
786 | 786 | ||
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 6545d1c99b61..a1c419a716af 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c | |||
@@ -560,7 +560,7 @@ static struct i2c_adapter mpc_ops = { | |||
560 | .timeout = HZ, | 560 | .timeout = HZ, |
561 | }; | 561 | }; |
562 | 562 | ||
563 | static int __devinit fsl_i2c_probe(struct of_device *op, | 563 | static int __devinit fsl_i2c_probe(struct platform_device *op, |
564 | const struct of_device_id *match) | 564 | const struct of_device_id *match) |
565 | { | 565 | { |
566 | struct mpc_i2c *i2c; | 566 | struct mpc_i2c *i2c; |
@@ -646,7 +646,7 @@ static int __devinit fsl_i2c_probe(struct of_device *op, | |||
646 | return result; | 646 | return result; |
647 | }; | 647 | }; |
648 | 648 | ||
649 | static int __devexit fsl_i2c_remove(struct of_device *op) | 649 | static int __devexit fsl_i2c_remove(struct platform_device *op) |
650 | { | 650 | { |
651 | struct mpc_i2c *i2c = dev_get_drvdata(&op->dev); | 651 | struct mpc_i2c *i2c = dev_get_drvdata(&op->dev); |
652 | 652 | ||
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index df937df845eb..6649176de940 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -20,7 +20,9 @@ | |||
20 | /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>. | 20 | /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>. |
21 | All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl> | 21 | All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl> |
22 | SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and | 22 | SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and |
23 | Jean Delvare <khali@linux-fr.org> */ | 23 | Jean Delvare <khali@linux-fr.org> |
24 | Mux support by Rodolfo Giometti <giometti@enneenne.com> and | ||
25 | Michael Lawnick <michael.lawnick.ext@nsn.com> */ | ||
24 | 26 | ||
25 | #include <linux/module.h> | 27 | #include <linux/module.h> |
26 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
@@ -423,11 +425,87 @@ static int __i2c_check_addr_busy(struct device *dev, void *addrp) | |||
423 | return 0; | 425 | return 0; |
424 | } | 426 | } |
425 | 427 | ||
428 | /* walk up mux tree */ | ||
429 | static int i2c_check_mux_parents(struct i2c_adapter *adapter, int addr) | ||
430 | { | ||
431 | int result; | ||
432 | |||
433 | result = device_for_each_child(&adapter->dev, &addr, | ||
434 | __i2c_check_addr_busy); | ||
435 | |||
436 | if (!result && i2c_parent_is_i2c_adapter(adapter)) | ||
437 | result = i2c_check_mux_parents( | ||
438 | to_i2c_adapter(adapter->dev.parent), addr); | ||
439 | |||
440 | return result; | ||
441 | } | ||
442 | |||
443 | /* recurse down mux tree */ | ||
444 | static int i2c_check_mux_children(struct device *dev, void *addrp) | ||
445 | { | ||
446 | int result; | ||
447 | |||
448 | if (dev->type == &i2c_adapter_type) | ||
449 | result = device_for_each_child(dev, addrp, | ||
450 | i2c_check_mux_children); | ||
451 | else | ||
452 | result = __i2c_check_addr_busy(dev, addrp); | ||
453 | |||
454 | return result; | ||
455 | } | ||
456 | |||
426 | static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr) | 457 | static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr) |
427 | { | 458 | { |
428 | return device_for_each_child(&adapter->dev, &addr, | 459 | int result = 0; |
429 | __i2c_check_addr_busy); | 460 | |
461 | if (i2c_parent_is_i2c_adapter(adapter)) | ||
462 | result = i2c_check_mux_parents( | ||
463 | to_i2c_adapter(adapter->dev.parent), addr); | ||
464 | |||
465 | if (!result) | ||
466 | result = device_for_each_child(&adapter->dev, &addr, | ||
467 | i2c_check_mux_children); | ||
468 | |||
469 | return result; | ||
470 | } | ||
471 | |||
472 | /** | ||
473 | * i2c_lock_adapter - Get exclusive access to an I2C bus segment | ||
474 | * @adapter: Target I2C bus segment | ||
475 | */ | ||
476 | void i2c_lock_adapter(struct i2c_adapter *adapter) | ||
477 | { | ||
478 | if (i2c_parent_is_i2c_adapter(adapter)) | ||
479 | i2c_lock_adapter(to_i2c_adapter(adapter->dev.parent)); | ||
480 | else | ||
481 | rt_mutex_lock(&adapter->bus_lock); | ||
482 | } | ||
483 | EXPORT_SYMBOL_GPL(i2c_lock_adapter); | ||
484 | |||
485 | /** | ||
486 | * i2c_trylock_adapter - Try to get exclusive access to an I2C bus segment | ||
487 | * @adapter: Target I2C bus segment | ||
488 | */ | ||
489 | static int i2c_trylock_adapter(struct i2c_adapter *adapter) | ||
490 | { | ||
491 | if (i2c_parent_is_i2c_adapter(adapter)) | ||
492 | return i2c_trylock_adapter(to_i2c_adapter(adapter->dev.parent)); | ||
493 | else | ||
494 | return rt_mutex_trylock(&adapter->bus_lock); | ||
495 | } | ||
496 | |||
497 | /** | ||
498 | * i2c_unlock_adapter - Release exclusive access to an I2C bus segment | ||
499 | * @adapter: Target I2C bus segment | ||
500 | */ | ||
501 | void i2c_unlock_adapter(struct i2c_adapter *adapter) | ||
502 | { | ||
503 | if (i2c_parent_is_i2c_adapter(adapter)) | ||
504 | i2c_unlock_adapter(to_i2c_adapter(adapter->dev.parent)); | ||
505 | else | ||
506 | rt_mutex_unlock(&adapter->bus_lock); | ||
430 | } | 507 | } |
508 | EXPORT_SYMBOL_GPL(i2c_unlock_adapter); | ||
431 | 509 | ||
432 | /** | 510 | /** |
433 | * i2c_new_device - instantiate an i2c device | 511 | * i2c_new_device - instantiate an i2c device |
@@ -633,9 +711,9 @@ i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr, | |||
633 | return -EINVAL; | 711 | return -EINVAL; |
634 | 712 | ||
635 | /* Keep track of the added device */ | 713 | /* Keep track of the added device */ |
636 | i2c_lock_adapter(adap); | 714 | mutex_lock(&adap->userspace_clients_lock); |
637 | list_add_tail(&client->detected, &adap->userspace_clients); | 715 | list_add_tail(&client->detected, &adap->userspace_clients); |
638 | i2c_unlock_adapter(adap); | 716 | mutex_unlock(&adap->userspace_clients_lock); |
639 | dev_info(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device", | 717 | dev_info(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device", |
640 | info.type, info.addr); | 718 | info.type, info.addr); |
641 | 719 | ||
@@ -674,7 +752,7 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr, | |||
674 | 752 | ||
675 | /* Make sure the device was added through sysfs */ | 753 | /* Make sure the device was added through sysfs */ |
676 | res = -ENOENT; | 754 | res = -ENOENT; |
677 | i2c_lock_adapter(adap); | 755 | mutex_lock(&adap->userspace_clients_lock); |
678 | list_for_each_entry_safe(client, next, &adap->userspace_clients, | 756 | list_for_each_entry_safe(client, next, &adap->userspace_clients, |
679 | detected) { | 757 | detected) { |
680 | if (client->addr == addr) { | 758 | if (client->addr == addr) { |
@@ -687,7 +765,7 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr, | |||
687 | break; | 765 | break; |
688 | } | 766 | } |
689 | } | 767 | } |
690 | i2c_unlock_adapter(adap); | 768 | mutex_unlock(&adap->userspace_clients_lock); |
691 | 769 | ||
692 | if (res < 0) | 770 | if (res < 0) |
693 | dev_err(dev, "%s: Can't find device in list\n", | 771 | dev_err(dev, "%s: Can't find device in list\n", |
@@ -714,10 +792,11 @@ static const struct attribute_group *i2c_adapter_attr_groups[] = { | |||
714 | NULL | 792 | NULL |
715 | }; | 793 | }; |
716 | 794 | ||
717 | static struct device_type i2c_adapter_type = { | 795 | struct device_type i2c_adapter_type = { |
718 | .groups = i2c_adapter_attr_groups, | 796 | .groups = i2c_adapter_attr_groups, |
719 | .release = i2c_adapter_dev_release, | 797 | .release = i2c_adapter_dev_release, |
720 | }; | 798 | }; |
799 | EXPORT_SYMBOL_GPL(i2c_adapter_type); | ||
721 | 800 | ||
722 | #ifdef CONFIG_I2C_COMPAT | 801 | #ifdef CONFIG_I2C_COMPAT |
723 | static struct class_compat *i2c_adapter_compat_class; | 802 | static struct class_compat *i2c_adapter_compat_class; |
@@ -760,7 +839,7 @@ static int __process_new_adapter(struct device_driver *d, void *data) | |||
760 | 839 | ||
761 | static int i2c_register_adapter(struct i2c_adapter *adap) | 840 | static int i2c_register_adapter(struct i2c_adapter *adap) |
762 | { | 841 | { |
763 | int res = 0, dummy; | 842 | int res = 0; |
764 | 843 | ||
765 | /* Can't register until after driver model init */ | 844 | /* Can't register until after driver model init */ |
766 | if (unlikely(WARN_ON(!i2c_bus_type.p))) { | 845 | if (unlikely(WARN_ON(!i2c_bus_type.p))) { |
@@ -769,6 +848,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap) | |||
769 | } | 848 | } |
770 | 849 | ||
771 | rt_mutex_init(&adap->bus_lock); | 850 | rt_mutex_init(&adap->bus_lock); |
851 | mutex_init(&adap->userspace_clients_lock); | ||
772 | INIT_LIST_HEAD(&adap->userspace_clients); | 852 | INIT_LIST_HEAD(&adap->userspace_clients); |
773 | 853 | ||
774 | /* Set default timeout to 1 second if not already set */ | 854 | /* Set default timeout to 1 second if not already set */ |
@@ -801,8 +881,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap) | |||
801 | 881 | ||
802 | /* Notify drivers */ | 882 | /* Notify drivers */ |
803 | mutex_lock(&core_lock); | 883 | mutex_lock(&core_lock); |
804 | dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap, | 884 | bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter); |
805 | __process_new_adapter); | ||
806 | mutex_unlock(&core_lock); | 885 | mutex_unlock(&core_lock); |
807 | 886 | ||
808 | return 0; | 887 | return 0; |
@@ -975,7 +1054,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
975 | return res; | 1054 | return res; |
976 | 1055 | ||
977 | /* Remove devices instantiated from sysfs */ | 1056 | /* Remove devices instantiated from sysfs */ |
978 | i2c_lock_adapter(adap); | 1057 | mutex_lock(&adap->userspace_clients_lock); |
979 | list_for_each_entry_safe(client, next, &adap->userspace_clients, | 1058 | list_for_each_entry_safe(client, next, &adap->userspace_clients, |
980 | detected) { | 1059 | detected) { |
981 | dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name, | 1060 | dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name, |
@@ -983,7 +1062,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
983 | list_del(&client->detected); | 1062 | list_del(&client->detected); |
984 | i2c_unregister_device(client); | 1063 | i2c_unregister_device(client); |
985 | } | 1064 | } |
986 | i2c_unlock_adapter(adap); | 1065 | mutex_unlock(&adap->userspace_clients_lock); |
987 | 1066 | ||
988 | /* Detach any active clients. This can't fail, thus we do not | 1067 | /* Detach any active clients. This can't fail, thus we do not |
989 | checking the returned value. */ | 1068 | checking the returned value. */ |
@@ -1238,12 +1317,12 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) | |||
1238 | #endif | 1317 | #endif |
1239 | 1318 | ||
1240 | if (in_atomic() || irqs_disabled()) { | 1319 | if (in_atomic() || irqs_disabled()) { |
1241 | ret = rt_mutex_trylock(&adap->bus_lock); | 1320 | ret = i2c_trylock_adapter(adap); |
1242 | if (!ret) | 1321 | if (!ret) |
1243 | /* I2C activity is ongoing. */ | 1322 | /* I2C activity is ongoing. */ |
1244 | return -EAGAIN; | 1323 | return -EAGAIN; |
1245 | } else { | 1324 | } else { |
1246 | rt_mutex_lock(&adap->bus_lock); | 1325 | i2c_lock_adapter(adap); |
1247 | } | 1326 | } |
1248 | 1327 | ||
1249 | /* Retry automatically on arbitration loss */ | 1328 | /* Retry automatically on arbitration loss */ |
@@ -1255,7 +1334,7 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) | |||
1255 | if (time_after(jiffies, orig_jiffies + adap->timeout)) | 1334 | if (time_after(jiffies, orig_jiffies + adap->timeout)) |
1256 | break; | 1335 | break; |
1257 | } | 1336 | } |
1258 | rt_mutex_unlock(&adap->bus_lock); | 1337 | i2c_unlock_adapter(adap); |
1259 | 1338 | ||
1260 | return ret; | 1339 | return ret; |
1261 | } else { | 1340 | } else { |
@@ -1350,13 +1429,17 @@ static int i2c_default_probe(struct i2c_adapter *adap, unsigned short addr) | |||
1350 | I2C_SMBUS_BYTE_DATA, &dummy); | 1429 | I2C_SMBUS_BYTE_DATA, &dummy); |
1351 | else | 1430 | else |
1352 | #endif | 1431 | #endif |
1353 | if ((addr & ~0x07) == 0x30 || (addr & ~0x0f) == 0x50 | 1432 | if (!((addr & ~0x07) == 0x30 || (addr & ~0x0f) == 0x50) |
1354 | || !i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK)) | 1433 | && i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK)) |
1355 | err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0, | ||
1356 | I2C_SMBUS_BYTE, &dummy); | ||
1357 | else | ||
1358 | err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_WRITE, 0, | 1434 | err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_WRITE, 0, |
1359 | I2C_SMBUS_QUICK, NULL); | 1435 | I2C_SMBUS_QUICK, NULL); |
1436 | else if (i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE)) | ||
1437 | err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0, | ||
1438 | I2C_SMBUS_BYTE, &dummy); | ||
1439 | else { | ||
1440 | dev_warn(&adap->dev, "No suitable probing method supported\n"); | ||
1441 | err = -EOPNOTSUPP; | ||
1442 | } | ||
1360 | 1443 | ||
1361 | return err >= 0; | 1444 | return err >= 0; |
1362 | } | 1445 | } |
@@ -1437,16 +1520,6 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) | |||
1437 | if (!(adapter->class & driver->class)) | 1520 | if (!(adapter->class & driver->class)) |
1438 | goto exit_free; | 1521 | goto exit_free; |
1439 | 1522 | ||
1440 | /* Stop here if the bus doesn't support probing */ | ||
1441 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE)) { | ||
1442 | if (address_list[0] == I2C_CLIENT_END) | ||
1443 | goto exit_free; | ||
1444 | |||
1445 | dev_warn(&adapter->dev, "Probing not supported\n"); | ||
1446 | err = -EOPNOTSUPP; | ||
1447 | goto exit_free; | ||
1448 | } | ||
1449 | |||
1450 | for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) { | 1523 | for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) { |
1451 | dev_dbg(&adapter->dev, "found normal entry for adapter %d, " | 1524 | dev_dbg(&adapter->dev, "found normal entry for adapter %d, " |
1452 | "addr 0x%02x\n", adap_id, address_list[i]); | 1525 | "addr 0x%02x\n", adap_id, address_list[i]); |
@@ -1461,18 +1534,23 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) | |||
1461 | return err; | 1534 | return err; |
1462 | } | 1535 | } |
1463 | 1536 | ||
1537 | int i2c_probe_func_quick_read(struct i2c_adapter *adap, unsigned short addr) | ||
1538 | { | ||
1539 | return i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0, | ||
1540 | I2C_SMBUS_QUICK, NULL) >= 0; | ||
1541 | } | ||
1542 | EXPORT_SYMBOL_GPL(i2c_probe_func_quick_read); | ||
1543 | |||
1464 | struct i2c_client * | 1544 | struct i2c_client * |
1465 | i2c_new_probed_device(struct i2c_adapter *adap, | 1545 | i2c_new_probed_device(struct i2c_adapter *adap, |
1466 | struct i2c_board_info *info, | 1546 | struct i2c_board_info *info, |
1467 | unsigned short const *addr_list) | 1547 | unsigned short const *addr_list, |
1548 | int (*probe)(struct i2c_adapter *, unsigned short addr)) | ||
1468 | { | 1549 | { |
1469 | int i; | 1550 | int i; |
1470 | 1551 | ||
1471 | /* Stop here if the bus doesn't support probing */ | 1552 | if (!probe) |
1472 | if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE)) { | 1553 | probe = i2c_default_probe; |
1473 | dev_err(&adap->dev, "Probing not supported\n"); | ||
1474 | return NULL; | ||
1475 | } | ||
1476 | 1554 | ||
1477 | for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) { | 1555 | for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) { |
1478 | /* Check address validity */ | 1556 | /* Check address validity */ |
@@ -1490,7 +1568,7 @@ i2c_new_probed_device(struct i2c_adapter *adap, | |||
1490 | } | 1568 | } |
1491 | 1569 | ||
1492 | /* Test address responsiveness */ | 1570 | /* Test address responsiveness */ |
1493 | if (i2c_default_probe(adap, addr_list[i])) | 1571 | if (probe(adap, addr_list[i])) |
1494 | break; | 1572 | break; |
1495 | } | 1573 | } |
1496 | 1574 | ||
@@ -2002,7 +2080,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, | |||
2002 | flags &= I2C_M_TEN | I2C_CLIENT_PEC; | 2080 | flags &= I2C_M_TEN | I2C_CLIENT_PEC; |
2003 | 2081 | ||
2004 | if (adapter->algo->smbus_xfer) { | 2082 | if (adapter->algo->smbus_xfer) { |
2005 | rt_mutex_lock(&adapter->bus_lock); | 2083 | i2c_lock_adapter(adapter); |
2006 | 2084 | ||
2007 | /* Retry automatically on arbitration loss */ | 2085 | /* Retry automatically on arbitration loss */ |
2008 | orig_jiffies = jiffies; | 2086 | orig_jiffies = jiffies; |
@@ -2016,7 +2094,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, | |||
2016 | orig_jiffies + adapter->timeout)) | 2094 | orig_jiffies + adapter->timeout)) |
2017 | break; | 2095 | break; |
2018 | } | 2096 | } |
2019 | rt_mutex_unlock(&adapter->bus_lock); | 2097 | i2c_unlock_adapter(adapter); |
2020 | } else | 2098 | } else |
2021 | res = i2c_smbus_xfer_emulated(adapter, addr, flags, read_write, | 2099 | res = i2c_smbus_xfer_emulated(adapter, addr, flags, read_write, |
2022 | command, protocol, data); | 2100 | command, protocol, data); |
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index e0694e4d86c7..5f3a52d517c3 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c | |||
@@ -167,13 +167,9 @@ static ssize_t i2cdev_write(struct file *file, const char __user *buf, | |||
167 | if (count > 8192) | 167 | if (count > 8192) |
168 | count = 8192; | 168 | count = 8192; |
169 | 169 | ||
170 | tmp = kmalloc(count, GFP_KERNEL); | 170 | tmp = memdup_user(buf, count); |
171 | if (tmp == NULL) | 171 | if (IS_ERR(tmp)) |
172 | return -ENOMEM; | 172 | return PTR_ERR(tmp); |
173 | if (copy_from_user(tmp, buf, count)) { | ||
174 | kfree(tmp); | ||
175 | return -EFAULT; | ||
176 | } | ||
177 | 173 | ||
178 | pr_debug("i2c-dev: i2c-%d writing %zu bytes.\n", | 174 | pr_debug("i2c-dev: i2c-%d writing %zu bytes.\n", |
179 | iminor(file->f_path.dentry->d_inode), count); | 175 | iminor(file->f_path.dentry->d_inode), count); |
@@ -193,12 +189,50 @@ static int i2cdev_check(struct device *dev, void *addrp) | |||
193 | return dev->driver ? -EBUSY : 0; | 189 | return dev->driver ? -EBUSY : 0; |
194 | } | 190 | } |
195 | 191 | ||
192 | /* walk up mux tree */ | ||
193 | static int i2cdev_check_mux_parents(struct i2c_adapter *adapter, int addr) | ||
194 | { | ||
195 | int result; | ||
196 | |||
197 | result = device_for_each_child(&adapter->dev, &addr, i2cdev_check); | ||
198 | |||
199 | if (!result && i2c_parent_is_i2c_adapter(adapter)) | ||
200 | result = i2cdev_check_mux_parents( | ||
201 | to_i2c_adapter(adapter->dev.parent), addr); | ||
202 | |||
203 | return result; | ||
204 | } | ||
205 | |||
206 | /* recurse down mux tree */ | ||
207 | static int i2cdev_check_mux_children(struct device *dev, void *addrp) | ||
208 | { | ||
209 | int result; | ||
210 | |||
211 | if (dev->type == &i2c_adapter_type) | ||
212 | result = device_for_each_child(dev, addrp, | ||
213 | i2cdev_check_mux_children); | ||
214 | else | ||
215 | result = i2cdev_check(dev, addrp); | ||
216 | |||
217 | return result; | ||
218 | } | ||
219 | |||
196 | /* This address checking function differs from the one in i2c-core | 220 | /* This address checking function differs from the one in i2c-core |
197 | in that it considers an address with a registered device, but no | 221 | in that it considers an address with a registered device, but no |
198 | driver bound to it, as NOT busy. */ | 222 | driver bound to it, as NOT busy. */ |
199 | static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) | 223 | static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) |
200 | { | 224 | { |
201 | return device_for_each_child(&adapter->dev, &addr, i2cdev_check); | 225 | int result = 0; |
226 | |||
227 | if (i2c_parent_is_i2c_adapter(adapter)) | ||
228 | result = i2cdev_check_mux_parents( | ||
229 | to_i2c_adapter(adapter->dev.parent), addr); | ||
230 | |||
231 | if (!result) | ||
232 | result = device_for_each_child(&adapter->dev, &addr, | ||
233 | i2cdev_check_mux_children); | ||
234 | |||
235 | return result; | ||
202 | } | 236 | } |
203 | 237 | ||
204 | static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, | 238 | static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, |
@@ -219,9 +253,7 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, | |||
219 | if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS) | 253 | if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS) |
220 | return -EINVAL; | 254 | return -EINVAL; |
221 | 255 | ||
222 | rdwr_pa = (struct i2c_msg *) | 256 | rdwr_pa = kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), GFP_KERNEL); |
223 | kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), | ||
224 | GFP_KERNEL); | ||
225 | if (!rdwr_pa) | 257 | if (!rdwr_pa) |
226 | return -ENOMEM; | 258 | return -ENOMEM; |
227 | 259 | ||
@@ -247,15 +279,9 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, | |||
247 | break; | 279 | break; |
248 | } | 280 | } |
249 | data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; | 281 | data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; |
250 | rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL); | 282 | rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len); |
251 | if (rdwr_pa[i].buf == NULL) { | 283 | if (IS_ERR(rdwr_pa[i].buf)) { |
252 | res = -ENOMEM; | 284 | res = PTR_ERR(rdwr_pa[i].buf); |
253 | break; | ||
254 | } | ||
255 | if (copy_from_user(rdwr_pa[i].buf, data_ptrs[i], | ||
256 | rdwr_pa[i].len)) { | ||
257 | ++i; /* Needs to be kfreed too */ | ||
258 | res = -EFAULT; | ||
259 | break; | 285 | break; |
260 | } | 286 | } |
261 | } | 287 | } |
diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c new file mode 100644 index 000000000000..d32a4843fc3a --- /dev/null +++ b/drivers/i2c/i2c-mux.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * Multiplexed I2C bus driver. | ||
3 | * | ||
4 | * Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it> | ||
5 | * Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it> | ||
6 | * Copyright (c) 2009-2010 NSN GmbH & Co KG <michael.lawnick.ext@nsn.com> | ||
7 | * | ||
8 | * Simplifies access to complex multiplexed I2C bus topologies, by presenting | ||
9 | * each multiplexed bus segment as an additional I2C adapter. | ||
10 | * Supports multi-level mux'ing (mux behind a mux). | ||
11 | * | ||
12 | * Based on: | ||
13 | * i2c-virt.c from Kumar Gala <galak@kernel.crashing.org> | ||
14 | * i2c-virtual.c from Ken Harrenstien, Copyright (c) 2004 Google, Inc. | ||
15 | * i2c-virtual.c from Brian Kuschak <bkuschak@yahoo.com> | ||
16 | * | ||
17 | * This file is licensed under the terms of the GNU General Public | ||
18 | * License version 2. This program is licensed "as is" without any | ||
19 | * warranty of any kind, whether express or implied. | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/i2c.h> | ||
26 | #include <linux/i2c-mux.h> | ||
27 | |||
28 | /* multiplexer per channel data */ | ||
29 | struct i2c_mux_priv { | ||
30 | struct i2c_adapter adap; | ||
31 | struct i2c_algorithm algo; | ||
32 | |||
33 | struct i2c_adapter *parent; | ||
34 | void *mux_dev; /* the mux chip/device */ | ||
35 | u32 chan_id; /* the channel id */ | ||
36 | |||
37 | int (*select)(struct i2c_adapter *, void *mux_dev, u32 chan_id); | ||
38 | int (*deselect)(struct i2c_adapter *, void *mux_dev, u32 chan_id); | ||
39 | }; | ||
40 | |||
41 | static int i2c_mux_master_xfer(struct i2c_adapter *adap, | ||
42 | struct i2c_msg msgs[], int num) | ||
43 | { | ||
44 | struct i2c_mux_priv *priv = adap->algo_data; | ||
45 | struct i2c_adapter *parent = priv->parent; | ||
46 | int ret; | ||
47 | |||
48 | /* Switch to the right mux port and perform the transfer. */ | ||
49 | |||
50 | ret = priv->select(parent, priv->mux_dev, priv->chan_id); | ||
51 | if (ret >= 0) | ||
52 | ret = parent->algo->master_xfer(parent, msgs, num); | ||
53 | if (priv->deselect) | ||
54 | priv->deselect(parent, priv->mux_dev, priv->chan_id); | ||
55 | |||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | static int i2c_mux_smbus_xfer(struct i2c_adapter *adap, | ||
60 | u16 addr, unsigned short flags, | ||
61 | char read_write, u8 command, | ||
62 | int size, union i2c_smbus_data *data) | ||
63 | { | ||
64 | struct i2c_mux_priv *priv = adap->algo_data; | ||
65 | struct i2c_adapter *parent = priv->parent; | ||
66 | int ret; | ||
67 | |||
68 | /* Select the right mux port and perform the transfer. */ | ||
69 | |||
70 | ret = priv->select(parent, priv->mux_dev, priv->chan_id); | ||
71 | if (ret >= 0) | ||
72 | ret = parent->algo->smbus_xfer(parent, addr, flags, | ||
73 | read_write, command, size, data); | ||
74 | if (priv->deselect) | ||
75 | priv->deselect(parent, priv->mux_dev, priv->chan_id); | ||
76 | |||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | /* Return the parent's functionality */ | ||
81 | static u32 i2c_mux_functionality(struct i2c_adapter *adap) | ||
82 | { | ||
83 | struct i2c_mux_priv *priv = adap->algo_data; | ||
84 | struct i2c_adapter *parent = priv->parent; | ||
85 | |||
86 | return parent->algo->functionality(parent); | ||
87 | } | ||
88 | |||
89 | struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, | ||
90 | void *mux_dev, u32 force_nr, u32 chan_id, | ||
91 | int (*select) (struct i2c_adapter *, | ||
92 | void *, u32), | ||
93 | int (*deselect) (struct i2c_adapter *, | ||
94 | void *, u32)) | ||
95 | { | ||
96 | struct i2c_mux_priv *priv; | ||
97 | int ret; | ||
98 | |||
99 | priv = kzalloc(sizeof(struct i2c_mux_priv), GFP_KERNEL); | ||
100 | if (!priv) | ||
101 | return NULL; | ||
102 | |||
103 | /* Set up private adapter data */ | ||
104 | priv->parent = parent; | ||
105 | priv->mux_dev = mux_dev; | ||
106 | priv->chan_id = chan_id; | ||
107 | priv->select = select; | ||
108 | priv->deselect = deselect; | ||
109 | |||
110 | /* Need to do algo dynamically because we don't know ahead | ||
111 | * of time what sort of physical adapter we'll be dealing with. | ||
112 | */ | ||
113 | if (parent->algo->master_xfer) | ||
114 | priv->algo.master_xfer = i2c_mux_master_xfer; | ||
115 | if (parent->algo->smbus_xfer) | ||
116 | priv->algo.smbus_xfer = i2c_mux_smbus_xfer; | ||
117 | priv->algo.functionality = i2c_mux_functionality; | ||
118 | |||
119 | /* Now fill out new adapter structure */ | ||
120 | snprintf(priv->adap.name, sizeof(priv->adap.name), | ||
121 | "i2c-%d-mux (chan_id %d)", i2c_adapter_id(parent), chan_id); | ||
122 | priv->adap.owner = THIS_MODULE; | ||
123 | priv->adap.id = parent->id; | ||
124 | priv->adap.algo = &priv->algo; | ||
125 | priv->adap.algo_data = priv; | ||
126 | priv->adap.dev.parent = &parent->dev; | ||
127 | |||
128 | if (force_nr) { | ||
129 | priv->adap.nr = force_nr; | ||
130 | ret = i2c_add_numbered_adapter(&priv->adap); | ||
131 | } else { | ||
132 | ret = i2c_add_adapter(&priv->adap); | ||
133 | } | ||
134 | if (ret < 0) { | ||
135 | dev_err(&parent->dev, | ||
136 | "failed to add mux-adapter (error=%d)\n", | ||
137 | ret); | ||
138 | kfree(priv); | ||
139 | return NULL; | ||
140 | } | ||
141 | |||
142 | dev_info(&parent->dev, "Added multiplexed i2c bus %d\n", | ||
143 | i2c_adapter_id(&priv->adap)); | ||
144 | |||
145 | return &priv->adap; | ||
146 | } | ||
147 | EXPORT_SYMBOL_GPL(i2c_add_mux_adapter); | ||
148 | |||
149 | int i2c_del_mux_adapter(struct i2c_adapter *adap) | ||
150 | { | ||
151 | struct i2c_mux_priv *priv = adap->algo_data; | ||
152 | int ret; | ||
153 | |||
154 | ret = i2c_del_adapter(adap); | ||
155 | if (ret < 0) | ||
156 | return ret; | ||
157 | kfree(priv); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | EXPORT_SYMBOL_GPL(i2c_del_mux_adapter); | ||
162 | |||
163 | MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); | ||
164 | MODULE_DESCRIPTION("I2C driver for multiplexed I2C busses"); | ||
165 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig new file mode 100644 index 000000000000..4c9a99c4fcb0 --- /dev/null +++ b/drivers/i2c/muxes/Kconfig | |||
@@ -0,0 +1,18 @@ | |||
1 | # | ||
2 | # Multiplexer I2C chip drivers configuration | ||
3 | # | ||
4 | |||
5 | menu "Multiplexer I2C Chip support" | ||
6 | depends on I2C_MUX | ||
7 | |||
8 | config I2C_MUX_PCA954x | ||
9 | tristate "Philips PCA954x I2C Mux/switches" | ||
10 | depends on EXPERIMENTAL | ||
11 | help | ||
12 | If you say yes here you get support for the Philips PCA954x | ||
13 | I2C mux/switch devices. | ||
14 | |||
15 | This driver can also be built as a module. If so, the module | ||
16 | will be called pca954x. | ||
17 | |||
18 | endmenu | ||
diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile new file mode 100644 index 000000000000..bd83b5274815 --- /dev/null +++ b/drivers/i2c/muxes/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # | ||
2 | # Makefile for multiplexer I2C chip drivers. | ||
3 | |||
4 | obj-$(CONFIG_I2C_MUX_PCA954x) += pca954x.o | ||
5 | |||
6 | ifeq ($(CONFIG_I2C_DEBUG_BUS),y) | ||
7 | EXTRA_CFLAGS += -DDEBUG | ||
8 | endif | ||
diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c new file mode 100644 index 000000000000..6f9accf3189d --- /dev/null +++ b/drivers/i2c/muxes/pca954x.c | |||
@@ -0,0 +1,301 @@ | |||
1 | /* | ||
2 | * I2C multiplexer | ||
3 | * | ||
4 | * Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it> | ||
5 | * Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it> | ||
6 | * | ||
7 | * This module supports the PCA954x series of I2C multiplexer/switch chips | ||
8 | * made by Philips Semiconductors. | ||
9 | * This includes the: | ||
10 | * PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547 | ||
11 | * and PCA9548. | ||
12 | * | ||
13 | * These chips are all controlled via the I2C bus itself, and all have a | ||
14 | * single 8-bit register. The upstream "parent" bus fans out to two, | ||
15 | * four, or eight downstream busses or channels; which of these | ||
16 | * are selected is determined by the chip type and register contents. A | ||
17 | * mux can select only one sub-bus at a time; a switch can select any | ||
18 | * combination simultaneously. | ||
19 | * | ||
20 | * Based on: | ||
21 | * pca954x.c from Kumar Gala <galak@kernel.crashing.org> | ||
22 | * Copyright (C) 2006 | ||
23 | * | ||
24 | * Based on: | ||
25 | * pca954x.c from Ken Harrenstien | ||
26 | * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) | ||
27 | * | ||
28 | * Based on: | ||
29 | * i2c-virtual_cb.c from Brian Kuschak <bkuschak@yahoo.com> | ||
30 | * and | ||
31 | * pca9540.c from Jean Delvare <khali@linux-fr.org>. | ||
32 | * | ||
33 | * This file is licensed under the terms of the GNU General Public | ||
34 | * License version 2. This program is licensed "as is" without any | ||
35 | * warranty of any kind, whether express or implied. | ||
36 | */ | ||
37 | |||
38 | #include <linux/module.h> | ||
39 | #include <linux/init.h> | ||
40 | #include <linux/slab.h> | ||
41 | #include <linux/device.h> | ||
42 | #include <linux/i2c.h> | ||
43 | #include <linux/i2c-mux.h> | ||
44 | |||
45 | #include <linux/i2c/pca954x.h> | ||
46 | |||
47 | #define PCA954X_MAX_NCHANS 8 | ||
48 | |||
49 | enum pca_type { | ||
50 | pca_9540, | ||
51 | pca_9542, | ||
52 | pca_9543, | ||
53 | pca_9544, | ||
54 | pca_9545, | ||
55 | pca_9546, | ||
56 | pca_9547, | ||
57 | pca_9548, | ||
58 | }; | ||
59 | |||
60 | struct pca954x { | ||
61 | enum pca_type type; | ||
62 | struct i2c_adapter *virt_adaps[PCA954X_MAX_NCHANS]; | ||
63 | |||
64 | u8 last_chan; /* last register value */ | ||
65 | }; | ||
66 | |||
67 | struct chip_desc { | ||
68 | u8 nchans; | ||
69 | u8 enable; /* used for muxes only */ | ||
70 | enum muxtype { | ||
71 | pca954x_ismux = 0, | ||
72 | pca954x_isswi | ||
73 | } muxtype; | ||
74 | }; | ||
75 | |||
76 | /* Provide specs for the PCA954x types we know about */ | ||
77 | static const struct chip_desc chips[] = { | ||
78 | [pca_9540] = { | ||
79 | .nchans = 2, | ||
80 | .enable = 0x4, | ||
81 | .muxtype = pca954x_ismux, | ||
82 | }, | ||
83 | [pca_9543] = { | ||
84 | .nchans = 2, | ||
85 | .muxtype = pca954x_isswi, | ||
86 | }, | ||
87 | [pca_9544] = { | ||
88 | .nchans = 4, | ||
89 | .enable = 0x4, | ||
90 | .muxtype = pca954x_ismux, | ||
91 | }, | ||
92 | [pca_9545] = { | ||
93 | .nchans = 4, | ||
94 | .muxtype = pca954x_isswi, | ||
95 | }, | ||
96 | [pca_9547] = { | ||
97 | .nchans = 8, | ||
98 | .enable = 0x8, | ||
99 | .muxtype = pca954x_ismux, | ||
100 | }, | ||
101 | [pca_9548] = { | ||
102 | .nchans = 8, | ||
103 | .muxtype = pca954x_isswi, | ||
104 | }, | ||
105 | }; | ||
106 | |||
107 | static const struct i2c_device_id pca954x_id[] = { | ||
108 | { "pca9540", pca_9540 }, | ||
109 | { "pca9542", pca_9540 }, | ||
110 | { "pca9543", pca_9543 }, | ||
111 | { "pca9544", pca_9544 }, | ||
112 | { "pca9545", pca_9545 }, | ||
113 | { "pca9546", pca_9545 }, | ||
114 | { "pca9547", pca_9547 }, | ||
115 | { "pca9548", pca_9548 }, | ||
116 | { } | ||
117 | }; | ||
118 | MODULE_DEVICE_TABLE(i2c, pca954x_id); | ||
119 | |||
120 | /* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() | ||
121 | for this as they will try to lock adapter a second time */ | ||
122 | static int pca954x_reg_write(struct i2c_adapter *adap, | ||
123 | struct i2c_client *client, u8 val) | ||
124 | { | ||
125 | int ret = -ENODEV; | ||
126 | |||
127 | if (adap->algo->master_xfer) { | ||
128 | struct i2c_msg msg; | ||
129 | char buf[1]; | ||
130 | |||
131 | msg.addr = client->addr; | ||
132 | msg.flags = 0; | ||
133 | msg.len = 1; | ||
134 | buf[0] = val; | ||
135 | msg.buf = buf; | ||
136 | ret = adap->algo->master_xfer(adap, &msg, 1); | ||
137 | } else { | ||
138 | union i2c_smbus_data data; | ||
139 | ret = adap->algo->smbus_xfer(adap, client->addr, | ||
140 | client->flags, | ||
141 | I2C_SMBUS_WRITE, | ||
142 | val, I2C_SMBUS_BYTE, &data); | ||
143 | } | ||
144 | |||
145 | return ret; | ||
146 | } | ||
147 | |||
148 | static int pca954x_select_chan(struct i2c_adapter *adap, | ||
149 | void *client, u32 chan) | ||
150 | { | ||
151 | struct pca954x *data = i2c_get_clientdata(client); | ||
152 | const struct chip_desc *chip = &chips[data->type]; | ||
153 | u8 regval; | ||
154 | int ret = 0; | ||
155 | |||
156 | /* we make switches look like muxes, not sure how to be smarter */ | ||
157 | if (chip->muxtype == pca954x_ismux) | ||
158 | regval = chan | chip->enable; | ||
159 | else | ||
160 | regval = 1 << chan; | ||
161 | |||
162 | /* Only select the channel if its different from the last channel */ | ||
163 | if (data->last_chan != regval) { | ||
164 | ret = pca954x_reg_write(adap, client, regval); | ||
165 | data->last_chan = regval; | ||
166 | } | ||
167 | |||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | static int pca954x_deselect_mux(struct i2c_adapter *adap, | ||
172 | void *client, u32 chan) | ||
173 | { | ||
174 | struct pca954x *data = i2c_get_clientdata(client); | ||
175 | |||
176 | /* Deselect active channel */ | ||
177 | data->last_chan = 0; | ||
178 | return pca954x_reg_write(adap, client, data->last_chan); | ||
179 | } | ||
180 | |||
181 | /* | ||
182 | * I2C init/probing/exit functions | ||
183 | */ | ||
184 | static int __devinit pca954x_probe(struct i2c_client *client, | ||
185 | const struct i2c_device_id *id) | ||
186 | { | ||
187 | struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); | ||
188 | struct pca954x_platform_data *pdata = client->dev.platform_data; | ||
189 | int num, force; | ||
190 | struct pca954x *data; | ||
191 | int ret = -ENODEV; | ||
192 | |||
193 | if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) | ||
194 | goto err; | ||
195 | |||
196 | data = kzalloc(sizeof(struct pca954x), GFP_KERNEL); | ||
197 | if (!data) { | ||
198 | ret = -ENOMEM; | ||
199 | goto err; | ||
200 | } | ||
201 | |||
202 | i2c_set_clientdata(client, data); | ||
203 | |||
204 | /* Read the mux register at addr to verify | ||
205 | * that the mux is in fact present. | ||
206 | */ | ||
207 | if (i2c_smbus_read_byte(client) < 0) { | ||
208 | dev_warn(&client->dev, "probe failed\n"); | ||
209 | goto exit_free; | ||
210 | } | ||
211 | |||
212 | data->type = id->driver_data; | ||
213 | data->last_chan = 0; /* force the first selection */ | ||
214 | |||
215 | /* Now create an adapter for each channel */ | ||
216 | for (num = 0; num < chips[data->type].nchans; num++) { | ||
217 | force = 0; /* dynamic adap number */ | ||
218 | if (pdata) { | ||
219 | if (num < pdata->num_modes) | ||
220 | /* force static number */ | ||
221 | force = pdata->modes[num].adap_id; | ||
222 | else | ||
223 | /* discard unconfigured channels */ | ||
224 | break; | ||
225 | } | ||
226 | |||
227 | data->virt_adaps[num] = | ||
228 | i2c_add_mux_adapter(adap, client, | ||
229 | force, num, pca954x_select_chan, | ||
230 | (pdata && pdata->modes[num].deselect_on_exit) | ||
231 | ? pca954x_deselect_mux : NULL); | ||
232 | |||
233 | if (data->virt_adaps[num] == NULL) { | ||
234 | ret = -ENODEV; | ||
235 | dev_err(&client->dev, | ||
236 | "failed to register multiplexed adapter" | ||
237 | " %d as bus %d\n", num, force); | ||
238 | goto virt_reg_failed; | ||
239 | } | ||
240 | } | ||
241 | |||
242 | dev_info(&client->dev, | ||
243 | "registered %d multiplexed busses for I2C %s %s\n", | ||
244 | num, chips[data->type].muxtype == pca954x_ismux | ||
245 | ? "mux" : "switch", client->name); | ||
246 | |||
247 | return 0; | ||
248 | |||
249 | virt_reg_failed: | ||
250 | for (num--; num >= 0; num--) | ||
251 | i2c_del_mux_adapter(data->virt_adaps[num]); | ||
252 | exit_free: | ||
253 | kfree(data); | ||
254 | err: | ||
255 | return ret; | ||
256 | } | ||
257 | |||
258 | static int __devexit pca954x_remove(struct i2c_client *client) | ||
259 | { | ||
260 | struct pca954x *data = i2c_get_clientdata(client); | ||
261 | const struct chip_desc *chip = &chips[data->type]; | ||
262 | int i, err; | ||
263 | |||
264 | for (i = 0; i < chip->nchans; ++i) | ||
265 | if (data->virt_adaps[i]) { | ||
266 | err = i2c_del_mux_adapter(data->virt_adaps[i]); | ||
267 | if (err) | ||
268 | return err; | ||
269 | data->virt_adaps[i] = NULL; | ||
270 | } | ||
271 | |||
272 | kfree(data); | ||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static struct i2c_driver pca954x_driver = { | ||
277 | .driver = { | ||
278 | .name = "pca954x", | ||
279 | .owner = THIS_MODULE, | ||
280 | }, | ||
281 | .probe = pca954x_probe, | ||
282 | .remove = __devexit_p(pca954x_remove), | ||
283 | .id_table = pca954x_id, | ||
284 | }; | ||
285 | |||
286 | static int __init pca954x_init(void) | ||
287 | { | ||
288 | return i2c_add_driver(&pca954x_driver); | ||
289 | } | ||
290 | |||
291 | static void __exit pca954x_exit(void) | ||
292 | { | ||
293 | i2c_del_driver(&pca954x_driver); | ||
294 | } | ||
295 | |||
296 | module_init(pca954x_init); | ||
297 | module_exit(pca954x_exit); | ||
298 | |||
299 | MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); | ||
300 | MODULE_DESCRIPTION("PCA954x I2C mux/switch driver"); | ||
301 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 3cb9c4e056ff..fa896210ed7b 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -177,7 +177,7 @@ EXPORT_SYMBOL_GPL(ide_pci_clk); | |||
177 | module_param_named(pci_clock, ide_pci_clk, int, 0); | 177 | module_param_named(pci_clock, ide_pci_clk, int, 0); |
178 | MODULE_PARM_DESC(pci_clock, "PCI bus clock frequency (in MHz)"); | 178 | MODULE_PARM_DESC(pci_clock, "PCI bus clock frequency (in MHz)"); |
179 | 179 | ||
180 | static int ide_set_dev_param_mask(const char *s, struct kernel_param *kp) | 180 | static int ide_set_dev_param_mask(const char *s, const struct kernel_param *kp) |
181 | { | 181 | { |
182 | int a, b, i, j = 1; | 182 | int a, b, i, j = 1; |
183 | unsigned int *dev_param_mask = (unsigned int *)kp->arg; | 183 | unsigned int *dev_param_mask = (unsigned int *)kp->arg; |
@@ -200,34 +200,40 @@ static int ide_set_dev_param_mask(const char *s, struct kernel_param *kp) | |||
200 | return 0; | 200 | return 0; |
201 | } | 201 | } |
202 | 202 | ||
203 | static struct kernel_param_ops param_ops_ide_dev_mask = { | ||
204 | .set = ide_set_dev_param_mask | ||
205 | }; | ||
206 | |||
207 | #define param_check_ide_dev_mask(name, p) param_check_uint(name, p) | ||
208 | |||
203 | static unsigned int ide_nodma; | 209 | static unsigned int ide_nodma; |
204 | 210 | ||
205 | module_param_call(nodma, ide_set_dev_param_mask, NULL, &ide_nodma, 0); | 211 | module_param_named(nodma, ide_nodma, ide_dev_mask, 0); |
206 | MODULE_PARM_DESC(nodma, "disallow DMA for a device"); | 212 | MODULE_PARM_DESC(nodma, "disallow DMA for a device"); |
207 | 213 | ||
208 | static unsigned int ide_noflush; | 214 | static unsigned int ide_noflush; |
209 | 215 | ||
210 | module_param_call(noflush, ide_set_dev_param_mask, NULL, &ide_noflush, 0); | 216 | module_param_named(noflush, ide_noflush, ide_dev_mask, 0); |
211 | MODULE_PARM_DESC(noflush, "disable flush requests for a device"); | 217 | MODULE_PARM_DESC(noflush, "disable flush requests for a device"); |
212 | 218 | ||
213 | static unsigned int ide_nohpa; | 219 | static unsigned int ide_nohpa; |
214 | 220 | ||
215 | module_param_call(nohpa, ide_set_dev_param_mask, NULL, &ide_nohpa, 0); | 221 | module_param_named(nohpa, ide_nohpa, ide_dev_mask, 0); |
216 | MODULE_PARM_DESC(nohpa, "disable Host Protected Area for a device"); | 222 | MODULE_PARM_DESC(nohpa, "disable Host Protected Area for a device"); |
217 | 223 | ||
218 | static unsigned int ide_noprobe; | 224 | static unsigned int ide_noprobe; |
219 | 225 | ||
220 | module_param_call(noprobe, ide_set_dev_param_mask, NULL, &ide_noprobe, 0); | 226 | module_param_named(noprobe, ide_noprobe, ide_dev_mask, 0); |
221 | MODULE_PARM_DESC(noprobe, "skip probing for a device"); | 227 | MODULE_PARM_DESC(noprobe, "skip probing for a device"); |
222 | 228 | ||
223 | static unsigned int ide_nowerr; | 229 | static unsigned int ide_nowerr; |
224 | 230 | ||
225 | module_param_call(nowerr, ide_set_dev_param_mask, NULL, &ide_nowerr, 0); | 231 | module_param_named(nowerr, ide_nowerr, ide_dev_mask, 0); |
226 | MODULE_PARM_DESC(nowerr, "ignore the ATA_DF bit for a device"); | 232 | MODULE_PARM_DESC(nowerr, "ignore the ATA_DF bit for a device"); |
227 | 233 | ||
228 | static unsigned int ide_cdroms; | 234 | static unsigned int ide_cdroms; |
229 | 235 | ||
230 | module_param_call(cdrom, ide_set_dev_param_mask, NULL, &ide_cdroms, 0); | 236 | module_param_named(cdrom, ide_cdroms, ide_dev_mask, 0); |
231 | MODULE_PARM_DESC(cdrom, "force device as a CD-ROM"); | 237 | MODULE_PARM_DESC(cdrom, "force device as a CD-ROM"); |
232 | 238 | ||
233 | struct chs_geom { | 239 | struct chs_geom { |
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 0136abd50dd4..aaf6023a4835 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h | |||
@@ -112,7 +112,7 @@ struct ehca_sport { | |||
112 | 112 | ||
113 | struct ehca_shca { | 113 | struct ehca_shca { |
114 | struct ib_device ib_device; | 114 | struct ib_device ib_device; |
115 | struct of_device *ofdev; | 115 | struct platform_device *ofdev; |
116 | u8 num_ports; | 116 | u8 num_ports; |
117 | int hw_level; | 117 | int hw_level; |
118 | struct list_head shca_list; | 118 | struct list_head shca_list; |
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index cfc4de7a5da4..c240e9972cb0 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c | |||
@@ -713,7 +713,7 @@ static struct attribute_group ehca_dev_attr_grp = { | |||
713 | .attrs = ehca_dev_attrs | 713 | .attrs = ehca_dev_attrs |
714 | }; | 714 | }; |
715 | 715 | ||
716 | static int __devinit ehca_probe(struct of_device *dev, | 716 | static int __devinit ehca_probe(struct platform_device *dev, |
717 | const struct of_device_id *id) | 717 | const struct of_device_id *id) |
718 | { | 718 | { |
719 | struct ehca_shca *shca; | 719 | struct ehca_shca *shca; |
@@ -879,7 +879,7 @@ probe1: | |||
879 | return -EINVAL; | 879 | return -EINVAL; |
880 | } | 880 | } |
881 | 881 | ||
882 | static int __devexit ehca_remove(struct of_device *dev) | 882 | static int __devexit ehca_remove(struct platform_device *dev) |
883 | { | 883 | { |
884 | struct ehca_shca *shca = dev_get_drvdata(&dev->dev); | 884 | struct ehca_shca *shca = dev_get_drvdata(&dev->dev); |
885 | unsigned long flags; | 885 | unsigned long flags; |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index b171f63fe4d7..9cc488d21490 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -395,6 +395,16 @@ config KEYBOARD_SH_KEYSC | |||
395 | To compile this driver as a module, choose M here: the | 395 | To compile this driver as a module, choose M here: the |
396 | module will be called sh_keysc. | 396 | module will be called sh_keysc. |
397 | 397 | ||
398 | config KEYBOARD_STMPE | ||
399 | tristate "STMPE keypad support" | ||
400 | depends on MFD_STMPE | ||
401 | help | ||
402 | Say Y here if you want to use the keypad controller on STMPE I/O | ||
403 | expanders. | ||
404 | |||
405 | To compile this driver as a module, choose M here: the module will be | ||
406 | called stmpe-keypad. | ||
407 | |||
398 | config KEYBOARD_DAVINCI | 408 | config KEYBOARD_DAVINCI |
399 | tristate "TI DaVinci Key Scan" | 409 | tristate "TI DaVinci Key Scan" |
400 | depends on ARCH_DAVINCI_DM365 | 410 | depends on ARCH_DAVINCI_DM365 |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 1a66d5f1ca8b..504b591be0cd 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -35,6 +35,7 @@ obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o | |||
35 | obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o | 35 | obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o |
36 | obj-$(CONFIG_KEYBOARD_SAMSUNG) += samsung-keypad.o | 36 | obj-$(CONFIG_KEYBOARD_SAMSUNG) += samsung-keypad.o |
37 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o | 37 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o |
38 | obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o | ||
38 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | 39 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o |
39 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o | 40 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o |
40 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o | 41 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o |
diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c new file mode 100644 index 000000000000..ab7610ca10eb --- /dev/null +++ b/drivers/input/keyboard/stmpe-keypad.c | |||
@@ -0,0 +1,386 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/input.h> | ||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/input/matrix_keypad.h> | ||
15 | #include <linux/mfd/stmpe.h> | ||
16 | |||
17 | /* These are at the same addresses in all STMPE variants */ | ||
18 | #define STMPE_KPC_COL 0x60 | ||
19 | #define STMPE_KPC_ROW_MSB 0x61 | ||
20 | #define STMPE_KPC_ROW_LSB 0x62 | ||
21 | #define STMPE_KPC_CTRL_MSB 0x63 | ||
22 | #define STMPE_KPC_CTRL_LSB 0x64 | ||
23 | #define STMPE_KPC_COMBI_KEY_0 0x65 | ||
24 | #define STMPE_KPC_COMBI_KEY_1 0x66 | ||
25 | #define STMPE_KPC_COMBI_KEY_2 0x67 | ||
26 | #define STMPE_KPC_DATA_BYTE0 0x68 | ||
27 | #define STMPE_KPC_DATA_BYTE1 0x69 | ||
28 | #define STMPE_KPC_DATA_BYTE2 0x6a | ||
29 | #define STMPE_KPC_DATA_BYTE3 0x6b | ||
30 | #define STMPE_KPC_DATA_BYTE4 0x6c | ||
31 | |||
32 | #define STMPE_KPC_CTRL_LSB_SCAN (0x1 << 0) | ||
33 | #define STMPE_KPC_CTRL_LSB_DEBOUNCE (0x7f << 1) | ||
34 | #define STMPE_KPC_CTRL_MSB_SCAN_COUNT (0xf << 4) | ||
35 | |||
36 | #define STMPE_KPC_ROW_MSB_ROWS 0xff | ||
37 | |||
38 | #define STMPE_KPC_DATA_UP (0x1 << 7) | ||
39 | #define STMPE_KPC_DATA_ROW (0xf << 3) | ||
40 | #define STMPE_KPC_DATA_COL (0x7 << 0) | ||
41 | #define STMPE_KPC_DATA_NOKEY_MASK 0x78 | ||
42 | |||
43 | #define STMPE_KEYPAD_MAX_DEBOUNCE 127 | ||
44 | #define STMPE_KEYPAD_MAX_SCAN_COUNT 15 | ||
45 | |||
46 | #define STMPE_KEYPAD_MAX_ROWS 8 | ||
47 | #define STMPE_KEYPAD_MAX_COLS 8 | ||
48 | #define STMPE_KEYPAD_ROW_SHIFT 3 | ||
49 | #define STMPE_KEYPAD_KEYMAP_SIZE \ | ||
50 | (STMPE_KEYPAD_MAX_ROWS * STMPE_KEYPAD_MAX_COLS) | ||
51 | |||
52 | /** | ||
53 | * struct stmpe_keypad_variant - model-specific attributes | ||
54 | * @auto_increment: whether the KPC_DATA_BYTE register address | ||
55 | * auto-increments on multiple read | ||
56 | * @num_data: number of data bytes | ||
57 | * @num_normal_data: number of normal keys' data bytes | ||
58 | * @max_cols: maximum number of columns supported | ||
59 | * @max_rows: maximum number of rows supported | ||
60 | * @col_gpios: bitmask of gpios which can be used for columns | ||
61 | * @row_gpios: bitmask of gpios which can be used for rows | ||
62 | */ | ||
63 | struct stmpe_keypad_variant { | ||
64 | bool auto_increment; | ||
65 | int num_data; | ||
66 | int num_normal_data; | ||
67 | int max_cols; | ||
68 | int max_rows; | ||
69 | unsigned int col_gpios; | ||
70 | unsigned int row_gpios; | ||
71 | }; | ||
72 | |||
73 | static const struct stmpe_keypad_variant stmpe_keypad_variants[] = { | ||
74 | [STMPE1601] = { | ||
75 | .auto_increment = true, | ||
76 | .num_data = 5, | ||
77 | .num_normal_data = 3, | ||
78 | .max_cols = 8, | ||
79 | .max_rows = 8, | ||
80 | .col_gpios = 0x000ff, /* GPIO 0 - 7 */ | ||
81 | .row_gpios = 0x0ff00, /* GPIO 8 - 15 */ | ||
82 | }, | ||
83 | [STMPE2401] = { | ||
84 | .auto_increment = false, | ||
85 | .num_data = 3, | ||
86 | .num_normal_data = 2, | ||
87 | .max_cols = 8, | ||
88 | .max_rows = 12, | ||
89 | .col_gpios = 0x0000ff, /* GPIO 0 - 7*/ | ||
90 | .row_gpios = 0x1fef00, /* GPIO 8-14, 16-20 */ | ||
91 | }, | ||
92 | [STMPE2403] = { | ||
93 | .auto_increment = true, | ||
94 | .num_data = 5, | ||
95 | .num_normal_data = 3, | ||
96 | .max_cols = 8, | ||
97 | .max_rows = 12, | ||
98 | .col_gpios = 0x0000ff, /* GPIO 0 - 7*/ | ||
99 | .row_gpios = 0x1fef00, /* GPIO 8-14, 16-20 */ | ||
100 | }, | ||
101 | }; | ||
102 | |||
103 | struct stmpe_keypad { | ||
104 | struct stmpe *stmpe; | ||
105 | struct input_dev *input; | ||
106 | const struct stmpe_keypad_variant *variant; | ||
107 | const struct stmpe_keypad_platform_data *plat; | ||
108 | |||
109 | unsigned int rows; | ||
110 | unsigned int cols; | ||
111 | |||
112 | unsigned short keymap[STMPE_KEYPAD_KEYMAP_SIZE]; | ||
113 | }; | ||
114 | |||
115 | static int stmpe_keypad_read_data(struct stmpe_keypad *keypad, u8 *data) | ||
116 | { | ||
117 | const struct stmpe_keypad_variant *variant = keypad->variant; | ||
118 | struct stmpe *stmpe = keypad->stmpe; | ||
119 | int ret; | ||
120 | int i; | ||
121 | |||
122 | if (variant->auto_increment) | ||
123 | return stmpe_block_read(stmpe, STMPE_KPC_DATA_BYTE0, | ||
124 | variant->num_data, data); | ||
125 | |||
126 | for (i = 0; i < variant->num_data; i++) { | ||
127 | ret = stmpe_reg_read(stmpe, STMPE_KPC_DATA_BYTE0 + i); | ||
128 | if (ret < 0) | ||
129 | return ret; | ||
130 | |||
131 | data[i] = ret; | ||
132 | } | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static irqreturn_t stmpe_keypad_irq(int irq, void *dev) | ||
138 | { | ||
139 | struct stmpe_keypad *keypad = dev; | ||
140 | struct input_dev *input = keypad->input; | ||
141 | const struct stmpe_keypad_variant *variant = keypad->variant; | ||
142 | u8 fifo[variant->num_data]; | ||
143 | int ret; | ||
144 | int i; | ||
145 | |||
146 | ret = stmpe_keypad_read_data(keypad, fifo); | ||
147 | if (ret < 0) | ||
148 | return IRQ_NONE; | ||
149 | |||
150 | for (i = 0; i < variant->num_normal_data; i++) { | ||
151 | u8 data = fifo[i]; | ||
152 | int row = (data & STMPE_KPC_DATA_ROW) >> 3; | ||
153 | int col = data & STMPE_KPC_DATA_COL; | ||
154 | int code = MATRIX_SCAN_CODE(row, col, STMPE_KEYPAD_ROW_SHIFT); | ||
155 | bool up = data & STMPE_KPC_DATA_UP; | ||
156 | |||
157 | if ((data & STMPE_KPC_DATA_NOKEY_MASK) | ||
158 | == STMPE_KPC_DATA_NOKEY_MASK) | ||
159 | continue; | ||
160 | |||
161 | input_event(input, EV_MSC, MSC_SCAN, code); | ||
162 | input_report_key(input, keypad->keymap[code], !up); | ||
163 | input_sync(input); | ||
164 | } | ||
165 | |||
166 | return IRQ_HANDLED; | ||
167 | } | ||
168 | |||
169 | static int __devinit stmpe_keypad_altfunc_init(struct stmpe_keypad *keypad) | ||
170 | { | ||
171 | const struct stmpe_keypad_variant *variant = keypad->variant; | ||
172 | unsigned int col_gpios = variant->col_gpios; | ||
173 | unsigned int row_gpios = variant->row_gpios; | ||
174 | struct stmpe *stmpe = keypad->stmpe; | ||
175 | unsigned int pins = 0; | ||
176 | int i; | ||
177 | |||
178 | /* | ||
179 | * Figure out which pins need to be set to the keypad alternate | ||
180 | * function. | ||
181 | * | ||
182 | * {cols,rows}_gpios are bitmasks of which pins on the chip can be used | ||
183 | * for the keypad. | ||
184 | * | ||
185 | * keypad->{cols,rows} are a bitmask of which pins (of the ones useable | ||
186 | * for the keypad) are used on the board. | ||
187 | */ | ||
188 | |||
189 | for (i = 0; i < variant->max_cols; i++) { | ||
190 | int num = __ffs(col_gpios); | ||
191 | |||
192 | if (keypad->cols & (1 << i)) | ||
193 | pins |= 1 << num; | ||
194 | |||
195 | col_gpios &= ~(1 << num); | ||
196 | } | ||
197 | |||
198 | for (i = 0; i < variant->max_rows; i++) { | ||
199 | int num = __ffs(row_gpios); | ||
200 | |||
201 | if (keypad->rows & (1 << i)) | ||
202 | pins |= 1 << num; | ||
203 | |||
204 | row_gpios &= ~(1 << num); | ||
205 | } | ||
206 | |||
207 | return stmpe_set_altfunc(stmpe, pins, STMPE_BLOCK_KEYPAD); | ||
208 | } | ||
209 | |||
210 | static int __devinit stmpe_keypad_chip_init(struct stmpe_keypad *keypad) | ||
211 | { | ||
212 | const struct stmpe_keypad_platform_data *plat = keypad->plat; | ||
213 | const struct stmpe_keypad_variant *variant = keypad->variant; | ||
214 | struct stmpe *stmpe = keypad->stmpe; | ||
215 | int ret; | ||
216 | |||
217 | if (plat->debounce_ms > STMPE_KEYPAD_MAX_DEBOUNCE) | ||
218 | return -EINVAL; | ||
219 | |||
220 | if (plat->scan_count > STMPE_KEYPAD_MAX_SCAN_COUNT) | ||
221 | return -EINVAL; | ||
222 | |||
223 | ret = stmpe_enable(stmpe, STMPE_BLOCK_KEYPAD); | ||
224 | if (ret < 0) | ||
225 | return ret; | ||
226 | |||
227 | ret = stmpe_keypad_altfunc_init(keypad); | ||
228 | if (ret < 0) | ||
229 | return ret; | ||
230 | |||
231 | ret = stmpe_reg_write(stmpe, STMPE_KPC_COL, keypad->cols); | ||
232 | if (ret < 0) | ||
233 | return ret; | ||
234 | |||
235 | ret = stmpe_reg_write(stmpe, STMPE_KPC_ROW_LSB, keypad->rows); | ||
236 | if (ret < 0) | ||
237 | return ret; | ||
238 | |||
239 | if (variant->max_rows > 8) { | ||
240 | ret = stmpe_set_bits(stmpe, STMPE_KPC_ROW_MSB, | ||
241 | STMPE_KPC_ROW_MSB_ROWS, | ||
242 | keypad->rows >> 8); | ||
243 | if (ret < 0) | ||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | ret = stmpe_set_bits(stmpe, STMPE_KPC_CTRL_MSB, | ||
248 | STMPE_KPC_CTRL_MSB_SCAN_COUNT, | ||
249 | plat->scan_count << 4); | ||
250 | if (ret < 0) | ||
251 | return ret; | ||
252 | |||
253 | return stmpe_set_bits(stmpe, STMPE_KPC_CTRL_LSB, | ||
254 | STMPE_KPC_CTRL_LSB_SCAN | | ||
255 | STMPE_KPC_CTRL_LSB_DEBOUNCE, | ||
256 | STMPE_KPC_CTRL_LSB_SCAN | | ||
257 | (plat->debounce_ms << 1)); | ||
258 | } | ||
259 | |||
260 | static int __devinit stmpe_keypad_probe(struct platform_device *pdev) | ||
261 | { | ||
262 | struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); | ||
263 | struct stmpe_keypad_platform_data *plat; | ||
264 | struct stmpe_keypad *keypad; | ||
265 | struct input_dev *input; | ||
266 | int ret; | ||
267 | int irq; | ||
268 | int i; | ||
269 | |||
270 | plat = stmpe->pdata->keypad; | ||
271 | if (!plat) | ||
272 | return -ENODEV; | ||
273 | |||
274 | irq = platform_get_irq(pdev, 0); | ||
275 | if (irq < 0) | ||
276 | return irq; | ||
277 | |||
278 | keypad = kzalloc(sizeof(struct stmpe_keypad), GFP_KERNEL); | ||
279 | if (!keypad) | ||
280 | return -ENOMEM; | ||
281 | |||
282 | input = input_allocate_device(); | ||
283 | if (!input) { | ||
284 | ret = -ENOMEM; | ||
285 | goto out_freekeypad; | ||
286 | } | ||
287 | |||
288 | input->name = "STMPE keypad"; | ||
289 | input->id.bustype = BUS_I2C; | ||
290 | input->dev.parent = &pdev->dev; | ||
291 | |||
292 | input_set_capability(input, EV_MSC, MSC_SCAN); | ||
293 | |||
294 | __set_bit(EV_KEY, input->evbit); | ||
295 | if (!plat->no_autorepeat) | ||
296 | __set_bit(EV_REP, input->evbit); | ||
297 | |||
298 | input->keycode = keypad->keymap; | ||
299 | input->keycodesize = sizeof(keypad->keymap[0]); | ||
300 | input->keycodemax = ARRAY_SIZE(keypad->keymap); | ||
301 | |||
302 | matrix_keypad_build_keymap(plat->keymap_data, STMPE_KEYPAD_ROW_SHIFT, | ||
303 | input->keycode, input->keybit); | ||
304 | |||
305 | for (i = 0; i < plat->keymap_data->keymap_size; i++) { | ||
306 | unsigned int key = plat->keymap_data->keymap[i]; | ||
307 | |||
308 | keypad->cols |= 1 << KEY_COL(key); | ||
309 | keypad->rows |= 1 << KEY_ROW(key); | ||
310 | } | ||
311 | |||
312 | keypad->stmpe = stmpe; | ||
313 | keypad->plat = plat; | ||
314 | keypad->input = input; | ||
315 | keypad->variant = &stmpe_keypad_variants[stmpe->partnum]; | ||
316 | |||
317 | ret = stmpe_keypad_chip_init(keypad); | ||
318 | if (ret < 0) | ||
319 | goto out_freeinput; | ||
320 | |||
321 | ret = input_register_device(input); | ||
322 | if (ret) { | ||
323 | dev_err(&pdev->dev, | ||
324 | "unable to register input device: %d\n", ret); | ||
325 | goto out_freeinput; | ||
326 | } | ||
327 | |||
328 | ret = request_threaded_irq(irq, NULL, stmpe_keypad_irq, IRQF_ONESHOT, | ||
329 | "stmpe-keypad", keypad); | ||
330 | if (ret) { | ||
331 | dev_err(&pdev->dev, "unable to get irq: %d\n", ret); | ||
332 | goto out_unregisterinput; | ||
333 | } | ||
334 | |||
335 | platform_set_drvdata(pdev, keypad); | ||
336 | |||
337 | return 0; | ||
338 | |||
339 | out_unregisterinput: | ||
340 | input_unregister_device(input); | ||
341 | input = NULL; | ||
342 | out_freeinput: | ||
343 | input_free_device(input); | ||
344 | out_freekeypad: | ||
345 | kfree(keypad); | ||
346 | return ret; | ||
347 | } | ||
348 | |||
349 | static int __devexit stmpe_keypad_remove(struct platform_device *pdev) | ||
350 | { | ||
351 | struct stmpe_keypad *keypad = platform_get_drvdata(pdev); | ||
352 | struct stmpe *stmpe = keypad->stmpe; | ||
353 | int irq = platform_get_irq(pdev, 0); | ||
354 | |||
355 | stmpe_disable(stmpe, STMPE_BLOCK_KEYPAD); | ||
356 | |||
357 | free_irq(irq, keypad); | ||
358 | input_unregister_device(keypad->input); | ||
359 | platform_set_drvdata(pdev, NULL); | ||
360 | kfree(keypad); | ||
361 | |||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static struct platform_driver stmpe_keypad_driver = { | ||
366 | .driver.name = "stmpe-keypad", | ||
367 | .driver.owner = THIS_MODULE, | ||
368 | .probe = stmpe_keypad_probe, | ||
369 | .remove = __devexit_p(stmpe_keypad_remove), | ||
370 | }; | ||
371 | |||
372 | static int __init stmpe_keypad_init(void) | ||
373 | { | ||
374 | return platform_driver_register(&stmpe_keypad_driver); | ||
375 | } | ||
376 | module_init(stmpe_keypad_init); | ||
377 | |||
378 | static void __exit stmpe_keypad_exit(void) | ||
379 | { | ||
380 | platform_driver_unregister(&stmpe_keypad_driver); | ||
381 | } | ||
382 | module_exit(stmpe_keypad_exit); | ||
383 | |||
384 | MODULE_LICENSE("GPL v2"); | ||
385 | MODULE_DESCRIPTION("STMPExxxx keypad driver"); | ||
386 | MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>"); | ||
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index e148749b5851..23257652b8e8 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c | |||
@@ -38,7 +38,8 @@ enum { | |||
38 | }; | 38 | }; |
39 | 39 | ||
40 | static int ati_remote2_set_mask(const char *val, | 40 | static int ati_remote2_set_mask(const char *val, |
41 | struct kernel_param *kp, unsigned int max) | 41 | const struct kernel_param *kp, |
42 | unsigned int max) | ||
42 | { | 43 | { |
43 | unsigned long mask; | 44 | unsigned long mask; |
44 | int ret; | 45 | int ret; |
@@ -59,28 +60,31 @@ static int ati_remote2_set_mask(const char *val, | |||
59 | } | 60 | } |
60 | 61 | ||
61 | static int ati_remote2_set_channel_mask(const char *val, | 62 | static int ati_remote2_set_channel_mask(const char *val, |
62 | struct kernel_param *kp) | 63 | const struct kernel_param *kp) |
63 | { | 64 | { |
64 | pr_debug("%s()\n", __func__); | 65 | pr_debug("%s()\n", __func__); |
65 | 66 | ||
66 | return ati_remote2_set_mask(val, kp, ATI_REMOTE2_MAX_CHANNEL_MASK); | 67 | return ati_remote2_set_mask(val, kp, ATI_REMOTE2_MAX_CHANNEL_MASK); |
67 | } | 68 | } |
68 | 69 | ||
69 | static int ati_remote2_get_channel_mask(char *buffer, struct kernel_param *kp) | 70 | static int ati_remote2_get_channel_mask(char *buffer, |
71 | const struct kernel_param *kp) | ||
70 | { | 72 | { |
71 | pr_debug("%s()\n", __func__); | 73 | pr_debug("%s()\n", __func__); |
72 | 74 | ||
73 | return sprintf(buffer, "0x%04x", *(unsigned int *)kp->arg); | 75 | return sprintf(buffer, "0x%04x", *(unsigned int *)kp->arg); |
74 | } | 76 | } |
75 | 77 | ||
76 | static int ati_remote2_set_mode_mask(const char *val, struct kernel_param *kp) | 78 | static int ati_remote2_set_mode_mask(const char *val, |
79 | const struct kernel_param *kp) | ||
77 | { | 80 | { |
78 | pr_debug("%s()\n", __func__); | 81 | pr_debug("%s()\n", __func__); |
79 | 82 | ||
80 | return ati_remote2_set_mask(val, kp, ATI_REMOTE2_MAX_MODE_MASK); | 83 | return ati_remote2_set_mask(val, kp, ATI_REMOTE2_MAX_MODE_MASK); |
81 | } | 84 | } |
82 | 85 | ||
83 | static int ati_remote2_get_mode_mask(char *buffer, struct kernel_param *kp) | 86 | static int ati_remote2_get_mode_mask(char *buffer, |
87 | const struct kernel_param *kp) | ||
84 | { | 88 | { |
85 | pr_debug("%s()\n", __func__); | 89 | pr_debug("%s()\n", __func__); |
86 | 90 | ||
@@ -89,15 +93,19 @@ static int ati_remote2_get_mode_mask(char *buffer, struct kernel_param *kp) | |||
89 | 93 | ||
90 | static unsigned int channel_mask = ATI_REMOTE2_MAX_CHANNEL_MASK; | 94 | static unsigned int channel_mask = ATI_REMOTE2_MAX_CHANNEL_MASK; |
91 | #define param_check_channel_mask(name, p) __param_check(name, p, unsigned int) | 95 | #define param_check_channel_mask(name, p) __param_check(name, p, unsigned int) |
92 | #define param_set_channel_mask ati_remote2_set_channel_mask | 96 | static struct kernel_param_ops param_ops_channel_mask = { |
93 | #define param_get_channel_mask ati_remote2_get_channel_mask | 97 | .set = ati_remote2_set_channel_mask, |
98 | .get = ati_remote2_get_channel_mask, | ||
99 | }; | ||
94 | module_param(channel_mask, channel_mask, 0644); | 100 | module_param(channel_mask, channel_mask, 0644); |
95 | MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>"); | 101 | MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>"); |
96 | 102 | ||
97 | static unsigned int mode_mask = ATI_REMOTE2_MAX_MODE_MASK; | 103 | static unsigned int mode_mask = ATI_REMOTE2_MAX_MODE_MASK; |
98 | #define param_check_mode_mask(name, p) __param_check(name, p, unsigned int) | 104 | #define param_check_mode_mask(name, p) __param_check(name, p, unsigned int) |
99 | #define param_set_mode_mask ati_remote2_set_mode_mask | 105 | static struct kernel_param_ops param_ops_mode_mask = { |
100 | #define param_get_mode_mask ati_remote2_get_mode_mask | 106 | .set = ati_remote2_set_mode_mask, |
107 | .get = ati_remote2_get_mode_mask, | ||
108 | }; | ||
101 | module_param(mode_mask, mode_mask, 0644); | 109 | module_param(mode_mask, mode_mask, 0644); |
102 | MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>"); | 110 | MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>"); |
103 | 111 | ||
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index f3bb92e9755f..8e130bf7d32b 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c | |||
@@ -173,7 +173,7 @@ static int __devinit sparcspkr_probe(struct device *dev) | |||
173 | return 0; | 173 | return 0; |
174 | } | 174 | } |
175 | 175 | ||
176 | static int sparcspkr_shutdown(struct of_device *dev) | 176 | static int sparcspkr_shutdown(struct platform_device *dev) |
177 | { | 177 | { |
178 | struct sparcspkr_state *state = dev_get_drvdata(&dev->dev); | 178 | struct sparcspkr_state *state = dev_get_drvdata(&dev->dev); |
179 | struct input_dev *input_dev = state->input_dev; | 179 | struct input_dev *input_dev = state->input_dev; |
@@ -184,7 +184,7 @@ static int sparcspkr_shutdown(struct of_device *dev) | |||
184 | return 0; | 184 | return 0; |
185 | } | 185 | } |
186 | 186 | ||
187 | static int __devinit bbc_beep_probe(struct of_device *op, const struct of_device_id *match) | 187 | static int __devinit bbc_beep_probe(struct platform_device *op, const struct of_device_id *match) |
188 | { | 188 | { |
189 | struct sparcspkr_state *state; | 189 | struct sparcspkr_state *state; |
190 | struct bbc_beep_info *info; | 190 | struct bbc_beep_info *info; |
@@ -231,7 +231,7 @@ out_err: | |||
231 | return err; | 231 | return err; |
232 | } | 232 | } |
233 | 233 | ||
234 | static int __devexit bbc_remove(struct of_device *op) | 234 | static int __devexit bbc_remove(struct platform_device *op) |
235 | { | 235 | { |
236 | struct sparcspkr_state *state = dev_get_drvdata(&op->dev); | 236 | struct sparcspkr_state *state = dev_get_drvdata(&op->dev); |
237 | struct input_dev *input_dev = state->input_dev; | 237 | struct input_dev *input_dev = state->input_dev; |
@@ -269,7 +269,7 @@ static struct of_platform_driver bbc_beep_driver = { | |||
269 | .shutdown = sparcspkr_shutdown, | 269 | .shutdown = sparcspkr_shutdown, |
270 | }; | 270 | }; |
271 | 271 | ||
272 | static int __devinit grover_beep_probe(struct of_device *op, const struct of_device_id *match) | 272 | static int __devinit grover_beep_probe(struct platform_device *op, const struct of_device_id *match) |
273 | { | 273 | { |
274 | struct sparcspkr_state *state; | 274 | struct sparcspkr_state *state; |
275 | struct grover_beep_info *info; | 275 | struct grover_beep_info *info; |
@@ -312,7 +312,7 @@ out_err: | |||
312 | return err; | 312 | return err; |
313 | } | 313 | } |
314 | 314 | ||
315 | static int __devexit grover_remove(struct of_device *op) | 315 | static int __devexit grover_remove(struct platform_device *op) |
316 | { | 316 | { |
317 | struct sparcspkr_state *state = dev_get_drvdata(&op->dev); | 317 | struct sparcspkr_state *state = dev_get_drvdata(&op->dev); |
318 | struct grover_beep_info *info = &state->u.grover; | 318 | struct grover_beep_info *info = &state->u.grover; |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 979c50215282..73a7af2542a8 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -39,11 +39,13 @@ MODULE_DESCRIPTION(DRIVER_DESC); | |||
39 | MODULE_LICENSE("GPL"); | 39 | MODULE_LICENSE("GPL"); |
40 | 40 | ||
41 | static unsigned int psmouse_max_proto = PSMOUSE_AUTO; | 41 | static unsigned int psmouse_max_proto = PSMOUSE_AUTO; |
42 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp); | 42 | static int psmouse_set_maxproto(const char *val, const struct kernel_param *); |
43 | static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp); | 43 | static int psmouse_get_maxproto(char *buffer, const struct kernel_param *kp); |
44 | static struct kernel_param_ops param_ops_proto_abbrev = { | ||
45 | .set = psmouse_set_maxproto, | ||
46 | .get = psmouse_get_maxproto, | ||
47 | }; | ||
44 | #define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int) | 48 | #define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int) |
45 | #define param_set_proto_abbrev psmouse_set_maxproto | ||
46 | #define param_get_proto_abbrev psmouse_get_maxproto | ||
47 | module_param_named(proto, psmouse_max_proto, proto_abbrev, 0644); | 49 | module_param_named(proto, psmouse_max_proto, proto_abbrev, 0644); |
48 | MODULE_PARM_DESC(proto, "Highest protocol extension to probe (bare, imps, exps, any). Useful for KVM switches."); | 50 | MODULE_PARM_DESC(proto, "Highest protocol extension to probe (bare, imps, exps, any). Useful for KVM switches."); |
49 | 51 | ||
@@ -1679,7 +1681,7 @@ static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, | |||
1679 | } | 1681 | } |
1680 | 1682 | ||
1681 | 1683 | ||
1682 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) | 1684 | static int psmouse_set_maxproto(const char *val, const struct kernel_param *kp) |
1683 | { | 1685 | { |
1684 | const struct psmouse_protocol *proto; | 1686 | const struct psmouse_protocol *proto; |
1685 | 1687 | ||
@@ -1696,7 +1698,7 @@ static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) | |||
1696 | return 0; | 1698 | return 0; |
1697 | } | 1699 | } |
1698 | 1700 | ||
1699 | static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) | 1701 | static int psmouse_get_maxproto(char *buffer, const struct kernel_param *kp) |
1700 | { | 1702 | { |
1701 | int type = *((unsigned int *)kp->arg); | 1703 | int type = *((unsigned int *)kp->arg); |
1702 | 1704 | ||
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index cb2a24b94746..c5cc4508d6df 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h | |||
@@ -49,7 +49,7 @@ static inline void i8042_write_command(int val) | |||
49 | #define OBP_PS2MS_NAME1 "kdmouse" | 49 | #define OBP_PS2MS_NAME1 "kdmouse" |
50 | #define OBP_PS2MS_NAME2 "mouse" | 50 | #define OBP_PS2MS_NAME2 "mouse" |
51 | 51 | ||
52 | static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_device_id *match) | 52 | static int __devinit sparc_i8042_probe(struct platform_device *op, const struct of_device_id *match) |
53 | { | 53 | { |
54 | struct device_node *dp = op->dev.of_node; | 54 | struct device_node *dp = op->dev.of_node; |
55 | 55 | ||
@@ -57,7 +57,7 @@ static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_dev | |||
57 | while (dp) { | 57 | while (dp) { |
58 | if (!strcmp(dp->name, OBP_PS2KBD_NAME1) || | 58 | if (!strcmp(dp->name, OBP_PS2KBD_NAME1) || |
59 | !strcmp(dp->name, OBP_PS2KBD_NAME2)) { | 59 | !strcmp(dp->name, OBP_PS2KBD_NAME2)) { |
60 | struct of_device *kbd = of_find_device_by_node(dp); | 60 | struct platform_device *kbd = of_find_device_by_node(dp); |
61 | unsigned int irq = kbd->archdata.irqs[0]; | 61 | unsigned int irq = kbd->archdata.irqs[0]; |
62 | if (irq == 0xffffffff) | 62 | if (irq == 0xffffffff) |
63 | irq = op->archdata.irqs[0]; | 63 | irq = op->archdata.irqs[0]; |
@@ -67,7 +67,7 @@ static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_dev | |||
67 | kbd_res = &kbd->resource[0]; | 67 | kbd_res = &kbd->resource[0]; |
68 | } else if (!strcmp(dp->name, OBP_PS2MS_NAME1) || | 68 | } else if (!strcmp(dp->name, OBP_PS2MS_NAME1) || |
69 | !strcmp(dp->name, OBP_PS2MS_NAME2)) { | 69 | !strcmp(dp->name, OBP_PS2MS_NAME2)) { |
70 | struct of_device *ms = of_find_device_by_node(dp); | 70 | struct platform_device *ms = of_find_device_by_node(dp); |
71 | unsigned int irq = ms->archdata.irqs[0]; | 71 | unsigned int irq = ms->archdata.irqs[0]; |
72 | if (irq == 0xffffffff) | 72 | if (irq == 0xffffffff) |
73 | irq = op->archdata.irqs[0]; | 73 | irq = op->archdata.irqs[0]; |
@@ -80,7 +80,7 @@ static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_dev | |||
80 | return 0; | 80 | return 0; |
81 | } | 81 | } |
82 | 82 | ||
83 | static int __devexit sparc_i8042_remove(struct of_device *op) | 83 | static int __devexit sparc_i8042_remove(struct platform_device *op) |
84 | { | 84 | { |
85 | of_iounmap(kbd_res, kbd_iobase, 8); | 85 | of_iounmap(kbd_res, kbd_iobase, 8); |
86 | 86 | ||
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index e2c028d2638f..bb14449fb022 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c | |||
@@ -232,7 +232,7 @@ static void sxps2_close(struct serio *pserio) | |||
232 | * It returns 0, if the driver is bound to the PS/2 device, or a negative | 232 | * It returns 0, if the driver is bound to the PS/2 device, or a negative |
233 | * value if there is an error. | 233 | * value if there is an error. |
234 | */ | 234 | */ |
235 | static int __devinit xps2_of_probe(struct of_device *ofdev, | 235 | static int __devinit xps2_of_probe(struct platform_device *ofdev, |
236 | const struct of_device_id *match) | 236 | const struct of_device_id *match) |
237 | { | 237 | { |
238 | struct resource r_irq; /* Interrupt resources */ | 238 | struct resource r_irq; /* Interrupt resources */ |
@@ -332,7 +332,7 @@ failed1: | |||
332 | * if the driver module is being unloaded. It frees any resources allocated to | 332 | * if the driver module is being unloaded. It frees any resources allocated to |
333 | * the device. | 333 | * the device. |
334 | */ | 334 | */ |
335 | static int __devexit xps2_of_remove(struct of_device *of_dev) | 335 | static int __devexit xps2_of_remove(struct platform_device *of_dev) |
336 | { | 336 | { |
337 | struct device *dev = &of_dev->dev; | 337 | struct device *dev = &of_dev->dev; |
338 | struct xps2data *drvdata = dev_get_drvdata(dev); | 338 | struct xps2data *drvdata = dev_get_drvdata(dev); |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 61f35184f76c..0069d9703fda 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -628,4 +628,14 @@ config TOUCHSCREEN_TPS6507X | |||
628 | To compile this driver as a module, choose M here: the | 628 | To compile this driver as a module, choose M here: the |
629 | module will be called tps6507x_ts. | 629 | module will be called tps6507x_ts. |
630 | 630 | ||
631 | config TOUCHSCREEN_STMPE | ||
632 | tristate "STMicroelectronics STMPE touchscreens" | ||
633 | depends on MFD_STMPE | ||
634 | help | ||
635 | Say Y here if you want support for STMicroelectronics | ||
636 | STMPE touchscreen controllers. | ||
637 | |||
638 | To compile this driver as a module, choose M here: the | ||
639 | module will be called stmpe-ts. | ||
640 | |||
631 | endif | 641 | endif |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index bd6f30b4ff70..28217e1dcafd 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -36,6 +36,7 @@ obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o | |||
36 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o | 36 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o |
37 | obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o | 37 | obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o |
38 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o | 38 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o |
39 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o | ||
39 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o | 40 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o |
40 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o | 41 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o |
41 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o | 42 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o |
diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c new file mode 100644 index 000000000000..656148ec0027 --- /dev/null +++ b/drivers/input/touchscreen/stmpe-ts.c | |||
@@ -0,0 +1,397 @@ | |||
1 | /* STMicroelectronics STMPE811 Touchscreen Driver | ||
2 | * | ||
3 | * (C) 2010 Luotao Fu <l.fu@pengutronix.de> | ||
4 | * All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/input.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/i2c.h> | ||
24 | #include <linux/workqueue.h> | ||
25 | |||
26 | #include <linux/mfd/stmpe.h> | ||
27 | |||
28 | /* Register layouts and functionalities are identical on all stmpexxx variants | ||
29 | * with touchscreen controller | ||
30 | */ | ||
31 | #define STMPE_REG_INT_STA 0x0B | ||
32 | #define STMPE_REG_ADC_CTRL1 0x20 | ||
33 | #define STMPE_REG_ADC_CTRL2 0x21 | ||
34 | #define STMPE_REG_TSC_CTRL 0x40 | ||
35 | #define STMPE_REG_TSC_CFG 0x41 | ||
36 | #define STMPE_REG_FIFO_TH 0x4A | ||
37 | #define STMPE_REG_FIFO_STA 0x4B | ||
38 | #define STMPE_REG_FIFO_SIZE 0x4C | ||
39 | #define STMPE_REG_TSC_DATA_XYZ 0x52 | ||
40 | #define STMPE_REG_TSC_FRACTION_Z 0x56 | ||
41 | #define STMPE_REG_TSC_I_DRIVE 0x58 | ||
42 | |||
43 | #define OP_MOD_XYZ 0 | ||
44 | |||
45 | #define STMPE_TSC_CTRL_TSC_EN (1<<0) | ||
46 | |||
47 | #define STMPE_FIFO_STA_RESET (1<<0) | ||
48 | |||
49 | #define STMPE_IRQ_TOUCH_DET 0 | ||
50 | |||
51 | #define SAMPLE_TIME(x) ((x & 0xf) << 4) | ||
52 | #define MOD_12B(x) ((x & 0x1) << 3) | ||
53 | #define REF_SEL(x) ((x & 0x1) << 1) | ||
54 | #define ADC_FREQ(x) (x & 0x3) | ||
55 | #define AVE_CTRL(x) ((x & 0x3) << 6) | ||
56 | #define DET_DELAY(x) ((x & 0x7) << 3) | ||
57 | #define SETTLING(x) (x & 0x7) | ||
58 | #define FRACTION_Z(x) (x & 0x7) | ||
59 | #define I_DRIVE(x) (x & 0x1) | ||
60 | #define OP_MODE(x) ((x & 0x7) << 1) | ||
61 | |||
62 | #define STMPE_TS_NAME "stmpe-ts" | ||
63 | #define XY_MASK 0xfff | ||
64 | |||
65 | struct stmpe_touch { | ||
66 | struct stmpe *stmpe; | ||
67 | struct input_dev *idev; | ||
68 | struct delayed_work work; | ||
69 | struct device *dev; | ||
70 | u8 sample_time; | ||
71 | u8 mod_12b; | ||
72 | u8 ref_sel; | ||
73 | u8 adc_freq; | ||
74 | u8 ave_ctrl; | ||
75 | u8 touch_det_delay; | ||
76 | u8 settling; | ||
77 | u8 fraction_z; | ||
78 | u8 i_drive; | ||
79 | }; | ||
80 | |||
81 | static int __stmpe_reset_fifo(struct stmpe *stmpe) | ||
82 | { | ||
83 | int ret; | ||
84 | |||
85 | ret = stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA, | ||
86 | STMPE_FIFO_STA_RESET, STMPE_FIFO_STA_RESET); | ||
87 | if (ret) | ||
88 | return ret; | ||
89 | |||
90 | return stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA, | ||
91 | STMPE_FIFO_STA_RESET, 0); | ||
92 | } | ||
93 | |||
94 | static void stmpe_work(struct work_struct *work) | ||
95 | { | ||
96 | int int_sta; | ||
97 | u32 timeout = 40; | ||
98 | |||
99 | struct stmpe_touch *ts = | ||
100 | container_of(work, struct stmpe_touch, work.work); | ||
101 | |||
102 | int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA); | ||
103 | |||
104 | /* | ||
105 | * touch_det sometimes get desasserted or just get stuck. This appears | ||
106 | * to be a silicon bug, We still have to clearify this with the | ||
107 | * manufacture. As a workaround We release the key anyway if the | ||
108 | * touch_det keeps coming in after 4ms, while the FIFO contains no value | ||
109 | * during the whole time. | ||
110 | */ | ||
111 | while ((int_sta & (1 << STMPE_IRQ_TOUCH_DET)) && (timeout > 0)) { | ||
112 | timeout--; | ||
113 | int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA); | ||
114 | udelay(100); | ||
115 | } | ||
116 | |||
117 | /* reset the FIFO before we report release event */ | ||
118 | __stmpe_reset_fifo(ts->stmpe); | ||
119 | |||
120 | input_report_abs(ts->idev, ABS_PRESSURE, 0); | ||
121 | input_sync(ts->idev); | ||
122 | } | ||
123 | |||
124 | static irqreturn_t stmpe_ts_handler(int irq, void *data) | ||
125 | { | ||
126 | u8 data_set[4]; | ||
127 | int x, y, z; | ||
128 | struct stmpe_touch *ts = data; | ||
129 | |||
130 | /* | ||
131 | * Cancel scheduled polling for release if we have new value | ||
132 | * available. Wait if the polling is already running. | ||
133 | */ | ||
134 | cancel_delayed_work_sync(&ts->work); | ||
135 | |||
136 | /* | ||
137 | * The FIFO sometimes just crashes and stops generating interrupts. This | ||
138 | * appears to be a silicon bug. We still have to clearify this with | ||
139 | * the manufacture. As a workaround we disable the TSC while we are | ||
140 | * collecting data and flush the FIFO after reading | ||
141 | */ | ||
142 | stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL, | ||
143 | STMPE_TSC_CTRL_TSC_EN, 0); | ||
144 | |||
145 | stmpe_block_read(ts->stmpe, STMPE_REG_TSC_DATA_XYZ, 4, data_set); | ||
146 | |||
147 | x = (data_set[0] << 4) | (data_set[1] >> 4); | ||
148 | y = ((data_set[1] & 0xf) << 8) | data_set[2]; | ||
149 | z = data_set[3]; | ||
150 | |||
151 | input_report_abs(ts->idev, ABS_X, x); | ||
152 | input_report_abs(ts->idev, ABS_Y, y); | ||
153 | input_report_abs(ts->idev, ABS_PRESSURE, z); | ||
154 | input_sync(ts->idev); | ||
155 | |||
156 | /* flush the FIFO after we have read out our values. */ | ||
157 | __stmpe_reset_fifo(ts->stmpe); | ||
158 | |||
159 | /* reenable the tsc */ | ||
160 | stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL, | ||
161 | STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN); | ||
162 | |||
163 | /* start polling for touch_det to detect release */ | ||
164 | schedule_delayed_work(&ts->work, HZ / 50); | ||
165 | |||
166 | return IRQ_HANDLED; | ||
167 | } | ||
168 | |||
169 | static int __devinit stmpe_init_hw(struct stmpe_touch *ts) | ||
170 | { | ||
171 | int ret; | ||
172 | u8 adc_ctrl1, adc_ctrl1_mask, tsc_cfg, tsc_cfg_mask; | ||
173 | struct stmpe *stmpe = ts->stmpe; | ||
174 | struct device *dev = ts->dev; | ||
175 | |||
176 | ret = stmpe_enable(stmpe, STMPE_BLOCK_TOUCHSCREEN | STMPE_BLOCK_ADC); | ||
177 | if (ret) { | ||
178 | dev_err(dev, "Could not enable clock for ADC and TS\n"); | ||
179 | return ret; | ||
180 | } | ||
181 | |||
182 | adc_ctrl1 = SAMPLE_TIME(ts->sample_time) | MOD_12B(ts->mod_12b) | | ||
183 | REF_SEL(ts->ref_sel); | ||
184 | adc_ctrl1_mask = SAMPLE_TIME(0xff) | MOD_12B(0xff) | REF_SEL(0xff); | ||
185 | |||
186 | ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1, | ||
187 | adc_ctrl1_mask, adc_ctrl1); | ||
188 | if (ret) { | ||
189 | dev_err(dev, "Could not setup ADC\n"); | ||
190 | return ret; | ||
191 | } | ||
192 | |||
193 | ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2, | ||
194 | ADC_FREQ(0xff), ADC_FREQ(ts->adc_freq)); | ||
195 | if (ret) { | ||
196 | dev_err(dev, "Could not setup ADC\n"); | ||
197 | return ret; | ||
198 | } | ||
199 | |||
200 | tsc_cfg = AVE_CTRL(ts->ave_ctrl) | DET_DELAY(ts->touch_det_delay) | | ||
201 | SETTLING(ts->settling); | ||
202 | tsc_cfg_mask = AVE_CTRL(0xff) | DET_DELAY(0xff) | SETTLING(0xff); | ||
203 | |||
204 | ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CFG, tsc_cfg_mask, tsc_cfg); | ||
205 | if (ret) { | ||
206 | dev_err(dev, "Could not config touch\n"); | ||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z, | ||
211 | FRACTION_Z(0xff), FRACTION_Z(ts->fraction_z)); | ||
212 | if (ret) { | ||
213 | dev_err(dev, "Could not config touch\n"); | ||
214 | return ret; | ||
215 | } | ||
216 | |||
217 | ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_I_DRIVE, | ||
218 | I_DRIVE(0xff), I_DRIVE(ts->i_drive)); | ||
219 | if (ret) { | ||
220 | dev_err(dev, "Could not config touch\n"); | ||
221 | return ret; | ||
222 | } | ||
223 | |||
224 | /* set FIFO to 1 for single point reading */ | ||
225 | ret = stmpe_reg_write(stmpe, STMPE_REG_FIFO_TH, 1); | ||
226 | if (ret) { | ||
227 | dev_err(dev, "Could not set FIFO\n"); | ||
228 | return ret; | ||
229 | } | ||
230 | |||
231 | ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CTRL, | ||
232 | OP_MODE(0xff), OP_MODE(OP_MOD_XYZ)); | ||
233 | if (ret) { | ||
234 | dev_err(dev, "Could not set mode\n"); | ||
235 | return ret; | ||
236 | } | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static int stmpe_ts_open(struct input_dev *dev) | ||
242 | { | ||
243 | struct stmpe_touch *ts = input_get_drvdata(dev); | ||
244 | int ret = 0; | ||
245 | |||
246 | ret = __stmpe_reset_fifo(ts->stmpe); | ||
247 | if (ret) | ||
248 | return ret; | ||
249 | |||
250 | return stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL, | ||
251 | STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN); | ||
252 | } | ||
253 | |||
254 | static void stmpe_ts_close(struct input_dev *dev) | ||
255 | { | ||
256 | struct stmpe_touch *ts = input_get_drvdata(dev); | ||
257 | |||
258 | cancel_delayed_work_sync(&ts->work); | ||
259 | |||
260 | stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL, | ||
261 | STMPE_TSC_CTRL_TSC_EN, 0); | ||
262 | } | ||
263 | |||
264 | static int __devinit stmpe_input_probe(struct platform_device *pdev) | ||
265 | { | ||
266 | struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); | ||
267 | struct stmpe_platform_data *pdata = stmpe->pdata; | ||
268 | struct stmpe_touch *ts; | ||
269 | struct input_dev *idev; | ||
270 | struct stmpe_ts_platform_data *ts_pdata = NULL; | ||
271 | int ret = 0; | ||
272 | int ts_irq; | ||
273 | |||
274 | ts_irq = platform_get_irq_byname(pdev, "FIFO_TH"); | ||
275 | if (ts_irq < 0) | ||
276 | return ts_irq; | ||
277 | |||
278 | ts = kzalloc(sizeof(*ts), GFP_KERNEL); | ||
279 | if (!ts) | ||
280 | goto err_out; | ||
281 | |||
282 | idev = input_allocate_device(); | ||
283 | if (!idev) | ||
284 | goto err_free_ts; | ||
285 | |||
286 | platform_set_drvdata(pdev, ts); | ||
287 | ts->stmpe = stmpe; | ||
288 | ts->idev = idev; | ||
289 | ts->dev = &pdev->dev; | ||
290 | |||
291 | if (pdata) | ||
292 | ts_pdata = pdata->ts; | ||
293 | |||
294 | if (ts_pdata) { | ||
295 | ts->sample_time = ts_pdata->sample_time; | ||
296 | ts->mod_12b = ts_pdata->mod_12b; | ||
297 | ts->ref_sel = ts_pdata->ref_sel; | ||
298 | ts->adc_freq = ts_pdata->adc_freq; | ||
299 | ts->ave_ctrl = ts_pdata->ave_ctrl; | ||
300 | ts->touch_det_delay = ts_pdata->touch_det_delay; | ||
301 | ts->settling = ts_pdata->settling; | ||
302 | ts->fraction_z = ts_pdata->fraction_z; | ||
303 | ts->i_drive = ts_pdata->i_drive; | ||
304 | } | ||
305 | |||
306 | INIT_DELAYED_WORK(&ts->work, stmpe_work); | ||
307 | |||
308 | ret = request_threaded_irq(ts_irq, NULL, stmpe_ts_handler, | ||
309 | IRQF_ONESHOT, STMPE_TS_NAME, ts); | ||
310 | if (ret) { | ||
311 | dev_err(&pdev->dev, "Failed to request IRQ %d\n", ts_irq); | ||
312 | goto err_free_input; | ||
313 | } | ||
314 | |||
315 | ret = stmpe_init_hw(ts); | ||
316 | if (ret) | ||
317 | goto err_free_irq; | ||
318 | |||
319 | idev->name = STMPE_TS_NAME; | ||
320 | idev->id.bustype = BUS_I2C; | ||
321 | idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
322 | idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
323 | |||
324 | idev->open = stmpe_ts_open; | ||
325 | idev->close = stmpe_ts_close; | ||
326 | |||
327 | input_set_drvdata(idev, ts); | ||
328 | |||
329 | input_set_abs_params(idev, ABS_X, 0, XY_MASK, 0, 0); | ||
330 | input_set_abs_params(idev, ABS_Y, 0, XY_MASK, 0, 0); | ||
331 | input_set_abs_params(idev, ABS_PRESSURE, 0x0, 0xff, 0, 0); | ||
332 | |||
333 | ret = input_register_device(idev); | ||
334 | if (ret) { | ||
335 | dev_err(&pdev->dev, "Could not register input device\n"); | ||
336 | goto err_free_irq; | ||
337 | } | ||
338 | |||
339 | return ret; | ||
340 | |||
341 | err_free_irq: | ||
342 | free_irq(ts_irq, ts); | ||
343 | err_free_input: | ||
344 | input_free_device(idev); | ||
345 | platform_set_drvdata(pdev, NULL); | ||
346 | err_free_ts: | ||
347 | kfree(ts); | ||
348 | err_out: | ||
349 | return ret; | ||
350 | } | ||
351 | |||
352 | static int __devexit stmpe_ts_remove(struct platform_device *pdev) | ||
353 | { | ||
354 | struct stmpe_touch *ts = platform_get_drvdata(pdev); | ||
355 | unsigned int ts_irq = platform_get_irq_byname(pdev, "FIFO_TH"); | ||
356 | |||
357 | stmpe_disable(ts->stmpe, STMPE_BLOCK_TOUCHSCREEN); | ||
358 | |||
359 | free_irq(ts_irq, ts); | ||
360 | |||
361 | platform_set_drvdata(pdev, NULL); | ||
362 | |||
363 | input_unregister_device(ts->idev); | ||
364 | input_free_device(ts->idev); | ||
365 | |||
366 | kfree(ts); | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static struct platform_driver stmpe_ts_driver = { | ||
372 | .driver = { | ||
373 | .name = STMPE_TS_NAME, | ||
374 | .owner = THIS_MODULE, | ||
375 | }, | ||
376 | .probe = stmpe_input_probe, | ||
377 | .remove = __devexit_p(stmpe_ts_remove), | ||
378 | }; | ||
379 | |||
380 | static int __init stmpe_ts_init(void) | ||
381 | { | ||
382 | return platform_driver_register(&stmpe_ts_driver); | ||
383 | } | ||
384 | |||
385 | module_init(stmpe_ts_init); | ||
386 | |||
387 | static void __exit stmpe_ts_exit(void) | ||
388 | { | ||
389 | platform_driver_unregister(&stmpe_ts_driver); | ||
390 | } | ||
391 | |||
392 | module_exit(stmpe_ts_exit); | ||
393 | |||
394 | MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>"); | ||
395 | MODULE_DESCRIPTION("STMPEXXX touchscreen driver"); | ||
396 | MODULE_LICENSE("GPL"); | ||
397 | MODULE_ALIAS("platform:" STMPE_TS_NAME); | ||
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index cc22eeefa10b..ea57e05d08f3 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c | |||
@@ -224,7 +224,7 @@ struct gpio_led_of_platform_data { | |||
224 | struct gpio_led_data led_data[]; | 224 | struct gpio_led_data led_data[]; |
225 | }; | 225 | }; |
226 | 226 | ||
227 | static int __devinit of_gpio_leds_probe(struct of_device *ofdev, | 227 | static int __devinit of_gpio_leds_probe(struct platform_device *ofdev, |
228 | const struct of_device_id *match) | 228 | const struct of_device_id *match) |
229 | { | 229 | { |
230 | struct device_node *np = ofdev->dev.of_node, *child; | 230 | struct device_node *np = ofdev->dev.of_node, *child; |
@@ -283,7 +283,7 @@ err: | |||
283 | return ret; | 283 | return ret; |
284 | } | 284 | } |
285 | 285 | ||
286 | static int __devexit of_gpio_leds_remove(struct of_device *ofdev) | 286 | static int __devexit of_gpio_leds_remove(struct platform_device *ofdev) |
287 | { | 287 | { |
288 | struct gpio_led_of_platform_data *pdata = dev_get_drvdata(&ofdev->dev); | 288 | struct gpio_led_of_platform_data *pdata = dev_get_drvdata(&ofdev->dev); |
289 | int i; | 289 | int i; |
diff --git a/drivers/macintosh/macio_sysfs.c b/drivers/macintosh/macio_sysfs.c index 6024038a5b9d..8eb40afbd0f5 100644 --- a/drivers/macintosh/macio_sysfs.c +++ b/drivers/macintosh/macio_sysfs.c | |||
@@ -15,7 +15,7 @@ field##_show (struct device *dev, struct device_attribute *attr, \ | |||
15 | static ssize_t | 15 | static ssize_t |
16 | compatible_show (struct device *dev, struct device_attribute *attr, char *buf) | 16 | compatible_show (struct device *dev, struct device_attribute *attr, char *buf) |
17 | { | 17 | { |
18 | struct of_device *of; | 18 | struct platform_device *of; |
19 | const char *compat; | 19 | const char *compat; |
20 | int cplen; | 20 | int cplen; |
21 | int length = 0; | 21 | int length = 0; |
@@ -52,9 +52,9 @@ static ssize_t modalias_show (struct device *dev, struct device_attribute *attr, | |||
52 | static ssize_t devspec_show(struct device *dev, | 52 | static ssize_t devspec_show(struct device *dev, |
53 | struct device_attribute *attr, char *buf) | 53 | struct device_attribute *attr, char *buf) |
54 | { | 54 | { |
55 | struct of_device *ofdev; | 55 | struct platform_device *ofdev; |
56 | 56 | ||
57 | ofdev = to_of_device(dev); | 57 | ofdev = to_platform_device(dev); |
58 | return sprintf(buf, "%s\n", ofdev->dev.of_node->full_name); | 58 | return sprintf(buf, "%s\n", ofdev->dev.of_node->full_name); |
59 | } | 59 | } |
60 | 60 | ||
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 2506c957712e..e58c3d33e035 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c | |||
@@ -75,7 +75,7 @@ struct smu_cmd_buf { | |||
75 | struct smu_device { | 75 | struct smu_device { |
76 | spinlock_t lock; | 76 | spinlock_t lock; |
77 | struct device_node *of_node; | 77 | struct device_node *of_node; |
78 | struct of_device *of_dev; | 78 | struct platform_device *of_dev; |
79 | int doorbell; /* doorbell gpio */ | 79 | int doorbell; /* doorbell gpio */ |
80 | u32 __iomem *db_buf; /* doorbell buffer */ | 80 | u32 __iomem *db_buf; /* doorbell buffer */ |
81 | struct device_node *db_node; | 81 | struct device_node *db_node; |
@@ -645,7 +645,7 @@ static void smu_expose_childs(struct work_struct *unused) | |||
645 | 645 | ||
646 | static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs); | 646 | static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs); |
647 | 647 | ||
648 | static int smu_platform_probe(struct of_device* dev, | 648 | static int smu_platform_probe(struct platform_device* dev, |
649 | const struct of_device_id *match) | 649 | const struct of_device_id *match) |
650 | { | 650 | { |
651 | if (!smu) | 651 | if (!smu) |
@@ -695,7 +695,7 @@ static int __init smu_init_sysfs(void) | |||
695 | 695 | ||
696 | device_initcall(smu_init_sysfs); | 696 | device_initcall(smu_init_sysfs); |
697 | 697 | ||
698 | struct of_device *smu_get_ofdev(void) | 698 | struct platform_device *smu_get_ofdev(void) |
699 | { | 699 | { |
700 | if (!smu) | 700 | if (!smu) |
701 | return NULL; | 701 | return NULL; |
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index c42eeb43042d..d0d221332db0 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c | |||
@@ -84,7 +84,7 @@ struct thermostat { | |||
84 | 84 | ||
85 | static enum {ADT7460, ADT7467} therm_type; | 85 | static enum {ADT7460, ADT7467} therm_type; |
86 | static int therm_bus, therm_address; | 86 | static int therm_bus, therm_address; |
87 | static struct of_device * of_dev; | 87 | static struct platform_device * of_dev; |
88 | static struct thermostat* thermostat; | 88 | static struct thermostat* thermostat; |
89 | static struct task_struct *thread_therm = NULL; | 89 | static struct task_struct *thread_therm = NULL; |
90 | 90 | ||
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index e60605bd0ea9..44549272333c 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c | |||
@@ -148,7 +148,7 @@ | |||
148 | * Driver statics | 148 | * Driver statics |
149 | */ | 149 | */ |
150 | 150 | ||
151 | static struct of_device * of_dev; | 151 | static struct platform_device * of_dev; |
152 | static struct i2c_adapter * u3_0; | 152 | static struct i2c_adapter * u3_0; |
153 | static struct i2c_adapter * u3_1; | 153 | static struct i2c_adapter * u3_1; |
154 | static struct i2c_adapter * k2; | 154 | static struct i2c_adapter * k2; |
@@ -2210,7 +2210,7 @@ static void fcu_lookup_fans(struct device_node *fcu_node) | |||
2210 | } | 2210 | } |
2211 | } | 2211 | } |
2212 | 2212 | ||
2213 | static int fcu_of_probe(struct of_device* dev, const struct of_device_id *match) | 2213 | static int fcu_of_probe(struct platform_device* dev, const struct of_device_id *match) |
2214 | { | 2214 | { |
2215 | state = state_detached; | 2215 | state = state_detached; |
2216 | 2216 | ||
@@ -2221,7 +2221,7 @@ static int fcu_of_probe(struct of_device* dev, const struct of_device_id *match) | |||
2221 | return i2c_add_driver(&therm_pm72_driver); | 2221 | return i2c_add_driver(&therm_pm72_driver); |
2222 | } | 2222 | } |
2223 | 2223 | ||
2224 | static int fcu_of_remove(struct of_device* dev) | 2224 | static int fcu_of_remove(struct platform_device* dev) |
2225 | { | 2225 | { |
2226 | i2c_del_driver(&therm_pm72_driver); | 2226 | i2c_del_driver(&therm_pm72_driver); |
2227 | 2227 | ||
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c index 5c9367acf0cf..c89f396e4c53 100644 --- a/drivers/macintosh/therm_windtunnel.c +++ b/drivers/macintosh/therm_windtunnel.c | |||
@@ -52,7 +52,7 @@ static struct { | |||
52 | struct task_struct *poll_task; | 52 | struct task_struct *poll_task; |
53 | 53 | ||
54 | struct mutex lock; | 54 | struct mutex lock; |
55 | struct of_device *of_dev; | 55 | struct platform_device *of_dev; |
56 | 56 | ||
57 | struct i2c_client *thermostat; | 57 | struct i2c_client *thermostat; |
58 | struct i2c_client *fan; | 58 | struct i2c_client *fan; |
@@ -322,10 +322,10 @@ do_attach( struct i2c_adapter *adapter ) | |||
322 | 322 | ||
323 | memset(&info, 0, sizeof(struct i2c_board_info)); | 323 | memset(&info, 0, sizeof(struct i2c_board_info)); |
324 | strlcpy(info.type, "therm_ds1775", I2C_NAME_SIZE); | 324 | strlcpy(info.type, "therm_ds1775", I2C_NAME_SIZE); |
325 | i2c_new_probed_device(adapter, &info, scan_ds1775); | 325 | i2c_new_probed_device(adapter, &info, scan_ds1775, NULL); |
326 | 326 | ||
327 | strlcpy(info.type, "therm_adm1030", I2C_NAME_SIZE); | 327 | strlcpy(info.type, "therm_adm1030", I2C_NAME_SIZE); |
328 | i2c_new_probed_device(adapter, &info, scan_adm1030); | 328 | i2c_new_probed_device(adapter, &info, scan_adm1030, NULL); |
329 | 329 | ||
330 | if( x.thermostat && x.fan ) { | 330 | if( x.thermostat && x.fan ) { |
331 | x.running = 1; | 331 | x.running = 1; |
@@ -444,13 +444,13 @@ static struct i2c_driver g4fan_driver = { | |||
444 | /************************************************************************/ | 444 | /************************************************************************/ |
445 | 445 | ||
446 | static int | 446 | static int |
447 | therm_of_probe( struct of_device *dev, const struct of_device_id *match ) | 447 | therm_of_probe( struct platform_device *dev, const struct of_device_id *match ) |
448 | { | 448 | { |
449 | return i2c_add_driver( &g4fan_driver ); | 449 | return i2c_add_driver( &g4fan_driver ); |
450 | } | 450 | } |
451 | 451 | ||
452 | static int | 452 | static int |
453 | therm_of_remove( struct of_device *dev ) | 453 | therm_of_remove( struct platform_device *dev ) |
454 | { | 454 | { |
455 | i2c_del_driver( &g4fan_driver ); | 455 | i2c_del_driver( &g4fan_driver ); |
456 | return 0; | 456 | return 0; |
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 3bdbb6115702..368e8e98f705 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
@@ -107,11 +107,10 @@ struct crypt_config { | |||
107 | struct workqueue_struct *io_queue; | 107 | struct workqueue_struct *io_queue; |
108 | struct workqueue_struct *crypt_queue; | 108 | struct workqueue_struct *crypt_queue; |
109 | 109 | ||
110 | /* | 110 | char *cipher; |
111 | * crypto related data | 111 | char *cipher_mode; |
112 | */ | 112 | |
113 | struct crypt_iv_operations *iv_gen_ops; | 113 | struct crypt_iv_operations *iv_gen_ops; |
114 | char *iv_mode; | ||
115 | union { | 114 | union { |
116 | struct iv_essiv_private essiv; | 115 | struct iv_essiv_private essiv; |
117 | struct iv_benbi_private benbi; | 116 | struct iv_benbi_private benbi; |
@@ -135,8 +134,6 @@ struct crypt_config { | |||
135 | unsigned int dmreq_start; | 134 | unsigned int dmreq_start; |
136 | struct ablkcipher_request *req; | 135 | struct ablkcipher_request *req; |
137 | 136 | ||
138 | char cipher[CRYPTO_MAX_ALG_NAME]; | ||
139 | char chainmode[CRYPTO_MAX_ALG_NAME]; | ||
140 | struct crypto_ablkcipher *tfm; | 137 | struct crypto_ablkcipher *tfm; |
141 | unsigned long flags; | 138 | unsigned long flags; |
142 | unsigned int key_size; | 139 | unsigned int key_size; |
@@ -999,82 +996,135 @@ static int crypt_wipe_key(struct crypt_config *cc) | |||
999 | return crypto_ablkcipher_setkey(cc->tfm, cc->key, cc->key_size); | 996 | return crypto_ablkcipher_setkey(cc->tfm, cc->key, cc->key_size); |
1000 | } | 997 | } |
1001 | 998 | ||
1002 | /* | 999 | static void crypt_dtr(struct dm_target *ti) |
1003 | * Construct an encryption mapping: | ||
1004 | * <cipher> <key> <iv_offset> <dev_path> <start> | ||
1005 | */ | ||
1006 | static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | ||
1007 | { | 1000 | { |
1008 | struct crypt_config *cc; | 1001 | struct crypt_config *cc = ti->private; |
1009 | struct crypto_ablkcipher *tfm; | ||
1010 | char *tmp; | ||
1011 | char *cipher; | ||
1012 | char *chainmode; | ||
1013 | char *ivmode; | ||
1014 | char *ivopts; | ||
1015 | unsigned int key_size; | ||
1016 | unsigned long long tmpll; | ||
1017 | 1002 | ||
1018 | if (argc != 5) { | 1003 | ti->private = NULL; |
1019 | ti->error = "Not enough arguments"; | 1004 | |
1005 | if (!cc) | ||
1006 | return; | ||
1007 | |||
1008 | if (cc->io_queue) | ||
1009 | destroy_workqueue(cc->io_queue); | ||
1010 | if (cc->crypt_queue) | ||
1011 | destroy_workqueue(cc->crypt_queue); | ||
1012 | |||
1013 | if (cc->bs) | ||
1014 | bioset_free(cc->bs); | ||
1015 | |||
1016 | if (cc->page_pool) | ||
1017 | mempool_destroy(cc->page_pool); | ||
1018 | if (cc->req_pool) | ||
1019 | mempool_destroy(cc->req_pool); | ||
1020 | if (cc->io_pool) | ||
1021 | mempool_destroy(cc->io_pool); | ||
1022 | |||
1023 | if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) | ||
1024 | cc->iv_gen_ops->dtr(cc); | ||
1025 | |||
1026 | if (cc->tfm && !IS_ERR(cc->tfm)) | ||
1027 | crypto_free_ablkcipher(cc->tfm); | ||
1028 | |||
1029 | if (cc->dev) | ||
1030 | dm_put_device(ti, cc->dev); | ||
1031 | |||
1032 | kzfree(cc->cipher); | ||
1033 | kzfree(cc->cipher_mode); | ||
1034 | |||
1035 | /* Must zero key material before freeing */ | ||
1036 | kzfree(cc); | ||
1037 | } | ||
1038 | |||
1039 | static int crypt_ctr_cipher(struct dm_target *ti, | ||
1040 | char *cipher_in, char *key) | ||
1041 | { | ||
1042 | struct crypt_config *cc = ti->private; | ||
1043 | char *tmp, *cipher, *chainmode, *ivmode, *ivopts; | ||
1044 | char *cipher_api = NULL; | ||
1045 | int ret = -EINVAL; | ||
1046 | |||
1047 | /* Convert to crypto api definition? */ | ||
1048 | if (strchr(cipher_in, '(')) { | ||
1049 | ti->error = "Bad cipher specification"; | ||
1020 | return -EINVAL; | 1050 | return -EINVAL; |
1021 | } | 1051 | } |
1022 | 1052 | ||
1023 | tmp = argv[0]; | 1053 | /* |
1054 | * Legacy dm-crypt cipher specification | ||
1055 | * cipher-mode-iv:ivopts | ||
1056 | */ | ||
1057 | tmp = cipher_in; | ||
1024 | cipher = strsep(&tmp, "-"); | 1058 | cipher = strsep(&tmp, "-"); |
1059 | |||
1060 | cc->cipher = kstrdup(cipher, GFP_KERNEL); | ||
1061 | if (!cc->cipher) | ||
1062 | goto bad_mem; | ||
1063 | |||
1064 | if (tmp) { | ||
1065 | cc->cipher_mode = kstrdup(tmp, GFP_KERNEL); | ||
1066 | if (!cc->cipher_mode) | ||
1067 | goto bad_mem; | ||
1068 | } | ||
1069 | |||
1025 | chainmode = strsep(&tmp, "-"); | 1070 | chainmode = strsep(&tmp, "-"); |
1026 | ivopts = strsep(&tmp, "-"); | 1071 | ivopts = strsep(&tmp, "-"); |
1027 | ivmode = strsep(&ivopts, ":"); | 1072 | ivmode = strsep(&ivopts, ":"); |
1028 | 1073 | ||
1029 | if (tmp) | 1074 | if (tmp) |
1030 | DMWARN("Unexpected additional cipher options"); | 1075 | DMWARN("Ignoring unexpected additional cipher options"); |
1031 | |||
1032 | key_size = strlen(argv[1]) >> 1; | ||
1033 | |||
1034 | cc = kzalloc(sizeof(*cc) + key_size * sizeof(u8), GFP_KERNEL); | ||
1035 | if (cc == NULL) { | ||
1036 | ti->error = | ||
1037 | "Cannot allocate transparent encryption context"; | ||
1038 | return -ENOMEM; | ||
1039 | } | ||
1040 | 1076 | ||
1041 | /* Compatibility mode for old dm-crypt cipher strings */ | 1077 | /* Compatibility mode for old dm-crypt mappings */ |
1042 | if (!chainmode || (strcmp(chainmode, "plain") == 0 && !ivmode)) { | 1078 | if (!chainmode || (!strcmp(chainmode, "plain") && !ivmode)) { |
1079 | kfree(cc->cipher_mode); | ||
1080 | cc->cipher_mode = kstrdup("cbc-plain", GFP_KERNEL); | ||
1043 | chainmode = "cbc"; | 1081 | chainmode = "cbc"; |
1044 | ivmode = "plain"; | 1082 | ivmode = "plain"; |
1045 | } | 1083 | } |
1046 | 1084 | ||
1047 | if (strcmp(chainmode, "ecb") && !ivmode) { | 1085 | if (strcmp(chainmode, "ecb") && !ivmode) { |
1048 | ti->error = "This chaining mode requires an IV mechanism"; | 1086 | ti->error = "IV mechanism required"; |
1049 | goto bad_cipher; | 1087 | return -EINVAL; |
1050 | } | 1088 | } |
1051 | 1089 | ||
1052 | if (snprintf(cc->cipher, CRYPTO_MAX_ALG_NAME, "%s(%s)", | 1090 | cipher_api = kmalloc(CRYPTO_MAX_ALG_NAME, GFP_KERNEL); |
1053 | chainmode, cipher) >= CRYPTO_MAX_ALG_NAME) { | 1091 | if (!cipher_api) |
1054 | ti->error = "Chain mode + cipher name is too long"; | 1092 | goto bad_mem; |
1055 | goto bad_cipher; | 1093 | |
1094 | ret = snprintf(cipher_api, CRYPTO_MAX_ALG_NAME, | ||
1095 | "%s(%s)", chainmode, cipher); | ||
1096 | if (ret < 0) { | ||
1097 | kfree(cipher_api); | ||
1098 | goto bad_mem; | ||
1056 | } | 1099 | } |
1057 | 1100 | ||
1058 | tfm = crypto_alloc_ablkcipher(cc->cipher, 0, 0); | 1101 | /* Allocate cipher */ |
1059 | if (IS_ERR(tfm)) { | 1102 | cc->tfm = crypto_alloc_ablkcipher(cipher_api, 0, 0); |
1103 | if (IS_ERR(cc->tfm)) { | ||
1104 | ret = PTR_ERR(cc->tfm); | ||
1060 | ti->error = "Error allocating crypto tfm"; | 1105 | ti->error = "Error allocating crypto tfm"; |
1061 | goto bad_cipher; | 1106 | goto bad; |
1062 | } | 1107 | } |
1063 | 1108 | ||
1064 | strcpy(cc->cipher, cipher); | 1109 | /* Initialize and set key */ |
1065 | strcpy(cc->chainmode, chainmode); | 1110 | ret = crypt_set_key(cc, key); |
1066 | cc->tfm = tfm; | 1111 | if (ret < 0) { |
1067 | |||
1068 | if (crypt_set_key(cc, argv[1]) < 0) { | ||
1069 | ti->error = "Error decoding and setting key"; | 1112 | ti->error = "Error decoding and setting key"; |
1070 | goto bad_ivmode; | 1113 | goto bad; |
1071 | } | 1114 | } |
1072 | 1115 | ||
1073 | /* | 1116 | /* Initialize IV */ |
1074 | * Choose ivmode. Valid modes: "plain", "essiv:<esshash>", "benbi". | 1117 | cc->iv_size = crypto_ablkcipher_ivsize(cc->tfm); |
1075 | * See comments at iv code | 1118 | if (cc->iv_size) |
1076 | */ | 1119 | /* at least a 64 bit sector number should fit in our buffer */ |
1120 | cc->iv_size = max(cc->iv_size, | ||
1121 | (unsigned int)(sizeof(u64) / sizeof(u8))); | ||
1122 | else if (ivmode) { | ||
1123 | DMWARN("Selected cipher does not support IVs"); | ||
1124 | ivmode = NULL; | ||
1125 | } | ||
1077 | 1126 | ||
1127 | /* Choose ivmode, see comments at iv code. */ | ||
1078 | if (ivmode == NULL) | 1128 | if (ivmode == NULL) |
1079 | cc->iv_gen_ops = NULL; | 1129 | cc->iv_gen_ops = NULL; |
1080 | else if (strcmp(ivmode, "plain") == 0) | 1130 | else if (strcmp(ivmode, "plain") == 0) |
@@ -1088,159 +1138,138 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1088 | else if (strcmp(ivmode, "null") == 0) | 1138 | else if (strcmp(ivmode, "null") == 0) |
1089 | cc->iv_gen_ops = &crypt_iv_null_ops; | 1139 | cc->iv_gen_ops = &crypt_iv_null_ops; |
1090 | else { | 1140 | else { |
1141 | ret = -EINVAL; | ||
1091 | ti->error = "Invalid IV mode"; | 1142 | ti->error = "Invalid IV mode"; |
1092 | goto bad_ivmode; | 1143 | goto bad; |
1093 | } | 1144 | } |
1094 | 1145 | ||
1095 | if (cc->iv_gen_ops && cc->iv_gen_ops->ctr && | 1146 | /* Allocate IV */ |
1096 | cc->iv_gen_ops->ctr(cc, ti, ivopts) < 0) | 1147 | if (cc->iv_gen_ops && cc->iv_gen_ops->ctr) { |
1097 | goto bad_ivmode; | 1148 | ret = cc->iv_gen_ops->ctr(cc, ti, ivopts); |
1098 | 1149 | if (ret < 0) { | |
1099 | if (cc->iv_gen_ops && cc->iv_gen_ops->init && | 1150 | ti->error = "Error creating IV"; |
1100 | cc->iv_gen_ops->init(cc) < 0) { | 1151 | goto bad; |
1101 | ti->error = "Error initialising IV"; | 1152 | } |
1102 | goto bad_slab_pool; | ||
1103 | } | 1153 | } |
1104 | 1154 | ||
1105 | cc->iv_size = crypto_ablkcipher_ivsize(tfm); | 1155 | /* Initialize IV (set keys for ESSIV etc) */ |
1106 | if (cc->iv_size) | 1156 | if (cc->iv_gen_ops && cc->iv_gen_ops->init) { |
1107 | /* at least a 64 bit sector number should fit in our buffer */ | 1157 | ret = cc->iv_gen_ops->init(cc); |
1108 | cc->iv_size = max(cc->iv_size, | 1158 | if (ret < 0) { |
1109 | (unsigned int)(sizeof(u64) / sizeof(u8))); | 1159 | ti->error = "Error initialising IV"; |
1110 | else { | 1160 | goto bad; |
1111 | if (cc->iv_gen_ops) { | ||
1112 | DMWARN("Selected cipher does not support IVs"); | ||
1113 | if (cc->iv_gen_ops->dtr) | ||
1114 | cc->iv_gen_ops->dtr(cc); | ||
1115 | cc->iv_gen_ops = NULL; | ||
1116 | } | 1161 | } |
1117 | } | 1162 | } |
1118 | 1163 | ||
1164 | ret = 0; | ||
1165 | bad: | ||
1166 | kfree(cipher_api); | ||
1167 | return ret; | ||
1168 | |||
1169 | bad_mem: | ||
1170 | ti->error = "Cannot allocate cipher strings"; | ||
1171 | return -ENOMEM; | ||
1172 | } | ||
1173 | |||
1174 | /* | ||
1175 | * Construct an encryption mapping: | ||
1176 | * <cipher> <key> <iv_offset> <dev_path> <start> | ||
1177 | */ | ||
1178 | static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | ||
1179 | { | ||
1180 | struct crypt_config *cc; | ||
1181 | unsigned int key_size; | ||
1182 | unsigned long long tmpll; | ||
1183 | int ret; | ||
1184 | |||
1185 | if (argc != 5) { | ||
1186 | ti->error = "Not enough arguments"; | ||
1187 | return -EINVAL; | ||
1188 | } | ||
1189 | |||
1190 | key_size = strlen(argv[1]) >> 1; | ||
1191 | |||
1192 | cc = kzalloc(sizeof(*cc) + key_size * sizeof(u8), GFP_KERNEL); | ||
1193 | if (!cc) { | ||
1194 | ti->error = "Cannot allocate encryption context"; | ||
1195 | return -ENOMEM; | ||
1196 | } | ||
1197 | |||
1198 | ti->private = cc; | ||
1199 | ret = crypt_ctr_cipher(ti, argv[0], argv[1]); | ||
1200 | if (ret < 0) | ||
1201 | goto bad; | ||
1202 | |||
1203 | ret = -ENOMEM; | ||
1119 | cc->io_pool = mempool_create_slab_pool(MIN_IOS, _crypt_io_pool); | 1204 | cc->io_pool = mempool_create_slab_pool(MIN_IOS, _crypt_io_pool); |
1120 | if (!cc->io_pool) { | 1205 | if (!cc->io_pool) { |
1121 | ti->error = "Cannot allocate crypt io mempool"; | 1206 | ti->error = "Cannot allocate crypt io mempool"; |
1122 | goto bad_slab_pool; | 1207 | goto bad; |
1123 | } | 1208 | } |
1124 | 1209 | ||
1125 | cc->dmreq_start = sizeof(struct ablkcipher_request); | 1210 | cc->dmreq_start = sizeof(struct ablkcipher_request); |
1126 | cc->dmreq_start += crypto_ablkcipher_reqsize(tfm); | 1211 | cc->dmreq_start += crypto_ablkcipher_reqsize(cc->tfm); |
1127 | cc->dmreq_start = ALIGN(cc->dmreq_start, crypto_tfm_ctx_alignment()); | 1212 | cc->dmreq_start = ALIGN(cc->dmreq_start, crypto_tfm_ctx_alignment()); |
1128 | cc->dmreq_start += crypto_ablkcipher_alignmask(tfm) & | 1213 | cc->dmreq_start += crypto_ablkcipher_alignmask(cc->tfm) & |
1129 | ~(crypto_tfm_ctx_alignment() - 1); | 1214 | ~(crypto_tfm_ctx_alignment() - 1); |
1130 | 1215 | ||
1131 | cc->req_pool = mempool_create_kmalloc_pool(MIN_IOS, cc->dmreq_start + | 1216 | cc->req_pool = mempool_create_kmalloc_pool(MIN_IOS, cc->dmreq_start + |
1132 | sizeof(struct dm_crypt_request) + cc->iv_size); | 1217 | sizeof(struct dm_crypt_request) + cc->iv_size); |
1133 | if (!cc->req_pool) { | 1218 | if (!cc->req_pool) { |
1134 | ti->error = "Cannot allocate crypt request mempool"; | 1219 | ti->error = "Cannot allocate crypt request mempool"; |
1135 | goto bad_req_pool; | 1220 | goto bad; |
1136 | } | 1221 | } |
1137 | cc->req = NULL; | 1222 | cc->req = NULL; |
1138 | 1223 | ||
1139 | cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0); | 1224 | cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0); |
1140 | if (!cc->page_pool) { | 1225 | if (!cc->page_pool) { |
1141 | ti->error = "Cannot allocate page mempool"; | 1226 | ti->error = "Cannot allocate page mempool"; |
1142 | goto bad_page_pool; | 1227 | goto bad; |
1143 | } | 1228 | } |
1144 | 1229 | ||
1145 | cc->bs = bioset_create(MIN_IOS, 0); | 1230 | cc->bs = bioset_create(MIN_IOS, 0); |
1146 | if (!cc->bs) { | 1231 | if (!cc->bs) { |
1147 | ti->error = "Cannot allocate crypt bioset"; | 1232 | ti->error = "Cannot allocate crypt bioset"; |
1148 | goto bad_bs; | 1233 | goto bad; |
1149 | } | 1234 | } |
1150 | 1235 | ||
1236 | ret = -EINVAL; | ||
1151 | if (sscanf(argv[2], "%llu", &tmpll) != 1) { | 1237 | if (sscanf(argv[2], "%llu", &tmpll) != 1) { |
1152 | ti->error = "Invalid iv_offset sector"; | 1238 | ti->error = "Invalid iv_offset sector"; |
1153 | goto bad_device; | 1239 | goto bad; |
1154 | } | 1240 | } |
1155 | cc->iv_offset = tmpll; | 1241 | cc->iv_offset = tmpll; |
1156 | 1242 | ||
1157 | if (sscanf(argv[4], "%llu", &tmpll) != 1) { | ||
1158 | ti->error = "Invalid device sector"; | ||
1159 | goto bad_device; | ||
1160 | } | ||
1161 | cc->start = tmpll; | ||
1162 | |||
1163 | if (dm_get_device(ti, argv[3], dm_table_get_mode(ti->table), &cc->dev)) { | 1243 | if (dm_get_device(ti, argv[3], dm_table_get_mode(ti->table), &cc->dev)) { |
1164 | ti->error = "Device lookup failed"; | 1244 | ti->error = "Device lookup failed"; |
1165 | goto bad_device; | 1245 | goto bad; |
1166 | } | 1246 | } |
1167 | 1247 | ||
1168 | if (ivmode && cc->iv_gen_ops) { | 1248 | if (sscanf(argv[4], "%llu", &tmpll) != 1) { |
1169 | if (ivopts) | 1249 | ti->error = "Invalid device sector"; |
1170 | *(ivopts - 1) = ':'; | 1250 | goto bad; |
1171 | cc->iv_mode = kmalloc(strlen(ivmode) + 1, GFP_KERNEL); | 1251 | } |
1172 | if (!cc->iv_mode) { | 1252 | cc->start = tmpll; |
1173 | ti->error = "Error kmallocing iv_mode string"; | ||
1174 | goto bad_ivmode_string; | ||
1175 | } | ||
1176 | strcpy(cc->iv_mode, ivmode); | ||
1177 | } else | ||
1178 | cc->iv_mode = NULL; | ||
1179 | 1253 | ||
1254 | ret = -ENOMEM; | ||
1180 | cc->io_queue = create_singlethread_workqueue("kcryptd_io"); | 1255 | cc->io_queue = create_singlethread_workqueue("kcryptd_io"); |
1181 | if (!cc->io_queue) { | 1256 | if (!cc->io_queue) { |
1182 | ti->error = "Couldn't create kcryptd io queue"; | 1257 | ti->error = "Couldn't create kcryptd io queue"; |
1183 | goto bad_io_queue; | 1258 | goto bad; |
1184 | } | 1259 | } |
1185 | 1260 | ||
1186 | cc->crypt_queue = create_singlethread_workqueue("kcryptd"); | 1261 | cc->crypt_queue = create_singlethread_workqueue("kcryptd"); |
1187 | if (!cc->crypt_queue) { | 1262 | if (!cc->crypt_queue) { |
1188 | ti->error = "Couldn't create kcryptd queue"; | 1263 | ti->error = "Couldn't create kcryptd queue"; |
1189 | goto bad_crypt_queue; | 1264 | goto bad; |
1190 | } | 1265 | } |
1191 | 1266 | ||
1192 | ti->num_flush_requests = 1; | 1267 | ti->num_flush_requests = 1; |
1193 | ti->private = cc; | ||
1194 | return 0; | 1268 | return 0; |
1195 | 1269 | ||
1196 | bad_crypt_queue: | 1270 | bad: |
1197 | destroy_workqueue(cc->io_queue); | 1271 | crypt_dtr(ti); |
1198 | bad_io_queue: | 1272 | return ret; |
1199 | kfree(cc->iv_mode); | ||
1200 | bad_ivmode_string: | ||
1201 | dm_put_device(ti, cc->dev); | ||
1202 | bad_device: | ||
1203 | bioset_free(cc->bs); | ||
1204 | bad_bs: | ||
1205 | mempool_destroy(cc->page_pool); | ||
1206 | bad_page_pool: | ||
1207 | mempool_destroy(cc->req_pool); | ||
1208 | bad_req_pool: | ||
1209 | mempool_destroy(cc->io_pool); | ||
1210 | bad_slab_pool: | ||
1211 | if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) | ||
1212 | cc->iv_gen_ops->dtr(cc); | ||
1213 | bad_ivmode: | ||
1214 | crypto_free_ablkcipher(tfm); | ||
1215 | bad_cipher: | ||
1216 | /* Must zero key material before freeing */ | ||
1217 | kzfree(cc); | ||
1218 | return -EINVAL; | ||
1219 | } | ||
1220 | |||
1221 | static void crypt_dtr(struct dm_target *ti) | ||
1222 | { | ||
1223 | struct crypt_config *cc = (struct crypt_config *) ti->private; | ||
1224 | |||
1225 | destroy_workqueue(cc->io_queue); | ||
1226 | destroy_workqueue(cc->crypt_queue); | ||
1227 | |||
1228 | if (cc->req) | ||
1229 | mempool_free(cc->req, cc->req_pool); | ||
1230 | |||
1231 | bioset_free(cc->bs); | ||
1232 | mempool_destroy(cc->page_pool); | ||
1233 | mempool_destroy(cc->req_pool); | ||
1234 | mempool_destroy(cc->io_pool); | ||
1235 | |||
1236 | kfree(cc->iv_mode); | ||
1237 | if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) | ||
1238 | cc->iv_gen_ops->dtr(cc); | ||
1239 | crypto_free_ablkcipher(cc->tfm); | ||
1240 | dm_put_device(ti, cc->dev); | ||
1241 | |||
1242 | /* Must zero key material before freeing */ | ||
1243 | kzfree(cc); | ||
1244 | } | 1273 | } |
1245 | 1274 | ||
1246 | static int crypt_map(struct dm_target *ti, struct bio *bio, | 1275 | static int crypt_map(struct dm_target *ti, struct bio *bio, |
@@ -1255,7 +1284,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, | |||
1255 | return DM_MAPIO_REMAPPED; | 1284 | return DM_MAPIO_REMAPPED; |
1256 | } | 1285 | } |
1257 | 1286 | ||
1258 | io = crypt_io_alloc(ti, bio, bio->bi_sector - ti->begin); | 1287 | io = crypt_io_alloc(ti, bio, dm_target_offset(ti, bio->bi_sector)); |
1259 | 1288 | ||
1260 | if (bio_data_dir(io->base_bio) == READ) | 1289 | if (bio_data_dir(io->base_bio) == READ) |
1261 | kcryptd_queue_io(io); | 1290 | kcryptd_queue_io(io); |
@@ -1268,7 +1297,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, | |||
1268 | static int crypt_status(struct dm_target *ti, status_type_t type, | 1297 | static int crypt_status(struct dm_target *ti, status_type_t type, |
1269 | char *result, unsigned int maxlen) | 1298 | char *result, unsigned int maxlen) |
1270 | { | 1299 | { |
1271 | struct crypt_config *cc = (struct crypt_config *) ti->private; | 1300 | struct crypt_config *cc = ti->private; |
1272 | unsigned int sz = 0; | 1301 | unsigned int sz = 0; |
1273 | 1302 | ||
1274 | switch (type) { | 1303 | switch (type) { |
@@ -1277,11 +1306,10 @@ static int crypt_status(struct dm_target *ti, status_type_t type, | |||
1277 | break; | 1306 | break; |
1278 | 1307 | ||
1279 | case STATUSTYPE_TABLE: | 1308 | case STATUSTYPE_TABLE: |
1280 | if (cc->iv_mode) | 1309 | if (cc->cipher_mode) |
1281 | DMEMIT("%s-%s-%s ", cc->cipher, cc->chainmode, | 1310 | DMEMIT("%s-%s ", cc->cipher, cc->cipher_mode); |
1282 | cc->iv_mode); | ||
1283 | else | 1311 | else |
1284 | DMEMIT("%s-%s ", cc->cipher, cc->chainmode); | 1312 | DMEMIT("%s ", cc->cipher); |
1285 | 1313 | ||
1286 | if (cc->key_size > 0) { | 1314 | if (cc->key_size > 0) { |
1287 | if ((maxlen - sz) < ((cc->key_size << 1) + 1)) | 1315 | if ((maxlen - sz) < ((cc->key_size << 1) + 1)) |
@@ -1378,7 +1406,7 @@ static int crypt_merge(struct dm_target *ti, struct bvec_merge_data *bvm, | |||
1378 | return max_size; | 1406 | return max_size; |
1379 | 1407 | ||
1380 | bvm->bi_bdev = cc->dev->bdev; | 1408 | bvm->bi_bdev = cc->dev->bdev; |
1381 | bvm->bi_sector = cc->start + bvm->bi_sector - ti->begin; | 1409 | bvm->bi_sector = cc->start + dm_target_offset(ti, bvm->bi_sector); |
1382 | 1410 | ||
1383 | return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); | 1411 | return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); |
1384 | } | 1412 | } |
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c index 852052880d7a..baa11912cc94 100644 --- a/drivers/md/dm-delay.c +++ b/drivers/md/dm-delay.c | |||
@@ -198,6 +198,7 @@ out: | |||
198 | atomic_set(&dc->may_delay, 1); | 198 | atomic_set(&dc->may_delay, 1); |
199 | 199 | ||
200 | ti->num_flush_requests = 1; | 200 | ti->num_flush_requests = 1; |
201 | ti->num_discard_requests = 1; | ||
201 | ti->private = dc; | 202 | ti->private = dc; |
202 | return 0; | 203 | return 0; |
203 | 204 | ||
@@ -281,14 +282,13 @@ static int delay_map(struct dm_target *ti, struct bio *bio, | |||
281 | bio->bi_bdev = dc->dev_write->bdev; | 282 | bio->bi_bdev = dc->dev_write->bdev; |
282 | if (bio_sectors(bio)) | 283 | if (bio_sectors(bio)) |
283 | bio->bi_sector = dc->start_write + | 284 | bio->bi_sector = dc->start_write + |
284 | (bio->bi_sector - ti->begin); | 285 | dm_target_offset(ti, bio->bi_sector); |
285 | 286 | ||
286 | return delay_bio(dc, dc->write_delay, bio); | 287 | return delay_bio(dc, dc->write_delay, bio); |
287 | } | 288 | } |
288 | 289 | ||
289 | bio->bi_bdev = dc->dev_read->bdev; | 290 | bio->bi_bdev = dc->dev_read->bdev; |
290 | bio->bi_sector = dc->start_read + | 291 | bio->bi_sector = dc->start_read + dm_target_offset(ti, bio->bi_sector); |
291 | (bio->bi_sector - ti->begin); | ||
292 | 292 | ||
293 | return delay_bio(dc, dc->read_delay, bio); | 293 | return delay_bio(dc, dc->read_delay, bio); |
294 | } | 294 | } |
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index 2b7907b6dd09..0bdb201c2c2a 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c | |||
@@ -173,7 +173,9 @@ int dm_exception_store_set_chunk_size(struct dm_exception_store *store, | |||
173 | 173 | ||
174 | /* Validate the chunk size against the device block size */ | 174 | /* Validate the chunk size against the device block size */ |
175 | if (chunk_size % | 175 | if (chunk_size % |
176 | (bdev_logical_block_size(dm_snap_cow(store->snap)->bdev) >> 9)) { | 176 | (bdev_logical_block_size(dm_snap_cow(store->snap)->bdev) >> 9) || |
177 | chunk_size % | ||
178 | (bdev_logical_block_size(dm_snap_origin(store->snap)->bdev) >> 9)) { | ||
177 | *error = "Chunk size is not a multiple of device blocksize"; | 179 | *error = "Chunk size is not a multiple of device blocksize"; |
178 | return -EINVAL; | 180 | return -EINVAL; |
179 | } | 181 | } |
diff --git a/drivers/md/dm-exception-store.h b/drivers/md/dm-exception-store.h index e8dfa06af3ba..0b2536247cf5 100644 --- a/drivers/md/dm-exception-store.h +++ b/drivers/md/dm-exception-store.h | |||
@@ -126,8 +126,9 @@ struct dm_exception_store { | |||
126 | }; | 126 | }; |
127 | 127 | ||
128 | /* | 128 | /* |
129 | * Obtain the cow device used by a given snapshot. | 129 | * Obtain the origin or cow device used by a given snapshot. |
130 | */ | 130 | */ |
131 | struct dm_dev *dm_snap_origin(struct dm_snapshot *snap); | ||
131 | struct dm_dev *dm_snap_cow(struct dm_snapshot *snap); | 132 | struct dm_dev *dm_snap_cow(struct dm_snapshot *snap); |
132 | 133 | ||
133 | /* | 134 | /* |
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index d7500e1c26f2..3e39193e5036 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c | |||
@@ -249,55 +249,66 @@ static void __hash_remove(struct hash_cell *hc) | |||
249 | 249 | ||
250 | static void dm_hash_remove_all(int keep_open_devices) | 250 | static void dm_hash_remove_all(int keep_open_devices) |
251 | { | 251 | { |
252 | int i, dev_skipped, dev_removed; | 252 | int i, dev_skipped; |
253 | struct hash_cell *hc; | 253 | struct hash_cell *hc; |
254 | struct list_head *tmp, *n; | 254 | struct mapped_device *md; |
255 | |||
256 | retry: | ||
257 | dev_skipped = 0; | ||
255 | 258 | ||
256 | down_write(&_hash_lock); | 259 | down_write(&_hash_lock); |
257 | 260 | ||
258 | retry: | ||
259 | dev_skipped = dev_removed = 0; | ||
260 | for (i = 0; i < NUM_BUCKETS; i++) { | 261 | for (i = 0; i < NUM_BUCKETS; i++) { |
261 | list_for_each_safe (tmp, n, _name_buckets + i) { | 262 | list_for_each_entry(hc, _name_buckets + i, name_list) { |
262 | hc = list_entry(tmp, struct hash_cell, name_list); | 263 | md = hc->md; |
264 | dm_get(md); | ||
263 | 265 | ||
264 | if (keep_open_devices && | 266 | if (keep_open_devices && dm_lock_for_deletion(md)) { |
265 | dm_lock_for_deletion(hc->md)) { | 267 | dm_put(md); |
266 | dev_skipped++; | 268 | dev_skipped++; |
267 | continue; | 269 | continue; |
268 | } | 270 | } |
271 | |||
269 | __hash_remove(hc); | 272 | __hash_remove(hc); |
270 | dev_removed = 1; | ||
271 | } | ||
272 | } | ||
273 | 273 | ||
274 | /* | 274 | up_write(&_hash_lock); |
275 | * Some mapped devices may be using other mapped devices, so if any | ||
276 | * still exist, repeat until we make no further progress. | ||
277 | */ | ||
278 | if (dev_skipped) { | ||
279 | if (dev_removed) | ||
280 | goto retry; | ||
281 | 275 | ||
282 | DMWARN("remove_all left %d open device(s)", dev_skipped); | 276 | dm_put(md); |
277 | if (likely(keep_open_devices)) | ||
278 | dm_destroy(md); | ||
279 | else | ||
280 | dm_destroy_immediate(md); | ||
281 | |||
282 | /* | ||
283 | * Some mapped devices may be using other mapped | ||
284 | * devices, so repeat until we make no further | ||
285 | * progress. If a new mapped device is created | ||
286 | * here it will also get removed. | ||
287 | */ | ||
288 | goto retry; | ||
289 | } | ||
283 | } | 290 | } |
284 | 291 | ||
285 | up_write(&_hash_lock); | 292 | up_write(&_hash_lock); |
293 | |||
294 | if (dev_skipped) | ||
295 | DMWARN("remove_all left %d open device(s)", dev_skipped); | ||
286 | } | 296 | } |
287 | 297 | ||
288 | static int dm_hash_rename(uint32_t cookie, uint32_t *flags, const char *old, | 298 | static struct mapped_device *dm_hash_rename(struct dm_ioctl *param, |
289 | const char *new) | 299 | const char *new) |
290 | { | 300 | { |
291 | char *new_name, *old_name; | 301 | char *new_name, *old_name; |
292 | struct hash_cell *hc; | 302 | struct hash_cell *hc; |
293 | struct dm_table *table; | 303 | struct dm_table *table; |
304 | struct mapped_device *md; | ||
294 | 305 | ||
295 | /* | 306 | /* |
296 | * duplicate new. | 307 | * duplicate new. |
297 | */ | 308 | */ |
298 | new_name = kstrdup(new, GFP_KERNEL); | 309 | new_name = kstrdup(new, GFP_KERNEL); |
299 | if (!new_name) | 310 | if (!new_name) |
300 | return -ENOMEM; | 311 | return ERR_PTR(-ENOMEM); |
301 | 312 | ||
302 | down_write(&_hash_lock); | 313 | down_write(&_hash_lock); |
303 | 314 | ||
@@ -306,24 +317,24 @@ static int dm_hash_rename(uint32_t cookie, uint32_t *flags, const char *old, | |||
306 | */ | 317 | */ |
307 | hc = __get_name_cell(new); | 318 | hc = __get_name_cell(new); |
308 | if (hc) { | 319 | if (hc) { |
309 | DMWARN("asked to rename to an already existing name %s -> %s", | 320 | DMWARN("asked to rename to an already-existing name %s -> %s", |
310 | old, new); | 321 | param->name, new); |
311 | dm_put(hc->md); | 322 | dm_put(hc->md); |
312 | up_write(&_hash_lock); | 323 | up_write(&_hash_lock); |
313 | kfree(new_name); | 324 | kfree(new_name); |
314 | return -EBUSY; | 325 | return ERR_PTR(-EBUSY); |
315 | } | 326 | } |
316 | 327 | ||
317 | /* | 328 | /* |
318 | * Is there such a device as 'old' ? | 329 | * Is there such a device as 'old' ? |
319 | */ | 330 | */ |
320 | hc = __get_name_cell(old); | 331 | hc = __get_name_cell(param->name); |
321 | if (!hc) { | 332 | if (!hc) { |
322 | DMWARN("asked to rename a non existent device %s -> %s", | 333 | DMWARN("asked to rename a non-existent device %s -> %s", |
323 | old, new); | 334 | param->name, new); |
324 | up_write(&_hash_lock); | 335 | up_write(&_hash_lock); |
325 | kfree(new_name); | 336 | kfree(new_name); |
326 | return -ENXIO; | 337 | return ERR_PTR(-ENXIO); |
327 | } | 338 | } |
328 | 339 | ||
329 | /* | 340 | /* |
@@ -345,13 +356,14 @@ static int dm_hash_rename(uint32_t cookie, uint32_t *flags, const char *old, | |||
345 | dm_table_put(table); | 356 | dm_table_put(table); |
346 | } | 357 | } |
347 | 358 | ||
348 | if (!dm_kobject_uevent(hc->md, KOBJ_CHANGE, cookie)) | 359 | if (!dm_kobject_uevent(hc->md, KOBJ_CHANGE, param->event_nr)) |
349 | *flags |= DM_UEVENT_GENERATED_FLAG; | 360 | param->flags |= DM_UEVENT_GENERATED_FLAG; |
350 | 361 | ||
351 | dm_put(hc->md); | 362 | md = hc->md; |
352 | up_write(&_hash_lock); | 363 | up_write(&_hash_lock); |
353 | kfree(old_name); | 364 | kfree(old_name); |
354 | return 0; | 365 | |
366 | return md; | ||
355 | } | 367 | } |
356 | 368 | ||
357 | /*----------------------------------------------------------------- | 369 | /*----------------------------------------------------------------- |
@@ -573,7 +585,7 @@ static struct dm_table *dm_get_live_or_inactive_table(struct mapped_device *md, | |||
573 | * Fills in a dm_ioctl structure, ready for sending back to | 585 | * Fills in a dm_ioctl structure, ready for sending back to |
574 | * userland. | 586 | * userland. |
575 | */ | 587 | */ |
576 | static int __dev_status(struct mapped_device *md, struct dm_ioctl *param) | 588 | static void __dev_status(struct mapped_device *md, struct dm_ioctl *param) |
577 | { | 589 | { |
578 | struct gendisk *disk = dm_disk(md); | 590 | struct gendisk *disk = dm_disk(md); |
579 | struct dm_table *table; | 591 | struct dm_table *table; |
@@ -617,8 +629,6 @@ static int __dev_status(struct mapped_device *md, struct dm_ioctl *param) | |||
617 | dm_table_put(table); | 629 | dm_table_put(table); |
618 | } | 630 | } |
619 | } | 631 | } |
620 | |||
621 | return 0; | ||
622 | } | 632 | } |
623 | 633 | ||
624 | static int dev_create(struct dm_ioctl *param, size_t param_size) | 634 | static int dev_create(struct dm_ioctl *param, size_t param_size) |
@@ -640,15 +650,17 @@ static int dev_create(struct dm_ioctl *param, size_t param_size) | |||
640 | r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md); | 650 | r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md); |
641 | if (r) { | 651 | if (r) { |
642 | dm_put(md); | 652 | dm_put(md); |
653 | dm_destroy(md); | ||
643 | return r; | 654 | return r; |
644 | } | 655 | } |
645 | 656 | ||
646 | param->flags &= ~DM_INACTIVE_PRESENT_FLAG; | 657 | param->flags &= ~DM_INACTIVE_PRESENT_FLAG; |
647 | 658 | ||
648 | r = __dev_status(md, param); | 659 | __dev_status(md, param); |
660 | |||
649 | dm_put(md); | 661 | dm_put(md); |
650 | 662 | ||
651 | return r; | 663 | return 0; |
652 | } | 664 | } |
653 | 665 | ||
654 | /* | 666 | /* |
@@ -742,6 +754,7 @@ static int dev_remove(struct dm_ioctl *param, size_t param_size) | |||
742 | param->flags |= DM_UEVENT_GENERATED_FLAG; | 754 | param->flags |= DM_UEVENT_GENERATED_FLAG; |
743 | 755 | ||
744 | dm_put(md); | 756 | dm_put(md); |
757 | dm_destroy(md); | ||
745 | return 0; | 758 | return 0; |
746 | } | 759 | } |
747 | 760 | ||
@@ -762,6 +775,7 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size) | |||
762 | { | 775 | { |
763 | int r; | 776 | int r; |
764 | char *new_name = (char *) param + param->data_start; | 777 | char *new_name = (char *) param + param->data_start; |
778 | struct mapped_device *md; | ||
765 | 779 | ||
766 | if (new_name < param->data || | 780 | if (new_name < param->data || |
767 | invalid_str(new_name, (void *) param + param_size) || | 781 | invalid_str(new_name, (void *) param + param_size) || |
@@ -774,10 +788,14 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size) | |||
774 | if (r) | 788 | if (r) |
775 | return r; | 789 | return r; |
776 | 790 | ||
777 | param->data_size = 0; | 791 | md = dm_hash_rename(param, new_name); |
792 | if (IS_ERR(md)) | ||
793 | return PTR_ERR(md); | ||
794 | |||
795 | __dev_status(md, param); | ||
796 | dm_put(md); | ||
778 | 797 | ||
779 | return dm_hash_rename(param->event_nr, ¶m->flags, param->name, | 798 | return 0; |
780 | new_name); | ||
781 | } | 799 | } |
782 | 800 | ||
783 | static int dev_set_geometry(struct dm_ioctl *param, size_t param_size) | 801 | static int dev_set_geometry(struct dm_ioctl *param, size_t param_size) |
@@ -818,8 +836,6 @@ static int dev_set_geometry(struct dm_ioctl *param, size_t param_size) | |||
818 | geometry.start = indata[3]; | 836 | geometry.start = indata[3]; |
819 | 837 | ||
820 | r = dm_set_geometry(md, &geometry); | 838 | r = dm_set_geometry(md, &geometry); |
821 | if (!r) | ||
822 | r = __dev_status(md, param); | ||
823 | 839 | ||
824 | param->data_size = 0; | 840 | param->data_size = 0; |
825 | 841 | ||
@@ -843,13 +859,17 @@ static int do_suspend(struct dm_ioctl *param) | |||
843 | if (param->flags & DM_NOFLUSH_FLAG) | 859 | if (param->flags & DM_NOFLUSH_FLAG) |
844 | suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG; | 860 | suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG; |
845 | 861 | ||
846 | if (!dm_suspended_md(md)) | 862 | if (!dm_suspended_md(md)) { |
847 | r = dm_suspend(md, suspend_flags); | 863 | r = dm_suspend(md, suspend_flags); |
864 | if (r) | ||
865 | goto out; | ||
866 | } | ||
848 | 867 | ||
849 | if (!r) | 868 | __dev_status(md, param); |
850 | r = __dev_status(md, param); | ||
851 | 869 | ||
870 | out: | ||
852 | dm_put(md); | 871 | dm_put(md); |
872 | |||
853 | return r; | 873 | return r; |
854 | } | 874 | } |
855 | 875 | ||
@@ -911,7 +931,7 @@ static int do_resume(struct dm_ioctl *param) | |||
911 | dm_table_destroy(old_map); | 931 | dm_table_destroy(old_map); |
912 | 932 | ||
913 | if (!r) | 933 | if (!r) |
914 | r = __dev_status(md, param); | 934 | __dev_status(md, param); |
915 | 935 | ||
916 | dm_put(md); | 936 | dm_put(md); |
917 | return r; | 937 | return r; |
@@ -935,16 +955,16 @@ static int dev_suspend(struct dm_ioctl *param, size_t param_size) | |||
935 | */ | 955 | */ |
936 | static int dev_status(struct dm_ioctl *param, size_t param_size) | 956 | static int dev_status(struct dm_ioctl *param, size_t param_size) |
937 | { | 957 | { |
938 | int r; | ||
939 | struct mapped_device *md; | 958 | struct mapped_device *md; |
940 | 959 | ||
941 | md = find_device(param); | 960 | md = find_device(param); |
942 | if (!md) | 961 | if (!md) |
943 | return -ENXIO; | 962 | return -ENXIO; |
944 | 963 | ||
945 | r = __dev_status(md, param); | 964 | __dev_status(md, param); |
946 | dm_put(md); | 965 | dm_put(md); |
947 | return r; | 966 | |
967 | return 0; | ||
948 | } | 968 | } |
949 | 969 | ||
950 | /* | 970 | /* |
@@ -1019,7 +1039,7 @@ static void retrieve_status(struct dm_table *table, | |||
1019 | */ | 1039 | */ |
1020 | static int dev_wait(struct dm_ioctl *param, size_t param_size) | 1040 | static int dev_wait(struct dm_ioctl *param, size_t param_size) |
1021 | { | 1041 | { |
1022 | int r; | 1042 | int r = 0; |
1023 | struct mapped_device *md; | 1043 | struct mapped_device *md; |
1024 | struct dm_table *table; | 1044 | struct dm_table *table; |
1025 | 1045 | ||
@@ -1040,9 +1060,7 @@ static int dev_wait(struct dm_ioctl *param, size_t param_size) | |||
1040 | * changed to trigger the event, so we may as well tell | 1060 | * changed to trigger the event, so we may as well tell |
1041 | * him and save an ioctl. | 1061 | * him and save an ioctl. |
1042 | */ | 1062 | */ |
1043 | r = __dev_status(md, param); | 1063 | __dev_status(md, param); |
1044 | if (r) | ||
1045 | goto out; | ||
1046 | 1064 | ||
1047 | table = dm_get_live_or_inactive_table(md, param); | 1065 | table = dm_get_live_or_inactive_table(md, param); |
1048 | if (table) { | 1066 | if (table) { |
@@ -1050,8 +1068,9 @@ static int dev_wait(struct dm_ioctl *param, size_t param_size) | |||
1050 | dm_table_put(table); | 1068 | dm_table_put(table); |
1051 | } | 1069 | } |
1052 | 1070 | ||
1053 | out: | 1071 | out: |
1054 | dm_put(md); | 1072 | dm_put(md); |
1073 | |||
1055 | return r; | 1074 | return r; |
1056 | } | 1075 | } |
1057 | 1076 | ||
@@ -1112,28 +1131,9 @@ static int populate_table(struct dm_table *table, | |||
1112 | next = spec->next; | 1131 | next = spec->next; |
1113 | } | 1132 | } |
1114 | 1133 | ||
1115 | r = dm_table_set_type(table); | ||
1116 | if (r) { | ||
1117 | DMWARN("unable to set table type"); | ||
1118 | return r; | ||
1119 | } | ||
1120 | |||
1121 | return dm_table_complete(table); | 1134 | return dm_table_complete(table); |
1122 | } | 1135 | } |
1123 | 1136 | ||
1124 | static int table_prealloc_integrity(struct dm_table *t, | ||
1125 | struct mapped_device *md) | ||
1126 | { | ||
1127 | struct list_head *devices = dm_table_get_devices(t); | ||
1128 | struct dm_dev_internal *dd; | ||
1129 | |||
1130 | list_for_each_entry(dd, devices, list) | ||
1131 | if (bdev_get_integrity(dd->dm_dev.bdev)) | ||
1132 | return blk_integrity_register(dm_disk(md), NULL); | ||
1133 | |||
1134 | return 0; | ||
1135 | } | ||
1136 | |||
1137 | static int table_load(struct dm_ioctl *param, size_t param_size) | 1137 | static int table_load(struct dm_ioctl *param, size_t param_size) |
1138 | { | 1138 | { |
1139 | int r; | 1139 | int r; |
@@ -1155,21 +1155,30 @@ static int table_load(struct dm_ioctl *param, size_t param_size) | |||
1155 | goto out; | 1155 | goto out; |
1156 | } | 1156 | } |
1157 | 1157 | ||
1158 | r = table_prealloc_integrity(t, md); | 1158 | /* Protect md->type and md->queue against concurrent table loads. */ |
1159 | if (r) { | 1159 | dm_lock_md_type(md); |
1160 | DMERR("%s: could not register integrity profile.", | 1160 | if (dm_get_md_type(md) == DM_TYPE_NONE) |
1161 | dm_device_name(md)); | 1161 | /* Initial table load: acquire type of table. */ |
1162 | dm_set_md_type(md, dm_table_get_type(t)); | ||
1163 | else if (dm_get_md_type(md) != dm_table_get_type(t)) { | ||
1164 | DMWARN("can't change device type after initial table load."); | ||
1162 | dm_table_destroy(t); | 1165 | dm_table_destroy(t); |
1166 | dm_unlock_md_type(md); | ||
1167 | r = -EINVAL; | ||
1163 | goto out; | 1168 | goto out; |
1164 | } | 1169 | } |
1165 | 1170 | ||
1166 | r = dm_table_alloc_md_mempools(t); | 1171 | /* setup md->queue to reflect md's type (may block) */ |
1172 | r = dm_setup_md_queue(md); | ||
1167 | if (r) { | 1173 | if (r) { |
1168 | DMWARN("unable to allocate mempools for this table"); | 1174 | DMWARN("unable to set up device queue for new table."); |
1169 | dm_table_destroy(t); | 1175 | dm_table_destroy(t); |
1176 | dm_unlock_md_type(md); | ||
1170 | goto out; | 1177 | goto out; |
1171 | } | 1178 | } |
1179 | dm_unlock_md_type(md); | ||
1172 | 1180 | ||
1181 | /* stage inactive table */ | ||
1173 | down_write(&_hash_lock); | 1182 | down_write(&_hash_lock); |
1174 | hc = dm_get_mdptr(md); | 1183 | hc = dm_get_mdptr(md); |
1175 | if (!hc || hc->md != md) { | 1184 | if (!hc || hc->md != md) { |
@@ -1186,7 +1195,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size) | |||
1186 | up_write(&_hash_lock); | 1195 | up_write(&_hash_lock); |
1187 | 1196 | ||
1188 | param->flags |= DM_INACTIVE_PRESENT_FLAG; | 1197 | param->flags |= DM_INACTIVE_PRESENT_FLAG; |
1189 | r = __dev_status(md, param); | 1198 | __dev_status(md, param); |
1190 | 1199 | ||
1191 | out: | 1200 | out: |
1192 | dm_put(md); | 1201 | dm_put(md); |
@@ -1196,7 +1205,6 @@ out: | |||
1196 | 1205 | ||
1197 | static int table_clear(struct dm_ioctl *param, size_t param_size) | 1206 | static int table_clear(struct dm_ioctl *param, size_t param_size) |
1198 | { | 1207 | { |
1199 | int r; | ||
1200 | struct hash_cell *hc; | 1208 | struct hash_cell *hc; |
1201 | struct mapped_device *md; | 1209 | struct mapped_device *md; |
1202 | 1210 | ||
@@ -1216,11 +1224,12 @@ static int table_clear(struct dm_ioctl *param, size_t param_size) | |||
1216 | 1224 | ||
1217 | param->flags &= ~DM_INACTIVE_PRESENT_FLAG; | 1225 | param->flags &= ~DM_INACTIVE_PRESENT_FLAG; |
1218 | 1226 | ||
1219 | r = __dev_status(hc->md, param); | 1227 | __dev_status(hc->md, param); |
1220 | md = hc->md; | 1228 | md = hc->md; |
1221 | up_write(&_hash_lock); | 1229 | up_write(&_hash_lock); |
1222 | dm_put(md); | 1230 | dm_put(md); |
1223 | return r; | 1231 | |
1232 | return 0; | ||
1224 | } | 1233 | } |
1225 | 1234 | ||
1226 | /* | 1235 | /* |
@@ -1265,7 +1274,6 @@ static void retrieve_deps(struct dm_table *table, | |||
1265 | 1274 | ||
1266 | static int table_deps(struct dm_ioctl *param, size_t param_size) | 1275 | static int table_deps(struct dm_ioctl *param, size_t param_size) |
1267 | { | 1276 | { |
1268 | int r = 0; | ||
1269 | struct mapped_device *md; | 1277 | struct mapped_device *md; |
1270 | struct dm_table *table; | 1278 | struct dm_table *table; |
1271 | 1279 | ||
@@ -1273,9 +1281,7 @@ static int table_deps(struct dm_ioctl *param, size_t param_size) | |||
1273 | if (!md) | 1281 | if (!md) |
1274 | return -ENXIO; | 1282 | return -ENXIO; |
1275 | 1283 | ||
1276 | r = __dev_status(md, param); | 1284 | __dev_status(md, param); |
1277 | if (r) | ||
1278 | goto out; | ||
1279 | 1285 | ||
1280 | table = dm_get_live_or_inactive_table(md, param); | 1286 | table = dm_get_live_or_inactive_table(md, param); |
1281 | if (table) { | 1287 | if (table) { |
@@ -1283,9 +1289,9 @@ static int table_deps(struct dm_ioctl *param, size_t param_size) | |||
1283 | dm_table_put(table); | 1289 | dm_table_put(table); |
1284 | } | 1290 | } |
1285 | 1291 | ||
1286 | out: | ||
1287 | dm_put(md); | 1292 | dm_put(md); |
1288 | return r; | 1293 | |
1294 | return 0; | ||
1289 | } | 1295 | } |
1290 | 1296 | ||
1291 | /* | 1297 | /* |
@@ -1294,7 +1300,6 @@ static int table_deps(struct dm_ioctl *param, size_t param_size) | |||
1294 | */ | 1300 | */ |
1295 | static int table_status(struct dm_ioctl *param, size_t param_size) | 1301 | static int table_status(struct dm_ioctl *param, size_t param_size) |
1296 | { | 1302 | { |
1297 | int r; | ||
1298 | struct mapped_device *md; | 1303 | struct mapped_device *md; |
1299 | struct dm_table *table; | 1304 | struct dm_table *table; |
1300 | 1305 | ||
@@ -1302,9 +1307,7 @@ static int table_status(struct dm_ioctl *param, size_t param_size) | |||
1302 | if (!md) | 1307 | if (!md) |
1303 | return -ENXIO; | 1308 | return -ENXIO; |
1304 | 1309 | ||
1305 | r = __dev_status(md, param); | 1310 | __dev_status(md, param); |
1306 | if (r) | ||
1307 | goto out; | ||
1308 | 1311 | ||
1309 | table = dm_get_live_or_inactive_table(md, param); | 1312 | table = dm_get_live_or_inactive_table(md, param); |
1310 | if (table) { | 1313 | if (table) { |
@@ -1312,9 +1315,9 @@ static int table_status(struct dm_ioctl *param, size_t param_size) | |||
1312 | dm_table_put(table); | 1315 | dm_table_put(table); |
1313 | } | 1316 | } |
1314 | 1317 | ||
1315 | out: | ||
1316 | dm_put(md); | 1318 | dm_put(md); |
1317 | return r; | 1319 | |
1320 | return 0; | ||
1318 | } | 1321 | } |
1319 | 1322 | ||
1320 | /* | 1323 | /* |
@@ -1333,10 +1336,6 @@ static int target_message(struct dm_ioctl *param, size_t param_size) | |||
1333 | if (!md) | 1336 | if (!md) |
1334 | return -ENXIO; | 1337 | return -ENXIO; |
1335 | 1338 | ||
1336 | r = __dev_status(md, param); | ||
1337 | if (r) | ||
1338 | goto out; | ||
1339 | |||
1340 | if (tmsg < (struct dm_target_msg *) param->data || | 1339 | if (tmsg < (struct dm_target_msg *) param->data || |
1341 | invalid_str(tmsg->message, (void *) param + param_size)) { | 1340 | invalid_str(tmsg->message, (void *) param + param_size)) { |
1342 | DMWARN("Invalid target message parameters."); | 1341 | DMWARN("Invalid target message parameters."); |
@@ -1593,18 +1592,22 @@ static long dm_compat_ctl_ioctl(struct file *file, uint command, ulong u) | |||
1593 | #endif | 1592 | #endif |
1594 | 1593 | ||
1595 | static const struct file_operations _ctl_fops = { | 1594 | static const struct file_operations _ctl_fops = { |
1595 | .open = nonseekable_open, | ||
1596 | .unlocked_ioctl = dm_ctl_ioctl, | 1596 | .unlocked_ioctl = dm_ctl_ioctl, |
1597 | .compat_ioctl = dm_compat_ctl_ioctl, | 1597 | .compat_ioctl = dm_compat_ctl_ioctl, |
1598 | .owner = THIS_MODULE, | 1598 | .owner = THIS_MODULE, |
1599 | }; | 1599 | }; |
1600 | 1600 | ||
1601 | static struct miscdevice _dm_misc = { | 1601 | static struct miscdevice _dm_misc = { |
1602 | .minor = MISC_DYNAMIC_MINOR, | 1602 | .minor = MAPPER_CTRL_MINOR, |
1603 | .name = DM_NAME, | 1603 | .name = DM_NAME, |
1604 | .nodename = "mapper/control", | 1604 | .nodename = DM_DIR "/" DM_CONTROL_NODE, |
1605 | .fops = &_ctl_fops | 1605 | .fops = &_ctl_fops |
1606 | }; | 1606 | }; |
1607 | 1607 | ||
1608 | MODULE_ALIAS_MISCDEV(MAPPER_CTRL_MINOR); | ||
1609 | MODULE_ALIAS("devname:" DM_DIR "/" DM_CONTROL_NODE); | ||
1610 | |||
1608 | /* | 1611 | /* |
1609 | * Create misc character device and link to DM_DIR/control. | 1612 | * Create misc character device and link to DM_DIR/control. |
1610 | */ | 1613 | */ |
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index 9200dbf2391a..3921e3bb43c1 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c | |||
@@ -53,6 +53,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
53 | } | 53 | } |
54 | 54 | ||
55 | ti->num_flush_requests = 1; | 55 | ti->num_flush_requests = 1; |
56 | ti->num_discard_requests = 1; | ||
56 | ti->private = lc; | 57 | ti->private = lc; |
57 | return 0; | 58 | return 0; |
58 | 59 | ||
@@ -73,7 +74,7 @@ static sector_t linear_map_sector(struct dm_target *ti, sector_t bi_sector) | |||
73 | { | 74 | { |
74 | struct linear_c *lc = ti->private; | 75 | struct linear_c *lc = ti->private; |
75 | 76 | ||
76 | return lc->start + (bi_sector - ti->begin); | 77 | return lc->start + dm_target_offset(ti, bi_sector); |
77 | } | 78 | } |
78 | 79 | ||
79 | static void linear_map_bio(struct dm_target *ti, struct bio *bio) | 80 | static void linear_map_bio(struct dm_target *ti, struct bio *bio) |
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 826bce7343b3..487ecda90ad4 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c | |||
@@ -706,6 +706,7 @@ static struct priority_group *parse_priority_group(struct arg_set *as, | |||
706 | 706 | ||
707 | if (as->argc < nr_params) { | 707 | if (as->argc < nr_params) { |
708 | ti->error = "not enough path parameters"; | 708 | ti->error = "not enough path parameters"; |
709 | r = -EINVAL; | ||
709 | goto bad; | 710 | goto bad; |
710 | } | 711 | } |
711 | 712 | ||
@@ -892,6 +893,7 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc, | |||
892 | } | 893 | } |
893 | 894 | ||
894 | ti->num_flush_requests = 1; | 895 | ti->num_flush_requests = 1; |
896 | ti->num_discard_requests = 1; | ||
895 | 897 | ||
896 | return 0; | 898 | return 0; |
897 | 899 | ||
@@ -1271,6 +1273,15 @@ static int do_end_io(struct multipath *m, struct request *clone, | |||
1271 | if (error == -EOPNOTSUPP) | 1273 | if (error == -EOPNOTSUPP) |
1272 | return error; | 1274 | return error; |
1273 | 1275 | ||
1276 | if (clone->cmd_flags & REQ_DISCARD) | ||
1277 | /* | ||
1278 | * Pass all discard request failures up. | ||
1279 | * FIXME: only fail_path if the discard failed due to a | ||
1280 | * transport problem. This requires precise understanding | ||
1281 | * of the underlying failure (e.g. the SCSI sense). | ||
1282 | */ | ||
1283 | return error; | ||
1284 | |||
1274 | if (mpio->pgpath) | 1285 | if (mpio->pgpath) |
1275 | fail_path(mpio->pgpath); | 1286 | fail_path(mpio->pgpath); |
1276 | 1287 | ||
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 74136262d654..7c081bcbc3cf 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
@@ -445,7 +445,7 @@ static sector_t map_sector(struct mirror *m, struct bio *bio) | |||
445 | { | 445 | { |
446 | if (unlikely(!bio->bi_size)) | 446 | if (unlikely(!bio->bi_size)) |
447 | return 0; | 447 | return 0; |
448 | return m->offset + (bio->bi_sector - m->ms->ti->begin); | 448 | return m->offset + dm_target_offset(m->ms->ti, bio->bi_sector); |
449 | } | 449 | } |
450 | 450 | ||
451 | static void map_bio(struct mirror *m, struct bio *bio) | 451 | static void map_bio(struct mirror *m, struct bio *bio) |
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index c097d8a4823d..cc2bdb83f9ad 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c | |||
@@ -266,7 +266,7 @@ static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, int rw, | |||
266 | */ | 266 | */ |
267 | static chunk_t area_location(struct pstore *ps, chunk_t area) | 267 | static chunk_t area_location(struct pstore *ps, chunk_t area) |
268 | { | 268 | { |
269 | return 1 + ((ps->exceptions_per_area + 1) * area); | 269 | return NUM_SNAPSHOT_HDR_CHUNKS + ((ps->exceptions_per_area + 1) * area); |
270 | } | 270 | } |
271 | 271 | ||
272 | /* | 272 | /* |
@@ -780,8 +780,8 @@ static int persistent_commit_merge(struct dm_exception_store *store, | |||
780 | * ps->current_area does not get reduced by prepare_merge() until | 780 | * ps->current_area does not get reduced by prepare_merge() until |
781 | * after commit_merge() has removed the nr_merged previous exceptions. | 781 | * after commit_merge() has removed the nr_merged previous exceptions. |
782 | */ | 782 | */ |
783 | ps->next_free = (area_location(ps, ps->current_area) - 1) + | 783 | ps->next_free = area_location(ps, ps->current_area) + |
784 | (ps->current_committed + 1) + NUM_SNAPSHOT_HDR_CHUNKS; | 784 | ps->current_committed + 1; |
785 | 785 | ||
786 | return 0; | 786 | return 0; |
787 | } | 787 | } |
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 54853773510c..5974d3094d97 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
@@ -148,6 +148,12 @@ struct dm_snapshot { | |||
148 | #define RUNNING_MERGE 0 | 148 | #define RUNNING_MERGE 0 |
149 | #define SHUTDOWN_MERGE 1 | 149 | #define SHUTDOWN_MERGE 1 |
150 | 150 | ||
151 | struct dm_dev *dm_snap_origin(struct dm_snapshot *s) | ||
152 | { | ||
153 | return s->origin; | ||
154 | } | ||
155 | EXPORT_SYMBOL(dm_snap_origin); | ||
156 | |||
151 | struct dm_dev *dm_snap_cow(struct dm_snapshot *s) | 157 | struct dm_dev *dm_snap_cow(struct dm_snapshot *s) |
152 | { | 158 | { |
153 | return s->cow; | 159 | return s->cow; |
@@ -1065,10 +1071,6 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1065 | origin_mode = FMODE_WRITE; | 1071 | origin_mode = FMODE_WRITE; |
1066 | } | 1072 | } |
1067 | 1073 | ||
1068 | origin_path = argv[0]; | ||
1069 | argv++; | ||
1070 | argc--; | ||
1071 | |||
1072 | s = kmalloc(sizeof(*s), GFP_KERNEL); | 1074 | s = kmalloc(sizeof(*s), GFP_KERNEL); |
1073 | if (!s) { | 1075 | if (!s) { |
1074 | ti->error = "Cannot allocate snapshot context private " | 1076 | ti->error = "Cannot allocate snapshot context private " |
@@ -1077,6 +1079,16 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1077 | goto bad; | 1079 | goto bad; |
1078 | } | 1080 | } |
1079 | 1081 | ||
1082 | origin_path = argv[0]; | ||
1083 | argv++; | ||
1084 | argc--; | ||
1085 | |||
1086 | r = dm_get_device(ti, origin_path, origin_mode, &s->origin); | ||
1087 | if (r) { | ||
1088 | ti->error = "Cannot get origin device"; | ||
1089 | goto bad_origin; | ||
1090 | } | ||
1091 | |||
1080 | cow_path = argv[0]; | 1092 | cow_path = argv[0]; |
1081 | argv++; | 1093 | argv++; |
1082 | argc--; | 1094 | argc--; |
@@ -1097,12 +1109,6 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1097 | argv += args_used; | 1109 | argv += args_used; |
1098 | argc -= args_used; | 1110 | argc -= args_used; |
1099 | 1111 | ||
1100 | r = dm_get_device(ti, origin_path, origin_mode, &s->origin); | ||
1101 | if (r) { | ||
1102 | ti->error = "Cannot get origin device"; | ||
1103 | goto bad_origin; | ||
1104 | } | ||
1105 | |||
1106 | s->ti = ti; | 1112 | s->ti = ti; |
1107 | s->valid = 1; | 1113 | s->valid = 1; |
1108 | s->active = 0; | 1114 | s->active = 0; |
@@ -1212,15 +1218,15 @@ bad_kcopyd: | |||
1212 | dm_exception_table_exit(&s->complete, exception_cache); | 1218 | dm_exception_table_exit(&s->complete, exception_cache); |
1213 | 1219 | ||
1214 | bad_hash_tables: | 1220 | bad_hash_tables: |
1215 | dm_put_device(ti, s->origin); | ||
1216 | |||
1217 | bad_origin: | ||
1218 | dm_exception_store_destroy(s->store); | 1221 | dm_exception_store_destroy(s->store); |
1219 | 1222 | ||
1220 | bad_store: | 1223 | bad_store: |
1221 | dm_put_device(ti, s->cow); | 1224 | dm_put_device(ti, s->cow); |
1222 | 1225 | ||
1223 | bad_cow: | 1226 | bad_cow: |
1227 | dm_put_device(ti, s->origin); | ||
1228 | |||
1229 | bad_origin: | ||
1224 | kfree(s); | 1230 | kfree(s); |
1225 | 1231 | ||
1226 | bad: | 1232 | bad: |
@@ -1314,12 +1320,12 @@ static void snapshot_dtr(struct dm_target *ti) | |||
1314 | 1320 | ||
1315 | mempool_destroy(s->pending_pool); | 1321 | mempool_destroy(s->pending_pool); |
1316 | 1322 | ||
1317 | dm_put_device(ti, s->origin); | ||
1318 | |||
1319 | dm_exception_store_destroy(s->store); | 1323 | dm_exception_store_destroy(s->store); |
1320 | 1324 | ||
1321 | dm_put_device(ti, s->cow); | 1325 | dm_put_device(ti, s->cow); |
1322 | 1326 | ||
1327 | dm_put_device(ti, s->origin); | ||
1328 | |||
1323 | kfree(s); | 1329 | kfree(s); |
1324 | } | 1330 | } |
1325 | 1331 | ||
@@ -1686,7 +1692,7 @@ static int snapshot_merge_map(struct dm_target *ti, struct bio *bio, | |||
1686 | chunk_t chunk; | 1692 | chunk_t chunk; |
1687 | 1693 | ||
1688 | if (unlikely(bio_empty_barrier(bio))) { | 1694 | if (unlikely(bio_empty_barrier(bio))) { |
1689 | if (!map_context->flush_request) | 1695 | if (!map_context->target_request_nr) |
1690 | bio->bi_bdev = s->origin->bdev; | 1696 | bio->bi_bdev = s->origin->bdev; |
1691 | else | 1697 | else |
1692 | bio->bi_bdev = s->cow->bdev; | 1698 | bio->bi_bdev = s->cow->bdev; |
@@ -1899,8 +1905,14 @@ static int snapshot_iterate_devices(struct dm_target *ti, | |||
1899 | iterate_devices_callout_fn fn, void *data) | 1905 | iterate_devices_callout_fn fn, void *data) |
1900 | { | 1906 | { |
1901 | struct dm_snapshot *snap = ti->private; | 1907 | struct dm_snapshot *snap = ti->private; |
1908 | int r; | ||
1909 | |||
1910 | r = fn(ti, snap->origin, 0, ti->len, data); | ||
1911 | |||
1912 | if (!r) | ||
1913 | r = fn(ti, snap->cow, 0, get_dev_size(snap->cow->bdev), data); | ||
1902 | 1914 | ||
1903 | return fn(ti, snap->origin, 0, ti->len, data); | 1915 | return r; |
1904 | } | 1916 | } |
1905 | 1917 | ||
1906 | 1918 | ||
@@ -2159,6 +2171,21 @@ static int origin_status(struct dm_target *ti, status_type_t type, char *result, | |||
2159 | return 0; | 2171 | return 0; |
2160 | } | 2172 | } |
2161 | 2173 | ||
2174 | static int origin_merge(struct dm_target *ti, struct bvec_merge_data *bvm, | ||
2175 | struct bio_vec *biovec, int max_size) | ||
2176 | { | ||
2177 | struct dm_dev *dev = ti->private; | ||
2178 | struct request_queue *q = bdev_get_queue(dev->bdev); | ||
2179 | |||
2180 | if (!q->merge_bvec_fn) | ||
2181 | return max_size; | ||
2182 | |||
2183 | bvm->bi_bdev = dev->bdev; | ||
2184 | bvm->bi_sector = bvm->bi_sector; | ||
2185 | |||
2186 | return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); | ||
2187 | } | ||
2188 | |||
2162 | static int origin_iterate_devices(struct dm_target *ti, | 2189 | static int origin_iterate_devices(struct dm_target *ti, |
2163 | iterate_devices_callout_fn fn, void *data) | 2190 | iterate_devices_callout_fn fn, void *data) |
2164 | { | 2191 | { |
@@ -2176,6 +2203,7 @@ static struct target_type origin_target = { | |||
2176 | .map = origin_map, | 2203 | .map = origin_map, |
2177 | .resume = origin_resume, | 2204 | .resume = origin_resume, |
2178 | .status = origin_status, | 2205 | .status = origin_status, |
2206 | .merge = origin_merge, | ||
2179 | .iterate_devices = origin_iterate_devices, | 2207 | .iterate_devices = origin_iterate_devices, |
2180 | }; | 2208 | }; |
2181 | 2209 | ||
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index d6e28d732b4d..c297f6da91ea 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c | |||
@@ -25,6 +25,8 @@ struct stripe { | |||
25 | 25 | ||
26 | struct stripe_c { | 26 | struct stripe_c { |
27 | uint32_t stripes; | 27 | uint32_t stripes; |
28 | int stripes_shift; | ||
29 | sector_t stripes_mask; | ||
28 | 30 | ||
29 | /* The size of this target / num. stripes */ | 31 | /* The size of this target / num. stripes */ |
30 | sector_t stripe_width; | 32 | sector_t stripe_width; |
@@ -162,16 +164,22 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
162 | 164 | ||
163 | /* Set pointer to dm target; used in trigger_event */ | 165 | /* Set pointer to dm target; used in trigger_event */ |
164 | sc->ti = ti; | 166 | sc->ti = ti; |
165 | |||
166 | sc->stripes = stripes; | 167 | sc->stripes = stripes; |
167 | sc->stripe_width = width; | 168 | sc->stripe_width = width; |
169 | |||
170 | if (stripes & (stripes - 1)) | ||
171 | sc->stripes_shift = -1; | ||
172 | else { | ||
173 | sc->stripes_shift = ffs(stripes) - 1; | ||
174 | sc->stripes_mask = ((sector_t) stripes) - 1; | ||
175 | } | ||
176 | |||
168 | ti->split_io = chunk_size; | 177 | ti->split_io = chunk_size; |
169 | ti->num_flush_requests = stripes; | 178 | ti->num_flush_requests = stripes; |
179 | ti->num_discard_requests = stripes; | ||
170 | 180 | ||
181 | sc->chunk_shift = ffs(chunk_size) - 1; | ||
171 | sc->chunk_mask = ((sector_t) chunk_size) - 1; | 182 | sc->chunk_mask = ((sector_t) chunk_size) - 1; |
172 | for (sc->chunk_shift = 0; chunk_size; sc->chunk_shift++) | ||
173 | chunk_size >>= 1; | ||
174 | sc->chunk_shift--; | ||
175 | 183 | ||
176 | /* | 184 | /* |
177 | * Get the stripe destinations. | 185 | * Get the stripe destinations. |
@@ -207,26 +215,79 @@ static void stripe_dtr(struct dm_target *ti) | |||
207 | kfree(sc); | 215 | kfree(sc); |
208 | } | 216 | } |
209 | 217 | ||
218 | static void stripe_map_sector(struct stripe_c *sc, sector_t sector, | ||
219 | uint32_t *stripe, sector_t *result) | ||
220 | { | ||
221 | sector_t offset = dm_target_offset(sc->ti, sector); | ||
222 | sector_t chunk = offset >> sc->chunk_shift; | ||
223 | |||
224 | if (sc->stripes_shift < 0) | ||
225 | *stripe = sector_div(chunk, sc->stripes); | ||
226 | else { | ||
227 | *stripe = chunk & sc->stripes_mask; | ||
228 | chunk >>= sc->stripes_shift; | ||
229 | } | ||
230 | |||
231 | *result = (chunk << sc->chunk_shift) | (offset & sc->chunk_mask); | ||
232 | } | ||
233 | |||
234 | static void stripe_map_range_sector(struct stripe_c *sc, sector_t sector, | ||
235 | uint32_t target_stripe, sector_t *result) | ||
236 | { | ||
237 | uint32_t stripe; | ||
238 | |||
239 | stripe_map_sector(sc, sector, &stripe, result); | ||
240 | if (stripe == target_stripe) | ||
241 | return; | ||
242 | *result &= ~sc->chunk_mask; /* round down */ | ||
243 | if (target_stripe < stripe) | ||
244 | *result += sc->chunk_mask + 1; /* next chunk */ | ||
245 | } | ||
246 | |||
247 | static int stripe_map_discard(struct stripe_c *sc, struct bio *bio, | ||
248 | uint32_t target_stripe) | ||
249 | { | ||
250 | sector_t begin, end; | ||
251 | |||
252 | stripe_map_range_sector(sc, bio->bi_sector, target_stripe, &begin); | ||
253 | stripe_map_range_sector(sc, bio->bi_sector + bio_sectors(bio), | ||
254 | target_stripe, &end); | ||
255 | if (begin < end) { | ||
256 | bio->bi_bdev = sc->stripe[target_stripe].dev->bdev; | ||
257 | bio->bi_sector = begin + sc->stripe[target_stripe].physical_start; | ||
258 | bio->bi_size = to_bytes(end - begin); | ||
259 | return DM_MAPIO_REMAPPED; | ||
260 | } else { | ||
261 | /* The range doesn't map to the target stripe */ | ||
262 | bio_endio(bio, 0); | ||
263 | return DM_MAPIO_SUBMITTED; | ||
264 | } | ||
265 | } | ||
266 | |||
210 | static int stripe_map(struct dm_target *ti, struct bio *bio, | 267 | static int stripe_map(struct dm_target *ti, struct bio *bio, |
211 | union map_info *map_context) | 268 | union map_info *map_context) |
212 | { | 269 | { |
213 | struct stripe_c *sc = (struct stripe_c *) ti->private; | 270 | struct stripe_c *sc = ti->private; |
214 | sector_t offset, chunk; | ||
215 | uint32_t stripe; | 271 | uint32_t stripe; |
272 | unsigned target_request_nr; | ||
216 | 273 | ||
217 | if (unlikely(bio_empty_barrier(bio))) { | 274 | if (unlikely(bio_empty_barrier(bio))) { |
218 | BUG_ON(map_context->flush_request >= sc->stripes); | 275 | target_request_nr = map_context->target_request_nr; |
219 | bio->bi_bdev = sc->stripe[map_context->flush_request].dev->bdev; | 276 | BUG_ON(target_request_nr >= sc->stripes); |
277 | bio->bi_bdev = sc->stripe[target_request_nr].dev->bdev; | ||
220 | return DM_MAPIO_REMAPPED; | 278 | return DM_MAPIO_REMAPPED; |
221 | } | 279 | } |
280 | if (unlikely(bio->bi_rw & REQ_DISCARD)) { | ||
281 | target_request_nr = map_context->target_request_nr; | ||
282 | BUG_ON(target_request_nr >= sc->stripes); | ||
283 | return stripe_map_discard(sc, bio, target_request_nr); | ||
284 | } | ||
222 | 285 | ||
223 | offset = bio->bi_sector - ti->begin; | 286 | stripe_map_sector(sc, bio->bi_sector, &stripe, &bio->bi_sector); |
224 | chunk = offset >> sc->chunk_shift; | ||
225 | stripe = sector_div(chunk, sc->stripes); | ||
226 | 287 | ||
288 | bio->bi_sector += sc->stripe[stripe].physical_start; | ||
227 | bio->bi_bdev = sc->stripe[stripe].dev->bdev; | 289 | bio->bi_bdev = sc->stripe[stripe].dev->bdev; |
228 | bio->bi_sector = sc->stripe[stripe].physical_start + | 290 | |
229 | (chunk << sc->chunk_shift) + (offset & sc->chunk_mask); | ||
230 | return DM_MAPIO_REMAPPED; | 291 | return DM_MAPIO_REMAPPED; |
231 | } | 292 | } |
232 | 293 | ||
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 9924ea23032d..f9fc07d7a4b9 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
@@ -54,6 +54,8 @@ struct dm_table { | |||
54 | sector_t *highs; | 54 | sector_t *highs; |
55 | struct dm_target *targets; | 55 | struct dm_target *targets; |
56 | 56 | ||
57 | unsigned discards_supported:1; | ||
58 | |||
57 | /* | 59 | /* |
58 | * Indicates the rw permissions for the new logical | 60 | * Indicates the rw permissions for the new logical |
59 | * device. This should be a combination of FMODE_READ | 61 | * device. This should be a combination of FMODE_READ |
@@ -203,6 +205,7 @@ int dm_table_create(struct dm_table **result, fmode_t mode, | |||
203 | 205 | ||
204 | INIT_LIST_HEAD(&t->devices); | 206 | INIT_LIST_HEAD(&t->devices); |
205 | atomic_set(&t->holders, 0); | 207 | atomic_set(&t->holders, 0); |
208 | t->discards_supported = 1; | ||
206 | 209 | ||
207 | if (!num_targets) | 210 | if (!num_targets) |
208 | num_targets = KEYS_PER_NODE; | 211 | num_targets = KEYS_PER_NODE; |
@@ -245,7 +248,7 @@ void dm_table_destroy(struct dm_table *t) | |||
245 | msleep(1); | 248 | msleep(1); |
246 | smp_mb(); | 249 | smp_mb(); |
247 | 250 | ||
248 | /* free the indexes (see dm_table_complete) */ | 251 | /* free the indexes */ |
249 | if (t->depth >= 2) | 252 | if (t->depth >= 2) |
250 | vfree(t->index[t->depth - 2]); | 253 | vfree(t->index[t->depth - 2]); |
251 | 254 | ||
@@ -770,6 +773,9 @@ int dm_table_add_target(struct dm_table *t, const char *type, | |||
770 | 773 | ||
771 | t->highs[t->num_targets++] = tgt->begin + tgt->len - 1; | 774 | t->highs[t->num_targets++] = tgt->begin + tgt->len - 1; |
772 | 775 | ||
776 | if (!tgt->num_discard_requests) | ||
777 | t->discards_supported = 0; | ||
778 | |||
773 | return 0; | 779 | return 0; |
774 | 780 | ||
775 | bad: | 781 | bad: |
@@ -778,7 +784,7 @@ int dm_table_add_target(struct dm_table *t, const char *type, | |||
778 | return r; | 784 | return r; |
779 | } | 785 | } |
780 | 786 | ||
781 | int dm_table_set_type(struct dm_table *t) | 787 | static int dm_table_set_type(struct dm_table *t) |
782 | { | 788 | { |
783 | unsigned i; | 789 | unsigned i; |
784 | unsigned bio_based = 0, request_based = 0; | 790 | unsigned bio_based = 0, request_based = 0; |
@@ -900,7 +906,7 @@ static int setup_indexes(struct dm_table *t) | |||
900 | /* | 906 | /* |
901 | * Builds the btree to index the map. | 907 | * Builds the btree to index the map. |
902 | */ | 908 | */ |
903 | int dm_table_complete(struct dm_table *t) | 909 | static int dm_table_build_index(struct dm_table *t) |
904 | { | 910 | { |
905 | int r = 0; | 911 | int r = 0; |
906 | unsigned int leaf_nodes; | 912 | unsigned int leaf_nodes; |
@@ -919,6 +925,55 @@ int dm_table_complete(struct dm_table *t) | |||
919 | return r; | 925 | return r; |
920 | } | 926 | } |
921 | 927 | ||
928 | /* | ||
929 | * Register the mapped device for blk_integrity support if | ||
930 | * the underlying devices support it. | ||
931 | */ | ||
932 | static int dm_table_prealloc_integrity(struct dm_table *t, struct mapped_device *md) | ||
933 | { | ||
934 | struct list_head *devices = dm_table_get_devices(t); | ||
935 | struct dm_dev_internal *dd; | ||
936 | |||
937 | list_for_each_entry(dd, devices, list) | ||
938 | if (bdev_get_integrity(dd->dm_dev.bdev)) | ||
939 | return blk_integrity_register(dm_disk(md), NULL); | ||
940 | |||
941 | return 0; | ||
942 | } | ||
943 | |||
944 | /* | ||
945 | * Prepares the table for use by building the indices, | ||
946 | * setting the type, and allocating mempools. | ||
947 | */ | ||
948 | int dm_table_complete(struct dm_table *t) | ||
949 | { | ||
950 | int r; | ||
951 | |||
952 | r = dm_table_set_type(t); | ||
953 | if (r) { | ||
954 | DMERR("unable to set table type"); | ||
955 | return r; | ||
956 | } | ||
957 | |||
958 | r = dm_table_build_index(t); | ||
959 | if (r) { | ||
960 | DMERR("unable to build btrees"); | ||
961 | return r; | ||
962 | } | ||
963 | |||
964 | r = dm_table_prealloc_integrity(t, t->md); | ||
965 | if (r) { | ||
966 | DMERR("could not register integrity profile."); | ||
967 | return r; | ||
968 | } | ||
969 | |||
970 | r = dm_table_alloc_md_mempools(t); | ||
971 | if (r) | ||
972 | DMERR("unable to allocate mempools"); | ||
973 | |||
974 | return r; | ||
975 | } | ||
976 | |||
922 | static DEFINE_MUTEX(_event_lock); | 977 | static DEFINE_MUTEX(_event_lock); |
923 | void dm_table_event_callback(struct dm_table *t, | 978 | void dm_table_event_callback(struct dm_table *t, |
924 | void (*fn)(void *), void *context) | 979 | void (*fn)(void *), void *context) |
@@ -1086,6 +1141,11 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, | |||
1086 | else | 1141 | else |
1087 | queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q); | 1142 | queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q); |
1088 | 1143 | ||
1144 | if (!dm_table_supports_discards(t)) | ||
1145 | queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q); | ||
1146 | else | ||
1147 | queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); | ||
1148 | |||
1089 | dm_table_set_integrity(t); | 1149 | dm_table_set_integrity(t); |
1090 | 1150 | ||
1091 | /* | 1151 | /* |
@@ -1232,6 +1292,39 @@ struct mapped_device *dm_table_get_md(struct dm_table *t) | |||
1232 | return t->md; | 1292 | return t->md; |
1233 | } | 1293 | } |
1234 | 1294 | ||
1295 | static int device_discard_capable(struct dm_target *ti, struct dm_dev *dev, | ||
1296 | sector_t start, sector_t len, void *data) | ||
1297 | { | ||
1298 | struct request_queue *q = bdev_get_queue(dev->bdev); | ||
1299 | |||
1300 | return q && blk_queue_discard(q); | ||
1301 | } | ||
1302 | |||
1303 | bool dm_table_supports_discards(struct dm_table *t) | ||
1304 | { | ||
1305 | struct dm_target *ti; | ||
1306 | unsigned i = 0; | ||
1307 | |||
1308 | if (!t->discards_supported) | ||
1309 | return 0; | ||
1310 | |||
1311 | /* | ||
1312 | * Ensure that at least one underlying device supports discards. | ||
1313 | * t->devices includes internal dm devices such as mirror logs | ||
1314 | * so we need to use iterate_devices here, which targets | ||
1315 | * supporting discard must provide. | ||
1316 | */ | ||
1317 | while (i < dm_table_get_num_targets(t)) { | ||
1318 | ti = dm_table_get_target(t, i++); | ||
1319 | |||
1320 | if (ti->type->iterate_devices && | ||
1321 | ti->type->iterate_devices(ti, device_discard_capable, NULL)) | ||
1322 | return 1; | ||
1323 | } | ||
1324 | |||
1325 | return 0; | ||
1326 | } | ||
1327 | |||
1235 | EXPORT_SYMBOL(dm_vcalloc); | 1328 | EXPORT_SYMBOL(dm_vcalloc); |
1236 | EXPORT_SYMBOL(dm_get_device); | 1329 | EXPORT_SYMBOL(dm_get_device); |
1237 | EXPORT_SYMBOL(dm_put_device); | 1330 | EXPORT_SYMBOL(dm_put_device); |
diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c index 11dea11dc0b6..8da366cf381c 100644 --- a/drivers/md/dm-target.c +++ b/drivers/md/dm-target.c | |||
@@ -113,6 +113,11 @@ void dm_unregister_target(struct target_type *tt) | |||
113 | */ | 113 | */ |
114 | static int io_err_ctr(struct dm_target *tt, unsigned int argc, char **args) | 114 | static int io_err_ctr(struct dm_target *tt, unsigned int argc, char **args) |
115 | { | 115 | { |
116 | /* | ||
117 | * Return error for discards instead of -EOPNOTSUPP | ||
118 | */ | ||
119 | tt->num_discard_requests = 1; | ||
120 | |||
116 | return 0; | 121 | return 0; |
117 | } | 122 | } |
118 | 123 | ||
diff --git a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c index bbc97030c0c2..cc2b3cb81946 100644 --- a/drivers/md/dm-zero.c +++ b/drivers/md/dm-zero.c | |||
@@ -22,6 +22,11 @@ static int zero_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
22 | return -EINVAL; | 22 | return -EINVAL; |
23 | } | 23 | } |
24 | 24 | ||
25 | /* | ||
26 | * Silently drop discards, avoiding -EOPNOTSUPP. | ||
27 | */ | ||
28 | ti->num_discard_requests = 1; | ||
29 | |||
25 | return 0; | 30 | return 0; |
26 | } | 31 | } |
27 | 32 | ||
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index a3f21dc02bd8..ac384b2a6a33 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/idr.h> | 21 | #include <linux/idr.h> |
22 | #include <linux/hdreg.h> | 22 | #include <linux/hdreg.h> |
23 | #include <linux/delay.h> | ||
23 | 24 | ||
24 | #include <trace/events/block.h> | 25 | #include <trace/events/block.h> |
25 | 26 | ||
@@ -124,6 +125,10 @@ struct mapped_device { | |||
124 | unsigned long flags; | 125 | unsigned long flags; |
125 | 126 | ||
126 | struct request_queue *queue; | 127 | struct request_queue *queue; |
128 | unsigned type; | ||
129 | /* Protect queue and type against concurrent access. */ | ||
130 | struct mutex type_lock; | ||
131 | |||
127 | struct gendisk *disk; | 132 | struct gendisk *disk; |
128 | char name[16]; | 133 | char name[16]; |
129 | 134 | ||
@@ -638,8 +643,14 @@ static void dec_pending(struct dm_io *io, int error) | |||
638 | * There can be just one barrier request so we use | 643 | * There can be just one barrier request so we use |
639 | * a per-device variable for error reporting. | 644 | * a per-device variable for error reporting. |
640 | * Note that you can't touch the bio after end_io_acct | 645 | * Note that you can't touch the bio after end_io_acct |
646 | * | ||
647 | * We ignore -EOPNOTSUPP for empty flush reported by | ||
648 | * underlying devices. We assume that if the device | ||
649 | * doesn't support empty barriers, it doesn't need | ||
650 | * cache flushing commands. | ||
641 | */ | 651 | */ |
642 | if (!md->barrier_error && io_error != -EOPNOTSUPP) | 652 | if (!md->barrier_error && |
653 | !(bio_empty_barrier(bio) && io_error == -EOPNOTSUPP)) | ||
643 | md->barrier_error = io_error; | 654 | md->barrier_error = io_error; |
644 | end_io_acct(io); | 655 | end_io_acct(io); |
645 | free_io(md, io); | 656 | free_io(md, io); |
@@ -1019,17 +1030,27 @@ static void end_clone_request(struct request *clone, int error) | |||
1019 | dm_complete_request(clone, error); | 1030 | dm_complete_request(clone, error); |
1020 | } | 1031 | } |
1021 | 1032 | ||
1022 | static sector_t max_io_len(struct mapped_device *md, | 1033 | /* |
1023 | sector_t sector, struct dm_target *ti) | 1034 | * Return maximum size of I/O possible at the supplied sector up to the current |
1035 | * target boundary. | ||
1036 | */ | ||
1037 | static sector_t max_io_len_target_boundary(sector_t sector, struct dm_target *ti) | ||
1038 | { | ||
1039 | sector_t target_offset = dm_target_offset(ti, sector); | ||
1040 | |||
1041 | return ti->len - target_offset; | ||
1042 | } | ||
1043 | |||
1044 | static sector_t max_io_len(sector_t sector, struct dm_target *ti) | ||
1024 | { | 1045 | { |
1025 | sector_t offset = sector - ti->begin; | 1046 | sector_t len = max_io_len_target_boundary(sector, ti); |
1026 | sector_t len = ti->len - offset; | ||
1027 | 1047 | ||
1028 | /* | 1048 | /* |
1029 | * Does the target need to split even further ? | 1049 | * Does the target need to split even further ? |
1030 | */ | 1050 | */ |
1031 | if (ti->split_io) { | 1051 | if (ti->split_io) { |
1032 | sector_t boundary; | 1052 | sector_t boundary; |
1053 | sector_t offset = dm_target_offset(ti, sector); | ||
1033 | boundary = ((offset + ti->split_io) & ~(ti->split_io - 1)) | 1054 | boundary = ((offset + ti->split_io) & ~(ti->split_io - 1)) |
1034 | - offset; | 1055 | - offset; |
1035 | if (len > boundary) | 1056 | if (len > boundary) |
@@ -1171,36 +1192,96 @@ static struct dm_target_io *alloc_tio(struct clone_info *ci, | |||
1171 | return tio; | 1192 | return tio; |
1172 | } | 1193 | } |
1173 | 1194 | ||
1174 | static void __flush_target(struct clone_info *ci, struct dm_target *ti, | 1195 | static void __issue_target_request(struct clone_info *ci, struct dm_target *ti, |
1175 | unsigned flush_nr) | 1196 | unsigned request_nr, sector_t len) |
1176 | { | 1197 | { |
1177 | struct dm_target_io *tio = alloc_tio(ci, ti); | 1198 | struct dm_target_io *tio = alloc_tio(ci, ti); |
1178 | struct bio *clone; | 1199 | struct bio *clone; |
1179 | 1200 | ||
1180 | tio->info.flush_request = flush_nr; | 1201 | tio->info.target_request_nr = request_nr; |
1181 | 1202 | ||
1182 | clone = bio_alloc_bioset(GFP_NOIO, 0, ci->md->bs); | 1203 | /* |
1204 | * Discard requests require the bio's inline iovecs be initialized. | ||
1205 | * ci->bio->bi_max_vecs is BIO_INLINE_VECS anyway, for both flush | ||
1206 | * and discard, so no need for concern about wasted bvec allocations. | ||
1207 | */ | ||
1208 | clone = bio_alloc_bioset(GFP_NOIO, ci->bio->bi_max_vecs, ci->md->bs); | ||
1183 | __bio_clone(clone, ci->bio); | 1209 | __bio_clone(clone, ci->bio); |
1184 | clone->bi_destructor = dm_bio_destructor; | 1210 | clone->bi_destructor = dm_bio_destructor; |
1211 | if (len) { | ||
1212 | clone->bi_sector = ci->sector; | ||
1213 | clone->bi_size = to_bytes(len); | ||
1214 | } | ||
1185 | 1215 | ||
1186 | __map_bio(ti, clone, tio); | 1216 | __map_bio(ti, clone, tio); |
1187 | } | 1217 | } |
1188 | 1218 | ||
1219 | static void __issue_target_requests(struct clone_info *ci, struct dm_target *ti, | ||
1220 | unsigned num_requests, sector_t len) | ||
1221 | { | ||
1222 | unsigned request_nr; | ||
1223 | |||
1224 | for (request_nr = 0; request_nr < num_requests; request_nr++) | ||
1225 | __issue_target_request(ci, ti, request_nr, len); | ||
1226 | } | ||
1227 | |||
1189 | static int __clone_and_map_empty_barrier(struct clone_info *ci) | 1228 | static int __clone_and_map_empty_barrier(struct clone_info *ci) |
1190 | { | 1229 | { |
1191 | unsigned target_nr = 0, flush_nr; | 1230 | unsigned target_nr = 0; |
1192 | struct dm_target *ti; | 1231 | struct dm_target *ti; |
1193 | 1232 | ||
1194 | while ((ti = dm_table_get_target(ci->map, target_nr++))) | 1233 | while ((ti = dm_table_get_target(ci->map, target_nr++))) |
1195 | for (flush_nr = 0; flush_nr < ti->num_flush_requests; | 1234 | __issue_target_requests(ci, ti, ti->num_flush_requests, 0); |
1196 | flush_nr++) | ||
1197 | __flush_target(ci, ti, flush_nr); | ||
1198 | 1235 | ||
1199 | ci->sector_count = 0; | 1236 | ci->sector_count = 0; |
1200 | 1237 | ||
1201 | return 0; | 1238 | return 0; |
1202 | } | 1239 | } |
1203 | 1240 | ||
1241 | /* | ||
1242 | * Perform all io with a single clone. | ||
1243 | */ | ||
1244 | static void __clone_and_map_simple(struct clone_info *ci, struct dm_target *ti) | ||
1245 | { | ||
1246 | struct bio *clone, *bio = ci->bio; | ||
1247 | struct dm_target_io *tio; | ||
1248 | |||
1249 | tio = alloc_tio(ci, ti); | ||
1250 | clone = clone_bio(bio, ci->sector, ci->idx, | ||
1251 | bio->bi_vcnt - ci->idx, ci->sector_count, | ||
1252 | ci->md->bs); | ||
1253 | __map_bio(ti, clone, tio); | ||
1254 | ci->sector_count = 0; | ||
1255 | } | ||
1256 | |||
1257 | static int __clone_and_map_discard(struct clone_info *ci) | ||
1258 | { | ||
1259 | struct dm_target *ti; | ||
1260 | sector_t len; | ||
1261 | |||
1262 | do { | ||
1263 | ti = dm_table_find_target(ci->map, ci->sector); | ||
1264 | if (!dm_target_is_valid(ti)) | ||
1265 | return -EIO; | ||
1266 | |||
1267 | /* | ||
1268 | * Even though the device advertised discard support, | ||
1269 | * reconfiguration might have changed that since the | ||
1270 | * check was performed. | ||
1271 | */ | ||
1272 | if (!ti->num_discard_requests) | ||
1273 | return -EOPNOTSUPP; | ||
1274 | |||
1275 | len = min(ci->sector_count, max_io_len_target_boundary(ci->sector, ti)); | ||
1276 | |||
1277 | __issue_target_requests(ci, ti, ti->num_discard_requests, len); | ||
1278 | |||
1279 | ci->sector += len; | ||
1280 | } while (ci->sector_count -= len); | ||
1281 | |||
1282 | return 0; | ||
1283 | } | ||
1284 | |||
1204 | static int __clone_and_map(struct clone_info *ci) | 1285 | static int __clone_and_map(struct clone_info *ci) |
1205 | { | 1286 | { |
1206 | struct bio *clone, *bio = ci->bio; | 1287 | struct bio *clone, *bio = ci->bio; |
@@ -1211,27 +1292,21 @@ static int __clone_and_map(struct clone_info *ci) | |||
1211 | if (unlikely(bio_empty_barrier(bio))) | 1292 | if (unlikely(bio_empty_barrier(bio))) |
1212 | return __clone_and_map_empty_barrier(ci); | 1293 | return __clone_and_map_empty_barrier(ci); |
1213 | 1294 | ||
1295 | if (unlikely(bio->bi_rw & REQ_DISCARD)) | ||
1296 | return __clone_and_map_discard(ci); | ||
1297 | |||
1214 | ti = dm_table_find_target(ci->map, ci->sector); | 1298 | ti = dm_table_find_target(ci->map, ci->sector); |
1215 | if (!dm_target_is_valid(ti)) | 1299 | if (!dm_target_is_valid(ti)) |
1216 | return -EIO; | 1300 | return -EIO; |
1217 | 1301 | ||
1218 | max = max_io_len(ci->md, ci->sector, ti); | 1302 | max = max_io_len(ci->sector, ti); |
1219 | |||
1220 | /* | ||
1221 | * Allocate a target io object. | ||
1222 | */ | ||
1223 | tio = alloc_tio(ci, ti); | ||
1224 | 1303 | ||
1225 | if (ci->sector_count <= max) { | 1304 | if (ci->sector_count <= max) { |
1226 | /* | 1305 | /* |
1227 | * Optimise for the simple case where we can do all of | 1306 | * Optimise for the simple case where we can do all of |
1228 | * the remaining io with a single clone. | 1307 | * the remaining io with a single clone. |
1229 | */ | 1308 | */ |
1230 | clone = clone_bio(bio, ci->sector, ci->idx, | 1309 | __clone_and_map_simple(ci, ti); |
1231 | bio->bi_vcnt - ci->idx, ci->sector_count, | ||
1232 | ci->md->bs); | ||
1233 | __map_bio(ti, clone, tio); | ||
1234 | ci->sector_count = 0; | ||
1235 | 1310 | ||
1236 | } else if (to_sector(bio->bi_io_vec[ci->idx].bv_len) <= max) { | 1311 | } else if (to_sector(bio->bi_io_vec[ci->idx].bv_len) <= max) { |
1237 | /* | 1312 | /* |
@@ -1252,6 +1327,7 @@ static int __clone_and_map(struct clone_info *ci) | |||
1252 | len += bv_len; | 1327 | len += bv_len; |
1253 | } | 1328 | } |
1254 | 1329 | ||
1330 | tio = alloc_tio(ci, ti); | ||
1255 | clone = clone_bio(bio, ci->sector, ci->idx, i - ci->idx, len, | 1331 | clone = clone_bio(bio, ci->sector, ci->idx, i - ci->idx, len, |
1256 | ci->md->bs); | 1332 | ci->md->bs); |
1257 | __map_bio(ti, clone, tio); | 1333 | __map_bio(ti, clone, tio); |
@@ -1274,13 +1350,12 @@ static int __clone_and_map(struct clone_info *ci) | |||
1274 | if (!dm_target_is_valid(ti)) | 1350 | if (!dm_target_is_valid(ti)) |
1275 | return -EIO; | 1351 | return -EIO; |
1276 | 1352 | ||
1277 | max = max_io_len(ci->md, ci->sector, ti); | 1353 | max = max_io_len(ci->sector, ti); |
1278 | |||
1279 | tio = alloc_tio(ci, ti); | ||
1280 | } | 1354 | } |
1281 | 1355 | ||
1282 | len = min(remaining, max); | 1356 | len = min(remaining, max); |
1283 | 1357 | ||
1358 | tio = alloc_tio(ci, ti); | ||
1284 | clone = split_bvec(bio, ci->sector, ci->idx, | 1359 | clone = split_bvec(bio, ci->sector, ci->idx, |
1285 | bv->bv_offset + offset, len, | 1360 | bv->bv_offset + offset, len, |
1286 | ci->md->bs); | 1361 | ci->md->bs); |
@@ -1362,7 +1437,7 @@ static int dm_merge_bvec(struct request_queue *q, | |||
1362 | /* | 1437 | /* |
1363 | * Find maximum amount of I/O that won't need splitting | 1438 | * Find maximum amount of I/O that won't need splitting |
1364 | */ | 1439 | */ |
1365 | max_sectors = min(max_io_len(md, bvm->bi_sector, ti), | 1440 | max_sectors = min(max_io_len(bvm->bi_sector, ti), |
1366 | (sector_t) BIO_MAX_SECTORS); | 1441 | (sector_t) BIO_MAX_SECTORS); |
1367 | max_size = (max_sectors << SECTOR_SHIFT) - bvm->bi_size; | 1442 | max_size = (max_sectors << SECTOR_SHIFT) - bvm->bi_size; |
1368 | if (max_size < 0) | 1443 | if (max_size < 0) |
@@ -1845,6 +1920,28 @@ static const struct block_device_operations dm_blk_dops; | |||
1845 | static void dm_wq_work(struct work_struct *work); | 1920 | static void dm_wq_work(struct work_struct *work); |
1846 | static void dm_rq_barrier_work(struct work_struct *work); | 1921 | static void dm_rq_barrier_work(struct work_struct *work); |
1847 | 1922 | ||
1923 | static void dm_init_md_queue(struct mapped_device *md) | ||
1924 | { | ||
1925 | /* | ||
1926 | * Request-based dm devices cannot be stacked on top of bio-based dm | ||
1927 | * devices. The type of this dm device has not been decided yet. | ||
1928 | * The type is decided at the first table loading time. | ||
1929 | * To prevent problematic device stacking, clear the queue flag | ||
1930 | * for request stacking support until then. | ||
1931 | * | ||
1932 | * This queue is new, so no concurrency on the queue_flags. | ||
1933 | */ | ||
1934 | queue_flag_clear_unlocked(QUEUE_FLAG_STACKABLE, md->queue); | ||
1935 | |||
1936 | md->queue->queuedata = md; | ||
1937 | md->queue->backing_dev_info.congested_fn = dm_any_congested; | ||
1938 | md->queue->backing_dev_info.congested_data = md; | ||
1939 | blk_queue_make_request(md->queue, dm_request); | ||
1940 | blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY); | ||
1941 | md->queue->unplug_fn = dm_unplug_all; | ||
1942 | blk_queue_merge_bvec(md->queue, dm_merge_bvec); | ||
1943 | } | ||
1944 | |||
1848 | /* | 1945 | /* |
1849 | * Allocate and initialise a blank device with a given minor. | 1946 | * Allocate and initialise a blank device with a given minor. |
1850 | */ | 1947 | */ |
@@ -1870,8 +1967,10 @@ static struct mapped_device *alloc_dev(int minor) | |||
1870 | if (r < 0) | 1967 | if (r < 0) |
1871 | goto bad_minor; | 1968 | goto bad_minor; |
1872 | 1969 | ||
1970 | md->type = DM_TYPE_NONE; | ||
1873 | init_rwsem(&md->io_lock); | 1971 | init_rwsem(&md->io_lock); |
1874 | mutex_init(&md->suspend_lock); | 1972 | mutex_init(&md->suspend_lock); |
1973 | mutex_init(&md->type_lock); | ||
1875 | spin_lock_init(&md->deferred_lock); | 1974 | spin_lock_init(&md->deferred_lock); |
1876 | spin_lock_init(&md->barrier_error_lock); | 1975 | spin_lock_init(&md->barrier_error_lock); |
1877 | rwlock_init(&md->map_lock); | 1976 | rwlock_init(&md->map_lock); |
@@ -1882,33 +1981,11 @@ static struct mapped_device *alloc_dev(int minor) | |||
1882 | INIT_LIST_HEAD(&md->uevent_list); | 1981 | INIT_LIST_HEAD(&md->uevent_list); |
1883 | spin_lock_init(&md->uevent_lock); | 1982 | spin_lock_init(&md->uevent_lock); |
1884 | 1983 | ||
1885 | md->queue = blk_init_queue(dm_request_fn, NULL); | 1984 | md->queue = blk_alloc_queue(GFP_KERNEL); |
1886 | if (!md->queue) | 1985 | if (!md->queue) |
1887 | goto bad_queue; | 1986 | goto bad_queue; |
1888 | 1987 | ||
1889 | /* | 1988 | dm_init_md_queue(md); |
1890 | * Request-based dm devices cannot be stacked on top of bio-based dm | ||
1891 | * devices. The type of this dm device has not been decided yet, | ||
1892 | * although we initialized the queue using blk_init_queue(). | ||
1893 | * The type is decided at the first table loading time. | ||
1894 | * To prevent problematic device stacking, clear the queue flag | ||
1895 | * for request stacking support until then. | ||
1896 | * | ||
1897 | * This queue is new, so no concurrency on the queue_flags. | ||
1898 | */ | ||
1899 | queue_flag_clear_unlocked(QUEUE_FLAG_STACKABLE, md->queue); | ||
1900 | md->saved_make_request_fn = md->queue->make_request_fn; | ||
1901 | md->queue->queuedata = md; | ||
1902 | md->queue->backing_dev_info.congested_fn = dm_any_congested; | ||
1903 | md->queue->backing_dev_info.congested_data = md; | ||
1904 | blk_queue_make_request(md->queue, dm_request); | ||
1905 | blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY); | ||
1906 | md->queue->unplug_fn = dm_unplug_all; | ||
1907 | blk_queue_merge_bvec(md->queue, dm_merge_bvec); | ||
1908 | blk_queue_softirq_done(md->queue, dm_softirq_done); | ||
1909 | blk_queue_prep_rq(md->queue, dm_prep_fn); | ||
1910 | blk_queue_lld_busy(md->queue, dm_lld_busy); | ||
1911 | blk_queue_ordered(md->queue, QUEUE_ORDERED_DRAIN_FLUSH); | ||
1912 | 1989 | ||
1913 | md->disk = alloc_disk(1); | 1990 | md->disk = alloc_disk(1); |
1914 | if (!md->disk) | 1991 | if (!md->disk) |
@@ -2123,6 +2200,72 @@ int dm_create(int minor, struct mapped_device **result) | |||
2123 | return 0; | 2200 | return 0; |
2124 | } | 2201 | } |
2125 | 2202 | ||
2203 | /* | ||
2204 | * Functions to manage md->type. | ||
2205 | * All are required to hold md->type_lock. | ||
2206 | */ | ||
2207 | void dm_lock_md_type(struct mapped_device *md) | ||
2208 | { | ||
2209 | mutex_lock(&md->type_lock); | ||
2210 | } | ||
2211 | |||
2212 | void dm_unlock_md_type(struct mapped_device *md) | ||
2213 | { | ||
2214 | mutex_unlock(&md->type_lock); | ||
2215 | } | ||
2216 | |||
2217 | void dm_set_md_type(struct mapped_device *md, unsigned type) | ||
2218 | { | ||
2219 | md->type = type; | ||
2220 | } | ||
2221 | |||
2222 | unsigned dm_get_md_type(struct mapped_device *md) | ||
2223 | { | ||
2224 | return md->type; | ||
2225 | } | ||
2226 | |||
2227 | /* | ||
2228 | * Fully initialize a request-based queue (->elevator, ->request_fn, etc). | ||
2229 | */ | ||
2230 | static int dm_init_request_based_queue(struct mapped_device *md) | ||
2231 | { | ||
2232 | struct request_queue *q = NULL; | ||
2233 | |||
2234 | if (md->queue->elevator) | ||
2235 | return 1; | ||
2236 | |||
2237 | /* Fully initialize the queue */ | ||
2238 | q = blk_init_allocated_queue(md->queue, dm_request_fn, NULL); | ||
2239 | if (!q) | ||
2240 | return 0; | ||
2241 | |||
2242 | md->queue = q; | ||
2243 | md->saved_make_request_fn = md->queue->make_request_fn; | ||
2244 | dm_init_md_queue(md); | ||
2245 | blk_queue_softirq_done(md->queue, dm_softirq_done); | ||
2246 | blk_queue_prep_rq(md->queue, dm_prep_fn); | ||
2247 | blk_queue_lld_busy(md->queue, dm_lld_busy); | ||
2248 | blk_queue_ordered(md->queue, QUEUE_ORDERED_DRAIN_FLUSH); | ||
2249 | |||
2250 | elv_register_queue(md->queue); | ||
2251 | |||
2252 | return 1; | ||
2253 | } | ||
2254 | |||
2255 | /* | ||
2256 | * Setup the DM device's queue based on md's type | ||
2257 | */ | ||
2258 | int dm_setup_md_queue(struct mapped_device *md) | ||
2259 | { | ||
2260 | if ((dm_get_md_type(md) == DM_TYPE_REQUEST_BASED) && | ||
2261 | !dm_init_request_based_queue(md)) { | ||
2262 | DMWARN("Cannot initialize queue for request-based mapped device"); | ||
2263 | return -EINVAL; | ||
2264 | } | ||
2265 | |||
2266 | return 0; | ||
2267 | } | ||
2268 | |||
2126 | static struct mapped_device *dm_find_md(dev_t dev) | 2269 | static struct mapped_device *dm_find_md(dev_t dev) |
2127 | { | 2270 | { |
2128 | struct mapped_device *md; | 2271 | struct mapped_device *md; |
@@ -2136,6 +2279,7 @@ static struct mapped_device *dm_find_md(dev_t dev) | |||
2136 | md = idr_find(&_minor_idr, minor); | 2279 | md = idr_find(&_minor_idr, minor); |
2137 | if (md && (md == MINOR_ALLOCED || | 2280 | if (md && (md == MINOR_ALLOCED || |
2138 | (MINOR(disk_devt(dm_disk(md))) != minor) || | 2281 | (MINOR(disk_devt(dm_disk(md))) != minor) || |
2282 | dm_deleting_md(md) || | ||
2139 | test_bit(DMF_FREEING, &md->flags))) { | 2283 | test_bit(DMF_FREEING, &md->flags))) { |
2140 | md = NULL; | 2284 | md = NULL; |
2141 | goto out; | 2285 | goto out; |
@@ -2170,6 +2314,7 @@ void dm_set_mdptr(struct mapped_device *md, void *ptr) | |||
2170 | void dm_get(struct mapped_device *md) | 2314 | void dm_get(struct mapped_device *md) |
2171 | { | 2315 | { |
2172 | atomic_inc(&md->holders); | 2316 | atomic_inc(&md->holders); |
2317 | BUG_ON(test_bit(DMF_FREEING, &md->flags)); | ||
2173 | } | 2318 | } |
2174 | 2319 | ||
2175 | const char *dm_device_name(struct mapped_device *md) | 2320 | const char *dm_device_name(struct mapped_device *md) |
@@ -2178,27 +2323,55 @@ const char *dm_device_name(struct mapped_device *md) | |||
2178 | } | 2323 | } |
2179 | EXPORT_SYMBOL_GPL(dm_device_name); | 2324 | EXPORT_SYMBOL_GPL(dm_device_name); |
2180 | 2325 | ||
2181 | void dm_put(struct mapped_device *md) | 2326 | static void __dm_destroy(struct mapped_device *md, bool wait) |
2182 | { | 2327 | { |
2183 | struct dm_table *map; | 2328 | struct dm_table *map; |
2184 | 2329 | ||
2185 | BUG_ON(test_bit(DMF_FREEING, &md->flags)); | 2330 | might_sleep(); |
2186 | 2331 | ||
2187 | if (atomic_dec_and_lock(&md->holders, &_minor_lock)) { | 2332 | spin_lock(&_minor_lock); |
2188 | map = dm_get_live_table(md); | 2333 | map = dm_get_live_table(md); |
2189 | idr_replace(&_minor_idr, MINOR_ALLOCED, | 2334 | idr_replace(&_minor_idr, MINOR_ALLOCED, MINOR(disk_devt(dm_disk(md)))); |
2190 | MINOR(disk_devt(dm_disk(md)))); | 2335 | set_bit(DMF_FREEING, &md->flags); |
2191 | set_bit(DMF_FREEING, &md->flags); | 2336 | spin_unlock(&_minor_lock); |
2192 | spin_unlock(&_minor_lock); | 2337 | |
2193 | if (!dm_suspended_md(md)) { | 2338 | if (!dm_suspended_md(md)) { |
2194 | dm_table_presuspend_targets(map); | 2339 | dm_table_presuspend_targets(map); |
2195 | dm_table_postsuspend_targets(map); | 2340 | dm_table_postsuspend_targets(map); |
2196 | } | ||
2197 | dm_sysfs_exit(md); | ||
2198 | dm_table_put(map); | ||
2199 | dm_table_destroy(__unbind(md)); | ||
2200 | free_dev(md); | ||
2201 | } | 2341 | } |
2342 | |||
2343 | /* | ||
2344 | * Rare, but there may be I/O requests still going to complete, | ||
2345 | * for example. Wait for all references to disappear. | ||
2346 | * No one should increment the reference count of the mapped_device, | ||
2347 | * after the mapped_device state becomes DMF_FREEING. | ||
2348 | */ | ||
2349 | if (wait) | ||
2350 | while (atomic_read(&md->holders)) | ||
2351 | msleep(1); | ||
2352 | else if (atomic_read(&md->holders)) | ||
2353 | DMWARN("%s: Forcibly removing mapped_device still in use! (%d users)", | ||
2354 | dm_device_name(md), atomic_read(&md->holders)); | ||
2355 | |||
2356 | dm_sysfs_exit(md); | ||
2357 | dm_table_put(map); | ||
2358 | dm_table_destroy(__unbind(md)); | ||
2359 | free_dev(md); | ||
2360 | } | ||
2361 | |||
2362 | void dm_destroy(struct mapped_device *md) | ||
2363 | { | ||
2364 | __dm_destroy(md, true); | ||
2365 | } | ||
2366 | |||
2367 | void dm_destroy_immediate(struct mapped_device *md) | ||
2368 | { | ||
2369 | __dm_destroy(md, false); | ||
2370 | } | ||
2371 | |||
2372 | void dm_put(struct mapped_device *md) | ||
2373 | { | ||
2374 | atomic_dec(&md->holders); | ||
2202 | } | 2375 | } |
2203 | EXPORT_SYMBOL_GPL(dm_put); | 2376 | EXPORT_SYMBOL_GPL(dm_put); |
2204 | 2377 | ||
@@ -2253,7 +2426,12 @@ static void process_barrier(struct mapped_device *md, struct bio *bio) | |||
2253 | 2426 | ||
2254 | if (!bio_empty_barrier(bio)) { | 2427 | if (!bio_empty_barrier(bio)) { |
2255 | __split_and_process_bio(md, bio); | 2428 | __split_and_process_bio(md, bio); |
2256 | dm_flush(md); | 2429 | /* |
2430 | * If the request isn't supported, don't waste time with | ||
2431 | * the second flush. | ||
2432 | */ | ||
2433 | if (md->barrier_error != -EOPNOTSUPP) | ||
2434 | dm_flush(md); | ||
2257 | } | 2435 | } |
2258 | 2436 | ||
2259 | if (md->barrier_error != DM_ENDIO_REQUEUE) | 2437 | if (md->barrier_error != DM_ENDIO_REQUEUE) |
@@ -2310,11 +2488,11 @@ static void dm_queue_flush(struct mapped_device *md) | |||
2310 | queue_work(md->wq, &md->work); | 2488 | queue_work(md->wq, &md->work); |
2311 | } | 2489 | } |
2312 | 2490 | ||
2313 | static void dm_rq_set_flush_nr(struct request *clone, unsigned flush_nr) | 2491 | static void dm_rq_set_target_request_nr(struct request *clone, unsigned request_nr) |
2314 | { | 2492 | { |
2315 | struct dm_rq_target_io *tio = clone->end_io_data; | 2493 | struct dm_rq_target_io *tio = clone->end_io_data; |
2316 | 2494 | ||
2317 | tio->info.flush_request = flush_nr; | 2495 | tio->info.target_request_nr = request_nr; |
2318 | } | 2496 | } |
2319 | 2497 | ||
2320 | /* Issue barrier requests to targets and wait for their completion. */ | 2498 | /* Issue barrier requests to targets and wait for their completion. */ |
@@ -2332,7 +2510,7 @@ static int dm_rq_barrier(struct mapped_device *md) | |||
2332 | ti = dm_table_get_target(map, i); | 2510 | ti = dm_table_get_target(map, i); |
2333 | for (j = 0; j < ti->num_flush_requests; j++) { | 2511 | for (j = 0; j < ti->num_flush_requests; j++) { |
2334 | clone = clone_rq(md->flush_request, md, GFP_NOIO); | 2512 | clone = clone_rq(md->flush_request, md, GFP_NOIO); |
2335 | dm_rq_set_flush_nr(clone, j); | 2513 | dm_rq_set_target_request_nr(clone, j); |
2336 | atomic_inc(&md->pending[rq_data_dir(clone)]); | 2514 | atomic_inc(&md->pending[rq_data_dir(clone)]); |
2337 | map_request(ti, clone, md); | 2515 | map_request(ti, clone, md); |
2338 | } | 2516 | } |
@@ -2398,13 +2576,6 @@ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table) | |||
2398 | goto out; | 2576 | goto out; |
2399 | } | 2577 | } |
2400 | 2578 | ||
2401 | /* cannot change the device type, once a table is bound */ | ||
2402 | if (md->map && | ||
2403 | (dm_table_get_type(md->map) != dm_table_get_type(table))) { | ||
2404 | DMWARN("can't change the device type after a table is bound"); | ||
2405 | goto out; | ||
2406 | } | ||
2407 | |||
2408 | map = __bind(md, table, &limits); | 2579 | map = __bind(md, table, &limits); |
2409 | 2580 | ||
2410 | out: | 2581 | out: |
diff --git a/drivers/md/dm.h b/drivers/md/dm.h index bad1724d4869..0c2dd5f4af76 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h | |||
@@ -59,13 +59,20 @@ void dm_table_postsuspend_targets(struct dm_table *t); | |||
59 | int dm_table_resume_targets(struct dm_table *t); | 59 | int dm_table_resume_targets(struct dm_table *t); |
60 | int dm_table_any_congested(struct dm_table *t, int bdi_bits); | 60 | int dm_table_any_congested(struct dm_table *t, int bdi_bits); |
61 | int dm_table_any_busy_target(struct dm_table *t); | 61 | int dm_table_any_busy_target(struct dm_table *t); |
62 | int dm_table_set_type(struct dm_table *t); | ||
63 | unsigned dm_table_get_type(struct dm_table *t); | 62 | unsigned dm_table_get_type(struct dm_table *t); |
64 | bool dm_table_request_based(struct dm_table *t); | 63 | bool dm_table_request_based(struct dm_table *t); |
64 | bool dm_table_supports_discards(struct dm_table *t); | ||
65 | int dm_table_alloc_md_mempools(struct dm_table *t); | 65 | int dm_table_alloc_md_mempools(struct dm_table *t); |
66 | void dm_table_free_md_mempools(struct dm_table *t); | 66 | void dm_table_free_md_mempools(struct dm_table *t); |
67 | struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t); | 67 | struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t); |
68 | 68 | ||
69 | void dm_lock_md_type(struct mapped_device *md); | ||
70 | void dm_unlock_md_type(struct mapped_device *md); | ||
71 | void dm_set_md_type(struct mapped_device *md, unsigned type); | ||
72 | unsigned dm_get_md_type(struct mapped_device *md); | ||
73 | |||
74 | int dm_setup_md_queue(struct mapped_device *md); | ||
75 | |||
69 | /* | 76 | /* |
70 | * To check the return value from dm_table_find_target(). | 77 | * To check the return value from dm_table_find_target(). |
71 | */ | 78 | */ |
@@ -122,6 +129,11 @@ void dm_linear_exit(void); | |||
122 | int dm_stripe_init(void); | 129 | int dm_stripe_init(void); |
123 | void dm_stripe_exit(void); | 130 | void dm_stripe_exit(void); |
124 | 131 | ||
132 | /* | ||
133 | * mapped_device operations | ||
134 | */ | ||
135 | void dm_destroy(struct mapped_device *md); | ||
136 | void dm_destroy_immediate(struct mapped_device *md); | ||
125 | int dm_open_count(struct mapped_device *md); | 137 | int dm_open_count(struct mapped_device *md); |
126 | int dm_lock_for_deletion(struct mapped_device *md); | 138 | int dm_lock_for_deletion(struct mapped_device *md); |
127 | 139 | ||
diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c index 407fa61e4cda..685d6597ee79 100644 --- a/drivers/media/video/bt8xx/bttv-i2c.c +++ b/drivers/media/video/bt8xx/bttv-i2c.c | |||
@@ -411,7 +411,7 @@ void __devinit init_bttv_i2c_ir(struct bttv *btv) | |||
411 | 411 | ||
412 | memset(&info, 0, sizeof(struct i2c_board_info)); | 412 | memset(&info, 0, sizeof(struct i2c_board_info)); |
413 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); | 413 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); |
414 | i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list); | 414 | i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list, NULL); |
415 | } | 415 | } |
416 | } | 416 | } |
417 | 417 | ||
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index 809f7d37129c..73ce90c2f577 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c | |||
@@ -117,7 +117,8 @@ static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw, | |||
117 | break; | 117 | break; |
118 | } | 118 | } |
119 | 119 | ||
120 | return i2c_new_probed_device(adap, &info, addr_list) == NULL ? -1 : 0; | 120 | return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ? |
121 | -1 : 0; | ||
121 | } | 122 | } |
122 | 123 | ||
123 | int cx18_i2c_register(struct cx18 *cx, unsigned idx) | 124 | int cx18_i2c_register(struct cx18 *cx, unsigned idx) |
diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index 1a391486e551..ed3d8f55029b 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c | |||
@@ -364,17 +364,10 @@ int cx23885_i2c_register(struct cx23885_i2c *bus) | |||
364 | 364 | ||
365 | memset(&info, 0, sizeof(struct i2c_board_info)); | 365 | memset(&info, 0, sizeof(struct i2c_board_info)); |
366 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); | 366 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); |
367 | /* | 367 | /* Use quick read command for probe, some IR chips don't |
368 | * We can't call i2c_new_probed_device() because it uses | 368 | * support writes */ |
369 | * quick writes for probing and the IR receiver device only | 369 | i2c_new_probed_device(&bus->i2c_adap, &info, addr_list, |
370 | * replies to reads. | 370 | i2c_probe_func_quick_read); |
371 | */ | ||
372 | if (i2c_smbus_xfer(&bus->i2c_adap, addr_list[0], 0, | ||
373 | I2C_SMBUS_READ, 0, I2C_SMBUS_QUICK, | ||
374 | NULL) >= 0) { | ||
375 | info.addr = addr_list[0]; | ||
376 | i2c_new_device(&bus->i2c_adap, &info); | ||
377 | } | ||
378 | } | 371 | } |
379 | 372 | ||
380 | return bus->i2c_rc; | 373 | return bus->i2c_rc; |
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 375ad53f7961..82db555b22dd 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c | |||
@@ -193,24 +193,13 @@ void cx88_i2c_init_ir(struct cx88_core *core) | |||
193 | 0x18, 0x6b, 0x71, | 193 | 0x18, 0x6b, 0x71, |
194 | I2C_CLIENT_END | 194 | I2C_CLIENT_END |
195 | }; | 195 | }; |
196 | const unsigned short *addrp; | ||
197 | 196 | ||
198 | memset(&info, 0, sizeof(struct i2c_board_info)); | 197 | memset(&info, 0, sizeof(struct i2c_board_info)); |
199 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); | 198 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); |
200 | /* | 199 | /* Use quick read command for probe, some IR chips don't |
201 | * We can't call i2c_new_probed_device() because it uses | 200 | * support writes */ |
202 | * quick writes for probing and at least some R receiver | 201 | i2c_new_probed_device(&core->i2c_adap, &info, addr_list, |
203 | * devices only reply to reads. | 202 | i2c_probe_func_quick_read); |
204 | */ | ||
205 | for (addrp = addr_list; *addrp != I2C_CLIENT_END; addrp++) { | ||
206 | if (i2c_smbus_xfer(&core->i2c_adap, *addrp, 0, | ||
207 | I2C_SMBUS_READ, 0, | ||
208 | I2C_SMBUS_QUICK, NULL) >= 0) { | ||
209 | info.addr = *addrp; | ||
210 | i2c_new_device(&core->i2c_adap, &info); | ||
211 | break; | ||
212 | } | ||
213 | } | ||
214 | } | 203 | } |
215 | } | 204 | } |
216 | 205 | ||
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index ffbe544e30f4..e7efb4bffabd 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -2385,7 +2385,7 @@ void em28xx_register_i2c_ir(struct em28xx *dev) | |||
2385 | 2385 | ||
2386 | if (dev->init_data.name) | 2386 | if (dev->init_data.name) |
2387 | info.platform_data = &dev->init_data; | 2387 | info.platform_data = &dev->init_data; |
2388 | i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); | 2388 | i2c_new_probed_device(&dev->i2c_adap, &info, addr_list, NULL); |
2389 | } | 2389 | } |
2390 | 2390 | ||
2391 | void em28xx_card_setup(struct em28xx *dev) | 2391 | void em28xx_card_setup(struct em28xx *dev) |
diff --git a/drivers/media/video/fsl-viu.c b/drivers/media/video/fsl-viu.c index 8f1c94f7e00c..43d208f1f586 100644 --- a/drivers/media/video/fsl-viu.c +++ b/drivers/media/video/fsl-viu.c | |||
@@ -1418,7 +1418,7 @@ static struct video_device viu_template = { | |||
1418 | .current_norm = V4L2_STD_NTSC_M, | 1418 | .current_norm = V4L2_STD_NTSC_M, |
1419 | }; | 1419 | }; |
1420 | 1420 | ||
1421 | static int __devinit viu_of_probe(struct of_device *op, | 1421 | static int __devinit viu_of_probe(struct platform_device *op, |
1422 | const struct of_device_id *match) | 1422 | const struct of_device_id *match) |
1423 | { | 1423 | { |
1424 | struct viu_dev *viu_dev; | 1424 | struct viu_dev *viu_dev; |
@@ -1549,7 +1549,7 @@ err: | |||
1549 | return ret; | 1549 | return ret; |
1550 | } | 1550 | } |
1551 | 1551 | ||
1552 | static int __devexit viu_of_remove(struct of_device *op) | 1552 | static int __devexit viu_of_remove(struct platform_device *op) |
1553 | { | 1553 | { |
1554 | struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); | 1554 | struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); |
1555 | struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); | 1555 | struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); |
@@ -1570,7 +1570,7 @@ static int __devexit viu_of_remove(struct of_device *op) | |||
1570 | } | 1570 | } |
1571 | 1571 | ||
1572 | #ifdef CONFIG_PM | 1572 | #ifdef CONFIG_PM |
1573 | static int viu_suspend(struct of_device *op, pm_message_t state) | 1573 | static int viu_suspend(struct platform_device *op, pm_message_t state) |
1574 | { | 1574 | { |
1575 | struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); | 1575 | struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); |
1576 | struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); | 1576 | struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); |
@@ -1579,7 +1579,7 @@ static int viu_suspend(struct of_device *op, pm_message_t state) | |||
1579 | return 0; | 1579 | return 0; |
1580 | } | 1580 | } |
1581 | 1581 | ||
1582 | static int viu_resume(struct of_device *op) | 1582 | static int viu_resume(struct platform_device *op) |
1583 | { | 1583 | { |
1584 | struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); | 1584 | struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); |
1585 | struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); | 1585 | struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); |
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index d391bbdb0b8a..a74fa099c565 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c | |||
@@ -183,8 +183,8 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) | |||
183 | return -1; | 183 | return -1; |
184 | memset(&info, 0, sizeof(struct i2c_board_info)); | 184 | memset(&info, 0, sizeof(struct i2c_board_info)); |
185 | strlcpy(info.type, type, I2C_NAME_SIZE); | 185 | strlcpy(info.type, type, I2C_NAME_SIZE); |
186 | return i2c_new_probed_device(adap, &info, addr_list) == NULL | 186 | return i2c_new_probed_device(adap, &info, addr_list, NULL) |
187 | ? -1 : 0; | 187 | == NULL ? -1 : 0; |
188 | } | 188 | } |
189 | 189 | ||
190 | /* Only allow one IR receiver to be registered per board */ | 190 | /* Only allow one IR receiver to be registered per board */ |
@@ -221,7 +221,8 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) | |||
221 | info.platform_data = init_data; | 221 | info.platform_data = init_data; |
222 | strlcpy(info.type, type, I2C_NAME_SIZE); | 222 | strlcpy(info.type, type, I2C_NAME_SIZE); |
223 | 223 | ||
224 | return i2c_new_probed_device(adap, &info, addr_list) == NULL ? -1 : 0; | 224 | return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ? |
225 | -1 : 0; | ||
225 | } | 226 | } |
226 | 227 | ||
227 | /* Instantiate the IR receiver device using probing -- undesirable */ | 228 | /* Instantiate the IR receiver device using probing -- undesirable */ |
@@ -249,7 +250,7 @@ struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv) | |||
249 | 250 | ||
250 | memset(&info, 0, sizeof(struct i2c_board_info)); | 251 | memset(&info, 0, sizeof(struct i2c_board_info)); |
251 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); | 252 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); |
252 | return i2c_new_probed_device(&itv->i2c_adap, &info, addr_list); | 253 | return i2c_new_probed_device(&itv->i2c_adap, &info, addr_list, NULL); |
253 | } | 254 | } |
254 | 255 | ||
255 | int ivtv_i2c_register(struct ivtv *itv, unsigned idx) | 256 | int ivtv_i2c_register(struct ivtv *itv, unsigned idx) |
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 3ce7c64e5789..8ee1179be926 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c | |||
@@ -381,7 +381,8 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev, | |||
381 | 381 | ||
382 | /* Create the i2c client */ | 382 | /* Create the i2c client */ |
383 | if (info->addr == 0 && probe_addrs) | 383 | if (info->addr == 0 && probe_addrs) |
384 | client = i2c_new_probed_device(adapter, info, probe_addrs); | 384 | client = i2c_new_probed_device(adapter, info, probe_addrs, |
385 | NULL); | ||
385 | else | 386 | else |
386 | client = i2c_new_device(adapter, info); | 387 | client = i2c_new_device(adapter, info); |
387 | 388 | ||
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index eef78a068fd1..d3f1a087eced 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c | |||
@@ -1048,6 +1048,7 @@ static int mspro_block_read_attributes(struct memstick_dev *card) | |||
1048 | snprintf(s_attr->name, sizeof(s_attr->name), | 1048 | snprintf(s_attr->name, sizeof(s_attr->name), |
1049 | "attr_x%02x", attr->entries[cnt].id); | 1049 | "attr_x%02x", attr->entries[cnt].id); |
1050 | 1050 | ||
1051 | sysfs_attr_init(&s_attr->dev_attr.attr); | ||
1051 | s_attr->dev_attr.attr.name = s_attr->name; | 1052 | s_attr->dev_attr.attr.name = s_attr->name; |
1052 | s_attr->dev_attr.attr.mode = S_IRUGO; | 1053 | s_attr->dev_attr.attr.mode = S_IRUGO; |
1053 | s_attr->dev_attr.show = mspro_block_attr_show(s_attr->id); | 1054 | s_attr->dev_attr.show = mspro_block_attr_show(s_attr->id); |
@@ -1338,13 +1339,14 @@ static void mspro_block_remove(struct memstick_dev *card) | |||
1338 | struct mspro_block_data *msb = memstick_get_drvdata(card); | 1339 | struct mspro_block_data *msb = memstick_get_drvdata(card); |
1339 | unsigned long flags; | 1340 | unsigned long flags; |
1340 | 1341 | ||
1341 | del_gendisk(msb->disk); | ||
1342 | dev_dbg(&card->dev, "mspro block remove\n"); | ||
1343 | spin_lock_irqsave(&msb->q_lock, flags); | 1342 | spin_lock_irqsave(&msb->q_lock, flags); |
1344 | msb->eject = 1; | 1343 | msb->eject = 1; |
1345 | blk_start_queue(msb->queue); | 1344 | blk_start_queue(msb->queue); |
1346 | spin_unlock_irqrestore(&msb->q_lock, flags); | 1345 | spin_unlock_irqrestore(&msb->q_lock, flags); |
1347 | 1346 | ||
1347 | del_gendisk(msb->disk); | ||
1348 | dev_dbg(&card->dev, "mspro block remove\n"); | ||
1349 | |||
1348 | blk_cleanup_queue(msb->queue); | 1350 | blk_cleanup_queue(msb->queue); |
1349 | msb->queue = NULL; | 1351 | msb->queue = NULL; |
1350 | 1352 | ||
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index c54674c482c7..b8f1719d7c02 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
@@ -110,8 +110,7 @@ MODULE_PARM_DESC(mpt_debug_level, " debug level - refer to mptdebug.h \ | |||
110 | 110 | ||
111 | int mpt_fwfault_debug; | 111 | int mpt_fwfault_debug; |
112 | EXPORT_SYMBOL(mpt_fwfault_debug); | 112 | EXPORT_SYMBOL(mpt_fwfault_debug); |
113 | module_param_call(mpt_fwfault_debug, param_set_int, param_get_int, | 113 | module_param(mpt_fwfault_debug, int, 0600); |
114 | &mpt_fwfault_debug, 0600); | ||
115 | MODULE_PARM_DESC(mpt_fwfault_debug, "Enable detection of Firmware fault" | 114 | MODULE_PARM_DESC(mpt_fwfault_debug, "Enable detection of Firmware fault" |
116 | " and halt Firmware on fault - (default=0)"); | 115 | " and halt Firmware on fault - (default=0)"); |
117 | 116 | ||
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 2c65a2c57294..07933f3f7e4c 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c | |||
@@ -74,12 +74,12 @@ static struct mfd_cell backlight_devs[] = { | |||
74 | } | 74 | } |
75 | 75 | ||
76 | static struct resource led_resources[] = { | 76 | static struct resource led_resources[] = { |
77 | PM8606_LED_RESOURCE(PM8606_LED1_RED, RGB2B), | 77 | PM8606_LED_RESOURCE(PM8606_LED1_RED, RGB1B), |
78 | PM8606_LED_RESOURCE(PM8606_LED1_GREEN, RGB2C), | 78 | PM8606_LED_RESOURCE(PM8606_LED1_GREEN, RGB1C), |
79 | PM8606_LED_RESOURCE(PM8606_LED1_BLUE, RGB2D), | 79 | PM8606_LED_RESOURCE(PM8606_LED1_BLUE, RGB1D), |
80 | PM8606_LED_RESOURCE(PM8606_LED2_RED, RGB1B), | 80 | PM8606_LED_RESOURCE(PM8606_LED2_RED, RGB2B), |
81 | PM8606_LED_RESOURCE(PM8606_LED2_GREEN, RGB1C), | 81 | PM8606_LED_RESOURCE(PM8606_LED2_GREEN, RGB2C), |
82 | PM8606_LED_RESOURCE(PM8606_LED2_BLUE, RGB1D), | 82 | PM8606_LED_RESOURCE(PM8606_LED2_BLUE, RGB2D), |
83 | }; | 83 | }; |
84 | 84 | ||
85 | #define PM8606_LED_DEVS(_i) \ | 85 | #define PM8606_LED_DEVS(_i) \ |
@@ -428,52 +428,44 @@ static int __devinit device_gpadc_init(struct pm860x_chip *chip, | |||
428 | { | 428 | { |
429 | struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ | 429 | struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ |
430 | : chip->companion; | 430 | : chip->companion; |
431 | int use_gpadc = 0, data, ret; | 431 | int data; |
432 | int ret; | ||
432 | 433 | ||
433 | /* initialize GPADC without activating it */ | 434 | /* initialize GPADC without activating it */ |
434 | 435 | ||
435 | if (pdata && pdata->touch) { | 436 | if (!pdata || !pdata->touch) |
436 | /* set GPADC MISC1 register */ | 437 | return -EINVAL; |
437 | data = 0; | ||
438 | data |= (pdata->touch->gpadc_prebias << 1) | ||
439 | & PM8607_GPADC_PREBIAS_MASK; | ||
440 | data |= (pdata->touch->slot_cycle << 3) | ||
441 | & PM8607_GPADC_SLOT_CYCLE_MASK; | ||
442 | data |= (pdata->touch->off_scale << 5) | ||
443 | & PM8607_GPADC_OFF_SCALE_MASK; | ||
444 | data |= (pdata->touch->sw_cal << 7) | ||
445 | & PM8607_GPADC_SW_CAL_MASK; | ||
446 | if (data) { | ||
447 | ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data); | ||
448 | if (ret < 0) | ||
449 | goto out; | ||
450 | } | ||
451 | /* set tsi prebias time */ | ||
452 | if (pdata->touch->tsi_prebias) { | ||
453 | data = pdata->touch->tsi_prebias; | ||
454 | ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data); | ||
455 | if (ret < 0) | ||
456 | goto out; | ||
457 | } | ||
458 | /* set prebias & prechg time of pen detect */ | ||
459 | data = 0; | ||
460 | data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK; | ||
461 | data |= (pdata->touch->pen_prechg << 5) | ||
462 | & PM8607_PD_PRECHG_MASK; | ||
463 | if (data) { | ||
464 | ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data); | ||
465 | if (ret < 0) | ||
466 | goto out; | ||
467 | } | ||
468 | 438 | ||
469 | use_gpadc = 1; | 439 | /* set GPADC MISC1 register */ |
440 | data = 0; | ||
441 | data |= (pdata->touch->gpadc_prebias << 1) & PM8607_GPADC_PREBIAS_MASK; | ||
442 | data |= (pdata->touch->slot_cycle << 3) & PM8607_GPADC_SLOT_CYCLE_MASK; | ||
443 | data |= (pdata->touch->off_scale << 5) & PM8607_GPADC_OFF_SCALE_MASK; | ||
444 | data |= (pdata->touch->sw_cal << 7) & PM8607_GPADC_SW_CAL_MASK; | ||
445 | if (data) { | ||
446 | ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data); | ||
447 | if (ret < 0) | ||
448 | goto out; | ||
470 | } | 449 | } |
471 | 450 | /* set tsi prebias time */ | |
472 | /* turn on GPADC */ | 451 | if (pdata->touch->tsi_prebias) { |
473 | if (use_gpadc) { | 452 | data = pdata->touch->tsi_prebias; |
474 | ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1, | 453 | ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data); |
475 | PM8607_GPADC_EN, PM8607_GPADC_EN); | 454 | if (ret < 0) |
455 | goto out; | ||
476 | } | 456 | } |
457 | /* set prebias & prechg time of pen detect */ | ||
458 | data = 0; | ||
459 | data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK; | ||
460 | data |= (pdata->touch->pen_prechg << 5) & PM8607_PD_PRECHG_MASK; | ||
461 | if (data) { | ||
462 | ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data); | ||
463 | if (ret < 0) | ||
464 | goto out; | ||
465 | } | ||
466 | |||
467 | ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1, | ||
468 | PM8607_GPADC_EN, PM8607_GPADC_EN); | ||
477 | out: | 469 | out: |
478 | return ret; | 470 | return ret; |
479 | } | 471 | } |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 9da0e504bbe9..db51ea1c6082 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -7,7 +7,16 @@ menuconfig MFD_SUPPORT | |||
7 | depends on HAS_IOMEM | 7 | depends on HAS_IOMEM |
8 | default y | 8 | default y |
9 | help | 9 | help |
10 | Configure MFD device drivers. | 10 | Multifunction devices embed several functions (e.g. GPIOs, |
11 | touchscreens, keyboards, current regulators, power management chips, | ||
12 | etc...) in one single integrated circuit. They usually talk to the | ||
13 | main CPU through one or more IRQ lines and low speed data busses (SPI, | ||
14 | I2C, etc..). They appear as one single device to the main system | ||
15 | through the data bus and the MFD framework allows for sub devices | ||
16 | (a.k.a. functions) to appear as discrete platform devices. | ||
17 | MFDs are typically found on embedded platforms. | ||
18 | |||
19 | This option alone does not add any kernel code. | ||
11 | 20 | ||
12 | if MFD_SUPPORT | 21 | if MFD_SUPPORT |
13 | 22 | ||
@@ -177,6 +186,38 @@ config TWL4030_CODEC | |||
177 | select MFD_CORE | 186 | select MFD_CORE |
178 | default n | 187 | default n |
179 | 188 | ||
189 | config TWL6030_PWM | ||
190 | tristate "TWL6030 PWM (Pulse Width Modulator) Support" | ||
191 | depends on TWL4030_CORE | ||
192 | select HAVE_PWM | ||
193 | default n | ||
194 | help | ||
195 | Say yes here if you want support for TWL6030 PWM. | ||
196 | This is used to control charging LED brightness. | ||
197 | |||
198 | config MFD_STMPE | ||
199 | bool "Support STMicroelectronics STMPE" | ||
200 | depends on I2C=y && GENERIC_HARDIRQS | ||
201 | select MFD_CORE | ||
202 | help | ||
203 | Support for the STMPE family of I/O Expanders from | ||
204 | STMicroelectronics. | ||
205 | |||
206 | Currently supported devices are: | ||
207 | |||
208 | STMPE811: GPIO, Touchscreen | ||
209 | STMPE1601: GPIO, Keypad | ||
210 | STMPE2401: GPIO, Keypad | ||
211 | STMPE2403: GPIO, Keypad | ||
212 | |||
213 | This driver provides common support for accessing the device, | ||
214 | additional drivers must be enabled in order to use the functionality | ||
215 | of the device. Currently available sub drivers are: | ||
216 | |||
217 | GPIO: stmpe-gpio | ||
218 | Keypad: stmpe-keypad | ||
219 | Touchscreen: stmpe-ts | ||
220 | |||
180 | config MFD_TC35892 | 221 | config MFD_TC35892 |
181 | bool "Support Toshiba TC35892" | 222 | bool "Support Toshiba TC35892" |
182 | depends on I2C=y && GENERIC_HARDIRQS | 223 | depends on I2C=y && GENERIC_HARDIRQS |
@@ -252,6 +293,16 @@ config MFD_MAX8925 | |||
252 | accessing the device, additional drivers must be enabled in order | 293 | accessing the device, additional drivers must be enabled in order |
253 | to use the functionality of the device. | 294 | to use the functionality of the device. |
254 | 295 | ||
296 | config MFD_MAX8998 | ||
297 | bool "Maxim Semiconductor MAX8998 PMIC Support" | ||
298 | depends on I2C=y | ||
299 | select MFD_CORE | ||
300 | help | ||
301 | Say yes here to support for Maxim Semiconductor MAX8998. This is | ||
302 | a Power Management IC. This driver provies common support for | ||
303 | accessing the device, additional drivers must be enabled in order | ||
304 | to use the functionality of the device. | ||
305 | |||
255 | config MFD_WM8400 | 306 | config MFD_WM8400 |
256 | tristate "Support Wolfson Microelectronics WM8400" | 307 | tristate "Support Wolfson Microelectronics WM8400" |
257 | select MFD_CORE | 308 | select MFD_CORE |
@@ -482,6 +533,28 @@ config MFD_JANZ_CMODIO | |||
482 | host many different types of MODULbus daughterboards, including | 533 | host many different types of MODULbus daughterboards, including |
483 | CAN and GPIO controllers. | 534 | CAN and GPIO controllers. |
484 | 535 | ||
536 | config MFD_JZ4740_ADC | ||
537 | tristate "Support for the JZ4740 SoC ADC core" | ||
538 | select MFD_CORE | ||
539 | depends on MACH_JZ4740 | ||
540 | help | ||
541 | Say yes here if you want support for the ADC unit in the JZ4740 SoC. | ||
542 | This driver is necessary for jz4740-battery and jz4740-hwmon driver. | ||
543 | |||
544 | config MFD_TPS6586X | ||
545 | tristate "TPS6586x Power Management chips" | ||
546 | depends on I2C && GPIOLIB | ||
547 | select MFD_CORE | ||
548 | help | ||
549 | If you say yes here you get support for the TPS6586X series of | ||
550 | Power Management chips. | ||
551 | This driver provides common support for accessing the device, | ||
552 | additional drivers must be enabled in order to use the | ||
553 | functionality of the device. | ||
554 | |||
555 | This driver can also be built as a module. If so, the module | ||
556 | will be called tps6586x. | ||
557 | |||
485 | endif # MFD_SUPPORT | 558 | endif # MFD_SUPPORT |
486 | 559 | ||
487 | menu "Multimedia Capabilities Port drivers" | 560 | menu "Multimedia Capabilities Port drivers" |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index fb503e77dc60..feaeeaeeddb7 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -15,6 +15,7 @@ obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o | |||
15 | obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o | 15 | obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o |
16 | obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o | 16 | obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o |
17 | 17 | ||
18 | obj-$(CONFIG_MFD_STMPE) += stmpe.o | ||
18 | obj-$(CONFIG_MFD_TC35892) += tc35892.o | 19 | obj-$(CONFIG_MFD_TC35892) += tc35892.o |
19 | obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o | 20 | obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o |
20 | obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o | 21 | obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o |
@@ -36,6 +37,7 @@ obj-$(CONFIG_MENELAUS) += menelaus.o | |||
36 | obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o | 37 | obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o |
37 | obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o | 38 | obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o |
38 | obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o | 39 | obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o |
40 | obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o | ||
39 | 41 | ||
40 | obj-$(CONFIG_MFD_MC13783) += mc13783-core.o | 42 | obj-$(CONFIG_MFD_MC13783) += mc13783-core.o |
41 | 43 | ||
@@ -56,6 +58,7 @@ obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o | |||
56 | obj-$(CONFIG_PMIC_DA903X) += da903x.o | 58 | obj-$(CONFIG_PMIC_DA903X) += da903x.o |
57 | max8925-objs := max8925-core.o max8925-i2c.o | 59 | max8925-objs := max8925-core.o max8925-i2c.o |
58 | obj-$(CONFIG_MFD_MAX8925) += max8925.o | 60 | obj-$(CONFIG_MFD_MAX8925) += max8925.o |
61 | obj-$(CONFIG_MFD_MAX8998) += max8998.o | ||
59 | 62 | ||
60 | pcf50633-objs := pcf50633-core.o pcf50633-irq.o | 63 | pcf50633-objs := pcf50633-core.o pcf50633-irq.o |
61 | obj-$(CONFIG_MFD_PCF50633) += pcf50633.o | 64 | obj-$(CONFIG_MFD_PCF50633) += pcf50633.o |
@@ -71,3 +74,5 @@ obj-$(CONFIG_PMIC_ADP5520) += adp5520.o | |||
71 | obj-$(CONFIG_LPC_SCH) += lpc_sch.o | 74 | obj-$(CONFIG_LPC_SCH) += lpc_sch.o |
72 | obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o | 75 | obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o |
73 | obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o | 76 | obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o |
77 | obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o | ||
78 | obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o | ||
diff --git a/drivers/mfd/ab3100-otp.c b/drivers/mfd/ab3100-otp.c index 63d2b727ddbb..8440010eb2b8 100644 --- a/drivers/mfd/ab3100-otp.c +++ b/drivers/mfd/ab3100-otp.c | |||
@@ -199,7 +199,7 @@ static int __init ab3100_otp_probe(struct platform_device *pdev) | |||
199 | 199 | ||
200 | err = ab3100_otp_read(otp); | 200 | err = ab3100_otp_read(otp); |
201 | if (err) | 201 | if (err) |
202 | return err; | 202 | goto err_otp_read; |
203 | 203 | ||
204 | dev_info(&pdev->dev, "AB3100 OTP readout registered\n"); | 204 | dev_info(&pdev->dev, "AB3100 OTP readout registered\n"); |
205 | 205 | ||
@@ -208,21 +208,21 @@ static int __init ab3100_otp_probe(struct platform_device *pdev) | |||
208 | err = device_create_file(&pdev->dev, | 208 | err = device_create_file(&pdev->dev, |
209 | &ab3100_otp_attrs[i]); | 209 | &ab3100_otp_attrs[i]); |
210 | if (err) | 210 | if (err) |
211 | goto out_no_sysfs; | 211 | goto err_create_file; |
212 | } | 212 | } |
213 | 213 | ||
214 | /* debugfs entries */ | 214 | /* debugfs entries */ |
215 | err = ab3100_otp_init_debugfs(&pdev->dev, otp); | 215 | err = ab3100_otp_init_debugfs(&pdev->dev, otp); |
216 | if (err) | 216 | if (err) |
217 | goto out_no_debugfs; | 217 | goto err_init_debugfs; |
218 | 218 | ||
219 | return 0; | 219 | return 0; |
220 | 220 | ||
221 | out_no_sysfs: | 221 | err_init_debugfs: |
222 | for (i = 0; i < ARRAY_SIZE(ab3100_otp_attrs); i++) | 222 | err_create_file: |
223 | device_remove_file(&pdev->dev, | 223 | while (--i >= 0) |
224 | &ab3100_otp_attrs[i]); | 224 | device_remove_file(&pdev->dev, &ab3100_otp_attrs[i]); |
225 | out_no_debugfs: | 225 | err_otp_read: |
226 | kfree(otp); | 226 | kfree(otp); |
227 | return err; | 227 | return err; |
228 | } | 228 | } |
diff --git a/drivers/mfd/ab3550-core.c b/drivers/mfd/ab3550-core.c index f54ab62e7bc6..8a98739e6d9c 100644 --- a/drivers/mfd/ab3550-core.c +++ b/drivers/mfd/ab3550-core.c | |||
@@ -589,16 +589,16 @@ static bool reg_read_allowed(const struct ab3550_reg_ranges *ranges, u8 reg) | |||
589 | } | 589 | } |
590 | 590 | ||
591 | /* | 591 | /* |
592 | * The exported register access functionality. | 592 | * The register access functionality. |
593 | */ | 593 | */ |
594 | int ab3550_get_chip_id(struct device *dev) | 594 | static int ab3550_get_chip_id(struct device *dev) |
595 | { | 595 | { |
596 | struct ab3550 *ab = dev_get_drvdata(dev->parent); | 596 | struct ab3550 *ab = dev_get_drvdata(dev->parent); |
597 | return (int)ab->chip_id; | 597 | return (int)ab->chip_id; |
598 | } | 598 | } |
599 | 599 | ||
600 | int ab3550_mask_and_set_register_interruptible(struct device *dev, u8 bank, | 600 | static int ab3550_mask_and_set_register_interruptible(struct device *dev, |
601 | u8 reg, u8 bitmask, u8 bitvalues) | 601 | u8 bank, u8 reg, u8 bitmask, u8 bitvalues) |
602 | { | 602 | { |
603 | struct ab3550 *ab; | 603 | struct ab3550 *ab; |
604 | struct platform_device *pdev = to_platform_device(dev); | 604 | struct platform_device *pdev = to_platform_device(dev); |
@@ -612,15 +612,15 @@ int ab3550_mask_and_set_register_interruptible(struct device *dev, u8 bank, | |||
612 | bitmask, bitvalues); | 612 | bitmask, bitvalues); |
613 | } | 613 | } |
614 | 614 | ||
615 | int ab3550_set_register_interruptible(struct device *dev, u8 bank, u8 reg, | 615 | static int ab3550_set_register_interruptible(struct device *dev, u8 bank, |
616 | u8 value) | 616 | u8 reg, u8 value) |
617 | { | 617 | { |
618 | return ab3550_mask_and_set_register_interruptible(dev, bank, reg, 0xFF, | 618 | return ab3550_mask_and_set_register_interruptible(dev, bank, reg, 0xFF, |
619 | value); | 619 | value); |
620 | } | 620 | } |
621 | 621 | ||
622 | int ab3550_get_register_interruptible(struct device *dev, u8 bank, u8 reg, | 622 | static int ab3550_get_register_interruptible(struct device *dev, u8 bank, |
623 | u8 *value) | 623 | u8 reg, u8 *value) |
624 | { | 624 | { |
625 | struct ab3550 *ab; | 625 | struct ab3550 *ab; |
626 | struct platform_device *pdev = to_platform_device(dev); | 626 | struct platform_device *pdev = to_platform_device(dev); |
@@ -633,7 +633,7 @@ int ab3550_get_register_interruptible(struct device *dev, u8 bank, u8 reg, | |||
633 | return get_register_interruptible(ab, bank, reg, value); | 633 | return get_register_interruptible(ab, bank, reg, value); |
634 | } | 634 | } |
635 | 635 | ||
636 | int ab3550_get_register_page_interruptible(struct device *dev, u8 bank, | 636 | static int ab3550_get_register_page_interruptible(struct device *dev, u8 bank, |
637 | u8 first_reg, u8 *regvals, u8 numregs) | 637 | u8 first_reg, u8 *regvals, u8 numregs) |
638 | { | 638 | { |
639 | struct ab3550 *ab; | 639 | struct ab3550 *ab; |
@@ -649,7 +649,8 @@ int ab3550_get_register_page_interruptible(struct device *dev, u8 bank, | |||
649 | numregs); | 649 | numregs); |
650 | } | 650 | } |
651 | 651 | ||
652 | int ab3550_event_registers_startup_state_get(struct device *dev, u8 *event) | 652 | static int ab3550_event_registers_startup_state_get(struct device *dev, |
653 | u8 *event) | ||
653 | { | 654 | { |
654 | struct ab3550 *ab; | 655 | struct ab3550 *ab; |
655 | 656 | ||
@@ -661,7 +662,7 @@ int ab3550_event_registers_startup_state_get(struct device *dev, u8 *event) | |||
661 | return 0; | 662 | return 0; |
662 | } | 663 | } |
663 | 664 | ||
664 | int ab3550_startup_irq_enabled(struct device *dev, unsigned int irq) | 665 | static int ab3550_startup_irq_enabled(struct device *dev, unsigned int irq) |
665 | { | 666 | { |
666 | struct ab3550 *ab; | 667 | struct ab3550 *ab; |
667 | struct ab3550_platform_data *plf_data; | 668 | struct ab3550_platform_data *plf_data; |
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index f3d26fa9c34d..defa786dee34 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
17 | #include <linux/mfd/core.h> | 17 | #include <linux/mfd/core.h> |
18 | #include <linux/mfd/ab8500.h> | 18 | #include <linux/mfd/ab8500.h> |
19 | #include <linux/regulator/ab8500.h> | ||
19 | 20 | ||
20 | /* | 21 | /* |
21 | * Interrupt register offsets | 22 | * Interrupt register offsets |
@@ -352,6 +353,7 @@ static struct mfd_cell ab8500_devs[] = { | |||
352 | { .name = "ab8500-audio", }, | 353 | { .name = "ab8500-audio", }, |
353 | { .name = "ab8500-usb", }, | 354 | { .name = "ab8500-usb", }, |
354 | { .name = "ab8500-pwm", }, | 355 | { .name = "ab8500-pwm", }, |
356 | { .name = "ab8500-regulator", }, | ||
355 | }; | 357 | }; |
356 | 358 | ||
357 | int __devinit ab8500_init(struct ab8500 *ab8500) | 359 | int __devinit ab8500_init(struct ab8500 *ab8500) |
@@ -411,7 +413,7 @@ int __devinit ab8500_init(struct ab8500 *ab8500) | |||
411 | goto out_removeirq; | 413 | goto out_removeirq; |
412 | } | 414 | } |
413 | 415 | ||
414 | ret = mfd_add_devices(ab8500->dev, -1, ab8500_devs, | 416 | ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, |
415 | ARRAY_SIZE(ab8500_devs), NULL, | 417 | ARRAY_SIZE(ab8500_devs), NULL, |
416 | ab8500->irq_base); | 418 | ab8500->irq_base); |
417 | if (ret) | 419 | if (ret) |
diff --git a/drivers/mfd/ab8500-spi.c b/drivers/mfd/ab8500-spi.c index b81d4f768ef6..e1c8b62b086d 100644 --- a/drivers/mfd/ab8500-spi.c +++ b/drivers/mfd/ab8500-spi.c | |||
@@ -68,7 +68,12 @@ static int ab8500_spi_read(struct ab8500 *ab8500, u16 addr) | |||
68 | 68 | ||
69 | ret = spi_sync(spi, &msg); | 69 | ret = spi_sync(spi, &msg); |
70 | if (!ret) | 70 | if (!ret) |
71 | ret = ab8500->rx_buf[0]; | 71 | /* |
72 | * Only the 8 lowermost bytes are | ||
73 | * defined with value, the rest may | ||
74 | * vary depending on chip/board noise. | ||
75 | */ | ||
76 | ret = ab8500->rx_buf[0] & 0xFFU; | ||
72 | 77 | ||
73 | return ret; | 78 | return ret; |
74 | } | 79 | } |
diff --git a/drivers/mfd/abx500-core.c b/drivers/mfd/abx500-core.c index 3b3b97ec32a7..f12720dbe126 100644 --- a/drivers/mfd/abx500-core.c +++ b/drivers/mfd/abx500-core.c | |||
@@ -36,7 +36,7 @@ int abx500_register_ops(struct device *dev, struct abx500_ops *ops) | |||
36 | struct abx500_device_entry *dev_entry; | 36 | struct abx500_device_entry *dev_entry; |
37 | 37 | ||
38 | dev_entry = kzalloc(sizeof(struct abx500_device_entry), GFP_KERNEL); | 38 | dev_entry = kzalloc(sizeof(struct abx500_device_entry), GFP_KERNEL); |
39 | if (IS_ERR(dev_entry)) { | 39 | if (!dev_entry) { |
40 | dev_err(dev, "register_ops kzalloc failed"); | 40 | dev_err(dev, "register_ops kzalloc failed"); |
41 | return -ENOMEM; | 41 | return -ENOMEM; |
42 | } | 42 | } |
diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c index 3e75f02e4778..33c923d215c7 100644 --- a/drivers/mfd/davinci_voicecodec.c +++ b/drivers/mfd/davinci_voicecodec.c | |||
@@ -94,7 +94,8 @@ static int __init davinci_vc_probe(struct platform_device *pdev) | |||
94 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 94 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
95 | if (!res) { | 95 | if (!res) { |
96 | dev_err(&pdev->dev, "no DMA resource\n"); | 96 | dev_err(&pdev->dev, "no DMA resource\n"); |
97 | return -ENXIO; | 97 | ret = -ENXIO; |
98 | goto fail4; | ||
98 | } | 99 | } |
99 | 100 | ||
100 | davinci_vc->davinci_vcif.dma_tx_channel = res->start; | 101 | davinci_vc->davinci_vcif.dma_tx_channel = res->start; |
@@ -104,7 +105,8 @@ static int __init davinci_vc_probe(struct platform_device *pdev) | |||
104 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | 105 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); |
105 | if (!res) { | 106 | if (!res) { |
106 | dev_err(&pdev->dev, "no DMA resource\n"); | 107 | dev_err(&pdev->dev, "no DMA resource\n"); |
107 | return -ENXIO; | 108 | ret = -ENXIO; |
109 | goto fail4; | ||
108 | } | 110 | } |
109 | 111 | ||
110 | davinci_vc->davinci_vcif.dma_rx_channel = res->start; | 112 | davinci_vc->davinci_vcif.dma_rx_channel = res->start; |
diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c index 9ed630799acc..36a166bcdb08 100644 --- a/drivers/mfd/janz-cmodio.c +++ b/drivers/mfd/janz-cmodio.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/slab.h> | ||
21 | #include <linux/mfd/core.h> | 22 | #include <linux/mfd/core.h> |
22 | 23 | ||
23 | #include <linux/mfd/janz.h> | 24 | #include <linux/mfd/janz.h> |
diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c new file mode 100644 index 000000000000..3ad492cb6c41 --- /dev/null +++ b/drivers/mfd/jz4740-adc.c | |||
@@ -0,0 +1,394 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> | ||
3 | * JZ4740 SoC ADC driver | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * You should have received a copy of the GNU General Public License along | ||
11 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
12 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
13 | * | ||
14 | * This driver synchronizes access to the JZ4740 ADC core between the | ||
15 | * JZ4740 battery and hwmon drivers. | ||
16 | */ | ||
17 | |||
18 | #include <linux/err.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/spinlock.h> | ||
26 | |||
27 | #include <linux/clk.h> | ||
28 | #include <linux/mfd/core.h> | ||
29 | |||
30 | #include <linux/jz4740-adc.h> | ||
31 | |||
32 | |||
33 | #define JZ_REG_ADC_ENABLE 0x00 | ||
34 | #define JZ_REG_ADC_CFG 0x04 | ||
35 | #define JZ_REG_ADC_CTRL 0x08 | ||
36 | #define JZ_REG_ADC_STATUS 0x0c | ||
37 | |||
38 | #define JZ_REG_ADC_TOUCHSCREEN_BASE 0x10 | ||
39 | #define JZ_REG_ADC_BATTERY_BASE 0x1c | ||
40 | #define JZ_REG_ADC_HWMON_BASE 0x20 | ||
41 | |||
42 | #define JZ_ADC_ENABLE_TOUCH BIT(2) | ||
43 | #define JZ_ADC_ENABLE_BATTERY BIT(1) | ||
44 | #define JZ_ADC_ENABLE_ADCIN BIT(0) | ||
45 | |||
46 | enum { | ||
47 | JZ_ADC_IRQ_ADCIN = 0, | ||
48 | JZ_ADC_IRQ_BATTERY, | ||
49 | JZ_ADC_IRQ_TOUCH, | ||
50 | JZ_ADC_IRQ_PENUP, | ||
51 | JZ_ADC_IRQ_PENDOWN, | ||
52 | }; | ||
53 | |||
54 | struct jz4740_adc { | ||
55 | struct resource *mem; | ||
56 | void __iomem *base; | ||
57 | |||
58 | int irq; | ||
59 | int irq_base; | ||
60 | |||
61 | struct clk *clk; | ||
62 | atomic_t clk_ref; | ||
63 | |||
64 | spinlock_t lock; | ||
65 | }; | ||
66 | |||
67 | static inline void jz4740_adc_irq_set_masked(struct jz4740_adc *adc, int irq, | ||
68 | bool masked) | ||
69 | { | ||
70 | unsigned long flags; | ||
71 | uint8_t val; | ||
72 | |||
73 | irq -= adc->irq_base; | ||
74 | |||
75 | spin_lock_irqsave(&adc->lock, flags); | ||
76 | |||
77 | val = readb(adc->base + JZ_REG_ADC_CTRL); | ||
78 | if (masked) | ||
79 | val |= BIT(irq); | ||
80 | else | ||
81 | val &= ~BIT(irq); | ||
82 | writeb(val, adc->base + JZ_REG_ADC_CTRL); | ||
83 | |||
84 | spin_unlock_irqrestore(&adc->lock, flags); | ||
85 | } | ||
86 | |||
87 | static void jz4740_adc_irq_mask(unsigned int irq) | ||
88 | { | ||
89 | struct jz4740_adc *adc = get_irq_chip_data(irq); | ||
90 | jz4740_adc_irq_set_masked(adc, irq, true); | ||
91 | } | ||
92 | |||
93 | static void jz4740_adc_irq_unmask(unsigned int irq) | ||
94 | { | ||
95 | struct jz4740_adc *adc = get_irq_chip_data(irq); | ||
96 | jz4740_adc_irq_set_masked(adc, irq, false); | ||
97 | } | ||
98 | |||
99 | static void jz4740_adc_irq_ack(unsigned int irq) | ||
100 | { | ||
101 | struct jz4740_adc *adc = get_irq_chip_data(irq); | ||
102 | |||
103 | irq -= adc->irq_base; | ||
104 | writeb(BIT(irq), adc->base + JZ_REG_ADC_STATUS); | ||
105 | } | ||
106 | |||
107 | static struct irq_chip jz4740_adc_irq_chip = { | ||
108 | .name = "jz4740-adc", | ||
109 | .mask = jz4740_adc_irq_mask, | ||
110 | .unmask = jz4740_adc_irq_unmask, | ||
111 | .ack = jz4740_adc_irq_ack, | ||
112 | }; | ||
113 | |||
114 | static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc) | ||
115 | { | ||
116 | struct jz4740_adc *adc = get_irq_desc_data(desc); | ||
117 | uint8_t status; | ||
118 | unsigned int i; | ||
119 | |||
120 | status = readb(adc->base + JZ_REG_ADC_STATUS); | ||
121 | |||
122 | for (i = 0; i < 5; ++i) { | ||
123 | if (status & BIT(i)) | ||
124 | generic_handle_irq(adc->irq_base + i); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | |||
129 | /* Refcounting for the ADC clock is done in here instead of in the clock | ||
130 | * framework, because it is the only clock which is shared between multiple | ||
131 | * devices and thus is the only clock which needs refcounting */ | ||
132 | static inline void jz4740_adc_clk_enable(struct jz4740_adc *adc) | ||
133 | { | ||
134 | if (atomic_inc_return(&adc->clk_ref) == 1) | ||
135 | clk_enable(adc->clk); | ||
136 | } | ||
137 | |||
138 | static inline void jz4740_adc_clk_disable(struct jz4740_adc *adc) | ||
139 | { | ||
140 | if (atomic_dec_return(&adc->clk_ref) == 0) | ||
141 | clk_disable(adc->clk); | ||
142 | } | ||
143 | |||
144 | static inline void jz4740_adc_set_enabled(struct jz4740_adc *adc, int engine, | ||
145 | bool enabled) | ||
146 | { | ||
147 | unsigned long flags; | ||
148 | uint8_t val; | ||
149 | |||
150 | spin_lock_irqsave(&adc->lock, flags); | ||
151 | |||
152 | val = readb(adc->base + JZ_REG_ADC_ENABLE); | ||
153 | if (enabled) | ||
154 | val |= BIT(engine); | ||
155 | else | ||
156 | val &= BIT(engine); | ||
157 | writeb(val, adc->base + JZ_REG_ADC_ENABLE); | ||
158 | |||
159 | spin_unlock_irqrestore(&adc->lock, flags); | ||
160 | } | ||
161 | |||
162 | static int jz4740_adc_cell_enable(struct platform_device *pdev) | ||
163 | { | ||
164 | struct jz4740_adc *adc = dev_get_drvdata(pdev->dev.parent); | ||
165 | |||
166 | jz4740_adc_clk_enable(adc); | ||
167 | jz4740_adc_set_enabled(adc, pdev->id, true); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static int jz4740_adc_cell_disable(struct platform_device *pdev) | ||
173 | { | ||
174 | struct jz4740_adc *adc = dev_get_drvdata(pdev->dev.parent); | ||
175 | |||
176 | jz4740_adc_set_enabled(adc, pdev->id, false); | ||
177 | jz4740_adc_clk_disable(adc); | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | int jz4740_adc_set_config(struct device *dev, uint32_t mask, uint32_t val) | ||
183 | { | ||
184 | struct jz4740_adc *adc = dev_get_drvdata(dev); | ||
185 | unsigned long flags; | ||
186 | uint32_t cfg; | ||
187 | |||
188 | if (!adc) | ||
189 | return -ENODEV; | ||
190 | |||
191 | spin_lock_irqsave(&adc->lock, flags); | ||
192 | |||
193 | cfg = readl(adc->base + JZ_REG_ADC_CFG); | ||
194 | |||
195 | cfg &= ~mask; | ||
196 | cfg |= val; | ||
197 | |||
198 | writel(cfg, adc->base + JZ_REG_ADC_CFG); | ||
199 | |||
200 | spin_unlock_irqrestore(&adc->lock, flags); | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | EXPORT_SYMBOL_GPL(jz4740_adc_set_config); | ||
205 | |||
206 | static struct resource jz4740_hwmon_resources[] = { | ||
207 | { | ||
208 | .start = JZ_ADC_IRQ_ADCIN, | ||
209 | .flags = IORESOURCE_IRQ, | ||
210 | }, | ||
211 | { | ||
212 | .start = JZ_REG_ADC_HWMON_BASE, | ||
213 | .end = JZ_REG_ADC_HWMON_BASE + 3, | ||
214 | .flags = IORESOURCE_MEM, | ||
215 | }, | ||
216 | }; | ||
217 | |||
218 | static struct resource jz4740_battery_resources[] = { | ||
219 | { | ||
220 | .start = JZ_ADC_IRQ_BATTERY, | ||
221 | .flags = IORESOURCE_IRQ, | ||
222 | }, | ||
223 | { | ||
224 | .start = JZ_REG_ADC_BATTERY_BASE, | ||
225 | .end = JZ_REG_ADC_BATTERY_BASE + 3, | ||
226 | .flags = IORESOURCE_MEM, | ||
227 | }, | ||
228 | }; | ||
229 | |||
230 | const struct mfd_cell jz4740_adc_cells[] = { | ||
231 | { | ||
232 | .id = 0, | ||
233 | .name = "jz4740-hwmon", | ||
234 | .num_resources = ARRAY_SIZE(jz4740_hwmon_resources), | ||
235 | .resources = jz4740_hwmon_resources, | ||
236 | .platform_data = (void *)&jz4740_adc_cells[0], | ||
237 | .data_size = sizeof(struct mfd_cell), | ||
238 | |||
239 | .enable = jz4740_adc_cell_enable, | ||
240 | .disable = jz4740_adc_cell_disable, | ||
241 | }, | ||
242 | { | ||
243 | .id = 1, | ||
244 | .name = "jz4740-battery", | ||
245 | .num_resources = ARRAY_SIZE(jz4740_battery_resources), | ||
246 | .resources = jz4740_battery_resources, | ||
247 | .platform_data = (void *)&jz4740_adc_cells[1], | ||
248 | .data_size = sizeof(struct mfd_cell), | ||
249 | |||
250 | .enable = jz4740_adc_cell_enable, | ||
251 | .disable = jz4740_adc_cell_disable, | ||
252 | }, | ||
253 | }; | ||
254 | |||
255 | static int __devinit jz4740_adc_probe(struct platform_device *pdev) | ||
256 | { | ||
257 | int ret; | ||
258 | struct jz4740_adc *adc; | ||
259 | struct resource *mem_base; | ||
260 | int irq; | ||
261 | |||
262 | adc = kmalloc(sizeof(*adc), GFP_KERNEL); | ||
263 | if (!adc) { | ||
264 | dev_err(&pdev->dev, "Failed to allocate driver structure\n"); | ||
265 | return -ENOMEM; | ||
266 | } | ||
267 | |||
268 | adc->irq = platform_get_irq(pdev, 0); | ||
269 | if (adc->irq < 0) { | ||
270 | ret = adc->irq; | ||
271 | dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret); | ||
272 | goto err_free; | ||
273 | } | ||
274 | |||
275 | adc->irq_base = platform_get_irq(pdev, 1); | ||
276 | if (adc->irq_base < 0) { | ||
277 | ret = adc->irq_base; | ||
278 | dev_err(&pdev->dev, "Failed to get irq base: %d\n", ret); | ||
279 | goto err_free; | ||
280 | } | ||
281 | |||
282 | mem_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
283 | if (!mem_base) { | ||
284 | ret = -ENOENT; | ||
285 | dev_err(&pdev->dev, "Failed to get platform mmio resource\n"); | ||
286 | goto err_free; | ||
287 | } | ||
288 | |||
289 | /* Only request the shared registers for the MFD driver */ | ||
290 | adc->mem = request_mem_region(mem_base->start, JZ_REG_ADC_STATUS, | ||
291 | pdev->name); | ||
292 | if (!adc->mem) { | ||
293 | ret = -EBUSY; | ||
294 | dev_err(&pdev->dev, "Failed to request mmio memory region\n"); | ||
295 | goto err_free; | ||
296 | } | ||
297 | |||
298 | adc->base = ioremap_nocache(adc->mem->start, resource_size(adc->mem)); | ||
299 | if (!adc->base) { | ||
300 | ret = -EBUSY; | ||
301 | dev_err(&pdev->dev, "Failed to ioremap mmio memory\n"); | ||
302 | goto err_release_mem_region; | ||
303 | } | ||
304 | |||
305 | adc->clk = clk_get(&pdev->dev, "adc"); | ||
306 | if (IS_ERR(adc->clk)) { | ||
307 | ret = PTR_ERR(adc->clk); | ||
308 | dev_err(&pdev->dev, "Failed to get clock: %d\n", ret); | ||
309 | goto err_iounmap; | ||
310 | } | ||
311 | |||
312 | spin_lock_init(&adc->lock); | ||
313 | atomic_set(&adc->clk_ref, 0); | ||
314 | |||
315 | platform_set_drvdata(pdev, adc); | ||
316 | |||
317 | for (irq = adc->irq_base; irq < adc->irq_base + 5; ++irq) { | ||
318 | set_irq_chip_data(irq, adc); | ||
319 | set_irq_chip_and_handler(irq, &jz4740_adc_irq_chip, | ||
320 | handle_level_irq); | ||
321 | } | ||
322 | |||
323 | set_irq_data(adc->irq, adc); | ||
324 | set_irq_chained_handler(adc->irq, jz4740_adc_irq_demux); | ||
325 | |||
326 | writeb(0x00, adc->base + JZ_REG_ADC_ENABLE); | ||
327 | writeb(0xff, adc->base + JZ_REG_ADC_CTRL); | ||
328 | |||
329 | ret = mfd_add_devices(&pdev->dev, 0, jz4740_adc_cells, | ||
330 | ARRAY_SIZE(jz4740_adc_cells), mem_base, adc->irq_base); | ||
331 | if (ret < 0) | ||
332 | goto err_clk_put; | ||
333 | |||
334 | return 0; | ||
335 | |||
336 | err_clk_put: | ||
337 | clk_put(adc->clk); | ||
338 | err_iounmap: | ||
339 | platform_set_drvdata(pdev, NULL); | ||
340 | iounmap(adc->base); | ||
341 | err_release_mem_region: | ||
342 | release_mem_region(adc->mem->start, resource_size(adc->mem)); | ||
343 | err_free: | ||
344 | kfree(adc); | ||
345 | |||
346 | return ret; | ||
347 | } | ||
348 | |||
349 | static int __devexit jz4740_adc_remove(struct platform_device *pdev) | ||
350 | { | ||
351 | struct jz4740_adc *adc = platform_get_drvdata(pdev); | ||
352 | |||
353 | mfd_remove_devices(&pdev->dev); | ||
354 | |||
355 | set_irq_data(adc->irq, NULL); | ||
356 | set_irq_chained_handler(adc->irq, NULL); | ||
357 | |||
358 | iounmap(adc->base); | ||
359 | release_mem_region(adc->mem->start, resource_size(adc->mem)); | ||
360 | |||
361 | clk_put(adc->clk); | ||
362 | |||
363 | platform_set_drvdata(pdev, NULL); | ||
364 | |||
365 | kfree(adc); | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | struct platform_driver jz4740_adc_driver = { | ||
371 | .probe = jz4740_adc_probe, | ||
372 | .remove = __devexit_p(jz4740_adc_remove), | ||
373 | .driver = { | ||
374 | .name = "jz4740-adc", | ||
375 | .owner = THIS_MODULE, | ||
376 | }, | ||
377 | }; | ||
378 | |||
379 | static int __init jz4740_adc_init(void) | ||
380 | { | ||
381 | return platform_driver_register(&jz4740_adc_driver); | ||
382 | } | ||
383 | module_init(jz4740_adc_init); | ||
384 | |||
385 | static void __exit jz4740_adc_exit(void) | ||
386 | { | ||
387 | platform_driver_unregister(&jz4740_adc_driver); | ||
388 | } | ||
389 | module_exit(jz4740_adc_exit); | ||
390 | |||
391 | MODULE_DESCRIPTION("JZ4740 SoC ADC driver"); | ||
392 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
393 | MODULE_LICENSE("GPL"); | ||
394 | MODULE_ALIAS("platform:jz4740-adc"); | ||
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index f621bcea3d02..04028a9ee082 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c | |||
@@ -90,6 +90,24 @@ static struct mfd_cell rtc_devs[] = { | |||
90 | }, | 90 | }, |
91 | }; | 91 | }; |
92 | 92 | ||
93 | static struct resource onkey_resources[] = { | ||
94 | { | ||
95 | .name = "max8925-onkey", | ||
96 | .start = MAX8925_IRQ_GPM_SW_3SEC, | ||
97 | .end = MAX8925_IRQ_GPM_SW_3SEC, | ||
98 | .flags = IORESOURCE_IRQ, | ||
99 | }, | ||
100 | }; | ||
101 | |||
102 | static struct mfd_cell onkey_devs[] = { | ||
103 | { | ||
104 | .name = "max8925-onkey", | ||
105 | .num_resources = 1, | ||
106 | .resources = &onkey_resources[0], | ||
107 | .id = -1, | ||
108 | }, | ||
109 | }; | ||
110 | |||
93 | #define MAX8925_REG_RESOURCE(_start, _end) \ | 111 | #define MAX8925_REG_RESOURCE(_start, _end) \ |
94 | { \ | 112 | { \ |
95 | .start = MAX8925_##_start, \ | 113 | .start = MAX8925_##_start, \ |
@@ -596,6 +614,15 @@ int __devinit max8925_device_init(struct max8925_chip *chip, | |||
596 | dev_err(chip->dev, "Failed to add rtc subdev\n"); | 614 | dev_err(chip->dev, "Failed to add rtc subdev\n"); |
597 | goto out; | 615 | goto out; |
598 | } | 616 | } |
617 | |||
618 | ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], | ||
619 | ARRAY_SIZE(onkey_devs), | ||
620 | &onkey_resources[0], 0); | ||
621 | if (ret < 0) { | ||
622 | dev_err(chip->dev, "Failed to add onkey subdev\n"); | ||
623 | goto out_dev; | ||
624 | } | ||
625 | |||
599 | if (pdata && pdata->regulator[0]) { | 626 | if (pdata && pdata->regulator[0]) { |
600 | ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], | 627 | ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], |
601 | ARRAY_SIZE(regulator_devs), | 628 | ARRAY_SIZE(regulator_devs), |
diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c new file mode 100644 index 000000000000..73e6f5c4efc9 --- /dev/null +++ b/drivers/mfd/max8998.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * max8698.c - mfd core driver for the Maxim 8998 | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Samsung Electronics | ||
5 | * Kyungmin Park <kyungmin.park@samsung.com> | ||
6 | * Marek Szyprowski <m.szyprowski@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/moduleparam.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <linux/mutex.h> | ||
29 | #include <linux/mfd/core.h> | ||
30 | #include <linux/mfd/max8998.h> | ||
31 | #include <linux/mfd/max8998-private.h> | ||
32 | |||
33 | static struct mfd_cell max8998_devs[] = { | ||
34 | { | ||
35 | .name = "max8998-pmic", | ||
36 | } | ||
37 | }; | ||
38 | |||
39 | static int max8998_i2c_device_read(struct max8998_dev *max8998, u8 reg, u8 *dest) | ||
40 | { | ||
41 | struct i2c_client *client = max8998->i2c_client; | ||
42 | int ret; | ||
43 | |||
44 | mutex_lock(&max8998->iolock); | ||
45 | ret = i2c_smbus_read_byte_data(client, reg); | ||
46 | mutex_unlock(&max8998->iolock); | ||
47 | if (ret < 0) | ||
48 | return ret; | ||
49 | |||
50 | ret &= 0xff; | ||
51 | *dest = ret; | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static int max8998_i2c_device_write(struct max8998_dev *max8998, u8 reg, u8 value) | ||
56 | { | ||
57 | struct i2c_client *client = max8998->i2c_client; | ||
58 | int ret; | ||
59 | |||
60 | mutex_lock(&max8998->iolock); | ||
61 | ret = i2c_smbus_write_byte_data(client, reg, value); | ||
62 | mutex_unlock(&max8998->iolock); | ||
63 | return ret; | ||
64 | } | ||
65 | |||
66 | static int max8998_i2c_device_update(struct max8998_dev *max8998, u8 reg, | ||
67 | u8 val, u8 mask) | ||
68 | { | ||
69 | struct i2c_client *client = max8998->i2c_client; | ||
70 | int ret; | ||
71 | |||
72 | mutex_lock(&max8998->iolock); | ||
73 | ret = i2c_smbus_read_byte_data(client, reg); | ||
74 | if (ret >= 0) { | ||
75 | u8 old_val = ret & 0xff; | ||
76 | u8 new_val = (val & mask) | (old_val & (~mask)); | ||
77 | ret = i2c_smbus_write_byte_data(client, reg, new_val); | ||
78 | if (ret >= 0) | ||
79 | ret = 0; | ||
80 | } | ||
81 | mutex_unlock(&max8998->iolock); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | static int max8998_i2c_probe(struct i2c_client *i2c, | ||
86 | const struct i2c_device_id *id) | ||
87 | { | ||
88 | struct max8998_dev *max8998; | ||
89 | int ret = 0; | ||
90 | |||
91 | max8998 = kzalloc(sizeof(struct max8998_dev), GFP_KERNEL); | ||
92 | if (max8998 == NULL) | ||
93 | return -ENOMEM; | ||
94 | |||
95 | i2c_set_clientdata(i2c, max8998); | ||
96 | max8998->dev = &i2c->dev; | ||
97 | max8998->i2c_client = i2c; | ||
98 | max8998->dev_read = max8998_i2c_device_read; | ||
99 | max8998->dev_write = max8998_i2c_device_write; | ||
100 | max8998->dev_update = max8998_i2c_device_update; | ||
101 | mutex_init(&max8998->iolock); | ||
102 | |||
103 | ret = mfd_add_devices(max8998->dev, -1, | ||
104 | max8998_devs, ARRAY_SIZE(max8998_devs), | ||
105 | NULL, 0); | ||
106 | if (ret < 0) | ||
107 | goto err; | ||
108 | |||
109 | return ret; | ||
110 | |||
111 | err: | ||
112 | mfd_remove_devices(max8998->dev); | ||
113 | kfree(max8998); | ||
114 | return ret; | ||
115 | } | ||
116 | |||
117 | static int max8998_i2c_remove(struct i2c_client *i2c) | ||
118 | { | ||
119 | struct max8998_dev *max8998 = i2c_get_clientdata(i2c); | ||
120 | |||
121 | mfd_remove_devices(max8998->dev); | ||
122 | kfree(max8998); | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static const struct i2c_device_id max8998_i2c_id[] = { | ||
128 | { "max8998", 0 }, | ||
129 | { } | ||
130 | }; | ||
131 | MODULE_DEVICE_TABLE(i2c, max8998_i2c_id); | ||
132 | |||
133 | static struct i2c_driver max8998_i2c_driver = { | ||
134 | .driver = { | ||
135 | .name = "max8998", | ||
136 | .owner = THIS_MODULE, | ||
137 | }, | ||
138 | .probe = max8998_i2c_probe, | ||
139 | .remove = max8998_i2c_remove, | ||
140 | .id_table = max8998_i2c_id, | ||
141 | }; | ||
142 | |||
143 | static int __init max8998_i2c_init(void) | ||
144 | { | ||
145 | return i2c_add_driver(&max8998_i2c_driver); | ||
146 | } | ||
147 | /* init early so consumer devices can complete system boot */ | ||
148 | subsys_initcall(max8998_i2c_init); | ||
149 | |||
150 | static void __exit max8998_i2c_exit(void) | ||
151 | { | ||
152 | i2c_del_driver(&max8998_i2c_driver); | ||
153 | } | ||
154 | module_exit(max8998_i2c_exit); | ||
155 | |||
156 | MODULE_DESCRIPTION("MAXIM 8998 multi-function core driver"); | ||
157 | MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>"); | ||
158 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/mc13783-core.c b/drivers/mfd/mc13783-core.c index fecf38a4f025..6df34989c1f6 100644 --- a/drivers/mfd/mc13783-core.c +++ b/drivers/mfd/mc13783-core.c | |||
@@ -11,9 +11,31 @@ | |||
11 | */ | 11 | */ |
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/mutex.h> | ||
16 | #include <linux/interrupt.h> | ||
14 | #include <linux/spi/spi.h> | 17 | #include <linux/spi/spi.h> |
15 | #include <linux/mfd/core.h> | 18 | #include <linux/mfd/core.h> |
16 | #include <linux/mfd/mc13783-private.h> | 19 | #include <linux/mfd/mc13783.h> |
20 | |||
21 | struct mc13783 { | ||
22 | struct spi_device *spidev; | ||
23 | struct mutex lock; | ||
24 | int irq; | ||
25 | int flags; | ||
26 | |||
27 | irq_handler_t irqhandler[MC13783_NUM_IRQ]; | ||
28 | void *irqdata[MC13783_NUM_IRQ]; | ||
29 | |||
30 | /* XXX these should go as platformdata to the regulator subdevice */ | ||
31 | struct mc13783_regulator_init_data *regulators; | ||
32 | int num_regulators; | ||
33 | }; | ||
34 | |||
35 | #define MC13783_REG_REVISION 7 | ||
36 | #define MC13783_REG_ADC_0 43 | ||
37 | #define MC13783_REG_ADC_1 44 | ||
38 | #define MC13783_REG_ADC_2 45 | ||
17 | 39 | ||
18 | #define MC13783_IRQSTAT0 0 | 40 | #define MC13783_IRQSTAT0 0 |
19 | #define MC13783_IRQSTAT0_ADCDONEI (1 << 0) | 41 | #define MC13783_IRQSTAT0_ADCDONEI (1 << 0) |
@@ -226,6 +248,12 @@ int mc13783_reg_rmw(struct mc13783 *mc13783, unsigned int offset, | |||
226 | } | 248 | } |
227 | EXPORT_SYMBOL(mc13783_reg_rmw); | 249 | EXPORT_SYMBOL(mc13783_reg_rmw); |
228 | 250 | ||
251 | int mc13783_get_flags(struct mc13783 *mc13783) | ||
252 | { | ||
253 | return mc13783->flags; | ||
254 | } | ||
255 | EXPORT_SYMBOL(mc13783_get_flags); | ||
256 | |||
229 | int mc13783_irq_mask(struct mc13783 *mc13783, int irq) | 257 | int mc13783_irq_mask(struct mc13783 *mc13783, int irq) |
230 | { | 258 | { |
231 | int ret; | 259 | int ret; |
diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c index a3fb4bcb9889..4ba85bbdb4c1 100644 --- a/drivers/mfd/menelaus.c +++ b/drivers/mfd/menelaus.c | |||
@@ -128,6 +128,39 @@ | |||
128 | #define MENELAUS_RESERVED14_IRQ 14 /* Reserved */ | 128 | #define MENELAUS_RESERVED14_IRQ 14 /* Reserved */ |
129 | #define MENELAUS_RESERVED15_IRQ 15 /* Reserved */ | 129 | #define MENELAUS_RESERVED15_IRQ 15 /* Reserved */ |
130 | 130 | ||
131 | /* VCORE_CTRL1 register */ | ||
132 | #define VCORE_CTRL1_BYP_COMP (1 << 5) | ||
133 | #define VCORE_CTRL1_HW_NSW (1 << 7) | ||
134 | |||
135 | /* GPIO_CTRL register */ | ||
136 | #define GPIO_CTRL_SLOTSELEN (1 << 5) | ||
137 | #define GPIO_CTRL_SLPCTLEN (1 << 6) | ||
138 | #define GPIO1_DIR_INPUT (1 << 0) | ||
139 | #define GPIO2_DIR_INPUT (1 << 1) | ||
140 | #define GPIO3_DIR_INPUT (1 << 2) | ||
141 | |||
142 | /* MCT_CTRL1 register */ | ||
143 | #define MCT_CTRL1_S1_CMD_OD (1 << 2) | ||
144 | #define MCT_CTRL1_S2_CMD_OD (1 << 3) | ||
145 | |||
146 | /* MCT_CTRL2 register */ | ||
147 | #define MCT_CTRL2_VS2_SEL_D0 (1 << 0) | ||
148 | #define MCT_CTRL2_VS2_SEL_D1 (1 << 1) | ||
149 | #define MCT_CTRL2_S1CD_BUFEN (1 << 4) | ||
150 | #define MCT_CTRL2_S2CD_BUFEN (1 << 5) | ||
151 | #define MCT_CTRL2_S1CD_DBEN (1 << 6) | ||
152 | #define MCT_CTRL2_S2CD_BEN (1 << 7) | ||
153 | |||
154 | /* MCT_CTRL3 register */ | ||
155 | #define MCT_CTRL3_SLOT1_EN (1 << 0) | ||
156 | #define MCT_CTRL3_SLOT2_EN (1 << 1) | ||
157 | #define MCT_CTRL3_S1_AUTO_EN (1 << 2) | ||
158 | #define MCT_CTRL3_S2_AUTO_EN (1 << 3) | ||
159 | |||
160 | /* MCT_PIN_ST register */ | ||
161 | #define MCT_PIN_ST_S1_CD_ST (1 << 0) | ||
162 | #define MCT_PIN_ST_S2_CD_ST (1 << 1) | ||
163 | |||
131 | static void menelaus_work(struct work_struct *_menelaus); | 164 | static void menelaus_work(struct work_struct *_menelaus); |
132 | 165 | ||
133 | struct menelaus_chip { | 166 | struct menelaus_chip { |
@@ -249,10 +282,10 @@ static void menelaus_mmc_cd_work(struct menelaus_chip *menelaus_hw) | |||
249 | return; | 282 | return; |
250 | 283 | ||
251 | if (!(reg & 0x1)) | 284 | if (!(reg & 0x1)) |
252 | card_mask |= (1 << 0); | 285 | card_mask |= MCT_PIN_ST_S1_CD_ST; |
253 | 286 | ||
254 | if (!(reg & 0x2)) | 287 | if (!(reg & 0x2)) |
255 | card_mask |= (1 << 1); | 288 | card_mask |= MCT_PIN_ST_S2_CD_ST; |
256 | 289 | ||
257 | if (menelaus_hw->mmc_callback) | 290 | if (menelaus_hw->mmc_callback) |
258 | menelaus_hw->mmc_callback(menelaus_hw->mmc_callback_data, | 291 | menelaus_hw->mmc_callback(menelaus_hw->mmc_callback_data, |
@@ -277,14 +310,14 @@ int menelaus_set_mmc_opendrain(int slot, int enable) | |||
277 | val = ret; | 310 | val = ret; |
278 | if (slot == 1) { | 311 | if (slot == 1) { |
279 | if (enable) | 312 | if (enable) |
280 | val |= 1 << 2; | 313 | val |= MCT_CTRL1_S1_CMD_OD; |
281 | else | 314 | else |
282 | val &= ~(1 << 2); | 315 | val &= ~MCT_CTRL1_S1_CMD_OD; |
283 | } else { | 316 | } else { |
284 | if (enable) | 317 | if (enable) |
285 | val |= 1 << 3; | 318 | val |= MCT_CTRL1_S2_CMD_OD; |
286 | else | 319 | else |
287 | val &= ~(1 << 3); | 320 | val &= ~MCT_CTRL1_S2_CMD_OD; |
288 | } | 321 | } |
289 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL1, val); | 322 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL1, val); |
290 | mutex_unlock(&the_menelaus->lock); | 323 | mutex_unlock(&the_menelaus->lock); |
@@ -301,11 +334,11 @@ int menelaus_set_slot_sel(int enable) | |||
301 | ret = menelaus_read_reg(MENELAUS_GPIO_CTRL); | 334 | ret = menelaus_read_reg(MENELAUS_GPIO_CTRL); |
302 | if (ret < 0) | 335 | if (ret < 0) |
303 | goto out; | 336 | goto out; |
304 | ret |= 0x02; | 337 | ret |= GPIO2_DIR_INPUT; |
305 | if (enable) | 338 | if (enable) |
306 | ret |= 1 << 5; | 339 | ret |= GPIO_CTRL_SLOTSELEN; |
307 | else | 340 | else |
308 | ret &= ~(1 << 5); | 341 | ret &= ~GPIO_CTRL_SLOTSELEN; |
309 | ret = menelaus_write_reg(MENELAUS_GPIO_CTRL, ret); | 342 | ret = menelaus_write_reg(MENELAUS_GPIO_CTRL, ret); |
310 | out: | 343 | out: |
311 | mutex_unlock(&the_menelaus->lock); | 344 | mutex_unlock(&the_menelaus->lock); |
@@ -330,14 +363,14 @@ int menelaus_set_mmc_slot(int slot, int enable, int power, int cd_en) | |||
330 | val = ret; | 363 | val = ret; |
331 | if (slot == 1) { | 364 | if (slot == 1) { |
332 | if (cd_en) | 365 | if (cd_en) |
333 | val |= (1 << 4) | (1 << 6); | 366 | val |= MCT_CTRL2_S1CD_BUFEN | MCT_CTRL2_S1CD_DBEN; |
334 | else | 367 | else |
335 | val &= ~((1 << 4) | (1 << 6)); | 368 | val &= ~(MCT_CTRL2_S1CD_BUFEN | MCT_CTRL2_S1CD_DBEN); |
336 | } else { | 369 | } else { |
337 | if (cd_en) | 370 | if (cd_en) |
338 | val |= (1 << 5) | (1 << 7); | 371 | val |= MCT_CTRL2_S2CD_BUFEN | MCT_CTRL2_S2CD_BEN; |
339 | else | 372 | else |
340 | val &= ~((1 << 5) | (1 << 7)); | 373 | val &= ~(MCT_CTRL2_S2CD_BUFEN | MCT_CTRL2_S2CD_BEN); |
341 | } | 374 | } |
342 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, val); | 375 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, val); |
343 | if (ret < 0) | 376 | if (ret < 0) |
@@ -349,25 +382,25 @@ int menelaus_set_mmc_slot(int slot, int enable, int power, int cd_en) | |||
349 | val = ret; | 382 | val = ret; |
350 | if (slot == 1) { | 383 | if (slot == 1) { |
351 | if (enable) | 384 | if (enable) |
352 | val |= 1 << 0; | 385 | val |= MCT_CTRL3_SLOT1_EN; |
353 | else | 386 | else |
354 | val &= ~(1 << 0); | 387 | val &= ~MCT_CTRL3_SLOT1_EN; |
355 | } else { | 388 | } else { |
356 | int b; | 389 | int b; |
357 | 390 | ||
358 | if (enable) | 391 | if (enable) |
359 | ret |= 1 << 1; | 392 | val |= MCT_CTRL3_SLOT2_EN; |
360 | else | 393 | else |
361 | ret &= ~(1 << 1); | 394 | val &= ~MCT_CTRL3_SLOT2_EN; |
362 | b = menelaus_read_reg(MENELAUS_MCT_CTRL2); | 395 | b = menelaus_read_reg(MENELAUS_MCT_CTRL2); |
363 | b &= ~0x03; | 396 | b &= ~(MCT_CTRL2_VS2_SEL_D0 | MCT_CTRL2_VS2_SEL_D1); |
364 | b |= power; | 397 | b |= power; |
365 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, b); | 398 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, b); |
366 | if (ret < 0) | 399 | if (ret < 0) |
367 | goto out; | 400 | goto out; |
368 | } | 401 | } |
369 | /* Disable autonomous shutdown */ | 402 | /* Disable autonomous shutdown */ |
370 | val &= ~(0x03 << 2); | 403 | val &= ~(MCT_CTRL3_S1_AUTO_EN | MCT_CTRL3_S2_AUTO_EN); |
371 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL3, val); | 404 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL3, val); |
372 | out: | 405 | out: |
373 | mutex_unlock(&the_menelaus->lock); | 406 | mutex_unlock(&the_menelaus->lock); |
@@ -552,7 +585,7 @@ int menelaus_set_vcore_hw(unsigned int roof_mV, unsigned int floor_mV) | |||
552 | if (!the_menelaus->vcore_hw_mode) { | 585 | if (!the_menelaus->vcore_hw_mode) { |
553 | val = menelaus_read_reg(MENELAUS_VCORE_CTRL1); | 586 | val = menelaus_read_reg(MENELAUS_VCORE_CTRL1); |
554 | /* HW mode, turn OFF byte comparator */ | 587 | /* HW mode, turn OFF byte comparator */ |
555 | val |= ((1 << 7) | (1 << 5)); | 588 | val |= (VCORE_CTRL1_HW_NSW | VCORE_CTRL1_BYP_COMP); |
556 | ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val); | 589 | ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val); |
557 | the_menelaus->vcore_hw_mode = 1; | 590 | the_menelaus->vcore_hw_mode = 1; |
558 | } | 591 | } |
@@ -749,7 +782,7 @@ int menelaus_set_regulator_sleep(int enable, u32 val) | |||
749 | ret = menelaus_read_reg(MENELAUS_GPIO_CTRL); | 782 | ret = menelaus_read_reg(MENELAUS_GPIO_CTRL); |
750 | if (ret < 0) | 783 | if (ret < 0) |
751 | goto out; | 784 | goto out; |
752 | t = ((1 << 6) | 0x04); | 785 | t = (GPIO_CTRL_SLPCTLEN | GPIO3_DIR_INPUT); |
753 | if (enable) | 786 | if (enable) |
754 | ret |= t; | 787 | ret |= t; |
755 | else | 788 | else |
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 7dd76bceaae8..1823a57b7d8f 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c | |||
@@ -70,7 +70,9 @@ static int mfd_add_device(struct device *parent, int id, | |||
70 | goto fail_res; | 70 | goto fail_res; |
71 | } | 71 | } |
72 | 72 | ||
73 | platform_device_add_resources(pdev, res, cell->num_resources); | 73 | ret = platform_device_add_resources(pdev, res, cell->num_resources); |
74 | if (ret) | ||
75 | goto fail_res; | ||
74 | 76 | ||
75 | ret = platform_device_add(pdev); | 77 | ret = platform_device_add(pdev); |
76 | if (ret) | 78 | if (ret) |
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c new file mode 100644 index 000000000000..0754c5e91995 --- /dev/null +++ b/drivers/mfd/stmpe.c | |||
@@ -0,0 +1,985 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
6 | */ | ||
7 | |||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/irq.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/mfd/core.h> | ||
15 | #include <linux/mfd/stmpe.h> | ||
16 | #include "stmpe.h" | ||
17 | |||
18 | static int __stmpe_enable(struct stmpe *stmpe, unsigned int blocks) | ||
19 | { | ||
20 | return stmpe->variant->enable(stmpe, blocks, true); | ||
21 | } | ||
22 | |||
23 | static int __stmpe_disable(struct stmpe *stmpe, unsigned int blocks) | ||
24 | { | ||
25 | return stmpe->variant->enable(stmpe, blocks, false); | ||
26 | } | ||
27 | |||
28 | static int __stmpe_reg_read(struct stmpe *stmpe, u8 reg) | ||
29 | { | ||
30 | int ret; | ||
31 | |||
32 | ret = i2c_smbus_read_byte_data(stmpe->i2c, reg); | ||
33 | if (ret < 0) | ||
34 | dev_err(stmpe->dev, "failed to read reg %#x: %d\n", | ||
35 | reg, ret); | ||
36 | |||
37 | dev_vdbg(stmpe->dev, "rd: reg %#x => data %#x\n", reg, ret); | ||
38 | |||
39 | return ret; | ||
40 | } | ||
41 | |||
42 | static int __stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 val) | ||
43 | { | ||
44 | int ret; | ||
45 | |||
46 | dev_vdbg(stmpe->dev, "wr: reg %#x <= %#x\n", reg, val); | ||
47 | |||
48 | ret = i2c_smbus_write_byte_data(stmpe->i2c, reg, val); | ||
49 | if (ret < 0) | ||
50 | dev_err(stmpe->dev, "failed to write reg %#x: %d\n", | ||
51 | reg, ret); | ||
52 | |||
53 | return ret; | ||
54 | } | ||
55 | |||
56 | static int __stmpe_set_bits(struct stmpe *stmpe, u8 reg, u8 mask, u8 val) | ||
57 | { | ||
58 | int ret; | ||
59 | |||
60 | ret = __stmpe_reg_read(stmpe, reg); | ||
61 | if (ret < 0) | ||
62 | return ret; | ||
63 | |||
64 | ret &= ~mask; | ||
65 | ret |= val; | ||
66 | |||
67 | return __stmpe_reg_write(stmpe, reg, ret); | ||
68 | } | ||
69 | |||
70 | static int __stmpe_block_read(struct stmpe *stmpe, u8 reg, u8 length, | ||
71 | u8 *values) | ||
72 | { | ||
73 | int ret; | ||
74 | |||
75 | ret = i2c_smbus_read_i2c_block_data(stmpe->i2c, reg, length, values); | ||
76 | if (ret < 0) | ||
77 | dev_err(stmpe->dev, "failed to read regs %#x: %d\n", | ||
78 | reg, ret); | ||
79 | |||
80 | dev_vdbg(stmpe->dev, "rd: reg %#x (%d) => ret %#x\n", reg, length, ret); | ||
81 | stmpe_dump_bytes("stmpe rd: ", values, length); | ||
82 | |||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | static int __stmpe_block_write(struct stmpe *stmpe, u8 reg, u8 length, | ||
87 | const u8 *values) | ||
88 | { | ||
89 | int ret; | ||
90 | |||
91 | dev_vdbg(stmpe->dev, "wr: regs %#x (%d)\n", reg, length); | ||
92 | stmpe_dump_bytes("stmpe wr: ", values, length); | ||
93 | |||
94 | ret = i2c_smbus_write_i2c_block_data(stmpe->i2c, reg, length, | ||
95 | values); | ||
96 | if (ret < 0) | ||
97 | dev_err(stmpe->dev, "failed to write regs %#x: %d\n", | ||
98 | reg, ret); | ||
99 | |||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | /** | ||
104 | * stmpe_enable - enable blocks on an STMPE device | ||
105 | * @stmpe: Device to work on | ||
106 | * @blocks: Mask of blocks (enum stmpe_block values) to enable | ||
107 | */ | ||
108 | int stmpe_enable(struct stmpe *stmpe, unsigned int blocks) | ||
109 | { | ||
110 | int ret; | ||
111 | |||
112 | mutex_lock(&stmpe->lock); | ||
113 | ret = __stmpe_enable(stmpe, blocks); | ||
114 | mutex_unlock(&stmpe->lock); | ||
115 | |||
116 | return ret; | ||
117 | } | ||
118 | EXPORT_SYMBOL_GPL(stmpe_enable); | ||
119 | |||
120 | /** | ||
121 | * stmpe_disable - disable blocks on an STMPE device | ||
122 | * @stmpe: Device to work on | ||
123 | * @blocks: Mask of blocks (enum stmpe_block values) to enable | ||
124 | */ | ||
125 | int stmpe_disable(struct stmpe *stmpe, unsigned int blocks) | ||
126 | { | ||
127 | int ret; | ||
128 | |||
129 | mutex_lock(&stmpe->lock); | ||
130 | ret = __stmpe_disable(stmpe, blocks); | ||
131 | mutex_unlock(&stmpe->lock); | ||
132 | |||
133 | return ret; | ||
134 | } | ||
135 | EXPORT_SYMBOL_GPL(stmpe_disable); | ||
136 | |||
137 | /** | ||
138 | * stmpe_reg_read() - read a single STMPE register | ||
139 | * @stmpe: Device to read from | ||
140 | * @reg: Register to read | ||
141 | */ | ||
142 | int stmpe_reg_read(struct stmpe *stmpe, u8 reg) | ||
143 | { | ||
144 | int ret; | ||
145 | |||
146 | mutex_lock(&stmpe->lock); | ||
147 | ret = __stmpe_reg_read(stmpe, reg); | ||
148 | mutex_unlock(&stmpe->lock); | ||
149 | |||
150 | return ret; | ||
151 | } | ||
152 | EXPORT_SYMBOL_GPL(stmpe_reg_read); | ||
153 | |||
154 | /** | ||
155 | * stmpe_reg_write() - write a single STMPE register | ||
156 | * @stmpe: Device to write to | ||
157 | * @reg: Register to write | ||
158 | * @val: Value to write | ||
159 | */ | ||
160 | int stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 val) | ||
161 | { | ||
162 | int ret; | ||
163 | |||
164 | mutex_lock(&stmpe->lock); | ||
165 | ret = __stmpe_reg_write(stmpe, reg, val); | ||
166 | mutex_unlock(&stmpe->lock); | ||
167 | |||
168 | return ret; | ||
169 | } | ||
170 | EXPORT_SYMBOL_GPL(stmpe_reg_write); | ||
171 | |||
172 | /** | ||
173 | * stmpe_set_bits() - set the value of a bitfield in a STMPE register | ||
174 | * @stmpe: Device to write to | ||
175 | * @reg: Register to write | ||
176 | * @mask: Mask of bits to set | ||
177 | * @val: Value to set | ||
178 | */ | ||
179 | int stmpe_set_bits(struct stmpe *stmpe, u8 reg, u8 mask, u8 val) | ||
180 | { | ||
181 | int ret; | ||
182 | |||
183 | mutex_lock(&stmpe->lock); | ||
184 | ret = __stmpe_set_bits(stmpe, reg, mask, val); | ||
185 | mutex_unlock(&stmpe->lock); | ||
186 | |||
187 | return ret; | ||
188 | } | ||
189 | EXPORT_SYMBOL_GPL(stmpe_set_bits); | ||
190 | |||
191 | /** | ||
192 | * stmpe_block_read() - read multiple STMPE registers | ||
193 | * @stmpe: Device to read from | ||
194 | * @reg: First register | ||
195 | * @length: Number of registers | ||
196 | * @values: Buffer to write to | ||
197 | */ | ||
198 | int stmpe_block_read(struct stmpe *stmpe, u8 reg, u8 length, u8 *values) | ||
199 | { | ||
200 | int ret; | ||
201 | |||
202 | mutex_lock(&stmpe->lock); | ||
203 | ret = __stmpe_block_read(stmpe, reg, length, values); | ||
204 | mutex_unlock(&stmpe->lock); | ||
205 | |||
206 | return ret; | ||
207 | } | ||
208 | EXPORT_SYMBOL_GPL(stmpe_block_read); | ||
209 | |||
210 | /** | ||
211 | * stmpe_block_write() - write multiple STMPE registers | ||
212 | * @stmpe: Device to write to | ||
213 | * @reg: First register | ||
214 | * @length: Number of registers | ||
215 | * @values: Values to write | ||
216 | */ | ||
217 | int stmpe_block_write(struct stmpe *stmpe, u8 reg, u8 length, | ||
218 | const u8 *values) | ||
219 | { | ||
220 | int ret; | ||
221 | |||
222 | mutex_lock(&stmpe->lock); | ||
223 | ret = __stmpe_block_write(stmpe, reg, length, values); | ||
224 | mutex_unlock(&stmpe->lock); | ||
225 | |||
226 | return ret; | ||
227 | } | ||
228 | EXPORT_SYMBOL_GPL(stmpe_block_write); | ||
229 | |||
230 | /** | ||
231 | * stmpe_set_altfunc: set the alternate function for STMPE pins | ||
232 | * @stmpe: Device to configure | ||
233 | * @pins: Bitmask of pins to affect | ||
234 | * @block: block to enable alternate functions for | ||
235 | * | ||
236 | * @pins is assumed to have a bit set for each of the bits whose alternate | ||
237 | * function is to be changed, numbered according to the GPIOXY numbers. | ||
238 | * | ||
239 | * If the GPIO module is not enabled, this function automatically enables it in | ||
240 | * order to perform the change. | ||
241 | */ | ||
242 | int stmpe_set_altfunc(struct stmpe *stmpe, u32 pins, enum stmpe_block block) | ||
243 | { | ||
244 | struct stmpe_variant_info *variant = stmpe->variant; | ||
245 | u8 regaddr = stmpe->regs[STMPE_IDX_GPAFR_U_MSB]; | ||
246 | int af_bits = variant->af_bits; | ||
247 | int numregs = DIV_ROUND_UP(stmpe->num_gpios * af_bits, 8); | ||
248 | int afperreg = 8 / af_bits; | ||
249 | int mask = (1 << af_bits) - 1; | ||
250 | u8 regs[numregs]; | ||
251 | int af; | ||
252 | int ret; | ||
253 | |||
254 | mutex_lock(&stmpe->lock); | ||
255 | |||
256 | ret = __stmpe_enable(stmpe, STMPE_BLOCK_GPIO); | ||
257 | if (ret < 0) | ||
258 | goto out; | ||
259 | |||
260 | ret = __stmpe_block_read(stmpe, regaddr, numregs, regs); | ||
261 | if (ret < 0) | ||
262 | goto out; | ||
263 | |||
264 | af = variant->get_altfunc(stmpe, block); | ||
265 | |||
266 | while (pins) { | ||
267 | int pin = __ffs(pins); | ||
268 | int regoffset = numregs - (pin / afperreg) - 1; | ||
269 | int pos = (pin % afperreg) * (8 / afperreg); | ||
270 | |||
271 | regs[regoffset] &= ~(mask << pos); | ||
272 | regs[regoffset] |= af << pos; | ||
273 | |||
274 | pins &= ~(1 << pin); | ||
275 | } | ||
276 | |||
277 | ret = __stmpe_block_write(stmpe, regaddr, numregs, regs); | ||
278 | |||
279 | out: | ||
280 | mutex_unlock(&stmpe->lock); | ||
281 | return ret; | ||
282 | } | ||
283 | EXPORT_SYMBOL_GPL(stmpe_set_altfunc); | ||
284 | |||
285 | /* | ||
286 | * GPIO (all variants) | ||
287 | */ | ||
288 | |||
289 | static struct resource stmpe_gpio_resources[] = { | ||
290 | /* Start and end filled dynamically */ | ||
291 | { | ||
292 | .flags = IORESOURCE_IRQ, | ||
293 | }, | ||
294 | }; | ||
295 | |||
296 | static struct mfd_cell stmpe_gpio_cell = { | ||
297 | .name = "stmpe-gpio", | ||
298 | .resources = stmpe_gpio_resources, | ||
299 | .num_resources = ARRAY_SIZE(stmpe_gpio_resources), | ||
300 | }; | ||
301 | |||
302 | /* | ||
303 | * Keypad (1601, 2401, 2403) | ||
304 | */ | ||
305 | |||
306 | static struct resource stmpe_keypad_resources[] = { | ||
307 | { | ||
308 | .name = "KEYPAD", | ||
309 | .start = 0, | ||
310 | .end = 0, | ||
311 | .flags = IORESOURCE_IRQ, | ||
312 | }, | ||
313 | { | ||
314 | .name = "KEYPAD_OVER", | ||
315 | .start = 1, | ||
316 | .end = 1, | ||
317 | .flags = IORESOURCE_IRQ, | ||
318 | }, | ||
319 | }; | ||
320 | |||
321 | static struct mfd_cell stmpe_keypad_cell = { | ||
322 | .name = "stmpe-keypad", | ||
323 | .resources = stmpe_keypad_resources, | ||
324 | .num_resources = ARRAY_SIZE(stmpe_keypad_resources), | ||
325 | }; | ||
326 | |||
327 | /* | ||
328 | * Touchscreen (STMPE811) | ||
329 | */ | ||
330 | |||
331 | static struct resource stmpe_ts_resources[] = { | ||
332 | { | ||
333 | .name = "TOUCH_DET", | ||
334 | .start = 0, | ||
335 | .end = 0, | ||
336 | .flags = IORESOURCE_IRQ, | ||
337 | }, | ||
338 | { | ||
339 | .name = "FIFO_TH", | ||
340 | .start = 1, | ||
341 | .end = 1, | ||
342 | .flags = IORESOURCE_IRQ, | ||
343 | }, | ||
344 | }; | ||
345 | |||
346 | static struct mfd_cell stmpe_ts_cell = { | ||
347 | .name = "stmpe-ts", | ||
348 | .resources = stmpe_ts_resources, | ||
349 | .num_resources = ARRAY_SIZE(stmpe_ts_resources), | ||
350 | }; | ||
351 | |||
352 | /* | ||
353 | * STMPE811 | ||
354 | */ | ||
355 | |||
356 | static const u8 stmpe811_regs[] = { | ||
357 | [STMPE_IDX_CHIP_ID] = STMPE811_REG_CHIP_ID, | ||
358 | [STMPE_IDX_ICR_LSB] = STMPE811_REG_INT_CTRL, | ||
359 | [STMPE_IDX_IER_LSB] = STMPE811_REG_INT_EN, | ||
360 | [STMPE_IDX_ISR_MSB] = STMPE811_REG_INT_STA, | ||
361 | [STMPE_IDX_GPMR_LSB] = STMPE811_REG_GPIO_MP_STA, | ||
362 | [STMPE_IDX_GPSR_LSB] = STMPE811_REG_GPIO_SET_PIN, | ||
363 | [STMPE_IDX_GPCR_LSB] = STMPE811_REG_GPIO_CLR_PIN, | ||
364 | [STMPE_IDX_GPDR_LSB] = STMPE811_REG_GPIO_DIR, | ||
365 | [STMPE_IDX_GPRER_LSB] = STMPE811_REG_GPIO_RE, | ||
366 | [STMPE_IDX_GPFER_LSB] = STMPE811_REG_GPIO_FE, | ||
367 | [STMPE_IDX_GPAFR_U_MSB] = STMPE811_REG_GPIO_AF, | ||
368 | [STMPE_IDX_IEGPIOR_LSB] = STMPE811_REG_GPIO_INT_EN, | ||
369 | [STMPE_IDX_ISGPIOR_MSB] = STMPE811_REG_GPIO_INT_STA, | ||
370 | [STMPE_IDX_GPEDR_MSB] = STMPE811_REG_GPIO_ED, | ||
371 | }; | ||
372 | |||
373 | static struct stmpe_variant_block stmpe811_blocks[] = { | ||
374 | { | ||
375 | .cell = &stmpe_gpio_cell, | ||
376 | .irq = STMPE811_IRQ_GPIOC, | ||
377 | .block = STMPE_BLOCK_GPIO, | ||
378 | }, | ||
379 | { | ||
380 | .cell = &stmpe_ts_cell, | ||
381 | .irq = STMPE811_IRQ_TOUCH_DET, | ||
382 | .block = STMPE_BLOCK_TOUCHSCREEN, | ||
383 | }, | ||
384 | }; | ||
385 | |||
386 | static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks, | ||
387 | bool enable) | ||
388 | { | ||
389 | unsigned int mask = 0; | ||
390 | |||
391 | if (blocks & STMPE_BLOCK_GPIO) | ||
392 | mask |= STMPE811_SYS_CTRL2_GPIO_OFF; | ||
393 | |||
394 | if (blocks & STMPE_BLOCK_ADC) | ||
395 | mask |= STMPE811_SYS_CTRL2_ADC_OFF; | ||
396 | |||
397 | if (blocks & STMPE_BLOCK_TOUCHSCREEN) | ||
398 | mask |= STMPE811_SYS_CTRL2_TSC_OFF; | ||
399 | |||
400 | return __stmpe_set_bits(stmpe, STMPE811_REG_SYS_CTRL2, mask, | ||
401 | enable ? 0 : mask); | ||
402 | } | ||
403 | |||
404 | static int stmpe811_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) | ||
405 | { | ||
406 | /* 0 for touchscreen, 1 for GPIO */ | ||
407 | return block != STMPE_BLOCK_TOUCHSCREEN; | ||
408 | } | ||
409 | |||
410 | static struct stmpe_variant_info stmpe811 = { | ||
411 | .name = "stmpe811", | ||
412 | .id_val = 0x0811, | ||
413 | .id_mask = 0xffff, | ||
414 | .num_gpios = 8, | ||
415 | .af_bits = 1, | ||
416 | .regs = stmpe811_regs, | ||
417 | .blocks = stmpe811_blocks, | ||
418 | .num_blocks = ARRAY_SIZE(stmpe811_blocks), | ||
419 | .num_irqs = STMPE811_NR_INTERNAL_IRQS, | ||
420 | .enable = stmpe811_enable, | ||
421 | .get_altfunc = stmpe811_get_altfunc, | ||
422 | }; | ||
423 | |||
424 | /* | ||
425 | * STMPE1601 | ||
426 | */ | ||
427 | |||
428 | static const u8 stmpe1601_regs[] = { | ||
429 | [STMPE_IDX_CHIP_ID] = STMPE1601_REG_CHIP_ID, | ||
430 | [STMPE_IDX_ICR_LSB] = STMPE1601_REG_ICR_LSB, | ||
431 | [STMPE_IDX_IER_LSB] = STMPE1601_REG_IER_LSB, | ||
432 | [STMPE_IDX_ISR_MSB] = STMPE1601_REG_ISR_MSB, | ||
433 | [STMPE_IDX_GPMR_LSB] = STMPE1601_REG_GPIO_MP_LSB, | ||
434 | [STMPE_IDX_GPSR_LSB] = STMPE1601_REG_GPIO_SET_LSB, | ||
435 | [STMPE_IDX_GPCR_LSB] = STMPE1601_REG_GPIO_CLR_LSB, | ||
436 | [STMPE_IDX_GPDR_LSB] = STMPE1601_REG_GPIO_SET_DIR_LSB, | ||
437 | [STMPE_IDX_GPRER_LSB] = STMPE1601_REG_GPIO_RE_LSB, | ||
438 | [STMPE_IDX_GPFER_LSB] = STMPE1601_REG_GPIO_FE_LSB, | ||
439 | [STMPE_IDX_GPAFR_U_MSB] = STMPE1601_REG_GPIO_AF_U_MSB, | ||
440 | [STMPE_IDX_IEGPIOR_LSB] = STMPE1601_REG_INT_EN_GPIO_MASK_LSB, | ||
441 | [STMPE_IDX_ISGPIOR_MSB] = STMPE1601_REG_INT_STA_GPIO_MSB, | ||
442 | [STMPE_IDX_GPEDR_MSB] = STMPE1601_REG_GPIO_ED_MSB, | ||
443 | }; | ||
444 | |||
445 | static struct stmpe_variant_block stmpe1601_blocks[] = { | ||
446 | { | ||
447 | .cell = &stmpe_gpio_cell, | ||
448 | .irq = STMPE24XX_IRQ_GPIOC, | ||
449 | .block = STMPE_BLOCK_GPIO, | ||
450 | }, | ||
451 | { | ||
452 | .cell = &stmpe_keypad_cell, | ||
453 | .irq = STMPE24XX_IRQ_KEYPAD, | ||
454 | .block = STMPE_BLOCK_KEYPAD, | ||
455 | }, | ||
456 | }; | ||
457 | |||
458 | /* supported autosleep timeout delay (in msecs) */ | ||
459 | static const int stmpe_autosleep_delay[] = { | ||
460 | 4, 16, 32, 64, 128, 256, 512, 1024, | ||
461 | }; | ||
462 | |||
463 | static int stmpe_round_timeout(int timeout) | ||
464 | { | ||
465 | int i; | ||
466 | |||
467 | for (i = 0; i < ARRAY_SIZE(stmpe_autosleep_delay); i++) { | ||
468 | if (stmpe_autosleep_delay[i] >= timeout) | ||
469 | return i; | ||
470 | } | ||
471 | |||
472 | /* | ||
473 | * requests for delays longer than supported should not return the | ||
474 | * longest supported delay | ||
475 | */ | ||
476 | return -EINVAL; | ||
477 | } | ||
478 | |||
479 | static int stmpe_autosleep(struct stmpe *stmpe, int autosleep_timeout) | ||
480 | { | ||
481 | int ret; | ||
482 | |||
483 | if (!stmpe->variant->enable_autosleep) | ||
484 | return -ENOSYS; | ||
485 | |||
486 | mutex_lock(&stmpe->lock); | ||
487 | ret = stmpe->variant->enable_autosleep(stmpe, autosleep_timeout); | ||
488 | mutex_unlock(&stmpe->lock); | ||
489 | |||
490 | return ret; | ||
491 | } | ||
492 | |||
493 | /* | ||
494 | * Both stmpe 1601/2403 support same layout for autosleep | ||
495 | */ | ||
496 | static int stmpe1601_autosleep(struct stmpe *stmpe, | ||
497 | int autosleep_timeout) | ||
498 | { | ||
499 | int ret, timeout; | ||
500 | |||
501 | /* choose the best available timeout */ | ||
502 | timeout = stmpe_round_timeout(autosleep_timeout); | ||
503 | if (timeout < 0) { | ||
504 | dev_err(stmpe->dev, "invalid timeout\n"); | ||
505 | return timeout; | ||
506 | } | ||
507 | |||
508 | ret = __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL2, | ||
509 | STMPE1601_AUTOSLEEP_TIMEOUT_MASK, | ||
510 | timeout); | ||
511 | if (ret < 0) | ||
512 | return ret; | ||
513 | |||
514 | return __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL2, | ||
515 | STPME1601_AUTOSLEEP_ENABLE, | ||
516 | STPME1601_AUTOSLEEP_ENABLE); | ||
517 | } | ||
518 | |||
519 | static int stmpe1601_enable(struct stmpe *stmpe, unsigned int blocks, | ||
520 | bool enable) | ||
521 | { | ||
522 | unsigned int mask = 0; | ||
523 | |||
524 | if (blocks & STMPE_BLOCK_GPIO) | ||
525 | mask |= STMPE1601_SYS_CTRL_ENABLE_GPIO; | ||
526 | |||
527 | if (blocks & STMPE_BLOCK_KEYPAD) | ||
528 | mask |= STMPE1601_SYS_CTRL_ENABLE_KPC; | ||
529 | |||
530 | return __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL, mask, | ||
531 | enable ? mask : 0); | ||
532 | } | ||
533 | |||
534 | static int stmpe1601_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) | ||
535 | { | ||
536 | switch (block) { | ||
537 | case STMPE_BLOCK_PWM: | ||
538 | return 2; | ||
539 | |||
540 | case STMPE_BLOCK_KEYPAD: | ||
541 | return 1; | ||
542 | |||
543 | case STMPE_BLOCK_GPIO: | ||
544 | default: | ||
545 | return 0; | ||
546 | } | ||
547 | } | ||
548 | |||
549 | static struct stmpe_variant_info stmpe1601 = { | ||
550 | .name = "stmpe1601", | ||
551 | .id_val = 0x0210, | ||
552 | .id_mask = 0xfff0, /* at least 0x0210 and 0x0212 */ | ||
553 | .num_gpios = 16, | ||
554 | .af_bits = 2, | ||
555 | .regs = stmpe1601_regs, | ||
556 | .blocks = stmpe1601_blocks, | ||
557 | .num_blocks = ARRAY_SIZE(stmpe1601_blocks), | ||
558 | .num_irqs = STMPE1601_NR_INTERNAL_IRQS, | ||
559 | .enable = stmpe1601_enable, | ||
560 | .get_altfunc = stmpe1601_get_altfunc, | ||
561 | .enable_autosleep = stmpe1601_autosleep, | ||
562 | }; | ||
563 | |||
564 | /* | ||
565 | * STMPE24XX | ||
566 | */ | ||
567 | |||
568 | static const u8 stmpe24xx_regs[] = { | ||
569 | [STMPE_IDX_CHIP_ID] = STMPE24XX_REG_CHIP_ID, | ||
570 | [STMPE_IDX_ICR_LSB] = STMPE24XX_REG_ICR_LSB, | ||
571 | [STMPE_IDX_IER_LSB] = STMPE24XX_REG_IER_LSB, | ||
572 | [STMPE_IDX_ISR_MSB] = STMPE24XX_REG_ISR_MSB, | ||
573 | [STMPE_IDX_GPMR_LSB] = STMPE24XX_REG_GPMR_LSB, | ||
574 | [STMPE_IDX_GPSR_LSB] = STMPE24XX_REG_GPSR_LSB, | ||
575 | [STMPE_IDX_GPCR_LSB] = STMPE24XX_REG_GPCR_LSB, | ||
576 | [STMPE_IDX_GPDR_LSB] = STMPE24XX_REG_GPDR_LSB, | ||
577 | [STMPE_IDX_GPRER_LSB] = STMPE24XX_REG_GPRER_LSB, | ||
578 | [STMPE_IDX_GPFER_LSB] = STMPE24XX_REG_GPFER_LSB, | ||
579 | [STMPE_IDX_GPAFR_U_MSB] = STMPE24XX_REG_GPAFR_U_MSB, | ||
580 | [STMPE_IDX_IEGPIOR_LSB] = STMPE24XX_REG_IEGPIOR_LSB, | ||
581 | [STMPE_IDX_ISGPIOR_MSB] = STMPE24XX_REG_ISGPIOR_MSB, | ||
582 | [STMPE_IDX_GPEDR_MSB] = STMPE24XX_REG_GPEDR_MSB, | ||
583 | }; | ||
584 | |||
585 | static struct stmpe_variant_block stmpe24xx_blocks[] = { | ||
586 | { | ||
587 | .cell = &stmpe_gpio_cell, | ||
588 | .irq = STMPE24XX_IRQ_GPIOC, | ||
589 | .block = STMPE_BLOCK_GPIO, | ||
590 | }, | ||
591 | { | ||
592 | .cell = &stmpe_keypad_cell, | ||
593 | .irq = STMPE24XX_IRQ_KEYPAD, | ||
594 | .block = STMPE_BLOCK_KEYPAD, | ||
595 | }, | ||
596 | }; | ||
597 | |||
598 | static int stmpe24xx_enable(struct stmpe *stmpe, unsigned int blocks, | ||
599 | bool enable) | ||
600 | { | ||
601 | unsigned int mask = 0; | ||
602 | |||
603 | if (blocks & STMPE_BLOCK_GPIO) | ||
604 | mask |= STMPE24XX_SYS_CTRL_ENABLE_GPIO; | ||
605 | |||
606 | if (blocks & STMPE_BLOCK_KEYPAD) | ||
607 | mask |= STMPE24XX_SYS_CTRL_ENABLE_KPC; | ||
608 | |||
609 | return __stmpe_set_bits(stmpe, STMPE24XX_REG_SYS_CTRL, mask, | ||
610 | enable ? mask : 0); | ||
611 | } | ||
612 | |||
613 | static int stmpe24xx_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) | ||
614 | { | ||
615 | switch (block) { | ||
616 | case STMPE_BLOCK_ROTATOR: | ||
617 | return 2; | ||
618 | |||
619 | case STMPE_BLOCK_KEYPAD: | ||
620 | return 1; | ||
621 | |||
622 | case STMPE_BLOCK_GPIO: | ||
623 | default: | ||
624 | return 0; | ||
625 | } | ||
626 | } | ||
627 | |||
628 | static struct stmpe_variant_info stmpe2401 = { | ||
629 | .name = "stmpe2401", | ||
630 | .id_val = 0x0101, | ||
631 | .id_mask = 0xffff, | ||
632 | .num_gpios = 24, | ||
633 | .af_bits = 2, | ||
634 | .regs = stmpe24xx_regs, | ||
635 | .blocks = stmpe24xx_blocks, | ||
636 | .num_blocks = ARRAY_SIZE(stmpe24xx_blocks), | ||
637 | .num_irqs = STMPE24XX_NR_INTERNAL_IRQS, | ||
638 | .enable = stmpe24xx_enable, | ||
639 | .get_altfunc = stmpe24xx_get_altfunc, | ||
640 | }; | ||
641 | |||
642 | static struct stmpe_variant_info stmpe2403 = { | ||
643 | .name = "stmpe2403", | ||
644 | .id_val = 0x0120, | ||
645 | .id_mask = 0xffff, | ||
646 | .num_gpios = 24, | ||
647 | .af_bits = 2, | ||
648 | .regs = stmpe24xx_regs, | ||
649 | .blocks = stmpe24xx_blocks, | ||
650 | .num_blocks = ARRAY_SIZE(stmpe24xx_blocks), | ||
651 | .num_irqs = STMPE24XX_NR_INTERNAL_IRQS, | ||
652 | .enable = stmpe24xx_enable, | ||
653 | .get_altfunc = stmpe24xx_get_altfunc, | ||
654 | .enable_autosleep = stmpe1601_autosleep, /* same as stmpe1601 */ | ||
655 | }; | ||
656 | |||
657 | static struct stmpe_variant_info *stmpe_variant_info[] = { | ||
658 | [STMPE811] = &stmpe811, | ||
659 | [STMPE1601] = &stmpe1601, | ||
660 | [STMPE2401] = &stmpe2401, | ||
661 | [STMPE2403] = &stmpe2403, | ||
662 | }; | ||
663 | |||
664 | static irqreturn_t stmpe_irq(int irq, void *data) | ||
665 | { | ||
666 | struct stmpe *stmpe = data; | ||
667 | struct stmpe_variant_info *variant = stmpe->variant; | ||
668 | int num = DIV_ROUND_UP(variant->num_irqs, 8); | ||
669 | u8 israddr = stmpe->regs[STMPE_IDX_ISR_MSB]; | ||
670 | u8 isr[num]; | ||
671 | int ret; | ||
672 | int i; | ||
673 | |||
674 | ret = stmpe_block_read(stmpe, israddr, num, isr); | ||
675 | if (ret < 0) | ||
676 | return IRQ_NONE; | ||
677 | |||
678 | for (i = 0; i < num; i++) { | ||
679 | int bank = num - i - 1; | ||
680 | u8 status = isr[i]; | ||
681 | u8 clear; | ||
682 | |||
683 | status &= stmpe->ier[bank]; | ||
684 | if (!status) | ||
685 | continue; | ||
686 | |||
687 | clear = status; | ||
688 | while (status) { | ||
689 | int bit = __ffs(status); | ||
690 | int line = bank * 8 + bit; | ||
691 | |||
692 | handle_nested_irq(stmpe->irq_base + line); | ||
693 | status &= ~(1 << bit); | ||
694 | } | ||
695 | |||
696 | stmpe_reg_write(stmpe, israddr + i, clear); | ||
697 | } | ||
698 | |||
699 | return IRQ_HANDLED; | ||
700 | } | ||
701 | |||
702 | static void stmpe_irq_lock(unsigned int irq) | ||
703 | { | ||
704 | struct stmpe *stmpe = get_irq_chip_data(irq); | ||
705 | |||
706 | mutex_lock(&stmpe->irq_lock); | ||
707 | } | ||
708 | |||
709 | static void stmpe_irq_sync_unlock(unsigned int irq) | ||
710 | { | ||
711 | struct stmpe *stmpe = get_irq_chip_data(irq); | ||
712 | struct stmpe_variant_info *variant = stmpe->variant; | ||
713 | int num = DIV_ROUND_UP(variant->num_irqs, 8); | ||
714 | int i; | ||
715 | |||
716 | for (i = 0; i < num; i++) { | ||
717 | u8 new = stmpe->ier[i]; | ||
718 | u8 old = stmpe->oldier[i]; | ||
719 | |||
720 | if (new == old) | ||
721 | continue; | ||
722 | |||
723 | stmpe->oldier[i] = new; | ||
724 | stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_IER_LSB] - i, new); | ||
725 | } | ||
726 | |||
727 | mutex_unlock(&stmpe->irq_lock); | ||
728 | } | ||
729 | |||
730 | static void stmpe_irq_mask(unsigned int irq) | ||
731 | { | ||
732 | struct stmpe *stmpe = get_irq_chip_data(irq); | ||
733 | int offset = irq - stmpe->irq_base; | ||
734 | int regoffset = offset / 8; | ||
735 | int mask = 1 << (offset % 8); | ||
736 | |||
737 | stmpe->ier[regoffset] &= ~mask; | ||
738 | } | ||
739 | |||
740 | static void stmpe_irq_unmask(unsigned int irq) | ||
741 | { | ||
742 | struct stmpe *stmpe = get_irq_chip_data(irq); | ||
743 | int offset = irq - stmpe->irq_base; | ||
744 | int regoffset = offset / 8; | ||
745 | int mask = 1 << (offset % 8); | ||
746 | |||
747 | stmpe->ier[regoffset] |= mask; | ||
748 | } | ||
749 | |||
750 | static struct irq_chip stmpe_irq_chip = { | ||
751 | .name = "stmpe", | ||
752 | .bus_lock = stmpe_irq_lock, | ||
753 | .bus_sync_unlock = stmpe_irq_sync_unlock, | ||
754 | .mask = stmpe_irq_mask, | ||
755 | .unmask = stmpe_irq_unmask, | ||
756 | }; | ||
757 | |||
758 | static int __devinit stmpe_irq_init(struct stmpe *stmpe) | ||
759 | { | ||
760 | int num_irqs = stmpe->variant->num_irqs; | ||
761 | int base = stmpe->irq_base; | ||
762 | int irq; | ||
763 | |||
764 | for (irq = base; irq < base + num_irqs; irq++) { | ||
765 | set_irq_chip_data(irq, stmpe); | ||
766 | set_irq_chip_and_handler(irq, &stmpe_irq_chip, | ||
767 | handle_edge_irq); | ||
768 | set_irq_nested_thread(irq, 1); | ||
769 | #ifdef CONFIG_ARM | ||
770 | set_irq_flags(irq, IRQF_VALID); | ||
771 | #else | ||
772 | set_irq_noprobe(irq); | ||
773 | #endif | ||
774 | } | ||
775 | |||
776 | return 0; | ||
777 | } | ||
778 | |||
779 | static void stmpe_irq_remove(struct stmpe *stmpe) | ||
780 | { | ||
781 | int num_irqs = stmpe->variant->num_irqs; | ||
782 | int base = stmpe->irq_base; | ||
783 | int irq; | ||
784 | |||
785 | for (irq = base; irq < base + num_irqs; irq++) { | ||
786 | #ifdef CONFIG_ARM | ||
787 | set_irq_flags(irq, 0); | ||
788 | #endif | ||
789 | set_irq_chip_and_handler(irq, NULL, NULL); | ||
790 | set_irq_chip_data(irq, NULL); | ||
791 | } | ||
792 | } | ||
793 | |||
794 | static int __devinit stmpe_chip_init(struct stmpe *stmpe) | ||
795 | { | ||
796 | unsigned int irq_trigger = stmpe->pdata->irq_trigger; | ||
797 | int autosleep_timeout = stmpe->pdata->autosleep_timeout; | ||
798 | struct stmpe_variant_info *variant = stmpe->variant; | ||
799 | u8 icr = STMPE_ICR_LSB_GIM; | ||
800 | unsigned int id; | ||
801 | u8 data[2]; | ||
802 | int ret; | ||
803 | |||
804 | ret = stmpe_block_read(stmpe, stmpe->regs[STMPE_IDX_CHIP_ID], | ||
805 | ARRAY_SIZE(data), data); | ||
806 | if (ret < 0) | ||
807 | return ret; | ||
808 | |||
809 | id = (data[0] << 8) | data[1]; | ||
810 | if ((id & variant->id_mask) != variant->id_val) { | ||
811 | dev_err(stmpe->dev, "unknown chip id: %#x\n", id); | ||
812 | return -EINVAL; | ||
813 | } | ||
814 | |||
815 | dev_info(stmpe->dev, "%s detected, chip id: %#x\n", variant->name, id); | ||
816 | |||
817 | /* Disable all modules -- subdrivers should enable what they need. */ | ||
818 | ret = stmpe_disable(stmpe, ~0); | ||
819 | if (ret) | ||
820 | return ret; | ||
821 | |||
822 | if (irq_trigger == IRQF_TRIGGER_FALLING || | ||
823 | irq_trigger == IRQF_TRIGGER_RISING) | ||
824 | icr |= STMPE_ICR_LSB_EDGE; | ||
825 | |||
826 | if (irq_trigger == IRQF_TRIGGER_RISING || | ||
827 | irq_trigger == IRQF_TRIGGER_HIGH) | ||
828 | icr |= STMPE_ICR_LSB_HIGH; | ||
829 | |||
830 | if (stmpe->pdata->irq_invert_polarity) | ||
831 | icr ^= STMPE_ICR_LSB_HIGH; | ||
832 | |||
833 | if (stmpe->pdata->autosleep) { | ||
834 | ret = stmpe_autosleep(stmpe, autosleep_timeout); | ||
835 | if (ret) | ||
836 | return ret; | ||
837 | } | ||
838 | |||
839 | return stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_ICR_LSB], icr); | ||
840 | } | ||
841 | |||
842 | static int __devinit stmpe_add_device(struct stmpe *stmpe, | ||
843 | struct mfd_cell *cell, int irq) | ||
844 | { | ||
845 | return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1, | ||
846 | NULL, stmpe->irq_base + irq); | ||
847 | } | ||
848 | |||
849 | static int __devinit stmpe_devices_init(struct stmpe *stmpe) | ||
850 | { | ||
851 | struct stmpe_variant_info *variant = stmpe->variant; | ||
852 | unsigned int platform_blocks = stmpe->pdata->blocks; | ||
853 | int ret = -EINVAL; | ||
854 | int i; | ||
855 | |||
856 | for (i = 0; i < variant->num_blocks; i++) { | ||
857 | struct stmpe_variant_block *block = &variant->blocks[i]; | ||
858 | |||
859 | if (!(platform_blocks & block->block)) | ||
860 | continue; | ||
861 | |||
862 | platform_blocks &= ~block->block; | ||
863 | ret = stmpe_add_device(stmpe, block->cell, block->irq); | ||
864 | if (ret) | ||
865 | return ret; | ||
866 | } | ||
867 | |||
868 | if (platform_blocks) | ||
869 | dev_warn(stmpe->dev, | ||
870 | "platform wants blocks (%#x) not present on variant", | ||
871 | platform_blocks); | ||
872 | |||
873 | return ret; | ||
874 | } | ||
875 | |||
876 | static int __devinit stmpe_probe(struct i2c_client *i2c, | ||
877 | const struct i2c_device_id *id) | ||
878 | { | ||
879 | struct stmpe_platform_data *pdata = i2c->dev.platform_data; | ||
880 | struct stmpe *stmpe; | ||
881 | int ret; | ||
882 | |||
883 | if (!pdata) | ||
884 | return -EINVAL; | ||
885 | |||
886 | stmpe = kzalloc(sizeof(struct stmpe), GFP_KERNEL); | ||
887 | if (!stmpe) | ||
888 | return -ENOMEM; | ||
889 | |||
890 | mutex_init(&stmpe->irq_lock); | ||
891 | mutex_init(&stmpe->lock); | ||
892 | |||
893 | stmpe->dev = &i2c->dev; | ||
894 | stmpe->i2c = i2c; | ||
895 | |||
896 | stmpe->pdata = pdata; | ||
897 | stmpe->irq_base = pdata->irq_base; | ||
898 | |||
899 | stmpe->partnum = id->driver_data; | ||
900 | stmpe->variant = stmpe_variant_info[stmpe->partnum]; | ||
901 | stmpe->regs = stmpe->variant->regs; | ||
902 | stmpe->num_gpios = stmpe->variant->num_gpios; | ||
903 | |||
904 | i2c_set_clientdata(i2c, stmpe); | ||
905 | |||
906 | ret = stmpe_chip_init(stmpe); | ||
907 | if (ret) | ||
908 | goto out_free; | ||
909 | |||
910 | ret = stmpe_irq_init(stmpe); | ||
911 | if (ret) | ||
912 | goto out_free; | ||
913 | |||
914 | ret = request_threaded_irq(stmpe->i2c->irq, NULL, stmpe_irq, | ||
915 | pdata->irq_trigger | IRQF_ONESHOT, | ||
916 | "stmpe", stmpe); | ||
917 | if (ret) { | ||
918 | dev_err(stmpe->dev, "failed to request IRQ: %d\n", ret); | ||
919 | goto out_removeirq; | ||
920 | } | ||
921 | |||
922 | ret = stmpe_devices_init(stmpe); | ||
923 | if (ret) { | ||
924 | dev_err(stmpe->dev, "failed to add children\n"); | ||
925 | goto out_removedevs; | ||
926 | } | ||
927 | |||
928 | return 0; | ||
929 | |||
930 | out_removedevs: | ||
931 | mfd_remove_devices(stmpe->dev); | ||
932 | free_irq(stmpe->i2c->irq, stmpe); | ||
933 | out_removeirq: | ||
934 | stmpe_irq_remove(stmpe); | ||
935 | out_free: | ||
936 | kfree(stmpe); | ||
937 | return ret; | ||
938 | } | ||
939 | |||
940 | static int __devexit stmpe_remove(struct i2c_client *client) | ||
941 | { | ||
942 | struct stmpe *stmpe = i2c_get_clientdata(client); | ||
943 | |||
944 | mfd_remove_devices(stmpe->dev); | ||
945 | |||
946 | free_irq(stmpe->i2c->irq, stmpe); | ||
947 | stmpe_irq_remove(stmpe); | ||
948 | |||
949 | kfree(stmpe); | ||
950 | |||
951 | return 0; | ||
952 | } | ||
953 | |||
954 | static const struct i2c_device_id stmpe_id[] = { | ||
955 | { "stmpe811", STMPE811 }, | ||
956 | { "stmpe1601", STMPE1601 }, | ||
957 | { "stmpe2401", STMPE2401 }, | ||
958 | { "stmpe2403", STMPE2403 }, | ||
959 | { } | ||
960 | }; | ||
961 | MODULE_DEVICE_TABLE(i2c, stmpe_id); | ||
962 | |||
963 | static struct i2c_driver stmpe_driver = { | ||
964 | .driver.name = "stmpe", | ||
965 | .driver.owner = THIS_MODULE, | ||
966 | .probe = stmpe_probe, | ||
967 | .remove = __devexit_p(stmpe_remove), | ||
968 | .id_table = stmpe_id, | ||
969 | }; | ||
970 | |||
971 | static int __init stmpe_init(void) | ||
972 | { | ||
973 | return i2c_add_driver(&stmpe_driver); | ||
974 | } | ||
975 | subsys_initcall(stmpe_init); | ||
976 | |||
977 | static void __exit stmpe_exit(void) | ||
978 | { | ||
979 | i2c_del_driver(&stmpe_driver); | ||
980 | } | ||
981 | module_exit(stmpe_exit); | ||
982 | |||
983 | MODULE_LICENSE("GPL v2"); | ||
984 | MODULE_DESCRIPTION("STMPE MFD core driver"); | ||
985 | MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>"); | ||
diff --git a/drivers/mfd/stmpe.h b/drivers/mfd/stmpe.h new file mode 100644 index 000000000000..0dbdc4e8cd77 --- /dev/null +++ b/drivers/mfd/stmpe.h | |||
@@ -0,0 +1,183 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
6 | */ | ||
7 | |||
8 | #ifndef __STMPE_H | ||
9 | #define __STMPE_H | ||
10 | |||
11 | #ifdef STMPE_DUMP_BYTES | ||
12 | static inline void stmpe_dump_bytes(const char *str, const void *buf, | ||
13 | size_t len) | ||
14 | { | ||
15 | print_hex_dump_bytes(str, DUMP_PREFIX_OFFSET, buf, len); | ||
16 | } | ||
17 | #else | ||
18 | static inline void stmpe_dump_bytes(const char *str, const void *buf, | ||
19 | size_t len) | ||
20 | { | ||
21 | } | ||
22 | #endif | ||
23 | |||
24 | /** | ||
25 | * struct stmpe_variant_block - information about block | ||
26 | * @cell: base mfd cell | ||
27 | * @irq: interrupt number to be added to each IORESOURCE_IRQ | ||
28 | * in the cell | ||
29 | * @block: block id; used for identification with platform data and for | ||
30 | * enable and altfunc callbacks | ||
31 | */ | ||
32 | struct stmpe_variant_block { | ||
33 | struct mfd_cell *cell; | ||
34 | int irq; | ||
35 | enum stmpe_block block; | ||
36 | }; | ||
37 | |||
38 | /** | ||
39 | * struct stmpe_variant_info - variant-specific information | ||
40 | * @name: part name | ||
41 | * @id_val: content of CHIPID register | ||
42 | * @id_mask: bits valid in CHIPID register for comparison with id_val | ||
43 | * @num_gpios: number of GPIOS | ||
44 | * @af_bits: number of bits used to specify the alternate function | ||
45 | * @blocks: list of blocks present on this device | ||
46 | * @num_blocks: number of blocks present on this device | ||
47 | * @num_irqs: number of internal IRQs available on this device | ||
48 | * @enable: callback to enable the specified blocks. | ||
49 | * Called with the I/O lock held. | ||
50 | * @get_altfunc: callback to get the alternate function number for the | ||
51 | * specific block | ||
52 | * @enable_autosleep: callback to configure autosleep with specified timeout | ||
53 | */ | ||
54 | struct stmpe_variant_info { | ||
55 | const char *name; | ||
56 | u16 id_val; | ||
57 | u16 id_mask; | ||
58 | int num_gpios; | ||
59 | int af_bits; | ||
60 | const u8 *regs; | ||
61 | struct stmpe_variant_block *blocks; | ||
62 | int num_blocks; | ||
63 | int num_irqs; | ||
64 | int (*enable)(struct stmpe *stmpe, unsigned int blocks, bool enable); | ||
65 | int (*get_altfunc)(struct stmpe *stmpe, enum stmpe_block block); | ||
66 | int (*enable_autosleep)(struct stmpe *stmpe, int autosleep_timeout); | ||
67 | }; | ||
68 | |||
69 | #define STMPE_ICR_LSB_HIGH (1 << 2) | ||
70 | #define STMPE_ICR_LSB_EDGE (1 << 1) | ||
71 | #define STMPE_ICR_LSB_GIM (1 << 0) | ||
72 | |||
73 | /* | ||
74 | * STMPE811 | ||
75 | */ | ||
76 | |||
77 | #define STMPE811_IRQ_TOUCH_DET 0 | ||
78 | #define STMPE811_IRQ_FIFO_TH 1 | ||
79 | #define STMPE811_IRQ_FIFO_OFLOW 2 | ||
80 | #define STMPE811_IRQ_FIFO_FULL 3 | ||
81 | #define STMPE811_IRQ_FIFO_EMPTY 4 | ||
82 | #define STMPE811_IRQ_TEMP_SENS 5 | ||
83 | #define STMPE811_IRQ_ADC 6 | ||
84 | #define STMPE811_IRQ_GPIOC 7 | ||
85 | #define STMPE811_NR_INTERNAL_IRQS 8 | ||
86 | |||
87 | #define STMPE811_REG_CHIP_ID 0x00 | ||
88 | #define STMPE811_REG_SYS_CTRL2 0x04 | ||
89 | #define STMPE811_REG_INT_CTRL 0x09 | ||
90 | #define STMPE811_REG_INT_EN 0x0A | ||
91 | #define STMPE811_REG_INT_STA 0x0B | ||
92 | #define STMPE811_REG_GPIO_INT_EN 0x0C | ||
93 | #define STMPE811_REG_GPIO_INT_STA 0x0D | ||
94 | #define STMPE811_REG_GPIO_SET_PIN 0x10 | ||
95 | #define STMPE811_REG_GPIO_CLR_PIN 0x11 | ||
96 | #define STMPE811_REG_GPIO_MP_STA 0x12 | ||
97 | #define STMPE811_REG_GPIO_DIR 0x13 | ||
98 | #define STMPE811_REG_GPIO_ED 0x14 | ||
99 | #define STMPE811_REG_GPIO_RE 0x15 | ||
100 | #define STMPE811_REG_GPIO_FE 0x16 | ||
101 | #define STMPE811_REG_GPIO_AF 0x17 | ||
102 | |||
103 | #define STMPE811_SYS_CTRL2_ADC_OFF (1 << 0) | ||
104 | #define STMPE811_SYS_CTRL2_TSC_OFF (1 << 1) | ||
105 | #define STMPE811_SYS_CTRL2_GPIO_OFF (1 << 2) | ||
106 | #define STMPE811_SYS_CTRL2_TS_OFF (1 << 3) | ||
107 | |||
108 | /* | ||
109 | * STMPE1601 | ||
110 | */ | ||
111 | |||
112 | #define STMPE1601_IRQ_GPIOC 8 | ||
113 | #define STMPE1601_IRQ_PWM3 7 | ||
114 | #define STMPE1601_IRQ_PWM2 6 | ||
115 | #define STMPE1601_IRQ_PWM1 5 | ||
116 | #define STMPE1601_IRQ_PWM0 4 | ||
117 | #define STMPE1601_IRQ_KEYPAD_OVER 2 | ||
118 | #define STMPE1601_IRQ_KEYPAD 1 | ||
119 | #define STMPE1601_IRQ_WAKEUP 0 | ||
120 | #define STMPE1601_NR_INTERNAL_IRQS 9 | ||
121 | |||
122 | #define STMPE1601_REG_SYS_CTRL 0x02 | ||
123 | #define STMPE1601_REG_SYS_CTRL2 0x03 | ||
124 | #define STMPE1601_REG_ICR_LSB 0x11 | ||
125 | #define STMPE1601_REG_IER_LSB 0x13 | ||
126 | #define STMPE1601_REG_ISR_MSB 0x14 | ||
127 | #define STMPE1601_REG_CHIP_ID 0x80 | ||
128 | #define STMPE1601_REG_INT_EN_GPIO_MASK_LSB 0x17 | ||
129 | #define STMPE1601_REG_INT_STA_GPIO_MSB 0x18 | ||
130 | #define STMPE1601_REG_GPIO_MP_LSB 0x87 | ||
131 | #define STMPE1601_REG_GPIO_SET_LSB 0x83 | ||
132 | #define STMPE1601_REG_GPIO_CLR_LSB 0x85 | ||
133 | #define STMPE1601_REG_GPIO_SET_DIR_LSB 0x89 | ||
134 | #define STMPE1601_REG_GPIO_ED_MSB 0x8A | ||
135 | #define STMPE1601_REG_GPIO_RE_LSB 0x8D | ||
136 | #define STMPE1601_REG_GPIO_FE_LSB 0x8F | ||
137 | #define STMPE1601_REG_GPIO_AF_U_MSB 0x92 | ||
138 | |||
139 | #define STMPE1601_SYS_CTRL_ENABLE_GPIO (1 << 3) | ||
140 | #define STMPE1601_SYS_CTRL_ENABLE_KPC (1 << 1) | ||
141 | #define STMPE1601_SYSCON_ENABLE_SPWM (1 << 0) | ||
142 | |||
143 | /* The 1601/2403 share the same masks */ | ||
144 | #define STMPE1601_AUTOSLEEP_TIMEOUT_MASK (0x7) | ||
145 | #define STPME1601_AUTOSLEEP_ENABLE (1 << 3) | ||
146 | |||
147 | /* | ||
148 | * STMPE24xx | ||
149 | */ | ||
150 | |||
151 | #define STMPE24XX_IRQ_GPIOC 8 | ||
152 | #define STMPE24XX_IRQ_PWM2 7 | ||
153 | #define STMPE24XX_IRQ_PWM1 6 | ||
154 | #define STMPE24XX_IRQ_PWM0 5 | ||
155 | #define STMPE24XX_IRQ_ROT_OVER 4 | ||
156 | #define STMPE24XX_IRQ_ROT 3 | ||
157 | #define STMPE24XX_IRQ_KEYPAD_OVER 2 | ||
158 | #define STMPE24XX_IRQ_KEYPAD 1 | ||
159 | #define STMPE24XX_IRQ_WAKEUP 0 | ||
160 | #define STMPE24XX_NR_INTERNAL_IRQS 9 | ||
161 | |||
162 | #define STMPE24XX_REG_SYS_CTRL 0x02 | ||
163 | #define STMPE24XX_REG_ICR_LSB 0x11 | ||
164 | #define STMPE24XX_REG_IER_LSB 0x13 | ||
165 | #define STMPE24XX_REG_ISR_MSB 0x14 | ||
166 | #define STMPE24XX_REG_CHIP_ID 0x80 | ||
167 | #define STMPE24XX_REG_IEGPIOR_LSB 0x18 | ||
168 | #define STMPE24XX_REG_ISGPIOR_MSB 0x19 | ||
169 | #define STMPE24XX_REG_GPMR_LSB 0xA5 | ||
170 | #define STMPE24XX_REG_GPSR_LSB 0x85 | ||
171 | #define STMPE24XX_REG_GPCR_LSB 0x88 | ||
172 | #define STMPE24XX_REG_GPDR_LSB 0x8B | ||
173 | #define STMPE24XX_REG_GPEDR_MSB 0x8C | ||
174 | #define STMPE24XX_REG_GPRER_LSB 0x91 | ||
175 | #define STMPE24XX_REG_GPFER_LSB 0x94 | ||
176 | #define STMPE24XX_REG_GPAFR_U_MSB 0x9B | ||
177 | |||
178 | #define STMPE24XX_SYS_CTRL_ENABLE_GPIO (1 << 3) | ||
179 | #define STMPE24XX_SYSCON_ENABLE_PWM (1 << 2) | ||
180 | #define STMPE24XX_SYS_CTRL_ENABLE_KPC (1 << 1) | ||
181 | #define STMPE24XX_SYSCON_ENABLE_ROT (1 << 0) | ||
182 | |||
183 | #endif | ||
diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c index 5041d33adf0b..006c121f3f0d 100644 --- a/drivers/mfd/t7l66xb.c +++ b/drivers/mfd/t7l66xb.c | |||
@@ -350,7 +350,6 @@ static int t7l66xb_probe(struct platform_device *dev) | |||
350 | t7l66xb->clk48m = clk_get(&dev->dev, "CLK_CK48M"); | 350 | t7l66xb->clk48m = clk_get(&dev->dev, "CLK_CK48M"); |
351 | if (IS_ERR(t7l66xb->clk48m)) { | 351 | if (IS_ERR(t7l66xb->clk48m)) { |
352 | ret = PTR_ERR(t7l66xb->clk48m); | 352 | ret = PTR_ERR(t7l66xb->clk48m); |
353 | clk_put(t7l66xb->clk32k); | ||
354 | goto err_clk48m_get; | 353 | goto err_clk48m_get; |
355 | } | 354 | } |
356 | 355 | ||
@@ -425,6 +424,8 @@ static int t7l66xb_remove(struct platform_device *dev) | |||
425 | ret = pdata->disable(dev); | 424 | ret = pdata->disable(dev); |
426 | clk_disable(t7l66xb->clk48m); | 425 | clk_disable(t7l66xb->clk48m); |
427 | clk_put(t7l66xb->clk48m); | 426 | clk_put(t7l66xb->clk48m); |
427 | clk_disable(t7l66xb->clk32k); | ||
428 | clk_put(t7l66xb->clk32k); | ||
428 | t7l66xb_detach_irq(dev); | 429 | t7l66xb_detach_irq(dev); |
429 | iounmap(t7l66xb->scr); | 430 | iounmap(t7l66xb->scr); |
430 | release_resource(&t7l66xb->rscr); | 431 | release_resource(&t7l66xb->rscr); |
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c index 517f9bcdeaac..6315f63f017d 100644 --- a/drivers/mfd/tc6387xb.c +++ b/drivers/mfd/tc6387xb.c | |||
@@ -137,7 +137,7 @@ static struct mfd_cell tc6387xb_cells[] = { | |||
137 | }, | 137 | }, |
138 | }; | 138 | }; |
139 | 139 | ||
140 | static int tc6387xb_probe(struct platform_device *dev) | 140 | static int __devinit tc6387xb_probe(struct platform_device *dev) |
141 | { | 141 | { |
142 | struct tc6387xb_platform_data *pdata = dev->dev.platform_data; | 142 | struct tc6387xb_platform_data *pdata = dev->dev.platform_data; |
143 | struct resource *iomem, *rscr; | 143 | struct resource *iomem, *rscr; |
@@ -201,6 +201,7 @@ static int tc6387xb_probe(struct platform_device *dev) | |||
201 | if (!ret) | 201 | if (!ret) |
202 | return 0; | 202 | return 0; |
203 | 203 | ||
204 | iounmap(tc6387xb->scr); | ||
204 | err_ioremap: | 205 | err_ioremap: |
205 | release_resource(&tc6387xb->rscr); | 206 | release_resource(&tc6387xb->rscr); |
206 | err_resource: | 207 | err_resource: |
@@ -211,14 +212,17 @@ err_no_irq: | |||
211 | return ret; | 212 | return ret; |
212 | } | 213 | } |
213 | 214 | ||
214 | static int tc6387xb_remove(struct platform_device *dev) | 215 | static int __devexit tc6387xb_remove(struct platform_device *dev) |
215 | { | 216 | { |
216 | struct clk *clk32k = platform_get_drvdata(dev); | 217 | struct tc6387xb *tc6387xb = platform_get_drvdata(dev); |
217 | 218 | ||
218 | mfd_remove_devices(&dev->dev); | 219 | mfd_remove_devices(&dev->dev); |
219 | clk_disable(clk32k); | 220 | iounmap(tc6387xb->scr); |
220 | clk_put(clk32k); | 221 | release_resource(&tc6387xb->rscr); |
222 | clk_disable(tc6387xb->clk32k); | ||
223 | clk_put(tc6387xb->clk32k); | ||
221 | platform_set_drvdata(dev, NULL); | 224 | platform_set_drvdata(dev, NULL); |
225 | kfree(tc6387xb); | ||
222 | 226 | ||
223 | return 0; | 227 | return 0; |
224 | } | 228 | } |
@@ -229,7 +233,7 @@ static struct platform_driver tc6387xb_platform_driver = { | |||
229 | .name = "tc6387xb", | 233 | .name = "tc6387xb", |
230 | }, | 234 | }, |
231 | .probe = tc6387xb_probe, | 235 | .probe = tc6387xb_probe, |
232 | .remove = tc6387xb_remove, | 236 | .remove = __devexit_p(tc6387xb_remove), |
233 | .suspend = tc6387xb_suspend, | 237 | .suspend = tc6387xb_suspend, |
234 | .resume = tc6387xb_resume, | 238 | .resume = tc6387xb_resume, |
235 | }; | 239 | }; |
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index fcf9068810fb..ef6c42c8917a 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c | |||
@@ -732,9 +732,9 @@ err_gpio_add: | |||
732 | if (tc6393xb->gpio.base != -1) | 732 | if (tc6393xb->gpio.base != -1) |
733 | temp = gpiochip_remove(&tc6393xb->gpio); | 733 | temp = gpiochip_remove(&tc6393xb->gpio); |
734 | tcpd->disable(dev); | 734 | tcpd->disable(dev); |
735 | err_clk_enable: | ||
736 | clk_disable(tc6393xb->clk); | ||
737 | err_enable: | 735 | err_enable: |
736 | clk_disable(tc6393xb->clk); | ||
737 | err_clk_enable: | ||
738 | iounmap(tc6393xb->scr); | 738 | iounmap(tc6393xb->scr); |
739 | err_ioremap: | 739 | err_ioremap: |
740 | release_resource(&tc6393xb->rscr); | 740 | release_resource(&tc6393xb->rscr); |
diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c index d859dffed39f..fc0197649281 100644 --- a/drivers/mfd/tps6507x.c +++ b/drivers/mfd/tps6507x.c | |||
@@ -89,10 +89,8 @@ static int tps6507x_i2c_probe(struct i2c_client *i2c, | |||
89 | int ret = 0; | 89 | int ret = 0; |
90 | 90 | ||
91 | tps6507x = kzalloc(sizeof(struct tps6507x_dev), GFP_KERNEL); | 91 | tps6507x = kzalloc(sizeof(struct tps6507x_dev), GFP_KERNEL); |
92 | if (tps6507x == NULL) { | 92 | if (tps6507x == NULL) |
93 | kfree(i2c); | ||
94 | return -ENOMEM; | 93 | return -ENOMEM; |
95 | } | ||
96 | 94 | ||
97 | i2c_set_clientdata(i2c, tps6507x); | 95 | i2c_set_clientdata(i2c, tps6507x); |
98 | tps6507x->dev = &i2c->dev; | 96 | tps6507x->dev = &i2c->dev; |
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c new file mode 100644 index 000000000000..4cde31e6a252 --- /dev/null +++ b/drivers/mfd/tps6586x.c | |||
@@ -0,0 +1,375 @@ | |||
1 | /* | ||
2 | * Core driver for TI TPS6586x PMIC family | ||
3 | * | ||
4 | * Copyright (c) 2010 CompuLab Ltd. | ||
5 | * Mike Rapoport <mike@compulab.co.il> | ||
6 | * | ||
7 | * Based on da903x.c. | ||
8 | * Copyright (C) 2008 Compulab, Ltd. | ||
9 | * Mike Rapoport <mike@compulab.co.il> | ||
10 | * Copyright (C) 2006-2008 Marvell International Ltd. | ||
11 | * Eric Miao <eric.miao@marvell.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/mutex.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/i2c.h> | ||
24 | |||
25 | #include <linux/mfd/core.h> | ||
26 | #include <linux/mfd/tps6586x.h> | ||
27 | |||
28 | /* GPIO control registers */ | ||
29 | #define TPS6586X_GPIOSET1 0x5d | ||
30 | #define TPS6586X_GPIOSET2 0x5e | ||
31 | |||
32 | /* device id */ | ||
33 | #define TPS6586X_VERSIONCRC 0xcd | ||
34 | #define TPS658621A_VERSIONCRC 0x15 | ||
35 | |||
36 | struct tps6586x { | ||
37 | struct mutex lock; | ||
38 | struct device *dev; | ||
39 | struct i2c_client *client; | ||
40 | |||
41 | struct gpio_chip gpio; | ||
42 | }; | ||
43 | |||
44 | static inline int __tps6586x_read(struct i2c_client *client, | ||
45 | int reg, uint8_t *val) | ||
46 | { | ||
47 | int ret; | ||
48 | |||
49 | ret = i2c_smbus_read_byte_data(client, reg); | ||
50 | if (ret < 0) { | ||
51 | dev_err(&client->dev, "failed reading at 0x%02x\n", reg); | ||
52 | return ret; | ||
53 | } | ||
54 | |||
55 | *val = (uint8_t)ret; | ||
56 | |||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static inline int __tps6586x_reads(struct i2c_client *client, int reg, | ||
61 | int len, uint8_t *val) | ||
62 | { | ||
63 | int ret; | ||
64 | |||
65 | ret = i2c_smbus_read_i2c_block_data(client, reg, len, val); | ||
66 | if (ret < 0) { | ||
67 | dev_err(&client->dev, "failed reading from 0x%02x\n", reg); | ||
68 | return ret; | ||
69 | } | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static inline int __tps6586x_write(struct i2c_client *client, | ||
75 | int reg, uint8_t val) | ||
76 | { | ||
77 | int ret; | ||
78 | |||
79 | ret = i2c_smbus_write_byte_data(client, reg, val); | ||
80 | if (ret < 0) { | ||
81 | dev_err(&client->dev, "failed writing 0x%02x to 0x%02x\n", | ||
82 | val, reg); | ||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static inline int __tps6586x_writes(struct i2c_client *client, int reg, | ||
90 | int len, uint8_t *val) | ||
91 | { | ||
92 | int ret; | ||
93 | |||
94 | ret = i2c_smbus_write_i2c_block_data(client, reg, len, val); | ||
95 | if (ret < 0) { | ||
96 | dev_err(&client->dev, "failed writings to 0x%02x\n", reg); | ||
97 | return ret; | ||
98 | } | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | int tps6586x_write(struct device *dev, int reg, uint8_t val) | ||
104 | { | ||
105 | return __tps6586x_write(to_i2c_client(dev), reg, val); | ||
106 | } | ||
107 | EXPORT_SYMBOL_GPL(tps6586x_write); | ||
108 | |||
109 | int tps6586x_writes(struct device *dev, int reg, int len, uint8_t *val) | ||
110 | { | ||
111 | return __tps6586x_writes(to_i2c_client(dev), reg, len, val); | ||
112 | } | ||
113 | EXPORT_SYMBOL_GPL(tps6586x_writes); | ||
114 | |||
115 | int tps6586x_read(struct device *dev, int reg, uint8_t *val) | ||
116 | { | ||
117 | return __tps6586x_read(to_i2c_client(dev), reg, val); | ||
118 | } | ||
119 | EXPORT_SYMBOL_GPL(tps6586x_read); | ||
120 | |||
121 | int tps6586x_reads(struct device *dev, int reg, int len, uint8_t *val) | ||
122 | { | ||
123 | return __tps6586x_reads(to_i2c_client(dev), reg, len, val); | ||
124 | } | ||
125 | EXPORT_SYMBOL_GPL(tps6586x_reads); | ||
126 | |||
127 | int tps6586x_set_bits(struct device *dev, int reg, uint8_t bit_mask) | ||
128 | { | ||
129 | struct tps6586x *tps6586x = dev_get_drvdata(dev); | ||
130 | uint8_t reg_val; | ||
131 | int ret = 0; | ||
132 | |||
133 | mutex_lock(&tps6586x->lock); | ||
134 | |||
135 | ret = __tps6586x_read(to_i2c_client(dev), reg, ®_val); | ||
136 | if (ret) | ||
137 | goto out; | ||
138 | |||
139 | if ((reg_val & bit_mask) == 0) { | ||
140 | reg_val |= bit_mask; | ||
141 | ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val); | ||
142 | } | ||
143 | out: | ||
144 | mutex_unlock(&tps6586x->lock); | ||
145 | return ret; | ||
146 | } | ||
147 | EXPORT_SYMBOL_GPL(tps6586x_set_bits); | ||
148 | |||
149 | int tps6586x_clr_bits(struct device *dev, int reg, uint8_t bit_mask) | ||
150 | { | ||
151 | struct tps6586x *tps6586x = dev_get_drvdata(dev); | ||
152 | uint8_t reg_val; | ||
153 | int ret = 0; | ||
154 | |||
155 | mutex_lock(&tps6586x->lock); | ||
156 | |||
157 | ret = __tps6586x_read(to_i2c_client(dev), reg, ®_val); | ||
158 | if (ret) | ||
159 | goto out; | ||
160 | |||
161 | if (reg_val & bit_mask) { | ||
162 | reg_val &= ~bit_mask; | ||
163 | ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val); | ||
164 | } | ||
165 | out: | ||
166 | mutex_unlock(&tps6586x->lock); | ||
167 | return ret; | ||
168 | } | ||
169 | EXPORT_SYMBOL_GPL(tps6586x_clr_bits); | ||
170 | |||
171 | int tps6586x_update(struct device *dev, int reg, uint8_t val, uint8_t mask) | ||
172 | { | ||
173 | struct tps6586x *tps6586x = dev_get_drvdata(dev); | ||
174 | uint8_t reg_val; | ||
175 | int ret = 0; | ||
176 | |||
177 | mutex_lock(&tps6586x->lock); | ||
178 | |||
179 | ret = __tps6586x_read(tps6586x->client, reg, ®_val); | ||
180 | if (ret) | ||
181 | goto out; | ||
182 | |||
183 | if ((reg_val & mask) != val) { | ||
184 | reg_val = (reg_val & ~mask) | val; | ||
185 | ret = __tps6586x_write(tps6586x->client, reg, reg_val); | ||
186 | } | ||
187 | out: | ||
188 | mutex_unlock(&tps6586x->lock); | ||
189 | return ret; | ||
190 | } | ||
191 | EXPORT_SYMBOL_GPL(tps6586x_update); | ||
192 | |||
193 | static int tps6586x_gpio_get(struct gpio_chip *gc, unsigned offset) | ||
194 | { | ||
195 | struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio); | ||
196 | uint8_t val; | ||
197 | int ret; | ||
198 | |||
199 | ret = __tps6586x_read(tps6586x->client, TPS6586X_GPIOSET2, &val); | ||
200 | if (ret) | ||
201 | return ret; | ||
202 | |||
203 | return !!(val & (1 << offset)); | ||
204 | } | ||
205 | |||
206 | |||
207 | static void tps6586x_gpio_set(struct gpio_chip *chip, unsigned offset, | ||
208 | int value) | ||
209 | { | ||
210 | struct tps6586x *tps6586x = container_of(chip, struct tps6586x, gpio); | ||
211 | |||
212 | __tps6586x_write(tps6586x->client, TPS6586X_GPIOSET2, | ||
213 | value << offset); | ||
214 | } | ||
215 | |||
216 | static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset, | ||
217 | int value) | ||
218 | { | ||
219 | struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio); | ||
220 | uint8_t val, mask; | ||
221 | |||
222 | tps6586x_gpio_set(gc, offset, value); | ||
223 | |||
224 | val = 0x1 << (offset * 2); | ||
225 | mask = 0x3 << (offset * 2); | ||
226 | |||
227 | return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask); | ||
228 | } | ||
229 | |||
230 | static void tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base) | ||
231 | { | ||
232 | int ret; | ||
233 | |||
234 | if (!gpio_base) | ||
235 | return; | ||
236 | |||
237 | tps6586x->gpio.owner = THIS_MODULE; | ||
238 | tps6586x->gpio.label = tps6586x->client->name; | ||
239 | tps6586x->gpio.dev = tps6586x->dev; | ||
240 | tps6586x->gpio.base = gpio_base; | ||
241 | tps6586x->gpio.ngpio = 4; | ||
242 | tps6586x->gpio.can_sleep = 1; | ||
243 | |||
244 | /* FIXME: add handling of GPIOs as dedicated inputs */ | ||
245 | tps6586x->gpio.direction_output = tps6586x_gpio_output; | ||
246 | tps6586x->gpio.set = tps6586x_gpio_set; | ||
247 | tps6586x->gpio.get = tps6586x_gpio_get; | ||
248 | |||
249 | ret = gpiochip_add(&tps6586x->gpio); | ||
250 | if (ret) | ||
251 | dev_warn(tps6586x->dev, "GPIO registration failed: %d\n", ret); | ||
252 | } | ||
253 | |||
254 | static int __remove_subdev(struct device *dev, void *unused) | ||
255 | { | ||
256 | platform_device_unregister(to_platform_device(dev)); | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static int tps6586x_remove_subdevs(struct tps6586x *tps6586x) | ||
261 | { | ||
262 | return device_for_each_child(tps6586x->dev, NULL, __remove_subdev); | ||
263 | } | ||
264 | |||
265 | static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x, | ||
266 | struct tps6586x_platform_data *pdata) | ||
267 | { | ||
268 | struct tps6586x_subdev_info *subdev; | ||
269 | struct platform_device *pdev; | ||
270 | int i, ret = 0; | ||
271 | |||
272 | for (i = 0; i < pdata->num_subdevs; i++) { | ||
273 | subdev = &pdata->subdevs[i]; | ||
274 | |||
275 | pdev = platform_device_alloc(subdev->name, subdev->id); | ||
276 | |||
277 | pdev->dev.parent = tps6586x->dev; | ||
278 | pdev->dev.platform_data = subdev->platform_data; | ||
279 | |||
280 | ret = platform_device_add(pdev); | ||
281 | if (ret) | ||
282 | goto failed; | ||
283 | } | ||
284 | return 0; | ||
285 | |||
286 | failed: | ||
287 | tps6586x_remove_subdevs(tps6586x); | ||
288 | return ret; | ||
289 | } | ||
290 | |||
291 | static int __devinit tps6586x_i2c_probe(struct i2c_client *client, | ||
292 | const struct i2c_device_id *id) | ||
293 | { | ||
294 | struct tps6586x_platform_data *pdata = client->dev.platform_data; | ||
295 | struct tps6586x *tps6586x; | ||
296 | int ret; | ||
297 | |||
298 | if (!pdata) { | ||
299 | dev_err(&client->dev, "tps6586x requires platform data\n"); | ||
300 | return -ENOTSUPP; | ||
301 | } | ||
302 | |||
303 | ret = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC); | ||
304 | if (ret < 0) { | ||
305 | dev_err(&client->dev, "Chip ID read failed: %d\n", ret); | ||
306 | return -EIO; | ||
307 | } | ||
308 | |||
309 | if (ret != TPS658621A_VERSIONCRC) { | ||
310 | dev_err(&client->dev, "Unsupported chip ID: %x\n", ret); | ||
311 | return -ENODEV; | ||
312 | } | ||
313 | |||
314 | tps6586x = kzalloc(sizeof(struct tps6586x), GFP_KERNEL); | ||
315 | if (tps6586x == NULL) | ||
316 | return -ENOMEM; | ||
317 | |||
318 | tps6586x->client = client; | ||
319 | tps6586x->dev = &client->dev; | ||
320 | i2c_set_clientdata(client, tps6586x); | ||
321 | |||
322 | mutex_init(&tps6586x->lock); | ||
323 | |||
324 | ret = tps6586x_add_subdevs(tps6586x, pdata); | ||
325 | if (ret) { | ||
326 | dev_err(&client->dev, "add devices failed: %d\n", ret); | ||
327 | goto err_add_devs; | ||
328 | } | ||
329 | |||
330 | tps6586x_gpio_init(tps6586x, pdata->gpio_base); | ||
331 | |||
332 | return 0; | ||
333 | |||
334 | err_add_devs: | ||
335 | kfree(tps6586x); | ||
336 | return ret; | ||
337 | } | ||
338 | |||
339 | static int __devexit tps6586x_i2c_remove(struct i2c_client *client) | ||
340 | { | ||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static const struct i2c_device_id tps6586x_id_table[] = { | ||
345 | { "tps6586x", 0 }, | ||
346 | { }, | ||
347 | }; | ||
348 | MODULE_DEVICE_TABLE(i2c, tps6586x_id_table); | ||
349 | |||
350 | static struct i2c_driver tps6586x_driver = { | ||
351 | .driver = { | ||
352 | .name = "tps6586x", | ||
353 | .owner = THIS_MODULE, | ||
354 | }, | ||
355 | .probe = tps6586x_i2c_probe, | ||
356 | .remove = __devexit_p(tps6586x_i2c_remove), | ||
357 | .id_table = tps6586x_id_table, | ||
358 | }; | ||
359 | |||
360 | static int __init tps6586x_init(void) | ||
361 | { | ||
362 | return i2c_add_driver(&tps6586x_driver); | ||
363 | } | ||
364 | subsys_initcall(tps6586x_init); | ||
365 | |||
366 | static void __exit tps6586x_exit(void) | ||
367 | { | ||
368 | i2c_del_driver(&tps6586x_driver); | ||
369 | } | ||
370 | module_exit(tps6586x_exit); | ||
371 | |||
372 | MODULE_DESCRIPTION("TPS6586X core driver"); | ||
373 | MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); | ||
374 | MODULE_LICENSE("GPL"); | ||
375 | |||
diff --git a/drivers/mfd/twl6030-pwm.c b/drivers/mfd/twl6030-pwm.c new file mode 100644 index 000000000000..5d25bdc78424 --- /dev/null +++ b/drivers/mfd/twl6030-pwm.c | |||
@@ -0,0 +1,163 @@ | |||
1 | /* | ||
2 | * twl6030_pwm.c | ||
3 | * Driver for PHOENIX (TWL6030) Pulse Width Modulator | ||
4 | * | ||
5 | * Copyright (C) 2010 Texas Instruments | ||
6 | * Author: Hemanth V <hemanthv@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License version 2 as published by | ||
10 | * the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/i2c/twl.h> | ||
24 | #include <linux/slab.h> | ||
25 | |||
26 | #define LED_PWM_CTRL1 0xF4 | ||
27 | #define LED_PWM_CTRL2 0xF5 | ||
28 | |||
29 | /* Max value for CTRL1 register */ | ||
30 | #define PWM_CTRL1_MAX 255 | ||
31 | |||
32 | /* Pull down disable */ | ||
33 | #define PWM_CTRL2_DIS_PD (1 << 6) | ||
34 | |||
35 | /* Current control 2.5 milli Amps */ | ||
36 | #define PWM_CTRL2_CURR_02 (2 << 4) | ||
37 | |||
38 | /* LED supply source */ | ||
39 | #define PWM_CTRL2_SRC_VAC (1 << 2) | ||
40 | |||
41 | /* LED modes */ | ||
42 | #define PWM_CTRL2_MODE_HW (0 << 0) | ||
43 | #define PWM_CTRL2_MODE_SW (1 << 0) | ||
44 | #define PWM_CTRL2_MODE_DIS (2 << 0) | ||
45 | |||
46 | #define PWM_CTRL2_MODE_MASK 0x3 | ||
47 | |||
48 | struct pwm_device { | ||
49 | const char *label; | ||
50 | unsigned int pwm_id; | ||
51 | }; | ||
52 | |||
53 | int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) | ||
54 | { | ||
55 | u8 duty_cycle; | ||
56 | int ret; | ||
57 | |||
58 | if (pwm == NULL || period_ns == 0 || duty_ns > period_ns) | ||
59 | return -EINVAL; | ||
60 | |||
61 | duty_cycle = (duty_ns * PWM_CTRL1_MAX) / period_ns; | ||
62 | |||
63 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, duty_cycle, LED_PWM_CTRL1); | ||
64 | |||
65 | if (ret < 0) { | ||
66 | pr_err("%s: Failed to configure PWM, Error %d\n", | ||
67 | pwm->label, ret); | ||
68 | return ret; | ||
69 | } | ||
70 | return 0; | ||
71 | } | ||
72 | EXPORT_SYMBOL(pwm_config); | ||
73 | |||
74 | int pwm_enable(struct pwm_device *pwm) | ||
75 | { | ||
76 | u8 val; | ||
77 | int ret; | ||
78 | |||
79 | ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2); | ||
80 | if (ret < 0) { | ||
81 | pr_err("%s: Failed to enable PWM, Error %d\n", pwm->label, ret); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | /* Change mode to software control */ | ||
86 | val &= ~PWM_CTRL2_MODE_MASK; | ||
87 | val |= PWM_CTRL2_MODE_SW; | ||
88 | |||
89 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2); | ||
90 | if (ret < 0) { | ||
91 | pr_err("%s: Failed to enable PWM, Error %d\n", pwm->label, ret); | ||
92 | return ret; | ||
93 | } | ||
94 | |||
95 | twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2); | ||
96 | return 0; | ||
97 | } | ||
98 | EXPORT_SYMBOL(pwm_enable); | ||
99 | |||
100 | void pwm_disable(struct pwm_device *pwm) | ||
101 | { | ||
102 | u8 val; | ||
103 | int ret; | ||
104 | |||
105 | ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2); | ||
106 | if (ret < 0) { | ||
107 | pr_err("%s: Failed to disable PWM, Error %d\n", | ||
108 | pwm->label, ret); | ||
109 | return; | ||
110 | } | ||
111 | |||
112 | val &= ~PWM_CTRL2_MODE_MASK; | ||
113 | val |= PWM_CTRL2_MODE_HW; | ||
114 | |||
115 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2); | ||
116 | if (ret < 0) { | ||
117 | pr_err("%s: Failed to disable PWM, Error %d\n", | ||
118 | pwm->label, ret); | ||
119 | return; | ||
120 | } | ||
121 | return; | ||
122 | } | ||
123 | EXPORT_SYMBOL(pwm_disable); | ||
124 | |||
125 | struct pwm_device *pwm_request(int pwm_id, const char *label) | ||
126 | { | ||
127 | u8 val; | ||
128 | int ret; | ||
129 | struct pwm_device *pwm; | ||
130 | |||
131 | pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); | ||
132 | if (pwm == NULL) { | ||
133 | pr_err("%s: failed to allocate memory\n", label); | ||
134 | return NULL; | ||
135 | } | ||
136 | |||
137 | pwm->label = label; | ||
138 | pwm->pwm_id = pwm_id; | ||
139 | |||
140 | /* Configure PWM */ | ||
141 | val = PWM_CTRL2_DIS_PD | PWM_CTRL2_CURR_02 | PWM_CTRL2_SRC_VAC | | ||
142 | PWM_CTRL2_MODE_HW; | ||
143 | |||
144 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2); | ||
145 | |||
146 | if (ret < 0) { | ||
147 | pr_err("%s: Failed to configure PWM, Error %d\n", | ||
148 | pwm->label, ret); | ||
149 | |||
150 | kfree(pwm); | ||
151 | return NULL; | ||
152 | } | ||
153 | |||
154 | return pwm; | ||
155 | } | ||
156 | EXPORT_SYMBOL(pwm_request); | ||
157 | |||
158 | void pwm_free(struct pwm_device *pwm) | ||
159 | { | ||
160 | pwm_disable(pwm); | ||
161 | kfree(pwm); | ||
162 | } | ||
163 | EXPORT_SYMBOL(pwm_free); | ||
diff --git a/drivers/mfd/ucb1400_core.c b/drivers/mfd/ucb1400_core.c index dbe280153f9e..d73f84ba0f08 100644 --- a/drivers/mfd/ucb1400_core.c +++ b/drivers/mfd/ucb1400_core.c | |||
@@ -114,7 +114,7 @@ static int ucb1400_core_probe(struct device *dev) | |||
114 | err3: | 114 | err3: |
115 | platform_device_put(ucb->ucb1400_ts); | 115 | platform_device_put(ucb->ucb1400_ts); |
116 | err2: | 116 | err2: |
117 | platform_device_unregister(ucb->ucb1400_gpio); | 117 | platform_device_del(ucb->ucb1400_gpio); |
118 | err1: | 118 | err1: |
119 | platform_device_put(ucb->ucb1400_gpio); | 119 | platform_device_put(ucb->ucb1400_gpio); |
120 | err0: | 120 | err0: |
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 1a968f34d679..1e7aaaf6cc6f 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c | |||
@@ -95,6 +95,7 @@ enum wm831x_parent { | |||
95 | WM8311 = 0x8311, | 95 | WM8311 = 0x8311, |
96 | WM8312 = 0x8312, | 96 | WM8312 = 0x8312, |
97 | WM8320 = 0x8320, | 97 | WM8320 = 0x8320, |
98 | WM8321 = 0x8321, | ||
98 | }; | 99 | }; |
99 | 100 | ||
100 | static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg) | 101 | static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg) |
@@ -1533,6 +1534,12 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1533 | dev_info(wm831x->dev, "WM8320 revision %c\n", 'A' + rev); | 1534 | dev_info(wm831x->dev, "WM8320 revision %c\n", 'A' + rev); |
1534 | break; | 1535 | break; |
1535 | 1536 | ||
1537 | case WM8321: | ||
1538 | parent = WM8321; | ||
1539 | wm831x->num_gpio = 12; | ||
1540 | dev_info(wm831x->dev, "WM8321 revision %c\n", 'A' + rev); | ||
1541 | break; | ||
1542 | |||
1536 | default: | 1543 | default: |
1537 | dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret); | 1544 | dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret); |
1538 | ret = -EINVAL; | 1545 | ret = -EINVAL; |
@@ -1607,6 +1614,12 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1607 | NULL, 0); | 1614 | NULL, 0); |
1608 | break; | 1615 | break; |
1609 | 1616 | ||
1617 | case WM8321: | ||
1618 | ret = mfd_add_devices(wm831x->dev, -1, | ||
1619 | wm8320_devs, ARRAY_SIZE(wm8320_devs), | ||
1620 | NULL, 0); | ||
1621 | break; | ||
1622 | |||
1610 | default: | 1623 | default: |
1611 | /* If this happens the bus probe function is buggy */ | 1624 | /* If this happens the bus probe function is buggy */ |
1612 | BUG(); | 1625 | BUG(); |
@@ -1744,10 +1757,8 @@ static int wm831x_i2c_probe(struct i2c_client *i2c, | |||
1744 | struct wm831x *wm831x; | 1757 | struct wm831x *wm831x; |
1745 | 1758 | ||
1746 | wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL); | 1759 | wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL); |
1747 | if (wm831x == NULL) { | 1760 | if (wm831x == NULL) |
1748 | kfree(i2c); | ||
1749 | return -ENOMEM; | 1761 | return -ENOMEM; |
1750 | } | ||
1751 | 1762 | ||
1752 | i2c_set_clientdata(i2c, wm831x); | 1763 | i2c_set_clientdata(i2c, wm831x); |
1753 | wm831x->dev = &i2c->dev; | 1764 | wm831x->dev = &i2c->dev; |
@@ -1779,6 +1790,7 @@ static const struct i2c_device_id wm831x_i2c_id[] = { | |||
1779 | { "wm8311", WM8311 }, | 1790 | { "wm8311", WM8311 }, |
1780 | { "wm8312", WM8312 }, | 1791 | { "wm8312", WM8312 }, |
1781 | { "wm8320", WM8320 }, | 1792 | { "wm8320", WM8320 }, |
1793 | { "wm8321", WM8321 }, | ||
1782 | { } | 1794 | { } |
1783 | }; | 1795 | }; |
1784 | MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id); | 1796 | MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id); |
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index b5807484b4c9..e81cc31e4202 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c | |||
@@ -536,6 +536,7 @@ static int wm8350_create_cache(struct wm8350 *wm8350, int type, int mode) | |||
536 | } | 536 | } |
537 | 537 | ||
538 | out: | 538 | out: |
539 | kfree(wm8350->reg_cache); | ||
539 | return ret; | 540 | return ret; |
540 | } | 541 | } |
541 | 542 | ||
@@ -700,7 +701,7 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, | |||
700 | 701 | ||
701 | ret = wm8350_irq_init(wm8350, irq, pdata); | 702 | ret = wm8350_irq_init(wm8350, irq, pdata); |
702 | if (ret < 0) | 703 | if (ret < 0) |
703 | goto err; | 704 | goto err_free; |
704 | 705 | ||
705 | if (wm8350->irq_base) { | 706 | if (wm8350->irq_base) { |
706 | ret = request_threaded_irq(wm8350->irq_base + | 707 | ret = request_threaded_irq(wm8350->irq_base + |
@@ -738,8 +739,9 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, | |||
738 | 739 | ||
739 | err_irq: | 740 | err_irq: |
740 | wm8350_irq_exit(wm8350); | 741 | wm8350_irq_exit(wm8350); |
741 | err: | 742 | err_free: |
742 | kfree(wm8350->reg_cache); | 743 | kfree(wm8350->reg_cache); |
744 | err: | ||
743 | return ret; | 745 | return ret; |
744 | } | 746 | } |
745 | EXPORT_SYMBOL_GPL(wm8350_device_init); | 747 | EXPORT_SYMBOL_GPL(wm8350_device_init); |
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index ec71c9368906..b3b2aaf89dbe 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c | |||
@@ -326,8 +326,10 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) | |||
326 | wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) * | 326 | wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) * |
327 | ARRAY_SIZE(wm8994_main_supplies), | 327 | ARRAY_SIZE(wm8994_main_supplies), |
328 | GFP_KERNEL); | 328 | GFP_KERNEL); |
329 | if (!wm8994->supplies) | 329 | if (!wm8994->supplies) { |
330 | ret = -ENOMEM; | ||
330 | goto err; | 331 | goto err; |
332 | } | ||
331 | 333 | ||
332 | for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++) | 334 | for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++) |
333 | wm8994->supplies[i].supply = wm8994_main_supplies[i]; | 335 | wm8994->supplies[i].supply = wm8994_main_supplies[i]; |
@@ -495,10 +497,8 @@ static int wm8994_i2c_probe(struct i2c_client *i2c, | |||
495 | struct wm8994 *wm8994; | 497 | struct wm8994 *wm8994; |
496 | 498 | ||
497 | wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL); | 499 | wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL); |
498 | if (wm8994 == NULL) { | 500 | if (wm8994 == NULL) |
499 | kfree(i2c); | ||
500 | return -ENOMEM; | 501 | return -ENOMEM; |
501 | } | ||
502 | 502 | ||
503 | i2c_set_clientdata(i2c, wm8994); | 503 | i2c_set_clientdata(i2c, wm8994); |
504 | wm8994->dev = &i2c->dev; | 504 | wm8994->dev = &i2c->dev; |
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 5bfb2a2041b8..ef34de7a8026 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c | |||
@@ -124,9 +124,9 @@ static int count = DEFAULT_COUNT; | |||
124 | module_param(recur_count, int, 0644); | 124 | module_param(recur_count, int, 0644); |
125 | MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\ | 125 | MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\ |
126 | "default is 10"); | 126 | "default is 10"); |
127 | module_param(cpoint_name, charp, 0644); | 127 | module_param(cpoint_name, charp, 0444); |
128 | MODULE_PARM_DESC(cpoint_name, " Crash Point, where kernel is to be crashed"); | 128 | MODULE_PARM_DESC(cpoint_name, " Crash Point, where kernel is to be crashed"); |
129 | module_param(cpoint_type, charp, 0644); | 129 | module_param(cpoint_type, charp, 0444); |
130 | MODULE_PARM_DESC(cpoint_type, " Crash Point Type, action to be taken on "\ | 130 | MODULE_PARM_DESC(cpoint_type, " Crash Point Type, action to be taken on "\ |
131 | "hitting the crash point"); | 131 | "hitting the crash point"); |
132 | module_param(cpoint_count, int, 0644); | 132 | module_param(cpoint_count, int, 0644); |
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 8433cde29c8b..d545f79f6000 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -247,7 +247,76 @@ static u32 get_card_status(struct mmc_card *card, struct request *req) | |||
247 | return cmd.resp[0]; | 247 | return cmd.resp[0]; |
248 | } | 248 | } |
249 | 249 | ||
250 | static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | 250 | static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req) |
251 | { | ||
252 | struct mmc_blk_data *md = mq->data; | ||
253 | struct mmc_card *card = md->queue.card; | ||
254 | unsigned int from, nr, arg; | ||
255 | int err = 0; | ||
256 | |||
257 | mmc_claim_host(card->host); | ||
258 | |||
259 | if (!mmc_can_erase(card)) { | ||
260 | err = -EOPNOTSUPP; | ||
261 | goto out; | ||
262 | } | ||
263 | |||
264 | from = blk_rq_pos(req); | ||
265 | nr = blk_rq_sectors(req); | ||
266 | |||
267 | if (mmc_can_trim(card)) | ||
268 | arg = MMC_TRIM_ARG; | ||
269 | else | ||
270 | arg = MMC_ERASE_ARG; | ||
271 | |||
272 | err = mmc_erase(card, from, nr, arg); | ||
273 | out: | ||
274 | spin_lock_irq(&md->lock); | ||
275 | __blk_end_request(req, err, blk_rq_bytes(req)); | ||
276 | spin_unlock_irq(&md->lock); | ||
277 | |||
278 | mmc_release_host(card->host); | ||
279 | |||
280 | return err ? 0 : 1; | ||
281 | } | ||
282 | |||
283 | static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, | ||
284 | struct request *req) | ||
285 | { | ||
286 | struct mmc_blk_data *md = mq->data; | ||
287 | struct mmc_card *card = md->queue.card; | ||
288 | unsigned int from, nr, arg; | ||
289 | int err = 0; | ||
290 | |||
291 | mmc_claim_host(card->host); | ||
292 | |||
293 | if (!mmc_can_secure_erase_trim(card)) { | ||
294 | err = -EOPNOTSUPP; | ||
295 | goto out; | ||
296 | } | ||
297 | |||
298 | from = blk_rq_pos(req); | ||
299 | nr = blk_rq_sectors(req); | ||
300 | |||
301 | if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr)) | ||
302 | arg = MMC_SECURE_TRIM1_ARG; | ||
303 | else | ||
304 | arg = MMC_SECURE_ERASE_ARG; | ||
305 | |||
306 | err = mmc_erase(card, from, nr, arg); | ||
307 | if (!err && arg == MMC_SECURE_TRIM1_ARG) | ||
308 | err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG); | ||
309 | out: | ||
310 | spin_lock_irq(&md->lock); | ||
311 | __blk_end_request(req, err, blk_rq_bytes(req)); | ||
312 | spin_unlock_irq(&md->lock); | ||
313 | |||
314 | mmc_release_host(card->host); | ||
315 | |||
316 | return err ? 0 : 1; | ||
317 | } | ||
318 | |||
319 | static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) | ||
251 | { | 320 | { |
252 | struct mmc_blk_data *md = mq->data; | 321 | struct mmc_blk_data *md = mq->data; |
253 | struct mmc_card *card = md->queue.card; | 322 | struct mmc_card *card = md->queue.card; |
@@ -475,6 +544,17 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
475 | return 0; | 544 | return 0; |
476 | } | 545 | } |
477 | 546 | ||
547 | static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | ||
548 | { | ||
549 | if (req->cmd_flags & REQ_DISCARD) { | ||
550 | if (req->cmd_flags & REQ_SECURE) | ||
551 | return mmc_blk_issue_secdiscard_rq(mq, req); | ||
552 | else | ||
553 | return mmc_blk_issue_discard_rq(mq, req); | ||
554 | } else { | ||
555 | return mmc_blk_issue_rw_rq(mq, req); | ||
556 | } | ||
557 | } | ||
478 | 558 | ||
479 | static inline int mmc_blk_readonly(struct mmc_card *card) | 559 | static inline int mmc_blk_readonly(struct mmc_card *card) |
480 | { | 560 | { |
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index 445d7db2277e..5dd8576b5c18 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | 17 | ||
18 | #include <linux/scatterlist.h> | 18 | #include <linux/scatterlist.h> |
19 | #include <linux/swap.h> /* For nr_free_buffer_pages() */ | ||
19 | 20 | ||
20 | #define RESULT_OK 0 | 21 | #define RESULT_OK 0 |
21 | #define RESULT_FAIL 1 | 22 | #define RESULT_FAIL 1 |
@@ -25,6 +26,60 @@ | |||
25 | #define BUFFER_ORDER 2 | 26 | #define BUFFER_ORDER 2 |
26 | #define BUFFER_SIZE (PAGE_SIZE << BUFFER_ORDER) | 27 | #define BUFFER_SIZE (PAGE_SIZE << BUFFER_ORDER) |
27 | 28 | ||
29 | /* | ||
30 | * Limit the test area size to the maximum MMC HC erase group size. Note that | ||
31 | * the maximum SD allocation unit size is just 4MiB. | ||
32 | */ | ||
33 | #define TEST_AREA_MAX_SIZE (128 * 1024 * 1024) | ||
34 | |||
35 | /** | ||
36 | * struct mmc_test_pages - pages allocated by 'alloc_pages()'. | ||
37 | * @page: first page in the allocation | ||
38 | * @order: order of the number of pages allocated | ||
39 | */ | ||
40 | struct mmc_test_pages { | ||
41 | struct page *page; | ||
42 | unsigned int order; | ||
43 | }; | ||
44 | |||
45 | /** | ||
46 | * struct mmc_test_mem - allocated memory. | ||
47 | * @arr: array of allocations | ||
48 | * @cnt: number of allocations | ||
49 | */ | ||
50 | struct mmc_test_mem { | ||
51 | struct mmc_test_pages *arr; | ||
52 | unsigned int cnt; | ||
53 | }; | ||
54 | |||
55 | /** | ||
56 | * struct mmc_test_area - information for performance tests. | ||
57 | * @max_sz: test area size (in bytes) | ||
58 | * @dev_addr: address on card at which to do performance tests | ||
59 | * @max_segs: maximum segments in scatterlist @sg | ||
60 | * @blocks: number of (512 byte) blocks currently mapped by @sg | ||
61 | * @sg_len: length of currently mapped scatterlist @sg | ||
62 | * @mem: allocated memory | ||
63 | * @sg: scatterlist | ||
64 | */ | ||
65 | struct mmc_test_area { | ||
66 | unsigned long max_sz; | ||
67 | unsigned int dev_addr; | ||
68 | unsigned int max_segs; | ||
69 | unsigned int blocks; | ||
70 | unsigned int sg_len; | ||
71 | struct mmc_test_mem *mem; | ||
72 | struct scatterlist *sg; | ||
73 | }; | ||
74 | |||
75 | /** | ||
76 | * struct mmc_test_card - test information. | ||
77 | * @card: card under test | ||
78 | * @scratch: transfer buffer | ||
79 | * @buffer: transfer buffer | ||
80 | * @highmem: buffer for highmem tests | ||
81 | * @area: information for performance tests | ||
82 | */ | ||
28 | struct mmc_test_card { | 83 | struct mmc_test_card { |
29 | struct mmc_card *card; | 84 | struct mmc_card *card; |
30 | 85 | ||
@@ -33,6 +88,7 @@ struct mmc_test_card { | |||
33 | #ifdef CONFIG_HIGHMEM | 88 | #ifdef CONFIG_HIGHMEM |
34 | struct page *highmem; | 89 | struct page *highmem; |
35 | #endif | 90 | #endif |
91 | struct mmc_test_area area; | ||
36 | }; | 92 | }; |
37 | 93 | ||
38 | /*******************************************************************/ | 94 | /*******************************************************************/ |
@@ -97,6 +153,12 @@ static void mmc_test_prepare_mrq(struct mmc_test_card *test, | |||
97 | mmc_set_data_timeout(mrq->data, test->card); | 153 | mmc_set_data_timeout(mrq->data, test->card); |
98 | } | 154 | } |
99 | 155 | ||
156 | static int mmc_test_busy(struct mmc_command *cmd) | ||
157 | { | ||
158 | return !(cmd->resp[0] & R1_READY_FOR_DATA) || | ||
159 | (R1_CURRENT_STATE(cmd->resp[0]) == 7); | ||
160 | } | ||
161 | |||
100 | /* | 162 | /* |
101 | * Wait for the card to finish the busy state | 163 | * Wait for the card to finish the busy state |
102 | */ | 164 | */ |
@@ -117,13 +179,13 @@ static int mmc_test_wait_busy(struct mmc_test_card *test) | |||
117 | if (ret) | 179 | if (ret) |
118 | break; | 180 | break; |
119 | 181 | ||
120 | if (!busy && !(cmd.resp[0] & R1_READY_FOR_DATA)) { | 182 | if (!busy && mmc_test_busy(&cmd)) { |
121 | busy = 1; | 183 | busy = 1; |
122 | printk(KERN_INFO "%s: Warning: Host did not " | 184 | printk(KERN_INFO "%s: Warning: Host did not " |
123 | "wait for busy state to end.\n", | 185 | "wait for busy state to end.\n", |
124 | mmc_hostname(test->card->host)); | 186 | mmc_hostname(test->card->host)); |
125 | } | 187 | } |
126 | } while (!(cmd.resp[0] & R1_READY_FOR_DATA)); | 188 | } while (mmc_test_busy(&cmd)); |
127 | 189 | ||
128 | return ret; | 190 | return ret; |
129 | } | 191 | } |
@@ -170,6 +232,248 @@ static int mmc_test_buffer_transfer(struct mmc_test_card *test, | |||
170 | return 0; | 232 | return 0; |
171 | } | 233 | } |
172 | 234 | ||
235 | static void mmc_test_free_mem(struct mmc_test_mem *mem) | ||
236 | { | ||
237 | if (!mem) | ||
238 | return; | ||
239 | while (mem->cnt--) | ||
240 | __free_pages(mem->arr[mem->cnt].page, | ||
241 | mem->arr[mem->cnt].order); | ||
242 | kfree(mem->arr); | ||
243 | kfree(mem); | ||
244 | } | ||
245 | |||
246 | /* | ||
247 | * Allocate a lot of memory, preferrably max_sz but at least min_sz. In case | ||
248 | * there isn't much memory do not exceed 1/16th total lowmem pages. | ||
249 | */ | ||
250 | static struct mmc_test_mem *mmc_test_alloc_mem(unsigned long min_sz, | ||
251 | unsigned long max_sz) | ||
252 | { | ||
253 | unsigned long max_page_cnt = DIV_ROUND_UP(max_sz, PAGE_SIZE); | ||
254 | unsigned long min_page_cnt = DIV_ROUND_UP(min_sz, PAGE_SIZE); | ||
255 | unsigned long page_cnt = 0; | ||
256 | unsigned long limit = nr_free_buffer_pages() >> 4; | ||
257 | struct mmc_test_mem *mem; | ||
258 | |||
259 | if (max_page_cnt > limit) | ||
260 | max_page_cnt = limit; | ||
261 | if (max_page_cnt < min_page_cnt) | ||
262 | max_page_cnt = min_page_cnt; | ||
263 | |||
264 | mem = kzalloc(sizeof(struct mmc_test_mem), GFP_KERNEL); | ||
265 | if (!mem) | ||
266 | return NULL; | ||
267 | |||
268 | mem->arr = kzalloc(sizeof(struct mmc_test_pages) * max_page_cnt, | ||
269 | GFP_KERNEL); | ||
270 | if (!mem->arr) | ||
271 | goto out_free; | ||
272 | |||
273 | while (max_page_cnt) { | ||
274 | struct page *page; | ||
275 | unsigned int order; | ||
276 | gfp_t flags = GFP_KERNEL | GFP_DMA | __GFP_NOWARN | | ||
277 | __GFP_NORETRY; | ||
278 | |||
279 | order = get_order(max_page_cnt << PAGE_SHIFT); | ||
280 | while (1) { | ||
281 | page = alloc_pages(flags, order); | ||
282 | if (page || !order) | ||
283 | break; | ||
284 | order -= 1; | ||
285 | } | ||
286 | if (!page) { | ||
287 | if (page_cnt < min_page_cnt) | ||
288 | goto out_free; | ||
289 | break; | ||
290 | } | ||
291 | mem->arr[mem->cnt].page = page; | ||
292 | mem->arr[mem->cnt].order = order; | ||
293 | mem->cnt += 1; | ||
294 | if (max_page_cnt <= (1UL << order)) | ||
295 | break; | ||
296 | max_page_cnt -= 1UL << order; | ||
297 | page_cnt += 1UL << order; | ||
298 | } | ||
299 | |||
300 | return mem; | ||
301 | |||
302 | out_free: | ||
303 | mmc_test_free_mem(mem); | ||
304 | return NULL; | ||
305 | } | ||
306 | |||
307 | /* | ||
308 | * Map memory into a scatterlist. Optionally allow the same memory to be | ||
309 | * mapped more than once. | ||
310 | */ | ||
311 | static int mmc_test_map_sg(struct mmc_test_mem *mem, unsigned long sz, | ||
312 | struct scatterlist *sglist, int repeat, | ||
313 | unsigned int max_segs, unsigned int *sg_len) | ||
314 | { | ||
315 | struct scatterlist *sg = NULL; | ||
316 | unsigned int i; | ||
317 | |||
318 | sg_init_table(sglist, max_segs); | ||
319 | |||
320 | *sg_len = 0; | ||
321 | do { | ||
322 | for (i = 0; i < mem->cnt; i++) { | ||
323 | unsigned long len = PAGE_SIZE << mem->arr[i].order; | ||
324 | |||
325 | if (sz < len) | ||
326 | len = sz; | ||
327 | if (sg) | ||
328 | sg = sg_next(sg); | ||
329 | else | ||
330 | sg = sglist; | ||
331 | if (!sg) | ||
332 | return -EINVAL; | ||
333 | sg_set_page(sg, mem->arr[i].page, len, 0); | ||
334 | sz -= len; | ||
335 | *sg_len += 1; | ||
336 | if (!sz) | ||
337 | break; | ||
338 | } | ||
339 | } while (sz && repeat); | ||
340 | |||
341 | if (sz) | ||
342 | return -EINVAL; | ||
343 | |||
344 | if (sg) | ||
345 | sg_mark_end(sg); | ||
346 | |||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | /* | ||
351 | * Map memory into a scatterlist so that no pages are contiguous. Allow the | ||
352 | * same memory to be mapped more than once. | ||
353 | */ | ||
354 | static int mmc_test_map_sg_max_scatter(struct mmc_test_mem *mem, | ||
355 | unsigned long sz, | ||
356 | struct scatterlist *sglist, | ||
357 | unsigned int max_segs, | ||
358 | unsigned int *sg_len) | ||
359 | { | ||
360 | struct scatterlist *sg = NULL; | ||
361 | unsigned int i = mem->cnt, cnt; | ||
362 | unsigned long len; | ||
363 | void *base, *addr, *last_addr = NULL; | ||
364 | |||
365 | sg_init_table(sglist, max_segs); | ||
366 | |||
367 | *sg_len = 0; | ||
368 | while (sz && i) { | ||
369 | base = page_address(mem->arr[--i].page); | ||
370 | cnt = 1 << mem->arr[i].order; | ||
371 | while (sz && cnt) { | ||
372 | addr = base + PAGE_SIZE * --cnt; | ||
373 | if (last_addr && last_addr + PAGE_SIZE == addr) | ||
374 | continue; | ||
375 | last_addr = addr; | ||
376 | len = PAGE_SIZE; | ||
377 | if (sz < len) | ||
378 | len = sz; | ||
379 | if (sg) | ||
380 | sg = sg_next(sg); | ||
381 | else | ||
382 | sg = sglist; | ||
383 | if (!sg) | ||
384 | return -EINVAL; | ||
385 | sg_set_page(sg, virt_to_page(addr), len, 0); | ||
386 | sz -= len; | ||
387 | *sg_len += 1; | ||
388 | } | ||
389 | } | ||
390 | |||
391 | if (sg) | ||
392 | sg_mark_end(sg); | ||
393 | |||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | /* | ||
398 | * Calculate transfer rate in bytes per second. | ||
399 | */ | ||
400 | static unsigned int mmc_test_rate(uint64_t bytes, struct timespec *ts) | ||
401 | { | ||
402 | uint64_t ns; | ||
403 | |||
404 | ns = ts->tv_sec; | ||
405 | ns *= 1000000000; | ||
406 | ns += ts->tv_nsec; | ||
407 | |||
408 | bytes *= 1000000000; | ||
409 | |||
410 | while (ns > UINT_MAX) { | ||
411 | bytes >>= 1; | ||
412 | ns >>= 1; | ||
413 | } | ||
414 | |||
415 | if (!ns) | ||
416 | return 0; | ||
417 | |||
418 | do_div(bytes, (uint32_t)ns); | ||
419 | |||
420 | return bytes; | ||
421 | } | ||
422 | |||
423 | /* | ||
424 | * Print the transfer rate. | ||
425 | */ | ||
426 | static void mmc_test_print_rate(struct mmc_test_card *test, uint64_t bytes, | ||
427 | struct timespec *ts1, struct timespec *ts2) | ||
428 | { | ||
429 | unsigned int rate, sectors = bytes >> 9; | ||
430 | struct timespec ts; | ||
431 | |||
432 | ts = timespec_sub(*ts2, *ts1); | ||
433 | |||
434 | rate = mmc_test_rate(bytes, &ts); | ||
435 | |||
436 | printk(KERN_INFO "%s: Transfer of %u sectors (%u%s KiB) took %lu.%09lu " | ||
437 | "seconds (%u kB/s, %u KiB/s)\n", | ||
438 | mmc_hostname(test->card->host), sectors, sectors >> 1, | ||
439 | (sectors == 1 ? ".5" : ""), (unsigned long)ts.tv_sec, | ||
440 | (unsigned long)ts.tv_nsec, rate / 1000, rate / 1024); | ||
441 | } | ||
442 | |||
443 | /* | ||
444 | * Print the average transfer rate. | ||
445 | */ | ||
446 | static void mmc_test_print_avg_rate(struct mmc_test_card *test, uint64_t bytes, | ||
447 | unsigned int count, struct timespec *ts1, | ||
448 | struct timespec *ts2) | ||
449 | { | ||
450 | unsigned int rate, sectors = bytes >> 9; | ||
451 | uint64_t tot = bytes * count; | ||
452 | struct timespec ts; | ||
453 | |||
454 | ts = timespec_sub(*ts2, *ts1); | ||
455 | |||
456 | rate = mmc_test_rate(tot, &ts); | ||
457 | |||
458 | printk(KERN_INFO "%s: Transfer of %u x %u sectors (%u x %u%s KiB) took " | ||
459 | "%lu.%09lu seconds (%u kB/s, %u KiB/s)\n", | ||
460 | mmc_hostname(test->card->host), count, sectors, count, | ||
461 | sectors >> 1, (sectors == 1 ? ".5" : ""), | ||
462 | (unsigned long)ts.tv_sec, (unsigned long)ts.tv_nsec, | ||
463 | rate / 1000, rate / 1024); | ||
464 | } | ||
465 | |||
466 | /* | ||
467 | * Return the card size in sectors. | ||
468 | */ | ||
469 | static unsigned int mmc_test_capacity(struct mmc_card *card) | ||
470 | { | ||
471 | if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) | ||
472 | return card->ext_csd.sectors; | ||
473 | else | ||
474 | return card->csd.capacity << (card->csd.read_blkbits - 9); | ||
475 | } | ||
476 | |||
173 | /*******************************************************************/ | 477 | /*******************************************************************/ |
174 | /* Test preparation and cleanup */ | 478 | /* Test preparation and cleanup */ |
175 | /*******************************************************************/ | 479 | /*******************************************************************/ |
@@ -893,8 +1197,419 @@ static int mmc_test_multi_read_high(struct mmc_test_card *test) | |||
893 | return 0; | 1197 | return 0; |
894 | } | 1198 | } |
895 | 1199 | ||
1200 | #else | ||
1201 | |||
1202 | static int mmc_test_no_highmem(struct mmc_test_card *test) | ||
1203 | { | ||
1204 | printk(KERN_INFO "%s: Highmem not configured - test skipped\n", | ||
1205 | mmc_hostname(test->card->host)); | ||
1206 | return 0; | ||
1207 | } | ||
1208 | |||
896 | #endif /* CONFIG_HIGHMEM */ | 1209 | #endif /* CONFIG_HIGHMEM */ |
897 | 1210 | ||
1211 | /* | ||
1212 | * Map sz bytes so that it can be transferred. | ||
1213 | */ | ||
1214 | static int mmc_test_area_map(struct mmc_test_card *test, unsigned long sz, | ||
1215 | int max_scatter) | ||
1216 | { | ||
1217 | struct mmc_test_area *t = &test->area; | ||
1218 | |||
1219 | t->blocks = sz >> 9; | ||
1220 | |||
1221 | if (max_scatter) { | ||
1222 | return mmc_test_map_sg_max_scatter(t->mem, sz, t->sg, | ||
1223 | t->max_segs, &t->sg_len); | ||
1224 | } else { | ||
1225 | return mmc_test_map_sg(t->mem, sz, t->sg, 1, t->max_segs, | ||
1226 | &t->sg_len); | ||
1227 | } | ||
1228 | } | ||
1229 | |||
1230 | /* | ||
1231 | * Transfer bytes mapped by mmc_test_area_map(). | ||
1232 | */ | ||
1233 | static int mmc_test_area_transfer(struct mmc_test_card *test, | ||
1234 | unsigned int dev_addr, int write) | ||
1235 | { | ||
1236 | struct mmc_test_area *t = &test->area; | ||
1237 | |||
1238 | return mmc_test_simple_transfer(test, t->sg, t->sg_len, dev_addr, | ||
1239 | t->blocks, 512, write); | ||
1240 | } | ||
1241 | |||
1242 | /* | ||
1243 | * Map and transfer bytes. | ||
1244 | */ | ||
1245 | static int mmc_test_area_io(struct mmc_test_card *test, unsigned long sz, | ||
1246 | unsigned int dev_addr, int write, int max_scatter, | ||
1247 | int timed) | ||
1248 | { | ||
1249 | struct timespec ts1, ts2; | ||
1250 | int ret; | ||
1251 | |||
1252 | ret = mmc_test_area_map(test, sz, max_scatter); | ||
1253 | if (ret) | ||
1254 | return ret; | ||
1255 | |||
1256 | if (timed) | ||
1257 | getnstimeofday(&ts1); | ||
1258 | |||
1259 | ret = mmc_test_area_transfer(test, dev_addr, write); | ||
1260 | if (ret) | ||
1261 | return ret; | ||
1262 | |||
1263 | if (timed) | ||
1264 | getnstimeofday(&ts2); | ||
1265 | |||
1266 | if (timed) | ||
1267 | mmc_test_print_rate(test, sz, &ts1, &ts2); | ||
1268 | |||
1269 | return 0; | ||
1270 | } | ||
1271 | |||
1272 | /* | ||
1273 | * Write the test area entirely. | ||
1274 | */ | ||
1275 | static int mmc_test_area_fill(struct mmc_test_card *test) | ||
1276 | { | ||
1277 | return mmc_test_area_io(test, test->area.max_sz, test->area.dev_addr, | ||
1278 | 1, 0, 0); | ||
1279 | } | ||
1280 | |||
1281 | /* | ||
1282 | * Erase the test area entirely. | ||
1283 | */ | ||
1284 | static int mmc_test_area_erase(struct mmc_test_card *test) | ||
1285 | { | ||
1286 | struct mmc_test_area *t = &test->area; | ||
1287 | |||
1288 | if (!mmc_can_erase(test->card)) | ||
1289 | return 0; | ||
1290 | |||
1291 | return mmc_erase(test->card, t->dev_addr, test->area.max_sz >> 9, | ||
1292 | MMC_ERASE_ARG); | ||
1293 | } | ||
1294 | |||
1295 | /* | ||
1296 | * Cleanup struct mmc_test_area. | ||
1297 | */ | ||
1298 | static int mmc_test_area_cleanup(struct mmc_test_card *test) | ||
1299 | { | ||
1300 | struct mmc_test_area *t = &test->area; | ||
1301 | |||
1302 | kfree(t->sg); | ||
1303 | mmc_test_free_mem(t->mem); | ||
1304 | |||
1305 | return 0; | ||
1306 | } | ||
1307 | |||
1308 | /* | ||
1309 | * Initialize an area for testing large transfers. The size of the area is the | ||
1310 | * preferred erase size which is a good size for optimal transfer speed. Note | ||
1311 | * that is typically 4MiB for modern cards. The test area is set to the middle | ||
1312 | * of the card because cards may have different charateristics at the front | ||
1313 | * (for FAT file system optimization). Optionally, the area is erased (if the | ||
1314 | * card supports it) which may improve write performance. Optionally, the area | ||
1315 | * is filled with data for subsequent read tests. | ||
1316 | */ | ||
1317 | static int mmc_test_area_init(struct mmc_test_card *test, int erase, int fill) | ||
1318 | { | ||
1319 | struct mmc_test_area *t = &test->area; | ||
1320 | unsigned long min_sz = 64 * 1024; | ||
1321 | int ret; | ||
1322 | |||
1323 | ret = mmc_test_set_blksize(test, 512); | ||
1324 | if (ret) | ||
1325 | return ret; | ||
1326 | |||
1327 | if (test->card->pref_erase > TEST_AREA_MAX_SIZE >> 9) | ||
1328 | t->max_sz = TEST_AREA_MAX_SIZE; | ||
1329 | else | ||
1330 | t->max_sz = (unsigned long)test->card->pref_erase << 9; | ||
1331 | /* | ||
1332 | * Try to allocate enough memory for the whole area. Less is OK | ||
1333 | * because the same memory can be mapped into the scatterlist more than | ||
1334 | * once. | ||
1335 | */ | ||
1336 | t->mem = mmc_test_alloc_mem(min_sz, t->max_sz); | ||
1337 | if (!t->mem) | ||
1338 | return -ENOMEM; | ||
1339 | |||
1340 | t->max_segs = DIV_ROUND_UP(t->max_sz, PAGE_SIZE); | ||
1341 | t->sg = kmalloc(sizeof(struct scatterlist) * t->max_segs, GFP_KERNEL); | ||
1342 | if (!t->sg) { | ||
1343 | ret = -ENOMEM; | ||
1344 | goto out_free; | ||
1345 | } | ||
1346 | |||
1347 | t->dev_addr = mmc_test_capacity(test->card) / 2; | ||
1348 | t->dev_addr -= t->dev_addr % (t->max_sz >> 9); | ||
1349 | |||
1350 | if (erase) { | ||
1351 | ret = mmc_test_area_erase(test); | ||
1352 | if (ret) | ||
1353 | goto out_free; | ||
1354 | } | ||
1355 | |||
1356 | if (fill) { | ||
1357 | ret = mmc_test_area_fill(test); | ||
1358 | if (ret) | ||
1359 | goto out_free; | ||
1360 | } | ||
1361 | |||
1362 | return 0; | ||
1363 | |||
1364 | out_free: | ||
1365 | mmc_test_area_cleanup(test); | ||
1366 | return ret; | ||
1367 | } | ||
1368 | |||
1369 | /* | ||
1370 | * Prepare for large transfers. Do not erase the test area. | ||
1371 | */ | ||
1372 | static int mmc_test_area_prepare(struct mmc_test_card *test) | ||
1373 | { | ||
1374 | return mmc_test_area_init(test, 0, 0); | ||
1375 | } | ||
1376 | |||
1377 | /* | ||
1378 | * Prepare for large transfers. Do erase the test area. | ||
1379 | */ | ||
1380 | static int mmc_test_area_prepare_erase(struct mmc_test_card *test) | ||
1381 | { | ||
1382 | return mmc_test_area_init(test, 1, 0); | ||
1383 | } | ||
1384 | |||
1385 | /* | ||
1386 | * Prepare for large transfers. Erase and fill the test area. | ||
1387 | */ | ||
1388 | static int mmc_test_area_prepare_fill(struct mmc_test_card *test) | ||
1389 | { | ||
1390 | return mmc_test_area_init(test, 1, 1); | ||
1391 | } | ||
1392 | |||
1393 | /* | ||
1394 | * Test best-case performance. Best-case performance is expected from | ||
1395 | * a single large transfer. | ||
1396 | * | ||
1397 | * An additional option (max_scatter) allows the measurement of the same | ||
1398 | * transfer but with no contiguous pages in the scatter list. This tests | ||
1399 | * the efficiency of DMA to handle scattered pages. | ||
1400 | */ | ||
1401 | static int mmc_test_best_performance(struct mmc_test_card *test, int write, | ||
1402 | int max_scatter) | ||
1403 | { | ||
1404 | return mmc_test_area_io(test, test->area.max_sz, test->area.dev_addr, | ||
1405 | write, max_scatter, 1); | ||
1406 | } | ||
1407 | |||
1408 | /* | ||
1409 | * Best-case read performance. | ||
1410 | */ | ||
1411 | static int mmc_test_best_read_performance(struct mmc_test_card *test) | ||
1412 | { | ||
1413 | return mmc_test_best_performance(test, 0, 0); | ||
1414 | } | ||
1415 | |||
1416 | /* | ||
1417 | * Best-case write performance. | ||
1418 | */ | ||
1419 | static int mmc_test_best_write_performance(struct mmc_test_card *test) | ||
1420 | { | ||
1421 | return mmc_test_best_performance(test, 1, 0); | ||
1422 | } | ||
1423 | |||
1424 | /* | ||
1425 | * Best-case read performance into scattered pages. | ||
1426 | */ | ||
1427 | static int mmc_test_best_read_perf_max_scatter(struct mmc_test_card *test) | ||
1428 | { | ||
1429 | return mmc_test_best_performance(test, 0, 1); | ||
1430 | } | ||
1431 | |||
1432 | /* | ||
1433 | * Best-case write performance from scattered pages. | ||
1434 | */ | ||
1435 | static int mmc_test_best_write_perf_max_scatter(struct mmc_test_card *test) | ||
1436 | { | ||
1437 | return mmc_test_best_performance(test, 1, 1); | ||
1438 | } | ||
1439 | |||
1440 | /* | ||
1441 | * Single read performance by transfer size. | ||
1442 | */ | ||
1443 | static int mmc_test_profile_read_perf(struct mmc_test_card *test) | ||
1444 | { | ||
1445 | unsigned long sz; | ||
1446 | unsigned int dev_addr; | ||
1447 | int ret; | ||
1448 | |||
1449 | for (sz = 512; sz < test->area.max_sz; sz <<= 1) { | ||
1450 | dev_addr = test->area.dev_addr + (sz >> 9); | ||
1451 | ret = mmc_test_area_io(test, sz, dev_addr, 0, 0, 1); | ||
1452 | if (ret) | ||
1453 | return ret; | ||
1454 | } | ||
1455 | dev_addr = test->area.dev_addr; | ||
1456 | return mmc_test_area_io(test, sz, dev_addr, 0, 0, 1); | ||
1457 | } | ||
1458 | |||
1459 | /* | ||
1460 | * Single write performance by transfer size. | ||
1461 | */ | ||
1462 | static int mmc_test_profile_write_perf(struct mmc_test_card *test) | ||
1463 | { | ||
1464 | unsigned long sz; | ||
1465 | unsigned int dev_addr; | ||
1466 | int ret; | ||
1467 | |||
1468 | ret = mmc_test_area_erase(test); | ||
1469 | if (ret) | ||
1470 | return ret; | ||
1471 | for (sz = 512; sz < test->area.max_sz; sz <<= 1) { | ||
1472 | dev_addr = test->area.dev_addr + (sz >> 9); | ||
1473 | ret = mmc_test_area_io(test, sz, dev_addr, 1, 0, 1); | ||
1474 | if (ret) | ||
1475 | return ret; | ||
1476 | } | ||
1477 | ret = mmc_test_area_erase(test); | ||
1478 | if (ret) | ||
1479 | return ret; | ||
1480 | dev_addr = test->area.dev_addr; | ||
1481 | return mmc_test_area_io(test, sz, dev_addr, 1, 0, 1); | ||
1482 | } | ||
1483 | |||
1484 | /* | ||
1485 | * Single trim performance by transfer size. | ||
1486 | */ | ||
1487 | static int mmc_test_profile_trim_perf(struct mmc_test_card *test) | ||
1488 | { | ||
1489 | unsigned long sz; | ||
1490 | unsigned int dev_addr; | ||
1491 | struct timespec ts1, ts2; | ||
1492 | int ret; | ||
1493 | |||
1494 | if (!mmc_can_trim(test->card)) | ||
1495 | return RESULT_UNSUP_CARD; | ||
1496 | |||
1497 | if (!mmc_can_erase(test->card)) | ||
1498 | return RESULT_UNSUP_HOST; | ||
1499 | |||
1500 | for (sz = 512; sz < test->area.max_sz; sz <<= 1) { | ||
1501 | dev_addr = test->area.dev_addr + (sz >> 9); | ||
1502 | getnstimeofday(&ts1); | ||
1503 | ret = mmc_erase(test->card, dev_addr, sz >> 9, MMC_TRIM_ARG); | ||
1504 | if (ret) | ||
1505 | return ret; | ||
1506 | getnstimeofday(&ts2); | ||
1507 | mmc_test_print_rate(test, sz, &ts1, &ts2); | ||
1508 | } | ||
1509 | dev_addr = test->area.dev_addr; | ||
1510 | getnstimeofday(&ts1); | ||
1511 | ret = mmc_erase(test->card, dev_addr, sz >> 9, MMC_TRIM_ARG); | ||
1512 | if (ret) | ||
1513 | return ret; | ||
1514 | getnstimeofday(&ts2); | ||
1515 | mmc_test_print_rate(test, sz, &ts1, &ts2); | ||
1516 | return 0; | ||
1517 | } | ||
1518 | |||
1519 | /* | ||
1520 | * Consecutive read performance by transfer size. | ||
1521 | */ | ||
1522 | static int mmc_test_profile_seq_read_perf(struct mmc_test_card *test) | ||
1523 | { | ||
1524 | unsigned long sz; | ||
1525 | unsigned int dev_addr, i, cnt; | ||
1526 | struct timespec ts1, ts2; | ||
1527 | int ret; | ||
1528 | |||
1529 | for (sz = 512; sz <= test->area.max_sz; sz <<= 1) { | ||
1530 | cnt = test->area.max_sz / sz; | ||
1531 | dev_addr = test->area.dev_addr; | ||
1532 | getnstimeofday(&ts1); | ||
1533 | for (i = 0; i < cnt; i++) { | ||
1534 | ret = mmc_test_area_io(test, sz, dev_addr, 0, 0, 0); | ||
1535 | if (ret) | ||
1536 | return ret; | ||
1537 | dev_addr += (sz >> 9); | ||
1538 | } | ||
1539 | getnstimeofday(&ts2); | ||
1540 | mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2); | ||
1541 | } | ||
1542 | return 0; | ||
1543 | } | ||
1544 | |||
1545 | /* | ||
1546 | * Consecutive write performance by transfer size. | ||
1547 | */ | ||
1548 | static int mmc_test_profile_seq_write_perf(struct mmc_test_card *test) | ||
1549 | { | ||
1550 | unsigned long sz; | ||
1551 | unsigned int dev_addr, i, cnt; | ||
1552 | struct timespec ts1, ts2; | ||
1553 | int ret; | ||
1554 | |||
1555 | for (sz = 512; sz <= test->area.max_sz; sz <<= 1) { | ||
1556 | ret = mmc_test_area_erase(test); | ||
1557 | if (ret) | ||
1558 | return ret; | ||
1559 | cnt = test->area.max_sz / sz; | ||
1560 | dev_addr = test->area.dev_addr; | ||
1561 | getnstimeofday(&ts1); | ||
1562 | for (i = 0; i < cnt; i++) { | ||
1563 | ret = mmc_test_area_io(test, sz, dev_addr, 1, 0, 0); | ||
1564 | if (ret) | ||
1565 | return ret; | ||
1566 | dev_addr += (sz >> 9); | ||
1567 | } | ||
1568 | getnstimeofday(&ts2); | ||
1569 | mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2); | ||
1570 | } | ||
1571 | return 0; | ||
1572 | } | ||
1573 | |||
1574 | /* | ||
1575 | * Consecutive trim performance by transfer size. | ||
1576 | */ | ||
1577 | static int mmc_test_profile_seq_trim_perf(struct mmc_test_card *test) | ||
1578 | { | ||
1579 | unsigned long sz; | ||
1580 | unsigned int dev_addr, i, cnt; | ||
1581 | struct timespec ts1, ts2; | ||
1582 | int ret; | ||
1583 | |||
1584 | if (!mmc_can_trim(test->card)) | ||
1585 | return RESULT_UNSUP_CARD; | ||
1586 | |||
1587 | if (!mmc_can_erase(test->card)) | ||
1588 | return RESULT_UNSUP_HOST; | ||
1589 | |||
1590 | for (sz = 512; sz <= test->area.max_sz; sz <<= 1) { | ||
1591 | ret = mmc_test_area_erase(test); | ||
1592 | if (ret) | ||
1593 | return ret; | ||
1594 | ret = mmc_test_area_fill(test); | ||
1595 | if (ret) | ||
1596 | return ret; | ||
1597 | cnt = test->area.max_sz / sz; | ||
1598 | dev_addr = test->area.dev_addr; | ||
1599 | getnstimeofday(&ts1); | ||
1600 | for (i = 0; i < cnt; i++) { | ||
1601 | ret = mmc_erase(test->card, dev_addr, sz >> 9, | ||
1602 | MMC_TRIM_ARG); | ||
1603 | if (ret) | ||
1604 | return ret; | ||
1605 | dev_addr += (sz >> 9); | ||
1606 | } | ||
1607 | getnstimeofday(&ts2); | ||
1608 | mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2); | ||
1609 | } | ||
1610 | return 0; | ||
1611 | } | ||
1612 | |||
898 | static const struct mmc_test_case mmc_test_cases[] = { | 1613 | static const struct mmc_test_case mmc_test_cases[] = { |
899 | { | 1614 | { |
900 | .name = "Basic write (no data verification)", | 1615 | .name = "Basic write (no data verification)", |
@@ -1040,8 +1755,100 @@ static const struct mmc_test_case mmc_test_cases[] = { | |||
1040 | .cleanup = mmc_test_cleanup, | 1755 | .cleanup = mmc_test_cleanup, |
1041 | }, | 1756 | }, |
1042 | 1757 | ||
1758 | #else | ||
1759 | |||
1760 | { | ||
1761 | .name = "Highmem write", | ||
1762 | .run = mmc_test_no_highmem, | ||
1763 | }, | ||
1764 | |||
1765 | { | ||
1766 | .name = "Highmem read", | ||
1767 | .run = mmc_test_no_highmem, | ||
1768 | }, | ||
1769 | |||
1770 | { | ||
1771 | .name = "Multi-block highmem write", | ||
1772 | .run = mmc_test_no_highmem, | ||
1773 | }, | ||
1774 | |||
1775 | { | ||
1776 | .name = "Multi-block highmem read", | ||
1777 | .run = mmc_test_no_highmem, | ||
1778 | }, | ||
1779 | |||
1043 | #endif /* CONFIG_HIGHMEM */ | 1780 | #endif /* CONFIG_HIGHMEM */ |
1044 | 1781 | ||
1782 | { | ||
1783 | .name = "Best-case read performance", | ||
1784 | .prepare = mmc_test_area_prepare_fill, | ||
1785 | .run = mmc_test_best_read_performance, | ||
1786 | .cleanup = mmc_test_area_cleanup, | ||
1787 | }, | ||
1788 | |||
1789 | { | ||
1790 | .name = "Best-case write performance", | ||
1791 | .prepare = mmc_test_area_prepare_erase, | ||
1792 | .run = mmc_test_best_write_performance, | ||
1793 | .cleanup = mmc_test_area_cleanup, | ||
1794 | }, | ||
1795 | |||
1796 | { | ||
1797 | .name = "Best-case read performance into scattered pages", | ||
1798 | .prepare = mmc_test_area_prepare_fill, | ||
1799 | .run = mmc_test_best_read_perf_max_scatter, | ||
1800 | .cleanup = mmc_test_area_cleanup, | ||
1801 | }, | ||
1802 | |||
1803 | { | ||
1804 | .name = "Best-case write performance from scattered pages", | ||
1805 | .prepare = mmc_test_area_prepare_erase, | ||
1806 | .run = mmc_test_best_write_perf_max_scatter, | ||
1807 | .cleanup = mmc_test_area_cleanup, | ||
1808 | }, | ||
1809 | |||
1810 | { | ||
1811 | .name = "Single read performance by transfer size", | ||
1812 | .prepare = mmc_test_area_prepare_fill, | ||
1813 | .run = mmc_test_profile_read_perf, | ||
1814 | .cleanup = mmc_test_area_cleanup, | ||
1815 | }, | ||
1816 | |||
1817 | { | ||
1818 | .name = "Single write performance by transfer size", | ||
1819 | .prepare = mmc_test_area_prepare, | ||
1820 | .run = mmc_test_profile_write_perf, | ||
1821 | .cleanup = mmc_test_area_cleanup, | ||
1822 | }, | ||
1823 | |||
1824 | { | ||
1825 | .name = "Single trim performance by transfer size", | ||
1826 | .prepare = mmc_test_area_prepare_fill, | ||
1827 | .run = mmc_test_profile_trim_perf, | ||
1828 | .cleanup = mmc_test_area_cleanup, | ||
1829 | }, | ||
1830 | |||
1831 | { | ||
1832 | .name = "Consecutive read performance by transfer size", | ||
1833 | .prepare = mmc_test_area_prepare_fill, | ||
1834 | .run = mmc_test_profile_seq_read_perf, | ||
1835 | .cleanup = mmc_test_area_cleanup, | ||
1836 | }, | ||
1837 | |||
1838 | { | ||
1839 | .name = "Consecutive write performance by transfer size", | ||
1840 | .prepare = mmc_test_area_prepare, | ||
1841 | .run = mmc_test_profile_seq_write_perf, | ||
1842 | .cleanup = mmc_test_area_cleanup, | ||
1843 | }, | ||
1844 | |||
1845 | { | ||
1846 | .name = "Consecutive trim performance by transfer size", | ||
1847 | .prepare = mmc_test_area_prepare, | ||
1848 | .run = mmc_test_profile_seq_trim_perf, | ||
1849 | .cleanup = mmc_test_area_cleanup, | ||
1850 | }, | ||
1851 | |||
1045 | }; | 1852 | }; |
1046 | 1853 | ||
1047 | static DEFINE_MUTEX(mmc_test_lock); | 1854 | static DEFINE_MUTEX(mmc_test_lock); |
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index c77eb49eda0e..e876678176be 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c | |||
@@ -30,9 +30,9 @@ | |||
30 | static int mmc_prep_request(struct request_queue *q, struct request *req) | 30 | static int mmc_prep_request(struct request_queue *q, struct request *req) |
31 | { | 31 | { |
32 | /* | 32 | /* |
33 | * We only like normal block requests. | 33 | * We only like normal block requests and discards. |
34 | */ | 34 | */ |
35 | if (req->cmd_type != REQ_TYPE_FS) { | 35 | if (req->cmd_type != REQ_TYPE_FS && !(req->cmd_flags & REQ_DISCARD)) { |
36 | blk_dump_rq_flags(req, "MMC bad request"); | 36 | blk_dump_rq_flags(req, "MMC bad request"); |
37 | return BLKPREP_KILL; | 37 | return BLKPREP_KILL; |
38 | } | 38 | } |
@@ -130,6 +130,21 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock | |||
130 | blk_queue_prep_rq(mq->queue, mmc_prep_request); | 130 | blk_queue_prep_rq(mq->queue, mmc_prep_request); |
131 | blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN); | 131 | blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN); |
132 | queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue); | 132 | queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue); |
133 | if (mmc_can_erase(card)) { | ||
134 | queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mq->queue); | ||
135 | mq->queue->limits.max_discard_sectors = UINT_MAX; | ||
136 | if (card->erased_byte == 0) | ||
137 | mq->queue->limits.discard_zeroes_data = 1; | ||
138 | if (!mmc_can_trim(card) && is_power_of_2(card->erase_size)) { | ||
139 | mq->queue->limits.discard_granularity = | ||
140 | card->erase_size << 9; | ||
141 | mq->queue->limits.discard_alignment = | ||
142 | card->erase_size << 9; | ||
143 | } | ||
144 | if (mmc_can_secure_erase_trim(card)) | ||
145 | queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, | ||
146 | mq->queue); | ||
147 | } | ||
133 | 148 | ||
134 | #ifdef CONFIG_MMC_BLOCK_BOUNCE | 149 | #ifdef CONFIG_MMC_BLOCK_BOUNCE |
135 | if (host->max_hw_segs == 1) { | 150 | if (host->max_hw_segs == 1) { |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 83240faa1dc8..5db49b124ffa 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -1050,6 +1050,352 @@ void mmc_detect_change(struct mmc_host *host, unsigned long delay) | |||
1050 | 1050 | ||
1051 | EXPORT_SYMBOL(mmc_detect_change); | 1051 | EXPORT_SYMBOL(mmc_detect_change); |
1052 | 1052 | ||
1053 | void mmc_init_erase(struct mmc_card *card) | ||
1054 | { | ||
1055 | unsigned int sz; | ||
1056 | |||
1057 | if (is_power_of_2(card->erase_size)) | ||
1058 | card->erase_shift = ffs(card->erase_size) - 1; | ||
1059 | else | ||
1060 | card->erase_shift = 0; | ||
1061 | |||
1062 | /* | ||
1063 | * It is possible to erase an arbitrarily large area of an SD or MMC | ||
1064 | * card. That is not desirable because it can take a long time | ||
1065 | * (minutes) potentially delaying more important I/O, and also the | ||
1066 | * timeout calculations become increasingly hugely over-estimated. | ||
1067 | * Consequently, 'pref_erase' is defined as a guide to limit erases | ||
1068 | * to that size and alignment. | ||
1069 | * | ||
1070 | * For SD cards that define Allocation Unit size, limit erases to one | ||
1071 | * Allocation Unit at a time. For MMC cards that define High Capacity | ||
1072 | * Erase Size, whether it is switched on or not, limit to that size. | ||
1073 | * Otherwise just have a stab at a good value. For modern cards it | ||
1074 | * will end up being 4MiB. Note that if the value is too small, it | ||
1075 | * can end up taking longer to erase. | ||
1076 | */ | ||
1077 | if (mmc_card_sd(card) && card->ssr.au) { | ||
1078 | card->pref_erase = card->ssr.au; | ||
1079 | card->erase_shift = ffs(card->ssr.au) - 1; | ||
1080 | } else if (card->ext_csd.hc_erase_size) { | ||
1081 | card->pref_erase = card->ext_csd.hc_erase_size; | ||
1082 | } else { | ||
1083 | sz = (card->csd.capacity << (card->csd.read_blkbits - 9)) >> 11; | ||
1084 | if (sz < 128) | ||
1085 | card->pref_erase = 512 * 1024 / 512; | ||
1086 | else if (sz < 512) | ||
1087 | card->pref_erase = 1024 * 1024 / 512; | ||
1088 | else if (sz < 1024) | ||
1089 | card->pref_erase = 2 * 1024 * 1024 / 512; | ||
1090 | else | ||
1091 | card->pref_erase = 4 * 1024 * 1024 / 512; | ||
1092 | if (card->pref_erase < card->erase_size) | ||
1093 | card->pref_erase = card->erase_size; | ||
1094 | else { | ||
1095 | sz = card->pref_erase % card->erase_size; | ||
1096 | if (sz) | ||
1097 | card->pref_erase += card->erase_size - sz; | ||
1098 | } | ||
1099 | } | ||
1100 | } | ||
1101 | |||
1102 | static void mmc_set_mmc_erase_timeout(struct mmc_card *card, | ||
1103 | struct mmc_command *cmd, | ||
1104 | unsigned int arg, unsigned int qty) | ||
1105 | { | ||
1106 | unsigned int erase_timeout; | ||
1107 | |||
1108 | if (card->ext_csd.erase_group_def & 1) { | ||
1109 | /* High Capacity Erase Group Size uses HC timeouts */ | ||
1110 | if (arg == MMC_TRIM_ARG) | ||
1111 | erase_timeout = card->ext_csd.trim_timeout; | ||
1112 | else | ||
1113 | erase_timeout = card->ext_csd.hc_erase_timeout; | ||
1114 | } else { | ||
1115 | /* CSD Erase Group Size uses write timeout */ | ||
1116 | unsigned int mult = (10 << card->csd.r2w_factor); | ||
1117 | unsigned int timeout_clks = card->csd.tacc_clks * mult; | ||
1118 | unsigned int timeout_us; | ||
1119 | |||
1120 | /* Avoid overflow: e.g. tacc_ns=80000000 mult=1280 */ | ||
1121 | if (card->csd.tacc_ns < 1000000) | ||
1122 | timeout_us = (card->csd.tacc_ns * mult) / 1000; | ||
1123 | else | ||
1124 | timeout_us = (card->csd.tacc_ns / 1000) * mult; | ||
1125 | |||
1126 | /* | ||
1127 | * ios.clock is only a target. The real clock rate might be | ||
1128 | * less but not that much less, so fudge it by multiplying by 2. | ||
1129 | */ | ||
1130 | timeout_clks <<= 1; | ||
1131 | timeout_us += (timeout_clks * 1000) / | ||
1132 | (card->host->ios.clock / 1000); | ||
1133 | |||
1134 | erase_timeout = timeout_us / 1000; | ||
1135 | |||
1136 | /* | ||
1137 | * Theoretically, the calculation could underflow so round up | ||
1138 | * to 1ms in that case. | ||
1139 | */ | ||
1140 | if (!erase_timeout) | ||
1141 | erase_timeout = 1; | ||
1142 | } | ||
1143 | |||
1144 | /* Multiplier for secure operations */ | ||
1145 | if (arg & MMC_SECURE_ARGS) { | ||
1146 | if (arg == MMC_SECURE_ERASE_ARG) | ||
1147 | erase_timeout *= card->ext_csd.sec_erase_mult; | ||
1148 | else | ||
1149 | erase_timeout *= card->ext_csd.sec_trim_mult; | ||
1150 | } | ||
1151 | |||
1152 | erase_timeout *= qty; | ||
1153 | |||
1154 | /* | ||
1155 | * Ensure at least a 1 second timeout for SPI as per | ||
1156 | * 'mmc_set_data_timeout()' | ||
1157 | */ | ||
1158 | if (mmc_host_is_spi(card->host) && erase_timeout < 1000) | ||
1159 | erase_timeout = 1000; | ||
1160 | |||
1161 | cmd->erase_timeout = erase_timeout; | ||
1162 | } | ||
1163 | |||
1164 | static void mmc_set_sd_erase_timeout(struct mmc_card *card, | ||
1165 | struct mmc_command *cmd, unsigned int arg, | ||
1166 | unsigned int qty) | ||
1167 | { | ||
1168 | if (card->ssr.erase_timeout) { | ||
1169 | /* Erase timeout specified in SD Status Register (SSR) */ | ||
1170 | cmd->erase_timeout = card->ssr.erase_timeout * qty + | ||
1171 | card->ssr.erase_offset; | ||
1172 | } else { | ||
1173 | /* | ||
1174 | * Erase timeout not specified in SD Status Register (SSR) so | ||
1175 | * use 250ms per write block. | ||
1176 | */ | ||
1177 | cmd->erase_timeout = 250 * qty; | ||
1178 | } | ||
1179 | |||
1180 | /* Must not be less than 1 second */ | ||
1181 | if (cmd->erase_timeout < 1000) | ||
1182 | cmd->erase_timeout = 1000; | ||
1183 | } | ||
1184 | |||
1185 | static void mmc_set_erase_timeout(struct mmc_card *card, | ||
1186 | struct mmc_command *cmd, unsigned int arg, | ||
1187 | unsigned int qty) | ||
1188 | { | ||
1189 | if (mmc_card_sd(card)) | ||
1190 | mmc_set_sd_erase_timeout(card, cmd, arg, qty); | ||
1191 | else | ||
1192 | mmc_set_mmc_erase_timeout(card, cmd, arg, qty); | ||
1193 | } | ||
1194 | |||
1195 | static int mmc_do_erase(struct mmc_card *card, unsigned int from, | ||
1196 | unsigned int to, unsigned int arg) | ||
1197 | { | ||
1198 | struct mmc_command cmd; | ||
1199 | unsigned int qty = 0; | ||
1200 | int err; | ||
1201 | |||
1202 | /* | ||
1203 | * qty is used to calculate the erase timeout which depends on how many | ||
1204 | * erase groups (or allocation units in SD terminology) are affected. | ||
1205 | * We count erasing part of an erase group as one erase group. | ||
1206 | * For SD, the allocation units are always a power of 2. For MMC, the | ||
1207 | * erase group size is almost certainly also power of 2, but it does not | ||
1208 | * seem to insist on that in the JEDEC standard, so we fall back to | ||
1209 | * division in that case. SD may not specify an allocation unit size, | ||
1210 | * in which case the timeout is based on the number of write blocks. | ||
1211 | * | ||
1212 | * Note that the timeout for secure trim 2 will only be correct if the | ||
1213 | * number of erase groups specified is the same as the total of all | ||
1214 | * preceding secure trim 1 commands. Since the power may have been | ||
1215 | * lost since the secure trim 1 commands occurred, it is generally | ||
1216 | * impossible to calculate the secure trim 2 timeout correctly. | ||
1217 | */ | ||
1218 | if (card->erase_shift) | ||
1219 | qty += ((to >> card->erase_shift) - | ||
1220 | (from >> card->erase_shift)) + 1; | ||
1221 | else if (mmc_card_sd(card)) | ||
1222 | qty += to - from + 1; | ||
1223 | else | ||
1224 | qty += ((to / card->erase_size) - | ||
1225 | (from / card->erase_size)) + 1; | ||
1226 | |||
1227 | if (!mmc_card_blockaddr(card)) { | ||
1228 | from <<= 9; | ||
1229 | to <<= 9; | ||
1230 | } | ||
1231 | |||
1232 | memset(&cmd, 0, sizeof(struct mmc_command)); | ||
1233 | if (mmc_card_sd(card)) | ||
1234 | cmd.opcode = SD_ERASE_WR_BLK_START; | ||
1235 | else | ||
1236 | cmd.opcode = MMC_ERASE_GROUP_START; | ||
1237 | cmd.arg = from; | ||
1238 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; | ||
1239 | err = mmc_wait_for_cmd(card->host, &cmd, 0); | ||
1240 | if (err) { | ||
1241 | printk(KERN_ERR "mmc_erase: group start error %d, " | ||
1242 | "status %#x\n", err, cmd.resp[0]); | ||
1243 | err = -EINVAL; | ||
1244 | goto out; | ||
1245 | } | ||
1246 | |||
1247 | memset(&cmd, 0, sizeof(struct mmc_command)); | ||
1248 | if (mmc_card_sd(card)) | ||
1249 | cmd.opcode = SD_ERASE_WR_BLK_END; | ||
1250 | else | ||
1251 | cmd.opcode = MMC_ERASE_GROUP_END; | ||
1252 | cmd.arg = to; | ||
1253 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; | ||
1254 | err = mmc_wait_for_cmd(card->host, &cmd, 0); | ||
1255 | if (err) { | ||
1256 | printk(KERN_ERR "mmc_erase: group end error %d, status %#x\n", | ||
1257 | err, cmd.resp[0]); | ||
1258 | err = -EINVAL; | ||
1259 | goto out; | ||
1260 | } | ||
1261 | |||
1262 | memset(&cmd, 0, sizeof(struct mmc_command)); | ||
1263 | cmd.opcode = MMC_ERASE; | ||
1264 | cmd.arg = arg; | ||
1265 | cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; | ||
1266 | mmc_set_erase_timeout(card, &cmd, arg, qty); | ||
1267 | err = mmc_wait_for_cmd(card->host, &cmd, 0); | ||
1268 | if (err) { | ||
1269 | printk(KERN_ERR "mmc_erase: erase error %d, status %#x\n", | ||
1270 | err, cmd.resp[0]); | ||
1271 | err = -EIO; | ||
1272 | goto out; | ||
1273 | } | ||
1274 | |||
1275 | if (mmc_host_is_spi(card->host)) | ||
1276 | goto out; | ||
1277 | |||
1278 | do { | ||
1279 | memset(&cmd, 0, sizeof(struct mmc_command)); | ||
1280 | cmd.opcode = MMC_SEND_STATUS; | ||
1281 | cmd.arg = card->rca << 16; | ||
1282 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; | ||
1283 | /* Do not retry else we can't see errors */ | ||
1284 | err = mmc_wait_for_cmd(card->host, &cmd, 0); | ||
1285 | if (err || (cmd.resp[0] & 0xFDF92000)) { | ||
1286 | printk(KERN_ERR "error %d requesting status %#x\n", | ||
1287 | err, cmd.resp[0]); | ||
1288 | err = -EIO; | ||
1289 | goto out; | ||
1290 | } | ||
1291 | } while (!(cmd.resp[0] & R1_READY_FOR_DATA) || | ||
1292 | R1_CURRENT_STATE(cmd.resp[0]) == 7); | ||
1293 | out: | ||
1294 | return err; | ||
1295 | } | ||
1296 | |||
1297 | /** | ||
1298 | * mmc_erase - erase sectors. | ||
1299 | * @card: card to erase | ||
1300 | * @from: first sector to erase | ||
1301 | * @nr: number of sectors to erase | ||
1302 | * @arg: erase command argument (SD supports only %MMC_ERASE_ARG) | ||
1303 | * | ||
1304 | * Caller must claim host before calling this function. | ||
1305 | */ | ||
1306 | int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr, | ||
1307 | unsigned int arg) | ||
1308 | { | ||
1309 | unsigned int rem, to = from + nr; | ||
1310 | |||
1311 | if (!(card->host->caps & MMC_CAP_ERASE) || | ||
1312 | !(card->csd.cmdclass & CCC_ERASE)) | ||
1313 | return -EOPNOTSUPP; | ||
1314 | |||
1315 | if (!card->erase_size) | ||
1316 | return -EOPNOTSUPP; | ||
1317 | |||
1318 | if (mmc_card_sd(card) && arg != MMC_ERASE_ARG) | ||
1319 | return -EOPNOTSUPP; | ||
1320 | |||
1321 | if ((arg & MMC_SECURE_ARGS) && | ||
1322 | !(card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN)) | ||
1323 | return -EOPNOTSUPP; | ||
1324 | |||
1325 | if ((arg & MMC_TRIM_ARGS) && | ||
1326 | !(card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN)) | ||
1327 | return -EOPNOTSUPP; | ||
1328 | |||
1329 | if (arg == MMC_SECURE_ERASE_ARG) { | ||
1330 | if (from % card->erase_size || nr % card->erase_size) | ||
1331 | return -EINVAL; | ||
1332 | } | ||
1333 | |||
1334 | if (arg == MMC_ERASE_ARG) { | ||
1335 | rem = from % card->erase_size; | ||
1336 | if (rem) { | ||
1337 | rem = card->erase_size - rem; | ||
1338 | from += rem; | ||
1339 | if (nr > rem) | ||
1340 | nr -= rem; | ||
1341 | else | ||
1342 | return 0; | ||
1343 | } | ||
1344 | rem = nr % card->erase_size; | ||
1345 | if (rem) | ||
1346 | nr -= rem; | ||
1347 | } | ||
1348 | |||
1349 | if (nr == 0) | ||
1350 | return 0; | ||
1351 | |||
1352 | to = from + nr; | ||
1353 | |||
1354 | if (to <= from) | ||
1355 | return -EINVAL; | ||
1356 | |||
1357 | /* 'from' and 'to' are inclusive */ | ||
1358 | to -= 1; | ||
1359 | |||
1360 | return mmc_do_erase(card, from, to, arg); | ||
1361 | } | ||
1362 | EXPORT_SYMBOL(mmc_erase); | ||
1363 | |||
1364 | int mmc_can_erase(struct mmc_card *card) | ||
1365 | { | ||
1366 | if ((card->host->caps & MMC_CAP_ERASE) && | ||
1367 | (card->csd.cmdclass & CCC_ERASE) && card->erase_size) | ||
1368 | return 1; | ||
1369 | return 0; | ||
1370 | } | ||
1371 | EXPORT_SYMBOL(mmc_can_erase); | ||
1372 | |||
1373 | int mmc_can_trim(struct mmc_card *card) | ||
1374 | { | ||
1375 | if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN) | ||
1376 | return 1; | ||
1377 | return 0; | ||
1378 | } | ||
1379 | EXPORT_SYMBOL(mmc_can_trim); | ||
1380 | |||
1381 | int mmc_can_secure_erase_trim(struct mmc_card *card) | ||
1382 | { | ||
1383 | if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN) | ||
1384 | return 1; | ||
1385 | return 0; | ||
1386 | } | ||
1387 | EXPORT_SYMBOL(mmc_can_secure_erase_trim); | ||
1388 | |||
1389 | int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from, | ||
1390 | unsigned int nr) | ||
1391 | { | ||
1392 | if (!card->erase_size) | ||
1393 | return 0; | ||
1394 | if (from % card->erase_size || nr % card->erase_size) | ||
1395 | return 0; | ||
1396 | return 1; | ||
1397 | } | ||
1398 | EXPORT_SYMBOL(mmc_erase_group_aligned); | ||
1053 | 1399 | ||
1054 | void mmc_rescan(struct work_struct *work) | 1400 | void mmc_rescan(struct work_struct *work) |
1055 | { | 1401 | { |
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index a811c52a1659..9d9eef50e5d1 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h | |||
@@ -29,6 +29,8 @@ struct mmc_bus_ops { | |||
29 | void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); | 29 | void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); |
30 | void mmc_detach_bus(struct mmc_host *host); | 30 | void mmc_detach_bus(struct mmc_host *host); |
31 | 31 | ||
32 | void mmc_init_erase(struct mmc_card *card); | ||
33 | |||
32 | void mmc_set_chip_select(struct mmc_host *host, int mode); | 34 | void mmc_set_chip_select(struct mmc_host *host, int mode); |
33 | void mmc_set_clock(struct mmc_host *host, unsigned int hz); | 35 | void mmc_set_clock(struct mmc_host *host, unsigned int hz); |
34 | void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); | 36 | void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); |
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index ccba3869c029..6909a54c39be 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -108,13 +108,23 @@ static int mmc_decode_cid(struct mmc_card *card) | |||
108 | return 0; | 108 | return 0; |
109 | } | 109 | } |
110 | 110 | ||
111 | static void mmc_set_erase_size(struct mmc_card *card) | ||
112 | { | ||
113 | if (card->ext_csd.erase_group_def & 1) | ||
114 | card->erase_size = card->ext_csd.hc_erase_size; | ||
115 | else | ||
116 | card->erase_size = card->csd.erase_size; | ||
117 | |||
118 | mmc_init_erase(card); | ||
119 | } | ||
120 | |||
111 | /* | 121 | /* |
112 | * Given a 128-bit response, decode to our card CSD structure. | 122 | * Given a 128-bit response, decode to our card CSD structure. |
113 | */ | 123 | */ |
114 | static int mmc_decode_csd(struct mmc_card *card) | 124 | static int mmc_decode_csd(struct mmc_card *card) |
115 | { | 125 | { |
116 | struct mmc_csd *csd = &card->csd; | 126 | struct mmc_csd *csd = &card->csd; |
117 | unsigned int e, m; | 127 | unsigned int e, m, a, b; |
118 | u32 *resp = card->raw_csd; | 128 | u32 *resp = card->raw_csd; |
119 | 129 | ||
120 | /* | 130 | /* |
@@ -152,6 +162,13 @@ static int mmc_decode_csd(struct mmc_card *card) | |||
152 | csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); | 162 | csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); |
153 | csd->write_partial = UNSTUFF_BITS(resp, 21, 1); | 163 | csd->write_partial = UNSTUFF_BITS(resp, 21, 1); |
154 | 164 | ||
165 | if (csd->write_blkbits >= 9) { | ||
166 | a = UNSTUFF_BITS(resp, 42, 5); | ||
167 | b = UNSTUFF_BITS(resp, 37, 5); | ||
168 | csd->erase_size = (a + 1) * (b + 1); | ||
169 | csd->erase_size <<= csd->write_blkbits - 9; | ||
170 | } | ||
171 | |||
155 | return 0; | 172 | return 0; |
156 | } | 173 | } |
157 | 174 | ||
@@ -261,8 +278,30 @@ static int mmc_read_ext_csd(struct mmc_card *card) | |||
261 | if (sa_shift > 0 && sa_shift <= 0x17) | 278 | if (sa_shift > 0 && sa_shift <= 0x17) |
262 | card->ext_csd.sa_timeout = | 279 | card->ext_csd.sa_timeout = |
263 | 1 << ext_csd[EXT_CSD_S_A_TIMEOUT]; | 280 | 1 << ext_csd[EXT_CSD_S_A_TIMEOUT]; |
281 | card->ext_csd.erase_group_def = | ||
282 | ext_csd[EXT_CSD_ERASE_GROUP_DEF]; | ||
283 | card->ext_csd.hc_erase_timeout = 300 * | ||
284 | ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT]; | ||
285 | card->ext_csd.hc_erase_size = | ||
286 | ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] << 10; | ||
287 | } | ||
288 | |||
289 | if (card->ext_csd.rev >= 4) { | ||
290 | card->ext_csd.sec_trim_mult = | ||
291 | ext_csd[EXT_CSD_SEC_TRIM_MULT]; | ||
292 | card->ext_csd.sec_erase_mult = | ||
293 | ext_csd[EXT_CSD_SEC_ERASE_MULT]; | ||
294 | card->ext_csd.sec_feature_support = | ||
295 | ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]; | ||
296 | card->ext_csd.trim_timeout = 300 * | ||
297 | ext_csd[EXT_CSD_TRIM_MULT]; | ||
264 | } | 298 | } |
265 | 299 | ||
300 | if (ext_csd[EXT_CSD_ERASED_MEM_CONT]) | ||
301 | card->erased_byte = 0xFF; | ||
302 | else | ||
303 | card->erased_byte = 0x0; | ||
304 | |||
266 | out: | 305 | out: |
267 | kfree(ext_csd); | 306 | kfree(ext_csd); |
268 | 307 | ||
@@ -274,6 +313,8 @@ MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1], | |||
274 | MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], | 313 | MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], |
275 | card->raw_csd[2], card->raw_csd[3]); | 314 | card->raw_csd[2], card->raw_csd[3]); |
276 | MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); | 315 | MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); |
316 | MMC_DEV_ATTR(erase_size, "%u\n", card->erase_size << 9); | ||
317 | MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9); | ||
277 | MMC_DEV_ATTR(fwrev, "0x%x\n", card->cid.fwrev); | 318 | MMC_DEV_ATTR(fwrev, "0x%x\n", card->cid.fwrev); |
278 | MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev); | 319 | MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev); |
279 | MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); | 320 | MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); |
@@ -285,6 +326,8 @@ static struct attribute *mmc_std_attrs[] = { | |||
285 | &dev_attr_cid.attr, | 326 | &dev_attr_cid.attr, |
286 | &dev_attr_csd.attr, | 327 | &dev_attr_csd.attr, |
287 | &dev_attr_date.attr, | 328 | &dev_attr_date.attr, |
329 | &dev_attr_erase_size.attr, | ||
330 | &dev_attr_preferred_erase_size.attr, | ||
288 | &dev_attr_fwrev.attr, | 331 | &dev_attr_fwrev.attr, |
289 | &dev_attr_hwrev.attr, | 332 | &dev_attr_hwrev.attr, |
290 | &dev_attr_manfid.attr, | 333 | &dev_attr_manfid.attr, |
@@ -421,6 +464,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
421 | err = mmc_read_ext_csd(card); | 464 | err = mmc_read_ext_csd(card); |
422 | if (err) | 465 | if (err) |
423 | goto free_card; | 466 | goto free_card; |
467 | /* Erase size depends on CSD and Extended CSD */ | ||
468 | mmc_set_erase_size(card); | ||
424 | } | 469 | } |
425 | 470 | ||
426 | /* | 471 | /* |
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index e6d7d9fab446..0f5241085557 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
@@ -119,6 +119,13 @@ static int mmc_decode_csd(struct mmc_card *card) | |||
119 | csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3); | 119 | csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3); |
120 | csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); | 120 | csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); |
121 | csd->write_partial = UNSTUFF_BITS(resp, 21, 1); | 121 | csd->write_partial = UNSTUFF_BITS(resp, 21, 1); |
122 | |||
123 | if (UNSTUFF_BITS(resp, 46, 1)) { | ||
124 | csd->erase_size = 1; | ||
125 | } else if (csd->write_blkbits >= 9) { | ||
126 | csd->erase_size = UNSTUFF_BITS(resp, 39, 7) + 1; | ||
127 | csd->erase_size <<= csd->write_blkbits - 9; | ||
128 | } | ||
122 | break; | 129 | break; |
123 | case 1: | 130 | case 1: |
124 | /* | 131 | /* |
@@ -147,6 +154,7 @@ static int mmc_decode_csd(struct mmc_card *card) | |||
147 | csd->r2w_factor = 4; /* Unused */ | 154 | csd->r2w_factor = 4; /* Unused */ |
148 | csd->write_blkbits = 9; | 155 | csd->write_blkbits = 9; |
149 | csd->write_partial = 0; | 156 | csd->write_partial = 0; |
157 | csd->erase_size = 1; | ||
150 | break; | 158 | break; |
151 | default: | 159 | default: |
152 | printk(KERN_ERR "%s: unrecognised CSD structure version %d\n", | 160 | printk(KERN_ERR "%s: unrecognised CSD structure version %d\n", |
@@ -154,6 +162,8 @@ static int mmc_decode_csd(struct mmc_card *card) | |||
154 | return -EINVAL; | 162 | return -EINVAL; |
155 | } | 163 | } |
156 | 164 | ||
165 | card->erase_size = csd->erase_size; | ||
166 | |||
157 | return 0; | 167 | return 0; |
158 | } | 168 | } |
159 | 169 | ||
@@ -179,10 +189,68 @@ static int mmc_decode_scr(struct mmc_card *card) | |||
179 | scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4); | 189 | scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4); |
180 | scr->bus_widths = UNSTUFF_BITS(resp, 48, 4); | 190 | scr->bus_widths = UNSTUFF_BITS(resp, 48, 4); |
181 | 191 | ||
192 | if (UNSTUFF_BITS(resp, 55, 1)) | ||
193 | card->erased_byte = 0xFF; | ||
194 | else | ||
195 | card->erased_byte = 0x0; | ||
196 | |||
182 | return 0; | 197 | return 0; |
183 | } | 198 | } |
184 | 199 | ||
185 | /* | 200 | /* |
201 | * Fetch and process SD Status register. | ||
202 | */ | ||
203 | static int mmc_read_ssr(struct mmc_card *card) | ||
204 | { | ||
205 | unsigned int au, es, et, eo; | ||
206 | int err, i; | ||
207 | u32 *ssr; | ||
208 | |||
209 | if (!(card->csd.cmdclass & CCC_APP_SPEC)) { | ||
210 | printk(KERN_WARNING "%s: card lacks mandatory SD Status " | ||
211 | "function.\n", mmc_hostname(card->host)); | ||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | ssr = kmalloc(64, GFP_KERNEL); | ||
216 | if (!ssr) | ||
217 | return -ENOMEM; | ||
218 | |||
219 | err = mmc_app_sd_status(card, ssr); | ||
220 | if (err) { | ||
221 | printk(KERN_WARNING "%s: problem reading SD Status " | ||
222 | "register.\n", mmc_hostname(card->host)); | ||
223 | err = 0; | ||
224 | goto out; | ||
225 | } | ||
226 | |||
227 | for (i = 0; i < 16; i++) | ||
228 | ssr[i] = be32_to_cpu(ssr[i]); | ||
229 | |||
230 | /* | ||
231 | * UNSTUFF_BITS only works with four u32s so we have to offset the | ||
232 | * bitfield positions accordingly. | ||
233 | */ | ||
234 | au = UNSTUFF_BITS(ssr, 428 - 384, 4); | ||
235 | if (au > 0 || au <= 9) { | ||
236 | card->ssr.au = 1 << (au + 4); | ||
237 | es = UNSTUFF_BITS(ssr, 408 - 384, 16); | ||
238 | et = UNSTUFF_BITS(ssr, 402 - 384, 6); | ||
239 | eo = UNSTUFF_BITS(ssr, 400 - 384, 2); | ||
240 | if (es && et) { | ||
241 | card->ssr.erase_timeout = (et * 1000) / es; | ||
242 | card->ssr.erase_offset = eo * 1000; | ||
243 | } | ||
244 | } else { | ||
245 | printk(KERN_WARNING "%s: SD Status: Invalid Allocation Unit " | ||
246 | "size.\n", mmc_hostname(card->host)); | ||
247 | } | ||
248 | out: | ||
249 | kfree(ssr); | ||
250 | return err; | ||
251 | } | ||
252 | |||
253 | /* | ||
186 | * Fetches and decodes switch information | 254 | * Fetches and decodes switch information |
187 | */ | 255 | */ |
188 | static int mmc_read_switch(struct mmc_card *card) | 256 | static int mmc_read_switch(struct mmc_card *card) |
@@ -289,6 +357,8 @@ MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], | |||
289 | card->raw_csd[2], card->raw_csd[3]); | 357 | card->raw_csd[2], card->raw_csd[3]); |
290 | MMC_DEV_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]); | 358 | MMC_DEV_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]); |
291 | MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); | 359 | MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); |
360 | MMC_DEV_ATTR(erase_size, "%u\n", card->erase_size << 9); | ||
361 | MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9); | ||
292 | MMC_DEV_ATTR(fwrev, "0x%x\n", card->cid.fwrev); | 362 | MMC_DEV_ATTR(fwrev, "0x%x\n", card->cid.fwrev); |
293 | MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev); | 363 | MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev); |
294 | MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); | 364 | MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); |
@@ -302,6 +372,8 @@ static struct attribute *sd_std_attrs[] = { | |||
302 | &dev_attr_csd.attr, | 372 | &dev_attr_csd.attr, |
303 | &dev_attr_scr.attr, | 373 | &dev_attr_scr.attr, |
304 | &dev_attr_date.attr, | 374 | &dev_attr_date.attr, |
375 | &dev_attr_erase_size.attr, | ||
376 | &dev_attr_preferred_erase_size.attr, | ||
305 | &dev_attr_fwrev.attr, | 377 | &dev_attr_fwrev.attr, |
306 | &dev_attr_hwrev.attr, | 378 | &dev_attr_hwrev.attr, |
307 | &dev_attr_manfid.attr, | 379 | &dev_attr_manfid.attr, |
@@ -397,6 +469,16 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, | |||
397 | return err; | 469 | return err; |
398 | 470 | ||
399 | /* | 471 | /* |
472 | * Fetch and process SD Status register. | ||
473 | */ | ||
474 | err = mmc_read_ssr(card); | ||
475 | if (err) | ||
476 | return err; | ||
477 | |||
478 | /* Erase init depends on CSD and SSR */ | ||
479 | mmc_init_erase(card); | ||
480 | |||
481 | /* | ||
400 | * Fetch switch information from card. | 482 | * Fetch switch information from card. |
401 | */ | 483 | */ |
402 | err = mmc_read_switch(card); | 484 | err = mmc_read_switch(card); |
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index 63772e7e7608..797cdb5887fd 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c | |||
@@ -346,3 +346,51 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group, | |||
346 | return 0; | 346 | return 0; |
347 | } | 347 | } |
348 | 348 | ||
349 | int mmc_app_sd_status(struct mmc_card *card, void *ssr) | ||
350 | { | ||
351 | int err; | ||
352 | struct mmc_request mrq; | ||
353 | struct mmc_command cmd; | ||
354 | struct mmc_data data; | ||
355 | struct scatterlist sg; | ||
356 | |||
357 | BUG_ON(!card); | ||
358 | BUG_ON(!card->host); | ||
359 | BUG_ON(!ssr); | ||
360 | |||
361 | /* NOTE: caller guarantees ssr is heap-allocated */ | ||
362 | |||
363 | err = mmc_app_cmd(card->host, card); | ||
364 | if (err) | ||
365 | return err; | ||
366 | |||
367 | memset(&mrq, 0, sizeof(struct mmc_request)); | ||
368 | memset(&cmd, 0, sizeof(struct mmc_command)); | ||
369 | memset(&data, 0, sizeof(struct mmc_data)); | ||
370 | |||
371 | mrq.cmd = &cmd; | ||
372 | mrq.data = &data; | ||
373 | |||
374 | cmd.opcode = SD_APP_SD_STATUS; | ||
375 | cmd.arg = 0; | ||
376 | cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_ADTC; | ||
377 | |||
378 | data.blksz = 64; | ||
379 | data.blocks = 1; | ||
380 | data.flags = MMC_DATA_READ; | ||
381 | data.sg = &sg; | ||
382 | data.sg_len = 1; | ||
383 | |||
384 | sg_init_one(&sg, ssr, 64); | ||
385 | |||
386 | mmc_set_data_timeout(&data, card); | ||
387 | |||
388 | mmc_wait_for_req(card->host, &mrq); | ||
389 | |||
390 | if (cmd.error) | ||
391 | return cmd.error; | ||
392 | if (data.error) | ||
393 | return data.error; | ||
394 | |||
395 | return 0; | ||
396 | } | ||
diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h index 9742d8a30664..ffc2305d905f 100644 --- a/drivers/mmc/core/sd_ops.h +++ b/drivers/mmc/core/sd_ops.h | |||
@@ -19,6 +19,7 @@ int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca); | |||
19 | int mmc_app_send_scr(struct mmc_card *card, u32 *scr); | 19 | int mmc_app_send_scr(struct mmc_card *card, u32 *scr); |
20 | int mmc_sd_switch(struct mmc_card *card, int mode, int group, | 20 | int mmc_sd_switch(struct mmc_card *card, int mode, int group, |
21 | u8 value, u8 *resp); | 21 | u8 value, u8 *resp); |
22 | int mmc_app_sd_status(struct mmc_card *card, void *ssr); | ||
22 | 23 | ||
23 | #endif | 24 | #endif |
24 | 25 | ||
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 7b0f3ef50f96..1145ea0792e6 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c | |||
@@ -1536,6 +1536,7 @@ static int __devexit mmc_spi_remove(struct spi_device *spi) | |||
1536 | #if defined(CONFIG_OF) | 1536 | #if defined(CONFIG_OF) |
1537 | static struct of_device_id mmc_spi_of_match_table[] __devinitdata = { | 1537 | static struct of_device_id mmc_spi_of_match_table[] __devinitdata = { |
1538 | { .compatible = "mmc-spi-slot", }, | 1538 | { .compatible = "mmc-spi-slot", }, |
1539 | {}, | ||
1539 | }; | 1540 | }; |
1540 | #endif | 1541 | #endif |
1541 | 1542 | ||
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c index 3bd8ff71ec22..6824917f5c60 100644 --- a/drivers/mmc/host/msm_sdcc.c +++ b/drivers/mmc/host/msm_sdcc.c | |||
@@ -1060,7 +1060,7 @@ msmsdcc_init_dma(struct msmsdcc_host *host) | |||
1060 | static int | 1060 | static int |
1061 | msmsdcc_probe(struct platform_device *pdev) | 1061 | msmsdcc_probe(struct platform_device *pdev) |
1062 | { | 1062 | { |
1063 | struct mmc_platform_data *plat = pdev->dev.platform_data; | 1063 | struct msm_mmc_platform_data *plat = pdev->dev.platform_data; |
1064 | struct msmsdcc_host *host; | 1064 | struct msmsdcc_host *host; |
1065 | struct mmc_host *mmc; | 1065 | struct mmc_host *mmc; |
1066 | struct resource *cmd_irqres = NULL; | 1066 | struct resource *cmd_irqres = NULL; |
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h index d7dedcf33b5b..ff2b0f74f6f4 100644 --- a/drivers/mmc/host/msm_sdcc.h +++ b/drivers/mmc/host/msm_sdcc.h | |||
@@ -225,7 +225,7 @@ struct msmsdcc_host { | |||
225 | 225 | ||
226 | u32 pwr; | 226 | u32 pwr; |
227 | u32 saved_irq0mask; /* MMCIMASK0 reg value */ | 227 | u32 saved_irq0mask; /* MMCIMASK0 reg value */ |
228 | struct mmc_platform_data *plat; | 228 | struct msm_mmc_platform_data *plat; |
229 | 229 | ||
230 | struct timer_list timer; | 230 | struct timer_list timer; |
231 | unsigned int oldstat; | 231 | unsigned int oldstat; |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index dc57ef6aef4f..4a8776f8afdd 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/clk.h> | 28 | #include <linux/clk.h> |
29 | #include <linux/mmc/host.h> | 29 | #include <linux/mmc/host.h> |
30 | #include <linux/mmc/core.h> | 30 | #include <linux/mmc/core.h> |
31 | #include <linux/mmc/mmc.h> | ||
31 | #include <linux/io.h> | 32 | #include <linux/io.h> |
32 | #include <linux/semaphore.h> | 33 | #include <linux/semaphore.h> |
33 | #include <linux/gpio.h> | 34 | #include <linux/gpio.h> |
@@ -78,6 +79,7 @@ | |||
78 | #define INT_EN_MASK 0x307F0033 | 79 | #define INT_EN_MASK 0x307F0033 |
79 | #define BWR_ENABLE (1 << 4) | 80 | #define BWR_ENABLE (1 << 4) |
80 | #define BRR_ENABLE (1 << 5) | 81 | #define BRR_ENABLE (1 << 5) |
82 | #define DTO_ENABLE (1 << 20) | ||
81 | #define INIT_STREAM (1 << 1) | 83 | #define INIT_STREAM (1 << 1) |
82 | #define DP_SELECT (1 << 21) | 84 | #define DP_SELECT (1 << 21) |
83 | #define DDIR (1 << 4) | 85 | #define DDIR (1 << 4) |
@@ -523,7 +525,8 @@ static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host) | |||
523 | dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stoped\n"); | 525 | dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stoped\n"); |
524 | } | 526 | } |
525 | 527 | ||
526 | static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host) | 528 | static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host, |
529 | struct mmc_command *cmd) | ||
527 | { | 530 | { |
528 | unsigned int irq_mask; | 531 | unsigned int irq_mask; |
529 | 532 | ||
@@ -532,6 +535,10 @@ static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host) | |||
532 | else | 535 | else |
533 | irq_mask = INT_EN_MASK; | 536 | irq_mask = INT_EN_MASK; |
534 | 537 | ||
538 | /* Disable timeout for erases */ | ||
539 | if (cmd->opcode == MMC_ERASE) | ||
540 | irq_mask &= ~DTO_ENABLE; | ||
541 | |||
535 | OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); | 542 | OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); |
536 | OMAP_HSMMC_WRITE(host->base, ISE, irq_mask); | 543 | OMAP_HSMMC_WRITE(host->base, ISE, irq_mask); |
537 | OMAP_HSMMC_WRITE(host->base, IE, irq_mask); | 544 | OMAP_HSMMC_WRITE(host->base, IE, irq_mask); |
@@ -782,7 +789,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, | |||
782 | mmc_hostname(host->mmc), cmd->opcode, cmd->arg); | 789 | mmc_hostname(host->mmc), cmd->opcode, cmd->arg); |
783 | host->cmd = cmd; | 790 | host->cmd = cmd; |
784 | 791 | ||
785 | omap_hsmmc_enable_irq(host); | 792 | omap_hsmmc_enable_irq(host, cmd); |
786 | 793 | ||
787 | host->response_busy = 0; | 794 | host->response_busy = 0; |
788 | if (cmd->flags & MMC_RSP_PRESENT) { | 795 | if (cmd->flags & MMC_RSP_PRESENT) { |
@@ -2107,7 +2114,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
2107 | mmc->max_seg_size = mmc->max_req_size; | 2114 | mmc->max_seg_size = mmc->max_req_size; |
2108 | 2115 | ||
2109 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | | 2116 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | |
2110 | MMC_CAP_WAIT_WHILE_BUSY; | 2117 | MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE; |
2111 | 2118 | ||
2112 | switch (mmc_slot(host).wires) { | 2119 | switch (mmc_slot(host).wires) { |
2113 | case 8: | 2120 | case 8: |
diff --git a/drivers/mmc/host/sdhci-of-core.c b/drivers/mmc/host/sdhci-of-core.c index dd1bdd168e66..c51b71174c1d 100644 --- a/drivers/mmc/host/sdhci-of-core.c +++ b/drivers/mmc/host/sdhci-of-core.c | |||
@@ -85,14 +85,14 @@ void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg) | |||
85 | 85 | ||
86 | #ifdef CONFIG_PM | 86 | #ifdef CONFIG_PM |
87 | 87 | ||
88 | static int sdhci_of_suspend(struct of_device *ofdev, pm_message_t state) | 88 | static int sdhci_of_suspend(struct platform_device *ofdev, pm_message_t state) |
89 | { | 89 | { |
90 | struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); | 90 | struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); |
91 | 91 | ||
92 | return mmc_suspend_host(host->mmc); | 92 | return mmc_suspend_host(host->mmc); |
93 | } | 93 | } |
94 | 94 | ||
95 | static int sdhci_of_resume(struct of_device *ofdev) | 95 | static int sdhci_of_resume(struct platform_device *ofdev) |
96 | { | 96 | { |
97 | struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); | 97 | struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); |
98 | 98 | ||
@@ -115,7 +115,7 @@ static bool __devinit sdhci_of_wp_inverted(struct device_node *np) | |||
115 | return machine_is(mpc837x_rdb) || machine_is(mpc837x_mds); | 115 | return machine_is(mpc837x_rdb) || machine_is(mpc837x_mds); |
116 | } | 116 | } |
117 | 117 | ||
118 | static int __devinit sdhci_of_probe(struct of_device *ofdev, | 118 | static int __devinit sdhci_of_probe(struct platform_device *ofdev, |
119 | const struct of_device_id *match) | 119 | const struct of_device_id *match) |
120 | { | 120 | { |
121 | struct device_node *np = ofdev->dev.of_node; | 121 | struct device_node *np = ofdev->dev.of_node; |
@@ -183,7 +183,7 @@ err_addr_map: | |||
183 | return ret; | 183 | return ret; |
184 | } | 184 | } |
185 | 185 | ||
186 | static int __devexit sdhci_of_remove(struct of_device *ofdev) | 186 | static int __devexit sdhci_of_remove(struct platform_device *ofdev) |
187 | { | 187 | { |
188 | struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); | 188 | struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); |
189 | 189 | ||
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index 6ac5f9f28ac3..00af55d7afba 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c | |||
@@ -43,7 +43,7 @@ struct of_flash { | |||
43 | #ifdef CONFIG_MTD_PARTITIONS | 43 | #ifdef CONFIG_MTD_PARTITIONS |
44 | #define OF_FLASH_PARTS(info) ((info)->parts) | 44 | #define OF_FLASH_PARTS(info) ((info)->parts) |
45 | 45 | ||
46 | static int parse_obsolete_partitions(struct of_device *dev, | 46 | static int parse_obsolete_partitions(struct platform_device *dev, |
47 | struct of_flash *info, | 47 | struct of_flash *info, |
48 | struct device_node *dp) | 48 | struct device_node *dp) |
49 | { | 49 | { |
@@ -93,7 +93,7 @@ static int parse_obsolete_partitions(struct of_device *dev, | |||
93 | #define parse_partitions(info, dev) (0) | 93 | #define parse_partitions(info, dev) (0) |
94 | #endif /* MTD_PARTITIONS */ | 94 | #endif /* MTD_PARTITIONS */ |
95 | 95 | ||
96 | static int of_flash_remove(struct of_device *dev) | 96 | static int of_flash_remove(struct platform_device *dev) |
97 | { | 97 | { |
98 | struct of_flash *info; | 98 | struct of_flash *info; |
99 | int i; | 99 | int i; |
@@ -140,7 +140,7 @@ static int of_flash_remove(struct of_device *dev) | |||
140 | /* Helper function to handle probing of the obsolete "direct-mapped" | 140 | /* Helper function to handle probing of the obsolete "direct-mapped" |
141 | * compatible binding, which has an extra "probe-type" property | 141 | * compatible binding, which has an extra "probe-type" property |
142 | * describing the type of flash probe necessary. */ | 142 | * describing the type of flash probe necessary. */ |
143 | static struct mtd_info * __devinit obsolete_probe(struct of_device *dev, | 143 | static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev, |
144 | struct map_info *map) | 144 | struct map_info *map) |
145 | { | 145 | { |
146 | struct device_node *dp = dev->dev.of_node; | 146 | struct device_node *dp = dev->dev.of_node; |
@@ -215,7 +215,7 @@ static void __devinit of_free_probes(const char **probes) | |||
215 | } | 215 | } |
216 | #endif | 216 | #endif |
217 | 217 | ||
218 | static int __devinit of_flash_probe(struct of_device *dev, | 218 | static int __devinit of_flash_probe(struct platform_device *dev, |
219 | const struct of_device_id *match) | 219 | const struct of_device_id *match) |
220 | { | 220 | { |
221 | #ifdef CONFIG_MTD_PARTITIONS | 221 | #ifdef CONFIG_MTD_PARTITIONS |
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c index 8984236a8d0a..3582ba1f9b09 100644 --- a/drivers/mtd/maps/sun_uflash.c +++ b/drivers/mtd/maps/sun_uflash.c | |||
@@ -48,7 +48,7 @@ struct map_info uflash_map_templ = { | |||
48 | .bankwidth = UFLASH_BUSWIDTH, | 48 | .bankwidth = UFLASH_BUSWIDTH, |
49 | }; | 49 | }; |
50 | 50 | ||
51 | int uflash_devinit(struct of_device *op, struct device_node *dp) | 51 | int uflash_devinit(struct platform_device *op, struct device_node *dp) |
52 | { | 52 | { |
53 | struct uflash_dev *up; | 53 | struct uflash_dev *up; |
54 | 54 | ||
@@ -108,7 +108,7 @@ int uflash_devinit(struct of_device *op, struct device_node *dp) | |||
108 | return 0; | 108 | return 0; |
109 | } | 109 | } |
110 | 110 | ||
111 | static int __devinit uflash_probe(struct of_device *op, const struct of_device_id *match) | 111 | static int __devinit uflash_probe(struct platform_device *op, const struct of_device_id *match) |
112 | { | 112 | { |
113 | struct device_node *dp = op->dev.of_node; | 113 | struct device_node *dp = op->dev.of_node; |
114 | 114 | ||
@@ -121,7 +121,7 @@ static int __devinit uflash_probe(struct of_device *op, const struct of_device_i | |||
121 | return uflash_devinit(op, dp); | 121 | return uflash_devinit(op, dp); |
122 | } | 122 | } |
123 | 123 | ||
124 | static int __devexit uflash_remove(struct of_device *op) | 124 | static int __devexit uflash_remove(struct platform_device *op) |
125 | { | 125 | { |
126 | struct uflash_dev *up = dev_get_drvdata(&op->dev); | 126 | struct uflash_dev *up = dev_get_drvdata(&op->dev); |
127 | 127 | ||
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 5084cc517944..80de0bff6c3a 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c | |||
@@ -958,7 +958,7 @@ static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl) | |||
958 | return 0; | 958 | return 0; |
959 | } | 959 | } |
960 | 960 | ||
961 | static int fsl_elbc_ctrl_remove(struct of_device *ofdev) | 961 | static int fsl_elbc_ctrl_remove(struct platform_device *ofdev) |
962 | { | 962 | { |
963 | struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev); | 963 | struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev); |
964 | int i; | 964 | int i; |
@@ -1013,7 +1013,7 @@ static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data) | |||
1013 | * in the chip probe function. | 1013 | * in the chip probe function. |
1014 | */ | 1014 | */ |
1015 | 1015 | ||
1016 | static int __devinit fsl_elbc_ctrl_probe(struct of_device *ofdev, | 1016 | static int __devinit fsl_elbc_ctrl_probe(struct platform_device *ofdev, |
1017 | const struct of_device_id *match) | 1017 | const struct of_device_id *match) |
1018 | { | 1018 | { |
1019 | struct device_node *child; | 1019 | struct device_node *child; |
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index 1312eda57ba6..4eff8b25e5af 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c | |||
@@ -217,7 +217,7 @@ err: | |||
217 | return ret; | 217 | return ret; |
218 | } | 218 | } |
219 | 219 | ||
220 | static int __devinit fun_probe(struct of_device *ofdev, | 220 | static int __devinit fun_probe(struct platform_device *ofdev, |
221 | const struct of_device_id *ofid) | 221 | const struct of_device_id *ofid) |
222 | { | 222 | { |
223 | struct fsl_upm_nand *fun; | 223 | struct fsl_upm_nand *fun; |
@@ -335,7 +335,7 @@ err1: | |||
335 | return ret; | 335 | return ret; |
336 | } | 336 | } |
337 | 337 | ||
338 | static int __devexit fun_remove(struct of_device *ofdev) | 338 | static int __devexit fun_remove(struct platform_device *ofdev) |
339 | { | 339 | { |
340 | struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev); | 340 | struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev); |
341 | int i; | 341 | int i; |
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index 0a130dcaa129..df0c1da4ff49 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c | |||
@@ -647,7 +647,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd) | |||
647 | iounmap(prv->csreg); | 647 | iounmap(prv->csreg); |
648 | } | 648 | } |
649 | 649 | ||
650 | static int __devinit mpc5121_nfc_probe(struct of_device *op, | 650 | static int __devinit mpc5121_nfc_probe(struct platform_device *op, |
651 | const struct of_device_id *match) | 651 | const struct of_device_id *match) |
652 | { | 652 | { |
653 | struct device_node *rootnode, *dn = op->dev.of_node; | 653 | struct device_node *rootnode, *dn = op->dev.of_node; |
@@ -869,7 +869,7 @@ error: | |||
869 | return retval; | 869 | return retval; |
870 | } | 870 | } |
871 | 871 | ||
872 | static int __devexit mpc5121_nfc_remove(struct of_device *op) | 872 | static int __devexit mpc5121_nfc_remove(struct platform_device *op) |
873 | { | 873 | { |
874 | struct device *dev = &op->dev; | 874 | struct device *dev = &op->dev; |
875 | struct mtd_info *mtd = dev_get_drvdata(dev); | 875 | struct mtd_info *mtd = dev_get_drvdata(dev); |
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 98fd2bdf8be1..510554e6c115 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c | |||
@@ -35,7 +35,7 @@ | |||
35 | 35 | ||
36 | 36 | ||
37 | struct ndfc_controller { | 37 | struct ndfc_controller { |
38 | struct of_device *ofdev; | 38 | struct platform_device *ofdev; |
39 | void __iomem *ndfcbase; | 39 | void __iomem *ndfcbase; |
40 | struct mtd_info mtd; | 40 | struct mtd_info mtd; |
41 | struct nand_chip chip; | 41 | struct nand_chip chip; |
@@ -225,7 +225,7 @@ err: | |||
225 | return ret; | 225 | return ret; |
226 | } | 226 | } |
227 | 227 | ||
228 | static int __devinit ndfc_probe(struct of_device *ofdev, | 228 | static int __devinit ndfc_probe(struct platform_device *ofdev, |
229 | const struct of_device_id *match) | 229 | const struct of_device_id *match) |
230 | { | 230 | { |
231 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 231 | struct ndfc_controller *ndfc = &ndfc_ctrl; |
@@ -277,7 +277,7 @@ static int __devinit ndfc_probe(struct of_device *ofdev, | |||
277 | return 0; | 277 | return 0; |
278 | } | 278 | } |
279 | 279 | ||
280 | static int __devexit ndfc_remove(struct of_device *ofdev) | 280 | static int __devexit ndfc_remove(struct platform_device *ofdev) |
281 | { | 281 | { |
282 | struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev); | 282 | struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev); |
283 | 283 | ||
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index f02af24d033a..6ddb2461d740 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c | |||
@@ -89,7 +89,7 @@ int pasemi_device_ready(struct mtd_info *mtd) | |||
89 | return !!(inl(lpcctl) & LBICTRL_LPCCTL_NR); | 89 | return !!(inl(lpcctl) & LBICTRL_LPCCTL_NR); |
90 | } | 90 | } |
91 | 91 | ||
92 | static int __devinit pasemi_nand_probe(struct of_device *ofdev, | 92 | static int __devinit pasemi_nand_probe(struct platform_device *ofdev, |
93 | const struct of_device_id *match) | 93 | const struct of_device_id *match) |
94 | { | 94 | { |
95 | struct pci_dev *pdev; | 95 | struct pci_dev *pdev; |
@@ -185,7 +185,7 @@ static int __devinit pasemi_nand_probe(struct of_device *ofdev, | |||
185 | return err; | 185 | return err; |
186 | } | 186 | } |
187 | 187 | ||
188 | static int __devexit pasemi_nand_remove(struct of_device *ofdev) | 188 | static int __devexit pasemi_nand_remove(struct platform_device *ofdev) |
189 | { | 189 | { |
190 | struct nand_chip *chip; | 190 | struct nand_chip *chip; |
191 | 191 | ||
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c index cc728b12de82..a8e403eebedb 100644 --- a/drivers/mtd/nand/socrates_nand.c +++ b/drivers/mtd/nand/socrates_nand.c | |||
@@ -162,7 +162,7 @@ static const char *part_probes[] = { "cmdlinepart", NULL }; | |||
162 | /* | 162 | /* |
163 | * Probe for the NAND device. | 163 | * Probe for the NAND device. |
164 | */ | 164 | */ |
165 | static int __devinit socrates_nand_probe(struct of_device *ofdev, | 165 | static int __devinit socrates_nand_probe(struct platform_device *ofdev, |
166 | const struct of_device_id *ofid) | 166 | const struct of_device_id *ofid) |
167 | { | 167 | { |
168 | struct socrates_nand_host *host; | 168 | struct socrates_nand_host *host; |
@@ -276,7 +276,7 @@ out: | |||
276 | /* | 276 | /* |
277 | * Remove a NAND device. | 277 | * Remove a NAND device. |
278 | */ | 278 | */ |
279 | static int __devexit socrates_nand_remove(struct of_device *ofdev) | 279 | static int __devexit socrates_nand_remove(struct platform_device *ofdev) |
280 | { | 280 | { |
281 | struct socrates_nand_host *host = dev_get_drvdata(&ofdev->dev); | 281 | struct socrates_nand_host *host = dev_get_drvdata(&ofdev->dev); |
282 | struct mtd_info *mtd = &host->mtd; | 282 | struct mtd_info *mtd = &host->mtd; |
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index af753936e835..b1bdc909090f 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c | |||
@@ -38,7 +38,7 @@ | |||
38 | 38 | ||
39 | struct mpc5xxx_can_data { | 39 | struct mpc5xxx_can_data { |
40 | unsigned int type; | 40 | unsigned int type; |
41 | u32 (*get_clock)(struct of_device *ofdev, const char *clock_name, | 41 | u32 (*get_clock)(struct platform_device *ofdev, const char *clock_name, |
42 | int *mscan_clksrc); | 42 | int *mscan_clksrc); |
43 | }; | 43 | }; |
44 | 44 | ||
@@ -48,7 +48,7 @@ static struct of_device_id __devinitdata mpc52xx_cdm_ids[] = { | |||
48 | {} | 48 | {} |
49 | }; | 49 | }; |
50 | 50 | ||
51 | static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev, | 51 | static u32 __devinit mpc52xx_can_get_clock(struct platform_device *ofdev, |
52 | const char *clock_name, | 52 | const char *clock_name, |
53 | int *mscan_clksrc) | 53 | int *mscan_clksrc) |
54 | { | 54 | { |
@@ -101,7 +101,7 @@ static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev, | |||
101 | return freq; | 101 | return freq; |
102 | } | 102 | } |
103 | #else /* !CONFIG_PPC_MPC52xx */ | 103 | #else /* !CONFIG_PPC_MPC52xx */ |
104 | static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev, | 104 | static u32 __devinit mpc52xx_can_get_clock(struct platform_device *ofdev, |
105 | const char *clock_name, | 105 | const char *clock_name, |
106 | int *mscan_clksrc) | 106 | int *mscan_clksrc) |
107 | { | 107 | { |
@@ -129,7 +129,7 @@ static struct of_device_id __devinitdata mpc512x_clock_ids[] = { | |||
129 | {} | 129 | {} |
130 | }; | 130 | }; |
131 | 131 | ||
132 | static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev, | 132 | static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, |
133 | const char *clock_name, | 133 | const char *clock_name, |
134 | int *mscan_clksrc) | 134 | int *mscan_clksrc) |
135 | { | 135 | { |
@@ -239,7 +239,7 @@ exit_unmap: | |||
239 | return freq; | 239 | return freq; |
240 | } | 240 | } |
241 | #else /* !CONFIG_PPC_MPC512x */ | 241 | #else /* !CONFIG_PPC_MPC512x */ |
242 | static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev, | 242 | static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, |
243 | const char *clock_name, | 243 | const char *clock_name, |
244 | int *mscan_clksrc) | 244 | int *mscan_clksrc) |
245 | { | 245 | { |
@@ -247,7 +247,7 @@ static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev, | |||
247 | } | 247 | } |
248 | #endif /* CONFIG_PPC_MPC512x */ | 248 | #endif /* CONFIG_PPC_MPC512x */ |
249 | 249 | ||
250 | static int __devinit mpc5xxx_can_probe(struct of_device *ofdev, | 250 | static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev, |
251 | const struct of_device_id *id) | 251 | const struct of_device_id *id) |
252 | { | 252 | { |
253 | struct mpc5xxx_can_data *data = (struct mpc5xxx_can_data *)id->data; | 253 | struct mpc5xxx_can_data *data = (struct mpc5xxx_can_data *)id->data; |
@@ -317,7 +317,7 @@ exit_unmap_mem: | |||
317 | return err; | 317 | return err; |
318 | } | 318 | } |
319 | 319 | ||
320 | static int __devexit mpc5xxx_can_remove(struct of_device *ofdev) | 320 | static int __devexit mpc5xxx_can_remove(struct platform_device *ofdev) |
321 | { | 321 | { |
322 | struct net_device *dev = dev_get_drvdata(&ofdev->dev); | 322 | struct net_device *dev = dev_get_drvdata(&ofdev->dev); |
323 | struct mscan_priv *priv = netdev_priv(dev); | 323 | struct mscan_priv *priv = netdev_priv(dev); |
@@ -334,7 +334,7 @@ static int __devexit mpc5xxx_can_remove(struct of_device *ofdev) | |||
334 | 334 | ||
335 | #ifdef CONFIG_PM | 335 | #ifdef CONFIG_PM |
336 | static struct mscan_regs saved_regs; | 336 | static struct mscan_regs saved_regs; |
337 | static int mpc5xxx_can_suspend(struct of_device *ofdev, pm_message_t state) | 337 | static int mpc5xxx_can_suspend(struct platform_device *ofdev, pm_message_t state) |
338 | { | 338 | { |
339 | struct net_device *dev = dev_get_drvdata(&ofdev->dev); | 339 | struct net_device *dev = dev_get_drvdata(&ofdev->dev); |
340 | struct mscan_priv *priv = netdev_priv(dev); | 340 | struct mscan_priv *priv = netdev_priv(dev); |
@@ -345,7 +345,7 @@ static int mpc5xxx_can_suspend(struct of_device *ofdev, pm_message_t state) | |||
345 | return 0; | 345 | return 0; |
346 | } | 346 | } |
347 | 347 | ||
348 | static int mpc5xxx_can_resume(struct of_device *ofdev) | 348 | static int mpc5xxx_can_resume(struct platform_device *ofdev) |
349 | { | 349 | { |
350 | struct net_device *dev = dev_get_drvdata(&ofdev->dev); | 350 | struct net_device *dev = dev_get_drvdata(&ofdev->dev); |
351 | struct mscan_priv *priv = netdev_priv(dev); | 351 | struct mscan_priv *priv = netdev_priv(dev); |
diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c index ac1a83d7c204..5bfccfdf3bbb 100644 --- a/drivers/net/can/sja1000/sja1000_of_platform.c +++ b/drivers/net/can/sja1000/sja1000_of_platform.c | |||
@@ -67,7 +67,7 @@ static void sja1000_ofp_write_reg(const struct sja1000_priv *priv, | |||
67 | out_8(priv->reg_base + reg, val); | 67 | out_8(priv->reg_base + reg, val); |
68 | } | 68 | } |
69 | 69 | ||
70 | static int __devexit sja1000_ofp_remove(struct of_device *ofdev) | 70 | static int __devexit sja1000_ofp_remove(struct platform_device *ofdev) |
71 | { | 71 | { |
72 | struct net_device *dev = dev_get_drvdata(&ofdev->dev); | 72 | struct net_device *dev = dev_get_drvdata(&ofdev->dev); |
73 | struct sja1000_priv *priv = netdev_priv(dev); | 73 | struct sja1000_priv *priv = netdev_priv(dev); |
@@ -87,7 +87,7 @@ static int __devexit sja1000_ofp_remove(struct of_device *ofdev) | |||
87 | return 0; | 87 | return 0; |
88 | } | 88 | } |
89 | 89 | ||
90 | static int __devinit sja1000_ofp_probe(struct of_device *ofdev, | 90 | static int __devinit sja1000_ofp_probe(struct platform_device *ofdev, |
91 | const struct of_device_id *id) | 91 | const struct of_device_id *id) |
92 | { | 92 | { |
93 | struct device_node *np = ofdev->dev.of_node; | 93 | struct device_node *np = ofdev->dev.of_node; |
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 0060e422f171..99a929964e3c 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h | |||
@@ -413,7 +413,7 @@ struct ehea_port_res { | |||
413 | 413 | ||
414 | struct ehea_adapter { | 414 | struct ehea_adapter { |
415 | u64 handle; | 415 | u64 handle; |
416 | struct of_device *ofdev; | 416 | struct platform_device *ofdev; |
417 | struct ehea_port *port[EHEA_MAX_PORTS]; | 417 | struct ehea_port *port[EHEA_MAX_PORTS]; |
418 | struct ehea_eq *neq; /* notification event queue */ | 418 | struct ehea_eq *neq; /* notification event queue */ |
419 | struct tasklet_struct neq_tasklet; | 419 | struct tasklet_struct neq_tasklet; |
@@ -465,7 +465,7 @@ struct ehea_port { | |||
465 | struct net_device *netdev; | 465 | struct net_device *netdev; |
466 | struct net_device_stats stats; | 466 | struct net_device_stats stats; |
467 | struct ehea_port_res port_res[EHEA_MAX_PORT_RES]; | 467 | struct ehea_port_res port_res[EHEA_MAX_PORT_RES]; |
468 | struct of_device ofdev; /* Open Firmware Device */ | 468 | struct platform_device ofdev; /* Open Firmware Device */ |
469 | struct ehea_mc_list *mc_list; /* Multicast MAC addresses */ | 469 | struct ehea_mc_list *mc_list; /* Multicast MAC addresses */ |
470 | struct vlan_group *vgrp; | 470 | struct vlan_group *vgrp; |
471 | struct ehea_eq *qp_eq; | 471 | struct ehea_eq *qp_eq; |
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 3beba70b7dea..897719b49f96 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c | |||
@@ -107,10 +107,10 @@ struct ehea_fw_handle_array ehea_fw_handles; | |||
107 | struct ehea_bcmc_reg_array ehea_bcmc_regs; | 107 | struct ehea_bcmc_reg_array ehea_bcmc_regs; |
108 | 108 | ||
109 | 109 | ||
110 | static int __devinit ehea_probe_adapter(struct of_device *dev, | 110 | static int __devinit ehea_probe_adapter(struct platform_device *dev, |
111 | const struct of_device_id *id); | 111 | const struct of_device_id *id); |
112 | 112 | ||
113 | static int __devexit ehea_remove(struct of_device *dev); | 113 | static int __devexit ehea_remove(struct platform_device *dev); |
114 | 114 | ||
115 | static struct of_device_id ehea_device_table[] = { | 115 | static struct of_device_id ehea_device_table[] = { |
116 | { | 116 | { |
@@ -3376,7 +3376,7 @@ static ssize_t ehea_remove_port(struct device *dev, | |||
3376 | static DEVICE_ATTR(probe_port, S_IWUSR, NULL, ehea_probe_port); | 3376 | static DEVICE_ATTR(probe_port, S_IWUSR, NULL, ehea_probe_port); |
3377 | static DEVICE_ATTR(remove_port, S_IWUSR, NULL, ehea_remove_port); | 3377 | static DEVICE_ATTR(remove_port, S_IWUSR, NULL, ehea_remove_port); |
3378 | 3378 | ||
3379 | int ehea_create_device_sysfs(struct of_device *dev) | 3379 | int ehea_create_device_sysfs(struct platform_device *dev) |
3380 | { | 3380 | { |
3381 | int ret = device_create_file(&dev->dev, &dev_attr_probe_port); | 3381 | int ret = device_create_file(&dev->dev, &dev_attr_probe_port); |
3382 | if (ret) | 3382 | if (ret) |
@@ -3387,13 +3387,13 @@ out: | |||
3387 | return ret; | 3387 | return ret; |
3388 | } | 3388 | } |
3389 | 3389 | ||
3390 | void ehea_remove_device_sysfs(struct of_device *dev) | 3390 | void ehea_remove_device_sysfs(struct platform_device *dev) |
3391 | { | 3391 | { |
3392 | device_remove_file(&dev->dev, &dev_attr_probe_port); | 3392 | device_remove_file(&dev->dev, &dev_attr_probe_port); |
3393 | device_remove_file(&dev->dev, &dev_attr_remove_port); | 3393 | device_remove_file(&dev->dev, &dev_attr_remove_port); |
3394 | } | 3394 | } |
3395 | 3395 | ||
3396 | static int __devinit ehea_probe_adapter(struct of_device *dev, | 3396 | static int __devinit ehea_probe_adapter(struct platform_device *dev, |
3397 | const struct of_device_id *id) | 3397 | const struct of_device_id *id) |
3398 | { | 3398 | { |
3399 | struct ehea_adapter *adapter; | 3399 | struct ehea_adapter *adapter; |
@@ -3492,7 +3492,7 @@ out: | |||
3492 | return ret; | 3492 | return ret; |
3493 | } | 3493 | } |
3494 | 3494 | ||
3495 | static int __devexit ehea_remove(struct of_device *dev) | 3495 | static int __devexit ehea_remove(struct platform_device *dev) |
3496 | { | 3496 | { |
3497 | struct ehea_adapter *adapter = dev_get_drvdata(&dev->dev); | 3497 | struct ehea_adapter *adapter = dev_get_drvdata(&dev->dev); |
3498 | int i; | 3498 | int i; |
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index d1a5b17b2a95..e3e10b4add9c 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c | |||
@@ -850,7 +850,7 @@ static const struct net_device_ops mpc52xx_fec_netdev_ops = { | |||
850 | /* ======================================================================== */ | 850 | /* ======================================================================== */ |
851 | 851 | ||
852 | static int __devinit | 852 | static int __devinit |
853 | mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) | 853 | mpc52xx_fec_probe(struct platform_device *op, const struct of_device_id *match) |
854 | { | 854 | { |
855 | int rv; | 855 | int rv; |
856 | struct net_device *ndev; | 856 | struct net_device *ndev; |
@@ -995,7 +995,7 @@ err_netdev: | |||
995 | } | 995 | } |
996 | 996 | ||
997 | static int | 997 | static int |
998 | mpc52xx_fec_remove(struct of_device *op) | 998 | mpc52xx_fec_remove(struct platform_device *op) |
999 | { | 999 | { |
1000 | struct net_device *ndev; | 1000 | struct net_device *ndev; |
1001 | struct mpc52xx_fec_priv *priv; | 1001 | struct mpc52xx_fec_priv *priv; |
@@ -1025,7 +1025,7 @@ mpc52xx_fec_remove(struct of_device *op) | |||
1025 | } | 1025 | } |
1026 | 1026 | ||
1027 | #ifdef CONFIG_PM | 1027 | #ifdef CONFIG_PM |
1028 | static int mpc52xx_fec_of_suspend(struct of_device *op, pm_message_t state) | 1028 | static int mpc52xx_fec_of_suspend(struct platform_device *op, pm_message_t state) |
1029 | { | 1029 | { |
1030 | struct net_device *dev = dev_get_drvdata(&op->dev); | 1030 | struct net_device *dev = dev_get_drvdata(&op->dev); |
1031 | 1031 | ||
@@ -1035,7 +1035,7 @@ static int mpc52xx_fec_of_suspend(struct of_device *op, pm_message_t state) | |||
1035 | return 0; | 1035 | return 0; |
1036 | } | 1036 | } |
1037 | 1037 | ||
1038 | static int mpc52xx_fec_of_resume(struct of_device *op) | 1038 | static int mpc52xx_fec_of_resume(struct platform_device *op) |
1039 | { | 1039 | { |
1040 | struct net_device *dev = dev_get_drvdata(&op->dev); | 1040 | struct net_device *dev = dev_get_drvdata(&op->dev); |
1041 | 1041 | ||
diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c index dbaf72cbb233..0b4cb6f15984 100644 --- a/drivers/net/fec_mpc52xx_phy.c +++ b/drivers/net/fec_mpc52xx_phy.c | |||
@@ -61,7 +61,7 @@ static int mpc52xx_fec_mdio_write(struct mii_bus *bus, int phy_id, int reg, | |||
61 | data | FEC_MII_WRITE_FRAME); | 61 | data | FEC_MII_WRITE_FRAME); |
62 | } | 62 | } |
63 | 63 | ||
64 | static int mpc52xx_fec_mdio_probe(struct of_device *of, | 64 | static int mpc52xx_fec_mdio_probe(struct platform_device *of, |
65 | const struct of_device_id *match) | 65 | const struct of_device_id *match) |
66 | { | 66 | { |
67 | struct device *dev = &of->dev; | 67 | struct device *dev = &of->dev; |
@@ -122,7 +122,7 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, | |||
122 | return err; | 122 | return err; |
123 | } | 123 | } |
124 | 124 | ||
125 | static int mpc52xx_fec_mdio_remove(struct of_device *of) | 125 | static int mpc52xx_fec_mdio_remove(struct platform_device *of) |
126 | { | 126 | { |
127 | struct device *dev = &of->dev; | 127 | struct device *dev = &of->dev; |
128 | struct mii_bus *bus = dev_get_drvdata(dev); | 128 | struct mii_bus *bus = dev_get_drvdata(dev); |
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index f08cff9020bd..d6e3111959ab 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c | |||
@@ -997,7 +997,7 @@ static const struct net_device_ops fs_enet_netdev_ops = { | |||
997 | #endif | 997 | #endif |
998 | }; | 998 | }; |
999 | 999 | ||
1000 | static int __devinit fs_enet_probe(struct of_device *ofdev, | 1000 | static int __devinit fs_enet_probe(struct platform_device *ofdev, |
1001 | const struct of_device_id *match) | 1001 | const struct of_device_id *match) |
1002 | { | 1002 | { |
1003 | struct net_device *ndev; | 1003 | struct net_device *ndev; |
@@ -1105,7 +1105,7 @@ out_free_fpi: | |||
1105 | return ret; | 1105 | return ret; |
1106 | } | 1106 | } |
1107 | 1107 | ||
1108 | static int fs_enet_remove(struct of_device *ofdev) | 1108 | static int fs_enet_remove(struct platform_device *ofdev) |
1109 | { | 1109 | { |
1110 | struct net_device *ndev = dev_get_drvdata(&ofdev->dev); | 1110 | struct net_device *ndev = dev_get_drvdata(&ofdev->dev); |
1111 | struct fs_enet_private *fep = netdev_priv(ndev); | 1111 | struct fs_enet_private *fep = netdev_priv(ndev); |
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c index 48e91b6242ce..7a84e45487e8 100644 --- a/drivers/net/fs_enet/mac-fcc.c +++ b/drivers/net/fs_enet/mac-fcc.c | |||
@@ -84,7 +84,7 @@ static inline int fcc_cr_cmd(struct fs_enet_private *fep, u32 op) | |||
84 | 84 | ||
85 | static int do_pd_setup(struct fs_enet_private *fep) | 85 | static int do_pd_setup(struct fs_enet_private *fep) |
86 | { | 86 | { |
87 | struct of_device *ofdev = to_of_device(fep->dev); | 87 | struct platform_device *ofdev = to_platform_device(fep->dev); |
88 | struct fs_platform_info *fpi = fep->fpi; | 88 | struct fs_platform_info *fpi = fep->fpi; |
89 | int ret = -EINVAL; | 89 | int ret = -EINVAL; |
90 | 90 | ||
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c index 7ca1642276d0..61035fc5599b 100644 --- a/drivers/net/fs_enet/mac-fec.c +++ b/drivers/net/fs_enet/mac-fec.c | |||
@@ -96,7 +96,7 @@ static int whack_reset(struct fec __iomem *fecp) | |||
96 | 96 | ||
97 | static int do_pd_setup(struct fs_enet_private *fep) | 97 | static int do_pd_setup(struct fs_enet_private *fep) |
98 | { | 98 | { |
99 | struct of_device *ofdev = to_of_device(fep->dev); | 99 | struct platform_device *ofdev = to_platform_device(fep->dev); |
100 | 100 | ||
101 | fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); | 101 | fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); |
102 | if (fep->interrupt == NO_IRQ) | 102 | if (fep->interrupt == NO_IRQ) |
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c index a3c44544846d..22a02a767069 100644 --- a/drivers/net/fs_enet/mac-scc.c +++ b/drivers/net/fs_enet/mac-scc.c | |||
@@ -96,7 +96,7 @@ static inline int scc_cr_cmd(struct fs_enet_private *fep, u32 op) | |||
96 | 96 | ||
97 | static int do_pd_setup(struct fs_enet_private *fep) | 97 | static int do_pd_setup(struct fs_enet_private *fep) |
98 | { | 98 | { |
99 | struct of_device *ofdev = to_of_device(fep->dev); | 99 | struct platform_device *ofdev = to_platform_device(fep->dev); |
100 | 100 | ||
101 | fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); | 101 | fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); |
102 | if (fep->interrupt == NO_IRQ) | 102 | if (fep->interrupt == NO_IRQ) |
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c index 3607340f3da7..3cda2b515471 100644 --- a/drivers/net/fs_enet/mii-bitbang.c +++ b/drivers/net/fs_enet/mii-bitbang.c | |||
@@ -150,7 +150,7 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus, | |||
150 | return 0; | 150 | return 0; |
151 | } | 151 | } |
152 | 152 | ||
153 | static int __devinit fs_enet_mdio_probe(struct of_device *ofdev, | 153 | static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev, |
154 | const struct of_device_id *match) | 154 | const struct of_device_id *match) |
155 | { | 155 | { |
156 | struct mii_bus *new_bus; | 156 | struct mii_bus *new_bus; |
@@ -200,7 +200,7 @@ out: | |||
200 | return ret; | 200 | return ret; |
201 | } | 201 | } |
202 | 202 | ||
203 | static int fs_enet_mdio_remove(struct of_device *ofdev) | 203 | static int fs_enet_mdio_remove(struct platform_device *ofdev) |
204 | { | 204 | { |
205 | struct mii_bus *bus = dev_get_drvdata(&ofdev->dev); | 205 | struct mii_bus *bus = dev_get_drvdata(&ofdev->dev); |
206 | struct bb_info *bitbang = bus->priv; | 206 | struct bb_info *bitbang = bus->priv; |
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c index bddffd169b93..dbb9c48623df 100644 --- a/drivers/net/fs_enet/mii-fec.c +++ b/drivers/net/fs_enet/mii-fec.c | |||
@@ -101,7 +101,7 @@ static int fs_enet_fec_mii_reset(struct mii_bus *bus) | |||
101 | return 0; | 101 | return 0; |
102 | } | 102 | } |
103 | 103 | ||
104 | static int __devinit fs_enet_mdio_probe(struct of_device *ofdev, | 104 | static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev, |
105 | const struct of_device_id *match) | 105 | const struct of_device_id *match) |
106 | { | 106 | { |
107 | struct resource res; | 107 | struct resource res; |
@@ -192,7 +192,7 @@ out: | |||
192 | return ret; | 192 | return ret; |
193 | } | 193 | } |
194 | 194 | ||
195 | static int fs_enet_mdio_remove(struct of_device *ofdev) | 195 | static int fs_enet_mdio_remove(struct platform_device *ofdev) |
196 | { | 196 | { |
197 | struct mii_bus *bus = dev_get_drvdata(&ofdev->dev); | 197 | struct mii_bus *bus = dev_get_drvdata(&ofdev->dev); |
198 | struct fec_info *fec = bus->priv; | 198 | struct fec_info *fec = bus->priv; |
diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c index f53f850b6418..d4bf91aac25f 100644 --- a/drivers/net/fsl_pq_mdio.c +++ b/drivers/net/fsl_pq_mdio.c | |||
@@ -265,7 +265,7 @@ static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id) | |||
265 | #endif | 265 | #endif |
266 | 266 | ||
267 | 267 | ||
268 | static int fsl_pq_mdio_probe(struct of_device *ofdev, | 268 | static int fsl_pq_mdio_probe(struct platform_device *ofdev, |
269 | const struct of_device_id *match) | 269 | const struct of_device_id *match) |
270 | { | 270 | { |
271 | struct device_node *np = ofdev->dev.of_node; | 271 | struct device_node *np = ofdev->dev.of_node; |
@@ -425,7 +425,7 @@ err_free_priv: | |||
425 | } | 425 | } |
426 | 426 | ||
427 | 427 | ||
428 | static int fsl_pq_mdio_remove(struct of_device *ofdev) | 428 | static int fsl_pq_mdio_remove(struct platform_device *ofdev) |
429 | { | 429 | { |
430 | struct device *device = &ofdev->dev; | 430 | struct device *device = &ofdev->dev; |
431 | struct mii_bus *bus = dev_get_drvdata(device); | 431 | struct mii_bus *bus = dev_get_drvdata(device); |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index a1b6301bc674..4f7c3f3ca234 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
@@ -122,9 +122,9 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id); | |||
122 | static void adjust_link(struct net_device *dev); | 122 | static void adjust_link(struct net_device *dev); |
123 | static void init_registers(struct net_device *dev); | 123 | static void init_registers(struct net_device *dev); |
124 | static int init_phy(struct net_device *dev); | 124 | static int init_phy(struct net_device *dev); |
125 | static int gfar_probe(struct of_device *ofdev, | 125 | static int gfar_probe(struct platform_device *ofdev, |
126 | const struct of_device_id *match); | 126 | const struct of_device_id *match); |
127 | static int gfar_remove(struct of_device *ofdev); | 127 | static int gfar_remove(struct platform_device *ofdev); |
128 | static void free_skb_resources(struct gfar_private *priv); | 128 | static void free_skb_resources(struct gfar_private *priv); |
129 | static void gfar_set_multi(struct net_device *dev); | 129 | static void gfar_set_multi(struct net_device *dev); |
130 | static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); | 130 | static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); |
@@ -605,7 +605,7 @@ static int gfar_parse_group(struct device_node *np, | |||
605 | return 0; | 605 | return 0; |
606 | } | 606 | } |
607 | 607 | ||
608 | static int gfar_of_init(struct of_device *ofdev, struct net_device **pdev) | 608 | static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) |
609 | { | 609 | { |
610 | const char *model; | 610 | const char *model; |
611 | const char *ctype; | 611 | const char *ctype; |
@@ -959,7 +959,7 @@ static void gfar_detect_errata(struct gfar_private *priv) | |||
959 | 959 | ||
960 | /* Set up the ethernet device structure, private data, | 960 | /* Set up the ethernet device structure, private data, |
961 | * and anything else we need before we start */ | 961 | * and anything else we need before we start */ |
962 | static int gfar_probe(struct of_device *ofdev, | 962 | static int gfar_probe(struct platform_device *ofdev, |
963 | const struct of_device_id *match) | 963 | const struct of_device_id *match) |
964 | { | 964 | { |
965 | u32 tempval; | 965 | u32 tempval; |
@@ -1238,7 +1238,7 @@ register_fail: | |||
1238 | return err; | 1238 | return err; |
1239 | } | 1239 | } |
1240 | 1240 | ||
1241 | static int gfar_remove(struct of_device *ofdev) | 1241 | static int gfar_remove(struct platform_device *ofdev) |
1242 | { | 1242 | { |
1243 | struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); | 1243 | struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); |
1244 | 1244 | ||
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 710810e2adb4..68984eb88ae0 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h | |||
@@ -1054,7 +1054,7 @@ struct gfar_private { | |||
1054 | 1054 | ||
1055 | struct device_node *node; | 1055 | struct device_node *node; |
1056 | struct net_device *ndev; | 1056 | struct net_device *ndev; |
1057 | struct of_device *ofdev; | 1057 | struct platform_device *ofdev; |
1058 | enum gfar_errata errata; | 1058 | enum gfar_errata errata; |
1059 | 1059 | ||
1060 | struct gfar_priv_grp gfargrp[MAXGROUPS]; | 1060 | struct gfar_priv_grp gfargrp[MAXGROUPS]; |
diff --git a/drivers/net/greth.c b/drivers/net/greth.c index 4d09eab3548e..f15c64f1cd38 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c | |||
@@ -1373,7 +1373,7 @@ error: | |||
1373 | } | 1373 | } |
1374 | 1374 | ||
1375 | /* Initialize the GRETH MAC */ | 1375 | /* Initialize the GRETH MAC */ |
1376 | static int __devinit greth_of_probe(struct of_device *ofdev, const struct of_device_id *match) | 1376 | static int __devinit greth_of_probe(struct platform_device *ofdev, const struct of_device_id *match) |
1377 | { | 1377 | { |
1378 | struct net_device *dev; | 1378 | struct net_device *dev; |
1379 | struct greth_private *greth; | 1379 | struct greth_private *greth; |
@@ -1412,7 +1412,7 @@ static int __devinit greth_of_probe(struct of_device *ofdev, const struct of_dev | |||
1412 | } | 1412 | } |
1413 | 1413 | ||
1414 | regs = (struct greth_regs *) greth->regs; | 1414 | regs = (struct greth_regs *) greth->regs; |
1415 | greth->irq = ofdev->irqs[0]; | 1415 | greth->irq = ofdev->archdata.irqs[0]; |
1416 | 1416 | ||
1417 | dev_set_drvdata(greth->dev, dev); | 1417 | dev_set_drvdata(greth->dev, dev); |
1418 | SET_NETDEV_DEV(dev, greth->dev); | 1418 | SET_NETDEV_DEV(dev, greth->dev); |
@@ -1572,7 +1572,7 @@ error1: | |||
1572 | return err; | 1572 | return err; |
1573 | } | 1573 | } |
1574 | 1574 | ||
1575 | static int __devexit greth_of_remove(struct of_device *of_dev) | 1575 | static int __devexit greth_of_remove(struct platform_device *of_dev) |
1576 | { | 1576 | { |
1577 | struct net_device *ndev = dev_get_drvdata(&of_dev->dev); | 1577 | struct net_device *ndev = dev_get_drvdata(&of_dev->dev); |
1578 | struct greth_private *greth = netdev_priv(ndev); | 1578 | struct greth_private *greth = netdev_priv(ndev); |
diff --git a/drivers/net/greth.h b/drivers/net/greth.h index 973388d6abca..03ad903cd676 100644 --- a/drivers/net/greth.h +++ b/drivers/net/greth.h | |||
@@ -118,7 +118,7 @@ struct greth_private { | |||
118 | 118 | ||
119 | int irq; | 119 | int irq; |
120 | 120 | ||
121 | struct device *dev; /* Pointer to of_device->dev */ | 121 | struct device *dev; /* Pointer to platform_device->dev */ |
122 | struct net_device *netdev; | 122 | struct net_device *netdev; |
123 | struct napi_struct napi; | 123 | struct napi_struct napi; |
124 | spinlock_t devlock; | 124 | spinlock_t devlock; |
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index eeec7bc2ce74..3506fd6ad726 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c | |||
@@ -2245,7 +2245,7 @@ static int emac_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) | |||
2245 | struct emac_depentry { | 2245 | struct emac_depentry { |
2246 | u32 phandle; | 2246 | u32 phandle; |
2247 | struct device_node *node; | 2247 | struct device_node *node; |
2248 | struct of_device *ofdev; | 2248 | struct platform_device *ofdev; |
2249 | void *drvdata; | 2249 | void *drvdata; |
2250 | }; | 2250 | }; |
2251 | 2251 | ||
@@ -2719,7 +2719,7 @@ static const struct net_device_ops emac_gige_netdev_ops = { | |||
2719 | .ndo_change_mtu = emac_change_mtu, | 2719 | .ndo_change_mtu = emac_change_mtu, |
2720 | }; | 2720 | }; |
2721 | 2721 | ||
2722 | static int __devinit emac_probe(struct of_device *ofdev, | 2722 | static int __devinit emac_probe(struct platform_device *ofdev, |
2723 | const struct of_device_id *match) | 2723 | const struct of_device_id *match) |
2724 | { | 2724 | { |
2725 | struct net_device *ndev; | 2725 | struct net_device *ndev; |
@@ -2941,7 +2941,7 @@ static int __devinit emac_probe(struct of_device *ofdev, | |||
2941 | return err; | 2941 | return err; |
2942 | } | 2942 | } |
2943 | 2943 | ||
2944 | static int __devexit emac_remove(struct of_device *ofdev) | 2944 | static int __devexit emac_remove(struct platform_device *ofdev) |
2945 | { | 2945 | { |
2946 | struct emac_instance *dev = dev_get_drvdata(&ofdev->dev); | 2946 | struct emac_instance *dev = dev_get_drvdata(&ofdev->dev); |
2947 | 2947 | ||
diff --git a/drivers/net/ibm_newemac/core.h b/drivers/net/ibm_newemac/core.h index b1cbe6fdfc7a..9e37e3d9c51d 100644 --- a/drivers/net/ibm_newemac/core.h +++ b/drivers/net/ibm_newemac/core.h | |||
@@ -170,12 +170,12 @@ struct emac_instance { | |||
170 | struct net_device *ndev; | 170 | struct net_device *ndev; |
171 | struct resource rsrc_regs; | 171 | struct resource rsrc_regs; |
172 | struct emac_regs __iomem *emacp; | 172 | struct emac_regs __iomem *emacp; |
173 | struct of_device *ofdev; | 173 | struct platform_device *ofdev; |
174 | struct device_node **blist; /* bootlist entry */ | 174 | struct device_node **blist; /* bootlist entry */ |
175 | 175 | ||
176 | /* MAL linkage */ | 176 | /* MAL linkage */ |
177 | u32 mal_ph; | 177 | u32 mal_ph; |
178 | struct of_device *mal_dev; | 178 | struct platform_device *mal_dev; |
179 | u32 mal_rx_chan; | 179 | u32 mal_rx_chan; |
180 | u32 mal_tx_chan; | 180 | u32 mal_tx_chan; |
181 | struct mal_instance *mal; | 181 | struct mal_instance *mal; |
@@ -196,24 +196,24 @@ struct emac_instance { | |||
196 | 196 | ||
197 | /* Shared MDIO if any */ | 197 | /* Shared MDIO if any */ |
198 | u32 mdio_ph; | 198 | u32 mdio_ph; |
199 | struct of_device *mdio_dev; | 199 | struct platform_device *mdio_dev; |
200 | struct emac_instance *mdio_instance; | 200 | struct emac_instance *mdio_instance; |
201 | struct mutex mdio_lock; | 201 | struct mutex mdio_lock; |
202 | 202 | ||
203 | /* ZMII infos if any */ | 203 | /* ZMII infos if any */ |
204 | u32 zmii_ph; | 204 | u32 zmii_ph; |
205 | u32 zmii_port; | 205 | u32 zmii_port; |
206 | struct of_device *zmii_dev; | 206 | struct platform_device *zmii_dev; |
207 | 207 | ||
208 | /* RGMII infos if any */ | 208 | /* RGMII infos if any */ |
209 | u32 rgmii_ph; | 209 | u32 rgmii_ph; |
210 | u32 rgmii_port; | 210 | u32 rgmii_port; |
211 | struct of_device *rgmii_dev; | 211 | struct platform_device *rgmii_dev; |
212 | 212 | ||
213 | /* TAH infos if any */ | 213 | /* TAH infos if any */ |
214 | u32 tah_ph; | 214 | u32 tah_ph; |
215 | u32 tah_port; | 215 | u32 tah_port; |
216 | struct of_device *tah_dev; | 216 | struct platform_device *tah_dev; |
217 | 217 | ||
218 | /* IRQs */ | 218 | /* IRQs */ |
219 | int wol_irq; | 219 | int wol_irq; |
diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c index fcff9e0bd382..d5717e2123e1 100644 --- a/drivers/net/ibm_newemac/mal.c +++ b/drivers/net/ibm_newemac/mal.c | |||
@@ -517,7 +517,7 @@ void *mal_dump_regs(struct mal_instance *mal, void *buf) | |||
517 | return regs + 1; | 517 | return regs + 1; |
518 | } | 518 | } |
519 | 519 | ||
520 | static int __devinit mal_probe(struct of_device *ofdev, | 520 | static int __devinit mal_probe(struct platform_device *ofdev, |
521 | const struct of_device_id *match) | 521 | const struct of_device_id *match) |
522 | { | 522 | { |
523 | struct mal_instance *mal; | 523 | struct mal_instance *mal; |
@@ -730,7 +730,7 @@ static int __devinit mal_probe(struct of_device *ofdev, | |||
730 | return err; | 730 | return err; |
731 | } | 731 | } |
732 | 732 | ||
733 | static int __devexit mal_remove(struct of_device *ofdev) | 733 | static int __devexit mal_remove(struct platform_device *ofdev) |
734 | { | 734 | { |
735 | struct mal_instance *mal = dev_get_drvdata(&ofdev->dev); | 735 | struct mal_instance *mal = dev_get_drvdata(&ofdev->dev); |
736 | 736 | ||
diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h index 9ededfbf0726..66084214bf45 100644 --- a/drivers/net/ibm_newemac/mal.h +++ b/drivers/net/ibm_newemac/mal.h | |||
@@ -210,7 +210,7 @@ struct mal_instance { | |||
210 | dma_addr_t bd_dma; | 210 | dma_addr_t bd_dma; |
211 | struct mal_descriptor *bd_virt; | 211 | struct mal_descriptor *bd_virt; |
212 | 212 | ||
213 | struct of_device *ofdev; | 213 | struct platform_device *ofdev; |
214 | int index; | 214 | int index; |
215 | spinlock_t lock; | 215 | spinlock_t lock; |
216 | 216 | ||
diff --git a/drivers/net/ibm_newemac/rgmii.c b/drivers/net/ibm_newemac/rgmii.c index 108919bcdf13..dd61798897ac 100644 --- a/drivers/net/ibm_newemac/rgmii.c +++ b/drivers/net/ibm_newemac/rgmii.c | |||
@@ -93,7 +93,7 @@ static inline u32 rgmii_mode_mask(int mode, int input) | |||
93 | } | 93 | } |
94 | } | 94 | } |
95 | 95 | ||
96 | int __devinit rgmii_attach(struct of_device *ofdev, int input, int mode) | 96 | int __devinit rgmii_attach(struct platform_device *ofdev, int input, int mode) |
97 | { | 97 | { |
98 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 98 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
99 | struct rgmii_regs __iomem *p = dev->base; | 99 | struct rgmii_regs __iomem *p = dev->base; |
@@ -122,7 +122,7 @@ int __devinit rgmii_attach(struct of_device *ofdev, int input, int mode) | |||
122 | return 0; | 122 | return 0; |
123 | } | 123 | } |
124 | 124 | ||
125 | void rgmii_set_speed(struct of_device *ofdev, int input, int speed) | 125 | void rgmii_set_speed(struct platform_device *ofdev, int input, int speed) |
126 | { | 126 | { |
127 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 127 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
128 | struct rgmii_regs __iomem *p = dev->base; | 128 | struct rgmii_regs __iomem *p = dev->base; |
@@ -144,7 +144,7 @@ void rgmii_set_speed(struct of_device *ofdev, int input, int speed) | |||
144 | mutex_unlock(&dev->lock); | 144 | mutex_unlock(&dev->lock); |
145 | } | 145 | } |
146 | 146 | ||
147 | void rgmii_get_mdio(struct of_device *ofdev, int input) | 147 | void rgmii_get_mdio(struct platform_device *ofdev, int input) |
148 | { | 148 | { |
149 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 149 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
150 | struct rgmii_regs __iomem *p = dev->base; | 150 | struct rgmii_regs __iomem *p = dev->base; |
@@ -165,7 +165,7 @@ void rgmii_get_mdio(struct of_device *ofdev, int input) | |||
165 | DBG2(dev, " fer = 0x%08x\n", fer); | 165 | DBG2(dev, " fer = 0x%08x\n", fer); |
166 | } | 166 | } |
167 | 167 | ||
168 | void rgmii_put_mdio(struct of_device *ofdev, int input) | 168 | void rgmii_put_mdio(struct platform_device *ofdev, int input) |
169 | { | 169 | { |
170 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 170 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
171 | struct rgmii_regs __iomem *p = dev->base; | 171 | struct rgmii_regs __iomem *p = dev->base; |
@@ -186,7 +186,7 @@ void rgmii_put_mdio(struct of_device *ofdev, int input) | |||
186 | mutex_unlock(&dev->lock); | 186 | mutex_unlock(&dev->lock); |
187 | } | 187 | } |
188 | 188 | ||
189 | void rgmii_detach(struct of_device *ofdev, int input) | 189 | void rgmii_detach(struct platform_device *ofdev, int input) |
190 | { | 190 | { |
191 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 191 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
192 | struct rgmii_regs __iomem *p; | 192 | struct rgmii_regs __iomem *p; |
@@ -206,13 +206,13 @@ void rgmii_detach(struct of_device *ofdev, int input) | |||
206 | mutex_unlock(&dev->lock); | 206 | mutex_unlock(&dev->lock); |
207 | } | 207 | } |
208 | 208 | ||
209 | int rgmii_get_regs_len(struct of_device *ofdev) | 209 | int rgmii_get_regs_len(struct platform_device *ofdev) |
210 | { | 210 | { |
211 | return sizeof(struct emac_ethtool_regs_subhdr) + | 211 | return sizeof(struct emac_ethtool_regs_subhdr) + |
212 | sizeof(struct rgmii_regs); | 212 | sizeof(struct rgmii_regs); |
213 | } | 213 | } |
214 | 214 | ||
215 | void *rgmii_dump_regs(struct of_device *ofdev, void *buf) | 215 | void *rgmii_dump_regs(struct platform_device *ofdev, void *buf) |
216 | { | 216 | { |
217 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 217 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
218 | struct emac_ethtool_regs_subhdr *hdr = buf; | 218 | struct emac_ethtool_regs_subhdr *hdr = buf; |
@@ -228,7 +228,7 @@ void *rgmii_dump_regs(struct of_device *ofdev, void *buf) | |||
228 | } | 228 | } |
229 | 229 | ||
230 | 230 | ||
231 | static int __devinit rgmii_probe(struct of_device *ofdev, | 231 | static int __devinit rgmii_probe(struct platform_device *ofdev, |
232 | const struct of_device_id *match) | 232 | const struct of_device_id *match) |
233 | { | 233 | { |
234 | struct device_node *np = ofdev->dev.of_node; | 234 | struct device_node *np = ofdev->dev.of_node; |
@@ -293,7 +293,7 @@ static int __devinit rgmii_probe(struct of_device *ofdev, | |||
293 | return rc; | 293 | return rc; |
294 | } | 294 | } |
295 | 295 | ||
296 | static int __devexit rgmii_remove(struct of_device *ofdev) | 296 | static int __devexit rgmii_remove(struct platform_device *ofdev) |
297 | { | 297 | { |
298 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 298 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
299 | 299 | ||
diff --git a/drivers/net/ibm_newemac/rgmii.h b/drivers/net/ibm_newemac/rgmii.h index c4a4b358a270..d69799049865 100644 --- a/drivers/net/ibm_newemac/rgmii.h +++ b/drivers/net/ibm_newemac/rgmii.h | |||
@@ -51,20 +51,20 @@ struct rgmii_instance { | |||
51 | int users; | 51 | int users; |
52 | 52 | ||
53 | /* OF device instance */ | 53 | /* OF device instance */ |
54 | struct of_device *ofdev; | 54 | struct platform_device *ofdev; |
55 | }; | 55 | }; |
56 | 56 | ||
57 | #ifdef CONFIG_IBM_NEW_EMAC_RGMII | 57 | #ifdef CONFIG_IBM_NEW_EMAC_RGMII |
58 | 58 | ||
59 | extern int rgmii_init(void); | 59 | extern int rgmii_init(void); |
60 | extern void rgmii_exit(void); | 60 | extern void rgmii_exit(void); |
61 | extern int rgmii_attach(struct of_device *ofdev, int input, int mode); | 61 | extern int rgmii_attach(struct platform_device *ofdev, int input, int mode); |
62 | extern void rgmii_detach(struct of_device *ofdev, int input); | 62 | extern void rgmii_detach(struct platform_device *ofdev, int input); |
63 | extern void rgmii_get_mdio(struct of_device *ofdev, int input); | 63 | extern void rgmii_get_mdio(struct platform_device *ofdev, int input); |
64 | extern void rgmii_put_mdio(struct of_device *ofdev, int input); | 64 | extern void rgmii_put_mdio(struct platform_device *ofdev, int input); |
65 | extern void rgmii_set_speed(struct of_device *ofdev, int input, int speed); | 65 | extern void rgmii_set_speed(struct platform_device *ofdev, int input, int speed); |
66 | extern int rgmii_get_regs_len(struct of_device *ofdev); | 66 | extern int rgmii_get_regs_len(struct platform_device *ofdev); |
67 | extern void *rgmii_dump_regs(struct of_device *ofdev, void *buf); | 67 | extern void *rgmii_dump_regs(struct platform_device *ofdev, void *buf); |
68 | 68 | ||
69 | #else | 69 | #else |
70 | 70 | ||
diff --git a/drivers/net/ibm_newemac/tah.c b/drivers/net/ibm_newemac/tah.c index 044637144c43..299aa49490c0 100644 --- a/drivers/net/ibm_newemac/tah.c +++ b/drivers/net/ibm_newemac/tah.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include "emac.h" | 23 | #include "emac.h" |
24 | #include "core.h" | 24 | #include "core.h" |
25 | 25 | ||
26 | int __devinit tah_attach(struct of_device *ofdev, int channel) | 26 | int __devinit tah_attach(struct platform_device *ofdev, int channel) |
27 | { | 27 | { |
28 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); | 28 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); |
29 | 29 | ||
@@ -35,7 +35,7 @@ int __devinit tah_attach(struct of_device *ofdev, int channel) | |||
35 | return 0; | 35 | return 0; |
36 | } | 36 | } |
37 | 37 | ||
38 | void tah_detach(struct of_device *ofdev, int channel) | 38 | void tah_detach(struct platform_device *ofdev, int channel) |
39 | { | 39 | { |
40 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); | 40 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); |
41 | 41 | ||
@@ -44,7 +44,7 @@ void tah_detach(struct of_device *ofdev, int channel) | |||
44 | mutex_unlock(&dev->lock); | 44 | mutex_unlock(&dev->lock); |
45 | } | 45 | } |
46 | 46 | ||
47 | void tah_reset(struct of_device *ofdev) | 47 | void tah_reset(struct platform_device *ofdev) |
48 | { | 48 | { |
49 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); | 49 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); |
50 | struct tah_regs __iomem *p = dev->base; | 50 | struct tah_regs __iomem *p = dev->base; |
@@ -66,13 +66,13 @@ void tah_reset(struct of_device *ofdev) | |||
66 | TAH_MR_DIG); | 66 | TAH_MR_DIG); |
67 | } | 67 | } |
68 | 68 | ||
69 | int tah_get_regs_len(struct of_device *ofdev) | 69 | int tah_get_regs_len(struct platform_device *ofdev) |
70 | { | 70 | { |
71 | return sizeof(struct emac_ethtool_regs_subhdr) + | 71 | return sizeof(struct emac_ethtool_regs_subhdr) + |
72 | sizeof(struct tah_regs); | 72 | sizeof(struct tah_regs); |
73 | } | 73 | } |
74 | 74 | ||
75 | void *tah_dump_regs(struct of_device *ofdev, void *buf) | 75 | void *tah_dump_regs(struct platform_device *ofdev, void *buf) |
76 | { | 76 | { |
77 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); | 77 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); |
78 | struct emac_ethtool_regs_subhdr *hdr = buf; | 78 | struct emac_ethtool_regs_subhdr *hdr = buf; |
@@ -87,7 +87,7 @@ void *tah_dump_regs(struct of_device *ofdev, void *buf) | |||
87 | return regs + 1; | 87 | return regs + 1; |
88 | } | 88 | } |
89 | 89 | ||
90 | static int __devinit tah_probe(struct of_device *ofdev, | 90 | static int __devinit tah_probe(struct platform_device *ofdev, |
91 | const struct of_device_id *match) | 91 | const struct of_device_id *match) |
92 | { | 92 | { |
93 | struct device_node *np = ofdev->dev.of_node; | 93 | struct device_node *np = ofdev->dev.of_node; |
@@ -139,7 +139,7 @@ static int __devinit tah_probe(struct of_device *ofdev, | |||
139 | return rc; | 139 | return rc; |
140 | } | 140 | } |
141 | 141 | ||
142 | static int __devexit tah_remove(struct of_device *ofdev) | 142 | static int __devexit tah_remove(struct platform_device *ofdev) |
143 | { | 143 | { |
144 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); | 144 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); |
145 | 145 | ||
diff --git a/drivers/net/ibm_newemac/tah.h b/drivers/net/ibm_newemac/tah.h index a068b5658dad..61dbeca006d1 100644 --- a/drivers/net/ibm_newemac/tah.h +++ b/drivers/net/ibm_newemac/tah.h | |||
@@ -48,7 +48,7 @@ struct tah_instance { | |||
48 | int users; | 48 | int users; |
49 | 49 | ||
50 | /* OF device instance */ | 50 | /* OF device instance */ |
51 | struct of_device *ofdev; | 51 | struct platform_device *ofdev; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | 54 | ||
@@ -74,11 +74,11 @@ struct tah_instance { | |||
74 | 74 | ||
75 | extern int tah_init(void); | 75 | extern int tah_init(void); |
76 | extern void tah_exit(void); | 76 | extern void tah_exit(void); |
77 | extern int tah_attach(struct of_device *ofdev, int channel); | 77 | extern int tah_attach(struct platform_device *ofdev, int channel); |
78 | extern void tah_detach(struct of_device *ofdev, int channel); | 78 | extern void tah_detach(struct platform_device *ofdev, int channel); |
79 | extern void tah_reset(struct of_device *ofdev); | 79 | extern void tah_reset(struct platform_device *ofdev); |
80 | extern int tah_get_regs_len(struct of_device *ofdev); | 80 | extern int tah_get_regs_len(struct platform_device *ofdev); |
81 | extern void *tah_dump_regs(struct of_device *ofdev, void *buf); | 81 | extern void *tah_dump_regs(struct platform_device *ofdev, void *buf); |
82 | 82 | ||
83 | #else | 83 | #else |
84 | 84 | ||
diff --git a/drivers/net/ibm_newemac/zmii.c b/drivers/net/ibm_newemac/zmii.c index 046dcd069c45..34ed6ee8ca8a 100644 --- a/drivers/net/ibm_newemac/zmii.c +++ b/drivers/net/ibm_newemac/zmii.c | |||
@@ -82,7 +82,7 @@ static inline u32 zmii_mode_mask(int mode, int input) | |||
82 | } | 82 | } |
83 | } | 83 | } |
84 | 84 | ||
85 | int __devinit zmii_attach(struct of_device *ofdev, int input, int *mode) | 85 | int __devinit zmii_attach(struct platform_device *ofdev, int input, int *mode) |
86 | { | 86 | { |
87 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 87 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
88 | struct zmii_regs __iomem *p = dev->base; | 88 | struct zmii_regs __iomem *p = dev->base; |
@@ -148,7 +148,7 @@ int __devinit zmii_attach(struct of_device *ofdev, int input, int *mode) | |||
148 | return 0; | 148 | return 0; |
149 | } | 149 | } |
150 | 150 | ||
151 | void zmii_get_mdio(struct of_device *ofdev, int input) | 151 | void zmii_get_mdio(struct platform_device *ofdev, int input) |
152 | { | 152 | { |
153 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 153 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
154 | u32 fer; | 154 | u32 fer; |
@@ -161,7 +161,7 @@ void zmii_get_mdio(struct of_device *ofdev, int input) | |||
161 | out_be32(&dev->base->fer, fer | ZMII_FER_MDI(input)); | 161 | out_be32(&dev->base->fer, fer | ZMII_FER_MDI(input)); |
162 | } | 162 | } |
163 | 163 | ||
164 | void zmii_put_mdio(struct of_device *ofdev, int input) | 164 | void zmii_put_mdio(struct platform_device *ofdev, int input) |
165 | { | 165 | { |
166 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 166 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
167 | 167 | ||
@@ -170,7 +170,7 @@ void zmii_put_mdio(struct of_device *ofdev, int input) | |||
170 | } | 170 | } |
171 | 171 | ||
172 | 172 | ||
173 | void zmii_set_speed(struct of_device *ofdev, int input, int speed) | 173 | void zmii_set_speed(struct platform_device *ofdev, int input, int speed) |
174 | { | 174 | { |
175 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 175 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
176 | u32 ssr; | 176 | u32 ssr; |
@@ -191,7 +191,7 @@ void zmii_set_speed(struct of_device *ofdev, int input, int speed) | |||
191 | mutex_unlock(&dev->lock); | 191 | mutex_unlock(&dev->lock); |
192 | } | 192 | } |
193 | 193 | ||
194 | void zmii_detach(struct of_device *ofdev, int input) | 194 | void zmii_detach(struct platform_device *ofdev, int input) |
195 | { | 195 | { |
196 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 196 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
197 | 197 | ||
@@ -210,13 +210,13 @@ void zmii_detach(struct of_device *ofdev, int input) | |||
210 | mutex_unlock(&dev->lock); | 210 | mutex_unlock(&dev->lock); |
211 | } | 211 | } |
212 | 212 | ||
213 | int zmii_get_regs_len(struct of_device *ofdev) | 213 | int zmii_get_regs_len(struct platform_device *ofdev) |
214 | { | 214 | { |
215 | return sizeof(struct emac_ethtool_regs_subhdr) + | 215 | return sizeof(struct emac_ethtool_regs_subhdr) + |
216 | sizeof(struct zmii_regs); | 216 | sizeof(struct zmii_regs); |
217 | } | 217 | } |
218 | 218 | ||
219 | void *zmii_dump_regs(struct of_device *ofdev, void *buf) | 219 | void *zmii_dump_regs(struct platform_device *ofdev, void *buf) |
220 | { | 220 | { |
221 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 221 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
222 | struct emac_ethtool_regs_subhdr *hdr = buf; | 222 | struct emac_ethtool_regs_subhdr *hdr = buf; |
@@ -231,7 +231,7 @@ void *zmii_dump_regs(struct of_device *ofdev, void *buf) | |||
231 | return regs + 1; | 231 | return regs + 1; |
232 | } | 232 | } |
233 | 233 | ||
234 | static int __devinit zmii_probe(struct of_device *ofdev, | 234 | static int __devinit zmii_probe(struct platform_device *ofdev, |
235 | const struct of_device_id *match) | 235 | const struct of_device_id *match) |
236 | { | 236 | { |
237 | struct device_node *np = ofdev->dev.of_node; | 237 | struct device_node *np = ofdev->dev.of_node; |
@@ -286,7 +286,7 @@ static int __devinit zmii_probe(struct of_device *ofdev, | |||
286 | return rc; | 286 | return rc; |
287 | } | 287 | } |
288 | 288 | ||
289 | static int __devexit zmii_remove(struct of_device *ofdev) | 289 | static int __devexit zmii_remove(struct platform_device *ofdev) |
290 | { | 290 | { |
291 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 291 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
292 | 292 | ||
diff --git a/drivers/net/ibm_newemac/zmii.h b/drivers/net/ibm_newemac/zmii.h index 6c9beba0c4b6..1333fa2b2781 100644 --- a/drivers/net/ibm_newemac/zmii.h +++ b/drivers/net/ibm_newemac/zmii.h | |||
@@ -48,20 +48,20 @@ struct zmii_instance { | |||
48 | u32 fer_save; | 48 | u32 fer_save; |
49 | 49 | ||
50 | /* OF device instance */ | 50 | /* OF device instance */ |
51 | struct of_device *ofdev; | 51 | struct platform_device *ofdev; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | #ifdef CONFIG_IBM_NEW_EMAC_ZMII | 54 | #ifdef CONFIG_IBM_NEW_EMAC_ZMII |
55 | 55 | ||
56 | extern int zmii_init(void); | 56 | extern int zmii_init(void); |
57 | extern void zmii_exit(void); | 57 | extern void zmii_exit(void); |
58 | extern int zmii_attach(struct of_device *ofdev, int input, int *mode); | 58 | extern int zmii_attach(struct platform_device *ofdev, int input, int *mode); |
59 | extern void zmii_detach(struct of_device *ofdev, int input); | 59 | extern void zmii_detach(struct platform_device *ofdev, int input); |
60 | extern void zmii_get_mdio(struct of_device *ofdev, int input); | 60 | extern void zmii_get_mdio(struct platform_device *ofdev, int input); |
61 | extern void zmii_put_mdio(struct of_device *ofdev, int input); | 61 | extern void zmii_put_mdio(struct platform_device *ofdev, int input); |
62 | extern void zmii_set_speed(struct of_device *ofdev, int input, int speed); | 62 | extern void zmii_set_speed(struct platform_device *ofdev, int input, int speed); |
63 | extern int zmii_get_regs_len(struct of_device *ocpdev); | 63 | extern int zmii_get_regs_len(struct platform_device *ocpdev); |
64 | extern void *zmii_dump_regs(struct of_device *ofdev, void *buf); | 64 | extern void *zmii_dump_regs(struct platform_device *ofdev, void *buf); |
65 | 65 | ||
66 | #else | 66 | #else |
67 | # define zmii_init() 0 | 67 | # define zmii_init() 0 |
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index 4eea3f70c5cf..c7b624711f5e 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c | |||
@@ -159,7 +159,7 @@ static void temac_dma_dcr_out(struct temac_local *lp, int reg, u32 value) | |||
159 | * temac_dcr_setup - If the DMA is DCR based, then setup the address and | 159 | * temac_dcr_setup - If the DMA is DCR based, then setup the address and |
160 | * I/O functions | 160 | * I/O functions |
161 | */ | 161 | */ |
162 | static int temac_dcr_setup(struct temac_local *lp, struct of_device *op, | 162 | static int temac_dcr_setup(struct temac_local *lp, struct platform_device *op, |
163 | struct device_node *np) | 163 | struct device_node *np) |
164 | { | 164 | { |
165 | unsigned int dcrs; | 165 | unsigned int dcrs; |
@@ -184,7 +184,7 @@ static int temac_dcr_setup(struct temac_local *lp, struct of_device *op, | |||
184 | * temac_dcr_setup - This is a stub for when DCR is not supported, | 184 | * temac_dcr_setup - This is a stub for when DCR is not supported, |
185 | * such as with MicroBlaze | 185 | * such as with MicroBlaze |
186 | */ | 186 | */ |
187 | static int temac_dcr_setup(struct temac_local *lp, struct of_device *op, | 187 | static int temac_dcr_setup(struct temac_local *lp, struct platform_device *op, |
188 | struct device_node *np) | 188 | struct device_node *np) |
189 | { | 189 | { |
190 | return -1; | 190 | return -1; |
@@ -952,7 +952,7 @@ static const struct attribute_group temac_attr_group = { | |||
952 | }; | 952 | }; |
953 | 953 | ||
954 | static int __init | 954 | static int __init |
955 | temac_of_probe(struct of_device *op, const struct of_device_id *match) | 955 | temac_of_probe(struct platform_device *op, const struct of_device_id *match) |
956 | { | 956 | { |
957 | struct device_node *np; | 957 | struct device_node *np; |
958 | struct temac_local *lp; | 958 | struct temac_local *lp; |
@@ -1094,7 +1094,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match) | |||
1094 | return rc; | 1094 | return rc; |
1095 | } | 1095 | } |
1096 | 1096 | ||
1097 | static int __devexit temac_of_remove(struct of_device *op) | 1097 | static int __devexit temac_of_remove(struct platform_device *op) |
1098 | { | 1098 | { |
1099 | struct net_device *ndev = dev_get_drvdata(&op->dev); | 1099 | struct net_device *ndev = dev_get_drvdata(&op->dev); |
1100 | struct temac_local *lp = netdev_priv(ndev); | 1100 | struct temac_local *lp = netdev_priv(ndev); |
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index d771d1650d60..fb2c0927d3cc 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
@@ -239,6 +239,7 @@ struct myri10ge_priv { | |||
239 | int watchdog_resets; | 239 | int watchdog_resets; |
240 | int watchdog_pause; | 240 | int watchdog_pause; |
241 | int pause; | 241 | int pause; |
242 | bool fw_name_allocated; | ||
242 | char *fw_name; | 243 | char *fw_name; |
243 | char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE]; | 244 | char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE]; |
244 | char *product_code_string; | 245 | char *product_code_string; |
@@ -271,6 +272,7 @@ MODULE_FIRMWARE("myri10ge_eth_z8e.dat"); | |||
271 | MODULE_FIRMWARE("myri10ge_rss_ethp_z8e.dat"); | 272 | MODULE_FIRMWARE("myri10ge_rss_ethp_z8e.dat"); |
272 | MODULE_FIRMWARE("myri10ge_rss_eth_z8e.dat"); | 273 | MODULE_FIRMWARE("myri10ge_rss_eth_z8e.dat"); |
273 | 274 | ||
275 | /* Careful: must be accessed under kparam_block_sysfs_write */ | ||
274 | static char *myri10ge_fw_name = NULL; | 276 | static char *myri10ge_fw_name = NULL; |
275 | module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR); | 277 | module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR); |
276 | MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name"); | 278 | MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name"); |
@@ -376,6 +378,14 @@ static inline void put_be32(__be32 val, __be32 __iomem * p) | |||
376 | 378 | ||
377 | static struct net_device_stats *myri10ge_get_stats(struct net_device *dev); | 379 | static struct net_device_stats *myri10ge_get_stats(struct net_device *dev); |
378 | 380 | ||
381 | static void set_fw_name(struct myri10ge_priv *mgp, char *name, bool allocated) | ||
382 | { | ||
383 | if (mgp->fw_name_allocated) | ||
384 | kfree(mgp->fw_name); | ||
385 | mgp->fw_name = name; | ||
386 | mgp->fw_name_allocated = allocated; | ||
387 | } | ||
388 | |||
379 | static int | 389 | static int |
380 | myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, | 390 | myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, |
381 | struct myri10ge_cmd *data, int atomic) | 391 | struct myri10ge_cmd *data, int atomic) |
@@ -747,7 +757,7 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp, int adopt) | |||
747 | dev_warn(&mgp->pdev->dev, "via hotplug\n"); | 757 | dev_warn(&mgp->pdev->dev, "via hotplug\n"); |
748 | } | 758 | } |
749 | 759 | ||
750 | mgp->fw_name = "adopted"; | 760 | set_fw_name(mgp, "adopted", false); |
751 | mgp->tx_boundary = 2048; | 761 | mgp->tx_boundary = 2048; |
752 | myri10ge_dummy_rdma(mgp, 1); | 762 | myri10ge_dummy_rdma(mgp, 1); |
753 | status = myri10ge_get_firmware_capabilities(mgp); | 763 | status = myri10ge_get_firmware_capabilities(mgp); |
@@ -3233,7 +3243,7 @@ static void myri10ge_firmware_probe(struct myri10ge_priv *mgp) | |||
3233 | * load the optimized firmware (which assumes aligned PCIe | 3243 | * load the optimized firmware (which assumes aligned PCIe |
3234 | * completions) in order to see if it works on this host. | 3244 | * completions) in order to see if it works on this host. |
3235 | */ | 3245 | */ |
3236 | mgp->fw_name = myri10ge_fw_aligned; | 3246 | set_fw_name(mgp, myri10ge_fw_aligned, false); |
3237 | status = myri10ge_load_firmware(mgp, 1); | 3247 | status = myri10ge_load_firmware(mgp, 1); |
3238 | if (status != 0) { | 3248 | if (status != 0) { |
3239 | goto abort; | 3249 | goto abort; |
@@ -3261,7 +3271,7 @@ static void myri10ge_firmware_probe(struct myri10ge_priv *mgp) | |||
3261 | abort: | 3271 | abort: |
3262 | /* fall back to using the unaligned firmware */ | 3272 | /* fall back to using the unaligned firmware */ |
3263 | mgp->tx_boundary = 2048; | 3273 | mgp->tx_boundary = 2048; |
3264 | mgp->fw_name = myri10ge_fw_unaligned; | 3274 | set_fw_name(mgp, myri10ge_fw_unaligned, false); |
3265 | 3275 | ||
3266 | } | 3276 | } |
3267 | 3277 | ||
@@ -3284,7 +3294,7 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) | |||
3284 | dev_info(&mgp->pdev->dev, "PCIE x%d Link\n", | 3294 | dev_info(&mgp->pdev->dev, "PCIE x%d Link\n", |
3285 | link_width); | 3295 | link_width); |
3286 | mgp->tx_boundary = 4096; | 3296 | mgp->tx_boundary = 4096; |
3287 | mgp->fw_name = myri10ge_fw_aligned; | 3297 | set_fw_name(mgp, myri10ge_fw_aligned, false); |
3288 | } else { | 3298 | } else { |
3289 | myri10ge_firmware_probe(mgp); | 3299 | myri10ge_firmware_probe(mgp); |
3290 | } | 3300 | } |
@@ -3293,22 +3303,29 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) | |||
3293 | dev_info(&mgp->pdev->dev, | 3303 | dev_info(&mgp->pdev->dev, |
3294 | "Assuming aligned completions (forced)\n"); | 3304 | "Assuming aligned completions (forced)\n"); |
3295 | mgp->tx_boundary = 4096; | 3305 | mgp->tx_boundary = 4096; |
3296 | mgp->fw_name = myri10ge_fw_aligned; | 3306 | set_fw_name(mgp, myri10ge_fw_aligned, false); |
3297 | } else { | 3307 | } else { |
3298 | dev_info(&mgp->pdev->dev, | 3308 | dev_info(&mgp->pdev->dev, |
3299 | "Assuming unaligned completions (forced)\n"); | 3309 | "Assuming unaligned completions (forced)\n"); |
3300 | mgp->tx_boundary = 2048; | 3310 | mgp->tx_boundary = 2048; |
3301 | mgp->fw_name = myri10ge_fw_unaligned; | 3311 | set_fw_name(mgp, myri10ge_fw_unaligned, false); |
3302 | } | 3312 | } |
3303 | } | 3313 | } |
3314 | |||
3315 | kparam_block_sysfs_write(myri10ge_fw_name); | ||
3304 | if (myri10ge_fw_name != NULL) { | 3316 | if (myri10ge_fw_name != NULL) { |
3305 | overridden = 1; | 3317 | char *fw_name = kstrdup(myri10ge_fw_name, GFP_KERNEL); |
3306 | mgp->fw_name = myri10ge_fw_name; | 3318 | if (fw_name) { |
3319 | overridden = 1; | ||
3320 | set_fw_name(mgp, fw_name, true); | ||
3321 | } | ||
3307 | } | 3322 | } |
3323 | kparam_unblock_sysfs_write(myri10ge_fw_name); | ||
3324 | |||
3308 | if (mgp->board_number < MYRI10GE_MAX_BOARDS && | 3325 | if (mgp->board_number < MYRI10GE_MAX_BOARDS && |
3309 | myri10ge_fw_names[mgp->board_number] != NULL && | 3326 | myri10ge_fw_names[mgp->board_number] != NULL && |
3310 | strlen(myri10ge_fw_names[mgp->board_number])) { | 3327 | strlen(myri10ge_fw_names[mgp->board_number])) { |
3311 | mgp->fw_name = myri10ge_fw_names[mgp->board_number]; | 3328 | set_fw_name(mgp, myri10ge_fw_names[mgp->board_number], false); |
3312 | overridden = 1; | 3329 | overridden = 1; |
3313 | } | 3330 | } |
3314 | if (overridden) | 3331 | if (overridden) |
@@ -3660,6 +3677,7 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp) | |||
3660 | struct myri10ge_cmd cmd; | 3677 | struct myri10ge_cmd cmd; |
3661 | struct pci_dev *pdev = mgp->pdev; | 3678 | struct pci_dev *pdev = mgp->pdev; |
3662 | char *old_fw; | 3679 | char *old_fw; |
3680 | bool old_allocated; | ||
3663 | int i, status, ncpus, msix_cap; | 3681 | int i, status, ncpus, msix_cap; |
3664 | 3682 | ||
3665 | mgp->num_slices = 1; | 3683 | mgp->num_slices = 1; |
@@ -3672,17 +3690,23 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp) | |||
3672 | 3690 | ||
3673 | /* try to load the slice aware rss firmware */ | 3691 | /* try to load the slice aware rss firmware */ |
3674 | old_fw = mgp->fw_name; | 3692 | old_fw = mgp->fw_name; |
3693 | old_allocated = mgp->fw_name_allocated; | ||
3694 | /* don't free old_fw if we override it. */ | ||
3695 | mgp->fw_name_allocated = false; | ||
3696 | |||
3675 | if (myri10ge_fw_name != NULL) { | 3697 | if (myri10ge_fw_name != NULL) { |
3676 | dev_info(&mgp->pdev->dev, "overriding rss firmware to %s\n", | 3698 | dev_info(&mgp->pdev->dev, "overriding rss firmware to %s\n", |
3677 | myri10ge_fw_name); | 3699 | myri10ge_fw_name); |
3678 | mgp->fw_name = myri10ge_fw_name; | 3700 | set_fw_name(mgp, myri10ge_fw_name, false); |
3679 | } else if (old_fw == myri10ge_fw_aligned) | 3701 | } else if (old_fw == myri10ge_fw_aligned) |
3680 | mgp->fw_name = myri10ge_fw_rss_aligned; | 3702 | set_fw_name(mgp, myri10ge_fw_rss_aligned, false); |
3681 | else | 3703 | else |
3682 | mgp->fw_name = myri10ge_fw_rss_unaligned; | 3704 | set_fw_name(mgp, myri10ge_fw_rss_unaligned, false); |
3683 | status = myri10ge_load_firmware(mgp, 0); | 3705 | status = myri10ge_load_firmware(mgp, 0); |
3684 | if (status != 0) { | 3706 | if (status != 0) { |
3685 | dev_info(&pdev->dev, "Rss firmware not found\n"); | 3707 | dev_info(&pdev->dev, "Rss firmware not found\n"); |
3708 | if (old_allocated) | ||
3709 | kfree(old_fw); | ||
3686 | return; | 3710 | return; |
3687 | } | 3711 | } |
3688 | 3712 | ||
@@ -3747,6 +3771,8 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp) | |||
3747 | mgp->num_slices); | 3771 | mgp->num_slices); |
3748 | if (status == 0) { | 3772 | if (status == 0) { |
3749 | pci_disable_msix(pdev); | 3773 | pci_disable_msix(pdev); |
3774 | if (old_allocated) | ||
3775 | kfree(old_fw); | ||
3750 | return; | 3776 | return; |
3751 | } | 3777 | } |
3752 | if (status > 0) | 3778 | if (status > 0) |
@@ -3763,7 +3789,7 @@ disable_msix: | |||
3763 | 3789 | ||
3764 | abort_with_fw: | 3790 | abort_with_fw: |
3765 | mgp->num_slices = 1; | 3791 | mgp->num_slices = 1; |
3766 | mgp->fw_name = old_fw; | 3792 | set_fw_name(mgp, old_fw, old_allocated); |
3767 | myri10ge_load_firmware(mgp, 0); | 3793 | myri10ge_load_firmware(mgp, 0); |
3768 | } | 3794 | } |
3769 | 3795 | ||
@@ -3993,6 +4019,7 @@ abort_with_enabled: | |||
3993 | pci_disable_device(pdev); | 4019 | pci_disable_device(pdev); |
3994 | 4020 | ||
3995 | abort_with_netdev: | 4021 | abort_with_netdev: |
4022 | set_fw_name(mgp, NULL, false); | ||
3996 | free_netdev(netdev); | 4023 | free_netdev(netdev); |
3997 | return status; | 4024 | return status; |
3998 | } | 4025 | } |
@@ -4037,6 +4064,7 @@ static void myri10ge_remove(struct pci_dev *pdev) | |||
4037 | dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd), | 4064 | dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd), |
4038 | mgp->cmd, mgp->cmd_bus); | 4065 | mgp->cmd, mgp->cmd_bus); |
4039 | 4066 | ||
4067 | set_fw_name(mgp, NULL, false); | ||
4040 | free_netdev(netdev); | 4068 | free_netdev(netdev); |
4041 | pci_disable_device(pdev); | 4069 | pci_disable_device(pdev); |
4042 | pci_set_drvdata(pdev, NULL); | 4070 | pci_set_drvdata(pdev, NULL); |
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 04e552aa14ec..617f898ba5f0 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c | |||
@@ -926,7 +926,7 @@ static const struct net_device_ops myri_ops = { | |||
926 | .ndo_validate_addr = eth_validate_addr, | 926 | .ndo_validate_addr = eth_validate_addr, |
927 | }; | 927 | }; |
928 | 928 | ||
929 | static int __devinit myri_sbus_probe(struct of_device *op, const struct of_device_id *match) | 929 | static int __devinit myri_sbus_probe(struct platform_device *op, const struct of_device_id *match) |
930 | { | 930 | { |
931 | struct device_node *dp = op->dev.of_node; | 931 | struct device_node *dp = op->dev.of_node; |
932 | static unsigned version_printed; | 932 | static unsigned version_printed; |
@@ -1124,7 +1124,7 @@ err: | |||
1124 | return -ENODEV; | 1124 | return -ENODEV; |
1125 | } | 1125 | } |
1126 | 1126 | ||
1127 | static int __devexit myri_sbus_remove(struct of_device *op) | 1127 | static int __devexit myri_sbus_remove(struct platform_device *op) |
1128 | { | 1128 | { |
1129 | struct myri_eth *mp = dev_get_drvdata(&op->dev); | 1129 | struct myri_eth *mp = dev_get_drvdata(&op->dev); |
1130 | struct net_device *net_dev = mp->dev; | 1130 | struct net_device *net_dev = mp->dev; |
diff --git a/drivers/net/myri_sbus.h b/drivers/net/myri_sbus.h index ff363e95d9cf..80a2fa5cf757 100644 --- a/drivers/net/myri_sbus.h +++ b/drivers/net/myri_sbus.h | |||
@@ -288,7 +288,7 @@ struct myri_eth { | |||
288 | struct myri_eeprom eeprom; /* Local copy of EEPROM. */ | 288 | struct myri_eeprom eeprom; /* Local copy of EEPROM. */ |
289 | unsigned int reg_size; /* Size of register space. */ | 289 | unsigned int reg_size; /* Size of register space. */ |
290 | unsigned int shmem_base; /* Offset to shared ram. */ | 290 | unsigned int shmem_base; /* Offset to shared ram. */ |
291 | struct of_device *myri_op; /* Our OF device struct. */ | 291 | struct platform_device *myri_op; /* Our OF device struct. */ |
292 | }; | 292 | }; |
293 | 293 | ||
294 | /* We use this to acquire receive skb's that we can DMA directly into. */ | 294 | /* We use this to acquire receive skb's that we can DMA directly into. */ |
diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 404f2d552888..bc695d53cdcc 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c | |||
@@ -9103,7 +9103,7 @@ retry: | |||
9103 | static int __devinit niu_n2_irq_init(struct niu *np, u8 *ldg_num_map) | 9103 | static int __devinit niu_n2_irq_init(struct niu *np, u8 *ldg_num_map) |
9104 | { | 9104 | { |
9105 | #ifdef CONFIG_SPARC64 | 9105 | #ifdef CONFIG_SPARC64 |
9106 | struct of_device *op = np->op; | 9106 | struct platform_device *op = np->op; |
9107 | const u32 *int_prop; | 9107 | const u32 *int_prop; |
9108 | int i; | 9108 | int i; |
9109 | 9109 | ||
@@ -9688,7 +9688,7 @@ static void __devinit niu_driver_version(void) | |||
9688 | 9688 | ||
9689 | static struct net_device * __devinit niu_alloc_and_init( | 9689 | static struct net_device * __devinit niu_alloc_and_init( |
9690 | struct device *gen_dev, struct pci_dev *pdev, | 9690 | struct device *gen_dev, struct pci_dev *pdev, |
9691 | struct of_device *op, const struct niu_ops *ops, | 9691 | struct platform_device *op, const struct niu_ops *ops, |
9692 | u8 port) | 9692 | u8 port) |
9693 | { | 9693 | { |
9694 | struct net_device *dev; | 9694 | struct net_device *dev; |
@@ -10064,7 +10064,7 @@ static const struct niu_ops niu_phys_ops = { | |||
10064 | .unmap_single = niu_phys_unmap_single, | 10064 | .unmap_single = niu_phys_unmap_single, |
10065 | }; | 10065 | }; |
10066 | 10066 | ||
10067 | static int __devinit niu_of_probe(struct of_device *op, | 10067 | static int __devinit niu_of_probe(struct platform_device *op, |
10068 | const struct of_device_id *match) | 10068 | const struct of_device_id *match) |
10069 | { | 10069 | { |
10070 | union niu_parent_id parent_id; | 10070 | union niu_parent_id parent_id; |
@@ -10179,7 +10179,7 @@ err_out: | |||
10179 | return err; | 10179 | return err; |
10180 | } | 10180 | } |
10181 | 10181 | ||
10182 | static int __devexit niu_of_remove(struct of_device *op) | 10182 | static int __devexit niu_of_remove(struct platform_device *op) |
10183 | { | 10183 | { |
10184 | struct net_device *dev = dev_get_drvdata(&op->dev); | 10184 | struct net_device *dev = dev_get_drvdata(&op->dev); |
10185 | 10185 | ||
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index fc5fef2a8175..f62c7b717bc8 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c | |||
@@ -188,7 +188,7 @@ static int __devexit mdio_gpio_remove(struct platform_device *pdev) | |||
188 | 188 | ||
189 | #ifdef CONFIG_OF_GPIO | 189 | #ifdef CONFIG_OF_GPIO |
190 | 190 | ||
191 | static int __devinit mdio_ofgpio_probe(struct of_device *ofdev, | 191 | static int __devinit mdio_ofgpio_probe(struct platform_device *ofdev, |
192 | const struct of_device_id *match) | 192 | const struct of_device_id *match) |
193 | { | 193 | { |
194 | struct mdio_gpio_platform_data *pdata; | 194 | struct mdio_gpio_platform_data *pdata; |
@@ -224,7 +224,7 @@ out_free: | |||
224 | return -ENODEV; | 224 | return -ENODEV; |
225 | } | 225 | } |
226 | 226 | ||
227 | static int __devexit mdio_ofgpio_remove(struct of_device *ofdev) | 227 | static int __devexit mdio_ofgpio_remove(struct platform_device *ofdev) |
228 | { | 228 | { |
229 | mdio_gpio_bus_destroy(&ofdev->dev); | 229 | mdio_gpio_bus_destroy(&ofdev->dev); |
230 | kfree(ofdev->dev.platform_data); | 230 | kfree(ofdev->dev.platform_data); |
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index 09c071bd6ad4..618643e3ca3e 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c | |||
@@ -97,7 +97,7 @@ static int qec_global_reset(void __iomem *gregs) | |||
97 | 97 | ||
98 | static void qec_init(struct bigmac *bp) | 98 | static void qec_init(struct bigmac *bp) |
99 | { | 99 | { |
100 | struct of_device *qec_op = bp->qec_op; | 100 | struct platform_device *qec_op = bp->qec_op; |
101 | void __iomem *gregs = bp->gregs; | 101 | void __iomem *gregs = bp->gregs; |
102 | u8 bsizes = bp->bigmac_bursts; | 102 | u8 bsizes = bp->bigmac_bursts; |
103 | u32 regval; | 103 | u32 regval; |
@@ -1083,8 +1083,8 @@ static const struct net_device_ops bigmac_ops = { | |||
1083 | .ndo_validate_addr = eth_validate_addr, | 1083 | .ndo_validate_addr = eth_validate_addr, |
1084 | }; | 1084 | }; |
1085 | 1085 | ||
1086 | static int __devinit bigmac_ether_init(struct of_device *op, | 1086 | static int __devinit bigmac_ether_init(struct platform_device *op, |
1087 | struct of_device *qec_op) | 1087 | struct platform_device *qec_op) |
1088 | { | 1088 | { |
1089 | static int version_printed; | 1089 | static int version_printed; |
1090 | struct net_device *dev; | 1090 | struct net_device *dev; |
@@ -1242,25 +1242,25 @@ fail_and_cleanup: | |||
1242 | /* QEC can be the parent of either QuadEthernet or a BigMAC. We want | 1242 | /* QEC can be the parent of either QuadEthernet or a BigMAC. We want |
1243 | * the latter. | 1243 | * the latter. |
1244 | */ | 1244 | */ |
1245 | static int __devinit bigmac_sbus_probe(struct of_device *op, | 1245 | static int __devinit bigmac_sbus_probe(struct platform_device *op, |
1246 | const struct of_device_id *match) | 1246 | const struct of_device_id *match) |
1247 | { | 1247 | { |
1248 | struct device *parent = op->dev.parent; | 1248 | struct device *parent = op->dev.parent; |
1249 | struct of_device *qec_op; | 1249 | struct platform_device *qec_op; |
1250 | 1250 | ||
1251 | qec_op = to_of_device(parent); | 1251 | qec_op = to_platform_device(parent); |
1252 | 1252 | ||
1253 | return bigmac_ether_init(op, qec_op); | 1253 | return bigmac_ether_init(op, qec_op); |
1254 | } | 1254 | } |
1255 | 1255 | ||
1256 | static int __devexit bigmac_sbus_remove(struct of_device *op) | 1256 | static int __devexit bigmac_sbus_remove(struct platform_device *op) |
1257 | { | 1257 | { |
1258 | struct bigmac *bp = dev_get_drvdata(&op->dev); | 1258 | struct bigmac *bp = dev_get_drvdata(&op->dev); |
1259 | struct device *parent = op->dev.parent; | 1259 | struct device *parent = op->dev.parent; |
1260 | struct net_device *net_dev = bp->dev; | 1260 | struct net_device *net_dev = bp->dev; |
1261 | struct of_device *qec_op; | 1261 | struct platform_device *qec_op; |
1262 | 1262 | ||
1263 | qec_op = to_of_device(parent); | 1263 | qec_op = to_platform_device(parent); |
1264 | 1264 | ||
1265 | unregister_netdev(net_dev); | 1265 | unregister_netdev(net_dev); |
1266 | 1266 | ||
diff --git a/drivers/net/sunbmac.h b/drivers/net/sunbmac.h index 8840bc0b840b..8db88945b889 100644 --- a/drivers/net/sunbmac.h +++ b/drivers/net/sunbmac.h | |||
@@ -329,8 +329,8 @@ struct bigmac { | |||
329 | unsigned int timer_ticks; | 329 | unsigned int timer_ticks; |
330 | 330 | ||
331 | struct net_device_stats enet_stats; | 331 | struct net_device_stats enet_stats; |
332 | struct of_device *qec_op; | 332 | struct platform_device *qec_op; |
333 | struct of_device *bigmac_op; | 333 | struct platform_device *bigmac_op; |
334 | struct net_device *dev; | 334 | struct net_device *dev; |
335 | }; | 335 | }; |
336 | 336 | ||
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index eec443f64079..bd0df1c14955 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c | |||
@@ -1591,7 +1591,7 @@ static int happy_meal_init(struct happy_meal *hp) | |||
1591 | */ | 1591 | */ |
1592 | #ifdef CONFIG_SBUS | 1592 | #ifdef CONFIG_SBUS |
1593 | if ((hp->happy_flags & HFLAG_PCI) == 0) { | 1593 | if ((hp->happy_flags & HFLAG_PCI) == 0) { |
1594 | struct of_device *op = hp->happy_dev; | 1594 | struct platform_device *op = hp->happy_dev; |
1595 | if (sbus_can_dma_64bit()) { | 1595 | if (sbus_can_dma_64bit()) { |
1596 | sbus_set_sbus64(&op->dev, | 1596 | sbus_set_sbus64(&op->dev, |
1597 | hp->happy_bursts); | 1597 | hp->happy_bursts); |
@@ -2480,7 +2480,7 @@ static void hme_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info | |||
2480 | #ifdef CONFIG_SBUS | 2480 | #ifdef CONFIG_SBUS |
2481 | else { | 2481 | else { |
2482 | const struct linux_prom_registers *regs; | 2482 | const struct linux_prom_registers *regs; |
2483 | struct of_device *op = hp->happy_dev; | 2483 | struct platform_device *op = hp->happy_dev; |
2484 | regs = of_get_property(op->dev.of_node, "regs", NULL); | 2484 | regs = of_get_property(op->dev.of_node, "regs", NULL); |
2485 | if (regs) | 2485 | if (regs) |
2486 | sprintf(info->bus_info, "SBUS:%d", | 2486 | sprintf(info->bus_info, "SBUS:%d", |
@@ -2515,13 +2515,13 @@ static int hme_version_printed; | |||
2515 | * | 2515 | * |
2516 | * Return NULL on failure. | 2516 | * Return NULL on failure. |
2517 | */ | 2517 | */ |
2518 | static struct quattro * __devinit quattro_sbus_find(struct of_device *child) | 2518 | static struct quattro * __devinit quattro_sbus_find(struct platform_device *child) |
2519 | { | 2519 | { |
2520 | struct device *parent = child->dev.parent; | 2520 | struct device *parent = child->dev.parent; |
2521 | struct of_device *op; | 2521 | struct platform_device *op; |
2522 | struct quattro *qp; | 2522 | struct quattro *qp; |
2523 | 2523 | ||
2524 | op = to_of_device(parent); | 2524 | op = to_platform_device(parent); |
2525 | qp = dev_get_drvdata(&op->dev); | 2525 | qp = dev_get_drvdata(&op->dev); |
2526 | if (qp) | 2526 | if (qp) |
2527 | return qp; | 2527 | return qp; |
@@ -2551,7 +2551,7 @@ static int __init quattro_sbus_register_irqs(void) | |||
2551 | struct quattro *qp; | 2551 | struct quattro *qp; |
2552 | 2552 | ||
2553 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { | 2553 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { |
2554 | struct of_device *op = qp->quattro_dev; | 2554 | struct platform_device *op = qp->quattro_dev; |
2555 | int err, qfe_slot, skip = 0; | 2555 | int err, qfe_slot, skip = 0; |
2556 | 2556 | ||
2557 | for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) { | 2557 | for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) { |
@@ -2580,7 +2580,7 @@ static void quattro_sbus_free_irqs(void) | |||
2580 | struct quattro *qp; | 2580 | struct quattro *qp; |
2581 | 2581 | ||
2582 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { | 2582 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { |
2583 | struct of_device *op = qp->quattro_dev; | 2583 | struct platform_device *op = qp->quattro_dev; |
2584 | int qfe_slot, skip = 0; | 2584 | int qfe_slot, skip = 0; |
2585 | 2585 | ||
2586 | for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) { | 2586 | for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) { |
@@ -2639,7 +2639,7 @@ static const struct net_device_ops hme_netdev_ops = { | |||
2639 | }; | 2639 | }; |
2640 | 2640 | ||
2641 | #ifdef CONFIG_SBUS | 2641 | #ifdef CONFIG_SBUS |
2642 | static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe) | 2642 | static int __devinit happy_meal_sbus_probe_one(struct platform_device *op, int is_qfe) |
2643 | { | 2643 | { |
2644 | struct device_node *dp = op->dev.of_node, *sbus_dp; | 2644 | struct device_node *dp = op->dev.of_node, *sbus_dp; |
2645 | struct quattro *qp = NULL; | 2645 | struct quattro *qp = NULL; |
@@ -2648,7 +2648,7 @@ static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe) | |||
2648 | int i, qfe_slot = -1; | 2648 | int i, qfe_slot = -1; |
2649 | int err = -ENODEV; | 2649 | int err = -ENODEV; |
2650 | 2650 | ||
2651 | sbus_dp = to_of_device(op->dev.parent)->dev.of_node; | 2651 | sbus_dp = op->dev.parent->of_node; |
2652 | 2652 | ||
2653 | /* We can match PCI devices too, do not accept those here. */ | 2653 | /* We can match PCI devices too, do not accept those here. */ |
2654 | if (strcmp(sbus_dp->name, "sbus")) | 2654 | if (strcmp(sbus_dp->name, "sbus")) |
@@ -3235,7 +3235,7 @@ static void happy_meal_pci_exit(void) | |||
3235 | #endif | 3235 | #endif |
3236 | 3236 | ||
3237 | #ifdef CONFIG_SBUS | 3237 | #ifdef CONFIG_SBUS |
3238 | static int __devinit hme_sbus_probe(struct of_device *op, const struct of_device_id *match) | 3238 | static int __devinit hme_sbus_probe(struct platform_device *op, const struct of_device_id *match) |
3239 | { | 3239 | { |
3240 | struct device_node *dp = op->dev.of_node; | 3240 | struct device_node *dp = op->dev.of_node; |
3241 | const char *model = of_get_property(dp, "model", NULL); | 3241 | const char *model = of_get_property(dp, "model", NULL); |
@@ -3247,7 +3247,7 @@ static int __devinit hme_sbus_probe(struct of_device *op, const struct of_device | |||
3247 | return happy_meal_sbus_probe_one(op, is_qfe); | 3247 | return happy_meal_sbus_probe_one(op, is_qfe); |
3248 | } | 3248 | } |
3249 | 3249 | ||
3250 | static int __devexit hme_sbus_remove(struct of_device *op) | 3250 | static int __devexit hme_sbus_remove(struct platform_device *op) |
3251 | { | 3251 | { |
3252 | struct happy_meal *hp = dev_get_drvdata(&op->dev); | 3252 | struct happy_meal *hp = dev_get_drvdata(&op->dev); |
3253 | struct net_device *net_dev = hp->dev; | 3253 | struct net_device *net_dev = hp->dev; |
diff --git a/drivers/net/sunhme.h b/drivers/net/sunhme.h index efd2ca0fcad3..756b5bf3aa89 100644 --- a/drivers/net/sunhme.h +++ b/drivers/net/sunhme.h | |||
@@ -407,7 +407,7 @@ struct happy_meal { | |||
407 | void (*write_rxd)(struct happy_meal_rxd *, u32, u32); | 407 | void (*write_rxd)(struct happy_meal_rxd *, u32, u32); |
408 | #endif | 408 | #endif |
409 | 409 | ||
410 | /* This is either an of_device or a pci_dev. */ | 410 | /* This is either an platform_device or a pci_dev. */ |
411 | void *happy_dev; | 411 | void *happy_dev; |
412 | struct device *dma_dev; | 412 | struct device *dma_dev; |
413 | 413 | ||
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index ee364fa75634..8dcb858f2168 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c | |||
@@ -250,7 +250,7 @@ struct lance_private { | |||
250 | int rx_new, tx_new; | 250 | int rx_new, tx_new; |
251 | int rx_old, tx_old; | 251 | int rx_old, tx_old; |
252 | 252 | ||
253 | struct of_device *ledma; /* If set this points to ledma */ | 253 | struct platform_device *ledma; /* If set this points to ledma */ |
254 | char tpe; /* cable-selection is TPE */ | 254 | char tpe; /* cable-selection is TPE */ |
255 | char auto_select; /* cable-selection by carrier */ | 255 | char auto_select; /* cable-selection by carrier */ |
256 | char burst_sizes; /* ledma SBus burst sizes */ | 256 | char burst_sizes; /* ledma SBus burst sizes */ |
@@ -265,8 +265,8 @@ struct lance_private { | |||
265 | char *name; | 265 | char *name; |
266 | dma_addr_t init_block_dvma; | 266 | dma_addr_t init_block_dvma; |
267 | struct net_device *dev; /* Backpointer */ | 267 | struct net_device *dev; /* Backpointer */ |
268 | struct of_device *op; | 268 | struct platform_device *op; |
269 | struct of_device *lebuffer; | 269 | struct platform_device *lebuffer; |
270 | struct timer_list multicast_timer; | 270 | struct timer_list multicast_timer; |
271 | }; | 271 | }; |
272 | 272 | ||
@@ -1272,7 +1272,7 @@ static void lance_free_hwresources(struct lance_private *lp) | |||
1272 | if (lp->lregs) | 1272 | if (lp->lregs) |
1273 | of_iounmap(&lp->op->resource[0], lp->lregs, LANCE_REG_SIZE); | 1273 | of_iounmap(&lp->op->resource[0], lp->lregs, LANCE_REG_SIZE); |
1274 | if (lp->dregs) { | 1274 | if (lp->dregs) { |
1275 | struct of_device *ledma = lp->ledma; | 1275 | struct platform_device *ledma = lp->ledma; |
1276 | 1276 | ||
1277 | of_iounmap(&ledma->resource[0], lp->dregs, | 1277 | of_iounmap(&ledma->resource[0], lp->dregs, |
1278 | resource_size(&ledma->resource[0])); | 1278 | resource_size(&ledma->resource[0])); |
@@ -1319,9 +1319,9 @@ static const struct net_device_ops sparc_lance_ops = { | |||
1319 | .ndo_validate_addr = eth_validate_addr, | 1319 | .ndo_validate_addr = eth_validate_addr, |
1320 | }; | 1320 | }; |
1321 | 1321 | ||
1322 | static int __devinit sparc_lance_probe_one(struct of_device *op, | 1322 | static int __devinit sparc_lance_probe_one(struct platform_device *op, |
1323 | struct of_device *ledma, | 1323 | struct platform_device *ledma, |
1324 | struct of_device *lebuffer) | 1324 | struct platform_device *lebuffer) |
1325 | { | 1325 | { |
1326 | struct device_node *dp = op->dev.of_node; | 1326 | struct device_node *dp = op->dev.of_node; |
1327 | static unsigned version_printed; | 1327 | static unsigned version_printed; |
@@ -1503,9 +1503,9 @@ fail: | |||
1503 | return -ENODEV; | 1503 | return -ENODEV; |
1504 | } | 1504 | } |
1505 | 1505 | ||
1506 | static int __devinit sunlance_sbus_probe(struct of_device *op, const struct of_device_id *match) | 1506 | static int __devinit sunlance_sbus_probe(struct platform_device *op, const struct of_device_id *match) |
1507 | { | 1507 | { |
1508 | struct of_device *parent = to_of_device(op->dev.parent); | 1508 | struct platform_device *parent = to_platform_device(op->dev.parent); |
1509 | struct device_node *parent_dp = parent->dev.of_node; | 1509 | struct device_node *parent_dp = parent->dev.of_node; |
1510 | int err; | 1510 | int err; |
1511 | 1511 | ||
@@ -1519,7 +1519,7 @@ static int __devinit sunlance_sbus_probe(struct of_device *op, const struct of_d | |||
1519 | return err; | 1519 | return err; |
1520 | } | 1520 | } |
1521 | 1521 | ||
1522 | static int __devexit sunlance_sbus_remove(struct of_device *op) | 1522 | static int __devexit sunlance_sbus_remove(struct platform_device *op) |
1523 | { | 1523 | { |
1524 | struct lance_private *lp = dev_get_drvdata(&op->dev); | 1524 | struct lance_private *lp = dev_get_drvdata(&op->dev); |
1525 | struct net_device *net_dev = lp->dev; | 1525 | struct net_device *net_dev = lp->dev; |
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index 5f84a5dadedd..72e65d4666ef 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c | |||
@@ -689,7 +689,7 @@ static void qe_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) | |||
689 | { | 689 | { |
690 | const struct linux_prom_registers *regs; | 690 | const struct linux_prom_registers *regs; |
691 | struct sunqe *qep = netdev_priv(dev); | 691 | struct sunqe *qep = netdev_priv(dev); |
692 | struct of_device *op; | 692 | struct platform_device *op; |
693 | 693 | ||
694 | strcpy(info->driver, "sunqe"); | 694 | strcpy(info->driver, "sunqe"); |
695 | strcpy(info->version, "3.0"); | 695 | strcpy(info->version, "3.0"); |
@@ -720,7 +720,7 @@ static const struct ethtool_ops qe_ethtool_ops = { | |||
720 | }; | 720 | }; |
721 | 721 | ||
722 | /* This is only called once at boot time for each card probed. */ | 722 | /* This is only called once at boot time for each card probed. */ |
723 | static void qec_init_once(struct sunqec *qecp, struct of_device *op) | 723 | static void qec_init_once(struct sunqec *qecp, struct platform_device *op) |
724 | { | 724 | { |
725 | u8 bsizes = qecp->qec_bursts; | 725 | u8 bsizes = qecp->qec_bursts; |
726 | 726 | ||
@@ -770,9 +770,9 @@ static u8 __devinit qec_get_burst(struct device_node *dp) | |||
770 | return bsizes; | 770 | return bsizes; |
771 | } | 771 | } |
772 | 772 | ||
773 | static struct sunqec * __devinit get_qec(struct of_device *child) | 773 | static struct sunqec * __devinit get_qec(struct platform_device *child) |
774 | { | 774 | { |
775 | struct of_device *op = to_of_device(child->dev.parent); | 775 | struct platform_device *op = to_platform_device(child->dev.parent); |
776 | struct sunqec *qecp; | 776 | struct sunqec *qecp; |
777 | 777 | ||
778 | qecp = dev_get_drvdata(&op->dev); | 778 | qecp = dev_get_drvdata(&op->dev); |
@@ -836,7 +836,7 @@ static const struct net_device_ops qec_ops = { | |||
836 | .ndo_validate_addr = eth_validate_addr, | 836 | .ndo_validate_addr = eth_validate_addr, |
837 | }; | 837 | }; |
838 | 838 | ||
839 | static int __devinit qec_ether_init(struct of_device *op) | 839 | static int __devinit qec_ether_init(struct platform_device *op) |
840 | { | 840 | { |
841 | static unsigned version_printed; | 841 | static unsigned version_printed; |
842 | struct net_device *dev; | 842 | struct net_device *dev; |
@@ -941,12 +941,12 @@ fail: | |||
941 | return res; | 941 | return res; |
942 | } | 942 | } |
943 | 943 | ||
944 | static int __devinit qec_sbus_probe(struct of_device *op, const struct of_device_id *match) | 944 | static int __devinit qec_sbus_probe(struct platform_device *op, const struct of_device_id *match) |
945 | { | 945 | { |
946 | return qec_ether_init(op); | 946 | return qec_ether_init(op); |
947 | } | 947 | } |
948 | 948 | ||
949 | static int __devexit qec_sbus_remove(struct of_device *op) | 949 | static int __devexit qec_sbus_remove(struct platform_device *op) |
950 | { | 950 | { |
951 | struct sunqe *qp = dev_get_drvdata(&op->dev); | 951 | struct sunqe *qp = dev_get_drvdata(&op->dev); |
952 | struct net_device *net_dev = qp->dev; | 952 | struct net_device *net_dev = qp->dev; |
@@ -997,7 +997,7 @@ static void __exit qec_exit(void) | |||
997 | 997 | ||
998 | while (root_qec_dev) { | 998 | while (root_qec_dev) { |
999 | struct sunqec *next = root_qec_dev->next_module; | 999 | struct sunqec *next = root_qec_dev->next_module; |
1000 | struct of_device *op = root_qec_dev->op; | 1000 | struct platform_device *op = root_qec_dev->op; |
1001 | 1001 | ||
1002 | free_irq(op->archdata.irqs[0], (void *) root_qec_dev); | 1002 | free_irq(op->archdata.irqs[0], (void *) root_qec_dev); |
1003 | of_iounmap(&op->resource[0], root_qec_dev->gregs, | 1003 | of_iounmap(&op->resource[0], root_qec_dev->gregs, |
diff --git a/drivers/net/sunqe.h b/drivers/net/sunqe.h index 5813a7b2faa5..581781b6b2fa 100644 --- a/drivers/net/sunqe.h +++ b/drivers/net/sunqe.h | |||
@@ -314,7 +314,7 @@ struct sunqec { | |||
314 | void __iomem *gregs; /* QEC Global Registers */ | 314 | void __iomem *gregs; /* QEC Global Registers */ |
315 | struct sunqe *qes[4]; /* Each child MACE */ | 315 | struct sunqe *qes[4]; /* Each child MACE */ |
316 | unsigned int qec_bursts; /* Support burst sizes */ | 316 | unsigned int qec_bursts; /* Support burst sizes */ |
317 | struct of_device *op; /* QEC's OF device */ | 317 | struct platform_device *op; /* QEC's OF device */ |
318 | struct sunqec *next_module; /* List of all QECs in system */ | 318 | struct sunqec *next_module; /* List of all QECs in system */ |
319 | }; | 319 | }; |
320 | 320 | ||
@@ -342,7 +342,7 @@ struct sunqe { | |||
342 | __u32 buffers_dvma; /* DVMA visible address. */ | 342 | __u32 buffers_dvma; /* DVMA visible address. */ |
343 | struct sunqec *parent; | 343 | struct sunqec *parent; |
344 | u8 mconfig; /* Base MACE mconfig value */ | 344 | u8 mconfig; /* Base MACE mconfig value */ |
345 | struct of_device *op; /* QE's OF device struct */ | 345 | struct platform_device *op; /* QE's OF device struct */ |
346 | struct net_device *dev; /* QE's netdevice struct */ | 346 | struct net_device *dev; /* QE's netdevice struct */ |
347 | int channel; /* Who am I? */ | 347 | int channel; /* Who am I? */ |
348 | }; | 348 | }; |
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 8d532f9b50d0..a4c3f5708246 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c | |||
@@ -3601,7 +3601,7 @@ static void ucc_geth_timeout(struct net_device *dev) | |||
3601 | 3601 | ||
3602 | #ifdef CONFIG_PM | 3602 | #ifdef CONFIG_PM |
3603 | 3603 | ||
3604 | static int ucc_geth_suspend(struct of_device *ofdev, pm_message_t state) | 3604 | static int ucc_geth_suspend(struct platform_device *ofdev, pm_message_t state) |
3605 | { | 3605 | { |
3606 | struct net_device *ndev = dev_get_drvdata(&ofdev->dev); | 3606 | struct net_device *ndev = dev_get_drvdata(&ofdev->dev); |
3607 | struct ucc_geth_private *ugeth = netdev_priv(ndev); | 3607 | struct ucc_geth_private *ugeth = netdev_priv(ndev); |
@@ -3629,7 +3629,7 @@ static int ucc_geth_suspend(struct of_device *ofdev, pm_message_t state) | |||
3629 | return 0; | 3629 | return 0; |
3630 | } | 3630 | } |
3631 | 3631 | ||
3632 | static int ucc_geth_resume(struct of_device *ofdev) | 3632 | static int ucc_geth_resume(struct platform_device *ofdev) |
3633 | { | 3633 | { |
3634 | struct net_device *ndev = dev_get_drvdata(&ofdev->dev); | 3634 | struct net_device *ndev = dev_get_drvdata(&ofdev->dev); |
3635 | struct ucc_geth_private *ugeth = netdev_priv(ndev); | 3635 | struct ucc_geth_private *ugeth = netdev_priv(ndev); |
@@ -3732,7 +3732,7 @@ static const struct net_device_ops ucc_geth_netdev_ops = { | |||
3732 | #endif | 3732 | #endif |
3733 | }; | 3733 | }; |
3734 | 3734 | ||
3735 | static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *match) | 3735 | static int ucc_geth_probe(struct platform_device* ofdev, const struct of_device_id *match) |
3736 | { | 3736 | { |
3737 | struct device *device = &ofdev->dev; | 3737 | struct device *device = &ofdev->dev; |
3738 | struct device_node *np = ofdev->dev.of_node; | 3738 | struct device_node *np = ofdev->dev.of_node; |
@@ -3954,7 +3954,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma | |||
3954 | return 0; | 3954 | return 0; |
3955 | } | 3955 | } |
3956 | 3956 | ||
3957 | static int ucc_geth_remove(struct of_device* ofdev) | 3957 | static int ucc_geth_remove(struct platform_device* ofdev) |
3958 | { | 3958 | { |
3959 | struct device *device = &ofdev->dev; | 3959 | struct device *device = &ofdev->dev; |
3960 | struct net_device *dev = dev_get_drvdata(device); | 3960 | struct net_device *dev = dev_get_drvdata(device); |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 6e71346a7550..ba854c70ab94 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -125,6 +125,8 @@ struct if_sdio_card { | |||
125 | 125 | ||
126 | const char *helper; | 126 | const char *helper; |
127 | const char *firmware; | 127 | const char *firmware; |
128 | bool helper_allocated; | ||
129 | bool firmware_allocated; | ||
128 | 130 | ||
129 | u8 buffer[65536]; | 131 | u8 buffer[65536]; |
130 | 132 | ||
@@ -984,16 +986,34 @@ static int if_sdio_probe(struct sdio_func *func, | |||
984 | card->helper = if_sdio_models[i].helper; | 986 | card->helper = if_sdio_models[i].helper; |
985 | card->firmware = if_sdio_models[i].firmware; | 987 | card->firmware = if_sdio_models[i].firmware; |
986 | 988 | ||
989 | kparam_block_sysfs_write(helper_name); | ||
987 | if (lbs_helper_name) { | 990 | if (lbs_helper_name) { |
991 | char *helper = kstrdup(lbs_helper_name, GFP_KERNEL); | ||
992 | if (!helper) { | ||
993 | kparam_unblock_sysfs_write(helper_name); | ||
994 | ret = -ENOMEM; | ||
995 | goto free; | ||
996 | } | ||
988 | lbs_deb_sdio("overriding helper firmware: %s\n", | 997 | lbs_deb_sdio("overriding helper firmware: %s\n", |
989 | lbs_helper_name); | 998 | lbs_helper_name); |
990 | card->helper = lbs_helper_name; | 999 | card->helper = helper; |
1000 | card->helper_allocated = true; | ||
991 | } | 1001 | } |
1002 | kparam_unblock_sysfs_write(helper_name); | ||
992 | 1003 | ||
1004 | kparam_block_sysfs_write(fw_name); | ||
993 | if (lbs_fw_name) { | 1005 | if (lbs_fw_name) { |
1006 | char *fw_name = kstrdup(lbs_fw_name, GFP_KERNEL); | ||
1007 | if (!fw_name) { | ||
1008 | kparam_unblock_sysfs_write(fw_name); | ||
1009 | ret = -ENOMEM; | ||
1010 | goto free; | ||
1011 | } | ||
994 | lbs_deb_sdio("overriding firmware: %s\n", lbs_fw_name); | 1012 | lbs_deb_sdio("overriding firmware: %s\n", lbs_fw_name); |
995 | card->firmware = lbs_fw_name; | 1013 | card->firmware = fw_name; |
1014 | card->firmware_allocated = true; | ||
996 | } | 1015 | } |
1016 | kparam_unblock_sysfs_write(fw_name); | ||
997 | 1017 | ||
998 | sdio_claim_host(func); | 1018 | sdio_claim_host(func); |
999 | 1019 | ||
@@ -1127,6 +1147,10 @@ free: | |||
1127 | kfree(packet); | 1147 | kfree(packet); |
1128 | } | 1148 | } |
1129 | 1149 | ||
1150 | if (card->helper_allocated) | ||
1151 | kfree(card->helper); | ||
1152 | if (card->firmware_allocated) | ||
1153 | kfree(card->firmware); | ||
1130 | kfree(card); | 1154 | kfree(card); |
1131 | 1155 | ||
1132 | goto out; | 1156 | goto out; |
@@ -1177,6 +1201,10 @@ static void if_sdio_remove(struct sdio_func *func) | |||
1177 | kfree(packet); | 1201 | kfree(packet); |
1178 | } | 1202 | } |
1179 | 1203 | ||
1204 | if (card->helper_allocated) | ||
1205 | kfree(card->helper); | ||
1206 | if (card->firmware_allocated) | ||
1207 | kfree(card->firmware); | ||
1180 | kfree(card); | 1208 | kfree(card); |
1181 | 1209 | ||
1182 | lbs_deb_leave(LBS_DEB_SDIO); | 1210 | lbs_deb_leave(LBS_DEB_SDIO); |
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 07ece9d26c63..3ff61063671a 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
@@ -289,10 +289,13 @@ static int if_usb_probe(struct usb_interface *intf, | |||
289 | } | 289 | } |
290 | 290 | ||
291 | /* Upload firmware */ | 291 | /* Upload firmware */ |
292 | kparam_block_sysfs_write(fw_name); | ||
292 | if (__if_usb_prog_firmware(cardp, lbs_fw_name, BOOT_CMD_FW_BY_USB)) { | 293 | if (__if_usb_prog_firmware(cardp, lbs_fw_name, BOOT_CMD_FW_BY_USB)) { |
294 | kparam_unblock_sysfs_write(fw_name); | ||
293 | lbs_deb_usbd(&udev->dev, "FW upload failed\n"); | 295 | lbs_deb_usbd(&udev->dev, "FW upload failed\n"); |
294 | goto err_prog_firmware; | 296 | goto err_prog_firmware; |
295 | } | 297 | } |
298 | kparam_unblock_sysfs_write(fw_name); | ||
296 | 299 | ||
297 | if (!(priv = lbs_add_card(cardp, &udev->dev))) | 300 | if (!(priv = lbs_add_card(cardp, &udev->dev))) |
298 | goto err_prog_firmware; | 301 | goto err_prog_firmware; |
diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c index b172f5d87a3b..41a4f214ade1 100644 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ b/drivers/net/wireless/libertas_tf/if_usb.c | |||
@@ -811,12 +811,15 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp) | |||
811 | 811 | ||
812 | lbtf_deb_enter(LBTF_DEB_USB); | 812 | lbtf_deb_enter(LBTF_DEB_USB); |
813 | 813 | ||
814 | kparam_block_sysfs_write(fw_name); | ||
814 | ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev); | 815 | ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev); |
815 | if (ret < 0) { | 816 | if (ret < 0) { |
816 | pr_err("request_firmware() failed with %#x\n", ret); | 817 | pr_err("request_firmware() failed with %#x\n", ret); |
817 | pr_err("firmware %s not found\n", lbtf_fw_name); | 818 | pr_err("firmware %s not found\n", lbtf_fw_name); |
819 | kparam_unblock_sysfs_write(fw_name); | ||
818 | goto done; | 820 | goto done; |
819 | } | 821 | } |
822 | kparam_unblock_sysfs_write(fw_name); | ||
820 | 823 | ||
821 | if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) | 824 | if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) |
822 | goto release_fw; | 825 | goto release_fw; |
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c index b2c2f391b29d..ecbbb688eba0 100644 --- a/drivers/net/xilinx_emaclite.c +++ b/drivers/net/xilinx_emaclite.c | |||
@@ -1086,7 +1086,7 @@ static void xemaclite_remove_ndev(struct net_device *ndev) | |||
1086 | * | 1086 | * |
1087 | * Return: Value of the parameter if the parameter is found, or 0 otherwise | 1087 | * Return: Value of the parameter if the parameter is found, or 0 otherwise |
1088 | */ | 1088 | */ |
1089 | static bool get_bool(struct of_device *ofdev, const char *s) | 1089 | static bool get_bool(struct platform_device *ofdev, const char *s) |
1090 | { | 1090 | { |
1091 | u32 *p = (u32 *)of_get_property(ofdev->dev.of_node, s, NULL); | 1091 | u32 *p = (u32 *)of_get_property(ofdev->dev.of_node, s, NULL); |
1092 | 1092 | ||
@@ -1115,7 +1115,7 @@ static struct net_device_ops xemaclite_netdev_ops; | |||
1115 | * Return: 0, if the driver is bound to the Emaclite device, or | 1115 | * Return: 0, if the driver is bound to the Emaclite device, or |
1116 | * a negative error if there is failure. | 1116 | * a negative error if there is failure. |
1117 | */ | 1117 | */ |
1118 | static int __devinit xemaclite_of_probe(struct of_device *ofdev, | 1118 | static int __devinit xemaclite_of_probe(struct platform_device *ofdev, |
1119 | const struct of_device_id *match) | 1119 | const struct of_device_id *match) |
1120 | { | 1120 | { |
1121 | struct resource r_irq; /* Interrupt resources */ | 1121 | struct resource r_irq; /* Interrupt resources */ |
@@ -1240,7 +1240,7 @@ error2: | |||
1240 | * | 1240 | * |
1241 | * Return: 0, always. | 1241 | * Return: 0, always. |
1242 | */ | 1242 | */ |
1243 | static int __devexit xemaclite_of_remove(struct of_device *of_dev) | 1243 | static int __devexit xemaclite_of_remove(struct platform_device *of_dev) |
1244 | { | 1244 | { |
1245 | struct device *dev = &of_dev->dev; | 1245 | struct device *dev = &of_dev->dev; |
1246 | struct net_device *ndev = dev_get_drvdata(dev); | 1246 | struct net_device *ndev = dev_get_drvdata(dev); |
diff --git a/drivers/of/device.c b/drivers/of/device.c index 0d8a0644f540..92de0eb74aea 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c | |||
@@ -14,7 +14,7 @@ | |||
14 | * @ids: array of of device match structures to search in | 14 | * @ids: array of of device match structures to search in |
15 | * @dev: the of device structure to match against | 15 | * @dev: the of device structure to match against |
16 | * | 16 | * |
17 | * Used by a driver to check whether an of_device present in the | 17 | * Used by a driver to check whether an platform_device present in the |
18 | * system is in its list of supported devices. | 18 | * system is in its list of supported devices. |
19 | */ | 19 | */ |
20 | const struct of_device_id *of_match_device(const struct of_device_id *matches, | 20 | const struct of_device_id *of_match_device(const struct of_device_id *matches, |
diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c index 210a6441a066..55ba118f1cf1 100644 --- a/drivers/parport/parport_sunbpp.c +++ b/drivers/parport/parport_sunbpp.c | |||
@@ -286,7 +286,7 @@ static struct parport_operations parport_sunbpp_ops = | |||
286 | .owner = THIS_MODULE, | 286 | .owner = THIS_MODULE, |
287 | }; | 287 | }; |
288 | 288 | ||
289 | static int __devinit bpp_probe(struct of_device *op, const struct of_device_id *match) | 289 | static int __devinit bpp_probe(struct platform_device *op, const struct of_device_id *match) |
290 | { | 290 | { |
291 | struct parport_operations *ops; | 291 | struct parport_operations *ops; |
292 | struct bpp_regs __iomem *regs; | 292 | struct bpp_regs __iomem *regs; |
@@ -351,7 +351,7 @@ out_unmap: | |||
351 | return err; | 351 | return err; |
352 | } | 352 | } |
353 | 353 | ||
354 | static int __devexit bpp_remove(struct of_device *op) | 354 | static int __devexit bpp_remove(struct platform_device *op) |
355 | { | 355 | { |
356 | struct parport *p = dev_get_drvdata(&op->dev); | 356 | struct parport *p = dev_get_drvdata(&op->dev); |
357 | struct parport_operations *ops = p->ops; | 357 | struct parport_operations *ops = p->ops; |
diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c index f94d8281cfb0..546d3024b6f0 100644 --- a/drivers/pcmcia/electra_cf.c +++ b/drivers/pcmcia/electra_cf.c | |||
@@ -44,7 +44,7 @@ struct electra_cf_socket { | |||
44 | unsigned present:1; | 44 | unsigned present:1; |
45 | unsigned active:1; | 45 | unsigned active:1; |
46 | 46 | ||
47 | struct of_device *ofdev; | 47 | struct platform_device *ofdev; |
48 | unsigned long mem_phys; | 48 | unsigned long mem_phys; |
49 | void __iomem * mem_base; | 49 | void __iomem * mem_base; |
50 | unsigned long mem_size; | 50 | unsigned long mem_size; |
@@ -181,7 +181,7 @@ static struct pccard_operations electra_cf_ops = { | |||
181 | .set_mem_map = electra_cf_set_mem_map, | 181 | .set_mem_map = electra_cf_set_mem_map, |
182 | }; | 182 | }; |
183 | 183 | ||
184 | static int __devinit electra_cf_probe(struct of_device *ofdev, | 184 | static int __devinit electra_cf_probe(struct platform_device *ofdev, |
185 | const struct of_device_id *match) | 185 | const struct of_device_id *match) |
186 | { | 186 | { |
187 | struct device *device = &ofdev->dev; | 187 | struct device *device = &ofdev->dev; |
@@ -325,7 +325,7 @@ fail1: | |||
325 | 325 | ||
326 | } | 326 | } |
327 | 327 | ||
328 | static int __devexit electra_cf_remove(struct of_device *ofdev) | 328 | static int __devexit electra_cf_remove(struct platform_device *ofdev) |
329 | { | 329 | { |
330 | struct device *device = &ofdev->dev; | 330 | struct device *device = &ofdev->dev; |
331 | struct electra_cf_socket *cf; | 331 | struct electra_cf_socket *cf; |
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c index f2f90a7d3e12..f0ecad99ce81 100644 --- a/drivers/pcmcia/m8xx_pcmcia.c +++ b/drivers/pcmcia/m8xx_pcmcia.c | |||
@@ -1149,7 +1149,7 @@ static struct pccard_operations m8xx_services = { | |||
1149 | .set_mem_map = m8xx_set_mem_map, | 1149 | .set_mem_map = m8xx_set_mem_map, |
1150 | }; | 1150 | }; |
1151 | 1151 | ||
1152 | static int __init m8xx_probe(struct of_device *ofdev, | 1152 | static int __init m8xx_probe(struct platform_device *ofdev, |
1153 | const struct of_device_id *match) | 1153 | const struct of_device_id *match) |
1154 | { | 1154 | { |
1155 | struct pcmcia_win *w; | 1155 | struct pcmcia_win *w; |
@@ -1249,7 +1249,7 @@ static int __init m8xx_probe(struct of_device *ofdev, | |||
1249 | return 0; | 1249 | return 0; |
1250 | } | 1250 | } |
1251 | 1251 | ||
1252 | static int m8xx_remove(struct of_device *ofdev) | 1252 | static int m8xx_remove(struct platform_device *ofdev) |
1253 | { | 1253 | { |
1254 | u32 m, i; | 1254 | u32 m, i; |
1255 | struct pcmcia_win *w; | 1255 | struct pcmcia_win *w; |
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 1e5506be39b4..07343568a12e 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
@@ -136,6 +136,12 @@ config BATTERY_Z2 | |||
136 | help | 136 | help |
137 | Say Y to include support for the battery on the Zipit Z2. | 137 | Say Y to include support for the battery on the Zipit Z2. |
138 | 138 | ||
139 | config BATTERY_S3C_ADC | ||
140 | tristate "Battery driver for Samsung ADC based monitoring" | ||
141 | depends on S3C_ADC | ||
142 | help | ||
143 | Say Y here to enable support for iPAQ h1930/h1940/rx1950 battery | ||
144 | |||
139 | config CHARGER_PCF50633 | 145 | config CHARGER_PCF50633 |
140 | tristate "NXP PCF50633 MBC" | 146 | tristate "NXP PCF50633 MBC" |
141 | depends on MFD_PCF50633 | 147 | depends on MFD_PCF50633 |
@@ -153,4 +159,11 @@ config BATTERY_JZ4740 | |||
153 | This driver can be build as a module. If so, the module will be | 159 | This driver can be build as a module. If so, the module will be |
154 | called jz4740-battery. | 160 | called jz4740-battery. |
155 | 161 | ||
162 | config BATTERY_INTEL_MID | ||
163 | tristate "Battery driver for Intel MID platforms" | ||
164 | depends on INTEL_SCU_IPC && SPI | ||
165 | help | ||
166 | Say Y here to enable the battery driver on Intel MID | ||
167 | platforms. | ||
168 | |||
156 | endif # POWER_SUPPLY | 169 | endif # POWER_SUPPLY |
diff --git a/drivers/power/Makefile b/drivers/power/Makefile index cf95009d9bcd..10143aaf4ee3 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile | |||
@@ -33,5 +33,7 @@ obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o | |||
33 | obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o | 33 | obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o |
34 | obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o | 34 | obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o |
35 | obj-$(CONFIG_BATTERY_Z2) += z2_battery.o | 35 | obj-$(CONFIG_BATTERY_Z2) += z2_battery.o |
36 | obj-$(CONFIG_BATTERY_S3C_ADC) += s3c_adc_battery.o | ||
36 | obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o | 37 | obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o |
37 | obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o | 38 | obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o |
39 | obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o | ||
diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c new file mode 100644 index 000000000000..c61ffec2ff10 --- /dev/null +++ b/drivers/power/intel_mid_battery.c | |||
@@ -0,0 +1,799 @@ | |||
1 | /* | ||
2 | * intel_mid_battery.c - Intel MID PMIC Battery Driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Intel Corporation | ||
5 | * | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
20 | * | ||
21 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
22 | * Author: Nithish Mahalingam <nithish.mahalingam@intel.com> | ||
23 | */ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/err.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/workqueue.h> | ||
30 | #include <linux/jiffies.h> | ||
31 | #include <linux/param.h> | ||
32 | #include <linux/device.h> | ||
33 | #include <linux/spi/spi.h> | ||
34 | #include <linux/platform_device.h> | ||
35 | #include <linux/power_supply.h> | ||
36 | |||
37 | #include <asm/intel_scu_ipc.h> | ||
38 | |||
39 | #define DRIVER_NAME "pmic_battery" | ||
40 | |||
41 | /********************************************************************* | ||
42 | * Generic defines | ||
43 | *********************************************************************/ | ||
44 | |||
45 | static int debug; | ||
46 | module_param(debug, int, 0444); | ||
47 | MODULE_PARM_DESC(debug, "Flag to enable PMIC Battery debug messages."); | ||
48 | |||
49 | #define PMIC_BATT_DRV_INFO_UPDATED 1 | ||
50 | #define PMIC_BATT_PRESENT 1 | ||
51 | #define PMIC_BATT_NOT_PRESENT 0 | ||
52 | #define PMIC_USB_PRESENT PMIC_BATT_PRESENT | ||
53 | #define PMIC_USB_NOT_PRESENT PMIC_BATT_NOT_PRESENT | ||
54 | |||
55 | /* pmic battery register related */ | ||
56 | #define PMIC_BATT_CHR_SCHRGINT_ADDR 0xD2 | ||
57 | #define PMIC_BATT_CHR_SBATOVP_MASK (1 << 1) | ||
58 | #define PMIC_BATT_CHR_STEMP_MASK (1 << 2) | ||
59 | #define PMIC_BATT_CHR_SCOMP_MASK (1 << 3) | ||
60 | #define PMIC_BATT_CHR_SUSBDET_MASK (1 << 4) | ||
61 | #define PMIC_BATT_CHR_SBATDET_MASK (1 << 5) | ||
62 | #define PMIC_BATT_CHR_SDCLMT_MASK (1 << 6) | ||
63 | #define PMIC_BATT_CHR_SUSBOVP_MASK (1 << 7) | ||
64 | #define PMIC_BATT_CHR_EXCPT_MASK 0xC6 | ||
65 | #define PMIC_BATT_ADC_ACCCHRG_MASK (1 << 31) | ||
66 | #define PMIC_BATT_ADC_ACCCHRGVAL_MASK 0x7FFFFFFF | ||
67 | |||
68 | /* pmic ipc related */ | ||
69 | #define PMIC_BATT_CHR_IPC_FCHRG_SUBID 0x4 | ||
70 | #define PMIC_BATT_CHR_IPC_TCHRG_SUBID 0x6 | ||
71 | |||
72 | /* types of battery charging */ | ||
73 | enum batt_charge_type { | ||
74 | BATT_USBOTG_500MA_CHARGE, | ||
75 | BATT_USBOTG_TRICKLE_CHARGE, | ||
76 | }; | ||
77 | |||
78 | /* valid battery events */ | ||
79 | enum batt_event { | ||
80 | BATT_EVENT_BATOVP_EXCPT, | ||
81 | BATT_EVENT_USBOVP_EXCPT, | ||
82 | BATT_EVENT_TEMP_EXCPT, | ||
83 | BATT_EVENT_DCLMT_EXCPT, | ||
84 | BATT_EVENT_EXCPT | ||
85 | }; | ||
86 | |||
87 | |||
88 | /********************************************************************* | ||
89 | * Battery properties | ||
90 | *********************************************************************/ | ||
91 | |||
92 | /* | ||
93 | * pmic battery info | ||
94 | */ | ||
95 | struct pmic_power_module_info { | ||
96 | bool is_dev_info_updated; | ||
97 | struct device *dev; | ||
98 | /* pmic battery data */ | ||
99 | unsigned long update_time; /* jiffies when data read */ | ||
100 | unsigned int usb_is_present; | ||
101 | unsigned int batt_is_present; | ||
102 | unsigned int batt_health; | ||
103 | unsigned int usb_health; | ||
104 | unsigned int batt_status; | ||
105 | unsigned int batt_charge_now; /* in mAS */ | ||
106 | unsigned int batt_prev_charge_full; /* in mAS */ | ||
107 | unsigned int batt_charge_rate; /* in units per second */ | ||
108 | |||
109 | struct power_supply usb; | ||
110 | struct power_supply batt; | ||
111 | int irq; /* GPE_ID or IRQ# */ | ||
112 | struct workqueue_struct *monitor_wqueue; | ||
113 | struct delayed_work monitor_battery; | ||
114 | struct work_struct handler; | ||
115 | }; | ||
116 | |||
117 | static unsigned int delay_time = 2000; /* in ms */ | ||
118 | |||
119 | /* | ||
120 | * pmic ac properties | ||
121 | */ | ||
122 | static enum power_supply_property pmic_usb_props[] = { | ||
123 | POWER_SUPPLY_PROP_PRESENT, | ||
124 | POWER_SUPPLY_PROP_HEALTH, | ||
125 | }; | ||
126 | |||
127 | /* | ||
128 | * pmic battery properties | ||
129 | */ | ||
130 | static enum power_supply_property pmic_battery_props[] = { | ||
131 | POWER_SUPPLY_PROP_STATUS, | ||
132 | POWER_SUPPLY_PROP_HEALTH, | ||
133 | POWER_SUPPLY_PROP_PRESENT, | ||
134 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
135 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
136 | }; | ||
137 | |||
138 | |||
139 | /* | ||
140 | * Glue functions for talking to the IPC | ||
141 | */ | ||
142 | |||
143 | struct battery_property { | ||
144 | u32 capacity; /* Charger capacity */ | ||
145 | u8 crnt; /* Quick charge current value*/ | ||
146 | u8 volt; /* Fine adjustment of constant charge voltage */ | ||
147 | u8 prot; /* CHRGPROT register value */ | ||
148 | u8 prot2; /* CHRGPROT1 register value */ | ||
149 | u8 timer; /* Charging timer */ | ||
150 | }; | ||
151 | |||
152 | #define IPCMSG_BATTERY 0xEF | ||
153 | |||
154 | /* Battery coulomb counter accumulator commands */ | ||
155 | #define IPC_CMD_CC_WR 0 /* Update coulomb counter value */ | ||
156 | #define IPC_CMD_CC_RD 1 /* Read coulomb counter value */ | ||
157 | #define IPC_CMD_BATTERY_PROPERTY 2 /* Read Battery property */ | ||
158 | |||
159 | /** | ||
160 | * pmic_scu_ipc_battery_cc_read - read battery cc | ||
161 | * @value: battery coulomb counter read | ||
162 | * | ||
163 | * Reads the battery couloumb counter value, returns 0 on success, or | ||
164 | * an error code | ||
165 | * | ||
166 | * This function may sleep. Locking for SCU accesses is handled for | ||
167 | * the caller. | ||
168 | */ | ||
169 | static int pmic_scu_ipc_battery_cc_read(u32 *value) | ||
170 | { | ||
171 | return intel_scu_ipc_command(IPCMSG_BATTERY, IPC_CMD_CC_RD, | ||
172 | NULL, 0, value, 1); | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * pmic_scu_ipc_battery_property_get - fetch properties | ||
177 | * @prop: battery properties | ||
178 | * | ||
179 | * Retrieve the battery properties from the power management | ||
180 | * | ||
181 | * This function may sleep. Locking for SCU accesses is handled for | ||
182 | * the caller. | ||
183 | */ | ||
184 | static int pmic_scu_ipc_battery_property_get(struct battery_property *prop) | ||
185 | { | ||
186 | u32 data[3]; | ||
187 | u8 *p = (u8 *)&data[1]; | ||
188 | int err = intel_scu_ipc_command(IPC_CMD_BATTERY_PROPERTY, | ||
189 | IPCMSG_BATTERY, NULL, 0, data, 3); | ||
190 | |||
191 | prop->capacity = data[0]; | ||
192 | prop->crnt = *p++; | ||
193 | prop->volt = *p++; | ||
194 | prop->prot = *p++; | ||
195 | prop->prot2 = *p++; | ||
196 | prop->timer = *p++; | ||
197 | |||
198 | return err; | ||
199 | } | ||
200 | |||
201 | /** | ||
202 | * pmic_scu_ipc_set_charger - set charger | ||
203 | * @charger: charger to select | ||
204 | * | ||
205 | * Switch the charging mode for the SCU | ||
206 | */ | ||
207 | |||
208 | static int pmic_scu_ipc_set_charger(int charger) | ||
209 | { | ||
210 | return intel_scu_ipc_simple_command(charger, IPCMSG_BATTERY); | ||
211 | } | ||
212 | |||
213 | /** | ||
214 | * pmic_battery_log_event - log battery events | ||
215 | * @event: battery event to be logged | ||
216 | * Context: can sleep | ||
217 | * | ||
218 | * There are multiple battery events which may be of interest to users; | ||
219 | * this battery function logs the different battery events onto the | ||
220 | * kernel log messages. | ||
221 | */ | ||
222 | static void pmic_battery_log_event(enum batt_event event) | ||
223 | { | ||
224 | printk(KERN_WARNING "pmic-battery: "); | ||
225 | switch (event) { | ||
226 | case BATT_EVENT_BATOVP_EXCPT: | ||
227 | printk(KERN_CONT "battery overvoltage condition\n"); | ||
228 | break; | ||
229 | case BATT_EVENT_USBOVP_EXCPT: | ||
230 | printk(KERN_CONT "usb charger overvoltage condition\n"); | ||
231 | break; | ||
232 | case BATT_EVENT_TEMP_EXCPT: | ||
233 | printk(KERN_CONT "high battery temperature condition\n"); | ||
234 | break; | ||
235 | case BATT_EVENT_DCLMT_EXCPT: | ||
236 | printk(KERN_CONT "over battery charge current condition\n"); | ||
237 | break; | ||
238 | default: | ||
239 | printk(KERN_CONT "charger/battery exception %d\n", event); | ||
240 | break; | ||
241 | } | ||
242 | } | ||
243 | |||
244 | /** | ||
245 | * pmic_battery_read_status - read battery status information | ||
246 | * @pbi: device info structure to update the read information | ||
247 | * Context: can sleep | ||
248 | * | ||
249 | * PMIC power source information need to be updated based on the data read | ||
250 | * from the PMIC battery registers. | ||
251 | * | ||
252 | */ | ||
253 | static void pmic_battery_read_status(struct pmic_power_module_info *pbi) | ||
254 | { | ||
255 | unsigned int update_time_intrvl; | ||
256 | unsigned int chrg_val; | ||
257 | u32 ccval; | ||
258 | u8 r8; | ||
259 | struct battery_property batt_prop; | ||
260 | int batt_present = 0; | ||
261 | int usb_present = 0; | ||
262 | int batt_exception = 0; | ||
263 | |||
264 | /* make sure the last batt_status read happened delay_time before */ | ||
265 | if (pbi->update_time && time_before(jiffies, pbi->update_time + | ||
266 | msecs_to_jiffies(delay_time))) | ||
267 | return; | ||
268 | |||
269 | update_time_intrvl = jiffies_to_msecs(jiffies - pbi->update_time); | ||
270 | pbi->update_time = jiffies; | ||
271 | |||
272 | /* read coulomb counter registers and schrgint register */ | ||
273 | if (pmic_scu_ipc_battery_cc_read(&ccval)) { | ||
274 | dev_warn(pbi->dev, "%s(): ipc config cmd failed\n", | ||
275 | __func__); | ||
276 | return; | ||
277 | } | ||
278 | |||
279 | if (intel_scu_ipc_ioread8(PMIC_BATT_CHR_SCHRGINT_ADDR, &r8)) { | ||
280 | dev_warn(pbi->dev, "%s(): ipc pmic read failed\n", | ||
281 | __func__); | ||
282 | return; | ||
283 | } | ||
284 | |||
285 | /* | ||
286 | * set pmic_power_module_info members based on pmic register values | ||
287 | * read. | ||
288 | */ | ||
289 | |||
290 | /* set batt_is_present */ | ||
291 | if (r8 & PMIC_BATT_CHR_SBATDET_MASK) { | ||
292 | pbi->batt_is_present = PMIC_BATT_PRESENT; | ||
293 | batt_present = 1; | ||
294 | } else { | ||
295 | pbi->batt_is_present = PMIC_BATT_NOT_PRESENT; | ||
296 | pbi->batt_health = POWER_SUPPLY_HEALTH_UNKNOWN; | ||
297 | pbi->batt_status = POWER_SUPPLY_STATUS_UNKNOWN; | ||
298 | } | ||
299 | |||
300 | /* set batt_health */ | ||
301 | if (batt_present) { | ||
302 | if (r8 & PMIC_BATT_CHR_SBATOVP_MASK) { | ||
303 | pbi->batt_health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; | ||
304 | pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
305 | pmic_battery_log_event(BATT_EVENT_BATOVP_EXCPT); | ||
306 | batt_exception = 1; | ||
307 | } else if (r8 & PMIC_BATT_CHR_SDCLMT_MASK) { | ||
308 | pbi->batt_health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; | ||
309 | pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
310 | pmic_battery_log_event(BATT_EVENT_DCLMT_EXCPT); | ||
311 | batt_exception = 1; | ||
312 | } else if (r8 & PMIC_BATT_CHR_STEMP_MASK) { | ||
313 | pbi->batt_health = POWER_SUPPLY_HEALTH_OVERHEAT; | ||
314 | pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
315 | pmic_battery_log_event(BATT_EVENT_TEMP_EXCPT); | ||
316 | batt_exception = 1; | ||
317 | } else { | ||
318 | pbi->batt_health = POWER_SUPPLY_HEALTH_GOOD; | ||
319 | } | ||
320 | } | ||
321 | |||
322 | /* set usb_is_present */ | ||
323 | if (r8 & PMIC_BATT_CHR_SUSBDET_MASK) { | ||
324 | pbi->usb_is_present = PMIC_USB_PRESENT; | ||
325 | usb_present = 1; | ||
326 | } else { | ||
327 | pbi->usb_is_present = PMIC_USB_NOT_PRESENT; | ||
328 | pbi->usb_health = POWER_SUPPLY_HEALTH_UNKNOWN; | ||
329 | } | ||
330 | |||
331 | if (usb_present) { | ||
332 | if (r8 & PMIC_BATT_CHR_SUSBOVP_MASK) { | ||
333 | pbi->usb_health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; | ||
334 | pmic_battery_log_event(BATT_EVENT_USBOVP_EXCPT); | ||
335 | } else { | ||
336 | pbi->usb_health = POWER_SUPPLY_HEALTH_GOOD; | ||
337 | } | ||
338 | } | ||
339 | |||
340 | chrg_val = ccval & PMIC_BATT_ADC_ACCCHRGVAL_MASK; | ||
341 | |||
342 | /* set batt_prev_charge_full to battery capacity the first time */ | ||
343 | if (!pbi->is_dev_info_updated) { | ||
344 | if (pmic_scu_ipc_battery_property_get(&batt_prop)) { | ||
345 | dev_warn(pbi->dev, "%s(): ipc config cmd failed\n", | ||
346 | __func__); | ||
347 | return; | ||
348 | } | ||
349 | pbi->batt_prev_charge_full = batt_prop.capacity; | ||
350 | } | ||
351 | |||
352 | /* set batt_status */ | ||
353 | if (batt_present && !batt_exception) { | ||
354 | if (r8 & PMIC_BATT_CHR_SCOMP_MASK) { | ||
355 | pbi->batt_status = POWER_SUPPLY_STATUS_FULL; | ||
356 | pbi->batt_prev_charge_full = chrg_val; | ||
357 | } else if (ccval & PMIC_BATT_ADC_ACCCHRG_MASK) { | ||
358 | pbi->batt_status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
359 | } else { | ||
360 | pbi->batt_status = POWER_SUPPLY_STATUS_CHARGING; | ||
361 | } | ||
362 | } | ||
363 | |||
364 | /* set batt_charge_rate */ | ||
365 | if (pbi->is_dev_info_updated && batt_present && !batt_exception) { | ||
366 | if (pbi->batt_status == POWER_SUPPLY_STATUS_DISCHARGING) { | ||
367 | if (pbi->batt_charge_now - chrg_val) { | ||
368 | pbi->batt_charge_rate = ((pbi->batt_charge_now - | ||
369 | chrg_val) * 1000 * 60) / | ||
370 | update_time_intrvl; | ||
371 | } | ||
372 | } else if (pbi->batt_status == POWER_SUPPLY_STATUS_CHARGING) { | ||
373 | if (chrg_val - pbi->batt_charge_now) { | ||
374 | pbi->batt_charge_rate = ((chrg_val - | ||
375 | pbi->batt_charge_now) * 1000 * 60) / | ||
376 | update_time_intrvl; | ||
377 | } | ||
378 | } else | ||
379 | pbi->batt_charge_rate = 0; | ||
380 | } else { | ||
381 | pbi->batt_charge_rate = -1; | ||
382 | } | ||
383 | |||
384 | /* batt_charge_now */ | ||
385 | if (batt_present && !batt_exception) | ||
386 | pbi->batt_charge_now = chrg_val; | ||
387 | else | ||
388 | pbi->batt_charge_now = -1; | ||
389 | |||
390 | pbi->is_dev_info_updated = PMIC_BATT_DRV_INFO_UPDATED; | ||
391 | } | ||
392 | |||
393 | /** | ||
394 | * pmic_usb_get_property - usb power source get property | ||
395 | * @psy: usb power supply context | ||
396 | * @psp: usb power source property | ||
397 | * @val: usb power source property value | ||
398 | * Context: can sleep | ||
399 | * | ||
400 | * PMIC usb power source property needs to be provided to power_supply | ||
401 | * subsytem for it to provide the information to users. | ||
402 | */ | ||
403 | static int pmic_usb_get_property(struct power_supply *psy, | ||
404 | enum power_supply_property psp, | ||
405 | union power_supply_propval *val) | ||
406 | { | ||
407 | struct pmic_power_module_info *pbi = container_of(psy, | ||
408 | struct pmic_power_module_info, usb); | ||
409 | |||
410 | /* update pmic_power_module_info members */ | ||
411 | pmic_battery_read_status(pbi); | ||
412 | |||
413 | switch (psp) { | ||
414 | case POWER_SUPPLY_PROP_PRESENT: | ||
415 | val->intval = pbi->usb_is_present; | ||
416 | break; | ||
417 | case POWER_SUPPLY_PROP_HEALTH: | ||
418 | val->intval = pbi->usb_health; | ||
419 | break; | ||
420 | default: | ||
421 | return -EINVAL; | ||
422 | } | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | static inline unsigned long mAStouAh(unsigned long v) | ||
428 | { | ||
429 | /* seconds to hours, mA to µA */ | ||
430 | return (v * 1000) / 3600; | ||
431 | } | ||
432 | |||
433 | /** | ||
434 | * pmic_battery_get_property - battery power source get property | ||
435 | * @psy: battery power supply context | ||
436 | * @psp: battery power source property | ||
437 | * @val: battery power source property value | ||
438 | * Context: can sleep | ||
439 | * | ||
440 | * PMIC battery power source property needs to be provided to power_supply | ||
441 | * subsytem for it to provide the information to users. | ||
442 | */ | ||
443 | static int pmic_battery_get_property(struct power_supply *psy, | ||
444 | enum power_supply_property psp, | ||
445 | union power_supply_propval *val) | ||
446 | { | ||
447 | struct pmic_power_module_info *pbi = container_of(psy, | ||
448 | struct pmic_power_module_info, batt); | ||
449 | |||
450 | /* update pmic_power_module_info members */ | ||
451 | pmic_battery_read_status(pbi); | ||
452 | |||
453 | switch (psp) { | ||
454 | case POWER_SUPPLY_PROP_STATUS: | ||
455 | val->intval = pbi->batt_status; | ||
456 | break; | ||
457 | case POWER_SUPPLY_PROP_HEALTH: | ||
458 | val->intval = pbi->batt_health; | ||
459 | break; | ||
460 | case POWER_SUPPLY_PROP_PRESENT: | ||
461 | val->intval = pbi->batt_is_present; | ||
462 | break; | ||
463 | case POWER_SUPPLY_PROP_CHARGE_NOW: | ||
464 | val->intval = mAStouAh(pbi->batt_charge_now); | ||
465 | break; | ||
466 | case POWER_SUPPLY_PROP_CHARGE_FULL: | ||
467 | val->intval = mAStouAh(pbi->batt_prev_charge_full); | ||
468 | break; | ||
469 | default: | ||
470 | return -EINVAL; | ||
471 | } | ||
472 | |||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | /** | ||
477 | * pmic_battery_monitor - monitor battery status | ||
478 | * @work: work structure | ||
479 | * Context: can sleep | ||
480 | * | ||
481 | * PMIC battery status needs to be monitored for any change | ||
482 | * and information needs to be frequently updated. | ||
483 | */ | ||
484 | static void pmic_battery_monitor(struct work_struct *work) | ||
485 | { | ||
486 | struct pmic_power_module_info *pbi = container_of(work, | ||
487 | struct pmic_power_module_info, monitor_battery.work); | ||
488 | |||
489 | /* update pmic_power_module_info members */ | ||
490 | pmic_battery_read_status(pbi); | ||
491 | queue_delayed_work(pbi->monitor_wqueue, &pbi->monitor_battery, HZ * 10); | ||
492 | } | ||
493 | |||
494 | /** | ||
495 | * pmic_battery_set_charger - set battery charger | ||
496 | * @pbi: device info structure | ||
497 | * @chrg: charge mode to set battery charger in | ||
498 | * Context: can sleep | ||
499 | * | ||
500 | * PMIC battery charger needs to be enabled based on the usb charge | ||
501 | * capabilities connected to the platform. | ||
502 | */ | ||
503 | static int pmic_battery_set_charger(struct pmic_power_module_info *pbi, | ||
504 | enum batt_charge_type chrg) | ||
505 | { | ||
506 | int retval; | ||
507 | |||
508 | /* set usblmt bits and chrgcntl register bits appropriately */ | ||
509 | switch (chrg) { | ||
510 | case BATT_USBOTG_500MA_CHARGE: | ||
511 | retval = pmic_scu_ipc_set_charger(PMIC_BATT_CHR_IPC_FCHRG_SUBID); | ||
512 | break; | ||
513 | case BATT_USBOTG_TRICKLE_CHARGE: | ||
514 | retval = pmic_scu_ipc_set_charger(PMIC_BATT_CHR_IPC_TCHRG_SUBID); | ||
515 | break; | ||
516 | default: | ||
517 | dev_warn(pbi->dev, "%s(): out of range usb charger " | ||
518 | "charge detected\n", __func__); | ||
519 | return -EINVAL; | ||
520 | } | ||
521 | |||
522 | if (retval) { | ||
523 | dev_warn(pbi->dev, "%s(): ipc pmic read failed\n", | ||
524 | __func__); | ||
525 | return retval;; | ||
526 | } | ||
527 | |||
528 | return 0; | ||
529 | } | ||
530 | |||
531 | /** | ||
532 | * pmic_battery_interrupt_handler - pmic battery interrupt handler | ||
533 | * Context: interrupt context | ||
534 | * | ||
535 | * PMIC battery interrupt handler which will be called with either | ||
536 | * battery full condition occurs or usb otg & battery connect | ||
537 | * condition occurs. | ||
538 | */ | ||
539 | static irqreturn_t pmic_battery_interrupt_handler(int id, void *dev) | ||
540 | { | ||
541 | struct pmic_power_module_info *pbi = dev; | ||
542 | |||
543 | schedule_work(&pbi->handler); | ||
544 | |||
545 | return IRQ_HANDLED; | ||
546 | } | ||
547 | |||
548 | /** | ||
549 | * pmic_battery_handle_intrpt - pmic battery service interrupt | ||
550 | * @work: work structure | ||
551 | * Context: can sleep | ||
552 | * | ||
553 | * PMIC battery needs to either update the battery status as full | ||
554 | * if it detects battery full condition caused the interrupt or needs | ||
555 | * to enable battery charger if it detects usb and battery detect | ||
556 | * caused the source of interrupt. | ||
557 | */ | ||
558 | static void pmic_battery_handle_intrpt(struct work_struct *work) | ||
559 | { | ||
560 | struct pmic_power_module_info *pbi = container_of(work, | ||
561 | struct pmic_power_module_info, handler); | ||
562 | enum batt_charge_type chrg; | ||
563 | u8 r8; | ||
564 | |||
565 | if (intel_scu_ipc_ioread8(PMIC_BATT_CHR_SCHRGINT_ADDR, &r8)) { | ||
566 | dev_warn(pbi->dev, "%s(): ipc pmic read failed\n", | ||
567 | __func__); | ||
568 | return; | ||
569 | } | ||
570 | /* find the cause of the interrupt */ | ||
571 | if (r8 & PMIC_BATT_CHR_SBATDET_MASK) { | ||
572 | pbi->batt_is_present = PMIC_BATT_PRESENT; | ||
573 | } else { | ||
574 | pbi->batt_is_present = PMIC_BATT_NOT_PRESENT; | ||
575 | pbi->batt_health = POWER_SUPPLY_HEALTH_UNKNOWN; | ||
576 | pbi->batt_status = POWER_SUPPLY_STATUS_UNKNOWN; | ||
577 | return; | ||
578 | } | ||
579 | |||
580 | if (r8 & PMIC_BATT_CHR_EXCPT_MASK) { | ||
581 | pbi->batt_health = POWER_SUPPLY_HEALTH_UNKNOWN; | ||
582 | pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
583 | pbi->usb_health = POWER_SUPPLY_HEALTH_UNKNOWN; | ||
584 | pmic_battery_log_event(BATT_EVENT_EXCPT); | ||
585 | return; | ||
586 | } else { | ||
587 | pbi->batt_health = POWER_SUPPLY_HEALTH_GOOD; | ||
588 | pbi->usb_health = POWER_SUPPLY_HEALTH_GOOD; | ||
589 | } | ||
590 | |||
591 | if (r8 & PMIC_BATT_CHR_SCOMP_MASK) { | ||
592 | u32 ccval; | ||
593 | pbi->batt_status = POWER_SUPPLY_STATUS_FULL; | ||
594 | |||
595 | if (pmic_scu_ipc_battery_cc_read(&ccval)) { | ||
596 | dev_warn(pbi->dev, "%s(): ipc config cmd " | ||
597 | "failed\n", __func__); | ||
598 | return; | ||
599 | } | ||
600 | pbi->batt_prev_charge_full = ccval & | ||
601 | PMIC_BATT_ADC_ACCCHRGVAL_MASK; | ||
602 | return; | ||
603 | } | ||
604 | |||
605 | if (r8 & PMIC_BATT_CHR_SUSBDET_MASK) { | ||
606 | pbi->usb_is_present = PMIC_USB_PRESENT; | ||
607 | } else { | ||
608 | pbi->usb_is_present = PMIC_USB_NOT_PRESENT; | ||
609 | pbi->usb_health = POWER_SUPPLY_HEALTH_UNKNOWN; | ||
610 | return; | ||
611 | } | ||
612 | |||
613 | /* setup battery charging */ | ||
614 | |||
615 | #if 0 | ||
616 | /* check usb otg power capability and set charger accordingly */ | ||
617 | retval = langwell_udc_maxpower(&power); | ||
618 | if (retval) { | ||
619 | dev_warn(pbi->dev, | ||
620 | "%s(): usb otg power query failed with error code %d\n", | ||
621 | __func__, retval); | ||
622 | return; | ||
623 | } | ||
624 | |||
625 | if (power >= 500) | ||
626 | chrg = BATT_USBOTG_500MA_CHARGE; | ||
627 | else | ||
628 | #endif | ||
629 | chrg = BATT_USBOTG_TRICKLE_CHARGE; | ||
630 | |||
631 | /* enable battery charging */ | ||
632 | if (pmic_battery_set_charger(pbi, chrg)) { | ||
633 | dev_warn(pbi->dev, | ||
634 | "%s(): failed to set up battery charging\n", __func__); | ||
635 | return; | ||
636 | } | ||
637 | |||
638 | dev_dbg(pbi->dev, | ||
639 | "pmic-battery: %s() - setting up battery charger successful\n", | ||
640 | __func__); | ||
641 | } | ||
642 | |||
643 | /** | ||
644 | * pmic_battery_probe - pmic battery initialize | ||
645 | * @irq: pmic battery device irq | ||
646 | * @dev: pmic battery device structure | ||
647 | * Context: can sleep | ||
648 | * | ||
649 | * PMIC battery initializes its internal data structue and other | ||
650 | * infrastructure components for it to work as expected. | ||
651 | */ | ||
652 | static __devinit int probe(int irq, struct device *dev) | ||
653 | { | ||
654 | int retval = 0; | ||
655 | struct pmic_power_module_info *pbi; | ||
656 | |||
657 | dev_dbg(dev, "pmic-battery: found pmic battery device\n"); | ||
658 | |||
659 | pbi = kzalloc(sizeof(*pbi), GFP_KERNEL); | ||
660 | if (!pbi) { | ||
661 | dev_err(dev, "%s(): memory allocation failed\n", | ||
662 | __func__); | ||
663 | return -ENOMEM; | ||
664 | } | ||
665 | |||
666 | pbi->dev = dev; | ||
667 | pbi->irq = irq; | ||
668 | dev_set_drvdata(dev, pbi); | ||
669 | |||
670 | /* initialize all required framework before enabling interrupts */ | ||
671 | INIT_WORK(&pbi->handler, pmic_battery_handle_intrpt); | ||
672 | INIT_DELAYED_WORK(&pbi->monitor_battery, pmic_battery_monitor); | ||
673 | pbi->monitor_wqueue = | ||
674 | create_singlethread_workqueue(dev_name(dev)); | ||
675 | if (!pbi->monitor_wqueue) { | ||
676 | dev_err(dev, "%s(): wqueue init failed\n", __func__); | ||
677 | retval = -ESRCH; | ||
678 | goto wqueue_failed; | ||
679 | } | ||
680 | |||
681 | /* register interrupt */ | ||
682 | retval = request_irq(pbi->irq, pmic_battery_interrupt_handler, | ||
683 | 0, DRIVER_NAME, pbi); | ||
684 | if (retval) { | ||
685 | dev_err(dev, "%s(): cannot get IRQ\n", __func__); | ||
686 | goto requestirq_failed; | ||
687 | } | ||
688 | |||
689 | /* register pmic-batt with power supply subsystem */ | ||
690 | pbi->batt.name = "pmic-batt"; | ||
691 | pbi->batt.type = POWER_SUPPLY_TYPE_BATTERY; | ||
692 | pbi->batt.properties = pmic_battery_props; | ||
693 | pbi->batt.num_properties = ARRAY_SIZE(pmic_battery_props); | ||
694 | pbi->batt.get_property = pmic_battery_get_property; | ||
695 | retval = power_supply_register(dev, &pbi->batt); | ||
696 | if (retval) { | ||
697 | dev_err(dev, | ||
698 | "%s(): failed to register pmic battery device with power supply subsystem\n", | ||
699 | __func__); | ||
700 | goto power_reg_failed; | ||
701 | } | ||
702 | |||
703 | dev_dbg(dev, "pmic-battery: %s() - pmic battery device " | ||
704 | "registration with power supply subsystem successful\n", | ||
705 | __func__); | ||
706 | |||
707 | queue_delayed_work(pbi->monitor_wqueue, &pbi->monitor_battery, HZ * 1); | ||
708 | |||
709 | /* register pmic-usb with power supply subsystem */ | ||
710 | pbi->usb.name = "pmic-usb"; | ||
711 | pbi->usb.type = POWER_SUPPLY_TYPE_USB; | ||
712 | pbi->usb.properties = pmic_usb_props; | ||
713 | pbi->usb.num_properties = ARRAY_SIZE(pmic_usb_props); | ||
714 | pbi->usb.get_property = pmic_usb_get_property; | ||
715 | retval = power_supply_register(dev, &pbi->usb); | ||
716 | if (retval) { | ||
717 | dev_err(dev, | ||
718 | "%s(): failed to register pmic usb device with power supply subsystem\n", | ||
719 | __func__); | ||
720 | goto power_reg_failed_1; | ||
721 | } | ||
722 | |||
723 | if (debug) | ||
724 | printk(KERN_INFO "pmic-battery: %s() - pmic usb device " | ||
725 | "registration with power supply subsystem successful\n", | ||
726 | __func__); | ||
727 | |||
728 | return retval; | ||
729 | |||
730 | power_reg_failed_1: | ||
731 | power_supply_unregister(&pbi->batt); | ||
732 | power_reg_failed: | ||
733 | cancel_rearming_delayed_workqueue(pbi->monitor_wqueue, | ||
734 | &pbi->monitor_battery); | ||
735 | requestirq_failed: | ||
736 | destroy_workqueue(pbi->monitor_wqueue); | ||
737 | wqueue_failed: | ||
738 | kfree(pbi); | ||
739 | |||
740 | return retval; | ||
741 | } | ||
742 | |||
743 | static int __devinit platform_pmic_battery_probe(struct platform_device *pdev) | ||
744 | { | ||
745 | return probe(pdev->id, &pdev->dev); | ||
746 | } | ||
747 | |||
748 | /** | ||
749 | * pmic_battery_remove - pmic battery finalize | ||
750 | * @dev: pmic battery device structure | ||
751 | * Context: can sleep | ||
752 | * | ||
753 | * PMIC battery finalizes its internal data structue and other | ||
754 | * infrastructure components that it initialized in | ||
755 | * pmic_battery_probe. | ||
756 | */ | ||
757 | |||
758 | static int __devexit platform_pmic_battery_remove(struct platform_device *pdev) | ||
759 | { | ||
760 | struct pmic_power_module_info *pbi = dev_get_drvdata(&pdev->dev); | ||
761 | |||
762 | free_irq(pbi->irq, pbi); | ||
763 | cancel_rearming_delayed_workqueue(pbi->monitor_wqueue, | ||
764 | &pbi->monitor_battery); | ||
765 | destroy_workqueue(pbi->monitor_wqueue); | ||
766 | |||
767 | power_supply_unregister(&pbi->usb); | ||
768 | power_supply_unregister(&pbi->batt); | ||
769 | |||
770 | flush_scheduled_work(); | ||
771 | kfree(pbi); | ||
772 | return 0; | ||
773 | } | ||
774 | |||
775 | static struct platform_driver platform_pmic_battery_driver = { | ||
776 | .driver = { | ||
777 | .name = DRIVER_NAME, | ||
778 | .owner = THIS_MODULE, | ||
779 | }, | ||
780 | .probe = platform_pmic_battery_probe, | ||
781 | .remove = __devexit_p(platform_pmic_battery_remove), | ||
782 | }; | ||
783 | |||
784 | static int __init platform_pmic_battery_module_init(void) | ||
785 | { | ||
786 | return platform_driver_register(&platform_pmic_battery_driver); | ||
787 | } | ||
788 | |||
789 | static void __exit platform_pmic_battery_module_exit(void) | ||
790 | { | ||
791 | platform_driver_unregister(&platform_pmic_battery_driver); | ||
792 | } | ||
793 | |||
794 | module_init(platform_pmic_battery_module_init); | ||
795 | module_exit(platform_pmic_battery_module_exit); | ||
796 | |||
797 | MODULE_AUTHOR("Nithish Mahalingam <nithish.mahalingam@intel.com>"); | ||
798 | MODULE_DESCRIPTION("Intel Moorestown PMIC Battery Driver"); | ||
799 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c index 5ab9109b69e6..aafc1c506eda 100644 --- a/drivers/power/olpc_battery.c +++ b/drivers/power/olpc_battery.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Battery driver for One Laptop Per Child board. | 2 | * Battery driver for One Laptop Per Child board. |
3 | * | 3 | * |
4 | * Copyright © 2006 David Woodhouse <dwmw2@infradead.org> | 4 | * Copyright © 2006-2010 David Woodhouse <dwmw2@infradead.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
diff --git a/drivers/power/s3c_adc_battery.c b/drivers/power/s3c_adc_battery.c new file mode 100644 index 000000000000..fe16b482e912 --- /dev/null +++ b/drivers/power/s3c_adc_battery.c | |||
@@ -0,0 +1,431 @@ | |||
1 | /* | ||
2 | * iPAQ h1930/h1940/rx1950 battery controler driver | ||
3 | * Copyright (c) Vasily Khoruzhick | ||
4 | * Based on h1940_battery.c by Arnaud Patard | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file COPYING in the main directory of this archive for | ||
8 | * more details. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/power_supply.h> | ||
15 | #include <linux/leds.h> | ||
16 | #include <linux/gpio.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/timer.h> | ||
19 | #include <linux/jiffies.h> | ||
20 | #include <linux/s3c_adc_battery.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/init.h> | ||
23 | |||
24 | #include <plat/adc.h> | ||
25 | |||
26 | #define BAT_POLL_INTERVAL 10000 /* ms */ | ||
27 | #define JITTER_DELAY 500 /* ms */ | ||
28 | |||
29 | struct s3c_adc_bat { | ||
30 | struct power_supply psy; | ||
31 | struct s3c_adc_client *client; | ||
32 | struct s3c_adc_bat_pdata *pdata; | ||
33 | int volt_value; | ||
34 | int cur_value; | ||
35 | unsigned int timestamp; | ||
36 | int level; | ||
37 | int status; | ||
38 | int cable_plugged:1; | ||
39 | }; | ||
40 | |||
41 | static struct delayed_work bat_work; | ||
42 | |||
43 | static void s3c_adc_bat_ext_power_changed(struct power_supply *psy) | ||
44 | { | ||
45 | schedule_delayed_work(&bat_work, | ||
46 | msecs_to_jiffies(JITTER_DELAY)); | ||
47 | } | ||
48 | |||
49 | static enum power_supply_property s3c_adc_backup_bat_props[] = { | ||
50 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
51 | POWER_SUPPLY_PROP_VOLTAGE_MIN, | ||
52 | POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, | ||
53 | }; | ||
54 | |||
55 | static int s3c_adc_backup_bat_get_property(struct power_supply *psy, | ||
56 | enum power_supply_property psp, | ||
57 | union power_supply_propval *val) | ||
58 | { | ||
59 | struct s3c_adc_bat *bat = container_of(psy, struct s3c_adc_bat, psy); | ||
60 | |||
61 | if (!bat) { | ||
62 | dev_err(psy->dev, "%s: no battery infos ?!\n", __func__); | ||
63 | return -EINVAL; | ||
64 | } | ||
65 | |||
66 | if (bat->volt_value < 0 || | ||
67 | jiffies_to_msecs(jiffies - bat->timestamp) > | ||
68 | BAT_POLL_INTERVAL) { | ||
69 | bat->volt_value = s3c_adc_read(bat->client, | ||
70 | bat->pdata->backup_volt_channel); | ||
71 | bat->volt_value *= bat->pdata->backup_volt_mult; | ||
72 | bat->timestamp = jiffies; | ||
73 | } | ||
74 | |||
75 | switch (psp) { | ||
76 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
77 | val->intval = bat->volt_value; | ||
78 | return 0; | ||
79 | case POWER_SUPPLY_PROP_VOLTAGE_MIN: | ||
80 | val->intval = bat->pdata->backup_volt_min; | ||
81 | return 0; | ||
82 | case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: | ||
83 | val->intval = bat->pdata->backup_volt_max; | ||
84 | return 0; | ||
85 | default: | ||
86 | return -EINVAL; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | static struct s3c_adc_bat backup_bat = { | ||
91 | .psy = { | ||
92 | .name = "backup-battery", | ||
93 | .type = POWER_SUPPLY_TYPE_BATTERY, | ||
94 | .properties = s3c_adc_backup_bat_props, | ||
95 | .num_properties = ARRAY_SIZE(s3c_adc_backup_bat_props), | ||
96 | .get_property = s3c_adc_backup_bat_get_property, | ||
97 | .use_for_apm = 1, | ||
98 | }, | ||
99 | }; | ||
100 | |||
101 | static enum power_supply_property s3c_adc_main_bat_props[] = { | ||
102 | POWER_SUPPLY_PROP_STATUS, | ||
103 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
104 | POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN, | ||
105 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
106 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
107 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
108 | }; | ||
109 | |||
110 | static int calc_full_volt(int volt_val, int cur_val, int impedance) | ||
111 | { | ||
112 | return volt_val + cur_val * impedance / 1000; | ||
113 | } | ||
114 | |||
115 | static int s3c_adc_bat_get_property(struct power_supply *psy, | ||
116 | enum power_supply_property psp, | ||
117 | union power_supply_propval *val) | ||
118 | { | ||
119 | struct s3c_adc_bat *bat = container_of(psy, struct s3c_adc_bat, psy); | ||
120 | |||
121 | int new_level; | ||
122 | int full_volt; | ||
123 | const struct s3c_adc_bat_thresh *lut = bat->pdata->lut_noac; | ||
124 | unsigned int lut_size = bat->pdata->lut_noac_cnt; | ||
125 | |||
126 | if (!bat) { | ||
127 | dev_err(psy->dev, "no battery infos ?!\n"); | ||
128 | return -EINVAL; | ||
129 | } | ||
130 | |||
131 | if (bat->volt_value < 0 || bat->cur_value < 0 || | ||
132 | jiffies_to_msecs(jiffies - bat->timestamp) > | ||
133 | BAT_POLL_INTERVAL) { | ||
134 | bat->volt_value = s3c_adc_read(bat->client, | ||
135 | bat->pdata->volt_channel) * bat->pdata->volt_mult; | ||
136 | bat->cur_value = s3c_adc_read(bat->client, | ||
137 | bat->pdata->current_channel) * bat->pdata->current_mult; | ||
138 | bat->timestamp = jiffies; | ||
139 | } | ||
140 | |||
141 | if (bat->cable_plugged && | ||
142 | ((bat->pdata->gpio_charge_finished < 0) || | ||
143 | !gpio_get_value(bat->pdata->gpio_charge_finished))) { | ||
144 | lut = bat->pdata->lut_acin; | ||
145 | lut_size = bat->pdata->lut_acin_cnt; | ||
146 | } | ||
147 | |||
148 | new_level = 100000; | ||
149 | full_volt = calc_full_volt((bat->volt_value / 1000), | ||
150 | (bat->cur_value / 1000), bat->pdata->internal_impedance); | ||
151 | |||
152 | if (full_volt < calc_full_volt(lut->volt, lut->cur, | ||
153 | bat->pdata->internal_impedance)) { | ||
154 | lut_size--; | ||
155 | while (lut_size--) { | ||
156 | int lut_volt1; | ||
157 | int lut_volt2; | ||
158 | |||
159 | lut_volt1 = calc_full_volt(lut[0].volt, lut[0].cur, | ||
160 | bat->pdata->internal_impedance); | ||
161 | lut_volt2 = calc_full_volt(lut[1].volt, lut[1].cur, | ||
162 | bat->pdata->internal_impedance); | ||
163 | if (full_volt < lut_volt1 && full_volt >= lut_volt2) { | ||
164 | new_level = (lut[1].level + | ||
165 | (lut[0].level - lut[1].level) * | ||
166 | (full_volt - lut_volt2) / | ||
167 | (lut_volt1 - lut_volt2)) * 1000; | ||
168 | break; | ||
169 | } | ||
170 | new_level = lut[1].level * 1000; | ||
171 | lut++; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | bat->level = new_level; | ||
176 | |||
177 | switch (psp) { | ||
178 | case POWER_SUPPLY_PROP_STATUS: | ||
179 | if (bat->pdata->gpio_charge_finished < 0) | ||
180 | val->intval = bat->level == 100000 ? | ||
181 | POWER_SUPPLY_STATUS_FULL : bat->status; | ||
182 | else | ||
183 | val->intval = bat->status; | ||
184 | return 0; | ||
185 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | ||
186 | val->intval = 100000; | ||
187 | return 0; | ||
188 | case POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN: | ||
189 | val->intval = 0; | ||
190 | return 0; | ||
191 | case POWER_SUPPLY_PROP_CHARGE_NOW: | ||
192 | val->intval = bat->level; | ||
193 | return 0; | ||
194 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
195 | val->intval = bat->volt_value; | ||
196 | return 0; | ||
197 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
198 | val->intval = bat->cur_value; | ||
199 | return 0; | ||
200 | default: | ||
201 | return -EINVAL; | ||
202 | } | ||
203 | } | ||
204 | |||
205 | static struct s3c_adc_bat main_bat = { | ||
206 | .psy = { | ||
207 | .name = "main-battery", | ||
208 | .type = POWER_SUPPLY_TYPE_BATTERY, | ||
209 | .properties = s3c_adc_main_bat_props, | ||
210 | .num_properties = ARRAY_SIZE(s3c_adc_main_bat_props), | ||
211 | .get_property = s3c_adc_bat_get_property, | ||
212 | .external_power_changed = s3c_adc_bat_ext_power_changed, | ||
213 | .use_for_apm = 1, | ||
214 | }, | ||
215 | }; | ||
216 | |||
217 | static void s3c_adc_bat_work(struct work_struct *work) | ||
218 | { | ||
219 | struct s3c_adc_bat *bat = &main_bat; | ||
220 | int is_charged; | ||
221 | int is_plugged; | ||
222 | static int was_plugged; | ||
223 | |||
224 | is_plugged = power_supply_am_i_supplied(&bat->psy); | ||
225 | bat->cable_plugged = is_plugged; | ||
226 | if (is_plugged != was_plugged) { | ||
227 | was_plugged = is_plugged; | ||
228 | if (is_plugged) { | ||
229 | if (bat->pdata->enable_charger) | ||
230 | bat->pdata->enable_charger(); | ||
231 | bat->status = POWER_SUPPLY_STATUS_CHARGING; | ||
232 | } else { | ||
233 | if (bat->pdata->disable_charger) | ||
234 | bat->pdata->disable_charger(); | ||
235 | bat->status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
236 | } | ||
237 | } else { | ||
238 | if ((bat->pdata->gpio_charge_finished >= 0) && is_plugged) { | ||
239 | is_charged = gpio_get_value( | ||
240 | main_bat.pdata->gpio_charge_finished); | ||
241 | if (is_charged) { | ||
242 | if (bat->pdata->disable_charger) | ||
243 | bat->pdata->disable_charger(); | ||
244 | bat->status = POWER_SUPPLY_STATUS_FULL; | ||
245 | } else { | ||
246 | if (bat->pdata->enable_charger) | ||
247 | bat->pdata->enable_charger(); | ||
248 | bat->status = POWER_SUPPLY_STATUS_CHARGING; | ||
249 | } | ||
250 | } | ||
251 | } | ||
252 | |||
253 | power_supply_changed(&bat->psy); | ||
254 | } | ||
255 | |||
256 | static irqreturn_t s3c_adc_bat_charged(int irq, void *dev_id) | ||
257 | { | ||
258 | schedule_delayed_work(&bat_work, | ||
259 | msecs_to_jiffies(JITTER_DELAY)); | ||
260 | return IRQ_HANDLED; | ||
261 | } | ||
262 | |||
263 | static int __init s3c_adc_bat_probe(struct platform_device *pdev) | ||
264 | { | ||
265 | struct s3c_adc_client *client; | ||
266 | struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data; | ||
267 | int ret; | ||
268 | |||
269 | client = s3c_adc_register(pdev, NULL, NULL, 0); | ||
270 | if (IS_ERR(client)) { | ||
271 | dev_err(&pdev->dev, "cannot register adc\n"); | ||
272 | return PTR_ERR(client); | ||
273 | } | ||
274 | |||
275 | platform_set_drvdata(pdev, client); | ||
276 | |||
277 | main_bat.client = client; | ||
278 | main_bat.pdata = pdata; | ||
279 | main_bat.volt_value = -1; | ||
280 | main_bat.cur_value = -1; | ||
281 | main_bat.cable_plugged = 0; | ||
282 | main_bat.status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
283 | |||
284 | ret = power_supply_register(&pdev->dev, &main_bat.psy); | ||
285 | if (ret) | ||
286 | goto err_reg_main; | ||
287 | if (pdata->backup_volt_mult) { | ||
288 | backup_bat.client = client; | ||
289 | backup_bat.pdata = pdev->dev.platform_data; | ||
290 | backup_bat.volt_value = -1; | ||
291 | ret = power_supply_register(&pdev->dev, &backup_bat.psy); | ||
292 | if (ret) | ||
293 | goto err_reg_backup; | ||
294 | } | ||
295 | |||
296 | INIT_DELAYED_WORK(&bat_work, s3c_adc_bat_work); | ||
297 | |||
298 | if (pdata->gpio_charge_finished >= 0) { | ||
299 | ret = gpio_request(pdata->gpio_charge_finished, "charged"); | ||
300 | if (ret) | ||
301 | goto err_gpio; | ||
302 | |||
303 | ret = request_irq(gpio_to_irq(pdata->gpio_charge_finished), | ||
304 | s3c_adc_bat_charged, | ||
305 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
306 | "battery charged", NULL); | ||
307 | if (ret) | ||
308 | goto err_irq; | ||
309 | } | ||
310 | |||
311 | if (pdata->init) { | ||
312 | ret = pdata->init(); | ||
313 | if (ret) | ||
314 | goto err_platform; | ||
315 | } | ||
316 | |||
317 | dev_info(&pdev->dev, "successfully loaded\n"); | ||
318 | device_init_wakeup(&pdev->dev, 1); | ||
319 | |||
320 | /* Schedule timer to check current status */ | ||
321 | schedule_delayed_work(&bat_work, | ||
322 | msecs_to_jiffies(JITTER_DELAY)); | ||
323 | |||
324 | return 0; | ||
325 | |||
326 | err_platform: | ||
327 | if (pdata->gpio_charge_finished >= 0) | ||
328 | free_irq(gpio_to_irq(pdata->gpio_charge_finished), NULL); | ||
329 | err_irq: | ||
330 | if (pdata->gpio_charge_finished >= 0) | ||
331 | gpio_free(pdata->gpio_charge_finished); | ||
332 | err_gpio: | ||
333 | if (pdata->backup_volt_mult) | ||
334 | power_supply_unregister(&backup_bat.psy); | ||
335 | err_reg_backup: | ||
336 | power_supply_unregister(&main_bat.psy); | ||
337 | err_reg_main: | ||
338 | return ret; | ||
339 | } | ||
340 | |||
341 | static int s3c_adc_bat_remove(struct platform_device *pdev) | ||
342 | { | ||
343 | struct s3c_adc_client *client = platform_get_drvdata(pdev); | ||
344 | struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data; | ||
345 | |||
346 | power_supply_unregister(&main_bat.psy); | ||
347 | if (pdata->backup_volt_mult) | ||
348 | power_supply_unregister(&backup_bat.psy); | ||
349 | |||
350 | s3c_adc_release(client); | ||
351 | |||
352 | if (pdata->gpio_charge_finished >= 0) { | ||
353 | free_irq(gpio_to_irq(pdata->gpio_charge_finished), NULL); | ||
354 | gpio_free(pdata->gpio_charge_finished); | ||
355 | } | ||
356 | |||
357 | cancel_delayed_work(&bat_work); | ||
358 | |||
359 | if (pdata->exit) | ||
360 | pdata->exit(); | ||
361 | |||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | #ifdef CONFIG_PM | ||
366 | static int s3c_adc_bat_suspend(struct platform_device *pdev, | ||
367 | pm_message_t state) | ||
368 | { | ||
369 | struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data; | ||
370 | |||
371 | if (pdata->gpio_charge_finished >= 0) { | ||
372 | if (device_may_wakeup(&pdev->dev)) | ||
373 | enable_irq_wake( | ||
374 | gpio_to_irq(pdata->gpio_charge_finished)); | ||
375 | else { | ||
376 | disable_irq(gpio_to_irq(pdata->gpio_charge_finished)); | ||
377 | main_bat.pdata->disable_charger(); | ||
378 | } | ||
379 | } | ||
380 | |||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | static int s3c_adc_bat_resume(struct platform_device *pdev) | ||
385 | { | ||
386 | struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data; | ||
387 | |||
388 | if (pdata->gpio_charge_finished >= 0) { | ||
389 | if (device_may_wakeup(&pdev->dev)) | ||
390 | disable_irq_wake( | ||
391 | gpio_to_irq(pdata->gpio_charge_finished)); | ||
392 | else | ||
393 | enable_irq(gpio_to_irq(pdata->gpio_charge_finished)); | ||
394 | } | ||
395 | |||
396 | /* Schedule timer to check current status */ | ||
397 | schedule_delayed_work(&bat_work, | ||
398 | msecs_to_jiffies(JITTER_DELAY)); | ||
399 | |||
400 | return 0; | ||
401 | } | ||
402 | #else | ||
403 | #define s3c_adc_battery_suspend NULL | ||
404 | #define s3c_adc_battery_resume NULL | ||
405 | #endif | ||
406 | |||
407 | static struct platform_driver s3c_adc_bat_driver = { | ||
408 | .driver = { | ||
409 | .name = "s3c-adc-battery", | ||
410 | }, | ||
411 | .probe = s3c_adc_bat_probe, | ||
412 | .remove = s3c_adc_bat_remove, | ||
413 | .suspend = s3c_adc_bat_suspend, | ||
414 | .resume = s3c_adc_bat_resume, | ||
415 | }; | ||
416 | |||
417 | static int __init s3c_adc_bat_init(void) | ||
418 | { | ||
419 | return platform_driver_register(&s3c_adc_bat_driver); | ||
420 | } | ||
421 | module_init(s3c_adc_bat_init); | ||
422 | |||
423 | static void __exit s3c_adc_bat_exit(void) | ||
424 | { | ||
425 | platform_driver_unregister(&s3c_adc_bat_driver); | ||
426 | } | ||
427 | module_exit(s3c_adc_bat_exit); | ||
428 | |||
429 | MODULE_AUTHOR("Vasily Khoruzhick <anarsoul@gmail.com>"); | ||
430 | MODULE_DESCRIPTION("iPAQ H1930/H1940/RX1950 battery controler driver"); | ||
431 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 04f2e085116a..172951bf23a4 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
@@ -100,6 +100,14 @@ config REGULATOR_MAX8925 | |||
100 | help | 100 | help |
101 | Say y here to support the voltage regulaltor of Maxim MAX8925 PMIC. | 101 | Say y here to support the voltage regulaltor of Maxim MAX8925 PMIC. |
102 | 102 | ||
103 | config REGULATOR_MAX8998 | ||
104 | tristate "Maxim 8998 voltage regulator" | ||
105 | depends on MFD_MAX8998 | ||
106 | help | ||
107 | This driver controls a Maxim 8998 voltage output regulator | ||
108 | via I2C bus. The provided regulator is suitable for S3C6410 | ||
109 | and S5PC1XX chips to control VCC_CORE and VCC_USIM voltages. | ||
110 | |||
103 | config REGULATOR_TWL4030 | 111 | config REGULATOR_TWL4030 |
104 | bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC" | 112 | bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC" |
105 | depends on TWL4030_CORE | 113 | depends on TWL4030_CORE |
@@ -201,5 +209,31 @@ config REGULATOR_88PM8607 | |||
201 | help | 209 | help |
202 | This driver supports 88PM8607 voltage regulator chips. | 210 | This driver supports 88PM8607 voltage regulator chips. |
203 | 211 | ||
212 | config REGULATOR_ISL6271A | ||
213 | tristate "Intersil ISL6271A Power regulator" | ||
214 | depends on I2C | ||
215 | help | ||
216 | This driver supports ISL6271A voltage regulator chip. | ||
217 | |||
218 | config REGULATOR_AD5398 | ||
219 | tristate "Analog Devices AD5398/AD5821 regulators" | ||
220 | depends on I2C | ||
221 | help | ||
222 | This driver supports AD5398 and AD5821 current regulator chips. | ||
223 | If building into module, its name is ad5398.ko. | ||
224 | |||
225 | config REGULATOR_AB8500 | ||
226 | bool "ST-Ericsson AB8500 Power Regulators" | ||
227 | depends on AB8500_CORE | ||
228 | help | ||
229 | This driver supports the regulators found on the ST-Ericsson mixed | ||
230 | signal AB8500 PMIC | ||
231 | |||
232 | config REGULATOR_TPS6586X | ||
233 | tristate "TI TPS6586X Power regulators" | ||
234 | depends on MFD_TPS6586X | ||
235 | help | ||
236 | This driver supports TPS6586X voltage regulator chips. | ||
237 | |||
204 | endif | 238 | endif |
205 | 239 | ||
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 4e7feece22d5..8285fd832e16 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
@@ -8,6 +8,7 @@ obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o | |||
8 | obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o | 8 | obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o |
9 | obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o | 9 | obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o |
10 | 10 | ||
11 | obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o | ||
11 | obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o | 12 | obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o |
12 | obj-$(CONFIG_REGULATOR_DUMMY) += dummy.o | 13 | obj-$(CONFIG_REGULATOR_DUMMY) += dummy.o |
13 | obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o | 14 | obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o |
@@ -16,12 +17,14 @@ obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o | |||
16 | obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o | 17 | obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o |
17 | obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o | 18 | obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o |
18 | obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o | 19 | obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o |
20 | obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o | ||
19 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o | 21 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o |
20 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o | 22 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o |
21 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o | 23 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o |
22 | obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o | 24 | obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o |
23 | obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o | 25 | obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o |
24 | obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o | 26 | obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o |
27 | obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o | ||
25 | obj-$(CONFIG_REGULATOR_DA903X) += da903x.o | 28 | obj-$(CONFIG_REGULATOR_DA903X) += da903x.o |
26 | obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o | 29 | obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o |
27 | obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o | 30 | obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o |
@@ -31,5 +34,7 @@ obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o | |||
31 | obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o | 34 | obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o |
32 | obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o | 35 | obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o |
33 | obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o | 36 | obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o |
37 | obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o | ||
38 | obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o | ||
34 | 39 | ||
35 | ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG | 40 | ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG |
diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c new file mode 100644 index 000000000000..dc3f1a491675 --- /dev/null +++ b/drivers/regulator/ab8500.c | |||
@@ -0,0 +1,427 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License v2 | ||
5 | * | ||
6 | * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson | ||
7 | * | ||
8 | * AB8500 peripheral regulators | ||
9 | * | ||
10 | * AB8500 supports the following regulators, | ||
11 | * LDOs - VAUDIO, VANAMIC2/2, VDIGMIC, VINTCORE12, VTVOUT, | ||
12 | * VAUX1/2/3, VANA | ||
13 | * | ||
14 | * for DB8500 cut 1.0 and previous versions of the silicon, all accesses | ||
15 | * to registers are through the DB8500 SPI. In cut 1.1 onwards, these | ||
16 | * accesses are through the DB8500 PRCMU I2C | ||
17 | * | ||
18 | */ | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/err.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/mfd/ab8500.h> | ||
24 | #include <linux/regulator/driver.h> | ||
25 | #include <linux/regulator/machine.h> | ||
26 | #include <linux/regulator/ab8500.h> | ||
27 | |||
28 | /** | ||
29 | * struct ab8500_regulator_info - ab8500 regulator information | ||
30 | * @desc: regulator description | ||
31 | * @ab8500: ab8500 parent | ||
32 | * @regulator_dev: regulator device | ||
33 | * @max_uV: maximum voltage (for variable voltage supplies) | ||
34 | * @min_uV: minimum voltage (for variable voltage supplies) | ||
35 | * @fixed_uV: typical voltage (for fixed voltage supplies) | ||
36 | * @update_reg: register to control on/off | ||
37 | * @mask: mask to enable/disable regulator | ||
38 | * @enable: bits to enable the regulator in normal(high power) mode | ||
39 | * @voltage_reg: register to control regulator voltage | ||
40 | * @voltage_mask: mask to control regulator voltage | ||
41 | * @supported_voltages: supported voltage table | ||
42 | * @voltages_len: number of supported voltages for the regulator | ||
43 | */ | ||
44 | struct ab8500_regulator_info { | ||
45 | struct device *dev; | ||
46 | struct regulator_desc desc; | ||
47 | struct ab8500 *ab8500; | ||
48 | struct regulator_dev *regulator; | ||
49 | int max_uV; | ||
50 | int min_uV; | ||
51 | int fixed_uV; | ||
52 | int update_reg; | ||
53 | int mask; | ||
54 | int enable; | ||
55 | int voltage_reg; | ||
56 | int voltage_mask; | ||
57 | int const *supported_voltages; | ||
58 | int voltages_len; | ||
59 | }; | ||
60 | |||
61 | /* voltage tables for the vauxn/vintcore supplies */ | ||
62 | static const int ldo_vauxn_voltages[] = { | ||
63 | 1100000, | ||
64 | 1200000, | ||
65 | 1300000, | ||
66 | 1400000, | ||
67 | 1500000, | ||
68 | 1800000, | ||
69 | 1850000, | ||
70 | 1900000, | ||
71 | 2500000, | ||
72 | 2650000, | ||
73 | 2700000, | ||
74 | 2750000, | ||
75 | 2800000, | ||
76 | 2900000, | ||
77 | 3000000, | ||
78 | 3300000, | ||
79 | }; | ||
80 | |||
81 | static const int ldo_vintcore_voltages[] = { | ||
82 | 1200000, | ||
83 | 1225000, | ||
84 | 1250000, | ||
85 | 1275000, | ||
86 | 1300000, | ||
87 | 1325000, | ||
88 | 1350000, | ||
89 | }; | ||
90 | |||
91 | static int ab8500_regulator_enable(struct regulator_dev *rdev) | ||
92 | { | ||
93 | int regulator_id, ret; | ||
94 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | ||
95 | |||
96 | regulator_id = rdev_get_id(rdev); | ||
97 | if (regulator_id >= AB8500_NUM_REGULATORS) | ||
98 | return -EINVAL; | ||
99 | |||
100 | ret = ab8500_set_bits(info->ab8500, info->update_reg, | ||
101 | info->mask, info->enable); | ||
102 | if (ret < 0) | ||
103 | dev_err(rdev_get_dev(rdev), | ||
104 | "couldn't set enable bits for regulator\n"); | ||
105 | return ret; | ||
106 | } | ||
107 | |||
108 | static int ab8500_regulator_disable(struct regulator_dev *rdev) | ||
109 | { | ||
110 | int regulator_id, ret; | ||
111 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | ||
112 | |||
113 | regulator_id = rdev_get_id(rdev); | ||
114 | if (regulator_id >= AB8500_NUM_REGULATORS) | ||
115 | return -EINVAL; | ||
116 | |||
117 | ret = ab8500_set_bits(info->ab8500, info->update_reg, | ||
118 | info->mask, 0x0); | ||
119 | if (ret < 0) | ||
120 | dev_err(rdev_get_dev(rdev), | ||
121 | "couldn't set disable bits for regulator\n"); | ||
122 | return ret; | ||
123 | } | ||
124 | |||
125 | static int ab8500_regulator_is_enabled(struct regulator_dev *rdev) | ||
126 | { | ||
127 | int regulator_id, ret; | ||
128 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | ||
129 | |||
130 | regulator_id = rdev_get_id(rdev); | ||
131 | if (regulator_id >= AB8500_NUM_REGULATORS) | ||
132 | return -EINVAL; | ||
133 | |||
134 | ret = ab8500_read(info->ab8500, info->update_reg); | ||
135 | if (ret < 0) { | ||
136 | dev_err(rdev_get_dev(rdev), | ||
137 | "couldn't read 0x%x register\n", info->update_reg); | ||
138 | return ret; | ||
139 | } | ||
140 | |||
141 | if (ret & info->mask) | ||
142 | return true; | ||
143 | else | ||
144 | return false; | ||
145 | } | ||
146 | |||
147 | static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector) | ||
148 | { | ||
149 | int regulator_id; | ||
150 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | ||
151 | |||
152 | regulator_id = rdev_get_id(rdev); | ||
153 | if (regulator_id >= AB8500_NUM_REGULATORS) | ||
154 | return -EINVAL; | ||
155 | |||
156 | /* return the uV for the fixed regulators */ | ||
157 | if (info->fixed_uV) | ||
158 | return info->fixed_uV; | ||
159 | |||
160 | if (selector > info->voltages_len) | ||
161 | return -EINVAL; | ||
162 | |||
163 | return info->supported_voltages[selector]; | ||
164 | } | ||
165 | |||
166 | static int ab8500_regulator_get_voltage(struct regulator_dev *rdev) | ||
167 | { | ||
168 | int regulator_id, ret, val; | ||
169 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | ||
170 | |||
171 | regulator_id = rdev_get_id(rdev); | ||
172 | if (regulator_id >= AB8500_NUM_REGULATORS) | ||
173 | return -EINVAL; | ||
174 | |||
175 | ret = ab8500_read(info->ab8500, info->voltage_reg); | ||
176 | if (ret < 0) { | ||
177 | dev_err(rdev_get_dev(rdev), | ||
178 | "couldn't read voltage reg for regulator\n"); | ||
179 | return ret; | ||
180 | } | ||
181 | |||
182 | /* vintcore has a different layout */ | ||
183 | val = ret & info->voltage_mask; | ||
184 | if (regulator_id == AB8500_LDO_INTCORE) | ||
185 | ret = info->supported_voltages[val >> 0x3]; | ||
186 | else | ||
187 | ret = info->supported_voltages[val]; | ||
188 | |||
189 | return ret; | ||
190 | } | ||
191 | |||
192 | static int ab8500_get_best_voltage_index(struct regulator_dev *rdev, | ||
193 | int min_uV, int max_uV) | ||
194 | { | ||
195 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | ||
196 | int i; | ||
197 | |||
198 | /* check the supported voltage */ | ||
199 | for (i = 0; i < info->voltages_len; i++) { | ||
200 | if ((info->supported_voltages[i] >= min_uV) && | ||
201 | (info->supported_voltages[i] <= max_uV)) | ||
202 | return i; | ||
203 | } | ||
204 | |||
205 | return -EINVAL; | ||
206 | } | ||
207 | |||
208 | static int ab8500_regulator_set_voltage(struct regulator_dev *rdev, | ||
209 | int min_uV, int max_uV) | ||
210 | { | ||
211 | int regulator_id, ret; | ||
212 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | ||
213 | |||
214 | regulator_id = rdev_get_id(rdev); | ||
215 | if (regulator_id >= AB8500_NUM_REGULATORS) | ||
216 | return -EINVAL; | ||
217 | |||
218 | /* get the appropriate voltages within the range */ | ||
219 | ret = ab8500_get_best_voltage_index(rdev, min_uV, max_uV); | ||
220 | if (ret < 0) { | ||
221 | dev_err(rdev_get_dev(rdev), | ||
222 | "couldn't get best voltage for regulator\n"); | ||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | /* set the registers for the request */ | ||
227 | ret = ab8500_set_bits(info->ab8500, info->voltage_reg, | ||
228 | info->voltage_mask, ret); | ||
229 | if (ret < 0) | ||
230 | dev_err(rdev_get_dev(rdev), | ||
231 | "couldn't set voltage reg for regulator\n"); | ||
232 | |||
233 | return ret; | ||
234 | } | ||
235 | |||
236 | static struct regulator_ops ab8500_regulator_ops = { | ||
237 | .enable = ab8500_regulator_enable, | ||
238 | .disable = ab8500_regulator_disable, | ||
239 | .is_enabled = ab8500_regulator_is_enabled, | ||
240 | .get_voltage = ab8500_regulator_get_voltage, | ||
241 | .set_voltage = ab8500_regulator_set_voltage, | ||
242 | .list_voltage = ab8500_list_voltage, | ||
243 | }; | ||
244 | |||
245 | static int ab8500_fixed_get_voltage(struct regulator_dev *rdev) | ||
246 | { | ||
247 | int regulator_id; | ||
248 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | ||
249 | |||
250 | regulator_id = rdev_get_id(rdev); | ||
251 | if (regulator_id >= AB8500_NUM_REGULATORS) | ||
252 | return -EINVAL; | ||
253 | |||
254 | return info->fixed_uV; | ||
255 | } | ||
256 | |||
257 | static struct regulator_ops ab8500_ldo_fixed_ops = { | ||
258 | .enable = ab8500_regulator_enable, | ||
259 | .disable = ab8500_regulator_disable, | ||
260 | .is_enabled = ab8500_regulator_is_enabled, | ||
261 | .get_voltage = ab8500_fixed_get_voltage, | ||
262 | .list_voltage = ab8500_list_voltage, | ||
263 | }; | ||
264 | |||
265 | #define AB8500_LDO(_id, min, max, reg, reg_mask, reg_enable, \ | ||
266 | volt_reg, volt_mask, voltages, \ | ||
267 | len_volts) \ | ||
268 | { \ | ||
269 | .desc = { \ | ||
270 | .name = "LDO-" #_id, \ | ||
271 | .ops = &ab8500_regulator_ops, \ | ||
272 | .type = REGULATOR_VOLTAGE, \ | ||
273 | .id = AB8500_LDO_##_id, \ | ||
274 | .owner = THIS_MODULE, \ | ||
275 | }, \ | ||
276 | .min_uV = (min) * 1000, \ | ||
277 | .max_uV = (max) * 1000, \ | ||
278 | .update_reg = reg, \ | ||
279 | .mask = reg_mask, \ | ||
280 | .enable = reg_enable, \ | ||
281 | .voltage_reg = volt_reg, \ | ||
282 | .voltage_mask = volt_mask, \ | ||
283 | .supported_voltages = voltages, \ | ||
284 | .voltages_len = len_volts, \ | ||
285 | .fixed_uV = 0, \ | ||
286 | } | ||
287 | |||
288 | #define AB8500_FIXED_LDO(_id, fixed, reg, reg_mask, \ | ||
289 | reg_enable) \ | ||
290 | { \ | ||
291 | .desc = { \ | ||
292 | .name = "LDO-" #_id, \ | ||
293 | .ops = &ab8500_ldo_fixed_ops, \ | ||
294 | .type = REGULATOR_VOLTAGE, \ | ||
295 | .id = AB8500_LDO_##_id, \ | ||
296 | .owner = THIS_MODULE, \ | ||
297 | }, \ | ||
298 | .fixed_uV = fixed * 1000, \ | ||
299 | .update_reg = reg, \ | ||
300 | .mask = reg_mask, \ | ||
301 | .enable = reg_enable, \ | ||
302 | } | ||
303 | |||
304 | static struct ab8500_regulator_info ab8500_regulator_info[] = { | ||
305 | /* | ||
306 | * Variable Voltage LDOs | ||
307 | * name, min uV, max uV, ctrl reg, reg mask, enable mask, | ||
308 | * volt ctrl reg, volt ctrl mask, volt table, num supported volts | ||
309 | */ | ||
310 | AB8500_LDO(AUX1, 1100, 3300, 0x0409, 0x3, 0x1, 0x041f, 0xf, | ||
311 | ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)), | ||
312 | AB8500_LDO(AUX2, 1100, 3300, 0x0409, 0xc, 0x4, 0x0420, 0xf, | ||
313 | ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)), | ||
314 | AB8500_LDO(AUX3, 1100, 3300, 0x040a, 0x3, 0x1, 0x0421, 0xf, | ||
315 | ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)), | ||
316 | AB8500_LDO(INTCORE, 1100, 3300, 0x0380, 0x4, 0x4, 0x0380, 0x38, | ||
317 | ldo_vintcore_voltages, ARRAY_SIZE(ldo_vintcore_voltages)), | ||
318 | |||
319 | /* | ||
320 | * Fixed Voltage LDOs | ||
321 | * name, o/p uV, ctrl reg, enable, disable | ||
322 | */ | ||
323 | AB8500_FIXED_LDO(TVOUT, 2000, 0x0380, 0x2, 0x2), | ||
324 | AB8500_FIXED_LDO(AUDIO, 2000, 0x0383, 0x2, 0x2), | ||
325 | AB8500_FIXED_LDO(ANAMIC1, 2050, 0x0383, 0x4, 0x4), | ||
326 | AB8500_FIXED_LDO(ANAMIC2, 2050, 0x0383, 0x8, 0x8), | ||
327 | AB8500_FIXED_LDO(DMIC, 1800, 0x0383, 0x10, 0x10), | ||
328 | AB8500_FIXED_LDO(ANA, 1200, 0x0383, 0xc, 0x4), | ||
329 | }; | ||
330 | |||
331 | static inline struct ab8500_regulator_info *find_regulator_info(int id) | ||
332 | { | ||
333 | struct ab8500_regulator_info *info; | ||
334 | int i; | ||
335 | |||
336 | for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { | ||
337 | info = &ab8500_regulator_info[i]; | ||
338 | if (info->desc.id == id) | ||
339 | return info; | ||
340 | } | ||
341 | return NULL; | ||
342 | } | ||
343 | |||
344 | static __devinit int ab8500_regulator_probe(struct platform_device *pdev) | ||
345 | { | ||
346 | struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); | ||
347 | struct ab8500_platform_data *pdata = dev_get_platdata(ab8500->dev); | ||
348 | int i, err; | ||
349 | |||
350 | if (!ab8500) { | ||
351 | dev_err(&pdev->dev, "null mfd parent\n"); | ||
352 | return -EINVAL; | ||
353 | } | ||
354 | |||
355 | /* register all regulators */ | ||
356 | for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { | ||
357 | struct ab8500_regulator_info *info = NULL; | ||
358 | |||
359 | /* assign per-regulator data */ | ||
360 | info = &ab8500_regulator_info[i]; | ||
361 | info->dev = &pdev->dev; | ||
362 | info->ab8500 = ab8500; | ||
363 | |||
364 | info->regulator = regulator_register(&info->desc, &pdev->dev, | ||
365 | pdata->regulator[i], info); | ||
366 | if (IS_ERR(info->regulator)) { | ||
367 | err = PTR_ERR(info->regulator); | ||
368 | dev_err(&pdev->dev, "failed to register regulator %s\n", | ||
369 | info->desc.name); | ||
370 | /* when we fail, un-register all earlier regulators */ | ||
371 | i--; | ||
372 | while (i > 0) { | ||
373 | info = &ab8500_regulator_info[i]; | ||
374 | regulator_unregister(info->regulator); | ||
375 | i--; | ||
376 | } | ||
377 | return err; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | static __devexit int ab8500_regulator_remove(struct platform_device *pdev) | ||
385 | { | ||
386 | int i; | ||
387 | |||
388 | for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { | ||
389 | struct ab8500_regulator_info *info = NULL; | ||
390 | info = &ab8500_regulator_info[i]; | ||
391 | regulator_unregister(info->regulator); | ||
392 | } | ||
393 | |||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | static struct platform_driver ab8500_regulator_driver = { | ||
398 | .probe = ab8500_regulator_probe, | ||
399 | .remove = __devexit_p(ab8500_regulator_remove), | ||
400 | .driver = { | ||
401 | .name = "ab8500-regulator", | ||
402 | .owner = THIS_MODULE, | ||
403 | }, | ||
404 | }; | ||
405 | |||
406 | static int __init ab8500_regulator_init(void) | ||
407 | { | ||
408 | int ret; | ||
409 | |||
410 | ret = platform_driver_register(&ab8500_regulator_driver); | ||
411 | if (ret != 0) | ||
412 | pr_err("Failed to register ab8500 regulator: %d\n", ret); | ||
413 | |||
414 | return ret; | ||
415 | } | ||
416 | subsys_initcall(ab8500_regulator_init); | ||
417 | |||
418 | static void __exit ab8500_regulator_exit(void) | ||
419 | { | ||
420 | platform_driver_unregister(&ab8500_regulator_driver); | ||
421 | } | ||
422 | module_exit(ab8500_regulator_exit); | ||
423 | |||
424 | MODULE_LICENSE("GPL v2"); | ||
425 | MODULE_AUTHOR("Sundar Iyer <sundar.iyer@stericsson.com>"); | ||
426 | MODULE_DESCRIPTION("Regulator Driver for ST-Ericsson AB8500 Mixed-Sig PMIC"); | ||
427 | MODULE_ALIAS("platform:ab8500-regulator"); | ||
diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c new file mode 100644 index 000000000000..d59d2f2314af --- /dev/null +++ b/drivers/regulator/ad5398.c | |||
@@ -0,0 +1,288 @@ | |||
1 | /* | ||
2 | * Voltage and current regulation for AD5398 and AD5821 | ||
3 | * | ||
4 | * Copyright 2010 Analog Devices Inc. | ||
5 | * | ||
6 | * Enter bugs at http://blackfin.uclinux.org/ | ||
7 | * | ||
8 | * Licensed under the GPL-2 or later. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/err.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/regulator/driver.h> | ||
17 | #include <linux/regulator/machine.h> | ||
18 | |||
19 | #define AD5398_CURRENT_EN_MASK 0x8000 | ||
20 | |||
21 | struct ad5398_chip_info { | ||
22 | struct i2c_client *client; | ||
23 | int min_uA; | ||
24 | int max_uA; | ||
25 | unsigned int current_level; | ||
26 | unsigned int current_mask; | ||
27 | unsigned int current_offset; | ||
28 | struct regulator_dev rdev; | ||
29 | }; | ||
30 | |||
31 | static int ad5398_calc_current(struct ad5398_chip_info *chip, | ||
32 | unsigned selector) | ||
33 | { | ||
34 | unsigned range_uA = chip->max_uA - chip->min_uA; | ||
35 | |||
36 | return chip->min_uA + (selector * range_uA / chip->current_level); | ||
37 | } | ||
38 | |||
39 | static int ad5398_read_reg(struct i2c_client *client, unsigned short *data) | ||
40 | { | ||
41 | unsigned short val; | ||
42 | int ret; | ||
43 | |||
44 | ret = i2c_master_recv(client, (char *)&val, 2); | ||
45 | if (ret < 0) { | ||
46 | dev_err(&client->dev, "I2C read error\n"); | ||
47 | return ret; | ||
48 | } | ||
49 | *data = be16_to_cpu(val); | ||
50 | |||
51 | return ret; | ||
52 | } | ||
53 | |||
54 | static int ad5398_write_reg(struct i2c_client *client, const unsigned short data) | ||
55 | { | ||
56 | unsigned short val; | ||
57 | int ret; | ||
58 | |||
59 | val = cpu_to_be16(data); | ||
60 | ret = i2c_master_send(client, (char *)&val, 2); | ||
61 | if (ret < 0) | ||
62 | dev_err(&client->dev, "I2C write error\n"); | ||
63 | |||
64 | return ret; | ||
65 | } | ||
66 | |||
67 | static int ad5398_get_current_limit(struct regulator_dev *rdev) | ||
68 | { | ||
69 | struct ad5398_chip_info *chip = rdev_get_drvdata(rdev); | ||
70 | struct i2c_client *client = chip->client; | ||
71 | unsigned short data; | ||
72 | int ret; | ||
73 | |||
74 | ret = ad5398_read_reg(client, &data); | ||
75 | if (ret < 0) | ||
76 | return ret; | ||
77 | |||
78 | ret = (data & chip->current_mask) >> chip->current_offset; | ||
79 | |||
80 | return ad5398_calc_current(chip, ret); | ||
81 | } | ||
82 | |||
83 | static int ad5398_set_current_limit(struct regulator_dev *rdev, int min_uA, int max_uA) | ||
84 | { | ||
85 | struct ad5398_chip_info *chip = rdev_get_drvdata(rdev); | ||
86 | struct i2c_client *client = chip->client; | ||
87 | unsigned range_uA = chip->max_uA - chip->min_uA; | ||
88 | unsigned selector; | ||
89 | unsigned short data; | ||
90 | int ret; | ||
91 | |||
92 | if (min_uA > chip->max_uA || min_uA < chip->min_uA) | ||
93 | return -EINVAL; | ||
94 | if (max_uA > chip->max_uA || max_uA < chip->min_uA) | ||
95 | return -EINVAL; | ||
96 | |||
97 | selector = ((min_uA - chip->min_uA) * chip->current_level + | ||
98 | range_uA - 1) / range_uA; | ||
99 | if (ad5398_calc_current(chip, selector) > max_uA) | ||
100 | return -EINVAL; | ||
101 | |||
102 | dev_dbg(&client->dev, "changing current %dmA\n", | ||
103 | ad5398_calc_current(chip, selector) / 1000); | ||
104 | |||
105 | /* read chip enable bit */ | ||
106 | ret = ad5398_read_reg(client, &data); | ||
107 | if (ret < 0) | ||
108 | return ret; | ||
109 | |||
110 | /* prepare register data */ | ||
111 | selector = (selector << chip->current_offset) & chip->current_mask; | ||
112 | data = (unsigned short)selector | (data & AD5398_CURRENT_EN_MASK); | ||
113 | |||
114 | /* write the new current value back as well as enable bit */ | ||
115 | ret = ad5398_write_reg(client, data); | ||
116 | |||
117 | return ret; | ||
118 | } | ||
119 | |||
120 | static int ad5398_is_enabled(struct regulator_dev *rdev) | ||
121 | { | ||
122 | struct ad5398_chip_info *chip = rdev_get_drvdata(rdev); | ||
123 | struct i2c_client *client = chip->client; | ||
124 | unsigned short data; | ||
125 | int ret; | ||
126 | |||
127 | ret = ad5398_read_reg(client, &data); | ||
128 | if (ret < 0) | ||
129 | return ret; | ||
130 | |||
131 | if (data & AD5398_CURRENT_EN_MASK) | ||
132 | return 1; | ||
133 | else | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static int ad5398_enable(struct regulator_dev *rdev) | ||
138 | { | ||
139 | struct ad5398_chip_info *chip = rdev_get_drvdata(rdev); | ||
140 | struct i2c_client *client = chip->client; | ||
141 | unsigned short data; | ||
142 | int ret; | ||
143 | |||
144 | ret = ad5398_read_reg(client, &data); | ||
145 | if (ret < 0) | ||
146 | return ret; | ||
147 | |||
148 | if (data & AD5398_CURRENT_EN_MASK) | ||
149 | return 0; | ||
150 | |||
151 | data |= AD5398_CURRENT_EN_MASK; | ||
152 | |||
153 | ret = ad5398_write_reg(client, data); | ||
154 | |||
155 | return ret; | ||
156 | } | ||
157 | |||
158 | static int ad5398_disable(struct regulator_dev *rdev) | ||
159 | { | ||
160 | struct ad5398_chip_info *chip = rdev_get_drvdata(rdev); | ||
161 | struct i2c_client *client = chip->client; | ||
162 | unsigned short data; | ||
163 | int ret; | ||
164 | |||
165 | ret = ad5398_read_reg(client, &data); | ||
166 | if (ret < 0) | ||
167 | return ret; | ||
168 | |||
169 | if (!(data & AD5398_CURRENT_EN_MASK)) | ||
170 | return 0; | ||
171 | |||
172 | data &= ~AD5398_CURRENT_EN_MASK; | ||
173 | |||
174 | ret = ad5398_write_reg(client, data); | ||
175 | |||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | static struct regulator_ops ad5398_ops = { | ||
180 | .get_current_limit = ad5398_get_current_limit, | ||
181 | .set_current_limit = ad5398_set_current_limit, | ||
182 | .enable = ad5398_enable, | ||
183 | .disable = ad5398_disable, | ||
184 | .is_enabled = ad5398_is_enabled, | ||
185 | }; | ||
186 | |||
187 | static struct regulator_desc ad5398_reg = { | ||
188 | .name = "isink", | ||
189 | .id = 0, | ||
190 | .ops = &ad5398_ops, | ||
191 | .type = REGULATOR_CURRENT, | ||
192 | .owner = THIS_MODULE, | ||
193 | }; | ||
194 | |||
195 | struct ad5398_current_data_format { | ||
196 | int current_bits; | ||
197 | int current_offset; | ||
198 | int min_uA; | ||
199 | int max_uA; | ||
200 | }; | ||
201 | |||
202 | static const struct ad5398_current_data_format df_10_4_120 = {10, 4, 0, 120000}; | ||
203 | |||
204 | static const struct i2c_device_id ad5398_id[] = { | ||
205 | { "ad5398", (kernel_ulong_t)&df_10_4_120 }, | ||
206 | { "ad5821", (kernel_ulong_t)&df_10_4_120 }, | ||
207 | { } | ||
208 | }; | ||
209 | MODULE_DEVICE_TABLE(i2c, ad5398_id); | ||
210 | |||
211 | static int __devinit ad5398_probe(struct i2c_client *client, | ||
212 | const struct i2c_device_id *id) | ||
213 | { | ||
214 | struct regulator_dev *rdev; | ||
215 | struct regulator_init_data *init_data = client->dev.platform_data; | ||
216 | struct ad5398_chip_info *chip; | ||
217 | const struct ad5398_current_data_format *df = | ||
218 | (struct ad5398_current_data_format *)id->driver_data; | ||
219 | int ret; | ||
220 | |||
221 | if (!init_data) | ||
222 | return -EINVAL; | ||
223 | |||
224 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
225 | if (!chip) | ||
226 | return -ENOMEM; | ||
227 | |||
228 | chip->client = client; | ||
229 | |||
230 | chip->min_uA = df->min_uA; | ||
231 | chip->max_uA = df->max_uA; | ||
232 | chip->current_level = 1 << df->current_bits; | ||
233 | chip->current_offset = df->current_offset; | ||
234 | chip->current_mask = (chip->current_level - 1) << chip->current_offset; | ||
235 | |||
236 | rdev = regulator_register(&ad5398_reg, &client->dev, init_data, chip); | ||
237 | if (IS_ERR(rdev)) { | ||
238 | ret = PTR_ERR(rdev); | ||
239 | dev_err(&client->dev, "failed to register %s %s\n", | ||
240 | id->name, ad5398_reg.name); | ||
241 | goto err; | ||
242 | } | ||
243 | |||
244 | i2c_set_clientdata(client, chip); | ||
245 | dev_dbg(&client->dev, "%s regulator driver is registered.\n", id->name); | ||
246 | return 0; | ||
247 | |||
248 | err: | ||
249 | kfree(chip); | ||
250 | return ret; | ||
251 | } | ||
252 | |||
253 | static int __devexit ad5398_remove(struct i2c_client *client) | ||
254 | { | ||
255 | struct ad5398_chip_info *chip = i2c_get_clientdata(client); | ||
256 | |||
257 | regulator_unregister(&chip->rdev); | ||
258 | kfree(chip); | ||
259 | i2c_set_clientdata(client, NULL); | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static struct i2c_driver ad5398_driver = { | ||
265 | .probe = ad5398_probe, | ||
266 | .remove = __devexit_p(ad5398_remove), | ||
267 | .driver = { | ||
268 | .name = "ad5398", | ||
269 | }, | ||
270 | .id_table = ad5398_id, | ||
271 | }; | ||
272 | |||
273 | static int __init ad5398_init(void) | ||
274 | { | ||
275 | return i2c_add_driver(&ad5398_driver); | ||
276 | } | ||
277 | subsys_initcall(ad5398_init); | ||
278 | |||
279 | static void __exit ad5398_exit(void) | ||
280 | { | ||
281 | i2c_del_driver(&ad5398_driver); | ||
282 | } | ||
283 | module_exit(ad5398_exit); | ||
284 | |||
285 | MODULE_DESCRIPTION("AD5398 and AD5821 current regulator driver"); | ||
286 | MODULE_AUTHOR("Sonic Zhang"); | ||
287 | MODULE_LICENSE("GPL"); | ||
288 | MODULE_ALIAS("i2c:ad5398-regulator"); | ||
diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c new file mode 100644 index 000000000000..e49d2bd393f2 --- /dev/null +++ b/drivers/regulator/isl6271a-regulator.c | |||
@@ -0,0 +1,236 @@ | |||
1 | /* | ||
2 | * isl6271a-regulator.c | ||
3 | * | ||
4 | * Support for Intersil ISL6271A voltage regulator | ||
5 | * | ||
6 | * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License as | ||
10 | * published by the Free Software Foundation version 2. | ||
11 | * | ||
12 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, | ||
13 | * whether express or implied; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/err.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/regulator/driver.h> | ||
24 | #include <linux/i2c.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/slab.h> | ||
27 | |||
28 | #define ISL6271A_VOLTAGE_MIN 850000 | ||
29 | #define ISL6271A_VOLTAGE_MAX 1600000 | ||
30 | #define ISL6271A_VOLTAGE_STEP 50000 | ||
31 | |||
32 | /* PMIC details */ | ||
33 | struct isl_pmic { | ||
34 | struct i2c_client *client; | ||
35 | struct regulator_dev *rdev[3]; | ||
36 | struct mutex mtx; | ||
37 | }; | ||
38 | |||
39 | static int isl6271a_get_voltage(struct regulator_dev *dev) | ||
40 | { | ||
41 | struct isl_pmic *pmic = rdev_get_drvdata(dev); | ||
42 | int idx, data; | ||
43 | |||
44 | mutex_lock(&pmic->mtx); | ||
45 | |||
46 | idx = i2c_smbus_read_byte(pmic->client); | ||
47 | if (idx < 0) { | ||
48 | dev_err(&pmic->client->dev, "Error getting voltage\n"); | ||
49 | data = idx; | ||
50 | goto out; | ||
51 | } | ||
52 | |||
53 | /* Convert the data from chip to microvolts */ | ||
54 | data = ISL6271A_VOLTAGE_MIN + (ISL6271A_VOLTAGE_STEP * (idx & 0xf)); | ||
55 | |||
56 | out: | ||
57 | mutex_unlock(&pmic->mtx); | ||
58 | return data; | ||
59 | } | ||
60 | |||
61 | static int isl6271a_set_voltage(struct regulator_dev *dev, int minuV, int maxuV) | ||
62 | { | ||
63 | struct isl_pmic *pmic = rdev_get_drvdata(dev); | ||
64 | int vsel, err, data; | ||
65 | |||
66 | if (minuV < ISL6271A_VOLTAGE_MIN || minuV > ISL6271A_VOLTAGE_MAX) | ||
67 | return -EINVAL; | ||
68 | if (maxuV < ISL6271A_VOLTAGE_MIN || maxuV > ISL6271A_VOLTAGE_MAX) | ||
69 | return -EINVAL; | ||
70 | |||
71 | /* Align to 50000 mV */ | ||
72 | vsel = minuV - (minuV % ISL6271A_VOLTAGE_STEP); | ||
73 | |||
74 | /* If the result fell out of [minuV,maxuV] range, put it back */ | ||
75 | if (vsel < minuV) | ||
76 | vsel += ISL6271A_VOLTAGE_STEP; | ||
77 | |||
78 | /* Convert the microvolts to data for the chip */ | ||
79 | data = (vsel - ISL6271A_VOLTAGE_MIN) / ISL6271A_VOLTAGE_STEP; | ||
80 | |||
81 | mutex_lock(&pmic->mtx); | ||
82 | |||
83 | err = i2c_smbus_write_byte(pmic->client, data); | ||
84 | if (err < 0) | ||
85 | dev_err(&pmic->client->dev, "Error setting voltage\n"); | ||
86 | |||
87 | mutex_unlock(&pmic->mtx); | ||
88 | return err; | ||
89 | } | ||
90 | |||
91 | static int isl6271a_list_voltage(struct regulator_dev *dev, unsigned selector) | ||
92 | { | ||
93 | return ISL6271A_VOLTAGE_MIN + (ISL6271A_VOLTAGE_STEP * selector); | ||
94 | } | ||
95 | |||
96 | static struct regulator_ops isl_core_ops = { | ||
97 | .get_voltage = isl6271a_get_voltage, | ||
98 | .set_voltage = isl6271a_set_voltage, | ||
99 | .list_voltage = isl6271a_list_voltage, | ||
100 | }; | ||
101 | |||
102 | static int isl6271a_get_fixed_voltage(struct regulator_dev *dev) | ||
103 | { | ||
104 | int id = rdev_get_id(dev); | ||
105 | return (id == 1) ? 1100000 : 1300000; | ||
106 | } | ||
107 | |||
108 | static int isl6271a_list_fixed_voltage(struct regulator_dev *dev, unsigned selector) | ||
109 | { | ||
110 | int id = rdev_get_id(dev); | ||
111 | return (id == 1) ? 1100000 : 1300000; | ||
112 | } | ||
113 | |||
114 | static struct regulator_ops isl_fixed_ops = { | ||
115 | .get_voltage = isl6271a_get_fixed_voltage, | ||
116 | .list_voltage = isl6271a_list_fixed_voltage, | ||
117 | }; | ||
118 | |||
119 | static struct regulator_desc isl_rd[] = { | ||
120 | { | ||
121 | .name = "Core Buck", | ||
122 | .id = 0, | ||
123 | .n_voltages = 16, | ||
124 | .ops = &isl_core_ops, | ||
125 | .type = REGULATOR_VOLTAGE, | ||
126 | .owner = THIS_MODULE, | ||
127 | }, { | ||
128 | .name = "LDO1", | ||
129 | .id = 1, | ||
130 | .n_voltages = 1, | ||
131 | .ops = &isl_fixed_ops, | ||
132 | .type = REGULATOR_VOLTAGE, | ||
133 | .owner = THIS_MODULE, | ||
134 | }, { | ||
135 | .name = "LDO2", | ||
136 | .id = 2, | ||
137 | .n_voltages = 1, | ||
138 | .ops = &isl_fixed_ops, | ||
139 | .type = REGULATOR_VOLTAGE, | ||
140 | .owner = THIS_MODULE, | ||
141 | }, | ||
142 | }; | ||
143 | |||
144 | static int __devinit isl6271a_probe(struct i2c_client *i2c, | ||
145 | const struct i2c_device_id *id) | ||
146 | { | ||
147 | struct regulator_init_data *init_data = i2c->dev.platform_data; | ||
148 | struct isl_pmic *pmic; | ||
149 | int err, i; | ||
150 | |||
151 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
152 | return -EIO; | ||
153 | |||
154 | if (!init_data) { | ||
155 | dev_err(&i2c->dev, "no platform data supplied\n"); | ||
156 | return -EIO; | ||
157 | } | ||
158 | |||
159 | pmic = kzalloc(sizeof(struct isl_pmic), GFP_KERNEL); | ||
160 | if (!pmic) | ||
161 | return -ENOMEM; | ||
162 | |||
163 | pmic->client = i2c; | ||
164 | |||
165 | mutex_init(&pmic->mtx); | ||
166 | |||
167 | for (i = 0; i < 3; i++) { | ||
168 | pmic->rdev[i] = regulator_register(&isl_rd[0], &i2c->dev, | ||
169 | init_data, pmic); | ||
170 | if (IS_ERR(pmic->rdev[i])) { | ||
171 | dev_err(&i2c->dev, "failed to register %s\n", id->name); | ||
172 | err = PTR_ERR(pmic->rdev); | ||
173 | goto error; | ||
174 | } | ||
175 | } | ||
176 | |||
177 | i2c_set_clientdata(i2c, pmic); | ||
178 | |||
179 | return 0; | ||
180 | |||
181 | error: | ||
182 | while (--i >= 0) | ||
183 | regulator_unregister(pmic->rdev[i]); | ||
184 | |||
185 | kfree(pmic); | ||
186 | return err; | ||
187 | } | ||
188 | |||
189 | static int __devexit isl6271a_remove(struct i2c_client *i2c) | ||
190 | { | ||
191 | struct isl_pmic *pmic = i2c_get_clientdata(i2c); | ||
192 | int i; | ||
193 | |||
194 | i2c_set_clientdata(i2c, NULL); | ||
195 | |||
196 | for (i = 0; i < 3; i++) | ||
197 | regulator_unregister(pmic->rdev[i]); | ||
198 | |||
199 | kfree(pmic); | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static const struct i2c_device_id isl6271a_id[] = { | ||
205 | {.name = "isl6271a", 0 }, | ||
206 | { }, | ||
207 | }; | ||
208 | |||
209 | MODULE_DEVICE_TABLE(i2c, isl6271a_id); | ||
210 | |||
211 | static struct i2c_driver isl6271a_i2c_driver = { | ||
212 | .driver = { | ||
213 | .name = "isl6271a", | ||
214 | .owner = THIS_MODULE, | ||
215 | }, | ||
216 | .probe = isl6271a_probe, | ||
217 | .remove = __devexit_p(isl6271a_remove), | ||
218 | .id_table = isl6271a_id, | ||
219 | }; | ||
220 | |||
221 | static int __init isl6271a_init(void) | ||
222 | { | ||
223 | return i2c_add_driver(&isl6271a_i2c_driver); | ||
224 | } | ||
225 | |||
226 | static void __exit isl6271a_cleanup(void) | ||
227 | { | ||
228 | i2c_del_driver(&isl6271a_i2c_driver); | ||
229 | } | ||
230 | |||
231 | subsys_initcall(isl6271a_init); | ||
232 | module_exit(isl6271a_cleanup); | ||
233 | |||
234 | MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); | ||
235 | MODULE_DESCRIPTION("Intersil ISL6271A voltage regulator driver"); | ||
236 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 8ae3732eb24b..3bb82b624e19 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c | |||
@@ -377,7 +377,7 @@ static int lp3971_i2c_read(struct i2c_client *i2c, char reg, int count, | |||
377 | if (count != 1) | 377 | if (count != 1) |
378 | return -EIO; | 378 | return -EIO; |
379 | ret = i2c_smbus_read_byte_data(i2c, reg); | 379 | ret = i2c_smbus_read_byte_data(i2c, reg); |
380 | if (ret < 0 || count != 1) | 380 | if (ret < 0) |
381 | return -EIO; | 381 | return -EIO; |
382 | 382 | ||
383 | *dest = ret; | 383 | *dest = ret; |
@@ -387,15 +387,9 @@ static int lp3971_i2c_read(struct i2c_client *i2c, char reg, int count, | |||
387 | static int lp3971_i2c_write(struct i2c_client *i2c, char reg, int count, | 387 | static int lp3971_i2c_write(struct i2c_client *i2c, char reg, int count, |
388 | const u16 *src) | 388 | const u16 *src) |
389 | { | 389 | { |
390 | int ret; | ||
391 | |||
392 | if (count != 1) | 390 | if (count != 1) |
393 | return -EIO; | 391 | return -EIO; |
394 | ret = i2c_smbus_write_byte_data(i2c, reg, *src); | 392 | return i2c_smbus_write_byte_data(i2c, reg, *src); |
395 | if (ret >= 0) | ||
396 | return 0; | ||
397 | |||
398 | return ret; | ||
399 | } | 393 | } |
400 | 394 | ||
401 | static u8 lp3971_reg_read(struct lp3971 *lp3971, u8 reg) | 395 | static u8 lp3971_reg_read(struct lp3971 *lp3971, u8 reg) |
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index 2b54d9d75f11..8867c2710a6d 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c | |||
@@ -223,7 +223,7 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client, | |||
223 | } | 223 | } |
224 | } | 224 | } |
225 | 225 | ||
226 | i2c_set_clientdata(client, rdev); | 226 | i2c_set_clientdata(client, max1586); |
227 | dev_info(&client->dev, "Maxim 1586 regulator driver loaded\n"); | 227 | dev_info(&client->dev, "Maxim 1586 regulator driver loaded\n"); |
228 | return 0; | 228 | return 0; |
229 | 229 | ||
@@ -238,13 +238,13 @@ out: | |||
238 | 238 | ||
239 | static int __devexit max1586_pmic_remove(struct i2c_client *client) | 239 | static int __devexit max1586_pmic_remove(struct i2c_client *client) |
240 | { | 240 | { |
241 | struct regulator_dev **rdev = i2c_get_clientdata(client); | 241 | struct max1586_data *max1586 = i2c_get_clientdata(client); |
242 | int i; | 242 | int i; |
243 | 243 | ||
244 | for (i = 0; i <= MAX1586_V6; i++) | 244 | for (i = 0; i <= MAX1586_V6; i++) |
245 | if (rdev[i]) | 245 | if (max1586->rdev[i]) |
246 | regulator_unregister(rdev[i]); | 246 | regulator_unregister(max1586->rdev[i]); |
247 | kfree(rdev); | 247 | kfree(max1586); |
248 | 248 | ||
249 | return 0; | 249 | return 0; |
250 | } | 250 | } |
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index d97220efae5a..c570e6eb0db2 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c | |||
@@ -450,7 +450,7 @@ static int __devinit max8660_probe(struct i2c_client *client, | |||
450 | } | 450 | } |
451 | } | 451 | } |
452 | 452 | ||
453 | i2c_set_clientdata(client, rdev); | 453 | i2c_set_clientdata(client, max8660); |
454 | dev_info(&client->dev, "Maxim 8660/8661 regulator driver loaded\n"); | 454 | dev_info(&client->dev, "Maxim 8660/8661 regulator driver loaded\n"); |
455 | return 0; | 455 | return 0; |
456 | 456 | ||
@@ -465,13 +465,13 @@ out: | |||
465 | 465 | ||
466 | static int __devexit max8660_remove(struct i2c_client *client) | 466 | static int __devexit max8660_remove(struct i2c_client *client) |
467 | { | 467 | { |
468 | struct regulator_dev **rdev = i2c_get_clientdata(client); | 468 | struct max8660 *max8660 = i2c_get_clientdata(client); |
469 | int i; | 469 | int i; |
470 | 470 | ||
471 | for (i = 0; i < MAX8660_V_END; i++) | 471 | for (i = 0; i < MAX8660_V_END; i++) |
472 | if (rdev[i]) | 472 | if (max8660->rdev[i]) |
473 | regulator_unregister(rdev[i]); | 473 | regulator_unregister(max8660->rdev[i]); |
474 | kfree(rdev); | 474 | kfree(max8660); |
475 | 475 | ||
476 | return 0; | 476 | return 0; |
477 | } | 477 | } |
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c new file mode 100644 index 000000000000..ab67298799f9 --- /dev/null +++ b/drivers/regulator/max8998.c | |||
@@ -0,0 +1,635 @@ | |||
1 | /* | ||
2 | * max8998.c - Voltage regulator driver for the Maxim 8998 | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Samsung Electronics | ||
5 | * Kyungmin Park <kyungmin.park@samsung.com> | ||
6 | * Marek Szyprowski <m.szyprowski@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/i2c.h> | ||
26 | #include <linux/err.h> | ||
27 | #include <linux/gpio.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/mutex.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/platform_device.h> | ||
33 | #include <linux/regulator/driver.h> | ||
34 | #include <linux/mfd/max8998.h> | ||
35 | #include <linux/mfd/max8998-private.h> | ||
36 | |||
37 | struct max8998_data { | ||
38 | struct device *dev; | ||
39 | struct max8998_dev *iodev; | ||
40 | int num_regulators; | ||
41 | struct regulator_dev **rdev; | ||
42 | }; | ||
43 | |||
44 | struct voltage_map_desc { | ||
45 | int min; | ||
46 | int max; | ||
47 | int step; | ||
48 | }; | ||
49 | |||
50 | /* Voltage maps */ | ||
51 | static const struct voltage_map_desc ldo23_voltage_map_desc = { | ||
52 | .min = 800, .step = 50, .max = 1300, | ||
53 | }; | ||
54 | static const struct voltage_map_desc ldo456711_voltage_map_desc = { | ||
55 | .min = 1600, .step = 100, .max = 3600, | ||
56 | }; | ||
57 | static const struct voltage_map_desc ldo8_voltage_map_desc = { | ||
58 | .min = 3000, .step = 100, .max = 3600, | ||
59 | }; | ||
60 | static const struct voltage_map_desc ldo9_voltage_map_desc = { | ||
61 | .min = 2800, .step = 100, .max = 3100, | ||
62 | }; | ||
63 | static const struct voltage_map_desc ldo10_voltage_map_desc = { | ||
64 | .min = 950, .step = 50, .max = 1300, | ||
65 | }; | ||
66 | static const struct voltage_map_desc ldo1213_voltage_map_desc = { | ||
67 | .min = 800, .step = 100, .max = 3300, | ||
68 | }; | ||
69 | static const struct voltage_map_desc ldo1415_voltage_map_desc = { | ||
70 | .min = 1200, .step = 100, .max = 3300, | ||
71 | }; | ||
72 | static const struct voltage_map_desc ldo1617_voltage_map_desc = { | ||
73 | .min = 1600, .step = 100, .max = 3600, | ||
74 | }; | ||
75 | static const struct voltage_map_desc buck12_voltage_map_desc = { | ||
76 | .min = 750, .step = 25, .max = 1525, | ||
77 | }; | ||
78 | static const struct voltage_map_desc buck3_voltage_map_desc = { | ||
79 | .min = 1600, .step = 100, .max = 3600, | ||
80 | }; | ||
81 | static const struct voltage_map_desc buck4_voltage_map_desc = { | ||
82 | .min = 800, .step = 100, .max = 2300, | ||
83 | }; | ||
84 | |||
85 | static const struct voltage_map_desc *ldo_voltage_map[] = { | ||
86 | NULL, | ||
87 | NULL, | ||
88 | &ldo23_voltage_map_desc, /* LDO2 */ | ||
89 | &ldo23_voltage_map_desc, /* LDO3 */ | ||
90 | &ldo456711_voltage_map_desc, /* LDO4 */ | ||
91 | &ldo456711_voltage_map_desc, /* LDO5 */ | ||
92 | &ldo456711_voltage_map_desc, /* LDO6 */ | ||
93 | &ldo456711_voltage_map_desc, /* LDO7 */ | ||
94 | &ldo8_voltage_map_desc, /* LDO8 */ | ||
95 | &ldo9_voltage_map_desc, /* LDO9 */ | ||
96 | &ldo10_voltage_map_desc, /* LDO10 */ | ||
97 | &ldo456711_voltage_map_desc, /* LDO11 */ | ||
98 | &ldo1213_voltage_map_desc, /* LDO12 */ | ||
99 | &ldo1213_voltage_map_desc, /* LDO13 */ | ||
100 | &ldo1415_voltage_map_desc, /* LDO14 */ | ||
101 | &ldo1415_voltage_map_desc, /* LDO15 */ | ||
102 | &ldo1617_voltage_map_desc, /* LDO16 */ | ||
103 | &ldo1617_voltage_map_desc, /* LDO17 */ | ||
104 | &buck12_voltage_map_desc, /* BUCK1 */ | ||
105 | &buck12_voltage_map_desc, /* BUCK2 */ | ||
106 | &buck3_voltage_map_desc, /* BUCK3 */ | ||
107 | &buck4_voltage_map_desc, /* BUCK4 */ | ||
108 | }; | ||
109 | |||
110 | static inline int max8998_get_ldo(struct regulator_dev *rdev) | ||
111 | { | ||
112 | return rdev_get_id(rdev); | ||
113 | } | ||
114 | |||
115 | static int max8998_list_voltage(struct regulator_dev *rdev, | ||
116 | unsigned int selector) | ||
117 | { | ||
118 | const struct voltage_map_desc *desc; | ||
119 | int ldo = max8998_get_ldo(rdev); | ||
120 | int val; | ||
121 | |||
122 | if (ldo >= ARRAY_SIZE(ldo_voltage_map)) | ||
123 | return -EINVAL; | ||
124 | |||
125 | desc = ldo_voltage_map[ldo]; | ||
126 | if (desc == NULL) | ||
127 | return -EINVAL; | ||
128 | |||
129 | val = desc->min + desc->step * selector; | ||
130 | if (val > desc->max) | ||
131 | return -EINVAL; | ||
132 | |||
133 | return val * 1000; | ||
134 | } | ||
135 | |||
136 | static int max8998_get_enable_register(struct regulator_dev *rdev, | ||
137 | int *reg, int *shift) | ||
138 | { | ||
139 | int ldo = max8998_get_ldo(rdev); | ||
140 | |||
141 | switch (ldo) { | ||
142 | case MAX8998_LDO2 ... MAX8998_LDO5: | ||
143 | *reg = MAX8998_REG_ONOFF1; | ||
144 | *shift = 3 - (ldo - MAX8998_LDO2); | ||
145 | break; | ||
146 | case MAX8998_LDO6 ... MAX8998_LDO13: | ||
147 | *reg = MAX8998_REG_ONOFF2; | ||
148 | *shift = 7 - (ldo - MAX8998_LDO6); | ||
149 | break; | ||
150 | case MAX8998_LDO14 ... MAX8998_LDO17: | ||
151 | *reg = MAX8998_REG_ONOFF3; | ||
152 | *shift = 7 - (ldo - MAX8998_LDO14); | ||
153 | break; | ||
154 | case MAX8998_BUCK1 ... MAX8998_BUCK4: | ||
155 | *reg = MAX8998_REG_ONOFF1; | ||
156 | *shift = 7 - (ldo - MAX8998_BUCK1); | ||
157 | break; | ||
158 | case MAX8998_EN32KHZ_AP ... MAX8998_ENVICHG: | ||
159 | *reg = MAX8998_REG_ONOFF4; | ||
160 | *shift = 7 - (ldo - MAX8998_EN32KHZ_AP); | ||
161 | break; | ||
162 | case MAX8998_ESAFEOUT1 ... MAX8998_ESAFEOUT2: | ||
163 | *reg = MAX8998_REG_CHGR2; | ||
164 | *shift = 7 - (ldo - MAX8998_ESAFEOUT1); | ||
165 | break; | ||
166 | default: | ||
167 | return -EINVAL; | ||
168 | } | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static int max8998_ldo_is_enabled(struct regulator_dev *rdev) | ||
174 | { | ||
175 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); | ||
176 | int ret, reg, shift = 8; | ||
177 | u8 val; | ||
178 | |||
179 | ret = max8998_get_enable_register(rdev, ®, &shift); | ||
180 | if (ret) | ||
181 | return ret; | ||
182 | |||
183 | ret = max8998_read_reg(max8998->iodev, reg, &val); | ||
184 | if (ret) | ||
185 | return ret; | ||
186 | |||
187 | return val & (1 << shift); | ||
188 | } | ||
189 | |||
190 | static int max8998_ldo_enable(struct regulator_dev *rdev) | ||
191 | { | ||
192 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); | ||
193 | int reg, shift = 8, ret; | ||
194 | |||
195 | ret = max8998_get_enable_register(rdev, ®, &shift); | ||
196 | if (ret) | ||
197 | return ret; | ||
198 | |||
199 | return max8998_update_reg(max8998->iodev, reg, 1<<shift, 1<<shift); | ||
200 | } | ||
201 | |||
202 | static int max8998_ldo_disable(struct regulator_dev *rdev) | ||
203 | { | ||
204 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); | ||
205 | int reg, shift = 8, ret; | ||
206 | |||
207 | ret = max8998_get_enable_register(rdev, ®, &shift); | ||
208 | if (ret) | ||
209 | return ret; | ||
210 | |||
211 | return max8998_update_reg(max8998->iodev, reg, 0, 1<<shift); | ||
212 | } | ||
213 | |||
214 | static int max8998_get_voltage_register(struct regulator_dev *rdev, | ||
215 | int *_reg, int *_shift, int *_mask) | ||
216 | { | ||
217 | int ldo = max8998_get_ldo(rdev); | ||
218 | int reg, shift = 0, mask = 0xff; | ||
219 | |||
220 | switch (ldo) { | ||
221 | case MAX8998_LDO2 ... MAX8998_LDO3: | ||
222 | reg = MAX8998_REG_LDO2_LDO3; | ||
223 | mask = 0xf; | ||
224 | if (ldo == MAX8998_LDO2) | ||
225 | shift = 4; | ||
226 | else | ||
227 | shift = 0; | ||
228 | break; | ||
229 | case MAX8998_LDO4 ... MAX8998_LDO7: | ||
230 | reg = MAX8998_REG_LDO4 + (ldo - MAX8998_LDO4); | ||
231 | break; | ||
232 | case MAX8998_LDO8 ... MAX8998_LDO9: | ||
233 | reg = MAX8998_REG_LDO8_LDO9; | ||
234 | mask = 0xf; | ||
235 | if (ldo == MAX8998_LDO8) | ||
236 | shift = 4; | ||
237 | else | ||
238 | shift = 0; | ||
239 | break; | ||
240 | case MAX8998_LDO10 ... MAX8998_LDO11: | ||
241 | reg = MAX8998_REG_LDO10_LDO11; | ||
242 | if (ldo == MAX8998_LDO10) { | ||
243 | shift = 5; | ||
244 | mask = 0x7; | ||
245 | } else { | ||
246 | shift = 0; | ||
247 | mask = 0x1f; | ||
248 | } | ||
249 | break; | ||
250 | case MAX8998_LDO12 ... MAX8998_LDO17: | ||
251 | reg = MAX8998_REG_LDO12 + (ldo - MAX8998_LDO12); | ||
252 | break; | ||
253 | case MAX8998_BUCK1: | ||
254 | reg = MAX8998_REG_BUCK1_DVSARM1; | ||
255 | break; | ||
256 | case MAX8998_BUCK2: | ||
257 | reg = MAX8998_REG_BUCK2_DVSINT1; | ||
258 | break; | ||
259 | case MAX8998_BUCK3: | ||
260 | reg = MAX8998_REG_BUCK3; | ||
261 | break; | ||
262 | case MAX8998_BUCK4: | ||
263 | reg = MAX8998_REG_BUCK4; | ||
264 | break; | ||
265 | default: | ||
266 | return -EINVAL; | ||
267 | } | ||
268 | |||
269 | *_reg = reg; | ||
270 | *_shift = shift; | ||
271 | *_mask = mask; | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static int max8998_get_voltage(struct regulator_dev *rdev) | ||
277 | { | ||
278 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); | ||
279 | int reg, shift = 0, mask, ret; | ||
280 | u8 val; | ||
281 | |||
282 | ret = max8998_get_voltage_register(rdev, ®, &shift, &mask); | ||
283 | if (ret) | ||
284 | return ret; | ||
285 | |||
286 | ret = max8998_read_reg(max8998->iodev, reg, &val); | ||
287 | if (ret) | ||
288 | return ret; | ||
289 | |||
290 | val >>= shift; | ||
291 | val &= mask; | ||
292 | |||
293 | return max8998_list_voltage(rdev, val); | ||
294 | } | ||
295 | |||
296 | static int max8998_set_voltage(struct regulator_dev *rdev, | ||
297 | int min_uV, int max_uV) | ||
298 | { | ||
299 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); | ||
300 | int min_vol = min_uV / 1000, max_vol = max_uV / 1000; | ||
301 | int previous_vol = 0; | ||
302 | const struct voltage_map_desc *desc; | ||
303 | int ldo = max8998_get_ldo(rdev); | ||
304 | int reg, shift = 0, mask, ret; | ||
305 | int i = 0; | ||
306 | u8 val; | ||
307 | bool en_ramp = false; | ||
308 | |||
309 | if (ldo >= ARRAY_SIZE(ldo_voltage_map)) | ||
310 | return -EINVAL; | ||
311 | |||
312 | desc = ldo_voltage_map[ldo]; | ||
313 | if (desc == NULL) | ||
314 | return -EINVAL; | ||
315 | |||
316 | if (max_vol < desc->min || min_vol > desc->max) | ||
317 | return -EINVAL; | ||
318 | |||
319 | while (desc->min + desc->step*i < min_vol && | ||
320 | desc->min + desc->step*i < desc->max) | ||
321 | i++; | ||
322 | |||
323 | if (desc->min + desc->step*i > max_vol) | ||
324 | return -EINVAL; | ||
325 | |||
326 | ret = max8998_get_voltage_register(rdev, ®, &shift, &mask); | ||
327 | if (ret) | ||
328 | return ret; | ||
329 | |||
330 | /* wait for RAMP_UP_DELAY if rdev is BUCK1/2 and | ||
331 | * ENRAMP is ON */ | ||
332 | if (ldo == MAX8998_BUCK1 || ldo == MAX8998_BUCK2) { | ||
333 | max8998_read_reg(max8998->iodev, MAX8998_REG_ONOFF4, &val); | ||
334 | if (val & (1 << 4)) { | ||
335 | en_ramp = true; | ||
336 | previous_vol = max8998_get_voltage(rdev); | ||
337 | } | ||
338 | } | ||
339 | |||
340 | ret = max8998_update_reg(max8998->iodev, reg, i<<shift, mask<<shift); | ||
341 | |||
342 | if (en_ramp == true) { | ||
343 | int difference = desc->min + desc->step*i - previous_vol/1000; | ||
344 | if (difference > 0) | ||
345 | udelay(difference / ((val & 0x0f) + 1)); | ||
346 | } | ||
347 | |||
348 | return ret; | ||
349 | } | ||
350 | |||
351 | static struct regulator_ops max8998_ldo_ops = { | ||
352 | .list_voltage = max8998_list_voltage, | ||
353 | .is_enabled = max8998_ldo_is_enabled, | ||
354 | .enable = max8998_ldo_enable, | ||
355 | .disable = max8998_ldo_disable, | ||
356 | .get_voltage = max8998_get_voltage, | ||
357 | .set_voltage = max8998_set_voltage, | ||
358 | .set_suspend_enable = max8998_ldo_enable, | ||
359 | .set_suspend_disable = max8998_ldo_disable, | ||
360 | }; | ||
361 | |||
362 | static struct regulator_ops max8998_buck_ops = { | ||
363 | .list_voltage = max8998_list_voltage, | ||
364 | .is_enabled = max8998_ldo_is_enabled, | ||
365 | .enable = max8998_ldo_enable, | ||
366 | .disable = max8998_ldo_disable, | ||
367 | .get_voltage = max8998_get_voltage, | ||
368 | .set_voltage = max8998_set_voltage, | ||
369 | .set_suspend_enable = max8998_ldo_enable, | ||
370 | .set_suspend_disable = max8998_ldo_disable, | ||
371 | }; | ||
372 | |||
373 | static struct regulator_ops max8998_others_ops = { | ||
374 | .is_enabled = max8998_ldo_is_enabled, | ||
375 | .enable = max8998_ldo_enable, | ||
376 | .disable = max8998_ldo_disable, | ||
377 | .set_suspend_enable = max8998_ldo_enable, | ||
378 | .set_suspend_disable = max8998_ldo_disable, | ||
379 | }; | ||
380 | |||
381 | static struct regulator_desc regulators[] = { | ||
382 | { | ||
383 | .name = "LDO2", | ||
384 | .id = MAX8998_LDO2, | ||
385 | .ops = &max8998_ldo_ops, | ||
386 | .type = REGULATOR_VOLTAGE, | ||
387 | .owner = THIS_MODULE, | ||
388 | }, { | ||
389 | .name = "LDO3", | ||
390 | .id = MAX8998_LDO3, | ||
391 | .ops = &max8998_ldo_ops, | ||
392 | .type = REGULATOR_VOLTAGE, | ||
393 | .owner = THIS_MODULE, | ||
394 | }, { | ||
395 | .name = "LDO4", | ||
396 | .id = MAX8998_LDO4, | ||
397 | .ops = &max8998_ldo_ops, | ||
398 | .type = REGULATOR_VOLTAGE, | ||
399 | .owner = THIS_MODULE, | ||
400 | }, { | ||
401 | .name = "LDO5", | ||
402 | .id = MAX8998_LDO5, | ||
403 | .ops = &max8998_ldo_ops, | ||
404 | .type = REGULATOR_VOLTAGE, | ||
405 | .owner = THIS_MODULE, | ||
406 | }, { | ||
407 | .name = "LDO6", | ||
408 | .id = MAX8998_LDO6, | ||
409 | .ops = &max8998_ldo_ops, | ||
410 | .type = REGULATOR_VOLTAGE, | ||
411 | .owner = THIS_MODULE, | ||
412 | }, { | ||
413 | .name = "LDO7", | ||
414 | .id = MAX8998_LDO7, | ||
415 | .ops = &max8998_ldo_ops, | ||
416 | .type = REGULATOR_VOLTAGE, | ||
417 | .owner = THIS_MODULE, | ||
418 | }, { | ||
419 | .name = "LDO8", | ||
420 | .id = MAX8998_LDO8, | ||
421 | .ops = &max8998_ldo_ops, | ||
422 | .type = REGULATOR_VOLTAGE, | ||
423 | .owner = THIS_MODULE, | ||
424 | }, { | ||
425 | .name = "LDO9", | ||
426 | .id = MAX8998_LDO9, | ||
427 | .ops = &max8998_ldo_ops, | ||
428 | .type = REGULATOR_VOLTAGE, | ||
429 | .owner = THIS_MODULE, | ||
430 | }, { | ||
431 | .name = "LDO10", | ||
432 | .id = MAX8998_LDO10, | ||
433 | .ops = &max8998_ldo_ops, | ||
434 | .type = REGULATOR_VOLTAGE, | ||
435 | .owner = THIS_MODULE, | ||
436 | }, { | ||
437 | .name = "LDO11", | ||
438 | .id = MAX8998_LDO11, | ||
439 | .ops = &max8998_ldo_ops, | ||
440 | .type = REGULATOR_VOLTAGE, | ||
441 | .owner = THIS_MODULE, | ||
442 | }, { | ||
443 | .name = "LDO12", | ||
444 | .id = MAX8998_LDO12, | ||
445 | .ops = &max8998_ldo_ops, | ||
446 | .type = REGULATOR_VOLTAGE, | ||
447 | .owner = THIS_MODULE, | ||
448 | }, { | ||
449 | .name = "LDO13", | ||
450 | .id = MAX8998_LDO13, | ||
451 | .ops = &max8998_ldo_ops, | ||
452 | .type = REGULATOR_VOLTAGE, | ||
453 | .owner = THIS_MODULE, | ||
454 | }, { | ||
455 | .name = "LDO14", | ||
456 | .id = MAX8998_LDO14, | ||
457 | .ops = &max8998_ldo_ops, | ||
458 | .type = REGULATOR_VOLTAGE, | ||
459 | .owner = THIS_MODULE, | ||
460 | }, { | ||
461 | .name = "LDO15", | ||
462 | .id = MAX8998_LDO15, | ||
463 | .ops = &max8998_ldo_ops, | ||
464 | .type = REGULATOR_VOLTAGE, | ||
465 | .owner = THIS_MODULE, | ||
466 | }, { | ||
467 | .name = "LDO16", | ||
468 | .id = MAX8998_LDO16, | ||
469 | .ops = &max8998_ldo_ops, | ||
470 | .type = REGULATOR_VOLTAGE, | ||
471 | .owner = THIS_MODULE, | ||
472 | }, { | ||
473 | .name = "LDO17", | ||
474 | .id = MAX8998_LDO17, | ||
475 | .ops = &max8998_ldo_ops, | ||
476 | .type = REGULATOR_VOLTAGE, | ||
477 | .owner = THIS_MODULE, | ||
478 | }, { | ||
479 | .name = "BUCK1", | ||
480 | .id = MAX8998_BUCK1, | ||
481 | .ops = &max8998_buck_ops, | ||
482 | .type = REGULATOR_VOLTAGE, | ||
483 | .owner = THIS_MODULE, | ||
484 | }, { | ||
485 | .name = "BUCK2", | ||
486 | .id = MAX8998_BUCK2, | ||
487 | .ops = &max8998_buck_ops, | ||
488 | .type = REGULATOR_VOLTAGE, | ||
489 | .owner = THIS_MODULE, | ||
490 | }, { | ||
491 | .name = "BUCK3", | ||
492 | .id = MAX8998_BUCK3, | ||
493 | .ops = &max8998_buck_ops, | ||
494 | .type = REGULATOR_VOLTAGE, | ||
495 | .owner = THIS_MODULE, | ||
496 | }, { | ||
497 | .name = "BUCK4", | ||
498 | .id = MAX8998_BUCK4, | ||
499 | .ops = &max8998_buck_ops, | ||
500 | .type = REGULATOR_VOLTAGE, | ||
501 | .owner = THIS_MODULE, | ||
502 | }, { | ||
503 | .name = "EN32KHz AP", | ||
504 | .id = MAX8998_EN32KHZ_AP, | ||
505 | .ops = &max8998_others_ops, | ||
506 | .type = REGULATOR_VOLTAGE, | ||
507 | .owner = THIS_MODULE, | ||
508 | }, { | ||
509 | .name = "EN32KHz CP", | ||
510 | .id = MAX8998_EN32KHZ_CP, | ||
511 | .ops = &max8998_others_ops, | ||
512 | .type = REGULATOR_VOLTAGE, | ||
513 | .owner = THIS_MODULE, | ||
514 | }, { | ||
515 | .name = "ENVICHG", | ||
516 | .id = MAX8998_ENVICHG, | ||
517 | .ops = &max8998_others_ops, | ||
518 | .type = REGULATOR_VOLTAGE, | ||
519 | .owner = THIS_MODULE, | ||
520 | }, { | ||
521 | .name = "ESAFEOUT1", | ||
522 | .id = MAX8998_ESAFEOUT1, | ||
523 | .ops = &max8998_others_ops, | ||
524 | .type = REGULATOR_VOLTAGE, | ||
525 | .owner = THIS_MODULE, | ||
526 | }, { | ||
527 | .name = "ESAFEOUT2", | ||
528 | .id = MAX8998_ESAFEOUT2, | ||
529 | .ops = &max8998_others_ops, | ||
530 | .type = REGULATOR_VOLTAGE, | ||
531 | .owner = THIS_MODULE, | ||
532 | } | ||
533 | }; | ||
534 | |||
535 | static __devinit int max8998_pmic_probe(struct platform_device *pdev) | ||
536 | { | ||
537 | struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent); | ||
538 | struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev); | ||
539 | struct regulator_dev **rdev; | ||
540 | struct max8998_data *max8998; | ||
541 | int i, ret, size; | ||
542 | |||
543 | if (!pdata) { | ||
544 | dev_err(pdev->dev.parent, "No platform init data supplied\n"); | ||
545 | return -ENODEV; | ||
546 | } | ||
547 | |||
548 | max8998 = kzalloc(sizeof(struct max8998_data), GFP_KERNEL); | ||
549 | if (!max8998) | ||
550 | return -ENOMEM; | ||
551 | |||
552 | size = sizeof(struct regulator_dev *) * (pdata->num_regulators + 1); | ||
553 | max8998->rdev = kzalloc(size, GFP_KERNEL); | ||
554 | if (!max8998->rdev) { | ||
555 | kfree(max8998); | ||
556 | return -ENOMEM; | ||
557 | } | ||
558 | |||
559 | rdev = max8998->rdev; | ||
560 | max8998->iodev = iodev; | ||
561 | platform_set_drvdata(pdev, max8998); | ||
562 | |||
563 | for (i = 0; i < pdata->num_regulators; i++) { | ||
564 | const struct voltage_map_desc *desc; | ||
565 | int id = pdata->regulators[i].id; | ||
566 | int index = id - MAX8998_LDO2; | ||
567 | |||
568 | desc = ldo_voltage_map[id]; | ||
569 | if (desc && regulators[index].ops != &max8998_others_ops) { | ||
570 | int count = (desc->max - desc->min) / desc->step + 1; | ||
571 | regulators[index].n_voltages = count; | ||
572 | } | ||
573 | rdev[i] = regulator_register(®ulators[index], max8998->dev, | ||
574 | pdata->regulators[i].initdata, max8998); | ||
575 | if (IS_ERR(rdev[i])) { | ||
576 | ret = PTR_ERR(rdev[i]); | ||
577 | dev_err(max8998->dev, "regulator init failed\n"); | ||
578 | rdev[i] = NULL; | ||
579 | goto err; | ||
580 | } | ||
581 | } | ||
582 | |||
583 | |||
584 | return 0; | ||
585 | err: | ||
586 | for (i = 0; i <= max8998->num_regulators; i++) | ||
587 | if (rdev[i]) | ||
588 | regulator_unregister(rdev[i]); | ||
589 | |||
590 | kfree(max8998->rdev); | ||
591 | kfree(max8998); | ||
592 | |||
593 | return ret; | ||
594 | } | ||
595 | |||
596 | static int __devexit max8998_pmic_remove(struct platform_device *pdev) | ||
597 | { | ||
598 | struct max8998_data *max8998 = platform_get_drvdata(pdev); | ||
599 | struct regulator_dev **rdev = max8998->rdev; | ||
600 | int i; | ||
601 | |||
602 | for (i = 0; i <= max8998->num_regulators; i++) | ||
603 | if (rdev[i]) | ||
604 | regulator_unregister(rdev[i]); | ||
605 | |||
606 | kfree(max8998->rdev); | ||
607 | kfree(max8998); | ||
608 | |||
609 | return 0; | ||
610 | } | ||
611 | |||
612 | static struct platform_driver max8998_pmic_driver = { | ||
613 | .driver = { | ||
614 | .name = "max8998-pmic", | ||
615 | .owner = THIS_MODULE, | ||
616 | }, | ||
617 | .probe = max8998_pmic_probe, | ||
618 | .remove = __devexit_p(max8998_pmic_remove), | ||
619 | }; | ||
620 | |||
621 | static int __init max8998_pmic_init(void) | ||
622 | { | ||
623 | return platform_driver_register(&max8998_pmic_driver); | ||
624 | } | ||
625 | subsys_initcall(max8998_pmic_init); | ||
626 | |||
627 | static void __exit max8998_pmic_cleanup(void) | ||
628 | { | ||
629 | platform_driver_unregister(&max8998_pmic_driver); | ||
630 | } | ||
631 | module_exit(max8998_pmic_cleanup); | ||
632 | |||
633 | MODULE_DESCRIPTION("MAXIM 8998 voltage regulator driver"); | ||
634 | MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>"); | ||
635 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index f50afc9f287a..cd6d4fc9d74f 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c | |||
@@ -585,6 +585,8 @@ static const struct tps_info tps65023_regs[] = { | |||
585 | static const struct i2c_device_id tps_65023_id[] = { | 585 | static const struct i2c_device_id tps_65023_id[] = { |
586 | {.name = "tps65023", | 586 | {.name = "tps65023", |
587 | .driver_data = (unsigned long) tps65023_regs,}, | 587 | .driver_data = (unsigned long) tps65023_regs,}, |
588 | {.name = "tps65021", | ||
589 | .driver_data = (unsigned long) tps65023_regs,}, | ||
588 | { }, | 590 | { }, |
589 | }; | 591 | }; |
590 | 592 | ||
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index 8152d65220f5..c239f42aa4a3 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c | |||
@@ -614,6 +614,7 @@ int tps6507x_pmic_probe(struct platform_device *pdev) | |||
614 | } | 614 | } |
615 | 615 | ||
616 | tps6507x_dev->pmic = tps; | 616 | tps6507x_dev->pmic = tps; |
617 | platform_set_drvdata(pdev, tps6507x_dev); | ||
617 | 618 | ||
618 | return 0; | 619 | return 0; |
619 | 620 | ||
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c new file mode 100644 index 000000000000..8cff1413a147 --- /dev/null +++ b/drivers/regulator/tps6586x-regulator.c | |||
@@ -0,0 +1,396 @@ | |||
1 | /* | ||
2 | * Regulator driver for TI TPS6586x | ||
3 | * | ||
4 | * Copyright (C) 2010 Compulab Ltd. | ||
5 | * Author: Mike Rapoport <mike@compulab.co.il> | ||
6 | * | ||
7 | * Based on da903x | ||
8 | * Copyright (C) 2006-2008 Marvell International Ltd. | ||
9 | * Copyright (C) 2008 Compulab Ltd. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/err.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/regulator/driver.h> | ||
22 | #include <linux/regulator/machine.h> | ||
23 | #include <linux/mfd/tps6586x.h> | ||
24 | |||
25 | /* supply control and voltage setting */ | ||
26 | #define TPS6586X_SUPPLYENA 0x10 | ||
27 | #define TPS6586X_SUPPLYENB 0x11 | ||
28 | #define TPS6586X_SUPPLYENC 0x12 | ||
29 | #define TPS6586X_SUPPLYEND 0x13 | ||
30 | #define TPS6586X_SUPPLYENE 0x14 | ||
31 | #define TPS6586X_VCC1 0x20 | ||
32 | #define TPS6586X_VCC2 0x21 | ||
33 | #define TPS6586X_SM1V1 0x23 | ||
34 | #define TPS6586X_SM1V2 0x24 | ||
35 | #define TPS6586X_SM1SL 0x25 | ||
36 | #define TPS6586X_SM0V1 0x26 | ||
37 | #define TPS6586X_SM0V2 0x27 | ||
38 | #define TPS6586X_SM0SL 0x28 | ||
39 | #define TPS6586X_LDO2AV1 0x29 | ||
40 | #define TPS6586X_LDO2AV2 0x2A | ||
41 | #define TPS6586X_LDO2BV1 0x2F | ||
42 | #define TPS6586X_LDO2BV2 0x30 | ||
43 | #define TPS6586X_LDO4V1 0x32 | ||
44 | #define TPS6586X_LDO4V2 0x33 | ||
45 | |||
46 | /* converter settings */ | ||
47 | #define TPS6586X_SUPPLYV1 0x41 | ||
48 | #define TPS6586X_SUPPLYV2 0x42 | ||
49 | #define TPS6586X_SUPPLYV3 0x43 | ||
50 | #define TPS6586X_SUPPLYV4 0x44 | ||
51 | #define TPS6586X_SUPPLYV5 0x45 | ||
52 | #define TPS6586X_SUPPLYV6 0x46 | ||
53 | #define TPS6586X_SMODE1 0x47 | ||
54 | #define TPS6586X_SMODE2 0x48 | ||
55 | |||
56 | struct tps6586x_regulator { | ||
57 | struct regulator_desc desc; | ||
58 | |||
59 | int volt_reg; | ||
60 | int volt_shift; | ||
61 | int volt_nbits; | ||
62 | int enable_bit[2]; | ||
63 | int enable_reg[2]; | ||
64 | |||
65 | int *voltages; | ||
66 | |||
67 | /* for DVM regulators */ | ||
68 | int go_reg; | ||
69 | int go_bit; | ||
70 | }; | ||
71 | |||
72 | static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev) | ||
73 | { | ||
74 | return rdev_get_dev(rdev)->parent->parent; | ||
75 | } | ||
76 | |||
77 | static int tps6586x_ldo_list_voltage(struct regulator_dev *rdev, | ||
78 | unsigned selector) | ||
79 | { | ||
80 | struct tps6586x_regulator *info = rdev_get_drvdata(rdev); | ||
81 | |||
82 | return info->voltages[selector] * 1000; | ||
83 | } | ||
84 | |||
85 | |||
86 | static int __tps6586x_ldo_set_voltage(struct device *parent, | ||
87 | struct tps6586x_regulator *ri, | ||
88 | int min_uV, int max_uV) | ||
89 | { | ||
90 | int val, uV; | ||
91 | uint8_t mask; | ||
92 | |||
93 | for (val = 0; val < ri->desc.n_voltages; val++) { | ||
94 | uV = ri->voltages[val] * 1000; | ||
95 | |||
96 | /* LDO0 has minimal voltage 1.2 rather than 1.25 */ | ||
97 | if (ri->desc.id == TPS6586X_ID_LDO_0 && val == 0) | ||
98 | uV -= 50 * 1000; | ||
99 | |||
100 | /* use the first in-range value */ | ||
101 | if (min_uV <= uV && uV <= max_uV) { | ||
102 | |||
103 | val <<= ri->volt_shift; | ||
104 | mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; | ||
105 | |||
106 | return tps6586x_update(parent, ri->volt_reg, val, mask); | ||
107 | } | ||
108 | } | ||
109 | |||
110 | return -EINVAL; | ||
111 | } | ||
112 | |||
113 | static int tps6586x_ldo_set_voltage(struct regulator_dev *rdev, | ||
114 | int min_uV, int max_uV) | ||
115 | { | ||
116 | struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); | ||
117 | struct device *parent = to_tps6586x_dev(rdev); | ||
118 | |||
119 | return __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV); | ||
120 | } | ||
121 | |||
122 | static int tps6586x_ldo_get_voltage(struct regulator_dev *rdev) | ||
123 | { | ||
124 | struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); | ||
125 | struct device *parent = to_tps6586x_dev(rdev); | ||
126 | uint8_t val, mask; | ||
127 | int ret; | ||
128 | |||
129 | ret = tps6586x_read(parent, ri->volt_reg, &val); | ||
130 | if (ret) | ||
131 | return ret; | ||
132 | |||
133 | mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; | ||
134 | val = (val & mask) >> ri->volt_shift; | ||
135 | |||
136 | if (val > ri->desc.n_voltages) | ||
137 | BUG(); | ||
138 | |||
139 | return ri->voltages[val] * 1000; | ||
140 | } | ||
141 | |||
142 | static int tps6586x_dvm_set_voltage(struct regulator_dev *rdev, | ||
143 | int min_uV, int max_uV) | ||
144 | { | ||
145 | struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); | ||
146 | struct device *parent = to_tps6586x_dev(rdev); | ||
147 | int ret; | ||
148 | |||
149 | ret = __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV); | ||
150 | if (ret) | ||
151 | return ret; | ||
152 | |||
153 | return tps6586x_set_bits(parent, ri->go_reg, ri->go_bit); | ||
154 | } | ||
155 | |||
156 | static int tps6586x_regulator_enable(struct regulator_dev *rdev) | ||
157 | { | ||
158 | struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); | ||
159 | struct device *parent = to_tps6586x_dev(rdev); | ||
160 | |||
161 | return tps6586x_set_bits(parent, ri->enable_reg[0], | ||
162 | 1 << ri->enable_bit[0]); | ||
163 | } | ||
164 | |||
165 | static int tps6586x_regulator_disable(struct regulator_dev *rdev) | ||
166 | { | ||
167 | struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); | ||
168 | struct device *parent = to_tps6586x_dev(rdev); | ||
169 | |||
170 | return tps6586x_clr_bits(parent, ri->enable_reg[0], | ||
171 | 1 << ri->enable_bit[0]); | ||
172 | } | ||
173 | |||
174 | static int tps6586x_regulator_is_enabled(struct regulator_dev *rdev) | ||
175 | { | ||
176 | struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); | ||
177 | struct device *parent = to_tps6586x_dev(rdev); | ||
178 | uint8_t reg_val; | ||
179 | int ret; | ||
180 | |||
181 | ret = tps6586x_read(parent, ri->enable_reg[0], ®_val); | ||
182 | if (ret) | ||
183 | return ret; | ||
184 | |||
185 | return !!(reg_val & (1 << ri->enable_bit[0])); | ||
186 | } | ||
187 | |||
188 | static struct regulator_ops tps6586x_regulator_ldo_ops = { | ||
189 | .list_voltage = tps6586x_ldo_list_voltage, | ||
190 | .get_voltage = tps6586x_ldo_get_voltage, | ||
191 | .set_voltage = tps6586x_ldo_set_voltage, | ||
192 | |||
193 | .is_enabled = tps6586x_regulator_is_enabled, | ||
194 | .enable = tps6586x_regulator_enable, | ||
195 | .disable = tps6586x_regulator_disable, | ||
196 | }; | ||
197 | |||
198 | static struct regulator_ops tps6586x_regulator_dvm_ops = { | ||
199 | .list_voltage = tps6586x_ldo_list_voltage, | ||
200 | .get_voltage = tps6586x_ldo_get_voltage, | ||
201 | .set_voltage = tps6586x_dvm_set_voltage, | ||
202 | |||
203 | .is_enabled = tps6586x_regulator_is_enabled, | ||
204 | .enable = tps6586x_regulator_enable, | ||
205 | .disable = tps6586x_regulator_disable, | ||
206 | }; | ||
207 | |||
208 | static int tps6586x_ldo_voltages[] = { | ||
209 | 1250, 1500, 1800, 2500, 2700, 2850, 3100, 3300, | ||
210 | }; | ||
211 | |||
212 | static int tps6586x_ldo4_voltages[] = { | ||
213 | 1700, 1725, 1750, 1775, 1800, 1825, 1850, 1875, | ||
214 | 1900, 1925, 1950, 1975, 2000, 2025, 2050, 2075, | ||
215 | 2100, 2125, 2150, 2175, 2200, 2225, 2250, 2275, | ||
216 | 2300, 2325, 2350, 2375, 2400, 2425, 2450, 2475, | ||
217 | }; | ||
218 | |||
219 | static int tps6586x_sm2_voltages[] = { | ||
220 | 3000, 3050, 3100, 3150, 3200, 3250, 3300, 3350, | ||
221 | 3400, 3450, 3500, 3550, 3600, 3650, 3700, 3750, | ||
222 | 3800, 3850, 3900, 3950, 4000, 4050, 4100, 4150, | ||
223 | 4200, 4250, 4300, 4350, 4400, 4450, 4500, 4550, | ||
224 | }; | ||
225 | |||
226 | static int tps6586x_dvm_voltages[] = { | ||
227 | 725, 750, 775, 800, 825, 850, 875, 900, | ||
228 | 925, 950, 975, 1000, 1025, 1050, 1075, 1100, | ||
229 | 1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300, | ||
230 | 1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500, | ||
231 | }; | ||
232 | |||
233 | #define TPS6586X_REGULATOR(_id, vdata, _ops, vreg, shift, nbits, \ | ||
234 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ | ||
235 | { \ | ||
236 | .desc = { \ | ||
237 | .name = "REG-" #_id, \ | ||
238 | .ops = &tps6586x_regulator_##_ops, \ | ||
239 | .type = REGULATOR_VOLTAGE, \ | ||
240 | .id = TPS6586X_ID_##_id, \ | ||
241 | .n_voltages = ARRAY_SIZE(tps6586x_##vdata##_voltages), \ | ||
242 | .owner = THIS_MODULE, \ | ||
243 | }, \ | ||
244 | .volt_reg = TPS6586X_##vreg, \ | ||
245 | .volt_shift = (shift), \ | ||
246 | .volt_nbits = (nbits), \ | ||
247 | .enable_reg[0] = TPS6586X_SUPPLY##ereg0, \ | ||
248 | .enable_bit[0] = (ebit0), \ | ||
249 | .enable_reg[1] = TPS6586X_SUPPLY##ereg1, \ | ||
250 | .enable_bit[1] = (ebit1), \ | ||
251 | .voltages = tps6586x_##vdata##_voltages, \ | ||
252 | } | ||
253 | |||
254 | #define TPS6586X_LDO(_id, vdata, vreg, shift, nbits, \ | ||
255 | ereg0, ebit0, ereg1, ebit1) \ | ||
256 | TPS6586X_REGULATOR(_id, vdata, ldo_ops, vreg, shift, nbits, \ | ||
257 | ereg0, ebit0, ereg1, ebit1, 0, 0) | ||
258 | |||
259 | #define TPS6586X_DVM(_id, vdata, vreg, shift, nbits, \ | ||
260 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ | ||
261 | TPS6586X_REGULATOR(_id, vdata, dvm_ops, vreg, shift, nbits, \ | ||
262 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) | ||
263 | |||
264 | static struct tps6586x_regulator tps6586x_regulator[] = { | ||
265 | TPS6586X_LDO(LDO_0, ldo, SUPPLYV1, 5, 3, ENC, 0, END, 0), | ||
266 | TPS6586X_LDO(LDO_3, ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2), | ||
267 | TPS6586X_LDO(LDO_5, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6), | ||
268 | TPS6586X_LDO(LDO_6, ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4), | ||
269 | TPS6586X_LDO(LDO_7, ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5), | ||
270 | TPS6586X_LDO(LDO_8, ldo, SUPPLYV1, 5, 3, ENC, 6, END, 6), | ||
271 | TPS6586X_LDO(LDO_9, ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7), | ||
272 | TPS6586X_LDO(LDO_RTC, ldo, SUPPLYV4, 3, 3, ENE, 7, ENE, 7), | ||
273 | TPS6586X_LDO(LDO_1, dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1), | ||
274 | TPS6586X_LDO(SM_2, sm2, SUPPLYV2, 0, 5, ENC, 1, END, 1), | ||
275 | |||
276 | TPS6586X_DVM(LDO_2, dvm, LDO2BV1, 0, 5, ENA, 3, ENB, 3, VCC2, 6), | ||
277 | TPS6586X_DVM(LDO_4, ldo4, LDO4V1, 0, 5, ENC, 3, END, 3, VCC1, 6), | ||
278 | TPS6586X_DVM(SM_0, dvm, SM0V1, 0, 5, ENA, 1, ENB, 1, VCC1, 2), | ||
279 | TPS6586X_DVM(SM_1, dvm, SM1V1, 0, 5, ENA, 0, ENB, 0, VCC1, 0), | ||
280 | }; | ||
281 | |||
282 | /* | ||
283 | * TPS6586X has 2 enable bits that are OR'ed to determine the actual | ||
284 | * regulator state. Clearing one of this bits allows switching | ||
285 | * regulator on and of with single register write. | ||
286 | */ | ||
287 | static inline int tps6586x_regulator_preinit(struct device *parent, | ||
288 | struct tps6586x_regulator *ri) | ||
289 | { | ||
290 | uint8_t val1, val2; | ||
291 | int ret; | ||
292 | |||
293 | ret = tps6586x_read(parent, ri->enable_reg[0], &val1); | ||
294 | if (ret) | ||
295 | return ret; | ||
296 | |||
297 | ret = tps6586x_read(parent, ri->enable_reg[1], &val2); | ||
298 | if (ret) | ||
299 | return ret; | ||
300 | |||
301 | if (!(val2 & ri->enable_bit[1])) | ||
302 | return 0; | ||
303 | |||
304 | /* | ||
305 | * The regulator is on, but it's enabled with the bit we don't | ||
306 | * want to use, so we switch the enable bits | ||
307 | */ | ||
308 | if (!(val1 & ri->enable_bit[0])) { | ||
309 | ret = tps6586x_set_bits(parent, ri->enable_reg[0], | ||
310 | 1 << ri->enable_bit[0]); | ||
311 | if (ret) | ||
312 | return ret; | ||
313 | } | ||
314 | |||
315 | return tps6586x_clr_bits(parent, ri->enable_reg[1], | ||
316 | 1 << ri->enable_bit[1]); | ||
317 | } | ||
318 | |||
319 | static inline struct tps6586x_regulator *find_regulator_info(int id) | ||
320 | { | ||
321 | struct tps6586x_regulator *ri; | ||
322 | int i; | ||
323 | |||
324 | for (i = 0; i < ARRAY_SIZE(tps6586x_regulator); i++) { | ||
325 | ri = &tps6586x_regulator[i]; | ||
326 | if (ri->desc.id == id) | ||
327 | return ri; | ||
328 | } | ||
329 | return NULL; | ||
330 | } | ||
331 | |||
332 | static int __devinit tps6586x_regulator_probe(struct platform_device *pdev) | ||
333 | { | ||
334 | struct tps6586x_regulator *ri = NULL; | ||
335 | struct regulator_dev *rdev; | ||
336 | int id = pdev->id; | ||
337 | int err; | ||
338 | |||
339 | dev_dbg(&pdev->dev, "Probing reulator %d\n", id); | ||
340 | |||
341 | ri = find_regulator_info(id); | ||
342 | if (ri == NULL) { | ||
343 | dev_err(&pdev->dev, "invalid regulator ID specified\n"); | ||
344 | return -EINVAL; | ||
345 | } | ||
346 | |||
347 | err = tps6586x_regulator_preinit(pdev->dev.parent, ri); | ||
348 | if (err) | ||
349 | return err; | ||
350 | |||
351 | rdev = regulator_register(&ri->desc, &pdev->dev, | ||
352 | pdev->dev.platform_data, ri); | ||
353 | if (IS_ERR(rdev)) { | ||
354 | dev_err(&pdev->dev, "failed to register regulator %s\n", | ||
355 | ri->desc.name); | ||
356 | return PTR_ERR(rdev); | ||
357 | } | ||
358 | |||
359 | platform_set_drvdata(pdev, rdev); | ||
360 | |||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | static int __devexit tps6586x_regulator_remove(struct platform_device *pdev) | ||
365 | { | ||
366 | struct regulator_dev *rdev = platform_get_drvdata(pdev); | ||
367 | |||
368 | regulator_unregister(rdev); | ||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | static struct platform_driver tps6586x_regulator_driver = { | ||
373 | .driver = { | ||
374 | .name = "tps6586x-regulator", | ||
375 | .owner = THIS_MODULE, | ||
376 | }, | ||
377 | .probe = tps6586x_regulator_probe, | ||
378 | .remove = __devexit_p(tps6586x_regulator_remove), | ||
379 | }; | ||
380 | |||
381 | static int __init tps6586x_regulator_init(void) | ||
382 | { | ||
383 | return platform_driver_register(&tps6586x_regulator_driver); | ||
384 | } | ||
385 | subsys_initcall(tps6586x_regulator_init); | ||
386 | |||
387 | static void __exit tps6586x_regulator_exit(void) | ||
388 | { | ||
389 | platform_driver_unregister(&tps6586x_regulator_driver); | ||
390 | } | ||
391 | module_exit(tps6586x_regulator_exit); | ||
392 | |||
393 | MODULE_LICENSE("GPL"); | ||
394 | MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); | ||
395 | MODULE_DESCRIPTION("Regulator Driver for TI TPS6586X PMIC"); | ||
396 | MODULE_ALIAS("platform:tps6586x-regulator"); | ||
diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index 5a1dc8a24d35..03713bc66e4a 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c | |||
@@ -219,8 +219,6 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev) | |||
219 | 219 | ||
220 | ldo->wm8994 = wm8994; | 220 | ldo->wm8994 = wm8994; |
221 | 221 | ||
222 | ldo->is_enabled = true; | ||
223 | |||
224 | if (pdata->ldo[id].enable && gpio_is_valid(pdata->ldo[id].enable)) { | 222 | if (pdata->ldo[id].enable && gpio_is_valid(pdata->ldo[id].enable)) { |
225 | ldo->enable = pdata->ldo[id].enable; | 223 | ldo->enable = pdata->ldo[id].enable; |
226 | 224 | ||
@@ -237,7 +235,8 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev) | |||
237 | ret); | 235 | ret); |
238 | goto err_gpio; | 236 | goto err_gpio; |
239 | } | 237 | } |
240 | } | 238 | } else |
239 | ldo->is_enabled = true; | ||
241 | 240 | ||
242 | ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &pdev->dev, | 241 | ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &pdev->dev, |
243 | pdata->ldo[id].init_data, ldo); | 242 | pdata->ldo[id].init_data, ldo); |
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index db5d8c416d26..dfcdf0901d21 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c | |||
@@ -268,7 +268,7 @@ static const struct rtc_class_ops mpc5121_rtc_ops = { | |||
268 | .update_irq_enable = mpc5121_rtc_update_irq_enable, | 268 | .update_irq_enable = mpc5121_rtc_update_irq_enable, |
269 | }; | 269 | }; |
270 | 270 | ||
271 | static int __devinit mpc5121_rtc_probe(struct of_device *op, | 271 | static int __devinit mpc5121_rtc_probe(struct platform_device *op, |
272 | const struct of_device_id *match) | 272 | const struct of_device_id *match) |
273 | { | 273 | { |
274 | struct mpc5121_rtc_data *rtc; | 274 | struct mpc5121_rtc_data *rtc; |
@@ -338,7 +338,7 @@ out_free: | |||
338 | return err; | 338 | return err; |
339 | } | 339 | } |
340 | 340 | ||
341 | static int __devexit mpc5121_rtc_remove(struct of_device *op) | 341 | static int __devexit mpc5121_rtc_remove(struct platform_device *op) |
342 | { | 342 | { |
343 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(&op->dev); | 343 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(&op->dev); |
344 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | 344 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; |
diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c index 103fdf6b0b89..160e7510aca6 100644 --- a/drivers/sbus/char/bbc_envctrl.c +++ b/drivers/sbus/char/bbc_envctrl.c | |||
@@ -443,7 +443,7 @@ static int kenvctrld(void *__unused) | |||
443 | return 0; | 443 | return 0; |
444 | } | 444 | } |
445 | 445 | ||
446 | static void attach_one_temp(struct bbc_i2c_bus *bp, struct of_device *op, | 446 | static void attach_one_temp(struct bbc_i2c_bus *bp, struct platform_device *op, |
447 | int temp_idx) | 447 | int temp_idx) |
448 | { | 448 | { |
449 | struct bbc_cpu_temperature *tp; | 449 | struct bbc_cpu_temperature *tp; |
@@ -488,7 +488,7 @@ static void attach_one_temp(struct bbc_i2c_bus *bp, struct of_device *op, | |||
488 | tp->fan_todo[FAN_CPU] = FAN_SAME; | 488 | tp->fan_todo[FAN_CPU] = FAN_SAME; |
489 | } | 489 | } |
490 | 490 | ||
491 | static void attach_one_fan(struct bbc_i2c_bus *bp, struct of_device *op, | 491 | static void attach_one_fan(struct bbc_i2c_bus *bp, struct platform_device *op, |
492 | int fan_idx) | 492 | int fan_idx) |
493 | { | 493 | { |
494 | struct bbc_fan_control *fp; | 494 | struct bbc_fan_control *fp; |
@@ -559,7 +559,7 @@ static void destroy_all_fans(struct bbc_i2c_bus *bp) | |||
559 | 559 | ||
560 | int bbc_envctrl_init(struct bbc_i2c_bus *bp) | 560 | int bbc_envctrl_init(struct bbc_i2c_bus *bp) |
561 | { | 561 | { |
562 | struct of_device *op; | 562 | struct platform_device *op; |
563 | int temp_index = 0; | 563 | int temp_index = 0; |
564 | int fan_index = 0; | 564 | int fan_index = 0; |
565 | int devidx = 0; | 565 | int devidx = 0; |
diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index 3e89c313e98d..614a5e114a19 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c | |||
@@ -51,7 +51,7 @@ | |||
51 | * The second controller also connects to the smartcard reader, if present. | 51 | * The second controller also connects to the smartcard reader, if present. |
52 | */ | 52 | */ |
53 | 53 | ||
54 | static void set_device_claimage(struct bbc_i2c_bus *bp, struct of_device *op, int val) | 54 | static void set_device_claimage(struct bbc_i2c_bus *bp, struct platform_device *op, int val) |
55 | { | 55 | { |
56 | int i; | 56 | int i; |
57 | 57 | ||
@@ -66,9 +66,9 @@ static void set_device_claimage(struct bbc_i2c_bus *bp, struct of_device *op, in | |||
66 | #define claim_device(BP,ECHILD) set_device_claimage(BP,ECHILD,1) | 66 | #define claim_device(BP,ECHILD) set_device_claimage(BP,ECHILD,1) |
67 | #define release_device(BP,ECHILD) set_device_claimage(BP,ECHILD,0) | 67 | #define release_device(BP,ECHILD) set_device_claimage(BP,ECHILD,0) |
68 | 68 | ||
69 | struct of_device *bbc_i2c_getdev(struct bbc_i2c_bus *bp, int index) | 69 | struct platform_device *bbc_i2c_getdev(struct bbc_i2c_bus *bp, int index) |
70 | { | 70 | { |
71 | struct of_device *op = NULL; | 71 | struct platform_device *op = NULL; |
72 | int curidx = 0, i; | 72 | int curidx = 0, i; |
73 | 73 | ||
74 | for (i = 0; i < NUM_CHILDREN; i++) { | 74 | for (i = 0; i < NUM_CHILDREN; i++) { |
@@ -86,7 +86,7 @@ out: | |||
86 | return NULL; | 86 | return NULL; |
87 | } | 87 | } |
88 | 88 | ||
89 | struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device *op) | 89 | struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct platform_device *op) |
90 | { | 90 | { |
91 | struct bbc_i2c_client *client; | 91 | struct bbc_i2c_client *client; |
92 | const u32 *reg; | 92 | const u32 *reg; |
@@ -114,7 +114,7 @@ struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device * | |||
114 | void bbc_i2c_detach(struct bbc_i2c_client *client) | 114 | void bbc_i2c_detach(struct bbc_i2c_client *client) |
115 | { | 115 | { |
116 | struct bbc_i2c_bus *bp = client->bp; | 116 | struct bbc_i2c_bus *bp = client->bp; |
117 | struct of_device *op = client->op; | 117 | struct platform_device *op = client->op; |
118 | 118 | ||
119 | release_device(bp, op); | 119 | release_device(bp, op); |
120 | kfree(client); | 120 | kfree(client); |
@@ -297,7 +297,7 @@ static void __init reset_one_i2c(struct bbc_i2c_bus *bp) | |||
297 | writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0); | 297 | writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0); |
298 | } | 298 | } |
299 | 299 | ||
300 | static struct bbc_i2c_bus * __init attach_one_i2c(struct of_device *op, int index) | 300 | static struct bbc_i2c_bus * __init attach_one_i2c(struct platform_device *op, int index) |
301 | { | 301 | { |
302 | struct bbc_i2c_bus *bp; | 302 | struct bbc_i2c_bus *bp; |
303 | struct device_node *dp; | 303 | struct device_node *dp; |
@@ -330,7 +330,7 @@ static struct bbc_i2c_bus * __init attach_one_i2c(struct of_device *op, int inde | |||
330 | for (dp = op->dev.of_node->child; | 330 | for (dp = op->dev.of_node->child; |
331 | dp && entry < 8; | 331 | dp && entry < 8; |
332 | dp = dp->sibling, entry++) { | 332 | dp = dp->sibling, entry++) { |
333 | struct of_device *child_op; | 333 | struct platform_device *child_op; |
334 | 334 | ||
335 | child_op = of_find_device_by_node(dp); | 335 | child_op = of_find_device_by_node(dp); |
336 | bp->devs[entry].device = child_op; | 336 | bp->devs[entry].device = child_op; |
@@ -361,7 +361,7 @@ fail: | |||
361 | extern int bbc_envctrl_init(struct bbc_i2c_bus *bp); | 361 | extern int bbc_envctrl_init(struct bbc_i2c_bus *bp); |
362 | extern void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp); | 362 | extern void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp); |
363 | 363 | ||
364 | static int __devinit bbc_i2c_probe(struct of_device *op, | 364 | static int __devinit bbc_i2c_probe(struct platform_device *op, |
365 | const struct of_device_id *match) | 365 | const struct of_device_id *match) |
366 | { | 366 | { |
367 | struct bbc_i2c_bus *bp; | 367 | struct bbc_i2c_bus *bp; |
@@ -386,7 +386,7 @@ static int __devinit bbc_i2c_probe(struct of_device *op, | |||
386 | return err; | 386 | return err; |
387 | } | 387 | } |
388 | 388 | ||
389 | static int __devexit bbc_i2c_remove(struct of_device *op) | 389 | static int __devexit bbc_i2c_remove(struct platform_device *op) |
390 | { | 390 | { |
391 | struct bbc_i2c_bus *bp = dev_get_drvdata(&op->dev); | 391 | struct bbc_i2c_bus *bp = dev_get_drvdata(&op->dev); |
392 | 392 | ||
diff --git a/drivers/sbus/char/bbc_i2c.h b/drivers/sbus/char/bbc_i2c.h index 83c4811b7b5e..4b4531066e75 100644 --- a/drivers/sbus/char/bbc_i2c.h +++ b/drivers/sbus/char/bbc_i2c.h | |||
@@ -7,7 +7,7 @@ | |||
7 | 7 | ||
8 | struct bbc_i2c_client { | 8 | struct bbc_i2c_client { |
9 | struct bbc_i2c_bus *bp; | 9 | struct bbc_i2c_bus *bp; |
10 | struct of_device *op; | 10 | struct platform_device *op; |
11 | int bus; | 11 | int bus; |
12 | int address; | 12 | int address; |
13 | }; | 13 | }; |
@@ -64,16 +64,16 @@ struct bbc_i2c_bus { | |||
64 | struct list_head temps; | 64 | struct list_head temps; |
65 | struct list_head fans; | 65 | struct list_head fans; |
66 | 66 | ||
67 | struct of_device *op; | 67 | struct platform_device *op; |
68 | struct { | 68 | struct { |
69 | struct of_device *device; | 69 | struct platform_device *device; |
70 | int client_claimed; | 70 | int client_claimed; |
71 | } devs[NUM_CHILDREN]; | 71 | } devs[NUM_CHILDREN]; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | /* Probing and attachment. */ | 74 | /* Probing and attachment. */ |
75 | extern struct of_device *bbc_i2c_getdev(struct bbc_i2c_bus *, int); | 75 | extern struct platform_device *bbc_i2c_getdev(struct bbc_i2c_bus *, int); |
76 | extern struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device *); | 76 | extern struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct platform_device *); |
77 | extern void bbc_i2c_detach(struct bbc_i2c_client *); | 77 | extern void bbc_i2c_detach(struct bbc_i2c_client *); |
78 | 78 | ||
79 | /* Register read/write. NOTE: Blocking! */ | 79 | /* Register read/write. NOTE: Blocking! */ |
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index 47db97583ea7..1690e53fb84a 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c | |||
@@ -170,7 +170,7 @@ static struct miscdevice d7s_miscdev = { | |||
170 | .fops = &d7s_fops | 170 | .fops = &d7s_fops |
171 | }; | 171 | }; |
172 | 172 | ||
173 | static int __devinit d7s_probe(struct of_device *op, | 173 | static int __devinit d7s_probe(struct platform_device *op, |
174 | const struct of_device_id *match) | 174 | const struct of_device_id *match) |
175 | { | 175 | { |
176 | struct device_node *opts; | 176 | struct device_node *opts; |
@@ -236,7 +236,7 @@ out_free: | |||
236 | goto out; | 236 | goto out; |
237 | } | 237 | } |
238 | 238 | ||
239 | static int __devexit d7s_remove(struct of_device *op) | 239 | static int __devexit d7s_remove(struct platform_device *op) |
240 | { | 240 | { |
241 | struct d7s *p = dev_get_drvdata(&op->dev); | 241 | struct d7s *p = dev_get_drvdata(&op->dev); |
242 | u8 regs = readb(p->regs); | 242 | u8 regs = readb(p->regs); |
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index 3c27f45e2b6d..078e5f4520ef 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c | |||
@@ -1027,7 +1027,7 @@ static int kenvctrld(void *__unused) | |||
1027 | return 0; | 1027 | return 0; |
1028 | } | 1028 | } |
1029 | 1029 | ||
1030 | static int __devinit envctrl_probe(struct of_device *op, | 1030 | static int __devinit envctrl_probe(struct platform_device *op, |
1031 | const struct of_device_id *match) | 1031 | const struct of_device_id *match) |
1032 | { | 1032 | { |
1033 | struct device_node *dp; | 1033 | struct device_node *dp; |
@@ -1104,7 +1104,7 @@ out_iounmap: | |||
1104 | return err; | 1104 | return err; |
1105 | } | 1105 | } |
1106 | 1106 | ||
1107 | static int __devexit envctrl_remove(struct of_device *op) | 1107 | static int __devexit envctrl_remove(struct platform_device *op) |
1108 | { | 1108 | { |
1109 | int index; | 1109 | int index; |
1110 | 1110 | ||
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index 8bb31c584b64..2b4b4b613c48 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c | |||
@@ -160,7 +160,7 @@ static const struct file_operations flash_fops = { | |||
160 | 160 | ||
161 | static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops }; | 161 | static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops }; |
162 | 162 | ||
163 | static int __devinit flash_probe(struct of_device *op, | 163 | static int __devinit flash_probe(struct platform_device *op, |
164 | const struct of_device_id *match) | 164 | const struct of_device_id *match) |
165 | { | 165 | { |
166 | struct device_node *dp = op->dev.of_node; | 166 | struct device_node *dp = op->dev.of_node; |
@@ -192,7 +192,7 @@ static int __devinit flash_probe(struct of_device *op, | |||
192 | return misc_register(&flash_dev); | 192 | return misc_register(&flash_dev); |
193 | } | 193 | } |
194 | 194 | ||
195 | static int __devexit flash_remove(struct of_device *op) | 195 | static int __devexit flash_remove(struct platform_device *op) |
196 | { | 196 | { |
197 | misc_deregister(&flash_dev); | 197 | misc_deregister(&flash_dev); |
198 | 198 | ||
diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c index 41eb6725ff5f..1b345be5cc02 100644 --- a/drivers/sbus/char/uctrl.c +++ b/drivers/sbus/char/uctrl.c | |||
@@ -348,7 +348,7 @@ static void uctrl_get_external_status(struct uctrl_driver *driver) | |||
348 | 348 | ||
349 | } | 349 | } |
350 | 350 | ||
351 | static int __devinit uctrl_probe(struct of_device *op, | 351 | static int __devinit uctrl_probe(struct platform_device *op, |
352 | const struct of_device_id *match) | 352 | const struct of_device_id *match) |
353 | { | 353 | { |
354 | struct uctrl_driver *p; | 354 | struct uctrl_driver *p; |
@@ -404,7 +404,7 @@ out_free: | |||
404 | goto out; | 404 | goto out; |
405 | } | 405 | } |
406 | 406 | ||
407 | static int __devexit uctrl_remove(struct of_device *op) | 407 | static int __devexit uctrl_remove(struct platform_device *op) |
408 | { | 408 | { |
409 | struct uctrl_driver *p = dev_get_drvdata(&op->dev); | 409 | struct uctrl_driver *p = dev_get_drvdata(&op->dev); |
410 | 410 | ||
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 915a29d6c7ad..ca04cc9d332f 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c | |||
@@ -788,6 +788,7 @@ bfad_drv_init(struct bfad_s *bfad) | |||
788 | memset(&driver_info, 0, sizeof(driver_info)); | 788 | memset(&driver_info, 0, sizeof(driver_info)); |
789 | strncpy(driver_info.version, BFAD_DRIVER_VERSION, | 789 | strncpy(driver_info.version, BFAD_DRIVER_VERSION, |
790 | sizeof(driver_info.version) - 1); | 790 | sizeof(driver_info.version) - 1); |
791 | __kernel_param_lock(); | ||
791 | if (host_name) | 792 | if (host_name) |
792 | strncpy(driver_info.host_machine_name, host_name, | 793 | strncpy(driver_info.host_machine_name, host_name, |
793 | sizeof(driver_info.host_machine_name) - 1); | 794 | sizeof(driver_info.host_machine_name) - 1); |
@@ -797,6 +798,7 @@ bfad_drv_init(struct bfad_s *bfad) | |||
797 | if (os_patch) | 798 | if (os_patch) |
798 | strncpy(driver_info.host_os_patch, os_patch, | 799 | strncpy(driver_info.host_os_patch, os_patch, |
799 | sizeof(driver_info.host_os_patch) - 1); | 800 | sizeof(driver_info.host_os_patch) - 1); |
801 | __kernel_param_unlock(); | ||
800 | 802 | ||
801 | strncpy(driver_info.os_device_name, bfad->pci_name, | 803 | strncpy(driver_info.os_device_name, bfad->pci_name, |
802 | sizeof(driver_info.os_device_name - 1)); | 804 | sizeof(driver_info.os_device_name - 1)); |
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 53d7ed0dc169..f8c561cf751e 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c | |||
@@ -704,7 +704,7 @@ static void __devexit qpti_chain_del(struct qlogicpti *qpti) | |||
704 | 704 | ||
705 | static int __devinit qpti_map_regs(struct qlogicpti *qpti) | 705 | static int __devinit qpti_map_regs(struct qlogicpti *qpti) |
706 | { | 706 | { |
707 | struct of_device *op = qpti->op; | 707 | struct platform_device *op = qpti->op; |
708 | 708 | ||
709 | qpti->qregs = of_ioremap(&op->resource[0], 0, | 709 | qpti->qregs = of_ioremap(&op->resource[0], 0, |
710 | resource_size(&op->resource[0]), | 710 | resource_size(&op->resource[0]), |
@@ -727,7 +727,7 @@ static int __devinit qpti_map_regs(struct qlogicpti *qpti) | |||
727 | 727 | ||
728 | static int __devinit qpti_register_irq(struct qlogicpti *qpti) | 728 | static int __devinit qpti_register_irq(struct qlogicpti *qpti) |
729 | { | 729 | { |
730 | struct of_device *op = qpti->op; | 730 | struct platform_device *op = qpti->op; |
731 | 731 | ||
732 | qpti->qhost->irq = qpti->irq = op->archdata.irqs[0]; | 732 | qpti->qhost->irq = qpti->irq = op->archdata.irqs[0]; |
733 | 733 | ||
@@ -752,7 +752,7 @@ fail: | |||
752 | 752 | ||
753 | static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) | 753 | static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) |
754 | { | 754 | { |
755 | struct of_device *op = qpti->op; | 755 | struct platform_device *op = qpti->op; |
756 | struct device_node *dp; | 756 | struct device_node *dp; |
757 | 757 | ||
758 | dp = op->dev.of_node; | 758 | dp = op->dev.of_node; |
@@ -773,7 +773,7 @@ static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) | |||
773 | 773 | ||
774 | static void qpti_get_bursts(struct qlogicpti *qpti) | 774 | static void qpti_get_bursts(struct qlogicpti *qpti) |
775 | { | 775 | { |
776 | struct of_device *op = qpti->op; | 776 | struct platform_device *op = qpti->op; |
777 | u8 bursts, bmask; | 777 | u8 bursts, bmask; |
778 | 778 | ||
779 | bursts = of_getintprop_default(op->dev.of_node, "burst-sizes", 0xff); | 779 | bursts = of_getintprop_default(op->dev.of_node, "burst-sizes", 0xff); |
@@ -806,7 +806,7 @@ static void qpti_get_clock(struct qlogicpti *qpti) | |||
806 | */ | 806 | */ |
807 | static int __devinit qpti_map_queues(struct qlogicpti *qpti) | 807 | static int __devinit qpti_map_queues(struct qlogicpti *qpti) |
808 | { | 808 | { |
809 | struct of_device *op = qpti->op; | 809 | struct platform_device *op = qpti->op; |
810 | 810 | ||
811 | #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) | 811 | #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) |
812 | qpti->res_cpu = dma_alloc_coherent(&op->dev, | 812 | qpti->res_cpu = dma_alloc_coherent(&op->dev, |
@@ -1290,7 +1290,7 @@ static struct scsi_host_template qpti_template = { | |||
1290 | .use_clustering = ENABLE_CLUSTERING, | 1290 | .use_clustering = ENABLE_CLUSTERING, |
1291 | }; | 1291 | }; |
1292 | 1292 | ||
1293 | static int __devinit qpti_sbus_probe(struct of_device *op, const struct of_device_id *match) | 1293 | static int __devinit qpti_sbus_probe(struct platform_device *op, const struct of_device_id *match) |
1294 | { | 1294 | { |
1295 | struct scsi_host_template *tpnt = match->data; | 1295 | struct scsi_host_template *tpnt = match->data; |
1296 | struct device_node *dp = op->dev.of_node; | 1296 | struct device_node *dp = op->dev.of_node; |
@@ -1401,7 +1401,7 @@ fail_unlink: | |||
1401 | return -ENODEV; | 1401 | return -ENODEV; |
1402 | } | 1402 | } |
1403 | 1403 | ||
1404 | static int __devexit qpti_sbus_remove(struct of_device *op) | 1404 | static int __devexit qpti_sbus_remove(struct platform_device *op) |
1405 | { | 1405 | { |
1406 | struct qlogicpti *qpti = dev_get_drvdata(&op->dev); | 1406 | struct qlogicpti *qpti = dev_get_drvdata(&op->dev); |
1407 | 1407 | ||
diff --git a/drivers/scsi/qlogicpti.h b/drivers/scsi/qlogicpti.h index e3c74d1ee2db..4377e87ee79c 100644 --- a/drivers/scsi/qlogicpti.h +++ b/drivers/scsi/qlogicpti.h | |||
@@ -342,7 +342,7 @@ struct qlogicpti { | |||
342 | u_int req_in_ptr; /* index of next request slot */ | 342 | u_int req_in_ptr; /* index of next request slot */ |
343 | u_int res_out_ptr; /* index of next result slot */ | 343 | u_int res_out_ptr; /* index of next result slot */ |
344 | long send_marker; /* must we send a marker? */ | 344 | long send_marker; /* must we send a marker? */ |
345 | struct of_device *op; | 345 | struct platform_device *op; |
346 | unsigned long __pad; | 346 | unsigned long __pad; |
347 | 347 | ||
348 | int cmd_count[MAX_TARGETS]; | 348 | int cmd_count[MAX_TARGETS]; |
diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c index 89ba6fe02f80..193b37ba1834 100644 --- a/drivers/scsi/sun_esp.c +++ b/drivers/scsi/sun_esp.c | |||
@@ -44,7 +44,7 @@ enum dvma_rev { | |||
44 | }; | 44 | }; |
45 | 45 | ||
46 | static int __devinit esp_sbus_setup_dma(struct esp *esp, | 46 | static int __devinit esp_sbus_setup_dma(struct esp *esp, |
47 | struct of_device *dma_of) | 47 | struct platform_device *dma_of) |
48 | { | 48 | { |
49 | esp->dma = dma_of; | 49 | esp->dma = dma_of; |
50 | 50 | ||
@@ -81,7 +81,7 @@ static int __devinit esp_sbus_setup_dma(struct esp *esp, | |||
81 | 81 | ||
82 | static int __devinit esp_sbus_map_regs(struct esp *esp, int hme) | 82 | static int __devinit esp_sbus_map_regs(struct esp *esp, int hme) |
83 | { | 83 | { |
84 | struct of_device *op = esp->dev; | 84 | struct platform_device *op = esp->dev; |
85 | struct resource *res; | 85 | struct resource *res; |
86 | 86 | ||
87 | /* On HME, two reg sets exist, first is DVMA, | 87 | /* On HME, two reg sets exist, first is DVMA, |
@@ -101,7 +101,7 @@ static int __devinit esp_sbus_map_regs(struct esp *esp, int hme) | |||
101 | 101 | ||
102 | static int __devinit esp_sbus_map_command_block(struct esp *esp) | 102 | static int __devinit esp_sbus_map_command_block(struct esp *esp) |
103 | { | 103 | { |
104 | struct of_device *op = esp->dev; | 104 | struct platform_device *op = esp->dev; |
105 | 105 | ||
106 | esp->command_block = dma_alloc_coherent(&op->dev, 16, | 106 | esp->command_block = dma_alloc_coherent(&op->dev, 16, |
107 | &esp->command_block_dma, | 107 | &esp->command_block_dma, |
@@ -114,15 +114,15 @@ static int __devinit esp_sbus_map_command_block(struct esp *esp) | |||
114 | static int __devinit esp_sbus_register_irq(struct esp *esp) | 114 | static int __devinit esp_sbus_register_irq(struct esp *esp) |
115 | { | 115 | { |
116 | struct Scsi_Host *host = esp->host; | 116 | struct Scsi_Host *host = esp->host; |
117 | struct of_device *op = esp->dev; | 117 | struct platform_device *op = esp->dev; |
118 | 118 | ||
119 | host->irq = op->archdata.irqs[0]; | 119 | host->irq = op->archdata.irqs[0]; |
120 | return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp); | 120 | return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp); |
121 | } | 121 | } |
122 | 122 | ||
123 | static void __devinit esp_get_scsi_id(struct esp *esp, struct of_device *espdma) | 123 | static void __devinit esp_get_scsi_id(struct esp *esp, struct platform_device *espdma) |
124 | { | 124 | { |
125 | struct of_device *op = esp->dev; | 125 | struct platform_device *op = esp->dev; |
126 | struct device_node *dp; | 126 | struct device_node *dp; |
127 | 127 | ||
128 | dp = op->dev.of_node; | 128 | dp = op->dev.of_node; |
@@ -144,7 +144,7 @@ done: | |||
144 | 144 | ||
145 | static void __devinit esp_get_differential(struct esp *esp) | 145 | static void __devinit esp_get_differential(struct esp *esp) |
146 | { | 146 | { |
147 | struct of_device *op = esp->dev; | 147 | struct platform_device *op = esp->dev; |
148 | struct device_node *dp; | 148 | struct device_node *dp; |
149 | 149 | ||
150 | dp = op->dev.of_node; | 150 | dp = op->dev.of_node; |
@@ -156,7 +156,7 @@ static void __devinit esp_get_differential(struct esp *esp) | |||
156 | 156 | ||
157 | static void __devinit esp_get_clock_params(struct esp *esp) | 157 | static void __devinit esp_get_clock_params(struct esp *esp) |
158 | { | 158 | { |
159 | struct of_device *op = esp->dev; | 159 | struct platform_device *op = esp->dev; |
160 | struct device_node *bus_dp, *dp; | 160 | struct device_node *bus_dp, *dp; |
161 | int fmhz; | 161 | int fmhz; |
162 | 162 | ||
@@ -170,10 +170,10 @@ static void __devinit esp_get_clock_params(struct esp *esp) | |||
170 | esp->cfreq = fmhz; | 170 | esp->cfreq = fmhz; |
171 | } | 171 | } |
172 | 172 | ||
173 | static void __devinit esp_get_bursts(struct esp *esp, struct of_device *dma_of) | 173 | static void __devinit esp_get_bursts(struct esp *esp, struct platform_device *dma_of) |
174 | { | 174 | { |
175 | struct device_node *dma_dp = dma_of->dev.of_node; | 175 | struct device_node *dma_dp = dma_of->dev.of_node; |
176 | struct of_device *op = esp->dev; | 176 | struct platform_device *op = esp->dev; |
177 | struct device_node *dp; | 177 | struct device_node *dp; |
178 | u8 bursts, val; | 178 | u8 bursts, val; |
179 | 179 | ||
@@ -195,7 +195,7 @@ static void __devinit esp_get_bursts(struct esp *esp, struct of_device *dma_of) | |||
195 | esp->bursts = bursts; | 195 | esp->bursts = bursts; |
196 | } | 196 | } |
197 | 197 | ||
198 | static void __devinit esp_sbus_get_props(struct esp *esp, struct of_device *espdma) | 198 | static void __devinit esp_sbus_get_props(struct esp *esp, struct platform_device *espdma) |
199 | { | 199 | { |
200 | esp_get_scsi_id(esp, espdma); | 200 | esp_get_scsi_id(esp, espdma); |
201 | esp_get_differential(esp); | 201 | esp_get_differential(esp); |
@@ -216,7 +216,7 @@ static u8 sbus_esp_read8(struct esp *esp, unsigned long reg) | |||
216 | static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf, | 216 | static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf, |
217 | size_t sz, int dir) | 217 | size_t sz, int dir) |
218 | { | 218 | { |
219 | struct of_device *op = esp->dev; | 219 | struct platform_device *op = esp->dev; |
220 | 220 | ||
221 | return dma_map_single(&op->dev, buf, sz, dir); | 221 | return dma_map_single(&op->dev, buf, sz, dir); |
222 | } | 222 | } |
@@ -224,7 +224,7 @@ static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf, | |||
224 | static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg, | 224 | static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg, |
225 | int num_sg, int dir) | 225 | int num_sg, int dir) |
226 | { | 226 | { |
227 | struct of_device *op = esp->dev; | 227 | struct platform_device *op = esp->dev; |
228 | 228 | ||
229 | return dma_map_sg(&op->dev, sg, num_sg, dir); | 229 | return dma_map_sg(&op->dev, sg, num_sg, dir); |
230 | } | 230 | } |
@@ -232,7 +232,7 @@ static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg, | |||
232 | static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr, | 232 | static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr, |
233 | size_t sz, int dir) | 233 | size_t sz, int dir) |
234 | { | 234 | { |
235 | struct of_device *op = esp->dev; | 235 | struct platform_device *op = esp->dev; |
236 | 236 | ||
237 | dma_unmap_single(&op->dev, addr, sz, dir); | 237 | dma_unmap_single(&op->dev, addr, sz, dir); |
238 | } | 238 | } |
@@ -240,7 +240,7 @@ static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr, | |||
240 | static void sbus_esp_unmap_sg(struct esp *esp, struct scatterlist *sg, | 240 | static void sbus_esp_unmap_sg(struct esp *esp, struct scatterlist *sg, |
241 | int num_sg, int dir) | 241 | int num_sg, int dir) |
242 | { | 242 | { |
243 | struct of_device *op = esp->dev; | 243 | struct platform_device *op = esp->dev; |
244 | 244 | ||
245 | dma_unmap_sg(&op->dev, sg, num_sg, dir); | 245 | dma_unmap_sg(&op->dev, sg, num_sg, dir); |
246 | } | 246 | } |
@@ -256,7 +256,7 @@ static void sbus_esp_reset_dma(struct esp *esp) | |||
256 | { | 256 | { |
257 | int can_do_burst16, can_do_burst32, can_do_burst64; | 257 | int can_do_burst16, can_do_burst32, can_do_burst64; |
258 | int can_do_sbus64, lim; | 258 | int can_do_sbus64, lim; |
259 | struct of_device *op; | 259 | struct platform_device *op; |
260 | u32 val; | 260 | u32 val; |
261 | 261 | ||
262 | can_do_burst16 = (esp->bursts & DMA_BURST16) != 0; | 262 | can_do_burst16 = (esp->bursts & DMA_BURST16) != 0; |
@@ -487,8 +487,8 @@ static const struct esp_driver_ops sbus_esp_ops = { | |||
487 | .dma_error = sbus_esp_dma_error, | 487 | .dma_error = sbus_esp_dma_error, |
488 | }; | 488 | }; |
489 | 489 | ||
490 | static int __devinit esp_sbus_probe_one(struct of_device *op, | 490 | static int __devinit esp_sbus_probe_one(struct platform_device *op, |
491 | struct of_device *espdma, | 491 | struct platform_device *espdma, |
492 | int hme) | 492 | int hme) |
493 | { | 493 | { |
494 | struct scsi_host_template *tpnt = &scsi_esp_template; | 494 | struct scsi_host_template *tpnt = &scsi_esp_template; |
@@ -562,11 +562,11 @@ fail: | |||
562 | return err; | 562 | return err; |
563 | } | 563 | } |
564 | 564 | ||
565 | static int __devinit esp_sbus_probe(struct of_device *op, const struct of_device_id *match) | 565 | static int __devinit esp_sbus_probe(struct platform_device *op, const struct of_device_id *match) |
566 | { | 566 | { |
567 | struct device_node *dma_node = NULL; | 567 | struct device_node *dma_node = NULL; |
568 | struct device_node *dp = op->dev.of_node; | 568 | struct device_node *dp = op->dev.of_node; |
569 | struct of_device *dma_of = NULL; | 569 | struct platform_device *dma_of = NULL; |
570 | int hme = 0; | 570 | int hme = 0; |
571 | 571 | ||
572 | if (dp->parent && | 572 | if (dp->parent && |
@@ -585,10 +585,10 @@ static int __devinit esp_sbus_probe(struct of_device *op, const struct of_device | |||
585 | return esp_sbus_probe_one(op, dma_of, hme); | 585 | return esp_sbus_probe_one(op, dma_of, hme); |
586 | } | 586 | } |
587 | 587 | ||
588 | static int __devexit esp_sbus_remove(struct of_device *op) | 588 | static int __devexit esp_sbus_remove(struct platform_device *op) |
589 | { | 589 | { |
590 | struct esp *esp = dev_get_drvdata(&op->dev); | 590 | struct esp *esp = dev_get_drvdata(&op->dev); |
591 | struct of_device *dma_of = esp->dma; | 591 | struct platform_device *dma_of = esp->dma; |
592 | unsigned int irq = esp->host->irq; | 592 | unsigned int irq = esp->host->irq; |
593 | bool is_hme; | 593 | bool is_hme; |
594 | u32 val; | 594 | u32 val; |
diff --git a/drivers/serial/apbuart.c b/drivers/serial/apbuart.c index 0099b8692b60..cc01c650a144 100644 --- a/drivers/serial/apbuart.c +++ b/drivers/serial/apbuart.c | |||
@@ -551,7 +551,7 @@ static struct uart_driver grlib_apbuart_driver = { | |||
551 | /* OF Platform Driver */ | 551 | /* OF Platform Driver */ |
552 | /* ======================================================================== */ | 552 | /* ======================================================================== */ |
553 | 553 | ||
554 | static int __devinit apbuart_probe(struct of_device *op, | 554 | static int __devinit apbuart_probe(struct platform_device *op, |
555 | const struct of_device_id *match) | 555 | const struct of_device_id *match) |
556 | { | 556 | { |
557 | int i = -1; | 557 | int i = -1; |
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 6016179db533..f2b8adcc6c92 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
@@ -1340,7 +1340,7 @@ static struct uart_driver cpm_reg = { | |||
1340 | 1340 | ||
1341 | static int probe_index; | 1341 | static int probe_index; |
1342 | 1342 | ||
1343 | static int __devinit cpm_uart_probe(struct of_device *ofdev, | 1343 | static int __devinit cpm_uart_probe(struct platform_device *ofdev, |
1344 | const struct of_device_id *match) | 1344 | const struct of_device_id *match) |
1345 | { | 1345 | { |
1346 | int index = probe_index++; | 1346 | int index = probe_index++; |
@@ -1364,7 +1364,7 @@ static int __devinit cpm_uart_probe(struct of_device *ofdev, | |||
1364 | return uart_add_one_port(&cpm_reg, &pinfo->port); | 1364 | return uart_add_one_port(&cpm_reg, &pinfo->port); |
1365 | } | 1365 | } |
1366 | 1366 | ||
1367 | static int __devexit cpm_uart_remove(struct of_device *ofdev) | 1367 | static int __devexit cpm_uart_remove(struct platform_device *ofdev) |
1368 | { | 1368 | { |
1369 | struct uart_cpm_port *pinfo = dev_get_drvdata(&ofdev->dev); | 1369 | struct uart_cpm_port *pinfo = dev_get_drvdata(&ofdev->dev); |
1370 | return uart_remove_one_port(&cpm_reg, &pinfo->port); | 1370 | return uart_remove_one_port(&cpm_reg, &pinfo->port); |
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 1a88b363005c..8dedb266f143 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
@@ -1298,7 +1298,7 @@ static struct of_device_id mpc52xx_uart_of_match[] = { | |||
1298 | }; | 1298 | }; |
1299 | 1299 | ||
1300 | static int __devinit | 1300 | static int __devinit |
1301 | mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) | 1301 | mpc52xx_uart_of_probe(struct platform_device *op, const struct of_device_id *match) |
1302 | { | 1302 | { |
1303 | int idx = -1; | 1303 | int idx = -1; |
1304 | unsigned int uartclk; | 1304 | unsigned int uartclk; |
@@ -1369,7 +1369,7 @@ mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) | |||
1369 | } | 1369 | } |
1370 | 1370 | ||
1371 | static int | 1371 | static int |
1372 | mpc52xx_uart_of_remove(struct of_device *op) | 1372 | mpc52xx_uart_of_remove(struct platform_device *op) |
1373 | { | 1373 | { |
1374 | struct uart_port *port = dev_get_drvdata(&op->dev); | 1374 | struct uart_port *port = dev_get_drvdata(&op->dev); |
1375 | dev_set_drvdata(&op->dev, NULL); | 1375 | dev_set_drvdata(&op->dev, NULL); |
@@ -1382,7 +1382,7 @@ mpc52xx_uart_of_remove(struct of_device *op) | |||
1382 | 1382 | ||
1383 | #ifdef CONFIG_PM | 1383 | #ifdef CONFIG_PM |
1384 | static int | 1384 | static int |
1385 | mpc52xx_uart_of_suspend(struct of_device *op, pm_message_t state) | 1385 | mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state) |
1386 | { | 1386 | { |
1387 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); | 1387 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); |
1388 | 1388 | ||
@@ -1393,7 +1393,7 @@ mpc52xx_uart_of_suspend(struct of_device *op, pm_message_t state) | |||
1393 | } | 1393 | } |
1394 | 1394 | ||
1395 | static int | 1395 | static int |
1396 | mpc52xx_uart_of_resume(struct of_device *op) | 1396 | mpc52xx_uart_of_resume(struct platform_device *op) |
1397 | { | 1397 | { |
1398 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); | 1398 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); |
1399 | 1399 | ||
diff --git a/drivers/serial/nwpserial.c b/drivers/serial/nwpserial.c index e65b0d9202a5..de173671e3d0 100644 --- a/drivers/serial/nwpserial.c +++ b/drivers/serial/nwpserial.c | |||
@@ -344,7 +344,7 @@ int nwpserial_register_port(struct uart_port *port) | |||
344 | 344 | ||
345 | mutex_lock(&nwpserial_mutex); | 345 | mutex_lock(&nwpserial_mutex); |
346 | 346 | ||
347 | dn = to_of_device(port->dev)->dev.of_node; | 347 | dn = port->dev->of_node; |
348 | if (dn == NULL) | 348 | if (dn == NULL) |
349 | goto out; | 349 | goto out; |
350 | 350 | ||
diff --git a/drivers/serial/of_serial.c b/drivers/serial/of_serial.c index a48d9080f552..659a695bdad6 100644 --- a/drivers/serial/of_serial.c +++ b/drivers/serial/of_serial.c | |||
@@ -27,7 +27,7 @@ struct of_serial_info { | |||
27 | /* | 27 | /* |
28 | * Fill a struct uart_port for a given device node | 28 | * Fill a struct uart_port for a given device node |
29 | */ | 29 | */ |
30 | static int __devinit of_platform_serial_setup(struct of_device *ofdev, | 30 | static int __devinit of_platform_serial_setup(struct platform_device *ofdev, |
31 | int type, struct uart_port *port) | 31 | int type, struct uart_port *port) |
32 | { | 32 | { |
33 | struct resource resource; | 33 | struct resource resource; |
@@ -80,7 +80,7 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev, | |||
80 | /* | 80 | /* |
81 | * Try to register a serial port | 81 | * Try to register a serial port |
82 | */ | 82 | */ |
83 | static int __devinit of_platform_serial_probe(struct of_device *ofdev, | 83 | static int __devinit of_platform_serial_probe(struct platform_device *ofdev, |
84 | const struct of_device_id *id) | 84 | const struct of_device_id *id) |
85 | { | 85 | { |
86 | struct of_serial_info *info; | 86 | struct of_serial_info *info; |
@@ -134,7 +134,7 @@ out: | |||
134 | /* | 134 | /* |
135 | * Release a line | 135 | * Release a line |
136 | */ | 136 | */ |
137 | static int of_platform_serial_remove(struct of_device *ofdev) | 137 | static int of_platform_serial_remove(struct platform_device *ofdev) |
138 | { | 138 | { |
139 | struct of_serial_info *info = dev_get_drvdata(&ofdev->dev); | 139 | struct of_serial_info *info = dev_get_drvdata(&ofdev->dev); |
140 | switch (info->type) { | 140 | switch (info->type) { |
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index a779e22d213e..c9014868297d 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c | |||
@@ -519,7 +519,7 @@ static struct console sunhv_console = { | |||
519 | .data = &sunhv_reg, | 519 | .data = &sunhv_reg, |
520 | }; | 520 | }; |
521 | 521 | ||
522 | static int __devinit hv_probe(struct of_device *op, const struct of_device_id *match) | 522 | static int __devinit hv_probe(struct platform_device *op, const struct of_device_id *match) |
523 | { | 523 | { |
524 | struct uart_port *port; | 524 | struct uart_port *port; |
525 | unsigned long minor; | 525 | unsigned long minor; |
@@ -598,7 +598,7 @@ out_free_port: | |||
598 | return err; | 598 | return err; |
599 | } | 599 | } |
600 | 600 | ||
601 | static int __devexit hv_remove(struct of_device *dev) | 601 | static int __devexit hv_remove(struct platform_device *dev) |
602 | { | 602 | { |
603 | struct uart_port *port = dev_get_drvdata(&dev->dev); | 603 | struct uart_port *port = dev_get_drvdata(&dev->dev); |
604 | 604 | ||
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 9845fb1cfb1f..5b246b18f42f 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c | |||
@@ -883,7 +883,7 @@ static int sunsab_console_setup(struct console *con, char *options) | |||
883 | printk("Console: ttyS%d (SAB82532)\n", | 883 | printk("Console: ttyS%d (SAB82532)\n", |
884 | (sunsab_reg.minor - 64) + con->index); | 884 | (sunsab_reg.minor - 64) + con->index); |
885 | 885 | ||
886 | sunserial_console_termios(con, to_of_device(up->port.dev)->dev.of_node); | 886 | sunserial_console_termios(con, up->port.dev->of_node); |
887 | 887 | ||
888 | switch (con->cflag & CBAUD) { | 888 | switch (con->cflag & CBAUD) { |
889 | case B150: baud = 150; break; | 889 | case B150: baud = 150; break; |
@@ -954,7 +954,7 @@ static inline struct console *SUNSAB_CONSOLE(void) | |||
954 | #endif | 954 | #endif |
955 | 955 | ||
956 | static int __devinit sunsab_init_one(struct uart_sunsab_port *up, | 956 | static int __devinit sunsab_init_one(struct uart_sunsab_port *up, |
957 | struct of_device *op, | 957 | struct platform_device *op, |
958 | unsigned long offset, | 958 | unsigned long offset, |
959 | int line) | 959 | int line) |
960 | { | 960 | { |
@@ -1006,7 +1006,7 @@ static int __devinit sunsab_init_one(struct uart_sunsab_port *up, | |||
1006 | return 0; | 1006 | return 0; |
1007 | } | 1007 | } |
1008 | 1008 | ||
1009 | static int __devinit sab_probe(struct of_device *op, const struct of_device_id *match) | 1009 | static int __devinit sab_probe(struct platform_device *op, const struct of_device_id *match) |
1010 | { | 1010 | { |
1011 | static int inst; | 1011 | static int inst; |
1012 | struct uart_sunsab_port *up; | 1012 | struct uart_sunsab_port *up; |
@@ -1062,7 +1062,7 @@ out: | |||
1062 | return err; | 1062 | return err; |
1063 | } | 1063 | } |
1064 | 1064 | ||
1065 | static int __devexit sab_remove(struct of_device *op) | 1065 | static int __devexit sab_remove(struct platform_device *op) |
1066 | { | 1066 | { |
1067 | struct uart_sunsab_port *up = dev_get_drvdata(&op->dev); | 1067 | struct uart_sunsab_port *up = dev_get_drvdata(&op->dev); |
1068 | 1068 | ||
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 3cdf74822db5..551ebfe3ccbb 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c | |||
@@ -1200,7 +1200,7 @@ static int __devinit sunsu_kbd_ms_init(struct uart_sunsu_port *up) | |||
1200 | return -ENODEV; | 1200 | return -ENODEV; |
1201 | 1201 | ||
1202 | printk("%s: %s port at %llx, irq %u\n", | 1202 | printk("%s: %s port at %llx, irq %u\n", |
1203 | to_of_device(up->port.dev)->dev.of_node->full_name, | 1203 | up->port.dev->of_node->full_name, |
1204 | (up->su_type == SU_PORT_KBD) ? "Keyboard" : "Mouse", | 1204 | (up->su_type == SU_PORT_KBD) ? "Keyboard" : "Mouse", |
1205 | (unsigned long long) up->port.mapbase, | 1205 | (unsigned long long) up->port.mapbase, |
1206 | up->port.irq); | 1206 | up->port.irq); |
@@ -1352,7 +1352,7 @@ static int __init sunsu_console_setup(struct console *co, char *options) | |||
1352 | spin_lock_init(&port->lock); | 1352 | spin_lock_init(&port->lock); |
1353 | 1353 | ||
1354 | /* Get firmware console settings. */ | 1354 | /* Get firmware console settings. */ |
1355 | sunserial_console_termios(co, to_of_device(port->dev)->dev.of_node); | 1355 | sunserial_console_termios(co, port->dev->of_node); |
1356 | 1356 | ||
1357 | memset(&termios, 0, sizeof(struct ktermios)); | 1357 | memset(&termios, 0, sizeof(struct ktermios)); |
1358 | termios.c_cflag = co->cflag; | 1358 | termios.c_cflag = co->cflag; |
@@ -1406,7 +1406,7 @@ static enum su_type __devinit su_get_type(struct device_node *dp) | |||
1406 | return SU_PORT_PORT; | 1406 | return SU_PORT_PORT; |
1407 | } | 1407 | } |
1408 | 1408 | ||
1409 | static int __devinit su_probe(struct of_device *op, const struct of_device_id *match) | 1409 | static int __devinit su_probe(struct platform_device *op, const struct of_device_id *match) |
1410 | { | 1410 | { |
1411 | static int inst; | 1411 | static int inst; |
1412 | struct device_node *dp = op->dev.of_node; | 1412 | struct device_node *dp = op->dev.of_node; |
@@ -1497,7 +1497,7 @@ out_unmap: | |||
1497 | return err; | 1497 | return err; |
1498 | } | 1498 | } |
1499 | 1499 | ||
1500 | static int __devexit su_remove(struct of_device *op) | 1500 | static int __devexit su_remove(struct platform_device *op) |
1501 | { | 1501 | { |
1502 | struct uart_sunsu_port *up = dev_get_drvdata(&op->dev); | 1502 | struct uart_sunsu_port *up = dev_get_drvdata(&op->dev); |
1503 | bool kbdms = false; | 1503 | bool kbdms = false; |
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index d1e6bcb59546..c1967ac1c07f 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c | |||
@@ -1230,7 +1230,7 @@ static int __init sunzilog_console_setup(struct console *con, char *options) | |||
1230 | (sunzilog_reg.minor - 64) + con->index, con->index); | 1230 | (sunzilog_reg.minor - 64) + con->index, con->index); |
1231 | 1231 | ||
1232 | /* Get firmware console settings. */ | 1232 | /* Get firmware console settings. */ |
1233 | sunserial_console_termios(con, to_of_device(up->port.dev)->dev.of_node); | 1233 | sunserial_console_termios(con, up->port.dev->of_node); |
1234 | 1234 | ||
1235 | /* Firmware console speed is limited to 150-->38400 baud so | 1235 | /* Firmware console speed is limited to 150-->38400 baud so |
1236 | * this hackish cflag thing is OK. | 1236 | * this hackish cflag thing is OK. |
@@ -1399,7 +1399,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) | |||
1399 | 1399 | ||
1400 | static int zilog_irq = -1; | 1400 | static int zilog_irq = -1; |
1401 | 1401 | ||
1402 | static int __devinit zs_probe(struct of_device *op, const struct of_device_id *match) | 1402 | static int __devinit zs_probe(struct platform_device *op, const struct of_device_id *match) |
1403 | { | 1403 | { |
1404 | static int kbm_inst, uart_inst; | 1404 | static int kbm_inst, uart_inst; |
1405 | int inst; | 1405 | int inst; |
@@ -1516,7 +1516,7 @@ static void __devexit zs_remove_one(struct uart_sunzilog_port *up) | |||
1516 | uart_remove_one_port(&sunzilog_reg, &up->port); | 1516 | uart_remove_one_port(&sunzilog_reg, &up->port); |
1517 | } | 1517 | } |
1518 | 1518 | ||
1519 | static int __devexit zs_remove(struct of_device *op) | 1519 | static int __devexit zs_remove(struct platform_device *op) |
1520 | { | 1520 | { |
1521 | struct uart_sunzilog_port *up = dev_get_drvdata(&op->dev); | 1521 | struct uart_sunzilog_port *up = dev_get_drvdata(&op->dev); |
1522 | struct zilog_layout __iomem *regs; | 1522 | struct zilog_layout __iomem *regs; |
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c index caf085d3a76a..9b03d7b3e456 100644 --- a/drivers/serial/uartlite.c +++ b/drivers/serial/uartlite.c | |||
@@ -584,7 +584,7 @@ static struct platform_driver ulite_platform_driver = { | |||
584 | */ | 584 | */ |
585 | #if defined(CONFIG_OF) && (defined(CONFIG_PPC32) || defined(CONFIG_MICROBLAZE)) | 585 | #if defined(CONFIG_OF) && (defined(CONFIG_PPC32) || defined(CONFIG_MICROBLAZE)) |
586 | static int __devinit | 586 | static int __devinit |
587 | ulite_of_probe(struct of_device *op, const struct of_device_id *match) | 587 | ulite_of_probe(struct platform_device *op, const struct of_device_id *match) |
588 | { | 588 | { |
589 | struct resource res; | 589 | struct resource res; |
590 | const unsigned int *id; | 590 | const unsigned int *id; |
@@ -605,7 +605,7 @@ ulite_of_probe(struct of_device *op, const struct of_device_id *match) | |||
605 | return ulite_assign(&op->dev, id ? *id : -1, res.start, irq); | 605 | return ulite_assign(&op->dev, id ? *id : -1, res.start, irq); |
606 | } | 606 | } |
607 | 607 | ||
608 | static int __devexit ulite_of_remove(struct of_device *op) | 608 | static int __devexit ulite_of_remove(struct platform_device *op) |
609 | { | 609 | { |
610 | return ulite_release(&op->dev); | 610 | return ulite_release(&op->dev); |
611 | } | 611 | } |
diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c index 907b06f5c447..3f4848e2174a 100644 --- a/drivers/serial/ucc_uart.c +++ b/drivers/serial/ucc_uart.c | |||
@@ -1194,7 +1194,7 @@ static void uart_firmware_cont(const struct firmware *fw, void *context) | |||
1194 | release_firmware(fw); | 1194 | release_firmware(fw); |
1195 | } | 1195 | } |
1196 | 1196 | ||
1197 | static int ucc_uart_probe(struct of_device *ofdev, | 1197 | static int ucc_uart_probe(struct platform_device *ofdev, |
1198 | const struct of_device_id *match) | 1198 | const struct of_device_id *match) |
1199 | { | 1199 | { |
1200 | struct device_node *np = ofdev->dev.of_node; | 1200 | struct device_node *np = ofdev->dev.of_node; |
@@ -1462,7 +1462,7 @@ static int ucc_uart_probe(struct of_device *ofdev, | |||
1462 | return 0; | 1462 | return 0; |
1463 | } | 1463 | } |
1464 | 1464 | ||
1465 | static int ucc_uart_remove(struct of_device *ofdev) | 1465 | static int ucc_uart_remove(struct platform_device *ofdev) |
1466 | { | 1466 | { |
1467 | struct uart_qe_port *qe_port = dev_get_drvdata(&ofdev->dev); | 1467 | struct uart_qe_port *qe_port = dev_get_drvdata(&ofdev->dev); |
1468 | 1468 | ||
diff --git a/drivers/spi/mpc512x_psc_spi.c b/drivers/spi/mpc512x_psc_spi.c index 10baac3f8ea5..cddbfceb324f 100644 --- a/drivers/spi/mpc512x_psc_spi.c +++ b/drivers/spi/mpc512x_psc_spi.c | |||
@@ -507,7 +507,7 @@ static int __exit mpc512x_psc_spi_do_remove(struct device *dev) | |||
507 | return 0; | 507 | return 0; |
508 | } | 508 | } |
509 | 509 | ||
510 | static int __init mpc512x_psc_spi_of_probe(struct of_device *op, | 510 | static int __init mpc512x_psc_spi_of_probe(struct platform_device *op, |
511 | const struct of_device_id *match) | 511 | const struct of_device_id *match) |
512 | { | 512 | { |
513 | const u32 *regaddr_p; | 513 | const u32 *regaddr_p; |
@@ -539,7 +539,7 @@ static int __init mpc512x_psc_spi_of_probe(struct of_device *op, | |||
539 | irq_of_parse_and_map(op->dev.of_node, 0), id); | 539 | irq_of_parse_and_map(op->dev.of_node, 0), id); |
540 | } | 540 | } |
541 | 541 | ||
542 | static int __exit mpc512x_psc_spi_of_remove(struct of_device *op) | 542 | static int __exit mpc512x_psc_spi_of_remove(struct platform_device *op) |
543 | { | 543 | { |
544 | return mpc512x_psc_spi_do_remove(&op->dev); | 544 | return mpc512x_psc_spi_do_remove(&op->dev); |
545 | } | 545 | } |
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c index 66d170147dcc..983fbbfce76e 100644 --- a/drivers/spi/mpc52xx_psc_spi.c +++ b/drivers/spi/mpc52xx_psc_spi.c | |||
@@ -465,7 +465,7 @@ static int __exit mpc52xx_psc_spi_do_remove(struct device *dev) | |||
465 | return 0; | 465 | return 0; |
466 | } | 466 | } |
467 | 467 | ||
468 | static int __init mpc52xx_psc_spi_of_probe(struct of_device *op, | 468 | static int __init mpc52xx_psc_spi_of_probe(struct platform_device *op, |
469 | const struct of_device_id *match) | 469 | const struct of_device_id *match) |
470 | { | 470 | { |
471 | const u32 *regaddr_p; | 471 | const u32 *regaddr_p; |
@@ -495,7 +495,7 @@ static int __init mpc52xx_psc_spi_of_probe(struct of_device *op, | |||
495 | irq_of_parse_and_map(op->dev.of_node, 0), id); | 495 | irq_of_parse_and_map(op->dev.of_node, 0), id); |
496 | } | 496 | } |
497 | 497 | ||
498 | static int __exit mpc52xx_psc_spi_of_remove(struct of_device *op) | 498 | static int __exit mpc52xx_psc_spi_of_remove(struct platform_device *op) |
499 | { | 499 | { |
500 | return mpc52xx_psc_spi_do_remove(&op->dev); | 500 | return mpc52xx_psc_spi_do_remove(&op->dev); |
501 | } | 501 | } |
diff --git a/drivers/spi/mpc52xx_spi.c b/drivers/spi/mpc52xx_spi.c index 56136ff00e01..ec9f0b1bf864 100644 --- a/drivers/spi/mpc52xx_spi.c +++ b/drivers/spi/mpc52xx_spi.c | |||
@@ -390,7 +390,7 @@ static int mpc52xx_spi_transfer(struct spi_device *spi, struct spi_message *m) | |||
390 | /* | 390 | /* |
391 | * OF Platform Bus Binding | 391 | * OF Platform Bus Binding |
392 | */ | 392 | */ |
393 | static int __devinit mpc52xx_spi_probe(struct of_device *op, | 393 | static int __devinit mpc52xx_spi_probe(struct platform_device *op, |
394 | const struct of_device_id *match) | 394 | const struct of_device_id *match) |
395 | { | 395 | { |
396 | struct spi_master *master; | 396 | struct spi_master *master; |
@@ -530,7 +530,7 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op, | |||
530 | return rc; | 530 | return rc; |
531 | } | 531 | } |
532 | 532 | ||
533 | static int __devexit mpc52xx_spi_remove(struct of_device *op) | 533 | static int __devexit mpc52xx_spi_remove(struct platform_device *op) |
534 | { | 534 | { |
535 | struct spi_master *master = dev_get_drvdata(&op->dev); | 535 | struct spi_master *master = dev_get_drvdata(&op->dev); |
536 | struct mpc52xx_spi *ms = spi_master_get_devdata(master); | 536 | struct mpc52xx_spi *ms = spi_master_get_devdata(master); |
diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c index aad9ae1b9c69..d31b57f7baaf 100644 --- a/drivers/spi/spi_mpc8xxx.c +++ b/drivers/spi/spi_mpc8xxx.c | |||
@@ -1236,7 +1236,7 @@ static int of_mpc8xxx_spi_free_chipselects(struct device *dev) | |||
1236 | return 0; | 1236 | return 0; |
1237 | } | 1237 | } |
1238 | 1238 | ||
1239 | static int __devinit of_mpc8xxx_spi_probe(struct of_device *ofdev, | 1239 | static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev, |
1240 | const struct of_device_id *ofid) | 1240 | const struct of_device_id *ofid) |
1241 | { | 1241 | { |
1242 | struct device *dev = &ofdev->dev; | 1242 | struct device *dev = &ofdev->dev; |
@@ -1308,7 +1308,7 @@ err_clk: | |||
1308 | return ret; | 1308 | return ret; |
1309 | } | 1309 | } |
1310 | 1310 | ||
1311 | static int __devexit of_mpc8xxx_spi_remove(struct of_device *ofdev) | 1311 | static int __devexit of_mpc8xxx_spi_remove(struct platform_device *ofdev) |
1312 | { | 1312 | { |
1313 | int ret; | 1313 | int ret; |
1314 | 1314 | ||
diff --git a/drivers/spi/spi_ppc4xx.c b/drivers/spi/spi_ppc4xx.c index 0f5fa7e2a550..80e172d3e72a 100644 --- a/drivers/spi/spi_ppc4xx.c +++ b/drivers/spi/spi_ppc4xx.c | |||
@@ -388,9 +388,9 @@ static void free_gpios(struct ppc4xx_spi *hw) | |||
388 | } | 388 | } |
389 | 389 | ||
390 | /* | 390 | /* |
391 | * of_device layer stuff... | 391 | * platform_device layer stuff... |
392 | */ | 392 | */ |
393 | static int __init spi_ppc4xx_of_probe(struct of_device *op, | 393 | static int __init spi_ppc4xx_of_probe(struct platform_device *op, |
394 | const struct of_device_id *match) | 394 | const struct of_device_id *match) |
395 | { | 395 | { |
396 | struct ppc4xx_spi *hw; | 396 | struct ppc4xx_spi *hw; |
@@ -565,7 +565,7 @@ free_master: | |||
565 | return ret; | 565 | return ret; |
566 | } | 566 | } |
567 | 567 | ||
568 | static int __exit spi_ppc4xx_of_remove(struct of_device *op) | 568 | static int __exit spi_ppc4xx_of_remove(struct platform_device *op) |
569 | { | 569 | { |
570 | struct spi_master *master = dev_get_drvdata(&op->dev); | 570 | struct spi_master *master = dev_get_drvdata(&op->dev); |
571 | struct ppc4xx_spi *hw = spi_master_get_devdata(master); | 571 | struct ppc4xx_spi *hw = spi_master_get_devdata(master); |
diff --git a/drivers/spi/xilinx_spi_of.c b/drivers/spi/xilinx_spi_of.c index f53d3f6b9f61..b66c2dbf20a5 100644 --- a/drivers/spi/xilinx_spi_of.c +++ b/drivers/spi/xilinx_spi_of.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include "xilinx_spi.h" | 38 | #include "xilinx_spi.h" |
39 | 39 | ||
40 | 40 | ||
41 | static int __devinit xilinx_spi_of_probe(struct of_device *ofdev, | 41 | static int __devinit xilinx_spi_of_probe(struct platform_device *ofdev, |
42 | const struct of_device_id *match) | 42 | const struct of_device_id *match) |
43 | { | 43 | { |
44 | struct spi_master *master; | 44 | struct spi_master *master; |
@@ -84,7 +84,7 @@ static int __devinit xilinx_spi_of_probe(struct of_device *ofdev, | |||
84 | return 0; | 84 | return 0; |
85 | } | 85 | } |
86 | 86 | ||
87 | static int __devexit xilinx_spi_remove(struct of_device *ofdev) | 87 | static int __devexit xilinx_spi_remove(struct platform_device *ofdev) |
88 | { | 88 | { |
89 | xilinx_spi_deinit(dev_get_drvdata(&ofdev->dev)); | 89 | xilinx_spi_deinit(dev_get_drvdata(&ofdev->dev)); |
90 | dev_set_drvdata(&ofdev->dev, 0); | 90 | dev_set_drvdata(&ofdev->dev, 0); |
@@ -93,7 +93,7 @@ static int __devexit xilinx_spi_remove(struct of_device *ofdev) | |||
93 | return 0; | 93 | return 0; |
94 | } | 94 | } |
95 | 95 | ||
96 | static int __exit xilinx_spi_of_remove(struct of_device *op) | 96 | static int __exit xilinx_spi_of_remove(struct platform_device *op) |
97 | { | 97 | { |
98 | return xilinx_spi_remove(op); | 98 | return xilinx_spi_remove(op); |
99 | } | 99 | } |
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index 49ab9fa9ffa7..ed7457bc24ea 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c | |||
@@ -61,7 +61,7 @@ static struct pci_device_id rtl8180_pci_id_tbl[] __devinitdata = { | |||
61 | }; | 61 | }; |
62 | 62 | ||
63 | 63 | ||
64 | static char *ifname = "wlan%d"; | 64 | static char ifname[IFNAMSIZ] = "wlan%d"; |
65 | static int hwseqnum = 0; | 65 | static int hwseqnum = 0; |
66 | static int hwwep = 0; | 66 | static int hwwep = 0; |
67 | static int channels = 0x3fff; | 67 | static int channels = 0x3fff; |
@@ -72,7 +72,7 @@ MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>"); | |||
72 | MODULE_DESCRIPTION("Linux driver for Realtek RTL8180 / RTL8185 WiFi cards"); | 72 | MODULE_DESCRIPTION("Linux driver for Realtek RTL8180 / RTL8185 WiFi cards"); |
73 | 73 | ||
74 | 74 | ||
75 | module_param(ifname, charp, S_IRUGO|S_IWUSR); | 75 | module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO|S_IWUSR); |
76 | module_param(hwseqnum, int, S_IRUGO|S_IWUSR); | 76 | module_param(hwseqnum, int, S_IRUGO|S_IWUSR); |
77 | module_param(hwwep, int, S_IRUGO|S_IWUSR); | 77 | module_param(hwwep, int, S_IRUGO|S_IWUSR); |
78 | module_param(channels, int, S_IRUGO|S_IWUSR); | 78 | module_param(channels, int, S_IRUGO|S_IWUSR); |
@@ -3609,7 +3609,7 @@ static int __devinit rtl8180_pci_probe(struct pci_dev *pdev, | |||
3609 | 3609 | ||
3610 | if (dev_alloc_name(dev, ifname) < 0) { | 3610 | if (dev_alloc_name(dev, ifname) < 0) { |
3611 | DMESG("Oops: devname already taken! Trying wlan%%d...\n"); | 3611 | DMESG("Oops: devname already taken! Trying wlan%%d...\n"); |
3612 | ifname = "wlan%d"; | 3612 | strcpy(ifname, "wlan%d"); |
3613 | dev_alloc_name(dev, ifname); | 3613 | dev_alloc_name(dev, ifname); |
3614 | } | 3614 | } |
3615 | 3615 | ||
diff --git a/drivers/staging/rtl8192e/r8192E_core.c b/drivers/staging/rtl8192e/r8192E_core.c index 4cd071adf84b..17a806f9ee77 100644 --- a/drivers/staging/rtl8192e/r8192E_core.c +++ b/drivers/staging/rtl8192e/r8192E_core.c | |||
@@ -112,7 +112,7 @@ static const struct pci_device_id rtl8192_pci_id_tbl[] __devinitdata = { | |||
112 | {} | 112 | {} |
113 | }; | 113 | }; |
114 | 114 | ||
115 | static char* ifname = "wlan%d"; | 115 | static char ifname[IFNAMSIZ] = "wlan%d"; |
116 | static int hwwep = 1; //default use hw. set 0 to use software security | 116 | static int hwwep = 1; //default use hw. set 0 to use software security |
117 | static int channels = 0x3fff; | 117 | static int channels = 0x3fff; |
118 | 118 | ||
@@ -123,7 +123,7 @@ MODULE_DEVICE_TABLE(pci, rtl8192_pci_id_tbl); | |||
123 | MODULE_DESCRIPTION("Linux driver for Realtek RTL819x WiFi cards"); | 123 | MODULE_DESCRIPTION("Linux driver for Realtek RTL819x WiFi cards"); |
124 | 124 | ||
125 | 125 | ||
126 | module_param(ifname, charp, S_IRUGO|S_IWUSR ); | 126 | module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO|S_IWUSR); |
127 | //module_param(hwseqnum,int, S_IRUGO|S_IWUSR); | 127 | //module_param(hwseqnum,int, S_IRUGO|S_IWUSR); |
128 | module_param(hwwep,int, S_IRUGO|S_IWUSR); | 128 | module_param(hwwep,int, S_IRUGO|S_IWUSR); |
129 | module_param(channels,int, S_IRUGO|S_IWUSR); | 129 | module_param(channels,int, S_IRUGO|S_IWUSR); |
@@ -6446,7 +6446,7 @@ static int __devinit rtl8192_pci_probe(struct pci_dev *pdev, | |||
6446 | 6446 | ||
6447 | if (dev_alloc_name(dev, ifname) < 0){ | 6447 | if (dev_alloc_name(dev, ifname) < 0){ |
6448 | RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n"); | 6448 | RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n"); |
6449 | ifname = "wlan%d"; | 6449 | strcpy(ifname, "wlan%d"); |
6450 | dev_alloc_name(dev, ifname); | 6450 | dev_alloc_name(dev, ifname); |
6451 | } | 6451 | } |
6452 | 6452 | ||
diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c index 6970c97713d8..df5b52baf893 100644 --- a/drivers/staging/rtl8192su/r8192U_core.c +++ b/drivers/staging/rtl8192su/r8192U_core.c | |||
@@ -144,13 +144,13 @@ MODULE_VERSION("V 1.1"); | |||
144 | MODULE_DEVICE_TABLE(usb, rtl8192_usb_id_tbl); | 144 | MODULE_DEVICE_TABLE(usb, rtl8192_usb_id_tbl); |
145 | MODULE_DESCRIPTION("Linux driver for Realtek RTL8192 USB WiFi cards"); | 145 | MODULE_DESCRIPTION("Linux driver for Realtek RTL8192 USB WiFi cards"); |
146 | 146 | ||
147 | static char* ifname = "wlan%d"; | 147 | static char ifname[IFNAMSIZ] = "wlan%d"; |
148 | static int hwwep = 1; //default use hw. set 0 to use software security | 148 | static int hwwep = 1; //default use hw. set 0 to use software security |
149 | static int channels = 0x3fff; | 149 | static int channels = 0x3fff; |
150 | 150 | ||
151 | 151 | ||
152 | 152 | ||
153 | module_param(ifname, charp, S_IRUGO|S_IWUSR ); | 153 | module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO|S_IWUSR); |
154 | //module_param(hwseqnum,int, S_IRUGO|S_IWUSR); | 154 | //module_param(hwseqnum,int, S_IRUGO|S_IWUSR); |
155 | module_param(hwwep,int, S_IRUGO|S_IWUSR); | 155 | module_param(hwwep,int, S_IRUGO|S_IWUSR); |
156 | module_param(channels,int, S_IRUGO|S_IWUSR); | 156 | module_param(channels,int, S_IRUGO|S_IWUSR); |
@@ -7406,7 +7406,7 @@ static int __devinit rtl8192_usb_probe(struct usb_interface *intf, | |||
7406 | 7406 | ||
7407 | if (dev_alloc_name(dev, ifname) < 0){ | 7407 | if (dev_alloc_name(dev, ifname) < 0){ |
7408 | RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n"); | 7408 | RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n"); |
7409 | ifname = "wlan%d"; | 7409 | strcpy(ifname, "wlan%d"); |
7410 | dev_alloc_name(dev, ifname); | 7410 | dev_alloc_name(dev, ifname); |
7411 | } | 7411 | } |
7412 | 7412 | ||
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 5b3f555e01c9..ea071a5b6eee 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c | |||
@@ -1577,6 +1577,7 @@ static void cmvs_file_name(struct uea_softc *sc, char *const cmv_name, int ver) | |||
1577 | char file_arr[] = "CMVxy.bin"; | 1577 | char file_arr[] = "CMVxy.bin"; |
1578 | char *file; | 1578 | char *file; |
1579 | 1579 | ||
1580 | kparam_block_sysfs_write(cmv_file); | ||
1580 | /* set proper name corresponding modem version and line type */ | 1581 | /* set proper name corresponding modem version and line type */ |
1581 | if (cmv_file[sc->modem_index] == NULL) { | 1582 | if (cmv_file[sc->modem_index] == NULL) { |
1582 | if (UEA_CHIP_VERSION(sc) == ADI930) | 1583 | if (UEA_CHIP_VERSION(sc) == ADI930) |
@@ -1595,6 +1596,7 @@ static void cmvs_file_name(struct uea_softc *sc, char *const cmv_name, int ver) | |||
1595 | strlcat(cmv_name, file, UEA_FW_NAME_MAX); | 1596 | strlcat(cmv_name, file, UEA_FW_NAME_MAX); |
1596 | if (ver == 2) | 1597 | if (ver == 2) |
1597 | strlcat(cmv_name, ".v2", UEA_FW_NAME_MAX); | 1598 | strlcat(cmv_name, ".v2", UEA_FW_NAME_MAX); |
1599 | kparam_unblock_sysfs_write(cmv_file); | ||
1598 | } | 1600 | } |
1599 | 1601 | ||
1600 | static int request_cmvs_old(struct uea_softc *sc, | 1602 | static int request_cmvs_old(struct uea_softc *sc, |
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index 9648b75f0283..a5ea2c1d8c93 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c | |||
@@ -2398,7 +2398,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | |||
2398 | EXPORT_SYMBOL(usb_gadget_unregister_driver); | 2398 | EXPORT_SYMBOL(usb_gadget_unregister_driver); |
2399 | 2399 | ||
2400 | /* udc structure's alloc and setup, include ep-param alloc */ | 2400 | /* udc structure's alloc and setup, include ep-param alloc */ |
2401 | static struct qe_udc __devinit *qe_udc_config(struct of_device *ofdev) | 2401 | static struct qe_udc __devinit *qe_udc_config(struct platform_device *ofdev) |
2402 | { | 2402 | { |
2403 | struct qe_udc *udc; | 2403 | struct qe_udc *udc; |
2404 | struct device_node *np = ofdev->dev.of_node; | 2404 | struct device_node *np = ofdev->dev.of_node; |
@@ -2523,7 +2523,7 @@ static void qe_udc_release(struct device *dev) | |||
2523 | } | 2523 | } |
2524 | 2524 | ||
2525 | /* Driver probe functions */ | 2525 | /* Driver probe functions */ |
2526 | static int __devinit qe_udc_probe(struct of_device *ofdev, | 2526 | static int __devinit qe_udc_probe(struct platform_device *ofdev, |
2527 | const struct of_device_id *match) | 2527 | const struct of_device_id *match) |
2528 | { | 2528 | { |
2529 | struct device_node *np = ofdev->dev.of_node; | 2529 | struct device_node *np = ofdev->dev.of_node; |
@@ -2679,18 +2679,18 @@ err1: | |||
2679 | } | 2679 | } |
2680 | 2680 | ||
2681 | #ifdef CONFIG_PM | 2681 | #ifdef CONFIG_PM |
2682 | static int qe_udc_suspend(struct of_device *dev, pm_message_t state) | 2682 | static int qe_udc_suspend(struct platform_device *dev, pm_message_t state) |
2683 | { | 2683 | { |
2684 | return -ENOTSUPP; | 2684 | return -ENOTSUPP; |
2685 | } | 2685 | } |
2686 | 2686 | ||
2687 | static int qe_udc_resume(struct of_device *dev) | 2687 | static int qe_udc_resume(struct platform_device *dev) |
2688 | { | 2688 | { |
2689 | return -ENOTSUPP; | 2689 | return -ENOTSUPP; |
2690 | } | 2690 | } |
2691 | #endif | 2691 | #endif |
2692 | 2692 | ||
2693 | static int __devexit qe_udc_remove(struct of_device *ofdev) | 2693 | static int __devexit qe_udc_remove(struct platform_device *ofdev) |
2694 | { | 2694 | { |
2695 | struct qe_ep *ep; | 2695 | struct qe_ep *ep; |
2696 | unsigned int size; | 2696 | unsigned int size; |
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index 5aec92866ab3..335ee699fd85 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c | |||
@@ -106,7 +106,7 @@ ppc44x_enable_bmt(struct device_node *dn) | |||
106 | 106 | ||
107 | 107 | ||
108 | static int __devinit | 108 | static int __devinit |
109 | ehci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) | 109 | ehci_hcd_ppc_of_probe(struct platform_device *op, const struct of_device_id *match) |
110 | { | 110 | { |
111 | struct device_node *dn = op->dev.of_node; | 111 | struct device_node *dn = op->dev.of_node; |
112 | struct usb_hcd *hcd; | 112 | struct usb_hcd *hcd; |
@@ -210,7 +210,7 @@ err_rmr: | |||
210 | } | 210 | } |
211 | 211 | ||
212 | 212 | ||
213 | static int ehci_hcd_ppc_of_remove(struct of_device *op) | 213 | static int ehci_hcd_ppc_of_remove(struct platform_device *op) |
214 | { | 214 | { |
215 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 215 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); |
216 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 216 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
@@ -253,7 +253,7 @@ static int ehci_hcd_ppc_of_remove(struct of_device *op) | |||
253 | } | 253 | } |
254 | 254 | ||
255 | 255 | ||
256 | static int ehci_hcd_ppc_of_shutdown(struct of_device *op) | 256 | static int ehci_hcd_ppc_of_shutdown(struct platform_device *op) |
257 | { | 257 | { |
258 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 258 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); |
259 | 259 | ||
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c index 4899f451add9..6c8076ad821d 100644 --- a/drivers/usb/host/ehci-xilinx-of.c +++ b/drivers/usb/host/ehci-xilinx-of.c | |||
@@ -140,7 +140,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = { | |||
140 | 140 | ||
141 | /** | 141 | /** |
142 | * ehci_hcd_xilinx_of_probe - Probe method for the USB host controller | 142 | * ehci_hcd_xilinx_of_probe - Probe method for the USB host controller |
143 | * @op: pointer to the of_device to which the host controller bound | 143 | * @op: pointer to the platform_device bound to the host controller |
144 | * @match: pointer to of_device_id structure, not used | 144 | * @match: pointer to of_device_id structure, not used |
145 | * | 145 | * |
146 | * This function requests resources and sets up appropriate properties for the | 146 | * This function requests resources and sets up appropriate properties for the |
@@ -149,7 +149,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = { | |||
149 | * entry, and sets an appropriate value for hcd->has_tt. | 149 | * entry, and sets an appropriate value for hcd->has_tt. |
150 | */ | 150 | */ |
151 | static int __devinit | 151 | static int __devinit |
152 | ehci_hcd_xilinx_of_probe(struct of_device *op, const struct of_device_id *match) | 152 | ehci_hcd_xilinx_of_probe(struct platform_device *op, const struct of_device_id *match) |
153 | { | 153 | { |
154 | struct device_node *dn = op->dev.of_node; | 154 | struct device_node *dn = op->dev.of_node; |
155 | struct usb_hcd *hcd; | 155 | struct usb_hcd *hcd; |
@@ -242,12 +242,12 @@ err_rmr: | |||
242 | 242 | ||
243 | /** | 243 | /** |
244 | * ehci_hcd_xilinx_of_remove - shutdown hcd and release resources | 244 | * ehci_hcd_xilinx_of_remove - shutdown hcd and release resources |
245 | * @op: pointer to of_device structure that is to be removed | 245 | * @op: pointer to platform_device structure that is to be removed |
246 | * | 246 | * |
247 | * Remove the hcd structure, and release resources that has been requested | 247 | * Remove the hcd structure, and release resources that has been requested |
248 | * during probe. | 248 | * during probe. |
249 | */ | 249 | */ |
250 | static int ehci_hcd_xilinx_of_remove(struct of_device *op) | 250 | static int ehci_hcd_xilinx_of_remove(struct platform_device *op) |
251 | { | 251 | { |
252 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 252 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); |
253 | dev_set_drvdata(&op->dev, NULL); | 253 | dev_set_drvdata(&op->dev, NULL); |
@@ -266,11 +266,11 @@ static int ehci_hcd_xilinx_of_remove(struct of_device *op) | |||
266 | 266 | ||
267 | /** | 267 | /** |
268 | * ehci_hcd_xilinx_of_shutdown - shutdown the hcd | 268 | * ehci_hcd_xilinx_of_shutdown - shutdown the hcd |
269 | * @op: pointer to of_device structure that is to be removed | 269 | * @op: pointer to platform_device structure that is to be removed |
270 | * | 270 | * |
271 | * Properly shutdown the hcd, call driver's shutdown routine. | 271 | * Properly shutdown the hcd, call driver's shutdown routine. |
272 | */ | 272 | */ |
273 | static int ehci_hcd_xilinx_of_shutdown(struct of_device *op) | 273 | static int ehci_hcd_xilinx_of_shutdown(struct platform_device *op) |
274 | { | 274 | { |
275 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 275 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); |
276 | 276 | ||
diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index c7c8392a88b9..20092a27a1e8 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c | |||
@@ -561,7 +561,7 @@ static const struct hc_driver fhci_driver = { | |||
561 | .hub_control = fhci_hub_control, | 561 | .hub_control = fhci_hub_control, |
562 | }; | 562 | }; |
563 | 563 | ||
564 | static int __devinit of_fhci_probe(struct of_device *ofdev, | 564 | static int __devinit of_fhci_probe(struct platform_device *ofdev, |
565 | const struct of_device_id *ofid) | 565 | const struct of_device_id *ofid) |
566 | { | 566 | { |
567 | struct device *dev = &ofdev->dev; | 567 | struct device *dev = &ofdev->dev; |
@@ -801,7 +801,7 @@ static int __devexit fhci_remove(struct device *dev) | |||
801 | return 0; | 801 | return 0; |
802 | } | 802 | } |
803 | 803 | ||
804 | static int __devexit of_fhci_remove(struct of_device *ofdev) | 804 | static int __devexit of_fhci_remove(struct platform_device *ofdev) |
805 | { | 805 | { |
806 | return fhci_remove(&ofdev->dev); | 806 | return fhci_remove(&ofdev->dev); |
807 | } | 807 | } |
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index ec85d0c3cc3e..3b28dbfca058 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #endif | 27 | #endif |
28 | 28 | ||
29 | #ifdef CONFIG_PPC_OF | 29 | #ifdef CONFIG_PPC_OF |
30 | static int of_isp1760_probe(struct of_device *dev, | 30 | static int of_isp1760_probe(struct platform_device *dev, |
31 | const struct of_device_id *match) | 31 | const struct of_device_id *match) |
32 | { | 32 | { |
33 | struct usb_hcd *hcd; | 33 | struct usb_hcd *hcd; |
@@ -95,7 +95,7 @@ release_reg: | |||
95 | return ret; | 95 | return ret; |
96 | } | 96 | } |
97 | 97 | ||
98 | static int of_isp1760_remove(struct of_device *dev) | 98 | static int of_isp1760_remove(struct platform_device *dev) |
99 | { | 99 | { |
100 | struct usb_hcd *hcd = dev_get_drvdata(&dev->dev); | 100 | struct usb_hcd *hcd = dev_get_drvdata(&dev->dev); |
101 | 101 | ||
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c index cd74bbdd007c..653d6a60edb5 100644 --- a/drivers/usb/host/ohci-pnx4008.c +++ b/drivers/usb/host/ohci-pnx4008.c | |||
@@ -329,7 +329,7 @@ static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev) | |||
329 | memset(&i2c_info, 0, sizeof(struct i2c_board_info)); | 329 | memset(&i2c_info, 0, sizeof(struct i2c_board_info)); |
330 | strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE); | 330 | strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE); |
331 | isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info, | 331 | isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info, |
332 | normal_i2c); | 332 | normal_i2c, NULL); |
333 | i2c_put_adapter(i2c_adap); | 333 | i2c_put_adapter(i2c_adap); |
334 | if (!isp1301_i2c_client) { | 334 | if (!isp1301_i2c_client) { |
335 | err("failed to connect I2C to ISP1301 USB Transceiver"); | 335 | err("failed to connect I2C to ISP1301 USB Transceiver"); |
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index df165917412a..b2c2dbf08766 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c | |||
@@ -81,7 +81,7 @@ static const struct hc_driver ohci_ppc_of_hc_driver = { | |||
81 | 81 | ||
82 | 82 | ||
83 | static int __devinit | 83 | static int __devinit |
84 | ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) | 84 | ohci_hcd_ppc_of_probe(struct platform_device *op, const struct of_device_id *match) |
85 | { | 85 | { |
86 | struct device_node *dn = op->dev.of_node; | 86 | struct device_node *dn = op->dev.of_node; |
87 | struct usb_hcd *hcd; | 87 | struct usb_hcd *hcd; |
@@ -183,7 +183,7 @@ err_rmr: | |||
183 | return rv; | 183 | return rv; |
184 | } | 184 | } |
185 | 185 | ||
186 | static int ohci_hcd_ppc_of_remove(struct of_device *op) | 186 | static int ohci_hcd_ppc_of_remove(struct platform_device *op) |
187 | { | 187 | { |
188 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 188 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); |
189 | dev_set_drvdata(&op->dev, NULL); | 189 | dev_set_drvdata(&op->dev, NULL); |
@@ -201,7 +201,7 @@ static int ohci_hcd_ppc_of_remove(struct of_device *op) | |||
201 | return 0; | 201 | return 0; |
202 | } | 202 | } |
203 | 203 | ||
204 | static int ohci_hcd_ppc_of_shutdown(struct of_device *op) | 204 | static int ohci_hcd_ppc_of_shutdown(struct platform_device *op) |
205 | { | 205 | { |
206 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 206 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); |
207 | 207 | ||
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index c7796637bafd..4dc13467281d 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c | |||
@@ -273,7 +273,7 @@ static int __devinit bw2_do_default_mode(struct bw2_par *par, | |||
273 | return 0; | 273 | return 0; |
274 | } | 274 | } |
275 | 275 | ||
276 | static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *match) | 276 | static int __devinit bw2_probe(struct platform_device *op, const struct of_device_id *match) |
277 | { | 277 | { |
278 | struct device_node *dp = op->dev.of_node; | 278 | struct device_node *dp = op->dev.of_node; |
279 | struct fb_info *info; | 279 | struct fb_info *info; |
@@ -350,7 +350,7 @@ out_err: | |||
350 | return err; | 350 | return err; |
351 | } | 351 | } |
352 | 352 | ||
353 | static int __devexit bw2_remove(struct of_device *op) | 353 | static int __devexit bw2_remove(struct platform_device *op) |
354 | { | 354 | { |
355 | struct fb_info *info = dev_get_drvdata(&op->dev); | 355 | struct fb_info *info = dev_get_drvdata(&op->dev); |
356 | struct bw2_par *par = info->par; | 356 | struct bw2_par *par = info->par; |
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index d09fde8beb69..24249535ac86 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c | |||
@@ -446,7 +446,7 @@ static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __devinitdata = { | |||
446 | { .size = 0 } | 446 | { .size = 0 } |
447 | }; | 447 | }; |
448 | 448 | ||
449 | static void cg14_unmap_regs(struct of_device *op, struct fb_info *info, | 449 | static void cg14_unmap_regs(struct platform_device *op, struct fb_info *info, |
450 | struct cg14_par *par) | 450 | struct cg14_par *par) |
451 | { | 451 | { |
452 | if (par->regs) | 452 | if (par->regs) |
@@ -463,7 +463,7 @@ static void cg14_unmap_regs(struct of_device *op, struct fb_info *info, | |||
463 | info->screen_base, info->fix.smem_len); | 463 | info->screen_base, info->fix.smem_len); |
464 | } | 464 | } |
465 | 465 | ||
466 | static int __devinit cg14_probe(struct of_device *op, const struct of_device_id *match) | 466 | static int __devinit cg14_probe(struct platform_device *op, const struct of_device_id *match) |
467 | { | 467 | { |
468 | struct device_node *dp = op->dev.of_node; | 468 | struct device_node *dp = op->dev.of_node; |
469 | struct fb_info *info; | 469 | struct fb_info *info; |
@@ -570,7 +570,7 @@ out_err: | |||
570 | return err; | 570 | return err; |
571 | } | 571 | } |
572 | 572 | ||
573 | static int __devexit cg14_remove(struct of_device *op) | 573 | static int __devexit cg14_remove(struct platform_device *op) |
574 | { | 574 | { |
575 | struct fb_info *info = dev_get_drvdata(&op->dev); | 575 | struct fb_info *info = dev_get_drvdata(&op->dev); |
576 | struct cg14_par *par = info->par; | 576 | struct cg14_par *par = info->par; |
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index 64aa29809fb9..09c0c3c42482 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c | |||
@@ -346,7 +346,7 @@ static int __devinit cg3_do_default_mode(struct cg3_par *par) | |||
346 | return 0; | 346 | return 0; |
347 | } | 347 | } |
348 | 348 | ||
349 | static int __devinit cg3_probe(struct of_device *op, | 349 | static int __devinit cg3_probe(struct platform_device *op, |
350 | const struct of_device_id *match) | 350 | const struct of_device_id *match) |
351 | { | 351 | { |
352 | struct device_node *dp = op->dev.of_node; | 352 | struct device_node *dp = op->dev.of_node; |
@@ -433,7 +433,7 @@ out_err: | |||
433 | return err; | 433 | return err; |
434 | } | 434 | } |
435 | 435 | ||
436 | static int __devexit cg3_remove(struct of_device *op) | 436 | static int __devexit cg3_remove(struct platform_device *op) |
437 | { | 437 | { |
438 | struct fb_info *info = dev_get_drvdata(&op->dev); | 438 | struct fb_info *info = dev_get_drvdata(&op->dev); |
439 | struct cg3_par *par = info->par; | 439 | struct cg3_par *par = info->par; |
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 2389a719dcc7..2b5a97058b08 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c | |||
@@ -718,7 +718,7 @@ static void __devinit cg6_chip_init(struct fb_info *info) | |||
718 | sbus_writel(info->var.yres - 1, &fbc->clipmaxy); | 718 | sbus_writel(info->var.yres - 1, &fbc->clipmaxy); |
719 | } | 719 | } |
720 | 720 | ||
721 | static void cg6_unmap_regs(struct of_device *op, struct fb_info *info, | 721 | static void cg6_unmap_regs(struct platform_device *op, struct fb_info *info, |
722 | struct cg6_par *par) | 722 | struct cg6_par *par) |
723 | { | 723 | { |
724 | if (par->fbc) | 724 | if (par->fbc) |
@@ -737,7 +737,7 @@ static void cg6_unmap_regs(struct of_device *op, struct fb_info *info, | |||
737 | info->fix.smem_len); | 737 | info->fix.smem_len); |
738 | } | 738 | } |
739 | 739 | ||
740 | static int __devinit cg6_probe(struct of_device *op, | 740 | static int __devinit cg6_probe(struct platform_device *op, |
741 | const struct of_device_id *match) | 741 | const struct of_device_id *match) |
742 | { | 742 | { |
743 | struct device_node *dp = op->dev.of_node; | 743 | struct device_node *dp = op->dev.of_node; |
@@ -827,7 +827,7 @@ out_err: | |||
827 | return err; | 827 | return err; |
828 | } | 828 | } |
829 | 829 | ||
830 | static int __devexit cg6_remove(struct of_device *op) | 830 | static int __devexit cg6_remove(struct platform_device *op) |
831 | { | 831 | { |
832 | struct fb_info *info = dev_get_drvdata(&op->dev); | 832 | struct fb_info *info = dev_get_drvdata(&op->dev); |
833 | struct cg6_par *par = info->par; | 833 | struct cg6_par *par = info->par; |
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index f6ecfab296d3..6739b2af3bc0 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c | |||
@@ -893,7 +893,7 @@ static void ffb_init_fix(struct fb_info *info) | |||
893 | info->fix.accel = FB_ACCEL_SUN_CREATOR; | 893 | info->fix.accel = FB_ACCEL_SUN_CREATOR; |
894 | } | 894 | } |
895 | 895 | ||
896 | static int __devinit ffb_probe(struct of_device *op, | 896 | static int __devinit ffb_probe(struct platform_device *op, |
897 | const struct of_device_id *match) | 897 | const struct of_device_id *match) |
898 | { | 898 | { |
899 | struct device_node *dp = op->dev.of_node; | 899 | struct device_node *dp = op->dev.of_node; |
@@ -1023,7 +1023,7 @@ out_err: | |||
1023 | return err; | 1023 | return err; |
1024 | } | 1024 | } |
1025 | 1025 | ||
1026 | static int __devexit ffb_remove(struct of_device *op) | 1026 | static int __devexit ffb_remove(struct platform_device *op) |
1027 | { | 1027 | { |
1028 | struct fb_info *info = dev_get_drvdata(&op->dev); | 1028 | struct fb_info *info = dev_get_drvdata(&op->dev); |
1029 | struct ffb_par *par = info->par; | 1029 | struct ffb_par *par = info->par; |
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index e38ad2224540..8bbbf08fa3ce 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c | |||
@@ -1393,7 +1393,7 @@ static void free_irq_local(int irq) | |||
1393 | * Power management hooks. Note that we won't be called from IRQ context, | 1393 | * Power management hooks. Note that we won't be called from IRQ context, |
1394 | * unlike the blank functions above, so we may sleep. | 1394 | * unlike the blank functions above, so we may sleep. |
1395 | */ | 1395 | */ |
1396 | static int fsl_diu_suspend(struct of_device *ofdev, pm_message_t state) | 1396 | static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state) |
1397 | { | 1397 | { |
1398 | struct fsl_diu_data *machine_data; | 1398 | struct fsl_diu_data *machine_data; |
1399 | 1399 | ||
@@ -1403,7 +1403,7 @@ static int fsl_diu_suspend(struct of_device *ofdev, pm_message_t state) | |||
1403 | return 0; | 1403 | return 0; |
1404 | } | 1404 | } |
1405 | 1405 | ||
1406 | static int fsl_diu_resume(struct of_device *ofdev) | 1406 | static int fsl_diu_resume(struct platform_device *ofdev) |
1407 | { | 1407 | { |
1408 | struct fsl_diu_data *machine_data; | 1408 | struct fsl_diu_data *machine_data; |
1409 | 1409 | ||
@@ -1487,7 +1487,7 @@ static ssize_t show_monitor(struct device *device, | |||
1487 | return diu_ops.show_monitor_port(machine_data->monitor_port, buf); | 1487 | return diu_ops.show_monitor_port(machine_data->monitor_port, buf); |
1488 | } | 1488 | } |
1489 | 1489 | ||
1490 | static int __devinit fsl_diu_probe(struct of_device *ofdev, | 1490 | static int __devinit fsl_diu_probe(struct platform_device *ofdev, |
1491 | const struct of_device_id *match) | 1491 | const struct of_device_id *match) |
1492 | { | 1492 | { |
1493 | struct device_node *np = ofdev->dev.of_node; | 1493 | struct device_node *np = ofdev->dev.of_node; |
@@ -1667,7 +1667,7 @@ error2: | |||
1667 | } | 1667 | } |
1668 | 1668 | ||
1669 | 1669 | ||
1670 | static int fsl_diu_remove(struct of_device *ofdev) | 1670 | static int fsl_diu_remove(struct platform_device *ofdev) |
1671 | { | 1671 | { |
1672 | struct fsl_diu_data *machine_data; | 1672 | struct fsl_diu_data *machine_data; |
1673 | int i; | 1673 | int i; |
diff --git a/drivers/video/leo.c b/drivers/video/leo.c index ad677637ffbb..b599e5e36ced 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c | |||
@@ -529,7 +529,7 @@ static void leo_fixup_var_rgb(struct fb_var_screeninfo *var) | |||
529 | var->transp.length = 0; | 529 | var->transp.length = 0; |
530 | } | 530 | } |
531 | 531 | ||
532 | static void leo_unmap_regs(struct of_device *op, struct fb_info *info, | 532 | static void leo_unmap_regs(struct platform_device *op, struct fb_info *info, |
533 | struct leo_par *par) | 533 | struct leo_par *par) |
534 | { | 534 | { |
535 | if (par->lc_ss0_usr) | 535 | if (par->lc_ss0_usr) |
@@ -547,7 +547,7 @@ static void leo_unmap_regs(struct of_device *op, struct fb_info *info, | |||
547 | of_iounmap(&op->resource[0], info->screen_base, 0x800000); | 547 | of_iounmap(&op->resource[0], info->screen_base, 0x800000); |
548 | } | 548 | } |
549 | 549 | ||
550 | static int __devinit leo_probe(struct of_device *op, | 550 | static int __devinit leo_probe(struct platform_device *op, |
551 | const struct of_device_id *match) | 551 | const struct of_device_id *match) |
552 | { | 552 | { |
553 | struct device_node *dp = op->dev.of_node; | 553 | struct device_node *dp = op->dev.of_node; |
@@ -637,7 +637,7 @@ out_err: | |||
637 | return err; | 637 | return err; |
638 | } | 638 | } |
639 | 639 | ||
640 | static int __devexit leo_remove(struct of_device *op) | 640 | static int __devexit leo_remove(struct platform_device *op) |
641 | { | 641 | { |
642 | struct fb_info *info = dev_get_drvdata(&op->dev); | 642 | struct fb_info *info = dev_get_drvdata(&op->dev); |
643 | struct leo_par *par = info->par; | 643 | struct leo_par *par = info->par; |
diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c index 403b14445a78..0fb280ead3dc 100644 --- a/drivers/video/matrox/i2c-matroxfb.c +++ b/drivers/video/matrox/i2c-matroxfb.c | |||
@@ -191,7 +191,7 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) { | |||
191 | }; | 191 | }; |
192 | 192 | ||
193 | i2c_new_probed_device(&m2info->maven.adapter, | 193 | i2c_new_probed_device(&m2info->maven.adapter, |
194 | &maven_info, addr_list); | 194 | &maven_info, addr_list, NULL); |
195 | } | 195 | } |
196 | } | 196 | } |
197 | return m2info; | 197 | return m2info; |
diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c index 4e2b8cc3d460..b1c4374cf940 100644 --- a/drivers/video/mb862xx/mb862xxfb.c +++ b/drivers/video/mb862xx/mb862xxfb.c | |||
@@ -550,7 +550,7 @@ static int mb862xx_gdc_init(struct mb862xxfb_par *par) | |||
550 | return 0; | 550 | return 0; |
551 | } | 551 | } |
552 | 552 | ||
553 | static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev, | 553 | static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev, |
554 | const struct of_device_id *id) | 554 | const struct of_device_id *id) |
555 | { | 555 | { |
556 | struct device_node *np = ofdev->dev.of_node; | 556 | struct device_node *np = ofdev->dev.of_node; |
@@ -669,7 +669,7 @@ fbrel: | |||
669 | return ret; | 669 | return ret; |
670 | } | 670 | } |
671 | 671 | ||
672 | static int __devexit of_platform_mb862xx_remove(struct of_device *ofdev) | 672 | static int __devexit of_platform_mb862xx_remove(struct platform_device *ofdev) |
673 | { | 673 | { |
674 | struct fb_info *fbi = dev_get_drvdata(&ofdev->dev); | 674 | struct fb_info *fbi = dev_get_drvdata(&ofdev->dev); |
675 | struct mb862xxfb_par *par = fbi->par; | 675 | struct mb862xxfb_par *par = fbi->par; |
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index 688b055abab2..b6c3fc2db632 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c | |||
@@ -249,7 +249,7 @@ static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_no | |||
249 | info->fix.accel = FB_ACCEL_SUN_CGTHREE; | 249 | info->fix.accel = FB_ACCEL_SUN_CGTHREE; |
250 | } | 250 | } |
251 | 251 | ||
252 | static int __devinit p9100_probe(struct of_device *op, const struct of_device_id *match) | 252 | static int __devinit p9100_probe(struct platform_device *op, const struct of_device_id *match) |
253 | { | 253 | { |
254 | struct device_node *dp = op->dev.of_node; | 254 | struct device_node *dp = op->dev.of_node; |
255 | struct fb_info *info; | 255 | struct fb_info *info; |
@@ -326,7 +326,7 @@ out_err: | |||
326 | return err; | 326 | return err; |
327 | } | 327 | } |
328 | 328 | ||
329 | static int __devexit p9100_remove(struct of_device *op) | 329 | static int __devexit p9100_remove(struct platform_device *op) |
330 | { | 330 | { |
331 | struct fb_info *info = dev_get_drvdata(&op->dev); | 331 | struct fb_info *info = dev_get_drvdata(&op->dev); |
332 | struct p9100_par *par = info->par; | 332 | struct p9100_par *par = info->par; |
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index 72a1f4c04732..a50e1977b316 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c | |||
@@ -533,7 +533,7 @@ static int __init platinumfb_setup(char *options) | |||
533 | #define invalidate_cache(addr) | 533 | #define invalidate_cache(addr) |
534 | #endif | 534 | #endif |
535 | 535 | ||
536 | static int __devinit platinumfb_probe(struct of_device* odev, | 536 | static int __devinit platinumfb_probe(struct platform_device* odev, |
537 | const struct of_device_id *match) | 537 | const struct of_device_id *match) |
538 | { | 538 | { |
539 | struct device_node *dp = odev->dev.of_node; | 539 | struct device_node *dp = odev->dev.of_node; |
@@ -646,7 +646,7 @@ static int __devinit platinumfb_probe(struct of_device* odev, | |||
646 | return rc; | 646 | return rc; |
647 | } | 647 | } |
648 | 648 | ||
649 | static int __devexit platinumfb_remove(struct of_device* odev) | 649 | static int __devexit platinumfb_remove(struct platform_device* odev) |
650 | { | 650 | { |
651 | struct fb_info *info = dev_get_drvdata(&odev->dev); | 651 | struct fb_info *info = dev_get_drvdata(&odev->dev); |
652 | struct fb_info_platinum *pinfo = info->par; | 652 | struct fb_info_platinum *pinfo = info->par; |
diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c index 7288934c0d49..5dbe06af2226 100644 --- a/drivers/video/sunxvr1000.c +++ b/drivers/video/sunxvr1000.c | |||
@@ -111,7 +111,7 @@ static int __devinit gfb_set_fbinfo(struct gfb_info *gp) | |||
111 | return 0; | 111 | return 0; |
112 | } | 112 | } |
113 | 113 | ||
114 | static int __devinit gfb_probe(struct of_device *op, | 114 | static int __devinit gfb_probe(struct platform_device *op, |
115 | const struct of_device_id *match) | 115 | const struct of_device_id *match) |
116 | { | 116 | { |
117 | struct device_node *dp = op->dev.of_node; | 117 | struct device_node *dp = op->dev.of_node; |
@@ -172,7 +172,7 @@ err_out: | |||
172 | return err; | 172 | return err; |
173 | } | 173 | } |
174 | 174 | ||
175 | static int __devexit gfb_remove(struct of_device *op) | 175 | static int __devexit gfb_remove(struct platform_device *op) |
176 | { | 176 | { |
177 | struct fb_info *info = dev_get_drvdata(&op->dev); | 177 | struct fb_info *info = dev_get_drvdata(&op->dev); |
178 | struct gfb_info *gp = info->par; | 178 | struct gfb_info *gp = info->par; |
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index f375e0db6776..77ad27955cf0 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c | |||
@@ -342,7 +342,7 @@ tcx_init_fix(struct fb_info *info, int linebytes) | |||
342 | info->fix.accel = FB_ACCEL_SUN_TCX; | 342 | info->fix.accel = FB_ACCEL_SUN_TCX; |
343 | } | 343 | } |
344 | 344 | ||
345 | static void tcx_unmap_regs(struct of_device *op, struct fb_info *info, | 345 | static void tcx_unmap_regs(struct platform_device *op, struct fb_info *info, |
346 | struct tcx_par *par) | 346 | struct tcx_par *par) |
347 | { | 347 | { |
348 | if (par->tec) | 348 | if (par->tec) |
@@ -362,7 +362,7 @@ static void tcx_unmap_regs(struct of_device *op, struct fb_info *info, | |||
362 | info->screen_base, info->fix.smem_len); | 362 | info->screen_base, info->fix.smem_len); |
363 | } | 363 | } |
364 | 364 | ||
365 | static int __devinit tcx_probe(struct of_device *op, | 365 | static int __devinit tcx_probe(struct platform_device *op, |
366 | const struct of_device_id *match) | 366 | const struct of_device_id *match) |
367 | { | 367 | { |
368 | struct device_node *dp = op->dev.of_node; | 368 | struct device_node *dp = op->dev.of_node; |
@@ -486,7 +486,7 @@ out_err: | |||
486 | return err; | 486 | return err; |
487 | } | 487 | } |
488 | 488 | ||
489 | static int __devexit tcx_remove(struct of_device *op) | 489 | static int __devexit tcx_remove(struct platform_device *op) |
490 | { | 490 | { |
491 | struct fb_info *info = dev_get_drvdata(&op->dev); | 491 | struct fb_info *info = dev_get_drvdata(&op->dev); |
492 | struct tcx_par *par = info->par; | 492 | struct tcx_par *par = info->par; |
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index 7b8839ebf3c4..52ec0959d462 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c | |||
@@ -1977,8 +1977,7 @@ static void __devexit uvesafb_exit(void) | |||
1977 | 1977 | ||
1978 | module_exit(uvesafb_exit); | 1978 | module_exit(uvesafb_exit); |
1979 | 1979 | ||
1980 | #define param_get_scroll NULL | 1980 | static int param_set_scroll(const char *val, const struct kernel_param *kp) |
1981 | static int param_set_scroll(const char *val, struct kernel_param *kp) | ||
1982 | { | 1981 | { |
1983 | ypan = 0; | 1982 | ypan = 0; |
1984 | 1983 | ||
@@ -1993,7 +1992,9 @@ static int param_set_scroll(const char *val, struct kernel_param *kp) | |||
1993 | 1992 | ||
1994 | return 0; | 1993 | return 0; |
1995 | } | 1994 | } |
1996 | 1995 | static struct kernel_param_ops param_ops_scroll = { | |
1996 | .set = param_set_scroll, | ||
1997 | }; | ||
1997 | #define param_check_scroll(name, p) __param_check(name, p, void) | 1998 | #define param_check_scroll(name, p) __param_check(name, p, void) |
1998 | 1999 | ||
1999 | module_param_named(scroll, ypan, scroll, 0); | 2000 | module_param_named(scroll, ypan, scroll, 0); |
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c index d31dc96f838a..85d76ec4c63e 100644 --- a/drivers/video/vt8623fb.c +++ b/drivers/video/vt8623fb.c | |||
@@ -726,7 +726,9 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi | |||
726 | 726 | ||
727 | /* Prepare startup mode */ | 727 | /* Prepare startup mode */ |
728 | 728 | ||
729 | kparam_block_sysfs_write(mode_option); | ||
729 | rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); | 730 | rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); |
731 | kparam_unblock_sysfs_write(mode_option); | ||
730 | if (! ((rc == 1) || (rc == 2))) { | 732 | if (! ((rc == 1) || (rc == 2))) { |
731 | rc = -EINVAL; | 733 | rc = -EINVAL; |
732 | dev_err(info->device, "mode %s not found\n", mode_option); | 734 | dev_err(info->device, "mode %s not found\n", mode_option); |
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 29b5daacc217..0c9ce88e95e8 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c | |||
@@ -397,7 +397,7 @@ static int xilinxfb_release(struct device *dev) | |||
397 | */ | 397 | */ |
398 | 398 | ||
399 | static int __devinit | 399 | static int __devinit |
400 | xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match) | 400 | xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match) |
401 | { | 401 | { |
402 | const u32 *prop; | 402 | const u32 *prop; |
403 | u32 *p; | 403 | u32 *p; |
@@ -477,7 +477,7 @@ xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match) | |||
477 | return -ENODEV; | 477 | return -ENODEV; |
478 | } | 478 | } |
479 | 479 | ||
480 | static int __devexit xilinxfb_of_remove(struct of_device *op) | 480 | static int __devexit xilinxfb_of_remove(struct platform_device *op) |
481 | { | 481 | { |
482 | return xilinxfb_release(&op->dev); | 482 | return xilinxfb_release(&op->dev); |
483 | } | 483 | } |
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index 30a2512fd52e..566343b3c131 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c | |||
@@ -526,7 +526,7 @@ static const struct file_operations cpwd_fops = { | |||
526 | .release = cpwd_release, | 526 | .release = cpwd_release, |
527 | }; | 527 | }; |
528 | 528 | ||
529 | static int __devinit cpwd_probe(struct of_device *op, | 529 | static int __devinit cpwd_probe(struct platform_device *op, |
530 | const struct of_device_id *match) | 530 | const struct of_device_id *match) |
531 | { | 531 | { |
532 | struct device_node *options; | 532 | struct device_node *options; |
@@ -639,7 +639,7 @@ out_free: | |||
639 | goto out; | 639 | goto out; |
640 | } | 640 | } |
641 | 641 | ||
642 | static int __devexit cpwd_remove(struct of_device *op) | 642 | static int __devexit cpwd_remove(struct platform_device *op) |
643 | { | 643 | { |
644 | struct cpwd *p = dev_get_drvdata(&op->dev); | 644 | struct cpwd *p = dev_get_drvdata(&op->dev); |
645 | int i; | 645 | int i; |
diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c index 1df284f9c2a1..9c21d19043a6 100644 --- a/drivers/watchdog/gef_wdt.c +++ b/drivers/watchdog/gef_wdt.c | |||
@@ -260,7 +260,7 @@ static struct miscdevice gef_wdt_miscdev = { | |||
260 | }; | 260 | }; |
261 | 261 | ||
262 | 262 | ||
263 | static int __devinit gef_wdt_probe(struct of_device *dev, | 263 | static int __devinit gef_wdt_probe(struct platform_device *dev, |
264 | const struct of_device_id *match) | 264 | const struct of_device_id *match) |
265 | { | 265 | { |
266 | int timeout = 10; | 266 | int timeout = 10; |
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c index 4cda64dd309c..8fa213cdb499 100644 --- a/drivers/watchdog/mpc8xxx_wdt.c +++ b/drivers/watchdog/mpc8xxx_wdt.c | |||
@@ -185,7 +185,7 @@ static struct miscdevice mpc8xxx_wdt_miscdev = { | |||
185 | .fops = &mpc8xxx_wdt_fops, | 185 | .fops = &mpc8xxx_wdt_fops, |
186 | }; | 186 | }; |
187 | 187 | ||
188 | static int __devinit mpc8xxx_wdt_probe(struct of_device *ofdev, | 188 | static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev, |
189 | const struct of_device_id *match) | 189 | const struct of_device_id *match) |
190 | { | 190 | { |
191 | int ret; | 191 | int ret; |
@@ -238,7 +238,7 @@ err_unmap: | |||
238 | return ret; | 238 | return ret; |
239 | } | 239 | } |
240 | 240 | ||
241 | static int __devexit mpc8xxx_wdt_remove(struct of_device *ofdev) | 241 | static int __devexit mpc8xxx_wdt_remove(struct platform_device *ofdev) |
242 | { | 242 | { |
243 | mpc8xxx_wdt_pr_warn("watchdog removed"); | 243 | mpc8xxx_wdt_pr_warn("watchdog removed"); |
244 | del_timer_sync(&wdt_timer); | 244 | del_timer_sync(&wdt_timer); |
diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c index 4082b4ace1fc..3faee1ae64bd 100644 --- a/drivers/watchdog/riowd.c +++ b/drivers/watchdog/riowd.c | |||
@@ -172,7 +172,7 @@ static struct miscdevice riowd_miscdev = { | |||
172 | .fops = &riowd_fops | 172 | .fops = &riowd_fops |
173 | }; | 173 | }; |
174 | 174 | ||
175 | static int __devinit riowd_probe(struct of_device *op, | 175 | static int __devinit riowd_probe(struct platform_device *op, |
176 | const struct of_device_id *match) | 176 | const struct of_device_id *match) |
177 | { | 177 | { |
178 | struct riowd *p; | 178 | struct riowd *p; |
@@ -219,7 +219,7 @@ out: | |||
219 | return err; | 219 | return err; |
220 | } | 220 | } |
221 | 221 | ||
222 | static int __devexit riowd_remove(struct of_device *op) | 222 | static int __devexit riowd_remove(struct platform_device *op) |
223 | { | 223 | { |
224 | struct riowd *p = dev_get_drvdata(&op->dev); | 224 | struct riowd *p = dev_get_drvdata(&op->dev); |
225 | 225 | ||
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 0a8826936639..60d71e9abe9f 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig | |||
@@ -71,4 +71,9 @@ config XEN_PLATFORM_PCI | |||
71 | initializing xenbus and grant_table when running in a Xen HVM | 71 | initializing xenbus and grant_table when running in a Xen HVM |
72 | domain. As a consequence this driver is required to run any Xen PV | 72 | domain. As a consequence this driver is required to run any Xen PV |
73 | frontend on Xen HVM. | 73 | frontend on Xen HVM. |
74 | |||
75 | config SWIOTLB_XEN | ||
76 | def_bool y | ||
77 | depends on SWIOTLB | ||
78 | |||
74 | endmenu | 79 | endmenu |
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index e392fb776af3..fcaf838f54be 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile | |||
@@ -11,3 +11,4 @@ obj-$(CONFIG_XEN_DEV_EVTCHN) += evtchn.o | |||
11 | obj-$(CONFIG_XENFS) += xenfs/ | 11 | obj-$(CONFIG_XENFS) += xenfs/ |
12 | obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o | 12 | obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o |
13 | obj-$(CONFIG_XEN_PLATFORM_PCI) += platform-pci.o | 13 | obj-$(CONFIG_XEN_PLATFORM_PCI) += platform-pci.o |
14 | obj-$(CONFIG_SWIOTLB_XEN) += swiotlb-xen.o | ||
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 1a0d8c2a0354..500290b150bb 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c | |||
@@ -85,13 +85,6 @@ static struct sys_device balloon_sysdev; | |||
85 | 85 | ||
86 | static int register_balloon(struct sys_device *sysdev); | 86 | static int register_balloon(struct sys_device *sysdev); |
87 | 87 | ||
88 | /* | ||
89 | * Protects atomic reservation decrease/increase against concurrent increases. | ||
90 | * Also protects non-atomic updates of current_pages and driver_pages, and | ||
91 | * balloon lists. | ||
92 | */ | ||
93 | static DEFINE_SPINLOCK(balloon_lock); | ||
94 | |||
95 | static struct balloon_stats balloon_stats; | 88 | static struct balloon_stats balloon_stats; |
96 | 89 | ||
97 | /* We increase/decrease in batches which fit in a page */ | 90 | /* We increase/decrease in batches which fit in a page */ |
@@ -210,7 +203,7 @@ static int increase_reservation(unsigned long nr_pages) | |||
210 | if (nr_pages > ARRAY_SIZE(frame_list)) | 203 | if (nr_pages > ARRAY_SIZE(frame_list)) |
211 | nr_pages = ARRAY_SIZE(frame_list); | 204 | nr_pages = ARRAY_SIZE(frame_list); |
212 | 205 | ||
213 | spin_lock_irqsave(&balloon_lock, flags); | 206 | spin_lock_irqsave(&xen_reservation_lock, flags); |
214 | 207 | ||
215 | page = balloon_first_page(); | 208 | page = balloon_first_page(); |
216 | for (i = 0; i < nr_pages; i++) { | 209 | for (i = 0; i < nr_pages; i++) { |
@@ -254,7 +247,7 @@ static int increase_reservation(unsigned long nr_pages) | |||
254 | balloon_stats.current_pages += rc; | 247 | balloon_stats.current_pages += rc; |
255 | 248 | ||
256 | out: | 249 | out: |
257 | spin_unlock_irqrestore(&balloon_lock, flags); | 250 | spin_unlock_irqrestore(&xen_reservation_lock, flags); |
258 | 251 | ||
259 | return rc < 0 ? rc : rc != nr_pages; | 252 | return rc < 0 ? rc : rc != nr_pages; |
260 | } | 253 | } |
@@ -299,7 +292,7 @@ static int decrease_reservation(unsigned long nr_pages) | |||
299 | kmap_flush_unused(); | 292 | kmap_flush_unused(); |
300 | flush_tlb_all(); | 293 | flush_tlb_all(); |
301 | 294 | ||
302 | spin_lock_irqsave(&balloon_lock, flags); | 295 | spin_lock_irqsave(&xen_reservation_lock, flags); |
303 | 296 | ||
304 | /* No more mappings: invalidate P2M and add to balloon. */ | 297 | /* No more mappings: invalidate P2M and add to balloon. */ |
305 | for (i = 0; i < nr_pages; i++) { | 298 | for (i = 0; i < nr_pages; i++) { |
@@ -315,7 +308,7 @@ static int decrease_reservation(unsigned long nr_pages) | |||
315 | 308 | ||
316 | balloon_stats.current_pages -= nr_pages; | 309 | balloon_stats.current_pages -= nr_pages; |
317 | 310 | ||
318 | spin_unlock_irqrestore(&balloon_lock, flags); | 311 | spin_unlock_irqrestore(&xen_reservation_lock, flags); |
319 | 312 | ||
320 | return need_sleep; | 313 | return need_sleep; |
321 | } | 314 | } |
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c new file mode 100644 index 000000000000..54469c3eeacd --- /dev/null +++ b/drivers/xen/swiotlb-xen.c | |||
@@ -0,0 +1,515 @@ | |||
1 | /* | ||
2 | * Copyright 2010 | ||
3 | * by Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | ||
4 | * | ||
5 | * This code provides a IOMMU for Xen PV guests with PCI passthrough. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License v2.0 as published by | ||
9 | * the Free Software Foundation | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * PV guests under Xen are running in an non-contiguous memory architecture. | ||
17 | * | ||
18 | * When PCI pass-through is utilized, this necessitates an IOMMU for | ||
19 | * translating bus (DMA) to virtual and vice-versa and also providing a | ||
20 | * mechanism to have contiguous pages for device drivers operations (say DMA | ||
21 | * operations). | ||
22 | * | ||
23 | * Specifically, under Xen the Linux idea of pages is an illusion. It | ||
24 | * assumes that pages start at zero and go up to the available memory. To | ||
25 | * help with that, the Linux Xen MMU provides a lookup mechanism to | ||
26 | * translate the page frame numbers (PFN) to machine frame numbers (MFN) | ||
27 | * and vice-versa. The MFN are the "real" frame numbers. Furthermore | ||
28 | * memory is not contiguous. Xen hypervisor stitches memory for guests | ||
29 | * from different pools, which means there is no guarantee that PFN==MFN | ||
30 | * and PFN+1==MFN+1. Lastly with Xen 4.0, pages (in debug mode) are | ||
31 | * allocated in descending order (high to low), meaning the guest might | ||
32 | * never get any MFN's under the 4GB mark. | ||
33 | * | ||
34 | */ | ||
35 | |||
36 | #include <linux/bootmem.h> | ||
37 | #include <linux/dma-mapping.h> | ||
38 | #include <xen/swiotlb-xen.h> | ||
39 | #include <xen/page.h> | ||
40 | #include <xen/xen-ops.h> | ||
41 | /* | ||
42 | * Used to do a quick range check in swiotlb_tbl_unmap_single and | ||
43 | * swiotlb_tbl_sync_single_*, to see if the memory was in fact allocated by this | ||
44 | * API. | ||
45 | */ | ||
46 | |||
47 | static char *xen_io_tlb_start, *xen_io_tlb_end; | ||
48 | static unsigned long xen_io_tlb_nslabs; | ||
49 | /* | ||
50 | * Quick lookup value of the bus address of the IOTLB. | ||
51 | */ | ||
52 | |||
53 | u64 start_dma_addr; | ||
54 | |||
55 | static dma_addr_t xen_phys_to_bus(phys_addr_t paddr) | ||
56 | { | ||
57 | return phys_to_machine(XPADDR(paddr)).maddr;; | ||
58 | } | ||
59 | |||
60 | static phys_addr_t xen_bus_to_phys(dma_addr_t baddr) | ||
61 | { | ||
62 | return machine_to_phys(XMADDR(baddr)).paddr; | ||
63 | } | ||
64 | |||
65 | static dma_addr_t xen_virt_to_bus(void *address) | ||
66 | { | ||
67 | return xen_phys_to_bus(virt_to_phys(address)); | ||
68 | } | ||
69 | |||
70 | static int check_pages_physically_contiguous(unsigned long pfn, | ||
71 | unsigned int offset, | ||
72 | size_t length) | ||
73 | { | ||
74 | unsigned long next_mfn; | ||
75 | int i; | ||
76 | int nr_pages; | ||
77 | |||
78 | next_mfn = pfn_to_mfn(pfn); | ||
79 | nr_pages = (offset + length + PAGE_SIZE-1) >> PAGE_SHIFT; | ||
80 | |||
81 | for (i = 1; i < nr_pages; i++) { | ||
82 | if (pfn_to_mfn(++pfn) != ++next_mfn) | ||
83 | return 0; | ||
84 | } | ||
85 | return 1; | ||
86 | } | ||
87 | |||
88 | static int range_straddles_page_boundary(phys_addr_t p, size_t size) | ||
89 | { | ||
90 | unsigned long pfn = PFN_DOWN(p); | ||
91 | unsigned int offset = p & ~PAGE_MASK; | ||
92 | |||
93 | if (offset + size <= PAGE_SIZE) | ||
94 | return 0; | ||
95 | if (check_pages_physically_contiguous(pfn, offset, size)) | ||
96 | return 0; | ||
97 | return 1; | ||
98 | } | ||
99 | |||
100 | static int is_xen_swiotlb_buffer(dma_addr_t dma_addr) | ||
101 | { | ||
102 | unsigned long mfn = PFN_DOWN(dma_addr); | ||
103 | unsigned long pfn = mfn_to_local_pfn(mfn); | ||
104 | phys_addr_t paddr; | ||
105 | |||
106 | /* If the address is outside our domain, it CAN | ||
107 | * have the same virtual address as another address | ||
108 | * in our domain. Therefore _only_ check address within our domain. | ||
109 | */ | ||
110 | if (pfn_valid(pfn)) { | ||
111 | paddr = PFN_PHYS(pfn); | ||
112 | return paddr >= virt_to_phys(xen_io_tlb_start) && | ||
113 | paddr < virt_to_phys(xen_io_tlb_end); | ||
114 | } | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int max_dma_bits = 32; | ||
119 | |||
120 | static int | ||
121 | xen_swiotlb_fixup(void *buf, size_t size, unsigned long nslabs) | ||
122 | { | ||
123 | int i, rc; | ||
124 | int dma_bits; | ||
125 | |||
126 | dma_bits = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT) + PAGE_SHIFT; | ||
127 | |||
128 | i = 0; | ||
129 | do { | ||
130 | int slabs = min(nslabs - i, (unsigned long)IO_TLB_SEGSIZE); | ||
131 | |||
132 | do { | ||
133 | rc = xen_create_contiguous_region( | ||
134 | (unsigned long)buf + (i << IO_TLB_SHIFT), | ||
135 | get_order(slabs << IO_TLB_SHIFT), | ||
136 | dma_bits); | ||
137 | } while (rc && dma_bits++ < max_dma_bits); | ||
138 | if (rc) | ||
139 | return rc; | ||
140 | |||
141 | i += slabs; | ||
142 | } while (i < nslabs); | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | void __init xen_swiotlb_init(int verbose) | ||
147 | { | ||
148 | unsigned long bytes; | ||
149 | int rc; | ||
150 | |||
151 | xen_io_tlb_nslabs = (64 * 1024 * 1024 >> IO_TLB_SHIFT); | ||
152 | xen_io_tlb_nslabs = ALIGN(xen_io_tlb_nslabs, IO_TLB_SEGSIZE); | ||
153 | |||
154 | bytes = xen_io_tlb_nslabs << IO_TLB_SHIFT; | ||
155 | |||
156 | /* | ||
157 | * Get IO TLB memory from any location. | ||
158 | */ | ||
159 | xen_io_tlb_start = alloc_bootmem(bytes); | ||
160 | if (!xen_io_tlb_start) | ||
161 | panic("Cannot allocate SWIOTLB buffer"); | ||
162 | |||
163 | xen_io_tlb_end = xen_io_tlb_start + bytes; | ||
164 | /* | ||
165 | * And replace that memory with pages under 4GB. | ||
166 | */ | ||
167 | rc = xen_swiotlb_fixup(xen_io_tlb_start, | ||
168 | bytes, | ||
169 | xen_io_tlb_nslabs); | ||
170 | if (rc) | ||
171 | goto error; | ||
172 | |||
173 | start_dma_addr = xen_virt_to_bus(xen_io_tlb_start); | ||
174 | swiotlb_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs, verbose); | ||
175 | |||
176 | return; | ||
177 | error: | ||
178 | panic("DMA(%d): Failed to exchange pages allocated for DMA with Xen! "\ | ||
179 | "We either don't have the permission or you do not have enough"\ | ||
180 | "free memory under 4GB!\n", rc); | ||
181 | } | ||
182 | |||
183 | void * | ||
184 | xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, | ||
185 | dma_addr_t *dma_handle, gfp_t flags) | ||
186 | { | ||
187 | void *ret; | ||
188 | int order = get_order(size); | ||
189 | u64 dma_mask = DMA_BIT_MASK(32); | ||
190 | unsigned long vstart; | ||
191 | |||
192 | /* | ||
193 | * Ignore region specifiers - the kernel's ideas of | ||
194 | * pseudo-phys memory layout has nothing to do with the | ||
195 | * machine physical layout. We can't allocate highmem | ||
196 | * because we can't return a pointer to it. | ||
197 | */ | ||
198 | flags &= ~(__GFP_DMA | __GFP_HIGHMEM); | ||
199 | |||
200 | if (dma_alloc_from_coherent(hwdev, size, dma_handle, &ret)) | ||
201 | return ret; | ||
202 | |||
203 | vstart = __get_free_pages(flags, order); | ||
204 | ret = (void *)vstart; | ||
205 | |||
206 | if (hwdev && hwdev->coherent_dma_mask) | ||
207 | dma_mask = dma_alloc_coherent_mask(hwdev, flags); | ||
208 | |||
209 | if (ret) { | ||
210 | if (xen_create_contiguous_region(vstart, order, | ||
211 | fls64(dma_mask)) != 0) { | ||
212 | free_pages(vstart, order); | ||
213 | return NULL; | ||
214 | } | ||
215 | memset(ret, 0, size); | ||
216 | *dma_handle = virt_to_machine(ret).maddr; | ||
217 | } | ||
218 | return ret; | ||
219 | } | ||
220 | EXPORT_SYMBOL_GPL(xen_swiotlb_alloc_coherent); | ||
221 | |||
222 | void | ||
223 | xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr, | ||
224 | dma_addr_t dev_addr) | ||
225 | { | ||
226 | int order = get_order(size); | ||
227 | |||
228 | if (dma_release_from_coherent(hwdev, order, vaddr)) | ||
229 | return; | ||
230 | |||
231 | xen_destroy_contiguous_region((unsigned long)vaddr, order); | ||
232 | free_pages((unsigned long)vaddr, order); | ||
233 | } | ||
234 | EXPORT_SYMBOL_GPL(xen_swiotlb_free_coherent); | ||
235 | |||
236 | |||
237 | /* | ||
238 | * Map a single buffer of the indicated size for DMA in streaming mode. The | ||
239 | * physical address to use is returned. | ||
240 | * | ||
241 | * Once the device is given the dma address, the device owns this memory until | ||
242 | * either xen_swiotlb_unmap_page or xen_swiotlb_dma_sync_single is performed. | ||
243 | */ | ||
244 | dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page, | ||
245 | unsigned long offset, size_t size, | ||
246 | enum dma_data_direction dir, | ||
247 | struct dma_attrs *attrs) | ||
248 | { | ||
249 | phys_addr_t phys = page_to_phys(page) + offset; | ||
250 | dma_addr_t dev_addr = xen_phys_to_bus(phys); | ||
251 | void *map; | ||
252 | |||
253 | BUG_ON(dir == DMA_NONE); | ||
254 | /* | ||
255 | * If the address happens to be in the device's DMA window, | ||
256 | * we can safely return the device addr and not worry about bounce | ||
257 | * buffering it. | ||
258 | */ | ||
259 | if (dma_capable(dev, dev_addr, size) && | ||
260 | !range_straddles_page_boundary(phys, size) && !swiotlb_force) | ||
261 | return dev_addr; | ||
262 | |||
263 | /* | ||
264 | * Oh well, have to allocate and map a bounce buffer. | ||
265 | */ | ||
266 | map = swiotlb_tbl_map_single(dev, start_dma_addr, phys, size, dir); | ||
267 | if (!map) | ||
268 | return DMA_ERROR_CODE; | ||
269 | |||
270 | dev_addr = xen_virt_to_bus(map); | ||
271 | |||
272 | /* | ||
273 | * Ensure that the address returned is DMA'ble | ||
274 | */ | ||
275 | if (!dma_capable(dev, dev_addr, size)) | ||
276 | panic("map_single: bounce buffer is not DMA'ble"); | ||
277 | |||
278 | return dev_addr; | ||
279 | } | ||
280 | EXPORT_SYMBOL_GPL(xen_swiotlb_map_page); | ||
281 | |||
282 | /* | ||
283 | * Unmap a single streaming mode DMA translation. The dma_addr and size must | ||
284 | * match what was provided for in a previous xen_swiotlb_map_page call. All | ||
285 | * other usages are undefined. | ||
286 | * | ||
287 | * After this call, reads by the cpu to the buffer are guaranteed to see | ||
288 | * whatever the device wrote there. | ||
289 | */ | ||
290 | static void xen_unmap_single(struct device *hwdev, dma_addr_t dev_addr, | ||
291 | size_t size, enum dma_data_direction dir) | ||
292 | { | ||
293 | phys_addr_t paddr = xen_bus_to_phys(dev_addr); | ||
294 | |||
295 | BUG_ON(dir == DMA_NONE); | ||
296 | |||
297 | /* NOTE: We use dev_addr here, not paddr! */ | ||
298 | if (is_xen_swiotlb_buffer(dev_addr)) { | ||
299 | swiotlb_tbl_unmap_single(hwdev, phys_to_virt(paddr), size, dir); | ||
300 | return; | ||
301 | } | ||
302 | |||
303 | if (dir != DMA_FROM_DEVICE) | ||
304 | return; | ||
305 | |||
306 | /* | ||
307 | * phys_to_virt doesn't work with hihgmem page but we could | ||
308 | * call dma_mark_clean() with hihgmem page here. However, we | ||
309 | * are fine since dma_mark_clean() is null on POWERPC. We can | ||
310 | * make dma_mark_clean() take a physical address if necessary. | ||
311 | */ | ||
312 | dma_mark_clean(phys_to_virt(paddr), size); | ||
313 | } | ||
314 | |||
315 | void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr, | ||
316 | size_t size, enum dma_data_direction dir, | ||
317 | struct dma_attrs *attrs) | ||
318 | { | ||
319 | xen_unmap_single(hwdev, dev_addr, size, dir); | ||
320 | } | ||
321 | EXPORT_SYMBOL_GPL(xen_swiotlb_unmap_page); | ||
322 | |||
323 | /* | ||
324 | * Make physical memory consistent for a single streaming mode DMA translation | ||
325 | * after a transfer. | ||
326 | * | ||
327 | * If you perform a xen_swiotlb_map_page() but wish to interrogate the buffer | ||
328 | * using the cpu, yet do not wish to teardown the dma mapping, you must | ||
329 | * call this function before doing so. At the next point you give the dma | ||
330 | * address back to the card, you must first perform a | ||
331 | * xen_swiotlb_dma_sync_for_device, and then the device again owns the buffer | ||
332 | */ | ||
333 | static void | ||
334 | xen_swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr, | ||
335 | size_t size, enum dma_data_direction dir, | ||
336 | enum dma_sync_target target) | ||
337 | { | ||
338 | phys_addr_t paddr = xen_bus_to_phys(dev_addr); | ||
339 | |||
340 | BUG_ON(dir == DMA_NONE); | ||
341 | |||
342 | /* NOTE: We use dev_addr here, not paddr! */ | ||
343 | if (is_xen_swiotlb_buffer(dev_addr)) { | ||
344 | swiotlb_tbl_sync_single(hwdev, phys_to_virt(paddr), size, dir, | ||
345 | target); | ||
346 | return; | ||
347 | } | ||
348 | |||
349 | if (dir != DMA_FROM_DEVICE) | ||
350 | return; | ||
351 | |||
352 | dma_mark_clean(phys_to_virt(paddr), size); | ||
353 | } | ||
354 | |||
355 | void | ||
356 | xen_swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr, | ||
357 | size_t size, enum dma_data_direction dir) | ||
358 | { | ||
359 | xen_swiotlb_sync_single(hwdev, dev_addr, size, dir, SYNC_FOR_CPU); | ||
360 | } | ||
361 | EXPORT_SYMBOL_GPL(xen_swiotlb_sync_single_for_cpu); | ||
362 | |||
363 | void | ||
364 | xen_swiotlb_sync_single_for_device(struct device *hwdev, dma_addr_t dev_addr, | ||
365 | size_t size, enum dma_data_direction dir) | ||
366 | { | ||
367 | xen_swiotlb_sync_single(hwdev, dev_addr, size, dir, SYNC_FOR_DEVICE); | ||
368 | } | ||
369 | EXPORT_SYMBOL_GPL(xen_swiotlb_sync_single_for_device); | ||
370 | |||
371 | /* | ||
372 | * Map a set of buffers described by scatterlist in streaming mode for DMA. | ||
373 | * This is the scatter-gather version of the above xen_swiotlb_map_page | ||
374 | * interface. Here the scatter gather list elements are each tagged with the | ||
375 | * appropriate dma address and length. They are obtained via | ||
376 | * sg_dma_{address,length}(SG). | ||
377 | * | ||
378 | * NOTE: An implementation may be able to use a smaller number of | ||
379 | * DMA address/length pairs than there are SG table elements. | ||
380 | * (for example via virtual mapping capabilities) | ||
381 | * The routine returns the number of addr/length pairs actually | ||
382 | * used, at most nents. | ||
383 | * | ||
384 | * Device ownership issues as mentioned above for xen_swiotlb_map_page are the | ||
385 | * same here. | ||
386 | */ | ||
387 | int | ||
388 | xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, | ||
389 | int nelems, enum dma_data_direction dir, | ||
390 | struct dma_attrs *attrs) | ||
391 | { | ||
392 | struct scatterlist *sg; | ||
393 | int i; | ||
394 | |||
395 | BUG_ON(dir == DMA_NONE); | ||
396 | |||
397 | for_each_sg(sgl, sg, nelems, i) { | ||
398 | phys_addr_t paddr = sg_phys(sg); | ||
399 | dma_addr_t dev_addr = xen_phys_to_bus(paddr); | ||
400 | |||
401 | if (swiotlb_force || | ||
402 | !dma_capable(hwdev, dev_addr, sg->length) || | ||
403 | range_straddles_page_boundary(paddr, sg->length)) { | ||
404 | void *map = swiotlb_tbl_map_single(hwdev, | ||
405 | start_dma_addr, | ||
406 | sg_phys(sg), | ||
407 | sg->length, dir); | ||
408 | if (!map) { | ||
409 | /* Don't panic here, we expect map_sg users | ||
410 | to do proper error handling. */ | ||
411 | xen_swiotlb_unmap_sg_attrs(hwdev, sgl, i, dir, | ||
412 | attrs); | ||
413 | sgl[0].dma_length = 0; | ||
414 | return DMA_ERROR_CODE; | ||
415 | } | ||
416 | sg->dma_address = xen_virt_to_bus(map); | ||
417 | } else | ||
418 | sg->dma_address = dev_addr; | ||
419 | sg->dma_length = sg->length; | ||
420 | } | ||
421 | return nelems; | ||
422 | } | ||
423 | EXPORT_SYMBOL_GPL(xen_swiotlb_map_sg_attrs); | ||
424 | |||
425 | int | ||
426 | xen_swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems, | ||
427 | enum dma_data_direction dir) | ||
428 | { | ||
429 | return xen_swiotlb_map_sg_attrs(hwdev, sgl, nelems, dir, NULL); | ||
430 | } | ||
431 | EXPORT_SYMBOL_GPL(xen_swiotlb_map_sg); | ||
432 | |||
433 | /* | ||
434 | * Unmap a set of streaming mode DMA translations. Again, cpu read rules | ||
435 | * concerning calls here are the same as for swiotlb_unmap_page() above. | ||
436 | */ | ||
437 | void | ||
438 | xen_swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl, | ||
439 | int nelems, enum dma_data_direction dir, | ||
440 | struct dma_attrs *attrs) | ||
441 | { | ||
442 | struct scatterlist *sg; | ||
443 | int i; | ||
444 | |||
445 | BUG_ON(dir == DMA_NONE); | ||
446 | |||
447 | for_each_sg(sgl, sg, nelems, i) | ||
448 | xen_unmap_single(hwdev, sg->dma_address, sg->dma_length, dir); | ||
449 | |||
450 | } | ||
451 | EXPORT_SYMBOL_GPL(xen_swiotlb_unmap_sg_attrs); | ||
452 | |||
453 | void | ||
454 | xen_swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems, | ||
455 | enum dma_data_direction dir) | ||
456 | { | ||
457 | return xen_swiotlb_unmap_sg_attrs(hwdev, sgl, nelems, dir, NULL); | ||
458 | } | ||
459 | EXPORT_SYMBOL_GPL(xen_swiotlb_unmap_sg); | ||
460 | |||
461 | /* | ||
462 | * Make physical memory consistent for a set of streaming mode DMA translations | ||
463 | * after a transfer. | ||
464 | * | ||
465 | * The same as swiotlb_sync_single_* but for a scatter-gather list, same rules | ||
466 | * and usage. | ||
467 | */ | ||
468 | static void | ||
469 | xen_swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sgl, | ||
470 | int nelems, enum dma_data_direction dir, | ||
471 | enum dma_sync_target target) | ||
472 | { | ||
473 | struct scatterlist *sg; | ||
474 | int i; | ||
475 | |||
476 | for_each_sg(sgl, sg, nelems, i) | ||
477 | xen_swiotlb_sync_single(hwdev, sg->dma_address, | ||
478 | sg->dma_length, dir, target); | ||
479 | } | ||
480 | |||
481 | void | ||
482 | xen_swiotlb_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg, | ||
483 | int nelems, enum dma_data_direction dir) | ||
484 | { | ||
485 | xen_swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_CPU); | ||
486 | } | ||
487 | EXPORT_SYMBOL_GPL(xen_swiotlb_sync_sg_for_cpu); | ||
488 | |||
489 | void | ||
490 | xen_swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg, | ||
491 | int nelems, enum dma_data_direction dir) | ||
492 | { | ||
493 | xen_swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_DEVICE); | ||
494 | } | ||
495 | EXPORT_SYMBOL_GPL(xen_swiotlb_sync_sg_for_device); | ||
496 | |||
497 | int | ||
498 | xen_swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr) | ||
499 | { | ||
500 | return !dma_addr; | ||
501 | } | ||
502 | EXPORT_SYMBOL_GPL(xen_swiotlb_dma_mapping_error); | ||
503 | |||
504 | /* | ||
505 | * Return whether the given device DMA address mask can be supported | ||
506 | * properly. For example, if your device can only drive the low 24-bits | ||
507 | * during bus mastering, then you would pass 0x00ffffff as the mask to | ||
508 | * this function. | ||
509 | */ | ||
510 | int | ||
511 | xen_swiotlb_dma_supported(struct device *hwdev, u64 mask) | ||
512 | { | ||
513 | return xen_virt_to_bus(xen_io_tlb_end - 1) <= mask; | ||
514 | } | ||
515 | EXPORT_SYMBOL_GPL(xen_swiotlb_dma_supported); | ||
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index ce12a2b06f8f..cca8eef736fc 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
@@ -759,12 +759,6 @@ extern unsigned afs_debug; | |||
759 | #define dbgprintk(FMT,...) \ | 759 | #define dbgprintk(FMT,...) \ |
760 | printk("[%-6.6s] "FMT"\n", current->comm ,##__VA_ARGS__) | 760 | printk("[%-6.6s] "FMT"\n", current->comm ,##__VA_ARGS__) |
761 | 761 | ||
762 | /* make sure we maintain the format strings, even when debugging is disabled */ | ||
763 | static inline __attribute__((format(printf,1,2))) | ||
764 | void _dbprintk(const char *fmt, ...) | ||
765 | { | ||
766 | } | ||
767 | |||
768 | #define kenter(FMT,...) dbgprintk("==> %s("FMT")",__func__ ,##__VA_ARGS__) | 762 | #define kenter(FMT,...) dbgprintk("==> %s("FMT")",__func__ ,##__VA_ARGS__) |
769 | #define kleave(FMT,...) dbgprintk("<== %s()"FMT"",__func__ ,##__VA_ARGS__) | 763 | #define kleave(FMT,...) dbgprintk("<== %s()"FMT"",__func__ ,##__VA_ARGS__) |
770 | #define kdebug(FMT,...) dbgprintk(" "FMT ,##__VA_ARGS__) | 764 | #define kdebug(FMT,...) dbgprintk(" "FMT ,##__VA_ARGS__) |
@@ -799,9 +793,9 @@ do { \ | |||
799 | } while (0) | 793 | } while (0) |
800 | 794 | ||
801 | #else | 795 | #else |
802 | #define _enter(FMT,...) _dbprintk("==> %s("FMT")",__func__ ,##__VA_ARGS__) | 796 | #define _enter(FMT,...) no_printk("==> %s("FMT")",__func__ ,##__VA_ARGS__) |
803 | #define _leave(FMT,...) _dbprintk("<== %s()"FMT"",__func__ ,##__VA_ARGS__) | 797 | #define _leave(FMT,...) no_printk("<== %s()"FMT"",__func__ ,##__VA_ARGS__) |
804 | #define _debug(FMT,...) _dbprintk(" "FMT ,##__VA_ARGS__) | 798 | #define _debug(FMT,...) no_printk(" "FMT ,##__VA_ARGS__) |
805 | #endif | 799 | #endif |
806 | 800 | ||
807 | /* | 801 | /* |
diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index a8cd821226da..bd6bc1bde2d7 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h | |||
@@ -267,13 +267,6 @@ do { \ | |||
267 | #define dbgprintk(FMT, ...) \ | 267 | #define dbgprintk(FMT, ...) \ |
268 | printk(KERN_DEBUG "[%-6.6s] "FMT"\n", current->comm, ##__VA_ARGS__) | 268 | printk(KERN_DEBUG "[%-6.6s] "FMT"\n", current->comm, ##__VA_ARGS__) |
269 | 269 | ||
270 | /* make sure we maintain the format strings, even when debugging is disabled */ | ||
271 | static inline void _dbprintk(const char *fmt, ...) | ||
272 | __attribute__((format(printf, 1, 2))); | ||
273 | static inline void _dbprintk(const char *fmt, ...) | ||
274 | { | ||
275 | } | ||
276 | |||
277 | #define kenter(FMT, ...) dbgprintk("==> %s("FMT")", __func__, ##__VA_ARGS__) | 270 | #define kenter(FMT, ...) dbgprintk("==> %s("FMT")", __func__, ##__VA_ARGS__) |
278 | #define kleave(FMT, ...) dbgprintk("<== %s()"FMT"", __func__, ##__VA_ARGS__) | 271 | #define kleave(FMT, ...) dbgprintk("<== %s()"FMT"", __func__, ##__VA_ARGS__) |
279 | #define kdebug(FMT, ...) dbgprintk(FMT, ##__VA_ARGS__) | 272 | #define kdebug(FMT, ...) dbgprintk(FMT, ##__VA_ARGS__) |
@@ -304,9 +297,9 @@ do { \ | |||
304 | } while (0) | 297 | } while (0) |
305 | 298 | ||
306 | #else | 299 | #else |
307 | #define _enter(FMT, ...) _dbprintk("==> %s("FMT")", __func__, ##__VA_ARGS__) | 300 | #define _enter(FMT, ...) no_printk("==> %s("FMT")", __func__, ##__VA_ARGS__) |
308 | #define _leave(FMT, ...) _dbprintk("<== %s()"FMT"", __func__, ##__VA_ARGS__) | 301 | #define _leave(FMT, ...) no_printk("<== %s()"FMT"", __func__, ##__VA_ARGS__) |
309 | #define _debug(FMT, ...) _dbprintk(FMT, ##__VA_ARGS__) | 302 | #define _debug(FMT, ...) no_printk(FMT, ##__VA_ARGS__) |
310 | #endif | 303 | #endif |
311 | 304 | ||
312 | #if 1 /* defined(__KDEBUGALL) */ | 305 | #if 1 /* defined(__KDEBUGALL) */ |
diff --git a/fs/file_table.c b/fs/file_table.c index 2fc3b3c08911..edecd36fed9b 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -230,15 +230,6 @@ static void __fput(struct file *file) | |||
230 | might_sleep(); | 230 | might_sleep(); |
231 | 231 | ||
232 | fsnotify_close(file); | 232 | fsnotify_close(file); |
233 | |||
234 | /* | ||
235 | * fsnotify_create_event may have taken one or more references on this | ||
236 | * file. If it did so it left one reference for us to drop to make sure | ||
237 | * its calls to fput could not prematurely destroy the file. | ||
238 | */ | ||
239 | if (atomic_long_read(&file->f_count)) | ||
240 | return fput(file); | ||
241 | |||
242 | /* | 233 | /* |
243 | * The function eventpoll_release() should be the first called | 234 | * The function eventpoll_release() should be the first called |
244 | * in the file cleanup chain. | 235 | * in the file cleanup chain. |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 2f76c4a081a2..7d9d06ba184b 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -68,7 +68,7 @@ int nr_pdflush_threads; | |||
68 | */ | 68 | */ |
69 | int writeback_in_progress(struct backing_dev_info *bdi) | 69 | int writeback_in_progress(struct backing_dev_info *bdi) |
70 | { | 70 | { |
71 | return !list_empty(&bdi->work_list); | 71 | return test_bit(BDI_writeback_running, &bdi->state); |
72 | } | 72 | } |
73 | 73 | ||
74 | static void bdi_queue_work(struct backing_dev_info *bdi, | 74 | static void bdi_queue_work(struct backing_dev_info *bdi, |
@@ -249,10 +249,18 @@ static void move_expired_inodes(struct list_head *delaying_queue, | |||
249 | 249 | ||
250 | /* | 250 | /* |
251 | * Queue all expired dirty inodes for io, eldest first. | 251 | * Queue all expired dirty inodes for io, eldest first. |
252 | * Before | ||
253 | * newly dirtied b_dirty b_io b_more_io | ||
254 | * =============> gf edc BA | ||
255 | * After | ||
256 | * newly dirtied b_dirty b_io b_more_io | ||
257 | * =============> g fBAedc | ||
258 | * | | ||
259 | * +--> dequeue for IO | ||
252 | */ | 260 | */ |
253 | static void queue_io(struct bdi_writeback *wb, unsigned long *older_than_this) | 261 | static void queue_io(struct bdi_writeback *wb, unsigned long *older_than_this) |
254 | { | 262 | { |
255 | list_splice_init(&wb->b_more_io, wb->b_io.prev); | 263 | list_splice_init(&wb->b_more_io, &wb->b_io); |
256 | move_expired_inodes(&wb->b_dirty, &wb->b_io, older_than_this); | 264 | move_expired_inodes(&wb->b_dirty, &wb->b_io, older_than_this); |
257 | } | 265 | } |
258 | 266 | ||
@@ -363,62 +371,35 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) | |||
363 | spin_lock(&inode_lock); | 371 | spin_lock(&inode_lock); |
364 | inode->i_state &= ~I_SYNC; | 372 | inode->i_state &= ~I_SYNC; |
365 | if (!(inode->i_state & I_FREEING)) { | 373 | if (!(inode->i_state & I_FREEING)) { |
366 | if ((inode->i_state & I_DIRTY_PAGES) && wbc->for_kupdate) { | 374 | if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { |
367 | /* | ||
368 | * More pages get dirtied by a fast dirtier. | ||
369 | */ | ||
370 | goto select_queue; | ||
371 | } else if (inode->i_state & I_DIRTY) { | ||
372 | /* | ||
373 | * At least XFS will redirty the inode during the | ||
374 | * writeback (delalloc) and on io completion (isize). | ||
375 | */ | ||
376 | redirty_tail(inode); | ||
377 | } else if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { | ||
378 | /* | 375 | /* |
379 | * We didn't write back all the pages. nfs_writepages() | 376 | * We didn't write back all the pages. nfs_writepages() |
380 | * sometimes bales out without doing anything. Redirty | 377 | * sometimes bales out without doing anything. |
381 | * the inode; Move it from b_io onto b_more_io/b_dirty. | ||
382 | */ | 378 | */ |
383 | /* | 379 | inode->i_state |= I_DIRTY_PAGES; |
384 | * akpm: if the caller was the kupdate function we put | 380 | if (wbc->nr_to_write <= 0) { |
385 | * this inode at the head of b_dirty so it gets first | ||
386 | * consideration. Otherwise, move it to the tail, for | ||
387 | * the reasons described there. I'm not really sure | ||
388 | * how much sense this makes. Presumably I had a good | ||
389 | * reasons for doing it this way, and I'd rather not | ||
390 | * muck with it at present. | ||
391 | */ | ||
392 | if (wbc->for_kupdate) { | ||
393 | /* | 381 | /* |
394 | * For the kupdate function we move the inode | 382 | * slice used up: queue for next turn |
395 | * to b_more_io so it will get more writeout as | ||
396 | * soon as the queue becomes uncongested. | ||
397 | */ | 383 | */ |
398 | inode->i_state |= I_DIRTY_PAGES; | 384 | requeue_io(inode); |
399 | select_queue: | ||
400 | if (wbc->nr_to_write <= 0) { | ||
401 | /* | ||
402 | * slice used up: queue for next turn | ||
403 | */ | ||
404 | requeue_io(inode); | ||
405 | } else { | ||
406 | /* | ||
407 | * somehow blocked: retry later | ||
408 | */ | ||
409 | redirty_tail(inode); | ||
410 | } | ||
411 | } else { | 385 | } else { |
412 | /* | 386 | /* |
413 | * Otherwise fully redirty the inode so that | 387 | * Writeback blocked by something other than |
414 | * other inodes on this superblock will get some | 388 | * congestion. Delay the inode for some time to |
415 | * writeout. Otherwise heavy writing to one | 389 | * avoid spinning on the CPU (100% iowait) |
416 | * file would indefinitely suspend writeout of | 390 | * retrying writeback of the dirty page/inode |
417 | * all the other files. | 391 | * that cannot be performed immediately. |
418 | */ | 392 | */ |
419 | inode->i_state |= I_DIRTY_PAGES; | ||
420 | redirty_tail(inode); | 393 | redirty_tail(inode); |
421 | } | 394 | } |
395 | } else if (inode->i_state & I_DIRTY) { | ||
396 | /* | ||
397 | * Filesystems can dirty the inode during writeback | ||
398 | * operations, such as delayed allocation during | ||
399 | * submission or metadata updates after data IO | ||
400 | * completion. | ||
401 | */ | ||
402 | redirty_tail(inode); | ||
422 | } else if (atomic_read(&inode->i_count)) { | 403 | } else if (atomic_read(&inode->i_count)) { |
423 | /* | 404 | /* |
424 | * The inode is clean, inuse | 405 | * The inode is clean, inuse |
@@ -590,7 +571,7 @@ static inline bool over_bground_thresh(void) | |||
590 | { | 571 | { |
591 | unsigned long background_thresh, dirty_thresh; | 572 | unsigned long background_thresh, dirty_thresh; |
592 | 573 | ||
593 | get_dirty_limits(&background_thresh, &dirty_thresh, NULL, NULL); | 574 | global_dirty_limits(&background_thresh, &dirty_thresh); |
594 | 575 | ||
595 | return (global_page_state(NR_FILE_DIRTY) + | 576 | return (global_page_state(NR_FILE_DIRTY) + |
596 | global_page_state(NR_UNSTABLE_NFS) >= background_thresh); | 577 | global_page_state(NR_UNSTABLE_NFS) >= background_thresh); |
@@ -759,6 +740,7 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait) | |||
759 | struct wb_writeback_work *work; | 740 | struct wb_writeback_work *work; |
760 | long wrote = 0; | 741 | long wrote = 0; |
761 | 742 | ||
743 | set_bit(BDI_writeback_running, &wb->bdi->state); | ||
762 | while ((work = get_next_work_item(bdi)) != NULL) { | 744 | while ((work = get_next_work_item(bdi)) != NULL) { |
763 | /* | 745 | /* |
764 | * Override sync mode, in case we must wait for completion | 746 | * Override sync mode, in case we must wait for completion |
@@ -785,6 +767,7 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait) | |||
785 | * Check for periodic writeback, kupdated() style | 767 | * Check for periodic writeback, kupdated() style |
786 | */ | 768 | */ |
787 | wrote += wb_check_old_data_flush(wb); | 769 | wrote += wb_check_old_data_flush(wb); |
770 | clear_bit(BDI_writeback_running, &wb->bdi->state); | ||
788 | 771 | ||
789 | return wrote; | 772 | return wrote; |
790 | } | 773 | } |
diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h index 6a026441c5a6..f6aad48d38a8 100644 --- a/fs/fscache/internal.h +++ b/fs/fscache/internal.h | |||
@@ -321,17 +321,11 @@ void fscache_put_context(struct fscache_cookie *cookie, void *context) | |||
321 | #define dbgprintk(FMT, ...) \ | 321 | #define dbgprintk(FMT, ...) \ |
322 | printk(KERN_DEBUG "[%-6.6s] "FMT"\n", current->comm, ##__VA_ARGS__) | 322 | printk(KERN_DEBUG "[%-6.6s] "FMT"\n", current->comm, ##__VA_ARGS__) |
323 | 323 | ||
324 | /* make sure we maintain the format strings, even when debugging is disabled */ | ||
325 | static inline __attribute__((format(printf, 1, 2))) | ||
326 | void _dbprintk(const char *fmt, ...) | ||
327 | { | ||
328 | } | ||
329 | |||
330 | #define kenter(FMT, ...) dbgprintk("==> %s("FMT")", __func__, ##__VA_ARGS__) | 324 | #define kenter(FMT, ...) dbgprintk("==> %s("FMT")", __func__, ##__VA_ARGS__) |
331 | #define kleave(FMT, ...) dbgprintk("<== %s()"FMT"", __func__, ##__VA_ARGS__) | 325 | #define kleave(FMT, ...) dbgprintk("<== %s()"FMT"", __func__, ##__VA_ARGS__) |
332 | #define kdebug(FMT, ...) dbgprintk(FMT, ##__VA_ARGS__) | 326 | #define kdebug(FMT, ...) dbgprintk(FMT, ##__VA_ARGS__) |
333 | 327 | ||
334 | #define kjournal(FMT, ...) _dbprintk(FMT, ##__VA_ARGS__) | 328 | #define kjournal(FMT, ...) no_printk(FMT, ##__VA_ARGS__) |
335 | 329 | ||
336 | #ifdef __KDEBUG | 330 | #ifdef __KDEBUG |
337 | #define _enter(FMT, ...) kenter(FMT, ##__VA_ARGS__) | 331 | #define _enter(FMT, ...) kenter(FMT, ##__VA_ARGS__) |
@@ -358,9 +352,9 @@ do { \ | |||
358 | } while (0) | 352 | } while (0) |
359 | 353 | ||
360 | #else | 354 | #else |
361 | #define _enter(FMT, ...) _dbprintk("==> %s("FMT")", __func__, ##__VA_ARGS__) | 355 | #define _enter(FMT, ...) no_printk("==> %s("FMT")", __func__, ##__VA_ARGS__) |
362 | #define _leave(FMT, ...) _dbprintk("<== %s()"FMT"", __func__, ##__VA_ARGS__) | 356 | #define _leave(FMT, ...) no_printk("<== %s()"FMT"", __func__, ##__VA_ARGS__) |
363 | #define _debug(FMT, ...) _dbprintk(FMT, ##__VA_ARGS__) | 357 | #define _debug(FMT, ...) no_printk(FMT, ##__VA_ARGS__) |
364 | #endif | 358 | #endif |
365 | 359 | ||
366 | /* | 360 | /* |
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 36dfdae95123..e17b49e2eabd 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
@@ -45,7 +45,7 @@ unsigned short nfs_callback_tcpport; | |||
45 | unsigned short nfs_callback_tcpport6; | 45 | unsigned short nfs_callback_tcpport6; |
46 | #define NFS_CALLBACK_MAXPORTNR (65535U) | 46 | #define NFS_CALLBACK_MAXPORTNR (65535U) |
47 | 47 | ||
48 | static int param_set_portnr(const char *val, struct kernel_param *kp) | 48 | static int param_set_portnr(const char *val, const struct kernel_param *kp) |
49 | { | 49 | { |
50 | unsigned long num; | 50 | unsigned long num; |
51 | int ret; | 51 | int ret; |
@@ -58,11 +58,10 @@ static int param_set_portnr(const char *val, struct kernel_param *kp) | |||
58 | *((unsigned int *)kp->arg) = num; | 58 | *((unsigned int *)kp->arg) = num; |
59 | return 0; | 59 | return 0; |
60 | } | 60 | } |
61 | 61 | static struct kernel_param_ops param_ops_portnr = { | |
62 | static int param_get_portnr(char *buffer, struct kernel_param *kp) | 62 | .set = param_set_portnr, |
63 | { | 63 | .get = param_get_uint, |
64 | return param_get_uint(buffer, kp); | 64 | }; |
65 | } | ||
66 | #define param_check_portnr(name, p) __param_check(name, p, unsigned int); | 65 | #define param_check_portnr(name, p) __param_check(name, p, unsigned int); |
67 | 66 | ||
68 | module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644); | 67 | module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644); |
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index eb8f73c9c131..756566fe8449 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c | |||
@@ -17,9 +17,9 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new) | |||
17 | old->data_type == new->data_type && | 17 | old->data_type == new->data_type && |
18 | old->tgid == new->tgid) { | 18 | old->tgid == new->tgid) { |
19 | switch (old->data_type) { | 19 | switch (old->data_type) { |
20 | case (FSNOTIFY_EVENT_FILE): | 20 | case (FSNOTIFY_EVENT_PATH): |
21 | if ((old->file->f_path.mnt == new->file->f_path.mnt) && | 21 | if ((old->path.mnt == new->path.mnt) && |
22 | (old->file->f_path.dentry == new->file->f_path.dentry)) | 22 | (old->path.dentry == new->path.dentry)) |
23 | return true; | 23 | return true; |
24 | case (FSNOTIFY_EVENT_NONE): | 24 | case (FSNOTIFY_EVENT_NONE): |
25 | return true; | 25 | return true; |
@@ -174,7 +174,7 @@ static bool fanotify_should_send_event(struct fsnotify_group *group, | |||
174 | return false; | 174 | return false; |
175 | 175 | ||
176 | /* if we don't have enough info to send an event to userspace say no */ | 176 | /* if we don't have enough info to send an event to userspace say no */ |
177 | if (data_type != FSNOTIFY_EVENT_FILE) | 177 | if (data_type != FSNOTIFY_EVENT_PATH) |
178 | return false; | 178 | return false; |
179 | 179 | ||
180 | if (inode_mark && vfsmnt_mark) { | 180 | if (inode_mark && vfsmnt_mark) { |
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 25a3b4dfcf61..032b837fcd11 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c | |||
@@ -65,7 +65,7 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event) | |||
65 | if (client_fd < 0) | 65 | if (client_fd < 0) |
66 | return client_fd; | 66 | return client_fd; |
67 | 67 | ||
68 | if (event->data_type != FSNOTIFY_EVENT_FILE) { | 68 | if (event->data_type != FSNOTIFY_EVENT_PATH) { |
69 | WARN_ON(1); | 69 | WARN_ON(1); |
70 | put_unused_fd(client_fd); | 70 | put_unused_fd(client_fd); |
71 | return -EINVAL; | 71 | return -EINVAL; |
@@ -75,8 +75,8 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event) | |||
75 | * we need a new file handle for the userspace program so it can read even if it was | 75 | * we need a new file handle for the userspace program so it can read even if it was |
76 | * originally opened O_WRONLY. | 76 | * originally opened O_WRONLY. |
77 | */ | 77 | */ |
78 | dentry = dget(event->file->f_path.dentry); | 78 | dentry = dget(event->path.dentry); |
79 | mnt = mntget(event->file->f_path.mnt); | 79 | mnt = mntget(event->path.mnt); |
80 | /* it's possible this event was an overflow event. in that case dentry and mnt | 80 | /* it's possible this event was an overflow event. in that case dentry and mnt |
81 | * are NULL; That's fine, just don't call dentry open */ | 81 | * are NULL; That's fine, just don't call dentry open */ |
82 | if (dentry && mnt) | 82 | if (dentry && mnt) |
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 4d2a82c1ceb1..3970392b2722 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c | |||
@@ -84,7 +84,7 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode) | |||
84 | } | 84 | } |
85 | 85 | ||
86 | /* Notify this dentry's parent about a child's events. */ | 86 | /* Notify this dentry's parent about a child's events. */ |
87 | void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask) | 87 | void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) |
88 | { | 88 | { |
89 | struct dentry *parent; | 89 | struct dentry *parent; |
90 | struct inode *p_inode; | 90 | struct inode *p_inode; |
@@ -92,7 +92,7 @@ void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask) | |||
92 | bool should_update_children = false; | 92 | bool should_update_children = false; |
93 | 93 | ||
94 | if (!dentry) | 94 | if (!dentry) |
95 | dentry = file->f_path.dentry; | 95 | dentry = path->dentry; |
96 | 96 | ||
97 | if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED)) | 97 | if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED)) |
98 | return; | 98 | return; |
@@ -124,8 +124,8 @@ void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask) | |||
124 | * specifies these are events which came from a child. */ | 124 | * specifies these are events which came from a child. */ |
125 | mask |= FS_EVENT_ON_CHILD; | 125 | mask |= FS_EVENT_ON_CHILD; |
126 | 126 | ||
127 | if (file) | 127 | if (path) |
128 | fsnotify(p_inode, mask, file, FSNOTIFY_EVENT_FILE, | 128 | fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH, |
129 | dentry->d_name.name, 0); | 129 | dentry->d_name.name, 0); |
130 | else | 130 | else |
131 | fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE, | 131 | fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE, |
@@ -217,8 +217,8 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, | |||
217 | /* global tests shouldn't care about events on child only the specific event */ | 217 | /* global tests shouldn't care about events on child only the specific event */ |
218 | __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); | 218 | __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); |
219 | 219 | ||
220 | if (data_is == FSNOTIFY_EVENT_FILE) | 220 | if (data_is == FSNOTIFY_EVENT_PATH) |
221 | mnt = ((struct file *)data)->f_path.mnt; | 221 | mnt = ((struct path *)data)->mnt; |
222 | else | 222 | else |
223 | mnt = NULL; | 223 | mnt = NULL; |
224 | 224 | ||
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index 5e73eeb2c697..a91b69a6a291 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c | |||
@@ -52,9 +52,9 @@ static bool event_compare(struct fsnotify_event *old, struct fsnotify_event *new | |||
52 | !strcmp(old->file_name, new->file_name)) | 52 | !strcmp(old->file_name, new->file_name)) |
53 | return true; | 53 | return true; |
54 | break; | 54 | break; |
55 | case (FSNOTIFY_EVENT_FILE): | 55 | case (FSNOTIFY_EVENT_PATH): |
56 | if ((old->file->f_path.mnt == new->file->f_path.mnt) && | 56 | if ((old->path.mnt == new->path.mnt) && |
57 | (old->file->f_path.dentry == new->file->f_path.dentry)) | 57 | (old->path.dentry == new->path.dentry)) |
58 | return true; | 58 | return true; |
59 | break; | 59 | break; |
60 | case (FSNOTIFY_EVENT_NONE): | 60 | case (FSNOTIFY_EVENT_NONE): |
@@ -147,10 +147,10 @@ static bool inotify_should_send_event(struct fsnotify_group *group, struct inode | |||
147 | __u32 mask, void *data, int data_type) | 147 | __u32 mask, void *data, int data_type) |
148 | { | 148 | { |
149 | if ((inode_mark->mask & FS_EXCL_UNLINK) && | 149 | if ((inode_mark->mask & FS_EXCL_UNLINK) && |
150 | (data_type == FSNOTIFY_EVENT_FILE)) { | 150 | (data_type == FSNOTIFY_EVENT_PATH)) { |
151 | struct file *file = data; | 151 | struct path *path = data; |
152 | 152 | ||
153 | if (d_unlinked(file->f_path.dentry)) | 153 | if (d_unlinked(path->dentry)) |
154 | return false; | 154 | return false; |
155 | } | 155 | } |
156 | 156 | ||
diff --git a/fs/notify/notification.c b/fs/notify/notification.c index d6c435adc7a2..f39260f8f865 100644 --- a/fs/notify/notification.c +++ b/fs/notify/notification.c | |||
@@ -31,7 +31,6 @@ | |||
31 | * allocated and used. | 31 | * allocated and used. |
32 | */ | 32 | */ |
33 | 33 | ||
34 | #include <linux/file.h> | ||
35 | #include <linux/fs.h> | 34 | #include <linux/fs.h> |
36 | #include <linux/init.h> | 35 | #include <linux/init.h> |
37 | #include <linux/kernel.h> | 36 | #include <linux/kernel.h> |
@@ -90,8 +89,8 @@ void fsnotify_put_event(struct fsnotify_event *event) | |||
90 | if (atomic_dec_and_test(&event->refcnt)) { | 89 | if (atomic_dec_and_test(&event->refcnt)) { |
91 | pr_debug("%s: event=%p\n", __func__, event); | 90 | pr_debug("%s: event=%p\n", __func__, event); |
92 | 91 | ||
93 | if (event->data_type == FSNOTIFY_EVENT_FILE) | 92 | if (event->data_type == FSNOTIFY_EVENT_PATH) |
94 | fput(event->file); | 93 | path_put(&event->path); |
95 | 94 | ||
96 | BUG_ON(!list_empty(&event->private_data_list)); | 95 | BUG_ON(!list_empty(&event->private_data_list)); |
97 | 96 | ||
@@ -376,8 +375,8 @@ struct fsnotify_event *fsnotify_clone_event(struct fsnotify_event *old_event) | |||
376 | } | 375 | } |
377 | } | 376 | } |
378 | event->tgid = get_pid(old_event->tgid); | 377 | event->tgid = get_pid(old_event->tgid); |
379 | if (event->data_type == FSNOTIFY_EVENT_FILE) | 378 | if (event->data_type == FSNOTIFY_EVENT_PATH) |
380 | get_file(event->file); | 379 | path_get(&event->path); |
381 | 380 | ||
382 | return event; | 381 | return event; |
383 | } | 382 | } |
@@ -424,22 +423,11 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, | |||
424 | event->data_type = data_type; | 423 | event->data_type = data_type; |
425 | 424 | ||
426 | switch (data_type) { | 425 | switch (data_type) { |
427 | case FSNOTIFY_EVENT_FILE: { | 426 | case FSNOTIFY_EVENT_PATH: { |
428 | event->file = data; | 427 | struct path *path = data; |
429 | /* | 428 | event->path.dentry = path->dentry; |
430 | * if this file is about to disappear hold an extra reference | 429 | event->path.mnt = path->mnt; |
431 | * until we return to __fput so we don't have to worry about | 430 | path_get(&event->path); |
432 | * future get/put destroying the file under us or generating | ||
433 | * additional events. Notice that we change f_mode without | ||
434 | * holding f_lock. This is safe since this is the only possible | ||
435 | * reference to this object in the kernel (it was about to be | ||
436 | * freed, remember?) | ||
437 | */ | ||
438 | if (!atomic_long_read(&event->file->f_count)) { | ||
439 | event->file->f_mode |= FMODE_NONOTIFY; | ||
440 | get_file(event->file); | ||
441 | } | ||
442 | get_file(event->file); | ||
443 | break; | 431 | break; |
444 | } | 432 | } |
445 | case FSNOTIFY_EVENT_INODE: | 433 | case FSNOTIFY_EVENT_INODE: |
@@ -447,7 +435,8 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, | |||
447 | break; | 435 | break; |
448 | case FSNOTIFY_EVENT_NONE: | 436 | case FSNOTIFY_EVENT_NONE: |
449 | event->inode = NULL; | 437 | event->inode = NULL; |
450 | event->file = NULL; | 438 | event->path.dentry = NULL; |
439 | event->path.mnt = NULL; | ||
451 | break; | 440 | break; |
452 | default: | 441 | default: |
453 | BUG(); | 442 | BUG(); |
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index e5039a2856f8..103f08aca764 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h | |||
@@ -148,13 +148,17 @@ static inline void *acpi_os_acquire_object(acpi_cache_t * cache) | |||
148 | #define ACPI_ALLOCATE_ZEROED(a) acpi_os_allocate_zeroed(a) | 148 | #define ACPI_ALLOCATE_ZEROED(a) acpi_os_allocate_zeroed(a) |
149 | #define ACPI_FREE(a) kfree(a) | 149 | #define ACPI_FREE(a) kfree(a) |
150 | 150 | ||
151 | /* Used within ACPICA to show where it is safe to preempt execution */ | 151 | #ifndef CONFIG_PREEMPT |
152 | #include <linux/hardirq.h> | 152 | /* |
153 | * Used within ACPICA to show where it is safe to preempt execution | ||
154 | * when CONFIG_PREEMPT=n | ||
155 | */ | ||
153 | #define ACPI_PREEMPTION_POINT() \ | 156 | #define ACPI_PREEMPTION_POINT() \ |
154 | do { \ | 157 | do { \ |
155 | if (!in_atomic_preempt_off() && !irqs_disabled()) \ | 158 | if (!irqs_disabled()) \ |
156 | cond_resched(); \ | 159 | cond_resched(); \ |
157 | } while (0) | 160 | } while (0) |
161 | #endif | ||
158 | 162 | ||
159 | #endif /* __KERNEL__ */ | 163 | #endif /* __KERNEL__ */ |
160 | 164 | ||
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index e2a4da7d7fab..2a512bc0d4ab 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
@@ -1075,7 +1075,6 @@ static __inline__ int drm_core_check_feature(struct drm_device *dev, | |||
1075 | return ((dev->driver->driver_features & feature) ? 1 : 0); | 1075 | return ((dev->driver->driver_features & feature) ? 1 : 0); |
1076 | } | 1076 | } |
1077 | 1077 | ||
1078 | |||
1079 | static inline int drm_dev_to_irq(struct drm_device *dev) | 1078 | static inline int drm_dev_to_irq(struct drm_device *dev) |
1080 | { | 1079 | { |
1081 | if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) | 1080 | if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) |
@@ -1084,11 +1083,22 @@ static inline int drm_dev_to_irq(struct drm_device *dev) | |||
1084 | return dev->pdev->irq; | 1083 | return dev->pdev->irq; |
1085 | } | 1084 | } |
1086 | 1085 | ||
1087 | #ifdef __alpha__ | 1086 | static inline int drm_get_pci_domain(struct drm_device *dev) |
1088 | #define drm_get_pci_domain(dev) dev->hose->index | 1087 | { |
1089 | #else | 1088 | if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) |
1090 | #define drm_get_pci_domain(dev) 0 | 1089 | return 0; |
1091 | #endif | 1090 | |
1091 | #ifndef __alpha__ | ||
1092 | /* For historical reasons, drm_get_pci_domain() is busticated | ||
1093 | * on most archs and has to remain so for userspace interface | ||
1094 | * < 1.4, except on alpha which was right from the beginning | ||
1095 | */ | ||
1096 | if (dev->if_version < 0x10004) | ||
1097 | return 0; | ||
1098 | #endif /* __alpha__ */ | ||
1099 | |||
1100 | return pci_domain_nr(dev->pdev->bus); | ||
1101 | } | ||
1092 | 1102 | ||
1093 | #if __OS_HAS_AGP | 1103 | #if __OS_HAS_AGP |
1094 | static inline int drm_core_has_AGP(struct drm_device *dev) | 1104 | static inline int drm_core_has_AGP(struct drm_device *dev) |
diff --git a/include/drm/drm_core.h b/include/drm/drm_core.h index 316739036079..4e7523863a4b 100644 --- a/include/drm/drm_core.h +++ b/include/drm/drm_core.h | |||
@@ -27,7 +27,7 @@ | |||
27 | #define CORE_DATE "20060810" | 27 | #define CORE_DATE "20060810" |
28 | 28 | ||
29 | #define DRM_IF_MAJOR 1 | 29 | #define DRM_IF_MAJOR 1 |
30 | #define DRM_IF_MINOR 3 | 30 | #define DRM_IF_MINOR 4 |
31 | 31 | ||
32 | #define CORE_MAJOR 1 | 32 | #define CORE_MAJOR 1 |
33 | #define CORE_MINOR 1 | 33 | #define CORE_MINOR 1 |
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c707270bff5a..c9f3cc5949a8 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
@@ -189,49 +189,16 @@ enum subpixel_order { | |||
189 | */ | 189 | */ |
190 | struct drm_display_info { | 190 | struct drm_display_info { |
191 | char name[DRM_DISPLAY_INFO_LEN]; | 191 | char name[DRM_DISPLAY_INFO_LEN]; |
192 | /* Input info */ | 192 | |
193 | bool serration_vsync; | ||
194 | bool sync_on_green; | ||
195 | bool composite_sync; | ||
196 | bool separate_syncs; | ||
197 | bool blank_to_black; | ||
198 | unsigned char video_level; | ||
199 | bool digital; | ||
200 | /* Physical size */ | 193 | /* Physical size */ |
201 | unsigned int width_mm; | 194 | unsigned int width_mm; |
202 | unsigned int height_mm; | 195 | unsigned int height_mm; |
203 | 196 | ||
204 | /* Display parameters */ | ||
205 | unsigned char gamma; /* FIXME: storage format */ | ||
206 | bool gtf_supported; | ||
207 | bool standard_color; | ||
208 | enum { | ||
209 | monochrome = 0, | ||
210 | rgb, | ||
211 | other, | ||
212 | unknown, | ||
213 | } display_type; | ||
214 | bool active_off_supported; | ||
215 | bool suspend_supported; | ||
216 | bool standby_supported; | ||
217 | |||
218 | /* Color info FIXME: storage format */ | ||
219 | unsigned short redx, redy; | ||
220 | unsigned short greenx, greeny; | ||
221 | unsigned short bluex, bluey; | ||
222 | unsigned short whitex, whitey; | ||
223 | |||
224 | /* Clock limits FIXME: storage format */ | 197 | /* Clock limits FIXME: storage format */ |
225 | unsigned int min_vfreq, max_vfreq; | 198 | unsigned int min_vfreq, max_vfreq; |
226 | unsigned int min_hfreq, max_hfreq; | 199 | unsigned int min_hfreq, max_hfreq; |
227 | unsigned int pixel_clock; | 200 | unsigned int pixel_clock; |
228 | 201 | ||
229 | /* White point indices FIXME: storage format */ | ||
230 | unsigned int wpx1, wpy1; | ||
231 | unsigned int wpgamma1; | ||
232 | unsigned int wpx2, wpy2; | ||
233 | unsigned int wpgamma2; | ||
234 | |||
235 | enum subpixel_order subpixel_order; | 202 | enum subpixel_order subpixel_order; |
236 | 203 | ||
237 | char *raw_edid; /* if any */ | 204 | char *raw_edid; /* if any */ |
@@ -342,7 +309,7 @@ struct drm_crtc_funcs { | |||
342 | 309 | ||
343 | /* Set gamma on the CRTC */ | 310 | /* Set gamma on the CRTC */ |
344 | void (*gamma_set)(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, | 311 | void (*gamma_set)(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, |
345 | uint32_t size); | 312 | uint32_t start, uint32_t size); |
346 | /* Object destroy routine */ | 313 | /* Object destroy routine */ |
347 | void (*destroy)(struct drm_crtc *crtc); | 314 | void (*destroy)(struct drm_crtc *crtc); |
348 | 315 | ||
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 39e2cc5c7e66..5881fad91faa 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h | |||
@@ -28,6 +28,12 @@ | |||
28 | #define EDID_LENGTH 128 | 28 | #define EDID_LENGTH 128 |
29 | #define DDC_ADDR 0x50 | 29 | #define DDC_ADDR 0x50 |
30 | 30 | ||
31 | #define CEA_EXT 0x02 | ||
32 | #define VTB_EXT 0x10 | ||
33 | #define DI_EXT 0x40 | ||
34 | #define LS_EXT 0x50 | ||
35 | #define MI_EXT 0x60 | ||
36 | |||
31 | struct est_timings { | 37 | struct est_timings { |
32 | u8 t1; | 38 | u8 t1; |
33 | u8 t2; | 39 | u8 t2; |
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index 7628219e5386..35b00746c712 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h | |||
@@ -31,6 +31,7 @@ enum bdi_state { | |||
31 | BDI_async_congested, /* The async (write) queue is getting full */ | 31 | BDI_async_congested, /* The async (write) queue is getting full */ |
32 | BDI_sync_congested, /* The sync queue is getting full */ | 32 | BDI_sync_congested, /* The sync queue is getting full */ |
33 | BDI_registered, /* bdi_register() was done */ | 33 | BDI_registered, /* bdi_register() was done */ |
34 | BDI_writeback_running, /* Writeback is in progress */ | ||
34 | BDI_unused, /* Available bits start here */ | 35 | BDI_unused, /* Available bits start here */ |
35 | }; | 36 | }; |
36 | 37 | ||
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 53691774d34e..ca83a97c9715 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h | |||
@@ -150,6 +150,7 @@ enum rq_flag_bits { | |||
150 | __REQ_FLUSH, /* request for cache flush */ | 150 | __REQ_FLUSH, /* request for cache flush */ |
151 | __REQ_IO_STAT, /* account I/O stat */ | 151 | __REQ_IO_STAT, /* account I/O stat */ |
152 | __REQ_MIXED_MERGE, /* merge of different types, fail separately */ | 152 | __REQ_MIXED_MERGE, /* merge of different types, fail separately */ |
153 | __REQ_SECURE, /* secure discard (used with __REQ_DISCARD) */ | ||
153 | __REQ_NR_BITS, /* stops here */ | 154 | __REQ_NR_BITS, /* stops here */ |
154 | }; | 155 | }; |
155 | 156 | ||
@@ -190,5 +191,6 @@ enum rq_flag_bits { | |||
190 | #define REQ_FLUSH (1 << __REQ_FLUSH) | 191 | #define REQ_FLUSH (1 << __REQ_FLUSH) |
191 | #define REQ_IO_STAT (1 << __REQ_IO_STAT) | 192 | #define REQ_IO_STAT (1 << __REQ_IO_STAT) |
192 | #define REQ_MIXED_MERGE (1 << __REQ_MIXED_MERGE) | 193 | #define REQ_MIXED_MERGE (1 << __REQ_MIXED_MERGE) |
194 | #define REQ_SECURE (1 << __REQ_SECURE) | ||
193 | 195 | ||
194 | #endif /* __LINUX_BLK_TYPES_H */ | 196 | #endif /* __LINUX_BLK_TYPES_H */ |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 89c855c5655c..2c54906f678f 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -389,6 +389,7 @@ struct request_queue | |||
389 | #define QUEUE_FLAG_DISCARD 16 /* supports DISCARD */ | 389 | #define QUEUE_FLAG_DISCARD 16 /* supports DISCARD */ |
390 | #define QUEUE_FLAG_NOXMERGES 17 /* No extended merges */ | 390 | #define QUEUE_FLAG_NOXMERGES 17 /* No extended merges */ |
391 | #define QUEUE_FLAG_ADD_RANDOM 18 /* Contributes to random pool */ | 391 | #define QUEUE_FLAG_ADD_RANDOM 18 /* Contributes to random pool */ |
392 | #define QUEUE_FLAG_SECDISCARD 19 /* supports SECDISCARD */ | ||
392 | 393 | ||
393 | #define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ | 394 | #define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ |
394 | (1 << QUEUE_FLAG_CLUSTER) | \ | 395 | (1 << QUEUE_FLAG_CLUSTER) | \ |
@@ -524,6 +525,8 @@ enum { | |||
524 | #define blk_queue_stackable(q) \ | 525 | #define blk_queue_stackable(q) \ |
525 | test_bit(QUEUE_FLAG_STACKABLE, &(q)->queue_flags) | 526 | test_bit(QUEUE_FLAG_STACKABLE, &(q)->queue_flags) |
526 | #define blk_queue_discard(q) test_bit(QUEUE_FLAG_DISCARD, &(q)->queue_flags) | 527 | #define blk_queue_discard(q) test_bit(QUEUE_FLAG_DISCARD, &(q)->queue_flags) |
528 | #define blk_queue_secdiscard(q) (blk_queue_discard(q) && \ | ||
529 | test_bit(QUEUE_FLAG_SECDISCARD, &(q)->queue_flags)) | ||
527 | 530 | ||
528 | #define blk_noretry_request(rq) \ | 531 | #define blk_noretry_request(rq) \ |
529 | ((rq)->cmd_flags & (REQ_FAILFAST_DEV|REQ_FAILFAST_TRANSPORT| \ | 532 | ((rq)->cmd_flags & (REQ_FAILFAST_DEV|REQ_FAILFAST_TRANSPORT| \ |
@@ -918,10 +921,12 @@ static inline struct request *blk_map_queue_find_tag(struct blk_queue_tag *bqt, | |||
918 | } | 921 | } |
919 | enum{ | 922 | enum{ |
920 | BLKDEV_WAIT, /* wait for completion */ | 923 | BLKDEV_WAIT, /* wait for completion */ |
921 | BLKDEV_BARRIER, /*issue request with barrier */ | 924 | BLKDEV_BARRIER, /* issue request with barrier */ |
925 | BLKDEV_SECURE, /* secure discard */ | ||
922 | }; | 926 | }; |
923 | #define BLKDEV_IFL_WAIT (1 << BLKDEV_WAIT) | 927 | #define BLKDEV_IFL_WAIT (1 << BLKDEV_WAIT) |
924 | #define BLKDEV_IFL_BARRIER (1 << BLKDEV_BARRIER) | 928 | #define BLKDEV_IFL_BARRIER (1 << BLKDEV_BARRIER) |
929 | #define BLKDEV_IFL_SECURE (1 << BLKDEV_SECURE) | ||
925 | extern int blkdev_issue_flush(struct block_device *, gfp_t, sector_t *, | 930 | extern int blkdev_issue_flush(struct block_device *, gfp_t, sector_t *, |
926 | unsigned long); | 931 | unsigned long); |
927 | extern int blkdev_issue_discard(struct block_device *bdev, sector_t sector, | 932 | extern int blkdev_issue_discard(struct block_device *bdev, sector_t sector, |
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 1381cd97b4ed..2970022faa63 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h | |||
@@ -22,7 +22,7 @@ typedef enum { STATUSTYPE_INFO, STATUSTYPE_TABLE } status_type_t; | |||
22 | union map_info { | 22 | union map_info { |
23 | void *ptr; | 23 | void *ptr; |
24 | unsigned long long ll; | 24 | unsigned long long ll; |
25 | unsigned flush_request; | 25 | unsigned target_request_nr; |
26 | }; | 26 | }; |
27 | 27 | ||
28 | /* | 28 | /* |
@@ -174,12 +174,18 @@ struct dm_target { | |||
174 | * A number of zero-length barrier requests that will be submitted | 174 | * A number of zero-length barrier requests that will be submitted |
175 | * to the target for the purpose of flushing cache. | 175 | * to the target for the purpose of flushing cache. |
176 | * | 176 | * |
177 | * The request number will be placed in union map_info->flush_request. | 177 | * The request number will be placed in union map_info->target_request_nr. |
178 | * It is a responsibility of the target driver to remap these requests | 178 | * It is a responsibility of the target driver to remap these requests |
179 | * to the real underlying devices. | 179 | * to the real underlying devices. |
180 | */ | 180 | */ |
181 | unsigned num_flush_requests; | 181 | unsigned num_flush_requests; |
182 | 182 | ||
183 | /* | ||
184 | * The number of discard requests that will be submitted to the | ||
185 | * target. map_info->request_nr is used just like num_flush_requests. | ||
186 | */ | ||
187 | unsigned num_discard_requests; | ||
188 | |||
183 | /* target specific data */ | 189 | /* target specific data */ |
184 | void *private; | 190 | void *private; |
185 | 191 | ||
@@ -392,6 +398,12 @@ void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size); | |||
392 | #define dm_array_too_big(fixed, obj, num) \ | 398 | #define dm_array_too_big(fixed, obj, num) \ |
393 | ((num) > (UINT_MAX - (fixed)) / (obj)) | 399 | ((num) > (UINT_MAX - (fixed)) / (obj)) |
394 | 400 | ||
401 | /* | ||
402 | * Sector offset taken relative to the start of the target instead of | ||
403 | * relative to the start of the device. | ||
404 | */ | ||
405 | #define dm_target_offset(ti, sector) ((sector) - (ti)->begin) | ||
406 | |||
395 | static inline sector_t to_sector(unsigned long n) | 407 | static inline sector_t to_sector(unsigned long n) |
396 | { | 408 | { |
397 | return (n >> SECTOR_SHIFT); | 409 | return (n >> SECTOR_SHIFT); |
diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h index 2c445e113790..49eab360d5d4 100644 --- a/include/linux/dm-ioctl.h +++ b/include/linux/dm-ioctl.h | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | 12 | ||
13 | #define DM_DIR "mapper" /* Slashes not supported */ | 13 | #define DM_DIR "mapper" /* Slashes not supported */ |
14 | #define DM_CONTROL_NODE "control" | ||
14 | #define DM_MAX_TYPE_NAME 16 | 15 | #define DM_MAX_TYPE_NAME 16 |
15 | #define DM_NAME_LEN 128 | 16 | #define DM_NAME_LEN 128 |
16 | #define DM_UUID_LEN 129 | 17 | #define DM_UUID_LEN 129 |
@@ -266,9 +267,9 @@ enum { | |||
266 | #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) | 267 | #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) |
267 | 268 | ||
268 | #define DM_VERSION_MAJOR 4 | 269 | #define DM_VERSION_MAJOR 4 |
269 | #define DM_VERSION_MINOR 17 | 270 | #define DM_VERSION_MINOR 18 |
270 | #define DM_VERSION_PATCHLEVEL 0 | 271 | #define DM_VERSION_PATCHLEVEL 0 |
271 | #define DM_VERSION_EXTRA "-ioctl (2010-03-05)" | 272 | #define DM_VERSION_EXTRA "-ioctl (2010-06-29)" |
272 | 273 | ||
273 | /* Status bits */ | 274 | /* Status bits */ |
274 | #define DM_READONLY_FLAG (1 << 0) /* In/Out */ | 275 | #define DM_READONLY_FLAG (1 << 0) /* In/Out */ |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 267d02630517..7a0625e26a39 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -174,6 +174,7 @@ struct inodes_stat_t { | |||
174 | */ | 174 | */ |
175 | #define DISCARD_NOBARRIER (WRITE | REQ_DISCARD) | 175 | #define DISCARD_NOBARRIER (WRITE | REQ_DISCARD) |
176 | #define DISCARD_BARRIER (WRITE | REQ_DISCARD | REQ_HARDBARRIER) | 176 | #define DISCARD_BARRIER (WRITE | REQ_DISCARD | REQ_HARDBARRIER) |
177 | #define DISCARD_SECURE (DISCARD_NOBARRIER | REQ_SECURE) | ||
177 | 178 | ||
178 | #define SEL_IN 1 | 179 | #define SEL_IN 1 |
179 | #define SEL_OUT 2 | 180 | #define SEL_OUT 2 |
@@ -317,6 +318,7 @@ struct inodes_stat_t { | |||
317 | #define BLKALIGNOFF _IO(0x12,122) | 318 | #define BLKALIGNOFF _IO(0x12,122) |
318 | #define BLKPBSZGET _IO(0x12,123) | 319 | #define BLKPBSZGET _IO(0x12,123) |
319 | #define BLKDISCARDZEROES _IO(0x12,124) | 320 | #define BLKDISCARDZEROES _IO(0x12,124) |
321 | #define BLKSECDISCARD _IO(0x12,125) | ||
320 | 322 | ||
321 | #define BMAP_IOCTL 1 /* obsolete - kept for compatibility */ | 323 | #define BMAP_IOCTL 1 /* obsolete - kept for compatibility */ |
322 | #define FIBMAP _IO(0x00,1) /* bmap access */ | 324 | #define FIBMAP _IO(0x00,1) /* bmap access */ |
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index e4e2204187ee..59d0df43ff9d 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h | |||
@@ -26,18 +26,19 @@ static inline void fsnotify_d_instantiate(struct dentry *dentry, | |||
26 | } | 26 | } |
27 | 27 | ||
28 | /* Notify this dentry's parent about a child's events. */ | 28 | /* Notify this dentry's parent about a child's events. */ |
29 | static inline void fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask) | 29 | static inline void fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) |
30 | { | 30 | { |
31 | if (!dentry) | 31 | if (!dentry) |
32 | dentry = file->f_path.dentry; | 32 | dentry = path->dentry; |
33 | 33 | ||
34 | __fsnotify_parent(file, dentry, mask); | 34 | __fsnotify_parent(path, dentry, mask); |
35 | } | 35 | } |
36 | 36 | ||
37 | /* simple call site for access decisions */ | 37 | /* simple call site for access decisions */ |
38 | static inline int fsnotify_perm(struct file *file, int mask) | 38 | static inline int fsnotify_perm(struct file *file, int mask) |
39 | { | 39 | { |
40 | struct inode *inode = file->f_path.dentry->d_inode; | 40 | struct path *path = &file->f_path; |
41 | struct inode *inode = path->dentry->d_inode; | ||
41 | __u32 fsnotify_mask = 0; | 42 | __u32 fsnotify_mask = 0; |
42 | 43 | ||
43 | if (file->f_mode & FMODE_NONOTIFY) | 44 | if (file->f_mode & FMODE_NONOTIFY) |
@@ -51,7 +52,7 @@ static inline int fsnotify_perm(struct file *file, int mask) | |||
51 | else | 52 | else |
52 | BUG(); | 53 | BUG(); |
53 | 54 | ||
54 | return fsnotify(inode, fsnotify_mask, file, FSNOTIFY_EVENT_FILE, NULL, 0); | 55 | return fsnotify(inode, fsnotify_mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); |
55 | } | 56 | } |
56 | 57 | ||
57 | /* | 58 | /* |
@@ -186,15 +187,16 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) | |||
186 | */ | 187 | */ |
187 | static inline void fsnotify_access(struct file *file) | 188 | static inline void fsnotify_access(struct file *file) |
188 | { | 189 | { |
189 | struct inode *inode = file->f_path.dentry->d_inode; | 190 | struct path *path = &file->f_path; |
191 | struct inode *inode = path->dentry->d_inode; | ||
190 | __u32 mask = FS_ACCESS; | 192 | __u32 mask = FS_ACCESS; |
191 | 193 | ||
192 | if (S_ISDIR(inode->i_mode)) | 194 | if (S_ISDIR(inode->i_mode)) |
193 | mask |= FS_IN_ISDIR; | 195 | mask |= FS_IN_ISDIR; |
194 | 196 | ||
195 | if (!(file->f_mode & FMODE_NONOTIFY)) { | 197 | if (!(file->f_mode & FMODE_NONOTIFY)) { |
196 | fsnotify_parent(file, NULL, mask); | 198 | fsnotify_parent(path, NULL, mask); |
197 | fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0); | 199 | fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); |
198 | } | 200 | } |
199 | } | 201 | } |
200 | 202 | ||
@@ -203,15 +205,16 @@ static inline void fsnotify_access(struct file *file) | |||
203 | */ | 205 | */ |
204 | static inline void fsnotify_modify(struct file *file) | 206 | static inline void fsnotify_modify(struct file *file) |
205 | { | 207 | { |
206 | struct inode *inode = file->f_path.dentry->d_inode; | 208 | struct path *path = &file->f_path; |
209 | struct inode *inode = path->dentry->d_inode; | ||
207 | __u32 mask = FS_MODIFY; | 210 | __u32 mask = FS_MODIFY; |
208 | 211 | ||
209 | if (S_ISDIR(inode->i_mode)) | 212 | if (S_ISDIR(inode->i_mode)) |
210 | mask |= FS_IN_ISDIR; | 213 | mask |= FS_IN_ISDIR; |
211 | 214 | ||
212 | if (!(file->f_mode & FMODE_NONOTIFY)) { | 215 | if (!(file->f_mode & FMODE_NONOTIFY)) { |
213 | fsnotify_parent(file, NULL, mask); | 216 | fsnotify_parent(path, NULL, mask); |
214 | fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0); | 217 | fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); |
215 | } | 218 | } |
216 | } | 219 | } |
217 | 220 | ||
@@ -220,15 +223,16 @@ static inline void fsnotify_modify(struct file *file) | |||
220 | */ | 223 | */ |
221 | static inline void fsnotify_open(struct file *file) | 224 | static inline void fsnotify_open(struct file *file) |
222 | { | 225 | { |
223 | struct inode *inode = file->f_path.dentry->d_inode; | 226 | struct path *path = &file->f_path; |
227 | struct inode *inode = path->dentry->d_inode; | ||
224 | __u32 mask = FS_OPEN; | 228 | __u32 mask = FS_OPEN; |
225 | 229 | ||
226 | if (S_ISDIR(inode->i_mode)) | 230 | if (S_ISDIR(inode->i_mode)) |
227 | mask |= FS_IN_ISDIR; | 231 | mask |= FS_IN_ISDIR; |
228 | 232 | ||
229 | if (!(file->f_mode & FMODE_NONOTIFY)) { | 233 | if (!(file->f_mode & FMODE_NONOTIFY)) { |
230 | fsnotify_parent(file, NULL, mask); | 234 | fsnotify_parent(path, NULL, mask); |
231 | fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0); | 235 | fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); |
232 | } | 236 | } |
233 | } | 237 | } |
234 | 238 | ||
@@ -237,6 +241,7 @@ static inline void fsnotify_open(struct file *file) | |||
237 | */ | 241 | */ |
238 | static inline void fsnotify_close(struct file *file) | 242 | static inline void fsnotify_close(struct file *file) |
239 | { | 243 | { |
244 | struct path *path = &file->f_path; | ||
240 | struct inode *inode = file->f_path.dentry->d_inode; | 245 | struct inode *inode = file->f_path.dentry->d_inode; |
241 | fmode_t mode = file->f_mode; | 246 | fmode_t mode = file->f_mode; |
242 | __u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE; | 247 | __u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE; |
@@ -245,8 +250,8 @@ static inline void fsnotify_close(struct file *file) | |||
245 | mask |= FS_IN_ISDIR; | 250 | mask |= FS_IN_ISDIR; |
246 | 251 | ||
247 | if (!(file->f_mode & FMODE_NONOTIFY)) { | 252 | if (!(file->f_mode & FMODE_NONOTIFY)) { |
248 | fsnotify_parent(file, NULL, mask); | 253 | fsnotify_parent(path, NULL, mask); |
249 | fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0); | 254 | fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); |
250 | } | 255 | } |
251 | } | 256 | } |
252 | 257 | ||
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 9bbfd7204b04..ed36fb57c426 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h | |||
@@ -203,20 +203,20 @@ struct fsnotify_event { | |||
203 | /* to_tell may ONLY be dereferenced during handle_event(). */ | 203 | /* to_tell may ONLY be dereferenced during handle_event(). */ |
204 | struct inode *to_tell; /* either the inode the event happened to or its parent */ | 204 | struct inode *to_tell; /* either the inode the event happened to or its parent */ |
205 | /* | 205 | /* |
206 | * depending on the event type we should have either a file or inode | 206 | * depending on the event type we should have either a path or inode |
207 | * We hold a reference on file, but NOT on inode. Since we have the ref on | 207 | * We hold a reference on path, but NOT on inode. Since we have the ref on |
208 | * the file, it may be dereferenced at any point during this object's | 208 | * the path, it may be dereferenced at any point during this object's |
209 | * lifetime. That reference is dropped when this object's refcnt hits | 209 | * lifetime. That reference is dropped when this object's refcnt hits |
210 | * 0. If this event contains an inode instead of a file, the inode may | 210 | * 0. If this event contains an inode instead of a path, the inode may |
211 | * ONLY be used during handle_event(). | 211 | * ONLY be used during handle_event(). |
212 | */ | 212 | */ |
213 | union { | 213 | union { |
214 | struct file *file; | 214 | struct path path; |
215 | struct inode *inode; | 215 | struct inode *inode; |
216 | }; | 216 | }; |
217 | /* when calling fsnotify tell it if the data is a path or inode */ | 217 | /* when calling fsnotify tell it if the data is a path or inode */ |
218 | #define FSNOTIFY_EVENT_NONE 0 | 218 | #define FSNOTIFY_EVENT_NONE 0 |
219 | #define FSNOTIFY_EVENT_FILE 1 | 219 | #define FSNOTIFY_EVENT_PATH 1 |
220 | #define FSNOTIFY_EVENT_INODE 2 | 220 | #define FSNOTIFY_EVENT_INODE 2 |
221 | int data_type; /* which of the above union we have */ | 221 | int data_type; /* which of the above union we have */ |
222 | atomic_t refcnt; /* how many groups still are using/need to send this event */ | 222 | atomic_t refcnt; /* how many groups still are using/need to send this event */ |
@@ -293,7 +293,7 @@ struct fsnotify_mark { | |||
293 | /* main fsnotify call to send events */ | 293 | /* main fsnotify call to send events */ |
294 | extern int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, | 294 | extern int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, |
295 | const unsigned char *name, u32 cookie); | 295 | const unsigned char *name, u32 cookie); |
296 | extern void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask); | 296 | extern void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask); |
297 | extern void __fsnotify_inode_delete(struct inode *inode); | 297 | extern void __fsnotify_inode_delete(struct inode *inode); |
298 | extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); | 298 | extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); |
299 | extern u32 fsnotify_get_cookie(void); | 299 | extern u32 fsnotify_get_cookie(void); |
@@ -422,7 +422,7 @@ static inline int fsnotify(struct inode *to_tell, __u32 mask, void *data, int da | |||
422 | return 0; | 422 | return 0; |
423 | } | 423 | } |
424 | 424 | ||
425 | static inline void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask) | 425 | static inline void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) |
426 | {} | 426 | {} |
427 | 427 | ||
428 | static inline void __fsnotify_inode_delete(struct inode *inode) | 428 | static inline void __fsnotify_inode_delete(struct inode *inode) |
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 78b4bc64c006..f479700df61b 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define _LINUX_HUGETLB_H | 2 | #define _LINUX_HUGETLB_H |
3 | 3 | ||
4 | #include <linux/fs.h> | 4 | #include <linux/fs.h> |
5 | #include <linux/hugetlb_inline.h> | ||
5 | 6 | ||
6 | struct ctl_table; | 7 | struct ctl_table; |
7 | struct user_struct; | 8 | struct user_struct; |
@@ -14,11 +15,6 @@ struct user_struct; | |||
14 | 15 | ||
15 | int PageHuge(struct page *page); | 16 | int PageHuge(struct page *page); |
16 | 17 | ||
17 | static inline int is_vm_hugetlb_page(struct vm_area_struct *vma) | ||
18 | { | ||
19 | return vma->vm_flags & VM_HUGETLB; | ||
20 | } | ||
21 | |||
22 | void reset_vma_resv_huge_pages(struct vm_area_struct *vma); | 18 | void reset_vma_resv_huge_pages(struct vm_area_struct *vma); |
23 | int hugetlb_sysctl_handler(struct ctl_table *, int, void __user *, size_t *, loff_t *); | 19 | int hugetlb_sysctl_handler(struct ctl_table *, int, void __user *, size_t *, loff_t *); |
24 | int hugetlb_overcommit_handler(struct ctl_table *, int, void __user *, size_t *, loff_t *); | 20 | int hugetlb_overcommit_handler(struct ctl_table *, int, void __user *, size_t *, loff_t *); |
@@ -47,6 +43,7 @@ int hugetlb_reserve_pages(struct inode *inode, long from, long to, | |||
47 | struct vm_area_struct *vma, | 43 | struct vm_area_struct *vma, |
48 | int acctflags); | 44 | int acctflags); |
49 | void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed); | 45 | void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed); |
46 | void __isolate_hwpoisoned_huge_page(struct page *page); | ||
50 | 47 | ||
51 | extern unsigned long hugepages_treat_as_movable; | 48 | extern unsigned long hugepages_treat_as_movable; |
52 | extern const unsigned long hugetlb_zero, hugetlb_infinity; | 49 | extern const unsigned long hugetlb_zero, hugetlb_infinity; |
@@ -77,11 +74,6 @@ static inline int PageHuge(struct page *page) | |||
77 | return 0; | 74 | return 0; |
78 | } | 75 | } |
79 | 76 | ||
80 | static inline int is_vm_hugetlb_page(struct vm_area_struct *vma) | ||
81 | { | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static inline void reset_vma_resv_huge_pages(struct vm_area_struct *vma) | 77 | static inline void reset_vma_resv_huge_pages(struct vm_area_struct *vma) |
86 | { | 78 | { |
87 | } | 79 | } |
@@ -108,6 +100,8 @@ static inline void hugetlb_report_meminfo(struct seq_file *m) | |||
108 | #define is_hugepage_only_range(mm, addr, len) 0 | 100 | #define is_hugepage_only_range(mm, addr, len) 0 |
109 | #define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) ({BUG(); 0; }) | 101 | #define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) ({BUG(); 0; }) |
110 | #define hugetlb_fault(mm, vma, addr, flags) ({ BUG(); 0; }) | 102 | #define hugetlb_fault(mm, vma, addr, flags) ({ BUG(); 0; }) |
103 | #define huge_pte_offset(mm, address) 0 | ||
104 | #define __isolate_hwpoisoned_huge_page(page) 0 | ||
111 | 105 | ||
112 | #define hugetlb_change_protection(vma, address, end, newprot) | 106 | #define hugetlb_change_protection(vma, address, end, newprot) |
113 | 107 | ||
diff --git a/include/linux/hugetlb_inline.h b/include/linux/hugetlb_inline.h new file mode 100644 index 000000000000..6931489a5c14 --- /dev/null +++ b/include/linux/hugetlb_inline.h | |||
@@ -0,0 +1,22 @@ | |||
1 | #ifndef _LINUX_HUGETLB_INLINE_H | ||
2 | #define _LINUX_HUGETLB_INLINE_H | ||
3 | |||
4 | #ifdef CONFIG_HUGETLB_PAGE | ||
5 | |||
6 | #include <linux/mm.h> | ||
7 | |||
8 | static inline int is_vm_hugetlb_page(struct vm_area_struct *vma) | ||
9 | { | ||
10 | return vma->vm_flags & VM_HUGETLB; | ||
11 | } | ||
12 | |||
13 | #else | ||
14 | |||
15 | static inline int is_vm_hugetlb_page(struct vm_area_struct *vma) | ||
16 | { | ||
17 | return 0; | ||
18 | } | ||
19 | |||
20 | #endif | ||
21 | |||
22 | #endif | ||
diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h new file mode 100644 index 000000000000..34536effd652 --- /dev/null +++ b/include/linux/i2c-mux.h | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * | ||
3 | * i2c-mux.h - functions for the i2c-bus mux support | ||
4 | * | ||
5 | * Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it> | ||
6 | * Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it> | ||
7 | * Michael Lawnick <michael.lawnick.ext@nsn.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #ifndef _LINUX_I2C_MUX_H | ||
25 | #define _LINUX_I2C_MUX_H | ||
26 | |||
27 | #ifdef __KERNEL__ | ||
28 | |||
29 | /* | ||
30 | * Called to create a i2c bus on a multiplexed bus segment. | ||
31 | * The mux_dev and chan_id parameters are passed to the select | ||
32 | * and deselect callback functions to perform hardware-specific | ||
33 | * mux control. | ||
34 | */ | ||
35 | struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, | ||
36 | void *mux_dev, u32 force_nr, u32 chan_id, | ||
37 | int (*select) (struct i2c_adapter *, | ||
38 | void *mux_dev, u32 chan_id), | ||
39 | int (*deselect) (struct i2c_adapter *, | ||
40 | void *mux_dev, u32 chan_id)); | ||
41 | |||
42 | int i2c_del_mux_adapter(struct i2c_adapter *adap); | ||
43 | |||
44 | #endif /* __KERNEL__ */ | ||
45 | |||
46 | #endif /* _LINUX_I2C_MUX_H */ | ||
diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 38dd4025aa4e..4bae0b72ed3c 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/of.h> /* for struct device_node */ | 37 | #include <linux/of.h> /* for struct device_node */ |
38 | 38 | ||
39 | extern struct bus_type i2c_bus_type; | 39 | extern struct bus_type i2c_bus_type; |
40 | extern struct device_type i2c_adapter_type; | ||
40 | 41 | ||
41 | /* --- General options ------------------------------------------------ */ | 42 | /* --- General options ------------------------------------------------ */ |
42 | 43 | ||
@@ -284,12 +285,18 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info); | |||
284 | 285 | ||
285 | /* If you don't know the exact address of an I2C device, use this variant | 286 | /* If you don't know the exact address of an I2C device, use this variant |
286 | * instead, which can probe for device presence in a list of possible | 287 | * instead, which can probe for device presence in a list of possible |
287 | * addresses. | 288 | * addresses. The "probe" callback function is optional. If it is provided, |
289 | * it must return 1 on successful probe, 0 otherwise. If it is not provided, | ||
290 | * a default probing method is used. | ||
288 | */ | 291 | */ |
289 | extern struct i2c_client * | 292 | extern struct i2c_client * |
290 | i2c_new_probed_device(struct i2c_adapter *adap, | 293 | i2c_new_probed_device(struct i2c_adapter *adap, |
291 | struct i2c_board_info *info, | 294 | struct i2c_board_info *info, |
292 | unsigned short const *addr_list); | 295 | unsigned short const *addr_list, |
296 | int (*probe)(struct i2c_adapter *, unsigned short addr)); | ||
297 | |||
298 | /* Common custom probe functions */ | ||
299 | extern int i2c_probe_func_quick_read(struct i2c_adapter *, unsigned short addr); | ||
293 | 300 | ||
294 | /* For devices that use several addresses, use i2c_new_dummy() to make | 301 | /* For devices that use several addresses, use i2c_new_dummy() to make |
295 | * client handles for the extra addresses. | 302 | * client handles for the extra addresses. |
@@ -362,6 +369,7 @@ struct i2c_adapter { | |||
362 | char name[48]; | 369 | char name[48]; |
363 | struct completion dev_released; | 370 | struct completion dev_released; |
364 | 371 | ||
372 | struct mutex userspace_clients_lock; | ||
365 | struct list_head userspace_clients; | 373 | struct list_head userspace_clients; |
366 | }; | 374 | }; |
367 | #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev) | 375 | #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev) |
@@ -376,23 +384,16 @@ static inline void i2c_set_adapdata(struct i2c_adapter *dev, void *data) | |||
376 | dev_set_drvdata(&dev->dev, data); | 384 | dev_set_drvdata(&dev->dev, data); |
377 | } | 385 | } |
378 | 386 | ||
379 | /** | 387 | static inline int i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter) |
380 | * i2c_lock_adapter - Prevent access to an I2C bus segment | ||
381 | * @adapter: Target I2C bus segment | ||
382 | */ | ||
383 | static inline void i2c_lock_adapter(struct i2c_adapter *adapter) | ||
384 | { | 388 | { |
385 | rt_mutex_lock(&adapter->bus_lock); | 389 | return adapter->dev.parent != NULL |
390 | && adapter->dev.parent->bus == &i2c_bus_type | ||
391 | && adapter->dev.parent->type == &i2c_adapter_type; | ||
386 | } | 392 | } |
387 | 393 | ||
388 | /** | 394 | /* Adapter locking functions, exported for shared pin cases */ |
389 | * i2c_unlock_adapter - Reauthorize access to an I2C bus segment | 395 | void i2c_lock_adapter(struct i2c_adapter *); |
390 | * @adapter: Target I2C bus segment | 396 | void i2c_unlock_adapter(struct i2c_adapter *); |
391 | */ | ||
392 | static inline void i2c_unlock_adapter(struct i2c_adapter *adapter) | ||
393 | { | ||
394 | rt_mutex_unlock(&adapter->bus_lock); | ||
395 | } | ||
396 | 397 | ||
397 | /*flags for the client struct: */ | 398 | /*flags for the client struct: */ |
398 | #define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */ | 399 | #define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */ |
diff --git a/include/linux/i2c/pca954x.h b/include/linux/i2c/pca954x.h new file mode 100644 index 000000000000..28f1f8d5ab1f --- /dev/null +++ b/include/linux/i2c/pca954x.h | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * | ||
3 | * pca954x.h - I2C multiplexer/switch support | ||
4 | * | ||
5 | * Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it> | ||
6 | * Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it> | ||
7 | * Michael Lawnick <michael.lawnick.ext@nsn.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | |||
25 | #ifndef _LINUX_I2C_PCA954X_H | ||
26 | #define _LINUX_I2C_PCA954X_H | ||
27 | |||
28 | /* Platform data for the PCA954x I2C multiplexers */ | ||
29 | |||
30 | /* Per channel initialisation data: | ||
31 | * @adap_id: bus number for the adapter. 0 = don't care | ||
32 | * @deselect_on_exit: set this entry to 1, if your H/W needs deselection | ||
33 | * of this channel after transaction. | ||
34 | * | ||
35 | */ | ||
36 | struct pca954x_platform_mode { | ||
37 | int adap_id; | ||
38 | unsigned int deselect_on_exit:1; | ||
39 | }; | ||
40 | |||
41 | /* Per mux/switch data, used with i2c_register_board_info */ | ||
42 | struct pca954x_platform_data { | ||
43 | struct pca954x_platform_mode *modes; | ||
44 | int num_modes; | ||
45 | }; | ||
46 | |||
47 | #endif /* _LINUX_I2C_PCA954X_H */ | ||
diff --git a/include/linux/io-mapping.h b/include/linux/io-mapping.h index e0ea40f6c515..0a6b3d5c490c 100644 --- a/include/linux/io-mapping.h +++ b/include/linux/io-mapping.h | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <asm/io.h> | 23 | #include <asm/io.h> |
24 | #include <asm/page.h> | 24 | #include <asm/page.h> |
25 | #include <asm/iomap.h> | ||
26 | 25 | ||
27 | /* | 26 | /* |
28 | * The io_mapping mechanism provides an abstraction for mapping | 27 | * The io_mapping mechanism provides an abstraction for mapping |
@@ -33,6 +32,8 @@ | |||
33 | 32 | ||
34 | #ifdef CONFIG_HAVE_ATOMIC_IOMAP | 33 | #ifdef CONFIG_HAVE_ATOMIC_IOMAP |
35 | 34 | ||
35 | #include <asm/iomap.h> | ||
36 | |||
36 | struct io_mapping { | 37 | struct io_mapping { |
37 | resource_size_t base; | 38 | resource_size_t base; |
38 | unsigned long size; | 39 | unsigned long size; |
diff --git a/include/linux/jz4740-adc.h b/include/linux/jz4740-adc.h new file mode 100644 index 000000000000..9053f95e9687 --- /dev/null +++ b/include/linux/jz4740-adc.h | |||
@@ -0,0 +1,32 @@ | |||
1 | |||
2 | #ifndef __LINUX_JZ4740_ADC | ||
3 | #define __LINUX_JZ4740_ADC | ||
4 | |||
5 | #include <linux/device.h> | ||
6 | |||
7 | /* | ||
8 | * jz4740_adc_set_config - Configure a JZ4740 adc device | ||
9 | * @dev: Pointer to a jz4740-adc device | ||
10 | * @mask: Mask for the config value to be set | ||
11 | * @val: Value to be set | ||
12 | * | ||
13 | * This function can be used by the JZ4740 ADC mfd cells to configure their | ||
14 | * options in the shared config register. | ||
15 | */ | ||
16 | int jz4740_adc_set_config(struct device *dev, uint32_t mask, uint32_t val); | ||
17 | |||
18 | #define JZ_ADC_CONFIG_SPZZ BIT(31) | ||
19 | #define JZ_ADC_CONFIG_EX_IN BIT(30) | ||
20 | #define JZ_ADC_CONFIG_DNUM_MASK (0x7 << 16) | ||
21 | #define JZ_ADC_CONFIG_DMA_ENABLE BIT(15) | ||
22 | #define JZ_ADC_CONFIG_XYZ_MASK (0x2 << 13) | ||
23 | #define JZ_ADC_CONFIG_SAMPLE_NUM_MASK (0x7 << 10) | ||
24 | #define JZ_ADC_CONFIG_CLKDIV_MASK (0xf << 5) | ||
25 | #define JZ_ADC_CONFIG_BAT_MB BIT(4) | ||
26 | |||
27 | #define JZ_ADC_CONFIG_DNUM(dnum) ((dnum) << 16) | ||
28 | #define JZ_ADC_CONFIG_XYZ_OFFSET(dnum) ((xyz) << 13) | ||
29 | #define JZ_ADC_CONFIG_SAMPLE_NUM(x) ((x) << 10) | ||
30 | #define JZ_ADC_CONFIG_CLKDIV(div) ((div) << 5) | ||
31 | |||
32 | #endif | ||
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index d848cb854655..2b0a35e6bc69 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
@@ -306,6 +306,13 @@ static inline void log_buf_kexec_setup(void) | |||
306 | } | 306 | } |
307 | #endif | 307 | #endif |
308 | 308 | ||
309 | /* | ||
310 | * Dummy printk for disabled debugging statements to use whilst maintaining | ||
311 | * gcc's format and side-effect checking. | ||
312 | */ | ||
313 | static inline __attribute__ ((format (printf, 1, 2))) | ||
314 | int no_printk(const char *s, ...) { return 0; } | ||
315 | |||
309 | extern int printk_needs_cpu(int cpu); | 316 | extern int printk_needs_cpu(int cpu); |
310 | extern void printk_tick(void); | 317 | extern void printk_tick(void); |
311 | 318 | ||
diff --git a/include/linux/mfd/ab8500.h b/include/linux/mfd/ab8500.h index b63ff3ba3351..f5cec4500f38 100644 --- a/include/linux/mfd/ab8500.h +++ b/include/linux/mfd/ab8500.h | |||
@@ -76,6 +76,8 @@ | |||
76 | #define AB8500_NR_IRQS 104 | 76 | #define AB8500_NR_IRQS 104 |
77 | #define AB8500_NUM_IRQ_REGS 13 | 77 | #define AB8500_NUM_IRQ_REGS 13 |
78 | 78 | ||
79 | #define AB8500_NUM_REGULATORS 15 | ||
80 | |||
79 | /** | 81 | /** |
80 | * struct ab8500 - ab8500 internal structure | 82 | * struct ab8500 - ab8500 internal structure |
81 | * @dev: parent device | 83 | * @dev: parent device |
@@ -108,14 +110,18 @@ struct ab8500 { | |||
108 | u8 oldmask[AB8500_NUM_IRQ_REGS]; | 110 | u8 oldmask[AB8500_NUM_IRQ_REGS]; |
109 | }; | 111 | }; |
110 | 112 | ||
113 | struct regulator_init_data; | ||
114 | |||
111 | /** | 115 | /** |
112 | * struct ab8500_platform_data - AB8500 platform data | 116 | * struct ab8500_platform_data - AB8500 platform data |
113 | * @irq_base: start of AB8500 IRQs, AB8500_NR_IRQS will be used | 117 | * @irq_base: start of AB8500 IRQs, AB8500_NR_IRQS will be used |
114 | * @init: board-specific initialization after detection of ab8500 | 118 | * @init: board-specific initialization after detection of ab8500 |
119 | * @regulator: machine-specific constraints for regulators | ||
115 | */ | 120 | */ |
116 | struct ab8500_platform_data { | 121 | struct ab8500_platform_data { |
117 | int irq_base; | 122 | int irq_base; |
118 | void (*init) (struct ab8500 *); | 123 | void (*init) (struct ab8500 *); |
124 | struct regulator_init_data *regulator[AB8500_NUM_REGULATORS]; | ||
119 | }; | 125 | }; |
120 | 126 | ||
121 | extern int ab8500_write(struct ab8500 *a8500, u16 addr, u8 data); | 127 | extern int ab8500_write(struct ab8500 *a8500, u16 addr, u8 data); |
diff --git a/include/linux/mfd/max8998-private.h b/include/linux/mfd/max8998-private.h new file mode 100644 index 000000000000..6dc75b3e2d33 --- /dev/null +++ b/include/linux/mfd/max8998-private.h | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * max8698.h - Voltage regulator driver for the Maxim 8998 | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Samsung Electrnoics | ||
5 | * Kyungmin Park <kyungmin.park@samsung.com> | ||
6 | * Marek Szyprowski <m.szyprowski@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #ifndef __LINUX_MFD_MAX8998_PRIV_H | ||
24 | #define __LINUX_MFD_MAX8998_PRIV_H | ||
25 | |||
26 | /* MAX 8998 registers */ | ||
27 | enum { | ||
28 | MAX8998_REG_IRQ1, | ||
29 | MAX8998_REG_IRQ2, | ||
30 | MAX8998_REG_IRQ3, | ||
31 | MAX8998_REG_IRQ4, | ||
32 | MAX8998_REG_IRQM1, | ||
33 | MAX8998_REG_IRQM2, | ||
34 | MAX8998_REG_IRQM3, | ||
35 | MAX8998_REG_IRQM4, | ||
36 | MAX8998_REG_STATUS1, | ||
37 | MAX8998_REG_STATUS2, | ||
38 | MAX8998_REG_STATUSM1, | ||
39 | MAX8998_REG_STATUSM2, | ||
40 | MAX8998_REG_CHGR1, | ||
41 | MAX8998_REG_CHGR2, | ||
42 | MAX8998_REG_LDO_ACTIVE_DISCHARGE1, | ||
43 | MAX8998_REG_LDO_ACTIVE_DISCHARGE2, | ||
44 | MAX8998_REG_BUCK_ACTIVE_DISCHARGE3, | ||
45 | MAX8998_REG_ONOFF1, | ||
46 | MAX8998_REG_ONOFF2, | ||
47 | MAX8998_REG_ONOFF3, | ||
48 | MAX8998_REG_ONOFF4, | ||
49 | MAX8998_REG_BUCK1_DVSARM1, | ||
50 | MAX8998_REG_BUCK1_DVSARM2, | ||
51 | MAX8998_REG_BUCK1_DVSARM3, | ||
52 | MAX8998_REG_BUCK1_DVSARM4, | ||
53 | MAX8998_REG_BUCK2_DVSINT1, | ||
54 | MAX8998_REG_BUCK2_DVSINT2, | ||
55 | MAX8998_REG_BUCK3, | ||
56 | MAX8998_REG_BUCK4, | ||
57 | MAX8998_REG_LDO2_LDO3, | ||
58 | MAX8998_REG_LDO4, | ||
59 | MAX8998_REG_LDO5, | ||
60 | MAX8998_REG_LDO6, | ||
61 | MAX8998_REG_LDO7, | ||
62 | MAX8998_REG_LDO8_LDO9, | ||
63 | MAX8998_REG_LDO10_LDO11, | ||
64 | MAX8998_REG_LDO12, | ||
65 | MAX8998_REG_LDO13, | ||
66 | MAX8998_REG_LDO14, | ||
67 | MAX8998_REG_LDO15, | ||
68 | MAX8998_REG_LDO16, | ||
69 | MAX8998_REG_LDO17, | ||
70 | MAX8998_REG_BKCHR, | ||
71 | MAX8998_REG_LBCNFG1, | ||
72 | MAX8998_REG_LBCNFG2, | ||
73 | }; | ||
74 | |||
75 | /** | ||
76 | * struct max8998_dev - max8998 master device for sub-drivers | ||
77 | * @dev: master device of the chip (can be used to access platform data) | ||
78 | * @i2c_client: i2c client private data | ||
79 | * @dev_read(): chip register read function | ||
80 | * @dev_write(): chip register write function | ||
81 | * @dev_update(): chip register update function | ||
82 | * @iolock: mutex for serializing io access | ||
83 | */ | ||
84 | |||
85 | struct max8998_dev { | ||
86 | struct device *dev; | ||
87 | struct i2c_client *i2c_client; | ||
88 | int (*dev_read)(struct max8998_dev *max8998, u8 reg, u8 *dest); | ||
89 | int (*dev_write)(struct max8998_dev *max8998, u8 reg, u8 val); | ||
90 | int (*dev_update)(struct max8998_dev *max8998, u8 reg, u8 val, u8 mask); | ||
91 | struct mutex iolock; | ||
92 | }; | ||
93 | |||
94 | static inline int max8998_read_reg(struct max8998_dev *max8998, u8 reg, | ||
95 | u8 *value) | ||
96 | { | ||
97 | return max8998->dev_read(max8998, reg, value); | ||
98 | } | ||
99 | |||
100 | static inline int max8998_write_reg(struct max8998_dev *max8998, u8 reg, | ||
101 | u8 value) | ||
102 | { | ||
103 | return max8998->dev_write(max8998, reg, value); | ||
104 | } | ||
105 | |||
106 | static inline int max8998_update_reg(struct max8998_dev *max8998, u8 reg, | ||
107 | u8 value, u8 mask) | ||
108 | { | ||
109 | return max8998->dev_update(max8998, reg, value, mask); | ||
110 | } | ||
111 | |||
112 | #endif /* __LINUX_MFD_MAX8998_PRIV_H */ | ||
diff --git a/include/linux/mfd/max8998.h b/include/linux/mfd/max8998.h new file mode 100644 index 000000000000..1d3601a2d853 --- /dev/null +++ b/include/linux/mfd/max8998.h | |||
@@ -0,0 +1,78 @@ | |||
1 | /* | ||
2 | * max8698.h - Voltage regulator driver for the Maxim 8998 | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Samsung Electrnoics | ||
5 | * Kyungmin Park <kyungmin.park@samsung.com> | ||
6 | * Marek Szyprowski <m.szyprowski@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #ifndef __LINUX_MFD_MAX8998_H | ||
24 | #define __LINUX_MFD_MAX8998_H | ||
25 | |||
26 | #include <linux/regulator/machine.h> | ||
27 | |||
28 | /* MAX 8998 regulator ids */ | ||
29 | enum { | ||
30 | MAX8998_LDO2 = 2, | ||
31 | MAX8998_LDO3, | ||
32 | MAX8998_LDO4, | ||
33 | MAX8998_LDO5, | ||
34 | MAX8998_LDO6, | ||
35 | MAX8998_LDO7, | ||
36 | MAX8998_LDO8, | ||
37 | MAX8998_LDO9, | ||
38 | MAX8998_LDO10, | ||
39 | MAX8998_LDO11, | ||
40 | MAX8998_LDO12, | ||
41 | MAX8998_LDO13, | ||
42 | MAX8998_LDO14, | ||
43 | MAX8998_LDO15, | ||
44 | MAX8998_LDO16, | ||
45 | MAX8998_LDO17, | ||
46 | MAX8998_BUCK1, | ||
47 | MAX8998_BUCK2, | ||
48 | MAX8998_BUCK3, | ||
49 | MAX8998_BUCK4, | ||
50 | MAX8998_EN32KHZ_AP, | ||
51 | MAX8998_EN32KHZ_CP, | ||
52 | MAX8998_ENVICHG, | ||
53 | MAX8998_ESAFEOUT1, | ||
54 | MAX8998_ESAFEOUT2, | ||
55 | }; | ||
56 | |||
57 | /** | ||
58 | * max8998_regulator_data - regulator data | ||
59 | * @id: regulator id | ||
60 | * @initdata: regulator init data (contraints, supplies, ...) | ||
61 | */ | ||
62 | struct max8998_regulator_data { | ||
63 | int id; | ||
64 | struct regulator_init_data *initdata; | ||
65 | }; | ||
66 | |||
67 | /** | ||
68 | * struct max8998_board - packages regulator init data | ||
69 | * @num_regulators: number of regultors used | ||
70 | * @regulators: array of defined regulators | ||
71 | */ | ||
72 | |||
73 | struct max8998_platform_data { | ||
74 | int num_regulators; | ||
75 | struct max8998_regulator_data *regulators; | ||
76 | }; | ||
77 | |||
78 | #endif /* __LINUX_MFD_MAX8998_H */ | ||
diff --git a/include/linux/mfd/mc13783-private.h b/include/linux/mfd/mc13783-private.h deleted file mode 100644 index 95cf9360553f..000000000000 --- a/include/linux/mfd/mc13783-private.h +++ /dev/null | |||
@@ -1,220 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> | ||
3 | * | ||
4 | * Initial development of this code was funded by | ||
5 | * Phytec Messtechnik GmbH, http://www.phytec.de | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef __LINUX_MFD_MC13783_PRIV_H | ||
23 | #define __LINUX_MFD_MC13783_PRIV_H | ||
24 | |||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/mfd/mc13783.h> | ||
27 | #include <linux/mutex.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | |||
30 | struct mc13783 { | ||
31 | struct spi_device *spidev; | ||
32 | struct mutex lock; | ||
33 | int irq; | ||
34 | int flags; | ||
35 | |||
36 | irq_handler_t irqhandler[MC13783_NUM_IRQ]; | ||
37 | void *irqdata[MC13783_NUM_IRQ]; | ||
38 | |||
39 | /* XXX these should go as platformdata to the regulator subdevice */ | ||
40 | struct mc13783_regulator_init_data *regulators; | ||
41 | int num_regulators; | ||
42 | }; | ||
43 | |||
44 | #define MC13783_REG_INTERRUPT_STATUS_0 0 | ||
45 | #define MC13783_REG_INTERRUPT_MASK_0 1 | ||
46 | #define MC13783_REG_INTERRUPT_SENSE_0 2 | ||
47 | #define MC13783_REG_INTERRUPT_STATUS_1 3 | ||
48 | #define MC13783_REG_INTERRUPT_MASK_1 4 | ||
49 | #define MC13783_REG_INTERRUPT_SENSE_1 5 | ||
50 | #define MC13783_REG_POWER_UP_MODE_SENSE 6 | ||
51 | #define MC13783_REG_REVISION 7 | ||
52 | #define MC13783_REG_SEMAPHORE 8 | ||
53 | #define MC13783_REG_ARBITRATION_PERIPHERAL_AUDIO 9 | ||
54 | #define MC13783_REG_ARBITRATION_SWITCHERS 10 | ||
55 | #define MC13783_REG_ARBITRATION_REGULATORS_0 11 | ||
56 | #define MC13783_REG_ARBITRATION_REGULATORS_1 12 | ||
57 | #define MC13783_REG_POWER_CONTROL_0 13 | ||
58 | #define MC13783_REG_POWER_CONTROL_1 14 | ||
59 | #define MC13783_REG_POWER_CONTROL_2 15 | ||
60 | #define MC13783_REG_REGEN_ASSIGNMENT 16 | ||
61 | #define MC13783_REG_CONTROL_SPARE 17 | ||
62 | #define MC13783_REG_MEMORY_A 18 | ||
63 | #define MC13783_REG_MEMORY_B 19 | ||
64 | #define MC13783_REG_RTC_TIME 20 | ||
65 | #define MC13783_REG_RTC_ALARM 21 | ||
66 | #define MC13783_REG_RTC_DAY 22 | ||
67 | #define MC13783_REG_RTC_DAY_ALARM 23 | ||
68 | #define MC13783_REG_SWITCHERS_0 24 | ||
69 | #define MC13783_REG_SWITCHERS_1 25 | ||
70 | #define MC13783_REG_SWITCHERS_2 26 | ||
71 | #define MC13783_REG_SWITCHERS_3 27 | ||
72 | #define MC13783_REG_SWITCHERS_4 28 | ||
73 | #define MC13783_REG_SWITCHERS_5 29 | ||
74 | #define MC13783_REG_REGULATOR_SETTING_0 30 | ||
75 | #define MC13783_REG_REGULATOR_SETTING_1 31 | ||
76 | #define MC13783_REG_REGULATOR_MODE_0 32 | ||
77 | #define MC13783_REG_REGULATOR_MODE_1 33 | ||
78 | #define MC13783_REG_POWER_MISCELLANEOUS 34 | ||
79 | #define MC13783_REG_POWER_SPARE 35 | ||
80 | #define MC13783_REG_AUDIO_RX_0 36 | ||
81 | #define MC13783_REG_AUDIO_RX_1 37 | ||
82 | #define MC13783_REG_AUDIO_TX 38 | ||
83 | #define MC13783_REG_AUDIO_SSI_NETWORK 39 | ||
84 | #define MC13783_REG_AUDIO_CODEC 40 | ||
85 | #define MC13783_REG_AUDIO_STEREO_DAC 41 | ||
86 | #define MC13783_REG_AUDIO_SPARE 42 | ||
87 | #define MC13783_REG_ADC_0 43 | ||
88 | #define MC13783_REG_ADC_1 44 | ||
89 | #define MC13783_REG_ADC_2 45 | ||
90 | #define MC13783_REG_ADC_3 46 | ||
91 | #define MC13783_REG_ADC_4 47 | ||
92 | #define MC13783_REG_CHARGER 48 | ||
93 | #define MC13783_REG_USB 49 | ||
94 | #define MC13783_REG_CHARGE_USB_SPARE 50 | ||
95 | #define MC13783_REG_LED_CONTROL_0 51 | ||
96 | #define MC13783_REG_LED_CONTROL_1 52 | ||
97 | #define MC13783_REG_LED_CONTROL_2 53 | ||
98 | #define MC13783_REG_LED_CONTROL_3 54 | ||
99 | #define MC13783_REG_LED_CONTROL_4 55 | ||
100 | #define MC13783_REG_LED_CONTROL_5 56 | ||
101 | #define MC13783_REG_SPARE 57 | ||
102 | #define MC13783_REG_TRIM_0 58 | ||
103 | #define MC13783_REG_TRIM_1 59 | ||
104 | #define MC13783_REG_TEST_0 60 | ||
105 | #define MC13783_REG_TEST_1 61 | ||
106 | #define MC13783_REG_TEST_2 62 | ||
107 | #define MC13783_REG_TEST_3 63 | ||
108 | #define MC13783_REG_NB 64 | ||
109 | |||
110 | /* | ||
111 | * Reg Regulator Mode 0 | ||
112 | */ | ||
113 | #define MC13783_REGCTRL_VAUDIO_EN (1 << 0) | ||
114 | #define MC13783_REGCTRL_VAUDIO_STBY (1 << 1) | ||
115 | #define MC13783_REGCTRL_VAUDIO_MODE (1 << 2) | ||
116 | #define MC13783_REGCTRL_VIOHI_EN (1 << 3) | ||
117 | #define MC13783_REGCTRL_VIOHI_STBY (1 << 4) | ||
118 | #define MC13783_REGCTRL_VIOHI_MODE (1 << 5) | ||
119 | #define MC13783_REGCTRL_VIOLO_EN (1 << 6) | ||
120 | #define MC13783_REGCTRL_VIOLO_STBY (1 << 7) | ||
121 | #define MC13783_REGCTRL_VIOLO_MODE (1 << 8) | ||
122 | #define MC13783_REGCTRL_VDIG_EN (1 << 9) | ||
123 | #define MC13783_REGCTRL_VDIG_STBY (1 << 10) | ||
124 | #define MC13783_REGCTRL_VDIG_MODE (1 << 11) | ||
125 | #define MC13783_REGCTRL_VGEN_EN (1 << 12) | ||
126 | #define MC13783_REGCTRL_VGEN_STBY (1 << 13) | ||
127 | #define MC13783_REGCTRL_VGEN_MODE (1 << 14) | ||
128 | #define MC13783_REGCTRL_VRFDIG_EN (1 << 15) | ||
129 | #define MC13783_REGCTRL_VRFDIG_STBY (1 << 16) | ||
130 | #define MC13783_REGCTRL_VRFDIG_MODE (1 << 17) | ||
131 | #define MC13783_REGCTRL_VRFREF_EN (1 << 18) | ||
132 | #define MC13783_REGCTRL_VRFREF_STBY (1 << 19) | ||
133 | #define MC13783_REGCTRL_VRFREF_MODE (1 << 20) | ||
134 | #define MC13783_REGCTRL_VRFCP_EN (1 << 21) | ||
135 | #define MC13783_REGCTRL_VRFCP_STBY (1 << 22) | ||
136 | #define MC13783_REGCTRL_VRFCP_MODE (1 << 23) | ||
137 | |||
138 | /* | ||
139 | * Reg Regulator Mode 1 | ||
140 | */ | ||
141 | #define MC13783_REGCTRL_VSIM_EN (1 << 0) | ||
142 | #define MC13783_REGCTRL_VSIM_STBY (1 << 1) | ||
143 | #define MC13783_REGCTRL_VSIM_MODE (1 << 2) | ||
144 | #define MC13783_REGCTRL_VESIM_EN (1 << 3) | ||
145 | #define MC13783_REGCTRL_VESIM_STBY (1 << 4) | ||
146 | #define MC13783_REGCTRL_VESIM_MODE (1 << 5) | ||
147 | #define MC13783_REGCTRL_VCAM_EN (1 << 6) | ||
148 | #define MC13783_REGCTRL_VCAM_STBY (1 << 7) | ||
149 | #define MC13783_REGCTRL_VCAM_MODE (1 << 8) | ||
150 | #define MC13783_REGCTRL_VRFBG_EN (1 << 9) | ||
151 | #define MC13783_REGCTRL_VRFBG_STBY (1 << 10) | ||
152 | #define MC13783_REGCTRL_VVIB_EN (1 << 11) | ||
153 | #define MC13783_REGCTRL_VRF1_EN (1 << 12) | ||
154 | #define MC13783_REGCTRL_VRF1_STBY (1 << 13) | ||
155 | #define MC13783_REGCTRL_VRF1_MODE (1 << 14) | ||
156 | #define MC13783_REGCTRL_VRF2_EN (1 << 15) | ||
157 | #define MC13783_REGCTRL_VRF2_STBY (1 << 16) | ||
158 | #define MC13783_REGCTRL_VRF2_MODE (1 << 17) | ||
159 | #define MC13783_REGCTRL_VMMC1_EN (1 << 18) | ||
160 | #define MC13783_REGCTRL_VMMC1_STBY (1 << 19) | ||
161 | #define MC13783_REGCTRL_VMMC1_MODE (1 << 20) | ||
162 | #define MC13783_REGCTRL_VMMC2_EN (1 << 21) | ||
163 | #define MC13783_REGCTRL_VMMC2_STBY (1 << 22) | ||
164 | #define MC13783_REGCTRL_VMMC2_MODE (1 << 23) | ||
165 | |||
166 | /* | ||
167 | * Reg Regulator Misc. | ||
168 | */ | ||
169 | #define MC13783_REGCTRL_GPO1_EN (1 << 6) | ||
170 | #define MC13783_REGCTRL_GPO2_EN (1 << 8) | ||
171 | #define MC13783_REGCTRL_GPO3_EN (1 << 10) | ||
172 | #define MC13783_REGCTRL_GPO4_EN (1 << 12) | ||
173 | #define MC13783_REGCTRL_VIBPINCTRL (1 << 14) | ||
174 | |||
175 | /* | ||
176 | * Reg Switcher 4 | ||
177 | */ | ||
178 | #define MC13783_SWCTRL_SW1A_MODE (1 << 0) | ||
179 | #define MC13783_SWCTRL_SW1A_STBY_MODE (1 << 2) | ||
180 | #define MC13783_SWCTRL_SW1A_DVS_SPEED (1 << 6) | ||
181 | #define MC13783_SWCTRL_SW1A_PANIC_MODE (1 << 8) | ||
182 | #define MC13783_SWCTRL_SW1A_SOFTSTART (1 << 9) | ||
183 | #define MC13783_SWCTRL_SW1B_MODE (1 << 10) | ||
184 | #define MC13783_SWCTRL_SW1B_STBY_MODE (1 << 12) | ||
185 | #define MC13783_SWCTRL_SW1B_DVS_SPEED (1 << 14) | ||
186 | #define MC13783_SWCTRL_SW1B_PANIC_MODE (1 << 16) | ||
187 | #define MC13783_SWCTRL_SW1B_SOFTSTART (1 << 17) | ||
188 | #define MC13783_SWCTRL_PLL_EN (1 << 18) | ||
189 | #define MC13783_SWCTRL_PLL_FACTOR (1 << 19) | ||
190 | |||
191 | /* | ||
192 | * Reg Switcher 5 | ||
193 | */ | ||
194 | #define MC13783_SWCTRL_SW2A_MODE (1 << 0) | ||
195 | #define MC13783_SWCTRL_SW2A_STBY_MODE (1 << 2) | ||
196 | #define MC13783_SWCTRL_SW2A_DVS_SPEED (1 << 6) | ||
197 | #define MC13783_SWCTRL_SW2A_PANIC_MODE (1 << 8) | ||
198 | #define MC13783_SWCTRL_SW2A_SOFTSTART (1 << 9) | ||
199 | #define MC13783_SWCTRL_SW2B_MODE (1 << 10) | ||
200 | #define MC13783_SWCTRL_SW2B_STBY_MODE (1 << 12) | ||
201 | #define MC13783_SWCTRL_SW2B_DVS_SPEED (1 << 14) | ||
202 | #define MC13783_SWCTRL_SW2B_PANIC_MODE (1 << 16) | ||
203 | #define MC13783_SWCTRL_SW2B_SOFTSTART (1 << 17) | ||
204 | #define MC13783_SWSET_SW3 (1 << 18) | ||
205 | #define MC13783_SWCTRL_SW3_EN (1 << 20) | ||
206 | #define MC13783_SWCTRL_SW3_STBY (1 << 21) | ||
207 | #define MC13783_SWCTRL_SW3_MODE (1 << 22) | ||
208 | |||
209 | static inline int mc13783_set_bits(struct mc13783 *mc13783, unsigned int offset, | ||
210 | u32 mask, u32 val) | ||
211 | { | ||
212 | int ret; | ||
213 | mc13783_lock(mc13783); | ||
214 | ret = mc13783_reg_rmw(mc13783, offset, mask, val); | ||
215 | mc13783_unlock(mc13783); | ||
216 | |||
217 | return ret; | ||
218 | } | ||
219 | |||
220 | #endif /* __LINUX_MFD_MC13783_PRIV_H */ | ||
diff --git a/include/linux/mfd/mc13783.h b/include/linux/mfd/mc13783.h index 4a894f688549..0fa44fb8dd26 100644 --- a/include/linux/mfd/mc13783.h +++ b/include/linux/mfd/mc13783.h | |||
@@ -21,6 +21,8 @@ int mc13783_reg_write(struct mc13783 *mc13783, unsigned int offset, u32 val); | |||
21 | int mc13783_reg_rmw(struct mc13783 *mc13783, unsigned int offset, | 21 | int mc13783_reg_rmw(struct mc13783 *mc13783, unsigned int offset, |
22 | u32 mask, u32 val); | 22 | u32 mask, u32 val); |
23 | 23 | ||
24 | int mc13783_get_flags(struct mc13783 *mc13783); | ||
25 | |||
24 | int mc13783_irq_request(struct mc13783 *mc13783, int irq, | 26 | int mc13783_irq_request(struct mc13783 *mc13783, int irq, |
25 | irq_handler_t handler, const char *name, void *dev); | 27 | irq_handler_t handler, const char *name, void *dev); |
26 | int mc13783_irq_request_nounmask(struct mc13783 *mc13783, int irq, | 28 | int mc13783_irq_request_nounmask(struct mc13783 *mc13783, int irq, |
diff --git a/include/linux/mfd/stmpe.h b/include/linux/mfd/stmpe.h new file mode 100644 index 000000000000..39ca7588659b --- /dev/null +++ b/include/linux/mfd/stmpe.h | |||
@@ -0,0 +1,201 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
6 | */ | ||
7 | |||
8 | #ifndef __LINUX_MFD_STMPE_H | ||
9 | #define __LINUX_MFD_STMPE_H | ||
10 | |||
11 | #include <linux/device.h> | ||
12 | |||
13 | enum stmpe_block { | ||
14 | STMPE_BLOCK_GPIO = 1 << 0, | ||
15 | STMPE_BLOCK_KEYPAD = 1 << 1, | ||
16 | STMPE_BLOCK_TOUCHSCREEN = 1 << 2, | ||
17 | STMPE_BLOCK_ADC = 1 << 3, | ||
18 | STMPE_BLOCK_PWM = 1 << 4, | ||
19 | STMPE_BLOCK_ROTATOR = 1 << 5, | ||
20 | }; | ||
21 | |||
22 | enum stmpe_partnum { | ||
23 | STMPE811, | ||
24 | STMPE1601, | ||
25 | STMPE2401, | ||
26 | STMPE2403, | ||
27 | }; | ||
28 | |||
29 | /* | ||
30 | * For registers whose locations differ on variants, the correct address is | ||
31 | * obtained by indexing stmpe->regs with one of the following. | ||
32 | */ | ||
33 | enum { | ||
34 | STMPE_IDX_CHIP_ID, | ||
35 | STMPE_IDX_ICR_LSB, | ||
36 | STMPE_IDX_IER_LSB, | ||
37 | STMPE_IDX_ISR_MSB, | ||
38 | STMPE_IDX_GPMR_LSB, | ||
39 | STMPE_IDX_GPSR_LSB, | ||
40 | STMPE_IDX_GPCR_LSB, | ||
41 | STMPE_IDX_GPDR_LSB, | ||
42 | STMPE_IDX_GPEDR_MSB, | ||
43 | STMPE_IDX_GPRER_LSB, | ||
44 | STMPE_IDX_GPFER_LSB, | ||
45 | STMPE_IDX_GPAFR_U_MSB, | ||
46 | STMPE_IDX_IEGPIOR_LSB, | ||
47 | STMPE_IDX_ISGPIOR_MSB, | ||
48 | STMPE_IDX_MAX, | ||
49 | }; | ||
50 | |||
51 | |||
52 | struct stmpe_variant_info; | ||
53 | |||
54 | /** | ||
55 | * struct stmpe - STMPE MFD structure | ||
56 | * @lock: lock protecting I/O operations | ||
57 | * @irq_lock: IRQ bus lock | ||
58 | * @dev: device, mostly for dev_dbg() | ||
59 | * @i2c: i2c client | ||
60 | * @variant: the detected STMPE model number | ||
61 | * @regs: list of addresses of registers which are at different addresses on | ||
62 | * different variants. Indexed by one of STMPE_IDX_*. | ||
63 | * @irq_base: starting IRQ number for internal IRQs | ||
64 | * @num_gpios: number of gpios, differs for variants | ||
65 | * @ier: cache of IER registers for bus_lock | ||
66 | * @oldier: cache of IER registers for bus_lock | ||
67 | * @pdata: platform data | ||
68 | */ | ||
69 | struct stmpe { | ||
70 | struct mutex lock; | ||
71 | struct mutex irq_lock; | ||
72 | struct device *dev; | ||
73 | struct i2c_client *i2c; | ||
74 | enum stmpe_partnum partnum; | ||
75 | struct stmpe_variant_info *variant; | ||
76 | const u8 *regs; | ||
77 | |||
78 | int irq_base; | ||
79 | int num_gpios; | ||
80 | u8 ier[2]; | ||
81 | u8 oldier[2]; | ||
82 | struct stmpe_platform_data *pdata; | ||
83 | }; | ||
84 | |||
85 | extern int stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 data); | ||
86 | extern int stmpe_reg_read(struct stmpe *stmpe, u8 reg); | ||
87 | extern int stmpe_block_read(struct stmpe *stmpe, u8 reg, u8 length, | ||
88 | u8 *values); | ||
89 | extern int stmpe_block_write(struct stmpe *stmpe, u8 reg, u8 length, | ||
90 | const u8 *values); | ||
91 | extern int stmpe_set_bits(struct stmpe *stmpe, u8 reg, u8 mask, u8 val); | ||
92 | extern int stmpe_set_altfunc(struct stmpe *stmpe, u32 pins, | ||
93 | enum stmpe_block block); | ||
94 | extern int stmpe_enable(struct stmpe *stmpe, unsigned int blocks); | ||
95 | extern int stmpe_disable(struct stmpe *stmpe, unsigned int blocks); | ||
96 | |||
97 | struct matrix_keymap_data; | ||
98 | |||
99 | /** | ||
100 | * struct stmpe_keypad_platform_data - STMPE keypad platform data | ||
101 | * @keymap_data: key map table and size | ||
102 | * @debounce_ms: debounce interval, in ms. Maximum is | ||
103 | * %STMPE_KEYPAD_MAX_DEBOUNCE. | ||
104 | * @scan_count: number of key scanning cycles to confirm key data. | ||
105 | * Maximum is %STMPE_KEYPAD_MAX_SCAN_COUNT. | ||
106 | * @no_autorepeat: disable key autorepeat | ||
107 | */ | ||
108 | struct stmpe_keypad_platform_data { | ||
109 | struct matrix_keymap_data *keymap_data; | ||
110 | unsigned int debounce_ms; | ||
111 | unsigned int scan_count; | ||
112 | bool no_autorepeat; | ||
113 | }; | ||
114 | |||
115 | /** | ||
116 | * struct stmpe_gpio_platform_data - STMPE GPIO platform data | ||
117 | * @gpio_base: first gpio number assigned. A maximum of | ||
118 | * %STMPE_NR_GPIOS GPIOs will be allocated. | ||
119 | */ | ||
120 | struct stmpe_gpio_platform_data { | ||
121 | int gpio_base; | ||
122 | void (*setup)(struct stmpe *stmpe, unsigned gpio_base); | ||
123 | void (*remove)(struct stmpe *stmpe, unsigned gpio_base); | ||
124 | }; | ||
125 | |||
126 | /** | ||
127 | * struct stmpe_ts_platform_data - stmpe811 touch screen controller platform | ||
128 | * data | ||
129 | * @sample_time: ADC converstion time in number of clock. | ||
130 | * (0 -> 36 clocks, 1 -> 44 clocks, 2 -> 56 clocks, 3 -> 64 clocks, | ||
131 | * 4 -> 80 clocks, 5 -> 96 clocks, 6 -> 144 clocks), | ||
132 | * recommended is 4. | ||
133 | * @mod_12b: ADC Bit mode (0 -> 10bit ADC, 1 -> 12bit ADC) | ||
134 | * @ref_sel: ADC reference source | ||
135 | * (0 -> internal reference, 1 -> external reference) | ||
136 | * @adc_freq: ADC Clock speed | ||
137 | * (0 -> 1.625 MHz, 1 -> 3.25 MHz, 2 || 3 -> 6.5 MHz) | ||
138 | * @ave_ctrl: Sample average control | ||
139 | * (0 -> 1 sample, 1 -> 2 samples, 2 -> 4 samples, 3 -> 8 samples) | ||
140 | * @touch_det_delay: Touch detect interrupt delay | ||
141 | * (0 -> 10 us, 1 -> 50 us, 2 -> 100 us, 3 -> 500 us, | ||
142 | * 4-> 1 ms, 5 -> 5 ms, 6 -> 10 ms, 7 -> 50 ms) | ||
143 | * recommended is 3 | ||
144 | * @settling: Panel driver settling time | ||
145 | * (0 -> 10 us, 1 -> 100 us, 2 -> 500 us, 3 -> 1 ms, | ||
146 | * 4 -> 5 ms, 5 -> 10 ms, 6 for 50 ms, 7 -> 100 ms) | ||
147 | * recommended is 2 | ||
148 | * @fraction_z: Length of the fractional part in z | ||
149 | * (fraction_z ([0..7]) = Count of the fractional part) | ||
150 | * recommended is 7 | ||
151 | * @i_drive: current limit value of the touchscreen drivers | ||
152 | * (0 -> 20 mA typical 35 mA max, 1 -> 50 mA typical 80 mA max) | ||
153 | * | ||
154 | * */ | ||
155 | struct stmpe_ts_platform_data { | ||
156 | u8 sample_time; | ||
157 | u8 mod_12b; | ||
158 | u8 ref_sel; | ||
159 | u8 adc_freq; | ||
160 | u8 ave_ctrl; | ||
161 | u8 touch_det_delay; | ||
162 | u8 settling; | ||
163 | u8 fraction_z; | ||
164 | u8 i_drive; | ||
165 | }; | ||
166 | |||
167 | /** | ||
168 | * struct stmpe_platform_data - STMPE platform data | ||
169 | * @id: device id to distinguish between multiple STMPEs on the same board | ||
170 | * @blocks: bitmask of blocks to enable (use STMPE_BLOCK_*) | ||
171 | * @irq_trigger: IRQ trigger to use for the interrupt to the host | ||
172 | * @irq_invert_polarity: IRQ line is connected with reversed polarity | ||
173 | * @autosleep: bool to enable/disable stmpe autosleep | ||
174 | * @autosleep_timeout: inactivity timeout in milliseconds for autosleep | ||
175 | * @irq_base: base IRQ number. %STMPE_NR_IRQS irqs will be used, or | ||
176 | * %STMPE_NR_INTERNAL_IRQS if the GPIO driver is not used. | ||
177 | * @gpio: GPIO-specific platform data | ||
178 | * @keypad: keypad-specific platform data | ||
179 | * @ts: touchscreen-specific platform data | ||
180 | */ | ||
181 | struct stmpe_platform_data { | ||
182 | int id; | ||
183 | unsigned int blocks; | ||
184 | int irq_base; | ||
185 | unsigned int irq_trigger; | ||
186 | bool irq_invert_polarity; | ||
187 | bool autosleep; | ||
188 | int autosleep_timeout; | ||
189 | |||
190 | struct stmpe_gpio_platform_data *gpio; | ||
191 | struct stmpe_keypad_platform_data *keypad; | ||
192 | struct stmpe_ts_platform_data *ts; | ||
193 | }; | ||
194 | |||
195 | #define STMPE_NR_INTERNAL_IRQS 9 | ||
196 | #define STMPE_INT_GPIO(x) (STMPE_NR_INTERNAL_IRQS + (x)) | ||
197 | |||
198 | #define STMPE_NR_GPIOS 24 | ||
199 | #define STMPE_NR_IRQS STMPE_INT_GPIO(STMPE_NR_GPIOS) | ||
200 | |||
201 | #endif | ||
diff --git a/include/linux/mfd/tps6586x.h b/include/linux/mfd/tps6586x.h new file mode 100644 index 000000000000..772b3ae640af --- /dev/null +++ b/include/linux/mfd/tps6586x.h | |||
@@ -0,0 +1,47 @@ | |||
1 | #ifndef __LINUX_MFD_TPS6586X_H | ||
2 | #define __LINUX_MFD_TPS6586X_H | ||
3 | |||
4 | enum { | ||
5 | TPS6586X_ID_SM_0, | ||
6 | TPS6586X_ID_SM_1, | ||
7 | TPS6586X_ID_SM_2, | ||
8 | TPS6586X_ID_LDO_0, | ||
9 | TPS6586X_ID_LDO_1, | ||
10 | TPS6586X_ID_LDO_2, | ||
11 | TPS6586X_ID_LDO_3, | ||
12 | TPS6586X_ID_LDO_4, | ||
13 | TPS6586X_ID_LDO_5, | ||
14 | TPS6586X_ID_LDO_6, | ||
15 | TPS6586X_ID_LDO_7, | ||
16 | TPS6586X_ID_LDO_8, | ||
17 | TPS6586X_ID_LDO_9, | ||
18 | TPS6586X_ID_LDO_RTC, | ||
19 | }; | ||
20 | |||
21 | struct tps6586x_subdev_info { | ||
22 | int id; | ||
23 | const char *name; | ||
24 | void *platform_data; | ||
25 | }; | ||
26 | |||
27 | struct tps6586x_platform_data { | ||
28 | int num_subdevs; | ||
29 | struct tps6586x_subdev_info *subdevs; | ||
30 | |||
31 | int gpio_base; | ||
32 | }; | ||
33 | |||
34 | /* | ||
35 | * NOTE: the functions below are not intended for use outside | ||
36 | * of the TPS6586X sub-device drivers | ||
37 | */ | ||
38 | extern int tps6586x_write(struct device *dev, int reg, uint8_t val); | ||
39 | extern int tps6586x_writes(struct device *dev, int reg, int len, uint8_t *val); | ||
40 | extern int tps6586x_read(struct device *dev, int reg, uint8_t *val); | ||
41 | extern int tps6586x_reads(struct device *dev, int reg, int len, uint8_t *val); | ||
42 | extern int tps6586x_set_bits(struct device *dev, int reg, uint8_t bit_mask); | ||
43 | extern int tps6586x_clr_bits(struct device *dev, int reg, uint8_t bit_mask); | ||
44 | extern int tps6586x_update(struct device *dev, int reg, uint8_t val, | ||
45 | uint8_t mask); | ||
46 | |||
47 | #endif /*__LINUX_MFD_TPS6586X_H */ | ||
diff --git a/include/linux/mfd/wm8994/gpio.h b/include/linux/mfd/wm8994/gpio.h index b4d4c22991e8..0c79b5ff4b5a 100644 --- a/include/linux/mfd/wm8994/gpio.h +++ b/include/linux/mfd/wm8994/gpio.h | |||
@@ -36,6 +36,10 @@ | |||
36 | #define WM8994_GP_FN_WSEQ_STATUS 16 | 36 | #define WM8994_GP_FN_WSEQ_STATUS 16 |
37 | #define WM8994_GP_FN_FIFO_ERROR 17 | 37 | #define WM8994_GP_FN_FIFO_ERROR 17 |
38 | #define WM8994_GP_FN_OPCLK 18 | 38 | #define WM8994_GP_FN_OPCLK 18 |
39 | #define WM8994_GP_FN_THW 19 | ||
40 | #define WM8994_GP_FN_DCS_DONE 20 | ||
41 | #define WM8994_GP_FN_FLL1_OUT 21 | ||
42 | #define WM8994_GP_FN_FLL2_OUT 22 | ||
39 | 43 | ||
40 | #define WM8994_GPN_DIR 0x8000 /* GPN_DIR */ | 44 | #define WM8994_GPN_DIR 0x8000 /* GPN_DIR */ |
41 | #define WM8994_GPN_DIR_MASK 0x8000 /* GPN_DIR */ | 45 | #define WM8994_GPN_DIR_MASK 0x8000 /* GPN_DIR */ |
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index f6c9b7dcb9fd..bafffc737903 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h | |||
@@ -38,6 +38,7 @@ | |||
38 | #define KVM_MINOR 232 | 38 | #define KVM_MINOR 232 |
39 | #define BTRFS_MINOR 234 | 39 | #define BTRFS_MINOR 234 |
40 | #define AUTOFS_MINOR 235 | 40 | #define AUTOFS_MINOR 235 |
41 | #define MAPPER_CTRL_MINOR 236 | ||
41 | #define MISC_DYNAMIC_MINOR 255 | 42 | #define MISC_DYNAMIC_MINOR 255 |
42 | 43 | ||
43 | struct device; | 44 | struct device; |
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 4d893eaf8174..6b7525099e56 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
@@ -31,6 +31,7 @@ struct mmc_csd { | |||
31 | unsigned int tacc_ns; | 31 | unsigned int tacc_ns; |
32 | unsigned int r2w_factor; | 32 | unsigned int r2w_factor; |
33 | unsigned int max_dtr; | 33 | unsigned int max_dtr; |
34 | unsigned int erase_size; /* In sectors */ | ||
34 | unsigned int read_blkbits; | 35 | unsigned int read_blkbits; |
35 | unsigned int write_blkbits; | 36 | unsigned int write_blkbits; |
36 | unsigned int capacity; | 37 | unsigned int capacity; |
@@ -42,9 +43,16 @@ struct mmc_csd { | |||
42 | 43 | ||
43 | struct mmc_ext_csd { | 44 | struct mmc_ext_csd { |
44 | u8 rev; | 45 | u8 rev; |
46 | u8 erase_group_def; | ||
47 | u8 sec_feature_support; | ||
45 | unsigned int sa_timeout; /* Units: 100ns */ | 48 | unsigned int sa_timeout; /* Units: 100ns */ |
46 | unsigned int hs_max_dtr; | 49 | unsigned int hs_max_dtr; |
47 | unsigned int sectors; | 50 | unsigned int sectors; |
51 | unsigned int hc_erase_size; /* In sectors */ | ||
52 | unsigned int hc_erase_timeout; /* In milliseconds */ | ||
53 | unsigned int sec_trim_mult; /* Secure trim multiplier */ | ||
54 | unsigned int sec_erase_mult; /* Secure erase multiplier */ | ||
55 | unsigned int trim_timeout; /* In milliseconds */ | ||
48 | }; | 56 | }; |
49 | 57 | ||
50 | struct sd_scr { | 58 | struct sd_scr { |
@@ -54,6 +62,12 @@ struct sd_scr { | |||
54 | #define SD_SCR_BUS_WIDTH_4 (1<<2) | 62 | #define SD_SCR_BUS_WIDTH_4 (1<<2) |
55 | }; | 63 | }; |
56 | 64 | ||
65 | struct sd_ssr { | ||
66 | unsigned int au; /* In sectors */ | ||
67 | unsigned int erase_timeout; /* In milliseconds */ | ||
68 | unsigned int erase_offset; /* In milliseconds */ | ||
69 | }; | ||
70 | |||
57 | struct sd_switch_caps { | 71 | struct sd_switch_caps { |
58 | unsigned int hs_max_dtr; | 72 | unsigned int hs_max_dtr; |
59 | }; | 73 | }; |
@@ -106,6 +120,11 @@ struct mmc_card { | |||
106 | #define MMC_QUIRK_NONSTD_SDIO (1<<2) /* non-standard SDIO card attached */ | 120 | #define MMC_QUIRK_NONSTD_SDIO (1<<2) /* non-standard SDIO card attached */ |
107 | /* (missing CIA registers) */ | 121 | /* (missing CIA registers) */ |
108 | 122 | ||
123 | unsigned int erase_size; /* erase size in sectors */ | ||
124 | unsigned int erase_shift; /* if erase unit is power 2 */ | ||
125 | unsigned int pref_erase; /* in sectors */ | ||
126 | u8 erased_byte; /* value of erased bytes */ | ||
127 | |||
109 | u32 raw_cid[4]; /* raw card CID */ | 128 | u32 raw_cid[4]; /* raw card CID */ |
110 | u32 raw_csd[4]; /* raw card CSD */ | 129 | u32 raw_csd[4]; /* raw card CSD */ |
111 | u32 raw_scr[2]; /* raw card SCR */ | 130 | u32 raw_scr[2]; /* raw card SCR */ |
@@ -113,6 +132,7 @@ struct mmc_card { | |||
113 | struct mmc_csd csd; /* card specific */ | 132 | struct mmc_csd csd; /* card specific */ |
114 | struct mmc_ext_csd ext_csd; /* mmc v4 extended card specific */ | 133 | struct mmc_ext_csd ext_csd; /* mmc v4 extended card specific */ |
115 | struct sd_scr scr; /* extra SD information */ | 134 | struct sd_scr scr; /* extra SD information */ |
135 | struct sd_ssr ssr; /* yet more SD information */ | ||
116 | struct sd_switch_caps sw_caps; /* switch (CMD6) caps */ | 136 | struct sd_switch_caps sw_caps; /* switch (CMD6) caps */ |
117 | 137 | ||
118 | unsigned int sdio_funcs; /* number of SDIO functions */ | 138 | unsigned int sdio_funcs; /* number of SDIO functions */ |
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index e4898e9eeb59..7429033acb66 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h | |||
@@ -92,6 +92,8 @@ struct mmc_command { | |||
92 | * actively failing requests | 92 | * actively failing requests |
93 | */ | 93 | */ |
94 | 94 | ||
95 | unsigned int erase_timeout; /* in milliseconds */ | ||
96 | |||
95 | struct mmc_data *data; /* data segment associated with cmd */ | 97 | struct mmc_data *data; /* data segment associated with cmd */ |
96 | struct mmc_request *mrq; /* associated request */ | 98 | struct mmc_request *mrq; /* associated request */ |
97 | }; | 99 | }; |
@@ -134,6 +136,23 @@ extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int); | |||
134 | extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *, | 136 | extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *, |
135 | struct mmc_command *, int); | 137 | struct mmc_command *, int); |
136 | 138 | ||
139 | #define MMC_ERASE_ARG 0x00000000 | ||
140 | #define MMC_SECURE_ERASE_ARG 0x80000000 | ||
141 | #define MMC_TRIM_ARG 0x00000001 | ||
142 | #define MMC_SECURE_TRIM1_ARG 0x80000001 | ||
143 | #define MMC_SECURE_TRIM2_ARG 0x80008000 | ||
144 | |||
145 | #define MMC_SECURE_ARGS 0x80000000 | ||
146 | #define MMC_TRIM_ARGS 0x00008001 | ||
147 | |||
148 | extern int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr, | ||
149 | unsigned int arg); | ||
150 | extern int mmc_can_erase(struct mmc_card *card); | ||
151 | extern int mmc_can_trim(struct mmc_card *card); | ||
152 | extern int mmc_can_secure_erase_trim(struct mmc_card *card); | ||
153 | extern int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from, | ||
154 | unsigned int nr); | ||
155 | |||
137 | extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *); | 156 | extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *); |
138 | extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int); | 157 | extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int); |
139 | 158 | ||
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 513ff0376b09..1575b52c3bfa 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h | |||
@@ -156,6 +156,7 @@ struct mmc_host { | |||
156 | #define MMC_CAP_DISABLE (1 << 7) /* Can the host be disabled */ | 156 | #define MMC_CAP_DISABLE (1 << 7) /* Can the host be disabled */ |
157 | #define MMC_CAP_NONREMOVABLE (1 << 8) /* Nonremovable e.g. eMMC */ | 157 | #define MMC_CAP_NONREMOVABLE (1 << 8) /* Nonremovable e.g. eMMC */ |
158 | #define MMC_CAP_WAIT_WHILE_BUSY (1 << 9) /* Waits while card is busy */ | 158 | #define MMC_CAP_WAIT_WHILE_BUSY (1 << 9) /* Waits while card is busy */ |
159 | #define MMC_CAP_ERASE (1 << 10) /* Allow erase/trim commands */ | ||
159 | 160 | ||
160 | mmc_pm_flag_t pm_caps; /* supported pm features */ | 161 | mmc_pm_flag_t pm_caps; /* supported pm features */ |
161 | 162 | ||
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index 52ce98866287..dd11ae51fb68 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h | |||
@@ -251,13 +251,21 @@ struct _mmc_csd { | |||
251 | * EXT_CSD fields | 251 | * EXT_CSD fields |
252 | */ | 252 | */ |
253 | 253 | ||
254 | #define EXT_CSD_BUS_WIDTH 183 /* R/W */ | 254 | #define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */ |
255 | #define EXT_CSD_HS_TIMING 185 /* R/W */ | 255 | #define EXT_CSD_ERASED_MEM_CONT 181 /* RO */ |
256 | #define EXT_CSD_CARD_TYPE 196 /* RO */ | 256 | #define EXT_CSD_BUS_WIDTH 183 /* R/W */ |
257 | #define EXT_CSD_STRUCTURE 194 /* RO */ | 257 | #define EXT_CSD_HS_TIMING 185 /* R/W */ |
258 | #define EXT_CSD_REV 192 /* RO */ | 258 | #define EXT_CSD_REV 192 /* RO */ |
259 | #define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ | 259 | #define EXT_CSD_STRUCTURE 194 /* RO */ |
260 | #define EXT_CSD_S_A_TIMEOUT 217 | 260 | #define EXT_CSD_CARD_TYPE 196 /* RO */ |
261 | #define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ | ||
262 | #define EXT_CSD_S_A_TIMEOUT 217 /* RO */ | ||
263 | #define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */ | ||
264 | #define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */ | ||
265 | #define EXT_CSD_SEC_TRIM_MULT 229 /* RO */ | ||
266 | #define EXT_CSD_SEC_ERASE_MULT 230 /* RO */ | ||
267 | #define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */ | ||
268 | #define EXT_CSD_TRIM_MULT 232 /* RO */ | ||
261 | 269 | ||
262 | /* | 270 | /* |
263 | * EXT_CSD field definitions | 271 | * EXT_CSD field definitions |
@@ -275,6 +283,10 @@ struct _mmc_csd { | |||
275 | #define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ | 283 | #define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ |
276 | #define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */ | 284 | #define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */ |
277 | 285 | ||
286 | #define EXT_CSD_SEC_ER_EN BIT(0) | ||
287 | #define EXT_CSD_SEC_BD_BLK_EN BIT(2) | ||
288 | #define EXT_CSD_SEC_GB_CL_EN BIT(4) | ||
289 | |||
278 | /* | 290 | /* |
279 | * MMC_SWITCH access modes | 291 | * MMC_SWITCH access modes |
280 | */ | 292 | */ |
diff --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h index f310062cffb4..3fd85e088cc3 100644 --- a/include/linux/mmc/sd.h +++ b/include/linux/mmc/sd.h | |||
@@ -21,8 +21,13 @@ | |||
21 | /* class 10 */ | 21 | /* class 10 */ |
22 | #define SD_SWITCH 6 /* adtc [31:0] See below R1 */ | 22 | #define SD_SWITCH 6 /* adtc [31:0] See below R1 */ |
23 | 23 | ||
24 | /* class 5 */ | ||
25 | #define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */ | ||
26 | #define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */ | ||
27 | |||
24 | /* Application commands */ | 28 | /* Application commands */ |
25 | #define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ | 29 | #define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ |
30 | #define SD_APP_SD_STATUS 13 /* adtc R1 */ | ||
26 | #define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */ | 31 | #define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */ |
27 | #define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ | 32 | #define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ |
28 | #define SD_APP_SEND_SCR 51 /* adtc R1 */ | 33 | #define SD_APP_SEND_SCR 51 /* adtc R1 */ |
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index 82a9124f7d75..9d2f1837b3d8 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h | |||
@@ -31,20 +31,23 @@ static const char __module_cat(name,__LINE__)[] \ | |||
31 | 31 | ||
32 | struct kernel_param; | 32 | struct kernel_param; |
33 | 33 | ||
34 | /* Returns 0, or -errno. arg is in kp->arg. */ | 34 | struct kernel_param_ops { |
35 | typedef int (*param_set_fn)(const char *val, struct kernel_param *kp); | 35 | /* Returns 0, or -errno. arg is in kp->arg. */ |
36 | /* Returns length written or -errno. Buffer is 4k (ie. be short!) */ | 36 | int (*set)(const char *val, const struct kernel_param *kp); |
37 | typedef int (*param_get_fn)(char *buffer, struct kernel_param *kp); | 37 | /* Returns length written or -errno. Buffer is 4k (ie. be short!) */ |
38 | int (*get)(char *buffer, const struct kernel_param *kp); | ||
39 | /* Optional function to free kp->arg when module unloaded. */ | ||
40 | void (*free)(void *arg); | ||
41 | }; | ||
38 | 42 | ||
39 | /* Flag bits for kernel_param.flags */ | 43 | /* Flag bits for kernel_param.flags */ |
40 | #define KPARAM_ISBOOL 2 | 44 | #define KPARAM_ISBOOL 2 |
41 | 45 | ||
42 | struct kernel_param { | 46 | struct kernel_param { |
43 | const char *name; | 47 | const char *name; |
48 | const struct kernel_param_ops *ops; | ||
44 | u16 perm; | 49 | u16 perm; |
45 | u16 flags; | 50 | u16 flags; |
46 | param_set_fn set; | ||
47 | param_get_fn get; | ||
48 | union { | 51 | union { |
49 | void *arg; | 52 | void *arg; |
50 | const struct kparam_string *str; | 53 | const struct kparam_string *str; |
@@ -63,12 +66,67 @@ struct kparam_array | |||
63 | { | 66 | { |
64 | unsigned int max; | 67 | unsigned int max; |
65 | unsigned int *num; | 68 | unsigned int *num; |
66 | param_set_fn set; | 69 | const struct kernel_param_ops *ops; |
67 | param_get_fn get; | ||
68 | unsigned int elemsize; | 70 | unsigned int elemsize; |
69 | void *elem; | 71 | void *elem; |
70 | }; | 72 | }; |
71 | 73 | ||
74 | /** | ||
75 | * module_param - typesafe helper for a module/cmdline parameter | ||
76 | * @value: the variable to alter, and exposed parameter name. | ||
77 | * @type: the type of the parameter | ||
78 | * @perm: visibility in sysfs. | ||
79 | * | ||
80 | * @value becomes the module parameter, or (prefixed by KBUILD_MODNAME and a | ||
81 | * ".") the kernel commandline parameter. Note that - is changed to _, so | ||
82 | * the user can use "foo-bar=1" even for variable "foo_bar". | ||
83 | * | ||
84 | * @perm is 0 if the the variable is not to appear in sysfs, or 0444 | ||
85 | * for world-readable, 0644 for root-writable, etc. Note that if it | ||
86 | * is writable, you may need to use kparam_block_sysfs_write() around | ||
87 | * accesses (esp. charp, which can be kfreed when it changes). | ||
88 | * | ||
89 | * The @type is simply pasted to refer to a param_ops_##type and a | ||
90 | * param_check_##type: for convenience many standard types are provided but | ||
91 | * you can create your own by defining those variables. | ||
92 | * | ||
93 | * Standard types are: | ||
94 | * byte, short, ushort, int, uint, long, ulong | ||
95 | * charp: a character pointer | ||
96 | * bool: a bool, values 0/1, y/n, Y/N. | ||
97 | * invbool: the above, only sense-reversed (N = true). | ||
98 | */ | ||
99 | #define module_param(name, type, perm) \ | ||
100 | module_param_named(name, name, type, perm) | ||
101 | |||
102 | /** | ||
103 | * module_param_named - typesafe helper for a renamed module/cmdline parameter | ||
104 | * @name: a valid C identifier which is the parameter name. | ||
105 | * @value: the actual lvalue to alter. | ||
106 | * @type: the type of the parameter | ||
107 | * @perm: visibility in sysfs. | ||
108 | * | ||
109 | * Usually it's a good idea to have variable names and user-exposed names the | ||
110 | * same, but that's harder if the variable must be non-static or is inside a | ||
111 | * structure. This allows exposure under a different name. | ||
112 | */ | ||
113 | #define module_param_named(name, value, type, perm) \ | ||
114 | param_check_##type(name, &(value)); \ | ||
115 | module_param_cb(name, ¶m_ops_##type, &value, perm); \ | ||
116 | __MODULE_PARM_TYPE(name, #type) | ||
117 | |||
118 | /** | ||
119 | * module_param_cb - general callback for a module/cmdline parameter | ||
120 | * @name: a valid C identifier which is the parameter name. | ||
121 | * @ops: the set & get operations for this parameter. | ||
122 | * @perm: visibility in sysfs. | ||
123 | * | ||
124 | * The ops can have NULL set or get functions. | ||
125 | */ | ||
126 | #define module_param_cb(name, ops, arg, perm) \ | ||
127 | __module_param_call(MODULE_PARAM_PREFIX, \ | ||
128 | name, ops, arg, __same_type((arg), bool *), perm) | ||
129 | |||
72 | /* On alpha, ia64 and ppc64 relocations to global data cannot go into | 130 | /* On alpha, ia64 and ppc64 relocations to global data cannot go into |
73 | read-only sections (which is part of respective UNIX ABI on these | 131 | read-only sections (which is part of respective UNIX ABI on these |
74 | platforms). So 'const' makes no sense and even causes compile failures | 132 | platforms). So 'const' makes no sense and even causes compile failures |
@@ -80,10 +138,8 @@ struct kparam_array | |||
80 | #endif | 138 | #endif |
81 | 139 | ||
82 | /* This is the fundamental function for registering boot/module | 140 | /* This is the fundamental function for registering boot/module |
83 | parameters. perm sets the visibility in sysfs: 000 means it's | 141 | parameters. */ |
84 | not there, read bits mean it's readable, write bits mean it's | 142 | #define __module_param_call(prefix, name, ops, arg, isbool, perm) \ |
85 | writable. */ | ||
86 | #define __module_param_call(prefix, name, set, get, arg, isbool, perm) \ | ||
87 | /* Default value instead of permissions? */ \ | 143 | /* Default value instead of permissions? */ \ |
88 | static int __param_perm_check_##name __attribute__((unused)) = \ | 144 | static int __param_perm_check_##name __attribute__((unused)) = \ |
89 | BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) \ | 145 | BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) \ |
@@ -92,31 +148,87 @@ struct kparam_array | |||
92 | static struct kernel_param __moduleparam_const __param_##name \ | 148 | static struct kernel_param __moduleparam_const __param_##name \ |
93 | __used \ | 149 | __used \ |
94 | __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ | 150 | __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ |
95 | = { __param_str_##name, perm, isbool ? KPARAM_ISBOOL : 0, \ | 151 | = { __param_str_##name, ops, perm, isbool ? KPARAM_ISBOOL : 0, \ |
96 | set, get, { arg } } | 152 | { arg } } |
153 | |||
154 | /* Obsolete - use module_param_cb() */ | ||
155 | #define module_param_call(name, set, get, arg, perm) \ | ||
156 | static struct kernel_param_ops __param_ops_##name = \ | ||
157 | { (void *)set, (void *)get }; \ | ||
158 | __module_param_call(MODULE_PARAM_PREFIX, \ | ||
159 | name, &__param_ops_##name, arg, \ | ||
160 | __same_type(arg, bool *), \ | ||
161 | (perm) + sizeof(__check_old_set_param(set))*0) | ||
162 | |||
163 | /* We don't get oldget: it's often a new-style param_get_uint, etc. */ | ||
164 | static inline int | ||
165 | __check_old_set_param(int (*oldset)(const char *, struct kernel_param *)) | ||
166 | { | ||
167 | return 0; | ||
168 | } | ||
97 | 169 | ||
98 | #define module_param_call(name, set, get, arg, perm) \ | 170 | /** |
99 | __module_param_call(MODULE_PARAM_PREFIX, \ | 171 | * kparam_block_sysfs_write - make sure a parameter isn't written via sysfs. |
100 | name, set, get, arg, \ | 172 | * @name: the name of the parameter |
101 | __same_type(*(arg), bool), perm) | 173 | * |
174 | * There's no point blocking write on a paramter that isn't writable via sysfs! | ||
175 | */ | ||
176 | #define kparam_block_sysfs_write(name) \ | ||
177 | do { \ | ||
178 | BUG_ON(!(__param_##name.perm & 0222)); \ | ||
179 | __kernel_param_lock(); \ | ||
180 | } while (0) | ||
102 | 181 | ||
103 | /* Helper functions: type is byte, short, ushort, int, uint, long, | 182 | /** |
104 | ulong, charp, bool or invbool, or XXX if you define param_get_XXX, | 183 | * kparam_unblock_sysfs_write - allows sysfs to write to a parameter again. |
105 | param_set_XXX and param_check_XXX. */ | 184 | * @name: the name of the parameter |
106 | #define module_param_named(name, value, type, perm) \ | 185 | */ |
107 | param_check_##type(name, &(value)); \ | 186 | #define kparam_unblock_sysfs_write(name) \ |
108 | module_param_call(name, param_set_##type, param_get_##type, &value, perm); \ | 187 | do { \ |
109 | __MODULE_PARM_TYPE(name, #type) | 188 | BUG_ON(!(__param_##name.perm & 0222)); \ |
189 | __kernel_param_unlock(); \ | ||
190 | } while (0) | ||
110 | 191 | ||
111 | #define module_param(name, type, perm) \ | 192 | /** |
112 | module_param_named(name, name, type, perm) | 193 | * kparam_block_sysfs_read - make sure a parameter isn't read via sysfs. |
194 | * @name: the name of the parameter | ||
195 | * | ||
196 | * This also blocks sysfs writes. | ||
197 | */ | ||
198 | #define kparam_block_sysfs_read(name) \ | ||
199 | do { \ | ||
200 | BUG_ON(!(__param_##name.perm & 0444)); \ | ||
201 | __kernel_param_lock(); \ | ||
202 | } while (0) | ||
203 | |||
204 | /** | ||
205 | * kparam_unblock_sysfs_read - allows sysfs to read a parameter again. | ||
206 | * @name: the name of the parameter | ||
207 | */ | ||
208 | #define kparam_unblock_sysfs_read(name) \ | ||
209 | do { \ | ||
210 | BUG_ON(!(__param_##name.perm & 0444)); \ | ||
211 | __kernel_param_unlock(); \ | ||
212 | } while (0) | ||
213 | |||
214 | #ifdef CONFIG_SYSFS | ||
215 | extern void __kernel_param_lock(void); | ||
216 | extern void __kernel_param_unlock(void); | ||
217 | #else | ||
218 | static inline void __kernel_param_lock(void) | ||
219 | { | ||
220 | } | ||
221 | static inline void __kernel_param_unlock(void) | ||
222 | { | ||
223 | } | ||
224 | #endif | ||
113 | 225 | ||
114 | #ifndef MODULE | 226 | #ifndef MODULE |
115 | /** | 227 | /** |
116 | * core_param - define a historical core kernel parameter. | 228 | * core_param - define a historical core kernel parameter. |
117 | * @name: the name of the cmdline and sysfs parameter (often the same as var) | 229 | * @name: the name of the cmdline and sysfs parameter (often the same as var) |
118 | * @var: the variable | 230 | * @var: the variable |
119 | * @type: the type (for param_set_##type and param_get_##type) | 231 | * @type: the type of the parameter |
120 | * @perm: visibility in sysfs | 232 | * @perm: visibility in sysfs |
121 | * | 233 | * |
122 | * core_param is just like module_param(), but cannot be modular and | 234 | * core_param is just like module_param(), but cannot be modular and |
@@ -126,23 +238,32 @@ struct kparam_array | |||
126 | */ | 238 | */ |
127 | #define core_param(name, var, type, perm) \ | 239 | #define core_param(name, var, type, perm) \ |
128 | param_check_##type(name, &(var)); \ | 240 | param_check_##type(name, &(var)); \ |
129 | __module_param_call("", name, param_set_##type, param_get_##type, \ | 241 | __module_param_call("", name, ¶m_ops_##type, \ |
130 | &var, __same_type(var, bool), perm) | 242 | &var, __same_type(var, bool), perm) |
131 | #endif /* !MODULE */ | 243 | #endif /* !MODULE */ |
132 | 244 | ||
133 | /* Actually copy string: maxlen param is usually sizeof(string). */ | 245 | /** |
246 | * module_param_string - a char array parameter | ||
247 | * @name: the name of the parameter | ||
248 | * @string: the string variable | ||
249 | * @len: the maximum length of the string, incl. terminator | ||
250 | * @perm: visibility in sysfs. | ||
251 | * | ||
252 | * This actually copies the string when it's set (unlike type charp). | ||
253 | * @len is usually just sizeof(string). | ||
254 | */ | ||
134 | #define module_param_string(name, string, len, perm) \ | 255 | #define module_param_string(name, string, len, perm) \ |
135 | static const struct kparam_string __param_string_##name \ | 256 | static const struct kparam_string __param_string_##name \ |
136 | = { len, string }; \ | 257 | = { len, string }; \ |
137 | __module_param_call(MODULE_PARAM_PREFIX, name, \ | 258 | __module_param_call(MODULE_PARAM_PREFIX, name, \ |
138 | param_set_copystring, param_get_string, \ | 259 | ¶m_ops_string, \ |
139 | .str = &__param_string_##name, 0, perm); \ | 260 | .str = &__param_string_##name, 0, perm); \ |
140 | __MODULE_PARM_TYPE(name, "string") | 261 | __MODULE_PARM_TYPE(name, "string") |
141 | 262 | ||
142 | /* Called on module insert or kernel boot */ | 263 | /* Called on module insert or kernel boot */ |
143 | extern int parse_args(const char *name, | 264 | extern int parse_args(const char *name, |
144 | char *args, | 265 | char *args, |
145 | struct kernel_param *params, | 266 | const struct kernel_param *params, |
146 | unsigned num, | 267 | unsigned num, |
147 | int (*unknown)(char *param, char *val)); | 268 | int (*unknown)(char *param, char *val)); |
148 | 269 | ||
@@ -162,72 +283,105 @@ static inline void destroy_params(const struct kernel_param *params, | |||
162 | #define __param_check(name, p, type) \ | 283 | #define __param_check(name, p, type) \ |
163 | static inline type *__check_##name(void) { return(p); } | 284 | static inline type *__check_##name(void) { return(p); } |
164 | 285 | ||
165 | extern int param_set_byte(const char *val, struct kernel_param *kp); | 286 | extern struct kernel_param_ops param_ops_byte; |
166 | extern int param_get_byte(char *buffer, struct kernel_param *kp); | 287 | extern int param_set_byte(const char *val, const struct kernel_param *kp); |
288 | extern int param_get_byte(char *buffer, const struct kernel_param *kp); | ||
167 | #define param_check_byte(name, p) __param_check(name, p, unsigned char) | 289 | #define param_check_byte(name, p) __param_check(name, p, unsigned char) |
168 | 290 | ||
169 | extern int param_set_short(const char *val, struct kernel_param *kp); | 291 | extern struct kernel_param_ops param_ops_short; |
170 | extern int param_get_short(char *buffer, struct kernel_param *kp); | 292 | extern int param_set_short(const char *val, const struct kernel_param *kp); |
293 | extern int param_get_short(char *buffer, const struct kernel_param *kp); | ||
171 | #define param_check_short(name, p) __param_check(name, p, short) | 294 | #define param_check_short(name, p) __param_check(name, p, short) |
172 | 295 | ||
173 | extern int param_set_ushort(const char *val, struct kernel_param *kp); | 296 | extern struct kernel_param_ops param_ops_ushort; |
174 | extern int param_get_ushort(char *buffer, struct kernel_param *kp); | 297 | extern int param_set_ushort(const char *val, const struct kernel_param *kp); |
298 | extern int param_get_ushort(char *buffer, const struct kernel_param *kp); | ||
175 | #define param_check_ushort(name, p) __param_check(name, p, unsigned short) | 299 | #define param_check_ushort(name, p) __param_check(name, p, unsigned short) |
176 | 300 | ||
177 | extern int param_set_int(const char *val, struct kernel_param *kp); | 301 | extern struct kernel_param_ops param_ops_int; |
178 | extern int param_get_int(char *buffer, struct kernel_param *kp); | 302 | extern int param_set_int(const char *val, const struct kernel_param *kp); |
303 | extern int param_get_int(char *buffer, const struct kernel_param *kp); | ||
179 | #define param_check_int(name, p) __param_check(name, p, int) | 304 | #define param_check_int(name, p) __param_check(name, p, int) |
180 | 305 | ||
181 | extern int param_set_uint(const char *val, struct kernel_param *kp); | 306 | extern struct kernel_param_ops param_ops_uint; |
182 | extern int param_get_uint(char *buffer, struct kernel_param *kp); | 307 | extern int param_set_uint(const char *val, const struct kernel_param *kp); |
308 | extern int param_get_uint(char *buffer, const struct kernel_param *kp); | ||
183 | #define param_check_uint(name, p) __param_check(name, p, unsigned int) | 309 | #define param_check_uint(name, p) __param_check(name, p, unsigned int) |
184 | 310 | ||
185 | extern int param_set_long(const char *val, struct kernel_param *kp); | 311 | extern struct kernel_param_ops param_ops_long; |
186 | extern int param_get_long(char *buffer, struct kernel_param *kp); | 312 | extern int param_set_long(const char *val, const struct kernel_param *kp); |
313 | extern int param_get_long(char *buffer, const struct kernel_param *kp); | ||
187 | #define param_check_long(name, p) __param_check(name, p, long) | 314 | #define param_check_long(name, p) __param_check(name, p, long) |
188 | 315 | ||
189 | extern int param_set_ulong(const char *val, struct kernel_param *kp); | 316 | extern struct kernel_param_ops param_ops_ulong; |
190 | extern int param_get_ulong(char *buffer, struct kernel_param *kp); | 317 | extern int param_set_ulong(const char *val, const struct kernel_param *kp); |
318 | extern int param_get_ulong(char *buffer, const struct kernel_param *kp); | ||
191 | #define param_check_ulong(name, p) __param_check(name, p, unsigned long) | 319 | #define param_check_ulong(name, p) __param_check(name, p, unsigned long) |
192 | 320 | ||
193 | extern int param_set_charp(const char *val, struct kernel_param *kp); | 321 | extern struct kernel_param_ops param_ops_charp; |
194 | extern int param_get_charp(char *buffer, struct kernel_param *kp); | 322 | extern int param_set_charp(const char *val, const struct kernel_param *kp); |
323 | extern int param_get_charp(char *buffer, const struct kernel_param *kp); | ||
195 | #define param_check_charp(name, p) __param_check(name, p, char *) | 324 | #define param_check_charp(name, p) __param_check(name, p, char *) |
196 | 325 | ||
197 | /* For historical reasons "bool" parameters can be (unsigned) "int". */ | 326 | /* For historical reasons "bool" parameters can be (unsigned) "int". */ |
198 | extern int param_set_bool(const char *val, struct kernel_param *kp); | 327 | extern struct kernel_param_ops param_ops_bool; |
199 | extern int param_get_bool(char *buffer, struct kernel_param *kp); | 328 | extern int param_set_bool(const char *val, const struct kernel_param *kp); |
329 | extern int param_get_bool(char *buffer, const struct kernel_param *kp); | ||
200 | #define param_check_bool(name, p) \ | 330 | #define param_check_bool(name, p) \ |
201 | static inline void __check_##name(void) \ | 331 | static inline void __check_##name(void) \ |
202 | { \ | 332 | { \ |
203 | BUILD_BUG_ON(!__same_type(*(p), bool) && \ | 333 | BUILD_BUG_ON(!__same_type((p), bool *) && \ |
204 | !__same_type(*(p), unsigned int) && \ | 334 | !__same_type((p), unsigned int *) && \ |
205 | !__same_type(*(p), int)); \ | 335 | !__same_type((p), int *)); \ |
206 | } | 336 | } |
207 | 337 | ||
208 | extern int param_set_invbool(const char *val, struct kernel_param *kp); | 338 | extern struct kernel_param_ops param_ops_invbool; |
209 | extern int param_get_invbool(char *buffer, struct kernel_param *kp); | 339 | extern int param_set_invbool(const char *val, const struct kernel_param *kp); |
340 | extern int param_get_invbool(char *buffer, const struct kernel_param *kp); | ||
210 | #define param_check_invbool(name, p) __param_check(name, p, bool) | 341 | #define param_check_invbool(name, p) __param_check(name, p, bool) |
211 | 342 | ||
212 | /* Comma-separated array: *nump is set to number they actually specified. */ | 343 | /** |
344 | * module_param_array - a parameter which is an array of some type | ||
345 | * @name: the name of the array variable | ||
346 | * @type: the type, as per module_param() | ||
347 | * @nump: optional pointer filled in with the number written | ||
348 | * @perm: visibility in sysfs | ||
349 | * | ||
350 | * Input and output are as comma-separated values. Commas inside values | ||
351 | * don't work properly (eg. an array of charp). | ||
352 | * | ||
353 | * ARRAY_SIZE(@name) is used to determine the number of elements in the | ||
354 | * array, so the definition must be visible. | ||
355 | */ | ||
356 | #define module_param_array(name, type, nump, perm) \ | ||
357 | module_param_array_named(name, name, type, nump, perm) | ||
358 | |||
359 | /** | ||
360 | * module_param_array_named - renamed parameter which is an array of some type | ||
361 | * @name: a valid C identifier which is the parameter name | ||
362 | * @array: the name of the array variable | ||
363 | * @type: the type, as per module_param() | ||
364 | * @nump: optional pointer filled in with the number written | ||
365 | * @perm: visibility in sysfs | ||
366 | * | ||
367 | * This exposes a different name than the actual variable name. See | ||
368 | * module_param_named() for why this might be necessary. | ||
369 | */ | ||
213 | #define module_param_array_named(name, array, type, nump, perm) \ | 370 | #define module_param_array_named(name, array, type, nump, perm) \ |
214 | static const struct kparam_array __param_arr_##name \ | 371 | static const struct kparam_array __param_arr_##name \ |
215 | = { ARRAY_SIZE(array), nump, param_set_##type, param_get_##type,\ | 372 | = { ARRAY_SIZE(array), nump, ¶m_ops_##type, \ |
216 | sizeof(array[0]), array }; \ | 373 | sizeof(array[0]), array }; \ |
217 | __module_param_call(MODULE_PARAM_PREFIX, name, \ | 374 | __module_param_call(MODULE_PARAM_PREFIX, name, \ |
218 | param_array_set, param_array_get, \ | 375 | ¶m_array_ops, \ |
219 | .arr = &__param_arr_##name, \ | 376 | .arr = &__param_arr_##name, \ |
220 | __same_type(array[0], bool), perm); \ | 377 | __same_type(array[0], bool), perm); \ |
221 | __MODULE_PARM_TYPE(name, "array of " #type) | 378 | __MODULE_PARM_TYPE(name, "array of " #type) |
222 | 379 | ||
223 | #define module_param_array(name, type, nump, perm) \ | 380 | extern struct kernel_param_ops param_array_ops; |
224 | module_param_array_named(name, name, type, nump, perm) | ||
225 | |||
226 | extern int param_array_set(const char *val, struct kernel_param *kp); | ||
227 | extern int param_array_get(char *buffer, struct kernel_param *kp); | ||
228 | 381 | ||
229 | extern int param_set_copystring(const char *val, struct kernel_param *kp); | 382 | extern struct kernel_param_ops param_ops_string; |
230 | extern int param_get_string(char *buffer, struct kernel_param *kp); | 383 | extern int param_set_copystring(const char *val, const struct kernel_param *); |
384 | extern int param_get_string(char *buffer, const struct kernel_param *kp); | ||
231 | 385 | ||
232 | /* for exporting parameters in /sys/parameters */ | 386 | /* for exporting parameters in /sys/parameters */ |
233 | 387 | ||
@@ -235,13 +389,13 @@ struct module; | |||
235 | 389 | ||
236 | #if defined(CONFIG_SYSFS) && defined(CONFIG_MODULES) | 390 | #if defined(CONFIG_SYSFS) && defined(CONFIG_MODULES) |
237 | extern int module_param_sysfs_setup(struct module *mod, | 391 | extern int module_param_sysfs_setup(struct module *mod, |
238 | struct kernel_param *kparam, | 392 | const struct kernel_param *kparam, |
239 | unsigned int num_params); | 393 | unsigned int num_params); |
240 | 394 | ||
241 | extern void module_param_sysfs_remove(struct module *mod); | 395 | extern void module_param_sysfs_remove(struct module *mod); |
242 | #else | 396 | #else |
243 | static inline int module_param_sysfs_setup(struct module *mod, | 397 | static inline int module_param_sysfs_setup(struct module *mod, |
244 | struct kernel_param *kparam, | 398 | const struct kernel_param *kparam, |
245 | unsigned int num_params) | 399 | unsigned int num_params) |
246 | { | 400 | { |
247 | return 0; | 401 | return 0; |
diff --git a/include/linux/of_device.h b/include/linux/of_device.h index 35aa44ad9f2c..835f85ecd2de 100644 --- a/include/linux/of_device.h +++ b/include/linux/of_device.h | |||
@@ -1,20 +1,6 @@ | |||
1 | #ifndef _LINUX_OF_DEVICE_H | 1 | #ifndef _LINUX_OF_DEVICE_H |
2 | #define _LINUX_OF_DEVICE_H | 2 | #define _LINUX_OF_DEVICE_H |
3 | 3 | ||
4 | /* | ||
5 | * The of_device *was* a kind of "base class" that was a superset of | ||
6 | * struct device for use by devices attached to an OF node and probed | ||
7 | * using OF properties. However, the important bit of OF-style | ||
8 | * probing, namely the device node pointer, has been moved into the | ||
9 | * common struct device when CONFIG_OF is set to make OF-style probing | ||
10 | * available to all bus types. So now, just make of_device and | ||
11 | * platform_device equivalent so that current of_platform bus users | ||
12 | * can be transparently migrated over to using the platform bus. | ||
13 | * | ||
14 | * This line will go away once all references to of_device are removed | ||
15 | * from the kernel. | ||
16 | */ | ||
17 | #define of_device platform_device | ||
18 | #include <linux/platform_device.h> | 4 | #include <linux/platform_device.h> |
19 | #include <linux/of_platform.h> /* temporary until merge */ | 5 | #include <linux/of_platform.h> /* temporary until merge */ |
20 | 6 | ||
@@ -23,8 +9,6 @@ | |||
23 | #include <linux/of.h> | 9 | #include <linux/of.h> |
24 | #include <linux/mod_devicetable.h> | 10 | #include <linux/mod_devicetable.h> |
25 | 11 | ||
26 | #define to_of_device(d) container_of(d, struct of_device, dev) | ||
27 | |||
28 | extern const struct of_device_id *of_match_device( | 12 | extern const struct of_device_id *of_match_device( |
29 | const struct of_device_id *matches, const struct device *dev); | 13 | const struct of_device_id *matches, const struct device *dev); |
30 | extern void of_device_make_bus_id(struct device *dev); | 14 | extern void of_device_make_bus_id(struct device *dev); |
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h index 4e6d989c06df..a68716ad38ce 100644 --- a/include/linux/of_platform.h +++ b/include/linux/of_platform.h | |||
@@ -19,9 +19,17 @@ | |||
19 | #include <linux/of_device.h> | 19 | #include <linux/of_device.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | 21 | ||
22 | /* | 22 | /** |
23 | * An of_platform_driver driver is attached to a basic of_device on | 23 | * of_platform_driver - Legacy of-aware driver for platform devices. |
24 | * the "platform bus" (platform_bus_type). | 24 | * |
25 | * An of_platform_driver driver is attached to a basic platform_device on | ||
26 | * ether the "platform bus" (platform_bus_type), or the ibm ebus | ||
27 | * (ibmebus_bus_type). | ||
28 | * | ||
29 | * of_platform_driver is being phased out when used with the platform_bus_type, | ||
30 | * and regular platform_drivers should be used instead. When the transition | ||
31 | * is complete, only ibmebus will be using this structure, and the | ||
32 | * platform_driver member of this structure will be removed. | ||
25 | */ | 33 | */ |
26 | struct of_platform_driver | 34 | struct of_platform_driver |
27 | { | 35 | { |
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 78a702ce4fcb..e12cdc6d79ee 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/gfp.h> | 13 | #include <linux/gfp.h> |
14 | #include <linux/bitops.h> | 14 | #include <linux/bitops.h> |
15 | #include <linux/hardirq.h> /* for in_interrupt() */ | 15 | #include <linux/hardirq.h> /* for in_interrupt() */ |
16 | #include <linux/hugetlb_inline.h> | ||
16 | 17 | ||
17 | /* | 18 | /* |
18 | * Bits in mapping->flags. The lower __GFP_BITS_SHIFT bits are the page | 19 | * Bits in mapping->flags. The lower __GFP_BITS_SHIFT bits are the page |
@@ -281,10 +282,16 @@ static inline loff_t page_offset(struct page *page) | |||
281 | return ((loff_t)page->index) << PAGE_CACHE_SHIFT; | 282 | return ((loff_t)page->index) << PAGE_CACHE_SHIFT; |
282 | } | 283 | } |
283 | 284 | ||
285 | extern pgoff_t linear_hugepage_index(struct vm_area_struct *vma, | ||
286 | unsigned long address); | ||
287 | |||
284 | static inline pgoff_t linear_page_index(struct vm_area_struct *vma, | 288 | static inline pgoff_t linear_page_index(struct vm_area_struct *vma, |
285 | unsigned long address) | 289 | unsigned long address) |
286 | { | 290 | { |
287 | pgoff_t pgoff = (address - vma->vm_start) >> PAGE_SHIFT; | 291 | pgoff_t pgoff; |
292 | if (unlikely(is_vm_hugetlb_page(vma))) | ||
293 | return linear_hugepage_index(vma, address); | ||
294 | pgoff = (address - vma->vm_start) >> PAGE_SHIFT; | ||
288 | pgoff += vma->vm_pgoff; | 295 | pgoff += vma->vm_pgoff; |
289 | return pgoff >> (PAGE_CACHE_SHIFT - PAGE_SHIFT); | 296 | return pgoff >> (PAGE_CACHE_SHIFT - PAGE_SHIFT); |
290 | } | 297 | } |
diff --git a/include/linux/poison.h b/include/linux/poison.h index 34066ffd893d..2110a81c5e2a 100644 --- a/include/linux/poison.h +++ b/include/linux/poison.h | |||
@@ -48,15 +48,6 @@ | |||
48 | #define POISON_FREE 0x6b /* for use-after-free poisoning */ | 48 | #define POISON_FREE 0x6b /* for use-after-free poisoning */ |
49 | #define POISON_END 0xa5 /* end-byte of poisoning */ | 49 | #define POISON_END 0xa5 /* end-byte of poisoning */ |
50 | 50 | ||
51 | /********** mm/hugetlb.c **********/ | ||
52 | /* | ||
53 | * Private mappings of hugetlb pages use this poisoned value for | ||
54 | * page->mapping. The core VM should not be doing anything with this mapping | ||
55 | * but futex requires the existence of some page->mapping value even though it | ||
56 | * is unused if PAGE_MAPPING_ANON is set. | ||
57 | */ | ||
58 | #define HUGETLB_POISON ((void *)(0x00300300 + POISON_POINTER_DELTA + PAGE_MAPPING_ANON)) | ||
59 | |||
60 | /********** arch/$ARCH/mm/init.c **********/ | 51 | /********** arch/$ARCH/mm/init.c **********/ |
61 | #define POISON_FREE_INITMEM 0xcc | 52 | #define POISON_FREE_INITMEM 0xcc |
62 | 53 | ||
diff --git a/include/linux/raid/pq.h b/include/linux/raid/pq.h index 1cbbd2c11aa9..2b59cc824395 100644 --- a/include/linux/raid/pq.h +++ b/include/linux/raid/pq.h | |||
@@ -62,7 +62,9 @@ extern const char raid6_empty_zero_page[PAGE_SIZE]; | |||
62 | #define disable_kernel_altivec() | 62 | #define disable_kernel_altivec() |
63 | 63 | ||
64 | #define EXPORT_SYMBOL(sym) | 64 | #define EXPORT_SYMBOL(sym) |
65 | #define EXPORT_SYMBOL_GPL(sym) | ||
65 | #define MODULE_LICENSE(licence) | 66 | #define MODULE_LICENSE(licence) |
67 | #define MODULE_DESCRIPTION(desc) | ||
66 | #define subsys_initcall(x) | 68 | #define subsys_initcall(x) |
67 | #define module_exit(x) | 69 | #define module_exit(x) |
68 | #endif /* __KERNEL__ */ | 70 | #endif /* __KERNEL__ */ |
diff --git a/include/linux/regulator/ab8500.h b/include/linux/regulator/ab8500.h new file mode 100644 index 000000000000..f509877c2ed4 --- /dev/null +++ b/include/linux/regulator/ab8500.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License v2 | ||
5 | * | ||
6 | * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #ifndef __LINUX_MFD_AB8500_REGULATOR_H | ||
11 | #define __LINUX_MFD_AB8500_REGULATOR_H | ||
12 | |||
13 | /* AB8500 regulators */ | ||
14 | #define AB8500_LDO_AUX1 0 | ||
15 | #define AB8500_LDO_AUX2 1 | ||
16 | #define AB8500_LDO_AUX3 2 | ||
17 | #define AB8500_LDO_INTCORE 3 | ||
18 | #define AB8500_LDO_TVOUT 4 | ||
19 | #define AB8500_LDO_AUDIO 5 | ||
20 | #define AB8500_LDO_ANAMIC1 6 | ||
21 | #define AB8500_LDO_ANAMIC2 7 | ||
22 | #define AB8500_LDO_DMIC 8 | ||
23 | #define AB8500_LDO_ANA 9 | ||
24 | |||
25 | #endif | ||
diff --git a/include/linux/rmap.h b/include/linux/rmap.h index d6661de56f30..31b2fd75dcba 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h | |||
@@ -168,6 +168,11 @@ void page_add_new_anon_rmap(struct page *, struct vm_area_struct *, unsigned lon | |||
168 | void page_add_file_rmap(struct page *); | 168 | void page_add_file_rmap(struct page *); |
169 | void page_remove_rmap(struct page *); | 169 | void page_remove_rmap(struct page *); |
170 | 170 | ||
171 | void hugepage_add_anon_rmap(struct page *, struct vm_area_struct *, | ||
172 | unsigned long); | ||
173 | void hugepage_add_new_anon_rmap(struct page *, struct vm_area_struct *, | ||
174 | unsigned long); | ||
175 | |||
171 | static inline void page_dup_rmap(struct page *page) | 176 | static inline void page_dup_rmap(struct page *page) |
172 | { | 177 | { |
173 | atomic_inc(&page->_mapcount); | 178 | atomic_inc(&page->_mapcount); |
diff --git a/include/linux/s3c_adc_battery.h b/include/linux/s3c_adc_battery.h new file mode 100644 index 000000000000..dbce22faa660 --- /dev/null +++ b/include/linux/s3c_adc_battery.h | |||
@@ -0,0 +1,36 @@ | |||
1 | #ifndef _S3C_ADC_BATTERY_H | ||
2 | #define _S3C_ADC_BATTERY_H | ||
3 | |||
4 | struct s3c_adc_bat_thresh { | ||
5 | int volt; /* mV */ | ||
6 | int cur; /* mA */ | ||
7 | int level; /* percent */ | ||
8 | }; | ||
9 | |||
10 | struct s3c_adc_bat_pdata { | ||
11 | int (*init)(void); | ||
12 | void (*exit)(void); | ||
13 | void (*enable_charger)(void); | ||
14 | void (*disable_charger)(void); | ||
15 | |||
16 | int gpio_charge_finished; | ||
17 | |||
18 | const struct s3c_adc_bat_thresh *lut_noac; | ||
19 | unsigned int lut_noac_cnt; | ||
20 | const struct s3c_adc_bat_thresh *lut_acin; | ||
21 | unsigned int lut_acin_cnt; | ||
22 | |||
23 | const unsigned int volt_channel; | ||
24 | const unsigned int current_channel; | ||
25 | const unsigned int backup_volt_channel; | ||
26 | |||
27 | const unsigned int volt_mult; | ||
28 | const unsigned int current_mult; | ||
29 | const unsigned int backup_volt_mult; | ||
30 | const unsigned int internal_impedance; | ||
31 | |||
32 | const unsigned int backup_volt_max; | ||
33 | const unsigned int backup_volt_min; | ||
34 | }; | ||
35 | |||
36 | #endif | ||
diff --git a/include/linux/time.h b/include/linux/time.h index cb34e35fabac..12612701b1ae 100644 --- a/include/linux/time.h +++ b/include/linux/time.h | |||
@@ -38,7 +38,7 @@ extern struct timezone sys_tz; | |||
38 | #define NSEC_PER_MSEC 1000000L | 38 | #define NSEC_PER_MSEC 1000000L |
39 | #define USEC_PER_SEC 1000000L | 39 | #define USEC_PER_SEC 1000000L |
40 | #define NSEC_PER_SEC 1000000000L | 40 | #define NSEC_PER_SEC 1000000000L |
41 | #define FSEC_PER_SEC 1000000000000000L | 41 | #define FSEC_PER_SEC 1000000000000000LL |
42 | 42 | ||
43 | #define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1) | 43 | #define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1) |
44 | 44 | ||
diff --git a/include/linux/vgaarb.h b/include/linux/vgaarb.h index 814f294d4cd0..6228b5b77d35 100644 --- a/include/linux/vgaarb.h +++ b/include/linux/vgaarb.h | |||
@@ -31,7 +31,6 @@ | |||
31 | #ifndef LINUX_VGA_H | 31 | #ifndef LINUX_VGA_H |
32 | #define LINUX_VGA_H | 32 | #define LINUX_VGA_H |
33 | 33 | ||
34 | #include <asm/vga.h> | ||
35 | 34 | ||
36 | /* Legacy VGA regions */ | 35 | /* Legacy VGA regions */ |
37 | #define VGA_RSRC_NONE 0x00 | 36 | #define VGA_RSRC_NONE 0x00 |
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index de05e96e0a70..01c2145118dc 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h | |||
@@ -7,6 +7,8 @@ | |||
7 | 7 | ||
8 | struct vm_area_struct; /* vma defining user mapping in mm_types.h */ | 8 | struct vm_area_struct; /* vma defining user mapping in mm_types.h */ |
9 | 9 | ||
10 | extern bool vmap_lazy_unmap; | ||
11 | |||
10 | /* bits in flags of vmalloc's vm_struct below */ | 12 | /* bits in flags of vmalloc's vm_struct below */ |
11 | #define VM_IOREMAP 0x00000001 /* ioremap() and friends */ | 13 | #define VM_IOREMAP 0x00000001 /* ioremap() and friends */ |
12 | #define VM_ALLOC 0x00000002 /* vmalloc() */ | 14 | #define VM_ALLOC 0x00000002 /* vmalloc() */ |
diff --git a/include/linux/writeback.h b/include/linux/writeback.h index c24eca71e80c..72a5d647a5f2 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h | |||
@@ -124,8 +124,9 @@ struct ctl_table; | |||
124 | int dirty_writeback_centisecs_handler(struct ctl_table *, int, | 124 | int dirty_writeback_centisecs_handler(struct ctl_table *, int, |
125 | void __user *, size_t *, loff_t *); | 125 | void __user *, size_t *, loff_t *); |
126 | 126 | ||
127 | void get_dirty_limits(unsigned long *pbackground, unsigned long *pdirty, | 127 | void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty); |
128 | unsigned long *pbdi_dirty, struct backing_dev_info *bdi); | 128 | unsigned long bdi_dirty_limit(struct backing_dev_info *bdi, |
129 | unsigned long dirty); | ||
129 | 130 | ||
130 | void page_writeback_init(void); | 131 | void page_writeback_init(void); |
131 | void balance_dirty_pages_ratelimited_nr(struct address_space *mapping, | 132 | void balance_dirty_pages_ratelimited_nr(struct address_space *mapping, |
diff --git a/include/xen/interface/memory.h b/include/xen/interface/memory.h index af36ead16817..d3938d3e71f8 100644 --- a/include/xen/interface/memory.h +++ b/include/xen/interface/memory.h | |||
@@ -9,6 +9,8 @@ | |||
9 | #ifndef __XEN_PUBLIC_MEMORY_H__ | 9 | #ifndef __XEN_PUBLIC_MEMORY_H__ |
10 | #define __XEN_PUBLIC_MEMORY_H__ | 10 | #define __XEN_PUBLIC_MEMORY_H__ |
11 | 11 | ||
12 | #include <linux/spinlock.h> | ||
13 | |||
12 | /* | 14 | /* |
13 | * Increase or decrease the specified domain's memory reservation. Returns a | 15 | * Increase or decrease the specified domain's memory reservation. Returns a |
14 | * -ve errcode on failure, or the # extents successfully allocated or freed. | 16 | * -ve errcode on failure, or the # extents successfully allocated or freed. |
@@ -53,6 +55,48 @@ struct xen_memory_reservation { | |||
53 | DEFINE_GUEST_HANDLE_STRUCT(xen_memory_reservation); | 55 | DEFINE_GUEST_HANDLE_STRUCT(xen_memory_reservation); |
54 | 56 | ||
55 | /* | 57 | /* |
58 | * An atomic exchange of memory pages. If return code is zero then | ||
59 | * @out.extent_list provides GMFNs of the newly-allocated memory. | ||
60 | * Returns zero on complete success, otherwise a negative error code. | ||
61 | * On complete success then always @nr_exchanged == @in.nr_extents. | ||
62 | * On partial success @nr_exchanged indicates how much work was done. | ||
63 | */ | ||
64 | #define XENMEM_exchange 11 | ||
65 | struct xen_memory_exchange { | ||
66 | /* | ||
67 | * [IN] Details of memory extents to be exchanged (GMFN bases). | ||
68 | * Note that @in.address_bits is ignored and unused. | ||
69 | */ | ||
70 | struct xen_memory_reservation in; | ||
71 | |||
72 | /* | ||
73 | * [IN/OUT] Details of new memory extents. | ||
74 | * We require that: | ||
75 | * 1. @in.domid == @out.domid | ||
76 | * 2. @in.nr_extents << @in.extent_order == | ||
77 | * @out.nr_extents << @out.extent_order | ||
78 | * 3. @in.extent_start and @out.extent_start lists must not overlap | ||
79 | * 4. @out.extent_start lists GPFN bases to be populated | ||
80 | * 5. @out.extent_start is overwritten with allocated GMFN bases | ||
81 | */ | ||
82 | struct xen_memory_reservation out; | ||
83 | |||
84 | /* | ||
85 | * [OUT] Number of input extents that were successfully exchanged: | ||
86 | * 1. The first @nr_exchanged input extents were successfully | ||
87 | * deallocated. | ||
88 | * 2. The corresponding first entries in the output extent list correctly | ||
89 | * indicate the GMFNs that were successfully exchanged. | ||
90 | * 3. All other input and output extents are untouched. | ||
91 | * 4. If not all input exents are exchanged then the return code of this | ||
92 | * command will be non-zero. | ||
93 | * 5. THIS FIELD MUST BE INITIALISED TO ZERO BY THE CALLER! | ||
94 | */ | ||
95 | unsigned long nr_exchanged; | ||
96 | }; | ||
97 | |||
98 | DEFINE_GUEST_HANDLE_STRUCT(xen_memory_exchange); | ||
99 | /* | ||
56 | * Returns the maximum machine frame number of mapped RAM in this system. | 100 | * Returns the maximum machine frame number of mapped RAM in this system. |
57 | * This command always succeeds (it never returns an error code). | 101 | * This command always succeeds (it never returns an error code). |
58 | * arg == NULL. | 102 | * arg == NULL. |
@@ -142,4 +186,10 @@ struct xen_translate_gpfn_list { | |||
142 | }; | 186 | }; |
143 | DEFINE_GUEST_HANDLE_STRUCT(xen_translate_gpfn_list); | 187 | DEFINE_GUEST_HANDLE_STRUCT(xen_translate_gpfn_list); |
144 | 188 | ||
189 | |||
190 | /* | ||
191 | * Prevent the balloon driver from changing the memory reservation | ||
192 | * during a driver critical region. | ||
193 | */ | ||
194 | extern spinlock_t xen_reservation_lock; | ||
145 | #endif /* __XEN_PUBLIC_MEMORY_H__ */ | 195 | #endif /* __XEN_PUBLIC_MEMORY_H__ */ |
diff --git a/include/xen/swiotlb-xen.h b/include/xen/swiotlb-xen.h new file mode 100644 index 000000000000..2ea2fdc79c16 --- /dev/null +++ b/include/xen/swiotlb-xen.h | |||
@@ -0,0 +1,65 @@ | |||
1 | #ifndef __LINUX_SWIOTLB_XEN_H | ||
2 | #define __LINUX_SWIOTLB_XEN_H | ||
3 | |||
4 | #include <linux/swiotlb.h> | ||
5 | |||
6 | extern void xen_swiotlb_init(int verbose); | ||
7 | |||
8 | extern void | ||
9 | *xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, | ||
10 | dma_addr_t *dma_handle, gfp_t flags); | ||
11 | |||
12 | extern void | ||
13 | xen_swiotlb_free_coherent(struct device *hwdev, size_t size, | ||
14 | void *vaddr, dma_addr_t dma_handle); | ||
15 | |||
16 | extern dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page, | ||
17 | unsigned long offset, size_t size, | ||
18 | enum dma_data_direction dir, | ||
19 | struct dma_attrs *attrs); | ||
20 | |||
21 | extern void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr, | ||
22 | size_t size, enum dma_data_direction dir, | ||
23 | struct dma_attrs *attrs); | ||
24 | /* | ||
25 | extern int | ||
26 | xen_swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nents, | ||
27 | enum dma_data_direction dir); | ||
28 | |||
29 | extern void | ||
30 | xen_swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents, | ||
31 | enum dma_data_direction dir); | ||
32 | */ | ||
33 | extern int | ||
34 | xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, | ||
35 | int nelems, enum dma_data_direction dir, | ||
36 | struct dma_attrs *attrs); | ||
37 | |||
38 | extern void | ||
39 | xen_swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl, | ||
40 | int nelems, enum dma_data_direction dir, | ||
41 | struct dma_attrs *attrs); | ||
42 | |||
43 | extern void | ||
44 | xen_swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr, | ||
45 | size_t size, enum dma_data_direction dir); | ||
46 | |||
47 | extern void | ||
48 | xen_swiotlb_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg, | ||
49 | int nelems, enum dma_data_direction dir); | ||
50 | |||
51 | extern void | ||
52 | xen_swiotlb_sync_single_for_device(struct device *hwdev, dma_addr_t dev_addr, | ||
53 | size_t size, enum dma_data_direction dir); | ||
54 | |||
55 | extern void | ||
56 | xen_swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg, | ||
57 | int nelems, enum dma_data_direction dir); | ||
58 | |||
59 | extern int | ||
60 | xen_swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr); | ||
61 | |||
62 | extern int | ||
63 | xen_swiotlb_dma_supported(struct device *hwdev, u64 mask); | ||
64 | |||
65 | #endif /* __LINUX_SWIOTLB_XEN_H */ | ||
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h index 46bc81ef74c6..351f4051f6d8 100644 --- a/include/xen/xen-ops.h +++ b/include/xen/xen-ops.h | |||
@@ -17,4 +17,10 @@ void xen_arch_resume(void); | |||
17 | 17 | ||
18 | int xen_setup_shutdown_event(void); | 18 | int xen_setup_shutdown_event(void); |
19 | 19 | ||
20 | extern unsigned long *xen_contiguous_bitmap; | ||
21 | int xen_create_contiguous_region(unsigned long vstart, unsigned int order, | ||
22 | unsigned int address_bits); | ||
23 | |||
24 | void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order); | ||
25 | |||
20 | #endif /* INCLUDE_XEN_OPS_H */ | 26 | #endif /* INCLUDE_XEN_OPS_H */ |
diff --git a/init/main.c b/init/main.c index 86cbfd085b01..22d61cb06f98 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -201,11 +201,11 @@ static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, }; | |||
201 | char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, }; | 201 | char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, }; |
202 | static const char *panic_later, *panic_param; | 202 | static const char *panic_later, *panic_param; |
203 | 203 | ||
204 | extern struct obs_kernel_param __setup_start[], __setup_end[]; | 204 | extern const struct obs_kernel_param __setup_start[], __setup_end[]; |
205 | 205 | ||
206 | static int __init obsolete_checksetup(char *line) | 206 | static int __init obsolete_checksetup(char *line) |
207 | { | 207 | { |
208 | struct obs_kernel_param *p; | 208 | const struct obs_kernel_param *p; |
209 | int had_early_param = 0; | 209 | int had_early_param = 0; |
210 | 210 | ||
211 | p = __setup_start; | 211 | p = __setup_start; |
@@ -458,7 +458,7 @@ static noinline void __init_refok rest_init(void) | |||
458 | /* Check for early params. */ | 458 | /* Check for early params. */ |
459 | static int __init do_early_param(char *param, char *val) | 459 | static int __init do_early_param(char *param, char *val) |
460 | { | 460 | { |
461 | struct obs_kernel_param *p; | 461 | const struct obs_kernel_param *p; |
462 | 462 | ||
463 | for (p = __setup_start; p < __setup_end; p++) { | 463 | for (p = __setup_start; p < __setup_end; p++) { |
464 | if ((p->early && strcmp(param, p->str) == 0) || | 464 | if ((p->early && strcmp(param, p->str) == 0) || |
@@ -536,7 +536,7 @@ static void __init mm_init(void) | |||
536 | asmlinkage void __init start_kernel(void) | 536 | asmlinkage void __init start_kernel(void) |
537 | { | 537 | { |
538 | char * command_line; | 538 | char * command_line; |
539 | extern struct kernel_param __start___param[], __stop___param[]; | 539 | extern const struct kernel_param __start___param[], __stop___param[]; |
540 | 540 | ||
541 | smp_setup_processor_id(); | 541 | smp_setup_processor_id(); |
542 | 542 | ||
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 6bf2306be7d6..f0c9b2e7542d 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c | |||
@@ -526,8 +526,8 @@ static int audit_watch_handle_event(struct fsnotify_group *group, | |||
526 | BUG_ON(group != audit_watch_group); | 526 | BUG_ON(group != audit_watch_group); |
527 | 527 | ||
528 | switch (event->data_type) { | 528 | switch (event->data_type) { |
529 | case (FSNOTIFY_EVENT_FILE): | 529 | case (FSNOTIFY_EVENT_PATH): |
530 | inode = event->file->f_path.dentry->d_inode; | 530 | inode = event->path.dentry->d_inode; |
531 | break; | 531 | break; |
532 | case (FSNOTIFY_EVENT_INODE): | 532 | case (FSNOTIFY_EVENT_INODE): |
533 | inode = event->inode; | 533 | inode = event->inode; |
diff --git a/kernel/cred.c b/kernel/cred.c index 60bc8b1e32e6..9a3e22641fe7 100644 --- a/kernel/cred.c +++ b/kernel/cred.c | |||
@@ -22,10 +22,6 @@ | |||
22 | #define kdebug(FMT, ...) \ | 22 | #define kdebug(FMT, ...) \ |
23 | printk("[%-5.5s%5u] "FMT"\n", current->comm, current->pid ,##__VA_ARGS__) | 23 | printk("[%-5.5s%5u] "FMT"\n", current->comm, current->pid ,##__VA_ARGS__) |
24 | #else | 24 | #else |
25 | static inline __attribute__((format(printf, 1, 2))) | ||
26 | void no_printk(const char *fmt, ...) | ||
27 | { | ||
28 | } | ||
29 | #define kdebug(FMT, ...) \ | 25 | #define kdebug(FMT, ...) \ |
30 | no_printk("[%-5.5s%5u] "FMT"\n", current->comm, current->pid ,##__VA_ARGS__) | 26 | no_printk("[%-5.5s%5u] "FMT"\n", current->comm, current->pid ,##__VA_ARGS__) |
31 | #endif | 27 | #endif |
diff --git a/kernel/kfifo.c b/kernel/kfifo.c index 02192dd905cc..4502604ecadf 100644 --- a/kernel/kfifo.c +++ b/kernel/kfifo.c | |||
@@ -10,7 +10,7 @@ | |||
10 | * | 10 | * |
11 | * This program is distributed in the hope that it will be useful, | 11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. | 14 | * GNU General Public License for more details. |
15 | * | 15 | * |
16 | * You should have received a copy of the GNU General Public License | 16 | * You should have received a copy of the GNU General Public License |
@@ -333,17 +333,16 @@ static int setup_sgl_buf(struct scatterlist *sgl, void *buf, | |||
333 | buf += PAGE_SIZE; | 333 | buf += PAGE_SIZE; |
334 | npage = virt_to_page(buf); | 334 | npage = virt_to_page(buf); |
335 | if (page_to_phys(page) != page_to_phys(npage) - l) { | 335 | if (page_to_phys(page) != page_to_phys(npage) - l) { |
336 | sgl->page_link = 0; | 336 | sg_set_page(sgl, page, l - off, off); |
337 | sg_set_page(sgl++, page, l - off, off); | 337 | sgl = sg_next(sgl); |
338 | if (++n == nents) | 338 | if (++n == nents || sgl == NULL) |
339 | return n; | 339 | return n; |
340 | page = npage; | 340 | page = npage; |
341 | len -= l - off; | 341 | len -= l - off; |
342 | l = off = 0; | 342 | l = off = 0; |
343 | } | 343 | } |
344 | } | 344 | } |
345 | sgl->page_link = 0; | 345 | sg_set_page(sgl, page, len, off); |
346 | sg_set_page(sgl++, page, len, off); | ||
347 | return n + 1; | 346 | return n + 1; |
348 | } | 347 | } |
349 | 348 | ||
@@ -363,7 +362,7 @@ static unsigned int setup_sgl(struct __kfifo *fifo, struct scatterlist *sgl, | |||
363 | } | 362 | } |
364 | l = min(len, size - off); | 363 | l = min(len, size - off); |
365 | 364 | ||
366 | n = setup_sgl_buf(sgl, fifo->data + off, nents, l); | 365 | n = setup_sgl_buf(sgl, fifo->data + off, nents, l); |
367 | n += setup_sgl_buf(sgl + n, fifo->data, nents - n, len - l); | 366 | n += setup_sgl_buf(sgl + n, fifo->data, nents - n, len - l); |
368 | 367 | ||
369 | if (n) | 368 | if (n) |
diff --git a/kernel/params.c b/kernel/params.c index 0b30ecd53a52..08107d181758 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
@@ -31,6 +31,42 @@ | |||
31 | #define DEBUGP(fmt, a...) | 31 | #define DEBUGP(fmt, a...) |
32 | #endif | 32 | #endif |
33 | 33 | ||
34 | /* Protects all parameters, and incidentally kmalloced_param list. */ | ||
35 | static DEFINE_MUTEX(param_lock); | ||
36 | |||
37 | /* This just allows us to keep track of which parameters are kmalloced. */ | ||
38 | struct kmalloced_param { | ||
39 | struct list_head list; | ||
40 | char val[]; | ||
41 | }; | ||
42 | static LIST_HEAD(kmalloced_params); | ||
43 | |||
44 | static void *kmalloc_parameter(unsigned int size) | ||
45 | { | ||
46 | struct kmalloced_param *p; | ||
47 | |||
48 | p = kmalloc(sizeof(*p) + size, GFP_KERNEL); | ||
49 | if (!p) | ||
50 | return NULL; | ||
51 | |||
52 | list_add(&p->list, &kmalloced_params); | ||
53 | return p->val; | ||
54 | } | ||
55 | |||
56 | /* Does nothing if parameter wasn't kmalloced above. */ | ||
57 | static void maybe_kfree_parameter(void *param) | ||
58 | { | ||
59 | struct kmalloced_param *p; | ||
60 | |||
61 | list_for_each_entry(p, &kmalloced_params, list) { | ||
62 | if (p->val == param) { | ||
63 | list_del(&p->list); | ||
64 | kfree(p); | ||
65 | break; | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | |||
34 | static inline char dash2underscore(char c) | 70 | static inline char dash2underscore(char c) |
35 | { | 71 | { |
36 | if (c == '-') | 72 | if (c == '-') |
@@ -49,18 +85,25 @@ static inline int parameq(const char *input, const char *paramname) | |||
49 | 85 | ||
50 | static int parse_one(char *param, | 86 | static int parse_one(char *param, |
51 | char *val, | 87 | char *val, |
52 | struct kernel_param *params, | 88 | const struct kernel_param *params, |
53 | unsigned num_params, | 89 | unsigned num_params, |
54 | int (*handle_unknown)(char *param, char *val)) | 90 | int (*handle_unknown)(char *param, char *val)) |
55 | { | 91 | { |
56 | unsigned int i; | 92 | unsigned int i; |
93 | int err; | ||
57 | 94 | ||
58 | /* Find parameter */ | 95 | /* Find parameter */ |
59 | for (i = 0; i < num_params; i++) { | 96 | for (i = 0; i < num_params; i++) { |
60 | if (parameq(param, params[i].name)) { | 97 | if (parameq(param, params[i].name)) { |
98 | /* Noone handled NULL, so do it here. */ | ||
99 | if (!val && params[i].ops->set != param_set_bool) | ||
100 | return -EINVAL; | ||
61 | DEBUGP("They are equal! Calling %p\n", | 101 | DEBUGP("They are equal! Calling %p\n", |
62 | params[i].set); | 102 | params[i].ops->set); |
63 | return params[i].set(val, ¶ms[i]); | 103 | mutex_lock(¶m_lock); |
104 | err = params[i].ops->set(val, ¶ms[i]); | ||
105 | mutex_unlock(¶m_lock); | ||
106 | return err; | ||
64 | } | 107 | } |
65 | } | 108 | } |
66 | 109 | ||
@@ -128,7 +171,7 @@ static char *next_arg(char *args, char **param, char **val) | |||
128 | /* Args looks like "foo=bar,bar2 baz=fuz wiz". */ | 171 | /* Args looks like "foo=bar,bar2 baz=fuz wiz". */ |
129 | int parse_args(const char *name, | 172 | int parse_args(const char *name, |
130 | char *args, | 173 | char *args, |
131 | struct kernel_param *params, | 174 | const struct kernel_param *params, |
132 | unsigned num, | 175 | unsigned num, |
133 | int (*unknown)(char *param, char *val)) | 176 | int (*unknown)(char *param, char *val)) |
134 | { | 177 | { |
@@ -176,22 +219,29 @@ int parse_args(const char *name, | |||
176 | 219 | ||
177 | /* Lazy bastard, eh? */ | 220 | /* Lazy bastard, eh? */ |
178 | #define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \ | 221 | #define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \ |
179 | int param_set_##name(const char *val, struct kernel_param *kp) \ | 222 | int param_set_##name(const char *val, const struct kernel_param *kp) \ |
180 | { \ | 223 | { \ |
181 | tmptype l; \ | 224 | tmptype l; \ |
182 | int ret; \ | 225 | int ret; \ |
183 | \ | 226 | \ |
184 | if (!val) return -EINVAL; \ | ||
185 | ret = strtolfn(val, 0, &l); \ | 227 | ret = strtolfn(val, 0, &l); \ |
186 | if (ret == -EINVAL || ((type)l != l)) \ | 228 | if (ret == -EINVAL || ((type)l != l)) \ |
187 | return -EINVAL; \ | 229 | return -EINVAL; \ |
188 | *((type *)kp->arg) = l; \ | 230 | *((type *)kp->arg) = l; \ |
189 | return 0; \ | 231 | return 0; \ |
190 | } \ | 232 | } \ |
191 | int param_get_##name(char *buffer, struct kernel_param *kp) \ | 233 | int param_get_##name(char *buffer, const struct kernel_param *kp) \ |
192 | { \ | 234 | { \ |
193 | return sprintf(buffer, format, *((type *)kp->arg)); \ | 235 | return sprintf(buffer, format, *((type *)kp->arg)); \ |
194 | } | 236 | } \ |
237 | struct kernel_param_ops param_ops_##name = { \ | ||
238 | .set = param_set_##name, \ | ||
239 | .get = param_get_##name, \ | ||
240 | }; \ | ||
241 | EXPORT_SYMBOL(param_set_##name); \ | ||
242 | EXPORT_SYMBOL(param_get_##name); \ | ||
243 | EXPORT_SYMBOL(param_ops_##name) | ||
244 | |||
195 | 245 | ||
196 | STANDARD_PARAM_DEF(byte, unsigned char, "%c", unsigned long, strict_strtoul); | 246 | STANDARD_PARAM_DEF(byte, unsigned char, "%c", unsigned long, strict_strtoul); |
197 | STANDARD_PARAM_DEF(short, short, "%hi", long, strict_strtol); | 247 | STANDARD_PARAM_DEF(short, short, "%hi", long, strict_strtol); |
@@ -201,39 +251,50 @@ STANDARD_PARAM_DEF(uint, unsigned int, "%u", unsigned long, strict_strtoul); | |||
201 | STANDARD_PARAM_DEF(long, long, "%li", long, strict_strtol); | 251 | STANDARD_PARAM_DEF(long, long, "%li", long, strict_strtol); |
202 | STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, strict_strtoul); | 252 | STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, strict_strtoul); |
203 | 253 | ||
204 | int param_set_charp(const char *val, struct kernel_param *kp) | 254 | int param_set_charp(const char *val, const struct kernel_param *kp) |
205 | { | 255 | { |
206 | if (!val) { | ||
207 | printk(KERN_ERR "%s: string parameter expected\n", | ||
208 | kp->name); | ||
209 | return -EINVAL; | ||
210 | } | ||
211 | |||
212 | if (strlen(val) > 1024) { | 256 | if (strlen(val) > 1024) { |
213 | printk(KERN_ERR "%s: string parameter too long\n", | 257 | printk(KERN_ERR "%s: string parameter too long\n", |
214 | kp->name); | 258 | kp->name); |
215 | return -ENOSPC; | 259 | return -ENOSPC; |
216 | } | 260 | } |
217 | 261 | ||
218 | /* This is a hack. We can't need to strdup in early boot, and we | 262 | maybe_kfree_parameter(*(char **)kp->arg); |
263 | |||
264 | /* This is a hack. We can't kmalloc in early boot, and we | ||
219 | * don't need to; this mangled commandline is preserved. */ | 265 | * don't need to; this mangled commandline is preserved. */ |
220 | if (slab_is_available()) { | 266 | if (slab_is_available()) { |
221 | *(char **)kp->arg = kstrdup(val, GFP_KERNEL); | 267 | *(char **)kp->arg = kmalloc_parameter(strlen(val)+1); |
222 | if (!*(char **)kp->arg) | 268 | if (!*(char **)kp->arg) |
223 | return -ENOMEM; | 269 | return -ENOMEM; |
270 | strcpy(*(char **)kp->arg, val); | ||
224 | } else | 271 | } else |
225 | *(const char **)kp->arg = val; | 272 | *(const char **)kp->arg = val; |
226 | 273 | ||
227 | return 0; | 274 | return 0; |
228 | } | 275 | } |
276 | EXPORT_SYMBOL(param_set_charp); | ||
229 | 277 | ||
230 | int param_get_charp(char *buffer, struct kernel_param *kp) | 278 | int param_get_charp(char *buffer, const struct kernel_param *kp) |
231 | { | 279 | { |
232 | return sprintf(buffer, "%s", *((char **)kp->arg)); | 280 | return sprintf(buffer, "%s", *((char **)kp->arg)); |
233 | } | 281 | } |
282 | EXPORT_SYMBOL(param_get_charp); | ||
283 | |||
284 | static void param_free_charp(void *arg) | ||
285 | { | ||
286 | maybe_kfree_parameter(*((char **)arg)); | ||
287 | } | ||
288 | |||
289 | struct kernel_param_ops param_ops_charp = { | ||
290 | .set = param_set_charp, | ||
291 | .get = param_get_charp, | ||
292 | .free = param_free_charp, | ||
293 | }; | ||
294 | EXPORT_SYMBOL(param_ops_charp); | ||
234 | 295 | ||
235 | /* Actually could be a bool or an int, for historical reasons. */ | 296 | /* Actually could be a bool or an int, for historical reasons. */ |
236 | int param_set_bool(const char *val, struct kernel_param *kp) | 297 | int param_set_bool(const char *val, const struct kernel_param *kp) |
237 | { | 298 | { |
238 | bool v; | 299 | bool v; |
239 | 300 | ||
@@ -258,8 +319,9 @@ int param_set_bool(const char *val, struct kernel_param *kp) | |||
258 | *(int *)kp->arg = v; | 319 | *(int *)kp->arg = v; |
259 | return 0; | 320 | return 0; |
260 | } | 321 | } |
322 | EXPORT_SYMBOL(param_set_bool); | ||
261 | 323 | ||
262 | int param_get_bool(char *buffer, struct kernel_param *kp) | 324 | int param_get_bool(char *buffer, const struct kernel_param *kp) |
263 | { | 325 | { |
264 | bool val; | 326 | bool val; |
265 | if (kp->flags & KPARAM_ISBOOL) | 327 | if (kp->flags & KPARAM_ISBOOL) |
@@ -270,9 +332,16 @@ int param_get_bool(char *buffer, struct kernel_param *kp) | |||
270 | /* Y and N chosen as being relatively non-coder friendly */ | 332 | /* Y and N chosen as being relatively non-coder friendly */ |
271 | return sprintf(buffer, "%c", val ? 'Y' : 'N'); | 333 | return sprintf(buffer, "%c", val ? 'Y' : 'N'); |
272 | } | 334 | } |
335 | EXPORT_SYMBOL(param_get_bool); | ||
336 | |||
337 | struct kernel_param_ops param_ops_bool = { | ||
338 | .set = param_set_bool, | ||
339 | .get = param_get_bool, | ||
340 | }; | ||
341 | EXPORT_SYMBOL(param_ops_bool); | ||
273 | 342 | ||
274 | /* This one must be bool. */ | 343 | /* This one must be bool. */ |
275 | int param_set_invbool(const char *val, struct kernel_param *kp) | 344 | int param_set_invbool(const char *val, const struct kernel_param *kp) |
276 | { | 345 | { |
277 | int ret; | 346 | int ret; |
278 | bool boolval; | 347 | bool boolval; |
@@ -285,18 +354,26 @@ int param_set_invbool(const char *val, struct kernel_param *kp) | |||
285 | *(bool *)kp->arg = !boolval; | 354 | *(bool *)kp->arg = !boolval; |
286 | return ret; | 355 | return ret; |
287 | } | 356 | } |
357 | EXPORT_SYMBOL(param_set_invbool); | ||
288 | 358 | ||
289 | int param_get_invbool(char *buffer, struct kernel_param *kp) | 359 | int param_get_invbool(char *buffer, const struct kernel_param *kp) |
290 | { | 360 | { |
291 | return sprintf(buffer, "%c", (*(bool *)kp->arg) ? 'N' : 'Y'); | 361 | return sprintf(buffer, "%c", (*(bool *)kp->arg) ? 'N' : 'Y'); |
292 | } | 362 | } |
363 | EXPORT_SYMBOL(param_get_invbool); | ||
364 | |||
365 | struct kernel_param_ops param_ops_invbool = { | ||
366 | .set = param_set_invbool, | ||
367 | .get = param_get_invbool, | ||
368 | }; | ||
369 | EXPORT_SYMBOL(param_ops_invbool); | ||
293 | 370 | ||
294 | /* We break the rule and mangle the string. */ | 371 | /* We break the rule and mangle the string. */ |
295 | static int param_array(const char *name, | 372 | static int param_array(const char *name, |
296 | const char *val, | 373 | const char *val, |
297 | unsigned int min, unsigned int max, | 374 | unsigned int min, unsigned int max, |
298 | void *elem, int elemsize, | 375 | void *elem, int elemsize, |
299 | int (*set)(const char *, struct kernel_param *kp), | 376 | int (*set)(const char *, const struct kernel_param *kp), |
300 | u16 flags, | 377 | u16 flags, |
301 | unsigned int *num) | 378 | unsigned int *num) |
302 | { | 379 | { |
@@ -309,12 +386,6 @@ static int param_array(const char *name, | |||
309 | kp.arg = elem; | 386 | kp.arg = elem; |
310 | kp.flags = flags; | 387 | kp.flags = flags; |
311 | 388 | ||
312 | /* No equals sign? */ | ||
313 | if (!val) { | ||
314 | printk(KERN_ERR "%s: expects arguments\n", name); | ||
315 | return -EINVAL; | ||
316 | } | ||
317 | |||
318 | *num = 0; | 389 | *num = 0; |
319 | /* We expect a comma-separated list of values. */ | 390 | /* We expect a comma-separated list of values. */ |
320 | do { | 391 | do { |
@@ -330,6 +401,7 @@ static int param_array(const char *name, | |||
330 | /* nul-terminate and parse */ | 401 | /* nul-terminate and parse */ |
331 | save = val[len]; | 402 | save = val[len]; |
332 | ((char *)val)[len] = '\0'; | 403 | ((char *)val)[len] = '\0'; |
404 | BUG_ON(!mutex_is_locked(¶m_lock)); | ||
333 | ret = set(val, &kp); | 405 | ret = set(val, &kp); |
334 | 406 | ||
335 | if (ret != 0) | 407 | if (ret != 0) |
@@ -347,17 +419,17 @@ static int param_array(const char *name, | |||
347 | return 0; | 419 | return 0; |
348 | } | 420 | } |
349 | 421 | ||
350 | int param_array_set(const char *val, struct kernel_param *kp) | 422 | static int param_array_set(const char *val, const struct kernel_param *kp) |
351 | { | 423 | { |
352 | const struct kparam_array *arr = kp->arr; | 424 | const struct kparam_array *arr = kp->arr; |
353 | unsigned int temp_num; | 425 | unsigned int temp_num; |
354 | 426 | ||
355 | return param_array(kp->name, val, 1, arr->max, arr->elem, | 427 | return param_array(kp->name, val, 1, arr->max, arr->elem, |
356 | arr->elemsize, arr->set, kp->flags, | 428 | arr->elemsize, arr->ops->set, kp->flags, |
357 | arr->num ?: &temp_num); | 429 | arr->num ?: &temp_num); |
358 | } | 430 | } |
359 | 431 | ||
360 | int param_array_get(char *buffer, struct kernel_param *kp) | 432 | static int param_array_get(char *buffer, const struct kernel_param *kp) |
361 | { | 433 | { |
362 | int i, off, ret; | 434 | int i, off, ret; |
363 | const struct kparam_array *arr = kp->arr; | 435 | const struct kparam_array *arr = kp->arr; |
@@ -368,7 +440,8 @@ int param_array_get(char *buffer, struct kernel_param *kp) | |||
368 | if (i) | 440 | if (i) |
369 | buffer[off++] = ','; | 441 | buffer[off++] = ','; |
370 | p.arg = arr->elem + arr->elemsize * i; | 442 | p.arg = arr->elem + arr->elemsize * i; |
371 | ret = arr->get(buffer + off, &p); | 443 | BUG_ON(!mutex_is_locked(¶m_lock)); |
444 | ret = arr->ops->get(buffer + off, &p); | ||
372 | if (ret < 0) | 445 | if (ret < 0) |
373 | return ret; | 446 | return ret; |
374 | off += ret; | 447 | off += ret; |
@@ -377,14 +450,27 @@ int param_array_get(char *buffer, struct kernel_param *kp) | |||
377 | return off; | 450 | return off; |
378 | } | 451 | } |
379 | 452 | ||
380 | int param_set_copystring(const char *val, struct kernel_param *kp) | 453 | static void param_array_free(void *arg) |
454 | { | ||
455 | unsigned int i; | ||
456 | const struct kparam_array *arr = arg; | ||
457 | |||
458 | if (arr->ops->free) | ||
459 | for (i = 0; i < (arr->num ? *arr->num : arr->max); i++) | ||
460 | arr->ops->free(arr->elem + arr->elemsize * i); | ||
461 | } | ||
462 | |||
463 | struct kernel_param_ops param_array_ops = { | ||
464 | .set = param_array_set, | ||
465 | .get = param_array_get, | ||
466 | .free = param_array_free, | ||
467 | }; | ||
468 | EXPORT_SYMBOL(param_array_ops); | ||
469 | |||
470 | int param_set_copystring(const char *val, const struct kernel_param *kp) | ||
381 | { | 471 | { |
382 | const struct kparam_string *kps = kp->str; | 472 | const struct kparam_string *kps = kp->str; |
383 | 473 | ||
384 | if (!val) { | ||
385 | printk(KERN_ERR "%s: missing param set value\n", kp->name); | ||
386 | return -EINVAL; | ||
387 | } | ||
388 | if (strlen(val)+1 > kps->maxlen) { | 474 | if (strlen(val)+1 > kps->maxlen) { |
389 | printk(KERN_ERR "%s: string doesn't fit in %u chars.\n", | 475 | printk(KERN_ERR "%s: string doesn't fit in %u chars.\n", |
390 | kp->name, kps->maxlen-1); | 476 | kp->name, kps->maxlen-1); |
@@ -393,12 +479,20 @@ int param_set_copystring(const char *val, struct kernel_param *kp) | |||
393 | strcpy(kps->string, val); | 479 | strcpy(kps->string, val); |
394 | return 0; | 480 | return 0; |
395 | } | 481 | } |
482 | EXPORT_SYMBOL(param_set_copystring); | ||
396 | 483 | ||
397 | int param_get_string(char *buffer, struct kernel_param *kp) | 484 | int param_get_string(char *buffer, const struct kernel_param *kp) |
398 | { | 485 | { |
399 | const struct kparam_string *kps = kp->str; | 486 | const struct kparam_string *kps = kp->str; |
400 | return strlcpy(buffer, kps->string, kps->maxlen); | 487 | return strlcpy(buffer, kps->string, kps->maxlen); |
401 | } | 488 | } |
489 | EXPORT_SYMBOL(param_get_string); | ||
490 | |||
491 | struct kernel_param_ops param_ops_string = { | ||
492 | .set = param_set_copystring, | ||
493 | .get = param_get_string, | ||
494 | }; | ||
495 | EXPORT_SYMBOL(param_ops_string); | ||
402 | 496 | ||
403 | /* sysfs output in /sys/modules/XYZ/parameters/ */ | 497 | /* sysfs output in /sys/modules/XYZ/parameters/ */ |
404 | #define to_module_attr(n) container_of(n, struct module_attribute, attr) | 498 | #define to_module_attr(n) container_of(n, struct module_attribute, attr) |
@@ -409,7 +503,7 @@ extern struct kernel_param __start___param[], __stop___param[]; | |||
409 | struct param_attribute | 503 | struct param_attribute |
410 | { | 504 | { |
411 | struct module_attribute mattr; | 505 | struct module_attribute mattr; |
412 | struct kernel_param *param; | 506 | const struct kernel_param *param; |
413 | }; | 507 | }; |
414 | 508 | ||
415 | struct module_param_attrs | 509 | struct module_param_attrs |
@@ -428,10 +522,12 @@ static ssize_t param_attr_show(struct module_attribute *mattr, | |||
428 | int count; | 522 | int count; |
429 | struct param_attribute *attribute = to_param_attr(mattr); | 523 | struct param_attribute *attribute = to_param_attr(mattr); |
430 | 524 | ||
431 | if (!attribute->param->get) | 525 | if (!attribute->param->ops->get) |
432 | return -EPERM; | 526 | return -EPERM; |
433 | 527 | ||
434 | count = attribute->param->get(buf, attribute->param); | 528 | mutex_lock(¶m_lock); |
529 | count = attribute->param->ops->get(buf, attribute->param); | ||
530 | mutex_unlock(¶m_lock); | ||
435 | if (count > 0) { | 531 | if (count > 0) { |
436 | strcat(buf, "\n"); | 532 | strcat(buf, "\n"); |
437 | ++count; | 533 | ++count; |
@@ -447,10 +543,12 @@ static ssize_t param_attr_store(struct module_attribute *mattr, | |||
447 | int err; | 543 | int err; |
448 | struct param_attribute *attribute = to_param_attr(mattr); | 544 | struct param_attribute *attribute = to_param_attr(mattr); |
449 | 545 | ||
450 | if (!attribute->param->set) | 546 | if (!attribute->param->ops->set) |
451 | return -EPERM; | 547 | return -EPERM; |
452 | 548 | ||
453 | err = attribute->param->set(buf, attribute->param); | 549 | mutex_lock(¶m_lock); |
550 | err = attribute->param->ops->set(buf, attribute->param); | ||
551 | mutex_unlock(¶m_lock); | ||
454 | if (!err) | 552 | if (!err) |
455 | return len; | 553 | return len; |
456 | return err; | 554 | return err; |
@@ -464,6 +562,18 @@ static ssize_t param_attr_store(struct module_attribute *mattr, | |||
464 | #endif | 562 | #endif |
465 | 563 | ||
466 | #ifdef CONFIG_SYSFS | 564 | #ifdef CONFIG_SYSFS |
565 | void __kernel_param_lock(void) | ||
566 | { | ||
567 | mutex_lock(¶m_lock); | ||
568 | } | ||
569 | EXPORT_SYMBOL(__kernel_param_lock); | ||
570 | |||
571 | void __kernel_param_unlock(void) | ||
572 | { | ||
573 | mutex_unlock(¶m_lock); | ||
574 | } | ||
575 | EXPORT_SYMBOL(__kernel_param_unlock); | ||
576 | |||
467 | /* | 577 | /* |
468 | * add_sysfs_param - add a parameter to sysfs | 578 | * add_sysfs_param - add a parameter to sysfs |
469 | * @mk: struct module_kobject | 579 | * @mk: struct module_kobject |
@@ -475,7 +585,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr, | |||
475 | * if there's an error. | 585 | * if there's an error. |
476 | */ | 586 | */ |
477 | static __modinit int add_sysfs_param(struct module_kobject *mk, | 587 | static __modinit int add_sysfs_param(struct module_kobject *mk, |
478 | struct kernel_param *kp, | 588 | const struct kernel_param *kp, |
479 | const char *name) | 589 | const char *name) |
480 | { | 590 | { |
481 | struct module_param_attrs *new; | 591 | struct module_param_attrs *new; |
@@ -557,7 +667,7 @@ static void free_module_param_attrs(struct module_kobject *mk) | |||
557 | * /sys/module/[mod->name]/parameters/ | 667 | * /sys/module/[mod->name]/parameters/ |
558 | */ | 668 | */ |
559 | int module_param_sysfs_setup(struct module *mod, | 669 | int module_param_sysfs_setup(struct module *mod, |
560 | struct kernel_param *kparam, | 670 | const struct kernel_param *kparam, |
561 | unsigned int num_params) | 671 | unsigned int num_params) |
562 | { | 672 | { |
563 | int i, err; | 673 | int i, err; |
@@ -602,7 +712,11 @@ void module_param_sysfs_remove(struct module *mod) | |||
602 | 712 | ||
603 | void destroy_params(const struct kernel_param *params, unsigned num) | 713 | void destroy_params(const struct kernel_param *params, unsigned num) |
604 | { | 714 | { |
605 | /* FIXME: This should free kmalloced charp parameters. It doesn't. */ | 715 | unsigned int i; |
716 | |||
717 | for (i = 0; i < num; i++) | ||
718 | if (params[i].ops->free) | ||
719 | params[i].ops->free(params[i].arg); | ||
606 | } | 720 | } |
607 | 721 | ||
608 | static void __init kernel_add_sysfs_param(const char *name, | 722 | static void __init kernel_add_sysfs_param(const char *name, |
@@ -768,28 +882,3 @@ static int __init param_sysfs_init(void) | |||
768 | subsys_initcall(param_sysfs_init); | 882 | subsys_initcall(param_sysfs_init); |
769 | 883 | ||
770 | #endif /* CONFIG_SYSFS */ | 884 | #endif /* CONFIG_SYSFS */ |
771 | |||
772 | EXPORT_SYMBOL(param_set_byte); | ||
773 | EXPORT_SYMBOL(param_get_byte); | ||
774 | EXPORT_SYMBOL(param_set_short); | ||
775 | EXPORT_SYMBOL(param_get_short); | ||
776 | EXPORT_SYMBOL(param_set_ushort); | ||
777 | EXPORT_SYMBOL(param_get_ushort); | ||
778 | EXPORT_SYMBOL(param_set_int); | ||
779 | EXPORT_SYMBOL(param_get_int); | ||
780 | EXPORT_SYMBOL(param_set_uint); | ||
781 | EXPORT_SYMBOL(param_get_uint); | ||
782 | EXPORT_SYMBOL(param_set_long); | ||
783 | EXPORT_SYMBOL(param_get_long); | ||
784 | EXPORT_SYMBOL(param_set_ulong); | ||
785 | EXPORT_SYMBOL(param_get_ulong); | ||
786 | EXPORT_SYMBOL(param_set_charp); | ||
787 | EXPORT_SYMBOL(param_get_charp); | ||
788 | EXPORT_SYMBOL(param_set_bool); | ||
789 | EXPORT_SYMBOL(param_get_bool); | ||
790 | EXPORT_SYMBOL(param_set_invbool); | ||
791 | EXPORT_SYMBOL(param_get_invbool); | ||
792 | EXPORT_SYMBOL(param_array_set); | ||
793 | EXPORT_SYMBOL(param_array_get); | ||
794 | EXPORT_SYMBOL(param_set_copystring); | ||
795 | EXPORT_SYMBOL(param_get_string); | ||
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index e14c839e9faa..e960d824263f 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -690,6 +690,7 @@ static void timekeeping_adjust(s64 offset) | |||
690 | static cycle_t logarithmic_accumulation(cycle_t offset, int shift) | 690 | static cycle_t logarithmic_accumulation(cycle_t offset, int shift) |
691 | { | 691 | { |
692 | u64 nsecps = (u64)NSEC_PER_SEC << timekeeper.shift; | 692 | u64 nsecps = (u64)NSEC_PER_SEC << timekeeper.shift; |
693 | u64 raw_nsecs; | ||
693 | 694 | ||
694 | /* If the offset is smaller then a shifted interval, do nothing */ | 695 | /* If the offset is smaller then a shifted interval, do nothing */ |
695 | if (offset < timekeeper.cycle_interval<<shift) | 696 | if (offset < timekeeper.cycle_interval<<shift) |
@@ -706,12 +707,14 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift) | |||
706 | second_overflow(); | 707 | second_overflow(); |
707 | } | 708 | } |
708 | 709 | ||
709 | /* Accumulate into raw time */ | 710 | /* Accumulate raw time */ |
710 | raw_time.tv_nsec += timekeeper.raw_interval << shift;; | 711 | raw_nsecs = timekeeper.raw_interval << shift; |
711 | while (raw_time.tv_nsec >= NSEC_PER_SEC) { | 712 | raw_nsecs += raw_time.tv_nsec; |
712 | raw_time.tv_nsec -= NSEC_PER_SEC; | 713 | while (raw_nsecs >= NSEC_PER_SEC) { |
714 | raw_nsecs -= NSEC_PER_SEC; | ||
713 | raw_time.tv_sec++; | 715 | raw_time.tv_sec++; |
714 | } | 716 | } |
717 | raw_time.tv_nsec = raw_nsecs; | ||
715 | 718 | ||
716 | /* Accumulate error between NTP and clock interval */ | 719 | /* Accumulate error between NTP and clock interval */ |
717 | timekeeper.ntp_error += tick_length << shift; | 720 | timekeeper.ntp_error += tick_length << shift; |
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index 82499a5bdcb7..959f8d6c8cc1 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c | |||
@@ -710,6 +710,9 @@ static void blk_add_trace_rq(struct request_queue *q, struct request *rq, | |||
710 | if (rq->cmd_flags & REQ_DISCARD) | 710 | if (rq->cmd_flags & REQ_DISCARD) |
711 | rw |= REQ_DISCARD; | 711 | rw |= REQ_DISCARD; |
712 | 712 | ||
713 | if (rq->cmd_flags & REQ_SECURE) | ||
714 | rw |= REQ_SECURE; | ||
715 | |||
713 | if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { | 716 | if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { |
714 | what |= BLK_TC_ACT(BLK_TC_PC); | 717 | what |= BLK_TC_ACT(BLK_TC_PC); |
715 | __blk_add_trace(bt, 0, blk_rq_bytes(rq), rw, | 718 | __blk_add_trace(bt, 0, blk_rq_bytes(rq), rw, |
@@ -1816,6 +1819,8 @@ void blk_fill_rwbs(char *rwbs, u32 rw, int bytes) | |||
1816 | rwbs[i++] = 'S'; | 1819 | rwbs[i++] = 'S'; |
1817 | if (rw & REQ_META) | 1820 | if (rw & REQ_META) |
1818 | rwbs[i++] = 'M'; | 1821 | rwbs[i++] = 'M'; |
1822 | if (rw & REQ_SECURE) | ||
1823 | rwbs[i++] = 'E'; | ||
1819 | 1824 | ||
1820 | rwbs[i] = '\0'; | 1825 | rwbs[i] = '\0'; |
1821 | } | 1826 | } |
@@ -1828,6 +1833,9 @@ void blk_fill_rwbs_rq(char *rwbs, struct request *rq) | |||
1828 | if (rq->cmd_flags & REQ_DISCARD) | 1833 | if (rq->cmd_flags & REQ_DISCARD) |
1829 | rw |= REQ_DISCARD; | 1834 | rw |= REQ_DISCARD; |
1830 | 1835 | ||
1836 | if (rq->cmd_flags & REQ_SECURE) | ||
1837 | rw |= REQ_SECURE; | ||
1838 | |||
1831 | bytes = blk_rq_bytes(rq); | 1839 | bytes = blk_rq_bytes(rq); |
1832 | 1840 | ||
1833 | blk_fill_rwbs(rwbs, rw, bytes); | 1841 | blk_fill_rwbs(rwbs, rw, bytes); |
diff --git a/lib/inflate.c b/lib/inflate.c index 677b738c2204..013a76193481 100644 --- a/lib/inflate.c +++ b/lib/inflate.c | |||
@@ -103,7 +103,9 @@ | |||
103 | the two sets of lengths. | 103 | the two sets of lengths. |
104 | */ | 104 | */ |
105 | #include <linux/compiler.h> | 105 | #include <linux/compiler.h> |
106 | #ifdef NO_INFLATE_MALLOC | ||
106 | #include <linux/slab.h> | 107 | #include <linux/slab.h> |
108 | #endif | ||
107 | 109 | ||
108 | #ifdef RCSID | 110 | #ifdef RCSID |
109 | static char rcsid[] = "#Id: inflate.c,v 0.14 1993/06/10 13:27:04 jloup Exp #"; | 111 | static char rcsid[] = "#Id: inflate.c,v 0.14 1993/06/10 13:27:04 jloup Exp #"; |
diff --git a/lib/raid6/Makefile b/lib/raid6/Makefile index 19bf32da644f..8a38102770f3 100644 --- a/lib/raid6/Makefile +++ b/lib/raid6/Makefile | |||
@@ -1,11 +1,8 @@ | |||
1 | obj-$(CONFIG_RAID6_PQ) += raid6_pq.o | 1 | obj-$(CONFIG_RAID6_PQ) += raid6_pq.o |
2 | 2 | ||
3 | raid6_pq-y += raid6algos.o raid6recov.o raid6tables.o \ | 3 | raid6_pq-y += algos.o recov.o tables.o int1.o int2.o int4.o \ |
4 | raid6int1.o raid6int2.o raid6int4.o \ | 4 | int8.o int16.o int32.o altivec1.o altivec2.o altivec4.o \ |
5 | raid6int8.o raid6int16.o raid6int32.o \ | 5 | altivec8.o mmx.o sse1.o sse2.o |
6 | raid6altivec1.o raid6altivec2.o raid6altivec4.o \ | ||
7 | raid6altivec8.o \ | ||
8 | raid6mmx.o raid6sse1.o raid6sse2.o | ||
9 | hostprogs-y += mktables | 6 | hostprogs-y += mktables |
10 | 7 | ||
11 | quiet_cmd_unroll = UNROLL $@ | 8 | quiet_cmd_unroll = UNROLL $@ |
@@ -16,63 +13,63 @@ ifeq ($(CONFIG_ALTIVEC),y) | |||
16 | altivec_flags := -maltivec -mabi=altivec | 13 | altivec_flags := -maltivec -mabi=altivec |
17 | endif | 14 | endif |
18 | 15 | ||
19 | targets += raid6int1.c | 16 | targets += int1.c |
20 | $(obj)/raid6int1.c: UNROLL := 1 | 17 | $(obj)/int1.c: UNROLL := 1 |
21 | $(obj)/raid6int1.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE | 18 | $(obj)/int1.c: $(src)/int.uc $(src)/unroll.awk FORCE |
22 | $(call if_changed,unroll) | 19 | $(call if_changed,unroll) |
23 | 20 | ||
24 | targets += raid6int2.c | 21 | targets += int2.c |
25 | $(obj)/raid6int2.c: UNROLL := 2 | 22 | $(obj)/int2.c: UNROLL := 2 |
26 | $(obj)/raid6int2.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE | 23 | $(obj)/int2.c: $(src)/int.uc $(src)/unroll.awk FORCE |
27 | $(call if_changed,unroll) | 24 | $(call if_changed,unroll) |
28 | 25 | ||
29 | targets += raid6int4.c | 26 | targets += int4.c |
30 | $(obj)/raid6int4.c: UNROLL := 4 | 27 | $(obj)/int4.c: UNROLL := 4 |
31 | $(obj)/raid6int4.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE | 28 | $(obj)/int4.c: $(src)/int.uc $(src)/unroll.awk FORCE |
32 | $(call if_changed,unroll) | 29 | $(call if_changed,unroll) |
33 | 30 | ||
34 | targets += raid6int8.c | 31 | targets += int8.c |
35 | $(obj)/raid6int8.c: UNROLL := 8 | 32 | $(obj)/int8.c: UNROLL := 8 |
36 | $(obj)/raid6int8.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE | 33 | $(obj)/int8.c: $(src)/int.uc $(src)/unroll.awk FORCE |
37 | $(call if_changed,unroll) | 34 | $(call if_changed,unroll) |
38 | 35 | ||
39 | targets += raid6int16.c | 36 | targets += int16.c |
40 | $(obj)/raid6int16.c: UNROLL := 16 | 37 | $(obj)/int16.c: UNROLL := 16 |
41 | $(obj)/raid6int16.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE | 38 | $(obj)/int16.c: $(src)/int.uc $(src)/unroll.awk FORCE |
42 | $(call if_changed,unroll) | 39 | $(call if_changed,unroll) |
43 | 40 | ||
44 | targets += raid6int32.c | 41 | targets += int32.c |
45 | $(obj)/raid6int32.c: UNROLL := 32 | 42 | $(obj)/int32.c: UNROLL := 32 |
46 | $(obj)/raid6int32.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE | 43 | $(obj)/int32.c: $(src)/int.uc $(src)/unroll.awk FORCE |
47 | $(call if_changed,unroll) | 44 | $(call if_changed,unroll) |
48 | 45 | ||
49 | CFLAGS_raid6altivec1.o += $(altivec_flags) | 46 | CFLAGS_altivec1.o += $(altivec_flags) |
50 | targets += raid6altivec1.c | 47 | targets += altivec1.c |
51 | $(obj)/raid6altivec1.c: UNROLL := 1 | 48 | $(obj)/altivec1.c: UNROLL := 1 |
52 | $(obj)/raid6altivec1.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE | 49 | $(obj)/altivec1.c: $(src)/altivec.uc $(src)/unroll.awk FORCE |
53 | $(call if_changed,unroll) | 50 | $(call if_changed,unroll) |
54 | 51 | ||
55 | CFLAGS_raid6altivec2.o += $(altivec_flags) | 52 | CFLAGS_altivec2.o += $(altivec_flags) |
56 | targets += raid6altivec2.c | 53 | targets += altivec2.c |
57 | $(obj)/raid6altivec2.c: UNROLL := 2 | 54 | $(obj)/altivec2.c: UNROLL := 2 |
58 | $(obj)/raid6altivec2.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE | 55 | $(obj)/altivec2.c: $(src)/altivec.uc $(src)/unroll.awk FORCE |
59 | $(call if_changed,unroll) | 56 | $(call if_changed,unroll) |
60 | 57 | ||
61 | CFLAGS_raid6altivec4.o += $(altivec_flags) | 58 | CFLAGS_altivec4.o += $(altivec_flags) |
62 | targets += raid6altivec4.c | 59 | targets += altivec4.c |
63 | $(obj)/raid6altivec4.c: UNROLL := 4 | 60 | $(obj)/altivec4.c: UNROLL := 4 |
64 | $(obj)/raid6altivec4.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE | 61 | $(obj)/altivec4.c: $(src)/altivec.uc $(src)/unroll.awk FORCE |
65 | $(call if_changed,unroll) | 62 | $(call if_changed,unroll) |
66 | 63 | ||
67 | CFLAGS_raid6altivec8.o += $(altivec_flags) | 64 | CFLAGS_altivec8.o += $(altivec_flags) |
68 | targets += raid6altivec8.c | 65 | targets += altivec8.c |
69 | $(obj)/raid6altivec8.c: UNROLL := 8 | 66 | $(obj)/altivec8.c: UNROLL := 8 |
70 | $(obj)/raid6altivec8.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE | 67 | $(obj)/altivec8.c: $(src)/altivec.uc $(src)/unroll.awk FORCE |
71 | $(call if_changed,unroll) | 68 | $(call if_changed,unroll) |
72 | 69 | ||
73 | quiet_cmd_mktable = TABLE $@ | 70 | quiet_cmd_mktable = TABLE $@ |
74 | cmd_mktable = $(obj)/mktables > $@ || ( rm -f $@ && exit 1 ) | 71 | cmd_mktable = $(obj)/mktables > $@ || ( rm -f $@ && exit 1 ) |
75 | 72 | ||
76 | targets += raid6tables.c | 73 | targets += tables.c |
77 | $(obj)/raid6tables.c: $(obj)/mktables FORCE | 74 | $(obj)/tables.c: $(obj)/mktables FORCE |
78 | $(call if_changed,mktable) | 75 | $(call if_changed,mktable) |
diff --git a/lib/raid6/raid6algos.c b/lib/raid6/algos.c index 1f8784bfd44d..b595f560bee7 100644 --- a/lib/raid6/raid6algos.c +++ b/lib/raid6/algos.c | |||
@@ -11,17 +11,17 @@ | |||
11 | * ----------------------------------------------------------------------- */ | 11 | * ----------------------------------------------------------------------- */ |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * raid6algos.c | 14 | * raid6/algos.c |
15 | * | 15 | * |
16 | * Algorithm list and algorithm selection for RAID-6 | 16 | * Algorithm list and algorithm selection for RAID-6 |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/raid/pq.h> | 19 | #include <linux/raid/pq.h> |
20 | #include <linux/gfp.h> | ||
21 | #ifndef __KERNEL__ | 20 | #ifndef __KERNEL__ |
22 | #include <sys/mman.h> | 21 | #include <sys/mman.h> |
23 | #include <stdio.h> | 22 | #include <stdio.h> |
24 | #else | 23 | #else |
24 | #include <linux/gfp.h> | ||
25 | #if !RAID6_USE_EMPTY_ZERO_PAGE | 25 | #if !RAID6_USE_EMPTY_ZERO_PAGE |
26 | /* In .bss so it's zeroed */ | 26 | /* In .bss so it's zeroed */ |
27 | const char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(256))); | 27 | const char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(256))); |
diff --git a/lib/raid6/raid6altivec.uc b/lib/raid6/altivec.uc index 2654d5c854be..2654d5c854be 100644 --- a/lib/raid6/raid6altivec.uc +++ b/lib/raid6/altivec.uc | |||
diff --git a/lib/raid6/raid6int.uc b/lib/raid6/int.uc index d1e276a14fab..d1e276a14fab 100644 --- a/lib/raid6/raid6int.uc +++ b/lib/raid6/int.uc | |||
diff --git a/lib/raid6/raid6mmx.c b/lib/raid6/mmx.c index e7f6c13132bf..279347f23094 100644 --- a/lib/raid6/raid6mmx.c +++ b/lib/raid6/mmx.c | |||
@@ -11,7 +11,7 @@ | |||
11 | * ----------------------------------------------------------------------- */ | 11 | * ----------------------------------------------------------------------- */ |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * raid6mmx.c | 14 | * raid6/mmx.c |
15 | * | 15 | * |
16 | * MMX implementation of RAID-6 syndrome functions | 16 | * MMX implementation of RAID-6 syndrome functions |
17 | */ | 17 | */ |
@@ -19,9 +19,9 @@ | |||
19 | #if defined(__i386__) && !defined(__arch_um__) | 19 | #if defined(__i386__) && !defined(__arch_um__) |
20 | 20 | ||
21 | #include <linux/raid/pq.h> | 21 | #include <linux/raid/pq.h> |
22 | #include "raid6x86.h" | 22 | #include "x86.h" |
23 | 23 | ||
24 | /* Shared with raid6sse1.c */ | 24 | /* Shared with raid6/sse1.c */ |
25 | const struct raid6_mmx_constants { | 25 | const struct raid6_mmx_constants { |
26 | u64 x1d; | 26 | u64 x1d; |
27 | } raid6_mmx_constants = { | 27 | } raid6_mmx_constants = { |
diff --git a/lib/raid6/raid6test/Makefile b/lib/raid6/raid6test/Makefile deleted file mode 100644 index 2874cbef529d..000000000000 --- a/lib/raid6/raid6test/Makefile +++ /dev/null | |||
@@ -1,75 +0,0 @@ | |||
1 | # | ||
2 | # This is a simple Makefile to test some of the RAID-6 code | ||
3 | # from userspace. | ||
4 | # | ||
5 | |||
6 | CC = gcc | ||
7 | OPTFLAGS = -O2 # Adjust as desired | ||
8 | CFLAGS = -I.. -I ../../../include -g $(OPTFLAGS) | ||
9 | LD = ld | ||
10 | AWK = awk | ||
11 | AR = ar | ||
12 | RANLIB = ranlib | ||
13 | |||
14 | .c.o: | ||
15 | $(CC) $(CFLAGS) -c -o $@ $< | ||
16 | |||
17 | %.c: ../%.c | ||
18 | cp -f $< $@ | ||
19 | |||
20 | %.uc: ../%.uc | ||
21 | cp -f $< $@ | ||
22 | |||
23 | all: raid6.a raid6test | ||
24 | |||
25 | raid6.a: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \ | ||
26 | raid6int32.o \ | ||
27 | raid6mmx.o raid6sse1.o raid6sse2.o \ | ||
28 | raid6altivec1.o raid6altivec2.o raid6altivec4.o raid6altivec8.o \ | ||
29 | raid6recov.o raid6algos.o \ | ||
30 | raid6tables.o | ||
31 | rm -f $@ | ||
32 | $(AR) cq $@ $^ | ||
33 | $(RANLIB) $@ | ||
34 | |||
35 | raid6test: test.c raid6.a | ||
36 | $(CC) $(CFLAGS) -o raid6test $^ | ||
37 | |||
38 | raid6altivec1.c: raid6altivec.uc ../unroll.awk | ||
39 | $(AWK) ../unroll.awk -vN=1 < raid6altivec.uc > $@ | ||
40 | |||
41 | raid6altivec2.c: raid6altivec.uc ../unroll.awk | ||
42 | $(AWK) ../unroll.awk -vN=2 < raid6altivec.uc > $@ | ||
43 | |||
44 | raid6altivec4.c: raid6altivec.uc ../unroll.awk | ||
45 | $(AWK) ../unroll.awk -vN=4 < raid6altivec.uc > $@ | ||
46 | |||
47 | raid6altivec8.c: raid6altivec.uc ../unroll.awk | ||
48 | $(AWK) ../unroll.awk -vN=8 < raid6altivec.uc > $@ | ||
49 | |||
50 | raid6int1.c: raid6int.uc ../unroll.awk | ||
51 | $(AWK) ../unroll.awk -vN=1 < raid6int.uc > $@ | ||
52 | |||
53 | raid6int2.c: raid6int.uc ../unroll.awk | ||
54 | $(AWK) ../unroll.awk -vN=2 < raid6int.uc > $@ | ||
55 | |||
56 | raid6int4.c: raid6int.uc ../unroll.awk | ||
57 | $(AWK) ../unroll.awk -vN=4 < raid6int.uc > $@ | ||
58 | |||
59 | raid6int8.c: raid6int.uc ../unroll.awk | ||
60 | $(AWK) ../unroll.awk -vN=8 < raid6int.uc > $@ | ||
61 | |||
62 | raid6int16.c: raid6int.uc ../unroll.awk | ||
63 | $(AWK) ../unroll.awk -vN=16 < raid6int.uc > $@ | ||
64 | |||
65 | raid6int32.c: raid6int.uc ../unroll.awk | ||
66 | $(AWK) ../unroll.awk -vN=32 < raid6int.uc > $@ | ||
67 | |||
68 | raid6tables.c: mktables | ||
69 | ./mktables > raid6tables.c | ||
70 | |||
71 | clean: | ||
72 | rm -f *.o *.a mktables mktables.c raid6int.uc raid6*.c raid6test | ||
73 | |||
74 | spotless: clean | ||
75 | rm -f *~ | ||
diff --git a/lib/raid6/raid6recov.c b/lib/raid6/recov.c index 2609f00e0d61..8590d19cf522 100644 --- a/lib/raid6/raid6recov.c +++ b/lib/raid6/recov.c | |||
@@ -11,7 +11,7 @@ | |||
11 | * ----------------------------------------------------------------------- */ | 11 | * ----------------------------------------------------------------------- */ |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * raid6recov.c | 14 | * raid6/recov.c |
15 | * | 15 | * |
16 | * RAID-6 data recovery in dual failure mode. In single failure mode, | 16 | * RAID-6 data recovery in dual failure mode. In single failure mode, |
17 | * use the RAID-5 algorithm (or, in the case of Q failure, just reconstruct | 17 | * use the RAID-5 algorithm (or, in the case of Q failure, just reconstruct |
diff --git a/lib/raid6/raid6sse1.c b/lib/raid6/sse1.c index b274dd5eab8f..10dd91948c07 100644 --- a/lib/raid6/raid6sse1.c +++ b/lib/raid6/sse1.c | |||
@@ -11,7 +11,7 @@ | |||
11 | * ----------------------------------------------------------------------- */ | 11 | * ----------------------------------------------------------------------- */ |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * raid6sse1.c | 14 | * raid6/sse1.c |
15 | * | 15 | * |
16 | * SSE-1/MMXEXT implementation of RAID-6 syndrome functions | 16 | * SSE-1/MMXEXT implementation of RAID-6 syndrome functions |
17 | * | 17 | * |
@@ -24,9 +24,9 @@ | |||
24 | #if defined(__i386__) && !defined(__arch_um__) | 24 | #if defined(__i386__) && !defined(__arch_um__) |
25 | 25 | ||
26 | #include <linux/raid/pq.h> | 26 | #include <linux/raid/pq.h> |
27 | #include "raid6x86.h" | 27 | #include "x86.h" |
28 | 28 | ||
29 | /* Defined in raid6mmx.c */ | 29 | /* Defined in raid6/mmx.c */ |
30 | extern const struct raid6_mmx_constants { | 30 | extern const struct raid6_mmx_constants { |
31 | u64 x1d; | 31 | u64 x1d; |
32 | } raid6_mmx_constants; | 32 | } raid6_mmx_constants; |
diff --git a/lib/raid6/raid6sse2.c b/lib/raid6/sse2.c index 6ed6c6c0389f..bc2d57daa589 100644 --- a/lib/raid6/raid6sse2.c +++ b/lib/raid6/sse2.c | |||
@@ -11,7 +11,7 @@ | |||
11 | * ----------------------------------------------------------------------- */ | 11 | * ----------------------------------------------------------------------- */ |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * raid6sse2.c | 14 | * raid6/sse2.c |
15 | * | 15 | * |
16 | * SSE-2 implementation of RAID-6 syndrome functions | 16 | * SSE-2 implementation of RAID-6 syndrome functions |
17 | * | 17 | * |
@@ -20,7 +20,7 @@ | |||
20 | #if (defined(__i386__) || defined(__x86_64__)) && !defined(__arch_um__) | 20 | #if (defined(__i386__) || defined(__x86_64__)) && !defined(__arch_um__) |
21 | 21 | ||
22 | #include <linux/raid/pq.h> | 22 | #include <linux/raid/pq.h> |
23 | #include "raid6x86.h" | 23 | #include "x86.h" |
24 | 24 | ||
25 | static const struct raid6_sse_constants { | 25 | static const struct raid6_sse_constants { |
26 | u64 x1d[2]; | 26 | u64 x1d[2]; |
diff --git a/lib/raid6/test/Makefile b/lib/raid6/test/Makefile new file mode 100644 index 000000000000..aa651697b6dc --- /dev/null +++ b/lib/raid6/test/Makefile | |||
@@ -0,0 +1,72 @@ | |||
1 | # | ||
2 | # This is a simple Makefile to test some of the RAID-6 code | ||
3 | # from userspace. | ||
4 | # | ||
5 | |||
6 | CC = gcc | ||
7 | OPTFLAGS = -O2 # Adjust as desired | ||
8 | CFLAGS = -I.. -I ../../../include -g $(OPTFLAGS) | ||
9 | LD = ld | ||
10 | AWK = awk -f | ||
11 | AR = ar | ||
12 | RANLIB = ranlib | ||
13 | |||
14 | .c.o: | ||
15 | $(CC) $(CFLAGS) -c -o $@ $< | ||
16 | |||
17 | %.c: ../%.c | ||
18 | cp -f $< $@ | ||
19 | |||
20 | %.uc: ../%.uc | ||
21 | cp -f $< $@ | ||
22 | |||
23 | all: raid6.a raid6test | ||
24 | |||
25 | raid6.a: int1.o int2.o int4.o int8.o int16.o int32.o mmx.o sse1.o sse2.o \ | ||
26 | altivec1.o altivec2.o altivec4.o altivec8.o recov.o algos.o \ | ||
27 | tables.o | ||
28 | rm -f $@ | ||
29 | $(AR) cq $@ $^ | ||
30 | $(RANLIB) $@ | ||
31 | |||
32 | raid6test: test.c raid6.a | ||
33 | $(CC) $(CFLAGS) -o raid6test $^ | ||
34 | |||
35 | altivec1.c: altivec.uc ../unroll.awk | ||
36 | $(AWK) ../unroll.awk -vN=1 < altivec.uc > $@ | ||
37 | |||
38 | altivec2.c: altivec.uc ../unroll.awk | ||
39 | $(AWK) ../unroll.awk -vN=2 < altivec.uc > $@ | ||
40 | |||
41 | altivec4.c: altivec.uc ../unroll.awk | ||
42 | $(AWK) ../unroll.awk -vN=4 < altivec.uc > $@ | ||
43 | |||
44 | altivec8.c: altivec.uc ../unroll.awk | ||
45 | $(AWK) ../unroll.awk -vN=8 < altivec.uc > $@ | ||
46 | |||
47 | int1.c: int.uc ../unroll.awk | ||
48 | $(AWK) ../unroll.awk -vN=1 < int.uc > $@ | ||
49 | |||
50 | int2.c: int.uc ../unroll.awk | ||
51 | $(AWK) ../unroll.awk -vN=2 < int.uc > $@ | ||
52 | |||
53 | int4.c: int.uc ../unroll.awk | ||
54 | $(AWK) ../unroll.awk -vN=4 < int.uc > $@ | ||
55 | |||
56 | int8.c: int.uc ../unroll.awk | ||
57 | $(AWK) ../unroll.awk -vN=8 < int.uc > $@ | ||
58 | |||
59 | int16.c: int.uc ../unroll.awk | ||
60 | $(AWK) ../unroll.awk -vN=16 < int.uc > $@ | ||
61 | |||
62 | int32.c: int.uc ../unroll.awk | ||
63 | $(AWK) ../unroll.awk -vN=32 < int.uc > $@ | ||
64 | |||
65 | tables.c: mktables | ||
66 | ./mktables > tables.c | ||
67 | |||
68 | clean: | ||
69 | rm -f *.o *.a mktables mktables.c *.uc int*.c altivec*.c tables.c raid6test | ||
70 | |||
71 | spotless: clean | ||
72 | rm -f *~ | ||
diff --git a/lib/raid6/raid6test/test.c b/lib/raid6/test/test.c index 7a930318b17d..7a930318b17d 100644 --- a/lib/raid6/raid6test/test.c +++ b/lib/raid6/test/test.c | |||
diff --git a/lib/raid6/raid6x86.h b/lib/raid6/x86.h index 4c22c1568558..cb2a8c91c886 100644 --- a/lib/raid6/raid6x86.h +++ b/lib/raid6/x86.h | |||
@@ -11,7 +11,7 @@ | |||
11 | * ----------------------------------------------------------------------- */ | 11 | * ----------------------------------------------------------------------- */ |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * raid6x86.h | 14 | * raid6/x86.h |
15 | * | 15 | * |
16 | * Definitions common to x86 and x86-64 RAID-6 code only | 16 | * Definitions common to x86 and x86-64 RAID-6 code only |
17 | */ | 17 | */ |
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 08d357522e78..eaa4a5bbe063 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c | |||
@@ -81,7 +81,8 @@ static int bdi_debug_stats_show(struct seq_file *m, void *v) | |||
81 | nr_more_io++; | 81 | nr_more_io++; |
82 | spin_unlock(&inode_lock); | 82 | spin_unlock(&inode_lock); |
83 | 83 | ||
84 | get_dirty_limits(&background_thresh, &dirty_thresh, &bdi_thresh, bdi); | 84 | global_dirty_limits(&background_thresh, &dirty_thresh); |
85 | bdi_thresh = bdi_dirty_limit(bdi, dirty_thresh); | ||
85 | 86 | ||
86 | #define K(x) ((x) << (PAGE_SHIFT - 10)) | 87 | #define K(x) ((x) << (PAGE_SHIFT - 10)) |
87 | seq_printf(m, | 88 | seq_printf(m, |
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index b61d2db9f34e..cc5be788a39f 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -18,6 +18,9 @@ | |||
18 | #include <linux/bootmem.h> | 18 | #include <linux/bootmem.h> |
19 | #include <linux/sysfs.h> | 19 | #include <linux/sysfs.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/rmap.h> | ||
22 | #include <linux/swap.h> | ||
23 | #include <linux/swapops.h> | ||
21 | 24 | ||
22 | #include <asm/page.h> | 25 | #include <asm/page.h> |
23 | #include <asm/pgtable.h> | 26 | #include <asm/pgtable.h> |
@@ -220,6 +223,12 @@ static pgoff_t vma_hugecache_offset(struct hstate *h, | |||
220 | (vma->vm_pgoff >> huge_page_order(h)); | 223 | (vma->vm_pgoff >> huge_page_order(h)); |
221 | } | 224 | } |
222 | 225 | ||
226 | pgoff_t linear_hugepage_index(struct vm_area_struct *vma, | ||
227 | unsigned long address) | ||
228 | { | ||
229 | return vma_hugecache_offset(hstate_vma(vma), vma, address); | ||
230 | } | ||
231 | |||
223 | /* | 232 | /* |
224 | * Return the size of the pages allocated when backing a VMA. In the majority | 233 | * Return the size of the pages allocated when backing a VMA. In the majority |
225 | * cases this will be same size as used by the page table entries. | 234 | * cases this will be same size as used by the page table entries. |
@@ -552,6 +561,7 @@ static void free_huge_page(struct page *page) | |||
552 | set_page_private(page, 0); | 561 | set_page_private(page, 0); |
553 | page->mapping = NULL; | 562 | page->mapping = NULL; |
554 | BUG_ON(page_count(page)); | 563 | BUG_ON(page_count(page)); |
564 | BUG_ON(page_mapcount(page)); | ||
555 | INIT_LIST_HEAD(&page->lru); | 565 | INIT_LIST_HEAD(&page->lru); |
556 | 566 | ||
557 | spin_lock(&hugetlb_lock); | 567 | spin_lock(&hugetlb_lock); |
@@ -605,6 +615,8 @@ int PageHuge(struct page *page) | |||
605 | return dtor == free_huge_page; | 615 | return dtor == free_huge_page; |
606 | } | 616 | } |
607 | 617 | ||
618 | EXPORT_SYMBOL_GPL(PageHuge); | ||
619 | |||
608 | static struct page *alloc_fresh_huge_page_node(struct hstate *h, int nid) | 620 | static struct page *alloc_fresh_huge_page_node(struct hstate *h, int nid) |
609 | { | 621 | { |
610 | struct page *page; | 622 | struct page *page; |
@@ -2129,6 +2141,7 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, | |||
2129 | entry = huge_ptep_get(src_pte); | 2141 | entry = huge_ptep_get(src_pte); |
2130 | ptepage = pte_page(entry); | 2142 | ptepage = pte_page(entry); |
2131 | get_page(ptepage); | 2143 | get_page(ptepage); |
2144 | page_dup_rmap(ptepage); | ||
2132 | set_huge_pte_at(dst, addr, dst_pte, entry); | 2145 | set_huge_pte_at(dst, addr, dst_pte, entry); |
2133 | } | 2146 | } |
2134 | spin_unlock(&src->page_table_lock); | 2147 | spin_unlock(&src->page_table_lock); |
@@ -2140,6 +2153,19 @@ nomem: | |||
2140 | return -ENOMEM; | 2153 | return -ENOMEM; |
2141 | } | 2154 | } |
2142 | 2155 | ||
2156 | static int is_hugetlb_entry_hwpoisoned(pte_t pte) | ||
2157 | { | ||
2158 | swp_entry_t swp; | ||
2159 | |||
2160 | if (huge_pte_none(pte) || pte_present(pte)) | ||
2161 | return 0; | ||
2162 | swp = pte_to_swp_entry(pte); | ||
2163 | if (non_swap_entry(swp) && is_hwpoison_entry(swp)) { | ||
2164 | return 1; | ||
2165 | } else | ||
2166 | return 0; | ||
2167 | } | ||
2168 | |||
2143 | void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, | 2169 | void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, |
2144 | unsigned long end, struct page *ref_page) | 2170 | unsigned long end, struct page *ref_page) |
2145 | { | 2171 | { |
@@ -2198,6 +2224,12 @@ void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, | |||
2198 | if (huge_pte_none(pte)) | 2224 | if (huge_pte_none(pte)) |
2199 | continue; | 2225 | continue; |
2200 | 2226 | ||
2227 | /* | ||
2228 | * HWPoisoned hugepage is already unmapped and dropped reference | ||
2229 | */ | ||
2230 | if (unlikely(is_hugetlb_entry_hwpoisoned(pte))) | ||
2231 | continue; | ||
2232 | |||
2201 | page = pte_page(pte); | 2233 | page = pte_page(pte); |
2202 | if (pte_dirty(pte)) | 2234 | if (pte_dirty(pte)) |
2203 | set_page_dirty(page); | 2235 | set_page_dirty(page); |
@@ -2207,6 +2239,7 @@ void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, | |||
2207 | flush_tlb_range(vma, start, end); | 2239 | flush_tlb_range(vma, start, end); |
2208 | mmu_notifier_invalidate_range_end(mm, start, end); | 2240 | mmu_notifier_invalidate_range_end(mm, start, end); |
2209 | list_for_each_entry_safe(page, tmp, &page_list, lru) { | 2241 | list_for_each_entry_safe(page, tmp, &page_list, lru) { |
2242 | page_remove_rmap(page); | ||
2210 | list_del(&page->lru); | 2243 | list_del(&page->lru); |
2211 | put_page(page); | 2244 | put_page(page); |
2212 | } | 2245 | } |
@@ -2272,6 +2305,9 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2272 | return 1; | 2305 | return 1; |
2273 | } | 2306 | } |
2274 | 2307 | ||
2308 | /* | ||
2309 | * Hugetlb_cow() should be called with page lock of the original hugepage held. | ||
2310 | */ | ||
2275 | static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma, | 2311 | static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma, |
2276 | unsigned long address, pte_t *ptep, pte_t pte, | 2312 | unsigned long address, pte_t *ptep, pte_t pte, |
2277 | struct page *pagecache_page) | 2313 | struct page *pagecache_page) |
@@ -2286,8 +2322,13 @@ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2286 | retry_avoidcopy: | 2322 | retry_avoidcopy: |
2287 | /* If no-one else is actually using this page, avoid the copy | 2323 | /* If no-one else is actually using this page, avoid the copy |
2288 | * and just make the page writable */ | 2324 | * and just make the page writable */ |
2289 | avoidcopy = (page_count(old_page) == 1); | 2325 | avoidcopy = (page_mapcount(old_page) == 1); |
2290 | if (avoidcopy) { | 2326 | if (avoidcopy) { |
2327 | if (!trylock_page(old_page)) { | ||
2328 | if (PageAnon(old_page)) | ||
2329 | page_move_anon_rmap(old_page, vma, address); | ||
2330 | } else | ||
2331 | unlock_page(old_page); | ||
2291 | set_huge_ptep_writable(vma, address, ptep); | 2332 | set_huge_ptep_writable(vma, address, ptep); |
2292 | return 0; | 2333 | return 0; |
2293 | } | 2334 | } |
@@ -2338,6 +2379,13 @@ retry_avoidcopy: | |||
2338 | return -PTR_ERR(new_page); | 2379 | return -PTR_ERR(new_page); |
2339 | } | 2380 | } |
2340 | 2381 | ||
2382 | /* | ||
2383 | * When the original hugepage is shared one, it does not have | ||
2384 | * anon_vma prepared. | ||
2385 | */ | ||
2386 | if (unlikely(anon_vma_prepare(vma))) | ||
2387 | return VM_FAULT_OOM; | ||
2388 | |||
2341 | copy_huge_page(new_page, old_page, address, vma); | 2389 | copy_huge_page(new_page, old_page, address, vma); |
2342 | __SetPageUptodate(new_page); | 2390 | __SetPageUptodate(new_page); |
2343 | 2391 | ||
@@ -2355,6 +2403,8 @@ retry_avoidcopy: | |||
2355 | huge_ptep_clear_flush(vma, address, ptep); | 2403 | huge_ptep_clear_flush(vma, address, ptep); |
2356 | set_huge_pte_at(mm, address, ptep, | 2404 | set_huge_pte_at(mm, address, ptep, |
2357 | make_huge_pte(vma, new_page, 1)); | 2405 | make_huge_pte(vma, new_page, 1)); |
2406 | page_remove_rmap(old_page); | ||
2407 | hugepage_add_anon_rmap(new_page, vma, address); | ||
2358 | /* Make the old page be freed below */ | 2408 | /* Make the old page be freed below */ |
2359 | new_page = old_page; | 2409 | new_page = old_page; |
2360 | mmu_notifier_invalidate_range_end(mm, | 2410 | mmu_notifier_invalidate_range_end(mm, |
@@ -2458,10 +2508,29 @@ retry: | |||
2458 | spin_lock(&inode->i_lock); | 2508 | spin_lock(&inode->i_lock); |
2459 | inode->i_blocks += blocks_per_huge_page(h); | 2509 | inode->i_blocks += blocks_per_huge_page(h); |
2460 | spin_unlock(&inode->i_lock); | 2510 | spin_unlock(&inode->i_lock); |
2511 | page_dup_rmap(page); | ||
2461 | } else { | 2512 | } else { |
2462 | lock_page(page); | 2513 | lock_page(page); |
2463 | page->mapping = HUGETLB_POISON; | 2514 | if (unlikely(anon_vma_prepare(vma))) { |
2515 | ret = VM_FAULT_OOM; | ||
2516 | goto backout_unlocked; | ||
2517 | } | ||
2518 | hugepage_add_new_anon_rmap(page, vma, address); | ||
2464 | } | 2519 | } |
2520 | } else { | ||
2521 | page_dup_rmap(page); | ||
2522 | } | ||
2523 | |||
2524 | /* | ||
2525 | * Since memory error handler replaces pte into hwpoison swap entry | ||
2526 | * at the time of error handling, a process which reserved but not have | ||
2527 | * the mapping to the error hugepage does not have hwpoison swap entry. | ||
2528 | * So we need to block accesses from such a process by checking | ||
2529 | * PG_hwpoison bit here. | ||
2530 | */ | ||
2531 | if (unlikely(PageHWPoison(page))) { | ||
2532 | ret = VM_FAULT_HWPOISON; | ||
2533 | goto backout_unlocked; | ||
2465 | } | 2534 | } |
2466 | 2535 | ||
2467 | /* | 2536 | /* |
@@ -2513,10 +2582,18 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2513 | pte_t *ptep; | 2582 | pte_t *ptep; |
2514 | pte_t entry; | 2583 | pte_t entry; |
2515 | int ret; | 2584 | int ret; |
2585 | struct page *page = NULL; | ||
2516 | struct page *pagecache_page = NULL; | 2586 | struct page *pagecache_page = NULL; |
2517 | static DEFINE_MUTEX(hugetlb_instantiation_mutex); | 2587 | static DEFINE_MUTEX(hugetlb_instantiation_mutex); |
2518 | struct hstate *h = hstate_vma(vma); | 2588 | struct hstate *h = hstate_vma(vma); |
2519 | 2589 | ||
2590 | ptep = huge_pte_offset(mm, address); | ||
2591 | if (ptep) { | ||
2592 | entry = huge_ptep_get(ptep); | ||
2593 | if (unlikely(is_hugetlb_entry_hwpoisoned(entry))) | ||
2594 | return VM_FAULT_HWPOISON; | ||
2595 | } | ||
2596 | |||
2520 | ptep = huge_pte_alloc(mm, address, huge_page_size(h)); | 2597 | ptep = huge_pte_alloc(mm, address, huge_page_size(h)); |
2521 | if (!ptep) | 2598 | if (!ptep) |
2522 | return VM_FAULT_OOM; | 2599 | return VM_FAULT_OOM; |
@@ -2554,6 +2631,11 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2554 | vma, address); | 2631 | vma, address); |
2555 | } | 2632 | } |
2556 | 2633 | ||
2634 | if (!pagecache_page) { | ||
2635 | page = pte_page(entry); | ||
2636 | lock_page(page); | ||
2637 | } | ||
2638 | |||
2557 | spin_lock(&mm->page_table_lock); | 2639 | spin_lock(&mm->page_table_lock); |
2558 | /* Check for a racing update before calling hugetlb_cow */ | 2640 | /* Check for a racing update before calling hugetlb_cow */ |
2559 | if (unlikely(!pte_same(entry, huge_ptep_get(ptep)))) | 2641 | if (unlikely(!pte_same(entry, huge_ptep_get(ptep)))) |
@@ -2579,6 +2661,8 @@ out_page_table_lock: | |||
2579 | if (pagecache_page) { | 2661 | if (pagecache_page) { |
2580 | unlock_page(pagecache_page); | 2662 | unlock_page(pagecache_page); |
2581 | put_page(pagecache_page); | 2663 | put_page(pagecache_page); |
2664 | } else { | ||
2665 | unlock_page(page); | ||
2582 | } | 2666 | } |
2583 | 2667 | ||
2584 | out_mutex: | 2668 | out_mutex: |
@@ -2791,3 +2875,19 @@ void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed) | |||
2791 | hugetlb_put_quota(inode->i_mapping, (chg - freed)); | 2875 | hugetlb_put_quota(inode->i_mapping, (chg - freed)); |
2792 | hugetlb_acct_memory(h, -(chg - freed)); | 2876 | hugetlb_acct_memory(h, -(chg - freed)); |
2793 | } | 2877 | } |
2878 | |||
2879 | /* | ||
2880 | * This function is called from memory failure code. | ||
2881 | * Assume the caller holds page lock of the head page. | ||
2882 | */ | ||
2883 | void __isolate_hwpoisoned_huge_page(struct page *hpage) | ||
2884 | { | ||
2885 | struct hstate *h = page_hstate(hpage); | ||
2886 | int nid = page_to_nid(hpage); | ||
2887 | |||
2888 | spin_lock(&hugetlb_lock); | ||
2889 | list_del(&hpage->lru); | ||
2890 | h->free_huge_pages--; | ||
2891 | h->free_huge_pages_node[nid]--; | ||
2892 | spin_unlock(&hugetlb_lock); | ||
2893 | } | ||
diff --git a/mm/hwpoison-inject.c b/mm/hwpoison-inject.c index 10ea71905c1f..0948f1072d6b 100644 --- a/mm/hwpoison-inject.c +++ b/mm/hwpoison-inject.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/mm.h> | 5 | #include <linux/mm.h> |
6 | #include <linux/swap.h> | 6 | #include <linux/swap.h> |
7 | #include <linux/pagemap.h> | 7 | #include <linux/pagemap.h> |
8 | #include <linux/hugetlb.h> | ||
8 | #include "internal.h" | 9 | #include "internal.h" |
9 | 10 | ||
10 | static struct dentry *hwpoison_dir; | 11 | static struct dentry *hwpoison_dir; |
@@ -13,6 +14,7 @@ static int hwpoison_inject(void *data, u64 val) | |||
13 | { | 14 | { |
14 | unsigned long pfn = val; | 15 | unsigned long pfn = val; |
15 | struct page *p; | 16 | struct page *p; |
17 | struct page *hpage; | ||
16 | int err; | 18 | int err; |
17 | 19 | ||
18 | if (!capable(CAP_SYS_ADMIN)) | 20 | if (!capable(CAP_SYS_ADMIN)) |
@@ -24,18 +26,19 @@ static int hwpoison_inject(void *data, u64 val) | |||
24 | return -ENXIO; | 26 | return -ENXIO; |
25 | 27 | ||
26 | p = pfn_to_page(pfn); | 28 | p = pfn_to_page(pfn); |
29 | hpage = compound_head(p); | ||
27 | /* | 30 | /* |
28 | * This implies unable to support free buddy pages. | 31 | * This implies unable to support free buddy pages. |
29 | */ | 32 | */ |
30 | if (!get_page_unless_zero(p)) | 33 | if (!get_page_unless_zero(hpage)) |
31 | return 0; | 34 | return 0; |
32 | 35 | ||
33 | if (!PageLRU(p)) | 36 | if (!PageLRU(p) && !PageHuge(p)) |
34 | shake_page(p, 0); | 37 | shake_page(p, 0); |
35 | /* | 38 | /* |
36 | * This implies unable to support non-LRU pages. | 39 | * This implies unable to support non-LRU pages. |
37 | */ | 40 | */ |
38 | if (!PageLRU(p)) | 41 | if (!PageLRU(p) && !PageHuge(p)) |
39 | return 0; | 42 | return 0; |
40 | 43 | ||
41 | /* | 44 | /* |
@@ -44,9 +47,9 @@ static int hwpoison_inject(void *data, u64 val) | |||
44 | * We temporarily take page lock for try_get_mem_cgroup_from_page(). | 47 | * We temporarily take page lock for try_get_mem_cgroup_from_page(). |
45 | * __memory_failure() will redo the check reliably inside page lock. | 48 | * __memory_failure() will redo the check reliably inside page lock. |
46 | */ | 49 | */ |
47 | lock_page(p); | 50 | lock_page(hpage); |
48 | err = hwpoison_filter(p); | 51 | err = hwpoison_filter(hpage); |
49 | unlock_page(p); | 52 | unlock_page(hpage); |
50 | if (err) | 53 | if (err) |
51 | return 0; | 54 | return 0; |
52 | 55 | ||
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 6b44e52cacaa..9c26eeca1342 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/suspend.h> | 46 | #include <linux/suspend.h> |
47 | #include <linux/slab.h> | 47 | #include <linux/slab.h> |
48 | #include <linux/swapops.h> | 48 | #include <linux/swapops.h> |
49 | #include <linux/hugetlb.h> | ||
49 | #include "internal.h" | 50 | #include "internal.h" |
50 | 51 | ||
51 | int sysctl_memory_failure_early_kill __read_mostly = 0; | 52 | int sysctl_memory_failure_early_kill __read_mostly = 0; |
@@ -690,17 +691,29 @@ static int me_swapcache_clean(struct page *p, unsigned long pfn) | |||
690 | /* | 691 | /* |
691 | * Huge pages. Needs work. | 692 | * Huge pages. Needs work. |
692 | * Issues: | 693 | * Issues: |
693 | * No rmap support so we cannot find the original mapper. In theory could walk | 694 | * - Error on hugepage is contained in hugepage unit (not in raw page unit.) |
694 | * all MMs and look for the mappings, but that would be non atomic and racy. | 695 | * To narrow down kill region to one page, we need to break up pmd. |
695 | * Need rmap for hugepages for this. Alternatively we could employ a heuristic, | 696 | * - To support soft-offlining for hugepage, we need to support hugepage |
696 | * like just walking the current process and hoping it has it mapped (that | 697 | * migration. |
697 | * should be usually true for the common "shared database cache" case) | ||
698 | * Should handle free huge pages and dequeue them too, but this needs to | ||
699 | * handle huge page accounting correctly. | ||
700 | */ | 698 | */ |
701 | static int me_huge_page(struct page *p, unsigned long pfn) | 699 | static int me_huge_page(struct page *p, unsigned long pfn) |
702 | { | 700 | { |
703 | return FAILED; | 701 | struct page *hpage = compound_head(p); |
702 | /* | ||
703 | * We can safely recover from error on free or reserved (i.e. | ||
704 | * not in-use) hugepage by dequeuing it from freelist. | ||
705 | * To check whether a hugepage is in-use or not, we can't use | ||
706 | * page->lru because it can be used in other hugepage operations, | ||
707 | * such as __unmap_hugepage_range() and gather_surplus_pages(). | ||
708 | * So instead we use page_mapping() and PageAnon(). | ||
709 | * We assume that this function is called with page lock held, | ||
710 | * so there is no race between isolation and mapping/unmapping. | ||
711 | */ | ||
712 | if (!(page_mapping(hpage) || PageAnon(hpage))) { | ||
713 | __isolate_hwpoisoned_huge_page(hpage); | ||
714 | return RECOVERED; | ||
715 | } | ||
716 | return DELAYED; | ||
704 | } | 717 | } |
705 | 718 | ||
706 | /* | 719 | /* |
@@ -838,6 +851,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, | |||
838 | int ret; | 851 | int ret; |
839 | int i; | 852 | int i; |
840 | int kill = 1; | 853 | int kill = 1; |
854 | struct page *hpage = compound_head(p); | ||
841 | 855 | ||
842 | if (PageReserved(p) || PageSlab(p)) | 856 | if (PageReserved(p) || PageSlab(p)) |
843 | return SWAP_SUCCESS; | 857 | return SWAP_SUCCESS; |
@@ -846,10 +860,10 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, | |||
846 | * This check implies we don't kill processes if their pages | 860 | * This check implies we don't kill processes if their pages |
847 | * are in the swap cache early. Those are always late kills. | 861 | * are in the swap cache early. Those are always late kills. |
848 | */ | 862 | */ |
849 | if (!page_mapped(p)) | 863 | if (!page_mapped(hpage)) |
850 | return SWAP_SUCCESS; | 864 | return SWAP_SUCCESS; |
851 | 865 | ||
852 | if (PageCompound(p) || PageKsm(p)) | 866 | if (PageKsm(p)) |
853 | return SWAP_FAIL; | 867 | return SWAP_FAIL; |
854 | 868 | ||
855 | if (PageSwapCache(p)) { | 869 | if (PageSwapCache(p)) { |
@@ -864,10 +878,11 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, | |||
864 | * XXX: the dirty test could be racy: set_page_dirty() may not always | 878 | * XXX: the dirty test could be racy: set_page_dirty() may not always |
865 | * be called inside page lock (it's recommended but not enforced). | 879 | * be called inside page lock (it's recommended but not enforced). |
866 | */ | 880 | */ |
867 | mapping = page_mapping(p); | 881 | mapping = page_mapping(hpage); |
868 | if (!PageDirty(p) && mapping && mapping_cap_writeback_dirty(mapping)) { | 882 | if (!PageDirty(hpage) && mapping && |
869 | if (page_mkclean(p)) { | 883 | mapping_cap_writeback_dirty(mapping)) { |
870 | SetPageDirty(p); | 884 | if (page_mkclean(hpage)) { |
885 | SetPageDirty(hpage); | ||
871 | } else { | 886 | } else { |
872 | kill = 0; | 887 | kill = 0; |
873 | ttu |= TTU_IGNORE_HWPOISON; | 888 | ttu |= TTU_IGNORE_HWPOISON; |
@@ -886,14 +901,14 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, | |||
886 | * there's nothing that can be done. | 901 | * there's nothing that can be done. |
887 | */ | 902 | */ |
888 | if (kill) | 903 | if (kill) |
889 | collect_procs(p, &tokill); | 904 | collect_procs(hpage, &tokill); |
890 | 905 | ||
891 | /* | 906 | /* |
892 | * try_to_unmap can fail temporarily due to races. | 907 | * try_to_unmap can fail temporarily due to races. |
893 | * Try a few times (RED-PEN better strategy?) | 908 | * Try a few times (RED-PEN better strategy?) |
894 | */ | 909 | */ |
895 | for (i = 0; i < N_UNMAP_TRIES; i++) { | 910 | for (i = 0; i < N_UNMAP_TRIES; i++) { |
896 | ret = try_to_unmap(p, ttu); | 911 | ret = try_to_unmap(hpage, ttu); |
897 | if (ret == SWAP_SUCCESS) | 912 | if (ret == SWAP_SUCCESS) |
898 | break; | 913 | break; |
899 | pr_debug("MCE %#lx: try_to_unmap retry needed %d\n", pfn, ret); | 914 | pr_debug("MCE %#lx: try_to_unmap retry needed %d\n", pfn, ret); |
@@ -901,7 +916,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, | |||
901 | 916 | ||
902 | if (ret != SWAP_SUCCESS) | 917 | if (ret != SWAP_SUCCESS) |
903 | printk(KERN_ERR "MCE %#lx: failed to unmap page (mapcount=%d)\n", | 918 | printk(KERN_ERR "MCE %#lx: failed to unmap page (mapcount=%d)\n", |
904 | pfn, page_mapcount(p)); | 919 | pfn, page_mapcount(hpage)); |
905 | 920 | ||
906 | /* | 921 | /* |
907 | * Now that the dirty bit has been propagated to the | 922 | * Now that the dirty bit has been propagated to the |
@@ -912,17 +927,35 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, | |||
912 | * use a more force-full uncatchable kill to prevent | 927 | * use a more force-full uncatchable kill to prevent |
913 | * any accesses to the poisoned memory. | 928 | * any accesses to the poisoned memory. |
914 | */ | 929 | */ |
915 | kill_procs_ao(&tokill, !!PageDirty(p), trapno, | 930 | kill_procs_ao(&tokill, !!PageDirty(hpage), trapno, |
916 | ret != SWAP_SUCCESS, pfn); | 931 | ret != SWAP_SUCCESS, pfn); |
917 | 932 | ||
918 | return ret; | 933 | return ret; |
919 | } | 934 | } |
920 | 935 | ||
936 | static void set_page_hwpoison_huge_page(struct page *hpage) | ||
937 | { | ||
938 | int i; | ||
939 | int nr_pages = 1 << compound_order(hpage); | ||
940 | for (i = 0; i < nr_pages; i++) | ||
941 | SetPageHWPoison(hpage + i); | ||
942 | } | ||
943 | |||
944 | static void clear_page_hwpoison_huge_page(struct page *hpage) | ||
945 | { | ||
946 | int i; | ||
947 | int nr_pages = 1 << compound_order(hpage); | ||
948 | for (i = 0; i < nr_pages; i++) | ||
949 | ClearPageHWPoison(hpage + i); | ||
950 | } | ||
951 | |||
921 | int __memory_failure(unsigned long pfn, int trapno, int flags) | 952 | int __memory_failure(unsigned long pfn, int trapno, int flags) |
922 | { | 953 | { |
923 | struct page_state *ps; | 954 | struct page_state *ps; |
924 | struct page *p; | 955 | struct page *p; |
956 | struct page *hpage; | ||
925 | int res; | 957 | int res; |
958 | unsigned int nr_pages; | ||
926 | 959 | ||
927 | if (!sysctl_memory_failure_recovery) | 960 | if (!sysctl_memory_failure_recovery) |
928 | panic("Memory failure from trap %d on page %lx", trapno, pfn); | 961 | panic("Memory failure from trap %d on page %lx", trapno, pfn); |
@@ -935,12 +968,14 @@ int __memory_failure(unsigned long pfn, int trapno, int flags) | |||
935 | } | 968 | } |
936 | 969 | ||
937 | p = pfn_to_page(pfn); | 970 | p = pfn_to_page(pfn); |
971 | hpage = compound_head(p); | ||
938 | if (TestSetPageHWPoison(p)) { | 972 | if (TestSetPageHWPoison(p)) { |
939 | printk(KERN_ERR "MCE %#lx: already hardware poisoned\n", pfn); | 973 | printk(KERN_ERR "MCE %#lx: already hardware poisoned\n", pfn); |
940 | return 0; | 974 | return 0; |
941 | } | 975 | } |
942 | 976 | ||
943 | atomic_long_add(1, &mce_bad_pages); | 977 | nr_pages = 1 << compound_order(hpage); |
978 | atomic_long_add(nr_pages, &mce_bad_pages); | ||
944 | 979 | ||
945 | /* | 980 | /* |
946 | * We need/can do nothing about count=0 pages. | 981 | * We need/can do nothing about count=0 pages. |
@@ -954,7 +989,7 @@ int __memory_failure(unsigned long pfn, int trapno, int flags) | |||
954 | * that may make page_freeze_refs()/page_unfreeze_refs() mismatch. | 989 | * that may make page_freeze_refs()/page_unfreeze_refs() mismatch. |
955 | */ | 990 | */ |
956 | if (!(flags & MF_COUNT_INCREASED) && | 991 | if (!(flags & MF_COUNT_INCREASED) && |
957 | !get_page_unless_zero(compound_head(p))) { | 992 | !get_page_unless_zero(hpage)) { |
958 | if (is_free_buddy_page(p)) { | 993 | if (is_free_buddy_page(p)) { |
959 | action_result(pfn, "free buddy", DELAYED); | 994 | action_result(pfn, "free buddy", DELAYED); |
960 | return 0; | 995 | return 0; |
@@ -972,9 +1007,9 @@ int __memory_failure(unsigned long pfn, int trapno, int flags) | |||
972 | * The check (unnecessarily) ignores LRU pages being isolated and | 1007 | * The check (unnecessarily) ignores LRU pages being isolated and |
973 | * walked by the page reclaim code, however that's not a big loss. | 1008 | * walked by the page reclaim code, however that's not a big loss. |
974 | */ | 1009 | */ |
975 | if (!PageLRU(p)) | 1010 | if (!PageLRU(p) && !PageHuge(p)) |
976 | shake_page(p, 0); | 1011 | shake_page(p, 0); |
977 | if (!PageLRU(p)) { | 1012 | if (!PageLRU(p) && !PageHuge(p)) { |
978 | /* | 1013 | /* |
979 | * shake_page could have turned it free. | 1014 | * shake_page could have turned it free. |
980 | */ | 1015 | */ |
@@ -992,7 +1027,7 @@ int __memory_failure(unsigned long pfn, int trapno, int flags) | |||
992 | * It's very difficult to mess with pages currently under IO | 1027 | * It's very difficult to mess with pages currently under IO |
993 | * and in many cases impossible, so we just avoid it here. | 1028 | * and in many cases impossible, so we just avoid it here. |
994 | */ | 1029 | */ |
995 | lock_page_nosync(p); | 1030 | lock_page_nosync(hpage); |
996 | 1031 | ||
997 | /* | 1032 | /* |
998 | * unpoison always clear PG_hwpoison inside page lock | 1033 | * unpoison always clear PG_hwpoison inside page lock |
@@ -1004,11 +1039,31 @@ int __memory_failure(unsigned long pfn, int trapno, int flags) | |||
1004 | } | 1039 | } |
1005 | if (hwpoison_filter(p)) { | 1040 | if (hwpoison_filter(p)) { |
1006 | if (TestClearPageHWPoison(p)) | 1041 | if (TestClearPageHWPoison(p)) |
1007 | atomic_long_dec(&mce_bad_pages); | 1042 | atomic_long_sub(nr_pages, &mce_bad_pages); |
1008 | unlock_page(p); | 1043 | unlock_page(hpage); |
1009 | put_page(p); | 1044 | put_page(hpage); |
1045 | return 0; | ||
1046 | } | ||
1047 | |||
1048 | /* | ||
1049 | * For error on the tail page, we should set PG_hwpoison | ||
1050 | * on the head page to show that the hugepage is hwpoisoned | ||
1051 | */ | ||
1052 | if (PageTail(p) && TestSetPageHWPoison(hpage)) { | ||
1053 | action_result(pfn, "hugepage already hardware poisoned", | ||
1054 | IGNORED); | ||
1055 | unlock_page(hpage); | ||
1056 | put_page(hpage); | ||
1010 | return 0; | 1057 | return 0; |
1011 | } | 1058 | } |
1059 | /* | ||
1060 | * Set PG_hwpoison on all pages in an error hugepage, | ||
1061 | * because containment is done in hugepage unit for now. | ||
1062 | * Since we have done TestSetPageHWPoison() for the head page with | ||
1063 | * page lock held, we can safely set PG_hwpoison bits on tail pages. | ||
1064 | */ | ||
1065 | if (PageHuge(p)) | ||
1066 | set_page_hwpoison_huge_page(hpage); | ||
1012 | 1067 | ||
1013 | wait_on_page_writeback(p); | 1068 | wait_on_page_writeback(p); |
1014 | 1069 | ||
@@ -1039,7 +1094,7 @@ int __memory_failure(unsigned long pfn, int trapno, int flags) | |||
1039 | } | 1094 | } |
1040 | } | 1095 | } |
1041 | out: | 1096 | out: |
1042 | unlock_page(p); | 1097 | unlock_page(hpage); |
1043 | return res; | 1098 | return res; |
1044 | } | 1099 | } |
1045 | EXPORT_SYMBOL_GPL(__memory_failure); | 1100 | EXPORT_SYMBOL_GPL(__memory_failure); |
@@ -1083,6 +1138,7 @@ int unpoison_memory(unsigned long pfn) | |||
1083 | struct page *page; | 1138 | struct page *page; |
1084 | struct page *p; | 1139 | struct page *p; |
1085 | int freeit = 0; | 1140 | int freeit = 0; |
1141 | unsigned int nr_pages; | ||
1086 | 1142 | ||
1087 | if (!pfn_valid(pfn)) | 1143 | if (!pfn_valid(pfn)) |
1088 | return -ENXIO; | 1144 | return -ENXIO; |
@@ -1095,9 +1151,11 @@ int unpoison_memory(unsigned long pfn) | |||
1095 | return 0; | 1151 | return 0; |
1096 | } | 1152 | } |
1097 | 1153 | ||
1154 | nr_pages = 1 << compound_order(page); | ||
1155 | |||
1098 | if (!get_page_unless_zero(page)) { | 1156 | if (!get_page_unless_zero(page)) { |
1099 | if (TestClearPageHWPoison(p)) | 1157 | if (TestClearPageHWPoison(p)) |
1100 | atomic_long_dec(&mce_bad_pages); | 1158 | atomic_long_sub(nr_pages, &mce_bad_pages); |
1101 | pr_debug("MCE: Software-unpoisoned free page %#lx\n", pfn); | 1159 | pr_debug("MCE: Software-unpoisoned free page %#lx\n", pfn); |
1102 | return 0; | 1160 | return 0; |
1103 | } | 1161 | } |
@@ -1109,11 +1167,13 @@ int unpoison_memory(unsigned long pfn) | |||
1109 | * the PG_hwpoison page will be caught and isolated on the entrance to | 1167 | * the PG_hwpoison page will be caught and isolated on the entrance to |
1110 | * the free buddy page pool. | 1168 | * the free buddy page pool. |
1111 | */ | 1169 | */ |
1112 | if (TestClearPageHWPoison(p)) { | 1170 | if (TestClearPageHWPoison(page)) { |
1113 | pr_debug("MCE: Software-unpoisoned page %#lx\n", pfn); | 1171 | pr_debug("MCE: Software-unpoisoned page %#lx\n", pfn); |
1114 | atomic_long_dec(&mce_bad_pages); | 1172 | atomic_long_sub(nr_pages, &mce_bad_pages); |
1115 | freeit = 1; | 1173 | freeit = 1; |
1116 | } | 1174 | } |
1175 | if (PageHuge(p)) | ||
1176 | clear_page_hwpoison_huge_page(page); | ||
1117 | unlock_page(page); | 1177 | unlock_page(page); |
1118 | 1178 | ||
1119 | put_page(page); | 1179 | put_page(page); |
diff --git a/mm/memory.c b/mm/memory.c index 858829d06a92..9b3b73f4ae9c 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -2760,6 +2760,26 @@ out_release: | |||
2760 | } | 2760 | } |
2761 | 2761 | ||
2762 | /* | 2762 | /* |
2763 | * This is like a special single-page "expand_downwards()", | ||
2764 | * except we must first make sure that 'address-PAGE_SIZE' | ||
2765 | * doesn't hit another vma. | ||
2766 | * | ||
2767 | * The "find_vma()" will do the right thing even if we wrap | ||
2768 | */ | ||
2769 | static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned long address) | ||
2770 | { | ||
2771 | address &= PAGE_MASK; | ||
2772 | if ((vma->vm_flags & VM_GROWSDOWN) && address == vma->vm_start) { | ||
2773 | address -= PAGE_SIZE; | ||
2774 | if (find_vma(vma->vm_mm, address) != vma) | ||
2775 | return -ENOMEM; | ||
2776 | |||
2777 | expand_stack(vma, address); | ||
2778 | } | ||
2779 | return 0; | ||
2780 | } | ||
2781 | |||
2782 | /* | ||
2763 | * We enter with non-exclusive mmap_sem (to exclude vma changes, | 2783 | * We enter with non-exclusive mmap_sem (to exclude vma changes, |
2764 | * but allow concurrent faults), and pte mapped but not yet locked. | 2784 | * but allow concurrent faults), and pte mapped but not yet locked. |
2765 | * We return with mmap_sem still held, but pte unmapped and unlocked. | 2785 | * We return with mmap_sem still held, but pte unmapped and unlocked. |
@@ -2772,6 +2792,11 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2772 | spinlock_t *ptl; | 2792 | spinlock_t *ptl; |
2773 | pte_t entry; | 2793 | pte_t entry; |
2774 | 2794 | ||
2795 | if (check_stack_guard_page(vma, address) < 0) { | ||
2796 | pte_unmap(page_table); | ||
2797 | return VM_FAULT_SIGBUS; | ||
2798 | } | ||
2799 | |||
2775 | if (!(flags & FAULT_FLAG_WRITE)) { | 2800 | if (!(flags & FAULT_FLAG_WRITE)) { |
2776 | entry = pte_mkspecial(pfn_pte(my_zero_pfn(address), | 2801 | entry = pte_mkspecial(pfn_pte(my_zero_pfn(address), |
2777 | vma->vm_page_prot)); | 2802 | vma->vm_page_prot)); |
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 0c6258bd1ba3..20890d80c7ef 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -253,32 +253,6 @@ static void bdi_writeout_fraction(struct backing_dev_info *bdi, | |||
253 | } | 253 | } |
254 | } | 254 | } |
255 | 255 | ||
256 | /* | ||
257 | * Clip the earned share of dirty pages to that which is actually available. | ||
258 | * This avoids exceeding the total dirty_limit when the floating averages | ||
259 | * fluctuate too quickly. | ||
260 | */ | ||
261 | static void clip_bdi_dirty_limit(struct backing_dev_info *bdi, | ||
262 | unsigned long dirty, unsigned long *pbdi_dirty) | ||
263 | { | ||
264 | unsigned long avail_dirty; | ||
265 | |||
266 | avail_dirty = global_page_state(NR_FILE_DIRTY) + | ||
267 | global_page_state(NR_WRITEBACK) + | ||
268 | global_page_state(NR_UNSTABLE_NFS) + | ||
269 | global_page_state(NR_WRITEBACK_TEMP); | ||
270 | |||
271 | if (avail_dirty < dirty) | ||
272 | avail_dirty = dirty - avail_dirty; | ||
273 | else | ||
274 | avail_dirty = 0; | ||
275 | |||
276 | avail_dirty += bdi_stat(bdi, BDI_RECLAIMABLE) + | ||
277 | bdi_stat(bdi, BDI_WRITEBACK); | ||
278 | |||
279 | *pbdi_dirty = min(*pbdi_dirty, avail_dirty); | ||
280 | } | ||
281 | |||
282 | static inline void task_dirties_fraction(struct task_struct *tsk, | 256 | static inline void task_dirties_fraction(struct task_struct *tsk, |
283 | long *numerator, long *denominator) | 257 | long *numerator, long *denominator) |
284 | { | 258 | { |
@@ -287,16 +261,24 @@ static inline void task_dirties_fraction(struct task_struct *tsk, | |||
287 | } | 261 | } |
288 | 262 | ||
289 | /* | 263 | /* |
290 | * scale the dirty limit | 264 | * task_dirty_limit - scale down dirty throttling threshold for one task |
291 | * | 265 | * |
292 | * task specific dirty limit: | 266 | * task specific dirty limit: |
293 | * | 267 | * |
294 | * dirty -= (dirty/8) * p_{t} | 268 | * dirty -= (dirty/8) * p_{t} |
269 | * | ||
270 | * To protect light/slow dirtying tasks from heavier/fast ones, we start | ||
271 | * throttling individual tasks before reaching the bdi dirty limit. | ||
272 | * Relatively low thresholds will be allocated to heavy dirtiers. So when | ||
273 | * dirty pages grow large, heavy dirtiers will be throttled first, which will | ||
274 | * effectively curb the growth of dirty pages. Light dirtiers with high enough | ||
275 | * dirty threshold may never get throttled. | ||
295 | */ | 276 | */ |
296 | static void task_dirty_limit(struct task_struct *tsk, unsigned long *pdirty) | 277 | static unsigned long task_dirty_limit(struct task_struct *tsk, |
278 | unsigned long bdi_dirty) | ||
297 | { | 279 | { |
298 | long numerator, denominator; | 280 | long numerator, denominator; |
299 | unsigned long dirty = *pdirty; | 281 | unsigned long dirty = bdi_dirty; |
300 | u64 inv = dirty >> 3; | 282 | u64 inv = dirty >> 3; |
301 | 283 | ||
302 | task_dirties_fraction(tsk, &numerator, &denominator); | 284 | task_dirties_fraction(tsk, &numerator, &denominator); |
@@ -304,10 +286,8 @@ static void task_dirty_limit(struct task_struct *tsk, unsigned long *pdirty) | |||
304 | do_div(inv, denominator); | 286 | do_div(inv, denominator); |
305 | 287 | ||
306 | dirty -= inv; | 288 | dirty -= inv; |
307 | if (dirty < *pdirty/2) | ||
308 | dirty = *pdirty/2; | ||
309 | 289 | ||
310 | *pdirty = dirty; | 290 | return max(dirty, bdi_dirty/2); |
311 | } | 291 | } |
312 | 292 | ||
313 | /* | 293 | /* |
@@ -417,9 +397,16 @@ unsigned long determine_dirtyable_memory(void) | |||
417 | return x + 1; /* Ensure that we never return 0 */ | 397 | return x + 1; /* Ensure that we never return 0 */ |
418 | } | 398 | } |
419 | 399 | ||
420 | void | 400 | /** |
421 | get_dirty_limits(unsigned long *pbackground, unsigned long *pdirty, | 401 | * global_dirty_limits - background-writeback and dirty-throttling thresholds |
422 | unsigned long *pbdi_dirty, struct backing_dev_info *bdi) | 402 | * |
403 | * Calculate the dirty thresholds based on sysctl parameters | ||
404 | * - vm.dirty_background_ratio or vm.dirty_background_bytes | ||
405 | * - vm.dirty_ratio or vm.dirty_bytes | ||
406 | * The dirty limits will be lifted by 1/4 for PF_LESS_THROTTLE (ie. nfsd) and | ||
407 | * runtime tasks. | ||
408 | */ | ||
409 | void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty) | ||
423 | { | 410 | { |
424 | unsigned long background; | 411 | unsigned long background; |
425 | unsigned long dirty; | 412 | unsigned long dirty; |
@@ -451,27 +438,37 @@ get_dirty_limits(unsigned long *pbackground, unsigned long *pdirty, | |||
451 | } | 438 | } |
452 | *pbackground = background; | 439 | *pbackground = background; |
453 | *pdirty = dirty; | 440 | *pdirty = dirty; |
441 | } | ||
442 | |||
443 | /** | ||
444 | * bdi_dirty_limit - @bdi's share of dirty throttling threshold | ||
445 | * | ||
446 | * Allocate high/low dirty limits to fast/slow devices, in order to prevent | ||
447 | * - starving fast devices | ||
448 | * - piling up dirty pages (that will take long time to sync) on slow devices | ||
449 | * | ||
450 | * The bdi's share of dirty limit will be adapting to its throughput and | ||
451 | * bounded by the bdi->min_ratio and/or bdi->max_ratio parameters, if set. | ||
452 | */ | ||
453 | unsigned long bdi_dirty_limit(struct backing_dev_info *bdi, unsigned long dirty) | ||
454 | { | ||
455 | u64 bdi_dirty; | ||
456 | long numerator, denominator; | ||
457 | |||
458 | /* | ||
459 | * Calculate this BDI's share of the dirty ratio. | ||
460 | */ | ||
461 | bdi_writeout_fraction(bdi, &numerator, &denominator); | ||
454 | 462 | ||
455 | if (bdi) { | 463 | bdi_dirty = (dirty * (100 - bdi_min_ratio)) / 100; |
456 | u64 bdi_dirty; | 464 | bdi_dirty *= numerator; |
457 | long numerator, denominator; | 465 | do_div(bdi_dirty, denominator); |
458 | 466 | ||
459 | /* | 467 | bdi_dirty += (dirty * bdi->min_ratio) / 100; |
460 | * Calculate this BDI's share of the dirty ratio. | 468 | if (bdi_dirty > (dirty * bdi->max_ratio) / 100) |
461 | */ | 469 | bdi_dirty = dirty * bdi->max_ratio / 100; |
462 | bdi_writeout_fraction(bdi, &numerator, &denominator); | 470 | |
463 | 471 | return bdi_dirty; | |
464 | bdi_dirty = (dirty * (100 - bdi_min_ratio)) / 100; | ||
465 | bdi_dirty *= numerator; | ||
466 | do_div(bdi_dirty, denominator); | ||
467 | bdi_dirty += (dirty * bdi->min_ratio) / 100; | ||
468 | if (bdi_dirty > (dirty * bdi->max_ratio) / 100) | ||
469 | bdi_dirty = dirty * bdi->max_ratio / 100; | ||
470 | |||
471 | *pbdi_dirty = bdi_dirty; | ||
472 | clip_bdi_dirty_limit(bdi, dirty, pbdi_dirty); | ||
473 | task_dirty_limit(current, pbdi_dirty); | ||
474 | } | ||
475 | } | 472 | } |
476 | 473 | ||
477 | /* | 474 | /* |
@@ -491,7 +488,7 @@ static void balance_dirty_pages(struct address_space *mapping, | |||
491 | unsigned long bdi_thresh; | 488 | unsigned long bdi_thresh; |
492 | unsigned long pages_written = 0; | 489 | unsigned long pages_written = 0; |
493 | unsigned long pause = 1; | 490 | unsigned long pause = 1; |
494 | 491 | bool dirty_exceeded = false; | |
495 | struct backing_dev_info *bdi = mapping->backing_dev_info; | 492 | struct backing_dev_info *bdi = mapping->backing_dev_info; |
496 | 493 | ||
497 | for (;;) { | 494 | for (;;) { |
@@ -502,18 +499,11 @@ static void balance_dirty_pages(struct address_space *mapping, | |||
502 | .range_cyclic = 1, | 499 | .range_cyclic = 1, |
503 | }; | 500 | }; |
504 | 501 | ||
505 | get_dirty_limits(&background_thresh, &dirty_thresh, | ||
506 | &bdi_thresh, bdi); | ||
507 | |||
508 | nr_reclaimable = global_page_state(NR_FILE_DIRTY) + | 502 | nr_reclaimable = global_page_state(NR_FILE_DIRTY) + |
509 | global_page_state(NR_UNSTABLE_NFS); | 503 | global_page_state(NR_UNSTABLE_NFS); |
510 | nr_writeback = global_page_state(NR_WRITEBACK); | 504 | nr_writeback = global_page_state(NR_WRITEBACK); |
511 | 505 | ||
512 | bdi_nr_reclaimable = bdi_stat(bdi, BDI_RECLAIMABLE); | 506 | global_dirty_limits(&background_thresh, &dirty_thresh); |
513 | bdi_nr_writeback = bdi_stat(bdi, BDI_WRITEBACK); | ||
514 | |||
515 | if (bdi_nr_reclaimable + bdi_nr_writeback <= bdi_thresh) | ||
516 | break; | ||
517 | 507 | ||
518 | /* | 508 | /* |
519 | * Throttle it only when the background writeback cannot | 509 | * Throttle it only when the background writeback cannot |
@@ -524,26 +514,8 @@ static void balance_dirty_pages(struct address_space *mapping, | |||
524 | (background_thresh + dirty_thresh) / 2) | 514 | (background_thresh + dirty_thresh) / 2) |
525 | break; | 515 | break; |
526 | 516 | ||
527 | if (!bdi->dirty_exceeded) | 517 | bdi_thresh = bdi_dirty_limit(bdi, dirty_thresh); |
528 | bdi->dirty_exceeded = 1; | 518 | bdi_thresh = task_dirty_limit(current, bdi_thresh); |
529 | |||
530 | /* Note: nr_reclaimable denotes nr_dirty + nr_unstable. | ||
531 | * Unstable writes are a feature of certain networked | ||
532 | * filesystems (i.e. NFS) in which data may have been | ||
533 | * written to the server's write cache, but has not yet | ||
534 | * been flushed to permanent storage. | ||
535 | * Only move pages to writeback if this bdi is over its | ||
536 | * threshold otherwise wait until the disk writes catch | ||
537 | * up. | ||
538 | */ | ||
539 | trace_wbc_balance_dirty_start(&wbc, bdi); | ||
540 | if (bdi_nr_reclaimable > bdi_thresh) { | ||
541 | writeback_inodes_wb(&bdi->wb, &wbc); | ||
542 | pages_written += write_chunk - wbc.nr_to_write; | ||
543 | get_dirty_limits(&background_thresh, &dirty_thresh, | ||
544 | &bdi_thresh, bdi); | ||
545 | trace_wbc_balance_dirty_written(&wbc, bdi); | ||
546 | } | ||
547 | 519 | ||
548 | /* | 520 | /* |
549 | * In order to avoid the stacked BDI deadlock we need | 521 | * In order to avoid the stacked BDI deadlock we need |
@@ -558,16 +530,44 @@ static void balance_dirty_pages(struct address_space *mapping, | |||
558 | if (bdi_thresh < 2*bdi_stat_error(bdi)) { | 530 | if (bdi_thresh < 2*bdi_stat_error(bdi)) { |
559 | bdi_nr_reclaimable = bdi_stat_sum(bdi, BDI_RECLAIMABLE); | 531 | bdi_nr_reclaimable = bdi_stat_sum(bdi, BDI_RECLAIMABLE); |
560 | bdi_nr_writeback = bdi_stat_sum(bdi, BDI_WRITEBACK); | 532 | bdi_nr_writeback = bdi_stat_sum(bdi, BDI_WRITEBACK); |
561 | } else if (bdi_nr_reclaimable) { | 533 | } else { |
562 | bdi_nr_reclaimable = bdi_stat(bdi, BDI_RECLAIMABLE); | 534 | bdi_nr_reclaimable = bdi_stat(bdi, BDI_RECLAIMABLE); |
563 | bdi_nr_writeback = bdi_stat(bdi, BDI_WRITEBACK); | 535 | bdi_nr_writeback = bdi_stat(bdi, BDI_WRITEBACK); |
564 | } | 536 | } |
565 | 537 | ||
566 | if (bdi_nr_reclaimable + bdi_nr_writeback <= bdi_thresh) | 538 | /* |
539 | * The bdi thresh is somehow "soft" limit derived from the | ||
540 | * global "hard" limit. The former helps to prevent heavy IO | ||
541 | * bdi or process from holding back light ones; The latter is | ||
542 | * the last resort safeguard. | ||
543 | */ | ||
544 | dirty_exceeded = | ||
545 | (bdi_nr_reclaimable + bdi_nr_writeback >= bdi_thresh) | ||
546 | || (nr_reclaimable + nr_writeback >= dirty_thresh); | ||
547 | |||
548 | if (!dirty_exceeded) | ||
567 | break; | 549 | break; |
568 | if (pages_written >= write_chunk) | ||
569 | break; /* We've done our duty */ | ||
570 | 550 | ||
551 | if (!bdi->dirty_exceeded) | ||
552 | bdi->dirty_exceeded = 1; | ||
553 | |||
554 | /* Note: nr_reclaimable denotes nr_dirty + nr_unstable. | ||
555 | * Unstable writes are a feature of certain networked | ||
556 | * filesystems (i.e. NFS) in which data may have been | ||
557 | * written to the server's write cache, but has not yet | ||
558 | * been flushed to permanent storage. | ||
559 | * Only move pages to writeback if this bdi is over its | ||
560 | * threshold otherwise wait until the disk writes catch | ||
561 | * up. | ||
562 | */ | ||
563 | trace_wbc_balance_dirty_start(&wbc, bdi); | ||
564 | if (bdi_nr_reclaimable > bdi_thresh) { | ||
565 | writeback_inodes_wb(&bdi->wb, &wbc); | ||
566 | pages_written += write_chunk - wbc.nr_to_write; | ||
567 | trace_wbc_balance_dirty_written(&wbc, bdi); | ||
568 | if (pages_written >= write_chunk) | ||
569 | break; /* We've done our duty */ | ||
570 | } | ||
571 | trace_wbc_balance_dirty_wait(&wbc, bdi); | 571 | trace_wbc_balance_dirty_wait(&wbc, bdi); |
572 | __set_current_state(TASK_INTERRUPTIBLE); | 572 | __set_current_state(TASK_INTERRUPTIBLE); |
573 | io_schedule_timeout(pause); | 573 | io_schedule_timeout(pause); |
@@ -581,8 +581,7 @@ static void balance_dirty_pages(struct address_space *mapping, | |||
581 | pause = HZ / 10; | 581 | pause = HZ / 10; |
582 | } | 582 | } |
583 | 583 | ||
584 | if (bdi_nr_reclaimable + bdi_nr_writeback < bdi_thresh && | 584 | if (!dirty_exceeded && bdi->dirty_exceeded) |
585 | bdi->dirty_exceeded) | ||
586 | bdi->dirty_exceeded = 0; | 585 | bdi->dirty_exceeded = 0; |
587 | 586 | ||
588 | if (writeback_in_progress(bdi)) | 587 | if (writeback_in_progress(bdi)) |
@@ -597,9 +596,7 @@ static void balance_dirty_pages(struct address_space *mapping, | |||
597 | * background_thresh, to keep the amount of dirty memory low. | 596 | * background_thresh, to keep the amount of dirty memory low. |
598 | */ | 597 | */ |
599 | if ((laptop_mode && pages_written) || | 598 | if ((laptop_mode && pages_written) || |
600 | (!laptop_mode && ((global_page_state(NR_FILE_DIRTY) | 599 | (!laptop_mode && (nr_reclaimable > background_thresh))) |
601 | + global_page_state(NR_UNSTABLE_NFS)) | ||
602 | > background_thresh))) | ||
603 | bdi_start_background_writeback(bdi); | 600 | bdi_start_background_writeback(bdi); |
604 | } | 601 | } |
605 | 602 | ||
@@ -663,7 +660,7 @@ void throttle_vm_writeout(gfp_t gfp_mask) | |||
663 | unsigned long dirty_thresh; | 660 | unsigned long dirty_thresh; |
664 | 661 | ||
665 | for ( ; ; ) { | 662 | for ( ; ; ) { |
666 | get_dirty_limits(&background_thresh, &dirty_thresh, NULL, NULL); | 663 | global_dirty_limits(&background_thresh, &dirty_thresh); |
667 | 664 | ||
668 | /* | 665 | /* |
669 | * Boost the allowable dirty threshold a bit for page | 666 | * Boost the allowable dirty threshold a bit for page |
@@ -825,10 +822,10 @@ void __init page_writeback_init(void) | |||
825 | /* | 822 | /* |
826 | * We tag pages in batches of WRITEBACK_TAG_BATCH to reduce tree_lock latency. | 823 | * We tag pages in batches of WRITEBACK_TAG_BATCH to reduce tree_lock latency. |
827 | */ | 824 | */ |
828 | #define WRITEBACK_TAG_BATCH 4096 | ||
829 | void tag_pages_for_writeback(struct address_space *mapping, | 825 | void tag_pages_for_writeback(struct address_space *mapping, |
830 | pgoff_t start, pgoff_t end) | 826 | pgoff_t start, pgoff_t end) |
831 | { | 827 | { |
828 | #define WRITEBACK_TAG_BATCH 4096 | ||
832 | unsigned long tagged; | 829 | unsigned long tagged; |
833 | 830 | ||
834 | do { | 831 | do { |
@@ -56,6 +56,7 @@ | |||
56 | #include <linux/memcontrol.h> | 56 | #include <linux/memcontrol.h> |
57 | #include <linux/mmu_notifier.h> | 57 | #include <linux/mmu_notifier.h> |
58 | #include <linux/migrate.h> | 58 | #include <linux/migrate.h> |
59 | #include <linux/hugetlb.h> | ||
59 | 60 | ||
60 | #include <asm/tlbflush.h> | 61 | #include <asm/tlbflush.h> |
61 | 62 | ||
@@ -350,6 +351,8 @@ vma_address(struct page *page, struct vm_area_struct *vma) | |||
350 | pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); | 351 | pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); |
351 | unsigned long address; | 352 | unsigned long address; |
352 | 353 | ||
354 | if (unlikely(is_vm_hugetlb_page(vma))) | ||
355 | pgoff = page->index << huge_page_order(page_hstate(page)); | ||
353 | address = vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT); | 356 | address = vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT); |
354 | if (unlikely(address < vma->vm_start || address >= vma->vm_end)) { | 357 | if (unlikely(address < vma->vm_start || address >= vma->vm_end)) { |
355 | /* page should be within @vma mapping range */ | 358 | /* page should be within @vma mapping range */ |
@@ -394,6 +397,12 @@ pte_t *page_check_address(struct page *page, struct mm_struct *mm, | |||
394 | pte_t *pte; | 397 | pte_t *pte; |
395 | spinlock_t *ptl; | 398 | spinlock_t *ptl; |
396 | 399 | ||
400 | if (unlikely(PageHuge(page))) { | ||
401 | pte = huge_pte_offset(mm, address); | ||
402 | ptl = &mm->page_table_lock; | ||
403 | goto check; | ||
404 | } | ||
405 | |||
397 | pgd = pgd_offset(mm, address); | 406 | pgd = pgd_offset(mm, address); |
398 | if (!pgd_present(*pgd)) | 407 | if (!pgd_present(*pgd)) |
399 | return NULL; | 408 | return NULL; |
@@ -414,6 +423,7 @@ pte_t *page_check_address(struct page *page, struct mm_struct *mm, | |||
414 | } | 423 | } |
415 | 424 | ||
416 | ptl = pte_lockptr(mm, pmd); | 425 | ptl = pte_lockptr(mm, pmd); |
426 | check: | ||
417 | spin_lock(ptl); | 427 | spin_lock(ptl); |
418 | if (pte_present(*pte) && page_to_pfn(page) == pte_pfn(*pte)) { | 428 | if (pte_present(*pte) && page_to_pfn(page) == pte_pfn(*pte)) { |
419 | *ptlp = ptl; | 429 | *ptlp = ptl; |
@@ -916,6 +926,12 @@ void page_remove_rmap(struct page *page) | |||
916 | page_clear_dirty(page); | 926 | page_clear_dirty(page); |
917 | set_page_dirty(page); | 927 | set_page_dirty(page); |
918 | } | 928 | } |
929 | /* | ||
930 | * Hugepages are not counted in NR_ANON_PAGES nor NR_FILE_MAPPED | ||
931 | * and not charged by memcg for now. | ||
932 | */ | ||
933 | if (unlikely(PageHuge(page))) | ||
934 | return; | ||
919 | if (PageAnon(page)) { | 935 | if (PageAnon(page)) { |
920 | mem_cgroup_uncharge_page(page); | 936 | mem_cgroup_uncharge_page(page); |
921 | __dec_zone_page_state(page, NR_ANON_PAGES); | 937 | __dec_zone_page_state(page, NR_ANON_PAGES); |
@@ -1524,3 +1540,46 @@ int rmap_walk(struct page *page, int (*rmap_one)(struct page *, | |||
1524 | return rmap_walk_file(page, rmap_one, arg); | 1540 | return rmap_walk_file(page, rmap_one, arg); |
1525 | } | 1541 | } |
1526 | #endif /* CONFIG_MIGRATION */ | 1542 | #endif /* CONFIG_MIGRATION */ |
1543 | |||
1544 | #ifdef CONFIG_HUGETLB_PAGE | ||
1545 | /* | ||
1546 | * The following three functions are for anonymous (private mapped) hugepages. | ||
1547 | * Unlike common anonymous pages, anonymous hugepages have no accounting code | ||
1548 | * and no lru code, because we handle hugepages differently from common pages. | ||
1549 | */ | ||
1550 | static void __hugepage_set_anon_rmap(struct page *page, | ||
1551 | struct vm_area_struct *vma, unsigned long address, int exclusive) | ||
1552 | { | ||
1553 | struct anon_vma *anon_vma = vma->anon_vma; | ||
1554 | BUG_ON(!anon_vma); | ||
1555 | if (!exclusive) { | ||
1556 | struct anon_vma_chain *avc; | ||
1557 | avc = list_entry(vma->anon_vma_chain.prev, | ||
1558 | struct anon_vma_chain, same_vma); | ||
1559 | anon_vma = avc->anon_vma; | ||
1560 | } | ||
1561 | anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON; | ||
1562 | page->mapping = (struct address_space *) anon_vma; | ||
1563 | page->index = linear_page_index(vma, address); | ||
1564 | } | ||
1565 | |||
1566 | void hugepage_add_anon_rmap(struct page *page, | ||
1567 | struct vm_area_struct *vma, unsigned long address) | ||
1568 | { | ||
1569 | struct anon_vma *anon_vma = vma->anon_vma; | ||
1570 | int first; | ||
1571 | BUG_ON(!anon_vma); | ||
1572 | BUG_ON(address < vma->vm_start || address >= vma->vm_end); | ||
1573 | first = atomic_inc_and_test(&page->_mapcount); | ||
1574 | if (first) | ||
1575 | __hugepage_set_anon_rmap(page, vma, address, 0); | ||
1576 | } | ||
1577 | |||
1578 | void hugepage_add_new_anon_rmap(struct page *page, | ||
1579 | struct vm_area_struct *vma, unsigned long address) | ||
1580 | { | ||
1581 | BUG_ON(address < vma->vm_start || address >= vma->vm_end); | ||
1582 | atomic_set(&page->_mapcount, 0); | ||
1583 | __hugepage_set_anon_rmap(page, vma, address, 1); | ||
1584 | } | ||
1585 | #endif /* CONFIG_HUGETLB_PAGE */ | ||
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 918c51335d64..6b8889da69a6 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <asm/tlbflush.h> | 31 | #include <asm/tlbflush.h> |
32 | #include <asm/shmparam.h> | 32 | #include <asm/shmparam.h> |
33 | 33 | ||
34 | bool vmap_lazy_unmap __read_mostly = true; | ||
34 | 35 | ||
35 | /*** Page table manipulation functions ***/ | 36 | /*** Page table manipulation functions ***/ |
36 | 37 | ||
@@ -502,6 +503,9 @@ static unsigned long lazy_max_pages(void) | |||
502 | { | 503 | { |
503 | unsigned int log; | 504 | unsigned int log; |
504 | 505 | ||
506 | if (!vmap_lazy_unmap) | ||
507 | return 0; | ||
508 | |||
505 | log = fls(num_online_cpus()); | 509 | log = fls(num_online_cpus()); |
506 | 510 | ||
507 | return log * (32UL * 1024 * 1024 / PAGE_SIZE); | 511 | return log * (32UL * 1024 * 1024 / PAGE_SIZE); |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 6d0bd198af19..be04d46110fe 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -103,6 +103,7 @@ ieee80211_rate_control_ops_get(const char *name) | |||
103 | struct rate_control_ops *ops; | 103 | struct rate_control_ops *ops; |
104 | const char *alg_name; | 104 | const char *alg_name; |
105 | 105 | ||
106 | kparam_block_sysfs_write(ieee80211_default_rc_algo); | ||
106 | if (!name) | 107 | if (!name) |
107 | alg_name = ieee80211_default_rc_algo; | 108 | alg_name = ieee80211_default_rc_algo; |
108 | else | 109 | else |
@@ -120,6 +121,7 @@ ieee80211_rate_control_ops_get(const char *name) | |||
120 | /* try built-in one if specific alg requested but not found */ | 121 | /* try built-in one if specific alg requested but not found */ |
121 | if (!ops && strlen(CONFIG_MAC80211_RC_DEFAULT)) | 122 | if (!ops && strlen(CONFIG_MAC80211_RC_DEFAULT)) |
122 | ops = ieee80211_try_rate_control_ops_get(CONFIG_MAC80211_RC_DEFAULT); | 123 | ops = ieee80211_try_rate_control_ops_get(CONFIG_MAC80211_RC_DEFAULT); |
124 | kparam_unblock_sysfs_write(ieee80211_default_rc_algo); | ||
123 | 125 | ||
124 | return ops; | 126 | return ops; |
125 | } | 127 | } |
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 7043b294bb67..8e22bd345e71 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h | |||
@@ -597,12 +597,6 @@ extern unsigned rxrpc_debug; | |||
597 | #define dbgprintk(FMT,...) \ | 597 | #define dbgprintk(FMT,...) \ |
598 | printk("[%-6.6s] "FMT"\n", current->comm ,##__VA_ARGS__) | 598 | printk("[%-6.6s] "FMT"\n", current->comm ,##__VA_ARGS__) |
599 | 599 | ||
600 | /* make sure we maintain the format strings, even when debugging is disabled */ | ||
601 | static inline __attribute__((format(printf,1,2))) | ||
602 | void _dbprintk(const char *fmt, ...) | ||
603 | { | ||
604 | } | ||
605 | |||
606 | #define kenter(FMT,...) dbgprintk("==> %s("FMT")",__func__ ,##__VA_ARGS__) | 600 | #define kenter(FMT,...) dbgprintk("==> %s("FMT")",__func__ ,##__VA_ARGS__) |
607 | #define kleave(FMT,...) dbgprintk("<== %s()"FMT"",__func__ ,##__VA_ARGS__) | 601 | #define kleave(FMT,...) dbgprintk("<== %s()"FMT"",__func__ ,##__VA_ARGS__) |
608 | #define kdebug(FMT,...) dbgprintk(" "FMT ,##__VA_ARGS__) | 602 | #define kdebug(FMT,...) dbgprintk(" "FMT ,##__VA_ARGS__) |
@@ -655,11 +649,11 @@ do { \ | |||
655 | } while (0) | 649 | } while (0) |
656 | 650 | ||
657 | #else | 651 | #else |
658 | #define _enter(FMT,...) _dbprintk("==> %s("FMT")",__func__ ,##__VA_ARGS__) | 652 | #define _enter(FMT,...) no_printk("==> %s("FMT")",__func__ ,##__VA_ARGS__) |
659 | #define _leave(FMT,...) _dbprintk("<== %s()"FMT"",__func__ ,##__VA_ARGS__) | 653 | #define _leave(FMT,...) no_printk("<== %s()"FMT"",__func__ ,##__VA_ARGS__) |
660 | #define _debug(FMT,...) _dbprintk(" "FMT ,##__VA_ARGS__) | 654 | #define _debug(FMT,...) no_printk(" "FMT ,##__VA_ARGS__) |
661 | #define _proto(FMT,...) _dbprintk("### "FMT ,##__VA_ARGS__) | 655 | #define _proto(FMT,...) no_printk("### "FMT ,##__VA_ARGS__) |
662 | #define _net(FMT,...) _dbprintk("@@@ "FMT ,##__VA_ARGS__) | 656 | #define _net(FMT,...) no_printk("@@@ "FMT ,##__VA_ARGS__) |
663 | #endif | 657 | #endif |
664 | 658 | ||
665 | /* | 659 | /* |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 880d0de3f50f..36cb66022a27 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -39,7 +39,7 @@ static LIST_HEAD(cred_unused); | |||
39 | static unsigned long number_cred_unused; | 39 | static unsigned long number_cred_unused; |
40 | 40 | ||
41 | #define MAX_HASHTABLE_BITS (10) | 41 | #define MAX_HASHTABLE_BITS (10) |
42 | static int param_set_hashtbl_sz(const char *val, struct kernel_param *kp) | 42 | static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp) |
43 | { | 43 | { |
44 | unsigned long num; | 44 | unsigned long num; |
45 | unsigned int nbits; | 45 | unsigned int nbits; |
@@ -61,7 +61,7 @@ out_inval: | |||
61 | return -EINVAL; | 61 | return -EINVAL; |
62 | } | 62 | } |
63 | 63 | ||
64 | static int param_get_hashtbl_sz(char *buffer, struct kernel_param *kp) | 64 | static int param_get_hashtbl_sz(char *buffer, const struct kernel_param *kp) |
65 | { | 65 | { |
66 | unsigned int nbits; | 66 | unsigned int nbits; |
67 | 67 | ||
@@ -71,6 +71,11 @@ static int param_get_hashtbl_sz(char *buffer, struct kernel_param *kp) | |||
71 | 71 | ||
72 | #define param_check_hashtbl_sz(name, p) __param_check(name, p, unsigned int); | 72 | #define param_check_hashtbl_sz(name, p) __param_check(name, p, unsigned int); |
73 | 73 | ||
74 | static struct kernel_param_ops param_ops_hashtbl_sz = { | ||
75 | .set = param_set_hashtbl_sz, | ||
76 | .get = param_get_hashtbl_sz, | ||
77 | }; | ||
78 | |||
74 | module_param_named(auth_hashtable_size, auth_hashbits, hashtbl_sz, 0644); | 79 | module_param_named(auth_hashtable_size, auth_hashbits, hashtbl_sz, 0644); |
75 | MODULE_PARM_DESC(auth_hashtable_size, "RPC credential cache hashtable size"); | 80 | MODULE_PARM_DESC(auth_hashtable_size, "RPC credential cache hashtable size"); |
76 | 81 | ||
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 7ca65c7005ea..49a62f0c4b87 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -2577,7 +2577,8 @@ void cleanup_socket_xprt(void) | |||
2577 | xprt_unregister_transport(&xs_bc_tcp_transport); | 2577 | xprt_unregister_transport(&xs_bc_tcp_transport); |
2578 | } | 2578 | } |
2579 | 2579 | ||
2580 | static int param_set_uint_minmax(const char *val, struct kernel_param *kp, | 2580 | static int param_set_uint_minmax(const char *val, |
2581 | const struct kernel_param *kp, | ||
2581 | unsigned int min, unsigned int max) | 2582 | unsigned int min, unsigned int max) |
2582 | { | 2583 | { |
2583 | unsigned long num; | 2584 | unsigned long num; |
@@ -2592,34 +2593,37 @@ static int param_set_uint_minmax(const char *val, struct kernel_param *kp, | |||
2592 | return 0; | 2593 | return 0; |
2593 | } | 2594 | } |
2594 | 2595 | ||
2595 | static int param_set_portnr(const char *val, struct kernel_param *kp) | 2596 | static int param_set_portnr(const char *val, const struct kernel_param *kp) |
2596 | { | 2597 | { |
2597 | return param_set_uint_minmax(val, kp, | 2598 | return param_set_uint_minmax(val, kp, |
2598 | RPC_MIN_RESVPORT, | 2599 | RPC_MIN_RESVPORT, |
2599 | RPC_MAX_RESVPORT); | 2600 | RPC_MAX_RESVPORT); |
2600 | } | 2601 | } |
2601 | 2602 | ||
2602 | static int param_get_portnr(char *buffer, struct kernel_param *kp) | 2603 | static struct kernel_param_ops param_ops_portnr = { |
2603 | { | 2604 | .set = param_set_portnr, |
2604 | return param_get_uint(buffer, kp); | 2605 | .get = param_get_uint, |
2605 | } | 2606 | }; |
2607 | |||
2606 | #define param_check_portnr(name, p) \ | 2608 | #define param_check_portnr(name, p) \ |
2607 | __param_check(name, p, unsigned int); | 2609 | __param_check(name, p, unsigned int); |
2608 | 2610 | ||
2609 | module_param_named(min_resvport, xprt_min_resvport, portnr, 0644); | 2611 | module_param_named(min_resvport, xprt_min_resvport, portnr, 0644); |
2610 | module_param_named(max_resvport, xprt_max_resvport, portnr, 0644); | 2612 | module_param_named(max_resvport, xprt_max_resvport, portnr, 0644); |
2611 | 2613 | ||
2612 | static int param_set_slot_table_size(const char *val, struct kernel_param *kp) | 2614 | static int param_set_slot_table_size(const char *val, |
2615 | const struct kernel_param *kp) | ||
2613 | { | 2616 | { |
2614 | return param_set_uint_minmax(val, kp, | 2617 | return param_set_uint_minmax(val, kp, |
2615 | RPC_MIN_SLOT_TABLE, | 2618 | RPC_MIN_SLOT_TABLE, |
2616 | RPC_MAX_SLOT_TABLE); | 2619 | RPC_MAX_SLOT_TABLE); |
2617 | } | 2620 | } |
2618 | 2621 | ||
2619 | static int param_get_slot_table_size(char *buffer, struct kernel_param *kp) | 2622 | static struct kernel_param_ops param_ops_slot_table_size = { |
2620 | { | 2623 | .set = param_set_slot_table_size, |
2621 | return param_get_uint(buffer, kp); | 2624 | .get = param_get_uint, |
2622 | } | 2625 | }; |
2626 | |||
2623 | #define param_check_slot_table_size(name, p) \ | 2627 | #define param_check_slot_table_size(name, p) \ |
2624 | __param_check(name, p, unsigned int); | 2628 | __param_check(name, p, unsigned int); |
2625 | 2629 | ||
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 7acbdd8fcaed..1ec7158b6c1f 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
@@ -790,6 +790,7 @@ static const char *section_white_list[] = | |||
790 | { | 790 | { |
791 | ".comment*", | 791 | ".comment*", |
792 | ".debug*", | 792 | ".debug*", |
793 | ".GCC-command-line", /* mn10300 */ | ||
793 | ".mdebug*", /* alpha, score, mips etc. */ | 794 | ".mdebug*", /* alpha, score, mips etc. */ |
794 | ".pdr", /* alpha, score, mips etc. */ | 795 | ".pdr", /* alpha, score, mips etc. */ |
795 | ".stab*", | 796 | ".stab*", |
@@ -1034,6 +1035,13 @@ static const struct sectioncheck *section_mismatch( | |||
1034 | * fromsec = .data* | 1035 | * fromsec = .data* |
1035 | * atsym =__param* | 1036 | * atsym =__param* |
1036 | * | 1037 | * |
1038 | * Pattern 1a: | ||
1039 | * module_param_call() ops can refer to __init set function if permissions=0 | ||
1040 | * The pattern is identified by: | ||
1041 | * tosec = .init.text | ||
1042 | * fromsec = .data* | ||
1043 | * atsym = __param_ops_* | ||
1044 | * | ||
1037 | * Pattern 2: | 1045 | * Pattern 2: |
1038 | * Many drivers utilise a *driver container with references to | 1046 | * Many drivers utilise a *driver container with references to |
1039 | * add, remove, probe functions etc. | 1047 | * add, remove, probe functions etc. |
@@ -1068,6 +1076,12 @@ static int secref_whitelist(const struct sectioncheck *mismatch, | |||
1068 | (strncmp(fromsym, "__param", strlen("__param")) == 0)) | 1076 | (strncmp(fromsym, "__param", strlen("__param")) == 0)) |
1069 | return 0; | 1077 | return 0; |
1070 | 1078 | ||
1079 | /* Check for pattern 1a */ | ||
1080 | if (strcmp(tosec, ".init.text") == 0 && | ||
1081 | match(fromsec, data_sections) && | ||
1082 | (strncmp(fromsym, "__param_ops_", strlen("__param_ops_")) == 0)) | ||
1083 | return 0; | ||
1084 | |||
1071 | /* Check for pattern 2 */ | 1085 | /* Check for pattern 2 */ |
1072 | if (match(tosec, init_exit_sections) && | 1086 | if (match(tosec, init_exit_sections) && |
1073 | match(fromsec, data_sections) && | 1087 | match(fromsec, data_sections) && |
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 8db33a8b50c4..d5666d3cc21b 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c | |||
@@ -667,17 +667,29 @@ static struct security_operations apparmor_ops = { | |||
667 | * AppArmor sysfs module parameters | 667 | * AppArmor sysfs module parameters |
668 | */ | 668 | */ |
669 | 669 | ||
670 | static int param_set_aabool(const char *val, struct kernel_param *kp); | 670 | static int param_set_aabool(const char *val, const struct kernel_param *kp); |
671 | static int param_get_aabool(char *buffer, struct kernel_param *kp); | 671 | static int param_get_aabool(char *buffer, const struct kernel_param *kp); |
672 | #define param_check_aabool(name, p) __param_check(name, p, int) | 672 | #define param_check_aabool(name, p) __param_check(name, p, int) |
673 | static struct kernel_param_ops param_ops_aabool = { | ||
674 | .set = param_set_aabool, | ||
675 | .get = param_get_aabool | ||
676 | }; | ||
673 | 677 | ||
674 | static int param_set_aauint(const char *val, struct kernel_param *kp); | 678 | static int param_set_aauint(const char *val, const struct kernel_param *kp); |
675 | static int param_get_aauint(char *buffer, struct kernel_param *kp); | 679 | static int param_get_aauint(char *buffer, const struct kernel_param *kp); |
676 | #define param_check_aauint(name, p) __param_check(name, p, int) | 680 | #define param_check_aauint(name, p) __param_check(name, p, int) |
681 | static struct kernel_param_ops param_ops_aauint = { | ||
682 | .set = param_set_aauint, | ||
683 | .get = param_get_aauint | ||
684 | }; | ||
677 | 685 | ||
678 | static int param_set_aalockpolicy(const char *val, struct kernel_param *kp); | 686 | static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp); |
679 | static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp); | 687 | static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp); |
680 | #define param_check_aalockpolicy(name, p) __param_check(name, p, int) | 688 | #define param_check_aalockpolicy(name, p) __param_check(name, p, int) |
689 | static struct kernel_param_ops param_ops_aalockpolicy = { | ||
690 | .set = param_set_aalockpolicy, | ||
691 | .get = param_get_aalockpolicy | ||
692 | }; | ||
681 | 693 | ||
682 | static int param_set_audit(const char *val, struct kernel_param *kp); | 694 | static int param_set_audit(const char *val, struct kernel_param *kp); |
683 | static int param_get_audit(char *buffer, struct kernel_param *kp); | 695 | static int param_get_audit(char *buffer, struct kernel_param *kp); |
@@ -751,7 +763,7 @@ static int __init apparmor_enabled_setup(char *str) | |||
751 | __setup("apparmor=", apparmor_enabled_setup); | 763 | __setup("apparmor=", apparmor_enabled_setup); |
752 | 764 | ||
753 | /* set global flag turning off the ability to load policy */ | 765 | /* set global flag turning off the ability to load policy */ |
754 | static int param_set_aalockpolicy(const char *val, struct kernel_param *kp) | 766 | static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp) |
755 | { | 767 | { |
756 | if (!capable(CAP_MAC_ADMIN)) | 768 | if (!capable(CAP_MAC_ADMIN)) |
757 | return -EPERM; | 769 | return -EPERM; |
@@ -760,35 +772,35 @@ static int param_set_aalockpolicy(const char *val, struct kernel_param *kp) | |||
760 | return param_set_bool(val, kp); | 772 | return param_set_bool(val, kp); |
761 | } | 773 | } |
762 | 774 | ||
763 | static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp) | 775 | static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp) |
764 | { | 776 | { |
765 | if (!capable(CAP_MAC_ADMIN)) | 777 | if (!capable(CAP_MAC_ADMIN)) |
766 | return -EPERM; | 778 | return -EPERM; |
767 | return param_get_bool(buffer, kp); | 779 | return param_get_bool(buffer, kp); |
768 | } | 780 | } |
769 | 781 | ||
770 | static int param_set_aabool(const char *val, struct kernel_param *kp) | 782 | static int param_set_aabool(const char *val, const struct kernel_param *kp) |
771 | { | 783 | { |
772 | if (!capable(CAP_MAC_ADMIN)) | 784 | if (!capable(CAP_MAC_ADMIN)) |
773 | return -EPERM; | 785 | return -EPERM; |
774 | return param_set_bool(val, kp); | 786 | return param_set_bool(val, kp); |
775 | } | 787 | } |
776 | 788 | ||
777 | static int param_get_aabool(char *buffer, struct kernel_param *kp) | 789 | static int param_get_aabool(char *buffer, const struct kernel_param *kp) |
778 | { | 790 | { |
779 | if (!capable(CAP_MAC_ADMIN)) | 791 | if (!capable(CAP_MAC_ADMIN)) |
780 | return -EPERM; | 792 | return -EPERM; |
781 | return param_get_bool(buffer, kp); | 793 | return param_get_bool(buffer, kp); |
782 | } | 794 | } |
783 | 795 | ||
784 | static int param_set_aauint(const char *val, struct kernel_param *kp) | 796 | static int param_set_aauint(const char *val, const struct kernel_param *kp) |
785 | { | 797 | { |
786 | if (!capable(CAP_MAC_ADMIN)) | 798 | if (!capable(CAP_MAC_ADMIN)) |
787 | return -EPERM; | 799 | return -EPERM; |
788 | return param_set_uint(val, kp); | 800 | return param_set_uint(val, kp); |
789 | } | 801 | } |
790 | 802 | ||
791 | static int param_get_aauint(char *buffer, struct kernel_param *kp) | 803 | static int param_get_aauint(char *buffer, const struct kernel_param *kp) |
792 | { | 804 | { |
793 | if (!capable(CAP_MAC_ADMIN)) | 805 | if (!capable(CAP_MAC_ADMIN)) |
794 | return -EPERM; | 806 | return -EPERM; |
diff --git a/security/keys/internal.h b/security/keys/internal.h index addb67b169f4..56a133d8f37d 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -15,11 +15,6 @@ | |||
15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
16 | #include <linux/key-type.h> | 16 | #include <linux/key-type.h> |
17 | 17 | ||
18 | static inline __attribute__((format(printf, 1, 2))) | ||
19 | void no_printk(const char *fmt, ...) | ||
20 | { | ||
21 | } | ||
22 | |||
23 | #ifdef __KDEBUG | 18 | #ifdef __KDEBUG |
24 | #define kenter(FMT, ...) \ | 19 | #define kenter(FMT, ...) \ |
25 | printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__) | 20 | printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__) |
diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c index 99ca7120e269..7487eb76e034 100644 --- a/sound/aoa/soundbus/core.c +++ b/sound/aoa/soundbus/core.c | |||
@@ -59,7 +59,7 @@ static int soundbus_probe(struct device *dev) | |||
59 | static int soundbus_uevent(struct device *dev, struct kobj_uevent_env *env) | 59 | static int soundbus_uevent(struct device *dev, struct kobj_uevent_env *env) |
60 | { | 60 | { |
61 | struct soundbus_dev * soundbus_dev; | 61 | struct soundbus_dev * soundbus_dev; |
62 | struct of_device * of; | 62 | struct platform_device * of; |
63 | const char *compat; | 63 | const char *compat; |
64 | int retval = 0; | 64 | int retval = 0; |
65 | int cplen, seen = 0; | 65 | int cplen, seen = 0; |
diff --git a/sound/aoa/soundbus/soundbus.h b/sound/aoa/soundbus/soundbus.h index a0f223c13f66..adecbf36f4f6 100644 --- a/sound/aoa/soundbus/soundbus.h +++ b/sound/aoa/soundbus/soundbus.h | |||
@@ -141,7 +141,7 @@ struct soundbus_dev { | |||
141 | struct list_head onbuslist; | 141 | struct list_head onbuslist; |
142 | 142 | ||
143 | /* the of device it represents */ | 143 | /* the of device it represents */ |
144 | struct of_device ofdev; | 144 | struct platform_device ofdev; |
145 | 145 | ||
146 | /* what modules go by */ | 146 | /* what modules go by */ |
147 | char modalias[32]; | 147 | char modalias[32]; |
diff --git a/sound/aoa/soundbus/sysfs.c b/sound/aoa/soundbus/sysfs.c index 6496e754f00a..e0980b5c2cd8 100644 --- a/sound/aoa/soundbus/sysfs.c +++ b/sound/aoa/soundbus/sysfs.c | |||
@@ -16,7 +16,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, | |||
16 | char *buf) | 16 | char *buf) |
17 | { | 17 | { |
18 | struct soundbus_dev *sdev = to_soundbus_device(dev); | 18 | struct soundbus_dev *sdev = to_soundbus_device(dev); |
19 | struct of_device *of = &sdev->ofdev; | 19 | struct platform_device *of = &sdev->ofdev; |
20 | int length; | 20 | int length; |
21 | 21 | ||
22 | if (*sdev->modalias) { | 22 | if (*sdev->modalias) { |
diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c index 24793c5b65ac..4d2a6ae978f7 100644 --- a/sound/oss/ad1848.c +++ b/sound/oss/ad1848.c | |||
@@ -716,7 +716,7 @@ static int ad1848_mixer_ioctl(int dev, unsigned int cmd, void __user *arg) | |||
716 | 716 | ||
717 | default: | 717 | default: |
718 | if (get_user(val, (int __user *)arg)) | 718 | if (get_user(val, (int __user *)arg)) |
719 | return -EFAULT; | 719 | return -EFAULT; |
720 | val = ad1848_mixer_set(devc, cmd & 0xff, val); | 720 | val = ad1848_mixer_set(devc, cmd & 0xff, val); |
721 | break; | 721 | break; |
722 | } | 722 | } |
diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c index c4a4cdc07ab9..c6f2621221ba 100644 --- a/sound/oss/au1550_ac97.c +++ b/sound/oss/au1550_ac97.c | |||
@@ -50,7 +50,6 @@ | |||
50 | #include <linux/poll.h> | 50 | #include <linux/poll.h> |
51 | #include <linux/bitops.h> | 51 | #include <linux/bitops.h> |
52 | #include <linux/spinlock.h> | 52 | #include <linux/spinlock.h> |
53 | #include <linux/smp_lock.h> | ||
54 | #include <linux/ac97_codec.h> | 53 | #include <linux/ac97_codec.h> |
55 | #include <linux/mutex.h> | 54 | #include <linux/mutex.h> |
56 | 55 | ||
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index a7802b99436c..720a81d711e3 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -971,6 +971,36 @@ static void restore_init_pincfgs(struct hda_codec *codec) | |||
971 | } | 971 | } |
972 | 972 | ||
973 | /* | 973 | /* |
974 | * audio-converter setup caches | ||
975 | */ | ||
976 | struct hda_cvt_setup { | ||
977 | hda_nid_t nid; | ||
978 | u8 stream_tag; | ||
979 | u8 channel_id; | ||
980 | u16 format_id; | ||
981 | unsigned char active; /* cvt is currently used */ | ||
982 | unsigned char dirty; /* setups should be cleared */ | ||
983 | }; | ||
984 | |||
985 | /* get or create a cache entry for the given audio converter NID */ | ||
986 | static struct hda_cvt_setup * | ||
987 | get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid) | ||
988 | { | ||
989 | struct hda_cvt_setup *p; | ||
990 | int i; | ||
991 | |||
992 | for (i = 0; i < codec->cvt_setups.used; i++) { | ||
993 | p = snd_array_elem(&codec->cvt_setups, i); | ||
994 | if (p->nid == nid) | ||
995 | return p; | ||
996 | } | ||
997 | p = snd_array_new(&codec->cvt_setups); | ||
998 | if (p) | ||
999 | p->nid = nid; | ||
1000 | return p; | ||
1001 | } | ||
1002 | |||
1003 | /* | ||
974 | * codec destructor | 1004 | * codec destructor |
975 | */ | 1005 | */ |
976 | static void snd_hda_codec_free(struct hda_codec *codec) | 1006 | static void snd_hda_codec_free(struct hda_codec *codec) |
@@ -1038,12 +1068,14 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, | |||
1038 | codec->addr = codec_addr; | 1068 | codec->addr = codec_addr; |
1039 | mutex_init(&codec->spdif_mutex); | 1069 | mutex_init(&codec->spdif_mutex); |
1040 | mutex_init(&codec->control_mutex); | 1070 | mutex_init(&codec->control_mutex); |
1071 | mutex_init(&codec->prepare_mutex); | ||
1041 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); | 1072 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); |
1042 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | 1073 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); |
1043 | snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32); | 1074 | snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32); |
1044 | snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32); | 1075 | snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32); |
1045 | snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); | 1076 | snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); |
1046 | snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); | 1077 | snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); |
1078 | snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8); | ||
1047 | if (codec->bus->modelname) { | 1079 | if (codec->bus->modelname) { |
1048 | codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); | 1080 | codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); |
1049 | if (!codec->modelname) { | 1081 | if (!codec->modelname) { |
@@ -1181,16 +1213,51 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
1181 | u32 stream_tag, | 1213 | u32 stream_tag, |
1182 | int channel_id, int format) | 1214 | int channel_id, int format) |
1183 | { | 1215 | { |
1216 | struct hda_cvt_setup *p; | ||
1217 | unsigned int oldval, newval; | ||
1218 | int i; | ||
1219 | |||
1184 | if (!nid) | 1220 | if (!nid) |
1185 | return; | 1221 | return; |
1186 | 1222 | ||
1187 | snd_printdd("hda_codec_setup_stream: " | 1223 | snd_printdd("hda_codec_setup_stream: " |
1188 | "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n", | 1224 | "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n", |
1189 | nid, stream_tag, channel_id, format); | 1225 | nid, stream_tag, channel_id, format); |
1190 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, | 1226 | p = get_hda_cvt_setup(codec, nid); |
1191 | (stream_tag << 4) | channel_id); | 1227 | if (!p) |
1192 | msleep(1); | 1228 | return; |
1193 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format); | 1229 | /* update the stream-id if changed */ |
1230 | if (p->stream_tag != stream_tag || p->channel_id != channel_id) { | ||
1231 | oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); | ||
1232 | newval = (stream_tag << 4) | channel_id; | ||
1233 | if (oldval != newval) | ||
1234 | snd_hda_codec_write(codec, nid, 0, | ||
1235 | AC_VERB_SET_CHANNEL_STREAMID, | ||
1236 | newval); | ||
1237 | p->stream_tag = stream_tag; | ||
1238 | p->channel_id = channel_id; | ||
1239 | } | ||
1240 | /* update the format-id if changed */ | ||
1241 | if (p->format_id != format) { | ||
1242 | oldval = snd_hda_codec_read(codec, nid, 0, | ||
1243 | AC_VERB_GET_STREAM_FORMAT, 0); | ||
1244 | if (oldval != format) { | ||
1245 | msleep(1); | ||
1246 | snd_hda_codec_write(codec, nid, 0, | ||
1247 | AC_VERB_SET_STREAM_FORMAT, | ||
1248 | format); | ||
1249 | } | ||
1250 | p->format_id = format; | ||
1251 | } | ||
1252 | p->active = 1; | ||
1253 | p->dirty = 0; | ||
1254 | |||
1255 | /* make other inactive cvts with the same stream-tag dirty */ | ||
1256 | for (i = 0; i < codec->cvt_setups.used; i++) { | ||
1257 | p = snd_array_elem(&codec->cvt_setups, i); | ||
1258 | if (!p->active && p->stream_tag == stream_tag) | ||
1259 | p->dirty = 1; | ||
1260 | } | ||
1194 | } | 1261 | } |
1195 | EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream); | 1262 | EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream); |
1196 | 1263 | ||
@@ -1201,17 +1268,54 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream); | |||
1201 | */ | 1268 | */ |
1202 | void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid) | 1269 | void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid) |
1203 | { | 1270 | { |
1271 | struct hda_cvt_setup *p; | ||
1272 | |||
1204 | if (!nid) | 1273 | if (!nid) |
1205 | return; | 1274 | return; |
1206 | 1275 | ||
1207 | snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid); | 1276 | snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid); |
1277 | /* here we just clear the active flag; actual clean-ups will be done | ||
1278 | * in purify_inactive_streams() | ||
1279 | */ | ||
1280 | p = get_hda_cvt_setup(codec, nid); | ||
1281 | if (p) | ||
1282 | p->active = 0; | ||
1283 | } | ||
1284 | EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream); | ||
1285 | |||
1286 | static void really_cleanup_stream(struct hda_codec *codec, | ||
1287 | struct hda_cvt_setup *q) | ||
1288 | { | ||
1289 | hda_nid_t nid = q->nid; | ||
1208 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0); | 1290 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0); |
1209 | #if 0 /* keep the format */ | ||
1210 | msleep(1); | ||
1211 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0); | 1291 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0); |
1212 | #endif | 1292 | memset(q, 0, sizeof(*q)); |
1293 | q->nid = nid; | ||
1294 | } | ||
1295 | |||
1296 | /* clean up the all conflicting obsolete streams */ | ||
1297 | static void purify_inactive_streams(struct hda_codec *codec) | ||
1298 | { | ||
1299 | int i; | ||
1300 | |||
1301 | for (i = 0; i < codec->cvt_setups.used; i++) { | ||
1302 | struct hda_cvt_setup *p = snd_array_elem(&codec->cvt_setups, i); | ||
1303 | if (p->dirty) | ||
1304 | really_cleanup_stream(codec, p); | ||
1305 | } | ||
1306 | } | ||
1307 | |||
1308 | /* clean up all streams; called from suspend */ | ||
1309 | static void hda_cleanup_all_streams(struct hda_codec *codec) | ||
1310 | { | ||
1311 | int i; | ||
1312 | |||
1313 | for (i = 0; i < codec->cvt_setups.used; i++) { | ||
1314 | struct hda_cvt_setup *p = snd_array_elem(&codec->cvt_setups, i); | ||
1315 | if (p->stream_tag) | ||
1316 | really_cleanup_stream(codec, p); | ||
1317 | } | ||
1213 | } | 1318 | } |
1214 | EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream); | ||
1215 | 1319 | ||
1216 | /* | 1320 | /* |
1217 | * amp access functions | 1321 | * amp access functions |
@@ -2928,6 +3032,7 @@ static void hda_call_codec_suspend(struct hda_codec *codec) | |||
2928 | { | 3032 | { |
2929 | if (codec->patch_ops.suspend) | 3033 | if (codec->patch_ops.suspend) |
2930 | codec->patch_ops.suspend(codec, PMSG_SUSPEND); | 3034 | codec->patch_ops.suspend(codec, PMSG_SUSPEND); |
3035 | hda_cleanup_all_streams(codec); | ||
2931 | hda_set_power_state(codec, | 3036 | hda_set_power_state(codec, |
2932 | codec->afg ? codec->afg : codec->mfg, | 3037 | codec->afg ? codec->afg : codec->mfg, |
2933 | AC_PWRST_D3); | 3038 | AC_PWRST_D3); |
@@ -3377,6 +3482,35 @@ static int set_pcm_default_values(struct hda_codec *codec, | |||
3377 | return 0; | 3482 | return 0; |
3378 | } | 3483 | } |
3379 | 3484 | ||
3485 | /* | ||
3486 | * codec prepare/cleanup entries | ||
3487 | */ | ||
3488 | int snd_hda_codec_prepare(struct hda_codec *codec, | ||
3489 | struct hda_pcm_stream *hinfo, | ||
3490 | unsigned int stream, | ||
3491 | unsigned int format, | ||
3492 | struct snd_pcm_substream *substream) | ||
3493 | { | ||
3494 | int ret; | ||
3495 | mutex_lock(&codec->prepare_mutex); | ||
3496 | ret = hinfo->ops.prepare(hinfo, codec, stream, format, substream); | ||
3497 | if (ret >= 0) | ||
3498 | purify_inactive_streams(codec); | ||
3499 | mutex_unlock(&codec->prepare_mutex); | ||
3500 | return ret; | ||
3501 | } | ||
3502 | EXPORT_SYMBOL_HDA(snd_hda_codec_prepare); | ||
3503 | |||
3504 | void snd_hda_codec_cleanup(struct hda_codec *codec, | ||
3505 | struct hda_pcm_stream *hinfo, | ||
3506 | struct snd_pcm_substream *substream) | ||
3507 | { | ||
3508 | mutex_lock(&codec->prepare_mutex); | ||
3509 | hinfo->ops.cleanup(hinfo, codec, substream); | ||
3510 | mutex_unlock(&codec->prepare_mutex); | ||
3511 | } | ||
3512 | EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup); | ||
3513 | |||
3380 | /* global */ | 3514 | /* global */ |
3381 | const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = { | 3515 | const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = { |
3382 | "Audio", "SPDIF", "HDMI", "Modem" | 3516 | "Audio", "SPDIF", "HDMI", "Modem" |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 0328cf55cdba..3f7a479881e5 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -826,12 +826,14 @@ struct hda_codec { | |||
826 | 826 | ||
827 | struct mutex spdif_mutex; | 827 | struct mutex spdif_mutex; |
828 | struct mutex control_mutex; | 828 | struct mutex control_mutex; |
829 | struct mutex prepare_mutex; | ||
829 | unsigned int spdif_status; /* IEC958 status bits */ | 830 | unsigned int spdif_status; /* IEC958 status bits */ |
830 | unsigned short spdif_ctls; /* SPDIF control bits */ | 831 | unsigned short spdif_ctls; /* SPDIF control bits */ |
831 | unsigned int spdif_in_enable; /* SPDIF input enable? */ | 832 | unsigned int spdif_in_enable; /* SPDIF input enable? */ |
832 | hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ | 833 | hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ |
833 | struct snd_array init_pins; /* initial (BIOS) pin configurations */ | 834 | struct snd_array init_pins; /* initial (BIOS) pin configurations */ |
834 | struct snd_array driver_pins; /* pin configs set by codec parser */ | 835 | struct snd_array driver_pins; /* pin configs set by codec parser */ |
836 | struct snd_array cvt_setups; /* audio convert setups */ | ||
835 | 837 | ||
836 | #ifdef CONFIG_SND_HDA_HWDEP | 838 | #ifdef CONFIG_SND_HDA_HWDEP |
837 | struct snd_hwdep *hwdep; /* assigned hwdep device */ | 839 | struct snd_hwdep *hwdep; /* assigned hwdep device */ |
@@ -948,6 +950,16 @@ int snd_hda_codec_build_controls(struct hda_codec *codec); | |||
948 | */ | 950 | */ |
949 | int snd_hda_build_pcms(struct hda_bus *bus); | 951 | int snd_hda_build_pcms(struct hda_bus *bus); |
950 | int snd_hda_codec_build_pcms(struct hda_codec *codec); | 952 | int snd_hda_codec_build_pcms(struct hda_codec *codec); |
953 | |||
954 | int snd_hda_codec_prepare(struct hda_codec *codec, | ||
955 | struct hda_pcm_stream *hinfo, | ||
956 | unsigned int stream, | ||
957 | unsigned int format, | ||
958 | struct snd_pcm_substream *substream); | ||
959 | void snd_hda_codec_cleanup(struct hda_codec *codec, | ||
960 | struct hda_pcm_stream *hinfo, | ||
961 | struct snd_pcm_substream *substream); | ||
962 | |||
951 | void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, | 963 | void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, |
952 | u32 stream_tag, | 964 | u32 stream_tag, |
953 | int channel_id, int format); | 965 | int channel_id, int format); |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 66d420212d9a..1053fff4bd0a 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -1634,7 +1634,7 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) | |||
1634 | azx_dev->period_bytes = 0; | 1634 | azx_dev->period_bytes = 0; |
1635 | azx_dev->format_val = 0; | 1635 | azx_dev->format_val = 0; |
1636 | 1636 | ||
1637 | hinfo->ops.cleanup(hinfo, apcm->codec, substream); | 1637 | snd_hda_codec_cleanup(apcm->codec, hinfo, substream); |
1638 | 1638 | ||
1639 | return snd_pcm_lib_free_pages(substream); | 1639 | return snd_pcm_lib_free_pages(substream); |
1640 | } | 1640 | } |
@@ -1688,8 +1688,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
1688 | else | 1688 | else |
1689 | azx_dev->fifo_size = 0; | 1689 | azx_dev->fifo_size = 0; |
1690 | 1690 | ||
1691 | return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag, | 1691 | return snd_hda_codec_prepare(apcm->codec, hinfo, azx_dev->stream_tag, |
1692 | azx_dev->format_val, substream); | 1692 | azx_dev->format_val, substream); |
1693 | } | 1693 | } |
1694 | 1694 | ||
1695 | static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | 1695 | static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index df8b19b17308..f7e234e5ee96 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -3206,6 +3206,8 @@ static struct hda_codec_preset snd_hda_preset_conexant[] = { | |||
3206 | .patch = patch_cxt5066 }, | 3206 | .patch = patch_cxt5066 }, |
3207 | { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)", | 3207 | { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)", |
3208 | .patch = patch_cxt5066 }, | 3208 | .patch = patch_cxt5066 }, |
3209 | { .id = 0x14f15068, .name = "CX20584", | ||
3210 | .patch = patch_cxt5066 }, | ||
3209 | { .id = 0x14f15069, .name = "CX20585", | 3211 | { .id = 0x14f15069, .name = "CX20585", |
3210 | .patch = patch_cxt5066 }, | 3212 | .patch = patch_cxt5066 }, |
3211 | {} /* terminator */ | 3213 | {} /* terminator */ |
@@ -3216,6 +3218,7 @@ MODULE_ALIAS("snd-hda-codec-id:14f15047"); | |||
3216 | MODULE_ALIAS("snd-hda-codec-id:14f15051"); | 3218 | MODULE_ALIAS("snd-hda-codec-id:14f15051"); |
3217 | MODULE_ALIAS("snd-hda-codec-id:14f15066"); | 3219 | MODULE_ALIAS("snd-hda-codec-id:14f15066"); |
3218 | MODULE_ALIAS("snd-hda-codec-id:14f15067"); | 3220 | MODULE_ALIAS("snd-hda-codec-id:14f15067"); |
3221 | MODULE_ALIAS("snd-hda-codec-id:14f15068"); | ||
3219 | MODULE_ALIAS("snd-hda-codec-id:14f15069"); | 3222 | MODULE_ALIAS("snd-hda-codec-id:14f15069"); |
3220 | 3223 | ||
3221 | MODULE_LICENSE("GPL"); | 3224 | MODULE_LICENSE("GPL"); |
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c index a281836fd472..77e2b4028b9f 100644 --- a/sound/pci/hda/patch_nvhdmi.c +++ b/sound/pci/hda/patch_nvhdmi.c | |||
@@ -540,26 +540,32 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) | |||
540 | * patch entries | 540 | * patch entries |
541 | */ | 541 | */ |
542 | static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { | 542 | static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { |
543 | { .id = 0x10de0002, .name = "MCP77/78 HDMI", | 543 | { .id = 0x10de0002, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, |
544 | .patch = patch_nvhdmi_8ch_7x }, | 544 | { .id = 0x10de0003, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, |
545 | { .id = 0x10de0003, .name = "MCP77/78 HDMI", | 545 | { .id = 0x10de0005, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, |
546 | .patch = patch_nvhdmi_8ch_7x }, | 546 | { .id = 0x10de0006, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, |
547 | { .id = 0x10de0005, .name = "MCP77/78 HDMI", | 547 | { .id = 0x10de0007, .name = "MCP79/7A HDMI", .patch = patch_nvhdmi_8ch_7x }, |
548 | .patch = patch_nvhdmi_8ch_7x }, | 548 | { .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
549 | { .id = 0x10de0006, .name = "MCP77/78 HDMI", | 549 | { .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
550 | .patch = patch_nvhdmi_8ch_7x }, | 550 | { .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_nvhdmi_8ch_89 }, |
551 | { .id = 0x10de0007, .name = "MCP79/7A HDMI", | 551 | { .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
552 | .patch = patch_nvhdmi_8ch_7x }, | 552 | { .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
553 | { .id = 0x10de000a, .name = "GT220 HDMI", | 553 | { .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
554 | .patch = patch_nvhdmi_8ch_89 }, | 554 | { .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
555 | { .id = 0x10de000b, .name = "GT21x HDMI", | 555 | { .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
556 | .patch = patch_nvhdmi_8ch_89 }, | 556 | { .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
557 | { .id = 0x10de000c, .name = "MCP89 HDMI", | 557 | { .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
558 | .patch = patch_nvhdmi_8ch_89 }, | 558 | { .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
559 | { .id = 0x10de000d, .name = "GT240 HDMI", | 559 | { .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
560 | .patch = patch_nvhdmi_8ch_89 }, | 560 | { .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
561 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | 561 | { .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
562 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | 562 | { .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
563 | { .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
564 | { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
565 | { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
566 | { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
567 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | ||
568 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | ||
563 | {} /* terminator */ | 569 | {} /* terminator */ |
564 | }; | 570 | }; |
565 | 571 | ||
@@ -572,6 +578,21 @@ MODULE_ALIAS("snd-hda-codec-id:10de000a"); | |||
572 | MODULE_ALIAS("snd-hda-codec-id:10de000b"); | 578 | MODULE_ALIAS("snd-hda-codec-id:10de000b"); |
573 | MODULE_ALIAS("snd-hda-codec-id:10de000c"); | 579 | MODULE_ALIAS("snd-hda-codec-id:10de000c"); |
574 | MODULE_ALIAS("snd-hda-codec-id:10de000d"); | 580 | MODULE_ALIAS("snd-hda-codec-id:10de000d"); |
581 | MODULE_ALIAS("snd-hda-codec-id:10de0010"); | ||
582 | MODULE_ALIAS("snd-hda-codec-id:10de0011"); | ||
583 | MODULE_ALIAS("snd-hda-codec-id:10de0012"); | ||
584 | MODULE_ALIAS("snd-hda-codec-id:10de0013"); | ||
585 | MODULE_ALIAS("snd-hda-codec-id:10de0014"); | ||
586 | MODULE_ALIAS("snd-hda-codec-id:10de0018"); | ||
587 | MODULE_ALIAS("snd-hda-codec-id:10de0019"); | ||
588 | MODULE_ALIAS("snd-hda-codec-id:10de001a"); | ||
589 | MODULE_ALIAS("snd-hda-codec-id:10de001b"); | ||
590 | MODULE_ALIAS("snd-hda-codec-id:10de001c"); | ||
591 | MODULE_ALIAS("snd-hda-codec-id:10de0040"); | ||
592 | MODULE_ALIAS("snd-hda-codec-id:10de0041"); | ||
593 | MODULE_ALIAS("snd-hda-codec-id:10de0042"); | ||
594 | MODULE_ALIAS("snd-hda-codec-id:10de0043"); | ||
595 | MODULE_ALIAS("snd-hda-codec-id:10de0044"); | ||
575 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); | 596 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); |
576 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); | 597 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); |
577 | 598 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6ac53f7de549..55d6e5b6bb7d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -137,6 +137,7 @@ enum { | |||
137 | ALC269VB_DMIC, | 137 | ALC269VB_DMIC, |
138 | ALC269_FUJITSU, | 138 | ALC269_FUJITSU, |
139 | ALC269_LIFEBOOK, | 139 | ALC269_LIFEBOOK, |
140 | ALC271_ACER, | ||
140 | ALC269_AUTO, | 141 | ALC269_AUTO, |
141 | ALC269_MODEL_LAST /* last tag */ | 142 | ALC269_MODEL_LAST /* last tag */ |
142 | }; | 143 | }; |
@@ -7041,6 +7042,7 @@ static int patch_alc260(struct hda_codec *codec) | |||
7041 | 7042 | ||
7042 | spec->stream_analog_playback = &alc260_pcm_analog_playback; | 7043 | spec->stream_analog_playback = &alc260_pcm_analog_playback; |
7043 | spec->stream_analog_capture = &alc260_pcm_analog_capture; | 7044 | spec->stream_analog_capture = &alc260_pcm_analog_capture; |
7045 | spec->stream_analog_alt_capture = &alc260_pcm_analog_capture; | ||
7044 | 7046 | ||
7045 | spec->stream_digital_playback = &alc260_pcm_digital_playback; | 7047 | spec->stream_digital_playback = &alc260_pcm_digital_playback; |
7046 | spec->stream_digital_capture = &alc260_pcm_digital_capture; | 7048 | spec->stream_digital_capture = &alc260_pcm_digital_capture; |
@@ -13475,7 +13477,6 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = { | |||
13475 | SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA), | 13477 | SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA), |
13476 | SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER), | 13478 | SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER), |
13477 | SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1), | 13479 | SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1), |
13478 | SND_PCI_QUIRK(0x1854, 0x1775, "LG R510", ALC268_DELL), | ||
13479 | {} | 13480 | {} |
13480 | }; | 13481 | }; |
13481 | 13482 | ||
@@ -13866,6 +13867,12 @@ static struct snd_kcontrol_new alc269vb_laptop_mixer[] = { | |||
13866 | { } /* end */ | 13867 | { } /* end */ |
13867 | }; | 13868 | }; |
13868 | 13869 | ||
13870 | static struct snd_kcontrol_new alc269_asus_mixer[] = { | ||
13871 | HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT), | ||
13872 | HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x0, HDA_INPUT), | ||
13873 | { } /* end */ | ||
13874 | }; | ||
13875 | |||
13869 | /* capture mixer elements */ | 13876 | /* capture mixer elements */ |
13870 | static struct snd_kcontrol_new alc269_laptop_analog_capture_mixer[] = { | 13877 | static struct snd_kcontrol_new alc269_laptop_analog_capture_mixer[] = { |
13871 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | 13878 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), |
@@ -14086,6 +14093,20 @@ static struct hda_verb alc269vb_laptop_amic_init_verbs[] = { | |||
14086 | {} | 14093 | {} |
14087 | }; | 14094 | }; |
14088 | 14095 | ||
14096 | static struct hda_verb alc271_acer_dmic_verbs[] = { | ||
14097 | {0x20, AC_VERB_SET_COEF_INDEX, 0x0d}, | ||
14098 | {0x20, AC_VERB_SET_PROC_COEF, 0x4000}, | ||
14099 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
14100 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
14101 | {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
14102 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
14103 | {0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
14104 | {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, | ||
14105 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, | ||
14106 | {0x22, AC_VERB_SET_CONNECT_SEL, 6}, | ||
14107 | { } | ||
14108 | }; | ||
14109 | |||
14089 | /* toggle speaker-output according to the hp-jack state */ | 14110 | /* toggle speaker-output according to the hp-jack state */ |
14090 | static void alc269_speaker_automute(struct hda_codec *codec) | 14111 | static void alc269_speaker_automute(struct hda_codec *codec) |
14091 | { | 14112 | { |
@@ -14465,6 +14486,7 @@ static const char *alc269_models[ALC269_MODEL_LAST] = { | |||
14465 | 14486 | ||
14466 | static struct snd_pci_quirk alc269_cfg_tbl[] = { | 14487 | static struct snd_pci_quirk alc269_cfg_tbl[] = { |
14467 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1), | 14488 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1), |
14489 | SND_PCI_QUIRK(0x1025, 0x047c, "ACER ZGA", ALC271_ACER), | ||
14468 | SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", | 14490 | SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", |
14469 | ALC269_AMIC), | 14491 | ALC269_AMIC), |
14470 | SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269VB_AMIC), | 14492 | SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269VB_AMIC), |
@@ -14626,6 +14648,23 @@ static struct alc_config_preset alc269_presets[] = { | |||
14626 | .unsol_event = alc269_lifebook_unsol_event, | 14648 | .unsol_event = alc269_lifebook_unsol_event, |
14627 | .init_hook = alc269_lifebook_init_hook, | 14649 | .init_hook = alc269_lifebook_init_hook, |
14628 | }, | 14650 | }, |
14651 | [ALC271_ACER] = { | ||
14652 | .mixers = { alc269_asus_mixer }, | ||
14653 | .cap_mixer = alc269vb_laptop_digital_capture_mixer, | ||
14654 | .init_verbs = { alc269_init_verbs, alc271_acer_dmic_verbs }, | ||
14655 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | ||
14656 | .dac_nids = alc269_dac_nids, | ||
14657 | .adc_nids = alc262_dmic_adc_nids, | ||
14658 | .num_adc_nids = ARRAY_SIZE(alc262_dmic_adc_nids), | ||
14659 | .capsrc_nids = alc262_dmic_capsrc_nids, | ||
14660 | .num_channel_mode = ARRAY_SIZE(alc269_modes), | ||
14661 | .channel_mode = alc269_modes, | ||
14662 | .input_mux = &alc269_capture_source, | ||
14663 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
14664 | .unsol_event = alc_sku_unsol_event, | ||
14665 | .setup = alc269vb_laptop_dmic_setup, | ||
14666 | .init_hook = alc_inithook, | ||
14667 | }, | ||
14629 | }; | 14668 | }; |
14630 | 14669 | ||
14631 | static int patch_alc269(struct hda_codec *codec) | 14670 | static int patch_alc269(struct hda_codec *codec) |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index b8d730c47df1..f3f861bd1bf8 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -94,6 +94,7 @@ enum { | |||
94 | STAC_92HD83XXX_PWR_REF, | 94 | STAC_92HD83XXX_PWR_REF, |
95 | STAC_DELL_S14, | 95 | STAC_DELL_S14, |
96 | STAC_92HD83XXX_HP, | 96 | STAC_92HD83XXX_HP, |
97 | STAC_HP_DV7_4000, | ||
97 | STAC_92HD83XXX_MODELS | 98 | STAC_92HD83XXX_MODELS |
98 | }; | 99 | }; |
99 | 100 | ||
@@ -1632,10 +1633,17 @@ static unsigned int dell_s14_pin_configs[10] = { | |||
1632 | 0x40f000f0, 0x40f000f0, | 1633 | 0x40f000f0, 0x40f000f0, |
1633 | }; | 1634 | }; |
1634 | 1635 | ||
1636 | static unsigned int hp_dv7_4000_pin_configs[10] = { | ||
1637 | 0x03a12050, 0x0321201f, 0x40f000f0, 0x90170110, | ||
1638 | 0x40f000f0, 0x40f000f0, 0x90170110, 0xd5a30140, | ||
1639 | 0x40f000f0, 0x40f000f0, | ||
1640 | }; | ||
1641 | |||
1635 | static unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { | 1642 | static unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { |
1636 | [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, | 1643 | [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, |
1637 | [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs, | 1644 | [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs, |
1638 | [STAC_DELL_S14] = dell_s14_pin_configs, | 1645 | [STAC_DELL_S14] = dell_s14_pin_configs, |
1646 | [STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs, | ||
1639 | }; | 1647 | }; |
1640 | 1648 | ||
1641 | static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { | 1649 | static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { |
@@ -1644,6 +1652,7 @@ static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { | |||
1644 | [STAC_92HD83XXX_PWR_REF] = "mic-ref", | 1652 | [STAC_92HD83XXX_PWR_REF] = "mic-ref", |
1645 | [STAC_DELL_S14] = "dell-s14", | 1653 | [STAC_DELL_S14] = "dell-s14", |
1646 | [STAC_92HD83XXX_HP] = "hp", | 1654 | [STAC_92HD83XXX_HP] = "hp", |
1655 | [STAC_HP_DV7_4000] = "hp-dv7-4000", | ||
1647 | }; | 1656 | }; |
1648 | 1657 | ||
1649 | static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { | 1658 | static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { |
@@ -5340,6 +5349,8 @@ again: | |||
5340 | case 0x111d7667: | 5349 | case 0x111d7667: |
5341 | case 0x111d7668: | 5350 | case 0x111d7668: |
5342 | case 0x111d7669: | 5351 | case 0x111d7669: |
5352 | case 0x111d76d1: | ||
5353 | case 0x111d76d9: | ||
5343 | spec->num_pins = ARRAY_SIZE(stac92hd88xxx_pin_nids); | 5354 | spec->num_pins = ARRAY_SIZE(stac92hd88xxx_pin_nids); |
5344 | spec->pin_nids = stac92hd88xxx_pin_nids; | 5355 | spec->pin_nids = stac92hd88xxx_pin_nids; |
5345 | spec->mono_nid = 0; | 5356 | spec->mono_nid = 0; |
@@ -6274,6 +6285,8 @@ static struct hda_codec_preset snd_hda_preset_sigmatel[] = { | |||
6274 | { .id = 0x111d76d4, .name = "92HD83C1C5", .patch = patch_stac92hd83xxx}, | 6285 | { .id = 0x111d76d4, .name = "92HD83C1C5", .patch = patch_stac92hd83xxx}, |
6275 | { .id = 0x111d7605, .name = "92HD81B1X5", .patch = patch_stac92hd83xxx}, | 6286 | { .id = 0x111d7605, .name = "92HD81B1X5", .patch = patch_stac92hd83xxx}, |
6276 | { .id = 0x111d76d5, .name = "92HD81B1C5", .patch = patch_stac92hd83xxx}, | 6287 | { .id = 0x111d76d5, .name = "92HD81B1C5", .patch = patch_stac92hd83xxx}, |
6288 | { .id = 0x111d76d1, .name = "92HD87B1/3", .patch = patch_stac92hd83xxx}, | ||
6289 | { .id = 0x111d76d9, .name = "92HD87B2/4", .patch = patch_stac92hd83xxx}, | ||
6277 | { .id = 0x111d7666, .name = "92HD88B3", .patch = patch_stac92hd83xxx}, | 6290 | { .id = 0x111d7666, .name = "92HD88B3", .patch = patch_stac92hd83xxx}, |
6278 | { .id = 0x111d7667, .name = "92HD88B1", .patch = patch_stac92hd83xxx}, | 6291 | { .id = 0x111d7667, .name = "92HD88B1", .patch = patch_stac92hd83xxx}, |
6279 | { .id = 0x111d7668, .name = "92HD88B2", .patch = patch_stac92hd83xxx}, | 6292 | { .id = 0x111d7668, .name = "92HD88B2", .patch = patch_stac92hd83xxx}, |
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index 8ef25025f3dc..3abeeddc67d3 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig | |||
@@ -105,13 +105,18 @@ config SND_BF5XX_RESET_GPIO_NUM | |||
105 | Set the correct GPIO for RESET the sound chip. | 105 | Set the correct GPIO for RESET the sound chip. |
106 | 106 | ||
107 | config SND_BF5XX_SOC_AD1980 | 107 | config SND_BF5XX_SOC_AD1980 |
108 | tristate "SoC AD1980/1 Audio support for BF5xx" | 108 | tristate "SoC AD1980/1 Audio support for BF5xx (Obsolete)" |
109 | depends on SND_BF5XX_AC97 | 109 | depends on SND_BF5XX_AC97 |
110 | select SND_BF5XX_SOC_AC97 | 110 | select SND_BF5XX_SOC_AC97 |
111 | select SND_SOC_AD1980 | 111 | select SND_SOC_AD1980 |
112 | help | 112 | help |
113 | Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT. | 113 | Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT. |
114 | 114 | ||
115 | Warning: | ||
116 | Because Analog Devices Inc. discontinued the ad1980 sound chip since | ||
117 | Sep. 2009, this ad1980 driver is not maintained, tested and supported | ||
118 | by ADI now. | ||
119 | |||
115 | config SND_BF5XX_SOC_SPORT | 120 | config SND_BF5XX_SOC_SPORT |
116 | tristate | 121 | tristate |
117 | 122 | ||
diff --git a/sound/soc/blackfin/bf5xx-ad1980.c b/sound/soc/blackfin/bf5xx-ad1980.c index d8f591273778..92f7c327bb7a 100644 --- a/sound/soc/blackfin/bf5xx-ad1980.c +++ b/sound/soc/blackfin/bf5xx-ad1980.c | |||
@@ -26,6 +26,14 @@ | |||
26 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 26 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
27 | */ | 27 | */ |
28 | 28 | ||
29 | /* | ||
30 | * WARNING: | ||
31 | * | ||
32 | * Because Analog Devices Inc. discontinued the ad1980 sound chip since | ||
33 | * Sep. 2009, this ad1980 driver is not maintained, tested and supported | ||
34 | * by ADI now. | ||
35 | */ | ||
36 | |||
29 | #include <linux/module.h> | 37 | #include <linux/module.h> |
30 | #include <linux/moduleparam.h> | 38 | #include <linux/moduleparam.h> |
31 | #include <linux/device.h> | 39 | #include <linux/device.h> |
@@ -109,5 +117,5 @@ module_exit(bf5xx_board_exit); | |||
109 | 117 | ||
110 | /* Module information */ | 118 | /* Module information */ |
111 | MODULE_AUTHOR("Cliff Cai"); | 119 | MODULE_AUTHOR("Cliff Cai"); |
112 | MODULE_DESCRIPTION("ALSA SoC AD1980/1 BF5xx board"); | 120 | MODULE_DESCRIPTION("ALSA SoC AD1980/1 BF5xx board (Obsolete)"); |
113 | MODULE_LICENSE("GPL"); | 121 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 042072738cdc..70cfaec3be2c 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
@@ -11,6 +11,14 @@ | |||
11 | * option) any later version. | 11 | * option) any later version. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | /* | ||
15 | * WARNING: | ||
16 | * | ||
17 | * Because Analog Devices Inc. discontinued the ad1980 sound chip since | ||
18 | * Sep. 2009, this ad1980 driver is not maintained, tested and supported | ||
19 | * by ADI now. | ||
20 | */ | ||
21 | |||
14 | #include <linux/init.h> | 22 | #include <linux/init.h> |
15 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
16 | #include <linux/module.h> | 24 | #include <linux/module.h> |
@@ -298,6 +306,6 @@ struct snd_soc_codec_device soc_codec_dev_ad1980 = { | |||
298 | }; | 306 | }; |
299 | EXPORT_SYMBOL_GPL(soc_codec_dev_ad1980); | 307 | EXPORT_SYMBOL_GPL(soc_codec_dev_ad1980); |
300 | 308 | ||
301 | MODULE_DESCRIPTION("ASoC ad1980 driver"); | 309 | MODULE_DESCRIPTION("ASoC ad1980 driver (Obsolete)"); |
302 | MODULE_AUTHOR("Roy Huang, Cliff Cai"); | 310 | MODULE_AUTHOR("Roy Huang, Cliff Cai"); |
303 | MODULE_LICENSE("GPL"); | 311 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/ad1980.h b/sound/soc/codecs/ad1980.h index db6c8500d66b..538f37c90806 100644 --- a/sound/soc/codecs/ad1980.h +++ b/sound/soc/codecs/ad1980.h | |||
@@ -1,5 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * ad1980.h -- ad1980 Soc Audio driver | 2 | * ad1980.h -- ad1980 Soc Audio driver |
3 | * | ||
4 | * WARNING: | ||
5 | * | ||
6 | * Because Analog Devices Inc. discontinued the ad1980 sound chip since | ||
7 | * Sep. 2009, this ad1980 driver is not maintained, tested and supported | ||
8 | * by ADI now. | ||
3 | */ | 9 | */ |
4 | 10 | ||
5 | #ifndef _AD1980_H | 11 | #ifndef _AD1980_H |
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index c3571ee5c11b..72deeabef4fe 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -269,9 +269,9 @@ SOC_DOUBLE("DAC2 Invert Switch", WM8580_DAC_CONTROL4, 2, 3, 1, 0), | |||
269 | SOC_DOUBLE("DAC3 Invert Switch", WM8580_DAC_CONTROL4, 4, 5, 1, 0), | 269 | SOC_DOUBLE("DAC3 Invert Switch", WM8580_DAC_CONTROL4, 4, 5, 1, 0), |
270 | 270 | ||
271 | SOC_SINGLE("DAC ZC Switch", WM8580_DAC_CONTROL5, 5, 1, 0), | 271 | SOC_SINGLE("DAC ZC Switch", WM8580_DAC_CONTROL5, 5, 1, 0), |
272 | SOC_SINGLE("DAC1 Switch", WM8580_DAC_CONTROL5, 0, 1, 0), | 272 | SOC_SINGLE("DAC1 Switch", WM8580_DAC_CONTROL5, 0, 1, 1), |
273 | SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 0), | 273 | SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 1), |
274 | SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 0), | 274 | SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 1), |
275 | 275 | ||
276 | SOC_DOUBLE("ADC Mute Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 0), | 276 | SOC_DOUBLE("ADC Mute Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 0), |
277 | SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0), | 277 | SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0), |
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index 1d4e7164e80a..3dcd1469f283 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c | |||
@@ -369,7 +369,7 @@ struct snd_soc_platform mpc5200_audio_dma_platform = { | |||
369 | }; | 369 | }; |
370 | EXPORT_SYMBOL_GPL(mpc5200_audio_dma_platform); | 370 | EXPORT_SYMBOL_GPL(mpc5200_audio_dma_platform); |
371 | 371 | ||
372 | int mpc5200_audio_dma_create(struct of_device *op) | 372 | int mpc5200_audio_dma_create(struct platform_device *op) |
373 | { | 373 | { |
374 | phys_addr_t fifo; | 374 | phys_addr_t fifo; |
375 | struct psc_dma *psc_dma; | 375 | struct psc_dma *psc_dma; |
@@ -488,7 +488,7 @@ out_unmap: | |||
488 | } | 488 | } |
489 | EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create); | 489 | EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create); |
490 | 490 | ||
491 | int mpc5200_audio_dma_destroy(struct of_device *op) | 491 | int mpc5200_audio_dma_destroy(struct platform_device *op) |
492 | { | 492 | { |
493 | struct psc_dma *psc_dma = dev_get_drvdata(&op->dev); | 493 | struct psc_dma *psc_dma = dev_get_drvdata(&op->dev); |
494 | 494 | ||
diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h index e1ec6d91ea38..ca99586f2ad9 100644 --- a/sound/soc/fsl/mpc5200_dma.h +++ b/sound/soc/fsl/mpc5200_dma.h | |||
@@ -81,8 +81,8 @@ to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma) | |||
81 | return &psc_dma->playback; | 81 | return &psc_dma->playback; |
82 | } | 82 | } |
83 | 83 | ||
84 | int mpc5200_audio_dma_create(struct of_device *op); | 84 | int mpc5200_audio_dma_create(struct platform_device *op); |
85 | int mpc5200_audio_dma_destroy(struct of_device *op); | 85 | int mpc5200_audio_dma_destroy(struct platform_device *op); |
86 | 86 | ||
87 | extern struct snd_soc_platform mpc5200_audio_dma_platform; | 87 | extern struct snd_soc_platform mpc5200_audio_dma_platform; |
88 | 88 | ||
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index e7f5d50ed084..a9560235daee 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c | |||
@@ -277,7 +277,7 @@ EXPORT_SYMBOL_GPL(psc_ac97_dai); | |||
277 | * - Probe/remove operations | 277 | * - Probe/remove operations |
278 | * - OF device match table | 278 | * - OF device match table |
279 | */ | 279 | */ |
280 | static int __devinit psc_ac97_of_probe(struct of_device *op, | 280 | static int __devinit psc_ac97_of_probe(struct platform_device *op, |
281 | const struct of_device_id *match) | 281 | const struct of_device_id *match) |
282 | { | 282 | { |
283 | int rc, i; | 283 | int rc, i; |
@@ -317,7 +317,7 @@ static int __devinit psc_ac97_of_probe(struct of_device *op, | |||
317 | return 0; | 317 | return 0; |
318 | } | 318 | } |
319 | 319 | ||
320 | static int __devexit psc_ac97_of_remove(struct of_device *op) | 320 | static int __devexit psc_ac97_of_remove(struct platform_device *op) |
321 | { | 321 | { |
322 | return mpc5200_audio_dma_destroy(op); | 322 | return mpc5200_audio_dma_destroy(op); |
323 | } | 323 | } |
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 676841cbae98..534f04cb15d7 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c | |||
@@ -152,7 +152,7 @@ EXPORT_SYMBOL_GPL(psc_i2s_dai); | |||
152 | * - Probe/remove operations | 152 | * - Probe/remove operations |
153 | * - OF device match table | 153 | * - OF device match table |
154 | */ | 154 | */ |
155 | static int __devinit psc_i2s_of_probe(struct of_device *op, | 155 | static int __devinit psc_i2s_of_probe(struct platform_device *op, |
156 | const struct of_device_id *match) | 156 | const struct of_device_id *match) |
157 | { | 157 | { |
158 | int rc; | 158 | int rc; |
@@ -205,7 +205,7 @@ static int __devinit psc_i2s_of_probe(struct of_device *op, | |||
205 | 205 | ||
206 | } | 206 | } |
207 | 207 | ||
208 | static int __devexit psc_i2s_of_remove(struct of_device *op) | 208 | static int __devexit psc_i2s_of_remove(struct platform_device *op) |
209 | { | 209 | { |
210 | return mpc5200_audio_dma_destroy(op); | 210 | return mpc5200_audio_dma_destroy(op); |
211 | } | 211 | } |
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 3a501062c244..3b13b8d65262 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c | |||
@@ -200,7 +200,7 @@ static struct snd_soc_ops mpc8610_hpcd_ops = { | |||
200 | * SSI devices. We also probably aren't compatible with the generic Elo DMA | 200 | * SSI devices. We also probably aren't compatible with the generic Elo DMA |
201 | * device driver. | 201 | * device driver. |
202 | */ | 202 | */ |
203 | static int mpc8610_hpcd_probe(struct of_device *ofdev, | 203 | static int mpc8610_hpcd_probe(struct platform_device *ofdev, |
204 | const struct of_device_id *match) | 204 | const struct of_device_id *match) |
205 | { | 205 | { |
206 | struct device_node *np = ofdev->dev.of_node; | 206 | struct device_node *np = ofdev->dev.of_node; |
@@ -534,7 +534,7 @@ error: | |||
534 | * | 534 | * |
535 | * This function is called when the OF device is removed. | 535 | * This function is called when the OF device is removed. |
536 | */ | 536 | */ |
537 | static int mpc8610_hpcd_remove(struct of_device *ofdev) | 537 | static int mpc8610_hpcd_remove(struct platform_device *ofdev) |
538 | { | 538 | { |
539 | struct platform_device *sound_device = dev_get_drvdata(&ofdev->dev); | 539 | struct platform_device *sound_device = dev_get_drvdata(&ofdev->dev); |
540 | struct mpc8610_hpcd_data *machine_data = | 540 | struct mpc8610_hpcd_data *machine_data = |
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index 52dac5e3874c..687c76fc0839 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig | |||
@@ -28,7 +28,9 @@ config SND_SOC_PHYCORE_AC97 | |||
28 | 28 | ||
29 | config SND_SOC_EUKREA_TLV320 | 29 | config SND_SOC_EUKREA_TLV320 |
30 | tristate "Eukrea TLV320" | 30 | tristate "Eukrea TLV320" |
31 | depends on MACH_EUKREA_MBIMX27_BASEBOARD || MACH_EUKREA_MBIMXSD_BASEBOARD | 31 | depends on MACH_EUKREA_MBIMX27_BASEBOARD \ |
32 | || MACH_EUKREA_MBIMXSD25_BASEBOARD \ | ||
33 | || MACH_EUKREA_MBIMXSD35_BASEBOARD | ||
32 | select SND_SOC_TLV320AIC23 | 34 | select SND_SOC_TLV320AIC23 |
33 | help | 35 | help |
34 | Enable I2S based access to the TLV320AIC23B codec attached | 36 | Enable I2S based access to the TLV320AIC23B codec attached |
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 472af38188c1..adbc68ce9050 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c | |||
@@ -340,7 +340,7 @@ static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec, | |||
340 | static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec, | 340 | static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec, |
341 | unsigned int reg) | 341 | unsigned int reg) |
342 | { | 342 | { |
343 | u16 *cache = codec->reg_cache; | 343 | u8 *cache = codec->reg_cache; |
344 | 344 | ||
345 | reg &= 0xff; | 345 | reg &= 0xff; |
346 | if (reg >= codec->reg_cache_size) | 346 | if (reg >= codec->reg_cache_size) |
@@ -351,7 +351,7 @@ static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec, | |||
351 | static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, | 351 | static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, |
352 | unsigned int value) | 352 | unsigned int value) |
353 | { | 353 | { |
354 | u16 *cache = codec->reg_cache; | 354 | u8 *cache = codec->reg_cache; |
355 | u8 data[3]; | 355 | u8 data[3]; |
356 | int ret; | 356 | int ret; |
357 | 357 | ||
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index 9eb1a4e0363b..f8bcfc30f800 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c | |||
@@ -336,7 +336,7 @@ struct snd_amd7930 { | |||
336 | int pgain; | 336 | int pgain; |
337 | int mgain; | 337 | int mgain; |
338 | 338 | ||
339 | struct of_device *op; | 339 | struct platform_device *op; |
340 | unsigned int irq; | 340 | unsigned int irq; |
341 | struct snd_amd7930 *next; | 341 | struct snd_amd7930 *next; |
342 | }; | 342 | }; |
@@ -906,7 +906,7 @@ static int __devinit snd_amd7930_mixer(struct snd_amd7930 *amd) | |||
906 | 906 | ||
907 | static int snd_amd7930_free(struct snd_amd7930 *amd) | 907 | static int snd_amd7930_free(struct snd_amd7930 *amd) |
908 | { | 908 | { |
909 | struct of_device *op = amd->op; | 909 | struct platform_device *op = amd->op; |
910 | 910 | ||
911 | amd7930_idle(amd); | 911 | amd7930_idle(amd); |
912 | 912 | ||
@@ -934,7 +934,7 @@ static struct snd_device_ops snd_amd7930_dev_ops = { | |||
934 | }; | 934 | }; |
935 | 935 | ||
936 | static int __devinit snd_amd7930_create(struct snd_card *card, | 936 | static int __devinit snd_amd7930_create(struct snd_card *card, |
937 | struct of_device *op, | 937 | struct platform_device *op, |
938 | int irq, int dev, | 938 | int irq, int dev, |
939 | struct snd_amd7930 **ramd) | 939 | struct snd_amd7930 **ramd) |
940 | { | 940 | { |
@@ -1002,7 +1002,7 @@ static int __devinit snd_amd7930_create(struct snd_card *card, | |||
1002 | return 0; | 1002 | return 0; |
1003 | } | 1003 | } |
1004 | 1004 | ||
1005 | static int __devinit amd7930_sbus_probe(struct of_device *op, const struct of_device_id *match) | 1005 | static int __devinit amd7930_sbus_probe(struct platform_device *op, const struct of_device_id *match) |
1006 | { | 1006 | { |
1007 | struct resource *rp = &op->resource[0]; | 1007 | struct resource *rp = &op->resource[0]; |
1008 | static int dev_num; | 1008 | static int dev_num; |
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 68570ee2c9bb..c276086c3b57 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c | |||
@@ -111,7 +111,7 @@ struct snd_cs4231 { | |||
111 | struct mutex mce_mutex; /* mutex for mce register */ | 111 | struct mutex mce_mutex; /* mutex for mce register */ |
112 | struct mutex open_mutex; /* mutex for ALSA open/close */ | 112 | struct mutex open_mutex; /* mutex for ALSA open/close */ |
113 | 113 | ||
114 | struct of_device *op; | 114 | struct platform_device *op; |
115 | unsigned int irq[2]; | 115 | unsigned int irq[2]; |
116 | unsigned int regs_size; | 116 | unsigned int regs_size; |
117 | struct snd_cs4231 *next; | 117 | struct snd_cs4231 *next; |
@@ -1771,7 +1771,7 @@ static unsigned int sbus_dma_addr(struct cs4231_dma_control *dma_cont) | |||
1771 | 1771 | ||
1772 | static int snd_cs4231_sbus_free(struct snd_cs4231 *chip) | 1772 | static int snd_cs4231_sbus_free(struct snd_cs4231 *chip) |
1773 | { | 1773 | { |
1774 | struct of_device *op = chip->op; | 1774 | struct platform_device *op = chip->op; |
1775 | 1775 | ||
1776 | if (chip->irq[0]) | 1776 | if (chip->irq[0]) |
1777 | free_irq(chip->irq[0], chip); | 1777 | free_irq(chip->irq[0], chip); |
@@ -1794,7 +1794,7 @@ static struct snd_device_ops snd_cs4231_sbus_dev_ops = { | |||
1794 | }; | 1794 | }; |
1795 | 1795 | ||
1796 | static int __devinit snd_cs4231_sbus_create(struct snd_card *card, | 1796 | static int __devinit snd_cs4231_sbus_create(struct snd_card *card, |
1797 | struct of_device *op, | 1797 | struct platform_device *op, |
1798 | int dev) | 1798 | int dev) |
1799 | { | 1799 | { |
1800 | struct snd_cs4231 *chip = card->private_data; | 1800 | struct snd_cs4231 *chip = card->private_data; |
@@ -1856,7 +1856,7 @@ static int __devinit snd_cs4231_sbus_create(struct snd_card *card, | |||
1856 | return 0; | 1856 | return 0; |
1857 | } | 1857 | } |
1858 | 1858 | ||
1859 | static int __devinit cs4231_sbus_probe(struct of_device *op, const struct of_device_id *match) | 1859 | static int __devinit cs4231_sbus_probe(struct platform_device *op, const struct of_device_id *match) |
1860 | { | 1860 | { |
1861 | struct resource *rp = &op->resource[0]; | 1861 | struct resource *rp = &op->resource[0]; |
1862 | struct snd_card *card; | 1862 | struct snd_card *card; |
@@ -1931,7 +1931,7 @@ static unsigned int _ebus_dma_addr(struct cs4231_dma_control *dma_cont) | |||
1931 | 1931 | ||
1932 | static int snd_cs4231_ebus_free(struct snd_cs4231 *chip) | 1932 | static int snd_cs4231_ebus_free(struct snd_cs4231 *chip) |
1933 | { | 1933 | { |
1934 | struct of_device *op = chip->op; | 1934 | struct platform_device *op = chip->op; |
1935 | 1935 | ||
1936 | if (chip->c_dma.ebus_info.regs) { | 1936 | if (chip->c_dma.ebus_info.regs) { |
1937 | ebus_dma_unregister(&chip->c_dma.ebus_info); | 1937 | ebus_dma_unregister(&chip->c_dma.ebus_info); |
@@ -1960,7 +1960,7 @@ static struct snd_device_ops snd_cs4231_ebus_dev_ops = { | |||
1960 | }; | 1960 | }; |
1961 | 1961 | ||
1962 | static int __devinit snd_cs4231_ebus_create(struct snd_card *card, | 1962 | static int __devinit snd_cs4231_ebus_create(struct snd_card *card, |
1963 | struct of_device *op, | 1963 | struct platform_device *op, |
1964 | int dev) | 1964 | int dev) |
1965 | { | 1965 | { |
1966 | struct snd_cs4231 *chip = card->private_data; | 1966 | struct snd_cs4231 *chip = card->private_data; |
@@ -2048,7 +2048,7 @@ static int __devinit snd_cs4231_ebus_create(struct snd_card *card, | |||
2048 | return 0; | 2048 | return 0; |
2049 | } | 2049 | } |
2050 | 2050 | ||
2051 | static int __devinit cs4231_ebus_probe(struct of_device *op, const struct of_device_id *match) | 2051 | static int __devinit cs4231_ebus_probe(struct platform_device *op, const struct of_device_id *match) |
2052 | { | 2052 | { |
2053 | struct snd_card *card; | 2053 | struct snd_card *card; |
2054 | int err; | 2054 | int err; |
@@ -2072,7 +2072,7 @@ static int __devinit cs4231_ebus_probe(struct of_device *op, const struct of_dev | |||
2072 | } | 2072 | } |
2073 | #endif | 2073 | #endif |
2074 | 2074 | ||
2075 | static int __devinit cs4231_probe(struct of_device *op, const struct of_device_id *match) | 2075 | static int __devinit cs4231_probe(struct platform_device *op, const struct of_device_id *match) |
2076 | { | 2076 | { |
2077 | #ifdef EBUS_SUPPORT | 2077 | #ifdef EBUS_SUPPORT |
2078 | if (!strcmp(op->dev.of_node->parent->name, "ebus")) | 2078 | if (!strcmp(op->dev.of_node->parent->name, "ebus")) |
@@ -2086,7 +2086,7 @@ static int __devinit cs4231_probe(struct of_device *op, const struct of_device_i | |||
2086 | return -ENODEV; | 2086 | return -ENODEV; |
2087 | } | 2087 | } |
2088 | 2088 | ||
2089 | static int __devexit cs4231_remove(struct of_device *op) | 2089 | static int __devexit cs4231_remove(struct platform_device *op) |
2090 | { | 2090 | { |
2091 | struct snd_cs4231 *chip = dev_get_drvdata(&op->dev); | 2091 | struct snd_cs4231 *chip = dev_get_drvdata(&op->dev); |
2092 | 2092 | ||
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index c421901c48d0..39cd5d69d051 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c | |||
@@ -299,7 +299,7 @@ struct dbri_streaminfo { | |||
299 | /* This structure holds the information for both chips (DBRI & CS4215) */ | 299 | /* This structure holds the information for both chips (DBRI & CS4215) */ |
300 | struct snd_dbri { | 300 | struct snd_dbri { |
301 | int regs_size, irq; /* Needed for unload */ | 301 | int regs_size, irq; /* Needed for unload */ |
302 | struct of_device *op; /* OF device info */ | 302 | struct platform_device *op; /* OF device info */ |
303 | spinlock_t lock; | 303 | spinlock_t lock; |
304 | 304 | ||
305 | struct dbri_dma *dma; /* Pointer to our DMA block */ | 305 | struct dbri_dma *dma; /* Pointer to our DMA block */ |
@@ -2523,7 +2523,7 @@ static void __devinit snd_dbri_proc(struct snd_card *card) | |||
2523 | static void snd_dbri_free(struct snd_dbri *dbri); | 2523 | static void snd_dbri_free(struct snd_dbri *dbri); |
2524 | 2524 | ||
2525 | static int __devinit snd_dbri_create(struct snd_card *card, | 2525 | static int __devinit snd_dbri_create(struct snd_card *card, |
2526 | struct of_device *op, | 2526 | struct platform_device *op, |
2527 | int irq, int dev) | 2527 | int irq, int dev) |
2528 | { | 2528 | { |
2529 | struct snd_dbri *dbri = card->private_data; | 2529 | struct snd_dbri *dbri = card->private_data; |
@@ -2592,7 +2592,7 @@ static void snd_dbri_free(struct snd_dbri *dbri) | |||
2592 | (void *)dbri->dma, dbri->dma_dvma); | 2592 | (void *)dbri->dma, dbri->dma_dvma); |
2593 | } | 2593 | } |
2594 | 2594 | ||
2595 | static int __devinit dbri_probe(struct of_device *op, const struct of_device_id *match) | 2595 | static int __devinit dbri_probe(struct platform_device *op, const struct of_device_id *match) |
2596 | { | 2596 | { |
2597 | struct snd_dbri *dbri; | 2597 | struct snd_dbri *dbri; |
2598 | struct resource *rp; | 2598 | struct resource *rp; |
@@ -2662,7 +2662,7 @@ _err: | |||
2662 | return err; | 2662 | return err; |
2663 | } | 2663 | } |
2664 | 2664 | ||
2665 | static int __devexit dbri_remove(struct of_device *op) | 2665 | static int __devexit dbri_remove(struct platform_device *op) |
2666 | { | 2666 | { |
2667 | struct snd_card *card = dev_get_drvdata(&op->dev); | 2667 | struct snd_card *card = dev_get_drvdata(&op->dev); |
2668 | 2668 | ||