diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-28 19:54:33 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-28 19:54:33 -0500 |
commit | 3c92ec8ae91ecf59d88c798301833d7cf83f2179 (patch) | |
tree | 08a38cd3523c42bd49882f17cd501fd879e7ca1c /drivers | |
parent | c4c9f0183b7c4e97836e8fecbb67898b06c47e78 (diff) | |
parent | ca9153a3a2a7556d091dfe080e42b0e67881fff6 (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (144 commits)
powerpc/44x: Support 16K/64K base page sizes on 44x
powerpc: Force memory size to be a multiple of PAGE_SIZE
powerpc/32: Wire up the trampoline code for kdump
powerpc/32: Add the ability for a classic ppc kernel to be loaded at 32M
powerpc/32: Allow __ioremap on RAM addresses for kdump kernel
powerpc/32: Setup OF properties for kdump
powerpc/32/kdump: Implement crash_setup_regs() using ppc_save_regs()
powerpc: Prepare xmon_save_regs for use with kdump
powerpc: Remove default kexec/crash_kernel ops assignments
powerpc: Make default kexec/crash_kernel ops implicit
powerpc: Setup OF properties for ppc32 kexec
powerpc/pseries: Fix cpu hotplug
powerpc: Fix KVM build on ppc440
powerpc/cell: add QPACE as a separate Cell platform
powerpc/cell: fix build breakage with CONFIG_SPUFS disabled
powerpc/mpc5200: fix error paths in PSC UART probe function
powerpc/mpc5200: add rts/cts handling in PSC UART driver
powerpc/mpc5200: Make PSC UART driver update serial errors counters
powerpc/mpc5200: Remove obsolete code from mpc5200 MDIO driver
powerpc/mpc5200: Add MDMA/UDMA support to MPC5200 ATA driver
...
Fix trivial conflict in drivers/char/Makefile as per Paul's directions
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/Kconfig | 3 | ||||
-rw-r--r-- | drivers/ata/pata_mpc52xx.c | 546 | ||||
-rw-r--r-- | drivers/char/Kconfig | 6 | ||||
-rw-r--r-- | drivers/char/Makefile | 1 | ||||
-rw-r--r-- | drivers/char/bsr.c | 84 | ||||
-rw-r--r-- | drivers/char/hvc_console.c | 13 | ||||
-rw-r--r-- | drivers/char/hvc_console.h | 2 | ||||
-rw-r--r-- | drivers/char/hvc_iseries.c | 4 | ||||
-rw-r--r-- | drivers/char/hvc_udbg.c | 96 | ||||
-rw-r--r-- | drivers/char/hvc_vio.c | 4 | ||||
-rw-r--r-- | drivers/char/hvcs.c | 2 | ||||
-rw-r--r-- | drivers/char/hvsi.c | 2 | ||||
-rw-r--r-- | drivers/edac/Kconfig | 2 | ||||
-rw-r--r-- | drivers/macintosh/via-pmu.c | 4 | ||||
-rw-r--r-- | drivers/macintosh/windfarm_smu_sat.c | 5 | ||||
-rw-r--r-- | drivers/net/fec_mpc52xx_phy.c | 5 | ||||
-rw-r--r-- | drivers/of/base.c | 68 | ||||
-rw-r--r-- | drivers/of/gpio.c | 70 | ||||
-rw-r--r-- | drivers/of/of_i2c.c | 11 | ||||
-rw-r--r-- | drivers/pci/hotplug/rpadlpar_core.c | 69 | ||||
-rw-r--r-- | drivers/ps3/ps3av.c | 20 | ||||
-rw-r--r-- | drivers/ps3/ps3av_cmd.c | 4 | ||||
-rw-r--r-- | drivers/rapidio/rio-scan.c | 8 | ||||
-rw-r--r-- | drivers/serial/mpc52xx_uart.c | 74 | ||||
-rw-r--r-- | drivers/serial/pmac_zilog.c | 27 | ||||
-rw-r--r-- | drivers/video/controlfb.c | 4 | ||||
-rw-r--r-- | drivers/video/ps3fb.c | 23 |
27 files changed, 926 insertions, 231 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 421b7c71e72d..1a7be96d627b 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig | |||
@@ -456,7 +456,8 @@ config PATA_MARVELL | |||
456 | 456 | ||
457 | config PATA_MPC52xx | 457 | config PATA_MPC52xx |
458 | tristate "Freescale MPC52xx SoC internal IDE" | 458 | tristate "Freescale MPC52xx SoC internal IDE" |
459 | depends on PPC_MPC52xx | 459 | depends on PPC_MPC52xx && PPC_BESTCOMM |
460 | select PPC_BESTCOMM_ATA | ||
460 | help | 461 | help |
461 | This option enables support for integrated IDE controller | 462 | This option enables support for integrated IDE controller |
462 | of the Freescale MPC52xx SoC. | 463 | of the Freescale MPC52xx SoC. |
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c index a9e827356d06..50ae6d13078a 100644 --- a/drivers/ata/pata_mpc52xx.c +++ b/drivers/ata/pata_mpc52xx.c | |||
@@ -6,6 +6,9 @@ | |||
6 | * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com> | 6 | * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com> |
7 | * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt | 7 | * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt |
8 | * | 8 | * |
9 | * UDMA support based on patches by Freescale (Bernard Kuhn, John Rigby), | ||
10 | * Domen Puncer and Tim Yamin. | ||
11 | * | ||
9 | * This file is licensed under the terms of the GNU General Public License | 12 | * This file is licensed under the terms of the GNU General Public License |
10 | * version 2. This program is licensed "as is" without any warranty of any | 13 | * version 2. This program is licensed "as is" without any warranty of any |
11 | * kind, whether express or implied. | 14 | * kind, whether express or implied. |
@@ -17,28 +20,46 @@ | |||
17 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
18 | #include <linux/libata.h> | 21 | #include <linux/libata.h> |
19 | #include <linux/of_platform.h> | 22 | #include <linux/of_platform.h> |
23 | #include <linux/types.h> | ||
20 | 24 | ||
21 | #include <asm/types.h> | 25 | #include <asm/cacheflush.h> |
22 | #include <asm/prom.h> | 26 | #include <asm/prom.h> |
23 | #include <asm/mpc52xx.h> | 27 | #include <asm/mpc52xx.h> |
24 | 28 | ||
29 | #include <sysdev/bestcomm/bestcomm.h> | ||
30 | #include <sysdev/bestcomm/bestcomm_priv.h> | ||
31 | #include <sysdev/bestcomm/ata.h> | ||
25 | 32 | ||
26 | #define DRV_NAME "mpc52xx_ata" | 33 | #define DRV_NAME "mpc52xx_ata" |
27 | #define DRV_VERSION "0.1.2" | ||
28 | |||
29 | 34 | ||
30 | /* Private structures used by the driver */ | 35 | /* Private structures used by the driver */ |
31 | struct mpc52xx_ata_timings { | 36 | struct mpc52xx_ata_timings { |
32 | u32 pio1; | 37 | u32 pio1; |
33 | u32 pio2; | 38 | u32 pio2; |
39 | u32 mdma1; | ||
40 | u32 mdma2; | ||
41 | u32 udma1; | ||
42 | u32 udma2; | ||
43 | u32 udma3; | ||
44 | u32 udma4; | ||
45 | u32 udma5; | ||
46 | int using_udma; | ||
34 | }; | 47 | }; |
35 | 48 | ||
36 | struct mpc52xx_ata_priv { | 49 | struct mpc52xx_ata_priv { |
37 | unsigned int ipb_period; | 50 | unsigned int ipb_period; |
38 | struct mpc52xx_ata __iomem * ata_regs; | 51 | struct mpc52xx_ata __iomem *ata_regs; |
52 | phys_addr_t ata_regs_pa; | ||
39 | int ata_irq; | 53 | int ata_irq; |
40 | struct mpc52xx_ata_timings timings[2]; | 54 | struct mpc52xx_ata_timings timings[2]; |
41 | int csel; | 55 | int csel; |
56 | |||
57 | /* DMA */ | ||
58 | struct bcom_task *dmatsk; | ||
59 | const struct udmaspec *udmaspec; | ||
60 | const struct mdmaspec *mdmaspec; | ||
61 | int mpc52xx_ata_dma_last_write; | ||
62 | int waiting_for_dma; | ||
42 | }; | 63 | }; |
43 | 64 | ||
44 | 65 | ||
@@ -53,6 +74,107 @@ static const int ataspec_ta[5] = { 35, 35, 35, 35, 35}; | |||
53 | 74 | ||
54 | #define CALC_CLKCYC(c,v) ((((v)+(c)-1)/(c))) | 75 | #define CALC_CLKCYC(c,v) ((((v)+(c)-1)/(c))) |
55 | 76 | ||
77 | /* ======================================================================== */ | ||
78 | |||
79 | /* ATAPI-4 MDMA specs (in clocks) */ | ||
80 | struct mdmaspec { | ||
81 | u32 t0M; | ||
82 | u32 td; | ||
83 | u32 th; | ||
84 | u32 tj; | ||
85 | u32 tkw; | ||
86 | u32 tm; | ||
87 | u32 tn; | ||
88 | }; | ||
89 | |||
90 | static const struct mdmaspec mdmaspec66[3] = { | ||
91 | { .t0M = 32, .td = 15, .th = 2, .tj = 2, .tkw = 15, .tm = 4, .tn = 1 }, | ||
92 | { .t0M = 10, .td = 6, .th = 1, .tj = 1, .tkw = 4, .tm = 2, .tn = 1 }, | ||
93 | { .t0M = 8, .td = 5, .th = 1, .tj = 1, .tkw = 2, .tm = 2, .tn = 1 }, | ||
94 | }; | ||
95 | |||
96 | static const struct mdmaspec mdmaspec132[3] = { | ||
97 | { .t0M = 64, .td = 29, .th = 3, .tj = 3, .tkw = 29, .tm = 7, .tn = 2 }, | ||
98 | { .t0M = 20, .td = 11, .th = 2, .tj = 1, .tkw = 7, .tm = 4, .tn = 1 }, | ||
99 | { .t0M = 16, .td = 10, .th = 2, .tj = 1, .tkw = 4, .tm = 4, .tn = 1 }, | ||
100 | }; | ||
101 | |||
102 | /* ATAPI-4 UDMA specs (in clocks) */ | ||
103 | struct udmaspec { | ||
104 | u32 tcyc; | ||
105 | u32 t2cyc; | ||
106 | u32 tds; | ||
107 | u32 tdh; | ||
108 | u32 tdvs; | ||
109 | u32 tdvh; | ||
110 | u32 tfs; | ||
111 | u32 tli; | ||
112 | u32 tmli; | ||
113 | u32 taz; | ||
114 | u32 tzah; | ||
115 | u32 tenv; | ||
116 | u32 tsr; | ||
117 | u32 trfs; | ||
118 | u32 trp; | ||
119 | u32 tack; | ||
120 | u32 tss; | ||
121 | }; | ||
122 | |||
123 | static const struct udmaspec udmaspec66[6] = { | ||
124 | { .tcyc = 8, .t2cyc = 16, .tds = 1, .tdh = 1, .tdvs = 5, .tdvh = 1, | ||
125 | .tfs = 16, .tli = 10, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2, | ||
126 | .tsr = 3, .trfs = 5, .trp = 11, .tack = 2, .tss = 4, | ||
127 | }, | ||
128 | { .tcyc = 5, .t2cyc = 11, .tds = 1, .tdh = 1, .tdvs = 4, .tdvh = 1, | ||
129 | .tfs = 14, .tli = 10, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2, | ||
130 | .tsr = 2, .trfs = 5, .trp = 9, .tack = 2, .tss = 4, | ||
131 | }, | ||
132 | { .tcyc = 4, .t2cyc = 8, .tds = 1, .tdh = 1, .tdvs = 3, .tdvh = 1, | ||
133 | .tfs = 12, .tli = 10, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2, | ||
134 | .tsr = 2, .trfs = 4, .trp = 7, .tack = 2, .tss = 4, | ||
135 | }, | ||
136 | { .tcyc = 3, .t2cyc = 6, .tds = 1, .tdh = 1, .tdvs = 2, .tdvh = 1, | ||
137 | .tfs = 9, .tli = 7, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2, | ||
138 | .tsr = 2, .trfs = 4, .trp = 7, .tack = 2, .tss = 4, | ||
139 | }, | ||
140 | { .tcyc = 2, .t2cyc = 4, .tds = 1, .tdh = 1, .tdvs = 1, .tdvh = 1, | ||
141 | .tfs = 8, .tli = 8, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2, | ||
142 | .tsr = 2, .trfs = 4, .trp = 7, .tack = 2, .tss = 4, | ||
143 | }, | ||
144 | { .tcyc = 2, .t2cyc = 2, .tds = 1, .tdh = 1, .tdvs = 1, .tdvh = 1, | ||
145 | .tfs = 6, .tli = 5, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2, | ||
146 | .tsr = 2, .trfs = 4, .trp = 6, .tack = 2, .tss = 4, | ||
147 | }, | ||
148 | }; | ||
149 | |||
150 | static const struct udmaspec udmaspec132[6] = { | ||
151 | { .tcyc = 15, .t2cyc = 31, .tds = 2, .tdh = 1, .tdvs = 10, .tdvh = 1, | ||
152 | .tfs = 30, .tli = 20, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3, | ||
153 | .tsr = 7, .trfs = 10, .trp = 22, .tack = 3, .tss = 7, | ||
154 | }, | ||
155 | { .tcyc = 10, .t2cyc = 21, .tds = 2, .tdh = 1, .tdvs = 7, .tdvh = 1, | ||
156 | .tfs = 27, .tli = 20, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3, | ||
157 | .tsr = 4, .trfs = 10, .trp = 17, .tack = 3, .tss = 7, | ||
158 | }, | ||
159 | { .tcyc = 6, .t2cyc = 12, .tds = 1, .tdh = 1, .tdvs = 5, .tdvh = 1, | ||
160 | .tfs = 23, .tli = 20, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3, | ||
161 | .tsr = 3, .trfs = 8, .trp = 14, .tack = 3, .tss = 7, | ||
162 | }, | ||
163 | { .tcyc = 7, .t2cyc = 12, .tds = 1, .tdh = 1, .tdvs = 3, .tdvh = 1, | ||
164 | .tfs = 15, .tli = 13, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3, | ||
165 | .tsr = 3, .trfs = 8, .trp = 14, .tack = 3, .tss = 7, | ||
166 | }, | ||
167 | { .tcyc = 2, .t2cyc = 5, .tds = 0, .tdh = 0, .tdvs = 1, .tdvh = 1, | ||
168 | .tfs = 16, .tli = 14, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2, | ||
169 | .tsr = 2, .trfs = 7, .trp = 13, .tack = 2, .tss = 6, | ||
170 | }, | ||
171 | { .tcyc = 3, .t2cyc = 6, .tds = 1, .tdh = 1, .tdvs = 1, .tdvh = 1, | ||
172 | .tfs = 12, .tli = 10, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3, | ||
173 | .tsr = 3, .trfs = 7, .trp = 12, .tack = 3, .tss = 7, | ||
174 | }, | ||
175 | }; | ||
176 | |||
177 | /* ======================================================================== */ | ||
56 | 178 | ||
57 | /* Bit definitions inside the registers */ | 179 | /* Bit definitions inside the registers */ |
58 | #define MPC52xx_ATA_HOSTCONF_SMR 0x80000000UL /* State machine reset */ | 180 | #define MPC52xx_ATA_HOSTCONF_SMR 0x80000000UL /* State machine reset */ |
@@ -66,6 +188,7 @@ static const int ataspec_ta[5] = { 35, 35, 35, 35, 35}; | |||
66 | #define MPC52xx_ATA_HOSTSTAT_WERR 0x01000000UL /* Write Error */ | 188 | #define MPC52xx_ATA_HOSTSTAT_WERR 0x01000000UL /* Write Error */ |
67 | 189 | ||
68 | #define MPC52xx_ATA_FIFOSTAT_EMPTY 0x01 /* FIFO Empty */ | 190 | #define MPC52xx_ATA_FIFOSTAT_EMPTY 0x01 /* FIFO Empty */ |
191 | #define MPC52xx_ATA_FIFOSTAT_ERROR 0x40 /* FIFO Error */ | ||
69 | 192 | ||
70 | #define MPC52xx_ATA_DMAMODE_WRITE 0x01 /* Write DMA */ | 193 | #define MPC52xx_ATA_DMAMODE_WRITE 0x01 /* Write DMA */ |
71 | #define MPC52xx_ATA_DMAMODE_READ 0x02 /* Read DMA */ | 194 | #define MPC52xx_ATA_DMAMODE_READ 0x02 /* Read DMA */ |
@@ -75,6 +198,8 @@ static const int ataspec_ta[5] = { 35, 35, 35, 35, 35}; | |||
75 | #define MPC52xx_ATA_DMAMODE_FR 0x20 /* FIFO Reset */ | 198 | #define MPC52xx_ATA_DMAMODE_FR 0x20 /* FIFO Reset */ |
76 | #define MPC52xx_ATA_DMAMODE_HUT 0x40 /* Host UDMA burst terminate */ | 199 | #define MPC52xx_ATA_DMAMODE_HUT 0x40 /* Host UDMA burst terminate */ |
77 | 200 | ||
201 | #define MAX_DMA_BUFFERS 128 | ||
202 | #define MAX_DMA_BUFFER_SIZE 0x20000u | ||
78 | 203 | ||
79 | /* Structure of the hardware registers */ | 204 | /* Structure of the hardware registers */ |
80 | struct mpc52xx_ata { | 205 | struct mpc52xx_ata { |
@@ -140,7 +265,6 @@ struct mpc52xx_ata { | |||
140 | 265 | ||
141 | 266 | ||
142 | /* MPC52xx low level hw control */ | 267 | /* MPC52xx low level hw control */ |
143 | |||
144 | static int | 268 | static int |
145 | mpc52xx_ata_compute_pio_timings(struct mpc52xx_ata_priv *priv, int dev, int pio) | 269 | mpc52xx_ata_compute_pio_timings(struct mpc52xx_ata_priv *priv, int dev, int pio) |
146 | { | 270 | { |
@@ -148,7 +272,7 @@ mpc52xx_ata_compute_pio_timings(struct mpc52xx_ata_priv *priv, int dev, int pio) | |||
148 | unsigned int ipb_period = priv->ipb_period; | 272 | unsigned int ipb_period = priv->ipb_period; |
149 | unsigned int t0, t1, t2_8, t2_16, t2i, t4, ta; | 273 | unsigned int t0, t1, t2_8, t2_16, t2i, t4, ta; |
150 | 274 | ||
151 | if ((pio<0) || (pio>4)) | 275 | if ((pio < 0) || (pio > 4)) |
152 | return -EINVAL; | 276 | return -EINVAL; |
153 | 277 | ||
154 | t0 = CALC_CLKCYC(ipb_period, 1000 * ataspec_t0[pio]); | 278 | t0 = CALC_CLKCYC(ipb_period, 1000 * ataspec_t0[pio]); |
@@ -165,6 +289,43 @@ mpc52xx_ata_compute_pio_timings(struct mpc52xx_ata_priv *priv, int dev, int pio) | |||
165 | return 0; | 289 | return 0; |
166 | } | 290 | } |
167 | 291 | ||
292 | static int | ||
293 | mpc52xx_ata_compute_mdma_timings(struct mpc52xx_ata_priv *priv, int dev, | ||
294 | int speed) | ||
295 | { | ||
296 | struct mpc52xx_ata_timings *t = &priv->timings[dev]; | ||
297 | const struct mdmaspec *s = &priv->mdmaspec[speed]; | ||
298 | |||
299 | if (speed < 0 || speed > 2) | ||
300 | return -EINVAL; | ||
301 | |||
302 | t->mdma1 = (s->t0M << 24) | (s->td << 16) | (s->tkw << 8) | (s->tm); | ||
303 | t->mdma2 = (s->th << 24) | (s->tj << 16) | (s->tn << 8); | ||
304 | t->using_udma = 0; | ||
305 | |||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | static int | ||
310 | mpc52xx_ata_compute_udma_timings(struct mpc52xx_ata_priv *priv, int dev, | ||
311 | int speed) | ||
312 | { | ||
313 | struct mpc52xx_ata_timings *t = &priv->timings[dev]; | ||
314 | const struct udmaspec *s = &priv->udmaspec[speed]; | ||
315 | |||
316 | if (speed < 0 || speed > 2) | ||
317 | return -EINVAL; | ||
318 | |||
319 | t->udma1 = (s->t2cyc << 24) | (s->tcyc << 16) | (s->tds << 8) | s->tdh; | ||
320 | t->udma2 = (s->tdvs << 24) | (s->tdvh << 16) | (s->tfs << 8) | s->tli; | ||
321 | t->udma3 = (s->tmli << 24) | (s->taz << 16) | (s->tenv << 8) | s->tsr; | ||
322 | t->udma4 = (s->tss << 24) | (s->trfs << 16) | (s->trp << 8) | s->tack; | ||
323 | t->udma5 = (s->tzah << 24); | ||
324 | t->using_udma = 1; | ||
325 | |||
326 | return 0; | ||
327 | } | ||
328 | |||
168 | static void | 329 | static void |
169 | mpc52xx_ata_apply_timings(struct mpc52xx_ata_priv *priv, int device) | 330 | mpc52xx_ata_apply_timings(struct mpc52xx_ata_priv *priv, int device) |
170 | { | 331 | { |
@@ -173,14 +334,13 @@ mpc52xx_ata_apply_timings(struct mpc52xx_ata_priv *priv, int device) | |||
173 | 334 | ||
174 | out_be32(®s->pio1, timing->pio1); | 335 | out_be32(®s->pio1, timing->pio1); |
175 | out_be32(®s->pio2, timing->pio2); | 336 | out_be32(®s->pio2, timing->pio2); |
176 | out_be32(®s->mdma1, 0); | 337 | out_be32(®s->mdma1, timing->mdma1); |
177 | out_be32(®s->mdma2, 0); | 338 | out_be32(®s->mdma2, timing->mdma2); |
178 | out_be32(®s->udma1, 0); | 339 | out_be32(®s->udma1, timing->udma1); |
179 | out_be32(®s->udma2, 0); | 340 | out_be32(®s->udma2, timing->udma2); |
180 | out_be32(®s->udma3, 0); | 341 | out_be32(®s->udma3, timing->udma3); |
181 | out_be32(®s->udma4, 0); | 342 | out_be32(®s->udma4, timing->udma4); |
182 | out_be32(®s->udma5, 0); | 343 | out_be32(®s->udma5, timing->udma5); |
183 | |||
184 | priv->csel = device; | 344 | priv->csel = device; |
185 | } | 345 | } |
186 | 346 | ||
@@ -208,7 +368,7 @@ mpc52xx_ata_hw_init(struct mpc52xx_ata_priv *priv) | |||
208 | 368 | ||
209 | /* Set the time slot to 1us */ | 369 | /* Set the time slot to 1us */ |
210 | tslot = CALC_CLKCYC(priv->ipb_period, 1000000); | 370 | tslot = CALC_CLKCYC(priv->ipb_period, 1000000); |
211 | out_be32(®s->share_cnt, tslot << 16 ); | 371 | out_be32(®s->share_cnt, tslot << 16); |
212 | 372 | ||
213 | /* Init timings to PIO0 */ | 373 | /* Init timings to PIO0 */ |
214 | memset(priv->timings, 0x00, 2*sizeof(struct mpc52xx_ata_timings)); | 374 | memset(priv->timings, 0x00, 2*sizeof(struct mpc52xx_ata_timings)); |
@@ -237,13 +397,37 @@ mpc52xx_ata_set_piomode(struct ata_port *ap, struct ata_device *adev) | |||
237 | rv = mpc52xx_ata_compute_pio_timings(priv, adev->devno, pio); | 397 | rv = mpc52xx_ata_compute_pio_timings(priv, adev->devno, pio); |
238 | 398 | ||
239 | if (rv) { | 399 | if (rv) { |
240 | printk(KERN_ERR DRV_NAME | 400 | dev_err(ap->dev, "error: invalid PIO mode: %d\n", pio); |
241 | ": Trying to select invalid PIO mode %d\n", pio); | 401 | return; |
402 | } | ||
403 | |||
404 | mpc52xx_ata_apply_timings(priv, adev->devno); | ||
405 | } | ||
406 | |||
407 | static void | ||
408 | mpc52xx_ata_set_dmamode(struct ata_port *ap, struct ata_device *adev) | ||
409 | { | ||
410 | struct mpc52xx_ata_priv *priv = ap->host->private_data; | ||
411 | int rv; | ||
412 | |||
413 | if (adev->dma_mode >= XFER_UDMA_0) { | ||
414 | int dma = adev->dma_mode - XFER_UDMA_0; | ||
415 | rv = mpc52xx_ata_compute_udma_timings(priv, adev->devno, dma); | ||
416 | } else { | ||
417 | int dma = adev->dma_mode - XFER_MW_DMA_0; | ||
418 | rv = mpc52xx_ata_compute_mdma_timings(priv, adev->devno, dma); | ||
419 | } | ||
420 | |||
421 | if (rv) { | ||
422 | dev_alert(ap->dev, | ||
423 | "Trying to select invalid DMA mode %d\n", | ||
424 | adev->dma_mode); | ||
242 | return; | 425 | return; |
243 | } | 426 | } |
244 | 427 | ||
245 | mpc52xx_ata_apply_timings(priv, adev->devno); | 428 | mpc52xx_ata_apply_timings(priv, adev->devno); |
246 | } | 429 | } |
430 | |||
247 | static void | 431 | static void |
248 | mpc52xx_ata_dev_select(struct ata_port *ap, unsigned int device) | 432 | mpc52xx_ata_dev_select(struct ata_port *ap, unsigned int device) |
249 | { | 433 | { |
@@ -252,7 +436,173 @@ mpc52xx_ata_dev_select(struct ata_port *ap, unsigned int device) | |||
252 | if (device != priv->csel) | 436 | if (device != priv->csel) |
253 | mpc52xx_ata_apply_timings(priv, device); | 437 | mpc52xx_ata_apply_timings(priv, device); |
254 | 438 | ||
255 | ata_sff_dev_select(ap,device); | 439 | ata_sff_dev_select(ap, device); |
440 | } | ||
441 | |||
442 | static int | ||
443 | mpc52xx_ata_build_dmatable(struct ata_queued_cmd *qc) | ||
444 | { | ||
445 | struct ata_port *ap = qc->ap; | ||
446 | struct mpc52xx_ata_priv *priv = ap->host->private_data; | ||
447 | struct bcom_ata_bd *bd; | ||
448 | unsigned int read = !(qc->tf.flags & ATA_TFLAG_WRITE), si; | ||
449 | struct scatterlist *sg; | ||
450 | int count = 0; | ||
451 | |||
452 | if (read) | ||
453 | bcom_ata_rx_prepare(priv->dmatsk); | ||
454 | else | ||
455 | bcom_ata_tx_prepare(priv->dmatsk); | ||
456 | |||
457 | for_each_sg(qc->sg, sg, qc->n_elem, si) { | ||
458 | dma_addr_t cur_addr = sg_dma_address(sg); | ||
459 | u32 cur_len = sg_dma_len(sg); | ||
460 | |||
461 | while (cur_len) { | ||
462 | unsigned int tc = min(cur_len, MAX_DMA_BUFFER_SIZE); | ||
463 | bd = (struct bcom_ata_bd *) | ||
464 | bcom_prepare_next_buffer(priv->dmatsk); | ||
465 | |||
466 | if (read) { | ||
467 | bd->status = tc; | ||
468 | bd->src_pa = (__force u32) priv->ata_regs_pa + | ||
469 | offsetof(struct mpc52xx_ata, fifo_data); | ||
470 | bd->dst_pa = (__force u32) cur_addr; | ||
471 | } else { | ||
472 | bd->status = tc; | ||
473 | bd->src_pa = (__force u32) cur_addr; | ||
474 | bd->dst_pa = (__force u32) priv->ata_regs_pa + | ||
475 | offsetof(struct mpc52xx_ata, fifo_data); | ||
476 | } | ||
477 | |||
478 | bcom_submit_next_buffer(priv->dmatsk, NULL); | ||
479 | |||
480 | cur_addr += tc; | ||
481 | cur_len -= tc; | ||
482 | count++; | ||
483 | |||
484 | if (count > MAX_DMA_BUFFERS) { | ||
485 | dev_alert(ap->dev, "dma table" | ||
486 | "too small\n"); | ||
487 | goto use_pio_instead; | ||
488 | } | ||
489 | } | ||
490 | } | ||
491 | return 1; | ||
492 | |||
493 | use_pio_instead: | ||
494 | bcom_ata_reset_bd(priv->dmatsk); | ||
495 | return 0; | ||
496 | } | ||
497 | |||
498 | static void | ||
499 | mpc52xx_bmdma_setup(struct ata_queued_cmd *qc) | ||
500 | { | ||
501 | struct ata_port *ap = qc->ap; | ||
502 | struct mpc52xx_ata_priv *priv = ap->host->private_data; | ||
503 | struct mpc52xx_ata __iomem *regs = priv->ata_regs; | ||
504 | |||
505 | unsigned int read = !(qc->tf.flags & ATA_TFLAG_WRITE); | ||
506 | u8 dma_mode; | ||
507 | |||
508 | if (!mpc52xx_ata_build_dmatable(qc)) | ||
509 | dev_alert(ap->dev, "%s: %i, return 1?\n", | ||
510 | __func__, __LINE__); | ||
511 | |||
512 | /* Check FIFO is OK... */ | ||
513 | if (in_8(&priv->ata_regs->fifo_status) & MPC52xx_ATA_FIFOSTAT_ERROR) | ||
514 | dev_alert(ap->dev, "%s: FIFO error detected: 0x%02x!\n", | ||
515 | __func__, in_8(&priv->ata_regs->fifo_status)); | ||
516 | |||
517 | if (read) { | ||
518 | dma_mode = MPC52xx_ATA_DMAMODE_IE | MPC52xx_ATA_DMAMODE_READ | | ||
519 | MPC52xx_ATA_DMAMODE_FE; | ||
520 | |||
521 | /* Setup FIFO if direction changed */ | ||
522 | if (priv->mpc52xx_ata_dma_last_write != 0) { | ||
523 | priv->mpc52xx_ata_dma_last_write = 0; | ||
524 | |||
525 | /* Configure FIFO with granularity to 7 */ | ||
526 | out_8(®s->fifo_control, 7); | ||
527 | out_be16(®s->fifo_alarm, 128); | ||
528 | |||
529 | /* Set FIFO Reset bit (FR) */ | ||
530 | out_8(®s->dma_mode, MPC52xx_ATA_DMAMODE_FR); | ||
531 | } | ||
532 | } else { | ||
533 | dma_mode = MPC52xx_ATA_DMAMODE_IE | MPC52xx_ATA_DMAMODE_WRITE; | ||
534 | |||
535 | /* Setup FIFO if direction changed */ | ||
536 | if (priv->mpc52xx_ata_dma_last_write != 1) { | ||
537 | priv->mpc52xx_ata_dma_last_write = 1; | ||
538 | |||
539 | /* Configure FIFO with granularity to 4 */ | ||
540 | out_8(®s->fifo_control, 4); | ||
541 | out_be16(®s->fifo_alarm, 128); | ||
542 | } | ||
543 | } | ||
544 | |||
545 | if (priv->timings[qc->dev->devno].using_udma) | ||
546 | dma_mode |= MPC52xx_ATA_DMAMODE_UDMA; | ||
547 | |||
548 | out_8(®s->dma_mode, dma_mode); | ||
549 | priv->waiting_for_dma = ATA_DMA_ACTIVE; | ||
550 | |||
551 | ata_wait_idle(ap); | ||
552 | ap->ops->sff_exec_command(ap, &qc->tf); | ||
553 | } | ||
554 | |||
555 | static void | ||
556 | mpc52xx_bmdma_start(struct ata_queued_cmd *qc) | ||
557 | { | ||
558 | struct ata_port *ap = qc->ap; | ||
559 | struct mpc52xx_ata_priv *priv = ap->host->private_data; | ||
560 | |||
561 | bcom_set_task_auto_start(priv->dmatsk->tasknum, priv->dmatsk->tasknum); | ||
562 | bcom_enable(priv->dmatsk); | ||
563 | } | ||
564 | |||
565 | static void | ||
566 | mpc52xx_bmdma_stop(struct ata_queued_cmd *qc) | ||
567 | { | ||
568 | struct ata_port *ap = qc->ap; | ||
569 | struct mpc52xx_ata_priv *priv = ap->host->private_data; | ||
570 | |||
571 | bcom_disable(priv->dmatsk); | ||
572 | bcom_ata_reset_bd(priv->dmatsk); | ||
573 | priv->waiting_for_dma = 0; | ||
574 | |||
575 | /* Check FIFO is OK... */ | ||
576 | if (in_8(&priv->ata_regs->fifo_status) & MPC52xx_ATA_FIFOSTAT_ERROR) | ||
577 | dev_alert(ap->dev, "%s: FIFO error detected: 0x%02x!\n", | ||
578 | __func__, in_8(&priv->ata_regs->fifo_status)); | ||
579 | } | ||
580 | |||
581 | static u8 | ||
582 | mpc52xx_bmdma_status(struct ata_port *ap) | ||
583 | { | ||
584 | struct mpc52xx_ata_priv *priv = ap->host->private_data; | ||
585 | |||
586 | /* Check FIFO is OK... */ | ||
587 | if (in_8(&priv->ata_regs->fifo_status) & MPC52xx_ATA_FIFOSTAT_ERROR) { | ||
588 | dev_alert(ap->dev, "%s: FIFO error detected: 0x%02x!\n", | ||
589 | __func__, in_8(&priv->ata_regs->fifo_status)); | ||
590 | return priv->waiting_for_dma | ATA_DMA_ERR; | ||
591 | } | ||
592 | |||
593 | return priv->waiting_for_dma; | ||
594 | } | ||
595 | |||
596 | static irqreturn_t | ||
597 | mpc52xx_ata_task_irq(int irq, void *vpriv) | ||
598 | { | ||
599 | struct mpc52xx_ata_priv *priv = vpriv; | ||
600 | while (bcom_buffer_done(priv->dmatsk)) | ||
601 | bcom_retrieve_buffer(priv->dmatsk, NULL, NULL); | ||
602 | |||
603 | priv->waiting_for_dma |= ATA_DMA_INTR; | ||
604 | |||
605 | return IRQ_HANDLED; | ||
256 | } | 606 | } |
257 | 607 | ||
258 | static struct scsi_host_template mpc52xx_ata_sht = { | 608 | static struct scsi_host_template mpc52xx_ata_sht = { |
@@ -262,14 +612,18 @@ static struct scsi_host_template mpc52xx_ata_sht = { | |||
262 | static struct ata_port_operations mpc52xx_ata_port_ops = { | 612 | static struct ata_port_operations mpc52xx_ata_port_ops = { |
263 | .inherits = &ata_sff_port_ops, | 613 | .inherits = &ata_sff_port_ops, |
264 | .sff_dev_select = mpc52xx_ata_dev_select, | 614 | .sff_dev_select = mpc52xx_ata_dev_select, |
265 | .cable_detect = ata_cable_40wire, | ||
266 | .set_piomode = mpc52xx_ata_set_piomode, | 615 | .set_piomode = mpc52xx_ata_set_piomode, |
267 | .post_internal_cmd = ATA_OP_NULL, | 616 | .set_dmamode = mpc52xx_ata_set_dmamode, |
617 | .bmdma_setup = mpc52xx_bmdma_setup, | ||
618 | .bmdma_start = mpc52xx_bmdma_start, | ||
619 | .bmdma_stop = mpc52xx_bmdma_stop, | ||
620 | .bmdma_status = mpc52xx_bmdma_status, | ||
621 | .qc_prep = ata_noop_qc_prep, | ||
268 | }; | 622 | }; |
269 | 623 | ||
270 | static int __devinit | 624 | static int __devinit |
271 | mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv, | 625 | mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv, |
272 | unsigned long raw_ata_regs) | 626 | unsigned long raw_ata_regs, int mwdma_mask, int udma_mask) |
273 | { | 627 | { |
274 | struct ata_host *host; | 628 | struct ata_host *host; |
275 | struct ata_port *ap; | 629 | struct ata_port *ap; |
@@ -281,9 +635,9 @@ mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv, | |||
281 | 635 | ||
282 | ap = host->ports[0]; | 636 | ap = host->ports[0]; |
283 | ap->flags |= ATA_FLAG_SLAVE_POSS; | 637 | ap->flags |= ATA_FLAG_SLAVE_POSS; |
284 | ap->pio_mask = 0x1f; /* Up to PIO4 */ | 638 | ap->pio_mask = ATA_PIO4; |
285 | ap->mwdma_mask = 0x00; /* No MWDMA */ | 639 | ap->mwdma_mask = mwdma_mask; |
286 | ap->udma_mask = 0x00; /* No UDMA */ | 640 | ap->udma_mask = udma_mask; |
287 | ap->ops = &mpc52xx_ata_port_ops; | 641 | ap->ops = &mpc52xx_ata_port_ops; |
288 | host->private_data = priv; | 642 | host->private_data = priv; |
289 | 643 | ||
@@ -330,89 +684,139 @@ mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match) | |||
330 | { | 684 | { |
331 | unsigned int ipb_freq; | 685 | unsigned int ipb_freq; |
332 | struct resource res_mem; | 686 | struct resource res_mem; |
333 | int ata_irq; | 687 | int ata_irq = 0; |
334 | struct mpc52xx_ata __iomem *ata_regs; | 688 | struct mpc52xx_ata __iomem *ata_regs; |
335 | struct mpc52xx_ata_priv *priv; | 689 | struct mpc52xx_ata_priv *priv = NULL; |
336 | int rv; | 690 | int rv, ret, task_irq = 0; |
691 | int mwdma_mask = 0, udma_mask = 0; | ||
692 | const __be32 *prop; | ||
693 | int proplen; | ||
694 | struct bcom_task *dmatsk = NULL; | ||
337 | 695 | ||
338 | /* Get ipb frequency */ | 696 | /* Get ipb frequency */ |
339 | ipb_freq = mpc52xx_find_ipb_freq(op->node); | 697 | ipb_freq = mpc52xx_find_ipb_freq(op->node); |
340 | if (!ipb_freq) { | 698 | if (!ipb_freq) { |
341 | printk(KERN_ERR DRV_NAME ": " | 699 | dev_err(&op->dev, "could not determine IPB bus frequency\n"); |
342 | "Unable to find IPB Bus frequency\n" ); | ||
343 | return -ENODEV; | 700 | return -ENODEV; |
344 | } | 701 | } |
345 | 702 | ||
346 | /* Get IRQ and register */ | 703 | /* Get device base address from device tree, request the region |
704 | * and ioremap it. */ | ||
347 | rv = of_address_to_resource(op->node, 0, &res_mem); | 705 | rv = of_address_to_resource(op->node, 0, &res_mem); |
348 | if (rv) { | 706 | if (rv) { |
349 | printk(KERN_ERR DRV_NAME ": " | 707 | dev_err(&op->dev, "could not determine device base address\n"); |
350 | "Error while parsing device node resource\n" ); | ||
351 | return rv; | 708 | return rv; |
352 | } | 709 | } |
353 | 710 | ||
354 | ata_irq = irq_of_parse_and_map(op->node, 0); | ||
355 | if (ata_irq == NO_IRQ) { | ||
356 | printk(KERN_ERR DRV_NAME ": " | ||
357 | "Error while mapping the irq\n"); | ||
358 | return -EINVAL; | ||
359 | } | ||
360 | |||
361 | /* Request mem region */ | ||
362 | if (!devm_request_mem_region(&op->dev, res_mem.start, | 711 | if (!devm_request_mem_region(&op->dev, res_mem.start, |
363 | sizeof(struct mpc52xx_ata), DRV_NAME)) { | 712 | sizeof(*ata_regs), DRV_NAME)) { |
364 | printk(KERN_ERR DRV_NAME ": " | 713 | dev_err(&op->dev, "error requesting register region\n"); |
365 | "Error while requesting mem region\n"); | 714 | return -EBUSY; |
366 | rv = -EBUSY; | ||
367 | goto err; | ||
368 | } | 715 | } |
369 | 716 | ||
370 | /* Remap registers */ | 717 | ata_regs = devm_ioremap(&op->dev, res_mem.start, sizeof(*ata_regs)); |
371 | ata_regs = devm_ioremap(&op->dev, res_mem.start, | ||
372 | sizeof(struct mpc52xx_ata)); | ||
373 | if (!ata_regs) { | 718 | if (!ata_regs) { |
374 | printk(KERN_ERR DRV_NAME ": " | 719 | dev_err(&op->dev, "error mapping device registers\n"); |
375 | "Error while mapping register set\n"); | ||
376 | rv = -ENOMEM; | 720 | rv = -ENOMEM; |
377 | goto err; | 721 | goto err; |
378 | } | 722 | } |
379 | 723 | ||
724 | /* | ||
725 | * By default, all DMA modes are disabled for the MPC5200. Some | ||
726 | * boards don't have the required signals routed to make DMA work. | ||
727 | * Also, the MPC5200B has a silicon bug that causes data corruption | ||
728 | * with UDMA if it is used at the same time as the LocalPlus bus. | ||
729 | * | ||
730 | * Instead of trying to guess what modes are usable, check the | ||
731 | * ATA device tree node to find out what DMA modes work on the board. | ||
732 | * UDMA/MWDMA modes can also be forced by adding "libata.force=<mode>" | ||
733 | * to the kernel boot parameters. | ||
734 | * | ||
735 | * The MPC5200 ATA controller supports MWDMA modes 0, 1 and 2 and | ||
736 | * UDMA modes 0, 1 and 2. | ||
737 | */ | ||
738 | prop = of_get_property(op->node, "mwdma-mode", &proplen); | ||
739 | if ((prop) && (proplen >= 4)) | ||
740 | mwdma_mask = 0x7 & ((1 << (*prop + 1)) - 1); | ||
741 | prop = of_get_property(op->node, "udma-mode", &proplen); | ||
742 | if ((prop) && (proplen >= 4)) | ||
743 | udma_mask = 0x7 & ((1 << (*prop + 1)) - 1); | ||
744 | |||
745 | ata_irq = irq_of_parse_and_map(op->node, 0); | ||
746 | if (ata_irq == NO_IRQ) { | ||
747 | dev_err(&op->dev, "error mapping irq\n"); | ||
748 | return -EINVAL; | ||
749 | } | ||
750 | |||
380 | /* Prepare our private structure */ | 751 | /* Prepare our private structure */ |
381 | priv = devm_kzalloc(&op->dev, sizeof(struct mpc52xx_ata_priv), | 752 | priv = devm_kzalloc(&op->dev, sizeof(*priv), GFP_ATOMIC); |
382 | GFP_ATOMIC); | ||
383 | if (!priv) { | 753 | if (!priv) { |
384 | printk(KERN_ERR DRV_NAME ": " | 754 | dev_err(&op->dev, "error allocating private structure\n"); |
385 | "Error while allocating private structure\n"); | ||
386 | rv = -ENOMEM; | 755 | rv = -ENOMEM; |
387 | goto err; | 756 | goto err; |
388 | } | 757 | } |
389 | 758 | ||
390 | priv->ipb_period = 1000000000 / (ipb_freq / 1000); | 759 | priv->ipb_period = 1000000000 / (ipb_freq / 1000); |
391 | priv->ata_regs = ata_regs; | 760 | priv->ata_regs = ata_regs; |
761 | priv->ata_regs_pa = res_mem.start; | ||
392 | priv->ata_irq = ata_irq; | 762 | priv->ata_irq = ata_irq; |
393 | priv->csel = -1; | 763 | priv->csel = -1; |
764 | priv->mpc52xx_ata_dma_last_write = -1; | ||
765 | |||
766 | if (ipb_freq/1000000 == 66) { | ||
767 | priv->mdmaspec = mdmaspec66; | ||
768 | priv->udmaspec = udmaspec66; | ||
769 | } else { | ||
770 | priv->mdmaspec = mdmaspec132; | ||
771 | priv->udmaspec = udmaspec132; | ||
772 | } | ||
773 | |||
774 | /* Allocate a BestComm task for DMA */ | ||
775 | dmatsk = bcom_ata_init(MAX_DMA_BUFFERS, MAX_DMA_BUFFER_SIZE); | ||
776 | if (!dmatsk) { | ||
777 | dev_err(&op->dev, "bestcomm initialization failed\n"); | ||
778 | rv = -ENOMEM; | ||
779 | goto err; | ||
780 | } | ||
781 | |||
782 | task_irq = bcom_get_task_irq(dmatsk); | ||
783 | ret = request_irq(task_irq, &mpc52xx_ata_task_irq, IRQF_DISABLED, | ||
784 | "ATA task", priv); | ||
785 | if (ret) { | ||
786 | dev_err(&op->dev, "error requesting DMA IRQ\n"); | ||
787 | goto err; | ||
788 | } | ||
789 | priv->dmatsk = dmatsk; | ||
394 | 790 | ||
395 | /* Init the hw */ | 791 | /* Init the hw */ |
396 | rv = mpc52xx_ata_hw_init(priv); | 792 | rv = mpc52xx_ata_hw_init(priv); |
397 | if (rv) { | 793 | if (rv) { |
398 | printk(KERN_ERR DRV_NAME ": Error during HW init\n"); | 794 | dev_err(&op->dev, "error initializing hardware\n"); |
399 | goto err; | 795 | goto err; |
400 | } | 796 | } |
401 | 797 | ||
402 | /* Register ourselves to libata */ | 798 | /* Register ourselves to libata */ |
403 | rv = mpc52xx_ata_init_one(&op->dev, priv, res_mem.start); | 799 | rv = mpc52xx_ata_init_one(&op->dev, priv, res_mem.start, |
800 | mwdma_mask, udma_mask); | ||
404 | if (rv) { | 801 | if (rv) { |
405 | printk(KERN_ERR DRV_NAME ": " | 802 | dev_err(&op->dev, "error registering with ATA layer\n"); |
406 | "Error while registering to ATA layer\n"); | 803 | goto err; |
407 | return rv; | ||
408 | } | 804 | } |
409 | 805 | ||
410 | /* Done */ | ||
411 | return 0; | 806 | return 0; |
412 | 807 | ||
413 | /* Error path */ | 808 | err: |
414 | err: | 809 | devm_release_mem_region(&op->dev, res_mem.start, sizeof(*ata_regs)); |
415 | irq_dispose_mapping(ata_irq); | 810 | if (ata_irq) |
811 | irq_dispose_mapping(ata_irq); | ||
812 | if (task_irq) | ||
813 | irq_dispose_mapping(task_irq); | ||
814 | if (dmatsk) | ||
815 | bcom_ata_release(dmatsk); | ||
816 | if (ata_regs) | ||
817 | devm_iounmap(&op->dev, ata_regs); | ||
818 | if (priv) | ||
819 | devm_kfree(&op->dev, priv); | ||
416 | return rv; | 820 | return rv; |
417 | } | 821 | } |
418 | 822 | ||
@@ -420,10 +824,23 @@ static int | |||
420 | mpc52xx_ata_remove(struct of_device *op) | 824 | mpc52xx_ata_remove(struct of_device *op) |
421 | { | 825 | { |
422 | struct mpc52xx_ata_priv *priv; | 826 | struct mpc52xx_ata_priv *priv; |
827 | int task_irq; | ||
423 | 828 | ||
829 | /* Deregister the ATA interface */ | ||
424 | priv = mpc52xx_ata_remove_one(&op->dev); | 830 | priv = mpc52xx_ata_remove_one(&op->dev); |
831 | |||
832 | /* Clean up DMA */ | ||
833 | task_irq = bcom_get_task_irq(priv->dmatsk); | ||
834 | irq_dispose_mapping(task_irq); | ||
835 | bcom_ata_release(priv->dmatsk); | ||
425 | irq_dispose_mapping(priv->ata_irq); | 836 | irq_dispose_mapping(priv->ata_irq); |
426 | 837 | ||
838 | /* Clear up IO allocations */ | ||
839 | devm_iounmap(&op->dev, priv->ata_regs); | ||
840 | devm_release_mem_region(&op->dev, priv->ata_regs_pa, | ||
841 | sizeof(*priv->ata_regs)); | ||
842 | devm_kfree(&op->dev, priv); | ||
843 | |||
427 | return 0; | 844 | return 0; |
428 | } | 845 | } |
429 | 846 | ||
@@ -447,7 +864,7 @@ mpc52xx_ata_resume(struct of_device *op) | |||
447 | 864 | ||
448 | rv = mpc52xx_ata_hw_init(priv); | 865 | rv = mpc52xx_ata_hw_init(priv); |
449 | if (rv) { | 866 | if (rv) { |
450 | printk(KERN_ERR DRV_NAME ": Error during HW init\n"); | 867 | dev_err(host->dev, "error initializing hardware\n"); |
451 | return rv; | 868 | return rv; |
452 | } | 869 | } |
453 | 870 | ||
@@ -507,5 +924,4 @@ MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>"); | |||
507 | MODULE_DESCRIPTION("Freescale MPC52xx IDE/ATA libata driver"); | 924 | MODULE_DESCRIPTION("Freescale MPC52xx IDE/ATA libata driver"); |
508 | MODULE_LICENSE("GPL"); | 925 | MODULE_LICENSE("GPL"); |
509 | MODULE_DEVICE_TABLE(of, mpc52xx_ata_of_match); | 926 | MODULE_DEVICE_TABLE(of, mpc52xx_ata_of_match); |
510 | MODULE_VERSION(DRV_VERSION); | ||
511 | 927 | ||
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 8783457b93d3..c602b547cc6e 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -641,6 +641,12 @@ config HVC_XEN | |||
641 | help | 641 | help |
642 | Xen virtual console device driver | 642 | Xen virtual console device driver |
643 | 643 | ||
644 | config HVC_UDBG | ||
645 | bool "udbg based fake hypervisor console" | ||
646 | depends on PPC && EXPERIMENTAL | ||
647 | select HVC_DRIVER | ||
648 | default n | ||
649 | |||
644 | config VIRTIO_CONSOLE | 650 | config VIRTIO_CONSOLE |
645 | tristate "Virtio console" | 651 | tristate "Virtio console" |
646 | depends on VIRTIO | 652 | depends on VIRTIO |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 36151bae0d72..9caf5b5ad1c0 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -51,6 +51,7 @@ obj-$(CONFIG_HVC_DRIVER) += hvc_console.o | |||
51 | obj-$(CONFIG_HVC_IRQ) += hvc_irq.o | 51 | obj-$(CONFIG_HVC_IRQ) += hvc_irq.o |
52 | obj-$(CONFIG_HVC_XEN) += hvc_xen.o | 52 | obj-$(CONFIG_HVC_XEN) += hvc_xen.o |
53 | obj-$(CONFIG_HVC_IUCV) += hvc_iucv.o | 53 | obj-$(CONFIG_HVC_IUCV) += hvc_iucv.o |
54 | obj-$(CONFIG_HVC_UDBG) += hvc_udbg.o | ||
54 | obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o | 55 | obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o |
55 | obj-$(CONFIG_RAW_DRIVER) += raw.o | 56 | obj-$(CONFIG_RAW_DRIVER) += raw.o |
56 | obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o | 57 | obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o |
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c index 456f54db73e2..977dfb1096a0 100644 --- a/drivers/char/bsr.c +++ b/drivers/char/bsr.c | |||
@@ -60,6 +60,8 @@ struct bsr_dev { | |||
60 | unsigned bsr_num; /* bsr id number for its type */ | 60 | unsigned bsr_num; /* bsr id number for its type */ |
61 | int bsr_minor; | 61 | int bsr_minor; |
62 | 62 | ||
63 | struct list_head bsr_list; | ||
64 | |||
63 | dev_t bsr_dev; | 65 | dev_t bsr_dev; |
64 | struct cdev bsr_cdev; | 66 | struct cdev bsr_cdev; |
65 | struct device *bsr_device; | 67 | struct device *bsr_device; |
@@ -67,8 +69,8 @@ struct bsr_dev { | |||
67 | 69 | ||
68 | }; | 70 | }; |
69 | 71 | ||
70 | static unsigned num_bsr_devs; | 72 | static unsigned total_bsr_devs; |
71 | static struct bsr_dev *bsr_devs; | 73 | static struct list_head bsr_devs = LIST_HEAD_INIT(bsr_devs); |
72 | static struct class *bsr_class; | 74 | static struct class *bsr_class; |
73 | static int bsr_major; | 75 | static int bsr_major; |
74 | 76 | ||
@@ -146,24 +148,25 @@ const static struct file_operations bsr_fops = { | |||
146 | 148 | ||
147 | static void bsr_cleanup_devs(void) | 149 | static void bsr_cleanup_devs(void) |
148 | { | 150 | { |
149 | int i; | 151 | struct bsr_dev *cur, *n; |
150 | for (i=0 ; i < num_bsr_devs; i++) { | 152 | |
151 | struct bsr_dev *cur = bsr_devs + i; | 153 | list_for_each_entry_safe(cur, n, &bsr_devs, bsr_list) { |
152 | if (cur->bsr_device) { | 154 | if (cur->bsr_device) { |
153 | cdev_del(&cur->bsr_cdev); | 155 | cdev_del(&cur->bsr_cdev); |
154 | device_del(cur->bsr_device); | 156 | device_del(cur->bsr_device); |
155 | } | 157 | } |
158 | list_del(&cur->bsr_list); | ||
159 | kfree(cur); | ||
156 | } | 160 | } |
157 | |||
158 | kfree(bsr_devs); | ||
159 | } | 161 | } |
160 | 162 | ||
161 | static int bsr_create_devs(struct device_node *bn) | 163 | static int bsr_add_node(struct device_node *bn) |
162 | { | 164 | { |
163 | int bsr_stride_len, bsr_bytes_len; | 165 | int bsr_stride_len, bsr_bytes_len, num_bsr_devs; |
164 | const u32 *bsr_stride; | 166 | const u32 *bsr_stride; |
165 | const u32 *bsr_bytes; | 167 | const u32 *bsr_bytes; |
166 | unsigned i; | 168 | unsigned i; |
169 | int ret = -ENODEV; | ||
167 | 170 | ||
168 | bsr_stride = of_get_property(bn, "ibm,lock-stride", &bsr_stride_len); | 171 | bsr_stride = of_get_property(bn, "ibm,lock-stride", &bsr_stride_len); |
169 | bsr_bytes = of_get_property(bn, "ibm,#lock-bytes", &bsr_bytes_len); | 172 | bsr_bytes = of_get_property(bn, "ibm,#lock-bytes", &bsr_bytes_len); |
@@ -171,35 +174,36 @@ static int bsr_create_devs(struct device_node *bn) | |||
171 | if (!bsr_stride || !bsr_bytes || | 174 | if (!bsr_stride || !bsr_bytes || |
172 | (bsr_stride_len != bsr_bytes_len)) { | 175 | (bsr_stride_len != bsr_bytes_len)) { |
173 | printk(KERN_ERR "bsr of-node has missing/incorrect property\n"); | 176 | printk(KERN_ERR "bsr of-node has missing/incorrect property\n"); |
174 | return -ENODEV; | 177 | return ret; |
175 | } | 178 | } |
176 | 179 | ||
177 | num_bsr_devs = bsr_bytes_len / sizeof(u32); | 180 | num_bsr_devs = bsr_bytes_len / sizeof(u32); |
178 | 181 | ||
179 | /* only a warning, its informational since we'll fail and exit */ | ||
180 | WARN_ON(num_bsr_devs > BSR_MAX_DEVS); | ||
181 | |||
182 | bsr_devs = kzalloc(sizeof(struct bsr_dev) * num_bsr_devs, GFP_KERNEL); | ||
183 | if (!bsr_devs) | ||
184 | return -ENOMEM; | ||
185 | |||
186 | for (i = 0 ; i < num_bsr_devs; i++) { | 182 | for (i = 0 ; i < num_bsr_devs; i++) { |
187 | struct bsr_dev *cur = bsr_devs + i; | 183 | struct bsr_dev *cur = kzalloc(sizeof(struct bsr_dev), |
184 | GFP_KERNEL); | ||
188 | struct resource res; | 185 | struct resource res; |
189 | int result; | 186 | int result; |
190 | 187 | ||
188 | if (!cur) { | ||
189 | printk(KERN_ERR "Unable to alloc bsr dev\n"); | ||
190 | ret = -ENOMEM; | ||
191 | goto out_err; | ||
192 | } | ||
193 | |||
191 | result = of_address_to_resource(bn, i, &res); | 194 | result = of_address_to_resource(bn, i, &res); |
192 | if (result < 0) { | 195 | if (result < 0) { |
193 | printk(KERN_ERR "bsr of-node has invalid reg property\n"); | 196 | printk(KERN_ERR "bsr of-node has invalid reg property, skipping\n"); |
194 | goto out_err; | 197 | kfree(cur); |
198 | continue; | ||
195 | } | 199 | } |
196 | 200 | ||
197 | cur->bsr_minor = i; | 201 | cur->bsr_minor = i + total_bsr_devs; |
198 | cur->bsr_addr = res.start; | 202 | cur->bsr_addr = res.start; |
199 | cur->bsr_len = res.end - res.start + 1; | 203 | cur->bsr_len = res.end - res.start + 1; |
200 | cur->bsr_bytes = bsr_bytes[i]; | 204 | cur->bsr_bytes = bsr_bytes[i]; |
201 | cur->bsr_stride = bsr_stride[i]; | 205 | cur->bsr_stride = bsr_stride[i]; |
202 | cur->bsr_dev = MKDEV(bsr_major, i); | 206 | cur->bsr_dev = MKDEV(bsr_major, i + total_bsr_devs); |
203 | 207 | ||
204 | switch(cur->bsr_bytes) { | 208 | switch(cur->bsr_bytes) { |
205 | case 8: | 209 | case 8: |
@@ -220,14 +224,15 @@ static int bsr_create_devs(struct device_node *bn) | |||
220 | } | 224 | } |
221 | 225 | ||
222 | cur->bsr_num = bsr_types[cur->bsr_type]; | 226 | cur->bsr_num = bsr_types[cur->bsr_type]; |
223 | bsr_types[cur->bsr_type] = cur->bsr_num + 1; | ||
224 | snprintf(cur->bsr_name, 32, "bsr%d_%d", | 227 | snprintf(cur->bsr_name, 32, "bsr%d_%d", |
225 | cur->bsr_bytes, cur->bsr_num); | 228 | cur->bsr_bytes, cur->bsr_num); |
226 | 229 | ||
227 | cdev_init(&cur->bsr_cdev, &bsr_fops); | 230 | cdev_init(&cur->bsr_cdev, &bsr_fops); |
228 | result = cdev_add(&cur->bsr_cdev, cur->bsr_dev, 1); | 231 | result = cdev_add(&cur->bsr_cdev, cur->bsr_dev, 1); |
229 | if (result) | 232 | if (result) { |
233 | kfree(cur); | ||
230 | goto out_err; | 234 | goto out_err; |
235 | } | ||
231 | 236 | ||
232 | cur->bsr_device = device_create(bsr_class, NULL, cur->bsr_dev, | 237 | cur->bsr_device = device_create(bsr_class, NULL, cur->bsr_dev, |
233 | cur, cur->bsr_name); | 238 | cur, cur->bsr_name); |
@@ -235,16 +240,37 @@ static int bsr_create_devs(struct device_node *bn) | |||
235 | printk(KERN_ERR "device_create failed for %s\n", | 240 | printk(KERN_ERR "device_create failed for %s\n", |
236 | cur->bsr_name); | 241 | cur->bsr_name); |
237 | cdev_del(&cur->bsr_cdev); | 242 | cdev_del(&cur->bsr_cdev); |
243 | kfree(cur); | ||
238 | goto out_err; | 244 | goto out_err; |
239 | } | 245 | } |
246 | |||
247 | bsr_types[cur->bsr_type] = cur->bsr_num + 1; | ||
248 | list_add_tail(&cur->bsr_list, &bsr_devs); | ||
240 | } | 249 | } |
241 | 250 | ||
251 | total_bsr_devs += num_bsr_devs; | ||
252 | |||
242 | return 0; | 253 | return 0; |
243 | 254 | ||
244 | out_err: | 255 | out_err: |
245 | 256 | ||
246 | bsr_cleanup_devs(); | 257 | bsr_cleanup_devs(); |
247 | return -ENODEV; | 258 | return ret; |
259 | } | ||
260 | |||
261 | static int bsr_create_devs(struct device_node *bn) | ||
262 | { | ||
263 | int ret; | ||
264 | |||
265 | while (bn) { | ||
266 | ret = bsr_add_node(bn); | ||
267 | if (ret) { | ||
268 | of_node_put(bn); | ||
269 | return ret; | ||
270 | } | ||
271 | bn = of_find_compatible_node(bn, NULL, "ibm,bsr"); | ||
272 | } | ||
273 | return 0; | ||
248 | } | 274 | } |
249 | 275 | ||
250 | static int __init bsr_init(void) | 276 | static int __init bsr_init(void) |
@@ -254,7 +280,7 @@ static int __init bsr_init(void) | |||
254 | int ret = -ENODEV; | 280 | int ret = -ENODEV; |
255 | int result; | 281 | int result; |
256 | 282 | ||
257 | np = of_find_compatible_node(NULL, "ibm,bsr", "ibm,bsr"); | 283 | np = of_find_compatible_node(NULL, NULL, "ibm,bsr"); |
258 | if (!np) | 284 | if (!np) |
259 | goto out_err; | 285 | goto out_err; |
260 | 286 | ||
@@ -272,10 +298,10 @@ static int __init bsr_init(void) | |||
272 | goto out_err_2; | 298 | goto out_err_2; |
273 | } | 299 | } |
274 | 300 | ||
275 | if ((ret = bsr_create_devs(np)) < 0) | 301 | if ((ret = bsr_create_devs(np)) < 0) { |
302 | np = NULL; | ||
276 | goto out_err_3; | 303 | goto out_err_3; |
277 | 304 | } | |
278 | of_node_put(np); | ||
279 | 305 | ||
280 | return 0; | 306 | return 0; |
281 | 307 | ||
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 5b819b12675a..fb57f67bb427 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
@@ -642,8 +642,11 @@ int hvc_poll(struct hvc_struct *hp) | |||
642 | /* Handle the SysRq Hack */ | 642 | /* Handle the SysRq Hack */ |
643 | /* XXX should support a sequence */ | 643 | /* XXX should support a sequence */ |
644 | if (buf[i] == '\x0f') { /* ^O */ | 644 | if (buf[i] == '\x0f') { /* ^O */ |
645 | sysrq_pressed = 1; | 645 | /* if ^O is pressed again, reset |
646 | continue; | 646 | * sysrq_pressed and flip ^O char */ |
647 | sysrq_pressed = !sysrq_pressed; | ||
648 | if (sysrq_pressed) | ||
649 | continue; | ||
647 | } else if (sysrq_pressed) { | 650 | } else if (sysrq_pressed) { |
648 | handle_sysrq(buf[i], tty); | 651 | handle_sysrq(buf[i], tty); |
649 | sysrq_pressed = 0; | 652 | sysrq_pressed = 0; |
@@ -689,10 +692,8 @@ EXPORT_SYMBOL_GPL(hvc_poll); | |||
689 | */ | 692 | */ |
690 | void hvc_resize(struct hvc_struct *hp, struct winsize ws) | 693 | void hvc_resize(struct hvc_struct *hp, struct winsize ws) |
691 | { | 694 | { |
692 | if ((hp->ws.ws_row != ws.ws_row) || (hp->ws.ws_col != ws.ws_col)) { | 695 | hp->ws = ws; |
693 | hp->ws = ws; | 696 | schedule_work(&hp->tty_resize); |
694 | schedule_work(&hp->tty_resize); | ||
695 | } | ||
696 | } | 697 | } |
697 | 698 | ||
698 | /* | 699 | /* |
diff --git a/drivers/char/hvc_console.h b/drivers/char/hvc_console.h index 8297dbc2e6ec..3c85d78c975c 100644 --- a/drivers/char/hvc_console.h +++ b/drivers/char/hvc_console.h | |||
@@ -48,7 +48,7 @@ struct hvc_struct { | |||
48 | spinlock_t lock; | 48 | spinlock_t lock; |
49 | int index; | 49 | int index; |
50 | struct tty_struct *tty; | 50 | struct tty_struct *tty; |
51 | unsigned int count; | 51 | int count; |
52 | int do_wakeup; | 52 | int do_wakeup; |
53 | char *outbuf; | 53 | char *outbuf; |
54 | int outbuf_size; | 54 | int outbuf_size; |
diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c index b74a2f8ab908..449727b6166d 100644 --- a/drivers/char/hvc_iseries.c +++ b/drivers/char/hvc_iseries.c | |||
@@ -575,8 +575,10 @@ static int __init hvc_find_vtys(void) | |||
575 | * of console adapters. | 575 | * of console adapters. |
576 | */ | 576 | */ |
577 | if ((num_found >= MAX_NR_HVC_CONSOLES) || | 577 | if ((num_found >= MAX_NR_HVC_CONSOLES) || |
578 | (num_found >= VTTY_PORTS)) | 578 | (num_found >= VTTY_PORTS)) { |
579 | of_node_put(vty); | ||
579 | break; | 580 | break; |
581 | } | ||
580 | 582 | ||
581 | vtermno = of_get_property(vty, "reg", NULL); | 583 | vtermno = of_get_property(vty, "reg", NULL); |
582 | if (!vtermno) | 584 | if (!vtermno) |
diff --git a/drivers/char/hvc_udbg.c b/drivers/char/hvc_udbg.c new file mode 100644 index 000000000000..bd63ba878a56 --- /dev/null +++ b/drivers/char/hvc_udbg.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * udbg interface to hvc_console.c | ||
3 | * | ||
4 | * (C) Copyright David Gibson, IBM Corporation 2008. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
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 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/console.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/err.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/moduleparam.h> | ||
26 | #include <linux/types.h> | ||
27 | #include <linux/irq.h> | ||
28 | |||
29 | #include <asm/udbg.h> | ||
30 | |||
31 | #include "hvc_console.h" | ||
32 | |||
33 | struct hvc_struct *hvc_udbg_dev; | ||
34 | |||
35 | static int hvc_udbg_put(uint32_t vtermno, const char *buf, int count) | ||
36 | { | ||
37 | int i; | ||
38 | |||
39 | for (i = 0; i < count; i++) | ||
40 | udbg_putc(buf[i]); | ||
41 | |||
42 | return i; | ||
43 | } | ||
44 | |||
45 | static int hvc_udbg_get(uint32_t vtermno, char *buf, int count) | ||
46 | { | ||
47 | int i, c; | ||
48 | |||
49 | if (!udbg_getc_poll) | ||
50 | return 0; | ||
51 | |||
52 | for (i = 0; i < count; i++) { | ||
53 | if ((c = udbg_getc_poll()) == -1) | ||
54 | break; | ||
55 | buf[i] = c; | ||
56 | } | ||
57 | |||
58 | return i; | ||
59 | } | ||
60 | |||
61 | static struct hv_ops hvc_udbg_ops = { | ||
62 | .get_chars = hvc_udbg_get, | ||
63 | .put_chars = hvc_udbg_put, | ||
64 | }; | ||
65 | |||
66 | static int __init hvc_udbg_init(void) | ||
67 | { | ||
68 | struct hvc_struct *hp; | ||
69 | |||
70 | BUG_ON(hvc_udbg_dev); | ||
71 | |||
72 | hp = hvc_alloc(0, NO_IRQ, &hvc_udbg_ops, 16); | ||
73 | if (IS_ERR(hp)) | ||
74 | return PTR_ERR(hp); | ||
75 | |||
76 | hvc_udbg_dev = hp; | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | module_init(hvc_udbg_init); | ||
81 | |||
82 | static void __exit hvc_udbg_exit(void) | ||
83 | { | ||
84 | if (hvc_udbg_dev) | ||
85 | hvc_remove(hvc_udbg_dev); | ||
86 | } | ||
87 | module_exit(hvc_udbg_exit); | ||
88 | |||
89 | static int __init hvc_udbg_console_init(void) | ||
90 | { | ||
91 | hvc_instantiate(0, 0, &hvc_udbg_ops); | ||
92 | add_preferred_console("hvc", 0, NULL); | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | console_initcall(hvc_udbg_console_init); | ||
diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c index 019e0b58593d..bd62dc86b47d 100644 --- a/drivers/char/hvc_vio.c +++ b/drivers/char/hvc_vio.c | |||
@@ -153,8 +153,10 @@ static int hvc_find_vtys(void) | |||
153 | /* We have statically defined space for only a certain number | 153 | /* We have statically defined space for only a certain number |
154 | * of console adapters. | 154 | * of console adapters. |
155 | */ | 155 | */ |
156 | if (num_found >= MAX_NR_HVC_CONSOLES) | 156 | if (num_found >= MAX_NR_HVC_CONSOLES) { |
157 | of_node_put(vty); | ||
157 | break; | 158 | break; |
159 | } | ||
158 | 160 | ||
159 | vtermno = of_get_property(vty, "reg", NULL); | 161 | vtermno = of_get_property(vty, "reg", NULL); |
160 | if (!vtermno) | 162 | if (!vtermno) |
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 473d9b14439a..6e6eb445d374 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c | |||
@@ -269,7 +269,7 @@ struct hvcs_struct { | |||
269 | unsigned int index; | 269 | unsigned int index; |
270 | 270 | ||
271 | struct tty_struct *tty; | 271 | struct tty_struct *tty; |
272 | unsigned int open_count; | 272 | int open_count; |
273 | 273 | ||
274 | /* | 274 | /* |
275 | * Used to tell the driver kernel_thread what operations need to take | 275 | * Used to tell the driver kernel_thread what operations need to take |
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index 59c6f9ab94e4..af055287271a 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c | |||
@@ -75,7 +75,7 @@ struct hvsi_struct { | |||
75 | spinlock_t lock; | 75 | spinlock_t lock; |
76 | int index; | 76 | int index; |
77 | struct tty_struct *tty; | 77 | struct tty_struct *tty; |
78 | unsigned int count; | 78 | int count; |
79 | uint8_t throttle_buf[128]; | 79 | uint8_t throttle_buf[128]; |
80 | uint8_t outbuf[N_OUTBUF]; /* to implement write_room and chars_in_buffer */ | 80 | uint8_t outbuf[N_OUTBUF]; /* to implement write_room and chars_in_buffer */ |
81 | /* inbuf is for packet reassembly. leave a little room for leftovers. */ | 81 | /* inbuf is for packet reassembly. leave a little room for leftovers. */ |
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index e0dbd388757f..e2667a8c2997 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig | |||
@@ -161,7 +161,7 @@ config EDAC_PASEMI | |||
161 | 161 | ||
162 | config EDAC_CELL | 162 | config EDAC_CELL |
163 | tristate "Cell Broadband Engine memory controller" | 163 | tristate "Cell Broadband Engine memory controller" |
164 | depends on EDAC_MM_EDAC && PPC_CELL_NATIVE | 164 | depends on EDAC_MM_EDAC && PPC_CELL_COMMON |
165 | help | 165 | help |
166 | Support for error detection and correction on the | 166 | Support for error detection and correction on the |
167 | Cell Broadband Engine internal memory controller | 167 | Cell Broadband Engine internal memory controller |
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index d524dc245a2c..b40fb9b6c862 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c | |||
@@ -1814,7 +1814,7 @@ static int powerbook_sleep_grackle(void) | |||
1814 | _set_L2CR(save_l2cr); | 1814 | _set_L2CR(save_l2cr); |
1815 | 1815 | ||
1816 | /* Restore userland MMU context */ | 1816 | /* Restore userland MMU context */ |
1817 | set_context(current->active_mm->context.id, current->active_mm->pgd); | 1817 | switch_mmu_context(NULL, current->active_mm); |
1818 | 1818 | ||
1819 | /* Power things up */ | 1819 | /* Power things up */ |
1820 | pmu_unlock(); | 1820 | pmu_unlock(); |
@@ -1903,7 +1903,7 @@ powerbook_sleep_Core99(void) | |||
1903 | _set_L3CR(save_l3cr); | 1903 | _set_L3CR(save_l3cr); |
1904 | 1904 | ||
1905 | /* Restore userland MMU context */ | 1905 | /* Restore userland MMU context */ |
1906 | set_context(current->active_mm->context.id, current->active_mm->pgd); | 1906 | switch_mmu_context(NULL, current->active_mm); |
1907 | 1907 | ||
1908 | /* Tell PMU we are ready */ | 1908 | /* Tell PMU we are ready */ |
1909 | pmu_unlock(); | 1909 | pmu_unlock(); |
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c index 7f2be4baaeda..7847e981ac33 100644 --- a/drivers/macintosh/windfarm_smu_sat.c +++ b/drivers/macintosh/windfarm_smu_sat.c | |||
@@ -87,11 +87,12 @@ struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, | |||
87 | return NULL; | 87 | return NULL; |
88 | } | 88 | } |
89 | 89 | ||
90 | len = i2c_smbus_read_word_data(&sat->i2c, 9); | 90 | err = i2c_smbus_read_word_data(&sat->i2c, 9); |
91 | if (len < 0) { | 91 | if (err < 0) { |
92 | printk(KERN_ERR "smu_sat_get_sdb_part rd len error\n"); | 92 | printk(KERN_ERR "smu_sat_get_sdb_part rd len error\n"); |
93 | return NULL; | 93 | return NULL; |
94 | } | 94 | } |
95 | len = err; | ||
95 | if (len == 0) { | 96 | if (len == 0) { |
96 | printk(KERN_ERR "smu_sat_get_sdb_part no partition %x\n", id); | 97 | printk(KERN_ERR "smu_sat_get_sdb_part no partition %x\n", id); |
97 | return NULL; | 98 | return NULL; |
diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c index 45dd9bdc5d62..dd9bfa42ac34 100644 --- a/drivers/net/fec_mpc52xx_phy.c +++ b/drivers/net/fec_mpc52xx_phy.c | |||
@@ -122,9 +122,6 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, | |||
122 | out_be32(&priv->regs->mii_speed, | 122 | out_be32(&priv->regs->mii_speed, |
123 | ((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1); | 123 | ((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1); |
124 | 124 | ||
125 | /* enable MII interrupt */ | ||
126 | out_be32(&priv->regs->imask, in_be32(&priv->regs->imask) | FEC_IMASK_MII); | ||
127 | |||
128 | err = mdiobus_register(bus); | 125 | err = mdiobus_register(bus); |
129 | if (err) | 126 | if (err) |
130 | goto out_unmap; | 127 | goto out_unmap; |
@@ -156,7 +153,7 @@ static int mpc52xx_fec_mdio_remove(struct of_device *of) | |||
156 | 153 | ||
157 | iounmap(priv->regs); | 154 | iounmap(priv->regs); |
158 | for (i=0; i<PHY_MAX_ADDR; i++) | 155 | for (i=0; i<PHY_MAX_ADDR; i++) |
159 | if (bus->irq[i]) | 156 | if (bus->irq[i] != PHY_POLL) |
160 | irq_dispose_mapping(bus->irq[i]); | 157 | irq_dispose_mapping(bus->irq[i]); |
161 | kfree(priv); | 158 | kfree(priv); |
162 | kfree(bus->irq); | 159 | kfree(bus->irq); |
diff --git a/drivers/of/base.c b/drivers/of/base.c index 7c79e94a35ea..cd17092b82bd 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -329,6 +329,41 @@ struct device_node *of_find_compatible_node(struct device_node *from, | |||
329 | EXPORT_SYMBOL(of_find_compatible_node); | 329 | EXPORT_SYMBOL(of_find_compatible_node); |
330 | 330 | ||
331 | /** | 331 | /** |
332 | * of_find_node_with_property - Find a node which has a property with | ||
333 | * the given name. | ||
334 | * @from: The node to start searching from or NULL, the node | ||
335 | * you pass will not be searched, only the next one | ||
336 | * will; typically, you pass what the previous call | ||
337 | * returned. of_node_put() will be called on it | ||
338 | * @prop_name: The name of the property to look for. | ||
339 | * | ||
340 | * Returns a node pointer with refcount incremented, use | ||
341 | * of_node_put() on it when done. | ||
342 | */ | ||
343 | struct device_node *of_find_node_with_property(struct device_node *from, | ||
344 | const char *prop_name) | ||
345 | { | ||
346 | struct device_node *np; | ||
347 | struct property *pp; | ||
348 | |||
349 | read_lock(&devtree_lock); | ||
350 | np = from ? from->allnext : allnodes; | ||
351 | for (; np; np = np->allnext) { | ||
352 | for (pp = np->properties; pp != 0; pp = pp->next) { | ||
353 | if (of_prop_cmp(pp->name, prop_name) == 0) { | ||
354 | of_node_get(np); | ||
355 | goto out; | ||
356 | } | ||
357 | } | ||
358 | } | ||
359 | out: | ||
360 | of_node_put(from); | ||
361 | read_unlock(&devtree_lock); | ||
362 | return np; | ||
363 | } | ||
364 | EXPORT_SYMBOL(of_find_node_with_property); | ||
365 | |||
366 | /** | ||
332 | * of_match_node - Tell if an device_node has a matching of_match structure | 367 | * of_match_node - Tell if an device_node has a matching of_match structure |
333 | * @matches: array of of device match structures to search in | 368 | * @matches: array of of device match structures to search in |
334 | * @node: the of device structure to match against | 369 | * @node: the of device structure to match against |
@@ -464,8 +499,8 @@ EXPORT_SYMBOL_GPL(of_modalias_node); | |||
464 | * @list_name: property name that contains a list | 499 | * @list_name: property name that contains a list |
465 | * @cells_name: property name that specifies phandles' arguments count | 500 | * @cells_name: property name that specifies phandles' arguments count |
466 | * @index: index of a phandle to parse out | 501 | * @index: index of a phandle to parse out |
467 | * @out_node: pointer to device_node struct pointer (will be filled) | 502 | * @out_node: optional pointer to device_node struct pointer (will be filled) |
468 | * @out_args: pointer to arguments pointer (will be filled) | 503 | * @out_args: optional pointer to arguments pointer (will be filled) |
469 | * | 504 | * |
470 | * This function is useful to parse lists of phandles and their arguments. | 505 | * This function is useful to parse lists of phandles and their arguments. |
471 | * Returns 0 on success and fills out_node and out_args, on error returns | 506 | * Returns 0 on success and fills out_node and out_args, on error returns |
@@ -499,7 +534,7 @@ int of_parse_phandles_with_args(struct device_node *np, const char *list_name, | |||
499 | int size; | 534 | int size; |
500 | int cur_index = 0; | 535 | int cur_index = 0; |
501 | struct device_node *node = NULL; | 536 | struct device_node *node = NULL; |
502 | const void *args; | 537 | const void *args = NULL; |
503 | 538 | ||
504 | list = of_get_property(np, list_name, &size); | 539 | list = of_get_property(np, list_name, &size); |
505 | if (!list) { | 540 | if (!list) { |
@@ -512,14 +547,12 @@ int of_parse_phandles_with_args(struct device_node *np, const char *list_name, | |||
512 | const u32 *cells; | 547 | const u32 *cells; |
513 | const phandle *phandle; | 548 | const phandle *phandle; |
514 | 549 | ||
515 | phandle = list; | 550 | phandle = list++; |
516 | args = list + 1; | 551 | args = list; |
517 | 552 | ||
518 | /* one cell hole in the list = <>; */ | 553 | /* one cell hole in the list = <>; */ |
519 | if (!*phandle) { | 554 | if (!*phandle) |
520 | list++; | ||
521 | goto next; | 555 | goto next; |
522 | } | ||
523 | 556 | ||
524 | node = of_find_node_by_phandle(*phandle); | 557 | node = of_find_node_by_phandle(*phandle); |
525 | if (!node) { | 558 | if (!node) { |
@@ -535,8 +568,7 @@ int of_parse_phandles_with_args(struct device_node *np, const char *list_name, | |||
535 | goto err1; | 568 | goto err1; |
536 | } | 569 | } |
537 | 570 | ||
538 | /* Next phandle is at offset of one phandle cell + #cells */ | 571 | list += *cells; |
539 | list += 1 + *cells; | ||
540 | if (list > list_end) { | 572 | if (list > list_end) { |
541 | pr_debug("%s: insufficient arguments length\n", | 573 | pr_debug("%s: insufficient arguments length\n", |
542 | np->full_name); | 574 | np->full_name); |
@@ -548,16 +580,26 @@ next: | |||
548 | 580 | ||
549 | of_node_put(node); | 581 | of_node_put(node); |
550 | node = NULL; | 582 | node = NULL; |
583 | args = NULL; | ||
551 | cur_index++; | 584 | cur_index++; |
552 | } | 585 | } |
553 | 586 | ||
554 | if (!node) { | 587 | if (!node) { |
555 | ret = -ENOENT; | 588 | /* |
589 | * args w/o node indicates that the loop above has stopped at | ||
590 | * the 'hole' cell. Report this differently. | ||
591 | */ | ||
592 | if (args) | ||
593 | ret = -EEXIST; | ||
594 | else | ||
595 | ret = -ENOENT; | ||
556 | goto err0; | 596 | goto err0; |
557 | } | 597 | } |
558 | 598 | ||
559 | *out_node = node; | 599 | if (out_node) |
560 | *out_args = args; | 600 | *out_node = node; |
601 | if (out_args) | ||
602 | *out_args = args; | ||
561 | 603 | ||
562 | return 0; | 604 | return 0; |
563 | err1: | 605 | err1: |
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c index 7cd7301b5839..6eea601a9204 100644 --- a/drivers/of/gpio.c +++ b/drivers/of/gpio.c | |||
@@ -19,14 +19,17 @@ | |||
19 | #include <asm/prom.h> | 19 | #include <asm/prom.h> |
20 | 20 | ||
21 | /** | 21 | /** |
22 | * of_get_gpio - Get a GPIO number from the device tree to use with GPIO API | 22 | * of_get_gpio_flags - Get a GPIO number and flags to use with GPIO API |
23 | * @np: device node to get GPIO from | 23 | * @np: device node to get GPIO from |
24 | * @index: index of the GPIO | 24 | * @index: index of the GPIO |
25 | * @flags: a flags pointer to fill in | ||
25 | * | 26 | * |
26 | * Returns GPIO number to use with Linux generic GPIO API, or one of the errno | 27 | * Returns GPIO number to use with Linux generic GPIO API, or one of the errno |
27 | * value on the error condition. | 28 | * value on the error condition. If @flags is not NULL the function also fills |
29 | * in flags for the GPIO. | ||
28 | */ | 30 | */ |
29 | int of_get_gpio(struct device_node *np, int index) | 31 | int of_get_gpio_flags(struct device_node *np, int index, |
32 | enum of_gpio_flags *flags) | ||
30 | { | 33 | { |
31 | int ret; | 34 | int ret; |
32 | struct device_node *gc; | 35 | struct device_node *gc; |
@@ -59,7 +62,11 @@ int of_get_gpio(struct device_node *np, int index) | |||
59 | goto err1; | 62 | goto err1; |
60 | } | 63 | } |
61 | 64 | ||
62 | ret = of_gc->xlate(of_gc, np, gpio_spec); | 65 | /* .xlate might decide to not fill in the flags, so clear it. */ |
66 | if (flags) | ||
67 | *flags = 0; | ||
68 | |||
69 | ret = of_gc->xlate(of_gc, np, gpio_spec, flags); | ||
63 | if (ret < 0) | 70 | if (ret < 0) |
64 | goto err1; | 71 | goto err1; |
65 | 72 | ||
@@ -70,26 +77,75 @@ err0: | |||
70 | pr_debug("%s exited with status %d\n", __func__, ret); | 77 | pr_debug("%s exited with status %d\n", __func__, ret); |
71 | return ret; | 78 | return ret; |
72 | } | 79 | } |
73 | EXPORT_SYMBOL(of_get_gpio); | 80 | EXPORT_SYMBOL(of_get_gpio_flags); |
74 | 81 | ||
75 | /** | 82 | /** |
76 | * of_gpio_simple_xlate - translate gpio_spec to the GPIO number | 83 | * of_gpio_count - Count GPIOs for a device |
84 | * @np: device node to count GPIOs for | ||
85 | * | ||
86 | * The function returns the count of GPIOs specified for a node. | ||
87 | * | ||
88 | * Note that the empty GPIO specifiers counts too. For example, | ||
89 | * | ||
90 | * gpios = <0 | ||
91 | * &pio1 1 2 | ||
92 | * 0 | ||
93 | * &pio2 3 4>; | ||
94 | * | ||
95 | * defines four GPIOs (so this function will return 4), two of which | ||
96 | * are not specified. | ||
97 | */ | ||
98 | unsigned int of_gpio_count(struct device_node *np) | ||
99 | { | ||
100 | unsigned int cnt = 0; | ||
101 | |||
102 | do { | ||
103 | int ret; | ||
104 | |||
105 | ret = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", | ||
106 | cnt, NULL, NULL); | ||
107 | /* A hole in the gpios = <> counts anyway. */ | ||
108 | if (ret < 0 && ret != -EEXIST) | ||
109 | break; | ||
110 | } while (++cnt); | ||
111 | |||
112 | return cnt; | ||
113 | } | ||
114 | EXPORT_SYMBOL(of_gpio_count); | ||
115 | |||
116 | /** | ||
117 | * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags | ||
77 | * @of_gc: pointer to the of_gpio_chip structure | 118 | * @of_gc: pointer to the of_gpio_chip structure |
78 | * @np: device node of the GPIO chip | 119 | * @np: device node of the GPIO chip |
79 | * @gpio_spec: gpio specifier as found in the device tree | 120 | * @gpio_spec: gpio specifier as found in the device tree |
121 | * @flags: a flags pointer to fill in | ||
80 | * | 122 | * |
81 | * This is simple translation function, suitable for the most 1:1 mapped | 123 | * This is simple translation function, suitable for the most 1:1 mapped |
82 | * gpio chips. This function performs only one sanity check: whether gpio | 124 | * gpio chips. This function performs only one sanity check: whether gpio |
83 | * is less than ngpios (that is specified in the gpio_chip). | 125 | * is less than ngpios (that is specified in the gpio_chip). |
84 | */ | 126 | */ |
85 | int of_gpio_simple_xlate(struct of_gpio_chip *of_gc, struct device_node *np, | 127 | int of_gpio_simple_xlate(struct of_gpio_chip *of_gc, struct device_node *np, |
86 | const void *gpio_spec) | 128 | const void *gpio_spec, enum of_gpio_flags *flags) |
87 | { | 129 | { |
88 | const u32 *gpio = gpio_spec; | 130 | const u32 *gpio = gpio_spec; |
89 | 131 | ||
132 | /* | ||
133 | * We're discouraging gpio_cells < 2, since that way you'll have to | ||
134 | * write your own xlate function (that will have to retrive the GPIO | ||
135 | * number and the flags from a single gpio cell -- this is possible, | ||
136 | * but not recommended). | ||
137 | */ | ||
138 | if (of_gc->gpio_cells < 2) { | ||
139 | WARN_ON(1); | ||
140 | return -EINVAL; | ||
141 | } | ||
142 | |||
90 | if (*gpio > of_gc->gc.ngpio) | 143 | if (*gpio > of_gc->gc.ngpio) |
91 | return -EINVAL; | 144 | return -EINVAL; |
92 | 145 | ||
146 | if (flags) | ||
147 | *flags = gpio[1]; | ||
148 | |||
93 | return *gpio; | 149 | return *gpio; |
94 | } | 150 | } |
95 | EXPORT_SYMBOL(of_gpio_simple_xlate); | 151 | EXPORT_SYMBOL(of_gpio_simple_xlate); |
diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c index 24bbef777c19..e1b0ad6e918f 100644 --- a/drivers/of/of_i2c.c +++ b/drivers/of/of_i2c.c | |||
@@ -24,6 +24,7 @@ void of_register_i2c_devices(struct i2c_adapter *adap, | |||
24 | 24 | ||
25 | for_each_child_of_node(adap_node, node) { | 25 | for_each_child_of_node(adap_node, node) { |
26 | struct i2c_board_info info = {}; | 26 | struct i2c_board_info info = {}; |
27 | struct dev_archdata dev_ad = {}; | ||
27 | const u32 *addr; | 28 | const u32 *addr; |
28 | int len; | 29 | int len; |
29 | 30 | ||
@@ -41,6 +42,9 @@ void of_register_i2c_devices(struct i2c_adapter *adap, | |||
41 | 42 | ||
42 | info.addr = *addr; | 43 | info.addr = *addr; |
43 | 44 | ||
45 | dev_archdata_set_node(&dev_ad, node); | ||
46 | info.archdata = &dev_ad; | ||
47 | |||
44 | request_module("%s", info.type); | 48 | request_module("%s", info.type); |
45 | 49 | ||
46 | result = i2c_new_device(adap, &info); | 50 | result = i2c_new_device(adap, &info); |
@@ -51,6 +55,13 @@ void of_register_i2c_devices(struct i2c_adapter *adap, | |||
51 | irq_dispose_mapping(info.irq); | 55 | irq_dispose_mapping(info.irq); |
52 | continue; | 56 | continue; |
53 | } | 57 | } |
58 | |||
59 | /* | ||
60 | * Get the node to not lose the dev_archdata->of_node. | ||
61 | * Currently there is no way to put it back, as well as no | ||
62 | * of_unregister_i2c_devices() call. | ||
63 | */ | ||
64 | of_node_get(node); | ||
54 | } | 65 | } |
55 | } | 66 | } |
56 | EXPORT_SYMBOL(of_register_i2c_devices); | 67 | EXPORT_SYMBOL(of_register_i2c_devices); |
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 9c2a22fed18b..4e3e0382c16e 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c | |||
@@ -14,6 +14,9 @@ | |||
14 | * as published by the Free Software Foundation; either version | 14 | * as published by the Free Software Foundation; either version |
15 | * 2 of the License, or (at your option) any later version. | 15 | * 2 of the License, or (at your option) any later version. |
16 | */ | 16 | */ |
17 | |||
18 | #undef DEBUG | ||
19 | |||
17 | #include <linux/init.h> | 20 | #include <linux/init.h> |
18 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
19 | #include <linux/string.h> | 22 | #include <linux/string.h> |
@@ -151,20 +154,20 @@ static void dlpar_pci_add_bus(struct device_node *dn) | |||
151 | return; | 154 | return; |
152 | } | 155 | } |
153 | 156 | ||
157 | /* Scan below the new bridge */ | ||
154 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || | 158 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || |
155 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) | 159 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) |
156 | of_scan_pci_bridge(dn, dev); | 160 | of_scan_pci_bridge(dn, dev); |
157 | 161 | ||
158 | pcibios_fixup_new_pci_devices(dev->subordinate); | ||
159 | |||
160 | /* Claim new bus resources */ | ||
161 | pcibios_claim_one_bus(dev->bus); | ||
162 | |||
163 | /* Map IO space for child bus, which may or may not succeed */ | 162 | /* Map IO space for child bus, which may or may not succeed */ |
164 | pcibios_map_io_space(dev->subordinate); | 163 | pcibios_map_io_space(dev->subordinate); |
165 | 164 | ||
166 | /* Add new devices to global lists. Register in proc, sysfs. */ | 165 | /* Finish adding it : resource allocation, adding devices, etc... |
167 | pci_bus_add_devices(phb->bus); | 166 | * Note that we need to perform the finish pass on the -parent- |
167 | * bus of the EADS bridge so the bridge device itself gets | ||
168 | * properly added | ||
169 | */ | ||
170 | pcibios_finish_adding_to_bus(phb->bus); | ||
168 | } | 171 | } |
169 | 172 | ||
170 | static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) | 173 | static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) |
@@ -203,27 +206,6 @@ static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) | |||
203 | return 0; | 206 | return 0; |
204 | } | 207 | } |
205 | 208 | ||
206 | static int dlpar_remove_root_bus(struct pci_controller *phb) | ||
207 | { | ||
208 | struct pci_bus *phb_bus; | ||
209 | int rc; | ||
210 | |||
211 | phb_bus = phb->bus; | ||
212 | if (!(list_empty(&phb_bus->children) && | ||
213 | list_empty(&phb_bus->devices))) { | ||
214 | return -EBUSY; | ||
215 | } | ||
216 | |||
217 | rc = pcibios_remove_root_bus(phb); | ||
218 | if (rc) | ||
219 | return -EIO; | ||
220 | |||
221 | device_unregister(phb_bus->bridge); | ||
222 | pci_remove_bus(phb_bus); | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int dlpar_remove_phb(char *drc_name, struct device_node *dn) | 209 | static int dlpar_remove_phb(char *drc_name, struct device_node *dn) |
228 | { | 210 | { |
229 | struct slot *slot; | 211 | struct slot *slot; |
@@ -235,18 +217,15 @@ static int dlpar_remove_phb(char *drc_name, struct device_node *dn) | |||
235 | 217 | ||
236 | /* If pci slot is hotplugable, use hotplug to remove it */ | 218 | /* If pci slot is hotplugable, use hotplug to remove it */ |
237 | slot = find_php_slot(dn); | 219 | slot = find_php_slot(dn); |
238 | if (slot) { | 220 | if (slot && rpaphp_deregister_slot(slot)) { |
239 | if (rpaphp_deregister_slot(slot)) { | 221 | printk(KERN_ERR "%s: unable to remove hotplug slot %s\n", |
240 | printk(KERN_ERR | 222 | __func__, drc_name); |
241 | "%s: unable to remove hotplug slot %s\n", | 223 | return -EIO; |
242 | __func__, drc_name); | ||
243 | return -EIO; | ||
244 | } | ||
245 | } | 224 | } |
246 | 225 | ||
247 | pdn = dn->data; | 226 | pdn = dn->data; |
248 | BUG_ON(!pdn || !pdn->phb); | 227 | BUG_ON(!pdn || !pdn->phb); |
249 | rc = dlpar_remove_root_bus(pdn->phb); | 228 | rc = remove_phb_dynamic(pdn->phb); |
250 | if (rc < 0) | 229 | if (rc < 0) |
251 | return rc; | 230 | return rc; |
252 | 231 | ||
@@ -378,26 +357,38 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) | |||
378 | if (!bus) | 357 | if (!bus) |
379 | return -EINVAL; | 358 | return -EINVAL; |
380 | 359 | ||
381 | /* If pci slot is hotplugable, use hotplug to remove it */ | 360 | pr_debug("PCI: Removing PCI slot below EADS bridge %s\n", |
361 | bus->self ? pci_name(bus->self) : "<!PHB!>"); | ||
362 | |||
382 | slot = find_php_slot(dn); | 363 | slot = find_php_slot(dn); |
383 | if (slot) { | 364 | if (slot) { |
365 | pr_debug("PCI: Removing hotplug slot for %04x:%02x...\n", | ||
366 | pci_domain_nr(bus), bus->number); | ||
367 | |||
384 | if (rpaphp_deregister_slot(slot)) { | 368 | if (rpaphp_deregister_slot(slot)) { |
385 | printk(KERN_ERR | 369 | printk(KERN_ERR |
386 | "%s: unable to remove hotplug slot %s\n", | 370 | "%s: unable to remove hotplug slot %s\n", |
387 | __func__, drc_name); | 371 | __func__, drc_name); |
388 | return -EIO; | 372 | return -EIO; |
389 | } | 373 | } |
390 | } else | 374 | } |
391 | pcibios_remove_pci_devices(bus); | 375 | |
376 | /* Remove all devices below slot */ | ||
377 | pcibios_remove_pci_devices(bus); | ||
392 | 378 | ||
379 | /* Unmap PCI IO space */ | ||
393 | if (pcibios_unmap_io_space(bus)) { | 380 | if (pcibios_unmap_io_space(bus)) { |
394 | printk(KERN_ERR "%s: failed to unmap bus range\n", | 381 | printk(KERN_ERR "%s: failed to unmap bus range\n", |
395 | __func__); | 382 | __func__); |
396 | return -ERANGE; | 383 | return -ERANGE; |
397 | } | 384 | } |
398 | 385 | ||
386 | /* Remove the EADS bridge device itself */ | ||
399 | BUG_ON(!bus->self); | 387 | BUG_ON(!bus->self); |
388 | pr_debug("PCI: Now removing bridge device %s\n", pci_name(bus->self)); | ||
389 | eeh_remove_bus_device(bus->self); | ||
400 | pci_remove_bus_device(bus->self); | 390 | pci_remove_bus_device(bus->self); |
391 | |||
401 | return 0; | 392 | return 0; |
402 | } | 393 | } |
403 | 394 | ||
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c index 06848b254d57..5324978b73fb 100644 --- a/drivers/ps3/ps3av.c +++ b/drivers/ps3/ps3av.c | |||
@@ -59,8 +59,6 @@ static struct ps3av { | |||
59 | struct ps3av_reply_hdr reply_hdr; | 59 | struct ps3av_reply_hdr reply_hdr; |
60 | u8 raw[PS3AV_BUF_SIZE]; | 60 | u8 raw[PS3AV_BUF_SIZE]; |
61 | } recv_buf; | 61 | } recv_buf; |
62 | void (*flip_ctl)(int on, void *data); | ||
63 | void *flip_data; | ||
64 | } *ps3av; | 62 | } *ps3av; |
65 | 63 | ||
66 | /* color space */ | 64 | /* color space */ |
@@ -939,24 +937,6 @@ int ps3av_audio_mute(int mute) | |||
939 | 937 | ||
940 | EXPORT_SYMBOL_GPL(ps3av_audio_mute); | 938 | EXPORT_SYMBOL_GPL(ps3av_audio_mute); |
941 | 939 | ||
942 | void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data), | ||
943 | void *flip_data) | ||
944 | { | ||
945 | mutex_lock(&ps3av->mutex); | ||
946 | ps3av->flip_ctl = flip_ctl; | ||
947 | ps3av->flip_data = flip_data; | ||
948 | mutex_unlock(&ps3av->mutex); | ||
949 | } | ||
950 | EXPORT_SYMBOL_GPL(ps3av_register_flip_ctl); | ||
951 | |||
952 | void ps3av_flip_ctl(int on) | ||
953 | { | ||
954 | mutex_lock(&ps3av->mutex); | ||
955 | if (ps3av->flip_ctl) | ||
956 | ps3av->flip_ctl(on, ps3av->flip_data); | ||
957 | mutex_unlock(&ps3av->mutex); | ||
958 | } | ||
959 | |||
960 | static int ps3av_probe(struct ps3_system_bus_device *dev) | 940 | static int ps3av_probe(struct ps3_system_bus_device *dev) |
961 | { | 941 | { |
962 | int res; | 942 | int res; |
diff --git a/drivers/ps3/ps3av_cmd.c b/drivers/ps3/ps3av_cmd.c index 11eb50318fec..716596e8e5b0 100644 --- a/drivers/ps3/ps3av_cmd.c +++ b/drivers/ps3/ps3av_cmd.c | |||
@@ -864,7 +864,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len) | |||
864 | { | 864 | { |
865 | int res; | 865 | int res; |
866 | 866 | ||
867 | ps3av_flip_ctl(0); /* flip off */ | 867 | mutex_lock(&ps3_gpu_mutex); |
868 | 868 | ||
869 | /* avb packet */ | 869 | /* avb packet */ |
870 | res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb), | 870 | res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb), |
@@ -878,7 +878,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len) | |||
878 | res); | 878 | res); |
879 | 879 | ||
880 | out: | 880 | out: |
881 | ps3av_flip_ctl(1); /* flip on */ | 881 | mutex_unlock(&ps3_gpu_mutex); |
882 | return res; | 882 | return res; |
883 | } | 883 | } |
884 | 884 | ||
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 643a6b98462b..5c13f61bfb1b 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c | |||
@@ -365,15 +365,15 @@ static struct rio_dev *rio_setup_device(struct rio_net *net, | |||
365 | rdid++) | 365 | rdid++) |
366 | rswitch->route_table[rdid] = RIO_INVALID_ROUTE; | 366 | rswitch->route_table[rdid] = RIO_INVALID_ROUTE; |
367 | rdev->rswitch = rswitch; | 367 | rdev->rswitch = rswitch; |
368 | sprintf(rio_name(rdev), "%02x:s:%04x", rdev->net->id, | 368 | dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, |
369 | rdev->rswitch->switchid); | 369 | rdev->rswitch->switchid); |
370 | rio_route_set_ops(rdev); | 370 | rio_route_set_ops(rdev); |
371 | 371 | ||
372 | list_add_tail(&rswitch->node, &rio_switches); | 372 | list_add_tail(&rswitch->node, &rio_switches); |
373 | 373 | ||
374 | } else | 374 | } else |
375 | sprintf(rio_name(rdev), "%02x:e:%04x", rdev->net->id, | 375 | dev_set_name(&rdev->dev, "%02x:e:%04x", rdev->net->id, |
376 | rdev->destid); | 376 | rdev->destid); |
377 | 377 | ||
378 | rdev->dev.bus = &rio_bus_type; | 378 | rdev->dev.bus = &rio_bus_type; |
379 | 379 | ||
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 28c00c3d58f5..0c3a2ab1612c 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
@@ -429,14 +429,24 @@ mpc52xx_uart_tx_empty(struct uart_port *port) | |||
429 | static void | 429 | static void |
430 | mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) | 430 | mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) |
431 | { | 431 | { |
432 | /* Not implemented */ | 432 | if (mctrl & TIOCM_RTS) |
433 | out_8(&PSC(port)->op1, MPC52xx_PSC_OP_RTS); | ||
434 | else | ||
435 | out_8(&PSC(port)->op0, MPC52xx_PSC_OP_RTS); | ||
433 | } | 436 | } |
434 | 437 | ||
435 | static unsigned int | 438 | static unsigned int |
436 | mpc52xx_uart_get_mctrl(struct uart_port *port) | 439 | mpc52xx_uart_get_mctrl(struct uart_port *port) |
437 | { | 440 | { |
438 | /* Not implemented */ | 441 | unsigned int ret = TIOCM_DSR; |
439 | return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; | 442 | u8 status = in_8(&PSC(port)->mpc52xx_psc_ipcr); |
443 | |||
444 | if (!(status & MPC52xx_PSC_CTS)) | ||
445 | ret |= TIOCM_CTS; | ||
446 | if (!(status & MPC52xx_PSC_DCD)) | ||
447 | ret |= TIOCM_CAR; | ||
448 | |||
449 | return ret; | ||
440 | } | 450 | } |
441 | 451 | ||
442 | static void | 452 | static void |
@@ -479,7 +489,15 @@ mpc52xx_uart_stop_rx(struct uart_port *port) | |||
479 | static void | 489 | static void |
480 | mpc52xx_uart_enable_ms(struct uart_port *port) | 490 | mpc52xx_uart_enable_ms(struct uart_port *port) |
481 | { | 491 | { |
482 | /* Not implemented */ | 492 | struct mpc52xx_psc __iomem *psc = PSC(port); |
493 | |||
494 | /* clear D_*-bits by reading them */ | ||
495 | in_8(&psc->mpc52xx_psc_ipcr); | ||
496 | /* enable CTS and DCD as IPC interrupts */ | ||
497 | out_8(&psc->mpc52xx_psc_acr, MPC52xx_PSC_IEC_CTS | MPC52xx_PSC_IEC_DCD); | ||
498 | |||
499 | port->read_status_mask |= MPC52xx_PSC_IMR_IPC; | ||
500 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | ||
483 | } | 501 | } |
484 | 502 | ||
485 | static void | 503 | static void |
@@ -580,6 +598,10 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, | |||
580 | MPC52xx_PSC_MODE_ONE_STOP_5_BITS : | 598 | MPC52xx_PSC_MODE_ONE_STOP_5_BITS : |
581 | MPC52xx_PSC_MODE_ONE_STOP; | 599 | MPC52xx_PSC_MODE_ONE_STOP; |
582 | 600 | ||
601 | if (new->c_cflag & CRTSCTS) { | ||
602 | mr1 |= MPC52xx_PSC_MODE_RXRTS; | ||
603 | mr2 |= MPC52xx_PSC_MODE_TXCTS; | ||
604 | } | ||
583 | 605 | ||
584 | baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16); | 606 | baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16); |
585 | quot = uart_get_divisor(port, baud); | 607 | quot = uart_get_divisor(port, baud); |
@@ -617,6 +639,9 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, | |||
617 | out_8(&psc->ctur, ctr >> 8); | 639 | out_8(&psc->ctur, ctr >> 8); |
618 | out_8(&psc->ctlr, ctr & 0xff); | 640 | out_8(&psc->ctlr, ctr & 0xff); |
619 | 641 | ||
642 | if (UART_ENABLE_MS(port, new->c_cflag)) | ||
643 | mpc52xx_uart_enable_ms(port); | ||
644 | |||
620 | /* Reenable TX & RX */ | 645 | /* Reenable TX & RX */ |
621 | out_8(&psc->command, MPC52xx_PSC_TX_ENABLE); | 646 | out_8(&psc->command, MPC52xx_PSC_TX_ENABLE); |
622 | out_8(&psc->command, MPC52xx_PSC_RX_ENABLE); | 647 | out_8(&psc->command, MPC52xx_PSC_RX_ENABLE); |
@@ -752,10 +777,15 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
752 | if (status & MPC52xx_PSC_SR_RB) { | 777 | if (status & MPC52xx_PSC_SR_RB) { |
753 | flag = TTY_BREAK; | 778 | flag = TTY_BREAK; |
754 | uart_handle_break(port); | 779 | uart_handle_break(port); |
755 | } else if (status & MPC52xx_PSC_SR_PE) | 780 | port->icount.brk++; |
781 | } else if (status & MPC52xx_PSC_SR_PE) { | ||
756 | flag = TTY_PARITY; | 782 | flag = TTY_PARITY; |
757 | else if (status & MPC52xx_PSC_SR_FE) | 783 | port->icount.parity++; |
784 | } | ||
785 | else if (status & MPC52xx_PSC_SR_FE) { | ||
758 | flag = TTY_FRAME; | 786 | flag = TTY_FRAME; |
787 | port->icount.frame++; | ||
788 | } | ||
759 | 789 | ||
760 | /* Clear error condition */ | 790 | /* Clear error condition */ |
761 | out_8(&PSC(port)->command, MPC52xx_PSC_RST_ERR_STAT); | 791 | out_8(&PSC(port)->command, MPC52xx_PSC_RST_ERR_STAT); |
@@ -769,6 +799,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
769 | * affect the current character | 799 | * affect the current character |
770 | */ | 800 | */ |
771 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | 801 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); |
802 | port->icount.overrun++; | ||
772 | } | 803 | } |
773 | } | 804 | } |
774 | 805 | ||
@@ -826,6 +857,7 @@ mpc52xx_uart_int(int irq, void *dev_id) | |||
826 | struct uart_port *port = dev_id; | 857 | struct uart_port *port = dev_id; |
827 | unsigned long pass = ISR_PASS_LIMIT; | 858 | unsigned long pass = ISR_PASS_LIMIT; |
828 | unsigned int keepgoing; | 859 | unsigned int keepgoing; |
860 | u8 status; | ||
829 | 861 | ||
830 | spin_lock(&port->lock); | 862 | spin_lock(&port->lock); |
831 | 863 | ||
@@ -842,6 +874,13 @@ mpc52xx_uart_int(int irq, void *dev_id) | |||
842 | if (psc_ops->tx_rdy(port)) | 874 | if (psc_ops->tx_rdy(port)) |
843 | keepgoing |= mpc52xx_uart_int_tx_chars(port); | 875 | keepgoing |= mpc52xx_uart_int_tx_chars(port); |
844 | 876 | ||
877 | status = in_8(&PSC(port)->mpc52xx_psc_ipcr); | ||
878 | if (status & MPC52xx_PSC_D_DCD) | ||
879 | uart_handle_dcd_change(port, !(status & MPC52xx_PSC_DCD)); | ||
880 | |||
881 | if (status & MPC52xx_PSC_D_CTS) | ||
882 | uart_handle_cts_change(port, !(status & MPC52xx_PSC_CTS)); | ||
883 | |||
845 | /* Limit number of iteration */ | 884 | /* Limit number of iteration */ |
846 | if (!(--pass)) | 885 | if (!(--pass)) |
847 | keepgoing = 0; | 886 | keepgoing = 0; |
@@ -1109,22 +1148,29 @@ mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) | |||
1109 | return ret; | 1148 | return ret; |
1110 | 1149 | ||
1111 | port->mapbase = res.start; | 1150 | port->mapbase = res.start; |
1151 | if (!port->mapbase) { | ||
1152 | dev_dbg(&op->dev, "Could not allocate resources for PSC\n"); | ||
1153 | return -EINVAL; | ||
1154 | } | ||
1155 | |||
1112 | port->irq = irq_of_parse_and_map(op->node, 0); | 1156 | port->irq = irq_of_parse_and_map(op->node, 0); |
1157 | if (port->irq == NO_IRQ) { | ||
1158 | dev_dbg(&op->dev, "Could not get irq\n"); | ||
1159 | return -EINVAL; | ||
1160 | } | ||
1113 | 1161 | ||
1114 | dev_dbg(&op->dev, "mpc52xx-psc uart at %p, irq=%x, freq=%i\n", | 1162 | dev_dbg(&op->dev, "mpc52xx-psc uart at %p, irq=%x, freq=%i\n", |
1115 | (void *)port->mapbase, port->irq, port->uartclk); | 1163 | (void *)port->mapbase, port->irq, port->uartclk); |
1116 | 1164 | ||
1117 | if ((port->irq == NO_IRQ) || !port->mapbase) { | ||
1118 | printk(KERN_ERR "Could not allocate resources for PSC\n"); | ||
1119 | return -EINVAL; | ||
1120 | } | ||
1121 | |||
1122 | /* Add the port to the uart sub-system */ | 1165 | /* Add the port to the uart sub-system */ |
1123 | ret = uart_add_one_port(&mpc52xx_uart_driver, port); | 1166 | ret = uart_add_one_port(&mpc52xx_uart_driver, port); |
1124 | if (!ret) | 1167 | if (ret) { |
1125 | dev_set_drvdata(&op->dev, (void *)port); | 1168 | irq_dispose_mapping(port->irq); |
1169 | return ret; | ||
1170 | } | ||
1126 | 1171 | ||
1127 | return ret; | 1172 | dev_set_drvdata(&op->dev, (void *)port); |
1173 | return 0; | ||
1128 | } | 1174 | } |
1129 | 1175 | ||
1130 | static int | 1176 | static int |
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 317b061f7641..ad3488504010 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c | |||
@@ -1383,6 +1383,29 @@ static int pmz_verify_port(struct uart_port *port, struct serial_struct *ser) | |||
1383 | return -EINVAL; | 1383 | return -EINVAL; |
1384 | } | 1384 | } |
1385 | 1385 | ||
1386 | #ifdef CONFIG_CONSOLE_POLL | ||
1387 | |||
1388 | static int pmz_poll_get_char(struct uart_port *port) | ||
1389 | { | ||
1390 | struct uart_pmac_port *uap = (struct uart_pmac_port *)port; | ||
1391 | |||
1392 | while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) | ||
1393 | udelay(5); | ||
1394 | return read_zsdata(uap); | ||
1395 | } | ||
1396 | |||
1397 | static void pmz_poll_put_char(struct uart_port *port, unsigned char c) | ||
1398 | { | ||
1399 | struct uart_pmac_port *uap = (struct uart_pmac_port *)port; | ||
1400 | |||
1401 | /* Wait for the transmit buffer to empty. */ | ||
1402 | while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0) | ||
1403 | udelay(5); | ||
1404 | write_zsdata(uap, c); | ||
1405 | } | ||
1406 | |||
1407 | #endif | ||
1408 | |||
1386 | static struct uart_ops pmz_pops = { | 1409 | static struct uart_ops pmz_pops = { |
1387 | .tx_empty = pmz_tx_empty, | 1410 | .tx_empty = pmz_tx_empty, |
1388 | .set_mctrl = pmz_set_mctrl, | 1411 | .set_mctrl = pmz_set_mctrl, |
@@ -1400,6 +1423,10 @@ static struct uart_ops pmz_pops = { | |||
1400 | .request_port = pmz_request_port, | 1423 | .request_port = pmz_request_port, |
1401 | .config_port = pmz_config_port, | 1424 | .config_port = pmz_config_port, |
1402 | .verify_port = pmz_verify_port, | 1425 | .verify_port = pmz_verify_port, |
1426 | #ifdef CONFIG_CONSOLE_POLL | ||
1427 | .poll_get_char = pmz_poll_get_char, | ||
1428 | .poll_put_char = pmz_poll_put_char, | ||
1429 | #endif | ||
1403 | }; | 1430 | }; |
1404 | 1431 | ||
1405 | /* | 1432 | /* |
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index b0be7eac32d8..49fcbe8f18ac 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c | |||
@@ -298,10 +298,10 @@ static int controlfb_mmap(struct fb_info *info, | |||
298 | return -EINVAL; | 298 | return -EINVAL; |
299 | start = info->fix.mmio_start; | 299 | start = info->fix.mmio_start; |
300 | len = PAGE_ALIGN((start & ~PAGE_MASK)+info->fix.mmio_len); | 300 | len = PAGE_ALIGN((start & ~PAGE_MASK)+info->fix.mmio_len); |
301 | pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED; | 301 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
302 | } else { | 302 | } else { |
303 | /* framebuffer */ | 303 | /* framebuffer */ |
304 | pgprot_val(vma->vm_page_prot) |= _PAGE_WRITETHRU; | 304 | vma->vm_page_prot = pgprot_cached_wthru(vma->vm_page_prot); |
305 | } | 305 | } |
306 | start &= PAGE_MASK; | 306 | start &= PAGE_MASK; |
307 | if ((vma->vm_end - vma->vm_start + off) > len) | 307 | if ((vma->vm_end - vma->vm_start + off) > len) |
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index 4b5d80771904..38ac805db97d 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c | |||
@@ -460,12 +460,16 @@ static void ps3fb_sync_image(struct device *dev, u64 frame_offset, | |||
460 | line_length |= (u64)src_line_length << 32; | 460 | line_length |= (u64)src_line_length << 32; |
461 | 461 | ||
462 | src_offset += GPU_FB_START; | 462 | src_offset += GPU_FB_START; |
463 | |||
464 | mutex_lock(&ps3_gpu_mutex); | ||
463 | status = lv1_gpu_context_attribute(ps3fb.context_handle, | 465 | status = lv1_gpu_context_attribute(ps3fb.context_handle, |
464 | L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, | 466 | L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, |
465 | dst_offset, GPU_IOIF + src_offset, | 467 | dst_offset, GPU_IOIF + src_offset, |
466 | L1GPU_FB_BLIT_WAIT_FOR_COMPLETION | | 468 | L1GPU_FB_BLIT_WAIT_FOR_COMPLETION | |
467 | (width << 16) | height, | 469 | (width << 16) | height, |
468 | line_length); | 470 | line_length); |
471 | mutex_unlock(&ps3_gpu_mutex); | ||
472 | |||
469 | if (status) | 473 | if (status) |
470 | dev_err(dev, | 474 | dev_err(dev, |
471 | "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n", | 475 | "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n", |
@@ -784,15 +788,6 @@ static int ps3fb_wait_for_vsync(u32 crtc) | |||
784 | return 0; | 788 | return 0; |
785 | } | 789 | } |
786 | 790 | ||
787 | static void ps3fb_flip_ctl(int on, void *data) | ||
788 | { | ||
789 | struct ps3fb_priv *priv = data; | ||
790 | if (on) | ||
791 | atomic_dec_if_positive(&priv->ext_flip); | ||
792 | else | ||
793 | atomic_inc(&priv->ext_flip); | ||
794 | } | ||
795 | |||
796 | 791 | ||
797 | /* | 792 | /* |
798 | * ioctl | 793 | * ioctl |
@@ -1228,7 +1223,6 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1228 | } | 1223 | } |
1229 | 1224 | ||
1230 | ps3fb.task = task; | 1225 | ps3fb.task = task; |
1231 | ps3av_register_flip_ctl(ps3fb_flip_ctl, &ps3fb); | ||
1232 | 1226 | ||
1233 | return 0; | 1227 | return 0; |
1234 | 1228 | ||
@@ -1258,10 +1252,9 @@ static int ps3fb_shutdown(struct ps3_system_bus_device *dev) | |||
1258 | 1252 | ||
1259 | dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); | 1253 | dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); |
1260 | 1254 | ||
1261 | ps3fb_flip_ctl(0, &ps3fb); /* flip off */ | 1255 | atomic_inc(&ps3fb.ext_flip); /* flip off */ |
1262 | ps3fb.dinfo->irq.mask = 0; | 1256 | ps3fb.dinfo->irq.mask = 0; |
1263 | 1257 | ||
1264 | ps3av_register_flip_ctl(NULL, NULL); | ||
1265 | if (ps3fb.task) { | 1258 | if (ps3fb.task) { |
1266 | struct task_struct *task = ps3fb.task; | 1259 | struct task_struct *task = ps3fb.task; |
1267 | ps3fb.task = NULL; | 1260 | ps3fb.task = NULL; |
@@ -1296,8 +1289,8 @@ static int ps3fb_shutdown(struct ps3_system_bus_device *dev) | |||
1296 | } | 1289 | } |
1297 | 1290 | ||
1298 | static struct ps3_system_bus_driver ps3fb_driver = { | 1291 | static struct ps3_system_bus_driver ps3fb_driver = { |
1299 | .match_id = PS3_MATCH_ID_GRAPHICS, | 1292 | .match_id = PS3_MATCH_ID_GPU, |
1300 | .match_sub_id = PS3_MATCH_SUB_ID_FB, | 1293 | .match_sub_id = PS3_MATCH_SUB_ID_GPU_FB, |
1301 | .core.name = DEVICE_NAME, | 1294 | .core.name = DEVICE_NAME, |
1302 | .core.owner = THIS_MODULE, | 1295 | .core.owner = THIS_MODULE, |
1303 | .probe = ps3fb_probe, | 1296 | .probe = ps3fb_probe, |
@@ -1355,4 +1348,4 @@ module_exit(ps3fb_exit); | |||
1355 | MODULE_LICENSE("GPL"); | 1348 | MODULE_LICENSE("GPL"); |
1356 | MODULE_DESCRIPTION("PS3 GPU Frame Buffer Driver"); | 1349 | MODULE_DESCRIPTION("PS3 GPU Frame Buffer Driver"); |
1357 | MODULE_AUTHOR("Sony Computer Entertainment Inc."); | 1350 | MODULE_AUTHOR("Sony Computer Entertainment Inc."); |
1358 | MODULE_ALIAS(PS3_MODULE_ALIAS_GRAPHICS); | 1351 | MODULE_ALIAS(PS3_MODULE_ALIAS_GPU_FB); |