diff options
61 files changed, 1676 insertions, 671 deletions
diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl index d260d92089ad..5bcbb6ee3bc0 100644 --- a/Documentation/DocBook/libata.tmpl +++ b/Documentation/DocBook/libata.tmpl | |||
@@ -120,14 +120,27 @@ void (*dev_config) (struct ata_port *, struct ata_device *); | |||
120 | <programlisting> | 120 | <programlisting> |
121 | void (*set_piomode) (struct ata_port *, struct ata_device *); | 121 | void (*set_piomode) (struct ata_port *, struct ata_device *); |
122 | void (*set_dmamode) (struct ata_port *, struct ata_device *); | 122 | void (*set_dmamode) (struct ata_port *, struct ata_device *); |
123 | void (*post_set_mode) (struct ata_port *ap); | 123 | void (*post_set_mode) (struct ata_port *); |
124 | unsigned int (*mode_filter) (struct ata_port *, struct ata_device *, unsigned int); | ||
124 | </programlisting> | 125 | </programlisting> |
125 | 126 | ||
126 | <para> | 127 | <para> |
127 | Hooks called prior to the issue of SET FEATURES - XFER MODE | 128 | Hooks called prior to the issue of SET FEATURES - XFER MODE |
128 | command. dev->pio_mode is guaranteed to be valid when | 129 | command. The optional ->mode_filter() hook is called when libata |
129 | ->set_piomode() is called, and dev->dma_mode is guaranteed to be | 130 | has built a mask of the possible modes. This is passed to the |
130 | valid when ->set_dmamode() is called. ->post_set_mode() is | 131 | ->mode_filter() function which should return a mask of valid modes |
132 | after filtering those unsuitable due to hardware limits. It is not | ||
133 | valid to use this interface to add modes. | ||
134 | </para> | ||
135 | <para> | ||
136 | dev->pio_mode and dev->dma_mode are guaranteed to be valid when | ||
137 | ->set_piomode() and when ->set_dmamode() is called. The timings for | ||
138 | any other drive sharing the cable will also be valid at this point. | ||
139 | That is the library records the decisions for the modes of each | ||
140 | drive on a channel before it attempts to set any of them. | ||
141 | </para> | ||
142 | <para> | ||
143 | ->post_set_mode() is | ||
131 | called unconditionally, after the SET FEATURES - XFER MODE | 144 | called unconditionally, after the SET FEATURES - XFER MODE |
132 | command completes successfully. | 145 | command completes successfully. |
133 | </para> | 146 | </para> |
@@ -230,6 +243,32 @@ void (*dev_select)(struct ata_port *ap, unsigned int device); | |||
230 | 243 | ||
231 | </sect2> | 244 | </sect2> |
232 | 245 | ||
246 | <sect2><title>Private tuning method</title> | ||
247 | <programlisting> | ||
248 | void (*set_mode) (struct ata_port *ap); | ||
249 | </programlisting> | ||
250 | |||
251 | <para> | ||
252 | By default libata performs drive and controller tuning in | ||
253 | accordance with the ATA timing rules and also applies blacklists | ||
254 | and cable limits. Some controllers need special handling and have | ||
255 | custom tuning rules, typically raid controllers that use ATA | ||
256 | commands but do not actually do drive timing. | ||
257 | </para> | ||
258 | |||
259 | <warning> | ||
260 | <para> | ||
261 | This hook should not be used to replace the standard controller | ||
262 | tuning logic when a controller has quirks. Replacing the default | ||
263 | tuning logic in that case would bypass handling for drive and | ||
264 | bridge quirks that may be important to data reliability. If a | ||
265 | controller needs to filter the mode selection it should use the | ||
266 | mode_filter hook instead. | ||
267 | </para> | ||
268 | </warning> | ||
269 | |||
270 | </sect2> | ||
271 | |||
233 | <sect2><title>Reset ATA bus</title> | 272 | <sect2><title>Reset ATA bus</title> |
234 | <programlisting> | 273 | <programlisting> |
235 | void (*phy_reset) (struct ata_port *ap); | 274 | void (*phy_reset) (struct ata_port *ap); |
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index 326595f3fa4d..ce3ef4fa0551 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S | |||
@@ -312,3 +312,4 @@ ENTRY(sys_call_table) | |||
312 | .long sys_unshare /* 310 */ | 312 | .long sys_unshare /* 310 */ |
313 | .long sys_set_robust_list | 313 | .long sys_set_robust_list |
314 | .long sys_get_robust_list | 314 | .long sys_get_robust_list |
315 | .long sys_splice | ||
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 0e3eda99e549..750e8e7fbdc3 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S | |||
@@ -1605,5 +1605,6 @@ sys_call_table: | |||
1605 | data8 sys_ni_syscall // reserved for pselect | 1605 | data8 sys_ni_syscall // reserved for pselect |
1606 | data8 sys_ni_syscall // 1295 reserved for ppoll | 1606 | data8 sys_ni_syscall // 1295 reserved for ppoll |
1607 | data8 sys_unshare | 1607 | data8 sys_unshare |
1608 | data8 sys_splice | ||
1608 | 1609 | ||
1609 | .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls | 1610 | .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls |
diff --git a/arch/ia64/kernel/gate.lds.S b/arch/ia64/kernel/gate.lds.S index e1e4aba9ecd0..7c99e6ec3daf 100644 --- a/arch/ia64/kernel/gate.lds.S +++ b/arch/ia64/kernel/gate.lds.S | |||
@@ -59,6 +59,7 @@ SECTIONS | |||
59 | *(.dynbss) | 59 | *(.dynbss) |
60 | *(.bss .bss.* .gnu.linkonce.b.*) | 60 | *(.bss .bss.* .gnu.linkonce.b.*) |
61 | *(__ex_table) | 61 | *(__ex_table) |
62 | *(__mca_table) | ||
62 | } | 63 | } |
63 | } | 64 | } |
64 | 65 | ||
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 8832c553230a..7956eb9058fc 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c | |||
@@ -9,54 +9,65 @@ | |||
9 | * Copyright (C) 1999 VA Linux Systems | 9 | * Copyright (C) 1999 VA Linux Systems |
10 | * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com> | 10 | * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com> |
11 | * | 11 | * |
12 | * 00/04/19 D. Mosberger Rewritten to mirror more closely the x86 I/O APIC code. | 12 | * 00/04/19 D. Mosberger Rewritten to mirror more closely the x86 I/O |
13 | * In particular, we now have separate handlers for edge | 13 | * APIC code. In particular, we now have separate |
14 | * and level triggered interrupts. | 14 | * handlers for edge and level triggered |
15 | * 00/10/27 Asit Mallick, Goutham Rao <goutham.rao@intel.com> IRQ vector allocation | 15 | * interrupts. |
16 | * PCI to vector mapping, shared PCI interrupts. | 16 | * 00/10/27 Asit Mallick, Goutham Rao <goutham.rao@intel.com> IRQ vector |
17 | * 00/10/27 D. Mosberger Document things a bit more to make them more understandable. | 17 | * allocation PCI to vector mapping, shared PCI |
18 | * Clean up much of the old IOSAPIC cruft. | 18 | * interrupts. |
19 | * 01/07/27 J.I. Lee PCI irq routing, Platform/Legacy interrupts and fixes for | 19 | * 00/10/27 D. Mosberger Document things a bit more to make them more |
20 | * ACPI S5(SoftOff) support. | 20 | * understandable. Clean up much of the old |
21 | * IOSAPIC cruft. | ||
22 | * 01/07/27 J.I. Lee PCI irq routing, Platform/Legacy interrupts | ||
23 | * and fixes for ACPI S5(SoftOff) support. | ||
21 | * 02/01/23 J.I. Lee iosapic pgm fixes for PCI irq routing from _PRT | 24 | * 02/01/23 J.I. Lee iosapic pgm fixes for PCI irq routing from _PRT |
22 | * 02/01/07 E. Focht <efocht@ess.nec.de> Redirectable interrupt vectors in | 25 | * 02/01/07 E. Focht <efocht@ess.nec.de> Redirectable interrupt |
23 | * iosapic_set_affinity(), initializations for | 26 | * vectors in iosapic_set_affinity(), |
24 | * /proc/irq/#/smp_affinity | 27 | * initializations for /proc/irq/#/smp_affinity |
25 | * 02/04/02 P. Diefenbaugh Cleaned up ACPI PCI IRQ routing. | 28 | * 02/04/02 P. Diefenbaugh Cleaned up ACPI PCI IRQ routing. |
26 | * 02/04/18 J.I. Lee bug fix in iosapic_init_pci_irq | 29 | * 02/04/18 J.I. Lee bug fix in iosapic_init_pci_irq |
27 | * 02/04/30 J.I. Lee bug fix in find_iosapic to fix ACPI PCI IRQ to IOSAPIC mapping | 30 | * 02/04/30 J.I. Lee bug fix in find_iosapic to fix ACPI PCI IRQ to |
28 | * error | 31 | * IOSAPIC mapping error |
29 | * 02/07/29 T. Kochi Allocate interrupt vectors dynamically | 32 | * 02/07/29 T. Kochi Allocate interrupt vectors dynamically |
30 | * 02/08/04 T. Kochi Cleaned up terminology (irq, global system interrupt, vector, etc.) | 33 | * 02/08/04 T. Kochi Cleaned up terminology (irq, global system |
31 | * 02/09/20 D. Mosberger Simplified by taking advantage of ACPI's pci_irq code. | 34 | * interrupt, vector, etc.) |
35 | * 02/09/20 D. Mosberger Simplified by taking advantage of ACPI's | ||
36 | * pci_irq code. | ||
32 | * 03/02/19 B. Helgaas Make pcat_compat system-wide, not per-IOSAPIC. | 37 | * 03/02/19 B. Helgaas Make pcat_compat system-wide, not per-IOSAPIC. |
33 | * Remove iosapic_address & gsi_base from external interfaces. | 38 | * Remove iosapic_address & gsi_base from |
34 | * Rationalize __init/__devinit attributes. | 39 | * external interfaces. Rationalize |
40 | * __init/__devinit attributes. | ||
35 | * 04/12/04 Ashok Raj <ashok.raj@intel.com> Intel Corporation 2004 | 41 | * 04/12/04 Ashok Raj <ashok.raj@intel.com> Intel Corporation 2004 |
36 | * Updated to work with irq migration necessary for CPU Hotplug | 42 | * Updated to work with irq migration necessary |
43 | * for CPU Hotplug | ||
37 | */ | 44 | */ |
38 | /* | 45 | /* |
39 | * Here is what the interrupt logic between a PCI device and the kernel looks like: | 46 | * Here is what the interrupt logic between a PCI device and the kernel looks |
47 | * like: | ||
40 | * | 48 | * |
41 | * (1) A PCI device raises one of the four interrupt pins (INTA, INTB, INTC, INTD). The | 49 | * (1) A PCI device raises one of the four interrupt pins (INTA, INTB, INTC, |
42 | * device is uniquely identified by its bus--, and slot-number (the function | 50 | * INTD). The device is uniquely identified by its bus-, and slot-number |
43 | * number does not matter here because all functions share the same interrupt | 51 | * (the function number does not matter here because all functions share |
44 | * lines). | 52 | * the same interrupt lines). |
45 | * | 53 | * |
46 | * (2) The motherboard routes the interrupt line to a pin on a IOSAPIC controller. | 54 | * (2) The motherboard routes the interrupt line to a pin on a IOSAPIC |
47 | * Multiple interrupt lines may have to share the same IOSAPIC pin (if they're level | 55 | * controller. Multiple interrupt lines may have to share the same |
48 | * triggered and use the same polarity). Each interrupt line has a unique Global | 56 | * IOSAPIC pin (if they're level triggered and use the same polarity). |
49 | * System Interrupt (GSI) number which can be calculated as the sum of the controller's | 57 | * Each interrupt line has a unique Global System Interrupt (GSI) number |
50 | * base GSI number and the IOSAPIC pin number to which the line connects. | 58 | * which can be calculated as the sum of the controller's base GSI number |
59 | * and the IOSAPIC pin number to which the line connects. | ||
51 | * | 60 | * |
52 | * (3) The IOSAPIC uses an internal routing table entries (RTEs) to map the IOSAPIC pin | 61 | * (3) The IOSAPIC uses an internal routing table entries (RTEs) to map the |
53 | * into the IA-64 interrupt vector. This interrupt vector is then sent to the CPU. | 62 | * IOSAPIC pin into the IA-64 interrupt vector. This interrupt vector is then |
63 | * sent to the CPU. | ||
54 | * | 64 | * |
55 | * (4) The kernel recognizes an interrupt as an IRQ. The IRQ interface is used as | 65 | * (4) The kernel recognizes an interrupt as an IRQ. The IRQ interface is |
56 | * architecture-independent interrupt handling mechanism in Linux. As an | 66 | * used as architecture-independent interrupt handling mechanism in Linux. |
57 | * IRQ is a number, we have to have IA-64 interrupt vector number <-> IRQ number | 67 | * As an IRQ is a number, we have to have |
58 | * mapping. On smaller systems, we use one-to-one mapping between IA-64 vector and | 68 | * IA-64 interrupt vector number <-> IRQ number mapping. On smaller |
59 | * IRQ. A platform can implement platform_irq_to_vector(irq) and | 69 | * systems, we use one-to-one mapping between IA-64 vector and IRQ. A |
70 | * platform can implement platform_irq_to_vector(irq) and | ||
60 | * platform_local_vector_to_irq(vector) APIs to differentiate the mapping. | 71 | * platform_local_vector_to_irq(vector) APIs to differentiate the mapping. |
61 | * Please see also include/asm-ia64/hw_irq.h for those APIs. | 72 | * Please see also include/asm-ia64/hw_irq.h for those APIs. |
62 | * | 73 | * |
@@ -64,9 +75,9 @@ | |||
64 | * | 75 | * |
65 | * PCI pin -> global system interrupt (GSI) -> IA-64 vector <-> IRQ | 76 | * PCI pin -> global system interrupt (GSI) -> IA-64 vector <-> IRQ |
66 | * | 77 | * |
67 | * Note: The term "IRQ" is loosely used everywhere in Linux kernel to describe interrupts. | 78 | * Note: The term "IRQ" is loosely used everywhere in Linux kernel to |
68 | * Now we use "IRQ" only for Linux IRQ's. ISA IRQ (isa_irq) is the only exception in this | 79 | * describeinterrupts. Now we use "IRQ" only for Linux IRQ's. ISA IRQ |
69 | * source code. | 80 | * (isa_irq) is the only exception in this source code. |
70 | */ | 81 | */ |
71 | #include <linux/config.h> | 82 | #include <linux/config.h> |
72 | 83 | ||
@@ -90,7 +101,6 @@ | |||
90 | #include <asm/ptrace.h> | 101 | #include <asm/ptrace.h> |
91 | #include <asm/system.h> | 102 | #include <asm/system.h> |
92 | 103 | ||
93 | |||
94 | #undef DEBUG_INTERRUPT_ROUTING | 104 | #undef DEBUG_INTERRUPT_ROUTING |
95 | 105 | ||
96 | #ifdef DEBUG_INTERRUPT_ROUTING | 106 | #ifdef DEBUG_INTERRUPT_ROUTING |
@@ -99,36 +109,46 @@ | |||
99 | #define DBG(fmt...) | 109 | #define DBG(fmt...) |
100 | #endif | 110 | #endif |
101 | 111 | ||
102 | #define NR_PREALLOCATE_RTE_ENTRIES (PAGE_SIZE / sizeof(struct iosapic_rte_info)) | 112 | #define NR_PREALLOCATE_RTE_ENTRIES \ |
113 | (PAGE_SIZE / sizeof(struct iosapic_rte_info)) | ||
103 | #define RTE_PREALLOCATED (1) | 114 | #define RTE_PREALLOCATED (1) |
104 | 115 | ||
105 | static DEFINE_SPINLOCK(iosapic_lock); | 116 | static DEFINE_SPINLOCK(iosapic_lock); |
106 | 117 | ||
107 | /* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */ | 118 | /* |
119 | * These tables map IA-64 vectors to the IOSAPIC pin that generates this | ||
120 | * vector. | ||
121 | */ | ||
108 | 122 | ||
109 | struct iosapic_rte_info { | 123 | struct iosapic_rte_info { |
110 | struct list_head rte_list; /* node in list of RTEs sharing the same vector */ | 124 | struct list_head rte_list; /* node in list of RTEs sharing the |
125 | * same vector */ | ||
111 | char __iomem *addr; /* base address of IOSAPIC */ | 126 | char __iomem *addr; /* base address of IOSAPIC */ |
112 | unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */ | 127 | unsigned int gsi_base; /* first GSI assigned to this |
128 | * IOSAPIC */ | ||
113 | char rte_index; /* IOSAPIC RTE index */ | 129 | char rte_index; /* IOSAPIC RTE index */ |
114 | int refcnt; /* reference counter */ | 130 | int refcnt; /* reference counter */ |
115 | unsigned int flags; /* flags */ | 131 | unsigned int flags; /* flags */ |
116 | } ____cacheline_aligned; | 132 | } ____cacheline_aligned; |
117 | 133 | ||
118 | static struct iosapic_intr_info { | 134 | static struct iosapic_intr_info { |
119 | struct list_head rtes; /* RTEs using this vector (empty => not an IOSAPIC interrupt) */ | 135 | struct list_head rtes; /* RTEs using this vector (empty => |
136 | * not an IOSAPIC interrupt) */ | ||
120 | int count; /* # of RTEs that shares this vector */ | 137 | int count; /* # of RTEs that shares this vector */ |
121 | u32 low32; /* current value of low word of Redirection table entry */ | 138 | u32 low32; /* current value of low word of |
139 | * Redirection table entry */ | ||
122 | unsigned int dest; /* destination CPU physical ID */ | 140 | unsigned int dest; /* destination CPU physical ID */ |
123 | unsigned char dmode : 3; /* delivery mode (see iosapic.h) */ | 141 | unsigned char dmode : 3; /* delivery mode (see iosapic.h) */ |
124 | unsigned char polarity: 1; /* interrupt polarity (see iosapic.h) */ | 142 | unsigned char polarity: 1; /* interrupt polarity |
143 | * (see iosapic.h) */ | ||
125 | unsigned char trigger : 1; /* trigger mode (see iosapic.h) */ | 144 | unsigned char trigger : 1; /* trigger mode (see iosapic.h) */ |
126 | } iosapic_intr_info[IA64_NUM_VECTORS]; | 145 | } iosapic_intr_info[IA64_NUM_VECTORS]; |
127 | 146 | ||
128 | static struct iosapic { | 147 | static struct iosapic { |
129 | char __iomem *addr; /* base address of IOSAPIC */ | 148 | char __iomem *addr; /* base address of IOSAPIC */ |
130 | unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */ | 149 | unsigned int gsi_base; /* first GSI assigned to this |
131 | unsigned short num_rte; /* number of RTE in this IOSAPIC */ | 150 | * IOSAPIC */ |
151 | unsigned short num_rte; /* # of RTEs on this IOSAPIC */ | ||
132 | int rtes_inuse; /* # of RTEs in use on this IOSAPIC */ | 152 | int rtes_inuse; /* # of RTEs in use on this IOSAPIC */ |
133 | #ifdef CONFIG_NUMA | 153 | #ifdef CONFIG_NUMA |
134 | unsigned short node; /* numa node association via pxm */ | 154 | unsigned short node; /* numa node association via pxm */ |
@@ -149,7 +169,8 @@ find_iosapic (unsigned int gsi) | |||
149 | int i; | 169 | int i; |
150 | 170 | ||
151 | for (i = 0; i < NR_IOSAPICS; i++) { | 171 | for (i = 0; i < NR_IOSAPICS; i++) { |
152 | if ((unsigned) (gsi - iosapic_lists[i].gsi_base) < iosapic_lists[i].num_rte) | 172 | if ((unsigned) (gsi - iosapic_lists[i].gsi_base) < |
173 | iosapic_lists[i].num_rte) | ||
153 | return i; | 174 | return i; |
154 | } | 175 | } |
155 | 176 | ||
@@ -162,7 +183,8 @@ _gsi_to_vector (unsigned int gsi) | |||
162 | struct iosapic_intr_info *info; | 183 | struct iosapic_intr_info *info; |
163 | struct iosapic_rte_info *rte; | 184 | struct iosapic_rte_info *rte; |
164 | 185 | ||
165 | for (info = iosapic_intr_info; info < iosapic_intr_info + IA64_NUM_VECTORS; ++info) | 186 | for (info = iosapic_intr_info; info < |
187 | iosapic_intr_info + IA64_NUM_VECTORS; ++info) | ||
166 | list_for_each_entry(rte, &info->rtes, rte_list) | 188 | list_for_each_entry(rte, &info->rtes, rte_list) |
167 | if (rte->gsi_base + rte->rte_index == gsi) | 189 | if (rte->gsi_base + rte->rte_index == gsi) |
168 | return info - iosapic_intr_info; | 190 | return info - iosapic_intr_info; |
@@ -185,8 +207,8 @@ gsi_to_irq (unsigned int gsi) | |||
185 | unsigned long flags; | 207 | unsigned long flags; |
186 | int irq; | 208 | int irq; |
187 | /* | 209 | /* |
188 | * XXX fix me: this assumes an identity mapping vetween IA-64 vector and Linux irq | 210 | * XXX fix me: this assumes an identity mapping between IA-64 vector |
189 | * numbers... | 211 | * and Linux irq numbers... |
190 | */ | 212 | */ |
191 | spin_lock_irqsave(&iosapic_lock, flags); | 213 | spin_lock_irqsave(&iosapic_lock, flags); |
192 | { | 214 | { |
@@ -197,7 +219,8 @@ gsi_to_irq (unsigned int gsi) | |||
197 | return irq; | 219 | return irq; |
198 | } | 220 | } |
199 | 221 | ||
200 | static struct iosapic_rte_info *gsi_vector_to_rte(unsigned int gsi, unsigned int vec) | 222 | static struct iosapic_rte_info *gsi_vector_to_rte(unsigned int gsi, |
223 | unsigned int vec) | ||
201 | { | 224 | { |
202 | struct iosapic_rte_info *rte; | 225 | struct iosapic_rte_info *rte; |
203 | 226 | ||
@@ -237,7 +260,9 @@ set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask) | |||
237 | 260 | ||
238 | for (irq = 0; irq < NR_IRQS; ++irq) | 261 | for (irq = 0; irq < NR_IRQS; ++irq) |
239 | if (irq_to_vector(irq) == vector) { | 262 | if (irq_to_vector(irq) == vector) { |
240 | set_irq_affinity_info(irq, (int)(dest & 0xffff), redir); | 263 | set_irq_affinity_info(irq, |
264 | (int)(dest & 0xffff), | ||
265 | redir); | ||
241 | break; | 266 | break; |
242 | } | 267 | } |
243 | } | 268 | } |
@@ -259,7 +284,7 @@ set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask) | |||
259 | } | 284 | } |
260 | 285 | ||
261 | static void | 286 | static void |
262 | nop (unsigned int vector) | 287 | nop (unsigned int irq) |
263 | { | 288 | { |
264 | /* do nothing... */ | 289 | /* do nothing... */ |
265 | } | 290 | } |
@@ -281,7 +306,8 @@ mask_irq (unsigned int irq) | |||
281 | { | 306 | { |
282 | /* set only the mask bit */ | 307 | /* set only the mask bit */ |
283 | low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK; | 308 | low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK; |
284 | list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { | 309 | list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, |
310 | rte_list) { | ||
285 | addr = rte->addr; | 311 | addr = rte->addr; |
286 | rte_index = rte->rte_index; | 312 | rte_index = rte->rte_index; |
287 | iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); | 313 | iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); |
@@ -306,7 +332,8 @@ unmask_irq (unsigned int irq) | |||
306 | spin_lock_irqsave(&iosapic_lock, flags); | 332 | spin_lock_irqsave(&iosapic_lock, flags); |
307 | { | 333 | { |
308 | low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK; | 334 | low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK; |
309 | list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { | 335 | list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, |
336 | rte_list) { | ||
310 | addr = rte->addr; | 337 | addr = rte->addr; |
311 | rte_index = rte->rte_index; | 338 | rte_index = rte->rte_index; |
312 | iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); | 339 | iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); |
@@ -346,21 +373,25 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) | |||
346 | 373 | ||
347 | spin_lock_irqsave(&iosapic_lock, flags); | 374 | spin_lock_irqsave(&iosapic_lock, flags); |
348 | { | 375 | { |
349 | low32 = iosapic_intr_info[vec].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT); | 376 | low32 = iosapic_intr_info[vec].low32 & |
377 | ~(7 << IOSAPIC_DELIVERY_SHIFT); | ||
350 | 378 | ||
351 | if (redir) | 379 | if (redir) |
352 | /* change delivery mode to lowest priority */ | 380 | /* change delivery mode to lowest priority */ |
353 | low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT); | 381 | low32 |= (IOSAPIC_LOWEST_PRIORITY << |
382 | IOSAPIC_DELIVERY_SHIFT); | ||
354 | else | 383 | else |
355 | /* change delivery mode to fixed */ | 384 | /* change delivery mode to fixed */ |
356 | low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT); | 385 | low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT); |
357 | 386 | ||
358 | iosapic_intr_info[vec].low32 = low32; | 387 | iosapic_intr_info[vec].low32 = low32; |
359 | iosapic_intr_info[vec].dest = dest; | 388 | iosapic_intr_info[vec].dest = dest; |
360 | list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { | 389 | list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, |
390 | rte_list) { | ||
361 | addr = rte->addr; | 391 | addr = rte->addr; |
362 | rte_index = rte->rte_index; | 392 | rte_index = rte->rte_index; |
363 | iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32); | 393 | iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), |
394 | high32); | ||
364 | iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); | 395 | iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); |
365 | } | 396 | } |
366 | } | 397 | } |
@@ -433,7 +464,8 @@ iosapic_ack_edge_irq (unsigned int irq) | |||
433 | * interrupt for real. This prevents IRQ storms from unhandled | 464 | * interrupt for real. This prevents IRQ storms from unhandled |
434 | * devices. | 465 | * devices. |
435 | */ | 466 | */ |
436 | if ((idesc->status & (IRQ_PENDING|IRQ_DISABLED)) == (IRQ_PENDING|IRQ_DISABLED)) | 467 | if ((idesc->status & (IRQ_PENDING|IRQ_DISABLED)) == |
468 | (IRQ_PENDING|IRQ_DISABLED)) | ||
437 | mask_irq(irq); | 469 | mask_irq(irq); |
438 | } | 470 | } |
439 | 471 | ||
@@ -467,7 +499,8 @@ iosapic_version (char __iomem *addr) | |||
467 | return iosapic_read(addr, IOSAPIC_VERSION); | 499 | return iosapic_read(addr, IOSAPIC_VERSION); |
468 | } | 500 | } |
469 | 501 | ||
470 | static int iosapic_find_sharable_vector (unsigned long trigger, unsigned long pol) | 502 | static int iosapic_find_sharable_vector (unsigned long trigger, |
503 | unsigned long pol) | ||
471 | { | 504 | { |
472 | int i, vector = -1, min_count = -1; | 505 | int i, vector = -1, min_count = -1; |
473 | struct iosapic_intr_info *info; | 506 | struct iosapic_intr_info *info; |
@@ -482,7 +515,8 @@ static int iosapic_find_sharable_vector (unsigned long trigger, unsigned long po | |||
482 | for (i = IA64_FIRST_DEVICE_VECTOR; i <= IA64_LAST_DEVICE_VECTOR; i++) { | 515 | for (i = IA64_FIRST_DEVICE_VECTOR; i <= IA64_LAST_DEVICE_VECTOR; i++) { |
483 | info = &iosapic_intr_info[i]; | 516 | info = &iosapic_intr_info[i]; |
484 | if (info->trigger == trigger && info->polarity == pol && | 517 | if (info->trigger == trigger && info->polarity == pol && |
485 | (info->dmode == IOSAPIC_FIXED || info->dmode == IOSAPIC_LOWEST_PRIORITY)) { | 518 | (info->dmode == IOSAPIC_FIXED || info->dmode == |
519 | IOSAPIC_LOWEST_PRIORITY)) { | ||
486 | if (min_count == -1 || info->count < min_count) { | 520 | if (min_count == -1 || info->count < min_count) { |
487 | vector = i; | 521 | vector = i; |
488 | min_count = info->count; | 522 | min_count = info->count; |
@@ -506,12 +540,15 @@ iosapic_reassign_vector (int vector) | |||
506 | new_vector = assign_irq_vector(AUTO_ASSIGN); | 540 | new_vector = assign_irq_vector(AUTO_ASSIGN); |
507 | if (new_vector < 0) | 541 | if (new_vector < 0) |
508 | panic("%s: out of interrupt vectors!\n", __FUNCTION__); | 542 | panic("%s: out of interrupt vectors!\n", __FUNCTION__); |
509 | printk(KERN_INFO "Reassigning vector %d to %d\n", vector, new_vector); | 543 | printk(KERN_INFO "Reassigning vector %d to %d\n", |
544 | vector, new_vector); | ||
510 | memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector], | 545 | memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector], |
511 | sizeof(struct iosapic_intr_info)); | 546 | sizeof(struct iosapic_intr_info)); |
512 | INIT_LIST_HEAD(&iosapic_intr_info[new_vector].rtes); | 547 | INIT_LIST_HEAD(&iosapic_intr_info[new_vector].rtes); |
513 | list_move(iosapic_intr_info[vector].rtes.next, &iosapic_intr_info[new_vector].rtes); | 548 | list_move(iosapic_intr_info[vector].rtes.next, |
514 | memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info)); | 549 | &iosapic_intr_info[new_vector].rtes); |
550 | memset(&iosapic_intr_info[vector], 0, | ||
551 | sizeof(struct iosapic_intr_info)); | ||
515 | iosapic_intr_info[vector].low32 = IOSAPIC_MASK; | 552 | iosapic_intr_info[vector].low32 = IOSAPIC_MASK; |
516 | INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); | 553 | INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); |
517 | } | 554 | } |
@@ -524,7 +561,8 @@ static struct iosapic_rte_info *iosapic_alloc_rte (void) | |||
524 | int preallocated = 0; | 561 | int preallocated = 0; |
525 | 562 | ||
526 | if (!iosapic_kmalloc_ok && list_empty(&free_rte_list)) { | 563 | if (!iosapic_kmalloc_ok && list_empty(&free_rte_list)) { |
527 | rte = alloc_bootmem(sizeof(struct iosapic_rte_info) * NR_PREALLOCATE_RTE_ENTRIES); | 564 | rte = alloc_bootmem(sizeof(struct iosapic_rte_info) * |
565 | NR_PREALLOCATE_RTE_ENTRIES); | ||
528 | if (!rte) | 566 | if (!rte) |
529 | return NULL; | 567 | return NULL; |
530 | for (i = 0; i < NR_PREALLOCATE_RTE_ENTRIES; i++, rte++) | 568 | for (i = 0; i < NR_PREALLOCATE_RTE_ENTRIES; i++, rte++) |
@@ -532,7 +570,8 @@ static struct iosapic_rte_info *iosapic_alloc_rte (void) | |||
532 | } | 570 | } |
533 | 571 | ||
534 | if (!list_empty(&free_rte_list)) { | 572 | if (!list_empty(&free_rte_list)) { |
535 | rte = list_entry(free_rte_list.next, struct iosapic_rte_info, rte_list); | 573 | rte = list_entry(free_rte_list.next, struct iosapic_rte_info, |
574 | rte_list); | ||
536 | list_del(&rte->rte_list); | 575 | list_del(&rte->rte_list); |
537 | preallocated++; | 576 | preallocated++; |
538 | } else { | 577 | } else { |
@@ -575,7 +614,8 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, | |||
575 | 614 | ||
576 | index = find_iosapic(gsi); | 615 | index = find_iosapic(gsi); |
577 | if (index < 0) { | 616 | if (index < 0) { |
578 | printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n", __FUNCTION__, gsi); | 617 | printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n", |
618 | __FUNCTION__, gsi); | ||
579 | return -ENODEV; | 619 | return -ENODEV; |
580 | } | 620 | } |
581 | 621 | ||
@@ -586,7 +626,8 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, | |||
586 | if (!rte) { | 626 | if (!rte) { |
587 | rte = iosapic_alloc_rte(); | 627 | rte = iosapic_alloc_rte(); |
588 | if (!rte) { | 628 | if (!rte) { |
589 | printk(KERN_WARNING "%s: cannot allocate memory\n", __FUNCTION__); | 629 | printk(KERN_WARNING "%s: cannot allocate memory\n", |
630 | __FUNCTION__); | ||
590 | return -ENOMEM; | 631 | return -ENOMEM; |
591 | } | 632 | } |
592 | 633 | ||
@@ -602,7 +643,9 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, | |||
602 | else if (vector_is_shared(vector)) { | 643 | else if (vector_is_shared(vector)) { |
603 | struct iosapic_intr_info *info = &iosapic_intr_info[vector]; | 644 | struct iosapic_intr_info *info = &iosapic_intr_info[vector]; |
604 | if (info->trigger != trigger || info->polarity != polarity) { | 645 | if (info->trigger != trigger || info->polarity != polarity) { |
605 | printk (KERN_WARNING "%s: cannot override the interrupt\n", __FUNCTION__); | 646 | printk (KERN_WARNING |
647 | "%s: cannot override the interrupt\n", | ||
648 | __FUNCTION__); | ||
606 | return -EINVAL; | 649 | return -EINVAL; |
607 | } | 650 | } |
608 | } | 651 | } |
@@ -619,8 +662,10 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, | |||
619 | idesc = irq_descp(vector); | 662 | idesc = irq_descp(vector); |
620 | if (idesc->handler != irq_type) { | 663 | if (idesc->handler != irq_type) { |
621 | if (idesc->handler != &no_irq_type) | 664 | if (idesc->handler != &no_irq_type) |
622 | printk(KERN_WARNING "%s: changing vector %d from %s to %s\n", | 665 | printk(KERN_WARNING |
623 | __FUNCTION__, vector, idesc->handler->typename, irq_type->typename); | 666 | "%s: changing vector %d from %s to %s\n", |
667 | __FUNCTION__, vector, | ||
668 | idesc->handler->typename, irq_type->typename); | ||
624 | idesc->handler = irq_type; | 669 | idesc->handler = irq_type; |
625 | } | 670 | } |
626 | return 0; | 671 | return 0; |
@@ -681,7 +726,7 @@ get_target_cpu (unsigned int gsi, int vector) | |||
681 | if (!num_cpus) | 726 | if (!num_cpus) |
682 | goto skip_numa_setup; | 727 | goto skip_numa_setup; |
683 | 728 | ||
684 | /* Use vector assigment to distribute across cpus in node */ | 729 | /* Use vector assignment to distribute across cpus in node */ |
685 | cpu_index = vector % num_cpus; | 730 | cpu_index = vector % num_cpus; |
686 | 731 | ||
687 | for (numa_cpu = first_cpu(cpu_mask) ; i < cpu_index ; i++) | 732 | for (numa_cpu = first_cpu(cpu_mask) ; i < cpu_index ; i++) |
@@ -703,7 +748,7 @@ skip_numa_setup: | |||
703 | } while (!cpu_online(cpu)); | 748 | } while (!cpu_online(cpu)); |
704 | 749 | ||
705 | return cpu_physical_id(cpu); | 750 | return cpu_physical_id(cpu); |
706 | #else | 751 | #else /* CONFIG_SMP */ |
707 | return cpu_physical_id(smp_processor_id()); | 752 | return cpu_physical_id(smp_processor_id()); |
708 | #endif | 753 | #endif |
709 | } | 754 | } |
@@ -755,7 +800,8 @@ again: | |||
755 | if (list_empty(&iosapic_intr_info[vector].rtes)) | 800 | if (list_empty(&iosapic_intr_info[vector].rtes)) |
756 | free_irq_vector(vector); | 801 | free_irq_vector(vector); |
757 | spin_unlock(&iosapic_lock); | 802 | spin_unlock(&iosapic_lock); |
758 | spin_unlock_irqrestore(&irq_descp(vector)->lock, flags); | 803 | spin_unlock_irqrestore(&irq_descp(vector)->lock, |
804 | flags); | ||
759 | goto again; | 805 | goto again; |
760 | } | 806 | } |
761 | 807 | ||
@@ -764,7 +810,8 @@ again: | |||
764 | polarity, trigger); | 810 | polarity, trigger); |
765 | if (err < 0) { | 811 | if (err < 0) { |
766 | spin_unlock(&iosapic_lock); | 812 | spin_unlock(&iosapic_lock); |
767 | spin_unlock_irqrestore(&irq_descp(vector)->lock, flags); | 813 | spin_unlock_irqrestore(&irq_descp(vector)->lock, |
814 | flags); | ||
768 | return err; | 815 | return err; |
769 | } | 816 | } |
770 | 817 | ||
@@ -806,7 +853,8 @@ iosapic_unregister_intr (unsigned int gsi) | |||
806 | */ | 853 | */ |
807 | irq = gsi_to_irq(gsi); | 854 | irq = gsi_to_irq(gsi); |
808 | if (irq < 0) { | 855 | if (irq < 0) { |
809 | printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", gsi); | 856 | printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", |
857 | gsi); | ||
810 | WARN_ON(1); | 858 | WARN_ON(1); |
811 | return; | 859 | return; |
812 | } | 860 | } |
@@ -817,7 +865,9 @@ iosapic_unregister_intr (unsigned int gsi) | |||
817 | spin_lock(&iosapic_lock); | 865 | spin_lock(&iosapic_lock); |
818 | { | 866 | { |
819 | if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) { | 867 | if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) { |
820 | printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", gsi); | 868 | printk(KERN_ERR |
869 | "iosapic_unregister_intr(%u) unbalanced\n", | ||
870 | gsi); | ||
821 | WARN_ON(1); | 871 | WARN_ON(1); |
822 | goto out; | 872 | goto out; |
823 | } | 873 | } |
@@ -827,7 +877,8 @@ iosapic_unregister_intr (unsigned int gsi) | |||
827 | 877 | ||
828 | /* Mask the interrupt */ | 878 | /* Mask the interrupt */ |
829 | low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK; | 879 | low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK; |
830 | iosapic_write(rte->addr, IOSAPIC_RTE_LOW(rte->rte_index), low32); | 880 | iosapic_write(rte->addr, IOSAPIC_RTE_LOW(rte->rte_index), |
881 | low32); | ||
831 | 882 | ||
832 | /* Remove the rte entry from the list */ | 883 | /* Remove the rte entry from the list */ |
833 | list_del(&rte->rte_list); | 884 | list_del(&rte->rte_list); |
@@ -840,7 +891,9 @@ iosapic_unregister_intr (unsigned int gsi) | |||
840 | trigger = iosapic_intr_info[vector].trigger; | 891 | trigger = iosapic_intr_info[vector].trigger; |
841 | polarity = iosapic_intr_info[vector].polarity; | 892 | polarity = iosapic_intr_info[vector].polarity; |
842 | dest = iosapic_intr_info[vector].dest; | 893 | dest = iosapic_intr_info[vector].dest; |
843 | printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d unregistered\n", | 894 | printk(KERN_INFO |
895 | "GSI %u (%s, %s) -> CPU %d (0x%04x)" | ||
896 | " vector %d unregistered\n", | ||
844 | gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), | 897 | gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), |
845 | (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), | 898 | (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), |
846 | cpu_logical_id(dest), dest, vector); | 899 | cpu_logical_id(dest), dest, vector); |
@@ -853,12 +906,15 @@ iosapic_unregister_intr (unsigned int gsi) | |||
853 | idesc->handler = &no_irq_type; | 906 | idesc->handler = &no_irq_type; |
854 | 907 | ||
855 | /* Clear the interrupt information */ | 908 | /* Clear the interrupt information */ |
856 | memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info)); | 909 | memset(&iosapic_intr_info[vector], 0, |
910 | sizeof(struct iosapic_intr_info)); | ||
857 | iosapic_intr_info[vector].low32 |= IOSAPIC_MASK; | 911 | iosapic_intr_info[vector].low32 |= IOSAPIC_MASK; |
858 | INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); | 912 | INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); |
859 | 913 | ||
860 | if (idesc->action) { | 914 | if (idesc->action) { |
861 | printk(KERN_ERR "interrupt handlers still exist on IRQ %u\n", irq); | 915 | printk(KERN_ERR |
916 | "interrupt handlers still exist on" | ||
917 | "IRQ %u\n", irq); | ||
862 | WARN_ON(1); | 918 | WARN_ON(1); |
863 | } | 919 | } |
864 | 920 | ||
@@ -873,7 +929,6 @@ iosapic_unregister_intr (unsigned int gsi) | |||
873 | 929 | ||
874 | /* | 930 | /* |
875 | * ACPI calls this when it finds an entry for a platform interrupt. | 931 | * ACPI calls this when it finds an entry for a platform interrupt. |
876 | * Note that the irq_base and IOSAPIC address must be set in iosapic_init(). | ||
877 | */ | 932 | */ |
878 | int __init | 933 | int __init |
879 | iosapic_register_platform_intr (u32 int_type, unsigned int gsi, | 934 | iosapic_register_platform_intr (u32 int_type, unsigned int gsi, |
@@ -907,13 +962,16 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, | |||
907 | mask = 1; | 962 | mask = 1; |
908 | break; | 963 | break; |
909 | default: | 964 | default: |
910 | printk(KERN_ERR "iosapic_register_platform_irq(): invalid int type 0x%x\n", int_type); | 965 | printk(KERN_ERR "%s: invalid int type 0x%x\n", __FUNCTION__, |
966 | int_type); | ||
911 | return -1; | 967 | return -1; |
912 | } | 968 | } |
913 | 969 | ||
914 | register_intr(gsi, vector, delivery, polarity, trigger); | 970 | register_intr(gsi, vector, delivery, polarity, trigger); |
915 | 971 | ||
916 | printk(KERN_INFO "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n", | 972 | printk(KERN_INFO |
973 | "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x)" | ||
974 | " vector %d\n", | ||
917 | int_type < ARRAY_SIZE(name) ? name[int_type] : "unknown", | 975 | int_type < ARRAY_SIZE(name) ? name[int_type] : "unknown", |
918 | int_type, gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), | 976 | int_type, gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), |
919 | (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), | 977 | (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), |
@@ -923,10 +981,8 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, | |||
923 | return vector; | 981 | return vector; |
924 | } | 982 | } |
925 | 983 | ||
926 | |||
927 | /* | 984 | /* |
928 | * ACPI calls this when it finds an entry for a legacy ISA IRQ override. | 985 | * ACPI calls this when it finds an entry for a legacy ISA IRQ override. |
929 | * Note that the gsi_base and IOSAPIC address must be set in iosapic_init(). | ||
930 | */ | 986 | */ |
931 | void __init | 987 | void __init |
932 | iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, | 988 | iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, |
@@ -955,16 +1011,19 @@ iosapic_system_init (int system_pcat_compat) | |||
955 | 1011 | ||
956 | for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) { | 1012 | for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) { |
957 | iosapic_intr_info[vector].low32 = IOSAPIC_MASK; | 1013 | iosapic_intr_info[vector].low32 = IOSAPIC_MASK; |
958 | INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); /* mark as unused */ | 1014 | /* mark as unused */ |
1015 | INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); | ||
959 | } | 1016 | } |
960 | 1017 | ||
961 | pcat_compat = system_pcat_compat; | 1018 | pcat_compat = system_pcat_compat; |
962 | if (pcat_compat) { | 1019 | if (pcat_compat) { |
963 | /* | 1020 | /* |
964 | * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support | 1021 | * Disable the compatibility mode interrupts (8259 style), |
965 | * enabled. | 1022 | * needs IN/OUT support enabled. |
966 | */ | 1023 | */ |
967 | printk(KERN_INFO "%s: Disabling PC-AT compatible 8259 interrupts\n", __FUNCTION__); | 1024 | printk(KERN_INFO |
1025 | "%s: Disabling PC-AT compatible 8259 interrupts\n", | ||
1026 | __FUNCTION__); | ||
968 | outb(0xff, 0xA1); | 1027 | outb(0xff, 0xA1); |
969 | outb(0xff, 0x21); | 1028 | outb(0xff, 0x21); |
970 | } | 1029 | } |
@@ -1004,10 +1063,7 @@ iosapic_check_gsi_range (unsigned int gsi_base, unsigned int ver) | |||
1004 | base = iosapic_lists[index].gsi_base; | 1063 | base = iosapic_lists[index].gsi_base; |
1005 | end = base + iosapic_lists[index].num_rte - 1; | 1064 | end = base + iosapic_lists[index].num_rte - 1; |
1006 | 1065 | ||
1007 | if (gsi_base < base && gsi_end < base) | 1066 | if (gsi_end < base || end < gsi_base) |
1008 | continue;/* OK */ | ||
1009 | |||
1010 | if (gsi_base > end && gsi_end > end) | ||
1011 | continue; /* OK */ | 1067 | continue; /* OK */ |
1012 | 1068 | ||
1013 | return -EBUSY; | 1069 | return -EBUSY; |
@@ -1053,12 +1109,14 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base) | |||
1053 | 1109 | ||
1054 | if ((gsi_base == 0) && pcat_compat) { | 1110 | if ((gsi_base == 0) && pcat_compat) { |
1055 | /* | 1111 | /* |
1056 | * Map the legacy ISA devices into the IOSAPIC data. Some of these may | 1112 | * Map the legacy ISA devices into the IOSAPIC data. Some of |
1057 | * get reprogrammed later on with data from the ACPI Interrupt Source | 1113 | * these may get reprogrammed later on with data from the ACPI |
1058 | * Override table. | 1114 | * Interrupt Source Override table. |
1059 | */ | 1115 | */ |
1060 | for (isa_irq = 0; isa_irq < 16; ++isa_irq) | 1116 | for (isa_irq = 0; isa_irq < 16; ++isa_irq) |
1061 | iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE); | 1117 | iosapic_override_isa_irq(isa_irq, isa_irq, |
1118 | IOSAPIC_POL_HIGH, | ||
1119 | IOSAPIC_EDGE); | ||
1062 | } | 1120 | } |
1063 | return 0; | 1121 | return 0; |
1064 | } | 1122 | } |
@@ -1081,7 +1139,8 @@ iosapic_remove (unsigned int gsi_base) | |||
1081 | 1139 | ||
1082 | if (iosapic_lists[index].rtes_inuse) { | 1140 | if (iosapic_lists[index].rtes_inuse) { |
1083 | err = -EBUSY; | 1141 | err = -EBUSY; |
1084 | printk(KERN_WARNING "%s: IOSAPIC for GSI base %u is busy\n", | 1142 | printk(KERN_WARNING |
1143 | "%s: IOSAPIC for GSI base %u is busy\n", | ||
1085 | __FUNCTION__, gsi_base); | 1144 | __FUNCTION__, gsi_base); |
1086 | goto out; | 1145 | goto out; |
1087 | } | 1146 | } |
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index 0b9e56dd7f05..783600fe52b2 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S | |||
@@ -70,6 +70,15 @@ SECTIONS | |||
70 | __stop___ex_table = .; | 70 | __stop___ex_table = .; |
71 | } | 71 | } |
72 | 72 | ||
73 | /* MCA table */ | ||
74 | . = ALIGN(16); | ||
75 | __mca_table : AT(ADDR(__mca_table) - LOAD_OFFSET) | ||
76 | { | ||
77 | __start___mca_table = .; | ||
78 | *(__mca_table) | ||
79 | __stop___mca_table = .; | ||
80 | } | ||
81 | |||
73 | /* Global data */ | 82 | /* Global data */ |
74 | _data = .; | 83 | _data = .; |
75 | 84 | ||
@@ -130,15 +139,6 @@ SECTIONS | |||
130 | __initcall_end = .; | 139 | __initcall_end = .; |
131 | } | 140 | } |
132 | 141 | ||
133 | /* MCA table */ | ||
134 | . = ALIGN(16); | ||
135 | __mca_table : AT(ADDR(__mca_table) - LOAD_OFFSET) | ||
136 | { | ||
137 | __start___mca_table = .; | ||
138 | *(__mca_table) | ||
139 | __stop___mca_table = .; | ||
140 | } | ||
141 | |||
142 | .data.patch.vtop : AT(ADDR(.data.patch.vtop) - LOAD_OFFSET) | 142 | .data.patch.vtop : AT(ADDR(.data.patch.vtop) - LOAD_OFFSET) |
143 | { | 143 | { |
144 | __start___vtop_patchlist = .; | 144 | __start___vtop_patchlist = .; |
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index 2ef1151cde90..cafa8776a53d 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c | |||
@@ -109,6 +109,7 @@ lazy_mmu_prot_update (pte_t pte) | |||
109 | { | 109 | { |
110 | unsigned long addr; | 110 | unsigned long addr; |
111 | struct page *page; | 111 | struct page *page; |
112 | unsigned long order; | ||
112 | 113 | ||
113 | if (!pte_exec(pte)) | 114 | if (!pte_exec(pte)) |
114 | return; /* not an executable page... */ | 115 | return; /* not an executable page... */ |
@@ -119,7 +120,12 @@ lazy_mmu_prot_update (pte_t pte) | |||
119 | if (test_bit(PG_arch_1, &page->flags)) | 120 | if (test_bit(PG_arch_1, &page->flags)) |
120 | return; /* i-cache is already coherent with d-cache */ | 121 | return; /* i-cache is already coherent with d-cache */ |
121 | 122 | ||
122 | flush_icache_range(addr, addr + PAGE_SIZE); | 123 | if (PageCompound(page)) { |
124 | order = (unsigned long) (page[1].lru.prev); | ||
125 | flush_icache_range(addr, addr + (1UL << order << PAGE_SHIFT)); | ||
126 | } | ||
127 | else | ||
128 | flush_icache_range(addr, addr + PAGE_SIZE); | ||
123 | set_bit(PG_arch_1, &page->flags); /* mark page as clean */ | 129 | set_bit(PG_arch_1, &page->flags); /* mark page as clean */ |
124 | } | 130 | } |
125 | 131 | ||
diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c index 62328621f99c..643ccc6960ce 100644 --- a/arch/ia64/mm/ioremap.c +++ b/arch/ia64/mm/ioremap.c | |||
@@ -21,12 +21,12 @@ __ioremap (unsigned long offset, unsigned long size) | |||
21 | void __iomem * | 21 | void __iomem * |
22 | ioremap (unsigned long offset, unsigned long size) | 22 | ioremap (unsigned long offset, unsigned long size) |
23 | { | 23 | { |
24 | if (efi_mem_attribute_range(offset, size, EFI_MEMORY_UC)) | ||
25 | return __ioremap(offset, size); | ||
26 | |||
27 | if (efi_mem_attribute_range(offset, size, EFI_MEMORY_WB)) | 24 | if (efi_mem_attribute_range(offset, size, EFI_MEMORY_WB)) |
28 | return phys_to_virt(offset); | 25 | return phys_to_virt(offset); |
29 | 26 | ||
27 | if (efi_mem_attribute_range(offset, size, EFI_MEMORY_UC)) | ||
28 | return __ioremap(offset, size); | ||
29 | |||
30 | /* | 30 | /* |
31 | * Someday this should check ACPI resources so we | 31 | * Someday this should check ACPI resources so we |
32 | * can do the right thing for hot-plugged regions. | 32 | * can do the right thing for hot-plugged regions. |
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index 6a4eec9113e8..4dbbca0b5e9c 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c | |||
@@ -156,17 +156,19 @@ flush_tlb_range (struct vm_area_struct *vma, unsigned long start, | |||
156 | nbits = purge.max_bits; | 156 | nbits = purge.max_bits; |
157 | start &= ~((1UL << nbits) - 1); | 157 | start &= ~((1UL << nbits) - 1); |
158 | 158 | ||
159 | # ifdef CONFIG_SMP | ||
160 | platform_global_tlb_purge(mm, start, end, nbits); | ||
161 | # else | ||
162 | preempt_disable(); | 159 | preempt_disable(); |
160 | #ifdef CONFIG_SMP | ||
161 | if (mm != current->active_mm || cpus_weight(mm->cpu_vm_mask) != 1) { | ||
162 | platform_global_tlb_purge(mm, start, end, nbits); | ||
163 | preempt_enable(); | ||
164 | return; | ||
165 | } | ||
166 | #endif | ||
163 | do { | 167 | do { |
164 | ia64_ptcl(start, (nbits<<2)); | 168 | ia64_ptcl(start, (nbits<<2)); |
165 | start += (1UL << nbits); | 169 | start += (1UL << nbits); |
166 | } while (start < end); | 170 | } while (start < end); |
167 | preempt_enable(); | 171 | preempt_enable(); |
168 | # endif | ||
169 | |||
170 | ia64_srlz_i(); /* srlz.i implies srlz.d */ | 172 | ia64_srlz_i(); /* srlz.i implies srlz.d */ |
171 | } | 173 | } |
172 | EXPORT_SYMBOL(flush_tlb_range); | 174 | EXPORT_SYMBOL(flush_tlb_range); |
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c index 70db21f3df21..d917afa30b27 100644 --- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c +++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c | |||
@@ -110,7 +110,11 @@ static int sn_hwperf_geoid_to_cnode(char *location) | |||
110 | if (sn_hwperf_location_to_bpos(location, &rack, &bay, &slot, &slab)) | 110 | if (sn_hwperf_location_to_bpos(location, &rack, &bay, &slot, &slab)) |
111 | return -1; | 111 | return -1; |
112 | 112 | ||
113 | for_each_node(cnode) { | 113 | /* |
114 | * FIXME: replace with cleaner for_each_XXX macro which addresses | ||
115 | * both compute and IO nodes once ACPI3.0 is available. | ||
116 | */ | ||
117 | for (cnode = 0; cnode < num_cnodes; cnode++) { | ||
114 | geoid = cnodeid_get_geoid(cnode); | 118 | geoid = cnodeid_get_geoid(cnode); |
115 | module_id = geo_module(geoid); | 119 | module_id = geo_module(geoid); |
116 | this_rack = MODULE_GET_RACK(module_id); | 120 | this_rack = MODULE_GET_RACK(module_id); |
@@ -605,7 +609,7 @@ static int sn_hwperf_op_cpu(struct sn_hwperf_op_info *op_info) | |||
605 | op_info->a->arg &= SN_HWPERF_ARG_OBJID_MASK; | 609 | op_info->a->arg &= SN_HWPERF_ARG_OBJID_MASK; |
606 | 610 | ||
607 | if (cpu != SN_HWPERF_ARG_ANY_CPU) { | 611 | if (cpu != SN_HWPERF_ARG_ANY_CPU) { |
608 | if (cpu >= num_online_cpus() || !cpu_online(cpu)) { | 612 | if (cpu >= NR_CPUS || !cpu_online(cpu)) { |
609 | r = -EINVAL; | 613 | r = -EINVAL; |
610 | goto out; | 614 | goto out; |
611 | } | 615 | } |
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 107df9fdba4e..edc72a6348a7 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h | |||
@@ -357,6 +357,12 @@ typedef struct drm_freelist { | |||
357 | spinlock_t lock; | 357 | spinlock_t lock; |
358 | } drm_freelist_t; | 358 | } drm_freelist_t; |
359 | 359 | ||
360 | typedef struct drm_dma_handle { | ||
361 | dma_addr_t busaddr; | ||
362 | void *vaddr; | ||
363 | size_t size; | ||
364 | } drm_dma_handle_t; | ||
365 | |||
360 | /** | 366 | /** |
361 | * Buffer entry. There is one of this for each buffer size order. | 367 | * Buffer entry. There is one of this for each buffer size order. |
362 | */ | 368 | */ |
@@ -366,7 +372,7 @@ typedef struct drm_buf_entry { | |||
366 | drm_buf_t *buflist; /**< buffer list */ | 372 | drm_buf_t *buflist; /**< buffer list */ |
367 | int seg_count; | 373 | int seg_count; |
368 | int page_order; | 374 | int page_order; |
369 | unsigned long *seglist; | 375 | drm_dma_handle_t **seglist; |
370 | 376 | ||
371 | drm_freelist_t freelist; | 377 | drm_freelist_t freelist; |
372 | } drm_buf_entry_t; | 378 | } drm_buf_entry_t; |
@@ -483,12 +489,6 @@ typedef struct drm_sigdata { | |||
483 | drm_hw_lock_t *lock; | 489 | drm_hw_lock_t *lock; |
484 | } drm_sigdata_t; | 490 | } drm_sigdata_t; |
485 | 491 | ||
486 | typedef struct drm_dma_handle { | ||
487 | dma_addr_t busaddr; | ||
488 | void *vaddr; | ||
489 | size_t size; | ||
490 | } drm_dma_handle_t; | ||
491 | |||
492 | /** | 492 | /** |
493 | * Mappings list | 493 | * Mappings list |
494 | */ | 494 | */ |
@@ -813,8 +813,6 @@ extern void drm_mem_init(void); | |||
813 | extern int drm_mem_info(char *buf, char **start, off_t offset, | 813 | extern int drm_mem_info(char *buf, char **start, off_t offset, |
814 | int request, int *eof, void *data); | 814 | int request, int *eof, void *data); |
815 | extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area); | 815 | extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area); |
816 | extern unsigned long drm_alloc_pages(int order, int area); | ||
817 | extern void drm_free_pages(unsigned long address, int order, int area); | ||
818 | extern void *drm_ioremap(unsigned long offset, unsigned long size, | 816 | extern void *drm_ioremap(unsigned long offset, unsigned long size, |
819 | drm_device_t * dev); | 817 | drm_device_t * dev); |
820 | extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size, | 818 | extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size, |
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index e2637b4d51de..8a9cf12e6183 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c | |||
@@ -474,8 +474,7 @@ static void drm_cleanup_buf_error(drm_device_t * dev, drm_buf_entry_t * entry) | |||
474 | if (entry->seg_count) { | 474 | if (entry->seg_count) { |
475 | for (i = 0; i < entry->seg_count; i++) { | 475 | for (i = 0; i < entry->seg_count; i++) { |
476 | if (entry->seglist[i]) { | 476 | if (entry->seglist[i]) { |
477 | drm_free_pages(entry->seglist[i], | 477 | drm_pci_free(dev, entry->seglist[i]); |
478 | entry->page_order, DRM_MEM_DMA); | ||
479 | } | 478 | } |
480 | } | 479 | } |
481 | drm_free(entry->seglist, | 480 | drm_free(entry->seglist, |
@@ -678,7 +677,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) | |||
678 | int total; | 677 | int total; |
679 | int page_order; | 678 | int page_order; |
680 | drm_buf_entry_t *entry; | 679 | drm_buf_entry_t *entry; |
681 | unsigned long page; | 680 | drm_dma_handle_t *dmah; |
682 | drm_buf_t *buf; | 681 | drm_buf_t *buf; |
683 | int alignment; | 682 | int alignment; |
684 | unsigned long offset; | 683 | unsigned long offset; |
@@ -781,8 +780,10 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) | |||
781 | page_count = 0; | 780 | page_count = 0; |
782 | 781 | ||
783 | while (entry->buf_count < count) { | 782 | while (entry->buf_count < count) { |
784 | page = drm_alloc_pages(page_order, DRM_MEM_DMA); | 783 | |
785 | if (!page) { | 784 | dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000, 0xfffffffful); |
785 | |||
786 | if (!dmah) { | ||
786 | /* Set count correctly so we free the proper amount. */ | 787 | /* Set count correctly so we free the proper amount. */ |
787 | entry->buf_count = count; | 788 | entry->buf_count = count; |
788 | entry->seg_count = count; | 789 | entry->seg_count = count; |
@@ -794,13 +795,13 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) | |||
794 | atomic_dec(&dev->buf_alloc); | 795 | atomic_dec(&dev->buf_alloc); |
795 | return -ENOMEM; | 796 | return -ENOMEM; |
796 | } | 797 | } |
797 | entry->seglist[entry->seg_count++] = page; | 798 | entry->seglist[entry->seg_count++] = dmah; |
798 | for (i = 0; i < (1 << page_order); i++) { | 799 | for (i = 0; i < (1 << page_order); i++) { |
799 | DRM_DEBUG("page %d @ 0x%08lx\n", | 800 | DRM_DEBUG("page %d @ 0x%08lx\n", |
800 | dma->page_count + page_count, | 801 | dma->page_count + page_count, |
801 | page + PAGE_SIZE * i); | 802 | (unsigned long)dmah->vaddr + PAGE_SIZE * i); |
802 | temp_pagelist[dma->page_count + page_count++] | 803 | temp_pagelist[dma->page_count + page_count++] |
803 | = page + PAGE_SIZE * i; | 804 | = (unsigned long)dmah->vaddr + PAGE_SIZE * i; |
804 | } | 805 | } |
805 | for (offset = 0; | 806 | for (offset = 0; |
806 | offset + size <= total && entry->buf_count < count; | 807 | offset + size <= total && entry->buf_count < count; |
@@ -811,7 +812,8 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) | |||
811 | buf->order = order; | 812 | buf->order = order; |
812 | buf->used = 0; | 813 | buf->used = 0; |
813 | buf->offset = (dma->byte_count + byte_count + offset); | 814 | buf->offset = (dma->byte_count + byte_count + offset); |
814 | buf->address = (void *)(page + offset); | 815 | buf->address = (void *)(dmah->vaddr + offset); |
816 | buf->bus_address = dmah->busaddr + offset; | ||
815 | buf->next = NULL; | 817 | buf->next = NULL; |
816 | buf->waiting = 0; | 818 | buf->waiting = 0; |
817 | buf->pending = 0; | 819 | buf->pending = 0; |
diff --git a/drivers/char/drm/drm_dma.c b/drivers/char/drm/drm_dma.c index 2afab95ca036..892db7096986 100644 --- a/drivers/char/drm/drm_dma.c +++ b/drivers/char/drm/drm_dma.c | |||
@@ -85,9 +85,7 @@ void drm_dma_takedown(drm_device_t * dev) | |||
85 | dma->bufs[i].seg_count); | 85 | dma->bufs[i].seg_count); |
86 | for (j = 0; j < dma->bufs[i].seg_count; j++) { | 86 | for (j = 0; j < dma->bufs[i].seg_count; j++) { |
87 | if (dma->bufs[i].seglist[j]) { | 87 | if (dma->bufs[i].seglist[j]) { |
88 | drm_free_pages(dma->bufs[i].seglist[j], | 88 | drm_pci_free(dev, dma->bufs[i].seglist[j]); |
89 | dma->bufs[i].page_order, | ||
90 | DRM_MEM_DMA); | ||
91 | } | 89 | } |
92 | } | 90 | } |
93 | drm_free(dma->bufs[i].seglist, | 91 | drm_free(dma->bufs[i].seglist, |
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c index 8074771e348f..dddf8de66143 100644 --- a/drivers/char/drm/drm_memory.c +++ b/drivers/char/drm/drm_memory.c | |||
@@ -79,65 +79,6 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area) | |||
79 | return pt; | 79 | return pt; |
80 | } | 80 | } |
81 | 81 | ||
82 | /** | ||
83 | * Allocate pages. | ||
84 | * | ||
85 | * \param order size order. | ||
86 | * \param area memory area. (Not used.) | ||
87 | * \return page address on success, or zero on failure. | ||
88 | * | ||
89 | * Allocate and reserve free pages. | ||
90 | */ | ||
91 | unsigned long drm_alloc_pages(int order, int area) | ||
92 | { | ||
93 | unsigned long address; | ||
94 | unsigned long bytes = PAGE_SIZE << order; | ||
95 | unsigned long addr; | ||
96 | unsigned int sz; | ||
97 | |||
98 | address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order); | ||
99 | if (!address) | ||
100 | return 0; | ||
101 | |||
102 | /* Zero */ | ||
103 | memset((void *)address, 0, bytes); | ||
104 | |||
105 | /* Reserve */ | ||
106 | for (addr = address, sz = bytes; | ||
107 | sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { | ||
108 | SetPageReserved(virt_to_page(addr)); | ||
109 | } | ||
110 | |||
111 | return address; | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * Free pages. | ||
116 | * | ||
117 | * \param address address of the pages to free. | ||
118 | * \param order size order. | ||
119 | * \param area memory area. (Not used.) | ||
120 | * | ||
121 | * Unreserve and free pages allocated by alloc_pages(). | ||
122 | */ | ||
123 | void drm_free_pages(unsigned long address, int order, int area) | ||
124 | { | ||
125 | unsigned long bytes = PAGE_SIZE << order; | ||
126 | unsigned long addr; | ||
127 | unsigned int sz; | ||
128 | |||
129 | if (!address) | ||
130 | return; | ||
131 | |||
132 | /* Unreserve */ | ||
133 | for (addr = address, sz = bytes; | ||
134 | sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { | ||
135 | ClearPageReserved(virt_to_page(addr)); | ||
136 | } | ||
137 | |||
138 | free_pages(address, order); | ||
139 | } | ||
140 | |||
141 | #if __OS_HAS_AGP | 82 | #if __OS_HAS_AGP |
142 | /** Wrapper around agp_allocate_memory() */ | 83 | /** Wrapper around agp_allocate_memory() */ |
143 | DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type) | 84 | DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type) |
diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h index e84605fc54af..7868341817da 100644 --- a/drivers/char/drm/drm_memory_debug.h +++ b/drivers/char/drm/drm_memory_debug.h | |||
@@ -206,76 +206,6 @@ void drm_free (void *pt, size_t size, int area) { | |||
206 | } | 206 | } |
207 | } | 207 | } |
208 | 208 | ||
209 | unsigned long drm_alloc_pages (int order, int area) { | ||
210 | unsigned long address; | ||
211 | unsigned long bytes = PAGE_SIZE << order; | ||
212 | unsigned long addr; | ||
213 | unsigned int sz; | ||
214 | |||
215 | spin_lock(&drm_mem_lock); | ||
216 | if ((drm_ram_used >> PAGE_SHIFT) | ||
217 | > (DRM_RAM_PERCENT * drm_ram_available) / 100) { | ||
218 | spin_unlock(&drm_mem_lock); | ||
219 | return 0; | ||
220 | } | ||
221 | spin_unlock(&drm_mem_lock); | ||
222 | |||
223 | address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order); | ||
224 | if (!address) { | ||
225 | spin_lock(&drm_mem_lock); | ||
226 | ++drm_mem_stats[area].fail_count; | ||
227 | spin_unlock(&drm_mem_lock); | ||
228 | return 0; | ||
229 | } | ||
230 | spin_lock(&drm_mem_lock); | ||
231 | ++drm_mem_stats[area].succeed_count; | ||
232 | drm_mem_stats[area].bytes_allocated += bytes; | ||
233 | drm_ram_used += bytes; | ||
234 | spin_unlock(&drm_mem_lock); | ||
235 | |||
236 | /* Zero outside the lock */ | ||
237 | memset((void *)address, 0, bytes); | ||
238 | |||
239 | /* Reserve */ | ||
240 | for (addr = address, sz = bytes; | ||
241 | sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { | ||
242 | SetPageReserved(virt_to_page(addr)); | ||
243 | } | ||
244 | |||
245 | return address; | ||
246 | } | ||
247 | |||
248 | void drm_free_pages (unsigned long address, int order, int area) { | ||
249 | unsigned long bytes = PAGE_SIZE << order; | ||
250 | int alloc_count; | ||
251 | int free_count; | ||
252 | unsigned long addr; | ||
253 | unsigned int sz; | ||
254 | |||
255 | if (!address) { | ||
256 | DRM_MEM_ERROR(area, "Attempt to free address 0\n"); | ||
257 | } else { | ||
258 | /* Unreserve */ | ||
259 | for (addr = address, sz = bytes; | ||
260 | sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { | ||
261 | ClearPageReserved(virt_to_page(addr)); | ||
262 | } | ||
263 | free_pages(address, order); | ||
264 | } | ||
265 | |||
266 | spin_lock(&drm_mem_lock); | ||
267 | free_count = ++drm_mem_stats[area].free_count; | ||
268 | alloc_count = drm_mem_stats[area].succeed_count; | ||
269 | drm_mem_stats[area].bytes_freed += bytes; | ||
270 | drm_ram_used -= bytes; | ||
271 | spin_unlock(&drm_mem_lock); | ||
272 | if (free_count > alloc_count) { | ||
273 | DRM_MEM_ERROR(area, | ||
274 | "Excess frees: %d frees, %d allocs\n", | ||
275 | free_count, alloc_count); | ||
276 | } | ||
277 | } | ||
278 | |||
279 | void *drm_ioremap (unsigned long offset, unsigned long size, | 209 | void *drm_ioremap (unsigned long offset, unsigned long size, |
280 | drm_device_t * dev) { | 210 | drm_device_t * dev) { |
281 | void *pt; | 211 | void *pt; |
diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c index 1fd7ff164817..b28ca9cea8a2 100644 --- a/drivers/char/drm/drm_pci.c +++ b/drivers/char/drm/drm_pci.c | |||
@@ -50,6 +50,10 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, | |||
50 | dma_addr_t maxaddr) | 50 | dma_addr_t maxaddr) |
51 | { | 51 | { |
52 | drm_dma_handle_t *dmah; | 52 | drm_dma_handle_t *dmah; |
53 | #if 1 | ||
54 | unsigned long addr; | ||
55 | size_t sz; | ||
56 | #endif | ||
53 | #ifdef DRM_DEBUG_MEMORY | 57 | #ifdef DRM_DEBUG_MEMORY |
54 | int area = DRM_MEM_DMA; | 58 | int area = DRM_MEM_DMA; |
55 | 59 | ||
@@ -79,7 +83,7 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, | |||
79 | return NULL; | 83 | return NULL; |
80 | 84 | ||
81 | dmah->size = size; | 85 | dmah->size = size; |
82 | dmah->vaddr = pci_alloc_consistent(dev->pdev, size, &dmah->busaddr); | 86 | dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size, &dmah->busaddr, GFP_KERNEL | __GFP_COMP); |
83 | 87 | ||
84 | #ifdef DRM_DEBUG_MEMORY | 88 | #ifdef DRM_DEBUG_MEMORY |
85 | if (dmah->vaddr == NULL) { | 89 | if (dmah->vaddr == NULL) { |
@@ -104,18 +108,29 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, | |||
104 | 108 | ||
105 | memset(dmah->vaddr, 0, size); | 109 | memset(dmah->vaddr, 0, size); |
106 | 110 | ||
111 | /* XXX - Is virt_to_page() legal for consistent mem? */ | ||
112 | /* Reserve */ | ||
113 | for (addr = (unsigned long)dmah->vaddr, sz = size; | ||
114 | sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { | ||
115 | SetPageReserved(virt_to_page(addr)); | ||
116 | } | ||
117 | |||
107 | return dmah; | 118 | return dmah; |
108 | } | 119 | } |
109 | 120 | ||
110 | EXPORT_SYMBOL(drm_pci_alloc); | 121 | EXPORT_SYMBOL(drm_pci_alloc); |
111 | 122 | ||
112 | /** | 123 | /** |
113 | * \brief Free a PCI consistent memory block with freeing its descriptor. | 124 | * \brief Free a PCI consistent memory block without freeing its descriptor. |
114 | * | 125 | * |
115 | * This function is for internal use in the Linux-specific DRM core code. | 126 | * This function is for internal use in the Linux-specific DRM core code. |
116 | */ | 127 | */ |
117 | void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah) | 128 | void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah) |
118 | { | 129 | { |
130 | #if 1 | ||
131 | unsigned long addr; | ||
132 | size_t sz; | ||
133 | #endif | ||
119 | #ifdef DRM_DEBUG_MEMORY | 134 | #ifdef DRM_DEBUG_MEMORY |
120 | int area = DRM_MEM_DMA; | 135 | int area = DRM_MEM_DMA; |
121 | int alloc_count; | 136 | int alloc_count; |
@@ -127,8 +142,14 @@ void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah) | |||
127 | DRM_MEM_ERROR(area, "Attempt to free address 0\n"); | 142 | DRM_MEM_ERROR(area, "Attempt to free address 0\n"); |
128 | #endif | 143 | #endif |
129 | } else { | 144 | } else { |
130 | pci_free_consistent(dev->pdev, dmah->size, dmah->vaddr, | 145 | /* XXX - Is virt_to_page() legal for consistent mem? */ |
131 | dmah->busaddr); | 146 | /* Unreserve */ |
147 | for (addr = (unsigned long)dmah->vaddr, sz = dmah->size; | ||
148 | sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { | ||
149 | ClearPageReserved(virt_to_page(addr)); | ||
150 | } | ||
151 | dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr, | ||
152 | dmah->busaddr); | ||
132 | } | 153 | } |
133 | 154 | ||
134 | #ifdef DRM_DEBUG_MEMORY | 155 | #ifdef DRM_DEBUG_MEMORY |
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index 2c17e88a8847..b1bb3c7b568d 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h | |||
@@ -3,49 +3,69 @@ | |||
3 | Please contact dri-devel@lists.sf.net to add new cards to this list | 3 | Please contact dri-devel@lists.sf.net to add new cards to this list |
4 | */ | 4 | */ |
5 | #define radeon_PCI_IDS \ | 5 | #define radeon_PCI_IDS \ |
6 | {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350},\ | 6 | {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ |
7 | {0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | ||
8 | {0x1002, 0x3154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | ||
9 | {0x1002, 0x3E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ | ||
10 | {0x1002, 0x3E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ | ||
7 | {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP}, \ | 11 | {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP}, \ |
8 | {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ | 12 | {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ |
9 | {0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ | 13 | {0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ |
10 | {0x1002, 0x4145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ | 14 | {0x1002, 0x4145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ |
11 | {0x1002, 0x4146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ | 15 | {0x1002, 0x4146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ |
12 | {0x1002, 0x4147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ | 16 | {0x1002, 0x4147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ |
17 | {0x1002, 0x4148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ | ||
18 | {0x1002, 0x4149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ | ||
19 | {0x1002, 0x414A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ | ||
20 | {0x1002, 0x414B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ | ||
13 | {0x1002, 0x4150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ | 21 | {0x1002, 0x4150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ |
14 | {0x1002, 0x4151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ | 22 | {0x1002, 0x4151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ |
15 | {0x1002, 0x4152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ | 23 | {0x1002, 0x4152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ |
16 | {0x1002, 0x4153, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ | 24 | {0x1002, 0x4153, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ |
17 | {0x1002, 0x4154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ | 25 | {0x1002, 0x4154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ |
26 | {0x1002, 0x4155, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ | ||
18 | {0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ | 27 | {0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ |
19 | {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS250|CHIP_IS_IGP}, \ | 28 | {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ |
20 | {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | 29 | {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ |
21 | {0x1002, 0x4243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | 30 | {0x1002, 0x4243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ |
22 | {0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ | 31 | {0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ |
23 | {0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ | 32 | {0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ |
24 | {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS250|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ | 33 | {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ |
25 | {0x1002, 0x4964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \ | 34 | {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \ |
26 | {0x1002, 0x4965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \ | 35 | {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \ |
27 | {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \ | 36 | {0x1002, 0x4A48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ |
28 | {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \ | 37 | {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ |
29 | {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \ | 38 | {0x1002, 0x4A4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ |
30 | {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \ | 39 | {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ |
40 | {0x1002, 0x4A4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
41 | {0x1002, 0x4A4D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
42 | {0x1002, 0x4A4E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | ||
43 | {0x1002, 0x4A4F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
44 | {0x1002, 0x4A50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
45 | {0x1002, 0x4A54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
46 | {0x1002, 0x4B49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
47 | {0x1002, 0x4B4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
48 | {0x1002, 0x4B4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
49 | {0x1002, 0x4B4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
31 | {0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \ | 50 | {0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \ |
32 | {0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \ | 51 | {0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \ |
33 | {0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \ | 52 | {0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \ |
34 | {0x1002, 0x4C5A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \ | 53 | {0x1002, 0x4C5A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \ |
35 | {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \ | 54 | {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ |
36 | {0x1002, 0x4C65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \ | 55 | {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ |
37 | {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \ | 56 | {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ |
38 | {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \ | ||
39 | {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ | 57 | {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ |
40 | {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ | 58 | {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ |
41 | {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ | 59 | {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ |
42 | {0x1002, 0x4E47, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ | 60 | {0x1002, 0x4E47, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ |
43 | {0x1002, 0x4E48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ | 61 | {0x1002, 0x4E48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ |
44 | {0x1002, 0x4E49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ | 62 | {0x1002, 0x4E49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ |
45 | {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ | 63 | {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ |
46 | {0x1002, 0x4E4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ | 64 | {0x1002, 0x4E4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ |
47 | {0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ | 65 | {0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ |
48 | {0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ | 66 | {0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ |
67 | {0x1002, 0x4E52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ | ||
68 | {0x1002, 0x4E53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ | ||
49 | {0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ | 69 | {0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ |
50 | {0x1002, 0x4E56, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ | 70 | {0x1002, 0x4E56, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ |
51 | {0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ | 71 | {0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ |
@@ -53,44 +73,66 @@ | |||
53 | {0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ | 73 | {0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ |
54 | {0x1002, 0x5147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ | 74 | {0x1002, 0x5147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ |
55 | {0x1002, 0x5148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | 75 | {0x1002, 0x5148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ |
56 | {0x1002, 0x5149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | ||
57 | {0x1002, 0x514A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | ||
58 | {0x1002, 0x514B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | ||
59 | {0x1002, 0x514C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | 76 | {0x1002, 0x514C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ |
60 | {0x1002, 0x514D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | 77 | {0x1002, 0x514D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ |
61 | {0x1002, 0x514E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | ||
62 | {0x1002, 0x514F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | ||
63 | {0x1002, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \ | 78 | {0x1002, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \ |
64 | {0x1002, 0x5158, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \ | 79 | {0x1002, 0x5158, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \ |
65 | {0x1002, 0x5159, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ | 80 | {0x1002, 0x5159, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ |
66 | {0x1002, 0x515A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ | 81 | {0x1002, 0x515A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ |
67 | {0x1002, 0x515E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ | 82 | {0x1002, 0x515E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ |
68 | {0x1002, 0x5168, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | 83 | {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ |
69 | {0x1002, 0x5169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | 84 | {0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ |
70 | {0x1002, 0x516A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | 85 | {0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ |
71 | {0x1002, 0x516B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | 86 | {0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ |
72 | {0x1002, 0x516C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | 87 | {0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ |
73 | {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ | 88 | {0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ |
74 | {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ | 89 | {0x1002, 0x554B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ |
90 | {0x1002, 0x554C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
91 | {0x1002, 0x554D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
92 | {0x1002, 0x554E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
93 | {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
94 | {0x1002, 0x5550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
95 | {0x1002, 0x5551, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
96 | {0x1002, 0x5552, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
97 | {0x1002, 0x5554, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
98 | {0x1002, 0x564A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | ||
99 | {0x1002, 0x564B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | ||
100 | {0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | ||
101 | {0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | ||
102 | {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | ||
75 | {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \ | 103 | {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \ |
76 | {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ | 104 | {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ |
77 | {0x1002, 0x5836, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \ | ||
78 | {0x1002, 0x5837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \ | ||
79 | {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 105 | {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ |
80 | {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 106 | {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ |
81 | {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 107 | {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ |
82 | {0x1002, 0x5963, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | ||
83 | {0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 108 | {0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ |
84 | {0x1002, 0x5968, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 109 | {0x1002, 0x5965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ |
85 | {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ | 110 | {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ |
86 | {0x1002, 0x596A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 111 | {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ |
87 | {0x1002, 0x596B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 112 | {0x1002, 0x5b62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ |
113 | {0x1002, 0x5b63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ | ||
114 | {0x1002, 0x5b64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ | ||
115 | {0x1002, 0x5b65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ | ||
88 | {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ | 116 | {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ |
89 | {0x1002, 0x5c62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | ||
90 | {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ | 117 | {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ |
91 | {0x1002, 0x5c64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 118 | {0x1002, 0x5d48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ |
92 | {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ | 119 | {0x1002, 0x5d49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ |
93 | {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \ | 120 | {0x1002, 0x5d4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ |
121 | {0x1002, 0x5d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
122 | {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
123 | {0x1002, 0x5d4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
124 | {0x1002, 0x5d4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
125 | {0x1002, 0x5d50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
126 | {0x1002, 0x5d52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
127 | {0x1002, 0x5d57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | ||
128 | {0x1002, 0x5e48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ | ||
129 | {0x1002, 0x5e4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ | ||
130 | {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ | ||
131 | {0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ | ||
132 | {0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ | ||
133 | {0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ | ||
134 | {0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_NEW_MEMMAP}, \ | ||
135 | {0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | ||
94 | {0, 0, 0} | 136 | {0, 0, 0} |
95 | 137 | ||
96 | #define r128_PCI_IDS \ | 138 | #define r128_PCI_IDS \ |
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index 1ff4c7ca0bff..9f4b8ce4c05e 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c | |||
@@ -495,8 +495,6 @@ static int i915_dispatch_batchbuffer(drm_device_t * dev, | |||
495 | } | 495 | } |
496 | } | 496 | } |
497 | 497 | ||
498 | dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; | ||
499 | |||
500 | i915_emit_breadcrumb(dev); | 498 | i915_emit_breadcrumb(dev); |
501 | 499 | ||
502 | return 0; | 500 | return 0; |
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c index d3879ac9970f..a752afd86ab8 100644 --- a/drivers/char/drm/i915_irq.c +++ b/drivers/char/drm/i915_irq.c | |||
@@ -53,6 +53,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
53 | 53 | ||
54 | I915_WRITE16(I915REG_INT_IDENTITY_R, temp); | 54 | I915_WRITE16(I915REG_INT_IDENTITY_R, temp); |
55 | 55 | ||
56 | dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); | ||
57 | |||
56 | if (temp & USER_INT_FLAG) | 58 | if (temp & USER_INT_FLAG) |
57 | DRM_WAKEUP(&dev_priv->irq_queue); | 59 | DRM_WAKEUP(&dev_priv->irq_queue); |
58 | 60 | ||
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index c08fa5076f05..b108c7f913b2 100644 --- a/drivers/char/drm/r300_cmdbuf.c +++ b/drivers/char/drm/r300_cmdbuf.c | |||
@@ -214,13 +214,13 @@ void r300_init_reg_flags(void) | |||
214 | ADD_RANGE(0x4F54, 1); | 214 | ADD_RANGE(0x4F54, 1); |
215 | 215 | ||
216 | ADD_RANGE(R300_TX_FILTER_0, 16); | 216 | ADD_RANGE(R300_TX_FILTER_0, 16); |
217 | ADD_RANGE(R300_TX_UNK1_0, 16); | 217 | ADD_RANGE(R300_TX_FILTER1_0, 16); |
218 | ADD_RANGE(R300_TX_SIZE_0, 16); | 218 | ADD_RANGE(R300_TX_SIZE_0, 16); |
219 | ADD_RANGE(R300_TX_FORMAT_0, 16); | 219 | ADD_RANGE(R300_TX_FORMAT_0, 16); |
220 | ADD_RANGE(R300_TX_PITCH_0, 16); | 220 | ADD_RANGE(R300_TX_PITCH_0, 16); |
221 | /* Texture offset is dangerous and needs more checking */ | 221 | /* Texture offset is dangerous and needs more checking */ |
222 | ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET); | 222 | ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET); |
223 | ADD_RANGE(R300_TX_UNK4_0, 16); | 223 | ADD_RANGE(R300_TX_CHROMA_KEY_0, 16); |
224 | ADD_RANGE(R300_TX_BORDER_COLOR_0, 16); | 224 | ADD_RANGE(R300_TX_BORDER_COLOR_0, 16); |
225 | 225 | ||
226 | /* Sporadic registers used as primitives are emitted */ | 226 | /* Sporadic registers used as primitives are emitted */ |
@@ -242,8 +242,10 @@ static __inline__ int r300_check_range(unsigned reg, int count) | |||
242 | return 0; | 242 | return 0; |
243 | } | 243 | } |
244 | 244 | ||
245 | /* we expect offsets passed to the framebuffer to be either within video memory or | 245 | /* |
246 | within AGP space */ | 246 | * we expect offsets passed to the framebuffer to be either within video |
247 | * memory or within AGP space | ||
248 | */ | ||
247 | static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv, | 249 | static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv, |
248 | u32 offset) | 250 | u32 offset) |
249 | { | 251 | { |
@@ -251,11 +253,11 @@ static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv, | |||
251 | but this value is not being kept. | 253 | but this value is not being kept. |
252 | This code is correct for now (does the same thing as the | 254 | This code is correct for now (does the same thing as the |
253 | code that sets MC_FB_LOCATION) in radeon_cp.c */ | 255 | code that sets MC_FB_LOCATION) in radeon_cp.c */ |
254 | if ((offset >= dev_priv->fb_location) && | 256 | if (offset >= dev_priv->fb_location && |
255 | (offset < dev_priv->gart_vm_start)) | 257 | offset < (dev_priv->fb_location + dev_priv->fb_size)) |
256 | return 0; | 258 | return 0; |
257 | if ((offset >= dev_priv->gart_vm_start) && | 259 | if (offset >= dev_priv->gart_vm_start && |
258 | (offset < dev_priv->gart_vm_start + dev_priv->gart_size)) | 260 | offset < (dev_priv->gart_vm_start + dev_priv->gart_size)) |
259 | return 0; | 261 | return 0; |
260 | return 1; | 262 | return 1; |
261 | } | 263 | } |
@@ -490,6 +492,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv, | |||
490 | 492 | ||
491 | return 0; | 493 | return 0; |
492 | } | 494 | } |
495 | |||
493 | static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, | 496 | static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, |
494 | drm_radeon_kcmd_buffer_t *cmdbuf) | 497 | drm_radeon_kcmd_buffer_t *cmdbuf) |
495 | { | 498 | { |
@@ -701,6 +704,64 @@ static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf) | |||
701 | buf->used = 0; | 704 | buf->used = 0; |
702 | } | 705 | } |
703 | 706 | ||
707 | static int r300_scratch(drm_radeon_private_t *dev_priv, | ||
708 | drm_radeon_kcmd_buffer_t *cmdbuf, | ||
709 | drm_r300_cmd_header_t header) | ||
710 | { | ||
711 | u32 *ref_age_base; | ||
712 | u32 i, buf_idx, h_pending; | ||
713 | RING_LOCALS; | ||
714 | |||
715 | if (cmdbuf->bufsz < | ||
716 | (sizeof(u64) + header.scratch.n_bufs * sizeof(buf_idx))) { | ||
717 | return DRM_ERR(EINVAL); | ||
718 | } | ||
719 | |||
720 | if (header.scratch.reg >= 5) { | ||
721 | return DRM_ERR(EINVAL); | ||
722 | } | ||
723 | |||
724 | dev_priv->scratch_ages[header.scratch.reg]++; | ||
725 | |||
726 | ref_age_base = *(u32 **)cmdbuf->buf; | ||
727 | |||
728 | cmdbuf->buf += sizeof(u64); | ||
729 | cmdbuf->bufsz -= sizeof(u64); | ||
730 | |||
731 | for (i=0; i < header.scratch.n_bufs; i++) { | ||
732 | buf_idx = *(u32 *)cmdbuf->buf; | ||
733 | buf_idx *= 2; /* 8 bytes per buf */ | ||
734 | |||
735 | if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) { | ||
736 | return DRM_ERR(EINVAL); | ||
737 | } | ||
738 | |||
739 | if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) { | ||
740 | return DRM_ERR(EINVAL); | ||
741 | } | ||
742 | |||
743 | if (h_pending == 0) { | ||
744 | return DRM_ERR(EINVAL); | ||
745 | } | ||
746 | |||
747 | h_pending--; | ||
748 | |||
749 | if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) { | ||
750 | return DRM_ERR(EINVAL); | ||
751 | } | ||
752 | |||
753 | cmdbuf->buf += sizeof(buf_idx); | ||
754 | cmdbuf->bufsz -= sizeof(buf_idx); | ||
755 | } | ||
756 | |||
757 | BEGIN_RING(2); | ||
758 | OUT_RING(CP_PACKET0(RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0)); | ||
759 | OUT_RING(dev_priv->scratch_ages[header.scratch.reg]); | ||
760 | ADVANCE_RING(); | ||
761 | |||
762 | return 0; | ||
763 | } | ||
764 | |||
704 | /** | 765 | /** |
705 | * Parses and validates a user-supplied command buffer and emits appropriate | 766 | * Parses and validates a user-supplied command buffer and emits appropriate |
706 | * commands on the DMA ring buffer. | 767 | * commands on the DMA ring buffer. |
@@ -838,6 +899,15 @@ int r300_do_cp_cmdbuf(drm_device_t *dev, | |||
838 | } | 899 | } |
839 | break; | 900 | break; |
840 | 901 | ||
902 | case R300_CMD_SCRATCH: | ||
903 | DRM_DEBUG("R300_CMD_SCRATCH\n"); | ||
904 | ret = r300_scratch(dev_priv, cmdbuf, header); | ||
905 | if (ret) { | ||
906 | DRM_ERROR("r300_scratch failed\n"); | ||
907 | goto cleanup; | ||
908 | } | ||
909 | break; | ||
910 | |||
841 | default: | 911 | default: |
842 | DRM_ERROR("bad cmd_type %i at %p\n", | 912 | DRM_ERROR("bad cmd_type %i at %p\n", |
843 | header.header.cmd_type, | 913 | header.header.cmd_type, |
diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h index d1e19954406b..a881f96c983e 100644 --- a/drivers/char/drm/r300_reg.h +++ b/drivers/char/drm/r300_reg.h | |||
@@ -711,8 +711,22 @@ I am fairly certain that they are correct unless stated otherwise in comments. | |||
711 | # define R300_TX_MAX_ANISO_16_TO_1 (8 << 21) | 711 | # define R300_TX_MAX_ANISO_16_TO_1 (8 << 21) |
712 | # define R300_TX_MAX_ANISO_MASK (14 << 21) | 712 | # define R300_TX_MAX_ANISO_MASK (14 << 21) |
713 | 713 | ||
714 | #define R300_TX_UNK1_0 0x4440 | 714 | #define R300_TX_FILTER1_0 0x4440 |
715 | # define R300_CHROMA_KEY_MODE_DISABLE 0 | ||
716 | # define R300_CHROMA_KEY_FORCE 1 | ||
717 | # define R300_CHROMA_KEY_BLEND 2 | ||
718 | # define R300_MC_ROUND_NORMAL (0<<2) | ||
719 | # define R300_MC_ROUND_MPEG4 (1<<2) | ||
715 | # define R300_LOD_BIAS_MASK 0x1fff | 720 | # define R300_LOD_BIAS_MASK 0x1fff |
721 | # define R300_EDGE_ANISO_EDGE_DIAG (0<<13) | ||
722 | # define R300_EDGE_ANISO_EDGE_ONLY (1<<13) | ||
723 | # define R300_MC_COORD_TRUNCATE_DISABLE (0<<14) | ||
724 | # define R300_MC_COORD_TRUNCATE_MPEG (1<<14) | ||
725 | # define R300_TX_TRI_PERF_0_8 (0<<15) | ||
726 | # define R300_TX_TRI_PERF_1_8 (1<<15) | ||
727 | # define R300_TX_TRI_PERF_1_4 (2<<15) | ||
728 | # define R300_TX_TRI_PERF_3_8 (3<<15) | ||
729 | # define R300_ANISO_THRESHOLD_MASK (7<<17) | ||
716 | 730 | ||
717 | #define R300_TX_SIZE_0 0x4480 | 731 | #define R300_TX_SIZE_0 0x4480 |
718 | # define R300_TX_WIDTHMASK_SHIFT 0 | 732 | # define R300_TX_WIDTHMASK_SHIFT 0 |
@@ -722,6 +736,8 @@ I am fairly certain that they are correct unless stated otherwise in comments. | |||
722 | # define R300_TX_UNK23 (1 << 23) | 736 | # define R300_TX_UNK23 (1 << 23) |
723 | # define R300_TX_SIZE_SHIFT 26 /* largest of width, height */ | 737 | # define R300_TX_SIZE_SHIFT 26 /* largest of width, height */ |
724 | # define R300_TX_SIZE_MASK (15 << 26) | 738 | # define R300_TX_SIZE_MASK (15 << 26) |
739 | # define R300_TX_SIZE_PROJECTED (1<<30) | ||
740 | # define R300_TX_SIZE_TXPITCH_EN (1<<31) | ||
725 | #define R300_TX_FORMAT_0 0x44C0 | 741 | #define R300_TX_FORMAT_0 0x44C0 |
726 | /* The interpretation of the format word by Wladimir van der Laan */ | 742 | /* The interpretation of the format word by Wladimir van der Laan */ |
727 | /* The X, Y, Z and W refer to the layout of the components. | 743 | /* The X, Y, Z and W refer to the layout of the components. |
@@ -750,7 +766,8 @@ I am fairly certain that they are correct unless stated otherwise in comments. | |||
750 | # define R300_TX_FORMAT_B8G8_B8G8 0x14 /* no swizzle */ | 766 | # define R300_TX_FORMAT_B8G8_B8G8 0x14 /* no swizzle */ |
751 | # define R300_TX_FORMAT_G8R8_G8B8 0x15 /* no swizzle */ | 767 | # define R300_TX_FORMAT_G8R8_G8B8 0x15 /* no swizzle */ |
752 | /* 0x16 - some 16 bit green format.. ?? */ | 768 | /* 0x16 - some 16 bit green format.. ?? */ |
753 | # define R300_TX_FORMAT_UNK25 (1 << 25) /* no swizzle */ | 769 | # define R300_TX_FORMAT_UNK25 (1 << 25) /* no swizzle */ |
770 | # define R300_TX_FORMAT_CUBIC_MAP (1 << 26) | ||
754 | 771 | ||
755 | /* gap */ | 772 | /* gap */ |
756 | /* Floating point formats */ | 773 | /* Floating point formats */ |
@@ -800,18 +817,20 @@ I am fairly certain that they are correct unless stated otherwise in comments. | |||
800 | 817 | ||
801 | # define R300_TX_FORMAT_YUV_MODE 0x00800000 | 818 | # define R300_TX_FORMAT_YUV_MODE 0x00800000 |
802 | 819 | ||
803 | #define R300_TX_PITCH_0 0x4500 | 820 | #define R300_TX_PITCH_0 0x4500 /* obvious missing in gap */ |
804 | #define R300_TX_OFFSET_0 0x4540 | 821 | #define R300_TX_OFFSET_0 0x4540 |
805 | /* BEGIN: Guess from R200 */ | 822 | /* BEGIN: Guess from R200 */ |
806 | # define R300_TXO_ENDIAN_NO_SWAP (0 << 0) | 823 | # define R300_TXO_ENDIAN_NO_SWAP (0 << 0) |
807 | # define R300_TXO_ENDIAN_BYTE_SWAP (1 << 0) | 824 | # define R300_TXO_ENDIAN_BYTE_SWAP (1 << 0) |
808 | # define R300_TXO_ENDIAN_WORD_SWAP (2 << 0) | 825 | # define R300_TXO_ENDIAN_WORD_SWAP (2 << 0) |
809 | # define R300_TXO_ENDIAN_HALFDW_SWAP (3 << 0) | 826 | # define R300_TXO_ENDIAN_HALFDW_SWAP (3 << 0) |
827 | # define R300_TXO_MACRO_TILE (1 << 2) | ||
828 | # define R300_TXO_MICRO_TILE (1 << 3) | ||
810 | # define R300_TXO_OFFSET_MASK 0xffffffe0 | 829 | # define R300_TXO_OFFSET_MASK 0xffffffe0 |
811 | # define R300_TXO_OFFSET_SHIFT 5 | 830 | # define R300_TXO_OFFSET_SHIFT 5 |
812 | /* END */ | 831 | /* END */ |
813 | #define R300_TX_UNK4_0 0x4580 | 832 | #define R300_TX_CHROMA_KEY_0 0x4580 /* 32 bit chroma key */ |
814 | #define R300_TX_BORDER_COLOR_0 0x45C0 //ff00ff00 == { 0, 1.0, 0, 1.0 } | 833 | #define R300_TX_BORDER_COLOR_0 0x45C0 //ff00ff00 == { 0, 1.0, 0, 1.0 } |
815 | 834 | ||
816 | /* END */ | 835 | /* END */ |
817 | 836 | ||
@@ -868,7 +887,9 @@ I am fairly certain that they are correct unless stated otherwise in comments. | |||
868 | # define R300_PFS_NODE_TEX_OFFSET_MASK (31 << 12) | 887 | # define R300_PFS_NODE_TEX_OFFSET_MASK (31 << 12) |
869 | # define R300_PFS_NODE_TEX_END_SHIFT 17 | 888 | # define R300_PFS_NODE_TEX_END_SHIFT 17 |
870 | # define R300_PFS_NODE_TEX_END_MASK (31 << 17) | 889 | # define R300_PFS_NODE_TEX_END_MASK (31 << 17) |
871 | # define R300_PFS_NODE_LAST_NODE (1 << 22) | 890 | /*# define R300_PFS_NODE_LAST_NODE (1 << 22) */ |
891 | # define R300_PFS_NODE_OUTPUT_COLOR (1 << 22) | ||
892 | # define R300_PFS_NODE_OUTPUT_DEPTH (1 << 23) | ||
872 | 893 | ||
873 | /* TEX | 894 | /* TEX |
874 | // As far as I can tell, texture instructions cannot write into output | 895 | // As far as I can tell, texture instructions cannot write into output |
@@ -887,6 +908,7 @@ I am fairly certain that they are correct unless stated otherwise in comments. | |||
887 | */ | 908 | */ |
888 | # define R300_FPITX_OPCODE_SHIFT 15 | 909 | # define R300_FPITX_OPCODE_SHIFT 15 |
889 | # define R300_FPITX_OP_TEX 1 | 910 | # define R300_FPITX_OP_TEX 1 |
911 | # define R300_FPITX_OP_KIL 2 | ||
890 | # define R300_FPITX_OP_TXP 3 | 912 | # define R300_FPITX_OP_TXP 3 |
891 | # define R300_FPITX_OP_TXB 4 | 913 | # define R300_FPITX_OP_TXB 4 |
892 | 914 | ||
@@ -962,9 +984,11 @@ I am fairly certain that they are correct unless stated otherwise in comments. | |||
962 | # define R300_FPI1_SRC2C_CONST (1 << 17) | 984 | # define R300_FPI1_SRC2C_CONST (1 << 17) |
963 | # define R300_FPI1_DSTC_SHIFT 18 | 985 | # define R300_FPI1_DSTC_SHIFT 18 |
964 | # define R300_FPI1_DSTC_MASK (31 << 18) | 986 | # define R300_FPI1_DSTC_MASK (31 << 18) |
987 | # define R300_FPI1_DSTC_REG_MASK_SHIFT 23 | ||
965 | # define R300_FPI1_DSTC_REG_X (1 << 23) | 988 | # define R300_FPI1_DSTC_REG_X (1 << 23) |
966 | # define R300_FPI1_DSTC_REG_Y (1 << 24) | 989 | # define R300_FPI1_DSTC_REG_Y (1 << 24) |
967 | # define R300_FPI1_DSTC_REG_Z (1 << 25) | 990 | # define R300_FPI1_DSTC_REG_Z (1 << 25) |
991 | # define R300_FPI1_DSTC_OUTPUT_MASK_SHIFT 26 | ||
968 | # define R300_FPI1_DSTC_OUTPUT_X (1 << 26) | 992 | # define R300_FPI1_DSTC_OUTPUT_X (1 << 26) |
969 | # define R300_FPI1_DSTC_OUTPUT_Y (1 << 27) | 993 | # define R300_FPI1_DSTC_OUTPUT_Y (1 << 27) |
970 | # define R300_FPI1_DSTC_OUTPUT_Z (1 << 28) | 994 | # define R300_FPI1_DSTC_OUTPUT_Z (1 << 28) |
@@ -983,6 +1007,7 @@ I am fairly certain that they are correct unless stated otherwise in comments. | |||
983 | # define R300_FPI3_DSTA_MASK (31 << 18) | 1007 | # define R300_FPI3_DSTA_MASK (31 << 18) |
984 | # define R300_FPI3_DSTA_REG (1 << 23) | 1008 | # define R300_FPI3_DSTA_REG (1 << 23) |
985 | # define R300_FPI3_DSTA_OUTPUT (1 << 24) | 1009 | # define R300_FPI3_DSTA_OUTPUT (1 << 24) |
1010 | # define R300_FPI3_DSTA_DEPTH (1 << 27) | ||
986 | 1011 | ||
987 | #define R300_PFS_INSTR0_0 0x48C0 | 1012 | #define R300_PFS_INSTR0_0 0x48C0 |
988 | # define R300_FPI0_ARGC_SRC0C_XYZ 0 | 1013 | # define R300_FPI0_ARGC_SRC0C_XYZ 0 |
@@ -1036,7 +1061,7 @@ I am fairly certain that they are correct unless stated otherwise in comments. | |||
1036 | # define R300_FPI0_OUTC_FRC (9 << 23) | 1061 | # define R300_FPI0_OUTC_FRC (9 << 23) |
1037 | # define R300_FPI0_OUTC_REPL_ALPHA (10 << 23) | 1062 | # define R300_FPI0_OUTC_REPL_ALPHA (10 << 23) |
1038 | # define R300_FPI0_OUTC_SAT (1 << 30) | 1063 | # define R300_FPI0_OUTC_SAT (1 << 30) |
1039 | # define R300_FPI0_UNKNOWN_31 (1 << 31) | 1064 | # define R300_FPI0_INSERT_NOP (1 << 31) |
1040 | 1065 | ||
1041 | #define R300_PFS_INSTR2_0 0x49C0 | 1066 | #define R300_PFS_INSTR2_0 0x49C0 |
1042 | # define R300_FPI2_ARGA_SRC0C_X 0 | 1067 | # define R300_FPI2_ARGA_SRC0C_X 0 |
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index 9bb8ae0c1c27..7f949c9c9691 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c | |||
@@ -1118,14 +1118,20 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, | |||
1118 | { | 1118 | { |
1119 | u32 ring_start, cur_read_ptr; | 1119 | u32 ring_start, cur_read_ptr; |
1120 | u32 tmp; | 1120 | u32 tmp; |
1121 | 1121 | ||
1122 | /* Initialize the memory controller */ | 1122 | /* Initialize the memory controller. With new memory map, the fb location |
1123 | RADEON_WRITE(RADEON_MC_FB_LOCATION, | 1123 | * is not changed, it should have been properly initialized already. Part |
1124 | ((dev_priv->gart_vm_start - 1) & 0xffff0000) | 1124 | * of the problem is that the code below is bogus, assuming the GART is |
1125 | | (dev_priv->fb_location >> 16)); | 1125 | * always appended to the fb which is not necessarily the case |
1126 | */ | ||
1127 | if (!dev_priv->new_memmap) | ||
1128 | RADEON_WRITE(RADEON_MC_FB_LOCATION, | ||
1129 | ((dev_priv->gart_vm_start - 1) & 0xffff0000) | ||
1130 | | (dev_priv->fb_location >> 16)); | ||
1126 | 1131 | ||
1127 | #if __OS_HAS_AGP | 1132 | #if __OS_HAS_AGP |
1128 | if (dev_priv->flags & CHIP_IS_AGP) { | 1133 | if (dev_priv->flags & CHIP_IS_AGP) { |
1134 | RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base); | ||
1129 | RADEON_WRITE(RADEON_MC_AGP_LOCATION, | 1135 | RADEON_WRITE(RADEON_MC_AGP_LOCATION, |
1130 | (((dev_priv->gart_vm_start - 1 + | 1136 | (((dev_priv->gart_vm_start - 1 + |
1131 | dev_priv->gart_size) & 0xffff0000) | | 1137 | dev_priv->gart_size) & 0xffff0000) | |
@@ -1153,8 +1159,6 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, | |||
1153 | 1159 | ||
1154 | #if __OS_HAS_AGP | 1160 | #if __OS_HAS_AGP |
1155 | if (dev_priv->flags & CHIP_IS_AGP) { | 1161 | if (dev_priv->flags & CHIP_IS_AGP) { |
1156 | /* set RADEON_AGP_BASE here instead of relying on X from user space */ | ||
1157 | RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base); | ||
1158 | RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, | 1162 | RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, |
1159 | dev_priv->ring_rptr->offset | 1163 | dev_priv->ring_rptr->offset |
1160 | - dev->agp->base + dev_priv->gart_vm_start); | 1164 | - dev->agp->base + dev_priv->gart_vm_start); |
@@ -1174,6 +1178,17 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, | |||
1174 | entry->handle + tmp_ofs); | 1178 | entry->handle + tmp_ofs); |
1175 | } | 1179 | } |
1176 | 1180 | ||
1181 | /* Set ring buffer size */ | ||
1182 | #ifdef __BIG_ENDIAN | ||
1183 | RADEON_WRITE(RADEON_CP_RB_CNTL, | ||
1184 | dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT); | ||
1185 | #else | ||
1186 | RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw); | ||
1187 | #endif | ||
1188 | |||
1189 | /* Start with assuming that writeback doesn't work */ | ||
1190 | dev_priv->writeback_works = 0; | ||
1191 | |||
1177 | /* Initialize the scratch register pointer. This will cause | 1192 | /* Initialize the scratch register pointer. This will cause |
1178 | * the scratch register values to be written out to memory | 1193 | * the scratch register values to be written out to memory |
1179 | * whenever they are updated. | 1194 | * whenever they are updated. |
@@ -1190,28 +1205,9 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, | |||
1190 | 1205 | ||
1191 | RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7); | 1206 | RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7); |
1192 | 1207 | ||
1193 | /* Writeback doesn't seem to work everywhere, test it first */ | 1208 | /* Turn on bus mastering */ |
1194 | DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0); | 1209 | tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; |
1195 | RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef); | 1210 | RADEON_WRITE(RADEON_BUS_CNTL, tmp); |
1196 | |||
1197 | for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) { | ||
1198 | if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) == | ||
1199 | 0xdeadbeef) | ||
1200 | break; | ||
1201 | DRM_UDELAY(1); | ||
1202 | } | ||
1203 | |||
1204 | if (tmp < dev_priv->usec_timeout) { | ||
1205 | dev_priv->writeback_works = 1; | ||
1206 | DRM_DEBUG("writeback test succeeded, tmp=%d\n", tmp); | ||
1207 | } else { | ||
1208 | dev_priv->writeback_works = 0; | ||
1209 | DRM_DEBUG("writeback test failed\n"); | ||
1210 | } | ||
1211 | if (radeon_no_wb == 1) { | ||
1212 | dev_priv->writeback_works = 0; | ||
1213 | DRM_DEBUG("writeback forced off\n"); | ||
1214 | } | ||
1215 | 1211 | ||
1216 | dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0; | 1212 | dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0; |
1217 | RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame); | 1213 | RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame); |
@@ -1223,26 +1219,45 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, | |||
1223 | dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0; | 1219 | dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0; |
1224 | RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear); | 1220 | RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear); |
1225 | 1221 | ||
1226 | /* Set ring buffer size */ | ||
1227 | #ifdef __BIG_ENDIAN | ||
1228 | RADEON_WRITE(RADEON_CP_RB_CNTL, | ||
1229 | dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT); | ||
1230 | #else | ||
1231 | RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw); | ||
1232 | #endif | ||
1233 | |||
1234 | radeon_do_wait_for_idle(dev_priv); | 1222 | radeon_do_wait_for_idle(dev_priv); |
1235 | 1223 | ||
1236 | /* Turn on bus mastering */ | ||
1237 | tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; | ||
1238 | RADEON_WRITE(RADEON_BUS_CNTL, tmp); | ||
1239 | |||
1240 | /* Sync everything up */ | 1224 | /* Sync everything up */ |
1241 | RADEON_WRITE(RADEON_ISYNC_CNTL, | 1225 | RADEON_WRITE(RADEON_ISYNC_CNTL, |
1242 | (RADEON_ISYNC_ANY2D_IDLE3D | | 1226 | (RADEON_ISYNC_ANY2D_IDLE3D | |
1243 | RADEON_ISYNC_ANY3D_IDLE2D | | 1227 | RADEON_ISYNC_ANY3D_IDLE2D | |
1244 | RADEON_ISYNC_WAIT_IDLEGUI | | 1228 | RADEON_ISYNC_WAIT_IDLEGUI | |
1245 | RADEON_ISYNC_CPSCRATCH_IDLEGUI)); | 1229 | RADEON_ISYNC_CPSCRATCH_IDLEGUI)); |
1230 | |||
1231 | } | ||
1232 | |||
1233 | static void radeon_test_writeback(drm_radeon_private_t * dev_priv) | ||
1234 | { | ||
1235 | u32 tmp; | ||
1236 | |||
1237 | /* Writeback doesn't seem to work everywhere, test it here and possibly | ||
1238 | * enable it if it appears to work | ||
1239 | */ | ||
1240 | DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0); | ||
1241 | RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef); | ||
1242 | |||
1243 | for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) { | ||
1244 | if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) == | ||
1245 | 0xdeadbeef) | ||
1246 | break; | ||
1247 | DRM_UDELAY(1); | ||
1248 | } | ||
1249 | |||
1250 | if (tmp < dev_priv->usec_timeout) { | ||
1251 | dev_priv->writeback_works = 1; | ||
1252 | DRM_INFO("writeback test succeeded in %d usecs\n", tmp); | ||
1253 | } else { | ||
1254 | dev_priv->writeback_works = 0; | ||
1255 | DRM_INFO("writeback test failed\n"); | ||
1256 | } | ||
1257 | if (radeon_no_wb == 1) { | ||
1258 | dev_priv->writeback_works = 0; | ||
1259 | DRM_INFO("writeback forced off\n"); | ||
1260 | } | ||
1246 | } | 1261 | } |
1247 | 1262 | ||
1248 | /* Enable or disable PCI-E GART on the chip */ | 1263 | /* Enable or disable PCI-E GART on the chip */ |
@@ -1317,6 +1332,14 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1317 | 1332 | ||
1318 | DRM_DEBUG("\n"); | 1333 | DRM_DEBUG("\n"); |
1319 | 1334 | ||
1335 | /* if we require new memory map but we don't have it fail */ | ||
1336 | if ((dev_priv->flags & CHIP_NEW_MEMMAP) && !dev_priv->new_memmap) | ||
1337 | { | ||
1338 | DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX\n"); | ||
1339 | radeon_do_cleanup_cp(dev); | ||
1340 | return DRM_ERR(EINVAL); | ||
1341 | } | ||
1342 | |||
1320 | if (init->is_pci && (dev_priv->flags & CHIP_IS_AGP)) | 1343 | if (init->is_pci && (dev_priv->flags & CHIP_IS_AGP)) |
1321 | { | 1344 | { |
1322 | DRM_DEBUG("Forcing AGP card to PCI mode\n"); | 1345 | DRM_DEBUG("Forcing AGP card to PCI mode\n"); |
@@ -1496,6 +1519,9 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1496 | 1519 | ||
1497 | dev_priv->fb_location = (RADEON_READ(RADEON_MC_FB_LOCATION) | 1520 | dev_priv->fb_location = (RADEON_READ(RADEON_MC_FB_LOCATION) |
1498 | & 0xffff) << 16; | 1521 | & 0xffff) << 16; |
1522 | dev_priv->fb_size = | ||
1523 | ((RADEON_READ(RADEON_MC_FB_LOCATION) & 0xffff0000u) + 0x10000) | ||
1524 | - dev_priv->fb_location; | ||
1499 | 1525 | ||
1500 | dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) | | 1526 | dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) | |
1501 | ((dev_priv->front_offset | 1527 | ((dev_priv->front_offset |
@@ -1510,8 +1536,46 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1510 | + dev_priv->fb_location) >> 10)); | 1536 | + dev_priv->fb_location) >> 10)); |
1511 | 1537 | ||
1512 | dev_priv->gart_size = init->gart_size; | 1538 | dev_priv->gart_size = init->gart_size; |
1513 | dev_priv->gart_vm_start = dev_priv->fb_location | 1539 | |
1514 | + RADEON_READ(RADEON_CONFIG_APER_SIZE); | 1540 | /* New let's set the memory map ... */ |
1541 | if (dev_priv->new_memmap) { | ||
1542 | u32 base = 0; | ||
1543 | |||
1544 | DRM_INFO("Setting GART location based on new memory map\n"); | ||
1545 | |||
1546 | /* If using AGP, try to locate the AGP aperture at the same | ||
1547 | * location in the card and on the bus, though we have to | ||
1548 | * align it down. | ||
1549 | */ | ||
1550 | #if __OS_HAS_AGP | ||
1551 | if (dev_priv->flags & CHIP_IS_AGP) { | ||
1552 | base = dev->agp->base; | ||
1553 | /* Check if valid */ | ||
1554 | if ((base + dev_priv->gart_size) > dev_priv->fb_location && | ||
1555 | base < (dev_priv->fb_location + dev_priv->fb_size)) { | ||
1556 | DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n", | ||
1557 | dev->agp->base); | ||
1558 | base = 0; | ||
1559 | } | ||
1560 | } | ||
1561 | #endif | ||
1562 | /* If not or if AGP is at 0 (Macs), try to put it elsewhere */ | ||
1563 | if (base == 0) { | ||
1564 | base = dev_priv->fb_location + dev_priv->fb_size; | ||
1565 | if (((base + dev_priv->gart_size) & 0xfffffffful) | ||
1566 | < base) | ||
1567 | base = dev_priv->fb_location | ||
1568 | - dev_priv->gart_size; | ||
1569 | } | ||
1570 | dev_priv->gart_vm_start = base & 0xffc00000u; | ||
1571 | if (dev_priv->gart_vm_start != base) | ||
1572 | DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n", | ||
1573 | base, dev_priv->gart_vm_start); | ||
1574 | } else { | ||
1575 | DRM_INFO("Setting GART location based on old memory map\n"); | ||
1576 | dev_priv->gart_vm_start = dev_priv->fb_location + | ||
1577 | RADEON_READ(RADEON_CONFIG_APER_SIZE); | ||
1578 | } | ||
1515 | 1579 | ||
1516 | #if __OS_HAS_AGP | 1580 | #if __OS_HAS_AGP |
1517 | if (dev_priv->flags & CHIP_IS_AGP) | 1581 | if (dev_priv->flags & CHIP_IS_AGP) |
@@ -1596,6 +1660,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1596 | dev_priv->last_buf = 0; | 1660 | dev_priv->last_buf = 0; |
1597 | 1661 | ||
1598 | radeon_do_engine_reset(dev); | 1662 | radeon_do_engine_reset(dev); |
1663 | radeon_test_writeback(dev_priv); | ||
1599 | 1664 | ||
1600 | return 0; | 1665 | return 0; |
1601 | } | 1666 | } |
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h index 9c177a6b2a4c..c8e279e89c2e 100644 --- a/drivers/char/drm/radeon_drm.h +++ b/drivers/char/drm/radeon_drm.h | |||
@@ -222,6 +222,7 @@ typedef union { | |||
222 | # define R300_WAIT_3D 0x2 | 222 | # define R300_WAIT_3D 0x2 |
223 | # define R300_WAIT_2D_CLEAN 0x3 | 223 | # define R300_WAIT_2D_CLEAN 0x3 |
224 | # define R300_WAIT_3D_CLEAN 0x4 | 224 | # define R300_WAIT_3D_CLEAN 0x4 |
225 | #define R300_CMD_SCRATCH 8 | ||
225 | 226 | ||
226 | typedef union { | 227 | typedef union { |
227 | unsigned int u; | 228 | unsigned int u; |
@@ -247,6 +248,9 @@ typedef union { | |||
247 | struct { | 248 | struct { |
248 | unsigned char cmd_type, flags, pad0, pad1; | 249 | unsigned char cmd_type, flags, pad0, pad1; |
249 | } wait; | 250 | } wait; |
251 | struct { | ||
252 | unsigned char cmd_type, reg, n_bufs, flags; | ||
253 | } scratch; | ||
250 | } drm_r300_cmd_header_t; | 254 | } drm_r300_cmd_header_t; |
251 | 255 | ||
252 | #define RADEON_FRONT 0x1 | 256 | #define RADEON_FRONT 0x1 |
@@ -697,6 +701,7 @@ typedef struct drm_radeon_setparam { | |||
697 | #define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */ | 701 | #define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */ |
698 | #define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */ | 702 | #define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */ |
699 | #define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ | 703 | #define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ |
704 | #define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ | ||
700 | 705 | ||
701 | /* 1.14: Clients can allocate/free a surface | 706 | /* 1.14: Clients can allocate/free a surface |
702 | */ | 707 | */ |
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index 1f7d2ab8c4fc..78345cee8f8e 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h | |||
@@ -38,7 +38,7 @@ | |||
38 | 38 | ||
39 | #define DRIVER_NAME "radeon" | 39 | #define DRIVER_NAME "radeon" |
40 | #define DRIVER_DESC "ATI Radeon" | 40 | #define DRIVER_DESC "ATI Radeon" |
41 | #define DRIVER_DATE "20051229" | 41 | #define DRIVER_DATE "20060225" |
42 | 42 | ||
43 | /* Interface history: | 43 | /* Interface history: |
44 | * | 44 | * |
@@ -91,9 +91,11 @@ | |||
91 | * 1.20- Add support for r300 texrect | 91 | * 1.20- Add support for r300 texrect |
92 | * 1.21- Add support for card type getparam | 92 | * 1.21- Add support for card type getparam |
93 | * 1.22- Add support for texture cache flushes (R300_TX_CNTL) | 93 | * 1.22- Add support for texture cache flushes (R300_TX_CNTL) |
94 | * 1.23- Add new radeon memory map work from benh | ||
95 | * 1.24- Add general-purpose packet for manipulating scratch registers (r300) | ||
94 | */ | 96 | */ |
95 | #define DRIVER_MAJOR 1 | 97 | #define DRIVER_MAJOR 1 |
96 | #define DRIVER_MINOR 22 | 98 | #define DRIVER_MINOR 24 |
97 | #define DRIVER_PATCHLEVEL 0 | 99 | #define DRIVER_PATCHLEVEL 0 |
98 | 100 | ||
99 | /* | 101 | /* |
@@ -101,20 +103,21 @@ | |||
101 | */ | 103 | */ |
102 | enum radeon_family { | 104 | enum radeon_family { |
103 | CHIP_R100, | 105 | CHIP_R100, |
104 | CHIP_RS100, | ||
105 | CHIP_RV100, | 106 | CHIP_RV100, |
107 | CHIP_RS100, | ||
106 | CHIP_RV200, | 108 | CHIP_RV200, |
107 | CHIP_R200, | ||
108 | CHIP_RS200, | 109 | CHIP_RS200, |
109 | CHIP_R250, | 110 | CHIP_R200, |
110 | CHIP_RS250, | ||
111 | CHIP_RV250, | 111 | CHIP_RV250, |
112 | CHIP_RS300, | ||
112 | CHIP_RV280, | 113 | CHIP_RV280, |
113 | CHIP_R300, | 114 | CHIP_R300, |
114 | CHIP_RS300, | ||
115 | CHIP_R350, | 115 | CHIP_R350, |
116 | CHIP_RV350, | 116 | CHIP_RV350, |
117 | CHIP_RV380, | ||
117 | CHIP_R420, | 118 | CHIP_R420, |
119 | CHIP_RV410, | ||
120 | CHIP_RS400, | ||
118 | CHIP_LAST, | 121 | CHIP_LAST, |
119 | }; | 122 | }; |
120 | 123 | ||
@@ -136,9 +139,11 @@ enum radeon_chip_flags { | |||
136 | CHIP_IS_AGP = 0x00080000UL, | 139 | CHIP_IS_AGP = 0x00080000UL, |
137 | CHIP_HAS_HIERZ = 0x00100000UL, | 140 | CHIP_HAS_HIERZ = 0x00100000UL, |
138 | CHIP_IS_PCIE = 0x00200000UL, | 141 | CHIP_IS_PCIE = 0x00200000UL, |
142 | CHIP_NEW_MEMMAP = 0x00400000UL, | ||
139 | }; | 143 | }; |
140 | 144 | ||
141 | #define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 ) | 145 | #define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \ |
146 | DRM_READ32( (dev_priv)->ring_rptr, 0 ) : RADEON_READ(RADEON_CP_RB_RPTR)) | ||
142 | #define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) ) | 147 | #define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) ) |
143 | 148 | ||
144 | typedef struct drm_radeon_freelist { | 149 | typedef struct drm_radeon_freelist { |
@@ -199,6 +204,8 @@ typedef struct drm_radeon_private { | |||
199 | drm_radeon_sarea_t *sarea_priv; | 204 | drm_radeon_sarea_t *sarea_priv; |
200 | 205 | ||
201 | u32 fb_location; | 206 | u32 fb_location; |
207 | u32 fb_size; | ||
208 | int new_memmap; | ||
202 | 209 | ||
203 | int gart_size; | 210 | int gart_size; |
204 | u32 gart_vm_start; | 211 | u32 gart_vm_start; |
@@ -272,6 +279,8 @@ typedef struct drm_radeon_private { | |||
272 | unsigned long pcigart_offset; | 279 | unsigned long pcigart_offset; |
273 | drm_ati_pcigart_info gart_info; | 280 | drm_ati_pcigart_info gart_info; |
274 | 281 | ||
282 | u32 scratch_ages[5]; | ||
283 | |||
275 | /* starting from here on, data is preserved accross an open */ | 284 | /* starting from here on, data is preserved accross an open */ |
276 | uint32_t flags; /* see radeon_chip_flags */ | 285 | uint32_t flags; /* see radeon_chip_flags */ |
277 | } drm_radeon_private_t; | 286 | } drm_radeon_private_t; |
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index 7bc27516d425..c5b8f774a599 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c | |||
@@ -45,22 +45,53 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * | |||
45 | u32 off = *offset; | 45 | u32 off = *offset; |
46 | struct drm_radeon_driver_file_fields *radeon_priv; | 46 | struct drm_radeon_driver_file_fields *radeon_priv; |
47 | 47 | ||
48 | if (off >= dev_priv->fb_location && | 48 | /* Hrm ... the story of the offset ... So this function converts |
49 | off < (dev_priv->gart_vm_start + dev_priv->gart_size)) | 49 | * the various ideas of what userland clients might have for an |
50 | return 0; | 50 | * offset in the card address space into an offset into the card |
51 | 51 | * address space :) So with a sane client, it should just keep | |
52 | radeon_priv = filp_priv->driver_priv; | 52 | * the value intact and just do some boundary checking. However, |
53 | off += radeon_priv->radeon_fb_delta; | 53 | * not all clients are sane. Some older clients pass us 0 based |
54 | * offsets relative to the start of the framebuffer and some may | ||
55 | * assume the AGP aperture it appended to the framebuffer, so we | ||
56 | * try to detect those cases and fix them up. | ||
57 | * | ||
58 | * Note: It might be a good idea here to make sure the offset lands | ||
59 | * in some "allowed" area to protect things like the PCIE GART... | ||
60 | */ | ||
54 | 61 | ||
55 | DRM_DEBUG("offset fixed up to 0x%x\n", off); | 62 | /* First, the best case, the offset already lands in either the |
63 | * framebuffer or the GART mapped space | ||
64 | */ | ||
65 | if ((off >= dev_priv->fb_location && | ||
66 | off < (dev_priv->fb_location + dev_priv->fb_size)) || | ||
67 | (off >= dev_priv->gart_vm_start && | ||
68 | off < (dev_priv->gart_vm_start + dev_priv->gart_size))) | ||
69 | return 0; | ||
56 | 70 | ||
57 | if (off < dev_priv->fb_location || | 71 | /* Ok, that didn't happen... now check if we have a zero based |
58 | off >= (dev_priv->gart_vm_start + dev_priv->gart_size)) | 72 | * offset that fits in the framebuffer + gart space, apply the |
59 | return DRM_ERR(EINVAL); | 73 | * magic offset we get from SETPARAM or calculated from fb_location |
74 | */ | ||
75 | if (off < (dev_priv->fb_size + dev_priv->gart_size)) { | ||
76 | radeon_priv = filp_priv->driver_priv; | ||
77 | off += radeon_priv->radeon_fb_delta; | ||
78 | } | ||
60 | 79 | ||
61 | *offset = off; | 80 | /* Finally, assume we aimed at a GART offset if beyond the fb */ |
81 | if (off > (dev_priv->fb_location + dev_priv->fb_size)) | ||
82 | off = off - (dev_priv->fb_location + dev_priv->fb_size) + | ||
83 | dev_priv->gart_vm_start; | ||
62 | 84 | ||
63 | return 0; | 85 | /* Now recheck and fail if out of bounds */ |
86 | if ((off >= dev_priv->fb_location && | ||
87 | off < (dev_priv->fb_location + dev_priv->fb_size)) || | ||
88 | (off >= dev_priv->gart_vm_start && | ||
89 | off < (dev_priv->gart_vm_start + dev_priv->gart_size))) { | ||
90 | DRM_DEBUG("offset fixed up to 0x%x\n", off); | ||
91 | *offset = off; | ||
92 | return 0; | ||
93 | } | ||
94 | return DRM_ERR(EINVAL); | ||
64 | } | 95 | } |
65 | 96 | ||
66 | static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * | 97 | static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * |
@@ -1939,11 +1970,6 @@ static int radeon_surface_alloc(DRM_IOCTL_ARGS) | |||
1939 | drm_radeon_private_t *dev_priv = dev->dev_private; | 1970 | drm_radeon_private_t *dev_priv = dev->dev_private; |
1940 | drm_radeon_surface_alloc_t alloc; | 1971 | drm_radeon_surface_alloc_t alloc; |
1941 | 1972 | ||
1942 | if (!dev_priv) { | ||
1943 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | ||
1944 | return DRM_ERR(EINVAL); | ||
1945 | } | ||
1946 | |||
1947 | DRM_COPY_FROM_USER_IOCTL(alloc, | 1973 | DRM_COPY_FROM_USER_IOCTL(alloc, |
1948 | (drm_radeon_surface_alloc_t __user *) data, | 1974 | (drm_radeon_surface_alloc_t __user *) data, |
1949 | sizeof(alloc)); | 1975 | sizeof(alloc)); |
@@ -1960,12 +1986,7 @@ static int radeon_surface_free(DRM_IOCTL_ARGS) | |||
1960 | drm_radeon_private_t *dev_priv = dev->dev_private; | 1986 | drm_radeon_private_t *dev_priv = dev->dev_private; |
1961 | drm_radeon_surface_free_t memfree; | 1987 | drm_radeon_surface_free_t memfree; |
1962 | 1988 | ||
1963 | if (!dev_priv) { | 1989 | DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_surface_free_t __user *) data, |
1964 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | ||
1965 | return DRM_ERR(EINVAL); | ||
1966 | } | ||
1967 | |||
1968 | DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *) data, | ||
1969 | sizeof(memfree)); | 1990 | sizeof(memfree)); |
1970 | 1991 | ||
1971 | if (free_surface(filp, dev_priv, memfree.address)) | 1992 | if (free_surface(filp, dev_priv, memfree.address)) |
@@ -2100,11 +2121,6 @@ static int radeon_cp_vertex(DRM_IOCTL_ARGS) | |||
2100 | 2121 | ||
2101 | LOCK_TEST_WITH_RETURN(dev, filp); | 2122 | LOCK_TEST_WITH_RETURN(dev, filp); |
2102 | 2123 | ||
2103 | if (!dev_priv) { | ||
2104 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | ||
2105 | return DRM_ERR(EINVAL); | ||
2106 | } | ||
2107 | |||
2108 | DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); | 2124 | DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); |
2109 | 2125 | ||
2110 | DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex_t __user *) data, | 2126 | DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex_t __user *) data, |
@@ -2189,11 +2205,6 @@ static int radeon_cp_indices(DRM_IOCTL_ARGS) | |||
2189 | 2205 | ||
2190 | LOCK_TEST_WITH_RETURN(dev, filp); | 2206 | LOCK_TEST_WITH_RETURN(dev, filp); |
2191 | 2207 | ||
2192 | if (!dev_priv) { | ||
2193 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | ||
2194 | return DRM_ERR(EINVAL); | ||
2195 | } | ||
2196 | |||
2197 | DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); | 2208 | DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); |
2198 | 2209 | ||
2199 | DRM_COPY_FROM_USER_IOCTL(elts, (drm_radeon_indices_t __user *) data, | 2210 | DRM_COPY_FROM_USER_IOCTL(elts, (drm_radeon_indices_t __user *) data, |
@@ -2340,11 +2351,6 @@ static int radeon_cp_indirect(DRM_IOCTL_ARGS) | |||
2340 | 2351 | ||
2341 | LOCK_TEST_WITH_RETURN(dev, filp); | 2352 | LOCK_TEST_WITH_RETURN(dev, filp); |
2342 | 2353 | ||
2343 | if (!dev_priv) { | ||
2344 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | ||
2345 | return DRM_ERR(EINVAL); | ||
2346 | } | ||
2347 | |||
2348 | DRM_COPY_FROM_USER_IOCTL(indirect, | 2354 | DRM_COPY_FROM_USER_IOCTL(indirect, |
2349 | (drm_radeon_indirect_t __user *) data, | 2355 | (drm_radeon_indirect_t __user *) data, |
2350 | sizeof(indirect)); | 2356 | sizeof(indirect)); |
@@ -2417,11 +2423,6 @@ static int radeon_cp_vertex2(DRM_IOCTL_ARGS) | |||
2417 | 2423 | ||
2418 | LOCK_TEST_WITH_RETURN(dev, filp); | 2424 | LOCK_TEST_WITH_RETURN(dev, filp); |
2419 | 2425 | ||
2420 | if (!dev_priv) { | ||
2421 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | ||
2422 | return DRM_ERR(EINVAL); | ||
2423 | } | ||
2424 | |||
2425 | DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); | 2426 | DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); |
2426 | 2427 | ||
2427 | DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex2_t __user *) data, | 2428 | DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex2_t __user *) data, |
@@ -2738,11 +2739,6 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS) | |||
2738 | 2739 | ||
2739 | LOCK_TEST_WITH_RETURN(dev, filp); | 2740 | LOCK_TEST_WITH_RETURN(dev, filp); |
2740 | 2741 | ||
2741 | if (!dev_priv) { | ||
2742 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | ||
2743 | return DRM_ERR(EINVAL); | ||
2744 | } | ||
2745 | |||
2746 | DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); | 2742 | DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); |
2747 | 2743 | ||
2748 | DRM_COPY_FROM_USER_IOCTL(cmdbuf, | 2744 | DRM_COPY_FROM_USER_IOCTL(cmdbuf, |
@@ -2897,11 +2893,6 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS) | |||
2897 | drm_radeon_getparam_t param; | 2893 | drm_radeon_getparam_t param; |
2898 | int value; | 2894 | int value; |
2899 | 2895 | ||
2900 | if (!dev_priv) { | ||
2901 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | ||
2902 | return DRM_ERR(EINVAL); | ||
2903 | } | ||
2904 | |||
2905 | DRM_COPY_FROM_USER_IOCTL(param, (drm_radeon_getparam_t __user *) data, | 2896 | DRM_COPY_FROM_USER_IOCTL(param, (drm_radeon_getparam_t __user *) data, |
2906 | sizeof(param)); | 2897 | sizeof(param)); |
2907 | 2898 | ||
@@ -2981,11 +2972,6 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS) | |||
2981 | drm_radeon_setparam_t sp; | 2972 | drm_radeon_setparam_t sp; |
2982 | struct drm_radeon_driver_file_fields *radeon_priv; | 2973 | struct drm_radeon_driver_file_fields *radeon_priv; |
2983 | 2974 | ||
2984 | if (!dev_priv) { | ||
2985 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | ||
2986 | return DRM_ERR(EINVAL); | ||
2987 | } | ||
2988 | |||
2989 | DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); | 2975 | DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); |
2990 | 2976 | ||
2991 | DRM_COPY_FROM_USER_IOCTL(sp, (drm_radeon_setparam_t __user *) data, | 2977 | DRM_COPY_FROM_USER_IOCTL(sp, (drm_radeon_setparam_t __user *) data, |
@@ -3012,6 +2998,9 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS) | |||
3012 | case RADEON_SETPARAM_PCIGART_LOCATION: | 2998 | case RADEON_SETPARAM_PCIGART_LOCATION: |
3013 | dev_priv->pcigart_offset = sp.value; | 2999 | dev_priv->pcigart_offset = sp.value; |
3014 | break; | 3000 | break; |
3001 | case RADEON_SETPARAM_NEW_MEMMAP: | ||
3002 | dev_priv->new_memmap = sp.value; | ||
3003 | break; | ||
3015 | default: | 3004 | default: |
3016 | DRM_DEBUG("Invalid parameter %d\n", sp.param); | 3005 | DRM_DEBUG("Invalid parameter %d\n", sp.param); |
3017 | return DRM_ERR(EINVAL); | 3006 | return DRM_ERR(EINVAL); |
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c index 6774d2fe3452..5e9936bc307f 100644 --- a/drivers/char/drm/sis_mm.c +++ b/drivers/char/drm/sis_mm.c | |||
@@ -110,7 +110,7 @@ static int sis_fb_alloc(DRM_IOCTL_ARGS) | |||
110 | 110 | ||
111 | DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb)); | 111 | DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb)); |
112 | 112 | ||
113 | DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset); | 113 | DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, req.offset); |
114 | 114 | ||
115 | return retval; | 115 | return retval; |
116 | } | 116 | } |
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index f7854b65fd55..ba54c856b0e5 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c | |||
@@ -227,6 +227,14 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device, | |||
227 | if (!is_vendor_oui(mad_reg_req->oui)) | 227 | if (!is_vendor_oui(mad_reg_req->oui)) |
228 | goto error1; | 228 | goto error1; |
229 | } | 229 | } |
230 | /* Make sure class supplied is consistent with RMPP */ | ||
231 | if (ib_is_mad_class_rmpp(mad_reg_req->mgmt_class)) { | ||
232 | if (!rmpp_version) | ||
233 | goto error1; | ||
234 | } else { | ||
235 | if (rmpp_version) | ||
236 | goto error1; | ||
237 | } | ||
230 | /* Make sure class supplied is consistent with QP type */ | 238 | /* Make sure class supplied is consistent with QP type */ |
231 | if (qp_type == IB_QPT_SMI) { | 239 | if (qp_type == IB_QPT_SMI) { |
232 | if ((mad_reg_req->mgmt_class != | 240 | if ((mad_reg_req->mgmt_class != |
@@ -890,6 +898,35 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, | |||
890 | } | 898 | } |
891 | EXPORT_SYMBOL(ib_create_send_mad); | 899 | EXPORT_SYMBOL(ib_create_send_mad); |
892 | 900 | ||
901 | int ib_get_mad_data_offset(u8 mgmt_class) | ||
902 | { | ||
903 | if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM) | ||
904 | return IB_MGMT_SA_HDR; | ||
905 | else if ((mgmt_class == IB_MGMT_CLASS_DEVICE_MGMT) || | ||
906 | (mgmt_class == IB_MGMT_CLASS_DEVICE_ADM) || | ||
907 | (mgmt_class == IB_MGMT_CLASS_BIS)) | ||
908 | return IB_MGMT_DEVICE_HDR; | ||
909 | else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && | ||
910 | (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) | ||
911 | return IB_MGMT_VENDOR_HDR; | ||
912 | else | ||
913 | return IB_MGMT_MAD_HDR; | ||
914 | } | ||
915 | EXPORT_SYMBOL(ib_get_mad_data_offset); | ||
916 | |||
917 | int ib_is_mad_class_rmpp(u8 mgmt_class) | ||
918 | { | ||
919 | if ((mgmt_class == IB_MGMT_CLASS_SUBN_ADM) || | ||
920 | (mgmt_class == IB_MGMT_CLASS_DEVICE_MGMT) || | ||
921 | (mgmt_class == IB_MGMT_CLASS_DEVICE_ADM) || | ||
922 | (mgmt_class == IB_MGMT_CLASS_BIS) || | ||
923 | ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && | ||
924 | (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))) | ||
925 | return 1; | ||
926 | return 0; | ||
927 | } | ||
928 | EXPORT_SYMBOL(ib_is_mad_class_rmpp); | ||
929 | |||
893 | void *ib_get_rmpp_segment(struct ib_mad_send_buf *send_buf, int seg_num) | 930 | void *ib_get_rmpp_segment(struct ib_mad_send_buf *send_buf, int seg_num) |
894 | { | 931 | { |
895 | struct ib_mad_send_wr_private *mad_send_wr; | 932 | struct ib_mad_send_wr_private *mad_send_wr; |
@@ -1022,6 +1059,13 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf, | |||
1022 | goto error; | 1059 | goto error; |
1023 | } | 1060 | } |
1024 | 1061 | ||
1062 | if (!ib_is_mad_class_rmpp(((struct ib_mad_hdr *) send_buf->mad)->mgmt_class)) { | ||
1063 | if (mad_agent_priv->agent.rmpp_version) { | ||
1064 | ret = -EINVAL; | ||
1065 | goto error; | ||
1066 | } | ||
1067 | } | ||
1068 | |||
1025 | /* | 1069 | /* |
1026 | * Save pointer to next work request to post in case the | 1070 | * Save pointer to next work request to post in case the |
1027 | * current one completes, and the user modifies the work | 1071 | * current one completes, and the user modifies the work |
@@ -1618,14 +1662,59 @@ static int is_data_mad(struct ib_mad_agent_private *mad_agent_priv, | |||
1618 | (rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA); | 1662 | (rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA); |
1619 | } | 1663 | } |
1620 | 1664 | ||
1665 | static inline int rcv_has_same_class(struct ib_mad_send_wr_private *wr, | ||
1666 | struct ib_mad_recv_wc *rwc) | ||
1667 | { | ||
1668 | return ((struct ib_mad *)(wr->send_buf.mad))->mad_hdr.mgmt_class == | ||
1669 | rwc->recv_buf.mad->mad_hdr.mgmt_class; | ||
1670 | } | ||
1671 | |||
1672 | static inline int rcv_has_same_gid(struct ib_mad_send_wr_private *wr, | ||
1673 | struct ib_mad_recv_wc *rwc ) | ||
1674 | { | ||
1675 | struct ib_ah_attr attr; | ||
1676 | u8 send_resp, rcv_resp; | ||
1677 | |||
1678 | send_resp = ((struct ib_mad *)(wr->send_buf.mad))-> | ||
1679 | mad_hdr.method & IB_MGMT_METHOD_RESP; | ||
1680 | rcv_resp = rwc->recv_buf.mad->mad_hdr.method & IB_MGMT_METHOD_RESP; | ||
1681 | |||
1682 | if (!send_resp && rcv_resp) | ||
1683 | /* is request/response. GID/LIDs are both local (same). */ | ||
1684 | return 1; | ||
1685 | |||
1686 | if (send_resp == rcv_resp) | ||
1687 | /* both requests, or both responses. GIDs different */ | ||
1688 | return 0; | ||
1689 | |||
1690 | if (ib_query_ah(wr->send_buf.ah, &attr)) | ||
1691 | /* Assume not equal, to avoid false positives. */ | ||
1692 | return 0; | ||
1693 | |||
1694 | if (!(attr.ah_flags & IB_AH_GRH) && !(rwc->wc->wc_flags & IB_WC_GRH)) | ||
1695 | return attr.dlid == rwc->wc->slid; | ||
1696 | else if ((attr.ah_flags & IB_AH_GRH) && | ||
1697 | (rwc->wc->wc_flags & IB_WC_GRH)) | ||
1698 | return memcmp(attr.grh.dgid.raw, | ||
1699 | rwc->recv_buf.grh->sgid.raw, 16) == 0; | ||
1700 | else | ||
1701 | /* one has GID, other does not. Assume different */ | ||
1702 | return 0; | ||
1703 | } | ||
1621 | struct ib_mad_send_wr_private* | 1704 | struct ib_mad_send_wr_private* |
1622 | ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid) | 1705 | ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, |
1706 | struct ib_mad_recv_wc *mad_recv_wc) | ||
1623 | { | 1707 | { |
1624 | struct ib_mad_send_wr_private *mad_send_wr; | 1708 | struct ib_mad_send_wr_private *mad_send_wr; |
1709 | struct ib_mad *mad; | ||
1710 | |||
1711 | mad = (struct ib_mad *)mad_recv_wc->recv_buf.mad; | ||
1625 | 1712 | ||
1626 | list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list, | 1713 | list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list, |
1627 | agent_list) { | 1714 | agent_list) { |
1628 | if (mad_send_wr->tid == tid) | 1715 | if ((mad_send_wr->tid == mad->mad_hdr.tid) && |
1716 | rcv_has_same_class(mad_send_wr, mad_recv_wc) && | ||
1717 | rcv_has_same_gid(mad_send_wr, mad_recv_wc)) | ||
1629 | return mad_send_wr; | 1718 | return mad_send_wr; |
1630 | } | 1719 | } |
1631 | 1720 | ||
@@ -1636,7 +1725,10 @@ ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid) | |||
1636 | list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list, | 1725 | list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list, |
1637 | agent_list) { | 1726 | agent_list) { |
1638 | if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) && | 1727 | if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) && |
1639 | mad_send_wr->tid == tid && mad_send_wr->timeout) { | 1728 | mad_send_wr->tid == mad->mad_hdr.tid && |
1729 | mad_send_wr->timeout && | ||
1730 | rcv_has_same_class(mad_send_wr, mad_recv_wc) && | ||
1731 | rcv_has_same_gid(mad_send_wr, mad_recv_wc)) { | ||
1640 | /* Verify request has not been canceled */ | 1732 | /* Verify request has not been canceled */ |
1641 | return (mad_send_wr->status == IB_WC_SUCCESS) ? | 1733 | return (mad_send_wr->status == IB_WC_SUCCESS) ? |
1642 | mad_send_wr : NULL; | 1734 | mad_send_wr : NULL; |
@@ -1661,7 +1753,6 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, | |||
1661 | struct ib_mad_send_wr_private *mad_send_wr; | 1753 | struct ib_mad_send_wr_private *mad_send_wr; |
1662 | struct ib_mad_send_wc mad_send_wc; | 1754 | struct ib_mad_send_wc mad_send_wc; |
1663 | unsigned long flags; | 1755 | unsigned long flags; |
1664 | __be64 tid; | ||
1665 | 1756 | ||
1666 | INIT_LIST_HEAD(&mad_recv_wc->rmpp_list); | 1757 | INIT_LIST_HEAD(&mad_recv_wc->rmpp_list); |
1667 | list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list); | 1758 | list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list); |
@@ -1677,9 +1768,8 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, | |||
1677 | 1768 | ||
1678 | /* Complete corresponding request */ | 1769 | /* Complete corresponding request */ |
1679 | if (response_mad(mad_recv_wc->recv_buf.mad)) { | 1770 | if (response_mad(mad_recv_wc->recv_buf.mad)) { |
1680 | tid = mad_recv_wc->recv_buf.mad->mad_hdr.tid; | ||
1681 | spin_lock_irqsave(&mad_agent_priv->lock, flags); | 1771 | spin_lock_irqsave(&mad_agent_priv->lock, flags); |
1682 | mad_send_wr = ib_find_send_mad(mad_agent_priv, tid); | 1772 | mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc); |
1683 | if (!mad_send_wr) { | 1773 | if (!mad_send_wr) { |
1684 | spin_unlock_irqrestore(&mad_agent_priv->lock, flags); | 1774 | spin_unlock_irqrestore(&mad_agent_priv->lock, flags); |
1685 | ib_free_recv_mad(mad_recv_wc); | 1775 | ib_free_recv_mad(mad_recv_wc); |
@@ -2408,11 +2498,11 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, | |||
2408 | } | 2498 | } |
2409 | } | 2499 | } |
2410 | sg_list.addr = dma_map_single(qp_info->port_priv-> | 2500 | sg_list.addr = dma_map_single(qp_info->port_priv-> |
2411 | device->dma_device, | 2501 | device->dma_device, |
2412 | &mad_priv->grh, | 2502 | &mad_priv->grh, |
2413 | sizeof *mad_priv - | 2503 | sizeof *mad_priv - |
2414 | sizeof mad_priv->header, | 2504 | sizeof mad_priv->header, |
2415 | DMA_FROM_DEVICE); | 2505 | DMA_FROM_DEVICE); |
2416 | pci_unmap_addr_set(&mad_priv->header, mapping, sg_list.addr); | 2506 | pci_unmap_addr_set(&mad_priv->header, mapping, sg_list.addr); |
2417 | recv_wr.wr_id = (unsigned long)&mad_priv->header.mad_list; | 2507 | recv_wr.wr_id = (unsigned long)&mad_priv->header.mad_list; |
2418 | mad_priv->header.mad_list.mad_queue = recv_queue; | 2508 | mad_priv->header.mad_list.mad_queue = recv_queue; |
diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h index a7125d4b5ccf..6c9c133d71ef 100644 --- a/drivers/infiniband/core/mad_priv.h +++ b/drivers/infiniband/core/mad_priv.h | |||
@@ -216,7 +216,8 @@ extern kmem_cache_t *ib_mad_cache; | |||
216 | int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr); | 216 | int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr); |
217 | 217 | ||
218 | struct ib_mad_send_wr_private * | 218 | struct ib_mad_send_wr_private * |
219 | ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid); | 219 | ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, |
220 | struct ib_mad_recv_wc *mad_recv_wc); | ||
220 | 221 | ||
221 | void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr, | 222 | void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr, |
222 | struct ib_mad_send_wc *mad_send_wc); | 223 | struct ib_mad_send_wc *mad_send_wc); |
diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c index bacfdd5bddad..dfd4e588ce03 100644 --- a/drivers/infiniband/core/mad_rmpp.c +++ b/drivers/infiniband/core/mad_rmpp.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2005 Intel Inc. All rights reserved. | 2 | * Copyright (c) 2005 Intel Inc. All rights reserved. |
3 | * Copyright (c) 2005 Voltaire, Inc. All rights reserved. | 3 | * Copyright (c) 2005-2006 Voltaire, Inc. All rights reserved. |
4 | * | 4 | * |
5 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
6 | * licenses. You may choose to be licensed under the terms of the GNU | 6 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -100,17 +100,6 @@ void ib_cancel_rmpp_recvs(struct ib_mad_agent_private *agent) | |||
100 | } | 100 | } |
101 | } | 101 | } |
102 | 102 | ||
103 | static int data_offset(u8 mgmt_class) | ||
104 | { | ||
105 | if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM) | ||
106 | return IB_MGMT_SA_HDR; | ||
107 | else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && | ||
108 | (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) | ||
109 | return IB_MGMT_VENDOR_HDR; | ||
110 | else | ||
111 | return IB_MGMT_RMPP_HDR; | ||
112 | } | ||
113 | |||
114 | static void format_ack(struct ib_mad_send_buf *msg, | 103 | static void format_ack(struct ib_mad_send_buf *msg, |
115 | struct ib_rmpp_mad *data, | 104 | struct ib_rmpp_mad *data, |
116 | struct mad_rmpp_recv *rmpp_recv) | 105 | struct mad_rmpp_recv *rmpp_recv) |
@@ -137,7 +126,7 @@ static void ack_recv(struct mad_rmpp_recv *rmpp_recv, | |||
137 | struct ib_mad_send_buf *msg; | 126 | struct ib_mad_send_buf *msg; |
138 | int ret, hdr_len; | 127 | int ret, hdr_len; |
139 | 128 | ||
140 | hdr_len = data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); | 129 | hdr_len = ib_get_mad_data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); |
141 | msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp, | 130 | msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp, |
142 | recv_wc->wc->pkey_index, 1, hdr_len, | 131 | recv_wc->wc->pkey_index, 1, hdr_len, |
143 | 0, GFP_KERNEL); | 132 | 0, GFP_KERNEL); |
@@ -163,7 +152,7 @@ static struct ib_mad_send_buf *alloc_response_msg(struct ib_mad_agent *agent, | |||
163 | if (IS_ERR(ah)) | 152 | if (IS_ERR(ah)) |
164 | return (void *) ah; | 153 | return (void *) ah; |
165 | 154 | ||
166 | hdr_len = data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); | 155 | hdr_len = ib_get_mad_data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); |
167 | msg = ib_create_send_mad(agent, recv_wc->wc->src_qp, | 156 | msg = ib_create_send_mad(agent, recv_wc->wc->src_qp, |
168 | recv_wc->wc->pkey_index, 1, | 157 | recv_wc->wc->pkey_index, 1, |
169 | hdr_len, 0, GFP_KERNEL); | 158 | hdr_len, 0, GFP_KERNEL); |
@@ -408,7 +397,7 @@ static inline int get_mad_len(struct mad_rmpp_recv *rmpp_recv) | |||
408 | 397 | ||
409 | rmpp_mad = (struct ib_rmpp_mad *)rmpp_recv->cur_seg_buf->mad; | 398 | rmpp_mad = (struct ib_rmpp_mad *)rmpp_recv->cur_seg_buf->mad; |
410 | 399 | ||
411 | hdr_size = data_offset(rmpp_mad->mad_hdr.mgmt_class); | 400 | hdr_size = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class); |
412 | data_size = sizeof(struct ib_rmpp_mad) - hdr_size; | 401 | data_size = sizeof(struct ib_rmpp_mad) - hdr_size; |
413 | pad = IB_MGMT_RMPP_DATA - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); | 402 | pad = IB_MGMT_RMPP_DATA - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); |
414 | if (pad > IB_MGMT_RMPP_DATA || pad < 0) | 403 | if (pad > IB_MGMT_RMPP_DATA || pad < 0) |
@@ -562,15 +551,15 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr) | |||
562 | return ib_send_mad(mad_send_wr); | 551 | return ib_send_mad(mad_send_wr); |
563 | } | 552 | } |
564 | 553 | ||
565 | static void abort_send(struct ib_mad_agent_private *agent, __be64 tid, | 554 | static void abort_send(struct ib_mad_agent_private *agent, |
566 | u8 rmpp_status) | 555 | struct ib_mad_recv_wc *mad_recv_wc, u8 rmpp_status) |
567 | { | 556 | { |
568 | struct ib_mad_send_wr_private *mad_send_wr; | 557 | struct ib_mad_send_wr_private *mad_send_wr; |
569 | struct ib_mad_send_wc wc; | 558 | struct ib_mad_send_wc wc; |
570 | unsigned long flags; | 559 | unsigned long flags; |
571 | 560 | ||
572 | spin_lock_irqsave(&agent->lock, flags); | 561 | spin_lock_irqsave(&agent->lock, flags); |
573 | mad_send_wr = ib_find_send_mad(agent, tid); | 562 | mad_send_wr = ib_find_send_mad(agent, mad_recv_wc); |
574 | if (!mad_send_wr) | 563 | if (!mad_send_wr) |
575 | goto out; /* Unmatched send */ | 564 | goto out; /* Unmatched send */ |
576 | 565 | ||
@@ -612,8 +601,7 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, | |||
612 | 601 | ||
613 | rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; | 602 | rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; |
614 | if (rmpp_mad->rmpp_hdr.rmpp_status) { | 603 | if (rmpp_mad->rmpp_hdr.rmpp_status) { |
615 | abort_send(agent, rmpp_mad->mad_hdr.tid, | 604 | abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); |
616 | IB_MGMT_RMPP_STATUS_BAD_STATUS); | ||
617 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); | 605 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); |
618 | return; | 606 | return; |
619 | } | 607 | } |
@@ -621,14 +609,13 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, | |||
621 | seg_num = be32_to_cpu(rmpp_mad->rmpp_hdr.seg_num); | 609 | seg_num = be32_to_cpu(rmpp_mad->rmpp_hdr.seg_num); |
622 | newwin = be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); | 610 | newwin = be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); |
623 | if (newwin < seg_num) { | 611 | if (newwin < seg_num) { |
624 | abort_send(agent, rmpp_mad->mad_hdr.tid, | 612 | abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_W2S); |
625 | IB_MGMT_RMPP_STATUS_W2S); | ||
626 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_W2S); | 613 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_W2S); |
627 | return; | 614 | return; |
628 | } | 615 | } |
629 | 616 | ||
630 | spin_lock_irqsave(&agent->lock, flags); | 617 | spin_lock_irqsave(&agent->lock, flags); |
631 | mad_send_wr = ib_find_send_mad(agent, rmpp_mad->mad_hdr.tid); | 618 | mad_send_wr = ib_find_send_mad(agent, mad_recv_wc); |
632 | if (!mad_send_wr) | 619 | if (!mad_send_wr) |
633 | goto out; /* Unmatched ACK */ | 620 | goto out; /* Unmatched ACK */ |
634 | 621 | ||
@@ -639,8 +626,7 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, | |||
639 | if (seg_num > mad_send_wr->send_buf.seg_count || | 626 | if (seg_num > mad_send_wr->send_buf.seg_count || |
640 | seg_num > mad_send_wr->newwin) { | 627 | seg_num > mad_send_wr->newwin) { |
641 | spin_unlock_irqrestore(&agent->lock, flags); | 628 | spin_unlock_irqrestore(&agent->lock, flags); |
642 | abort_send(agent, rmpp_mad->mad_hdr.tid, | 629 | abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B); |
643 | IB_MGMT_RMPP_STATUS_S2B); | ||
644 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B); | 630 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B); |
645 | return; | 631 | return; |
646 | } | 632 | } |
@@ -728,12 +714,10 @@ static void process_rmpp_stop(struct ib_mad_agent_private *agent, | |||
728 | rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; | 714 | rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; |
729 | 715 | ||
730 | if (rmpp_mad->rmpp_hdr.rmpp_status != IB_MGMT_RMPP_STATUS_RESX) { | 716 | if (rmpp_mad->rmpp_hdr.rmpp_status != IB_MGMT_RMPP_STATUS_RESX) { |
731 | abort_send(agent, rmpp_mad->mad_hdr.tid, | 717 | abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); |
732 | IB_MGMT_RMPP_STATUS_BAD_STATUS); | ||
733 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); | 718 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); |
734 | } else | 719 | } else |
735 | abort_send(agent, rmpp_mad->mad_hdr.tid, | 720 | abort_send(agent, mad_recv_wc, rmpp_mad->rmpp_hdr.rmpp_status); |
736 | rmpp_mad->rmpp_hdr.rmpp_status); | ||
737 | } | 721 | } |
738 | 722 | ||
739 | static void process_rmpp_abort(struct ib_mad_agent_private *agent, | 723 | static void process_rmpp_abort(struct ib_mad_agent_private *agent, |
@@ -745,12 +729,10 @@ static void process_rmpp_abort(struct ib_mad_agent_private *agent, | |||
745 | 729 | ||
746 | if (rmpp_mad->rmpp_hdr.rmpp_status < IB_MGMT_RMPP_STATUS_ABORT_MIN || | 730 | if (rmpp_mad->rmpp_hdr.rmpp_status < IB_MGMT_RMPP_STATUS_ABORT_MIN || |
747 | rmpp_mad->rmpp_hdr.rmpp_status > IB_MGMT_RMPP_STATUS_ABORT_MAX) { | 731 | rmpp_mad->rmpp_hdr.rmpp_status > IB_MGMT_RMPP_STATUS_ABORT_MAX) { |
748 | abort_send(agent, rmpp_mad->mad_hdr.tid, | 732 | abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); |
749 | IB_MGMT_RMPP_STATUS_BAD_STATUS); | ||
750 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); | 733 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); |
751 | } else | 734 | } else |
752 | abort_send(agent, rmpp_mad->mad_hdr.tid, | 735 | abort_send(agent, mad_recv_wc, rmpp_mad->rmpp_hdr.rmpp_status); |
753 | rmpp_mad->rmpp_hdr.rmpp_status); | ||
754 | } | 736 | } |
755 | 737 | ||
756 | struct ib_mad_recv_wc * | 738 | struct ib_mad_recv_wc * |
@@ -764,8 +746,7 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent, | |||
764 | return mad_recv_wc; | 746 | return mad_recv_wc; |
765 | 747 | ||
766 | if (rmpp_mad->rmpp_hdr.rmpp_version != IB_MGMT_RMPP_VERSION) { | 748 | if (rmpp_mad->rmpp_hdr.rmpp_version != IB_MGMT_RMPP_VERSION) { |
767 | abort_send(agent, rmpp_mad->mad_hdr.tid, | 749 | abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV); |
768 | IB_MGMT_RMPP_STATUS_UNV); | ||
769 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV); | 750 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV); |
770 | goto out; | 751 | goto out; |
771 | } | 752 | } |
@@ -783,8 +764,7 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent, | |||
783 | process_rmpp_abort(agent, mad_recv_wc); | 764 | process_rmpp_abort(agent, mad_recv_wc); |
784 | break; | 765 | break; |
785 | default: | 766 | default: |
786 | abort_send(agent, rmpp_mad->mad_hdr.tid, | 767 | abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT); |
787 | IB_MGMT_RMPP_STATUS_BADT); | ||
788 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT); | 768 | nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT); |
789 | break; | 769 | break; |
790 | } | 770 | } |
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index fb6cd42601f9..afe70a549c2f 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c | |||
@@ -177,17 +177,6 @@ static int queue_packet(struct ib_umad_file *file, | |||
177 | return ret; | 177 | return ret; |
178 | } | 178 | } |
179 | 179 | ||
180 | static int data_offset(u8 mgmt_class) | ||
181 | { | ||
182 | if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM) | ||
183 | return IB_MGMT_SA_HDR; | ||
184 | else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && | ||
185 | (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) | ||
186 | return IB_MGMT_VENDOR_HDR; | ||
187 | else | ||
188 | return IB_MGMT_RMPP_HDR; | ||
189 | } | ||
190 | |||
191 | static void send_handler(struct ib_mad_agent *agent, | 180 | static void send_handler(struct ib_mad_agent *agent, |
192 | struct ib_mad_send_wc *send_wc) | 181 | struct ib_mad_send_wc *send_wc) |
193 | { | 182 | { |
@@ -283,7 +272,7 @@ static ssize_t copy_recv_mad(char __user *buf, struct ib_umad_packet *packet, | |||
283 | */ | 272 | */ |
284 | return -ENOSPC; | 273 | return -ENOSPC; |
285 | } | 274 | } |
286 | offset = data_offset(recv_buf->mad->mad_hdr.mgmt_class); | 275 | offset = ib_get_mad_data_offset(recv_buf->mad->mad_hdr.mgmt_class); |
287 | max_seg_payload = sizeof (struct ib_mad) - offset; | 276 | max_seg_payload = sizeof (struct ib_mad) - offset; |
288 | 277 | ||
289 | for (left = packet->length - seg_payload, buf += seg_payload; | 278 | for (left = packet->length - seg_payload, buf += seg_payload; |
@@ -441,21 +430,14 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, | |||
441 | } | 430 | } |
442 | 431 | ||
443 | rmpp_mad = (struct ib_rmpp_mad *) packet->mad.data; | 432 | rmpp_mad = (struct ib_rmpp_mad *) packet->mad.data; |
444 | if (rmpp_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_ADM) { | 433 | hdr_len = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class); |
445 | hdr_len = IB_MGMT_SA_HDR; | 434 | if (!ib_is_mad_class_rmpp(rmpp_mad->mad_hdr.mgmt_class)) { |
446 | copy_offset = IB_MGMT_RMPP_HDR; | 435 | copy_offset = IB_MGMT_MAD_HDR; |
447 | rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & | 436 | rmpp_active = 0; |
448 | IB_MGMT_RMPP_FLAG_ACTIVE; | 437 | } else { |
449 | } else if (rmpp_mad->mad_hdr.mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START && | ||
450 | rmpp_mad->mad_hdr.mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END) { | ||
451 | hdr_len = IB_MGMT_VENDOR_HDR; | ||
452 | copy_offset = IB_MGMT_RMPP_HDR; | 438 | copy_offset = IB_MGMT_RMPP_HDR; |
453 | rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & | 439 | rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & |
454 | IB_MGMT_RMPP_FLAG_ACTIVE; | 440 | IB_MGMT_RMPP_FLAG_ACTIVE; |
455 | } else { | ||
456 | hdr_len = IB_MGMT_MAD_HDR; | ||
457 | copy_offset = IB_MGMT_MAD_HDR; | ||
458 | rmpp_active = 0; | ||
459 | } | 441 | } |
460 | 442 | ||
461 | data_len = count - sizeof (struct ib_user_mad) - hdr_len; | 443 | data_len = count - sizeof (struct ib_user_mad) - hdr_len; |
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c index f023d3936518..bc5bdcbe51b5 100644 --- a/drivers/infiniband/hw/mthca/mthca_av.c +++ b/drivers/infiniband/hw/mthca/mthca_av.c | |||
@@ -265,7 +265,7 @@ int __devinit mthca_init_av_table(struct mthca_dev *dev) | |||
265 | return -ENOMEM; | 265 | return -ENOMEM; |
266 | } | 266 | } |
267 | 267 | ||
268 | void __devexit mthca_cleanup_av_table(struct mthca_dev *dev) | 268 | void mthca_cleanup_av_table(struct mthca_dev *dev) |
269 | { | 269 | { |
270 | if (mthca_is_memfree(dev)) | 270 | if (mthca_is_memfree(dev)) |
271 | return; | 271 | return; |
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c index 76aabc5bf371..312cf90731ea 100644 --- a/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/drivers/infiniband/hw/mthca/mthca_cq.c | |||
@@ -973,7 +973,7 @@ int __devinit mthca_init_cq_table(struct mthca_dev *dev) | |||
973 | return err; | 973 | return err; |
974 | } | 974 | } |
975 | 975 | ||
976 | void __devexit mthca_cleanup_cq_table(struct mthca_dev *dev) | 976 | void mthca_cleanup_cq_table(struct mthca_dev *dev) |
977 | { | 977 | { |
978 | mthca_array_cleanup(&dev->cq_table.cq, dev->limits.num_cqs); | 978 | mthca_array_cleanup(&dev->cq_table.cq, dev->limits.num_cqs); |
979 | mthca_alloc_cleanup(&dev->cq_table.alloc); | 979 | mthca_alloc_cleanup(&dev->cq_table.alloc); |
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index cbdc348fb689..99f109c3815d 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c | |||
@@ -765,7 +765,7 @@ static int __devinit mthca_map_eq_regs(struct mthca_dev *dev) | |||
765 | 765 | ||
766 | } | 766 | } |
767 | 767 | ||
768 | static void __devexit mthca_unmap_eq_regs(struct mthca_dev *dev) | 768 | static void mthca_unmap_eq_regs(struct mthca_dev *dev) |
769 | { | 769 | { |
770 | if (mthca_is_memfree(dev)) { | 770 | if (mthca_is_memfree(dev)) { |
771 | mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) & | 771 | mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) & |
@@ -821,7 +821,7 @@ int __devinit mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt) | |||
821 | return ret; | 821 | return ret; |
822 | } | 822 | } |
823 | 823 | ||
824 | void __devexit mthca_unmap_eq_icm(struct mthca_dev *dev) | 824 | void mthca_unmap_eq_icm(struct mthca_dev *dev) |
825 | { | 825 | { |
826 | u8 status; | 826 | u8 status; |
827 | 827 | ||
@@ -954,7 +954,7 @@ err_out_free: | |||
954 | return err; | 954 | return err; |
955 | } | 955 | } |
956 | 956 | ||
957 | void __devexit mthca_cleanup_eq_table(struct mthca_dev *dev) | 957 | void mthca_cleanup_eq_table(struct mthca_dev *dev) |
958 | { | 958 | { |
959 | u8 status; | 959 | u8 status; |
960 | int i; | 960 | int i; |
diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c index 4ace6a392f41..dfb482eac9a2 100644 --- a/drivers/infiniband/hw/mthca/mthca_mad.c +++ b/drivers/infiniband/hw/mthca/mthca_mad.c | |||
@@ -271,7 +271,7 @@ err: | |||
271 | return PTR_ERR(agent); | 271 | return PTR_ERR(agent); |
272 | } | 272 | } |
273 | 273 | ||
274 | void mthca_free_agents(struct mthca_dev *dev) | 274 | void __devexit mthca_free_agents(struct mthca_dev *dev) |
275 | { | 275 | { |
276 | struct ib_mad_agent *agent; | 276 | struct ib_mad_agent *agent; |
277 | int p, q; | 277 | int p, q; |
diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c index 9965bda9afed..47ca8a9b7247 100644 --- a/drivers/infiniband/hw/mthca/mthca_mcg.c +++ b/drivers/infiniband/hw/mthca/mthca_mcg.c | |||
@@ -388,7 +388,7 @@ int __devinit mthca_init_mcg_table(struct mthca_dev *dev) | |||
388 | return 0; | 388 | return 0; |
389 | } | 389 | } |
390 | 390 | ||
391 | void __devexit mthca_cleanup_mcg_table(struct mthca_dev *dev) | 391 | void mthca_cleanup_mcg_table(struct mthca_dev *dev) |
392 | { | 392 | { |
393 | mthca_alloc_cleanup(&dev->mcg_table.alloc); | 393 | mthca_alloc_cleanup(&dev->mcg_table.alloc); |
394 | } | 394 | } |
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c index 698b62125765..25e1c1db9a40 100644 --- a/drivers/infiniband/hw/mthca/mthca_mr.c +++ b/drivers/infiniband/hw/mthca/mthca_mr.c | |||
@@ -170,7 +170,7 @@ err_out: | |||
170 | return -ENOMEM; | 170 | return -ENOMEM; |
171 | } | 171 | } |
172 | 172 | ||
173 | static void __devexit mthca_buddy_cleanup(struct mthca_buddy *buddy) | 173 | static void mthca_buddy_cleanup(struct mthca_buddy *buddy) |
174 | { | 174 | { |
175 | int i; | 175 | int i; |
176 | 176 | ||
@@ -866,7 +866,7 @@ err_mtt_buddy: | |||
866 | return err; | 866 | return err; |
867 | } | 867 | } |
868 | 868 | ||
869 | void __devexit mthca_cleanup_mr_table(struct mthca_dev *dev) | 869 | void mthca_cleanup_mr_table(struct mthca_dev *dev) |
870 | { | 870 | { |
871 | /* XXX check if any MRs are still allocated? */ | 871 | /* XXX check if any MRs are still allocated? */ |
872 | if (dev->limits.fmr_reserved_mtts) | 872 | if (dev->limits.fmr_reserved_mtts) |
diff --git a/drivers/infiniband/hw/mthca/mthca_pd.c b/drivers/infiniband/hw/mthca/mthca_pd.c index 105fc5faaddf..59df51614c85 100644 --- a/drivers/infiniband/hw/mthca/mthca_pd.c +++ b/drivers/infiniband/hw/mthca/mthca_pd.c | |||
@@ -77,7 +77,7 @@ int __devinit mthca_init_pd_table(struct mthca_dev *dev) | |||
77 | dev->limits.reserved_pds); | 77 | dev->limits.reserved_pds); |
78 | } | 78 | } |
79 | 79 | ||
80 | void __devexit mthca_cleanup_pd_table(struct mthca_dev *dev) | 80 | void mthca_cleanup_pd_table(struct mthca_dev *dev) |
81 | { | 81 | { |
82 | /* XXX check if any PDs are still allocated? */ | 82 | /* XXX check if any PDs are still allocated? */ |
83 | mthca_alloc_cleanup(&dev->pd_table.alloc); | 83 | mthca_alloc_cleanup(&dev->pd_table.alloc); |
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 1bc2678c2fae..057c8e6af87b 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c | |||
@@ -2204,7 +2204,7 @@ int __devinit mthca_init_qp_table(struct mthca_dev *dev) | |||
2204 | return err; | 2204 | return err; |
2205 | } | 2205 | } |
2206 | 2206 | ||
2207 | void __devexit mthca_cleanup_qp_table(struct mthca_dev *dev) | 2207 | void mthca_cleanup_qp_table(struct mthca_dev *dev) |
2208 | { | 2208 | { |
2209 | int i; | 2209 | int i; |
2210 | u8 status; | 2210 | u8 status; |
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 0cfd15802217..2dd3aea05341 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c | |||
@@ -206,7 +206,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, | |||
206 | roundup_pow_of_two(sizeof (struct mthca_next_seg) + | 206 | roundup_pow_of_two(sizeof (struct mthca_next_seg) + |
207 | srq->max_gs * sizeof (struct mthca_data_seg))); | 207 | srq->max_gs * sizeof (struct mthca_data_seg))); |
208 | 208 | ||
209 | if (ds > dev->limits.max_desc_sz) | 209 | if (!mthca_is_memfree(dev) && (ds > dev->limits.max_desc_sz)) |
210 | return -EINVAL; | 210 | return -EINVAL; |
211 | 211 | ||
212 | srq->wqe_shift = long_log2(ds); | 212 | srq->wqe_shift = long_log2(ds); |
@@ -684,7 +684,7 @@ int __devinit mthca_init_srq_table(struct mthca_dev *dev) | |||
684 | return err; | 684 | return err; |
685 | } | 685 | } |
686 | 686 | ||
687 | void __devexit mthca_cleanup_srq_table(struct mthca_dev *dev) | 687 | void mthca_cleanup_srq_table(struct mthca_dev *dev) |
688 | { | 688 | { |
689 | if (!(dev->mthca_flags & MTHCA_FLAG_SRQ)) | 689 | if (!(dev->mthca_flags & MTHCA_FLAG_SRQ)) |
690 | return; | 690 | return; |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 53a32f65788d..9b0bd7c746ca 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -723,7 +723,7 @@ static int ipoib_hard_header(struct sk_buff *skb, | |||
723 | * destination address onto the front of the skb so we can | 723 | * destination address onto the front of the skb so we can |
724 | * figure out where to send the packet later. | 724 | * figure out where to send the packet later. |
725 | */ | 725 | */ |
726 | if (!skb->dst || !skb->dst->neighbour) { | 726 | if ((!skb->dst || !skb->dst->neighbour) && daddr) { |
727 | struct ipoib_pseudoheader *phdr = | 727 | struct ipoib_pseudoheader *phdr = |
728 | (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr); | 728 | (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr); |
729 | memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN); | 729 | memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN); |
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 61924cc30e55..fd8a95a9c5d3 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
@@ -607,10 +607,10 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd, | |||
607 | */ | 607 | */ |
608 | if (likely(scmnd->use_sg)) { | 608 | if (likely(scmnd->use_sg)) { |
609 | nents = scmnd->use_sg; | 609 | nents = scmnd->use_sg; |
610 | scat = (struct scatterlist *) scmnd->request_buffer; | 610 | scat = scmnd->request_buffer; |
611 | } else { | 611 | } else { |
612 | nents = 1; | 612 | nents = 1; |
613 | scat = (struct scatterlist *) scmnd->request_buffer; | 613 | scat = &req->fake_sg; |
614 | } | 614 | } |
615 | 615 | ||
616 | dma_unmap_sg(target->srp_host->dev->dma_device, scat, nents, | 616 | dma_unmap_sg(target->srp_host->dev->dma_device, scat, nents, |
diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c index 95d81d86d8b7..835dff0bafdc 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/scsi/libata-bmdma.c | |||
@@ -703,6 +703,7 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int | |||
703 | struct ata_probe_ent *probe_ent = | 703 | struct ata_probe_ent *probe_ent = |
704 | ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]); | 704 | ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]); |
705 | int p = 0; | 705 | int p = 0; |
706 | unsigned long bmdma; | ||
706 | 707 | ||
707 | if (!probe_ent) | 708 | if (!probe_ent) |
708 | return NULL; | 709 | return NULL; |
@@ -716,7 +717,12 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int | |||
716 | probe_ent->port[p].altstatus_addr = | 717 | probe_ent->port[p].altstatus_addr = |
717 | probe_ent->port[p].ctl_addr = | 718 | probe_ent->port[p].ctl_addr = |
718 | pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; | 719 | pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; |
719 | probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4); | 720 | bmdma = pci_resource_start(pdev, 4); |
721 | if (bmdma) { | ||
722 | if (inb(bmdma + 2) & 0x80) | ||
723 | probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; | ||
724 | probe_ent->port[p].bmdma_addr = bmdma; | ||
725 | } | ||
720 | ata_std_ports(&probe_ent->port[p]); | 726 | ata_std_ports(&probe_ent->port[p]); |
721 | p++; | 727 | p++; |
722 | } | 728 | } |
@@ -726,7 +732,13 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int | |||
726 | probe_ent->port[p].altstatus_addr = | 732 | probe_ent->port[p].altstatus_addr = |
727 | probe_ent->port[p].ctl_addr = | 733 | probe_ent->port[p].ctl_addr = |
728 | pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; | 734 | pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; |
729 | probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4) + 8; | 735 | bmdma = pci_resource_start(pdev, 4); |
736 | if (bmdma) { | ||
737 | bmdma += 8; | ||
738 | if(inb(bmdma + 2) & 0x80) | ||
739 | probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; | ||
740 | probe_ent->port[p].bmdma_addr = bmdma; | ||
741 | } | ||
730 | ata_std_ports(&probe_ent->port[p]); | 742 | ata_std_ports(&probe_ent->port[p]); |
731 | p++; | 743 | p++; |
732 | } | 744 | } |
@@ -740,6 +752,7 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, | |||
740 | struct ata_port_info *port, int port_num) | 752 | struct ata_port_info *port, int port_num) |
741 | { | 753 | { |
742 | struct ata_probe_ent *probe_ent; | 754 | struct ata_probe_ent *probe_ent; |
755 | unsigned long bmdma; | ||
743 | 756 | ||
744 | probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port); | 757 | probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port); |
745 | if (!probe_ent) | 758 | if (!probe_ent) |
@@ -766,8 +779,13 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, | |||
766 | break; | 779 | break; |
767 | } | 780 | } |
768 | 781 | ||
769 | probe_ent->port[0].bmdma_addr = | 782 | bmdma = pci_resource_start(pdev, 4); |
770 | pci_resource_start(pdev, 4) + 8 * port_num; | 783 | if (bmdma != 0) { |
784 | bmdma += 8 * port_num; | ||
785 | probe_ent->port[0].bmdma_addr = bmdma; | ||
786 | if (inb(bmdma + 2) & 0x80) | ||
787 | probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; | ||
788 | } | ||
771 | ata_std_ports(&probe_ent->port[0]); | 789 | ata_std_ports(&probe_ent->port[0]); |
772 | 790 | ||
773 | return probe_ent; | 791 | return probe_ent; |
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d279666dcb38..21b0ed583b8a 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -62,7 +62,9 @@ | |||
62 | #include "libata.h" | 62 | #include "libata.h" |
63 | 63 | ||
64 | static unsigned int ata_dev_init_params(struct ata_port *ap, | 64 | static unsigned int ata_dev_init_params(struct ata_port *ap, |
65 | struct ata_device *dev); | 65 | struct ata_device *dev, |
66 | u16 heads, | ||
67 | u16 sectors); | ||
66 | static void ata_set_mode(struct ata_port *ap); | 68 | static void ata_set_mode(struct ata_port *ap); |
67 | static unsigned int ata_dev_set_xfermode(struct ata_port *ap, | 69 | static unsigned int ata_dev_set_xfermode(struct ata_port *ap, |
68 | struct ata_device *dev); | 70 | struct ata_device *dev); |
@@ -1081,9 +1083,8 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) | |||
1081 | * | 1083 | * |
1082 | * Read ID data from the specified device. ATA_CMD_ID_ATA is | 1084 | * Read ID data from the specified device. ATA_CMD_ID_ATA is |
1083 | * performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI | 1085 | * performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI |
1084 | * devices. This function also takes care of EDD signature | 1086 | * devices. This function also issues ATA_CMD_INIT_DEV_PARAMS |
1085 | * misreporting (to be removed once EDD support is gone) and | 1087 | * for pre-ATA4 drives. |
1086 | * issues ATA_CMD_INIT_DEV_PARAMS for pre-ATA4 drives. | ||
1087 | * | 1088 | * |
1088 | * LOCKING: | 1089 | * LOCKING: |
1089 | * Kernel thread context (may sleep) | 1090 | * Kernel thread context (may sleep) |
@@ -1095,7 +1096,6 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, | |||
1095 | unsigned int *p_class, int post_reset, u16 **p_id) | 1096 | unsigned int *p_class, int post_reset, u16 **p_id) |
1096 | { | 1097 | { |
1097 | unsigned int class = *p_class; | 1098 | unsigned int class = *p_class; |
1098 | unsigned int using_edd; | ||
1099 | struct ata_taskfile tf; | 1099 | struct ata_taskfile tf; |
1100 | unsigned int err_mask = 0; | 1100 | unsigned int err_mask = 0; |
1101 | u16 *id; | 1101 | u16 *id; |
@@ -1104,12 +1104,6 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, | |||
1104 | 1104 | ||
1105 | DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno); | 1105 | DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno); |
1106 | 1106 | ||
1107 | if (ap->ops->probe_reset || | ||
1108 | ap->flags & (ATA_FLAG_SRST | ATA_FLAG_SATA_RESET)) | ||
1109 | using_edd = 0; | ||
1110 | else | ||
1111 | using_edd = 1; | ||
1112 | |||
1113 | ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ | 1107 | ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ |
1114 | 1108 | ||
1115 | id = kmalloc(sizeof(id[0]) * ATA_ID_WORDS, GFP_KERNEL); | 1109 | id = kmalloc(sizeof(id[0]) * ATA_ID_WORDS, GFP_KERNEL); |
@@ -1139,39 +1133,16 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, | |||
1139 | 1133 | ||
1140 | err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE, | 1134 | err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE, |
1141 | id, sizeof(id[0]) * ATA_ID_WORDS); | 1135 | id, sizeof(id[0]) * ATA_ID_WORDS); |
1142 | |||
1143 | if (err_mask) { | 1136 | if (err_mask) { |
1144 | rc = -EIO; | 1137 | rc = -EIO; |
1145 | reason = "I/O error"; | 1138 | reason = "I/O error"; |
1146 | |||
1147 | if (err_mask & ~AC_ERR_DEV) | ||
1148 | goto err_out; | ||
1149 | |||
1150 | /* | ||
1151 | * arg! EDD works for all test cases, but seems to return | ||
1152 | * the ATA signature for some ATAPI devices. Until the | ||
1153 | * reason for this is found and fixed, we fix up the mess | ||
1154 | * here. If IDENTIFY DEVICE returns command aborted | ||
1155 | * (as ATAPI devices do), then we issue an | ||
1156 | * IDENTIFY PACKET DEVICE. | ||
1157 | * | ||
1158 | * ATA software reset (SRST, the default) does not appear | ||
1159 | * to have this problem. | ||
1160 | */ | ||
1161 | if ((using_edd) && (class == ATA_DEV_ATA)) { | ||
1162 | u8 err = tf.feature; | ||
1163 | if (err & ATA_ABORTED) { | ||
1164 | class = ATA_DEV_ATAPI; | ||
1165 | goto retry; | ||
1166 | } | ||
1167 | } | ||
1168 | goto err_out; | 1139 | goto err_out; |
1169 | } | 1140 | } |
1170 | 1141 | ||
1171 | swap_buf_le16(id, ATA_ID_WORDS); | 1142 | swap_buf_le16(id, ATA_ID_WORDS); |
1172 | 1143 | ||
1173 | /* sanity check */ | 1144 | /* sanity check */ |
1174 | if ((class == ATA_DEV_ATA) != ata_id_is_ata(id)) { | 1145 | if ((class == ATA_DEV_ATA) != (ata_id_is_ata(id) | ata_id_is_cfa(id))) { |
1175 | rc = -EINVAL; | 1146 | rc = -EINVAL; |
1176 | reason = "device reports illegal type"; | 1147 | reason = "device reports illegal type"; |
1177 | goto err_out; | 1148 | goto err_out; |
@@ -1187,7 +1158,7 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, | |||
1187 | * Some drives were very specific about that exact sequence. | 1158 | * Some drives were very specific about that exact sequence. |
1188 | */ | 1159 | */ |
1189 | if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) { | 1160 | if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) { |
1190 | err_mask = ata_dev_init_params(ap, dev); | 1161 | err_mask = ata_dev_init_params(ap, dev, id[3], id[6]); |
1191 | if (err_mask) { | 1162 | if (err_mask) { |
1192 | rc = -EIO; | 1163 | rc = -EIO; |
1193 | reason = "INIT_DEV_PARAMS failed"; | 1164 | reason = "INIT_DEV_PARAMS failed"; |
@@ -1440,7 +1411,11 @@ static int ata_bus_probe(struct ata_port *ap) | |||
1440 | if (!found) | 1411 | if (!found) |
1441 | goto err_out_disable; | 1412 | goto err_out_disable; |
1442 | 1413 | ||
1443 | ata_set_mode(ap); | 1414 | if (ap->ops->set_mode) |
1415 | ap->ops->set_mode(ap); | ||
1416 | else | ||
1417 | ata_set_mode(ap); | ||
1418 | |||
1444 | if (ap->flags & ATA_FLAG_PORT_DISABLED) | 1419 | if (ap->flags & ATA_FLAG_PORT_DISABLED) |
1445 | goto err_out_disable; | 1420 | goto err_out_disable; |
1446 | 1421 | ||
@@ -1845,7 +1820,7 @@ static void ata_host_set_dma(struct ata_port *ap) | |||
1845 | */ | 1820 | */ |
1846 | static void ata_set_mode(struct ata_port *ap) | 1821 | static void ata_set_mode(struct ata_port *ap) |
1847 | { | 1822 | { |
1848 | int i, rc; | 1823 | int i, rc, used_dma = 0; |
1849 | 1824 | ||
1850 | /* step 1: calculate xfer_mask */ | 1825 | /* step 1: calculate xfer_mask */ |
1851 | for (i = 0; i < ATA_MAX_DEVICES; i++) { | 1826 | for (i = 0; i < ATA_MAX_DEVICES; i++) { |
@@ -1863,6 +1838,9 @@ static void ata_set_mode(struct ata_port *ap) | |||
1863 | dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask); | 1838 | dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask); |
1864 | dev->pio_mode = ata_xfer_mask2mode(pio_mask); | 1839 | dev->pio_mode = ata_xfer_mask2mode(pio_mask); |
1865 | dev->dma_mode = ata_xfer_mask2mode(dma_mask); | 1840 | dev->dma_mode = ata_xfer_mask2mode(dma_mask); |
1841 | |||
1842 | if (dev->dma_mode) | ||
1843 | used_dma = 1; | ||
1866 | } | 1844 | } |
1867 | 1845 | ||
1868 | /* step 2: always set host PIO timings */ | 1846 | /* step 2: always set host PIO timings */ |
@@ -1884,6 +1862,17 @@ static void ata_set_mode(struct ata_port *ap) | |||
1884 | goto err_out; | 1862 | goto err_out; |
1885 | } | 1863 | } |
1886 | 1864 | ||
1865 | /* | ||
1866 | * Record simplex status. If we selected DMA then the other | ||
1867 | * host channels are not permitted to do so. | ||
1868 | */ | ||
1869 | |||
1870 | if (used_dma && (ap->host_set->flags & ATA_HOST_SIMPLEX)) | ||
1871 | ap->host_set->simplex_claimed = 1; | ||
1872 | |||
1873 | /* | ||
1874 | * Chip specific finalisation | ||
1875 | */ | ||
1887 | if (ap->ops->post_set_mode) | 1876 | if (ap->ops->post_set_mode) |
1888 | ap->ops->post_set_mode(ap); | 1877 | ap->ops->post_set_mode(ap); |
1889 | 1878 | ||
@@ -2005,45 +1994,6 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask) | |||
2005 | ap->ops->dev_select(ap, 0); | 1994 | ap->ops->dev_select(ap, 0); |
2006 | } | 1995 | } |
2007 | 1996 | ||
2008 | /** | ||
2009 | * ata_bus_edd - Issue EXECUTE DEVICE DIAGNOSTIC command. | ||
2010 | * @ap: Port to reset and probe | ||
2011 | * | ||
2012 | * Use the EXECUTE DEVICE DIAGNOSTIC command to reset and | ||
2013 | * probe the bus. Not often used these days. | ||
2014 | * | ||
2015 | * LOCKING: | ||
2016 | * PCI/etc. bus probe sem. | ||
2017 | * Obtains host_set lock. | ||
2018 | * | ||
2019 | */ | ||
2020 | |||
2021 | static unsigned int ata_bus_edd(struct ata_port *ap) | ||
2022 | { | ||
2023 | struct ata_taskfile tf; | ||
2024 | unsigned long flags; | ||
2025 | |||
2026 | /* set up execute-device-diag (bus reset) taskfile */ | ||
2027 | /* also, take interrupts to a known state (disabled) */ | ||
2028 | DPRINTK("execute-device-diag\n"); | ||
2029 | ata_tf_init(ap, &tf, 0); | ||
2030 | tf.ctl |= ATA_NIEN; | ||
2031 | tf.command = ATA_CMD_EDD; | ||
2032 | tf.protocol = ATA_PROT_NODATA; | ||
2033 | |||
2034 | /* do bus reset */ | ||
2035 | spin_lock_irqsave(&ap->host_set->lock, flags); | ||
2036 | ata_tf_to_host(ap, &tf); | ||
2037 | spin_unlock_irqrestore(&ap->host_set->lock, flags); | ||
2038 | |||
2039 | /* spec says at least 2ms. but who knows with those | ||
2040 | * crazy ATAPI devices... | ||
2041 | */ | ||
2042 | msleep(150); | ||
2043 | |||
2044 | return ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); | ||
2045 | } | ||
2046 | |||
2047 | static unsigned int ata_bus_softreset(struct ata_port *ap, | 1997 | static unsigned int ata_bus_softreset(struct ata_port *ap, |
2048 | unsigned int devmask) | 1998 | unsigned int devmask) |
2049 | { | 1999 | { |
@@ -2078,13 +2028,12 @@ static unsigned int ata_bus_softreset(struct ata_port *ap, | |||
2078 | */ | 2028 | */ |
2079 | msleep(150); | 2029 | msleep(150); |
2080 | 2030 | ||
2081 | |||
2082 | /* Before we perform post reset processing we want to see if | 2031 | /* Before we perform post reset processing we want to see if |
2083 | the bus shows 0xFF because the odd clown forgets the D7 pulldown | 2032 | * the bus shows 0xFF because the odd clown forgets the D7 |
2084 | resistor */ | 2033 | * pulldown resistor. |
2085 | 2034 | */ | |
2086 | if (ata_check_status(ap) == 0xFF) | 2035 | if (ata_check_status(ap) == 0xFF) |
2087 | return 1; /* Positive is failure for some reason */ | 2036 | return AC_ERR_OTHER; |
2088 | 2037 | ||
2089 | ata_bus_post_reset(ap, devmask); | 2038 | ata_bus_post_reset(ap, devmask); |
2090 | 2039 | ||
@@ -2116,7 +2065,7 @@ void ata_bus_reset(struct ata_port *ap) | |||
2116 | struct ata_ioports *ioaddr = &ap->ioaddr; | 2065 | struct ata_ioports *ioaddr = &ap->ioaddr; |
2117 | unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; | 2066 | unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; |
2118 | u8 err; | 2067 | u8 err; |
2119 | unsigned int dev0, dev1 = 0, rc = 0, devmask = 0; | 2068 | unsigned int dev0, dev1 = 0, devmask = 0; |
2120 | 2069 | ||
2121 | DPRINTK("ENTER, host %u, port %u\n", ap->id, ap->port_no); | 2070 | DPRINTK("ENTER, host %u, port %u\n", ap->id, ap->port_no); |
2122 | 2071 | ||
@@ -2139,18 +2088,8 @@ void ata_bus_reset(struct ata_port *ap) | |||
2139 | 2088 | ||
2140 | /* issue bus reset */ | 2089 | /* issue bus reset */ |
2141 | if (ap->flags & ATA_FLAG_SRST) | 2090 | if (ap->flags & ATA_FLAG_SRST) |
2142 | rc = ata_bus_softreset(ap, devmask); | 2091 | if (ata_bus_softreset(ap, devmask)) |
2143 | else if ((ap->flags & ATA_FLAG_SATA_RESET) == 0) { | 2092 | goto err_out; |
2144 | /* set up device control */ | ||
2145 | if (ap->flags & ATA_FLAG_MMIO) | ||
2146 | writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr); | ||
2147 | else | ||
2148 | outb(ap->ctl, ioaddr->ctl_addr); | ||
2149 | rc = ata_bus_edd(ap); | ||
2150 | } | ||
2151 | |||
2152 | if (rc) | ||
2153 | goto err_out; | ||
2154 | 2093 | ||
2155 | /* | 2094 | /* |
2156 | * determine by signature whether we have ATA or ATAPI devices | 2095 | * determine by signature whether we have ATA or ATAPI devices |
@@ -2223,9 +2162,9 @@ static int sata_phy_resume(struct ata_port *ap) | |||
2223 | * so makes reset sequence different from the original | 2162 | * so makes reset sequence different from the original |
2224 | * ->phy_reset implementation and Jeff nervous. :-P | 2163 | * ->phy_reset implementation and Jeff nervous. :-P |
2225 | */ | 2164 | */ |
2226 | extern void ata_std_probeinit(struct ata_port *ap) | 2165 | void ata_std_probeinit(struct ata_port *ap) |
2227 | { | 2166 | { |
2228 | if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) { | 2167 | if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) { |
2229 | sata_phy_resume(ap); | 2168 | sata_phy_resume(ap); |
2230 | if (sata_dev_present(ap)) | 2169 | if (sata_dev_present(ap)) |
2231 | ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); | 2170 | ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); |
@@ -2714,18 +2653,23 @@ static int ata_dma_blacklisted(const struct ata_device *dev) | |||
2714 | * known limits including host controller limits, device | 2653 | * known limits including host controller limits, device |
2715 | * blacklist, etc... | 2654 | * blacklist, etc... |
2716 | * | 2655 | * |
2656 | * FIXME: The current implementation limits all transfer modes to | ||
2657 | * the fastest of the lowested device on the port. This is not | ||
2658 | * required on most controllers. | ||
2659 | * | ||
2717 | * LOCKING: | 2660 | * LOCKING: |
2718 | * None. | 2661 | * None. |
2719 | */ | 2662 | */ |
2720 | static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) | 2663 | static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) |
2721 | { | 2664 | { |
2665 | struct ata_host_set *hs = ap->host_set; | ||
2722 | unsigned long xfer_mask; | 2666 | unsigned long xfer_mask; |
2723 | int i; | 2667 | int i; |
2724 | 2668 | ||
2725 | xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask, | 2669 | xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask, |
2726 | ap->udma_mask); | 2670 | ap->udma_mask); |
2727 | 2671 | ||
2728 | /* use port-wide xfermask for now */ | 2672 | /* FIXME: Use port-wide xfermask for now */ |
2729 | for (i = 0; i < ATA_MAX_DEVICES; i++) { | 2673 | for (i = 0; i < ATA_MAX_DEVICES; i++) { |
2730 | struct ata_device *d = &ap->device[i]; | 2674 | struct ata_device *d = &ap->device[i]; |
2731 | if (!ata_dev_present(d)) | 2675 | if (!ata_dev_present(d)) |
@@ -2735,12 +2679,23 @@ static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) | |||
2735 | xfer_mask &= ata_id_xfermask(d->id); | 2679 | xfer_mask &= ata_id_xfermask(d->id); |
2736 | if (ata_dma_blacklisted(d)) | 2680 | if (ata_dma_blacklisted(d)) |
2737 | xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); | 2681 | xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); |
2682 | /* Apply cable rule here. Don't apply it early because when | ||
2683 | we handle hot plug the cable type can itself change */ | ||
2684 | if (ap->cbl == ATA_CBL_PATA40) | ||
2685 | xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA); | ||
2738 | } | 2686 | } |
2739 | 2687 | ||
2740 | if (ata_dma_blacklisted(dev)) | 2688 | if (ata_dma_blacklisted(dev)) |
2741 | printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, " | 2689 | printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, " |
2742 | "disabling DMA\n", ap->id, dev->devno); | 2690 | "disabling DMA\n", ap->id, dev->devno); |
2743 | 2691 | ||
2692 | if (hs->flags & ATA_HOST_SIMPLEX) { | ||
2693 | if (hs->simplex_claimed) | ||
2694 | xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); | ||
2695 | } | ||
2696 | if (ap->ops->mode_filter) | ||
2697 | xfer_mask = ap->ops->mode_filter(ap, dev, xfer_mask); | ||
2698 | |||
2744 | ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask, | 2699 | ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask, |
2745 | &dev->udma_mask); | 2700 | &dev->udma_mask); |
2746 | } | 2701 | } |
@@ -2795,16 +2750,16 @@ static unsigned int ata_dev_set_xfermode(struct ata_port *ap, | |||
2795 | */ | 2750 | */ |
2796 | 2751 | ||
2797 | static unsigned int ata_dev_init_params(struct ata_port *ap, | 2752 | static unsigned int ata_dev_init_params(struct ata_port *ap, |
2798 | struct ata_device *dev) | 2753 | struct ata_device *dev, |
2754 | u16 heads, | ||
2755 | u16 sectors) | ||
2799 | { | 2756 | { |
2800 | struct ata_taskfile tf; | 2757 | struct ata_taskfile tf; |
2801 | unsigned int err_mask; | 2758 | unsigned int err_mask; |
2802 | u16 sectors = dev->id[6]; | ||
2803 | u16 heads = dev->id[3]; | ||
2804 | 2759 | ||
2805 | /* Number of sectors per track 1-255. Number of heads 1-16 */ | 2760 | /* Number of sectors per track 1-255. Number of heads 1-16 */ |
2806 | if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16) | 2761 | if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16) |
2807 | return 0; | 2762 | return AC_ERR_INVALID; |
2808 | 2763 | ||
2809 | /* set up init dev params taskfile */ | 2764 | /* set up init dev params taskfile */ |
2810 | DPRINTK("init dev params \n"); | 2765 | DPRINTK("init dev params \n"); |
@@ -4536,6 +4491,14 @@ static struct ata_port * ata_host_add(const struct ata_probe_ent *ent, | |||
4536 | int rc; | 4491 | int rc; |
4537 | 4492 | ||
4538 | DPRINTK("ENTER\n"); | 4493 | DPRINTK("ENTER\n"); |
4494 | |||
4495 | if (!ent->port_ops->probe_reset && | ||
4496 | !(ent->host_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) { | ||
4497 | printk(KERN_ERR "ata%u: no reset mechanism available\n", | ||
4498 | port_no); | ||
4499 | return NULL; | ||
4500 | } | ||
4501 | |||
4539 | host = scsi_host_alloc(ent->sht, sizeof(struct ata_port)); | 4502 | host = scsi_host_alloc(ent->sht, sizeof(struct ata_port)); |
4540 | if (!host) | 4503 | if (!host) |
4541 | return NULL; | 4504 | return NULL; |
@@ -4596,6 +4559,7 @@ int ata_device_add(const struct ata_probe_ent *ent) | |||
4596 | host_set->mmio_base = ent->mmio_base; | 4559 | host_set->mmio_base = ent->mmio_base; |
4597 | host_set->private_data = ent->private_data; | 4560 | host_set->private_data = ent->private_data; |
4598 | host_set->ops = ent->port_ops; | 4561 | host_set->ops = ent->port_ops; |
4562 | host_set->flags = ent->host_set_flags; | ||
4599 | 4563 | ||
4600 | /* register each port bound to this device */ | 4564 | /* register each port bound to this device */ |
4601 | for (i = 0; i < ent->n_ports; i++) { | 4565 | for (i = 0; i < ent->n_ports; i++) { |
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 275ed9bd898c..fa901fd65085 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c | |||
@@ -1010,7 +1010,7 @@ static void mv_fill_sg(struct ata_queued_cmd *qc) | |||
1010 | 1010 | ||
1011 | pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff); | 1011 | pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff); |
1012 | pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16); | 1012 | pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16); |
1013 | pp->sg_tbl[i].flags_size = cpu_to_le32(len); | 1013 | pp->sg_tbl[i].flags_size = cpu_to_le32(len & 0xffff); |
1014 | 1014 | ||
1015 | sg_len -= len; | 1015 | sg_len -= len; |
1016 | addr += len; | 1016 | addr += len; |
@@ -1350,7 +1350,6 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, | |||
1350 | { | 1350 | { |
1351 | void __iomem *mmio = host_set->mmio_base; | 1351 | void __iomem *mmio = host_set->mmio_base; |
1352 | void __iomem *hc_mmio = mv_hc_base(mmio, hc); | 1352 | void __iomem *hc_mmio = mv_hc_base(mmio, hc); |
1353 | struct ata_port *ap; | ||
1354 | struct ata_queued_cmd *qc; | 1353 | struct ata_queued_cmd *qc; |
1355 | u32 hc_irq_cause; | 1354 | u32 hc_irq_cause; |
1356 | int shift, port, port0, hard_port, handled; | 1355 | int shift, port, port0, hard_port, handled; |
@@ -1373,25 +1372,32 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, | |||
1373 | 1372 | ||
1374 | for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) { | 1373 | for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) { |
1375 | u8 ata_status = 0; | 1374 | u8 ata_status = 0; |
1376 | ap = host_set->ports[port]; | 1375 | struct ata_port *ap = host_set->ports[port]; |
1376 | struct mv_port_priv *pp = ap->private_data; | ||
1377 | |||
1377 | hard_port = port & MV_PORT_MASK; /* range 0-3 */ | 1378 | hard_port = port & MV_PORT_MASK; /* range 0-3 */ |
1378 | handled = 0; /* ensure ata_status is set if handled++ */ | 1379 | handled = 0; /* ensure ata_status is set if handled++ */ |
1379 | 1380 | ||
1380 | if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) { | 1381 | /* Note that DEV_IRQ might happen spuriously during EDMA, |
1381 | /* new CRPB on the queue; just one at a time until NCQ | 1382 | * and should be ignored in such cases. We could mask it, |
1382 | */ | 1383 | * but it's pretty rare and may not be worth the overhead. |
1383 | ata_status = mv_get_crpb_status(ap); | 1384 | */ |
1384 | handled++; | 1385 | if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) { |
1385 | } else if ((DEV_IRQ << hard_port) & hc_irq_cause) { | 1386 | /* EDMA: check for response queue interrupt */ |
1386 | /* received ATA IRQ; read the status reg to clear INTRQ | 1387 | if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) { |
1387 | */ | 1388 | ata_status = mv_get_crpb_status(ap); |
1388 | ata_status = readb((void __iomem *) | 1389 | handled = 1; |
1390 | } | ||
1391 | } else { | ||
1392 | /* PIO: check for device (drive) interrupt */ | ||
1393 | if ((DEV_IRQ << hard_port) & hc_irq_cause) { | ||
1394 | ata_status = readb((void __iomem *) | ||
1389 | ap->ioaddr.status_addr); | 1395 | ap->ioaddr.status_addr); |
1390 | handled++; | 1396 | handled = 1; |
1397 | } | ||
1391 | } | 1398 | } |
1392 | 1399 | ||
1393 | if (ap && | 1400 | if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)) |
1394 | (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) | ||
1395 | continue; | 1401 | continue; |
1396 | 1402 | ||
1397 | err_mask = ac_err_mask(ata_status); | 1403 | err_mask = ac_err_mask(ata_status); |
@@ -1403,12 +1409,12 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, | |||
1403 | if ((PORT0_ERR << shift) & relevant) { | 1409 | if ((PORT0_ERR << shift) & relevant) { |
1404 | mv_err_intr(ap); | 1410 | mv_err_intr(ap); |
1405 | err_mask |= AC_ERR_OTHER; | 1411 | err_mask |= AC_ERR_OTHER; |
1406 | handled++; | 1412 | handled = 1; |
1407 | } | 1413 | } |
1408 | 1414 | ||
1409 | if (handled && ap) { | 1415 | if (handled) { |
1410 | qc = ata_qc_from_tag(ap, ap->active_tag); | 1416 | qc = ata_qc_from_tag(ap, ap->active_tag); |
1411 | if (NULL != qc) { | 1417 | if (qc && (qc->flags & ATA_QCFLAG_ACTIVE)) { |
1412 | VPRINTK("port %u IRQ found for qc, " | 1418 | VPRINTK("port %u IRQ found for qc, " |
1413 | "ata_status 0x%x\n", port,ata_status); | 1419 | "ata_status 0x%x\n", port,ata_status); |
1414 | /* mark qc status appropriately */ | 1420 | /* mark qc status appropriately */ |
diff --git a/fs/Makefile b/fs/Makefile index 080b3867be4d..f3a4f7077175 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
@@ -10,7 +10,7 @@ obj-y := open.o read_write.o file_table.o buffer.o bio.o super.o \ | |||
10 | ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \ | 10 | ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \ |
11 | attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \ | 11 | attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \ |
12 | seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \ | 12 | seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \ |
13 | ioprio.o pnode.o drop_caches.o | 13 | ioprio.o pnode.o drop_caches.o splice.o |
14 | 14 | ||
15 | obj-$(CONFIG_INOTIFY) += inotify.o | 15 | obj-$(CONFIG_INOTIFY) += inotify.o |
16 | obj-$(CONFIG_EPOLL) += eventpoll.o | 16 | obj-$(CONFIG_EPOLL) += eventpoll.o |
diff --git a/fs/ext2/file.c b/fs/ext2/file.c index 509cceca04db..23e2c7ccec1d 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c | |||
@@ -53,6 +53,8 @@ const struct file_operations ext2_file_operations = { | |||
53 | .readv = generic_file_readv, | 53 | .readv = generic_file_readv, |
54 | .writev = generic_file_writev, | 54 | .writev = generic_file_writev, |
55 | .sendfile = generic_file_sendfile, | 55 | .sendfile = generic_file_sendfile, |
56 | .splice_read = generic_file_splice_read, | ||
57 | .splice_write = generic_file_splice_write, | ||
56 | }; | 58 | }; |
57 | 59 | ||
58 | #ifdef CONFIG_EXT2_FS_XIP | 60 | #ifdef CONFIG_EXT2_FS_XIP |
diff --git a/fs/ext3/file.c b/fs/ext3/file.c index 783a796220bb..1efefb630ea9 100644 --- a/fs/ext3/file.c +++ b/fs/ext3/file.c | |||
@@ -119,6 +119,8 @@ const struct file_operations ext3_file_operations = { | |||
119 | .release = ext3_release_file, | 119 | .release = ext3_release_file, |
120 | .fsync = ext3_sync_file, | 120 | .fsync = ext3_sync_file, |
121 | .sendfile = generic_file_sendfile, | 121 | .sendfile = generic_file_sendfile, |
122 | .splice_read = generic_file_splice_read, | ||
123 | .splice_write = generic_file_splice_write, | ||
122 | }; | 124 | }; |
123 | 125 | ||
124 | struct inode_operations ext3_file_inode_operations = { | 126 | struct inode_operations ext3_file_inode_operations = { |
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/pipe_fs_i.h> | 15 | #include <linux/pipe_fs_i.h> |
16 | #include <linux/uio.h> | 16 | #include <linux/uio.h> |
17 | #include <linux/highmem.h> | 17 | #include <linux/highmem.h> |
18 | #include <linux/pagemap.h> | ||
18 | 19 | ||
19 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
20 | #include <asm/ioctls.h> | 21 | #include <asm/ioctls.h> |
@@ -94,11 +95,20 @@ static void anon_pipe_buf_release(struct pipe_inode_info *info, struct pipe_buff | |||
94 | { | 95 | { |
95 | struct page *page = buf->page; | 96 | struct page *page = buf->page; |
96 | 97 | ||
97 | if (info->tmp_page) { | 98 | /* |
98 | __free_page(page); | 99 | * If nobody else uses this page, and we don't already have a |
100 | * temporary page, let's keep track of it as a one-deep | ||
101 | * allocation cache | ||
102 | */ | ||
103 | if (page_count(page) == 1 && !info->tmp_page) { | ||
104 | info->tmp_page = page; | ||
99 | return; | 105 | return; |
100 | } | 106 | } |
101 | info->tmp_page = page; | 107 | |
108 | /* | ||
109 | * Otherwise just release our reference to it | ||
110 | */ | ||
111 | page_cache_release(page); | ||
102 | } | 112 | } |
103 | 113 | ||
104 | static void *anon_pipe_buf_map(struct file *file, struct pipe_inode_info *info, struct pipe_buffer *buf) | 114 | static void *anon_pipe_buf_map(struct file *file, struct pipe_inode_info *info, struct pipe_buffer *buf) |
@@ -111,11 +121,19 @@ static void anon_pipe_buf_unmap(struct pipe_inode_info *info, struct pipe_buffer | |||
111 | kunmap(buf->page); | 121 | kunmap(buf->page); |
112 | } | 122 | } |
113 | 123 | ||
124 | static int anon_pipe_buf_steal(struct pipe_inode_info *info, | ||
125 | struct pipe_buffer *buf) | ||
126 | { | ||
127 | buf->stolen = 1; | ||
128 | return 0; | ||
129 | } | ||
130 | |||
114 | static struct pipe_buf_operations anon_pipe_buf_ops = { | 131 | static struct pipe_buf_operations anon_pipe_buf_ops = { |
115 | .can_merge = 1, | 132 | .can_merge = 1, |
116 | .map = anon_pipe_buf_map, | 133 | .map = anon_pipe_buf_map, |
117 | .unmap = anon_pipe_buf_unmap, | 134 | .unmap = anon_pipe_buf_unmap, |
118 | .release = anon_pipe_buf_release, | 135 | .release = anon_pipe_buf_release, |
136 | .steal = anon_pipe_buf_steal, | ||
119 | }; | 137 | }; |
120 | 138 | ||
121 | static ssize_t | 139 | static ssize_t |
@@ -152,6 +170,11 @@ pipe_readv(struct file *filp, const struct iovec *_iov, | |||
152 | chars = total_len; | 170 | chars = total_len; |
153 | 171 | ||
154 | addr = ops->map(filp, info, buf); | 172 | addr = ops->map(filp, info, buf); |
173 | if (IS_ERR(addr)) { | ||
174 | if (!ret) | ||
175 | ret = PTR_ERR(addr); | ||
176 | break; | ||
177 | } | ||
155 | error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars); | 178 | error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars); |
156 | ops->unmap(info, buf); | 179 | ops->unmap(info, buf); |
157 | if (unlikely(error)) { | 180 | if (unlikely(error)) { |
@@ -254,8 +277,16 @@ pipe_writev(struct file *filp, const struct iovec *_iov, | |||
254 | struct pipe_buf_operations *ops = buf->ops; | 277 | struct pipe_buf_operations *ops = buf->ops; |
255 | int offset = buf->offset + buf->len; | 278 | int offset = buf->offset + buf->len; |
256 | if (ops->can_merge && offset + chars <= PAGE_SIZE) { | 279 | if (ops->can_merge && offset + chars <= PAGE_SIZE) { |
257 | void *addr = ops->map(filp, info, buf); | 280 | void *addr; |
258 | int error = pipe_iov_copy_from_user(offset + addr, iov, chars); | 281 | int error; |
282 | |||
283 | addr = ops->map(filp, info, buf); | ||
284 | if (IS_ERR(addr)) { | ||
285 | error = PTR_ERR(addr); | ||
286 | goto out; | ||
287 | } | ||
288 | error = pipe_iov_copy_from_user(offset + addr, iov, | ||
289 | chars); | ||
259 | ops->unmap(info, buf); | 290 | ops->unmap(info, buf); |
260 | ret = error; | 291 | ret = error; |
261 | do_wakeup = 1; | 292 | do_wakeup = 1; |
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index 010094d14da6..cf6e1cf40351 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c | |||
@@ -1576,6 +1576,8 @@ const struct file_operations reiserfs_file_operations = { | |||
1576 | .sendfile = generic_file_sendfile, | 1576 | .sendfile = generic_file_sendfile, |
1577 | .aio_read = generic_file_aio_read, | 1577 | .aio_read = generic_file_aio_read, |
1578 | .aio_write = reiserfs_aio_write, | 1578 | .aio_write = reiserfs_aio_write, |
1579 | .splice_read = generic_file_splice_read, | ||
1580 | .splice_write = generic_file_splice_write, | ||
1579 | }; | 1581 | }; |
1580 | 1582 | ||
1581 | struct inode_operations reiserfs_file_inode_operations = { | 1583 | struct inode_operations reiserfs_file_inode_operations = { |
diff --git a/fs/splice.c b/fs/splice.c new file mode 100644 index 000000000000..4a026f95884f --- /dev/null +++ b/fs/splice.c | |||
@@ -0,0 +1,659 @@ | |||
1 | /* | ||
2 | * "splice": joining two ropes together by interweaving their strands. | ||
3 | * | ||
4 | * This is the "extended pipe" functionality, where a pipe is used as | ||
5 | * an arbitrary in-memory buffer. Think of a pipe as a small kernel | ||
6 | * buffer that you can use to transfer data from one end to the other. | ||
7 | * | ||
8 | * The traditional unix read/write is extended with a "splice()" operation | ||
9 | * that transfers data buffers to or from a pipe buffer. | ||
10 | * | ||
11 | * Named by Larry McVoy, original implementation from Linus, extended by | ||
12 | * Jens to support splicing to files and fixing the initial implementation | ||
13 | * bugs. | ||
14 | * | ||
15 | * Copyright (C) 2005 Jens Axboe <axboe@suse.de> | ||
16 | * Copyright (C) 2005 Linus Torvalds <torvalds@osdl.org> | ||
17 | * | ||
18 | */ | ||
19 | #include <linux/fs.h> | ||
20 | #include <linux/file.h> | ||
21 | #include <linux/pagemap.h> | ||
22 | #include <linux/pipe_fs_i.h> | ||
23 | #include <linux/mm_inline.h> | ||
24 | #include <linux/swap.h> | ||
25 | |||
26 | /* | ||
27 | * Passed to the actors | ||
28 | */ | ||
29 | struct splice_desc { | ||
30 | unsigned int len, total_len; /* current and remaining length */ | ||
31 | unsigned int flags; /* splice flags */ | ||
32 | struct file *file; /* file to read/write */ | ||
33 | loff_t pos; /* file position */ | ||
34 | }; | ||
35 | |||
36 | static int page_cache_pipe_buf_steal(struct pipe_inode_info *info, | ||
37 | struct pipe_buffer *buf) | ||
38 | { | ||
39 | struct page *page = buf->page; | ||
40 | |||
41 | WARN_ON(!PageLocked(page)); | ||
42 | WARN_ON(!PageUptodate(page)); | ||
43 | |||
44 | if (!remove_mapping(page_mapping(page), page)) | ||
45 | return 1; | ||
46 | |||
47 | if (PageLRU(page)) { | ||
48 | struct zone *zone = page_zone(page); | ||
49 | |||
50 | spin_lock_irq(&zone->lru_lock); | ||
51 | BUG_ON(!PageLRU(page)); | ||
52 | __ClearPageLRU(page); | ||
53 | del_page_from_lru(zone, page); | ||
54 | spin_unlock_irq(&zone->lru_lock); | ||
55 | } | ||
56 | |||
57 | buf->stolen = 1; | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static void page_cache_pipe_buf_release(struct pipe_inode_info *info, | ||
62 | struct pipe_buffer *buf) | ||
63 | { | ||
64 | page_cache_release(buf->page); | ||
65 | buf->page = NULL; | ||
66 | buf->stolen = 0; | ||
67 | } | ||
68 | |||
69 | static void *page_cache_pipe_buf_map(struct file *file, | ||
70 | struct pipe_inode_info *info, | ||
71 | struct pipe_buffer *buf) | ||
72 | { | ||
73 | struct page *page = buf->page; | ||
74 | |||
75 | lock_page(page); | ||
76 | |||
77 | if (!PageUptodate(page)) { | ||
78 | unlock_page(page); | ||
79 | return ERR_PTR(-EIO); | ||
80 | } | ||
81 | |||
82 | if (!page->mapping) { | ||
83 | unlock_page(page); | ||
84 | return ERR_PTR(-ENODATA); | ||
85 | } | ||
86 | |||
87 | return kmap(buf->page); | ||
88 | } | ||
89 | |||
90 | static void page_cache_pipe_buf_unmap(struct pipe_inode_info *info, | ||
91 | struct pipe_buffer *buf) | ||
92 | { | ||
93 | if (!buf->stolen) | ||
94 | unlock_page(buf->page); | ||
95 | kunmap(buf->page); | ||
96 | } | ||
97 | |||
98 | static struct pipe_buf_operations page_cache_pipe_buf_ops = { | ||
99 | .can_merge = 0, | ||
100 | .map = page_cache_pipe_buf_map, | ||
101 | .unmap = page_cache_pipe_buf_unmap, | ||
102 | .release = page_cache_pipe_buf_release, | ||
103 | .steal = page_cache_pipe_buf_steal, | ||
104 | }; | ||
105 | |||
106 | static ssize_t move_to_pipe(struct inode *inode, struct page **pages, | ||
107 | int nr_pages, unsigned long offset, | ||
108 | unsigned long len) | ||
109 | { | ||
110 | struct pipe_inode_info *info; | ||
111 | int ret, do_wakeup, i; | ||
112 | |||
113 | ret = 0; | ||
114 | do_wakeup = 0; | ||
115 | i = 0; | ||
116 | |||
117 | mutex_lock(PIPE_MUTEX(*inode)); | ||
118 | |||
119 | info = inode->i_pipe; | ||
120 | for (;;) { | ||
121 | int bufs; | ||
122 | |||
123 | if (!PIPE_READERS(*inode)) { | ||
124 | send_sig(SIGPIPE, current, 0); | ||
125 | if (!ret) | ||
126 | ret = -EPIPE; | ||
127 | break; | ||
128 | } | ||
129 | |||
130 | bufs = info->nrbufs; | ||
131 | if (bufs < PIPE_BUFFERS) { | ||
132 | int newbuf = (info->curbuf + bufs) & (PIPE_BUFFERS - 1); | ||
133 | struct pipe_buffer *buf = info->bufs + newbuf; | ||
134 | struct page *page = pages[i++]; | ||
135 | unsigned long this_len; | ||
136 | |||
137 | this_len = PAGE_CACHE_SIZE - offset; | ||
138 | if (this_len > len) | ||
139 | this_len = len; | ||
140 | |||
141 | buf->page = page; | ||
142 | buf->offset = offset; | ||
143 | buf->len = this_len; | ||
144 | buf->ops = &page_cache_pipe_buf_ops; | ||
145 | info->nrbufs = ++bufs; | ||
146 | do_wakeup = 1; | ||
147 | |||
148 | ret += this_len; | ||
149 | len -= this_len; | ||
150 | offset = 0; | ||
151 | if (!--nr_pages) | ||
152 | break; | ||
153 | if (!len) | ||
154 | break; | ||
155 | if (bufs < PIPE_BUFFERS) | ||
156 | continue; | ||
157 | |||
158 | break; | ||
159 | } | ||
160 | |||
161 | if (signal_pending(current)) { | ||
162 | if (!ret) | ||
163 | ret = -ERESTARTSYS; | ||
164 | break; | ||
165 | } | ||
166 | |||
167 | if (do_wakeup) { | ||
168 | wake_up_interruptible_sync(PIPE_WAIT(*inode)); | ||
169 | kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, | ||
170 | POLL_IN); | ||
171 | do_wakeup = 0; | ||
172 | } | ||
173 | |||
174 | PIPE_WAITING_WRITERS(*inode)++; | ||
175 | pipe_wait(inode); | ||
176 | PIPE_WAITING_WRITERS(*inode)--; | ||
177 | } | ||
178 | |||
179 | mutex_unlock(PIPE_MUTEX(*inode)); | ||
180 | |||
181 | if (do_wakeup) { | ||
182 | wake_up_interruptible(PIPE_WAIT(*inode)); | ||
183 | kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN); | ||
184 | } | ||
185 | |||
186 | while (i < nr_pages) | ||
187 | page_cache_release(pages[i++]); | ||
188 | |||
189 | return ret; | ||
190 | } | ||
191 | |||
192 | static int __generic_file_splice_read(struct file *in, struct inode *pipe, | ||
193 | size_t len) | ||
194 | { | ||
195 | struct address_space *mapping = in->f_mapping; | ||
196 | unsigned int offset, nr_pages; | ||
197 | struct page *pages[PIPE_BUFFERS], *shadow[PIPE_BUFFERS]; | ||
198 | struct page *page; | ||
199 | pgoff_t index, pidx; | ||
200 | int i, j; | ||
201 | |||
202 | index = in->f_pos >> PAGE_CACHE_SHIFT; | ||
203 | offset = in->f_pos & ~PAGE_CACHE_MASK; | ||
204 | nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | ||
205 | |||
206 | if (nr_pages > PIPE_BUFFERS) | ||
207 | nr_pages = PIPE_BUFFERS; | ||
208 | |||
209 | /* | ||
210 | * initiate read-ahead on this page range | ||
211 | */ | ||
212 | do_page_cache_readahead(mapping, in, index, nr_pages); | ||
213 | |||
214 | /* | ||
215 | * Get as many pages from the page cache as possible.. | ||
216 | * Start IO on the page cache entries we create (we | ||
217 | * can assume that any pre-existing ones we find have | ||
218 | * already had IO started on them). | ||
219 | */ | ||
220 | i = find_get_pages(mapping, index, nr_pages, pages); | ||
221 | |||
222 | /* | ||
223 | * common case - we found all pages and they are contiguous, | ||
224 | * kick them off | ||
225 | */ | ||
226 | if (i && (pages[i - 1]->index == index + i - 1)) | ||
227 | goto splice_them; | ||
228 | |||
229 | /* | ||
230 | * fill shadow[] with pages at the right locations, so we only | ||
231 | * have to fill holes | ||
232 | */ | ||
233 | memset(shadow, 0, i * sizeof(struct page *)); | ||
234 | for (j = 0, pidx = index; j < i; pidx++, j++) | ||
235 | shadow[pages[j]->index - pidx] = pages[j]; | ||
236 | |||
237 | /* | ||
238 | * now fill in the holes | ||
239 | */ | ||
240 | for (i = 0, pidx = index; i < nr_pages; pidx++, i++) { | ||
241 | int error; | ||
242 | |||
243 | if (shadow[i]) | ||
244 | continue; | ||
245 | |||
246 | /* | ||
247 | * no page there, look one up / create it | ||
248 | */ | ||
249 | page = find_or_create_page(mapping, pidx, | ||
250 | mapping_gfp_mask(mapping)); | ||
251 | if (!page) | ||
252 | break; | ||
253 | |||
254 | if (PageUptodate(page)) | ||
255 | unlock_page(page); | ||
256 | else { | ||
257 | error = mapping->a_ops->readpage(in, page); | ||
258 | |||
259 | if (unlikely(error)) { | ||
260 | page_cache_release(page); | ||
261 | break; | ||
262 | } | ||
263 | } | ||
264 | shadow[i] = page; | ||
265 | } | ||
266 | |||
267 | if (!i) { | ||
268 | for (i = 0; i < nr_pages; i++) { | ||
269 | if (shadow[i]) | ||
270 | page_cache_release(shadow[i]); | ||
271 | } | ||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | memcpy(pages, shadow, i * sizeof(struct page *)); | ||
276 | |||
277 | /* | ||
278 | * Now we splice them into the pipe.. | ||
279 | */ | ||
280 | splice_them: | ||
281 | return move_to_pipe(pipe, pages, i, offset, len); | ||
282 | } | ||
283 | |||
284 | ssize_t generic_file_splice_read(struct file *in, struct inode *pipe, | ||
285 | size_t len, unsigned int flags) | ||
286 | { | ||
287 | ssize_t spliced; | ||
288 | int ret; | ||
289 | |||
290 | ret = 0; | ||
291 | spliced = 0; | ||
292 | while (len) { | ||
293 | ret = __generic_file_splice_read(in, pipe, len); | ||
294 | |||
295 | if (ret <= 0) | ||
296 | break; | ||
297 | |||
298 | in->f_pos += ret; | ||
299 | len -= ret; | ||
300 | spliced += ret; | ||
301 | } | ||
302 | |||
303 | if (spliced) | ||
304 | return spliced; | ||
305 | |||
306 | return ret; | ||
307 | } | ||
308 | |||
309 | /* | ||
310 | * Send 'len' bytes to socket from 'file' at position 'pos' using sendpage(). | ||
311 | */ | ||
312 | static int pipe_to_sendpage(struct pipe_inode_info *info, | ||
313 | struct pipe_buffer *buf, struct splice_desc *sd) | ||
314 | { | ||
315 | struct file *file = sd->file; | ||
316 | loff_t pos = sd->pos; | ||
317 | unsigned int offset; | ||
318 | ssize_t ret; | ||
319 | void *ptr; | ||
320 | |||
321 | /* | ||
322 | * sub-optimal, but we are limited by the pipe ->map. we don't | ||
323 | * need a kmap'ed buffer here, we just want to make sure we | ||
324 | * have the page pinned if the pipe page originates from the | ||
325 | * page cache | ||
326 | */ | ||
327 | ptr = buf->ops->map(file, info, buf); | ||
328 | if (IS_ERR(ptr)) | ||
329 | return PTR_ERR(ptr); | ||
330 | |||
331 | offset = pos & ~PAGE_CACHE_MASK; | ||
332 | |||
333 | ret = file->f_op->sendpage(file, buf->page, offset, sd->len, &pos, | ||
334 | sd->len < sd->total_len); | ||
335 | |||
336 | buf->ops->unmap(info, buf); | ||
337 | if (ret == sd->len) | ||
338 | return 0; | ||
339 | |||
340 | return -EIO; | ||
341 | } | ||
342 | |||
343 | /* | ||
344 | * This is a little more tricky than the file -> pipe splicing. There are | ||
345 | * basically three cases: | ||
346 | * | ||
347 | * - Destination page already exists in the address space and there | ||
348 | * are users of it. For that case we have no other option that | ||
349 | * copying the data. Tough luck. | ||
350 | * - Destination page already exists in the address space, but there | ||
351 | * are no users of it. Make sure it's uptodate, then drop it. Fall | ||
352 | * through to last case. | ||
353 | * - Destination page does not exist, we can add the pipe page to | ||
354 | * the page cache and avoid the copy. | ||
355 | * | ||
356 | * For now we just do the slower thing and always copy pages over, it's | ||
357 | * easier than migrating pages from the pipe to the target file. For the | ||
358 | * case of doing file | file splicing, the migrate approach had some LRU | ||
359 | * nastiness... | ||
360 | */ | ||
361 | static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf, | ||
362 | struct splice_desc *sd) | ||
363 | { | ||
364 | struct file *file = sd->file; | ||
365 | struct address_space *mapping = file->f_mapping; | ||
366 | unsigned int offset; | ||
367 | struct page *page; | ||
368 | pgoff_t index; | ||
369 | char *src; | ||
370 | int ret; | ||
371 | |||
372 | /* | ||
373 | * after this, page will be locked and unmapped | ||
374 | */ | ||
375 | src = buf->ops->map(file, info, buf); | ||
376 | if (IS_ERR(src)) | ||
377 | return PTR_ERR(src); | ||
378 | |||
379 | index = sd->pos >> PAGE_CACHE_SHIFT; | ||
380 | offset = sd->pos & ~PAGE_CACHE_MASK; | ||
381 | |||
382 | /* | ||
383 | * reuse buf page, if SPLICE_F_MOVE is set | ||
384 | */ | ||
385 | if (sd->flags & SPLICE_F_MOVE) { | ||
386 | if (buf->ops->steal(info, buf)) | ||
387 | goto find_page; | ||
388 | |||
389 | page = buf->page; | ||
390 | if (add_to_page_cache_lru(page, mapping, index, | ||
391 | mapping_gfp_mask(mapping))) | ||
392 | goto find_page; | ||
393 | } else { | ||
394 | find_page: | ||
395 | ret = -ENOMEM; | ||
396 | page = find_or_create_page(mapping, index, | ||
397 | mapping_gfp_mask(mapping)); | ||
398 | if (!page) | ||
399 | goto out; | ||
400 | |||
401 | /* | ||
402 | * If the page is uptodate, it is also locked. If it isn't | ||
403 | * uptodate, we can mark it uptodate if we are filling the | ||
404 | * full page. Otherwise we need to read it in first... | ||
405 | */ | ||
406 | if (!PageUptodate(page)) { | ||
407 | if (sd->len < PAGE_CACHE_SIZE) { | ||
408 | ret = mapping->a_ops->readpage(file, page); | ||
409 | if (unlikely(ret)) | ||
410 | goto out; | ||
411 | |||
412 | lock_page(page); | ||
413 | |||
414 | if (!PageUptodate(page)) { | ||
415 | /* | ||
416 | * page got invalidated, repeat | ||
417 | */ | ||
418 | if (!page->mapping) { | ||
419 | unlock_page(page); | ||
420 | page_cache_release(page); | ||
421 | goto find_page; | ||
422 | } | ||
423 | ret = -EIO; | ||
424 | goto out; | ||
425 | } | ||
426 | } else { | ||
427 | WARN_ON(!PageLocked(page)); | ||
428 | SetPageUptodate(page); | ||
429 | } | ||
430 | } | ||
431 | } | ||
432 | |||
433 | ret = mapping->a_ops->prepare_write(file, page, 0, sd->len); | ||
434 | if (ret) | ||
435 | goto out; | ||
436 | |||
437 | if (!buf->stolen) { | ||
438 | char *dst = kmap_atomic(page, KM_USER0); | ||
439 | |||
440 | memcpy(dst + offset, src + buf->offset, sd->len); | ||
441 | flush_dcache_page(page); | ||
442 | kunmap_atomic(dst, KM_USER0); | ||
443 | } | ||
444 | |||
445 | ret = mapping->a_ops->commit_write(file, page, 0, sd->len); | ||
446 | if (ret < 0) | ||
447 | goto out; | ||
448 | |||
449 | set_page_dirty(page); | ||
450 | ret = write_one_page(page, 0); | ||
451 | out: | ||
452 | if (ret < 0) | ||
453 | unlock_page(page); | ||
454 | if (!buf->stolen) | ||
455 | page_cache_release(page); | ||
456 | buf->ops->unmap(info, buf); | ||
457 | return ret; | ||
458 | } | ||
459 | |||
460 | typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *, | ||
461 | struct splice_desc *); | ||
462 | |||
463 | static ssize_t move_from_pipe(struct inode *inode, struct file *out, | ||
464 | size_t len, unsigned int flags, | ||
465 | splice_actor *actor) | ||
466 | { | ||
467 | struct pipe_inode_info *info; | ||
468 | int ret, do_wakeup, err; | ||
469 | struct splice_desc sd; | ||
470 | |||
471 | ret = 0; | ||
472 | do_wakeup = 0; | ||
473 | |||
474 | sd.total_len = len; | ||
475 | sd.flags = flags; | ||
476 | sd.file = out; | ||
477 | sd.pos = out->f_pos; | ||
478 | |||
479 | mutex_lock(PIPE_MUTEX(*inode)); | ||
480 | |||
481 | info = inode->i_pipe; | ||
482 | for (;;) { | ||
483 | int bufs = info->nrbufs; | ||
484 | |||
485 | if (bufs) { | ||
486 | int curbuf = info->curbuf; | ||
487 | struct pipe_buffer *buf = info->bufs + curbuf; | ||
488 | struct pipe_buf_operations *ops = buf->ops; | ||
489 | |||
490 | sd.len = buf->len; | ||
491 | if (sd.len > sd.total_len) | ||
492 | sd.len = sd.total_len; | ||
493 | |||
494 | err = actor(info, buf, &sd); | ||
495 | if (err) { | ||
496 | if (!ret && err != -ENODATA) | ||
497 | ret = err; | ||
498 | |||
499 | break; | ||
500 | } | ||
501 | |||
502 | ret += sd.len; | ||
503 | buf->offset += sd.len; | ||
504 | buf->len -= sd.len; | ||
505 | if (!buf->len) { | ||
506 | buf->ops = NULL; | ||
507 | ops->release(info, buf); | ||
508 | curbuf = (curbuf + 1) & (PIPE_BUFFERS - 1); | ||
509 | info->curbuf = curbuf; | ||
510 | info->nrbufs = --bufs; | ||
511 | do_wakeup = 1; | ||
512 | } | ||
513 | |||
514 | sd.pos += sd.len; | ||
515 | sd.total_len -= sd.len; | ||
516 | if (!sd.total_len) | ||
517 | break; | ||
518 | } | ||
519 | |||
520 | if (bufs) | ||
521 | continue; | ||
522 | if (!PIPE_WRITERS(*inode)) | ||
523 | break; | ||
524 | if (!PIPE_WAITING_WRITERS(*inode)) { | ||
525 | if (ret) | ||
526 | break; | ||
527 | } | ||
528 | |||
529 | if (signal_pending(current)) { | ||
530 | if (!ret) | ||
531 | ret = -ERESTARTSYS; | ||
532 | break; | ||
533 | } | ||
534 | |||
535 | if (do_wakeup) { | ||
536 | wake_up_interruptible_sync(PIPE_WAIT(*inode)); | ||
537 | kill_fasync(PIPE_FASYNC_WRITERS(*inode),SIGIO,POLL_OUT); | ||
538 | do_wakeup = 0; | ||
539 | } | ||
540 | |||
541 | pipe_wait(inode); | ||
542 | } | ||
543 | |||
544 | mutex_unlock(PIPE_MUTEX(*inode)); | ||
545 | |||
546 | if (do_wakeup) { | ||
547 | wake_up_interruptible(PIPE_WAIT(*inode)); | ||
548 | kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT); | ||
549 | } | ||
550 | |||
551 | mutex_lock(&out->f_mapping->host->i_mutex); | ||
552 | out->f_pos = sd.pos; | ||
553 | mutex_unlock(&out->f_mapping->host->i_mutex); | ||
554 | return ret; | ||
555 | |||
556 | } | ||
557 | |||
558 | ssize_t generic_file_splice_write(struct inode *inode, struct file *out, | ||
559 | size_t len, unsigned int flags) | ||
560 | { | ||
561 | return move_from_pipe(inode, out, len, flags, pipe_to_file); | ||
562 | } | ||
563 | |||
564 | ssize_t generic_splice_sendpage(struct inode *inode, struct file *out, | ||
565 | size_t len, unsigned int flags) | ||
566 | { | ||
567 | return move_from_pipe(inode, out, len, flags, pipe_to_sendpage); | ||
568 | } | ||
569 | |||
570 | static long do_splice_from(struct inode *pipe, struct file *out, size_t len, | ||
571 | unsigned int flags) | ||
572 | { | ||
573 | loff_t pos; | ||
574 | int ret; | ||
575 | |||
576 | if (!out->f_op || !out->f_op->splice_write) | ||
577 | return -EINVAL; | ||
578 | |||
579 | if (!(out->f_mode & FMODE_WRITE)) | ||
580 | return -EBADF; | ||
581 | |||
582 | pos = out->f_pos; | ||
583 | ret = rw_verify_area(WRITE, out, &pos, len); | ||
584 | if (unlikely(ret < 0)) | ||
585 | return ret; | ||
586 | |||
587 | return out->f_op->splice_write(pipe, out, len, flags); | ||
588 | } | ||
589 | |||
590 | static long do_splice_to(struct file *in, struct inode *pipe, size_t len, | ||
591 | unsigned int flags) | ||
592 | { | ||
593 | loff_t pos, isize, left; | ||
594 | int ret; | ||
595 | |||
596 | if (!in->f_op || !in->f_op->splice_read) | ||
597 | return -EINVAL; | ||
598 | |||
599 | if (!(in->f_mode & FMODE_READ)) | ||
600 | return -EBADF; | ||
601 | |||
602 | pos = in->f_pos; | ||
603 | ret = rw_verify_area(READ, in, &pos, len); | ||
604 | if (unlikely(ret < 0)) | ||
605 | return ret; | ||
606 | |||
607 | isize = i_size_read(in->f_mapping->host); | ||
608 | if (unlikely(in->f_pos >= isize)) | ||
609 | return 0; | ||
610 | |||
611 | left = isize - in->f_pos; | ||
612 | if (left < len) | ||
613 | len = left; | ||
614 | |||
615 | return in->f_op->splice_read(in, pipe, len, flags); | ||
616 | } | ||
617 | |||
618 | static long do_splice(struct file *in, struct file *out, size_t len, | ||
619 | unsigned int flags) | ||
620 | { | ||
621 | struct inode *pipe; | ||
622 | |||
623 | pipe = in->f_dentry->d_inode; | ||
624 | if (pipe->i_pipe) | ||
625 | return do_splice_from(pipe, out, len, flags); | ||
626 | |||
627 | pipe = out->f_dentry->d_inode; | ||
628 | if (pipe->i_pipe) | ||
629 | return do_splice_to(in, pipe, len, flags); | ||
630 | |||
631 | return -EINVAL; | ||
632 | } | ||
633 | |||
634 | asmlinkage long sys_splice(int fdin, int fdout, size_t len, unsigned int flags) | ||
635 | { | ||
636 | long error; | ||
637 | struct file *in, *out; | ||
638 | int fput_in, fput_out; | ||
639 | |||
640 | if (unlikely(!len)) | ||
641 | return 0; | ||
642 | |||
643 | error = -EBADF; | ||
644 | in = fget_light(fdin, &fput_in); | ||
645 | if (in) { | ||
646 | if (in->f_mode & FMODE_READ) { | ||
647 | out = fget_light(fdout, &fput_out); | ||
648 | if (out) { | ||
649 | if (out->f_mode & FMODE_WRITE) | ||
650 | error = do_splice(in, out, len, flags); | ||
651 | fput_light(out, fput_out); | ||
652 | } | ||
653 | } | ||
654 | |||
655 | fput_light(in, fput_in); | ||
656 | } | ||
657 | |||
658 | return error; | ||
659 | } | ||
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h index 014e3562895b..789e9bdd0a40 100644 --- a/include/asm-i386/unistd.h +++ b/include/asm-i386/unistd.h | |||
@@ -318,8 +318,9 @@ | |||
318 | #define __NR_unshare 310 | 318 | #define __NR_unshare 310 |
319 | #define __NR_set_robust_list 311 | 319 | #define __NR_set_robust_list 311 |
320 | #define __NR_get_robust_list 312 | 320 | #define __NR_get_robust_list 312 |
321 | #define __NR_sys_splice 313 | ||
321 | 322 | ||
322 | #define NR_syscalls 313 | 323 | #define NR_syscalls 314 |
323 | 324 | ||
324 | /* | 325 | /* |
325 | * user-visible error numbers are in the range -1 - -128: see | 326 | * user-visible error numbers are in the range -1 - -128: see |
diff --git a/include/asm-ia64/asmmacro.h b/include/asm-ia64/asmmacro.h index d4cec32083d8..edf2cebb2969 100644 --- a/include/asm-ia64/asmmacro.h +++ b/include/asm-ia64/asmmacro.h | |||
@@ -38,6 +38,10 @@ name: | |||
38 | 38 | ||
39 | /* | 39 | /* |
40 | * Helper macros for accessing user memory. | 40 | * Helper macros for accessing user memory. |
41 | * | ||
42 | * When adding any new .section/.previous entries here, make sure to | ||
43 | * also add it to the DISCARD section in arch/ia64/kernel/gate.lds.S or | ||
44 | * unpleasant things will happen. | ||
41 | */ | 45 | */ |
42 | 46 | ||
43 | .section "__ex_table", "a" // declare section & section attributes | 47 | .section "__ex_table", "a" // declare section & section attributes |
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h index 019956c613e4..36070c1014d8 100644 --- a/include/asm-ia64/unistd.h +++ b/include/asm-ia64/unistd.h | |||
@@ -285,12 +285,13 @@ | |||
285 | #define __NR_faccessat 1293 | 285 | #define __NR_faccessat 1293 |
286 | /* 1294, 1295 reserved for pselect/ppoll */ | 286 | /* 1294, 1295 reserved for pselect/ppoll */ |
287 | #define __NR_unshare 1296 | 287 | #define __NR_unshare 1296 |
288 | #define __NR_splice 1297 | ||
288 | 289 | ||
289 | #ifdef __KERNEL__ | 290 | #ifdef __KERNEL__ |
290 | 291 | ||
291 | #include <linux/config.h> | 292 | #include <linux/config.h> |
292 | 293 | ||
293 | #define NR_syscalls 273 /* length of syscall table */ | 294 | #define NR_syscalls 274 /* length of syscall table */ |
294 | 295 | ||
295 | #define __ARCH_WANT_SYS_RT_SIGACTION | 296 | #define __ARCH_WANT_SYS_RT_SIGACTION |
296 | 297 | ||
diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h index 1e990747dce7..536ba0873052 100644 --- a/include/asm-powerpc/unistd.h +++ b/include/asm-powerpc/unistd.h | |||
@@ -301,8 +301,9 @@ | |||
301 | #define __NR_pselect6 280 | 301 | #define __NR_pselect6 280 |
302 | #define __NR_ppoll 281 | 302 | #define __NR_ppoll 281 |
303 | #define __NR_unshare 282 | 303 | #define __NR_unshare 282 |
304 | #define __NR_splice 283 | ||
304 | 305 | ||
305 | #define __NR_syscalls 283 | 306 | #define __NR_syscalls 284 |
306 | 307 | ||
307 | #ifdef __KERNEL__ | 308 | #ifdef __KERNEL__ |
308 | #define __NR__exit __NR_exit | 309 | #define __NR__exit __NR_exit |
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h index fcc516353087..f21ff2c1e960 100644 --- a/include/asm-x86_64/unistd.h +++ b/include/asm-x86_64/unistd.h | |||
@@ -609,8 +609,10 @@ __SYSCALL(__NR_unshare, sys_unshare) | |||
609 | __SYSCALL(__NR_set_robust_list, sys_set_robust_list) | 609 | __SYSCALL(__NR_set_robust_list, sys_set_robust_list) |
610 | #define __NR_get_robust_list 274 | 610 | #define __NR_get_robust_list 274 |
611 | __SYSCALL(__NR_get_robust_list, sys_get_robust_list) | 611 | __SYSCALL(__NR_get_robust_list, sys_get_robust_list) |
612 | #define __NR_splice 275 | ||
613 | __SYSCALL(__NR_splice, sys_splice) | ||
612 | 614 | ||
613 | #define __NR_syscall_max __NR_get_robust_list | 615 | #define __NR_syscall_max __NR_splice |
614 | 616 | ||
615 | #ifndef __NO_STUBS | 617 | #ifndef __NO_STUBS |
616 | 618 | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index 408fe89498f4..20fa5f6d7269 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1032,6 +1032,8 @@ struct file_operations { | |||
1032 | int (*check_flags)(int); | 1032 | int (*check_flags)(int); |
1033 | int (*dir_notify)(struct file *filp, unsigned long arg); | 1033 | int (*dir_notify)(struct file *filp, unsigned long arg); |
1034 | int (*flock) (struct file *, int, struct file_lock *); | 1034 | int (*flock) (struct file *, int, struct file_lock *); |
1035 | ssize_t (*splice_write)(struct inode *, struct file *, size_t, unsigned int); | ||
1036 | ssize_t (*splice_read)(struct file *, struct inode *, size_t, unsigned int); | ||
1035 | }; | 1037 | }; |
1036 | 1038 | ||
1037 | struct inode_operations { | 1039 | struct inode_operations { |
@@ -1609,6 +1611,8 @@ extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor | |||
1609 | extern void do_generic_mapping_read(struct address_space *mapping, | 1611 | extern void do_generic_mapping_read(struct address_space *mapping, |
1610 | struct file_ra_state *, struct file *, | 1612 | struct file_ra_state *, struct file *, |
1611 | loff_t *, read_descriptor_t *, read_actor_t); | 1613 | loff_t *, read_descriptor_t *, read_actor_t); |
1614 | extern ssize_t generic_file_splice_read(struct file *, struct inode *, size_t, unsigned int); | ||
1615 | extern ssize_t generic_file_splice_write(struct inode *, struct file *, size_t, unsigned int); | ||
1612 | extern void | 1616 | extern void |
1613 | file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); | 1617 | file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); |
1614 | extern ssize_t generic_file_readv(struct file *filp, const struct iovec *iov, | 1618 | extern ssize_t generic_file_readv(struct file *filp, const struct iovec *iov, |
diff --git a/include/linux/libata.h b/include/linux/libata.h index 047192253c3a..0d61357604d5 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -160,8 +160,10 @@ enum { | |||
160 | ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE, | 160 | ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE, |
161 | ATA_QCFLAG_EH_SCHEDULED = (1 << 5), /* EH scheduled */ | 161 | ATA_QCFLAG_EH_SCHEDULED = (1 << 5), /* EH scheduled */ |
162 | 162 | ||
163 | /* host set flags */ | ||
164 | ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host_set only */ | ||
165 | |||
163 | /* various lengths of time */ | 166 | /* various lengths of time */ |
164 | ATA_TMOUT_EDD = 5 * HZ, /* heuristic */ | ||
165 | ATA_TMOUT_PIO = 30 * HZ, | 167 | ATA_TMOUT_PIO = 30 * HZ, |
166 | ATA_TMOUT_BOOT = 30 * HZ, /* heuristic */ | 168 | ATA_TMOUT_BOOT = 30 * HZ, /* heuristic */ |
167 | ATA_TMOUT_BOOT_QUICK = 7 * HZ, /* heuristic */ | 169 | ATA_TMOUT_BOOT_QUICK = 7 * HZ, /* heuristic */ |
@@ -279,6 +281,7 @@ struct ata_probe_ent { | |||
279 | unsigned long irq; | 281 | unsigned long irq; |
280 | unsigned int irq_flags; | 282 | unsigned int irq_flags; |
281 | unsigned long host_flags; | 283 | unsigned long host_flags; |
284 | unsigned long host_set_flags; | ||
282 | void __iomem *mmio_base; | 285 | void __iomem *mmio_base; |
283 | void *private_data; | 286 | void *private_data; |
284 | }; | 287 | }; |
@@ -291,6 +294,9 @@ struct ata_host_set { | |||
291 | unsigned int n_ports; | 294 | unsigned int n_ports; |
292 | void *private_data; | 295 | void *private_data; |
293 | const struct ata_port_operations *ops; | 296 | const struct ata_port_operations *ops; |
297 | unsigned long flags; | ||
298 | int simplex_claimed; /* Keep seperate in case we | ||
299 | ever need to do this locked */ | ||
294 | struct ata_port * ports[0]; | 300 | struct ata_port * ports[0]; |
295 | }; | 301 | }; |
296 | 302 | ||
@@ -420,6 +426,7 @@ struct ata_port_operations { | |||
420 | 426 | ||
421 | void (*set_piomode) (struct ata_port *, struct ata_device *); | 427 | void (*set_piomode) (struct ata_port *, struct ata_device *); |
422 | void (*set_dmamode) (struct ata_port *, struct ata_device *); | 428 | void (*set_dmamode) (struct ata_port *, struct ata_device *); |
429 | unsigned long (*mode_filter) (const struct ata_port *, struct ata_device *, unsigned long); | ||
423 | 430 | ||
424 | void (*tf_load) (struct ata_port *ap, const struct ata_taskfile *tf); | 431 | void (*tf_load) (struct ata_port *ap, const struct ata_taskfile *tf); |
425 | void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf); | 432 | void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf); |
@@ -430,6 +437,7 @@ struct ata_port_operations { | |||
430 | void (*dev_select)(struct ata_port *ap, unsigned int device); | 437 | void (*dev_select)(struct ata_port *ap, unsigned int device); |
431 | 438 | ||
432 | void (*phy_reset) (struct ata_port *ap); /* obsolete */ | 439 | void (*phy_reset) (struct ata_port *ap); /* obsolete */ |
440 | void (*set_mode) (struct ata_port *ap); | ||
433 | int (*probe_reset) (struct ata_port *ap, unsigned int *classes); | 441 | int (*probe_reset) (struct ata_port *ap, unsigned int *classes); |
434 | 442 | ||
435 | void (*post_set_mode) (struct ata_port *ap); | 443 | void (*post_set_mode) (struct ata_port *ap); |
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index b12e59c75752..75c7f55023ab 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h | |||
@@ -9,6 +9,7 @@ struct pipe_buffer { | |||
9 | struct page *page; | 9 | struct page *page; |
10 | unsigned int offset, len; | 10 | unsigned int offset, len; |
11 | struct pipe_buf_operations *ops; | 11 | struct pipe_buf_operations *ops; |
12 | unsigned int stolen; | ||
12 | }; | 13 | }; |
13 | 14 | ||
14 | struct pipe_buf_operations { | 15 | struct pipe_buf_operations { |
@@ -16,6 +17,7 @@ struct pipe_buf_operations { | |||
16 | void * (*map)(struct file *, struct pipe_inode_info *, struct pipe_buffer *); | 17 | void * (*map)(struct file *, struct pipe_inode_info *, struct pipe_buffer *); |
17 | void (*unmap)(struct pipe_inode_info *, struct pipe_buffer *); | 18 | void (*unmap)(struct pipe_inode_info *, struct pipe_buffer *); |
18 | void (*release)(struct pipe_inode_info *, struct pipe_buffer *); | 19 | void (*release)(struct pipe_inode_info *, struct pipe_buffer *); |
20 | int (*steal)(struct pipe_inode_info *, struct pipe_buffer *); | ||
19 | }; | 21 | }; |
20 | 22 | ||
21 | struct pipe_inode_info { | 23 | struct pipe_inode_info { |
@@ -53,4 +55,10 @@ void pipe_wait(struct inode * inode); | |||
53 | struct inode* pipe_new(struct inode* inode); | 55 | struct inode* pipe_new(struct inode* inode); |
54 | void free_pipe_info(struct inode* inode); | 56 | void free_pipe_info(struct inode* inode); |
55 | 57 | ||
58 | /* | ||
59 | * splice is tied to pipes as a transport (at least for now), so we'll just | ||
60 | * add the splice flags here. | ||
61 | */ | ||
62 | #define SPLICE_F_MOVE (0x01) /* move pages instead of copying */ | ||
63 | |||
56 | #endif | 64 | #endif |
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index e487e3b60f60..e78ffc7d5b56 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h | |||
@@ -569,5 +569,7 @@ asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user * filename, | |||
569 | asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename, | 569 | asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename, |
570 | int flags, int mode); | 570 | int flags, int mode); |
571 | asmlinkage long sys_unshare(unsigned long unshare_flags); | 571 | asmlinkage long sys_unshare(unsigned long unshare_flags); |
572 | asmlinkage long sys_splice(int fdin, int fdout, size_t len, | ||
573 | unsigned int flags); | ||
572 | 574 | ||
573 | #endif | 575 | #endif |
diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h index 51ab8eddb295..5ff77558013b 100644 --- a/include/rdma/ib_mad.h +++ b/include/rdma/ib_mad.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * Copyright (c) 2004 Infinicon Corporation. All rights reserved. | 3 | * Copyright (c) 2004 Infinicon Corporation. All rights reserved. |
4 | * Copyright (c) 2004 Intel Corporation. All rights reserved. | 4 | * Copyright (c) 2004 Intel Corporation. All rights reserved. |
5 | * Copyright (c) 2004 Topspin Corporation. All rights reserved. | 5 | * Copyright (c) 2004 Topspin Corporation. All rights reserved. |
6 | * Copyright (c) 2004 Voltaire Corporation. All rights reserved. | 6 | * Copyright (c) 2004-2006 Voltaire Corporation. All rights reserved. |
7 | * | 7 | * |
8 | * This software is available to you under a choice of one of two | 8 | * This software is available to you under a choice of one of two |
9 | * licenses. You may choose to be licensed under the terms of the GNU | 9 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -55,6 +55,10 @@ | |||
55 | #define IB_MGMT_CLASS_DEVICE_MGMT 0x06 | 55 | #define IB_MGMT_CLASS_DEVICE_MGMT 0x06 |
56 | #define IB_MGMT_CLASS_CM 0x07 | 56 | #define IB_MGMT_CLASS_CM 0x07 |
57 | #define IB_MGMT_CLASS_SNMP 0x08 | 57 | #define IB_MGMT_CLASS_SNMP 0x08 |
58 | #define IB_MGMT_CLASS_DEVICE_ADM 0x10 | ||
59 | #define IB_MGMT_CLASS_BOOT_MGMT 0x11 | ||
60 | #define IB_MGMT_CLASS_BIS 0x12 | ||
61 | #define IB_MGMT_CLASS_CONG_MGMT 0x21 | ||
58 | #define IB_MGMT_CLASS_VENDOR_RANGE2_START 0x30 | 62 | #define IB_MGMT_CLASS_VENDOR_RANGE2_START 0x30 |
59 | #define IB_MGMT_CLASS_VENDOR_RANGE2_END 0x4F | 63 | #define IB_MGMT_CLASS_VENDOR_RANGE2_END 0x4F |
60 | 64 | ||
@@ -117,6 +121,8 @@ enum { | |||
117 | IB_MGMT_VENDOR_DATA = 216, | 121 | IB_MGMT_VENDOR_DATA = 216, |
118 | IB_MGMT_SA_HDR = 56, | 122 | IB_MGMT_SA_HDR = 56, |
119 | IB_MGMT_SA_DATA = 200, | 123 | IB_MGMT_SA_DATA = 200, |
124 | IB_MGMT_DEVICE_HDR = 64, | ||
125 | IB_MGMT_DEVICE_DATA = 192, | ||
120 | }; | 126 | }; |
121 | 127 | ||
122 | struct ib_mad_hdr { | 128 | struct ib_mad_hdr { |
@@ -603,6 +609,25 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, | |||
603 | gfp_t gfp_mask); | 609 | gfp_t gfp_mask); |
604 | 610 | ||
605 | /** | 611 | /** |
612 | * ib_is_mad_class_rmpp - returns whether given management class | ||
613 | * supports RMPP. | ||
614 | * @mgmt_class: management class | ||
615 | * | ||
616 | * This routine returns whether the management class supports RMPP. | ||
617 | */ | ||
618 | int ib_is_mad_class_rmpp(u8 mgmt_class); | ||
619 | |||
620 | /** | ||
621 | * ib_get_mad_data_offset - returns the data offset for a given | ||
622 | * management class. | ||
623 | * @mgmt_class: management class | ||
624 | * | ||
625 | * This routine returns the data offset in the MAD for the management | ||
626 | * class requested. | ||
627 | */ | ||
628 | int ib_get_mad_data_offset(u8 mgmt_class); | ||
629 | |||
630 | /** | ||
606 | * ib_get_rmpp_segment - returns the data buffer for a given RMPP segment. | 631 | * ib_get_rmpp_segment - returns the data buffer for a given RMPP segment. |
607 | * @send_buf: Previously allocated send data buffer. | 632 | * @send_buf: Previously allocated send data buffer. |
608 | * @seg_num: number of segment to return | 633 | * @seg_num: number of segment to return |
diff --git a/net/socket.c b/net/socket.c index fcd77eac0ccf..b13042f68c02 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -119,6 +119,9 @@ static ssize_t sock_writev(struct file *file, const struct iovec *vector, | |||
119 | static ssize_t sock_sendpage(struct file *file, struct page *page, | 119 | static ssize_t sock_sendpage(struct file *file, struct page *page, |
120 | int offset, size_t size, loff_t *ppos, int more); | 120 | int offset, size_t size, loff_t *ppos, int more); |
121 | 121 | ||
122 | extern ssize_t generic_splice_sendpage(struct inode *inode, struct file *out, | ||
123 | size_t len, unsigned int flags); | ||
124 | |||
122 | 125 | ||
123 | /* | 126 | /* |
124 | * Socket files have a set of 'special' operations as well as the generic file ones. These don't appear | 127 | * Socket files have a set of 'special' operations as well as the generic file ones. These don't appear |
@@ -141,7 +144,8 @@ static struct file_operations socket_file_ops = { | |||
141 | .fasync = sock_fasync, | 144 | .fasync = sock_fasync, |
142 | .readv = sock_readv, | 145 | .readv = sock_readv, |
143 | .writev = sock_writev, | 146 | .writev = sock_writev, |
144 | .sendpage = sock_sendpage | 147 | .sendpage = sock_sendpage, |
148 | .splice_write = generic_splice_sendpage, | ||
145 | }; | 149 | }; |
146 | 150 | ||
147 | /* | 151 | /* |